diff --git a/src/tools/delegate-task/unstable-agent-task.terminal-fast-path.test.ts b/src/tools/delegate-task/unstable-agent-task.terminal-fast-path.test.ts new file mode 100644 index 000000000..44eb4cb3a --- /dev/null +++ b/src/tools/delegate-task/unstable-agent-task.terminal-fast-path.test.ts @@ -0,0 +1,67 @@ +/// +import { describe, expect, test } from "bun:test" +import { unsafeTestValue } from "../../../test-support/unsafe-test-value" +import { executeUnstableAgentTask } from "./unstable-agent-task" +import type { DelegateTaskArgs } from "./types" + +const args: DelegateTaskArgs = { + description: "terminal task", + prompt: "do it", + category: "quick", + load_skills: [], + run_in_background: false, +} + +describe("executeUnstableAgentTask terminal fast path", () => { + test("#given launched task is already interrupted #when monitoring starts #then it returns without waiting for the poll interval", async () => { + // given + const startedAt = Date.now() + + // when + const output = await executeUnstableAgentTask( + args, + { + sessionID: "ses_parent", + messageID: "msg_parent", + agent: "sisyphus", + abort: new AbortController().signal, + }, + unsafeTestValue({ + manager: { + launch: async () => ({ + id: "bg_terminal", + sessionId: "ses_terminal", + description: "terminal task", + agent: "sisyphus-junior", + status: "interrupt", + error: "already stopped", + }), + getTask: () => ({ + id: "bg_terminal", + sessionId: "ses_terminal", + description: "terminal task", + agent: "sisyphus-junior", + status: "interrupt", + error: "already stopped", + }), + }, + client: { + session: { + status: async () => ({ data: {} }), + messages: async () => ({ data: [] }), + }, + }, + }), + { sessionID: "ses_parent", messageID: "msg_parent", agent: "sisyphus" }, + "sisyphus-junior", + undefined, + undefined, + "test-model", + ) + + // then + expect(Date.now() - startedAt).toBeLessThan(200) + expect(output).toContain("SUPERVISED TASK FAILED") + expect(output).toContain("already stopped") + }) +}) diff --git a/src/tools/delegate-task/unstable-agent-task.ts b/src/tools/delegate-task/unstable-agent-task.ts index 0f9c026dd..e34ce20fe 100644 --- a/src/tools/delegate-task/unstable-agent-task.ts +++ b/src/tools/delegate-task/unstable-agent-task.ts @@ -108,13 +108,19 @@ export async function executeUnstableAgentTask( return `Task aborted (was running in background mode).\n\nSession ID: ${sessionID}` } - await new Promise(resolve => setTimeout(resolve, timingCfg.POLL_INTERVAL_MS)) - const currentTask = manager.getTask(task.id) if (currentTask && (currentTask.status === "interrupt" || currentTask.status === "error" || currentTask.status === "cancelled")) { terminalStatus = { status: currentTask.status, error: currentTask.error } break } + if (currentTask?.status === "completed") { + completedDuringMonitoring = true + break + } + + const timeoutBudgetMs = syncPollTimeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS + const remainingBudgetMs = timeoutBudgetMs - (Date.now() - pollStart) + await new Promise(resolve => setTimeout(resolve, Math.min(timingCfg.POLL_INTERVAL_MS, Math.max(1, remainingBudgetMs)))) const statusResult = await client.session.status() const allStatuses = normalizeSDKResponse(statusResult, {} as Record)