fix(quota): ignore GLM MCP call counts and announce a cleared quota - #210
Merged
Merged
Conversation
The older GLM Coding Plans report a monthly TIME_LIMIT item that counts calls to Z.ai's own MCP tools (search-prime, web-reader, zread). Those calls never pass through the gateway, so the count says nothing about whether requests through it will be served. It was still reported as the `monthly` quota window, shown, counted towards the tightest window and able to raise a used-up notice. - The TIME_LIMIT item is ignored and `monthly` is no longer a quota window. - A 1310 on a model request means the weekly quota is used up, so it marks `weekly` only, whatever its message says. 1316-1321 still take 5h or weekly from the message, and otherwise the fuller of the known 5h and weekly windows. - `credits` are read only from credit-plan items (CREDIT_LIMIT). A TOKENS_LIMIT item carrying usage/currentValue/remaining counts tokens, and showing those as credits would be wrong. - When a key is found to have no plan and core clears the quota it had stored for that upstream, it now emits a QuotaSeen with empty `windows`. The UI already replaces an upstream's quota with the windows of the event, so the quota cell collapses at once instead of on the next read of /quota. Nothing is emitted when nothing was stored. CONTROL_API_VERSION is now 24: the window vocabulary no longer has `monthly`, and an empty QuotaSeen means the upstream's quota was taken down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
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.
What this changes
The GLM Coding Plan quota added in 0.50.0 (#204, #208) no longer reports the MCP call count of the older plans, and core now tells the UI when it takes an upstream's quota down.
TIME_LIMITitem is ignored. In the older plans' answer from the quota endpoint it counts calls to Z.ai's own MCP tools (search-prime, web-reader, zread). It is no longer read, so there is nomonthlywindow: it is not reported, not shown, does not count towards the tightest window and cannot raise a used-up notice.weeklyonly. On a model request 1310 means the weekly quota is used up, whatever its message says ("Weekly/Monthly", "Monthly", "5 hour" all giveweekly). 1308 is unchanged. 1316-1321 keep the existing mapping withoutmonthly: 5h or weekly when the message says which, otherwise the fuller of the known 5h and weekly windows, and weekly when neither is known.guess_windowno longer takes the code, since only 1316-1321 reach it now.creditscome only fromCREDIT_LIMITitems. Withmonthlygone, the doc comments ofQuotaCreditsandQuotaWindow::creditsdescribe the credit plan only. The parser now enforces it as well: aTOKENS_LIMITitem that carriesusage/currentValue/remainingcounts tokens, and the app would show those numbers as credits.QuotaSeenwith emptywindows. Nothing is emitted when nothing was stored.Why
The MCP calls never pass through the gateway, so their count says nothing about whether requests through it will be served. It showed up as a quota window, and a used-up monthly count could colour the upstream as used up or notify.
A key found to have no plan had its quota cleared silently, so the app kept showing the old quota until it next read
/quota. The app already replaces an upstream's quota with the windows of eachQuotaSeenit receives (useUpstreamStatsin Lite), so an emptyQuotaSeencollapses the quota cell at once. Reusing that event is the smallest change that does this: no new variant, and the bus and recorder already treatQuotaSeenas upstream state, not request history.Protocol changes
CONTROL_API_VERSION23 -> 24.QuotaWindow.window,QuotaExhausted.window) no longer hasmonthly.QuotaSeenis documented as carrying the upstream's full set of windows, to replace what the client had. Emptywindowsmeans the upstream's quota was taken down: the earlier windows no longer count and the upstream is gone from/quota. It is emitted when a GLM key is found to have no plan and core had a quota stored for it.QuotaWindow.credits/QuotaCredits: only credit-plan windows (CREDIT_LIMIT) have them.No endpoints, types or message codes change. The config manual does not change.
How it was verified
cargo fmt --all -- --check: cleancargo clippy --workspace --all-targets -- -D warnings: cleancargo test --workspace(proxy variables unset): 1696 passed, 0 failedcargo clippy -p tw-api --all-targets --features ts -- -D warnings,cargo test -p tw-api --features ts,export_tsandtsc --noEmit --stricton the export: clean,CONTROL_API_VERSION = 24in the bindingsNew or changed tests:
glm::tests::an_old_v2_plan_adds_a_weekly_window_and_ignores_the_mcp_calls: a V2 answer whoseTIME_LIMITis used up (100%, remaining 0) gives exactlyweeklyand5h, and nothing is marked rejected because of it.an_old_v1_plan_has_only_the_five_hour_windowdoes the same for V1.glm::tests::a_1310_is_the_weekly_window_whatever_the_message_saysandstate::glm::tests::a_1310_marks_only_the_weekly_window: a 1310 whose message says "Monthly" marks onlyweekly, even when the known 5h window is fuller, and emits a singleQuotaExhaustedforweekly.glm::tests::team_limits_count_too: 1316-1321 read 5h and weekly from the message, and a message that says monthly names no window.glm::tests::only_a_credit_window_has_credits: aTOKENS_LIMITitem with the three numbers has nocredits.state::glm::tests::forgetting_a_quota_tells_the_ui_with_an_empty_quota_seen: clearing a stored quota emits one emptyQuotaSeen, clearing again emits nothing, and a later used-up window is reported again.tests/glm_quota.rs::a_key_found_to_have_no_plan_takes_its_quota_down_at_once: end to end against the fake GLM. A key with a credit plan is read, the key is replaced by one without a plan, and the next/quotarefresh clears the quota and emits an emptyQuotaSeen.Notes for review
monthly(harmless once core stops sending it).QuotaSeencarries, so an empty one clears none. Lite can treat an emptyQuotaSeenas clearing that upstream's quota notices. That is a change on the Lite side, not here.🤖 Generated with Claude Code