Skip to content

feat: add X-Session-Id header for proxy cache routing affinity - #31511

Merged
rekram1-node merged 1 commit into
anomalyco:devfrom
songchaow:feat/x-session-id-header
Jun 9, 2026
Merged

feat: add X-Session-Id header for proxy cache routing affinity#31511
rekram1-node merged 1 commit into
anomalyco:devfrom
songchaow:feat/x-session-id-header

Conversation

@songchaow

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes N/A (improvement — no existing issue)

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds an X-Session-Id header (set to the session ID) alongside the existing x-session-affinity header for all non-opencode providers.

Why: Anthropic API proxies (e.g. enterprise gateways that front multiple upstream Anthropic accounts) use X-Session-Id to implement routing affinity — pinning all requests from the same session to the same upstream account. This maximizes KV-Cache hit rate on the upstream side because the cached prompt prefix lives on that specific account.

Without this header, multi-turn conversations get scattered across different upstream accounts by the load balancer, causing frequent prompt cache misses and significantly higher latency + cost.

The header name X-Session-Id is the convention used by Anthropic-compatible proxy providers (documented in their API specs). It is sent unconditionally for non-opencode providers — providers that do not recognize it will simply ignore an unknown header, so there is no behavioral change for direct Anthropic API usage or other providers.

The change is a single line addition in packages/opencode/src/session/llm/request.ts.

How did you verify your code works?

  1. Built locally with bun run build --skip-embed-web-ui --single
  2. Set up an HTTP header inspection proxy between opencode and the API endpoint — confirmed X-Session-Id is present in all outgoing requests
  3. Ran an end-to-end cache hit test: two sequential requests with the same session ID and same system prompt showed cache_creation_input_tokens: 1538 on request 1, then cache_read_input_tokens: 1538 on request 2 — confirming the routing affinity enables cache hits
  4. Full typecheck passed (23/23 packages)

Screenshots / recordings

N/A — backend-only change, no UI impact.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
@songchaow
songchaow force-pushed the feat/x-session-id-header branch from 35e9346 to 9b67f1c Compare June 9, 2026 12:18
Providers like LLM++ (TimiAI) use X-Session-Id to route requests from
the same session to the same upstream account, maximizing KV-Cache hit
rate. Without this header, multi-turn conversations get scattered across
different upstream accounts, causing frequent cache misses.

The header is sent alongside the existing x-session-affinity header for
all non-opencode providers.
@songchaow
songchaow force-pushed the feat/x-session-id-header branch from 9b67f1c to e1e97f4 Compare June 9, 2026 13:24
@rekram1-node

Copy link
Copy Markdown
Collaborator

which providers are requiring this one?

@rekram1-node
rekram1-node merged commit 80c0b06 into anomalyco:dev Jun 9, 2026
8 checks passed
shoootyou added a commit to shoootyou/opencode that referenced this pull request Jun 10, 2026
* test(core): cover skill directory output (anomalyco#31263)

* fix(opencode): avoid duplicate skill catalog (anomalyco#31269)

* chore(opencode): update MCP SDK to 1.29.0 (anomalyco#31268)

* chore: generate

* chore: update nix node_modules hashes

* run: make minimal mode more minimal (anomalyco#31227)

* chore: generate

* chore: update web and desktop code owners (anomalyco#31289)

* fix(desktop): few WSL bugs (anomalyco#31095)

* chore: generate

* fix(opencode): respect MCP server capabilities (anomalyco#31271)

* console: update email

* zen: fix

* fix(opencode): include acp pending tool input (anomalyco#31321)

* fix(lsp): resolve JDTLS root to topmost pom.xml in Java Maven multi-module projects (anomalyco#28761)

Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>

* chore: generate

* fix(session): merge per-call tool rules into session permission (anomalyco#30529)

Co-authored-by: Simon Klee <hello@simonklee.dk>

* docs(go): update MiniMax M3 pricing (anomalyco#31350)

* fix: speed up fff file search (anomalyco#31366)

* chore: generate

* fix(stats): show new for leaderboard deltas

* fix: stabilize fff file results (anomalyco#31369)

* chore: generate

* fix(core): restore npm proxy agent patch (anomalyco#31373)

* chore: update nix node_modules hashes

* chore: upgrade OpenTUI to v0.3.4 (anomalyco#31326)

* chore: update nix node_modules hashes

* fix(core): disable fff trace logs (anomalyco#31380)

* fix(session): avoid sticky prompt tool overrides (anomalyco#31394)

* fix(opencode): await run event loop (anomalyco#31389)

* refactor(core): replace legacy logger with Effect logging (anomalyco#31310)

* chore: generate

* fix(tui): trim select footer action highlight (anomalyco#31411)

* fix(opencode): support MiniMax M3 thinking toggle (anomalyco#31426)

* fix: adjust item id stripping to happen prior to request signing (anomalyco#31429)

* fix(opencode): generate reasoning variants for all OpenRouter models. (anomalyco#30332)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>

* feat(app): add draft tab support to tabs store (anomalyco#31343)

* chore: generate

* fix(opencode): paginate MCP catalogs (anomalyco#31442)

* fix(opencode): pass abort signal to MCP tool calls (anomalyco#31455)

* feat(app): draft prompt state (anomalyco#31452)

* chore: generate

* feat(app): tabs help button (anomalyco#31454)

* feat: add "reasoning" as interleaved field option for vLLM providers (anomalyco#30477)

Co-authored-by: Ben Sandbrook <1126483+delta9000@users.noreply.github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>

* fix(app): clip rounded session panels (anomalyco#31462)

* core: fix idle CPU use in file logger (anomalyco#31478)

* docs: add uninstall troubleshooting steps (anomalyco#31424)

Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>

* leave a breadcrumb comment about batchWindow zero (anomalyco#31508)

* chore: stats -> data

* test(core): avoid Windows worker close race (anomalyco#31532)

* refactor(tui): centralize application exit (anomalyco#31524)

* chore: generate

* feat(opencode): configure Cohere North model (anomalyco#31536)

* refactor(core): consolidate references (anomalyco#31539)

* feat(tui): show project copy in session list (anomalyco#31421)

* chore: generate

* fix(stats): use data branding assets

* drop citation_options from cohere (anomalyco#31543)

* zen: add north mini code model

* fix(data): timestamp formatting

* fix(opencode): support Claude Fable reasoning (anomalyco#31546)

* fix(mcp): log actionable connection statuses (anomalyco#31544)

* refactor(core): simplify location filesystem (anomalyco#31545)

* chore: generate

* chore: update nix node_modules hashes

* fix(opencode): restore effect error logging (anomalyco#31551)

* chore: generate

* feat(opencode): add typed application layer graph (anomalyco#31531)

* zen: add claude fable 5

* chore: generate

* refactor(mcp): simplify service helpers (anomalyco#31549)

* feat: add X-Session-Id header for proxy cache routing affinity (anomalyco#31511)

* zen: update email

* fix(desktop): update Electron stack and panel layout (anomalyco#31571)

* chore: generate

* chore: update nix node_modules hashes

---------

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Simon Klee <hello@simonklee.dk>
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
Co-authored-by: Filip <34747899+neriousy@users.noreply.github.com>
Co-authored-by: Frank <frank@anoma.ly>
Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
Co-authored-by: huangli <areyouok@gmail.com>
Co-authored-by: Tommy D. Rossi <beats.by.morse@gmail.com>
Co-authored-by: Jack <jack@anoma.ly>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: Dax <mail@thdxr.com>
Co-authored-by: James Long <longster@gmail.com>
Co-authored-by: Anthony Lau <anthony.lau2000@live.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Ben Sandbrook <sandbrookvt@gmail.com>
Co-authored-by: Ben Sandbrook <1126483+delta9000@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Sebastian <hasta84@gmail.com>
Co-authored-by: Songchao Wang <songchaow@outlook.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
@songchaow

Copy link
Copy Markdown
Contributor Author

which providers are requiring this one?

Seems to be zenlayer.

@ItsNilDev

Copy link
Copy Markdown

does this also maximize KV-Cache hit rate for deepseek-v4 models?

BYK added a commit to BYK/loreai that referenced this pull request Jun 11, 2026
…#687)

## Summary

Adds first-class support for OpenCode v1.17+'s new `X-Session-Id` header
for deterministic Tier-1 session identification, and simplifies the
vestigial client-type detection code.

## Context

OpenCode v1.17.0
([#31511](anomalyco/opencode#31511)) added an
`X-Session-Id` header alongside the existing `x-session-affinity` header
for proxy setups that need sticky routing. Both carry the same stable
session ID value. The gateway already recognized `x-session-affinity`,
so this was functionally handled — but only through the legacy name.
Adding explicit `x-session-id` recognition future-proofs against
OpenCode dropping the legacy header and supports any other client
adopting the standard name.

## Changes

- **Add `x-session-id` to `KNOWN_SESSION_HEADERS`** (`session.ts`):
ranked above `x-session-affinity` so the standard name wins when both
are present. Intentionally **not** added to `GATEWAY_MANAGED_HEADERS` —
the header is forwarded upstream as designed for sticky cache routing.
- **Fix stale `x-session-affinity` comment**: was described as "nanoid,
volatile — regenerated on restart" which is no longer accurate (current
OpenCode sets it to the stable DB session ID).
- **Replace `detectClientType()` with `isClaudeCodeClient()`**: the
tri-state `ClientType` (`claude-code` / `opencode` / `generic`) was
vestigial — nothing branched on `=== "opencode"`. The only behavioral
question is "is this Claude Code?" (for `max_tokens` sizing), which is
now a simple boolean. Removes the `ClientType` type export entirely.
- **Update tests**: replaced `detectClientType` tests with
`isClaudeCodeClient` tests, including coverage for the new
`x-session-id` header returning false (session identity ≠ client
identity).
isaacfinnegan pushed a commit to isaacfinnegan/whispercode that referenced this pull request Jun 15, 2026
leduyphuc1702 pushed a commit to leduyphuc1702/opencode-workflow that referenced this pull request Jun 16, 2026
markjaquith pushed a commit to markjaquith/opencode that referenced this pull request Jun 23, 2026
BenGu3 pushed a commit to BenGu3/opencode that referenced this pull request Jun 27, 2026
zackslash pushed a commit to zackslash/opencode that referenced this pull request Jun 28, 2026
banlanzs pushed a commit to banlanzs/opencode that referenced this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants