/** * Matching ladder for the `edit` tool. * * Models routinely hallucinate whitespace when reproducing code they read * many turns ago: trailing spaces appear, indentation shifts by a level, * tabs become spaces. A strict exact-match `old_string` fails on all of * these even though the intended target is unambiguous. This module * implements a graded fallback chain — each tier is strictly more permissive * and strictly lower-confidence than the previous one: * * 1. `exact` — substring match (the classic behavior). * 2. `trailing-whitespace` — whole-line window match ignoring trailing * whitespace per line. Zero ambiguity risk * beyond exact (trailing blanks never carry * meaning in the languages we edit). * 3. `whitespace-normalized` — whole-line window match ignoring leading * AND trailing whitespace per line. The * replacement is re-indented to the file's * actual indentation. * 4. `fuzzy` — block-anchor match: first and last lines * must match (trimmed), interior lines are * compared by Levenshtein similarity. Only a * single candidate with a clear margin over * the runner-up is accepted. * * The caller (edit.ts) enforces per-tier uniqueness, restricts `replace_all` * to tiers 1–2, and surfaces the tier + confidence in the tool output so the * model and the session log both see when a fallback fired. */ export type MatchTier = 'exact' | 'trailing-whitespace' | 'whitespace-normalized' | 'fuzzy'; interface LadderMatch { /** Char offset (inclusive) of the match start in the LF-normalized file. */ start: number; /** Char offset (exclusive) of the match end. */ end: number; /** 1-based line number of the first matched line (for error messages). */ startLine: number; } interface LadderResult { tier: MatchTier; matches: LadderMatch[]; /** Similarity score of the best candidate — only set for the fuzzy tier. */ score?: number | undefined; /** * Fuzzy tier only: true when two candidates scored within the ambiguity * margin of each other, so no single target can be trusted. `matches` * then contains the rival candidates for the error message. */ ambiguous?: boolean | undefined; } /** Human-readable label per tier, used in notes and error messages. */ export declare const TIER_LABEL: Record; /** Confidence per tier, recorded in the tool output note. */ export declare const TIER_CONFIDENCE: Record; /** * Walk the ladder and return the first tier that produces at least one * match. Returns `undefined` when no tier matches. */ export declare function findLadderMatches(fileLf: string, oldLf: string): LadderResult | undefined; /** Normalized similarity in [0, 1]: 1 − levenshtein / max-length. */ export declare function similarity(a: string, b: string): number; /** Leading whitespace (spaces/tabs) of the first non-empty line, or ''. */ export declare function firstLineIndent(text: string): string; /** * Shift `newLf` from the needle's indentation to the matched block's actual * indentation. Only clean prefix relationships are adjusted (purely adding * or removing leading whitespace); a tabs-vs-spaces mismatch is left alone * rather than guessed at — the diff in the tool output makes the result * visible either way. */ export declare function adjustIndent(newLf: string, fromIndent: string, toIndent: string): { text: string; adjusted: boolean; }; /** * Best-effort locator for the no-match error: find the window whose trimmed * lines are most similar to the needle. Returns the 1-based line * and a short snippet the model can use to correct itself without re-reading. */ export declare function nearestMatchHint(fileLf: string, oldLf: string): { line: number; snippet: string; } | undefined; export {}; //# sourceMappingURL=_edit-match.d.ts.map