Skip to content

fix(responses): strip web_search fields for Muse Spark Contributor Free tiers - #3906

Closed
MohamadSabree8 wants to merge 1 commit into
lidge-jun:devfrom
MohamadSabree8:fix/muse-spark-free-web-search-strip
Closed

fix(responses): strip web_search fields for Muse Spark Contributor Free tiers#3906
MohamadSabree8 wants to merge 1 commit into
lidge-jun:devfrom
MohamadSabree8:fix/muse-spark-free-web-search-strip

Conversation

@MohamadSabree8

@MohamadSabree8 MohamadSabree8 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

The Contributor Free tiers (muse-spark-1.2-contributor-free, muse-spark-1.3-contributor-free) run on the same Zen Responses wire and gateway contract as the paid tiers, so a Codex web_search call with search_content_types or indexed_web_access 400s for them just like it did for paid before #2621.

This adds both -free ids to MUSE_SPARK_WEB_SEARCH_STRICT_MODELS and adds a compat test that mirrors the paid-tier assertions.

Verified with bun test tests/providers/muse-spark-web-search-compat.test.ts: 12 pass, 0 fail.

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.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

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

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

Run ID: ef66147f-6f01-467f-9b6f-1f88cb5ad2bf

📥 Commits

Reviewing files that changed from the base of the PR and between f4a4b46 and 97812cf.

📒 Files selected for processing (2)
  • src/adapters/openai-responses.ts
  • tests/providers/muse-spark-web-search-compat.test.ts

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


📝 Walkthrough

Walkthrough

The strict web-search model set now includes Muse Spark 1.2 and 1.3 Contributor Free identifiers. Regression tests verify that unsupported fields are removed while supported fields remain.

Changes

Muse Spark web search compatibility

Layer / File(s) Summary
Extend strict web-search model coverage
src/adapters/openai-responses.ts, tests/providers/muse-spark-web-search-compat.test.ts
Lines 2127–2129 add both Contributor Free model IDs to strict sanitization. Lines 161–176 verify removal of search_content_types and indexed_web_access while preserving the web_search tool type and search_context_size.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to 97812

Muse Spark Contributor Free web-search requests now omit unsupported fields, matching paid-tier compatibility behavior. The targeted regression coverage supports merge readiness with no active risk identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: stripping unsupported web_search fields for Muse Spark Contributor Free tiers.
✨ 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.

@github-actions

github-actions Bot commented Sep 7, 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 September 7, 2026 12:24
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 70 / 80

이 PR은 지금 dev(HEAD f4a4b468f, 패키지 2.47.0, 최근 팁 #3864 레지스트리 스모크 복구) 위에서 Muse Spark Contributor Free 티어가 Zen Responses로 나갈 때 Codex가 붙이는 web_search 필드 때문에 나는 400을 막는 아주 좁은 호환 수정입니다. 이미 HEAD의 src/adapters/openai-responses.ts에는 stripMuseSparkUnsupportedWebSearchFields가 있고, MUSE_SPARK_WEB_SEARCH_STRICT_MODELSmuse-spark-1.3-contributor / muse-spark-1.2-contributor만 들어 있습니다. 그 집합에 들어 있고, 목적지가 https://opencode.ai/zen/v1/responses 또는 https://opencode.ai/zen/go/v1/responses일 때만 search_content_typesindexed_web_access를 지웁니다. web_search 도구 자체와 search_context_size 같은 허용 필드는 그대로 둡니다. Meta 직행(api.meta.ai)은 URL 가드 때문에 손대지 않습니다.

왜 Free가 문제냐면, Zen/Go 쪽 Free Contributor 모델도 유료 Contributor와 같은 Responses 게이트웨이 계약을 씁니다. Codex는 web_search_tool_type: TextAndImage일 때 위 두 필드를 붙이는데, Muse Spark 게이트웨이는 plain web_search에서 그걸 거절합니다. 유료 쪽은 #2617#2621, 이후 #3378 계열로 이미 막아 두었고, 코드 주석도 "equality가 아니라 membership"이라고 못 박아 두었습니다. 1.3이 1.2 후속으로 같은 와이어에 올라왔을 때 equality면 전부 400이 났을 그 설계입니다. 지금 Free id(muse-spark-1.2-contributor-free, muse-spark-1.3-contributor-free)만 집합 밖이라, Responses로 탄 Free 요청만 다시 같은 400을 맞습니다. 이 PR은 집합에 Free id 두 줄을 넣고, 유료와 같은 주장을 tests/providers/muse-spark-web-search-compat.test.ts에 한 케이스로 고정합니다. types.ts/config.ts 대규모 분리에 무효화될 종류가 아닙니다.

범위도 HEAD와 잘 맞습니다. 건드리는 파일은 어댑터 집합 2줄과 테스트 한 블록뿐이고, 기존 유료·preview·다른 모델·Meta 보존 테스트는 그대로입니다. 로컬에서 현재 HEAD 기준 같은 테스트 파일은 11 pass였고, 이 PR은 Free 루프 케이스를 더해 12 pass를 주장합니다. 수정 패턴도 저장소 관례와 같습니다. 새 필드가 발견되면 MUSE_SPARK_UNSUPPORTED_WEB_SEARCH_FIELDS에 한 줄, 새 모델이 같은 와이어면 Set에 한 줄 — 주석이 이미 그렇게 쓰라고 안내합니다.

다만 한 가지를 메인테이너가 같이 봐야 합니다. HEAD의 opencode-go modelWireDefaults에는 유료 muse-spark-1.3-contributor / muse-spark-1.2-contributoropenai-responses로 잡혀 있고, -free id는 없습니다. modelContextWindows / modelInputModalities도 유료만 1M·이미지입니다. opencode-zen / opencode-free 기본 어댑터는 openai-chat입니다. 그래서 기본 카탈로그만 보면 Free가 Chat로 갈 수 있고, 이 스트립 함수는 Responses 경로에서만 돕습니다. 작성자 말대로 Free가 이미 Zen Responses 와이어를 탄다면(명시 modelAdapters, 커스텀 목적지, 또는 live roster가 Responses로 붙는 경우) 이 Set 확장이 바로 400을 끊습니다. 반대로 Free를 Go 카탈로그에서도 유료와 같이 Responses로 기본 라우팅하고 싶다면, 이번 diff만으로는 부족하고 레지스트리 wire/window/modality 엔트리가 따로 필요합니다. 이 PR은 그 라우팅 결정을 하지 않고, 이미 Responses로 탄 Free 요청의 게이트웨이 계약을 맞춥니다.

라인 2125-2130 src/adapters/openai-responses.ts MUSE_SPARK_WEB_SEARCH_STRICT_MODELS - Free id 두 개 추가. membership 설계와 일치하고, URL 가드·필드 삭제 로직은 그대로라 유료 경로를 건드리지 않음.
테스트 tests/providers/muse-spark-web-search-compat.test.ts 신규 "Contributor Free tiers…" - Zen fixture로 Free 두 id의 필드 제거를 고정. 유료 1.2/1.3과 같은 주장.
경로 테스트 커버리지 - Free 케이스는 top-level tools만 보고, 유료에 있는 nested additional_tools / OpenCode Go fixture / split baseUrl+responsesPath는 Free에 대해 반복하지 않음. Set membership이면 Go도 같이 타지만, 회귀 문서 측면에선 Go Free 한 줄이 있으면 더 단단함.
경로 src/providers/registry.ts opencode-go modelWireDefaults - 이번 PR 밖. Free id가 Responses 기본이 아니면 일반 사용자는 Chat로 가서 이 수정 효과를 못 볼 수 있음. Free를 유료와 같은 Responses 기본으로 올릴지는 별도 판단.
상태 draft - 하이진·target 체크는 통과했지만 아직 draft라 병합 전에 Ready로 올려야 함.

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

  • Free Contributor를 opencode-go(또는 Zen)에서 유료와 같이 modelWireDefaultsopenai-responses (+ 1M window / image modality)로 기본 등록할지, 아니면 이 PR처럼 Responses에 이미 탄 경우만 스트립할지.
  • Free 테스트에 Go destination / nested additional_tools를 같은 PR에 더 넣을지, 지금 Zen top-level만으로 충분한지.
  • draft를 Ready로 올린 뒤 바로 머지할지, 레지스트리 wire 후속을 같은 기여자에게 부탁할지.

너의 추천
의도·범위·테스트 패턴이 HEAD의 #2621/#3378 계열과 같아서, draft만 Ready로 바꾸면 병합해도 됩니다. Free를 카탈로그 기본으로 Responses에 태울 계획이면 같은 PR 또는 바로 이어서 opencode-go-free wire/window/modality를 넣고, 가능하면 Free×Go 테스트 한 줄을 보태세요. types/config 분리에 닫을 대상 아닙니다.

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

…ee tiers

The -free tiers ride the same Zen Responses wire with the same gateway
contract, so a Codex web_search carrying search_content_types /
indexed_web_access 400s for them exactly like the paid tiers.
@MohamadSabree8
MohamadSabree8 force-pushed the fix/muse-spark-free-web-search-strip branch from 97812cf to 11c498b Compare September 7, 2026 12:39
@MohamadSabree8
MohamadSabree8 marked this pull request as ready for review September 7, 2026 12:42
lidge-jun added a commit that referenced this pull request Sep 7, 2026
…3942)

* docs(devlog): plan the workstream-A Responses compatibility stack

Roadmap for landing four Responses-compatibility changes on dev as one
dependent branch chain whose tip carries all of them, so a single CI run
certifies the set: PR #3906 (Muse Spark Free web_search strip), PR #3886
(Spark Responses Lite header), issue #3922 (Claude tool strict default,
new work), and PR #3917 (routed agent_message conversion).

Each phase doc carries exact path:line anchors and before/after diffs.
Three rounds of independent audit corrected the Layer 2 HTTP/WebSocket
coverage boundary, the Claude compatibility semantics, the Layer 3 test
that an added strict field breaks, the converted authMode set, and the
landing proof for each GitHub merge method.

* fix(responses): strip web_search fields for Muse Spark Contributor Free tiers

The -free tiers ride the same Zen Responses wire with the same gateway
contract, so a Codex web_search carrying search_content_types /
indexed_web_access 400s for them exactly like the paid tiers.

(cherry picked from commit 11c498b)

Co-authored-by: MohamadSabree8 <mohamadsabree8@users.noreply.github.com>

* test(responses): cover nested and preview cases for Muse Spark Free tiers

The carried fix covered a top-level web_search tool for the two Contributor
Free ids. The sanitizer also walks input[].additional_tools.tools, and it
must leave web_search_preview alone, so pin both for the free ids the way
the paid ids are already pinned.

Co-authored-by: MohamadSabree8 <mohamadsabree8@users.noreply.github.com>

* fix(responses): disable Lite transport for Spark

The canonical backend starts a Spark SSE response with the Responses Lite header but closes it before a terminal event, which the adapter correctly surfaces as adapter_eof. The identical request completes without that header.

Select the compatibility exception from the final wire model and remove both caller-provided and statically configured Lite headers only for gpt-5.3-codex-spark. Other canonical models retain the existing metadata path.

Regression: cover Spark suppression and unaffected Sol forwarding at the adapter boundary.

(cherry picked from commit 83c1d9b)

Co-authored-by: R <53855466+cb8010d6@users.noreply.github.com>

* docs(devlog): note the layer-1 line drift in the layer-2 anchors

Layer 1 inserts two lines above the canonical-forward block, so the phase
doc now states both the pinned-base line numbers and where the same code
sits on this branch.

* fix(claude): carry the source strict intent into translated Responses tools

Anthropic enables strict tool use by setting strict: true, while the
Responses API reads an omitted strict as permission to normalize the schema
into strict mode. Translating a Claude Code tool without the field therefore
made every optional input_schema parameter behave as required upstream, so a
tool call that omitted one failed even though the client never asked for
strict mode.

Emit the field from the source tool: an explicit true or false is preserved,
an omitted one becomes an explicit false, and a non-boolean value cannot opt
the tool into strict mode. The input_schema is forwarded unchanged, hosted
web_search leaves the translator before this branch, and native Anthropic
passthrough never reaches it.

The existing exact expectation on the translated Read tool gains the field.
The new regression asserts the three cases on the serialized outbound body
built by a real Responses adapter, because parsed._rawBody is the
translator's own object and reading it back would prove nothing about the
wire.

Closes #3922.

* fix(adapters): convert Codex agent_message for every routed Responses destination

`agent_message` is Codex's private multi-agent input item and exists only in the
ChatGPT Codex backend's schema. Codex writes every sub-agent reply into the
rollout, so it is replayed in the `input` of every later turn of that thread. A
routed Responses destination answers the whole body with
`422 unknown item type "agent_message"`, and 422 is a client error nothing fails
over, so the thread stays broken until the history is dropped.

The plaintext conversion already existed but was scoped to the OpenCode Go
destination. Nothing about the rejection is destination-specific, so the
conversion now applies to every destination with `authMode` other than
"forward". Forward destinations keep the item unchanged, and genuine ciphertext
and unknown part types keep their existing fail-closed path; the encrypted v2
task surface still owns those through `unreadable_encrypted_agent_task` and the
opt-in recovery route.

`isOpenCodeGo` existed only to scope this call and is removed with it. The
helper and its tests move to destination-neutral names.

Opaque-blob recovery repairs an undecryptable part into an omission marker,
which leaves the item entirely plaintext; on a routed retry it is now converted
too, which is what lets that retry be accepted at all.

Fixes #3911

(cherry picked from commit 2430724)

Co-authored-by: mashfromband <matsumoto.yukuhashi@gmail.com>

* test(adapters): pin an OAuth destination and narrow the routed-422 wording

The carried conversion is gated on authMode rather than on the destination
URL, but its regression only exercised key and forward. The reported
xAI/Grok failure is an OAuth pool destination, so pin one: a future
narrowing of the gate back toward key-only would otherwise pass unnoticed.

Also narrow the two reference pages. The conversion is justified by the
destinations that actually reported the 422; authMode is an authentication
setting, so it cannot establish what every custom upstream accepts.

Co-authored-by: mashfromband <matsumoto.yukuhashi@gmail.com>

* docs(devlog): drop a trailing blank line in the layer-1 phase doc

---------

Co-authored-by: Codex <a@b.com>
Co-authored-by: MohamadSabree8 <mohamadsabree8@users.noreply.github.com>
Co-authored-by: R <53855466+cb8010d6@users.noreply.github.com>
Co-authored-by: mashfromband <matsumoto.yukuhashi@gmail.com>
@lidge-jun

Copy link
Copy Markdown
Owner

The work from this pull request has landed on dev through the workstream-A compatibility stack in #3942, squash-merged as a13041740.

Your commit was carried onto the stack with its original authorship intact: the carried commit kept you as its author and its cherry picked from provenance line, and a Co-authored-by trailer naming you is present on the squash commit that landed, so the contribution is attributed to you on the merged record.

One addition on top of your change: the guard also walks nested input[].additional_tools.tools and must leave web_search_preview alone, so the free-tier regression now pins those two cases the way the paid tiers already were.

Verified on a fetched origin/dev: git diff between the stack tip and dev is empty across every path the stack touched. Closing this as landed rather than superseded. Thank you for the fix.

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

2 participants