/** * Child process trees: spawn, track, and stop them for sure. * * A runner child (pipeline Python, Assistant host, RAG ingest, venv build) can * start its own children (a CLI model provider, a browser, pip). Killing only * the direct child leaves those grandchildren running after the runner exits. * * - POSIX: every tracked child is spawned as the leader of its own process * group (`detached: true`), so one signal to `-pid` reaches the whole tree. * - Windows: `taskkill /PID /T` first (asks windowed processes such as * browsers to close), then `taskkill /PID /T /F` after the grace period. * * Every tracked child is also killed synchronously on process exit, so a crash * or a `process.exit()` elsewhere does not leave orphans. */ import { spawn as rawSpawn, type ChildProcess } from "child_process"; /** Track a child so shutdown (and process exit) stops its whole tree. Returns the child. */ export declare function trackChild(child: T): T; /** Live tracked children (for diagnostics and tests). */ export declare function trackedChildren(): ChildProcess[]; /** * Drop-in replacement for child_process.spawn: the child leads its own process * group on POSIX (unless the caller set `detached` itself) and is tracked. * Windows keeps the default (detached there means a new console window). */ export declare const spawnTracked: typeof rawSpawn; /** * Stop a child and every descendant: a graceful request first, then a forced * kill once `graceMs` has passed. Resolves when the tree is gone (or the forced * kill was issued). Never throws. */ export declare function terminateTree(child: ChildProcess, opts?: { graceMs?: number; }): Promise; /** Stop every tracked child tree, in parallel, within the grace period. */ export declare function terminateAllTracked(opts?: { graceMs?: number; }): Promise; /** Last resort on process exit: synchronous forced kill of every tracked tree. */ export declare function killAllTrackedSync(): void; export interface ShutdownStep { name: string; /** Upper bound for this step; the shutdown moves on when it passes. */ deadlineMs: number; run: () => unknown | Promise; } export interface ShutdownStepResult { name: string; outcome: "ok" | "timeout" | "error"; ms: number; error?: string; } /** Run independent shutdown steps in parallel, each bounded by its own deadline. */ export declare function runShutdownSteps(steps: ShutdownStep[]): Promise; /** One line for logs: "runs ok 12ms, browsers timeout 3000ms". */ export declare function formatShutdownResults(results: ShutdownStepResult[]): string; export declare function claimGracefulShutdown(): void; export declare function gracefulShutdownClaimed(): boolean; /** Run this child below normal priority for its whole life (fire-and-forget warm-ups). */ export declare function lowerPriority(child: ChildProcess): ChildProcess; /** Mark a setup child; it runs below normal priority while setup is in background mode. */ export declare function registerSetupChild(child: ChildProcess): ChildProcess; /** Background mode on: new setup children start below normal priority. */ export declare function setSetupBackground(on: boolean): void; export declare function setupIsBackground(): boolean;