Repository navigation
fix(accounts): try alternatives after rejected API keys cool down - #8147
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
未发现阻塞性问题。使用已启用 API 账号池的 Chat 或管家,在暂时额度拒绝后继续原来已授权的工作。 首个 Key 被流式额度错误拒绝,下一次独立请求在五分钟冷却之后到来;旧版又选中首个 Key,新版先尝试其他未被拒绝的候选。 离线真实 HTTP 中转证明后续独立请求能够改用第二个 Key,原失败流保持原样且只派发一次。 本 PR 不改变模型候选、工作 Agent 的订阅优先策略、管家 API 角色、原 Turn 的重放资格或实际账户付费权限。 远端账户当前可用额度、安装后的实际调用与原 Bot 补回复仍需独立验收,测试成功不代表这些工作已经完成。
改动思路 / Approach
候选顺序仍由已有 TypeScript policy 决定,Python 仅传递已有观察并按返回顺序取私有 Key;无需增加轮换游标或第二份状态。 本次只交付未来独立请求的 Key 选择与 0.15.3 provider 包;已开始流的错误观察和原服务的执行恢复仍各归原 owner。 原有冷却先过滤,新顺序只影响后续独立请求;没有延长冷却、清除失败或添加新的轮换状态。只把冷却改长会继续在更晚的请求重现同一问题,而在当前流内重试会违背已有安全边界,因此没有采用这两条替代方案。
| 场景 | base | 本 head |
|---|---|---|
| 首 Key 拒绝,冷却未结束 | 跳过首 Key | 保持 |
| 首 Key 拒绝,冷却结束且有其他候选 | 又回首 Key | 先试其他候选 |
| 只剩过期首 Key | 可重新尝试 | 保持 |
| 当前流已开始后失败 | 不重放 | 保持 |
具体改动 / Changes
基准契约是 packages/loopx-codex-provider-routing/NATIVE.md,spec_revision 817dd2461a93b376e3420363a36f77e89287fcf8,先于本次文档修改读取。API-cooldown 对应有效冷却、模型权限和未来候选;API-no-replay 对应已开始流与未知网络不重放;API-consumer-role 对应工作 Agent 订阅优先、管家独立角色,三项均由现有入口及本次正负例验证。新增排序是有意修复,未用新文档倒推旧版已承诺此顺序。
关键代码讲解
apiKeys使用现有四类结构化拒绝和有限观察时间派生优先级。有效冷却先排除;无拒绝的候选先行,过期拒绝按最早时间重新考虑。相同时间稳定保留配置顺序,其他模型的 permission 不受降序影响;纯函数不写磁盘,也不把过期当余额恢复。OpenAIKeys.candidates传递无内容的 state、observed_at 与原冷却/模型字段。原按 membership 过滤会把 TypeScript 排序抹掉,本次按 IDs 映射返回真实凭据行;Key 值没有流入策略进程。该消费者修复由真实 HTTP 用例检验,不能只靠排序 helper 单测。RelayHandler._model_request是未改动但实际受影响的生产调用方:角色准入、dispatch 前再检查删除/禁用,以及开始流后不换 Key 的分支保留。两个新用例将时钟推进超过冷却,旧版均在下一次 Authorization 相同处失败;新版还验证成功候选持续使用,以及删除该候选后旧 Key 仍可恢复。
8 文件 +71/-7 中,生产行为集中在以上两个选择函数;其余为回归、操作文档和三个一致的 0.15.3 版本声明。wheel 内 Python、TypeScript 和 native manifest 已与本精确提交逐字节核对。
对主干的风险 / Risks
主要风险是改变曾失败 Key 的恢复优先级,故测试明确保留单候选重新尝试、所有失败按最早观察排序及模型范围边界。没有新 actor、付费权、重放权或 native login 切换;未知效果不会因为这个排序变成已知未执行。API disabled、Origin/token 拒绝、活动订阅、未知网络和流中断的原 HTTP 控制在 base/head 均覆盖。自动生成流仍不能证明远端账户有余额,也不能证明欠答已回原会话。
语义与 CI 对齐
复用既有 runtime 词汇与唯一 policy owner;没有改 Core quota、Goal 或委派义务。旧版同一 harness 的 17 个原控制通过,两个新增间隔回归预期失败;head 的 HTTP/store/owner 共 19 项通过,策略 4 项及 consumer/native 17 项通过。standard premerge 的 diff、Python 编译及 RFC 配对通过,catalog 选择数为零,不能称全仓测试。按本 Goal 的 wait_for_ci=false,未获取、轮询或等待 CI。没有放宽预算或移除失败断言。
我的整体评价 / Verdict
这是有实际调用方和反例证据的 justified_increment:long_horizon 改善跨冷却间隔的持续选择,user_experience 通过原请求路径受益,新增人工轮次为零。兼容性保留旧无观察行,配置/凭据 store 不迁移;最小修复落在既有 owner,无需新增游标。检查了 API transport、调用方路由及 NATIVE.md,本 PR 没有改变任何渲染页面。 未验证范围是:无渲染改动;真实模型可用额度及原消息补回复不在离线测试覆盖内。远端账户当前可用额度、安装后的实际调用与原 Bot 补回复仍需独立验收,测试成功不代表这些工作已经完成。 APPROVE 仅是本精确 head 的审查结论,合并资格和安装采用分别核验。
English verdict: APPROVE — head 37f5062df26b7e055a6eb18efcf584cb92a0ed91 fixes spaced-request API-key starvation; real loopback regressions and retained safety/consumer controls pass. Production capacity and message recovery remain unverified.
API Key 的已知额度拒绝在冷却过期后重新回到配置首位,导致间隔较长的独立请求反复命中同一个耗尽 Key,其他候选始终得不到尝试。
本改动复用现有运行观察:候选先过滤有效冷却,再优先尝试没有已知拒绝的 Key;被拒绝的候选按最早观察时间重试,同时间保留配置顺序。Python 传递必要的无内容观察并遵循 TypeScript owner 返回的完整顺序。没有增加状态库、后台探测或已开始流的重放,工作 Agent 的订阅优先和管家独立 API 角色保持原约束。Provider 升为 0.15.3,三个版本声明一致。
验证: