/** * A reply that has begun repeating itself. * * Reported with a screenshot: qwen3-coder wrote "First, let me look at the package.json file to * understand how to start the application:" followed by a fenced block, five times, identically, * and the turn ended having done nothing. Forty-five seconds and two hundred tokens for no work * at all. The user's word for it was "dull". * * Degeneration like this is normal for a small local model with a short window, and there is * nothing to be gained by watching it: the second copy of a block carries no information the * first did not, and the tenth is just billed time. Detecting it and cutting the stream turns a * wasted turn into a short one that can be corrected. * * Only the tail is examined, because that is where a loop lives. A block quoted twice in the * middle of an explanation is not a loop, and a document that legitimately repeats a line — a * table, a list of identical imports — must survive. */ export interface Repetition { /** The repeating unit. */ block: string; /** How many consecutive copies end the text. */ count: number; } /** * Shortest unit worth calling a repetition. * * Below this the false positives are real: a divider row in a table, `};` closing a run of * functions, a column of identical enum values. Forty characters is about a line of prose. */ export declare const MIN_BLOCK = 40; /** Fewer than three copies is a coincidence or a rhetorical device. Three is a loop. */ export declare const MIN_COUNT = 3; /** How far back to look. A loop shows itself long before this. */ export declare const WINDOW = 12000; /** Longest unit considered — a repeated paragraph, not a repeated chapter. */ export declare const MAX_BLOCK = 2000; /** * The repetition ending this text, if there is one. * * Works backwards from the end: for each candidate block length, take that many characters from * the tail and count how many identical copies precede it. The shortest block that repeats enough * wins, because that is the tightest description of the loop — a paragraph repeated six times * would otherwise also match as a double-paragraph repeated three. */ export declare function findTailRepetition(text: string, minBlock?: number, minCount?: number): Repetition | null; /** * The text with a trailing loop reduced to one copy. * * One copy is kept rather than none: it is usually the model's actual intent — a sentence, or a * tool call it meant to make once — and throwing it away would turn a recoverable turn into an * empty one. */ export declare function trimTailRepetition(text: string, found: Repetition): string; /** * How often to look while streaming. * * The scan is O(block length squared) in the worst case, which is nothing at these sizes, but * running it on every token of a long reply is still waste. Once per this many new characters * catches a loop within one extra copy of it. */ export declare const CHECK_EVERY = 240; /** What the model is told, so the next turn does something instead of repeating. */ export declare function repetitionNotice(found: Repetition): string; //# sourceMappingURL=repetition.d.ts.map