如何精准检测Codex订阅状态:codex-console多源解析与Rate Limit窗口识别原理
【免费下载链接】codex-consolecodex-console 是一个集成化控制台项目,支持任务管理、批量处理、数据导出、自动上传、日志查看与打包支持。项目地址: https://gitcode.com/gh_mirrors/co/codex-console
codex-console 是一个面向 Codex 账号的集成化控制台,它通过多源解析 + Rate Limit 窗口识别双引擎,精准检测 Codex 订阅状态(Plus / Team / Basic)与 5 小时、周配额额度,还能在代理异常、接口抖动时自动降级,避免误判。本文将拆解它的订阅状态检测原理。
一、为什么单接口检测不够可靠?
OpenAI 的订阅与配额信息分散在多个后端接口中,且字段会随版本变化。只依赖某一个接口,容易出现"昨天能跑、今天翻车"的问题:
- 某个接口返回 403 / 404 时,直接判为"无订阅"会造成误判降级;
- 配额字段名不统一(
used_percent可能是 0~1 比例,也可能是 0~100 百分比); - 5 小时窗口和周窗口的字段可能互换位置。
codex-console 的解法是:并发抓多个来源、按优先级交叉验证、失败时静默降级,核心逻辑在 src/core/openai/overview.py。
二、多端点并发抓取:3 个数据源各司其职
检测入口是fetch_codex_overview(),它同时请求 3 个后端接口:
| 数据源 | 接口 | 角色 | 失败策略 |
|---|---|---|---|
me | /backend-api/me | 计划类型核心来源(必选) | 重试 2 次,计入错误 |
wham_usage | /backend-api/wham/usage | 配额 + 计划核心来源(必选) | 重试 2 次,计入错误 |
codex_usage | /backend-api/codex/usage | 兜底补充(可选) | 401/403/404 时静默降级 |
端点定义见 overview.py#L26-L32。三个请求通过ThreadPoolExecutor并发执行,主入口见 overview.py#L788-L843。
两个关键的容错设计:
- 代理回退直连:请求优先走当前代理,代理异常时自动回退直连重试一次(
_request_json_with_proxy_fallback); - 可重试错误识别:只对 408、429、5xx 和超时类错误重试,401/403/404 不重试,避免无效等待。
三、多源解析:如何判断是 Plus / Team / Basic?
计划类型识别是订阅检测的重头戏。_detect_plan()采用六级优先链,逐级降级,确保任何一级拿到信号就能定论(源码见 overview.py#L727-L785):
- me 接口的 plan 字段:扫描
plan_type、subscription_plan、tier等 10 余个候选字段,并归一化——enterprise/team → Team、plus → Plus、pro → Pro、free/basic → Basic; - org / workspace 信息:
me.orgs里的workspace_plan_type为 team/enterprise 时直接判为 Team; - 订阅布尔信号:
has_paid_subscription、is_subscribed等为true时按 Plus 处理; - wham/usage 与 codex/usage 的 plan_type:这是与官方工具同款的核心信号;
- JWT 声明兜底:解码
id_token/access_token的 payload,读取chatgpt_plan_type声明,不依赖任何网络刷新; - 数据库已有订阅字段,仍无信号则默认为 Basic。
每一级检测都会记录plan_source(如me.plan、id_token.chatgpt_plan_type),让你可以追溯结论来自哪个来源,排查误判时一目了然。
四、Rate Limit 窗口识别:区分 5 小时配额与周配额
这是 codex-console 最有特色的部分。wham/usage返回的rate_limit包含primary_window和secondary_window两个窗口,但窗口位置并不总是一成不变——接口改版后,7 天窗口可能出现在 primary 位置。
基于窗口时长的置信推断
_infer_rate_limit_window_type()用两条阈值线判定窗口类型(overview.py#L437-L448):
- 窗口时长
limit_window_seconds≥5 天→ 判定为weekly(周窗口),高置信; - 窗口时长 ≤12 小时→ 判定为hourly(5 小时窗口),高置信;
- 无时长信息时,退化到 key 语义:
primary_window倾向 hourly,secondary_window倾向 weekly,但置信度标记为低。
三级选择策略
_select_rate_limit_window()(overview.py#L451-L478)按置信度三级筛选:
- 优先高置信匹配:基于窗口时长推断且类型命中,避免把 7 天窗口误判成 5 小时窗口;
- 普通语义匹配:无时长信息时按 key 语义兜底;
- 历史 key 兜底:单窗口账号场景下,按
primary=5h / secondary=周的历史约定取值,避免页面上出现--空值。
配额数值归一化
窗口内部的字段同样被做了防御式解析(_extract_quota_from_rate_limit_window):
used_percent在 0~1 与 0~100 之间自动换算;total / used / remaining三者互相推算,任一缺失可由另外两个补出;resets_at与resets_in_seconds互推,最终渲染成"1小时23分"这类人类可读的剩余时间;- 时间戳兼容秒 / 毫秒两种 epoch 格式。
最终每个账号输出hourly_quota(5 小时窗口)、weekly_quota(周窗口)、code_review_quota(Code Review 专属配额)三组数据,且每个窗口都标注了source溯源路径。
五、缓存与信任源:让检测又快又稳
服务层 accounts.py#L585-L679 的_get_account_overview_data()在抓取之外还做了几件重要的事:
- 缓存优先:结果缓存在账号
extra_data.codex_overview中,TTL 内直接读缓存,首屏卡片列表默认不发网络请求,避免被远端接口阻塞; - 过期缓存标记 stale:刷新失败时返回旧数据并打上
stale标记,而不是显示空白; - 信任源同步:只有来自
me.、wham_usage.、codex_usage.、id_token.等高置信来源的计划类型,才会回写数据库subscription_type字段; - 防降级保护:本地已确认的 Plus / Team 账号,不会被远端偶发的 free/basic 响应覆盖降级,只记录日志跳过;
- 停用识别:请求过程中抛出
AccountDeactivatedError时,账号直接标记为 BANNED 并记录停用时间。
六、批量刷新体验
Web UI 的批量刷新走 accounts.py#L1235 的/api/accounts/overview/refresh接口:
- 默认只刷新"卡片可见的付费账号"(plus / team),无关账号不会拖慢整体进度;
- 支持按状态、邮箱服务、关键词筛选刷新范围;
- 每个账号优先使用其绑定的代理(
account.proxy_used),无绑定代理时才用全局代理; - 结果明细里带上
plan_type与各窗口percentage,日志中还记录每个配额的数据来源,方便逐账号核对。
七、核心文件速查
| 文件 | 职责 |
|---|---|
| src/core/openai/overview.py | 订阅状态与配额抓取解析核心:多端点并发、计划六级解析链、窗口识别 |
| src/web/routes/accounts.py | 缓存策略、信任源回写、批量刷新 API |
| static/js/accounts_overview.js | 总览卡片前端交互 |
| tests/ | 覆盖注册、上传、安全等链路的自动化测试 |
小结
codex-console 的订阅状态检测可以概括为一句话:"多点并发取数、按置信度定级、失败静默降级"。多源交叉验证消除了单点接口波动带来的误判,Rate Limit 窗口识别则让 5 小时 / 周配额在不同接口布局下都能被准确归类——这正是它在 v1.1 版本修复"无法检查订阅状态"问题后的核心能力。
【免费下载链接】codex-consolecodex-console 是一个集成化控制台项目,支持任务管理、批量处理、数据导出、自动上传、日志查看与打包支持。项目地址: https://gitcode.com/gh_mirrors/co/codex-console
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考