import type { Readable, Writable } from "node:stream"; /** * Grace the wrapped server gets before `SIGKILL`. Must exceed that server's * own teardown budget or its graceful path never completes: axe-mcp-server * publishes {@link SERVER_TEARDOWN_BUDGET_MS}, so this leaves a second of * margin. Raising that budget means raising this. * * TODO(nayanrajDQ): measure a live Chromium teardown against this grace. */ export declare const TEARDOWN_GRACE_MS = 4000; /** * The budget axe-mcp-server publishes as `MAX_TEARDOWN_BUDGET_MS`. Restated * here because the two are separately released packages with no shared code; * a test pins each side so raising one without the other fails loudly. */ export declare const SERVER_TEARDOWN_BUDGET_MS = 3000; /** Each rung's signal and how long to wait *before* sending it. */ export type TeardownLadder = ReadonlyArray<{ signal: NodeJS.Signals; delayBeforeMs: number; }>; /** * Upper bound on the ladder once teardown starts. Exported so `runSession` * bounds its wait on the ladder's arithmetic, not a constant of its own. */ export declare const MAX_TEARDOWN_MS: number; /** Options for {@link supervise}. */ export interface SuperviseOptions { /** Executable to run (e.g. `docker`, `npx`). */ command: string; /** Arguments passed to the executable. */ args: string[]; /** Environment for the child. Defaults to `process.env`. */ env?: NodeJS.ProcessEnv; /** Stream feeding the child's stdin. Defaults to `process.stdin`. */ stdin?: Readable; /** Stream the child's stdout is written to. Defaults to `process.stdout`. */ stdout?: Writable; /** Stream the child's stderr is written to. Defaults to `process.stderr`. */ stderr?: Writable; /** Registers a termination-signal handler. Injectable for tests; defaults to `process.on`. */ onSignal?: (signal: NodeJS.Signals, handler: () => void) => void; /** Registers a parent-death watchdog. Injectable for tests; defaults to polling {@link SuperviseOptions.readParentPID}. */ onParentExit?: (handler: () => void) => void; /** Reads the launching process's pid. Injectable for tests; defaults to `process.ppid`. */ readParentPID?: () => number; /** Tears the child down when aborted, e.g. because the caller hit a fatal error. */ signal?: AbortSignal; /** * Signal-and-wait rungs teardown escalates through. Injectable so tests can * exercise an escalation without sleeping out the shipped grace; defaults to * the real ladder, which one test keeps covered at its true timings. */ ladder?: TeardownLadder; } /** * Spawn `command` and transparently bridge this process's stdio to it: the * parent's stdin drives the child's stdin (so the MCP client's JSON-RPC stream * reaches the wrapped server untouched), the child's stdout and stderr flow * back out, termination signals are forwarded, and the child's exit is * propagated. Resolves with the child's exit code, or `128 + signal` when the * child is killed by a signal (shell convention); rejects only if the child * fails to spawn. * * stdin EOF, a forwarded signal, {@link SuperviseOptions.signal}, and the * launching process vanishing each put the child on a bounded teardown ladder. * * A client that leaks stdin open without signalling or exiting fires none of * those. The wrapped server catches that itself by probing the client, and its * exit unwinds this supervisor. */ export default function supervise(options: SuperviseOptions): Promise;