import { type CompletedOperation } from "./outcomes.js"; export interface ToolAttempt { step: number; callName: string; canonicalSignature: string; ok: boolean; exitCode?: number | undefined; observationDigest?: string | undefined; } export interface LoopGuardOptions { /** @deprecated Retry authorization belongs in RetryContext passed to shouldBlock. */ allowUnlimitedFailedRetries?: boolean; /** @deprecated Unchanged failed retries are blocked immediately. */ failedRetryLimit?: number; } export interface RetryContext { dependenciesChanged?: boolean; environmentChanged?: boolean; stateKey?: string | undefined; retryReason?: { code: string; detail: string; }; } export interface LoopDecision { block: boolean; kind?: "failed-retry" | "unchanged-success" | undefined; reason?: string | undefined; } export declare const IDENTICAL_POLL_WARN_THRESHOLD = 2; export declare const IDENTICAL_POLL_BLOCK_THRESHOLD = 4; export interface ActionSequenceDecision { suppress: boolean; terminal: boolean; repetitions: number; totalSuppressions: number; oscillation: boolean; warn: boolean; warnMessage?: string | undefined; } export declare class LoopGuard { private attempts; private signatureCount; private signatureSuccess; private lastActionSequence; private lastActionSequenceEligible; private actionSequenceRepetitions; private lastActionSequenceOutcome; private unchangedActionSequenceRuns; private consecutiveSequenceRepeats; private totalSequenceSuppressions; private sequenceRunCounts; private sequenceOutcomes; private emptySuccessfulCalls; private failedReadRetryUsed; private successfulOutputs; private successfulProbes; private failedProbes; private lastSuccessfulNonMetaStep; private identicalPolls; constructor(_options?: LoopGuardOptions); private recordPollObservation; identicalPollRepeats(name: string, args: Record): number; clearIdenticalPolls(): void; restoreCompletedOperations(operations: readonly CompletedOperation[]): void; canonicalize(name: string, args: Record): string; private sequenceSignature; private callNeedsOutcomeComparison; private sequenceNeedsOutcomeComparison; private callHasUnsafeImmediateRetry; private callIsStatePolling; private sequenceIsStatePolling; observeActionSequence(calls: readonly { name: string; args: Record; stateKey?: string | undefined; }[]): ActionSequenceDecision; completeActionSequence(calls: readonly { name: string; args: Record; stateKey?: string | undefined; }[], eligible: boolean, outcomeFingerprint?: string | undefined): void; resetSequenceCount(calls: readonly { name: string; args: Record; stateKey?: string | undefined; }[]): boolean; resetSequenceCountBySignature(signature: string): boolean; resetAllSequenceCounts(): void; getSequenceRunCount(calls: readonly { name: string; args: Record; stateKey?: string | undefined; }[]): number; currentActionSequenceSignature(): string | undefined; recordAttempt(step: number, name: string, args: Record, ok: boolean, exitCode?: number | undefined, output?: string | undefined, context?: RetryContext | undefined): void; private isPathMutatingTool; private invalidateReadsAfterSuccess; getPriorObservation(name: string, args: Record): string | undefined; private hasInterveningAttempt; private hasRepeatedEquivalentAttempt; private hasThreeEquivalentAttempts; shouldBlock(name: string, args: Record, retryContext?: RetryContext): LoopDecision; getAttemptCount(name: string, args: Record): number; hasRepeatedFailures(threshold?: number): boolean; consecutiveFailureCount(): number; getFailureReflection(): string | null; resetReadOnly(): void; get totalAttempts(): number; }