Repository navigation
w738, w739: each person's Claude token pool; orchestrators and the ops worker on it; the dispatcher's reserve - #241
Merged
Merged
Conversation
…e ops worker on it, the dispatcher's reserve A person's runs use that person's own vault Claude tokens (several per person: people/<id>/claude-tokens/<name> on the FFBox host, loaded by fff-vm vault-sync), picked by server/tokenPool.ts at every process start: the weekly window that resets soonest first, the 5-hour reset as tie-break; no new process at 80% of the 5-hour window, one at a time at 95% weekly, retired at 99%, used up at 100; a session keeps its token only while it passes. A worker, standing agent and the ops worker are held with the reason when the pool is capped (no fallback); a person's orchestrator uses the pool up and then stops with a message. No shared Claude token, nobody else's. A person with no vault token keeps today's account. - claudeAccounts.orchestrator "vault" (an owner's setting; the dispatcher stays on the token file): poolRunEnv gives the orchestrator and the ops worker the person's one token with every other Claude credential removed. - The ops worker starts a fresh conversation and process for every new job and every change of caller. - Limits are config vault.pool.* (80/95/99, 5% a day, 20%): one system-wide set anyone can change with set_app_config, checked 0-100, one-at-a-time not above retired, logged with who, read at each process start. - The dispatcher's credential (resolved from config) and the host token keep a reserve of 5% of the weekly window per day left and 20% of the 5-hour window; the dispatcher may run into it; system_status and a dashboard banner show it. - Usage: a token without user:profile (403) is read from the rate-limit headers as FFBox does; near-limit tokens are polled every 2 minutes; the SDK's rate_limit_event raises a meter between polls. - fffctl vault list and system_status show each pool; vault.sh loads claude-tokens/<name>. Request: w738 Request: w739 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…g test waits up to 30 s for its test socket (a slow runner) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Request: w738
Request: w739
One PR for both (they share the pick, the account setting and the tests; lothsahn agreed).
TL;DR: each person's runs use only that person's own pool of vault Claude tokens (several per person), picked by weekly reset, with the 80 / 95 / 99 limits. Their orchestrator (
claudeAccounts.orchestrator = "vault") and the ops worker (per job and per caller) run on it too. The dispatcher keeps the shared token file and a reserve (5% of the week per day left, 20% of the 5-hour window). Tokens withoutuser:profileare read from the rate-limit headers, as FFBox does. Needs a portal deploy and the newvault.shon the FFBox host. No live config change.What it does (the rules are in
server/tokenPool.ts, pure functions;docs/vault.mdsection 4 has them in full)fffctl vault listnames it "not in any pool"). Work nobody asked for uses the system payer's pool.vault.pool.*, one system-wide set, 0-100, one-at-a-time not above retired, any person's orchestrator may set them, logged with who, read at each process start): 5-hour >= 80 no new process; weekly >= 95 one process at a time; weekly >= 99 retired; 100 used up. No numbers counts as 50%. A session keeps its token only while it passes.poolRunEnvgives the one token with every other Claude credential removed (as the token file does), read at each session start; an owner's setting; the dispatcher refuses"vault"and keeps the token file (an inherited"vault"resolves to the token file).claudeAccounts.dispatcheris, today the token file) plus the host token; 5% of the weekly window per day left to its reset and 20% of the 5-hour window; the dispatcher may always run into it and nothing checks it before it starts (tested). Others on that credential (a person with no vault token) are not refused, since they have nothing else;system_statusshows each reserve and the dashboard warns while runs use the buffer. Until the first reading it counts as inside its reserve. One token is one account (no matching of two tokens).fetchTokenLimits(rate-limit headers) now also runs on HTTP 403, remembered for 6 h; tokens near a limit (5-hour >= 60, weekly >= 90, or no numbers) are polled alone every 2 minutes; the SDK'srate_limit_eventraises a meter between polls. FFBox's method:scripts/claude_keys.pyin Final-Factory/ffbox, last changed in57c35a5b4b(masteredfddd5160): the usage endpoints 403 for a setup-token ("measured 2026-09-04"), so one Haiku call withmax_tokens1 is made andanthropic-ratelimit-unified-5h-/7d-utilizationand-resetare read, also off a 429 reply.system_statushas a line per person's pool (each token's last four characters, state, meters, resets, agents running on it) and per reserved credential;fffctl vault listends with the pools; a dashboard banner for a pool used up or over its caps and for the dispatcher's buffer in use.claude-tokens/<name>files per person;vault-syncloads them ashost-<user>-claude-<name>.Evidence
server/tokenPool.test.ts(9),server/vaultPool.test.ts(18), additions tousage.test.ts(3),opsWorker.test.ts(1), updatedvault.test.ts; the full unit suite passes except 4 tests that fail only in this sandbox's temp folder (EPERM onrmSyncofff-msb-*; they are unrelated and run in CI).tscclean for the server and the web.via the API's rate-limit headers), the SDK event's scale and frequency, and the overshoot between polls (no poll history existed; every poll logs its percentages, so a week of journal gives it).fffctl vault listwith a second pool token and a refused file name in the nested VM.🤖 Generated with Claude Code