Some providers (e.g. Kimi, Anthropic-API mirrors) reject OpenAI-format
chat-completions requests and/or only accept requests from a recognized
coding-agent User-Agent (e.g. Claude Code, Roo Code, Kilo Code). The
OpenAI-compat proxy previously translated every profile's request to
OpenAI format and overwrote the User-Agent with a fixed sentinel,
which made these providers unreachable.
This change adds an opt-in Anthropic passthrough mode:
- New CCS_OPENAI_PROXY_PASSTHROUGH=1 env var on a profile opts it in.
- The base URL is auto-detected as Anthropic-style for known hosts
(api.kimi.com, api.minimax.com, api.anthropic.com) or any base URL
ending in /v1.
- In passthrough mode the proxy forwards the incoming Anthropic body
verbatim to the upstream /v1/messages endpoint, preserving the
original User-Agent (or x-stainless-user-agent) so coding-agent
provider checks pass.
- The Anthropic-format response is streamed back unchanged.
Adds:
- isAnthropicPassthroughProfile() + passthrough option on
resolveOpenAIChatCompletionsUrl/resolveOpenAIModelsUrl
- CCS_OPENAI_PROXY_PASSTHROUGH env var on OpenAICompatProfileConfig
- readRawBody() helper for the passthrough path
- Preserved User-Agent (or x-stainless-user-agent) on the upstream
request, falling back to CCS-OpenAI-Compat-Proxy/1.0
- Skip SSE response transformation in passthrough mode (upstream
already returns Anthropic-format bytes)
Tests:
- 9 new tests in upstream-url.test.ts covering auto-detection and the
passthrough URL contract
- 2 new tests in profile-router.test.ts covering the env var
Verified end-to-end against api.kimi.com: a request through the
modified proxy returned a real Kimi response (model kimi-k2p7-coding)
with the original claude-cli/2.1.170 User-Agent preserved.
- reject pending tool_result layouts that cannot be translated without reordering user content
- keep interleaved GLMT tool_use blocks open until finalization instead of stopping early
- cover leading/interleaved tool_result regressions and interleaved streaming tool fragments
- enforce strict tool_result ordering and pairing against assistant tool_use ids
- reject tool_result image payloads that cannot map to OpenAI tool messages
- preserve raw tool schemas on the /v1/messages proxy path instead of silently tightening them
- forward Anthropic tool_choice semantics and cover adaptive routing plus upstream payload checks