|
6 | 6 |
|
7 | 7 | import type { ReactorEmittedEvent } from "@intx/inference"; |
8 | 8 | import { DEFAULT_CLOSE_DEADLINE_MS } from "./dispose.js"; |
9 | | -import { stopReasonFromReport } from "./report.js"; |
| 9 | +import type { ForcedStopReason } from "./stop-policy.js"; |
10 | 10 | import { toolCallPreview } from "./tool-preview.js"; |
11 | 11 |
|
12 | 12 | export type SubAgentSessionStatus = "running" | "done" | "failed" | "cancelled"; |
@@ -79,9 +79,8 @@ export interface SubAgentSession { |
79 | 79 | report?: string; |
80 | 80 | error?: string; |
81 | 81 | /** |
82 | | - * Machine-readable termination reason for a forced stop (stall abort, |
83 | | - * operator cancel) — the report's `Stopped:` line, or `cancelled — <reason>` |
84 | | - * on cancel. Absent on clean completes. |
| 82 | + * Typed ForcedStopReason from runSubAgent, or `cancelled — <reason>` on |
| 83 | + * cancel(). Absent on clean completes. Never parsed from report prose. |
85 | 84 | */ |
86 | 85 | stopReason?: string; |
87 | 86 | // Session id of the orchestrator that dispatched this worker, when this is |
@@ -147,7 +146,11 @@ export interface SubAgentSessionStore { |
147 | 146 | // deadline/cancel salvage resolves the same promise agent-fleet routes |
148 | 147 | // here but always disposes its agent first, so omitting/false-ing this |
149 | 148 | // keeps a disposed session from ever reporting as resumable. |
150 | | - complete(id: string, report: string, opts?: { agentRetained?: boolean }): void; |
| 149 | + complete( |
| 150 | + id: string, |
| 151 | + report: string, |
| 152 | + opts?: { agentRetained?: boolean; stopReason?: ForcedStopReason }, |
| 153 | + ): void; |
151 | 154 | fail(id: string, error: string): void; |
152 | 155 | // Register the live abort handle for a running session so cancel() can stop |
153 | 156 | // the child reactor (agent.close), not only flip status. |
@@ -767,7 +770,11 @@ export function createSubAgentSessionStore( |
767 | 770 | }); |
768 | 771 | }, |
769 | 772 |
|
770 | | - complete(id: string, report: string, opts?: { agentRetained?: boolean }): void { |
| 773 | + complete( |
| 774 | + id: string, |
| 775 | + report: string, |
| 776 | + opts?: { agentRetained?: boolean; stopReason?: ForcedStopReason }, |
| 777 | + ): void { |
771 | 778 | // CL-7001: run.ts always disposes on a salvage return (deadline/cancel) |
772 | 779 | // even though it resolves through this same success path — only trust |
773 | 780 | // "still open, resumable" when the caller says the agent genuinely |
@@ -795,10 +802,7 @@ export function createSubAgentSessionStore( |
795 | 802 | session.finishedAt = now(); |
796 | 803 | clearToolCalls(session); |
797 | 804 | session.report = report; |
798 | | - // A forced-stop salvage arrives via complete(); its Stopped: line is |
799 | | - // the terminal reason (stall abort, etc). |
800 | | - const stopped = stopReasonFromReport(report); |
801 | | - if (stopped !== null) session.stopReason = stopped; |
| 805 | + if (opts?.stopReason !== undefined) session.stopReason = opts.stopReason; |
802 | 806 | pushEntry(session, { kind: "report", content: capText(report, maxEntryChars) }); |
803 | 807 | // A disposed salvage has nothing left for its close handle to do — |
804 | 808 | // release it now rather than leaving a stale reference around. |
|
0 commit comments