Skip to content

fix(qoder): support Codex-owned capture-only tool bridge - #5726

Closed
juzijia wants to merge 3 commits into
lidge-jun:devfrom
juzijia:fix/qoder-capture-only-tool-bridge-current-dev
Closed

juzijia wants to merge 3 commits into
lidge-jun:devfrom
juzijia:fix/qoder-capture-only-tool-bridge-current-dev

Conversation

@juzijia

@juzijia juzijia commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add a Qoder capture-only tool bridge. Its private MCP helper captures tool-call intent without executing tools; Qoder-local code pairs that intent with native call IDs and validates the result. Codex retains ownership of tool approval, sandboxing, and execution, with tool results returned through continuation.

The shared coding-agent changes provide provider-neutral runtime support. CodeBuddy is an existing capture-only bridge precedent, not an implementation copied into Qoder.

Fixes #5270. This implementation supersedes the earlier approach in #5554; #5554 is now closed.

Verification

  • Current author HEAD: 2fc06bbea1e7327709c845255f2a6ff88120247a.
  • Baseline validation on 184470aa962aa8adb43e8c8981806638e0b3c205: Qoder targeted tests 147/147 PASS; CodeBuddy regression tests 125/125 PASS; bun run typecheck PASS; git diff --check PASS.
  • Isolated real-provider smoke on 184470aa962aa8adb43e8c8981806638e0b3c205 with Qoder CLI 1.1.60: PASS. tool_call → Codex-side test client execution → function_call_output → continuation → final response completed; sum_numbers(a=2,b=3) returned 5. The smoke logs contained no duplicate or protocol_error, and the production OpenCodex instance was not modified, restarted, or replaced.
  • Follow-up review fixes on the current HEAD: a second native tool call in one assistant turn now fails closed with protocol_error; Qoder forced continuation is limited to completed responses that contain a function_call, while Kiro/Cursor behavior is unchanged.
  • Follow-up validation on the current HEAD: Qoder turn tests 47/47 PASS; targeted continuation test 1/1 PASS; bun run typecheck PASS; git diff --check PASS.
  • Bridged tool turns still do not add --max-turns 1; static evidence was insufficient to confirm that flag with Qoder CLI 1.1.60, so no behavior change or additional real-provider test was made for that point.
  • Partial usage emitted before message_stop remains marked estimated by design. Vendor code 118 / credit usage limit handling remains Qoder-local; no evidence was found that CodeBuddy requires that mapping.
  • The full repository test suite was not run.

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.

Review readiness checklist

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

  • Required local validation passed; commands, results, and any full-suite exception are documented.

  • I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Sep 24, 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

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

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

github-actions Bot commented Sep 24, 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

  • ⬜ Required local validation passed; commands, results, and any full-suite exception are documented.
  • ⬜ I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
  • ⬜ 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

리뷰 · 우선순위 52 / 80

Qoder가 도구를 직접 실행하지 못하게 막는 변경이다. 요청에 도구가 있으면 OpenCodex는 그 목록만 작은 도우미 프로그램으로 보여 준다. 도우미는 "이 도구를 이 값으로 부르고 싶다"는 기록만 파일로 남기고, 실행하지 않은 채 멈춘다. 부모 프로세스가 Qoder가 보낸 호출 번호와 그 기록을 짝지어, 맞는 첫 호출만 Codex로 넘긴다. Codex가 승인하고 격리된 공간에서 실행한 뒤, 다음 요청에 결과를 다시 넣는다. 도구가 없는 요청은 예전처럼 글과 추론만 한다. 베이스는 dev다. 머리는 184470aa962aa8adb43e8c8981806638e0b3c205다. 아직 초안이다.

같은 일을 하려다 닫힌 #5554를 이 풀리퀘스트가 대신한다. #5554는 2026-09-24에 이미 닫혀 있다. 이슈 #5270은 아직 열려 있고, 본문은 이 풀리퀘스트가 그 이슈를 고친다고 적는다.

작성자가 적은 검증은 Qoder 테스트 147개, CodeBuddy 회귀 125개, 타입체크, 그리고 Qoder CLI 1.1.60으로 sum_numbers(2, 3)이 5가 된 한 번의 실제 호출이다. 저장소 전체 테스트는 돌리지 않았다고 본문에 적혀 있다. 그 명령은 여기서 다시 실행하지 않았다.

라인 - src/adapters/qoder/adapter.ts의 buildQoderArgs. 도구가 없을 때만 --max-turns 1을 붙인다. 도구가 있으면 그 상한이 빠진다. 모델이 도구를 안 부르면, 부모는 출력이 끝나거나 프로세스 시간 제한에 걸릴 때까지 Qoder CLI를 붙잡고 있는다.

라인 - src/adapters/qoder/turn.ts의 consumeQoderFrames. 한 번의 대답 안에서 도구 호출이 두 번째부터면 그 호출은 클라이언트에 보내지 않는다. 본문도 추가 병렬 호출은 실행하지 않는다고 적는다. 그런데 두 번째 기록 파일에 error가 있으면, 첫 번째가 맞아도 그 자리에서 턴 전체를 실패시킨다. payload.error 분기는 몇 번째 호출인지 보지 않는다.

라인 - src/server/responses/core-replay.ts의 adapterNeedsForcedContinuation. qoder를 kiro, cursor 옆에 넣었다. src/responses/state.ts의 rememberResponseState는 force가 있으면, 클라이언트가 대화를 저장하지 말라고 해도 이어가기 상태를 남긴다. 도구 결과를 다음 턴에 붙이려면 필요하다. 글만 답하는 Qoder 턴까지 같은 저장을 탄다. 그 저장은 입력 전체를 들고 있어서, 대화가 길어지면 메모리가 커진다. 그 파일 주석은 아직 kiro와 cursor만 적혀 있다.

라인 - src/adapters/qoder/turn.ts의 commitSideChannelCapture. 도구 호출로 프로세스를 끊을 때 Qoder의 문장 종료 신호(message_stop)를 아직 못 봤으면, 공급자가 준 사용량에 estimated: true를 붙인다. isPositiveAuthoritativeUsage는 그 표시가 있으면 공식 사용량으로 세지 않는다. 공급자 숫자가 있어도 추정 사용량으로 나간다. CodeBuddy가 쓰는 공통 경로는 이 표시를 붙이지 않는다.

라인 - src/adapters/coding-agent/protocol.ts의 mapStreamMessageToEvents. 공급자 코드 118과 "credit usage limit" 판별을 공통 파서에서 뺐다. Qoder는 mapQoderStreamMessage가 결과 프레임에서 다시 HTTP 429 insufficient_quota로 붙인다. 가이드의 할당량 문장은 그대로다. 공통 함수를 그대로 쓰는 쪽은 CodeBuddy다. CodeBuddy가 118을 내는지는 이번 리뷰에서 실행으로 확인하지 않았다.

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

초안 체크리스트 네 칸이 모두 비어 있다. 전체 테스트를 면제할지를 본문 한 줄로 끝낼지, 칸을 채울 때까지 초안을 유지할지. 도구가 있는 턴의 --max-turns를 몇으로 둘지. 한 대답에 도구 호출이 둘 이상이면 첫 번째만 살릴지, 턴을 실패시킬지. 저장 강제를 도구가 있는 Qoder 요청만으로 좁힐지. --append-system-prompt-file을 지원하는 Qoder CLI를 스모크에 쓴 1.1.60만으로 볼지.

너의 추천

방향은 맞다. Codex가 실행하고 Qoder는 부르고 싶은 도구만 넘긴다. 초안인 채로 두고, 체크리스트를 채운 뒤에 머지한다. 한 대답에 호출이 둘 이상이면 그 턴을 실패로 닫는다. 저장 강제는 도구가 있는 턴으로 한정한다. 도구 턴에도 턴 횟수 상한을 남긴다. #5554는 이미 닫혀 있다. 그 상태는 유지하면 된다. #5270은 이 풀리퀘스트가 머지될 때 닫히면 된다.

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

@juzijia juzijia closed this Sep 24, 2026
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.

3 participants