UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

37 lines (36 loc) • 2.13 kB
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]; }