@sema-agent/core
Version:
Stateless, task-oriented AI agent core
61 lines (60 loc) • 3.66 kB
JavaScript
import { tierAliasVia } from "./roles.js";
export function contextOverlayFor(settings, ref, catalog) {
if (settings === undefined || typeof ref !== "string")
return undefined;
for (const word of [ref, ...tierAliasVia(ref, catalog?.models)])
if (Object.hasOwn(settings, word))
return settings[word];
return undefined;
}
export function assertContextSettingsWords(settings, models, where) {
const unknown = Object.keys(settings ?? {}).filter((w) => models === undefined || !Object.hasOwn(models, w));
if (unknown.length === 0)
return settings;
const e = new Error(`${where}: contextSettings declares ${unknown.map((w) => JSON.stringify(w)).join(", ")}, which ${unknown.length === 1 ? "is" : "are"} not a word of the model catalog (its keys, and the tier words and aliases \`tiers\` expanded) — an overlay no leg can be keyed by governs nothing; the current settings stay in force`);
e.code = "config.context_settings_unknown_word";
throw e;
}
export function assertContextSettingsValue(v, where) {
if (v === undefined)
return undefined;
if (v === null || typeof v !== "object" || Array.isArray(v)) {
throw new Error(`${where}: contextSettings must be a plain Record<string, {contextTokens?, autoCompactTokens?, enabled?}> (got ${v === null ? "null" : Array.isArray(v) ? "array" : typeof v})`);
}
const out = {};
for (const [word, raw] of Object.entries(v)) {
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
throw new Error(`${where}: contextSettings[${JSON.stringify(word)}] must be a plain object (got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw})`);
}
const o = raw;
const unknown = Object.keys(o).filter((k) => k !== "contextTokens" && k !== "autoCompactTokens" && k !== "enabled");
if (unknown.length > 0) {
throw new Error(`${where}: contextSettings[${JSON.stringify(word)}] carries ${unknown.map((k) => JSON.stringify(k)).join(", ")} — this seat declares window geometry only (contextTokens | autoCompactTokens | enabled); routing, pricing and fencing stay on the model card`);
}
for (const k of ["contextTokens", "autoCompactTokens"]) {
const n = o[k];
if (n !== undefined && (typeof n !== "number" || !Number.isFinite(n) || n <= 0)) {
throw new Error(`${where}: contextSettings[${JSON.stringify(word)}].${k} must be a positive finite number (got ${JSON.stringify(n)}) — an unusable window is a configuration defect, not a request to fall back to the model's own`);
}
}
if (o.enabled !== undefined && typeof o.enabled !== "boolean") {
throw new Error(`${where}: contextSettings[${JSON.stringify(word)}].enabled must be a boolean (got ${JSON.stringify(o.enabled)})`);
}
out[word] = Object.freeze({
...(o.contextTokens !== undefined ? { contextTokens: o.contextTokens } : {}),
...(o.autoCompactTokens !== undefined ? { autoCompactTokens: o.autoCompactTokens } : {}),
...(o.enabled !== undefined ? { enabled: o.enabled } : {}),
});
}
return Object.freeze(out);
}
export function compactionEnabled(specEnabled, overlay) {
return specEnabled ?? overlay?.enabled ?? true;
}
export function physicalWindowOf(model, overlay) {
const card = model.contextTokens ?? model.contextWindow;
const declared = overlay?.contextTokens;
if (declared === undefined)
return card;
return Number.isFinite(card) && card > 0 ? Math.min(declared, card) : declared;
}