diff --git a/packages/paperclip-runner/package.json b/packages/paperclip-runner/package.json index 91caeb26fe6..3a84ddbe099 100644 --- a/packages/paperclip-runner/package.json +++ b/packages/paperclip-runner/package.json @@ -6,6 +6,7 @@ "type": "module", "bin": { "paperclip-runner-eval-session": "./dist/cli/eval-session.js", + "paperclip-runner-codex-proxy": "./dist/cli/codex-app-server-unix-proxy.js", "paperclip-runner-opencode-proxy": "./dist/cli/opencode-app-server-proxy.js", "paperclip-runner-acpx-sidecar": "./dist/cli/acpx-runtime-sidecar.js" }, diff --git a/packages/paperclip-runner/src/cli/codex-app-server-unix-proxy.ts b/packages/paperclip-runner/src/cli/codex-app-server-unix-proxy.ts new file mode 100644 index 00000000000..1fc622f32c4 --- /dev/null +++ b/packages/paperclip-runner/src/cli/codex-app-server-unix-proxy.ts @@ -0,0 +1,24 @@ +#!/usr/bin/env node +import { createConnection } from "node:net"; + +function socketArgument(argv: string[]): string { + const index = argv.indexOf("--socket"); + const value = index >= 0 ? argv[index + 1] : undefined; + if (!value) throw new Error("--socket requires a Unix socket path"); + return value; +} + +try { + const socket = createConnection(socketArgument(process.argv.slice(2))); + socket.once("connect", () => { + process.stdin.pipe(socket); + socket.pipe(process.stdout); + }); + socket.once("error", (error) => { + process.stderr.write(`Codex app-server socket error: ${error.message}\n`); + process.exitCode = 1; + }); +} catch (error) { + process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`); + process.exitCode = 1; +} diff --git a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts index 9d224716f39..b28e3b5797a 100644 --- a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts +++ b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts @@ -2418,6 +2418,9 @@ export async function runDurableEvalSession( const acpxSidecarPath = input.acpxSidecarPath ?? fileURLToPath(new URL("../cli/acpx-runtime-sidecar.js", import.meta.url)); + const codexUnixProxyPath = fileURLToPath( + new URL("../cli/codex-app-server-unix-proxy.js", import.meta.url), + ); const acpxProfile = providerKind === "acpx" ? resolveQualifiedAcpxProfile(input.acpxAgent ?? "pi", input.model) @@ -2429,13 +2432,7 @@ export async function runDurableEvalSession( input.providerArgs ?? (input.nativeResume === undefined ? providerArgs - : [ - ...codexConfigArgs, - "app-server", - "proxy", - "--sock", - sharedCodexSocket, - ]); + : [codexUnixProxyPath, "--socket", sharedCodexSocket]); let sharedCodexServer: ChildProcessWithoutNullStreams | null = null; let sharedCodexServerStderr = ""; let sharedCodexServerError: Error | null = null; @@ -2483,7 +2480,9 @@ export async function runDurableEvalSession( kind: providerKind, command: input.providerCommand ?? - (providerKind === "opencode" + (input.nativeResume !== undefined + ? process.execPath + : providerKind === "opencode" ? process.execPath : (process.env.PAPERCLIP_CODEX_COMMAND ?? "codex")), args: