Skip to content

[Feature] Preserve Claude Code /v1/messages payload semantics - #2351

Merged
diegosouzapw merged 4 commits into
cheaper-inference:release/v3.8.0from
terence71-glitch:enhancement/claude-code-payload-passthrough
May 18, 2026
Merged

diegosouzapw merged 4 commits into
cheaper-inference:release/v3.8.0from
terence71-glitch:enhancement/claude-code-payload-passthrough

Conversation

@terence71-glitch

Copy link
Copy Markdown
Contributor

Summary

This implements semantic passthrough for valid Claude Code /v1/messages payloads on direct Claude-Code-style routes:

What changed

  • Added narrow Claude Code semantic passthrough detection for direct Claude-Code paths.
  • Detects Claude Code / Claude CLI requests using indicators such as:
    • claude-code
    • claude-cli
    • x-app: cli
    • x-claude-code-session-id
  • Skips broad normalizeClaudeUpstreamMessages() for verified Claude Code requests on the native claude path.
  • Preserves Claude-native messages[] through the anthropic-compatible-cc-* relay path before required relay-specific transforms.
  • Keeps non-Claude-Code Claude-shaped requests on the existing normalization/repair path.
  • Keeps model resolution, credential selection, native Claude OAuth behavior, compatible relay URL/path/header/signing behavior, and response handling intact.

Why

Claude Code already emits valid Anthropic Messages API payloads for coding tasks, including message ordering, tool-use/tool-result structure, system blocks, cache-control placement, and thinking/context fields.
Broad normalization on direct Claude-Code-style routes can unnecessarily change that structure by:

  • moving role: "system" messages into top-level system
  • removing system messages from messages[]
  • filtering empty text blocks
  • converting file/document-like blocks into text
  • dropping unknown-but-valid content block types
  • changing tool-use/tool-result history shape
    This PR keeps the client-provided messages[] semantics intact for valid native Claude Code traffic while still allowing OmniRoute to perform routing, model resolution, OAuth/account handling, headers/signing, and provider-specific compatibility work.

Scope

This is semantic passthrough, not raw byte-for-byte passthrough.
OmniRoute still parses JSON and may still apply required behavior such as:

  • resolving the final upstream model id
  • selecting credentials/accounts
  • applying native Claude OAuth headers/signing behavior
  • choosing the Claude Code-compatible relay path for anthropic-compatible-cc-*
  • preserving required relay builder behavior
  • performing targeted compatibility work where required
    This does not change general cross-provider translation behavior.

Acceptance criteria covered

  • Valid native Claude Code /v1/messages requests to claude keep messages[] unchanged through chatCore translation.
  • Valid native Claude Code /v1/messages requests to anthropic-compatible-cc-* keep messages[] unchanged before required relay transforms.
  • Non-Claude-Code Claude requests still use existing normalization behavior.
  • Native Claude Code requests still receive the resolved upstream model.
  • Claude Code-compatible relay requests still use the compatible relay builder and /v1/messages?beta=true-style path behavior.
  • Existing OpenAI/Gemini/non-CC translation paths are unaffected.

Tests

node --import tsx --test --test-force-exit tests/unit/chatcore-translation-paths.test.ts tests/unit/claude-code-compatible-request.test.ts tests/unit/chatcore-sanitization.test.ts
Result:
tests 87
pass 87
fail 0
Notes
npm run typecheck:core is currently blocked by pre-existing unrelated errors in open-sse/services/contextManager.ts.

diegosouzapw and others added 3 commits May 17, 2026 14:16
…fix+providers-missing-button-i18n

fix(providers): fix missing i18n keys and add 'Add Provider' button to empty state

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a 'semantic passthrough' mechanism for Claude Code and CLI requests, allowing them to bypass standard message normalization and preserve complex content blocks like documents and tool results. It includes detection logic based on headers and User-Agent strings, updates to the translation service to handle preserved messages, and comprehensive unit tests. A review comment identified an opportunity to optimize performance by removing redundant deep cloning of the messages array during the semantic body preparation.

Comment on lines +828 to +830
messages: Array.isArray(claudeBody.messages)
? (cloneValue(claudeBody.messages) as Array<Record<string, unknown>>)
: [],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The messages array is being deep-cloned twice when preserveClaudeMessages is enabled. First, prepareClaudeCodeCompatibleSemanticBody performs a deep clone of the entire array. Subsequently, cloneClaudeCodeCompatibleMessagesFromClaude (called from buildClaudeCodeCompatibleRequest) iterates over this already-cloned array and performs another deep clone on each individual message object. For large conversation histories typical in Claude Code sessions, this redundant deep cloning can impact performance and memory usage.

Suggested change
messages: Array.isArray(claudeBody.messages)
? (cloneValue(claudeBody.messages) as Array<Record<string, unknown>>)
: [],
messages: Array.isArray(claudeBody.messages)
? (claudeBody.messages as Array<Record<string, unknown>>)
: [],

@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.0 May 18, 2026 00:06
@diegosouzapw
diegosouzapw merged commit db8a2dc into cheaper-inference:release/v3.8.0 May 18, 2026
1 of 2 checks passed
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thank you @terence71-glitch for this excellent contribution! 🎉

Your semantic passthrough implementation is exactly what Claude Code users need — preserving the carefully structured messages[] array (document blocks, tool_use/tool_result chains, cache_control placement) for native Claude-Code routes while keeping the existing normalization path intact for everything else.

The 87-test coverage is outstanding, and the narrowly scoped detection logic (User-Agent + x-app + session-id headers) is clean and robust.

This has been merged into release/v3.8.0 and will ship in the upcoming release. Thanks again for the quality work! 🚀

diegosouzapw added a commit that referenced this pull request May 18, 2026
- feat(claude-code): semantic passthrough (#2351 — thanks @terence71-glitch)
- fix(usage): flat cached_tokens/reasoning_tokens extraction (#2350 — thanks @TF0rd)
diegosouzapw pushed a commit that referenced this pull request May 22, 2026
…assthrough (#2472)

PR #2351 introduced isClaudeCodeSemanticPassthrough to preserve native Claude Code
payloads by skipping normalizeClaudeUpstreamMessages — but that was the only path that
lifted role:"system"/"developer" messages from messages[] to the top-level system
parameter, which Anthropic requires. Memory/system injection was silently 400ing.
Rebased linearly onto the repaired release/v3.8.2; coexists with the Claude passthrough
beta-flag/thinking changes (tests: system-role-extraction 9/9).
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…e#2351)

Integrated into release/v3.8.0 — Claude Code semantic passthrough for /v1/messages payloads
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…nference#2350

- feat(claude-code): semantic passthrough (cheaper-inference#2351 — thanks @terence71-glitch)
- fix(usage): flat cached_tokens/reasoning_tokens extraction (cheaper-inference#2350 — thanks @TF0rd)
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…e#2351)

Integrated into release/v3.8.0 — Claude Code semantic passthrough for /v1/messages payloads
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…nference#2350

- feat(claude-code): semantic passthrough (cheaper-inference#2351 — thanks @terence71-glitch)
- fix(usage): flat cached_tokens/reasoning_tokens extraction (cheaper-inference#2350 — thanks @TF0rd)
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…e#2351)

Integrated into release/v3.8.0 — Claude Code semantic passthrough for /v1/messages payloads
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…nference#2350

- feat(claude-code): semantic passthrough (cheaper-inference#2351 — thanks @terence71-glitch)
- fix(usage): flat cached_tokens/reasoning_tokens extraction (cheaper-inference#2350 — thanks @TF0rd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Preserve Claude Code /v1/messages payload semantics on direct Claude-Code paths

2 participants