Skip to content

fix: pin Union Alpha wire and namespace Go sessions - #4930

Merged
lidge-jun merged 3 commits into
devfrom
codex/lane-b-union-alpha-wire2
Sep 17, 2026
Merged

lidge-jun merged 3 commits into
devfrom
codex/lane-b-union-alpha-wire2

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Hard-pin OpenCode Go's exact union-alpha model id to the Anthropic wire, based on the evidence in [Provider]: Union Alpha inference fails on OpenCode routes; per-model Anthropic protocol mismatch #4847, while leaving sibling Chat and Responses models unchanged.
  • Namespace generated x-opencode-session values by the final wire protocol with a versioned hash separator. Sessions remain stable for the same lane and protocol, and operator-supplied headers still win unchanged.
  • Protect destination recognition from wire-selection order: each request retains the original routed provider for the registry destination check, settles the final wire separately, and passes both values to the transport helper. The helper therefore hashes the settled adapter without asking the adapter-sensitive registry matcher to recognize the already-flipped provider.
  • The direct Messages reproduction still returned 503 Endpoint is unavailable with a session header. This change does not establish successful Union Alpha inference; it fixes protocol selection and session namespacing only.

Refs #4847

Verification

  • git diff --check
  • Static call-graph inspection of src/server/responses/core-normalize.ts, src/server/chat-completions.ts, src/providers/opencode-go-transport.ts, and src/server/adapter-resolve.ts.
  • Independent SHA-256 vector calculation for Chat and Responses session namespaces, then comparison with the fixed expectations in tests/providers/opencode-go-session-header.test.ts.
  • Confirmed every resolveOpenCodeGoTransport call supplies the original routed destination separately from the settled provider.
  • Local Bun tests, typecheck, builds, dependency installation, and the ocx binary were not run because this lane explicitly forbids local verification. Hosted CI remains the executable verification.

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.

Summary by CodeRabbit

  • New Features

    • Added protocol-specific session affinity for OpenCode Go, keeping Chat, Responses, and Anthropic sessions distinct.
    • Ensured union-alpha consistently uses the Anthropic-compatible wire protocol.
    • Preserved OpenCode Go destination recognition when providers use adapter overrides.
    • Maintained operator-supplied session header precedence.
  • Bug Fixes

    • Fixed routing and session handling for per-model wire protocol overrides.
    • Improved compatibility for union-alpha requests across supported entry points.
  • Documentation

    • Updated transport documentation to describe protocol-specific session behavior and routing.

Known one-time effect: existing Go sessions rotate once

The derivation prefix moves from opencodex/opencode-go/session/v1 to .../v2, so every generated
x-opencode-session value changes on upgrade. A conversation that was in flight across the upgrade
is seen by OpenCode Go as a new session once, which costs that conversation its routing affinity for
one turn. Sessions are stable again from that point, and an operator-supplied session header is never
rewritten.

The version bump is deliberate rather than avoidable: the hash input genuinely changed, and reusing
v1 would have produced two different derivations behind one version label. The alternative —
namespacing only the Anthropic wire and leaving Chat and Responses on the v1 value — would have kept
existing sessions intact, but it makes the derivation depend on which protocol you happen to be on
and leaves the versioned prefix lying about its input.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 17, 2026 19:03
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T19:08:30.991764Z 4207419 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 1 minute.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 3aed183d-4cc9-4e74-a114-ae47574c11bf

📥 Commits

Reviewing files that changed from the base of the PR and between 4207419 and 68c2de6.

📒 Files selected for processing (1)
  • tests/providers/opencode-go-session-header.test.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 47343206-e3c6-4b54-be5b-219a4129a049

📥 Commits

Reviewing files that changed from the base of the PR and between 43cd1ad and 4207419.

📒 Files selected for processing (8)
  • src/providers/opencode-go-transport.ts
  • src/server/chat-completions.ts
  • src/server/responses/core-normalize.ts
  • src/types/wire.ts
  • structure/transports/responses.md
  • tests/adapters/key-failover.test.ts
  • tests/providers/opencode-go-session-header.test.ts
  • tests/server/adapter-resolve.test.ts

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


📝 Walkthrough

Walkthrough

The change makes OpenCode Go session values protocol-specific, preserves destination recognition after adapter overrides, reorders wire resolution before transport resolution, and pins union-alpha to the Anthropic wire. Tests cover affinity, routing, header precedence, failover, and wire selection.

Changes

OpenCode Go session routing

Layer / File(s) Summary
Protocol-aware session contract
src/providers/opencode-go-transport.ts, src/types/wire.ts, structure/transports/responses.md
deriveOpenCodeGoSessionId now hashes the wire protocol with the session lane under session/v2. Transport recognition checks the original destination provider. union-alpha is pinned to the Anthropic wire. The transport contract documents these rules.
Wire resolution and transport integration
src/server/chat-completions.ts, src/server/responses/core-normalize.ts
Both routing paths settle the wire provider before resolving OpenCode Go transport and pass the original routed provider for destination recognition.
Session affinity and wire-pinning validation
tests/providers/opencode-go-session-header.test.ts, tests/server/adapter-resolve.test.ts, tests/adapters/key-failover.test.ts
Tests use separate Chat and Responses vectors and verify protocol separation, routed-destination recognition, retry stability, operator header precedence, key failover, and union-alpha pinning.

Priority: ➖ Normal

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

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant RouteResolver
  participant OpenCodeGoTransport
  participant SessionHeader
  Request->>RouteResolver: provide routed provider and model
  RouteResolver->>RouteResolver: resolve wire protocol override
  RouteResolver->>OpenCodeGoTransport: pass settled provider and routed destination
  OpenCodeGoTransport->>SessionHeader: derive protocol-specific session value
Loading

Merge Risk: ⚪ Minimal · up to 42074

The routing, session namespacing, and wire-pinning changes have no established merge-blocking risk in the supplied evidence.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 7 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately identifies the two primary changes: pinning the Union Alpha wire protocol and adding protocol-specific namespaces for OpenCode Go sessions. It is concise and specific.
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.
Full details: Docstring Coverage

Explanation

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

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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 17, 2026
@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 75 / 80

이 PR은 OpenCode Go의 union-alpha 모델이 지금 dev에서 잘못된 전선(wire)으로 나가는 문제를 고치려는 작업이다. 지금 devsrc/types/wire.tsANTHROPIC_WIRE_MODELS["opencode-go"]에는 minimax-m2.5 / minimax-m2.7 / minimax-m3만 하드핀되어 있고, union-alpha는 없다. 그래서 Go 공급자의 기본 OpenAI-호환 어댑터로 가면 Chat은 500에 가깝게 깨지고, Messages로 가도 세션 검사까지는 가지만 실제 추론은 아직 안 된다(#4847). 이 PR은 그 표에 exact id union-alpha만 추가해서 Anthropic Messages 전선으로 고정한다. 형제 모델(예: glm-5.2)의 Chat/Responses 선택은 그대로 둔다.

그런데 Anthropic으로 어댑터를 뒤집으면, 예전에 resolveOpenCodeGoTransport가 “이미 뒤집힌” provider로 Go 목적지를 판별하던 길이 깨질 수 있다. 레지스트리 목적지 인식이 어댑터에 민감하기 때문이다. 그래서 호출 순서를 바꾼다. src/server/chat-completions.tssrc/server/responses/core-normalize.ts에서 먼저 resolveWireProtocolOverride로 최종 전선을 정하고, 그다음에 resolveOpenCodeGoTransport(wireProvider, sessionLane, routedProvider)를 부른다. 세 번째 인자 destinationProvider는 라우팅 직후의 원래 Go 행이다. src/providers/opencode-go-transport.ts는 목적지 판별을 destinationProvider로 하고, 해시에는 이미 정착된 provider.adapter를 넣는다.

세션 헤더 x-opencode-session도 v1에서 v2로 바뀐다. deriveOpenCodeGoSessionId(sessionLane, wireProtocol)가 레인뿐 아니라 최종 전선 문자열을 도메인 분리자에 넣어서, Chat / Responses / Anthropic이 같은 대화라도 전선마다 다른 불투명 값을 쓴다. 운영자가 직접 넣은 헤더는 대소문자 무시로 그대로 이긴다. PR 본문이 솔직히 말하듯, 직접 Messages 재현은 여전히 503 Endpoint is unavailable이다. 이 변경은 “프로토콜 선택 + 세션 네임스페이스”만 고치고, Union Alpha 추론 성공을 주장하지 않는다. Refs #4847이지 Closes가 아닌 이유가 여기에 있다. 테스트는 tests/server/adapter-resolve.test.ts에 핀 단언을 추가하고, tests/providers/opencode-go-session-header.test.ts에 Chat/Responses용 고정 SHA-256 벡터를 나눠 두었으며, structure/transports/responses.md도 같은 정책으로 맞춰 두었다. 현재 dev HEAD는 43cd1ade(#4623 offload 노트 정리)이고 패키지는 2.59.0이다. 이 PR은 그 위에 Go 전선/세션 경로만 건드리는 좁은 수정이다.

라인 tests/providers/opencode-go-session-header.test.ts (~315–370) - for (const [model, url] of [[CHAT_MODEL, ..., CHAT_SESSION_VECTORS], [MUSE_MODEL, ..., RESPONSES_SESSION_VECTORS]])처럼 튜플에 세 번째 벡터를 넣었는데 구조 분해는 여전히 [model, url]뿐이다. 블록 안에서는 sessionVectors.metadataA / sessionVectors.client / sessionVectors.native를 참조한다. 이 sessionVectors는 위쪽 for (const model of …) 루프 안의 const라서 여기 스코프에 없다. 타입체크나 테스트 실행 시 ReferenceError(또는 TS cannot find name)로 깨질 가능성이 매우 높다. 고치는 법은 for (const [model, url, sessionVectors] of …)로 세 칸을 모두 받는 것이다.

라인 src/providers/opencode-go-transport.ts (deriveOpenCodeGoSessionId v2) - 도메인 문자열이 opencodex/opencode-go/session/v1에서 v2로 바뀌고 wire가 해시 입력에 들어간다. 같은 대화라도 Chat↔Responses(또는 Anthropic 핀) 사이에서는 예전에 공유하던 affinity가 갈라진다. 의도에 맞는 breaking이지만, 롤아웃 노트에 “기존 Go 세션 쿠키/헤더 기대값이 바뀐다”를 한 줄 더 적어 두면 운영자가 덜 놀란다.

경로 #4847 vs 이 PR - 이 패치는 wire pin과 session namespace까지만 간다. PR 본문도 Messages 503이 남는다고 적었다. 이슈를 닫으면 “Union Alpha가 된다”로 오해된다. Refs 유지를 권한다.

경로 CI - 헤드 4207419 기준 hosted 체크가 아직 대부분 pending이다. 위 테스트 스코프 버그가 있으면 gates/test에서 바로 드러날 것이다. exact-SHA hosted CI가 녹색이 되기 전에는 머지하지 않는 편이 맞다.

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

  • Chat/Responses/Anthropic 세션 네임스페이스를 의도적으로 분리하는 v2 해시를 지금 릴리스 레인에 넣을지, 아니면 Union Alpha 핀만 먼저 넣고 session v2는 후속 PR로 나눌지
  • #4847을 이 PR에 묶은 채 열어둘지, 아니면 “wire pin landed, inference still 503” 진행 댓글만 남기고 이슈 상태를 어떻게 표기할지
  • 테스트 루프의 sessionVectors 구조 분해를 같은 커밋에서 고칠지, follow-up push로 받을지

너의 추천
for (const [model, url, sessionVectors] of …)로 테스트 ReferenceError를 고친 뒤, exact-head hosted CI가 통과하면 dev에 머지한다. #4847은 Closes 하지 말고 Refs로 남기고, 머지 후 이슈에 “wire pin + session v2 landed; Messages 503 still open” 한 줄을 남긴다. 추론 성공(503 해소)은 별도 후속 작업으로 둔다.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4207419ff3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +15 to +16
/** Derive a provider- and wire-scoped opaque value without exposing Codex task or subagent ids. */
export function deriveOpenCodeGoSessionId(sessionLane: string, wireProtocol: string): string {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update every mapped structure document

This changes behavior in both src/providers/ and src/server/, but updates only structure/transports/responses.md. structure/INDEX.md maps those source areas to several additional contract documents, including runtime.md, subagents.md, and transports/inventory.md; synchronize every mapped document in this change, or correct the ownership map if those documents no longer describe these areas, so the maintained architecture contracts do not drift.

AGENTS.md reference: src/AGENTS.md:L10-L11

Useful? React with 👍 / 👎.

The Claude metadata lane is not the hashed metadata.user_id. claude-messages.ts turns
prompt_cache_key into a UUID through uuidFromHex and normalizes THAT, so the lane is
sha256(uuidFromHex(sha256(user_id)[:32]))[:32]. The three metadata vectors were computed without
that step.

Derived independently of the production helpers and validated against the unchanged v1 values
these tests carried before the namespace change: the same reconstruction reproduces both of the
previous metadata vectors exactly, which is what shows the lane is right rather than merely
self-consistent. The other eight vectors were already correct and are untouched.
The loop lists CHAT_SESSION_VECTORS for glm-5.2 and RESPONSES_SESSION_VECTORS for the Muse model
but destructured only [model, url], so every case in it read whichever sessionVectors binding was
in scope instead of its own. Muse settles on the Responses wire, and these vectors are now
protocol-scoped, so each model needs the table the loop names for it.
@lidge-jun
lidge-jun merged commit d20b25d into dev Sep 17, 2026
28 checks passed
@lidge-jun
lidge-jun deleted the codex/lane-b-union-alpha-wire2 branch September 17, 2026 21:00
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.

1 participant