import { type AgentTool, type AgentTurnTiming, type TransformContextOptions } from "@kenkaiiii/gg-agent";
import type { Message, Provider, ThinkingLevel, TextContent, ImageContent, VideoContent } from "@kenkaiiii/gg-ai";
import { type IdealReviewStats, type ReviewCoverageTracker } from "../../core/ideal-review.js";
import type { LspManager } from "../../core/lsp/manager.js";
import { type LoopBreakStats } from "../../core/loop-breaker.js";
export declare function shouldRetainThinkingDelta(): boolean;
export interface ActiveToolCall {
    toolCallId: string;
    name: string;
    args: Record<string, unknown>;
    startTime: number;
    updates: unknown[];
}
export interface AgentLoopOptions {
    provider: Provider;
    model: string;
    tools: AgentTool[];
    webSearch?: boolean;
    maxTokens: number;
    /** Whether the active model supports native image input. */
    supportsImages?: boolean;
    /** Whether the active model supports native video input. */
    supportsVideo?: boolean;
    thinking?: ThinkingLevel;
    apiKey?: string;
    baseUrl?: string;
    accountId?: string;
    projectId?: string;
    /** Resolve fresh credentials before each run (e.g. OAuth token refresh).
     *  When `forceRefresh` is true, bypass cache and fetch a new token (used on 401 retry). */
    resolveCredentials?: (opts?: {
        forceRefresh?: boolean;
    }) => Promise<{
        apiKey: string;
        accountId?: string;
        projectId?: string;
    }>;
    transformContext?: (messages: Message[], options: TransformContextOptions) => Message[] | Promise<Message[]>;
    getIdealReviewMessage?: (stats: IdealReviewStats, touchedFiles: string[]) => Message | null;
    /** Harness-owned successful read/mutation evidence for fail-closed Ideal review. */
    reviewCoverageTracker?: ReviewCoverageTracker;
    /** Detailed diagnostics evidence shown only to the internal review turn. */
    lspManager?: LspManager;
    /** Polled mid-loop when the agent appears stuck (repeated failures / calls /
     *  edits, or degenerate output). Return a user message to break the loop. */
    getLoopBreakMessage?: (stats: LoopBreakStats, stage: 1 | 2) => Message | null;
    /** Polled mid-loop after a compaction reduced the context. Return a user
     *  message that re-pins the original request. */
    getRegroundingMessage?: (originalRequest: string) => Message | null;
}
export type ActivityPhase = "waiting" | "thinking" | "generating" | "tools" | "retrying" | "idle";
export interface RetryInfo {
    reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch" | "runaway_toolcall";
    attempt: number;
    maxAttempts: number;
    delayMs: number;
}
export type UserContent = string | (TextContent | ImageContent | VideoContent)[];
export interface StreamSnapshot {
    text: string;
    thinking: string;
    thinkingMs: number;
}
export interface UseAgentLoopReturn {
    run: (userContent: UserContent) => Promise<void>;
    abort: () => void;
    reset: () => void;
    /** Queue a message to be processed after the current run completes.
     *  `text` is the original typed text, retained so it can be restored to the
     *  composer if the run is interrupted before the queue drains. */
    queueMessage: (content: UserContent, text?: string) => void;
    /** Number of messages currently waiting in the queue. */
    queuedCount: number;
    /** Clear all queued messages. */
    clearQueue: () => void;
    /** Pop every queued message, clear the queue, and return the combined
     *  original text (joined with blank lines). Empty string when nothing was
     *  queued. Used to restore unsent input to the composer on interrupt. */
    drainQueuedText: () => string;
    isRunning: boolean;
    streamingText: string;
    streamingThinking: string;
    activeToolCalls: ActiveToolCall[];
    currentTurn: number;
    totalTokens: {
        input: number;
        output: number;
    };
    /** Latest turn's input tokens — reflects current context window usage */
    contextUsed: number;
    activityPhase: ActivityPhase;
    retryInfo: RetryInfo | null;
    /** Non-null when the agent stopped due to an unrecoverable stream error (e.g. stall retries exhausted). */
    stallError: string | null;
    elapsedMs: number;
    thinkingMs: number;
    isThinking: boolean;
    streamedTokenEstimate: number;
    /** Raw character count ref — read directly by ActivityIndicator for smooth animation */
    charCountRef: React.RefObject<number>;
    /** Accumulated real tokens from completed turns */
    realTokensAccumRef: React.RefObject<number>;
    /** Run start timestamp ref — for smooth elapsed time computation */
    runStartRef: React.RefObject<number>;
    linesChanged: {
        added: number;
        removed: number;
    };
}
export declare function useAgentLoop(messages: React.MutableRefObject<Message[]>, options: AgentLoopOptions, callbacks?: {
    onComplete?: (newMessages: Message[]) => void;
    onTurnText?: (text: string, thinking: string, thinkingMs: number) => void;
    onToolStart?: (toolCallId: string, name: string, args: Record<string, unknown>, stream: StreamSnapshot) => void;
    onToolUpdate?: (toolCallId: string, update: unknown) => void;
    onToolEnd?: (toolCallId: string, name: string, result: string, isError: boolean, durationMs: number, details?: unknown, args?: Record<string, unknown>) => void;
    onServerToolCall?: (id: string, name: string, input: unknown, stream: StreamSnapshot) => void;
    onServerToolResult?: (toolUseId: string, resultType: string, data: unknown) => void;
    onTurnEnd?: (turn: number, stopReason: string, usage: {
        inputTokens: number;
        outputTokens: number;
        cacheRead?: number;
        cacheWrite?: number;
    }, timing: AgentTurnTiming) => void;
    onDone?: (durationMs: number, toolsUsed: string[], runStats?: {
        counts: Record<string, number>;
        tokens: number;
    }) => void;
    onAborted?: () => void;
    /** Called when a queued message starts processing (after the previous run completes). */
    onQueuedStart?: (content: UserContent) => void;
    /** Called when the agent restarts a turn after a stall/overload retry.
     *  The UI should roll back any pending progressive flushes from the
     *  aborted attempt so the retry's regenerated text doesn't duplicate. */
    onRetry?: () => void;
    /** Called when a turn ended on a non-clean stop (max_tokens/refusal/error)
     *  so the UI can warn instead of presenting truncated output as done. */
    onTruncated?: (reason: "max_tokens" | "refusal" | "provider_error", continued: boolean) => void;
    /** Polled when the agent would otherwise stop. Return a user message to
     *  inject and continue the loop (e.g. "continue with the next plan step"). */
    getFollowUpMessages?: () => Message[] | null;
}): UseAgentLoopReturn;
//# sourceMappingURL=useAgentLoop.d.ts.map