export interface LoopDetectionResult {
    status: "ok" | "warning" | "critical";
    pattern?: "generic_repeat" | "ping_pong" | "no_progress" | "circuit_breaker";
    message?: string;
    count?: number;
}
export interface ToolLoopDetectorOptions {
    /**
     * Maximum tool calls since the last substantive progress signal before
     * the circuit breaker trips. Defaults to 25 — calibrated for Claude,
     * which interleaves >100-char reasoning text with tool calls. OpenAI
     * (Chat Completions) tends to return empty `content` alongside
     * `tool_calls`, so it benefits from a higher cap (~40).
     */
    circuitBreakerThreshold?: number;
    /**
     * If the recent history contains at least this many unique tool-call
     * signatures, treat that diversity as a progress signal and skip the
     * circuit breaker even when no substantive text response has been
     * produced. Set to 0 to disable (original behavior); recommended ~10
     * for OpenAI/empty-content-style protocols. The other pattern checks
     * (generic_repeat / no_progress / ping_pong) still apply, so genuine
     * stuck loops are caught even when this bypass is enabled.
     */
    circuitBreakerDiversityBypass?: number;
}
/**
 * Per-protocol detector tuning. Claude keeps the original thresholds —
 * its >100-char text habit is the existing baseline. OpenAI Chat
 * Completions returns empty `content` next to tool_calls most of the
 * time (observed ~89% empty vs Claude's ~48% on dipcoin002), so it
 * needs (a) a slightly higher cap and (b) diversity bypass to avoid
 * tripping circuit_breaker while making genuine progress.
 */
export declare function detectorOptionsForProtocol(protocol: "claude" | "openai"): ToolLoopDetectorOptions;
export declare class ToolLoopDetector {
    private history;
    private totalCalls;
    private lastSubstantiveResponse;
    private circuitBreakerThreshold;
    private circuitBreakerDiversityBypass;
    constructor(options?: ToolLoopDetectorOptions);
    /**
     * Record a tool call and its result.
     */
    record(name: string, action: string, args: Record<string, unknown>, result: string): void;
    /**
     * Notify the detector that the LLM produced a substantive text response.
     */
    notifySubstantiveResponse(): void;
    /**
     * Check for loop patterns. Call this BEFORE each LLM request.
     */
    check(): LoopDetectionResult;
    reset(): void;
    private consecutiveRepeatCount;
    private noProgressCount;
    private uniqueSignatureCount;
    private pingPongCount;
}
