






















@@ -115,6 +115,155 @@ function expectNoNoteContaining(message: string, title: string): void {
115115}
116116117117describe("maybeRepairLegacyCronStore", () => {
118+it("surfaces cron payload model overrides without rewriting current jobs", async () => {
119+const storePath = await makeTempStorePath();
120+await writeCronStore(storePath, [
121+{
122+id: "api-pinned",
123+name: "API pinned",
124+enabled: true,
125+createdAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
126+updatedAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
127+schedule: { kind: "cron", expr: "0 7 * * *", tz: "UTC" },
128+sessionTarget: "isolated",
129+wakeMode: "now",
130+payload: {
131+kind: "agentTurn",
132+message: "Morning brief",
133+model: "openai/gpt-5.4",
134+thinking: "high",
135+},
136+state: {},
137+},
138+{
139+id: "other-pinned",
140+name: "Other pinned",
141+enabled: true,
142+createdAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
143+updatedAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
144+schedule: { kind: "cron", expr: "0 8 * * *", tz: "UTC" },
145+sessionTarget: "isolated",
146+wakeMode: "now",
147+payload: {
148+kind: "agentTurn",
149+message: "Morning brief",
150+model: "anthropic/claude-sonnet-4-6",
151+},
152+state: {},
153+},
154+{
155+id: "inherits-default",
156+name: "Inherits default",
157+enabled: true,
158+createdAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
159+updatedAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
160+schedule: { kind: "cron", expr: "0 9 * * *", tz: "UTC" },
161+sessionTarget: "isolated",
162+wakeMode: "now",
163+payload: {
164+kind: "agentTurn",
165+message: "Morning brief",
166+},
167+state: {},
168+},
169+]);
170+const prompter = makePrompter(true);
171+172+await maybeRepairLegacyCronStore({
173+cfg: {
174+cron: { store: storePath },
175+agents: {
176+defaults: {
177+model: { primary: "openai/gpt-5.5", fallbacks: [] },
178+},
179+},
180+},
181+options: {},
182+ prompter,
183+});
184+185+expect(prompter.confirm).not.toHaveBeenCalled();
186+expectNoteContaining("Cron model overrides detected", "Cron");
187+expectNoteContaining("2 jobs set `payload.model`", "Cron");
188+expectNoteContaining("Provider namespaces: anthropic=1, openai=1", "Cron");
189+expectNoteContaining("2 jobs use a different model than `agents.defaults.model`", "Cron");
190+191+const jobs = await readPersistedJobs(storePath);
192+const job = requirePersistedJob(jobs, 0);
193+const payload = requireRecord(job.payload, "cron payload");
194+expect(payload.model).toBe("openai/gpt-5.4");
195+expect(payload.thinking).toBe("high");
196+});
197+198+it("does not surface cron model override diagnostics when jobs inherit the default", async () => {
199+const storePath = await makeTempStorePath();
200+await writeCronStore(storePath, [
201+{
202+id: "inherits-default",
203+name: "Inherits default",
204+enabled: true,
205+createdAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
206+updatedAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
207+schedule: { kind: "cron", expr: "0 9 * * *", tz: "UTC" },
208+sessionTarget: "isolated",
209+wakeMode: "now",
210+payload: {
211+kind: "agentTurn",
212+message: "Morning brief",
213+},
214+state: {},
215+},
216+]);
217+218+await maybeRepairLegacyCronStore({
219+cfg: createCronConfig(storePath),
220+options: {},
221+prompter: makePrompter(true),
222+});
223+224+expectNoNoteContaining("Cron model overrides detected", "Cron");
225+});
226+227+it("counts alias model pins as default mismatches", async () => {
228+const storePath = await makeTempStorePath();
229+await writeCronStore(storePath, [
230+{
231+id: "alias-pinned",
232+name: "Alias pinned",
233+enabled: true,
234+createdAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
235+updatedAtMs: Date.parse("2026-05-01T00:00:00.000Z"),
236+schedule: { kind: "cron", expr: "0 10 * * *", tz: "UTC" },
237+sessionTarget: "isolated",
238+wakeMode: "now",
239+payload: {
240+kind: "agentTurn",
241+message: "Morning brief",
242+model: "gpt",
243+},
244+state: {},
245+},
246+]);
247+248+await maybeRepairLegacyCronStore({
249+cfg: {
250+cron: { store: storePath },
251+agents: {
252+defaults: {
253+model: { primary: "pi:opus", fallbacks: [] },
254+},
255+},
256+},
257+options: {},
258+prompter: makePrompter(true),
259+});
260+261+expectNoteContaining("1 job set `payload.model`", "Cron");
262+expectNoteContaining("Provider namespaces: bare/alias=1", "Cron");
263+expectNoteContaining("1 job uses a different model than `agents.defaults.model`", "Cron");
264+expectNoteContaining("Examples: alias-pinned -> gpt", "Cron");
265+});
266+118267it("repairs legacy cron store fields and migrates notify fallback to webhook delivery", async () => {
119268const storePath = await makeTempStorePath();
120269await writeCronStore(storePath, [createLegacyCronJob()]);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。