UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

105 lines (104 loc) • 3.6 kB
export const DEGENERATE_MESSAGE = "degenerate repetition detected — the model looped on the same text; output cut off at the repetition"; const MIN_LEN = 64; const WINDOW = 400; const CHAR_RUN = 60; const CHAR_RUN_SYMBOL = 200; const MIN_REPS = 6; const MIN_COVER = 120; const MAX_PERIOD = 100; const SATURATION_REPS = 16; const SEGMENT_MAX = 120; function clipSegment(s) { return s.length > SEGMENT_MAX ? s.slice(0, SEGMENT_MAX) : s; } function trailingRepeats(text, unit, cap) { let n = 0; let end = text.length; while (n < cap && end - unit.length >= 0 && text.startsWith(unit, end - unit.length)) { n++; end -= unit.length; } return n; } function looksLikeCodeLineUnit(unit) { if (!unit.includes("\n")) { return false; } const structural = unit.match(/[<>{}[\]()=,;:|\\/*+~`$#@&^%_-]/g); if (structural !== null && structural.length >= 2) { return true; } return /^[ \t]{2,}/.test(unit) || /\n[ \t]{2,}/.test(unit); } export function inspectDegenerate(text) { const spared = []; const n = text.length; if (n < MIN_LEN) { return { degenerate: false, spared }; } const tail = text.slice(-WINDOW); const t = tail.length; let run = 1; for (let i = t - 1; i > 0 && tail[i] === tail[i - 1]; i--) { run++; } if (run >= CHAR_RUN) { const event = { rule: "char-run", period: 1, reps: run, segment: clipSegment(tail.slice(t - run)) }; const isLetterOrDigit = /[\p{L}\p{N}]/u.test(tail[t - 1]); if (isLetterOrDigit || run >= CHAR_RUN_SYMBOL) { return { degenerate: true, cut: event, spared }; } spared.push(event); } const maxP = Math.min(MAX_PERIOD, t >> 2); let sparedUnitLoop = false; for (let p = 2; p <= maxP; p++) { const unit = tail.slice(t - p); if (unit === unit[0].repeat(p)) { continue; } let reps = 1; let pos = t - p; while (pos - p >= 0 && tail.slice(pos - p, pos) === unit) { reps++; pos -= p; } if (reps >= MIN_REPS && reps * p >= MIN_COVER) { const event = { rule: "unit-loop", period: p, reps, segment: clipSegment(unit) }; if (!looksLikeCodeLineUnit(unit)) { return { degenerate: true, cut: event, spared }; } if (t === WINDOW && reps * p >= t - p && trailingRepeats(text, unit, SATURATION_REPS) >= SATURATION_REPS) { return { degenerate: true, cut: event, spared }; } if (!sparedUnitLoop) { sparedUnitLoop = true; spared.push(event); } } } return { degenerate: false, spared }; } export function looksDegenerate(text) { return inspectDegenerate(text).degenerate; } export function trimDegenerateTail(text, cut) { const unit = cut.rule === "char-run" ? (cut.segment[0] ?? "") : cut.segment; if (unit.length === 0 || (cut.rule === "unit-loop" && unit.length !== cut.period)) return text; let end = text.length; for (let k = unit.length - 1; k >= 1; k--) { if (end - k - unit.length >= 0 && text.slice(end - k, end) === unit.slice(0, k) && text.slice(end - k - unit.length, end - k) === unit) { end -= k; break; } } let reps = 0; while (end - unit.length >= 0 && text.slice(end - unit.length, end) === unit) { end -= unit.length; reps++; } if (reps < 2) return text; return text.slice(0, end) + unit; }