ccquota asked one vendor one question. The shape that generalizes is two parts:
a small set of probe adapters, and a declarative override for a provider nobody
anticipated.
Three adapters, each verified against a LIVE endpoint rather than assumed:
- deepseek family: GET /user/balance →
{is_available, balance_infos:[{currency,total,granted,topped_up}]}.
Granted vs topped-up is kept separate on purpose: gift credit expiring on a
schedule is a different operational fact from prepaid money.
- OpenAI console shape: /v1/dashboard/billing/subscription +
.../billing/usage. This reports LIMITS and SPEND, not a balance — the live
provider has hard_limit_usd 1e8. There is deliberately no `remaining`:
ceiling - spend would read as "$99,999,339 left", a number nobody should
believe. It renders as spend against a ceiling instead.
- commandcode: rolling 5h / weekly / monthly windows plus billing period.
A provider with no working adapter is SKIPPED and listed by name at the bottom.
Most of these upstreams are small re-sells whose dashboard paths return an HTML
page rather than JSON; a table full of "unknown" rows teaches the operator to
ignore the page entirely. Failures that are NOT "no endpoint" — a 403 on a key we
hold — stay visible, because those are the ones worth fixing.
## Cost control, and a lock the probe runs under
First load measured 101s for 21 sources: 3 adapters x 2 attempts x 4s, times 21.
Call() holds the plugin's write lock for the whole invocation, so every
__llmsproxy_http round trip inside it blocks request_end hooks — which is how
billing accrues money. A slow upstream is not just a slow card.
- Timeout cut to 4s (from 10s).
- A host->adapter memo, persisted in plugin.state, so the dead ends are
discovered once per process instead of on every page open. Steady state is
22s.
- The memo records NEGATIVE results too, which is what actually paid: only
recording successes left every silent source re-probing forever.
- Negatives carry a timestamp and expire after 30 minutes. "This upstream has
no balance endpoint" is a fact that changes — vendors ship dashboards — and a
permanent negative makes the page quietly stop reporting a source that
started working.
- The page calls collect_source concurrently, one call per source, so a single
502 over 21 sequential probes becomes 21 independent answers.
## Two bugs the page found
- deepseek reports topped_up_balance -0.02 against a positive grant; the `v <= 0
→ "0.00"` branch flattened a real debit to zero. Negative balances now render
as -¥0.02.
- PLAN_CAPS was declared below the adapter that reads it, so Command Code hit
"attempt to index global 'PLAN_CAPS' (a nil value)" on every probe. A Lua local
is nil until its assignment runs.
Verified on production: 5 sources report, 16 skipped by name, 1 visible failure
(tabitoken 403). deepseek ¥0.32 (赠送 0.34 · 充值 -0.02), justwoker $360,865.71
spent against an ∞ ceiling, both Command Code seats with their three windows.
Co-Authored-By: ModelRouter <noreply@modelrouter.dev>