import * as path from "node:path"; import type { AgentToolResult } from "@earendil-works/pi-agent-core"; import type { Details, SubagentState } from "../../shared/types.ts"; import { deliverStopRequest } from "../background/control-channel.ts"; import { reconcileAsyncRun } from "../background/stale-run-reconciler.ts"; function getAsyncStopTarget( state: SubagentState, runId: string | undefined, location?: { asyncDir: string | null; resolvedId?: string }, ): { asyncId: string; asyncDir: string } | undefined { if (location?.asyncDir) { return { asyncId: location.resolvedId ?? runId ?? path.basename(location.asyncDir), asyncDir: location.asyncDir, }; } if (!runId) return undefined; const direct = state.asyncJobs.get(runId); return direct ? { asyncId: direct.asyncId, asyncDir: direct.asyncDir } : undefined; } export function stopAsyncRun( state: SubagentState, runId: string | undefined, kill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean, location?: { asyncDir: string | null; resolvedId?: string }, ): AgentToolResult
| null { const target = getAsyncStopTarget(state, runId, location); if (!target) return null; const status = reconcileAsyncRun(target.asyncDir, { kill }).status; if (state.currentSessionId && status?.sessionId !== state.currentSessionId) { return { content: [{ type: "text", text: `Async run '${target.asyncId}' was not found in the active session.` }], isError: true, details: { mode: "management", results: [] }, }; } if (!status || (status.state !== "running" && status.state !== "queued")) { return { content: [{ type: "text", text: `No running or queued async run was found for '${runId ?? "current"}'.` }], isError: true, details: { mode: "management", results: [] }, }; } try { deliverStopRequest({ asyncDir: target.asyncDir, pid: typeof status.pid === "number" ? status.pid : undefined, kill, source: "stop-action" }); const tracked = state.asyncJobs.get(target.asyncId); if (tracked) { tracked.activityState = undefined; tracked.updatedAt = Date.now(); } return { content: [{ type: "text", text: `Stop requested for async run ${target.asyncId}.` }], details: { mode: "management", results: [] }, }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Failed to stop async run ${target.asyncId}: ${message}` }], isError: true, details: { mode: "management", results: [] }, }; } }