/**
 * Pool core for the anthropic-interactive-pool adapter.
 *
 * Manages a fixed-size set of long-lived `claude` REPL sessions in tmux.
 * Each session can serve many prompts before being retired (auto-retire
 * defends against context-window overflow).
 *
 * Lifecycle:
 *   spawning → ready ⇄ busy → retiring → dead
 *
 * Allocation: LRU (least-recently-used ready session wins).
 * Recycling: when a session is retired, the pool spawns a fresh one in its
 * place so the steady-state size is preserved.
 */
import { EventEmitter } from 'node:events';
import type { InteractivePoolConfig } from './config.js';
export type PoolSessionState = 'spawning' | 'ready' | 'busy' | 'retiring' | 'dead';
export interface PoolSession {
    id: string;
    tmuxName: string;
    state: PoolSessionState;
    messageCount: number;
    spawnedAt: number;
    lastUsedAt: number;
    /** Provider-side Claude session UUID once bound (via hook event). */
    claudeSessionId?: string;
}
export interface PoolEvents {
    'session:spawned': PoolSession;
    'session:ready': PoolSession;
    'session:allocated': PoolSession;
    'session:released': PoolSession;
    'session:retired': PoolSession;
    'session:died': PoolSession;
    /**
     * Emitted when an attempt to spawn (or re-spawn) a pool session fails.
     * `attempt` is 0 for the original spawn attempt, 1+ for retry attempts.
     * The pool will schedule a retry with exponential backoff up to
     * `MAX_REPLACEMENT_ATTEMPTS` total; after that, `pool:degraded_persistent`
     * fires once and no more retries are scheduled.
     */
    'pool:degraded': {
        error: Error;
        attempt: number;
    };
    /**
     * Emitted exactly once when a replacement-retry sequence succeeds. The
     * pool is back at steady-state size.
     */
    'pool:healed': {
        afterAttempts: number;
    };
    /**
     * Emitted exactly once when all retries have been exhausted without
     * success. The pool is below steady-state size and will stay there
     * until something external triggers another replacement (next retire,
     * manual intervention).
     */
    'pool:degraded_persistent': {
        totalAttempts: number;
    };
    'pool:shutdown': void;
}
export declare class InteractivePool extends EventEmitter {
    private readonly config;
    private readonly sessions;
    private readonly waiters;
    /** Pending retry timers for replacement spawns. Cleared on shutdown. */
    private readonly pendingRetryTimers;
    /** Has the startup empty-prompt canary already run in this process lifetime? */
    private canaryHasRunInCurrentLifetime;
    /** Interval handle for the scheduled recurring canary. Cleared on shutdown. */
    private scheduledCanaryTimer;
    /** Lock to prevent overlapping scheduled-canary runs if the previous one is slow. */
    private scheduledCanaryInFlight;
    /** Interval handle for the idle-retirement sweep. Cleared on shutdown. */
    private idleSweepTimer;
    private shuttingDown;
    constructor(config: InteractivePoolConfig);
    /** The tmux session-name prefix for this pool (see config.sessionPrefix). */
    private get sessionPrefix();
    start(): Promise<void>;
    /** Kill leftover `<prefix>-*` tmux sessions from a previous process. */
    private killStaleSessions;
    private hasSessionNamed;
    /** Retire ready sessions idle past maxIdleMinutes (no immediate replace). */
    private sweepIdleSessions;
    /**
     * Schedule the recurring empty-prompt canary. Each tick allocates a
     * ready session, runs the canary, releases. Self-healing and
     * degradation surfacing reuse the same paths as the startup canary.
     * Re-entrancy is guarded by `scheduledCanaryInFlight` — if the
     * previous tick is still running when the next interval fires
     * (shouldn't happen at default 1h cadence but possible under
     * misconfiguration), the new tick is skipped.
     */
    private scheduleRecurringCanary;
    /**
     * Run one canary cycle on a borrowed pool session. Handles result
     * surfacing identically to the startup canary path in spawnOne.
     */
    private runScheduledCanary;
    private spawnOne;
    private waitForReady;
    capturePane(tmuxName: string, lines: number): Promise<string | null>;
    /**
     * Allocate a ready session. Marks it busy and returns. If no session is
     * ready, waits up to `allocateTimeoutMs`. If no session becomes ready
     * in time, throws.
     */
    allocate(): Promise<PoolSession>;
    private findReadyLru;
    private markBusy;
    private flushWaiter;
    /**
     * Return a session to ready. Increments messageCount and checks retire
     * thresholds; auto-retires if needed.
     */
    release(s: PoolSession): Promise<void>;
    /**
     * Gracefully retire a session. By default spawns a replacement (the
     * busy-path retirement contract — a caller is likely waiting); idle
     * retirement passes `replace: false` so an idle agent holds zero REPLs
     * and allocate() respawns on demand.
     */
    retire(s: PoolSession, opts?: {
        replace?: boolean;
    }): Promise<void>;
    private replaceRetired;
    private scheduleRetryReplacement;
    /** Force-kill a session without graceful retirement. */
    hardKill(s: PoolSession): Promise<void>;
    /** Shutdown the pool. */
    shutdown(): Promise<void>;
    /** Snapshot of pool state. */
    status(): {
        total: number;
        ready: number;
        busy: number;
        retiring: number;
        sessions: ReadonlyArray<Readonly<PoolSession>>;
    };
    getById(id: string): PoolSession | undefined;
}
//# sourceMappingURL=pool.d.ts.map