diff --git a/src/features/background-agent/abort-with-timeout.test.ts b/src/features/background-agent/abort-with-timeout.test.ts index 3655a4172..46b34e917 100644 --- a/src/features/background-agent/abort-with-timeout.test.ts +++ b/src/features/background-agent/abort-with-timeout.test.ts @@ -37,6 +37,22 @@ describe("abortWithTimeout", () => { expect(logMock).not.toHaveBeenCalled() }) + test("#given abort resolves with an SDK error response #when abortWithTimeout runs #then it reports cancellation failure", async () => { + // given + const error = { message: "session not found" } + const abort = mock(async () => ({ error })) + + // when + const result = await abortWithTimeout(createClient(abort), "session-error-response", 10) + + // then + expect(result).toBe(false) + expect(logMock).toHaveBeenCalledWith( + "[background-agent] Session abort returned an error response:", + { sessionID: "session-error-response", error }, + ) + }) + test("#given abort hangs indefinitely #when abortWithTimeout runs #then it logs warning and continues", async () => { // given const abort = mock(() => new Promise(() => {})) diff --git a/src/features/background-agent/abort-with-timeout.ts b/src/features/background-agent/abort-with-timeout.ts index 49f1170f2..9e4d9d7a6 100644 --- a/src/features/background-agent/abort-with-timeout.ts +++ b/src/features/background-agent/abort-with-timeout.ts @@ -1,6 +1,13 @@ import { log } from "../../shared" +import { isRecord } from "../../shared/record-type-guard" import type { OpencodeClient } from "./opencode-client" +function getAbortResponseError(response: unknown): unknown | undefined { + if (!isRecord(response)) return undefined + const error = response.error + return error === undefined || error === null ? undefined : error +} + export async function abortWithTimeout( client: OpencodeClient, sessionID: string, @@ -10,7 +17,26 @@ export async function abortWithTimeout( try { const result = await Promise.race([ - client.session.abort({ path: { id: sessionID } }).then(() => "aborted" as const), + client.session.abort({ path: { id: sessionID } }).then( + (response) => { + const error = getAbortResponseError(response) + if (error !== undefined) { + log("[background-agent] Session abort returned an error response:", { + sessionID, + error, + }) + return "failed" as const + } + return "aborted" as const + }, + (error) => { + log("[background-agent] Session abort failed:", { + sessionID, + error, + }) + return "failed" as const + }, + ), new Promise<"timed_out">((resolve) => { timeoutHandle = setTimeout(() => { resolve("timed_out") @@ -26,7 +52,7 @@ export async function abortWithTimeout( return false } - return true + return result === "aborted" } finally { if (timeoutHandle) { clearTimeout(timeoutHandle)