Skip to content

fix(responses): always carry query on web_search_call for Console Go - #3069

Closed
justin-mc-lai wants to merge 2 commits into
lidge-jun:devfrom
justin-mc-lai:fix/web-search-call-query-backfill
Closed

fix(responses): always carry query on web_search_call for Console Go#3069
justin-mc-lai wants to merge 2 commits into
lidge-jun:devfrom
justin-mc-lai:fix/web-search-call-query-backfill

Conversation

@justin-mc-lai

@justin-mc-lai justin-mc-lai commented Aug 31, 2026

Copy link
Copy Markdown

What & why

Fixes #3071 (sibling of #930). A multi-query web_search_call emitted by webSearchAction() only carried queries (plural). DeepSeek's native Responses parser requires queries, but Console Go's upstream validator requires the singular query — so once a batch search was recorded, every replayed turn 400'd with:

[invalid_request_error] `input[N].action` missing required field `query`

Changes

  • src/bridge.ts: webSearchAction() now always includes action.query (= first query) alongside queries, so both strict parsers are satisfied on new items.
  • src/adapters/openai-responses.ts: backfillWebSearchQueries() repairs pre-existing recorded items in either missing direction — adds queries from query (was there), or adds query from queries[0] (new), so old conversations heal at the replay boundary and stop 400-ing.

Tests

  • tests/bridge.test.ts: batched search asserts both query and queries on new items; single-query and empty-query cases unchanged.
  • tests/openai-responses-passthrough.test.ts: backfill test now also asserts the reverse repair direction (multi-query action gains singular query).
  • Local run: 176 pass, 0 fail across both files.

Trade-off

A multi-query batch loses the " ..." ellipsis in codex-rs and shows the first query as the cell label (the same label source Console Go needs).

Verification

Locally patched + restarted the proxy, then replayed an old-format multi-query web_search_call in a Responses request: completed with 200 instead of the previous 400.

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.

Summary by CodeRabbit

  • Bug Fixes

    • Improved web search compatibility by consistently providing both singular and multiple-query fields.
    • Multi-query searches now retain the first query while preserving the complete query list.
    • Replayed search actions are repaired when either query format is missing.
  • Tests

    • Expanded coverage for single-query and multi-query search actions.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • missing_regression_test — Behavior changed under src/ or gui/src/ without a test change. Add focused coverage or obtain test-exception-approved.

@github-actions github-actions Bot added the bug Something isn't working label Aug 31, 2026
@github-actions github-actions Bot changed the title fix(responses): always carry query on web_search_call for Console Go [WRONG BRANCH] fix(responses): always carry query on web_search_call for Console Go Aug 31, 2026
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

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.

4/4 boxes ticked.

This pull request is already Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers: @lidge-jun @Ingwannu

Hygiene

Deterministic PR hygiene checks passed.

@github-actions
github-actions Bot marked this pull request as draft August 31, 2026 10:02
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2f984c11-679b-41d2-9d9b-0d782b189d0a

📥 Commits

Reviewing files that changed from the base of the PR and between 542b1e5 and 5cf5cc1.

📒 Files selected for processing (2)
  • tests/bridge.test.ts
  • tests/openai-responses-passthrough.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The bridge now emits both query and queries for web-search actions. Replay repair now restores either missing field in existing actions.

Changes

Web-search action contract

Layer / File(s) Summary
Emit both web-search query fields
src/bridge.ts, tests/bridge.test.ts
webSearchAction() now always returns query as the first query and queries as a non-empty array. The test verifies both fields for multi-query searches. The documentation records the provider requirements and the multi-query label trade-off.
Repair incomplete replayed actions
src/adapters/openai-responses.ts, tests/openai-responses-passthrough.test.ts
backfillWebSearchQueries now derives query from a nonempty queries array and derives queries from a singular query. The test verifies repair in both directions. Complete actions remain unchanged.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 5cf5c

The change preserves both singular and plural search fields for new and replayed web-search actions, preventing the reported validation failure; no actionable merge-blocking risk remains beyond normal checks and review.

Possibly related PRs

  • lidge-jun/opencodex#932: Extends the web-search action and replay-repair changes to normalize both singular and plural query fields.

Suggested reviewers: ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary fix: preserving the singular query field on web_search_call items for Console Go. It is concise and specific.
Linked Issues check ✅ Passed The changes satisfy issue #3071. src/bridge.ts now emits both query and queries for generated searches. src/adapters/openai-responses.ts backfills queries from query and query from nonem…
Out of Scope Changes check ✅ Passed All production and test changes directly support issue #3071. The updates modify web-search action generation, replay backfill behavior, documentation comments, and focused test coverage. No unrelated…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files.
Full details: Linked Issues check

Explanation

The changes satisfy issue #3071. src/bridge.ts now emits both query and queries for generated searches. src/adapters/openai-responses.ts backfills queries from query and query from nonempty queries arrays during replay. The related tests cover batched actions and both backfill directions.

Full details: Out of Scope Changes check

Explanation

All production and test changes directly support issue #3071. The updates modify web-search action generation, replay backfill behavior, documentation comments, and focused test coverage. No unrelated code changes are identified.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 50 / 80

이 PR은 OpenCode Go(저장소에서 부르는 이름은 Console Go / Zen Go)의 네이티브 Responses 경로에서, 예전에 기록된 여러 검색어 web_search_call을 다음 턴에 다시 보내면 업스트림이 400을 내는 버그(#3068)를 고치려 합니다. 지금 dev HEAD는 7ee96b94e(#3058, 패키지 2.38.0)입니다. Console Go는 src/providers/registry.tsopencode-go입니다. 기본 어댑터는 openai-chat이고 주소는 https://opencode.ai/zen/go/v1입니다. 다만 muse-spark-1.2-contributorgpt-5.6-lunamodelWireDefaultsopenai-responses를 탑니다(#2617). Muse Spark 창은 이미 1M입니다(#2785). 같은 파일에 Muse만 web_searchsearch_content_types를 빼는 stripMuseSparkUnsupportedWebSearchFields(1880행)도 있습니다. 이 400은 그 필드가 아니라, 히스토리에 남은 검색 아이템 모양 문제입니다. types.ts/config.ts 분할과 무관하고, 같은 webSearchAction/backfillWebSearchQueries를 고치는 열린 PR은 없습니다. #2908(보내기 시각 providerFetch HTTP 버전), #2712(opt-in x_search), #2932(사이드카 루프 recovery)와는 층이 다릅니다. 초안이고 체크리스트 4칸이 전부 비어 있습니다. 베이스가 dev가 아니라 main이라 제목에 [WRONG BRANCH]가 붙었고, enforce-target이 실패했습니다. 위생 검사는 missing_regression_test로 실패했습니다.

지금 HEAD의 검색 아이템은 src/bridge.ts webSearchAction(164행)이 만듭니다. 검색어가 하나이거나 비면 { type:"search", query, queries:[query] }입니다. 검색어가 둘 이상이면 { type:"search", queries }만 넣고 단수 query는 빼 둡니다. 이 비대칭은 주석(152–159행)과 테스트가 일부러 잠근 계약입니다. DeepSeek 네이티브 Responses 파서는 queries가 없으면 다음 턴마다 missing field 'queries'로 400을 냅니다(#930, 이미 닫힘). 그래서 단수 쪽에 queries를 넣었습니다. 반대로 codex-rs는 칸 제목을 단수 query에서 읽고, query가 없고 queries.len() > 1일 때만 " ..." 말줄임표를 그립니다. 배치에 query를 넣으면 그 말줄임표가 사라집니다. src/adapters/openai-responses.ts backfillWebSearchQueries(916행)는 예전에 단수만 기록된 아이템에 queries:[query]를 채워 줍니다. query가 문자열이고 queries가 배열이 아닐 때만 고칩니다. 배치 아이템은 그대로 둡니다. 이 함수는 buildRequest 2103행에서 Responses 요청마다 돌아서, OpenCode Go로 나가는 히스토리에도 적용됩니다.

증상은 이렇습니다. opencode-go/muse-spark-1.2-contributor로 배치 검색이 한 번 기록되면, 그 web_search_callactionqueries만 있고 query가 없습니다. Console Go 업스트림 검사기는 단수 query를 필수라고 봅니다. 그래서 input[N].action missing required field query 400이 납니다. 그 아이템은 같은 대화의 다음 요청마다 다시 실려 가서, 업그레이드만으로는 대화가 영원히 막힙니다. #930과 같은 종류의 재현입니다. 다만 빠진 키가 반대입니다. 작성자가 로컬에서 옛 형식 아이템을 다시 보냈을 때 200이 되었다고 본문에 적었습니다.

고치는 코드는 두 곳입니다. webSearchAction은 검색어 개수와 상관없이 query를 첫 검색어로 넣고 queries도 같이 넣습니다. 빈 배열은 예전처럼 query:"", queries:[""]입니다. backfillWebSearchQueries는 빠진 쪽을 채웁니다. query가 없고 queries[0]이 있으면 query를 넣고, query만 있으면 예전처럼 queries를 넣습니다. 방향은 Console Go와 DeepSeek를 같이 살리려는 것이고, 파일 위치도 맞습니다. 다만 이 한 줄이 HEAD가 잠가 둔 배치 계약을 뒤집습니다.

문제는 테스트가 그 옛 계약을 아직 믿고 있다는 점입니다. tests/bridge.test.ts 1078행 테스트 이름은 "a batched (plural) search emits action.search.queries without a singular query"이고, action{ type:"search", queries:[...] }이며 action.queryundefined이길 기대합니다. tests/openai-responses-passthrough.test.ts 1298행 #930 테스트는 배치 아이템 ws_batch를 고치지 말고 { type:"search", queries:["a","b"] }로 남겨 두라고 적혀 있습니다. 주석도 "adding query would collapse the native plural rendering"입니다. 이 PR은 테스트 파일을 하나도 안 바꿨습니다. 그래서 위생이 missing_regression_test로 막혔고, 테스트를 안 고치면 그 두 단언이 바로 실패합니다. tests/web-search.test.ts 1894행은 toMatchObject라서 query가 추가돼도 그 줄은 통과합니다. 새 방향(배치에 query가 없음 → 채움)을 잠그는 테스트는 없습니다.

라인 149 src/bridge.ts 주석 - 아래 긴 설명은 "매번 두 키를 다 넣는다"로 바꿨는데, 바로 위 요약은 아직도 "Batch → { queries } with NO singular query"로 남아 있다. 다음 사람이 배치에서 query를 빼야 한다고 읽게 된다
라인 164 webSearchAction (PR) - 배치에도 query를 첫 검색어로 넣는다. 그 자체는 Console Go를 살리는 방향이 맞다. 다만 HEAD의 테스트 두 개가 그 반대를 잠그고 있어서, 테스트를 같이 뒤집지 않으면 CI가 빨갛다
라인 904 backfillWebSearchQueries JSDoc - 함수 본문은 양방향을 고치는데, 주석은 아직도 "단수 query만 있는 아이템에 queries를 채운다"(#930)만 말한다
라인 923 근처 (PR 본문) rep.query = action.queries[0] - queries[0]이 문자열인지 보지 않는다. 배열이기만 하면 숫자·객체도 query에 들어간다. Console Go가 문자열을 원하면 이 백필은 400을 못 없앤다
경로 tests/bridge.test.ts 1078행 - 배치에 query가 없기를 잠근다. 이 PR이 그 단언을 바꾸지 않았다
경로 tests/openai-responses-passthrough.test.ts 1324행 - 백필이 배치를 그대로 두기를 잠근다. Console Go 방향의 새 단언( queries만 있는 아이템에 query가 생기는지 )도 없다
라인 2103 backfillWebSearchQueries(outBody) - 호출 위치는 맞다. OpenCode Go Responses로 나가기 전에 히스토리를 고친다. Muse 전용 stripMuseSparkUnsupportedWebSearchFields(2139행)보다 앞이다. 다만 빈 queries: [] 이고 query가 없는 옛 아이템은 이 조건(length > 0)에 안 걸려서 그대로 400일 수 있다

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

  • 배치 칸 제목의 " ..." 말줄임표를 포기하고, Console Go·DeepSeek가 둘 다 통과하는 양쪽 키를 표준으로 삼을지.
  • 말줄임표를 살리고 싶다면 OpenCode Go로 나갈 때만 query를 채울지, 모든 Responses 업스트림에 항상 넣을지.
  • #3068이 템플릿 없이 한 번 닫혔다가 다시 열렸다. 이 PR의 Fixes #3068을 이대로 둘지, 버그 템플릿 이슈로 다시 받을지.
  • 초안·체크리스트 0/4·main 타깃을 먼저 고칠지, 테스트 계약부터 뒤집을지.

너의 추천

지금 형태로는 머지하지 마라. 진단(배치 web_search_callquery가 없어서 Console Go가 다음 턴마다 400)은 받고, 고치는 파일도 webSearchActionbackfillWebSearchQueries가 맞다. 먼저 베이스를 dev로 돌려라. 그다음 테스트 두 개를 새 계약으로 바꿔라. 배치 아이템은 { type:"search", query: 첫검색어, queries: 전체 }여야 하고, 백필은 queries만 있는 옛 아이템에 query를 넣어야 한다. queries[0]은 문자열일 때만 복사하라. 비어 있는 queries: []query:""로 채워질지 한 줄을 넣어라. 위생이 다시 돌아가고 체크리스트 4칸을 채운 뒤에 레디로 올려라. types/config 분할 무효화·중복 닫기 해당 없음. 프리뷰 배포는 계획에 없다. 관련 이슈 #3068은 같은 내용이다.

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

@github-actions github-actions Bot removed the intake: hygiene-blocked Deterministic PR hygiene checks failed label Aug 31, 2026
DeepSeek's native Responses parser requires 'queries', while Console Go's
upstream validator requires 'query'. A multi-query web_search_call emitted
by webSearchAction only carried 'queries', so replayed history 400'd on
every subsequent turn with: input[N].action missing required field 'query'
(sibling of lidge-jun#930).

- webSearchAction now always includes action.query (first query) alongside
  queries, satisfying both strict parsers.
- backfillWebSearchQueries repairs pre-existing recorded items in either
  missing direction (adds queries from query, or query from queries[0]).

Verified: a Responses request replaying an old-format multi-query
web_search_call now completes instead of 400ing on upstream.
…-jun#3071)

- bridge: batched search now asserts both 'query' and 'queries' (was:
  queries-only), matching the new webSearchAction output.
- passthrough: backfill test now asserts the reverse repair direction
  (multi-query action gains singular 'query'), matching the extended
  backfillWebSearchQueries.
@justin-mc-lai
justin-mc-lai force-pushed the fix/web-search-call-query-backfill branch from 429be1e to 5cf5cc1 Compare August 31, 2026 10:29
@justin-mc-lai
justin-mc-lai changed the base branch from main to dev August 31, 2026 10:29
@github-actions github-actions Bot changed the title [WRONG BRANCH] fix(responses): always carry query on web_search_call for Console Go fix(responses): always carry query on web_search_call for Console Go Aug 31, 2026
@github-actions
github-actions Bot marked this pull request as ready for review August 31, 2026 10:32

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 5cf5cc1d23025f3e30c8282b0f524212d3b88731. The underlying failure is real and the two-key direction is appropriate: new and replayed search actions need query for Console Go and queries for strict DeepSeek Responses parsers. Two current-head contract issues remain.

  1. src/bridge.ts:149-150 still states Batch → { queries } with NO singular query immediately before the new explanation and implementation say every batch carries both keys. Update the summary contract so future maintenance does not reintroduce the old shape.

  2. src/adapters/openai-responses.ts:928-930 copies action.queries[0] without proving it is a string. A replayed or caller-supplied queries: [123], object, or other malformed value now creates a non-string query, which still violates the Console Go contract and makes the repair itself produce an invalid shape. Validate the first member before copying. Define the behavior for an empty queries: [] as well: either repair it to the canonical empty search shape or deliberately leave/reject it, but cover both empty and non-string arrays so the adapter never claims a successful repair with an invalid singular field.

The focused assertions for valid single and batch histories are otherwise aligned with the intended contract. This head currently has only target/hygiene checks, not executed exact-head runtime CI, and is behind the advancing dev release version line. After the two fixes, rebase onto the then-current dev and run the exact-head matrix before approval.

@lidge-jun

Copy link
Copy Markdown
Owner

Landed via #3089 at a0d386b

@lidge-jun lidge-jun added the landed-via-maintainer Original PR closed after landing via a maintainer merge train label Aug 31, 2026
@lidge-jun lidge-jun closed this Aug 31, 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 landed-via-maintainer Original PR closed after landing via a maintainer merge train review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Console Go web_search_call 400: input[N].action missing required field query on replayed multi-query search

4 participants