From 2499accca03e189cbf97e2a34bf2e884791832eb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 7 Apr 2026 09:41:51 +0800 Subject: [PATCH] Tests: move cron message-tool skip to seam --- ...p-recipient-besteffortdeliver-true.test.ts | 36 ----------------- .../run.message-tool-policy.test.ts | 40 +++++++++++++++++++ src/cron/isolated-agent/run.test-harness.ts | 32 +++++++++++++++ 3 files changed, 72 insertions(+), 36 deletions(-) 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 d319e156072..86cc5e0951a 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 @@ -24,17 +24,6 @@ vi.mock("../agents/auth-profiles/session-override.js", () => ({ })); const TELEGRAM_TARGET = { mode: "announce", channel: "telegram", to: "123" } as const; -async function runExplicitTelegramAnnounceTurn(params: { - home: string; - storePath: string; - deps: CliDeps; - deliveryContract?: "cron-owned" | "shared"; -}): Promise>> { - return runTelegramAnnounceTurn({ - ...params, - delivery: TELEGRAM_TARGET, - }); -} async function withTelegramAnnounceFixture( run: (params: { home: string; storePath: string; deps: CliDeps }) => Promise, @@ -53,11 +42,6 @@ async function withTelegramAnnounceFixture( }); } -function expectDeliveredOk(result: Awaited>): void { - expect(result.status).toBe("ok"); - expect(result.delivered).toBe(true); -} - async function expectBestEffortTelegramNotDelivered( payload: Record, ): Promise { @@ -248,26 +232,6 @@ describe("runCronIsolatedAgentTurn", () => { setupIsolatedAgentTurnMocks({ fast: true }); }); - it("skips announce when messaging tool already sent to target", async () => { - await withTelegramAnnounceFixture(async ({ home, storePath, deps }) => { - mockAgentPayloads([{ text: "sent" }], { - didSendViaMessagingTool: true, - messagingToolSentTargets: [{ tool: "message", provider: "telegram", to: "123" }], - }); - - const res = await runExplicitTelegramAnnounceTurn({ - home, - storePath, - deps, - deliveryContract: "shared", - }); - - expectDeliveredOk(res); - expect(runSubagentAnnounceFlow).not.toHaveBeenCalled(); - expect(deps.sendMessageTelegram).not.toHaveBeenCalled(); - }); - }); - it("reports not-delivered when best-effort structured outbound sends all fail", async () => { await expectBestEffortTelegramNotDelivered({ text: "caption", diff --git a/src/cron/isolated-agent/run.message-tool-policy.test.ts b/src/cron/isolated-agent/run.message-tool-policy.test.ts index a92b19f5337..314250a80d4 100644 --- a/src/cron/isolated-agent/run.message-tool-policy.test.ts +++ b/src/cron/isolated-agent/run.message-tool-policy.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { clearFastTestEnv, + dispatchCronDeliveryMock, loadRunCronIsolatedAgentTurn, mockRunCronFallbackPassthrough, resetRunCronIsolatedAgentTurnHarness, @@ -92,4 +93,43 @@ describe("runCronIsolatedAgentTurn message tool policy", () => { expect(runEmbeddedPiAgentMock).toHaveBeenCalledTimes(1); expect(runEmbeddedPiAgentMock.mock.calls[0]?.[0]?.disableMessageTool).toBe(false); }); + + it("skips cron delivery when a shared caller already sent to the same target", async () => { + mockRunCronFallbackPassthrough(); + const params = makeParams(); + const job = { + id: "message-tool-policy", + name: "Message Tool Policy", + schedule: { kind: "every", everyMs: 60_000 }, + sessionTarget: "isolated", + payload: { kind: "agentTurn", message: "send a message" }, + delivery: { mode: "announce", channel: "telegram", to: "123" }, + } as const; + resolveCronDeliveryPlanMock.mockReturnValue({ + requested: true, + mode: "announce", + channel: "telegram", + to: "123", + }); + runEmbeddedPiAgentMock.mockResolvedValue({ + payloads: [{ text: "sent" }], + didSendViaMessagingTool: true, + messagingToolSentTargets: [{ tool: "message", provider: "telegram", to: "123" }], + meta: { agentMeta: { usage: { input: 10, output: 20 } } }, + }); + + await runCronIsolatedAgentTurn({ + ...params, + deliveryContract: "shared", + job: job as never, + }); + + expect(dispatchCronDeliveryMock).toHaveBeenCalledTimes(1); + expect(dispatchCronDeliveryMock.mock.calls[0]?.[0]).toEqual( + expect.objectContaining({ + deliveryRequested: true, + skipMessagingToolDelivery: true, + }), + ); + }); }); diff --git a/src/cron/isolated-agent/run.test-harness.ts b/src/cron/isolated-agent/run.test-harness.ts index 4c9921a3859..8965bc78dfc 100644 --- a/src/cron/isolated-agent/run.test-harness.ts +++ b/src/cron/isolated-agent/run.test-harness.ts @@ -63,6 +63,7 @@ export const pickLastNonEmptyTextFromPayloadsMock = createMock(); export const resolveCronPayloadOutcomeMock = createMock(); export const resolveCronDeliveryPlanMock = createMock(); export const resolveDeliveryTargetMock = createMock(); +export const dispatchCronDeliveryMock = createMock(); export const resolveSessionAuthProfileOverrideMock = createMock(); export const resolveFastModeStateMock = createMock(); @@ -165,6 +166,15 @@ vi.mock("./delivery-target.js", () => ({ resolveDeliveryTarget: resolveDeliveryTargetMock, })); +vi.mock("./delivery-dispatch.js", async () => { + const actual = + await vi.importActual("./delivery-dispatch.js"); + return { + ...actual, + dispatchCronDelivery: dispatchCronDeliveryMock, + }; +}); + vi.mock("./helpers.js", () => ({ isHeartbeatOnlyResponse: vi.fn().mockReturnValue(false), pickLastDeliverablePayload: vi.fn().mockReturnValue(undefined), @@ -328,6 +338,28 @@ function resetRunOutcomeMocks(): void { accountId: undefined, error: undefined, }); + dispatchCronDeliveryMock.mockReset(); + dispatchCronDeliveryMock.mockImplementation( + ({ + deliveryPayloads, + summary, + outputText, + synthesizedText, + deliveryRequested, + skipHeartbeatDelivery, + skipMessagingToolDelivery, + }) => ({ + result: undefined, + delivered: Boolean(deliveryRequested && !skipHeartbeatDelivery && !skipMessagingToolDelivery), + deliveryAttempted: Boolean( + deliveryRequested && !skipHeartbeatDelivery && !skipMessagingToolDelivery, + ), + summary, + outputText, + synthesizedText, + deliveryPayloads, + }), + ); resolveSessionAuthProfileOverrideMock.mockReset(); resolveSessionAuthProfileOverrideMock.mockResolvedValue(undefined); }