fix(cliproxyapi): detect Anthropic shape on minimal Capy bodies - #2192
Conversation
Discovered post-deploy: simple Capy /v1/messages requests (string content, no system block) were misdetected as OpenAI-shape and routed to /v1/chat/completions instead of /v1/messages. CPA then responded with chat.completion shape, leaking OpenAI shape to Anthropic SDK clients and skipping the Anthropic CC wire-image cloak. Strengthen isAnthropicShape with two more strong signals (any one is decisive): - top-level `thinking` field (Anthropic-only; OpenAI uses `reasoning`) - top-level `metadata.user_id` (CC wire-image OAuth identifier) These survive even on minimal bodies where messages[0].content is a string and no system block is present. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request updates the CliproxyapiExecutor to improve the detection of Anthropic-specific request bodies by checking for the thinking field and metadata.user_id. The unit tests have been updated to ensure that OpenAI-shaped bodies, including those with reasoning_effort, are correctly handled. I have no feedback to provide.
|
Update after 2026-05-12 empirical bisect (11 variants × 2 turns + 5-turn stress against live Anthropic via CPA cloak): The detection improvements in this PR ( I'm closing the companion PRs that targeted the strip side-effects of this detection (#2194 mcp_ prose rewrite, #2195 metadata strip): the bisect confirmed Anthropic accepts those fields intact through the CPA cloak, so the strips were over-engineered preemptive defense that silently dropped valid client content. The detection itself (this PR) is orthogonal and stands. The fork-side cleanup is in NomenAK/OmniRoute@cleanup/remove-over-engineered-strips (commits 4e9e534, 3166060, 4bb93c5) — keeping this PR open as-is for the detection signals. |
|
Thanks @NomenAK for the focused ClipProxyAPI fix. I synced the PR branch with release/v3.8.0, validated tests/unit/cliproxyapi-executor.test.ts locally, and will include this in the upcoming release. |
…osouzapw#2192) Integrated into release/v3.8.0 after syncing the contributor branch and validating tests/unit/cliproxyapi-executor.test.ts locally.
…osouzapw#2192) Integrated into release/v3.8.0 after syncing the contributor branch and validating tests/unit/cliproxyapi-executor.test.ts locally.
Summary
isAnthropicShapein the CliProxyApi executor missed minimal Anthropic bodies (messages[0].contentas a plain string, nosystemblock) and routed them to/v1/chat/completionsinstead of/v1/messages. The downstream symptom was Anthropic SDK clients receiving an OpenAI Chat Completions response shape and failing to parse.Strengthen the detector with two more strong signals — top-level
thinkingfield and top-levelmetadata.user_id— so the minimal-body case is also recognized.Related Issues
Motivation
#2165introduced the Anthropic-shape detector that routes Capy and other Claude SDK clients to CPA's/v1/messages. The detector required either :body.system !== undefined— Anthropic-only fieldmessages[0].contentis array — Anthropic content-block shapeCaptured artifact for a minimal
/v1/messagesCapy call :body.system: absent ✗ (Capy omits when no system prompt)messages[0].content: string ✗ (Anthropic allows both string and array per API docs)Both indicators miss. Executor routes to
/v1/chat/completions→ CPA returns OpenAI Chat Completions shape → Anthropic SDK client seeschoices[]instead ofcontent[]and either drops the response or surfaces a parse error.Changes
open-sse/executors/cliproxyapi.ts—isAnthropicShapeadds two strong indicators :Both are decisive ; either alone routes to
/v1/messages.Validation
chat.completionshape ; post-fix returns proper Anthropic shape withcontent: [{type:'text', text:'…'}].it("does not strip OpenAI-shape bodies (no thinking, no system, string content)")— confirms genuine OpenAI bodies still skip the Anthropic strips when no Anthropic indicators are present.🤖 Generated with Claude Code