Skip to content

fix(claude): preserve usable Go session affinity across translation - #3961

Merged
lidge-jun merged 3 commits into
devfrom
codex/248-a-go-8c62
Sep 7, 2026
Merged

fix(claude): preserve usable Go session affinity across translation#3961
lidge-jun merged 3 commits into
devfrom
codex/248-a-go-8c62

Conversation

@lidge-jun

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

Copy link
Copy Markdown
Owner

Summary

Preserve Claude Messages conversation affinity when the selected destination is canonical OpenCode Go, including renamed providers and model-specific wire overrides. Carry #3949 and retain David Wang's authorship.

Forward usable explicit Go session identity and use the existing metadata-derived fallback only when no usable explicit lane exists. Reject empty/unusable metadata for newly synthesized Go affinity. Preserve configured operator-header precedence and native Anthropic/ChatGPT behavior. Regression cases exercise the real outbound Chat and Responses paths with isolated fixtures.

Closes #3945.

Verification

  • Local product tests, typecheck, builds and dependency installs: NOT RUN, prohibited by owner instruction.
  • Fresh independent source/security audit found one additional invalid session_id presence guard; corrected only Go synthesis, added both-wire regressions and passed interdiff re-review on ac8010db910ed598770e05f454e552a3865f54e4.
  • Current-head hosted CI 34168444860 succeeded (19 successful jobs, Windows runtime shards and macOS unsharded control skipped). Linux shard logs show all 26 OpenCode Go session-affinity cases passing, including invalid identity fallback, empty metadata omission, explicit/operator precedence, renamed and unrelated destinations. Pending or skipped checks are not passing evidence.
  • Previous-head run 34168269932 was cancelled after the source correction; it is not final-head evidence.
  • No live account, provider call, release or deployment is included. This PR contains one bug only.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed; compatibility restoration stays within the existing session identity contract.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults; credentials and requests in tests are synthetic.

Co-authored-by: David Wang 72378768+david-wang-0@users.noreply.github.com

Owner-authorized maintainer integration into dev after independent source/security review and current-head hosted CI. One bug per PR and squash commit; preserve David Wang and the original source trailers.

Pre-merge base refresh: eb4188a adds only #3962, capturing one already-stored fixture JWT instead of regenerating it across a second boundary. No production source, Go tests, shared fixture environment, dependencies or workflow changed. Existing candidate CI remains exact-head evidence; the final combination with this independent test correction is not claimed to have executed before merge. The whole landed tree will be compared with the merge calculation.

Summary by CodeRabbit

  • New Features
    • Improved Claude Messages compatibility with the OpenCode Go provider.
    • Session information can now be preserved across requests, supporting more consistent prompt-cache affinity.
    • Claude session metadata can help maintain stable routing when supported.
    • Explicit session and operator-provided headers continue to take precedence, with safe fallback behavior for invalid or unsupported destinations.

david-wang-0 and others added 2 commits September 8, 2026 07:51
Co-authored-by: GPT-6 Astra <noreply@openai.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit a2909be)
Count explicit OpenCode session identity only when the downstream normalizer accepts it, allowing valid metadata fallback. Require usable metadata for Go synthesis on both Chat and Responses wires while preserving native ChatGPT synthesis.

Add final-outbound contract cases for invalid and oversized headers, absent and unusable metadata, and explicit lane/operator precedence using independent fixed vectors. Local tests, typecheck, build, install, and runtime checks: NOT RUN by user instruction; patch self-inspected with Git/source/diff only.

Source-commit: a2909be
Co-authored-by: David Wang <72378768+david-wang-0@users.noreply.github.com>
Co-authored-by: GPT-6 Astra <noreply@openai.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 96a7c160-c580-4e5d-a845-7b32d2c770b8

📥 Commits

Reviewing files that changed from the base of the PR and between 5cd71ec and ac8010d.

📒 Files selected for processing (2)
  • src/server/claude-messages.ts
  • tests/providers/opencode-go-session-header.test.ts

📝 Walkthrough

Walkthrough

The Claude Messages path now recognizes canonical OpenCode Go destinations, forwards explicit session headers, and synthesizes session affinity from Claude metadata. Tests cover routing, precedence, fallback behavior, wire selection, streaming responses, and custom destinations.

Changes

Claude OpenCode Go session affinity

Layer / File(s) Summary
OpenCode Go route and session handling
src/server/claude-messages.ts
The handler resolves the routed registry destination, identifies opencode-go, forwards x-opencode-session, and applies explicit or metadata-derived session identity rules.
Claude ingress regression coverage
tests/providers/opencode-go-session-header.test.ts
The test harness supports Claude Messages and SSE responses. Tests verify stable metadata affinity, explicit header precedence, fallback rules, wire selection, and exclusion of custom or lookalike destinations.

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

Sequence Diagram(s)

sequenceDiagram
  participant ClaudeClient
  participant ClaudeMessages
  participant ProviderRegistry
  participant OpenCodeGo
  ClaudeClient->>ClaudeMessages: POST /v1/messages with metadata and optional session header
  ClaudeMessages->>ProviderRegistry: resolve routed destination
  ProviderRegistry-->>ClaudeMessages: identify canonical opencode-go route
  ClaudeMessages->>ClaudeMessages: preserve or synthesize session identity
  ClaudeMessages->>OpenCodeGo: send chat completion with session headers
  OpenCodeGo-->>ClaudeMessages: return JSON or SSE response
  ClaudeMessages-->>ClaudeClient: return Claude Messages response
Loading

Suggested reviewers: makesomethingshit

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/248-a-go-8c62

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

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 7, 2026
@lidge-jun
lidge-jun marked this pull request as ready for review September 7, 2026 23:11
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 7, 2026 23:11
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 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-07T23:16:45.822468Z ac8010d Draft marked ready
ℹ️ 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.

@lidge-jun
lidge-jun merged commit 60bcb90 into dev Sep 7, 2026
34 of 37 checks passed
@lidge-jun
lidge-jun deleted the codex/248-a-go-8c62 branch September 7, 2026 23:12
@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 71 / 80

이 PR은 Claude Code가 /v1/messagescanonical OpenCode Go에 붙을 때 세션 친화도(affinity)가 끊기는 문제를 고칩니다. 닫힌 이슈 #3945와 같고, #3949 캐리를 이어 가며 David Wang 저작을 남깁니다. 지금 devsrc/server/claude-messages.ts는 native ChatGPT 경로에서 metadata.user_idsession_id를 합성하지만, Go 목적지는 그 게이트 밖에 있습니다. 그래서 Claude → Go 번역 구간에서 x-opencode-session 레인이 비거나, 쓸 수 없는 명시 헤더만 남거나, 공유 system 해시로 잘못 묶일 수 있습니다.

패치 요지는 세 겹입니다. (1) registryEntryForProviderDestination(route.provider)?.id === "opencode-go"로 이름 바꾼 Go 프로바이더까지 포함해 Go 루트를 고정합니다. (2) 요청에 쓸 수 있는 명시 Go 세션이 있으면 그걸 살리고, 없을 때만 Claude metadata에서 레인을 합성합니다. (3) 빈 문자열·공백만·제어문자·과긴 identity는 명시 레인으로 치지 않고 metadata fallback으로 돌아가며, metadata도 쓸 수 없으면 affinity 헤더를 아예 안 붙입니다. 운영자 설정 헤더 우선순위와 native Anthropic/ChatGPT 동작은 유지한다고 본문에 적혀 있습니다.

테스트 tests/providers/opencode-go-session-header.test.ts가 Claude 경로를 실제로 handleClaudeMessages로 돌립니다. 턴 간 안정성, 대화 분리, renamed Go, 명시 헤더 우선, Chat vs Responses 와이어 선택, invalid explicit → metadata fallback, 빈 metadata에서 생략/명시 보존까지 덮습니다. 범위는 claude-messages.ts + 테스트뿐이라 types/config 분할과 겹치지 않습니다. 다만 상태는 draft이고, 본문이 “로컬 제품 테스트·타입체크 금지, hosted Cross-platform CI와 독립 소스 감사 필요”라고 못 박았습니다.

라인 src/server/claude-messages.ts · opencodeGoRoute - destination registry id로 판별하므로 lookalike URL을 Go로 오인하지 않습니다. 커스텀 Go 호환 엔드포인트를 쓰는 사용자는 이 게이트 밖입니다. 그게 의도인지 한 번만 확인하면 됩니다.

라인 src/server/claude-messages.ts · synthesizeGoSession / hasExplicitGoSession - sessionLaneIdFromRequestnormalizeLogConversationId(x-opencode-session) 둘 다로 “쓸 수 있는 명시 레인”을 봅니다. invalid explicit이 metadata로 떨어지는 테스트가 있어 회귀면이 분명합니다.

경로 draft + CI - 머지 전에 undraft와 hosted CI 그린이 전제입니다. #3945는 이미 CLOSED 상태이므로, 머지 시 이슈 상태보다 PR close/landing 코멘트가 중요합니다.

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

  • draft를 언제 ready로 올릴지, 그리고 필수 hosted CI 샤드 목록
  • renamed-go 외 “Go처럼 보이는 커스텀 baseUrl”을 지원할 계획이 있는지(지금은 registry id만)
  • 머지 후 fix(claude): preserve OpenCode Go session affinity #3949 leftover가 남아 있으면 landed-via 처리할지

너의 추천
방향은 dev의 Go affinity 열차(#3880 등)와 맞습니다. undraft하고 hosted CI가 그린이면 머지하세요. draft 상태에서는 큐 앞에 두지 마세요. types/config 분할에 무효화될 모양은 아닙니다.

이 댓글은 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: ac8010db91

ℹ️ 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".

const route = routeModel(config, internalBody.model as string, evidenceFromBody(internalBody));
// Match the fixed key-auth destination before per-model wire overrides, including
// renamed Go providers without treating custom or lookalike URLs as Go.
opencodeGoRoute = registryEntryForProviderDestination(route.provider)?.id === "opencode-go";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive Go affinity from the final combo target

When a Claude request names a combo using the random strategy, this preflight routeModel call and handleComboResponses' separate pick at src/server/responses/core.ts:2618 can select different targets. If preflight selects a non-Go key provider but dispatch selects OpenCode Go, opencodeGoRoute remains false and no metadata-derived session lane is added, so Go affinity is intermittently lost. Carry the validated metadata identity through the replay and apply it after the combo/fallback target is finalized, and add a combo regression case.

Useful? React with 👍 / 👎.

david-wang-0 added a commit to david-wang-0/opencodex that referenced this pull request Sep 8, 2026
Carry validated Claude affinity privately through combo replay and consume it only at the final canonical Go transport. Preserve explicit identity and operator precedence without leaking Go-only headers to other destinations.

Addresses the late review on lidge-jun#3961. Adds deterministic random and failover regressions across both Go wires.

Co-authored-by: GPT-6 Astra <noreply@openai.com>
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.

2 participants