/** * ensureRuntime — the one lifecycle primitive. * * Every surface that needs the Decibel runtime (MCP adapters, the CLI, the * VS Code extension, shell hooks) calls this. None of them should carry their * own "is the daemon up? should I start it?" logic — that duplication is how * five subtly different startup behaviours end up in one codebase. * * Two things this deliberately does NOT do: * * 1. It does not use the PID file as the source of truth. `~/.decibel/daemon.pid` * goes stale — an unclean exit leaves a pid pointing at nothing, or worse, * at a recycled pid belonging to an unrelated process. A successful * `/health` response is the only proof the runtime is actually serving. * * 2. It does not check-then-spawn. When six clients start at once, six * "is it running? no → start it" sequences race and you get six daemons * fighting over one port. Startup is arbitrated by an atomic O_EXCL lock * file: exactly one caller wins the right to spawn, and the losers wait * for the winner's daemon rather than starting their own. */ /** Default port the daemon binds. Overridden by daemon.meta or DECIBEL_DAEMON_PORT. */ export declare const DEFAULT_RUNTIME_PORT = 4888; export interface RuntimeHealth { status: string; version: string; protocol_version?: string; pid: number; uptime_ms: number; facade_count: number; license_tier: string; [key: string]: unknown; } export interface RuntimeHandle { /** Base URL, e.g. `http://127.0.0.1:4888`. No trailing slash. */ url: string; port: number; /** PID of the serving runtime — reported by /health, not read from a pid file. */ pid: number; /** Package version of the running runtime. */ version: string; /** Wire protocol the running runtime speaks. */ protocolVersion: string; licenseTier: string; /** True when this call started the runtime; false when it was already up. */ spawned: boolean; health: RuntimeHealth; } export interface EnsureRuntimeOptions { /** Protocol version this client requires. Defaults to the compiled-in version. */ protocolVersion?: string; /** Port override. Falls back to daemon.meta, then DECIBEL_DAEMON_PORT, then 4888. */ port?: number; /** Total time to wait for a runtime to become healthy. */ timeoutMs?: number; /** * When false, never spawn — probe only, and throw if nothing is serving. * Used by callers that must not have side effects (status commands, health * checks, anything running inside a hook with a hard timeout). */ autoStart?: boolean; /** Absolute path to the runtime entry point. Defaults to this package's dist/server.js. */ serverEntry?: string; } /** Thrown when a runtime is serving but speaks an incompatible protocol. */ export declare class RuntimeProtocolMismatchError extends Error { readonly serverVersion: string | undefined; readonly clientVersion: string; constructor(serverVersion: string | undefined, clientVersion: string, reason: string); } /** Thrown when no runtime is serving and one could not be started. */ export declare class RuntimeUnavailableError extends Error { constructor(port: number, detail: string); } /** * Resolve the port to talk to, in precedence order: * explicit option → DECIBEL_DAEMON_PORT → daemon.meta → default. * * daemon.meta is a *hint*, not proof of life — it records the port the daemon * last bound. We still confirm with /health before trusting anything. */ export declare function resolveRuntimePort(explicit?: number): number; /** * GET /health. Returns null when nothing is listening or the response is not a * usable health payload — callers treat null as "no runtime here", never as an * error worth surfacing. */ export declare function probeRuntime(port: number): Promise; /** * Return a handle to a healthy, protocol-compatible runtime, starting one if * needed. * * Throws rather than degrading: * - RuntimeProtocolMismatchError when something is serving but speaks a * contract this client does not understand. * - RuntimeUnavailableError when nothing is serving and none could be started. * * Callers must not silently fall back to doing the work in-process. A client * that quietly becomes a second writer is exactly the failure this runtime * exists to prevent. */ export declare function ensureRuntime(options?: EnsureRuntimeOptions): Promise; //# sourceMappingURL=ensureRuntime.d.ts.map