UNPKG

framework

Version:

The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.

60 lines 2.94 kB
import { QuotaPoller } from '../quota-poller.js'; import { quotaBoundaryStatus } from '../quota-boundary.js'; import { ClaudeCodeDriver } from '../driver/index.js'; import { readPreferences } from '../registry.js'; import { DEFAULT_SPEND_OFFSET } from '../preference-defaults.js'; /** * A {@link QuotaSource} backed by a live poller. * * Both questions are measured per call rather than captured: the boundary moves with the clock, * so a cached one would be stale the moment the week's day rolls over. Neither costs a reading — * the poller's last good windows are measured again, so asking per project is free. * * The panel's own boundary names no model on purpose: the bar is about the account, and a model's * own week only narrows the gate for a run that has chosen one (#879/#1619). */ export function pollerQuotaSource(poller, now = () => Date.now(), /** The user's slider position, read per call so moving it takes effect without a restart (#960). */ limitOffset = () => DEFAULT_SPEND_OFFSET) { const measure = async (model) => { const windows = poller.current().lastGood?.windows ?? []; return quotaBoundaryStatus({ windows, now: now(), ...(model ? { model } : {}), limitOffset: await limitOffset() }); }; return { stop: () => poller.stop(), boundaryFor: model => measure(model), read: async () => { const envelope = poller.current(); const windows = envelope.lastGood?.windows ?? []; const boundary = await measure(); const view = { windows, ...(boundary ? { boundary } : {}), ...(envelope.lastGoodAt !== undefined ? { readAt: envelope.lastGoodAt } : {}), ...(envelope.latest && !envelope.latest.available ? { unavailable: envelope.latest.reason } : {}), }; return view; }, }; } /** * The daemon's own quota source: it polls for the whole life of the dashboard, * not just during an agent, because the panel has to show where the account stands * even when nothing is running. * * Separate from the per-agent guard on purpose — that one exists to pause an agent * and dies with it, this one exists to draw a bar. */ export function defaultQuotaSource(env = process.env) { const driver = new ClaudeCodeDriver(); const poller = new QuotaPoller({ read: () => driver.readQuota() }); poller.start(); // One source, so the bar the user reads and the line auto PM obeys cannot disagree (#960): the // slider is read here rather than in each consumer. An unreadable registry means the default // policy, which is what a fresh install runs anyway. return pollerQuotaSource(poller, undefined, async () => { const prefs = await readPreferences(undefined, env).catch(() => ({})); return prefs.autoSpendOffset ?? DEFAULT_SPEND_OFFSET; }); } //# sourceMappingURL=quota.js.map