ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

opencodex PR 46 深度解析:native passthrough SSE 的 usage 终结记录修复与脏树安全 Cherry-Pick 实践

opencodex PR 46 深度解析:native passthrough SSE 的 usage 终结记录修复与脏树安全 Cherry-Pick 实践 opencodex PR #46 深度解析native passthrough SSE 的 usage 终结记录修复与脏树安全 Cherry-Pick 实践【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodex导读本文围绕 opencodex 仓库 devlog 中记录的 PR #46 合并计划 展开剖析fix(logs): finalize native passthrough SSE usage这一修复如何让原生透传native passthroughSSE 响应在缺少 Codex pool terminal recorder 的情况下依然能正确终结/api/logs与/api/usage并完整还原一次脏工作树 并发编辑场景下的安全 cherry-pick 操作流程以及一次 stash 误操作事故的完整恢复过程。读完本文你将掌握 opencodex 中 terminal outcome 记录的门控逻辑、对应回归测试的验证方式以及一套可复用的 Git 事故恢复方法论。一、背景为什么 native passthrough SSE 需要单独的 usage 终结修复opencodex 作为 Universal provider proxy为 OpenAI Codex 与 Claude Code 提供统一代理在将上游 Responses API 的 SSE 流透传给客户端时需要把流的最终状态completed/failed/incomplete回写进请求日志与用量统计。在修复之前native passthrough 路径的终结记录存在一个缺口只有当terminalBodyWillRecord recordTerminalOutcomes同时成立时透传流的终态才会被记录。而terminalBodyWillRecord的定义见 passthrough-delivery.ts为const terminalRecorder recordTerminalOutcome ? (status: ResponsesTerminalStatus, httpStatusOverride?: number): void { if (terminalOutcomeRecorded) return; terminalOutcomeRecorded true; recordTerminalOutcome(status, httpStatusOverride); } : undefined; const terminalBodyWillRecord !!terminalRecorder upstreamResponse.ok isEventStream;它依赖terminalRecorder存在即 Codex forward pool 的终端 outcome 记录器被挂载。一旦请求没有经过 Codex pool 认证/记录链路例如直接使用自定义 provider、openai-responsesadapter 单测等场景terminalRecorder为空整条终结记录链路就被静默跳过——请求日志/api/logs缺少 terminalStatus、usageStatus/api/usage无法累加 token。这正是 devlog 中 issue_044_request-log-native-passthrough-gap 所追踪的缺口。从源码结构看该缺口与recordTerminalOutcomes的语义紧密相关它在 core-options.ts 中定义为可选开关默认在 response-effects.ts 中被解释为options.recordTerminalOutcomes ! false即默认开启而在 websocket-handler.ts 中则显式传入recordTerminalOutcomes: false——说明不同传输路径对终结记录的门控策略并不一致。二、PR #46 核心变更放宽门控 可选链PR #46单提交a0db10b作者0disoft rodisoft1gmail.com对服务端入口原计划中的src/server.ts当前仓库该文件已重构拆分至 src/server/ 目录做了最小改动2/-3门控条件放宽将 native-passthrough 终结记录的判定从terminalBodyWillRecord recordTerminalOutcomes收窄为仅依赖recordTerminalOutcomes。含义是只要请求上下文允许记录终端结果即使没有 Codex pool 提供的terminalRecorder也要让流正常终结/api/logs与 usage 统计。可选链调用对terminalRecorder?.(status)使用 optional chaining保证terminalRecorder为空时调用安全、不抛异常。这一变更在 passthrough-delivery.ts 的 eager relay 分支中落地为reportNativeTerminalconst reportNativeTerminal recordTerminalOutcomes ? (status: ResponsesTerminalStatus, httpStatusOverride?: number) { terminalRecorder?.(status, httpStatusOverride); if (status failed || status incomplete) { const quotaFailureMessage [httpStatusOverride, logCtx.terminalHttpStatus] .find(value value 429 || value 402); if (!isFixedCodexAccount(admissionState.authCtx) quotaFailureMessage ! undefined) { recordSubagentQuotaFailureForThreadSpawn(/* ... */); } } options.onNativePassthroughTerminal?.(status); } : undefined;可以看到terminalRecorder?.(...)的调用已被可选链保护即使记录器缺失onNativePassthroughTerminal等副作用仍可执行同时failed/incomplete状态下的 429/402 配额失败判定recordSubagentQuotaFailureForThreadSpawn也保留了下来。同样的terminalRecorder生命周期管理还出现在 core-combo.ts声明、core-combo.ts通过setTerminalOutcomeRecorder注入等路径中PR #46 正是把必须由 pool 提供 recorder这一隐含前提从 native passthrough 路径上移除。三、回归测试一个 18 tokens 的 SSE 用例验证两个 APIPR #46 同步新增了 81 行回归测试位于 tests/server/server-auth.test.ts用例名直接点明意图native passthrough SSE records completed usage without pool terminal tracking无 pool 终端跟踪时native passthrough SSE 仍记录完成态用量。测试的搭建与断言逻辑构造上游 SSE用Bun.serve起一个本地上游返回text/event-stream内容仅含一个response.completed事件event: response.completed data: {type:response.completed,response:{status:completed,model:gpt-5.5,usage:{input_tokens:11,output_tokens:7,input_tokens_details:{cached_tokens:3},output_tokens_details:{reasoning_tokens:2}}}}配置 opencodex以openai-responsesadapter、baseUrl指向该上游、allowPrivateNetwork: true、默认模型gpt-5.5启动服务并 POST/v1/responsesstream: true完成一次真实透传。断言/api/logs日志尾部记录应为status: 200、terminalStatus: completed、closeReason: terminal、usageStatus: reported、totalTokens: 18且 usage 细分被正确解析inputTokens: 11、outputTokens: 7、cachedInputTokens: 3、reasoningOutputTokens: 2。断言/api/usage/api/usage?rangeallsurfacecodex返回requests: 1、reportedRequests: 1、totalTokens: 18模型维度provider: test-openai、model: gpt-5.5累计一致同时surfaceclaude的请求数为 0确认统计归属 surface 隔离正确。这个用例的验证价值在于它完全绕开了 Codex pool 认证链路直接证明透传流的终态记录不依赖terminalRecorder——即 PR #46 修复的目标场景。四、脏树安全的 Cherry-Pick隔离并发工作再合并合并计划中最大的操作风险是目标分支feat/kiro-on-dev工作树并不干净——一个并发 agent 正在编辑src/adapters/base.ts4 行与src/adapters/kiro.ts8 行这些未提交修改绝对不能被破坏。而git cherry-pick在脏工作树下会直接拒绝执行。计划的解决策略三步法隔离git stash push -- src/adapters/base.ts src/adapters/kiro.ts只把并发 agent 的两个文件暂存起来push -- paths形式只影响指定路径这是与普通git stash的关键区别。合并在干净工作树上git cherry-pick a0db10b自动保留原作者0disoft的署名cherry-pick 天然保留 author无需额外配置。恢复git stash pop还原并发工作并确认 base.ts / kiro.ts 的编辑原样保留。操作前提是文件无重叠PR #46 只触及src/server.ts2/-3与tests/server-auth.test.ts81与并发 agent 的 base.ts / kiro.ts 编辑互不相交因此 stash 隔离 cherry-pick pop 可以安全执行。五、事故复盘一条错误 flag 引发的 stash 误弹与恢复计划执行中发生了一起值得记录的事故执行者使用了一个格式错误的 flaggit stash push -ufalse导致后续出现一次杂散的git stash pop误把一条无关的历史 stashgoogle-antigravity WIP应用进了工作树产生 7 个文件的 UUunmerged冲突。恢复过程分为两步回滚冲突文件对这 7 个 google-antigravity 文件执行git checkout HEAD --恢复。由于这些内容仍安全保存在对应的 stashstash{0}中回滚没有造成数据损失。清理泄漏的未跟踪文件误弹还带出了 2 个原本不应存在的未跟踪文件src/oauth/google-antigravity.ts、tests/google-antigravity.test.ts将其移除并备份至/tmp/pr46_leaked_files同时保留在 stash{0} 中作为兜底。最终确认并发 agent 的工作零丢失——base.ts / kiro.ts 的编辑经 stash pop 以 3-way 自动合并干净恢复无冲突。这条事故给 Git 操作带来的实践要点git stash push的-u/--include-untracked是布尔开关不要写成-ufalse这种带值的错误形式否则该 flag 可能被解析为其他含义导致 push 行为与预期不符在存在多个 stash 的环境中执行git stash pop前先git stash list确认目标误弹造成的冲突文件可通过git checkout HEAD -- files快速还原只要对应 stash 未删除数据就仍在恢复范围内对泄漏的未跟踪文件先备份再清理保留一条可回退路径。六、验证与验收结果合并完成后按计划执行了完整验证测试bun test tests/server/server-auth.test.ts tests/request-log.test.ts tests/passthrough-abort.test.ts→57 pass / 0 fail其中包含 PR #46 新增的 native-passthrough usage 用例类型检查bun x tsc --noEmit→exit 0合并提交与并发工作树叠加状态下均通过提交审计git show确认 cherry-pick 产物只包含 server.ts 与测试文件author 为0disoftgit status确认 pop 后 base.ts / kiro.ts 仍处于已修改状态并发工作完好。最终 cherry-pick 落为提交2481c80且与原计划中的并发编辑位置server.ts:112/591/909相比PR #46 的改动点位于 server.ts:529改动位置同样不相交进一步降低了冲突概率。修复合并后按计划在 issue #44 上同步了合并结果。七、总结一次修复 流程双重价值的技术合并从技术层面看PR #46 用两行门控调整解决了 native passthrough SSE 的用量统计缺口把是否有 pool recorder与是否记录终态解耦让透传流在任何认证形态下都能正确终结/api/logs与/api/usage并以一个 18 tokens 的端到端用例锁定行为后续还可在 server-auth.test.ts 中找到caller abort 不惩罚 poolL4215与upstream reset 记录 502 并惩罚 poolL4256等相邻回归用例共同构成 native passthrough 终结语义的完整防线。从工程流程层面看这份 devlog 同时示范了多 agent 并发开发下的安全合并范式路径级 stash 隔离 → cherry-pick → pop 还原以及一次 stash 误操作从冲突到零丢失恢复的完整闭环。对于任何维护多人/多 agent 共享工作树、且需要保留外部贡献者署名的开源项目这套操作流程都具备直接的可复制价值。延伸阅读感兴趣可继续查看 passthrough-delivery.tsnative passthrough 完整传输与终结逻辑、core-options.tsrecordTerminalOutcomes开关定义、response-effects.ts默认值解释以及 issue_044_request-log-native-passthrough-gap 中对该缺口的前置追踪。【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodex创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表