Skip to content

Translator patches: reasoning fallback + cache_control strip (sc-988867)#1

Merged
sash merged 3 commits into
mainfrom
feature/sc-988867-translator-patches
May 18, 2026
Merged

Translator patches: reasoning fallback + cache_control strip (sc-988867)#1
sash merged 3 commits into
mainfrom
feature/sc-988867-translator-patches

Conversation

@sash
Copy link
Copy Markdown

@sash sash commented May 18, 2026

Summary

First ampeco-specific commit series on this fork. Closes two OpenRouter protocol-translation gaps surfaced during the 2026-05-15 validation of story #988867 (centralized CLIProxyAPI on mm007 — fleet-wide Claude account pool).

Both patches are strict-additive: each only fires when its condition is met, so providers that don't trigger it are unaffected.

Patch series

Patch 1 — reasoning field fallback (commit 496152ee)

internal/translator/openai/claude/openai_claude_response.go — three call sites (streaming chunk, non-stream helper, exported non-stream entry).

OpenRouter emits the reasoning field as reasoning; upstream only looks for reasoning_content. Result: reasoning blocks silently disappear from all OpenRouter-backed providers (kimi, qwen, glm, deepseek, minimax, ...). Patch: when reasoning_content is empty/absent, fall back to reasoning. When both are present, reasoning_content still wins.

Patch 2 — strip cache_control markers (commit 944e6739)

internal/translator/openai/claude/openai_claude_request.go — new stripCacheControl helper invoked at the top of ConvertClaudeRequestToOpenAI.

Anthropic clients embed cache_control (prompt caching) on messages[].content[], system[], and tools[]. Upstream's Claude→OpenAI request translator has no defined handling; OpenAI-compatible providers either ignore the field silently or may reject the request. Mirrors CCR's OpenrouterTransformer (lines 17-29).

README (commit 5b14d12f)

Adds a fork-specific section at the top describing why the fork exists, the patch series, test coverage, the monthly intentional-rebase cadence, and escalation options.

Test plan

  • go test ./internal/translator/openai/claude/... passes (new tests + existing tests).
  • go test ./... passes for every package that this PR touches.
  • Pre-existing TestUpdateAntigravityCreditsBalance_LoadCodeAssistUserAgent failure on upstream main is unrelated to this PR (verified by stashing the patches and running the same test against unmodified upstream/main).
  • Strict-additive property covered: reasoning_content still wins when both fields are present (negative test).
  • stripCacheControl is idempotent and a no-op on clean input (TestStripCacheControl_IsIdempotent).

Implementation note (file path)

The implementation plan for sc-988867 referenced internal/translator/claude/openai/chat-completions/claude_openai_request.go for Patch 2. That file actually handles the opposite direction (OpenAI→Claude); the correct file for stripping cache_control on the Claude→OpenAI path is internal/translator/openai/claude/openai_claude_request.go. Verified via the translator.Register(<source>, <destination>, ...) calls in each package's init.go. The fix is in the correct file in this PR.

🤖 Generated with Claude Code

Alexander (SASh) Alexiev (AI Bot) added 3 commits May 18, 2026 15:44
…s empty (ampeco fork)

Upstream's OpenAI->Claude response translator looks only at `reasoning_content`,
but OpenRouter emits the field as `reasoning`. As a result, reasoning blocks from
every OpenRouter-backed provider (kimi, qwen, glm, deepseek, minimax, ...) are
silently dropped and never surface as Anthropic `thinking` blocks.

Add a fallback at all three call sites (streaming chunk converter, non-stream
helper, exported non-stream entry point): when `reasoning_content` is empty or
absent, use `reasoning` instead. Strict-additive — when both fields are present,
`reasoning_content` still wins, so providers that emit it (OpenAI o-series,
DeepSeek direct) are unaffected.

Cover all three sites and the strict-additive property in
`TestConvertOpenAIResponseToClaude_ReasoningFallback`.

Refs: AMPECO story sc-988867
…OpenAI (ampeco fork)

Anthropic clients embed `cache_control` markers (used for Anthropic prompt
caching) on `messages[].content[]`, `system[]`, and `tools[]`. Upstream's
Claude->OpenAI request translator has no defined handling for the field; OpenAI-
compatible providers either ignore it silently or may reject the request.

Add a `stripCacheControl` helper invoked at the top of
`ConvertClaudeRequestToOpenAI` that deletes `cache_control` from every location
where it can appear in a Claude request. Mirrors CCR's `OpenrouterTransformer`
(lines 17-29). Applied universally because the field has no valid meaning on the
Claude->OpenAI path — only deletes when the field is present, so providers
without it are unaffected.

Covered by `TestConvertClaudeRequestToOpenAI_StripsCacheControl` (all four
locations), `TestConvertClaudeRequestToOpenAI_PreservesContentWhenStrippingCacheControl`
(surrounding content survives), and `TestStripCacheControl_IsIdempotent`.

Refs: AMPECO story sc-988867
…cadence

Add a fork-specific section at the top of the README describing:
- Why the fork exists (validated 2026-05-15: two OpenRouter protocol-translation
  gaps surfaced; both closed by the patches in this commit series)
- Patch 1: `reasoning` fallback in OpenAI->Claude response translator
- Patch 2: `cache_control` stripping in Claude->OpenAI request translator
- Test coverage for both patches
- Monthly intentional-rebase cadence against upstream
- Escalation options if rebase cost grows

Refs: AMPECO story sc-988867
@sash sash merged commit 52d10b0 into main May 18, 2026
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.

1 participant