Skip to content

fix(responses): recover routed continuations after replay misses - #4086

Draft
Eleven-is-cool wants to merge 1 commit into
lidge-jun:devfrom
Eleven-is-cool:fix/routed-continuation-replay
Draft

fix(responses): recover routed continuations after replay misses#4086
Eleven-is-cool wants to merge 1 commit into
lidge-jun:devfrom
Eleven-is-cool:fix/routed-continuation-replay

Conversation

@Eleven-is-cool

@Eleven-is-cool Eleven-is-cool commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Recover routed Responses continuations when local replay state is missing or expired. Stateless destinations now return previous_response_not_found before dispatch, allowing a client to resend complete history instead of forwarding an orphaned tool result.
  • Request the same recovery when custom-tool lowering lacks the original call needed to determine a delta result's wire type. For example, a function call restored to a client custom call must not return upstream as an unmatched custom result. Full replay uses the existing paired conversion rather than guessing types or synthesizing calls.
  • Scope the check to the selected Responses adapter, explicit statelessResponses capability, and actual tool declarations. Preserve upstream-owned native function/native-only custom continuations, existing defaults, and the canonical forward recovery path. No model-specific special cases, new retention store, or request-body logging.
  • Cover missing/expired state over HTTP and WebSocket, full-history retry with reasoning intact, the next incremental turn, noncanonical forward routes, model adapter overrides, and native-tool preservation. All fixtures are synthetic. HTTP clients must explicitly resend full input; WebSocket coverage exercises the recovery protocol with a test client, not a live Desktop session.

Verification

Using Bun 1.4.2:

  • bun test tests/responses/custom-tool-compat.test.ts tests/responses/responses-custom-tool-repair.test.ts tests/codex-integration/issue-702-expired-replay-state.test.ts --timeout 30000: focused suites passed; subsequent HTTP/native/custom-forward/model-override additions also passed their focused runs and the full-suite run. The four initial routed recovery scenarios failed before the production change and passed afterward.
  • bun run typecheck: passed.
  • bun run privacy:scan and git diff --check: passed. Added lines were also checked for private paths, identifiers, endpoint details, and business content.
  • cd docs-site && bun install --frozen-lockfile && bun run build: passed, 425 pages built.
  • bun run test --timeout 30000: not fully green. The parallel lane reported 21,785 passed, 17 skipped, and 3 failed; all six serial lanes passed (180 additional tests). Failures:
    • server-auth.test.ts: OpenAI option auth matrix keeps direct, pool, and API credentials independent — WebSocket timeout.
    • native-profile-drain-server.test.ts: HTTP and Responses WebSocket keep Direct live while main Pool frames are rejected — WebSocket timeout.
    • responses-state.test.ts: periodic reclaim frees abandoned temps without any continuation access — cleanup count assertion.
  • Re-running those three files with --parallel=1 produced 258 passed and the same two WebSocket failures; the cleanup test passed. Running those three failing test names on an unmodified 8026405 baseline reproduced both WebSocket failures and passed the cleanup test. Unrelated tests were not changed to hide these failures.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

This PR remains draft because the full local test run is not green. No running user installation or provider configuration was changed.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ⬜ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@lidge-jun

Copy link
Copy Markdown
Owner

@/home/box/developer/review-comments/pr-4086.md

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 63 / 80

이 PR(draft, Eleven-is-cool)은 routed Responses에서 로컬 replay가 없거나 만료됐을 때 orphan tool result를 upstream으로 보내지 않고, 클라이언트가 전체 히스토리를 다시 보내게 합니다. 지금 dev HEAD 4b379b9ecsrc/server/responses/core.ts는 canonical OpenAI forward에 대해서만 hasUnexpandedPreviousResponseprevious_response_not_found를 먼저 돌려 #702 경로를 막습니다. routed·stateless 쪽은 문서/타입이 “miss면 전체 재전송”을 말하지만, 코드는 orphan repair에 더 기대는 형태였습니다. 이번 변경은 statelessResponses === true이거나 hasUnmappedRoutedCustomToolOutput(delta custom 결과에 짝 call이 없음)일 때 같은 400을 upstream 전에 냅니다. src/responses/custom-tool-compat.ts에 판정 함수를 두고, 영·한 가이드·providers 설정 문서·structure 노트도 맞춥니다. 테스트가 HTTP/WS·reasoning 보존·다음 incremental·native 전달을 잠급니다. 다만 PR이 아직 draft이고 로컬 full suite가 완전 그린이 아니며(작성자 말로는 baseline에서도 WS timeout 재현), readiness 체크리스트가 비어 있습니다. types/config 분할로 무효화될 대형 리팩터는 아닙니다.

라인 src/server/responses/core.ts · hasUnexpandedPreviousResponse 블록 - openai-responses + (statelessResponses 또는 unmapped custom output)만 막습니다. stateful native function/custom은 upstream 소유로 남깁니다.
라인 src/responses/custom-tool-compat.ts · hasUnmappedRoutedCustomToolOutput - call_id 없는 delta를 추측하지 않고 replay를 요구합니다. nested tools·additional_tools 테스트가 있습니다.
라인 src/types/provider.ts · statelessResponses 주석 - orphan repair 서술에서 previous_response_not_found 신호로 바뀌어 코드와 문서가 맞습니다.
경로 draft - readiness 네 칸이 비어 있고 작성자가 full suite NOT green을 명시합니다. draft로 두는 판단이 맞습니다.
경로 #702 계열 - canonical forward 가드는 그대로 두고 routed로 확장하는 방향이라 #702와 충돌하지 않습니다. 다만 기존 orphan-repair 경로와 새 early-reject의 경계가 운영에서 어떻게 보이는지는 한 번 더 보면 좋습니다.

메인테이너의 판단이 필요한 지점

  • statelessResponses 기본값을 바꾸지 않는 현재 설계를 유지할지(게이트웨이만 명시 opt-in)
  • draft를 ready로 올리기 전에 요구할 exact-head CI 범위
  • custom-tool unmapped 판정을 기본 routed 경로에 항상 켤지, flag 뒤로 둘지

너의 추천
방향은 맞고 문서·테스트도 실합니다. 지금은 draft를 유지하고, tip 4b379b9ec에 rebase한 뒤 exact-head CI가 그린 다음에만 ready/머지하세요. 로컬에서 재현되는 WS timeout을 이 PR 책임으로 숨기지 말고 baseline 이슈로 분리 기록하세요. types/config 분할 때문에 close할 대상은 아닙니다.

이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants