# sub2api-overdraft 5h / 7d 额度透支定制记录 本文件是维护者实现与升级记录。面向部署者的完整安装、验证、升级和故障排查说明见 [CODEX_OVERDRAFT_DEPLOYMENT_CN.md](CODEX_OVERDRAFT_DEPLOYMENT_CN.md)。 ## 基本信息 - 当前官方合并基线:Sub2API `v0.1.179`,`upstream/main` 提交 `2bc139ab5` - 参考实现: - 功能开关:`gateway.codex_quota_overdraft_enabled` - 代码默认值:关闭;`deploy/config.example.yaml` 部署示例默认开启 - OpenAI 账号固定指纹开关:`gateway.openai_account_unique_fingerprint_enabled` - 固定指纹开关默认开启;没有显式账号模式时按账号 ID 派生稳定设备指纹,账号 extra 中显式设置 `codex_fingerprint_mode: off` 可单独关闭 - 账号编辑页新增 `账号唯一设备(新增,推荐)` 选项,对应 `codex_fingerprint_mode: account_device`;它只固定该账号的设备指纹,不改变会话/线程收敛 - Fork 版本文件:`FORK_VERSION` - 更新源:`DeanZFC/sub2api-overdraft` 的 `codex-overdraft` 分支 ## Fork 更新检查 源码 Docker 构建会读取根目录的 `FORK_VERSION`,并以 `BuildType=source` 写入二进制。后台更新服务通过 GitHub Contents API 读取 Fork 分支上的同名文件,使用语义化版本比较判断是否有新版本。Redis 缓存同时记录仓库和构建类型,因此旧的官方更新缓存不会继续生效。 源码构建仅显示 `git pull` 更新提示,`PerformUpdate`、指定版本回退和在线回退列表均被禁用,防止官方二进制覆盖透支功能。维护者每次发布 Fork 更新都必须递增 `FORK_VERSION`;当前版本为 `0.1.179-overdraft.3`。 Sub2API `v0.1.179` 继续保留原生 remote compaction v2 在 `/responses` 路径。本定制同时检查旧 Compact 路径和原生 v2 请求信号,二者都不会开启额度透支调度或注入透支请求形态。 ## 后台测试连接与残留限流修复 管理页面的 OpenAI OAuth 常规文本“测试账号连接”与真实业务请求使用相同策略:用量达到 95% 后注入;100% 时成功直接确认 `passed`,明确额度 429 直接确认 `failed`。API Key、Shadow、图片和 Compact 测试不启用该行为。 探测得到 `passed`,或额度周期进入 `recovered` 后,会清除仍残留的账号级 `rate_limit_reset_at` 以及本功能或额度阈值产生的暂停。这里不再要求当前重置时间与探测开始时记录的 `observed_rate_limit_reset_at` 完全相同,因为并发 429 可能在探测期间更新该字段;`failed` 状态不会清理限流。发生清理时记录 `codex_quota_overdraft_stale_rate_limit_cleared`。 ## PostgreSQL 兼容性修复 探测计划使用原子 claim 写入 `accounts.extra`。`jsonb_build_object` 的键参数必须显式 转换为 `text`,否则 PostgreSQL 会报 `could not determine data type of parameter $1`,导致 所有探测在启动前失败。对应 SQL 使用: ```sql jsonb_build_object($1::text, $2::jsonb) ``` ## 启用方式 在实际使用的 `config.yaml` 中加入: ```yaml gateway: codex_quota_overdraft_enabled: true openai_account_unique_fingerprint_enabled: true ``` 修改配置后重启 sub2api。出现上游兼容问题时可改为 `false` 并重启,立即恢复官方调度和请求行为。 ## OpenAI 账号固定指纹 固定指纹行为覆盖 HTTP Responses、OpenAI 透传、Responses WebSocket 和账号测试/额度探测。 默认模式为 `device`:同一 OpenAI OAuth 账号的 `x-codex-installation-id` 在请求、重启和 重新构建后保持不变,不同账号按账号 ID 派生不同 UUID。已经配置 `device`、`session`、`full` 或 `off` 的账号保持原有显式配置优先级;全局开关关闭后,未显式配置模式的账号恢复原样。 老账号即使没有 `codex_fingerprint_seed` 也不需要立即执行迁移,运行时会使用账号 ID 派生稳定 种子;显式 `device/session/full` 模式仍要求账号已有有效种子。该功能只对 OpenAI OAuth/Codex 账号生效,不会改写 API Key 或其他平台账号。 ## 完整行为 开启后,对 OpenAI OAuth 普通账号和 Agent Identity 账号生效,Shadow 账号除外。支持路径: - `/v1/responses` - `/v1/chat/completions` 转换到 Responses 的请求 - `/v1/messages` 转换到 Responses 的请求 - Responses WebSocket v2 首轮和后续轮 - 管理页面 OpenAI OAuth 常规文本“测试账号连接” 用量达到 95% 后,每次最终发往上游前,如果 `input` 最后一项是用户消息,则追加一对与参考项目相同的无操作 `custom_tool_call` 和 `custom_tool_call_output`。请求体超过 32 MiB、JSON 无效、形状不匹配或已经注入时保持原样。 5h 或 7d 额度达到 100%,或者收到包含明确额度证据的真实 429 时,执行以下混合判定: 1. 实际注入的业务请求成功时直接判定 `passed`,账号继续调度并开始透支统计,不额外消耗探测请求。 2. 实际注入的业务请求返回明确额度 429 时直接判定 `failed`,账号暂停到对应额度恢复时间并切号;5h 和 7d 同时耗尽时取最晚恢复时间。 3. 如果没有可用的业务成功证据,同一额度周期仅启动 1 次独立 Responses 探测,最长 20 秒并优先使用当前业务模型。多实例使用 PostgreSQL 原子 claim 去重。 4. 独立探测成功即判定 `passed`,明确 `quota_limited` 即判定 `failed`;网络错误、超时、5xx、普通瞬时 429(包括 `error.type=rate_limit_error`)和无效响应判定 `inconclusive`,同周期不自动重试。 5. `failed` 状态、临时暂停和调度 outbox 在同一数据库事务中提交。同周期 `failed` 为终态,晚到的业务成功或探测结果不能覆盖;业务明确额度 429 可以把并发产生的 `passed` 或 `inconclusive` 收敛为 `failed`。 6. 401/403、账号停用等认证问题交给原有认证异常逻辑处理;400/404 判定为 `inconclusive`,不会暂停整个账号。 7. 账号禁用、过载、代理/传输故障、模型级冷却及其他临时不可调度原因不被绕过。 8. 额度恢复后状态改为 `recovered`,清理本功能或额度阈值产生的暂停;5h 与 7d 分别维护透支起点,不会因另一窗口后来耗尽而重置已有统计。 状态值包括 `pending`、`passed`、`failed`、`inconclusive`、`recovered`。账号用量页面显示探测状态、尝试次数、额度周期、透支期成功请求数、Token、账号金额及预计恢复时间。 不需要新增数据库表或执行数据库结构迁移(schema migration);周期状态保存在现有 `accounts.extra` JSONB 字段,透支统计读取现有 `usage_logs`。 `/responses/compact`、生图请求、Embedding、Count Tokens、Live 等端点不启用额度透支。 ## 低冲突集成结构 从 `0.1.177-overdraft.6` 起,透支行为保持不变,但实现按“独立模块 + 固定钩子”组织,以减少同步官方更新时的冲突: - 四个 PostgreSQL 原子状态方法及临时暂停查询扩展位于 `backend/internal/repository/account_repo_codex_overdraft.go`,`account_repo.go` 不再承载大段透支 SQL。 - Gateway 通过 `sync.Once` 懒加载并持有全进程唯一协调器;账号用量服务和账号测试服务从同一个 Gateway 获取实例,不再向 Wire 图添加 Fork 专用 Provider。 - `backend/cmd/server/wire_gen.go` 由官方 Wire 图正常生成,不包含透支专用变量或参数。 - 调度、429、业务成功、用量快照和账号测试接线统一放在 `openai_codex_quota_overdraft_hooks.go`、`openai_codex_quota_overdraft_integration.go` 和 `account_test_codex_overdraft.go`;官方热点文件仅保留短调用。 - 前端状态徽标和透支统计分别位于 `CodexOverdraftStatus.vue`、`CodexOverdraftStats.vue`,官方账号用量组件仅负责传入原有数据。 这次调整没有修改 95% 注入门槛、Payload 内容、额度信号解析、429 分类、探测次数、状态转换、事务边界、暂停/恢复规则、统计口径或页面文案。升级时应优先保留独立文件,再逐一核对官方文件中的短钩子。 ## 修改文件 后端配置、路由和调度: - `backend/internal/config/config.go` - `backend/internal/handler/openai_chat_completions.go` - `backend/internal/handler/openai_gateway_handler.go` - `backend/internal/repository/account_repo.go` - `backend/internal/repository/account_repo_codex_overdraft.go` - `backend/internal/repository/account_repo_schedulable_projection_test.go` - `backend/internal/service/account_test_codex_overdraft.go` - `backend/internal/service/openai_account_runtime_block_fastpath.go` - `backend/internal/service/openai_account_scheduler.go` - `backend/internal/service/openai_codex_quota_overdraft.go` - `backend/internal/service/openai_codex_quota_overdraft_hooks.go` - `backend/internal/service/openai_codex_quota_overdraft_integration.go` - `backend/internal/service/openai_codex_quota_overdraft_probe.go` - `backend/internal/service/openai_codex_quota_overdraft_test.go` - `backend/internal/service/openai_codex_quota_overdraft_probe_test.go` - `backend/internal/service/openai_gateway_forward.go` - `backend/internal/service/openai_gateway_passthrough.go` - `backend/internal/service/openai_gateway_scheduling.go` - `backend/internal/service/openai_gateway_service.go` - `backend/internal/service/openai_gateway_usage.go` - `backend/internal/service/openai_ws_forwarder_ingress.go` - `backend/internal/service/openai_ws_forwarder_support.go` - `backend/internal/service/openai_ws_forwarder_v2.go` - `backend/internal/service/openai_ws_v2_passthrough_adapter.go` - `backend/internal/service/ratelimit_service.go` - `backend/internal/service/account_usage_service.go` - `backend/internal/service/account_test_service.go` - `backend/internal/service/account_test_service_openai_test.go` - `backend/internal/service/account_test_service_openai_compact_test.go` - `backend/internal/service/wire.go` 前端、配置示例和测试: - `frontend/src/types/index.ts` - `frontend/src/components/account/CodexOverdraftStats.vue` - `frontend/src/components/account/CodexOverdraftStatus.vue` - `frontend/src/components/account/UsageProgressBar.vue` - `frontend/src/components/account/AccountUsageCell.vue` - `frontend/src/components/account/__tests__/UsageProgressBar.spec.ts` - `frontend/src/components/account/__tests__/AccountUsageCell.spec.ts` - `frontend/src/i18n/locales/zh/dashboard.ts` - `frontend/src/i18n/locales/en/dashboard.ts` - `deploy/config.example.yaml` ## 官方更新后的重新实施 普通 `git pull` 不会静默丢弃未提交修改:能自动合并时会保留,冲突时会停止。安装脚本若强制重置、删除目录后重拉或重新解压,则可能覆盖本定制。 1. 更新前保存补丁:`git diff > codex-quota-overdraft.patch` 2. 拉取官方代码并处理冲突。 3. 尝试恢复补丁:`git apply --3way codex-quota-overdraft.patch` 4. 无法自动应用时,按本文件“完整行为”和“修改文件”逐项重新接入。 5. 在 `backend` 执行 `go generate ./cmd/server`,重新生成 Wire。 6. 确认实际 `config.yaml` 仍有 `gateway.codex_quota_overdraft_enabled: true`。 7. 运行验证: ```bash cd backend gofmt -w internal/service/openai_codex_quota_overdraft*.go go test -tags=unit ./internal/repository ./internal/handler ./internal/service \ -run 'CodexQuotaOverdraft|AccountTestService_OpenAI|AccountSchedulingThreshold|SchedulerSnapshot|SchedulableAccountQueryScopesCodex' -count=1 go test ./internal/repository ./internal/handler ./internal/service ./cmd/server -run '^$' -count=1 cd ../frontend pnpm install --frozen-lockfile pnpm run typecheck pnpm exec vitest run \ src/components/account/__tests__/UsageProgressBar.spec.ts \ src/components/account/__tests__/AccountUsageCell.spec.ts cd .. git diff --check ``` 人工核对所有 Responses 出站路径仍在最终发送前注入,并检查日志关键字: ```text codex_quota_overdraft_probe_passed codex_quota_overdraft_probe_failed codex_quota_overdraft_probe_inconclusive codex_quota_overdraft_probe_attempt codex_quota_overdraft_business_passed codex_quota_overdraft_business_exhausted codex_quota_overdraft_pause_applied codex_quota_overdraft_stale_rate_limit_cleared ``` 数据库状态可这样检查: ```sql SELECT id, name, extra->'codex_quota_overdraft_probe' FROM accounts WHERE platform = 'openai' AND type = 'oauth'; ```