import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
import { type BackoffOptions } from "../internal/backoff.js";
import { ConversationStore } from "../internal/store/index.js";
/** Return value of {@link useExecutionStream}. */
export interface UseExecutionStreamReturn {
    /** Latest full execution snapshot from the stream, or `null` before the first update arrives. */
    readonly execution: AgentExecution | null;
    /**
     * Convenience extraction of `execution.status.phase`.
     *
     * Derived from `execution` — always consistent with the current
     * snapshot. Returns `EXECUTION_PHASE_UNSPECIFIED` when `execution`
     * is `null`.
     */
    readonly phase: ExecutionPhase;
    /** `true` while receiving non-terminal updates from the server stream. */
    readonly isStreaming: boolean;
    /** `true` after subscription starts but before the first snapshot arrives. */
    readonly isConnecting: boolean;
    /**
     * `true` while a transient drop is being retried automatically in the
     * background. The last snapshot stays visible and `error` remains `null` —
     * surface a subtle "Reconnecting…" affordance, not an error. Becomes
     * `false` once a snapshot is received (back to `isStreaming`) or retries
     * are exhausted (then `error` is set).
     */
    readonly isReconnecting: boolean;
    /** 1-based count of the in-flight reconnect attempt; `0` when not reconnecting. */
    readonly reconnectAttempt: number;
    /**
     * Error from the last failed stream attempt, or `null` when healthy.
     *
     * Only set once auto-reconnect has exhausted its attempts (or for a
     * non-transient failure that is not retried). It stays `null` throughout
     * background reconnection so a recoverable hiccup never shows as an error.
     */
    readonly error: Error | null;
    /**
     * `true` when the stream opened but no first snapshot arrived within the
     * connect-timeout window, even after one silent self-heal. Distinct from
     * `error` (a thrown/closed stream that auto-reconnect retries): this is the
     * *silent* hang the retry loop can never observe. Surface an actionable
     * "the agent hasn't started — Retry" affordance wired to `reconnect()`.
     * Cleared by the next snapshot or a manual `reconnect()`. Never auto-aborts.
     */
    readonly connectTimedOut: boolean;
    /**
     * `true` when a non-terminal stream has produced no new snapshot for the
     * slow-stall window. Purely informational ("still working — taking longer
     * than usual"); cleared by the next snapshot. Never an error, never aborts.
     */
    readonly isSlow: boolean;
    /**
     * Reset error state and re-establish the stream subscription.
     *
     * The fallback after auto-reconnect exhausts, and a manual escape hatch in
     * any lifecycle state — error, complete, or mid-stream. Resets the retry
     * counter and preserves the last snapshot (no flash to empty). Uses the
     * `connectKey` counter pattern consistent with `refetch()` in other SDK hooks.
     */
    readonly reconnect: () => void;
}
/**
 * Options for {@link useExecutionStream}.
 */
export interface UseExecutionStreamOptions {
    /**
     * External `ConversationStore` to ingest snapshots into.
     *
     * When provided, the hook writes directly to this store and reads
     * the execution snapshot back via `useSyncExternalStore`. This
     * allows `useSessionConversation` to share a single store instance
     * across the stream hook and the rendering tree.
     *
     * When omitted, an internal store is created automatically —
     * preserving backward compatibility for standalone usage.
     */
    readonly store?: ConversationStore;
    /**
     * Automatically re-establish the subscription with exponential backoff
     * when a non-terminal stream drops (transport error, idle timeout, laptop
     * sleep). Defaults to `true`. Set `false` to opt out and surface every
     * drop as an immediate `error` for manual `reconnect()`.
     */
    readonly autoReconnect?: boolean;
    /**
     * Tune the auto-reconnect backoff schedule and attempt cap. Omitted fields
     * fall back to SDK defaults (base 1s, ×2, max 30s, 10 attempts).
     */
    readonly reconnectOptions?: BackoffOptions & {
        /** Max attempts before surfacing a terminal `error`. */
        readonly maxAttempts?: number;
    };
    /**
     * Hard connect-timeout in ms: how long the stream may stay `connecting`
     * (no first snapshot) before the watchdog self-heals once and then surfaces
     * `connectTimedOut`. Defaults to {@link DEFAULT_CONNECT_TIMEOUT_MS} (10s).
     */
    readonly connectTimeoutMs?: number;
    /**
     * Soft slow-stall threshold in ms: how long a non-terminal stream may go
     * without a new snapshot before `isSlow` flips on. Defaults to
     * {@link DEFAULT_SLOW_THRESHOLD_MS} (60s).
     */
    readonly slowThresholdMs?: number;
}
/**
 * Behavior hook that subscribes to real-time {@link AgentExecution}
 * updates via `stigmer.agentExecution.subscribe()`.
 *
 * Manages the full subscription lifecycle through a finite state
 * machine: connection establishment, rAF-coalesced snapshot streaming,
 * terminal-phase detection, automatic reconnection with exponential
 * backoff on transient drops, and manual reconnection as the fallback.
 *
 * **Resilience:** a non-terminal stream drop — whether a thrown transport
 * error (WebKit "Load failed", `fetch failed`, `Unavailable`) or a graceful
 * server close mid-run (idle timeout, load-balancer recycle) — is retried
 * automatically with backoff. The last snapshot stays visible
 * (`isReconnecting`), the access token is re-read on each attempt via the
 * per-request interceptor, and `error` is surfaced only once attempts are
 * exhausted. Completion is decided by the terminal phase, never by the
 * stream merely ending (a graceful close of a running execution reconnects
 * rather than falsely reporting "complete"). Opt out via `autoReconnect: false`.
 *
 * **Performance characteristics:**
 * - Non-terminal snapshots are coalesced via `requestAnimationFrame`
 *   so React commits at most once per display frame (~60Hz)
 * - Terminal snapshots (complete/failed/cancelled) flush immediately
 * - Store updates are wrapped in `startTransition` so thread renders
 *   don't block urgent interactions (e.g. composer typing)
 *
 * Pass `null` as `executionId` to skip subscribing (stable no-op).
 * When `executionId` changes, the previous subscription is aborted
 * and a fresh one begins.
 *
 * @example
 * ```tsx
 * function LiveExecution({ id }: { id: string }) {
 *   const { execution, isStreaming, error, reconnect } =
 *     useExecutionStream(id);
 *
 *   if (error) return <p>{error.message} <button onClick={reconnect}>Retry</button></p>;
 *   if (!execution) return <p>Connecting…</p>;
 *
 *   return (
 *     <div>
 *       {execution.status?.messages.map((m, i) => (
 *         <p key={i}>{m.content}</p>
 *       ))}
 *       {isStreaming && <span>Streaming…</span>}
 *     </div>
 *   );
 * }
 * ```
 */
export declare function useExecutionStream(executionId: string | null, options?: UseExecutionStreamOptions): UseExecutionStreamReturn;
//# sourceMappingURL=useExecutionStream.d.ts.map