/** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */ import { type ResolvedCredentialEnvScrub } from '../exec/credential-env.js'; /** * ProcessManager, tracks background processes for a single GoodVibes runtime. * * Extracted from tools/exec/index.ts so that other modules (UI, agent system, * live-tail) can query running processes without importing the exec tool. */ export interface BackgroundProcess { id: string; pid: number; cmd: string; startTime: number; /** * Output chunks collected so far. Appended AS THE PROCESS RUNS, not only at * exit, so `bg_output` on a still-running process returns what it has printed * up to now. This is also what supplies the output tail an on-exit trigger * payload carries. */ stdout: string[]; stderr: string[]; exitCode: number | null; done: boolean; /** * Timestamp (ms since epoch) when SIGKILL was scheduled after a timeout. * Null if the process completed normally or SIGKILL was never scheduled. */ killDeadline: number | null; completedAt?: number | undefined; /** POSIX signal name that terminated the process, or null if it exited. */ signal?: string | null | undefined; /** True when the watchdog terminated the process at its timeout. */ timedOut?: boolean | undefined; } export interface SpawnOptions { /** Abort the process if it hasn't completed within this many ms. Default: 60000. */ timeout_ms?: number | undefined; /** Grace period (ms) between SIGTERM and SIGKILL after timeout. Default: 5000. */ sigterm_grace_ms?: number | undefined; /** * Whether the timeout watchdog may terminate the process. Default: true. * * Set false for a process whose lifetime is not the caller's to end, a * browser, an editor, a long-running server. `timeout_ms` then bounds only * how long a caller waits, and the process keeps running until it is stopped * explicitly. Killing such a process on a routine timeout destroys a * user-facing application as the default outcome of a normal parameter. */ kill_on_timeout?: boolean | undefined; /** * Credential-bearing env-var scrub applied to the inherited base environment * before spawning. Defaults to enabled with an empty allowlist, so a * background process is protected even when a caller does not thread config. */ credentialEnvScrub?: ResolvedCredentialEnvScrub | undefined; /** * Child stdin. Defaults to 'ignore' (closed): a background process has * nobody at the keyboard, so a prompt must EOF rather than hang. */ stdin?: 'ignore' | 'pipe' | undefined; } export interface BgCommandResult { cmd: string; exit_code: number | null; stdout: string; stderr: string; success: boolean; process_id?: string | undefined; pid?: number | undefined; } export declare class ProcessManager { private _counter; private _processes; private _procs; private newId; /** * Spawn a background process and start collecting its output. * * @param cmd Shell command to run via /bin/sh -c. * @param cwd Working directory (undefined = inherit). * @param env Extra env vars merged with the current process env. * @param opts Timeout and SIGKILL grace configuration. * * @returns A BgCommandResult with the process_id and pid, or rejects if * the binary is missing (ENOENT) or exec permission is denied (EACCES). */ spawn(cmd: string, cwd: string | undefined, env: Record | undefined, opts?: SpawnOptions): Promise; /** * Spawn a background process from argv, with NO shell in between. * * Same tracking, credential-env scrub, live output collection and timeout * watchdog as `spawn`, the only difference is that nothing is handed to * /bin/sh, so no argument can be reinterpreted as a shell metacharacter. * On-exit triggers use this: their command is pre-registered and * digest-pinned, and keeping it argv-shaped means the pin covers exactly * what runs. */ spawnArgv(command: string, args: readonly string[], cwd: string | undefined, env: Record | undefined, opts?: SpawnOptions): Promise; private launch; /** Get the status record for a background process, or undefined if not found. */ getStatus(id: string): BackgroundProcess | undefined; /** Get the accumulated stdout/stderr for a background process. */ getOutput(id: string): { stdout: string; stderr: string; } | undefined; /** * Stop a background process by ID. * Returns true if the process was found and stopped, false if unknown. */ stop(id: string): boolean; /** List all tracked background processes with their status summaries. */ list(): Array<{ id: string; pid: number; cmd: string; status: string; }>; /** * Handle bg_status / bg_output / bg_stop / bg_list special commands. * Returns a BgCommandResult if the command was handled, null otherwise. */ handleCommand(cmd: string): BgCommandResult | null; private pruneCompletedProcesses; } /** * One status line that never claims success it cannot prove: a timed-out or * signalled process reads as such rather than as "done (exit null)". */ export declare function describeProcessStatus(entry: BackgroundProcess): string; //# sourceMappingURL=process-manager.d.ts.map