Files
jason.woltjeandClaude Opus 5.5 aa625565f6 bus, cli, webui: token limits per instance, model, provider and key (row 125, #1619)
Adds token limits under launch.limits.tokens (instances, providers, keys,
models.P.M). Core (packages/bus/src/limits.mjs) reads the organization
file and the per-turn usage records row 124 writes, then asks every
switched-on limit-check plug-in; the first refusal wins. A limit no
switched-on check reports reads "not enforced". The limit-check kind is
interface 2 (mayLaunch, mustStop, report); a v1 check is refused at load.
The shipped token-limit check is pure and counts known end records only;
unknown turns add nothing and are shown as their own count.

The launcher refuses limit-reached through the host's mayLaunch op, or
limit-check-failed naming the check. The broker asks mustStop after a
usage end and stops the run at its next receive or state. Settings stamps
since on a new or changed limit and runs reset; launch.mjs and
business.mjs validate the shape. Readers: mosaic limits and mosaic limits
reset, the bus limits view, the Console /api/bus/limits route and the
Settings token table with Reset. Key limits stay "not enforced" until
row 126 names accounts on records.

Owner Dewey, design under lead decision 150.
Reviewer Filbert: r1 changes (comment 28965), r2 approve (28981), r3
approve (28996) on candidate manifest 8b71c405...fe56 after the rebase
onto row 164 (37 of 38 paths with identical +/- lines, TOOLS.md:621
bracket). Decision 123 go on the bus.js hunk from Mos (mos-0814). Sage
gate on b6827d19e: 25 steps, all rc 0 (15 packages, 10 script suites), 2295 node tests and 422 script selftests, 0 failed, 20:03:25Z to 20:08:08Z, network sage-r125_default removed.

Live stays as pinned. Not part of the 8e7ea89a1 window.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 15:21:49 -05:00

31 lines
1.6 KiB
Markdown

# Token limit check
Row 125 (#1619), REQ-LIMIT-3 and REQ-LIMIT-4, limit-check interface 2. Enable
with `"plugins": { "limit-check": ["token-limit"] }` in the organization file,
keeping its other plug-in kinds. Human changes use `mosaic plugins set` and the
current revision.
It enforces `launch.limits.tokens`: per role instance (`instances`), provider
(`providers`), provider and model (`models.<provider>.<model>`) and key
(`keys`). Each limit is `{limit, since}`.
- A count is `input + output + cacheWrite + cacheRead` summed over the known
per-turn records whose subject matches and whose `at` is at or after `since`.
An unknown turn adds nothing; `unknownTurns` counts the distinct unknown
turns apart, so a count is a floor, not proof.
- With no usage source switched on, every turn's record is unknown (source
`@none`), so every limit counts zero.
- `mayLaunch` and `mustStop` answer the first limit, in the order above, that
covers the subject and whose count is at or over it. A limit of 0 refuses
every launch of its subject.
- A key matches a record's `account`. Until accounts are named (row 126),
every record's account is null, so a key limit matches nothing and `report`
shows it as `not enforced: no records name a key` (lead decision 150, Q1).
- Counts are summed as BigInt; one past `Number.MAX_SAFE_INTEGER` is reported
as a digit string.
The module is pure: it reads no file and no store. A bad `since` or record
`at` throws `bad-time`, a bad amount `bad-record`, and records that aren't a
list `bad-records`; core turns any throw into a refusal, a stop, or `check
failed` (fail closed).