Skip to content

Commit aec5e20

Browse files
authored
fix: clean up codex on shut down (#836)
1 parent 8ed432a commit aec5e20

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

packages/agent/src/adapters/acp-connection.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
22
import { POSTHOG_NOTIFICATIONS } from "@/acp-extensions.js";
33
import type { SessionLogWriter } from "@/session-log-writer.js";
4+
import type { ProcessSpawnedCallback } from "@/types.js";
45
import { Logger } from "@/utils/logger.js";
56
import {
67
createBidirectionalStreams,
@@ -9,10 +10,7 @@ import {
910
nodeWritableToWebWritable,
1011
type StreamPair,
1112
} from "@/utils/streams.js";
12-
import {
13-
ClaudeAcpAgent,
14-
type ClaudeAcpAgentOptions,
15-
} from "./claude/claude-agent.js";
13+
import { ClaudeAcpAgent } from "./claude/claude-agent.js";
1614
import { type CodexProcessOptions, spawnCodexProcess } from "./codex/spawn.js";
1715

1816
export type AgentAdapter = "claude" | "codex";
@@ -25,7 +23,7 @@ export type AcpConnectionConfig = {
2523
/** Deployment environment - "local" for desktop, "cloud" for cloud sandbox */
2624
deviceType?: "local" | "cloud";
2725
logger?: Logger;
28-
processCallbacks?: ClaudeAcpAgentOptions;
26+
processCallbacks?: ProcessSpawnedCallback;
2927
codexOptions?: CodexProcessOptions;
3028
allowedModelIds?: Set<string>;
3129
};
@@ -239,6 +237,7 @@ function createCodexConnection(config: AcpConnectionConfig): AcpConnection {
239237
const codexProcess = spawnCodexProcess({
240238
...config.codexOptions,
241239
logger,
240+
processCallbacks: config.processCallbacks,
242241
});
243242

244243
let clientReadable = nodeReadableToWebReadable(codexProcess.stdout);

packages/agent/src/adapters/codex/spawn.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type ChildProcess, spawn } from "node:child_process";
22
import { existsSync } from "node:fs";
33
import type { Readable, Writable } from "node:stream";
4+
import type { ProcessSpawnedCallback } from "@/types.js";
45
import { Logger } from "@/utils/logger.js";
56

67
export interface CodexProcessOptions {
@@ -10,6 +11,7 @@ export interface CodexProcessOptions {
1011
model?: string;
1112
binaryPath?: string;
1213
logger?: Logger;
14+
processCallbacks?: ProcessSpawnedCallback;
1315
}
1416

1517
export interface CodexProcess {
@@ -97,18 +99,28 @@ export function spawnCodexProcess(options: CodexProcessOptions): CodexProcess {
9799

98100
child.on("exit", (code, signal) => {
99101
logger.info("codex-acp process exited", { code, signal });
102+
if (child.pid && options.processCallbacks?.onProcessExited) {
103+
options.processCallbacks.onProcessExited(child.pid);
104+
}
100105
});
101106

102107
if (!child.stdin || !child.stdout) {
103108
throw new Error("Failed to get stdio streams from codex-acp process");
104109
}
105110

111+
if (child.pid && options.processCallbacks?.onProcessSpawned) {
112+
options.processCallbacks.onProcessSpawned({
113+
pid: child.pid,
114+
command,
115+
});
116+
}
117+
106118
return {
107119
process: child,
108120
stdin: child.stdin,
109121
stdout: child.stdout,
110122
kill: () => {
111-
logger.info("Killing codex-acp process");
123+
logger.info("Killing codex-acp process", { pid: child.pid });
112124
child.kill("SIGTERM");
113125
},
114126
};

packages/agent/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export interface ProcessSpawnedCallback {
100100
onProcessSpawned?: (info: {
101101
pid: number;
102102
command: string;
103-
sessionId: string;
103+
sessionId?: string;
104104
}) => void;
105105
onProcessExited?: (pid: number) => void;
106106
}

0 commit comments

Comments
 (0)