@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
80 lines • 3.19 kB
JavaScript
/** The first window whose token or spend ceiling is reached, as a {@link QuotaBlock}. */
export function exhaustedWindow(windows) {
for (const window of windows) {
const tokensOut = window.limitTokens !== undefined && (window.usedTokens ?? 0) >= window.limitTokens;
const spendOut = window.limitUsd !== undefined && window.usedUsd >= window.limitUsd;
if (tokensOut || spendOut) {
return {
period: window.period,
reason: `${window.period === 'day' ? 'Daily' : 'Monthly'} ${spendOut ? 'spend' : 'token'} limit reached`,
};
}
}
return undefined;
}
/** How much of `window`'s ceilings is used, `0..1+` (the larger of spend and tokens), or `null`. */
export function quotaUsedRatio(window) {
const ratios = [];
if (window.limitUsd !== undefined && window.limitUsd > 0) {
ratios.push(window.usedUsd / window.limitUsd);
}
if (window.limitTokens !== undefined &&
window.limitTokens > 0 &&
window.usedTokens !== undefined) {
ratios.push(window.usedTokens / window.limitTokens);
}
return ratios.length === 0 ? null : Math.max(...ratios);
}
/**
* The fullest window past its `warnAt`, as a {@link QuotaWarning} — `undefined` when none is, or
* when one is exhausted (that is `blocked`, not a warning).
*/
export function quotaWarning(windows) {
if (exhaustedWindow(windows) !== undefined)
return undefined;
let fullest;
for (const window of windows) {
if (window.warnAt === undefined)
continue;
const ratio = quotaUsedRatio(window);
if (ratio === null || ratio < window.warnAt)
continue;
if (fullest === undefined || ratio > fullest.ratio) {
fullest = { period: window.period, ratio };
}
}
return fullest;
}
/** The UTC day range (`YYYY-MM-DD`, inclusive) and reset instant of `period` around `now`. */
export function quotaPeriodRange(period, now) {
const year = now.getUTCFullYear();
const month = now.getUTCMonth();
const day = now.toISOString().slice(0, 10);
if (period === 'day') {
const next = new Date(Date.UTC(year, month, now.getUTCDate() + 1));
return { fromDay: day, toDay: day, resetsAt: next.toISOString() };
}
const first = new Date(Date.UTC(year, month, 1));
const last = new Date(Date.UTC(year, month + 1, 0));
return {
fromDay: first.toISOString().slice(0, 10),
toDay: last.toISOString().slice(0, 10),
resetsAt: new Date(Date.UTC(year, month + 1, 1)).toISOString(),
};
}
/** Is this a {@link QuotaProvider} (rather than a daily `QuotaStore`)? */
export function isQuotaProvider(value) {
return (typeof value === 'object' &&
value !== null &&
typeof value.report === 'function');
}
/** A send refused because a budget window is exhausted — the chat route's `429 quota_exceeded`. */
export class QuotaBlockedError extends Error {
period;
constructor(period, message) {
super(message);
this.period = period;
this.name = 'QuotaBlockedError';
}
}
//# sourceMappingURL=quota-provider.js.map