fix(config): preserve config data when validation fails
When readConfigFileSnapshot encounters validation errors, it now: 1. Returns the resolved config data instead of empty object 2. Uses passthrough() on main schema to preserve unknown fields This prevents config loss when: - User has custom/unknown fields - Legacy config issues are detected but config is otherwise valid - Zod schema does not recognize newer fields Fixes config being overwritten with empty object on validation failure.
This commit is contained in:
committed by
Peter Steinberger
parent
b32f6a0e00
commit
20ba8d4891
@@ -1685,3 +1685,46 @@ describe("multi-agent agentDir validation", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("config preservation on validation failure", () => {
|
||||||
|
it("preserves unknown fields via passthrough", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const res = validateConfigObject({
|
||||||
|
agents: { list: [{ id: "pi" }] },
|
||||||
|
customUnknownField: { nested: "value" },
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
expect(
|
||||||
|
(res as { config: Record<string, unknown> }).config.customUnknownField,
|
||||||
|
).toEqual({
|
||||||
|
nested: "value",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves config data when validation fails", async () => {
|
||||||
|
await withTempHome(async (home) => {
|
||||||
|
const configDir = path.join(home, ".clawdbot");
|
||||||
|
await fs.mkdir(configDir, { recursive: true });
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(configDir, "clawdbot.json"),
|
||||||
|
JSON.stringify({
|
||||||
|
agents: { list: [{ id: "pi" }] },
|
||||||
|
routing: { allowFrom: ["+15555550123"] },
|
||||||
|
customData: { preserved: true },
|
||||||
|
}),
|
||||||
|
"utf-8",
|
||||||
|
);
|
||||||
|
|
||||||
|
vi.resetModules();
|
||||||
|
const { readConfigFileSnapshot } = await import("./config.js");
|
||||||
|
const snap = await readConfigFileSnapshot();
|
||||||
|
|
||||||
|
expect(snap.valid).toBe(false);
|
||||||
|
expect(snap.legacyIssues.length).toBeGreaterThan(0);
|
||||||
|
expect((snap.config as Record<string, unknown>).customData).toEqual({
|
||||||
|
preserved: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
|||||||
raw,
|
raw,
|
||||||
parsed: parsedRes.parsed,
|
parsed: parsedRes.parsed,
|
||||||
valid: false,
|
valid: false,
|
||||||
config: {},
|
config: resolved as ClawdbotConfig,
|
||||||
issues: validated.issues,
|
issues: validated.issues,
|
||||||
legacyIssues,
|
legacyIssues,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1757,6 +1757,7 @@ export const ClawdbotSchema = z
|
|||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
})
|
})
|
||||||
|
.passthrough()
|
||||||
.superRefine((cfg, ctx) => {
|
.superRefine((cfg, ctx) => {
|
||||||
const agents = cfg.agents?.list ?? [];
|
const agents = cfg.agents?.list ?? [];
|
||||||
if (agents.length === 0) return;
|
if (agents.length === 0) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user