fix(providers): keep thinking on the newest Claude models, fix the Bedrock ids

Measured on Bedrock: Claude Opus 4.7, 4.8 and every Claude 5 model reject
a thinking budget ("thinking.type.enabled") and a temperature, and all of
them accept adaptive thinking. The retry used to drop thinking, so with
a thinking budget set these models did not think at all. It now switches
to adaptive thinking with display "summarized"; without that setting the
models think but send no thinking text to show.

The suggested Bedrock ids had no region prefix, and the newer models only
answer through an inference profile id: "anthropic.claude-sonnet-5-5"
fails with "on-demand throughput isn't supported". Each suggested id was
called once; the Claude ones now start with "global.", Llama, Pixtral and
Nova 2 Lite with "us.". Nova Premier (end of life) and the ids without a
working profile are gone. The docs example had the same problem and a
wrong date.
This commit is contained in:
dayuan.jiang
2026-10-04 21:18:45 +09:00
parent 89a712bca4
commit 65e3dd1dde
6 changed files with 54 additions and 34 deletions
+3 -1
View File
@@ -149,9 +149,11 @@ AZURE_REASONING_SUMMARY=detailed # 可选:none, brief, detailed
AWS_REGION=us-west-2
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AI_MODEL=anthropic.claude-sonnet-4-5-20250514-v1:0
AI_MODEL=global.anthropic.claude-sonnet-5-5
```
较新的 Claude 模型只能通过推理配置文件(inference profile)的 ID 调用,这种 ID 以地区前缀开头,例如 `global.` 或 `us.`。直接用 `anthropic.claude-sonnet-5-5` 这样的 ID 会报错 “on-demand throughput isn't supported”。
注意:在 AWS 环境(Lambda、带有 IAM 角色的 EC2)中,凭证会自动从 IAM 角色获取。
### OpenRouter
+3 -1
View File
@@ -164,9 +164,11 @@ AZURE_REASONING_SUMMARY=detailed # Optional: none, brief, detailed
AWS_REGION=us-west-2
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AI_MODEL=anthropic.claude-sonnet-4-5-20250514-v1:0
AI_MODEL=global.anthropic.claude-sonnet-5-5
```
Recent Claude models answer only through an inference profile id, which starts with a region prefix such as `global.` or `us.`. The plain id (`anthropic.claude-sonnet-5-5`) fails with "on-demand throughput isn't supported".
Note: On AWS (Lambda, EC2 with IAM role), credentials are automatically obtained from the IAM role.
### OpenRouter
+3 -1
View File
@@ -149,9 +149,11 @@ AZURE_REASONING_SUMMARY=detailed # 任意: none, brief, detailed
AWS_REGION=us-west-2
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AI_MODEL=anthropic.claude-sonnet-4-5-20250514-v1:0
AI_MODEL=global.anthropic.claude-sonnet-5-5
```
最近の Claude モデルは、推論プロファイル(inference profile)の ID でのみ呼び出せます。この ID は `global.` や `us.` などのリージョン接頭辞で始まります。`anthropic.claude-sonnet-5-5` のような接頭辞なしの ID では「on-demand throughput isn't supported」というエラーになります。
注: AWS 上(IAM ロールを持つ Lambda や EC2)では、認証情報は IAM ロールから自動的に取得されます。
### OpenRouter
+13 -9
View File
@@ -18,21 +18,25 @@ interface CallParams {
providerOptions?: Record<string, Record<string, unknown> | undefined>
}
/** Drop a thinking config of type "enabled" stored under key, if any. */
function withoutEnabledThinking(
// What these models take instead of a budget. Without display "summarized"
// they think but send no thinking text to show.
const ADAPTIVE_THINKING = { type: "adaptive", display: "summarized" }
/** Turn a thinking config of type "enabled" stored under key into adaptive */
function adaptiveThinking(
options: Record<string, unknown> | undefined,
key: string,
): Record<string, unknown> | undefined {
const config = options?.[key] as { type?: string } | undefined
if (config?.type !== "enabled") return options
const { [key]: _, ...rest } = options as Record<string, unknown>
return rest
return { ...options, [key]: ADAPTIVE_THINKING }
}
/**
* The params without the settings newer Claude models reject, or null when
* the error is about something else or there is nothing to drop. The model
* then runs with its own default sampling and thinking.
* the error is about something else or there is nothing to change. The
* model then runs with its default sampling, and a thinking budget becomes
* adaptive thinking.
*/
export function withoutDeprecatedParams<T extends CallParams>(
error: unknown,
@@ -43,8 +47,8 @@ export function withoutDeprecatedParams<T extends CallParams>(
const { temperature, topP, topK, ...rest } = params
const options = params.providerOptions
const anthropic = withoutEnabledThinking(options?.anthropic, "thinking")
const bedrock = withoutEnabledThinking(options?.bedrock, "reasoningConfig")
const anthropic = adaptiveThinking(options?.anthropic, "thinking")
const bedrock = adaptiveThinking(options?.bedrock, "reasoningConfig")
const changed =
temperature !== undefined ||
topP !== undefined ||
@@ -80,7 +84,7 @@ export function withDeprecatedParamsFallback(
const retry = withoutDeprecatedParams(error, params)
if (!retry) throw error
console.warn(
"[model params] Rejected sampling or thinking settings, retrying with the model defaults",
"[model params] Rejected sampling or thinking settings, retrying with default sampling and adaptive thinking",
)
return await inner.doStream(retry)
}
+21 -18
View File
@@ -347,32 +347,35 @@ export const SUGGESTED_MODELS: Partial<Record<ProviderName, string[]>> = {
"o3",
"o4-mini",
],
// Newer models only answer through an inference profile id (the region
// prefix). Each id here was called once on 2026-10-04.
bedrock: [
// Anthropic Claude
"anthropic.claude-opus-4-8",
"anthropic.claude-opus-4-7",
"anthropic.claude-sonnet-4-6",
"anthropic.claude-opus-4-6-v1",
"anthropic.claude-opus-4-5-20251101-v1:0",
"anthropic.claude-sonnet-4-5-20250929-v1:0",
"anthropic.claude-haiku-4-5-20251001-v1:0",
"anthropic.claude-opus-4-1-20250805-v1:0",
"anthropic.claude-opus-4-20250514-v1:0",
"anthropic.claude-sonnet-4-20250514-v1:0",
"anthropic.claude-3-5-haiku-20241022-v1:0",
// Anthropic Claude ("global." works from any region)
"global.anthropic.claude-opus-5-5",
"global.anthropic.claude-sonnet-5-5",
"global.anthropic.claude-fable-5-1",
"global.anthropic.claude-opus-5",
"global.anthropic.claude-sonnet-5",
"global.anthropic.claude-opus-4-8",
"global.anthropic.claude-opus-4-7",
"global.anthropic.claude-sonnet-4-6",
"global.anthropic.claude-opus-4-6-v1",
"global.anthropic.claude-opus-4-5-20251101-v1:0",
"global.anthropic.claude-sonnet-4-5-20250929-v1:0",
"global.anthropic.claude-haiku-4-5-20251001-v1:0",
"global.anthropic.claude-sonnet-4-20250514-v1:0",
// Amazon Nova
"amazon.nova-2-lite-v1:0",
"amazon.nova-premier-v1:0",
"us.amazon.nova-2-lite-v1:0",
"amazon.nova-pro-v1:0",
"amazon.nova-lite-v1:0",
"amazon.nova-micro-v1:0",
// Meta Llama
"meta.llama4-maverick-17b-instruct-v1:0",
"meta.llama4-scout-17b-instruct-v1:0",
"meta.llama3-3-70b-instruct-v1:0",
"us.meta.llama4-maverick-17b-instruct-v1:0",
"us.meta.llama4-scout-17b-instruct-v1:0",
"us.meta.llama3-3-70b-instruct-v1:0",
// Mistral
"mistral.mistral-large-3-675b-instruct",
"mistral.pixtral-large-2502-v1:0",
"us.mistral.pixtral-large-2502-v1:0",
],
openrouter: [
// Anthropic
+11 -4
View File
@@ -31,18 +31,25 @@ describe("withoutDeprecatedParams", () => {
},
}
it("drops sampling settings and the thinking budget", () => {
// Measured on Bedrock: Opus 4.7, 4.8 and every Claude 5 model accept
// adaptive thinking, and return its text only with display "summarized"
const ADAPTIVE = { type: "adaptive", display: "summarized" }
it("drops sampling settings and switches to adaptive thinking", () => {
for (const error of [TEMPERATURE, THINKING]) {
expect(withoutDeprecatedParams(error, params)).toEqual({
maxOutputTokens: 1000,
providerOptions: {
anthropic: { cacheControl: { type: "ephemeral" } },
anthropic: {
thinking: ADAPTIVE,
cacheControl: { type: "ephemeral" },
},
},
})
}
})
it("drops a Bedrock thinking budget", () => {
it("switches a Bedrock thinking budget to adaptive thinking", () => {
const bedrock = {
providerOptions: {
bedrock: {
@@ -51,7 +58,7 @@ describe("withoutDeprecatedParams", () => {
},
}
expect(withoutDeprecatedParams(THINKING, bedrock)).toEqual({
providerOptions: { bedrock: {} },
providerOptions: { bedrock: { reasoningConfig: ADAPTIVE } },
})
})