import * as http from "node:http";
import { type ChildProcess } from "node:child_process";
import type { Router } from "./router.js";
export declare const STDOUT_BUFFER_CAP: number;
export type JobEvent = "progress" | "done";
export interface SpawnJob<TMeta extends object> {
    id: string;
    meta: TMeta;
    proc: ChildProcess;
    stdoutBuffer: string;
    stderrBuffer: string;
    exitCode: number | null;
    done: boolean;
    subscribers: Set<(event: JobEvent, data: unknown) => void>;
    pastEvents: Array<{
        event: JobEvent;
        data: unknown;
    }>;
}
export interface StartSpawnJobOptions<TMeta extends object> {
    command: string;
    args: string[];
    meta: TMeta;
    timeoutMs: number;
    jobs: Map<string, SpawnJob<TMeta>>;
}
export declare function isLocalhost(req: http.IncomingMessage): boolean;
export declare function trimRing(buf: string, cap: number): string;
/**
 * Spawn `command` with `args`, wire stdout/stderr to per-line "progress"
 * events, register the job in `jobs`, and emit "done" on exit / error /
 * timeout. Returns the registered job synchronously so the HTTP handler
 * can reply with `{ jobId }` immediately.
 */
export declare function startSpawnJob<TMeta extends object>(opts: StartSpawnJobOptions<TMeta>): SpawnJob<TMeta>;
/**
 * Mount `GET <prefix>/:jobId/stream` on `router`. The handler enforces the
 * localhost gate, replays buffered events, then subscribes the SSE response
 * to live "progress"/"done" events until disconnect.
 */
export declare function mountSpawnStreamRoute<TMeta extends object>(router: Router, prefix: string, jobs: Map<string, SpawnJob<TMeta>>): void;
