Skip to content

feat(quota): 接入 Codex 与 Antigravity 实时额度探测与监控 - #845

Open
ana52070 wants to merge 3 commits into
xintaofei:mainfrom
ana52070:feat/agent-quota-monitor
Open

ana52070 wants to merge 3 commits into
xintaofei:mainfrom
ana52070:feat/agent-quota-monitor

Conversation

@ana52070

Copy link
Copy Markdown

背景

在多智能体协作与代码生成场景下,用户无法直观了解当前生效智能体的剩余配额窗口(如 5 小时短窗口限流、周额度、每日请求数等)。在密集编码或自动化调度过程中极易突遭 429 配额耗尽或限流中断。

现有的客户端和后端仅有各 Agent 会话本身的交互逻辑,缺少对主流 CLI / OAuth 智能体账户真实使用额度的读取、探测与状态展示。

改动

在输入框工具栏(Composer)新增智能体配额徽章(ComposerQuotaBadge),并在后端实现统一的 QuotaManager 探测管理体系,首期打通 OpenAI Codex 与 Google Antigravity 的真实配额接口。

几条定死的语义与机制保证:

  • 零侵入读取与安全边界:仅读取本地已有的认证上下文(~/.codex/auth.json 与 ~/.gemini/antigravity-acp/acp_token.json),绝不向任何第三方转发凭据。未登录或凭据损坏时优雅降级为未登录提示,不阻断主窗口与正常对话流程。
  • 内存 TTL 缓存抑制下游风暴:额度探测由 QuotaManager 托管,默认 30 秒线程安全 TTL 缓存;快速切换 Agent 或连续发送消息时直接命中缓存,避免频繁请求触发第三方端点的反爬或频控。
  • 双通道架构(Desktop + Remote):桌面端走 Tauri IPC 命令 get_agent_quota;远程/Web 端走 Axum REST 端点 GET /api/quota/:agent_type,同一套数据模型与业务逻辑。

实现分布:

  • src-tauri/src/quota/:
    • mod.rs — 核心 QuotaManager,基于 Arc<RwLock<HashMap<String, CachedQuota>>> 管理缓存、失效及分发。
    • codex.rs — 探通 OpenAI 官方 Wham usage 端点(https://chatgpt.com/backend-api/wham/usage)。自动解析 access_token 与可选的 account_id(完美支持个人版与 ChatGPT Team 团队版空间),提取 5 小时主要窗口、周限制窗口使用率及精准重置倒计时。
    • antigravity.rs — 接入 Google Cloud Code Private API (CCPA) Consumer Daily 端点(loadCodeAssist 与 retrieveUserQuotaSummary)。集成 Google OAuth Refresh Token 自动换票,解析用户套餐(如 Google AI Pro / Free Tier)及 Gemini 模型组(5h / weekly)实时配额 bucket。
  • src-tauri/src/models/quota.rs:AgentQuotaInfo、QuotaWindow、SpendLimit 数据模型,全链路 camelCase 序列化并配套 6 个 Rust 单测。
  • src-tauri/src/commands/quota.rs & web/handlers/quota.rs:注册桌面 Tauri 命令与 Web 路由。
  • src/components/chat/composer-quota-badge.tsx:
    • 徽章集成于 Composer 工具栏(智能体切换器旁),根据当前选中的 Agent 动态呈现。
    • 三级健康度色标:健康绿色(剩余 >30%)、警示黄色(10%~30%)、临界红色(<10%)。
    • 浮层卡片展开查看细分窗口(短窗口 / 周限制 / 计划名 / 重置时间倒计时),支持手动一键刷新。
  • src/components/chat/composer-quota-badge.test.tsx:覆盖挂载渲染、色标阶段、popover 详情、手动刷新及未登录降级等 7 个前端用例。
  • 10 种语言的 i18n 词条全量补齐(zh-CN, zh-TW, en, ja, ko, es, fr, de, pt, ar)。

验证

  • 实机端点验证:
    • 本地 Codex(ChatGPT Team):成功拉取真实使用率 67% used / 33% remaining,5小时窗口倒计时精准匹配。
    • 本地 Antigravity(Google AI Pro):成功拉取 loadCodeAssist 套餐及 retrieveUserQuotaSummary Gemini 5小时(剩余约 52.7%)与周额度(剩余约 86%)。
  • 测试通过:
    • cargo test quota --no-default-features --bin codeg-server --lib → 21 个单测全部通过。
    • pnpm test → 439 个测试文件全量通过(含 7 个 quota badge 前端测试)。
image image

- 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 added a commit to SousekiL/codeg that referenced this pull request Sep 27, 2026
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 added a commit to SousekiL/codeg that referenced this pull request Sep 27, 2026
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 added a commit to SousekiL/codeg that referenced this pull request Sep 27, 2026
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>
- 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
Author

Update:
采纳了 @SousekiL 在 #850 中的建议,补充了一个 UX 细节优化(commit 26692b3):

  • 徽章改为优先展示剩余百分比更低(即最先告罄)的瓶颈窗口(Binding Window)。
  • 避免了在 ChatGPT Pro 等套餐下,短周期窗口(5h)一直处于 100%、而实际消耗的周度预算(7d)无法及时在徽章直观呈现的问题。
  • 补充了相关场景的单测与边界判断,目前所有单元测试与类型检查均已通过。

SousekiL added a commit to SousekiL/codeg that referenced this pull request Sep 28, 2026
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 added a commit to SousekiL/codeg that referenced this pull request Sep 28, 2026
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 added a commit to SousekiL/codeg that referenced this pull request Sep 28, 2026
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 added a commit to SousekiL/codeg that referenced this pull request Sep 28, 2026
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>
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.

1 participant