Skip to content

fix(opencode-go): satisfy provider wire contract - #3405

Merged
lidge-jun merged 1 commit into
lidge-jun:devfrom
adtumk:fix/opencode-go-wire-contract
Sep 4, 2026
Merged

fix(opencode-go): satisfy provider wire contract#3405
lidge-jun merged 1 commit into
lidge-jun:devfrom
adtumk:fix/opencode-go-wire-contract

Conversation

@adtumk

@adtumk adtumk commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • derive a stable, opaque x-opencode-session value from OpenCodex's existing session lane for canonical OpenCode Go traffic
  • preserve an explicit operator-provided session header and carry generated affinity across API-key rotation
  • strip the rejected indexed_web_access field alongside search_content_types from plain Muse Spark 1.2/1.3 web_search tools, while leaving preview tools and unrelated models unchanged
  • document the provider-specific wire contract

Closes #3378

Verification

  • bun x tsc --noEmit and the doctor-service memory-contract typecheck
  • bun test tests/opencode-go-session-header.test.ts tests/muse-spark-web-search-compat.test.ts tests/key-failover.test.ts — 26 pass, 0 fail
  • latest upstream catalog tests after rebase — 303 pass, 0 fail
  • full CI-equivalent four-shard Windows run with CI's 60-second test timeout — 17,650 pass, 78 skip, 4 fail across all 1,051 test files
    • two pre-existing .cmd quoting failures in multi-agent-keep-native-v1.test.ts
    • one test-temp ACL cleanup failure in oauth-store-multi.test.ts
    • one upstream CREDITS.md privacy failure introduced by the current dev base
  • GUI suite — 1,326 pass, 2 pre-existing Windows absolute-path failures in i18n-orphans.test.ts
  • bun run privacy:scan currently fails only on the three email-shaped examples newly added to upstream CREDITS.md; this PR does not touch that file or the scanner
  • the exact dev base (db2e2eb4709905fc8e7acfa982b5e945f859e15e) is itself red in upstream CI for the privacy gate, macOS suite, and test shard 2/4: https://github.com/lidge-jun/opencodex/actions/runs/33820290617
  • generated skill surface, release-helper build, CLI help smoke, and git diff --check pass
  • local OpenCode Go / Muse Spark 1.3 Contributor validation showed stable per-session cache reuse during normal and subagent work; provider cache residency remains best-effort rather than a guaranteed 100% hit rate

No GUI changes.

Review readiness checklist

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

  • No CI failures were introduced by this PR; the current dev baseline failures are documented above.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

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.

@github-actions

github-actions Bot commented Sep 3, 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 3, 2026
@github-actions

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

@github-actions
github-actions Bot marked this pull request as draft September 3, 2026 23:48
@coderabbitai

coderabbitai Bot commented Sep 3, 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: b3168edb-d266-48de-9c1d-4b5c499295cf

📥 Commits

Reviewing files that changed from the base of the PR and between d4ef2b3 and 9b20297.

📒 Files selected for processing (7)
  • src/adapters/openai-responses.ts
  • src/providers/opencode-go-transport.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md
  • tests/key-failover.test.ts
  • tests/muse-spark-web-search-compat.test.ts
  • tests/opencode-go-session-header.test.ts

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


📝 Walkthrough

Walkthrough

The change adds OpenCode Go session-header resolution during route normalization and preserves that header during key failover. It also expands Muse Spark web-search sanitization to remove indexed_web_access alongside search_content_types, with coverage for nested and preview tools.

Changes

Provider compatibility

Layer / File(s) Summary
Muse Spark web-search sanitization
src/adapters/openai-responses.ts:1969-2004, tests/muse-spark-web-search-compat.test.ts:21-126
The sanitizer centralizes the rejected fields and removes search_content_types and indexed_web_access from plain web_search tools. Tests cover top-level and nested tools, Muse Spark versions 1.2 and 1.3, preview tools, and unaffected models.
OpenCode Go transport resolution
src/providers/opencode-go-transport.ts:1-41, src/server/responses/core.ts:244, src/server/responses/core.ts:291, src/server/responses/core.ts:2064, structure/04_transports-and-sidecars.md:308-332
The resolver derives an ocx_-prefixed SHA-256 session value from the session lane. It injects the header only for the opencode-go destination when no case-insensitive override exists. Route normalization applies the resolver before wire overrides.
Session affinity and failover validation
tests/opencode-go-session-header.test.ts:1-143, tests/key-failover.test.ts:13, tests/key-failover.test.ts:137-166
Tests verify stable headers across Responses and Chat requests, distinct sibling sessions, renamed-provider matching, explicit overrides, runtime-only metadata, lookalike destinations, and key rotation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 9b202

This update adds stable OpenCode Go session affinity and removes rejected Muse Spark web-search fields while preserving documented exceptions. The covered behavior is ready to merge.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant handleResponses
  participant resolveOpenCodeGoTransport
  participant OpenCodeGoEndpoint
  Client->>handleResponses: Send request with session lane
  handleResponses->>resolveOpenCodeGoTransport: Resolve provider transport
  resolveOpenCodeGoTransport->>resolveOpenCodeGoTransport: Derive x-opencode-session
  resolveOpenCodeGoTransport->>OpenCodeGoEndpoint: Send normalized request
  OpenCodeGoEndpoint-->>handleResponses: Return provider response
  handleResponses-->>Client: Return response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 6 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy linked issue #3378. src/providers/opencode-go-transport.ts derives a stable opaque x-opencode-session value from the session lane, preserves explicit headers case-insensitively…
Out of Scope Changes check ✅ Passed The code, tests, and documentation changes are directly related to the linked provider compatibility requirements in #3378. The transport resolver, route integration, failover coverage, Muse Spark san…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary OpenCode Go compatibility change: satisfying the provider wire contract through session-header handling. It is concise and remains related to the changeset, ev…
Full details: Linked Issues check

Explanation

The changes satisfy linked issue #3378. src/providers/opencode-go-transport.ts derives a stable opaque x-opencode-session value from the session lane, preserves explicit headers case-insensitively, scopes injection to the canonical opencode-go destination, and keeps generated metadata runtime-only. src/server/responses/core.ts integrates the resolver, and tests/key-failover.test.ts verifies header preservation during key rotation. src/adapters/openai-responses.ts centralizes and removes both indexed_web_access and search_content_types for plain Muse Spark web_search tools. The tests verify preview tools and unrelated models remain unchanged.

Full details: Out of Scope Changes check

Explanation

The code, tests, and documentation changes are directly related to the linked provider compatibility requirements in #3378. The transport resolver, route integration, failover coverage, Muse Spark sanitizer update, targeted tests, and provider wire-contract documentation all support the stated objectives. No unrelated code changes are identified.

Full details: Docstring Coverage

Explanation

Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 6 files. (1 skipped: 1 unsupported.)

Full details: Title check

Explanation

The title clearly identifies the primary OpenCode Go compatibility change: satisfying the provider wire contract through session-header handling. It is concise and remains related to the changeset, even though it does not mention the secondary Muse Spark update.

  • Fix all pre-merge checks with AI
✨ 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

리뷰 · 우선순위 70 / 80

설명

이 PR은 OpenCode Go(opencode-go) 쪽이 요구하는 와이어 계약을 opencodex가 아직 맞춰 주지 않아서 생기던 두 가지 호환 버그를 한 번에 고칩니다. 묶인 이슈는 #3378이고, 그 안에 이미 닫힌 #3344(세션 헤더 누락, @colthreepv)와 #3362(Muse Spark가 indexed_web_access 거절, @0disoft)가 흡수되어 있습니다.

첫 번째 문제는 세션 친화도입니다. OpenCode Go는 요청마다 x-opencode-session 값이 있어야 같은 대화의 캐시를 재사용할 수 있는데, 지금 devsrc/providers/registry.ts opencode-go 행에는 그 동작이 없고, 코드베이스에도 이 헤더 문자열이 없습니다. 그래서 Codex → 프록시 → Go 경로로 나가면 upstream이 세션을 못 붙잡습니다.

고치는 방식은 xAI 쪽 src/providers/xai-transport.ts와 같은 패턴입니다. 새 파일 src/providers/opencode-go-transport.ts에서 기존 세션 레인(sessionLaneIdFromRequest, parent\0child 쌍)을 SHA-256으로 짧게 해시한 뒤 ocx_ 접두 불투명 값을 만들고, 레지스트리 목적지가 진짜 opencode-go일 때만 헤더를 붙입니다. 운영자가 이미 헤더를 넣었으면 대소문자 무시하고 그대로 두고, 설정 파일에는 쓰지 않고 런타임 route 객체에만 얹습니다. 키 로테이션 테스트도 같은 값이 유지되는지 확인합니다.

두 번째 문제는 Muse Spark plain web_search 필드입니다. 이미 #2617search_content_types는 빼고 있었는데, 1.3이 indexed_web_access도 거절합니다. src/adapters/openai-responses.tsstripMuseSparkUnsupportedWebSearchFields를 필드 목록 방식으로 바꿔서 다음 거절 필드가 생기면 한 줄만 추가하면 되게 했고, preview 도구와 Luna 등 다른 모델은 그대로 둡니다.

현재 dev HEAD는 d4ef2b385 (Responses unknown usage-field passthrough 핀 #3365, package 2.42.0)입니다. types.ts/config.ts 분할 캠페인으로 무효화되는 종류의 변경이 아닙니다. 베이스도 dev이고, 범위는 transport 헬퍼 + Muse sanitizer + 문서 + 테스트입니다. 같은 opencode-go 축의 열린 PR #3394(Grok 4.6 Responses)와는 겹치는 파일이 거의 없어 충돌 위험이 낮습니다. hygiene/enforce-target/label은 이미 통과했고 CodeRabbit만 pending입니다.

우선순위 70은 “OpenCode Go/Muse 실사용에서 캐시 친화도와 web_search 400이 바로 깨지는 프로바이더 와이어 버그”이지만, Codex 전 사용자 공통 블로커는 아니고 native Chat 경로 후속 여부가 남아 있어서 즉시 강제 랜딩보다 CI·CodeRabbit 확인 후 머지가 맞는 위치입니다.

라인 src/providers/opencode-go-transport.ts deriveOpenCodeGoSessionId - 레인 문자열을 버전 네임스페이스와 함께 해시해 ocx_ + 32hex로 만드는 방식은 맞습니다. 원본 Codex thread/session id가 밖으로 안 새게 한 점도 테스트로 고정되어 있습니다.
라인 src/providers/opencode-go-transport.ts resolveOpenCodeGoTransport - registryEntryForProviderDestination(...).id === "opencode-go" 게이트가 이름 바꾸기·lookalike URL을 가르는 핵심입니다. evil.test 목적지에 헤더를 안 넣는 테스트가 있어서 좋습니다.
라인 src/server/responses/core.ts applyFinalRouteRequestNormalization - 주입 지점이 Responses 정규화 한곳뿐입니다. 테스트의 Chat 모델(glm-5.2)도 /v1/responses → upstream chat/completions 경로라서 Codex 기본 경로는 커버됩니다. 다만 native POST /v1/chat/completions(handleChatCompletions)에는 같은 호출이 없습니다.
라인 src/adapters/openai-responses.ts MUSE_SPARK_UNSUPPORTED_WEB_SEARCH_FIELDS - search_content_typesindexed_web_access를 목록으로 묶은 확장은 #2617 sanitizer의 자연스러운 연장입니다. preview/Luna 비변경 기대값도 같이 갱신되어 있습니다.
경로 tests/opencode-go-session-header.test.ts / tests/key-failover.test.ts - Responses·Chat 동일값, 형제 서브에이전트 분리, 운영자 헤더 우선, 레인 없을 때 생략, 키 로테이션 유지까지 한 축으로 잘 묶여 있습니다.
경로 PR 본문 Verification - 관련 유닛 26 pass와 typecheck/privacy:scan을 적었고, 전체 bun run test는 Windows 900초 천장에 걸렸다고 솔직히 적혀 있습니다. 체크리스트는 채워져 있습니다.

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

  • native /v1/chat/completions → opencode-go 경로에도 같은 transport를 넣을지, Codex Responses 경로만으로 이번 이슈를 닫을지
  • #3378만 닫을지, 이미 CLOSED인 #3344/#3362에 landed-via 코멘트를 남길지(상태상 추가 조치는 선택)
  • CodeRabbit pending을 기다릴지, hygiene/enforce-target 그린과 로컬 관련 테스트만으로 랜딩할지
  • 열린 #3394(opencode-go Grok 4.6)와 머지 순서를 어떻게 잡을지

너의 추천
의도·범위·테스트가 머지 후보입니다. CodeRabbit과 관련 CI가 깨끗해지면 dev에 랜딩하고 #3378을 닫으세요. native Chat 경로 헤더는 후속 이슈로 남겨도 이번 Closes 범위와 맞습니다. types/config 분할 때문에 닫을 PR이 아닙니다.

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

@adtumk
adtumk force-pushed the fix/opencode-go-wire-contract branch from 9b20297 to 06c4d8f Compare September 4, 2026 00:25
@github-actions
github-actions Bot marked this pull request as ready for review September 4, 2026 00:37

@lidge-jun lidge-jun 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 as maintainer for the 260904 bug-backlog merge train.

Verified both halves of #3378. Destination matching is exact and rejects lookalike provider names, the session value is an opaque hash rather than anything caller-derived, an explicitly configured header still wins case-insensitively, config is not mutated, and generated affinity survives API-key rotation. Injection happens before model wire selection, so both the Chat and Responses paths carry it. The Muse sanitizer change stays scoped to plain web_search on the affected models and leaves preview tools and unrelated models alone.

On the four suite failures your description attributes to the dev baseline: this train verifies against hosted CI rather than a local full-suite run, and every required check on this PR is green, so that attribution is recorded rather than re-litigated here. It lands last in the train; #3420 touched src/adapters/openai-responses.ts too, but only the output-repair helpers, and mergeability was re-confirmed after that merge landed.

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

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants