@sema-agent/core
Version:
Stateless, task-oriented AI agent core
105 lines (104 loc) • 3.6 kB
JavaScript
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;
}