@sema-agent/core
Version:
Stateless, task-oriented AI agent core
191 lines (190 loc) • 10.5 kB
JavaScript
export const GLOBAL_USAGE_KEY = "__usage_global__";
export const EMPTY_USAGE_WINDOW_RECORD = Object.freeze({
slots: Object.freeze([]),
buckets: Object.freeze([]),
});
function usageConfigError(code, message) {
const e = new Error(message);
e.code = code;
return e;
}
export function resolveUsageWindows(windows) {
if (windows === undefined)
return undefined;
if (!Array.isArray(windows)) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows must be an array (got ${typeof windows})`);
}
for (const w of windows) {
if (w === null || typeof w !== "object") {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows entries must be objects (got ${String(w)})`);
}
if (typeof w.windowMs !== "number" || !Number.isFinite(w.windowMs) || w.windowMs <= 0) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].windowMs must be a finite number of milliseconds > 0 (got ${String(w.windowMs)})`);
}
if (w.maxTokens !== undefined && (typeof w.maxTokens !== "number" || !Number.isFinite(w.maxTokens) || w.maxTokens < 0)) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].maxTokens must be a finite, non-negative number when present (got ${String(w.maxTokens)})`);
}
if (w.maxCostUsd !== undefined && (typeof w.maxCostUsd !== "number" || !Number.isFinite(w.maxCostUsd) || w.maxCostUsd < 0)) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].maxCostUsd must be a finite, non-negative number of USD when present (got ${String(w.maxCostUsd)})`);
}
const maxCostMicroUsd = maxCostMicroUsdOf(w);
if (maxCostMicroUsd !== undefined && !Number.isFinite(maxCostMicroUsd)) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].maxCostUsd ${String(w.maxCostUsd)} overflows the ledger's micro-USD unit (${String(w.maxCostUsd)} × 1e6 = ${String(maxCostMicroUsd)}) — Infinity is not the declared ceiling in the unit this ledger counts, so the window would read as governed while enforcing nothing it was given. Declare a ceiling below 1.79e302 USD.`);
}
if (w.maxTokens === undefined && w.maxCostUsd === undefined) {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[] must declare at least one ceiling — maxTokens, maxCostUsd, or both (got neither, over windowMs ${String(w.windowMs)}, ${String(w.anchor)}). A window with no ceiling admits everything, which is not what declaring a window means.`);
}
if (w.anchor !== "first-use" && w.anchor !== "rolling") {
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].anchor must be "first-use" or "rolling" (got ${String(w.anchor)})`);
}
}
return windows;
}
function rollingHorizonMs(windows) {
let widest;
for (const w of windows) {
if (w.anchor !== "rolling")
continue;
if (widest === undefined || w.windowMs > widest)
widest = w.windowMs;
}
return widest;
}
export function windowsGovernCost(windows) {
return windows.some((w) => w.maxCostUsd !== undefined);
}
function maxCostMicroUsdOf(w) {
return w.maxCostUsd === undefined ? undefined : Math.ceil(Number((w.maxCostUsd * 1e6).toPrecision(12)));
}
export function chargeUsageRecord(record, tokens, at, windows, costMicroUsd) {
const horizon = rollingHorizonMs(windows);
const governsCost = windowsGovernCost(windows);
if (governsCost && costMicroUsd === undefined) {
throw usageConfigError("usage_window.store_cost_unanswered", "a usage-window CHARGE for a deployment that governs maxCostUsd arrived with no cost figure at all. Core supplies one (a number, or an explicit null for spend nothing could price) on every such charge, so an absent one means a store in the chain does not carry the cost argument — folding it to 0 would leave the money ceiling open forever with nothing able to notice. Forward `costMicroUsd` from `UsageWindowStore.charge` into `chargeUsageRecord`.");
}
const cost = governsCost && costMicroUsd !== null ? costMicroUsd : undefined;
const unknown = governsCost && costMicroUsd === null;
const moves = tokens > 0 || (cost !== undefined && cost > 0) || unknown;
const keptSlots = horizon === undefined
? []
: record.slots
.filter((s) => s.at > at - horizon)
.map((s) => ({
at: s.at,
tokens: s.tokens,
...(s.costMicroUsd === undefined ? {} : { costMicroUsd: s.costMicroUsd }),
...(s.costUnknown === true ? { costUnknown: true } : {}),
}));
if (horizon !== undefined && moves) {
keptSlots.push({ at, tokens, ...(cost === undefined ? {} : { costMicroUsd: cost }), ...(unknown ? { costUnknown: true } : {}) });
}
const buckets = [];
for (const w of windows) {
if (w.anchor !== "first-use")
continue;
if (buckets.some((b) => b.windowMs === w.windowMs))
continue;
const prior = record.buckets.find((b) => b.windowMs === w.windowMs);
const lapsed = prior === undefined || at >= prior.openedAt + w.windowMs;
if (lapsed) {
if (moves) {
buckets.push({ windowMs: w.windowMs, openedAt: at, tokens, ...(cost === undefined ? {} : { costMicroUsd: cost }), ...(unknown ? { costUnknown: true } : {}) });
}
continue;
}
const priorCost = prior.costMicroUsd;
const nextCost = cost === undefined ? priorCost : (priorCost ?? 0) + cost;
const nextUnknown = unknown || prior.costUnknown === true;
buckets.push({
windowMs: w.windowMs,
openedAt: prior.openedAt,
tokens: prior.tokens + tokens,
...(nextCost === undefined ? {} : { costMicroUsd: nextCost }),
...(nextUnknown ? { costUnknown: true } : {}),
});
}
return { slots: keptSlots, buckets };
}
export function readUsageRecord(record, windows, now) {
const readings = [];
for (const w of windows) {
let tokens = 0;
let costMicroUsd = 0;
let costUnknown = false;
let freesAt;
if (w.anchor === "rolling") {
const floor = now - w.windowMs;
let oldest;
for (const s of record.slots) {
if (s.at <= floor)
continue;
tokens += s.tokens;
costMicroUsd += s.costMicroUsd ?? 0;
if (s.costUnknown === true)
costUnknown = true;
if (oldest === undefined || s.at < oldest)
oldest = s.at;
}
if (oldest !== undefined)
freesAt = oldest + w.windowMs;
}
else {
const row = record.buckets.find((b) => b.windowMs === w.windowMs);
if (row !== undefined && now < row.openedAt + w.windowMs) {
tokens = row.tokens;
costMicroUsd = row.costMicroUsd ?? 0;
if (row.costUnknown === true)
costUnknown = true;
freesAt = row.openedAt + w.windowMs;
}
}
const maxCostMicroUsd = maxCostMicroUsdOf(w);
const exhausted = (w.maxTokens !== undefined && tokens >= w.maxTokens) ||
(maxCostMicroUsd !== undefined && costMicroUsd >= maxCostMicroUsd);
const retryAfterMs = exhausted ? Math.max(1, freesAt === undefined ? w.windowMs : freesAt - now) : 0;
readings.push({
window: w,
tokens,
...(maxCostMicroUsd !== undefined ? { costMicroUsd } : {}),
...(maxCostMicroUsd !== undefined && costUnknown ? { costUnknown: true } : {}),
exhausted,
retryAfterMs,
});
}
return readings;
}
export function usageRetryAfterMs(readings, windows) {
if (windows !== undefined) {
if (readings.length !== windows.length) {
throw usageConfigError("usage_window.store_cost_unanswered", `the usage-window ledger answered ${String(readings.length)} reading(s) for ${String(windows.length)} declared window(s) — the read contract is one reading per window, in the order given. A window with no reading was never evaluated: refused rather than treated as open.`);
}
for (let i = 0; i < windows.length; i++) {
const w = windows[i];
const echoed = readings[i].window;
if (echoed === undefined || echoed.windowMs !== w.windowMs || echoed.anchor !== w.anchor || echoed.maxTokens !== w.maxTokens || echoed.maxCostUsd !== w.maxCostUsd) {
throw usageConfigError("usage_window.store_cost_unanswered", `the usage-window ledger's reading #${String(i)} does not echo declared window #${String(i)} verbatim (declared: windowMs ${String(w.windowMs)}, ${String(w.anchor)}, maxTokens ${String(w.maxTokens)}, maxCostUsd ${String(w.maxCostUsd)}) — the read contract requires the window back verbatim, in order, so its ceilings are provably the ones evaluated. Refused rather than re-attributed.`);
}
}
}
let worst;
for (const r of readings) {
if (r.window?.maxCostUsd !== undefined && r.costMicroUsd === undefined) {
throw usageConfigError("usage_window.store_cost_unanswered", `the usage-window ledger answered a window that declares maxCostUsd ${String(r.window.maxCostUsd)} (windowMs ${String(r.window.windowMs)}, ${String(r.window.anchor)}) with NO costMicroUsd — the money ceiling was never evaluated. Refused rather than treated as open: the store must persist the cost charged to it and report what the window holds.`);
}
if (!r.exhausted)
continue;
if (worst === undefined || r.retryAfterMs > worst)
worst = r.retryAfterMs;
}
return worst;
}
export class InMemoryUsageWindowStore {
records = new Map();
async charge(key, tokens, at, windows, costMicroUsd) {
const prior = this.records.get(key) ?? EMPTY_USAGE_WINDOW_RECORD;
this.records.set(key, chargeUsageRecord(prior, tokens, at, windows, costMicroUsd));
}
async read(key, windows, now) {
return readUsageRecord(this.records.get(key) ?? EMPTY_USAGE_WINDOW_RECORD, windows, now);
}
}