From cc88d1031f23d977104e4767edced05c03157bf8 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sat, 7 Nov 2026 12:21:45 -0600 Subject: [PATCH] Revert "fix(runner): name the spawned opencode serve in OpenCode session start" This reverts commit af78a9c57f3613ce39edea025cc4338692237b67. --- .../opencode/opencode-server-driver.test.ts | 6 --- .../opencode/opencode-server-driver.ts | 10 ----- .../src/live/linux-process-start.ts | 45 ------------------- .../src/live/runnerd-codex-transport.ts | 45 ++++++++++++++++++- 4 files changed, 44 insertions(+), 62 deletions(-) diff --git a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts index 8c7b8b945ee..fbb618c57d2 100644 --- a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts +++ b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.test.ts @@ -1188,12 +1188,6 @@ describe("OpenCodeServerDriver", () => { expect( events.filter((event) => event.eventType === "item.delta"), ).toHaveLength(1); - // The session names the exact spawned `opencode serve`, so cleanup can prove it is gone. - expect(events.find((event) => event.eventType === "session.started")?.payload).toMatchObject({ - processId: spawns[0]!.pid, - processGroupId: spawns[0]!.processGroupId, - processStartedAt: expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/), - }); expect( events.find((event) => event.eventType === "item.delta")?.payload.text, ).toBe("done [guide](guide.md)"); diff --git a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts index fa1451c4caa..76f9fd97e1d 100644 --- a/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts +++ b/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts @@ -1,5 +1,4 @@ import { isOpenRouterUrl, OPENROUTER_ATTRIBUTION_HEADERS } from "../openrouter-attribution.js"; -import { readLocalProcessStartedAt } from "../../live/linux-process-start.js"; import { spawn, type ChildProcess } from "node:child_process"; import { resolveCompletionContinuation } from "../completion-continuation.js"; import { createHash, randomBytes } from "node:crypto"; @@ -232,8 +231,6 @@ interface OpenCodeRuntime { version: string; permissionMode: "allow" | "ask" | "deny"; process: ChildProcess; - /** OS identity of the spawned `opencode serve`, so cleanup can prove that exact process is gone. */ - processIdentity: { processId: number; processGroupId: number | null; processStartedAt: string | null } | null; bridge: OpenCodeMcpBridge; trace: ProviderTraceFileSink | null; sensitiveValues: readonly string[]; @@ -627,7 +624,6 @@ class OpenCodeHarnessSession implements HarnessSession { this.#emit(input.snapshot ? "session.resumed" : "session.started", { driverSessionId: input.providerSessionId, providerSessionId: input.providerSessionId, - ...(input.runtime.processIdentity ?? {}), context: { protocolVersion: "http+sse/v1", opencodeVersion: input.runtime.version, @@ -2730,11 +2726,6 @@ async function startRuntime(input: { providerChild.once("spawn", resolve); providerChild.once("error", reject); }); - const processIdentity = child.pid ? { - processId: child.pid, - processGroupId: globalThis.process.platform === "win32" || !isolateProcessGroup ? null : child.pid, - processStartedAt: readLocalProcessStartedAt(child.pid), - } : null; if (child.pid) await input.options.onSpawn?.({ pid: child.pid, @@ -2771,7 +2762,6 @@ async function startRuntime(input: { version, permissionMode: input.options.permissionMode ?? "allow", process: child, - processIdentity, bridge, trace: input.trace, sensitiveValues, diff --git a/packages/paperclip-runner/src/live/linux-process-start.ts b/packages/paperclip-runner/src/live/linux-process-start.ts index ed46e1da3f6..66abe1322dc 100644 --- a/packages/paperclip-runner/src/live/linux-process-start.ts +++ b/packages/paperclip-runner/src/live/linux-process-start.ts @@ -38,48 +38,3 @@ export function readLinuxProcessStartedAt(pid: number, options: LinuxProcessStar } return new Date(value).toISOString(); } - -/** OS start time of a local process as an ISO string, or null when it cannot be read. */ -export function readLocalProcessStartedAt(pid: number): string | null { - if (!Number.isInteger(pid) || pid <= 0) return null; - try { - if (process.platform === "linux") { - return readLinuxProcessStartedAt(pid); - } - if ( - ["darwin", "freebsd", "openbsd", "aix", "sunos"].includes( - process.platform, - ) - ) { - const raw = execFileSync("ps", ["-o", "lstart=", "-p", String(pid)], { - encoding: "utf8", - timeout: 1_500, - windowsHide: true, - }).trim(); - const parsed = new Date(raw); - return Number.isNaN(parsed.getTime()) ? null : parsed.toISOString(); - } - if (process.platform === "win32") { - const script = [ - `$target = Get-Process -Id ${pid} -ErrorAction Stop`, - "$target.StartTime.ToUniversalTime().ToString('o')", - ].join("; "); - for (const command of ["powershell.exe", "pwsh.exe"]) { - try { - const raw = execFileSync( - command, - ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], - { encoding: "utf8", timeout: 1_500, windowsHide: true }, - ).trim(); - const parsed = new Date(raw); - if (!Number.isNaN(parsed.getTime())) return parsed.toISOString(); - } catch { - // Try the other supported PowerShell host. - } - } - } - } catch { - // Process exit and restricted process metadata both produce no fingerprint. - } - return null; -} diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts index e5398ce79ff..c5cdae6cb56 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts @@ -25,7 +25,7 @@ import { waitForWarmAttachmentReadiness } from "./warm-attachment-readiness.js"; import { resolveCodexCommand } from "../drivers/codex/codex-command.js"; import { isCanonicalProviderEventType } from "../provider-events.js"; import { execFileSync } from "node:child_process"; -import { readLocalProcessStartedAt } from "./linux-process-start.js"; +import { readLinuxProcessStartedAt } from "./linux-process-start.js"; import { createHash, randomUUID } from "node:crypto"; import { appendFileSync, @@ -117,6 +117,49 @@ const RUNNER_BOOTSTRAP_TICKET_TTL_MS = 60_000; const RUNNERD_MAX_OUTBOX_BYTES = 16 * 1024 * 1024; const RUNNERD_P0_RESERVE_BYTES = 1024 * 1024; +function readLocalProcessStartedAt(pid: number): string | null { + if (!Number.isInteger(pid) || pid <= 0) return null; + try { + if (process.platform === "linux") { + return readLinuxProcessStartedAt(pid); + } + if ( + ["darwin", "freebsd", "openbsd", "aix", "sunos"].includes( + process.platform, + ) + ) { + const raw = execFileSync("ps", ["-o", "lstart=", "-p", String(pid)], { + encoding: "utf8", + timeout: 1_500, + windowsHide: true, + }).trim(); + const parsed = new Date(raw); + return Number.isNaN(parsed.getTime()) ? null : parsed.toISOString(); + } + if (process.platform === "win32") { + const script = [ + `$target = Get-Process -Id ${pid} -ErrorAction Stop`, + "$target.StartTime.ToUniversalTime().ToString('o')", + ].join("; "); + for (const command of ["powershell.exe", "pwsh.exe"]) { + try { + const raw = execFileSync( + command, + ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], + { encoding: "utf8", timeout: 1_500, windowsHide: true }, + ).trim(); + const parsed = new Date(raw); + if (!Number.isNaN(parsed.getTime())) return parsed.toISOString(); + } catch { + // Try the other supported PowerShell host. + } + } + } + } catch { + // Process exit and restricted process metadata both produce no fingerprint. + } + return null; +} const CONTROL_PLANE_STATE_MAX_BYTES = 256 * 1024 * 1024;