Repository navigation
feat(accounts): separate steward API primary from worker fallback - #8035
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
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 (Codex); OpenAI; self_reported
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
同时运行工作 Agent、Codex App 和管家,并复用本机 API Key 池的操作者。 工作账号 A 仍有订阅额度时,旧管家无法独立用 API;现在管家用专属 loopback 凭据,工作账号仍为 A,worker selector 不变。 设置页可独立选择管家 primary/fallback/disabled 并读回;工作 Agent 与 App 保持订阅优先;变更仅在原队列的未开始边界采用。 不创建新 Key 池、购买额度、改变模型候选、扩大工具权限、重放未知效果或代办业务。 本 PR 交付独立账号优先级及设置、CLI/HTTP、原生模型传输;合并后还需安装和运行服务读回,不据测试或合并宣称历史业务消息已全部回传。
改动思路 / Approach
沿原生账号 owner 区分调用方的 API role,复用原 Key 池、额度选择器与队列准入;凭据准备和空闲身份观察留在 native_chat 模块,不复制凭据库或重建消费队列。 primary/fallback/disabled 表达的是调用方的付费顺序,模型候选与权限仍由原 owner 决定。原生 decide() 不读取管家角色,故不会把 API primary 传播给工作 Agent。管家用原 Key 池上的独立随机本地凭据与 HTTP 路径;没有第二个账号库、消息消费者或自动重放流程。本 PR 交付独立账号优先级及设置、CLI/HTTP、原生模型传输;合并后还需安装和运行服务读回,不据测试或合并宣称历史业务消息已全部回传。
具体改动 / Changes
规格基准:spec_ref = packages/loopx-codex-provider-routing/NATIVE.md,spec_revision = 2dd1d8c201b81142469f700299915907ec0e5a32。逐条核对 single-credential-owner(原凭据 owner)、worker-subscription-first(原订阅耗尽证明)、consumer-api-role(显式调用方角色)、no-effect-replay(原队列准入和输出边界)。新文档明确替代原来未区分调用方的笼统 API 优先级描述;worker 合同继续保留。
关键代码讲解
apiRole/modelRoute/stewardRoute复用同一 TypeScript 决策 owner:worker 只能禁用或兜底;管家显式 primary 可先尝试同一池,已知模型级拒绝仍按实际模型过滤,异常角色拒绝。NativeAccounts.model_transport()先检查原 profile 与关闭状态,再准备原 relay。默认关闭不启动 Node/原生账号进程。主力 API 不需要先启用订阅自动切换;相反,worker 的 API 仍需原耗尽路由。idle epoch 只更新原未开始消息的适配器,不授予业务继续许可。CodexApiTransport使用进程内本地 token 和每会话 provider,排除 shell 环境,保留独立项目认证及显式 provider,拒绝保留 alias 冲突。原thread/resume与 provider 读回继续验证,未复制 auth/config/history。RelayHandler._admitted()区分两个随机凭据和路径,dispatch 前重读策略。worker token 不可用于管家路径;撤销即时阻断后续请求,已开始的流不重放。真实 Key 仍在原OpenAIKeys。
设置页与 JSON CLI/HTTP 都调用同一 CAS owner。API 主力的用量计费后果直接显示;Key 为空仍能选择关闭。两张图片是当前 NATIVE 操作指南的规范示例,非归档截图包。像素已检查为合成数据,PNG 无文本/EXIF 元数据。
体积检查曾发现两个大 Chat 模块增长,已把认证准备、隔离认证和空闲观察放回原 native_chat owner:最终 2031/2397 行,无新增大模块债务。另四处 Any 计数债务在完整、带独立 Git index 的 immutable base 上同样复现,来自已合入 4e89bcbefdb22d9504e6d8b3dd8d835c64c6a8c7 的 cast 注解;本 diff 只把四个计数更新到精确实测 22/107/50/12,对应源码 blob 未变,没有额外余量或新例外。
对主干的风险 / Risks
最强反例是管家选择无意改变 worker 登录、共享凭据跨角色调用,或关闭时仍启动策略进程。使用真实合成私有 owner、真实 loopback HTTP 与原 API owner 验证了这些负例,默认关闭测试明确禁止任一策略/原生进程。已知 quota/auth/permission/rate-limit 拒绝只在输出前换 Key;未知网络效果与已开始流保持原不重试边界。每次请求仍检查角色,错误 profile、保留 alias、独立项目认证和显式 provider 不被覆盖。没有以模型列表读取成功冒充可消费额度。
验证:最终 head 647 项受影响测试通过、13 项 native-policy 通过;同一 16 组 worker 输入在 immutable base 与当前函数的完整输出一致。真实 Codex 进程使用 gpt-6.1-sol 到达本地合成 HTTP endpoint,未写 auth 文件、未接触全局 home、零上游模型调用。较广集成曾有 1115 项通过,认证 owner 提取后由最终受影响 suite 重新覆盖。预合并直接、catalog、risk 和文本边界检查均通过;两个二进制 image hold 已按像素、元数据和实际指南消费者完成独立人工检查,不称为自动隐私扫描。
语义与 CI 对齐
ApiRole 是可选账号提供方的局部 vocabulary,既有 Core 队列、工具权限、Goal/quota 语义不变。新角色和 capability projection 是有意的可选字段,缺失保留原兜底;无新必填输入或 Agent 指令。diff semantic advisory 没有支持范围内的新 Core carrier,未把该空报告当作全量语义证明。按配置 wait_for_ci=false,未查询、轮询或等待 CI。
我的整体评价 / Verdict
没有剩余阻塞发现,当前 exact head 可以合并。long_horizon 改善在于不同调用方不再争用同一付费选择,原消息和原准入继续保留。user_experience 改善在于现有页面一次选择和读回,零新增必需交互;1440×1000/390×844 首屏能看见两种付费边界,长名称换行、混合未知/已检查状态可读,帮助在原位展开,失败恢复与空 Key 撤销均验证,无横向溢出且键盘可达。原生 WebView 样式、真实上游推理额度及所有历史业务回传未由合成测试证明;部署和真实回传继续按原 owner 验收。范围和机制成本相称,未新增凭据库、队列或治理词汇。
1440×1000 和 390×844 首屏同时给出工作订阅边界与管家独立选择;长名称换行,帮助按需展开,失败显式可恢复;无横向溢出,键盘焦点可达。 原生 WebView 样式与真实上游推理额度未由该合成场景验收。
English verdict: APPROVE c17ab37; consumer-scoped API primary is isolated from worker subscription-first fallback, original admission/replay guards remain, and affected local/product/native boundaries pass.
The steward currently follows the native worker login, so preferring API would also move working Agents away from available subscriptions. This change gives API an explicit consumer role: workers retain subscription-first fallback; the steward can independently use API as primary, follow subscription fallback, or disable API.
The existing account owner and key pool remain authoritative. A separate random loopback credential and per-thread model configuration let the steward use the pool without rewriting desktop credentials or copying auth/history into project stores. API rejection can rotate keys only before output; unknown effects and started streams never replay. Explicit provider choices and separate native profiles remain fenced.
Validation at
c17ab3782df9a41fd8241e7babf0b11bc41540f4: 647 affected tests; 13 native policy cases; 16 identical worker base/head comparisons; real Codex process using a synthetic local HTTP endpoint withgpt-6.1-sol, no upstream inference or auth file; packaged settings against the real disposable account HTTP/store. Source failure/recovery, long names, mixed key observations, empty inventory revocation and keyboard focus were exercised. The wider integration run passed 1115 tests before the bounded auth-owner extraction; the final affected suite requalified that extraction. Connection/model-list evidence does not establish inference allowance. CI is not consulted under the configured workflow.The premerge check also exposed four pre-existing Any-count ceilings left behind by the already merged type-only repair
4e89bcbefdb22d9504e6d8b3dd8d835c64c6a8c7. This diff synchronizes only those four exact measured counts (15→22, 85→107, 49→50, 11→12). Their source blobs are unchanged; no future slack or exception is added. The two large Chat modules do not grow.Visual evidence: production built UI and public synthetic workspace/account data, desktop 1440×1000 and narrow 390×844. Working-Agent cost policy and the independent steward choice remain visible in the first viewport. Long names wrap, help stays on demand, source failures remain explicit and no horizontal overflow was observed. Native WebView styling is unverified. The two canonical images are consumed by the current activation guide in NATIVE.md; they are not an archived capture pack.