# CLIProxyAPI 与 Codex 用量同步 ## 外部依赖与凭据边界 Codex Helper 不再启动 `codex app-server`,也不保存 Codex OAuth token。所有 Codex 登录、凭据持久化和刷新均由外部 CLIProxyAPI(CPA)负责;本项目只通过环境变量读取: - `CLIPROXY_API_BASE_URL`:CPA Management API 根地址。 - `CLIPROXY_API_MANAGEMENT_KEY`:CPA management key,只进入服务端请求头,不写入 SQLite、日志或前端响应。 每条 `accounts` 记录保存一个唯一的非空 `auth_index`。添加或修改绑定时,后端先调用 CPA `GET /v0/management/auth-files?auth_index=...`,确认索引唯一匹配、provider/type 为 `codex`,且凭据未 disabled。CPA 的临时 `unavailable`/error 状态可能正是额度耗尽导致,不能据此拒绝读取,否则仪表盘无法显示 100% 用量和重置时间。账号邮箱、套餐和 ChatGPT account ID 来自该认证条目的安全元数据与 ID token claims;原始 token 不会进入 Codex Helper。 旧数据库迁移会为已有账号增加空 `auth_index`。这些账号会保持未连接,直到管理员在设置页绑定 CPA authIndex。新数据库不再自动创建无凭据的默认账号。 ## Management API 代请求 后端通过 CPA `POST /v0/management/api-call` 发起上游请求,请求体使用 `auth_index` 选择凭据,并在 Authorization 中传递 `Bearer $TOKEN$` 占位符,由 CPA 注入和刷新真实 access token。关键上游请求是: - `GET https://chatgpt.com/backend-api/wham/usage`:套餐、普通限额、代码审查限额、`additional_rate_limits` 和可用重置卡摘要。 - `GET https://chatgpt.com/backend-api/wham/profiles/me`:Token 活动摘要与每日 bucket。 - `GET https://chatgpt.com/backend-api/wham/rate-limit-reset-credits`:可选的重置卡详情及到期时间。 CPA HTTP 层和包装的上游状态分别校验。错误只包含安全的阶段、HTTP 状态和上游错误类型,不包含 management key、OAuth token、原始响应正文或 CPA 凭据内容。请求均有超时和响应体大小限制。 这些 `/wham/*` 路径属于 ChatGPT/Codex 内部接口,并非稳定公开 API;CLIProxyAPI 版本、当前解析代码和测试是本项目的实际兼容基线。 ## 限额归一化 一次成功同步会把 `/wham/usage` 转换为现有 `Dashboard.Limits`: - 顶层 `rate_limit` 使用稳定 `limitId=codex`。 - `code_review_rate_limit` 使用稳定 `limitId=code_review`。 - `additional_rate_limits[]` 优先使用 `metered_feature` 作为 limit ID,`limit_name` 作为显示名称;例如 Spark 的 `codex_bengalfox`。 - `primary_window` 和 `secondary_window` 分别保留为 `windowType=primary|secondary`,前端依据窗口时长识别小时和周额度,不假定字段顺序。 - `limit_window_seconds` 向上取整转换为分钟。 - `used_percent` 限制在 0–100,但保留小数。 - 重置时间优先使用 Unix 秒 `reset_at`;缺失时以本次响应时间加 `reset_after_seconds` 推算。 - `plan_type` 未知时按原值保留,并由现有套餐分类逻辑安全显示为 unknown。 可用重置卡数量优先以详情接口的 `available_count` 为准,详情接口失败时可退回 `/wham/usage` 的 `rate_limit_reset_credits.available_count`。只有状态为 available 且能解析 RFC3339 `expires_at` 的记录才进入到期时间列表;详情失败不影响主同步。 ## Token 活动与当前周期 `/wham/profiles/me` 的 `stats` 提供 lifetime、单日峰值、最长任务、连续天数以及 `daily_usage_buckets`。每日 bucket 继续写入按 `account_id` 隔离的 `daily_usage`;optional、`null`、未来新增字段和暂缺 bucket 必须安全降级,不能合成调用次数、输入/输出 Token、价格或账单日期。 同步成功后,以当前仍有效的最长限额窗口作为当前重置周期,按每日 bucket 汇总周期起点至当前日期的 Token,写入 `Dashboard.currentCycle`。周期边界只有日期粒度,因此边界日按整日汇总。额度和 Profile Token 活动来自不同上游聚合链路,数据新鲜度可能不同。 ## 调度、并发与失败 应用启动后异步同步全部已绑定账号,之后固定每五分钟同步;手动同步和 Telegram 立即刷新使用同一链路。每个账号的 `syncing` mutex 串行同步并保护内存 Dashboard,不同账号仍保持数据库、历史和提醒隔离。 `auth_index` 缺失、CPA 未配置、认证条目不可用或核心 `/wham/usage` 失败会使本次同步失败:已有 Dashboard 保留并标记 `stale=true`,内部错误仅对已登录管理员可见。`/wham/profiles/me` 的 Token 活动和重置卡详情都是可选数据;Profile 失败时同一进程内保留上次成功的摘要和每日历史,没有旧值时降级为空,重置卡详情失败时退回用量接口的可用数量。两者都不会隐藏已成功读取的额度窗口。成功同步会清除 stale/error、写入限额快照、检测百分比回落并更新账号元数据。 删除账号只删除 Codex Helper 中的绑定、数据库历史和内存 Dashboard,不调用 CPA 删除认证文件。CPA OAuth 凭据的删除和恢复必须在 CLIProxyAPI 中单独执行。