Skip to content

feat(quota): add Claude Code and Devin subscription quota probes - #850

Draft
SousekiL wants to merge 5 commits into
xintaofei:mainfrom
SousekiL:feat/quota-claude-devin
Draft

SousekiL wants to merge 5 commits into
xintaofei:mainfrom
SousekiL:feat/quota-claude-devin

Conversation

@SousekiL

@SousekiL SousekiL commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Adds two more quota-detection sources on top of the QuotaManager from #845 (this PR stacks on top of #845 and includes its commits; the binding-window display now lives in #845 itself; recommend merging this PR after #845 lands, or having @ana52070 fold these two providers directly into #845):

  • Claude Code: reads the OAuth credentials Claude Code itself saves after login (the macOS Keychain entry Claude Code-credentials, or <CLAUDE_CONFIG_DIR|~/.claude>/.credentials.json on other platforms), and calls the same endpoint used by Claude Code's /usage command, https://api.anthropic.com/api/oauth/usage (with anthropic-beta: oauth-2025-04-20), mapping the five_hour / seven_day utilization to the 5-hour and weekly windows, and mapping subscriptionType to the plan name. Shows a clear message instead of a raw HTTP error when the login has expired.
  • Devin CLI: reads windsurf_api_key and api_server_url from ~/.local/share/devin/credentials.toml (supports XDG_DATA_HOME), and calls the same Connect RPC that Devin CLI itself uses, exa.seat_management_pb.SeatManagementService/GetUserStatus, taking daily / weekly quota remaining percentage, reset time, plan name, and ACU usage from PlanStatus (ACU is appended after the plan name in the form 12.2 / 150 ACU). Both the built-in devin id and the user-registered custom:devin id point to the same account and the same detection.
  • Frontend SUPPORTED_AGENTS gains claude_code, devin, custom:devin; reuses feat(quota): 接入 Codex 与 Antigravity 实时额度探测与监控 #845's badge and popover, no new UI.
  • Consistent with feat(quota): 接入 Codex 与 Antigravity 实时额度探测与监控 #845: credentials are only sent to their issuer, never persisted to disk, never forwarded elsewhere.

Testing

  • cargo test --no-default-features --bin codeg-server --lib quota → 27 unit tests pass (6 new: payload parsing for both sides, missing-field tolerance, credential validation, camelCase / snake_case compatibility).
  • composer-quota-badge.test.tsx → 9 pass (2 new cases for Claude and custom:devin; the original "unsupported agent" case now uses gemini).
  • tsc --noEmit passes.
  • Note: the response fields for both remote endpoints were written based on the definitions found in the Claude Code / Devin CLI binaries, with parsing tolerant of both camelCase and snake_case. Verification against my own live accounts is still in progress; I'll follow up with fixes on this PR if any fields turn out to differ.

Assisted with Claude Code

- Add QuotaManager with TTL cache mechanism in Rust backend
- Support 5h sliding window and weekly quota parsing for Codex and Antigravity
- Implement dual-runtime commands and Axum endpoints (/api/quota/{agentType})
- Add ComposerQuotaBadge component in chat composer with countdown and progress bars
- Support manual refresh, low quota alerts, and full internationalization (10 languages)
- Add comprehensive unit tests covering models, parsers, and UI components
@SousekiL
SousekiL force-pushed the feat/quota-claude-devin branch from 34de477 to e170580 Compare September 27, 2026 17:26
@ana52070

Copy link
Copy Markdown

感谢补充 Claude Code 和 Devin 的额度探测支持!
我倾向于保持 #845 先完成 QuotaManager + Codex / Antigravity 的基础实现,等 #845 合并后,再让 #850 基于最新 main 继续合入 Claude Code / Devin,这样 review 和提交历史会更清晰一些。
如果维护者更希望一次性处理,也可以将这两个 provider 一并收进 #845,我这边可以配合调整。

@SousekiL

Copy link
Copy Markdown
Contributor Author

Agreed — #845 first. I've marked this as draft and will rebase onto main once #845 lands.

One thing for #845 itself: the badge always prefers the 5-hour window, but ChatGPT Pro reports one that stays ~100% while the weekly budget drains, so Pro users see a meaningless "5h" figure. My last commit here (fix(quota): badge shows the binding window…) shows whichever window has less left. It touches your badge code, so it may fit better in #845 — feel free to take it.

@SousekiL
SousekiL marked this pull request as draft September 27, 2026 19:10
@ana52070

Copy link
Copy Markdown

Thanks, that makes sense. I'll bring the binding-window badge fix into #845. Appreciate you catching this!

- Pick whichever window has less remaining percentage via pickBindingWindow
- Map daily limit labels to 1d
- Add tests covering ChatGPT Pro binding window and tie-breaking cases
@ana52070

Copy link
Copy Markdown

The binding-window badge fix has been committed and pushed to #845 (26692b3). Thanks again for the spot and suggestion!

@SousekiL

Copy link
Copy Markdown
Contributor Author

Nice, thanks for the quick fix!

Builds on the QuotaManager from xintaofei#845 with two more providers.

Claude Code: reads the CLI's own OAuth credentials (macOS Keychain item
"Claude Code-credentials", else <CLAUDE_CONFIG_DIR|~/.claude>/.credentials.json)
and calls the same https://api.anthropic.com/api/oauth/usage endpoint the
CLI's /usage command uses, mapping five_hour / seven_day utilization onto
the 5-hour and weekly windows and subscriptionType onto the plan name. An
expired login is reported as such rather than as an opaque HTTP error.

Devin CLI: reads windsurf_api_key + api_server_url from
~/.local/share/devin/credentials.toml (XDG_DATA_HOME aware) and calls the
CLI's SeatManagementService/GetUserStatus Connect RPC; PlanStatus supplies
the daily / weekly remaining percentages and reset times, plan name and
ACU counters. Both the built-in `devin` id and the `custom:devin` wire id
of a user-registered Devin ACP agent resolve to this probe.

Credentials are only ever sent to their issuing service and never stored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@SousekiL
SousekiL force-pushed the feat/quota-claude-devin branch from c9787b2 to ea0cd62 Compare September 28, 2026 05:39
It is read only by the macOS Keychain branch, so Linux and Windows builds
flagged it as dead code under clippy -D warnings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants