fix(delegate-task): recover aborted-operation messages in sync flows

This commit is contained in:
YeonGyu-Kim
2026-05-11 09:01:17 +09:00
parent 468bf25dcb
commit e018739d2c
4 changed files with 113 additions and 2 deletions
@@ -244,6 +244,62 @@ describe("executeSyncContinuation - toast cleanup error paths", () => {
expect(removeTaskCalls[0]).toBe("resume_sync_ses_test")
})
test("recovers from canonical aborted-operation message", async () => {
const mockClient = {
session: {
messages: async () => ({
data: [
{ info: { id: "msg_001", role: "user", time: { created: 1000 } } },
{
info: { id: "msg_002", role: "assistant", time: { created: 2000 }, finish: "end_turn" },
parts: [{ type: "text", text: "Response" }],
},
],
}),
promptAsync: async () => ({}),
status: async () => ({
data: { ses_test: { type: "idle" } },
}),
},
}
const { executeSyncContinuation } = require("./sync-continuation")
const deps = {
pollSyncSession: async () => "The operation was aborted.",
fetchSyncResult: async () => ({ ok: true as const, textContent: "Recovered result" }),
}
const mockCtx = {
sessionID: "parent-session",
callID: "call-123",
metadata: () => {},
}
const mockExecutorCtx = {
client: mockClient,
}
const args = {
task_id: "ses_test_12345678",
prompt: "test prompt",
description: "test task",
category: "test",
load_skills: [],
run_in_background: false,
}
//#when
const result = await executeSyncContinuation(args, mockCtx, mockExecutorCtx, {
sessionID: "parent-session",
messageID: "parent-message",
}, deps)
//#then
expect(result).toContain("Task continued and completed in")
expect(result).toContain("Recovered result")
})
test("returns MessageAbortedError poll error when recovery fetch has no result", async () => {
const mockClient = {
session: {
@@ -43,6 +43,10 @@ function shouldAttemptPollErrorRecovery(pollError: string): boolean {
return true
}
if (/^the operation was aborted\.?$/iu.test(trimmed)) {
return true
}
return false
}
+49 -2
View File
@@ -224,6 +224,53 @@ describe("executeSyncTask - cleanup on error paths", () => {
expect(deleteCalls[0]).toBe("ses_test_12345678")
})
test("recovers from canonical aborted-operation message", async () => {
const mockClient = {
session: {
create: async () => ({ data: { id: "ses_test_12345678" } }),
},
}
const { executeSyncTask } = require("./sync-task")
const deps = {
createSyncSession: async () => ({ ok: true, sessionID: "ses_test_12345678" }),
sendSyncPrompt: async () => null,
pollSyncSession: async () => "The operation was aborted.",
fetchSyncResult: async () => ({ ok: true as const, textContent: "Recovered result" }),
}
const mockCtx = {
sessionID: "parent-session",
callID: "call-123",
metadata: () => {},
}
const mockExecutorCtx = {
client: mockClient,
directory: "/tmp",
onSyncSessionCreated: null,
}
const args = {
prompt: "test prompt",
description: "test task",
category: "test",
load_skills: [],
run_in_background: false,
command: null,
}
//#when
const result = await executeSyncTask(args, mockCtx, mockExecutorCtx, {
sessionID: "parent-session",
}, "test-agent", undefined, undefined, undefined, undefined, deps)
//#then
expect(result).toContain("Task completed in")
expect(result).toContain("Recovered result")
})
test("does not recover from non-abort poll error containing abort-like words", async () => {
const mockClient = {
session: {
@@ -607,7 +654,7 @@ describe("executeSyncTask - cleanup on error paths", () => {
expect(result).toContain("Result from ses_second")
expect(deleteCalls).toContain("ses_first")
const finalMetadata = metadataCalls.at(-1)
const finalMetadata = metadataCalls[metadataCalls.length - 1]
expect(finalMetadata.metadata.sessionId).toBe("ses_second")
expect(finalMetadata.metadata.taskId).toBe("ses_second")
expect(finalMetadata.metadata.model).toEqual({
@@ -758,7 +805,7 @@ describe("executeSyncTask - cleanup on error paths", () => {
}, "sisyphus-junior", initialModel, undefined, undefined, fallbackChain, deps)
expect(result).toBe("Final retry failed")
const finalMetadata = metadataCalls.at(-1)
const finalMetadata = metadataCalls[metadataCalls.length - 1]
expect(finalMetadata.metadata.sessionId).toBe("ses_second")
expect(finalMetadata.metadata.taskId).toBe("ses_second")
expect(finalMetadata.metadata.model).toEqual({
+4
View File
@@ -34,6 +34,10 @@ function shouldAttemptPollErrorRecovery(pollError: string): boolean {
return true
}
if (/^the operation was aborted\.?$/iu.test(trimmed)) {
return true
}
return false
}