/** * useChipStalenessGuard — detects when a statusline chip fails to refresh, * diagnoses the root cause, and forces a re-render to recover. * * Root causes detected: * 1. `animation_frozen` — the agent is running/streaming but the spinner * phase hasn't advanced within the expected interval. * 2. `data_source_stale` — a chip that should be receiving updates (based * on agent state) hasn't changed its data fingerprint within the * staleness threshold. * 3. `subscription_dropped` — the token/cost counter stopped emitting * events while the agent is actively streaming. * * The hook is intentionally lightweight: it runs a single setInterval at * STALENESS_CHECK_INTERVAL_MS and compares lightweight fingerprints * (string hashes of key props) against their last-seen values. When * staleness is detected, it bumps a counter that the StatusBar uses as a * `key` fragment to force a full re-render of the chip rail. */ export type ChipStalenessRootCause = 'animation_frozen' | 'data_source_stale' | 'subscription_dropped'; export interface ChipStalenessDiagnosis { /** Which chip category is stale. */ chip: string; /** The diagnosed root cause. */ rootCause: ChipStalenessRootCause; /** How long (ms) since the chip last updated. */ staleForMs: number; /** Timestamp when staleness was first detected. */ detectedAt: number; } export interface ChipStalenessGuardState { /** Bumped every time a forced re-render is triggered. Use as a key fragment. */ renderNonce: number; /** Current staleness diagnoses (empty = all healthy). */ diagnoses: ChipStalenessDiagnosis[]; /** Total number of staleness recoveries since mount. */ recoveryCount: number; } export interface UseChipStalenessGuardOptions { /** Agent run state — determines which chips SHOULD be updating. */ agentState: 'idle' | 'running' | 'streaming' | 'aborting'; /** Current spinner phase index (advances every SPINNER_INTERVAL_MS while active). */ spinnerPhase: number; /** Token usage fingerprint — changes when new token events arrive. */ tokenFingerprint: string; /** Context usage ratio (0..1) — changes as context grows. */ contextRatio: number | undefined; /** Whether the token counter event subscription is active. */ tokenSubscriptionActive: boolean; /** * Staleness threshold in ms. If a chip that should be updating hasn't * changed within this window, it's flagged. Default: 15_000 (15s). */ stalenessThresholdMs?: number; /** * Check interval in ms. How often the guard polls for staleness. * Default: 10_000 (10s). */ checkIntervalMs?: number; /** * Maximum recoveries before the guard backs off (prevents infinite * re-render loops if the root cause is unfixable). Default: 5. */ maxRecoveries?: number; } export declare function useChipStalenessGuard(opts: UseChipStalenessGuardOptions): ChipStalenessGuardState; /** * Compute a lightweight fingerprint string for token usage data. * Used to detect when token events stop arriving. * * Intentionally covers only input, output, and cost — the primary token * counters that change on every streaming event. Cache stats (`cacheStats`) * are excluded because they update on a different cadence (prompt-cache * lookups) and including them would add noise without improving * subscription-drop detection. */ export declare function computeTokenFingerprint(input: number | undefined, output: number | undefined, cost: number | undefined): string; /** * Format a staleness diagnosis into a human-readable debug string. * Useful for the /statusline detail panel or debug logging. */ export declare function formatDiagnosis(d: ChipStalenessDiagnosis): string; //# sourceMappingURL=use-chip-staleness-guard.d.ts.map