fix(proxy): treat self-contained client replays as resume-not-applicable#585
Merged
Merged
Conversation
…ble, not missing_tool_calls When Codex CLI sends a self-contained full-history replay — e.g. after /compact or error recovery — the input contains both the historical function_call entries AND their paired function_call_output entries. The proxy was treating this as an implicit-resume candidate because session-affinity still had a recent response_id for the conversation, then bouncing it as missing_tool_calls because the function_call_output call_ids weren't in stored functionCallIds (they live in the input itself, not in any prior upstream response we tracked). The payload guard then 413'd subsequent retries, freezing the conversation. evaluateImplicitResume now accepts an inlineFunctionCallIds argument populated by buildProxySessionContext via getInlineFunctionCallIds. When every function_call_output call_id is satisfied by an inline function_call in the same request, the evaluator returns reason="self_contained_replay" (active=false) and the request flows through to upstream normally. Genuine missing-tool-call cases — where neither inline nor stored ids cover the outputs — still resolve to missing_tool_calls so the payload guard can still catch runaway loops. Adds 4 unit tests covering pure-inline replay, mixed inline+truly-missing, self-contained precedence over missing, plus helper-level tests for getInlineFunctionCallIds and isSelfContainedReplay. Updates the existing buildProxySessionContext expectation to include the new inlineFunctionCallIds field.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
修根因。配合上一个 PR #584 的 guard 阈值放宽,这个 PR 让 proxy 一开始就不会把 client 自包含 full replay 误判成
missing_tool_calls。背景
Codex CLI 在
/compact或 error recovery 时会发自包含 full replay:input 里同时有历史function_call和它们配对的function_call_output。proxy 之前的逻辑:reason: "missing_tool_calls"→ payload guard 413 → 客户端连续重试都被拦,对话冻死guard 阈值放宽(#584)已经把"卡死"问题降级到"偶发烧 token"。本 PR 修上游:让 evaluator 一开始就识别出这是合法的 client replay。
Fix
evaluateImplicitResume新增inlineFunctionCallIds入参,由buildProxySessionContext通过新增的 helpergetInlineFunctionCallIds(codexRequest.input)在调用前收集 input 里所有function_call项的 call_id。新增判定(在 missing_tool_calls 检查之前):
self_contained_replay不在 payload guard 拦截的 reason 列表里,请求正常透传给上游。混合场景(部分 inline、部分既不 inline 也不 stored)仍然判missing_tool_calls,留 guard 挡真 runaway。Changes
src/routes/shared/proxy-session-helpers.ts— 新增getInlineFunctionCallIds/isSelfContainedReplay辅助;ImplicitResumeOpts加inlineFunctionCallIds?字段;evaluateImplicitResume加 self-contained-replay 前置检查。src/routes/shared/proxy-session-context.ts—buildProxySessionContext在 implicit-prev 路径上收集 inlineFunctionCallIds,并把它塞进resumeEvaluationInput。tests/unit/routes/shared/proxy-handler-implicit-resume.test.ts— 新增 7 个测试覆盖 self-contained replay / 混合 / inline 优先 / helper 行为。tests/unit/routes/shared/proxy-session-context.test.ts— 现有resumeEvaluationInput期望值加inlineFunctionCallIds。Test Plan
npx vitest run tests/unit/routes/shared/proxy-handler-implicit-resume.test.ts— 18 passnpx vitest run— 2273 pass / 1 skipped / 0 fail (230 files)npx tsc --noEmit— cleanself_contained_replay分支正常透传(具体效果等真请求触发后查 log 验证)Notes
与 #584 是父子关系:#584 是 hotfix(拉宽阈值),本 PR 是根因修复。两个都合上后:guard 仍在,但只对真正的 runaway loop 触发;正常 client 重放走透传不被打扰。