/** * Spawn an `opencode acp` (or any ACP-speaking) harness as a subprocess and adapt * its stdio to the {@link AcpTransport} port — ADR 0062, slice 2. * * This is the **only** module in the ACP backend that touches `node:child_process`: * the JSON-RPC peer and client speak solely to the transport port, so the whole * ingestion stack is exercisable in-memory (see `inMemoryTransportPair`) without a * live process. `initialize` still runs against a real `opencode acp` in the * env-gated integration test. */ import { type ChildProcessWithoutNullStreams } from "node:child_process"; import { type AcpTransport } from "./transport.ts"; export interface SpawnAcpOptions { /** The harness executable (e.g. `"opencode"`). */ readonly command: string; /** Its arguments (e.g. `["acp"]`). */ readonly args?: readonly string[]; /** Working directory for the harness process. */ readonly cwd?: string; /** Extra environment for the harness (merged over `process.env`). */ readonly env?: Readonly>; /** Where to route the harness's stderr diagnostics. Default: drained and discarded. */ readonly onStderr?: (chunk: string) => void; } /** An {@link AcpTransport} bound to a spawned harness, exposing the child handle. */ export interface SpawnedAcpTransport extends AcpTransport { /** The underlying child process (for lifecycle assertions / signals). */ readonly child: ChildProcessWithoutNullStreams; } /** * Spawn the harness and return a transport over its stdin/stdout with ACP's * newline-delimited JSON framing. The child's stderr is protocol-irrelevant * (diagnostics only): it is always piped and routed to `onStderr` when provided, * otherwise drained and discarded (never inherited by the parent's stderr). */ export declare function spawnAcpTransport(options: SpawnAcpOptions): SpawnedAcpTransport;