diff --git a/src/mgr/queue-dispatch.ts b/src/mgr/queue-dispatch.ts index 1c19b96..1582c46 100644 --- a/src/mgr/queue-dispatch.ts +++ b/src/mgr/queue-dispatch.ts @@ -1,5 +1,5 @@ import { AgentRunError } from "../common/errors.js"; -import type { CreateRunInput, JsonRecord, JsonValue, QueueAttemptRef, QueueDispatchResult, QueueTaskRecord, QueueTaskState, RunRecord } from "../common/types.js"; +import type { CommandRecord, CreateRunInput, JsonRecord, JsonValue, QueueAttemptRef, QueueDispatchResult, QueueTaskRecord, QueueTaskState, RunRecord } from "../common/types.js"; import { asRecord } from "../common/validation.js"; import type { AgentRunStore } from "./store.js"; import { isTerminalQueueTaskState } from "./store.js"; @@ -66,7 +66,7 @@ export async function refreshQueueTaskFromCore(store: AgentRunStore, taskId: str if (!latestAttempt?.runId || !latestAttempt.commandId) throw new AgentRunError("schema-invalid", `queue task ${taskId} has no Core attempt to refresh`, { httpStatus: 409 }); const [run, command] = await Promise.all([store.getRun(latestAttempt.runId), store.getCommand(latestAttempt.commandId)]); if (command.runId !== run.id) throw new AgentRunError("schema-invalid", `queue task ${taskId} attempt references mismatched run and command`, { httpStatus: 409 }); - const state = queueStateFromRun(run); + const state = queueStateFromCore(run, command); const sessionId = run.sessionRef?.sessionId ?? latestAttempt.sessionId ?? null; const sessionPath = sessionId ? `/api/v1/sessions/${encodeURIComponent(sessionId)}` : latestAttempt.sessionPath ?? null; const nextAttempt: QueueAttemptRef = { ...latestAttempt, state, sessionId, sessionPath }; @@ -81,7 +81,10 @@ function assertDispatchable(task: QueueTaskRecord): void { if (!task.executionPolicy) throw new AgentRunError("schema-invalid", "queue dispatch requires executionPolicy", { httpStatus: 400 }); } -function queueStateFromRun(run: RunRecord): QueueTaskState { +function queueStateFromCore(run: RunRecord, command: CommandRecord): QueueTaskState { + if (command.state === "completed") return "completed"; + if (command.state === "failed") return "failed"; + if (command.state === "cancelled") return "cancelled"; if (run.status === "completed") return "completed"; if (run.status === "failed") return "failed"; if (run.status === "blocked") return "blocked"; diff --git a/src/selftest/cases/75-queue-q2-dispatch.ts b/src/selftest/cases/75-queue-q2-dispatch.ts index 00d3962..b970ff4 100644 --- a/src/selftest/cases/75-queue-q2-dispatch.ts +++ b/src/selftest/cases/75-queue-q2-dispatch.ts @@ -84,7 +84,6 @@ console.log(JSON.stringify({ apiVersion: manifest.apiVersion, kind: manifest.kin (error) => error instanceof Error && error.message.includes("not pending"), ); await client.patch(`/api/v1/commands/${dispatched.command.id}/status`, { terminalStatus: "completed", failureKind: null, failureMessage: null }); - await client.patch(`/api/v1/runs/${dispatched.run.id}/status`, { terminalStatus: "completed", failureKind: null, failureMessage: null }); const refreshed = await client.post(`/api/v1/queue/tasks/${created.id}/refresh`, {}) as QueueTaskRecord; assert.equal(refreshed.state, "completed"); assert.equal(refreshed.latestAttempt?.state, "completed");