@sema-agent/core
Version:
Stateless, task-oriented AI agent core
37 lines (36 loc) • 2.13 kB
JavaScript
import { refuseRetentionPolicy } from "./retention-policy.js";
export const DEFAULT_FILE_HISTORY_BOUNDARY_KEEP = 100;
const KNOWN_KNOBS = new Set(["keep"]);
export function resolveFileHistoryRetention(label, policy) {
if (policy === undefined)
return DEFAULT_FILE_HISTORY_BOUNDARY_KEEP;
if (typeof policy !== "object" || policy === null || Array.isArray(policy)) {
refuseRetentionPolicy(label, "retention", policy, `an object of retention knobs (${[...KNOWN_KNOBS].join(", ")}) or omitted`);
}
const unknown = Object.keys(policy).filter((k) => !KNOWN_KNOBS.has(k));
if (unknown.length > 0) {
const first = unknown[0];
refuseRetentionPolicy(label, `retention.${first}`, policy[first], `omitted — ${JSON.stringify(first)} is not a retention knob (the only knob is "keep"), and a misspelled one would leave the engine default in force while the operator believes their own number is`);
}
const keep = policy.keep;
if (keep === undefined)
return DEFAULT_FILE_HISTORY_BOUNDARY_KEEP;
if (keep === "unbounded")
return null;
if (keep === 0) {
refuseRetentionPolicy(label, "retention.keep", keep, `at least 1 boundary — a cap of 0 would reap the boundary its own commit just minted, leaving a rewind seat that answers ok to every snapshot and false to every canRestore; write "unbounded" to mean "do not trim" (omitting the knob does NOT mean that — it selects the engine default of ${DEFAULT_FILE_HISTORY_BOUNDARY_KEEP})`);
}
if (typeof keep !== "number" || !Number.isInteger(keep) || keep < 1) {
refuseRetentionPolicy(label, "retention.keep", keep, `a whole number of boundaries, 1 or more, or the literal "unbounded"`);
}
return keep;
}
export function fileHistoryBoundariesToKeep(orderedOldestFirst, justCommitted, keep) {
if (orderedOldestFirst.length <= keep)
return null;
const survivors = new Set([justCommitted]);
for (let i = orderedOldestFirst.length - 1; i >= 0 && survivors.size < keep; i--) {
survivors.add(orderedOldestFirst[i]);
}
return [...survivors];
}