diff --git a/src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts b/src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts index 5678b75e4f7..6316f394b9c 100644 --- a/src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts +++ b/src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts @@ -1,6 +1,7 @@ import "./isolated-agent.mocks.js"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js"; +import * as modelSelection from "../agents/model-selection.js"; import { runEmbeddedPiAgent } from "../agents/pi-embedded.js"; import { runSubagentAnnounceFlow } from "../agents/subagent-announce.js"; import type { CliDeps } from "../cli/deps.js"; @@ -72,6 +73,7 @@ async function runTelegramAnnounceTurn(params: { describe("runCronIsolatedAgentTurn", () => { beforeEach(() => { + vi.spyOn(modelSelection, "resolveThinkingDefault").mockReturnValue(undefined); setupIsolatedAgentTurnMocks({ fast: true }); }); diff --git a/src/cron/isolated-agent.model-formatting.test.ts b/src/cron/isolated-agent.model-formatting.test.ts index b09a9db5ea1..c783247e6f3 100644 --- a/src/cron/isolated-agent.model-formatting.test.ts +++ b/src/cron/isolated-agent.model-formatting.test.ts @@ -1,6 +1,7 @@ import "./isolated-agent.mocks.js"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { loadModelCatalog } from "../agents/model-catalog.js"; +import * as modelSelection from "../agents/model-selection.js"; import { runEmbeddedPiAgent } from "../agents/pi-embedded.js"; import { createCliDeps, mockAgentPayloads } from "./isolated-agent.delivery.test-helpers.js"; import { runCronIsolatedAgentTurn } from "./isolated-agent.js"; @@ -125,6 +126,7 @@ async function expectInvalidModel(home: string, model: string) { describe("cron model formatting and precedence edge cases", () => { beforeEach(() => { + vi.spyOn(modelSelection, "resolveThinkingDefault").mockReturnValue(undefined); vi.mocked(runEmbeddedPiAgent).mockClear(); vi.mocked(loadModelCatalog).mockResolvedValue([]); }); diff --git a/src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts b/src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts index 5abbb453f35..639c207459e 100644 --- a/src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts +++ b/src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts @@ -1,6 +1,7 @@ import "./isolated-agent.mocks.js"; import fs from "node:fs/promises"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import * as modelSelection from "../agents/model-selection.js"; import { runSubagentAnnounceFlow } from "../agents/subagent-announce.js"; import type { CliDeps } from "../cli/deps.js"; import { @@ -261,6 +262,7 @@ async function assertExplicitTelegramTargetDelivery(params: { describe("runCronIsolatedAgentTurn", () => { beforeEach(() => { + vi.spyOn(modelSelection, "resolveThinkingDefault").mockReturnValue(undefined); setupIsolatedAgentTurnMocks(); }); 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 2a4b786f99c..5830029d9e7 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 @@ -3,6 +3,7 @@ import fs from "node:fs/promises"; import path from "node:path"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { loadModelCatalog } from "../agents/model-catalog.js"; +import * as modelSelection from "../agents/model-selection.js"; import { runEmbeddedPiAgent } from "../agents/pi-embedded.js"; import type { CliDeps } from "../cli/deps.js"; import { runCronIsolatedAgentTurn } from "./isolated-agent.js"; @@ -15,6 +16,10 @@ import { } from "./isolated-agent.test-harness.js"; import type { CronJob } from "./types.js"; +let resolveThinkingDefaultSpy: ReturnType< + typeof vi.spyOn +>; + function makeDeps(): CliDeps { return { sendMessageSlack: vi.fn(), @@ -163,6 +168,9 @@ async function runStoredOverrideAndExpectModel(params: { describe("runCronIsolatedAgentTurn", () => { beforeEach(() => { + resolveThinkingDefaultSpy = vi + .spyOn(modelSelection, "resolveThinkingDefault") + .mockReturnValue(undefined); vi.mocked(runEmbeddedPiAgent).mockClear(); vi.mocked(loadModelCatalog).mockResolvedValue([]); }); @@ -503,16 +511,9 @@ describe("runCronIsolatedAgentTurn", () => { }); }); - it("defaults thinking to low for reasoning-capable models", async () => { + it("passes through the resolved default thinking level", async () => { await withTempHome(async (home) => { - vi.mocked(loadModelCatalog).mockResolvedValueOnce([ - { - id: "claude-opus-4-5", - name: "Opus 4.5", - provider: "anthropic", - reasoning: true, - }, - ]); + resolveThinkingDefaultSpy.mockReturnValueOnce("low"); await runCronTurn(home, { jobPayload: DEFAULT_AGENT_TURN_PAYLOAD, diff --git a/src/cron/isolated-agent/run.ts b/src/cron/isolated-agent/run.ts index 8a074338da7..9f3f28584e3 100644 --- a/src/cron/isolated-agent/run.ts +++ b/src/cron/isolated-agent/run.ts @@ -171,6 +171,27 @@ async function resolveCronDeliveryContext(params: { deliveryContract: IsolatedDeliveryContract; }) { const deliveryPlan = resolveCronDeliveryPlan(params.job); + if (!deliveryPlan.requested) { + const resolvedDelivery = { + ok: false as const, + channel: undefined, + to: undefined, + accountId: undefined, + threadId: undefined, + mode: "implicit" as const, + error: new Error("cron delivery not requested"), + }; + return { + deliveryPlan, + deliveryRequested: false, + resolvedDelivery, + toolPolicy: resolveCronToolPolicy({ + deliveryRequested: false, + resolvedDelivery, + deliveryContract: params.deliveryContract, + }), + }; + } const resolvedDelivery = await resolveDeliveryTarget(params.cfg, params.agentId, { channel: deliveryPlan.channel ?? "last", to: deliveryPlan.to,