61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
/**
|
|
* POST /api/chat/stop
|
|
*
|
|
* Abort an active agent run. Called by the Stop button.
|
|
* The child process is sent SIGTERM and the run transitions to "error" state.
|
|
*/
|
|
import { abortRun } from "@/lib/active-runs";
|
|
import {
|
|
abortSubagent,
|
|
hasActiveSubagent,
|
|
isSubagentRunning,
|
|
ensureRegisteredFromDisk,
|
|
} from "@/lib/subagent-runs";
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { resolveOpenClawStateDir } from "@/lib/workspace";
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
function deriveSubagentParentSessionId(sessionKey: string): string {
|
|
const registryPath = join(resolveOpenClawStateDir(), "subagents", "runs.json");
|
|
if (!existsSync(registryPath)) {return "";}
|
|
try {
|
|
const raw = JSON.parse(readFileSync(registryPath, "utf-8")) as {
|
|
runs?: Record<string, Record<string, unknown>>;
|
|
};
|
|
for (const entry of Object.values(raw.runs ?? {})) {
|
|
if (entry.childSessionKey !== sessionKey) {continue;}
|
|
const requester = typeof entry.requesterSessionKey === "string" ? entry.requesterSessionKey : "";
|
|
const match = requester.match(/^agent:[^:]+:web:(.+)$/);
|
|
return match?.[1] ?? "";
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
return "";
|
|
}
|
|
|
|
export async function POST(req: Request) {
|
|
const body: { sessionId?: string; sessionKey?: string } = await req
|
|
.json()
|
|
.catch(() => ({}));
|
|
|
|
const isSubagentSession = typeof body.sessionKey === "string" && body.sessionKey.includes(":subagent:");
|
|
if (isSubagentSession && body.sessionKey) {
|
|
if (!hasActiveSubagent(body.sessionKey)) {
|
|
const parentWebSessionId = deriveSubagentParentSessionId(body.sessionKey);
|
|
ensureRegisteredFromDisk(body.sessionKey, parentWebSessionId);
|
|
}
|
|
const aborted = isSubagentRunning(body.sessionKey) ? abortSubagent(body.sessionKey) : false;
|
|
return Response.json({ aborted });
|
|
}
|
|
|
|
if (!body.sessionId) {
|
|
return new Response("sessionId or subagent sessionKey required", { status: 400 });
|
|
}
|
|
|
|
const aborted = abortRun(body.sessionId);
|
|
return Response.json({ aborted });
|
|
}
|