From 817ca42a4cafd2df263f8b732b8b30ec47df9ba2 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Thu, 12 Feb 2026 16:58:25 -0500 Subject: [PATCH] fix: add cron model precedence regression coverage (openclaw#14983) thanks @shtse8 --- ....uses-last-non-empty-agent-text-as.test.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts b/src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts index 47d5b25e39b..09b3f0361f4 100644 --- a/src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts +++ b/src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts @@ -298,6 +298,99 @@ describe("runCronIsolatedAgentTurn", () => { }); }); + it("uses stored session override when no job model override is provided", async () => { + await withTempHome(async (home) => { + const storePath = await writeSessionStore(home, { + "agent:main:cron:job-1": { + sessionId: "existing-cron-session", + updatedAt: Date.now(), + providerOverride: "openai", + modelOverride: "gpt-4.1-mini", + }, + }); + const deps: CliDeps = { + sendMessageWhatsApp: vi.fn(), + sendMessageTelegram: vi.fn(), + sendMessageDiscord: vi.fn(), + sendMessageSignal: vi.fn(), + sendMessageIMessage: vi.fn(), + }; + vi.mocked(runEmbeddedPiAgent).mockResolvedValue({ + payloads: [{ text: "ok" }], + meta: { + durationMs: 5, + agentMeta: { sessionId: "s", provider: "p", model: "m" }, + }, + }); + + const res = await runCronIsolatedAgentTurn({ + cfg: makeCfg(home, storePath), + deps, + job: makeJob({ kind: "agentTurn", message: "do it", deliver: false }), + message: "do it", + sessionKey: "cron:job-1", + lane: "cron", + }); + + expect(res.status).toBe("ok"); + const call = vi.mocked(runEmbeddedPiAgent).mock.calls[0]?.[0] as { + provider?: string; + model?: string; + }; + expect(call?.provider).toBe("openai"); + expect(call?.model).toBe("gpt-4.1-mini"); + }); + }); + + it("prefers job model override over stored session override", async () => { + await withTempHome(async (home) => { + const storePath = await writeSessionStore(home, { + "agent:main:cron:job-1": { + sessionId: "existing-cron-session", + updatedAt: Date.now(), + providerOverride: "openai", + modelOverride: "gpt-4.1-mini", + }, + }); + const deps: CliDeps = { + sendMessageWhatsApp: vi.fn(), + sendMessageTelegram: vi.fn(), + sendMessageDiscord: vi.fn(), + sendMessageSignal: vi.fn(), + sendMessageIMessage: vi.fn(), + }; + vi.mocked(runEmbeddedPiAgent).mockResolvedValue({ + payloads: [{ text: "ok" }], + meta: { + durationMs: 5, + agentMeta: { sessionId: "s", provider: "p", model: "m" }, + }, + }); + + const res = await runCronIsolatedAgentTurn({ + cfg: makeCfg(home, storePath), + deps, + job: makeJob({ + kind: "agentTurn", + message: "do it", + model: "anthropic/claude-opus-4-5", + deliver: false, + }), + message: "do it", + sessionKey: "cron:job-1", + lane: "cron", + }); + + expect(res.status).toBe("ok"); + const call = vi.mocked(runEmbeddedPiAgent).mock.calls[0]?.[0] as { + provider?: string; + model?: string; + }; + expect(call?.provider).toBe("anthropic"); + expect(call?.model).toBe("claude-opus-4-5"); + }); + }); + it("uses hooks.gmail.model for Gmail hook sessions", async () => { await withTempHome(async (home) => { const storePath = await writeSessionStore(home);