From 8ba82534e6c98410e19b226f3534b285fd75d278 Mon Sep 17 00:00:00 2001 From: Josh Lehman Date: Sun, 26 Apr 2026 13:30:54 -0700 Subject: [PATCH] fix: preserve cron telegram topic delivery after timeout (#72317) --- ...gent.direct-delivery-core-channels.test.ts | 12 +++++++ src/cron/isolated-agent/run-executor.ts | 1 + .../isolated-agent/run.skill-filter.test.ts | 35 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/cron/isolated-agent.direct-delivery-core-channels.test.ts b/src/cron/isolated-agent.direct-delivery-core-channels.test.ts index 9a59c793c1c..6af4a869d82 100644 --- a/src/cron/isolated-agent.direct-delivery-core-channels.test.ts +++ b/src/cron/isolated-agent.direct-delivery-core-channels.test.ts @@ -363,6 +363,18 @@ describe("runCronIsolatedAgentTurn telegram forum-topic direct delivery", () => }); }); + it("preserves explicit supergroup topic targets for cron announce delivery", async () => { + await expectTelegramAnnounceDelivery({ + to: "-1003774691294:topic:47", + payloads: [{ text: "topic 47 completion" }], + expected: { + chatId: "-1003774691294", + text: "topic 47 completion", + messageThreadId: 47, + }, + }); + }); + it("delivers only the final assistant-visible text to forum-topic telegram targets", async () => { await expectTelegramAnnounceDelivery({ to: "123:topic:42", diff --git a/src/cron/isolated-agent/run-executor.ts b/src/cron/isolated-agent/run-executor.ts index 2941c39835e..9beb0b1cb33 100644 --- a/src/cron/isolated-agent/run-executor.ts +++ b/src/cron/isolated-agent/run-executor.ts @@ -143,6 +143,7 @@ export function createCronPromptExecutor(params: { cliSessionId, skillsSnapshot: params.skillsSnapshot, messageChannel: params.messageChannel, + abortSignal: params.abortSignal, bootstrapPromptWarningSignaturesSeen, bootstrapPromptWarningSignature, senderIsOwner: true, diff --git a/src/cron/isolated-agent/run.skill-filter.test.ts b/src/cron/isolated-agent/run.skill-filter.test.ts index 7be58645924..87ab88c243b 100644 --- a/src/cron/isolated-agent/run.skill-filter.test.ts +++ b/src/cron/isolated-agent/run.skill-filter.test.ts @@ -6,6 +6,7 @@ import { } from "./run.suite-helpers.js"; import { buildWorkspaceSkillSnapshotMock, + dispatchCronDeliveryMock, getCliSessionIdMock, isCliProviderMock, lookupContextTokensMock, @@ -257,6 +258,40 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { }); describe("CLI session handoff (issue #29774)", () => { + it("passes the cron abort signal to CLI runs and drops late CLI results", async () => { + const abortController = new AbortController(); + let markCliStarted!: () => void; + const cliStarted = new Promise((resolve) => { + markCliStarted = resolve; + }); + + isCliProviderMock.mockReturnValue(true); + runCliAgentMock.mockImplementationOnce(async (params: { abortSignal?: AbortSignal }) => { + expect(params.abortSignal).toBe(abortController.signal); + markCliStarted(); + await new Promise((resolve) => { + params.abortSignal?.addEventListener("abort", () => resolve(), { once: true }); + }); + return { + payloads: [{ text: "late cli output" }], + meta: { agentMeta: { sessionId: "late-cli-session", usage: { input: 5, output: 10 } } }, + }; + }); + mockCliFallbackInvocation(); + + const runPromise = runCronIsolatedAgentTurn( + makeSkillParams({ abortSignal: abortController.signal }), + ); + await cliStarted; + abortController.abort("cron: job execution timed out"); + + const result = await runPromise; + + expect(result.status).toBe("error"); + expect(result.error).toBe("cron: job execution timed out"); + expect(dispatchCronDeliveryMock).not.toHaveBeenCalled(); + }); + it("does not pass stored cliSessionId on fresh isolated runs (isNewSession=true)", async () => { // Simulate a persisted CLI session ID from a previous run. getCliSessionIdMock.mockReturnValue("prev-cli-session-abc");