/** * PTY lifecycle for interactive CLI/xterm engines. * * Rules: * - A PTY is not reaped because it is old. Native agent loops can legitimately * sit idle for days and wake themselves later. * - maxLivePtys is an IDLE warm-PTY cap. Running turns and actively viewed * terminals are never counted against it or killed to satisfy it. * - When the idle cap is exceeded, the stalest idle/unviewed PTY is released. */ export interface PtyHandle { pid: number; killed: boolean; kill: (signal?: string) => void; } /** What node-pty reports when a PTY's process goes away. The claude watchdog path * only ever sees an exit code, so both halves are optional. */ export interface PtyExit { exitCode?: number | null; signal?: number | null; } /** * Why a turn ended when the PTY process it was talking to went away. * * Lives beside `PtyHandle` because all four interactive engines settle their * active turn with one of these and have to agree on the shape. Two rules bind it: * it must keep starting with `Interrupted`, because `wasQuietlyPreempted` * (sessions/turn/runner.ts) reads that prefix to settle the turn silently rather * than report a failure nobody caused; and everything after the sentence is * diagnostics, because a bare "claude process exited" was the entire account an * 82-minute session got of why it ended. */ export declare function processExitInterruption(engine: string, exit?: PtyExit): string; /** Whether an interruption reason is one of the above. A prefix test rather than an * equality one, because the sentence now carries per-exit diagnostics after it. */ export declare function isProcessExitInterruption(reason: string): boolean; export interface PtyLifecycleOpts { maxLivePtys: number; /** Called after a new PTY session is adopted — used to refresh gateway.json pids. */ onAdopt?: (sessionId: string) => void; /** Called after a PTY is killed/removed — used to clean the --settings file, hook registry, gateway.json pids. */ onCleanup?: (sessionId: string) => void; /** Called after adoption or state changes may have changed global idle-cap pressure. */ onIdleStateChange?: () => void; /** Default true. Server-managed lifecycles disable this and enforce one global cap. */ enforceLocalCap?: boolean; } export interface PtyAdoptState { /** Set for cold spawns that are immediately serving a turn. */ turnRunning?: boolean; /** Optional initial viewer count for a terminal-born PTY. */ viewerCount?: number; } export interface PtyIdleCandidate { manager: PtyLifecycleManager; sessionId: string; idleSince: number; } export declare function enforcePtyIdleCap(managers: PtyLifecycleManager[], maxIdlePtys: number): void; export declare class PtyLifecycleManager { private opts; private entries; private releaseListeners; constructor(opts: PtyLifecycleOpts); adopt(sessionId: string, handle: PtyHandle, state?: PtyAdoptState): void; getWarm(sessionId: string): PtyHandle | undefined; isAtCapacity(): boolean; livePids(): number[]; viewerEnter(sessionId: string): void; viewerLeave(sessionId: string): void; turnStarted(sessionId: string): void; setRuntimeActive(sessionId: string, active: boolean): void; turnEnded(sessionId: string): void; /** Engine-side release hook: invoked for EVERY released session (manual release, * LRU eviction, sweep reap, killAll), after the gateway's onCleanup. Engines use * it to purge per-session bookkeeping (spawn params, output timestamps) so their * maps don't grow forever in a long-running daemon. */ onRelease(listener: (sessionId: string) => void): void; releaseSession(sessionId: string): void; killAll(): void; /** Release only PTYs that are not serving foreground or native runtime work. * A session is spared if its entry has `turnRunning` / `runtimeActive` set OR * the caller's `isActive` predicate flags it (covers the cold-spawn window * where the engine's active set is populated before `turnStarted` mirrors it). */ releaseIdle(isActive: (sessionId: string) => boolean): void; private idleWarmCount; idleCandidates(): PtyIdleCandidate[]; private enforceLocalIdleCap; dispose(): void; } //# sourceMappingURL=pty-lifecycle.d.ts.map