Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions assistant/src/__tests__/config-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,37 @@ describe("loadConfig with schema validation", () => {
expect(config.calls.provider).toBe("twilio");
});

test("recovers from partial filing.activeHours without wiping unrelated fields", () => {
// Only activeHoursStart is set. The superRefine must emit the issue so
// the loader's delete-and-retry can strip the set field; otherwise the
// mismatch persists and the config falls back to full defaults (which
// would reset maxTokens below to 64000).
writeConfig({
maxTokens: 4096,
filing: { activeHoursStart: 8 },
});
const config = loadConfig();
expect(config.maxTokens).toBe(4096);
expect(config.filing.activeHoursStart).toBeNull();
expect(config.filing.activeHoursEnd).toBeNull();
});

test("recovers from partial heartbeat.activeHours without wiping unrelated fields", () => {
// activeHoursStart is explicitly nulled while activeHoursEnd defaults to
// 22 — a mismatch. Without emitting on both paths, delete-and-retry can't
// resolve this (deleting the null side is a no-op) and the whole config
// would be reset to defaults.
writeConfig({
maxTokens: 4096,
heartbeat: { activeHoursStart: null },
});
const config = loadConfig();
expect(config.maxTokens).toBe(4096);
// Both fall back to the heartbeat defaults (8, 22).
expect(config.heartbeat.activeHoursStart).toBe(8);
expect(config.heartbeat.activeHoursEnd).toBe(22);
});

test("applies calls defaults when not specified", () => {
writeConfig({});
const config = loadConfig();
Expand Down
15 changes: 12 additions & 3 deletions assistant/src/config/schemas/filing.ts
Comment thread
siddseethepalli marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,20 @@ export const FilingConfigSchema = z
const startNull = config.activeHoursStart == null;
const endNull = config.activeHoursEnd == null;
if (startNull !== endNull) {
// Emit on both fields so validateWithSchema's delete-and-retry repair
// can strip whichever side was set (and no-op the null side), letting
// the config fall back to both-null defaults without a full reset.
const message =
"filing.activeHoursStart and filing.activeHoursEnd must both be set or both be null";
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: [startNull ? "activeHoursStart" : "activeHoursEnd"],
message:
"filing.activeHoursStart and filing.activeHoursEnd must both be set or both be null",
path: ["activeHoursStart"],
message,
});
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["activeHoursEnd"],
message,
});
return;
}
Expand Down
15 changes: 12 additions & 3 deletions assistant/src/config/schemas/heartbeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,20 @@ export const HeartbeatConfigSchema = z
const startNull = config.activeHoursStart == null;
const endNull = config.activeHoursEnd == null;
if (startNull !== endNull) {
// Emit on both fields so validateWithSchema's delete-and-retry repair
// can strip whichever side was set (and no-op the null side), letting
// the config fall back to the schema defaults without a full reset.
const message =
"heartbeat.activeHoursStart and heartbeat.activeHoursEnd must both be set or both be null";
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: [startNull ? "activeHoursStart" : "activeHoursEnd"],
message:
"heartbeat.activeHoursStart and heartbeat.activeHoursEnd must both be set or both be null",
path: ["activeHoursStart"],
message,
});
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["activeHoursEnd"],
message,
Comment thread
siddseethepalli marked this conversation as resolved.
});
return;
}
Expand Down
Loading