import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
import type { StreamState } from "./store/conversation-store.js";
/**
 * Hard connect-timeout: time the stream may stay `connecting` (no first
 * snapshot) before the watchdog acts. Sized well above a healthy connect
 * (the server sends the initial snapshot in ~1 RTT) yet short enough that a
 * silent hang surfaces an affordance within a few seconds, not minutes.
 */
export declare const DEFAULT_CONNECT_TIMEOUT_MS = 10000;
/**
 * Soft slow-stall threshold: a non-terminal stream that produces no new
 * snapshot for this long flips an informational "still working" hint. Long
 * enough that ordinary model thinking-time never trips it.
 */
export declare const DEFAULT_SLOW_THRESHOLD_MS = 60000;
/**
 * Callback interface for the stream controller to communicate with
 * its host (the React hook). All mutations to external state go
 * through these callbacks.
 */
export interface StreamControllerSink {
    /** Ingest a snapshot into the store (applies structural sharing). */
    ingestSnapshot(snapshot: AgentExecution): void;
    /** Transition the store's stream lifecycle state. */
    setStreamState(state: StreamState): void;
    /**
     * The hard connect-timeout elapsed while still `connecting`. The host owns
     * the self-heal-once-then-surface policy (it holds the `connectKey` reconnect
     * counter and the per-subscription guard that survives a reconnect, which
     * the controller — reset on every teardown — cannot).
     */
    onConnectTimeout(): void;
    /** Set or clear the soft slow-stall hint signal. */
    setSlow(value: boolean): void;
}
/**
 * Injectable watchdog configuration. Timers default to `setTimeout`/
 * `clearTimeout`; tests pass fakes so the watchdog is exercised without real
 * time. Mirrors the existing `scheduleFlush`/`cancelFlush` injection idiom.
 */
export interface StreamControllerWatchdog {
    readonly setTimer?: (cb: () => void, ms: number) => number;
    readonly clearTimer?: (id: number) => void;
    readonly connectTimeoutMs?: number;
    readonly slowThresholdMs?: number;
}
/**
 * Framework-agnostic finite state machine that manages the lifecycle
 * of a single execution stream subscription.
 *
 * Responsibilities:
 * - Track FSM state transitions (idle → connecting → streaming → complete/error)
 * - Buffer incoming snapshots and coalesce via `requestAnimationFrame`
 * - Flush terminal snapshots immediately (no rAF delay)
 * - Provide abort/reconnect semantics
 *
 * This class has no React dependency. It communicates outward through
 * a {@link StreamControllerSink} and a `scheduleFlush` function
 * (typically `requestAnimationFrame`).
 */
export declare class StreamController {
    private _state;
    private _bufferedSnapshot;
    private _rafId;
    private _sink;
    private _scheduleFlush;
    private _cancelFlush;
    private _setTimer;
    private _clearTimer;
    private _connectTimeoutMs;
    private _slowThresholdMs;
    private _connectTimerId;
    private _slowTimerId;
    constructor(sink: StreamControllerSink, scheduleFlush?: (cb: () => void) => number, cancelFlush?: (id: number) => void, watchdog?: StreamControllerWatchdog);
    /** Current FSM state (read-only). */
    get state(): StreamState;
    /**
     * Transition to `connecting` for the given execution ID.
     * If already active for a different ID, resets first.
     */
    start(executionId: string): void;
    /**
     * Handle an incoming snapshot from the gRPC stream.
     * Non-terminal snapshots are buffered for rAF coalescing.
     * Terminal snapshots flush immediately.
     */
    handleSnapshot(snapshot: AgentExecution): void;
    /**
     * Enter the `reconnecting` stage after a transient drop. Unlike
     * {@link start}, this preserves the buffered snapshot and never resets the
     * store, so the last-known-good conversation stays on screen while the
     * background retry is in flight. No-op once idle (the subscription is
     * already torn down).
     */
    handleReconnecting(attempt: number, error: Error): void;
    /**
     * Handle stream completion (iterator exhausted without error).
     * If we still have a buffered snapshot, flush it first.
     */
    handleStreamEnd(): void;
    /**
     * Handle a stream error. Flushes any buffered snapshot first
     * so the UI shows the last known good state alongside the error.
     */
    handleError(error: Error): void;
    /** Reset to idle. Cancels any pending flush and watchdog timers. */
    reset(): void;
    /** Whether the controller has a buffered snapshot awaiting flush. */
    get hasPendingFlush(): boolean;
    private _activeExecutionId;
    private _transition;
    private _scheduleFlushOnce;
    private _flushBuffer;
    private _cancelPendingFlush;
    private _armConnectTimer;
    private _armSlowTimer;
    private _cancelConnectTimer;
    private _cancelSlowTimer;
    private _cancelWatchdogs;
}
//# sourceMappingURL=stream-controller.d.ts.map