mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 14:01:30 +08:00
hotfix: disable native structured output for AiHubMix/NewAPI Anthropic models (#14376)
<!-- Template from https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?--> <!-- Thanks for sending a pull request! Here are some tips for you: 1. Consider creating this PR as draft: https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md --> <!-- 🚨 Branch Strategy Change (Effective April 3, 2026) 🚨 The `main` branch is now under CODE FREEZE. - main branch: Only accepts critical bug fixes via `hotfix/*` branches. Fix PRs must be minimal in scope and must not include any refactoring code. - v2 branch: All new features, refactoring, and optimizations should be submitted to the `v2` branch. If you are submitting a bug fix to main, please ensure your PR is from a `hotfix/*` branch. --> ### What this PR does Before this PR: sending any request with tools (MCP or otherwise) through the AiHubMix or NewAPI provider using Claude Opus 4.6 / Sonnet 4.6 / Opus 4.5 / Sonnet 4.5 / Haiku 4.5 / Opus 4.1 fails immediately with `invalid_request_error: Unexpected value(s) 'structured-outputs-2025-11-13' for the 'anthropic-beta' header` when the proxy routes the model to a Vertex AI or Bedrock backend. After this PR: `supportsNativeStructuredOutput: false` is passed to `AnthropicMessagesLanguageModel` inside both proxy providers, so `@ai-sdk/anthropic` no longer emits the `structured-outputs-2025-11-13` beta and falls back to function-tool-based structured outputs, which every downstream backend accepts. MCP and plain tool calls work again. Fixes #14375 ### Why we need it and why it was done in this way `@ai-sdk/anthropic` (currently `3.0.64`, same behavior through `3.0.71` and `4.0.0-beta.37`) marks `claude-opus-4-6` / `claude-sonnet-4-6` / `claude-*-4-5` / `claude-opus-4-1` as `supportsStructuredOutput: true` in `getModelCapabilities()`, and unconditionally adds `anthropic-beta: structured-outputs-2025-11-13` whenever tools are attached. That beta is only accepted on the direct Anthropic API. Vertex AI and Bedrock reject it — the issue's `req_vrtx_` request ID confirms the user's AiHubMix account routed the request to Vertex. The SDK only exposes this knob at provider construction time via `supportsNativeStructuredOutput`, not per request. Since AiHubMix and NewAPI are multi-backend proxies — a single Claude model ID can land on Anthropic direct, Vertex, or Bedrock depending on the account — Cherry has no reliable way to pick the right value at call time. Defaulting to `false` unblocks the failing request at the cost of native structured output for `generateObject` / `streamObject`; function-tool fallback is already the legacy path and remains correct. The following tradeoffs were made: - Users of AiHubMix/NewAPI who relied on `generateObject`/`streamObject` native mode will now go through function-tool fallback. MCP tool use (the reported breakage) is unaffected. - Direct Anthropic / Vertex Anthropic / Bedrock providers are untouched. The following alternatives were considered: - Upgrade `@ai-sdk/anthropic`: does not help — `3.0.71` and `4.0.0-beta.37` contain identical logic. - Request-time `providerOptions.anthropic.structuredOutputMode = 'functionTool'`: does not suppress the beta header; `supportsStructuredOutput` and the `structureOutputMode` option are independent code paths in the SDK. - Add a per-provider "backend" config field: correct long-term fix but requires new UI/schema, which is out of scope for a `main`-branch hotfix under code freeze. Tracked as a v2 follow-up issue. Links to places where the discussion took place: #14375 ### Breaking changes None for end users. AiHubMix/NewAPI users invoking `generateObject`/`streamObject` will silently switch to function-tool fallback; outputs remain JSON-schema-valid. ### Special notes for your reviewer The comment in each provider file names the affected model IDs explicitly so future readers understand why the knob is set. The change is confined to two lines of behavior in two files — no refactoring. ### Checklist This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR. Approvers are expected to review this list. - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: [Write code that humans can understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans) and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle) - [x] Refactor: You have [left the code cleaner than you found it (Boy Scout Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [x] Documentation: A [user-guide update](https://docs.cherry-ai.com) was considered and is present (link) or not required. Check this only when the PR introduces or changes a user-facing feature or behavior. - [x] Self-review: I have reviewed my own code (e.g., via [`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`, or GitHub UI) before requesting review from others ### Release note <!-- Write your release note: 1. Enter your extended release note in the below block. If the PR requires additional action from users switching to the new release, include the string "action required". 2. If no release note is required, just write "NONE". 3. Only include user-facing changes (new features, bug fixes visible to users, UI changes, behavior changes). For CI, maintenance, internal refactoring, build tooling, or other non-user-facing work, write "NONE". --> ```release-note Fix invalid_request_error when calling Claude Opus 4.6 / Sonnet 4.6 / 4.5 series / Opus 4.1 with tools (including MCP) through AiHubMix or NewAPI: the `structured-outputs-2025-11-13` beta header is no longer sent, so requests routed to Vertex AI / Bedrock backends succeed. ``` Signed-off-by: suyao <sy20010504@gmail.com>
This commit is contained in:
@@ -61,7 +61,13 @@ export function createAihubmix(options: AihubmixProviderSettings = {}): Aihubmix
|
||||
baseURL,
|
||||
headers: () => ({ ...headers, 'x-api-key': resolveApiKey() }),
|
||||
fetch: customFetch,
|
||||
supportedUrls: () => ({ 'image/*': [/^https?:\/\/.*$/] })
|
||||
supportedUrls: () => ({ 'image/*': [/^https?:\/\/.*$/] }),
|
||||
// AiHubMix may route Claude models to Vertex/Bedrock backends, which reject the
|
||||
// `structured-outputs-2025-11-13` beta header added by @ai-sdk/anthropic for
|
||||
// claude-opus-4-6 / claude-sonnet-4-6 / claude-*-4-5 / claude-opus-4-1. Falling
|
||||
// back to function-tool-based structured outputs keeps tool use (incl. MCP) working
|
||||
// across all downstream backends. See issue #14375.
|
||||
supportsNativeStructuredOutput: false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,13 @@ export function createNewApi(options: NewApiProviderSettings = {}): NewApiProvid
|
||||
baseURL,
|
||||
headers: () => ({ ...headers, 'x-api-key': resolveApiKey() }),
|
||||
fetch: customFetch,
|
||||
supportedUrls: () => ({ 'image/*': [/^https?:\/\/.*$/] })
|
||||
supportedUrls: () => ({ 'image/*': [/^https?:\/\/.*$/] }),
|
||||
// NewAPI may route Claude models to Vertex/Bedrock backends, which reject the
|
||||
// `structured-outputs-2025-11-13` beta header added by @ai-sdk/anthropic for
|
||||
// claude-opus-4-6 / claude-sonnet-4-6 / claude-*-4-5 / claude-opus-4-1. Falling
|
||||
// back to function-tool-based structured outputs keeps tool use (incl. MCP) working
|
||||
// across all downstream backends. See issue #14375.
|
||||
supportsNativeStructuredOutput: false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user