UNPKG

framework

Version:

The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.

47 lines 2.63 kB
/** * Holds the Node event loop open while the agent is parked on the user (#1359). * * A daemon-spawned agent has nothing ref'd at a parked gate: the daemon spawns it detached with * every stdio ignored and `--no-dashboard` (so no server), the claude-code driver spawns and * reaps a child per prompt (so nothing runs between turns), and the control watcher is * deliberately unref'd so steering alone never keeps a finished agent alive (#344). The moment * `requestChoice` parked a bare Promise between turns, the event loop was empty and Node exited * 0 mid-await — no `end` event, empty stderr, and picks landing in `control.jsonl` that nothing * would ever read. The same silently-unwired-channel family as #905/#922, one layer down: the * channel was wired, but the process waiting on it was not held. * * This is the narrow inverse of the watcher's unref: a ref'd (but idle) interval that exists * only while at least one held promise is pending. Waiting for the answer IS the agent's work at * that moment, so holding the loop is correct exactly there — and nowhere else, which is why the * watcher itself stays unref'd (the actions-abort hang is what unref'ing it fixed). */ /** The slice of a timer handle the keepalive needs; `hasRef` is what a test asserts on. */ export interface KeepaliveTimer { hasRef?(): boolean; } /** The timer seam, injected by tests so nothing waits on real time. */ export interface KeepaliveTimers { /** Start the loop-holding timer. Must return a ref'd handle. */ start(): KeepaliveTimer; /** Stop a timer {@link start} returned. */ stop(timer: KeepaliveTimer): void; } /** * The real timers: a ref'd no-op interval (`setInterval` refs by default — the ref IS the * fix, so a test asserts `hasRef()` on what `start` returns rather than trusting this comment). */ export declare const nodeKeepaliveTimers: KeepaliveTimers; /** A live keepalive. One per agent process; every parked wait shares it. */ export interface GateKeepalive { /** Pass a parked promise through; the loop is held until it settles (resolve or reject). */ hold<T>(pending: Promise<T>): Promise<T>; /** How many holds are currently pending. */ held(): number; } /** * Create the agent's keepalive. Counter-based: the first pending hold starts one ref'd idle * timer, overlapping holds share it, and the last one to settle stops it — so the process can * exit the moment nothing is parked, exactly as before this existed. */ export declare function createGateKeepalive(timers?: KeepaliveTimers): GateKeepalive; //# sourceMappingURL=gate-keepalive.d.ts.map