From 05c06fc46769bc4403fa37e1557ded7ef58cd9be Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Sun, 29 Mar 2026 18:47:26 +0900 Subject: [PATCH] feat: graceful agent abort on SIGTERM via AbortController When /stop sends SIGTERM, the runner now calls AbortController.abort() on the Claude SDK query, allowing graceful cleanup of in-flight API requests before the process exits. Falls back to SIGKILL after 5s. --- runners/agent-runner/src/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/runners/agent-runner/src/index.ts b/runners/agent-runner/src/index.ts index ebfc342..81eda16 100644 --- a/runners/agent-runner/src/index.ts +++ b/runners/agent-runner/src/index.ts @@ -287,6 +287,13 @@ function log(message: string): void { console.error(`[agent-runner] ${message}`); } +// Graceful shutdown: SIGTERM → abort SDK query, allowing cleanup +const agentAbortController = new AbortController(); +process.on('SIGTERM', () => { + log('Received SIGTERM, aborting agent query...'); + agentAbortController.abort(); +}); + function extractAssistantText(message: unknown): string | null { const assistant = message as { message?: { @@ -755,6 +762,7 @@ async function runQuery( permissionMode: 'bypassPermissions', allowDangerouslySkipPermissions: true, settingSources: ['project', 'user'], + abortController: agentAbortController, mcpServers: { ejclaw: { command: 'node', @@ -1089,6 +1097,7 @@ async function main(): Promise { permissionMode: 'bypassPermissions' as const, allowDangerouslySkipPermissions: true, settingSources: ['project', 'user'] as const, + abortController: agentAbortController, hooks: { PreCompact: [{ hooks: [createPreCompactHook(containerInput.assistantName)] }], },