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.

84 lines 3.99 kB
import { contextAutoPm, contextAutoPmSweep, contextQuota } from './context.js'; // The usage panel's read surface (#533): where the account's subscription quota stands, // and where it stands against the quota boundary (#879). The source is threaded through // the Telefunc request context by the daemon, which polls for its whole life; a public // host (the relay) leaves it unwired, so the panel reports it has no reading rather than // an empty one. /** An honest empty view: no reading, and so no boundary to measure against. */ function noReading() { // No windows and no boundary rather than zeroes: an empty bar reads as // "nothing used", which is the one thing this panel must never imply. return { windows: [], unavailable: 'fetch-failed' }; } /** Where the account's quota stands against its boundary. */ export async function onQuota() { const source = contextQuota(); if (!source) return noReading(); return source.read().catch(() => noReading()); } /** * What auto PM last decided (#1161), for the line under the panel's toggle. It sits beside * `onQuota` because it is the same panel and the same gate: auto PM spends against exactly the * boundary drawn above it. * * `undefined` on a host with no sweep (the relay), which the panel reads as "nothing to say" * rather than as an idle sweep — the distinction this whole read exists to make. */ export async function onAutoPm() { const report = contextAutoPm(); if (!report) return undefined; try { return report(); } catch { return undefined; } } /** * Sweep now rather than at the next interval (#1210). The loop already had this — it is what a * write that switches the preference on triggers (#1167) — but until now nothing could ask for * it directly, so the only way to fast-forward was to tick the box off and on again. * * The `autoPm` preference does not gate it: that preference is consent to spend quota *unasked*, * and this call is asking. So with auto-run off the daemon still sweeps once — every other * stand-down reason in force — and the schedule stays wherever the box says. * * Awaits the sweep and returns what it decided, one line per project (#1433): the click used to * be fire-and-forget, so two presses could show literally nothing — no loading state, no * outcome, and the stand-down reason recoverable only from the source. The outcomes are read * off the loop's own report once the tick resolves, so the card can say them without a poll * having to race the sweep. `false` still means a host with no loop (the relay), which the * button reads as "nothing here to trigger". * * `drainOnly` narrows the sweep to working the queue (#1204): the drain routine's Run now spins * agents up on the queue's entries — the fan-out only the sweep can do — and an empty queue is * reported rather than borrowed for a rotation job. */ export async function sendAutoPmSweep(opts) { const sweep = contextAutoPmSweep(); // The reporter is captured BEFORE the sweep is awaited: the Telefunc request context does not // survive an await, so a post-await `contextAutoPm()` found nothing on every real request and // the card fell back to "The sweep ran." — the very fallback this RPC exists to avoid. The // captured closure needs no context to be called later. const reporter = contextAutoPm(); if (!sweep) return { ok: false }; try { await sweep(opts?.drainOnly ? { drainOnly: true } : undefined); } catch { return { ok: false }; } // The outcomes live on the loop's report — the same lines `onAutoPm` polls — read once the // tick has resolved, so they describe the sweep this click fired. try { const report = reporter?.(); return { ok: true, ...(report ? { outcomes: report.outcomes } : {}) }; } catch { return { ok: true }; } } //# sourceMappingURL=quota.telefunc.js.map