@ai-sdk/anthropic 4.0.19 → 4.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.d.ts +17 -4
- package/dist/index.js +177 -70
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal/index.js +176 -69
- package/dist/internal/index.js.map +1 -1
- package/docs/05-anthropic.mdx +79 -2
- package/package.json +1 -1
- package/src/anthropic-api.ts +24 -1
- package/src/anthropic-language-model-options.ts +64 -20
- package/src/anthropic-language-model.ts +56 -4
- package/src/convert-anthropic-usage.ts +8 -2
- package/src/convert-to-anthropic-prompt.ts +64 -12
- package/src/index.ts +1 -0
package/docs/05-anthropic.mdx
CHANGED
|
@@ -175,7 +175,9 @@ const result = streamText({
|
|
|
175
175
|
|
|
176
176
|
### Effort
|
|
177
177
|
|
|
178
|
-
Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7`, `claude-opus-4-8`, `claude-fable-5`, and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
|
|
178
|
+
Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, `claude-fable-5`, and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
|
|
179
|
+
|
|
180
|
+
On `claude-opus-5`, thinking can only be disabled at effort levels up to and including `high`. When you combine `thinking: { type: 'disabled' }` with `effort: 'xhigh'` or `effort: 'max'`, the AI SDK lowers the effort to `high` and emits a warning instead of sending a request that the API would reject.
|
|
179
181
|
|
|
180
182
|
```ts highlight="8-10"
|
|
181
183
|
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
@@ -301,7 +303,26 @@ A classifier block looks like this:
|
|
|
301
303
|
|
|
302
304
|
Branch on the finish reason rather than on the presence of `stop_details` — the API may return a refusal with no details at all.
|
|
303
305
|
|
|
304
|
-
To avoid receiving a classifier block, pass the `fallbacks` option. When the primary model's classifiers block a turn, the API automatically retries it server-side on
|
|
306
|
+
To avoid receiving a classifier block, pass the `fallbacks` option. When the primary model's classifiers block a turn, the API automatically retries it server-side on a fallback model and returns that model's answer. The required beta header is added for you.
|
|
307
|
+
|
|
308
|
+
The recommended configuration is `fallbacks: 'default'`, which lets the API route the retry to Anthropic's recommended fallback model based on the refusal category and removes the need to migrate when a fallback model is deprecated:
|
|
309
|
+
|
|
310
|
+
```ts highlight="8-10"
|
|
311
|
+
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
312
|
+
import { generateText } from 'ai';
|
|
313
|
+
|
|
314
|
+
const { text } = await generateText({
|
|
315
|
+
model: anthropic('claude-fable-5'),
|
|
316
|
+
prompt: 'Explain the history of cryptography.',
|
|
317
|
+
providerOptions: {
|
|
318
|
+
anthropic: {
|
|
319
|
+
fallbacks: 'default',
|
|
320
|
+
} satisfies AnthropicLanguageModelOptions,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
You can also pin an explicit fallback chain:
|
|
305
326
|
|
|
306
327
|
```ts highlight="8-10"
|
|
307
328
|
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
@@ -1187,6 +1208,61 @@ const result = await generateText({
|
|
|
1187
1208
|
|
|
1188
1209
|
This sends `tool_reference` blocks to Anthropic, which loads the corresponding deferred tool schemas into Claude's context.
|
|
1189
1210
|
|
|
1211
|
+
### Mid-Conversation Tool Changes
|
|
1212
|
+
|
|
1213
|
+
With `claude-opus-4-8`, you can add or remove tools between turns of a conversation without invalidating the prompt cache. Attach `toolChanges` to a system message that appears mid-conversation (right before an assistant message or at the end of the messages). The required `mid-conversation-tool-changes-2026-07-01` beta header is added automatically.
|
|
1214
|
+
|
|
1215
|
+
Tools referenced by a `tool_addition` must be declared in the `tools` option — typically with `deferLoading: true`, so they are not loaded into context until the addition surfaces them. A `tool_removal` removes a previously available tool from the conversation going forward.
|
|
1216
|
+
|
|
1217
|
+
```ts
|
|
1218
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
1219
|
+
import { generateText, tool } from 'ai';
|
|
1220
|
+
import { z } from 'zod';
|
|
1221
|
+
|
|
1222
|
+
const result = await generateText({
|
|
1223
|
+
model: anthropic('claude-opus-4-8'),
|
|
1224
|
+
// required for system messages inside `messages`:
|
|
1225
|
+
allowSystemInMessages: true,
|
|
1226
|
+
tools: {
|
|
1227
|
+
get_weather: tool({
|
|
1228
|
+
description: 'Get weather',
|
|
1229
|
+
inputSchema: z.object({ city: z.string() }),
|
|
1230
|
+
}),
|
|
1231
|
+
get_forecast: tool({
|
|
1232
|
+
description: 'Get 5-day forecast',
|
|
1233
|
+
inputSchema: z.object({ city: z.string() }),
|
|
1234
|
+
providerOptions: {
|
|
1235
|
+
// declared up front but not loaded until a tool_addition surfaces it
|
|
1236
|
+
anthropic: { deferLoading: true },
|
|
1237
|
+
},
|
|
1238
|
+
}),
|
|
1239
|
+
},
|
|
1240
|
+
messages: [
|
|
1241
|
+
{ role: 'user', content: 'What tools do you have for weather in Paris?' },
|
|
1242
|
+
{
|
|
1243
|
+
role: 'system',
|
|
1244
|
+
content: '',
|
|
1245
|
+
providerOptions: {
|
|
1246
|
+
anthropic: {
|
|
1247
|
+
toolChanges: [
|
|
1248
|
+
{ type: 'tool_addition', toolName: 'get_forecast' },
|
|
1249
|
+
{ type: 'tool_removal', toolName: 'get_weather' },
|
|
1250
|
+
],
|
|
1251
|
+
},
|
|
1252
|
+
},
|
|
1253
|
+
},
|
|
1254
|
+
],
|
|
1255
|
+
});
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
To change a tool's definition, remove the old definition at the end of one request, then carry the conversation forward with the updated definition in `tools` on the next request.
|
|
1259
|
+
|
|
1260
|
+
<Note>
|
|
1261
|
+
Tool changes are not supported on the initial system message. The AI SDK
|
|
1262
|
+
ignores them there and emits a warning — configure the initial tool set via
|
|
1263
|
+
the `tools` option instead.
|
|
1264
|
+
</Note>
|
|
1265
|
+
|
|
1190
1266
|
### MCP Connectors
|
|
1191
1267
|
|
|
1192
1268
|
Anthropic supports connecting to [MCP servers](https://docs.claude.com/en/docs/agents-and-tools/mcp-connector) as part of their execution.
|
|
@@ -1611,6 +1687,7 @@ and the `mediaType` should be set to `'application/pdf'`.
|
|
|
1611
1687
|
|
|
1612
1688
|
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
|
|
1613
1689
|
| ------------------- | ----------- | ----------------- | ---------- | ------------ | ---------- | ----------- | ---------- |
|
|
1690
|
+
| `claude-opus-5` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1614
1691
|
| `claude-sonnet-5` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1615
1692
|
| `claude-fable-5` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1616
1693
|
| `claude-opus-4-8` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
package/package.json
CHANGED
package/src/anthropic-api.ts
CHANGED
|
@@ -23,7 +23,20 @@ export type AnthropicCacheControl = {
|
|
|
23
23
|
|
|
24
24
|
export interface AnthropicSystemMessage {
|
|
25
25
|
role: 'system';
|
|
26
|
-
content: Array<AnthropicTextContent>;
|
|
26
|
+
content: Array<AnthropicTextContent | AnthropicToolChangeContent>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Mid-conversation tool change content block. Adds or removes a tool from the
|
|
31
|
+
* conversation's tool set without invalidating the prompt cache.
|
|
32
|
+
*
|
|
33
|
+
* Only valid inside system messages that appear in the `messages` array.
|
|
34
|
+
* Requires the `mid-conversation-tool-changes-2026-07-01` beta.
|
|
35
|
+
*/
|
|
36
|
+
export interface AnthropicToolChangeContent {
|
|
37
|
+
type: 'tool_addition' | 'tool_removal';
|
|
38
|
+
tool: { type: 'tool_reference'; name: string };
|
|
39
|
+
cache_control?: never;
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
export interface AnthropicUserMessage {
|
|
@@ -936,6 +949,11 @@ export const anthropicResponseSchema = lazySchema(() =>
|
|
|
936
949
|
usage: z.looseObject({
|
|
937
950
|
input_tokens: z.number(),
|
|
938
951
|
output_tokens: z.number(),
|
|
952
|
+
output_tokens_details: z
|
|
953
|
+
.object({
|
|
954
|
+
thinking_tokens: z.number().nullish(),
|
|
955
|
+
})
|
|
956
|
+
.nullish(),
|
|
939
957
|
cache_creation_input_tokens: z.number().nullish(),
|
|
940
958
|
cache_read_input_tokens: z.number().nullish(),
|
|
941
959
|
iterations: z
|
|
@@ -1414,6 +1432,11 @@ export const anthropicChunkSchema = lazySchema(() =>
|
|
|
1414
1432
|
usage: z.looseObject({
|
|
1415
1433
|
input_tokens: z.number().nullish(),
|
|
1416
1434
|
output_tokens: z.number(),
|
|
1435
|
+
output_tokens_details: z
|
|
1436
|
+
.object({
|
|
1437
|
+
thinking_tokens: z.number().nullish(),
|
|
1438
|
+
})
|
|
1439
|
+
.nullish(),
|
|
1417
1440
|
cache_creation_input_tokens: z.number().nullish(),
|
|
1418
1441
|
cache_read_input_tokens: z.number().nullish(),
|
|
1419
1442
|
iterations: z
|
|
@@ -19,6 +19,7 @@ export type AnthropicModelId =
|
|
|
19
19
|
| 'claude-opus-4-6'
|
|
20
20
|
| 'claude-opus-4-7'
|
|
21
21
|
| 'claude-opus-4-8'
|
|
22
|
+
| 'claude-opus-5'
|
|
22
23
|
| 'claude-fable-5'
|
|
23
24
|
| 'claude-sonnet-5'
|
|
24
25
|
| (string & {});
|
|
@@ -65,6 +66,44 @@ export type AnthropicFilePartProviderOptions = z.infer<
|
|
|
65
66
|
typeof anthropicFilePartProviderOptions
|
|
66
67
|
>;
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Anthropic provider options for system messages.
|
|
71
|
+
*/
|
|
72
|
+
export const anthropicSystemMessageProviderOptions = z.object({
|
|
73
|
+
/**
|
|
74
|
+
* Mid-conversation tool changes. Adds or removes tools from the
|
|
75
|
+
* conversation's tool set between turns without invalidating the prompt
|
|
76
|
+
* cache.
|
|
77
|
+
*
|
|
78
|
+
* Only supported on system messages that appear mid-conversation (not the
|
|
79
|
+
* initial system prompt). A system message carrying tool changes must come
|
|
80
|
+
* right before an assistant message or at the end of the messages.
|
|
81
|
+
*
|
|
82
|
+
* Tools referenced by a `tool_addition` must be declared in the `tools`
|
|
83
|
+
* option (typically with `deferLoading: true` so they are not loaded until
|
|
84
|
+
* the addition surfaces them). The required
|
|
85
|
+
* `mid-conversation-tool-changes-2026-07-01` beta is added automatically.
|
|
86
|
+
*/
|
|
87
|
+
toolChanges: z
|
|
88
|
+
.array(
|
|
89
|
+
z.discriminatedUnion('type', [
|
|
90
|
+
z.object({
|
|
91
|
+
type: z.literal('tool_addition'),
|
|
92
|
+
toolName: z.string(),
|
|
93
|
+
}),
|
|
94
|
+
z.object({
|
|
95
|
+
type: z.literal('tool_removal'),
|
|
96
|
+
toolName: z.string(),
|
|
97
|
+
}),
|
|
98
|
+
]),
|
|
99
|
+
)
|
|
100
|
+
.optional(),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export type AnthropicSystemMessageProviderOptions = z.infer<
|
|
104
|
+
typeof anthropicSystemMessageProviderOptions
|
|
105
|
+
>;
|
|
106
|
+
|
|
68
107
|
export const anthropicLanguageModelOptions = z.object({
|
|
69
108
|
/**
|
|
70
109
|
* Whether to send reasoning to the model.
|
|
@@ -240,31 +279,36 @@ export const anthropicLanguageModelOptions = z.object({
|
|
|
240
279
|
inferenceGeo: z.enum(['us', 'global']).optional(),
|
|
241
280
|
|
|
242
281
|
/**
|
|
243
|
-
* Server-side fallback
|
|
282
|
+
* Server-side fallback configuration.
|
|
244
283
|
*
|
|
245
284
|
* When the primary model's safety classifiers block a turn, the API
|
|
246
|
-
* automatically retries it on
|
|
247
|
-
* `content-filter` finish reason means the
|
|
285
|
+
* automatically retries it server-side on a fallback model. A
|
|
286
|
+
* `content-filter` finish reason means the fallback(s) refused as well.
|
|
248
287
|
*
|
|
249
|
-
*
|
|
250
|
-
* model
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
288
|
+
* - `'default'` (recommended): the API routes the retry to Anthropic's
|
|
289
|
+
* recommended fallback model based on the refusal category. Requires the
|
|
290
|
+
* `server-side-fallback-2026-07-01` beta, which is added automatically.
|
|
291
|
+
* - Array form: an explicit fallback chain. Each entry is merged into the
|
|
292
|
+
* request as a direct request to that entry's model, so it must be
|
|
293
|
+
* formatted accordingly: `model` is required, and an entry may
|
|
294
|
+
* additionally override `max_tokens`, `thinking`, `output_config`, and
|
|
295
|
+
* `speed` for that attempt only (`speed` additionally requires the speed
|
|
296
|
+
* beta). The value is passed through to the API as-is, and the
|
|
297
|
+
* `server-side-fallback-2026-06-01` beta is added automatically.
|
|
257
298
|
*/
|
|
258
299
|
fallbacks: z
|
|
259
|
-
.
|
|
260
|
-
z.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
300
|
+
.union([
|
|
301
|
+
z.literal('default'),
|
|
302
|
+
z.array(
|
|
303
|
+
z.object({
|
|
304
|
+
model: z.string(),
|
|
305
|
+
max_tokens: z.number().int().optional(),
|
|
306
|
+
thinking: z.record(z.string(), z.unknown()).optional(),
|
|
307
|
+
output_config: z.record(z.string(), z.unknown()).optional(),
|
|
308
|
+
speed: z.enum(['fast', 'standard']).optional(),
|
|
309
|
+
}),
|
|
310
|
+
),
|
|
311
|
+
])
|
|
268
312
|
.optional(),
|
|
269
313
|
|
|
270
314
|
/**
|
|
@@ -298,6 +298,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
298
298
|
supportsAdaptiveThinking,
|
|
299
299
|
rejectsSamplingParameters,
|
|
300
300
|
supportsXhighEffort,
|
|
301
|
+
rejectsThinkingDisabledAboveHighEffort,
|
|
301
302
|
isKnownModel,
|
|
302
303
|
} = getModelCapabilities(this.modelId);
|
|
303
304
|
|
|
@@ -443,6 +444,25 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
443
444
|
}
|
|
444
445
|
}
|
|
445
446
|
|
|
447
|
+
// Newer models only allow disabling thinking at effort levels up to and
|
|
448
|
+
// including `high`; at `xhigh` and `max` the API returns a 400. Lower
|
|
449
|
+
// the effort to `high` to preserve the explicit request to run without
|
|
450
|
+
// thinking.
|
|
451
|
+
if (
|
|
452
|
+
rejectsThinkingDisabledAboveHighEffort &&
|
|
453
|
+
anthropicOptions?.thinking?.type === 'disabled' &&
|
|
454
|
+
(anthropicOptions.effort === 'xhigh' || anthropicOptions.effort === 'max')
|
|
455
|
+
) {
|
|
456
|
+
warnings.push({
|
|
457
|
+
type: 'unsupported',
|
|
458
|
+
feature: 'providerOptions.anthropic.effort',
|
|
459
|
+
details:
|
|
460
|
+
`effort '${anthropicOptions.effort}' is not supported by ${this.modelId} when thinking is disabled. ` +
|
|
461
|
+
`The effort has been lowered to 'high'.`,
|
|
462
|
+
});
|
|
463
|
+
anthropicOptions.effort = 'high';
|
|
464
|
+
}
|
|
465
|
+
|
|
446
466
|
const thinkingType = anthropicOptions?.thinking?.type;
|
|
447
467
|
const isThinking =
|
|
448
468
|
thinkingType === 'enabled' || thinkingType === 'adaptive';
|
|
@@ -514,8 +534,9 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
514
534
|
...(anthropicOptions?.inferenceGeo && {
|
|
515
535
|
inference_geo: anthropicOptions.inferenceGeo,
|
|
516
536
|
}),
|
|
517
|
-
...(anthropicOptions?.fallbacks &&
|
|
518
|
-
anthropicOptions.fallbacks
|
|
537
|
+
...(anthropicOptions?.fallbacks != null &&
|
|
538
|
+
(anthropicOptions.fallbacks === 'default' ||
|
|
539
|
+
anthropicOptions.fallbacks.length > 0) && {
|
|
519
540
|
fallbacks: anthropicOptions.fallbacks,
|
|
520
541
|
}),
|
|
521
542
|
...(anthropicOptions?.cacheControl && {
|
|
@@ -750,7 +771,12 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
750
771
|
betas.add('fast-mode-2026-02-01');
|
|
751
772
|
}
|
|
752
773
|
|
|
753
|
-
if (anthropicOptions?.fallbacks
|
|
774
|
+
if (anthropicOptions?.fallbacks === 'default') {
|
|
775
|
+
betas.add('server-side-fallback-2026-07-01');
|
|
776
|
+
} else if (
|
|
777
|
+
anthropicOptions?.fallbacks &&
|
|
778
|
+
anthropicOptions.fallbacks.length > 0
|
|
779
|
+
) {
|
|
754
780
|
betas.add('server-side-fallback-2026-06-01');
|
|
755
781
|
}
|
|
756
782
|
|
|
@@ -2478,6 +2504,9 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
2478
2504
|
usage.input_tokens = value.usage.input_tokens;
|
|
2479
2505
|
}
|
|
2480
2506
|
usage.output_tokens = value.usage.output_tokens;
|
|
2507
|
+
if (value.usage.output_tokens_details != null) {
|
|
2508
|
+
usage.output_tokens_details = value.usage.output_tokens_details;
|
|
2509
|
+
}
|
|
2481
2510
|
|
|
2482
2511
|
if (value.usage.cache_read_input_tokens != null) {
|
|
2483
2512
|
usage.cache_read_input_tokens =
|
|
@@ -2650,9 +2679,20 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2650
2679
|
supportsAdaptiveThinking: boolean;
|
|
2651
2680
|
rejectsSamplingParameters: boolean;
|
|
2652
2681
|
supportsXhighEffort: boolean;
|
|
2682
|
+
rejectsThinkingDisabledAboveHighEffort: boolean;
|
|
2653
2683
|
isKnownModel: boolean;
|
|
2654
2684
|
} {
|
|
2655
|
-
if (
|
|
2685
|
+
if (modelId.includes('claude-opus-5')) {
|
|
2686
|
+
return {
|
|
2687
|
+
maxOutputTokens: 128000,
|
|
2688
|
+
supportsStructuredOutput: true,
|
|
2689
|
+
supportsAdaptiveThinking: true,
|
|
2690
|
+
rejectsSamplingParameters: true,
|
|
2691
|
+
supportsXhighEffort: true,
|
|
2692
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2693
|
+
isKnownModel: true,
|
|
2694
|
+
};
|
|
2695
|
+
} else if (
|
|
2656
2696
|
modelId.includes('claude-opus-4-8') ||
|
|
2657
2697
|
modelId.includes('claude-opus-4-7') ||
|
|
2658
2698
|
modelId.includes('claude-fable-5') ||
|
|
@@ -2664,6 +2704,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2664
2704
|
supportsAdaptiveThinking: true,
|
|
2665
2705
|
rejectsSamplingParameters: true,
|
|
2666
2706
|
supportsXhighEffort: true,
|
|
2707
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2667
2708
|
isKnownModel: true,
|
|
2668
2709
|
};
|
|
2669
2710
|
} else if (
|
|
@@ -2676,6 +2717,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2676
2717
|
supportsAdaptiveThinking: true,
|
|
2677
2718
|
rejectsSamplingParameters: false,
|
|
2678
2719
|
supportsXhighEffort: false,
|
|
2720
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2679
2721
|
isKnownModel: true,
|
|
2680
2722
|
};
|
|
2681
2723
|
} else if (
|
|
@@ -2689,6 +2731,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2689
2731
|
supportsAdaptiveThinking: false,
|
|
2690
2732
|
rejectsSamplingParameters: false,
|
|
2691
2733
|
supportsXhighEffort: false,
|
|
2734
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2692
2735
|
isKnownModel: true,
|
|
2693
2736
|
};
|
|
2694
2737
|
} else if (modelId.includes('claude-opus-4-1')) {
|
|
@@ -2698,6 +2741,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2698
2741
|
supportsAdaptiveThinking: false,
|
|
2699
2742
|
rejectsSamplingParameters: false,
|
|
2700
2743
|
supportsXhighEffort: false,
|
|
2744
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2701
2745
|
isKnownModel: true,
|
|
2702
2746
|
};
|
|
2703
2747
|
} else if (modelId.includes('claude-sonnet-4-')) {
|
|
@@ -2707,6 +2751,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2707
2751
|
supportsAdaptiveThinking: false,
|
|
2708
2752
|
rejectsSamplingParameters: false,
|
|
2709
2753
|
supportsXhighEffort: false,
|
|
2754
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2710
2755
|
isKnownModel: true,
|
|
2711
2756
|
};
|
|
2712
2757
|
} else if (modelId.includes('claude-opus-4-')) {
|
|
@@ -2716,6 +2761,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2716
2761
|
supportsAdaptiveThinking: false,
|
|
2717
2762
|
rejectsSamplingParameters: false,
|
|
2718
2763
|
supportsXhighEffort: false,
|
|
2764
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2719
2765
|
isKnownModel: true,
|
|
2720
2766
|
};
|
|
2721
2767
|
} else if (modelId.includes('claude-3-haiku')) {
|
|
@@ -2725,6 +2771,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2725
2771
|
supportsAdaptiveThinking: false,
|
|
2726
2772
|
rejectsSamplingParameters: false,
|
|
2727
2773
|
supportsXhighEffort: false,
|
|
2774
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2728
2775
|
isKnownModel: true,
|
|
2729
2776
|
};
|
|
2730
2777
|
} else if (
|
|
@@ -2736,6 +2783,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2736
2783
|
supportsAdaptiveThinking: false,
|
|
2737
2784
|
rejectsSamplingParameters: false,
|
|
2738
2785
|
supportsXhighEffort: false,
|
|
2786
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2739
2787
|
isKnownModel: false,
|
|
2740
2788
|
};
|
|
2741
2789
|
} else if (modelId.includes('claude-')) {
|
|
@@ -2748,15 +2796,19 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2748
2796
|
supportsAdaptiveThinking: true,
|
|
2749
2797
|
rejectsSamplingParameters: true,
|
|
2750
2798
|
supportsXhighEffort: true,
|
|
2799
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2751
2800
|
isKnownModel: false,
|
|
2752
2801
|
};
|
|
2753
2802
|
} else {
|
|
2803
|
+
// Non-Claude models (e.g. served through Anthropic-compatible APIs)
|
|
2804
|
+
// keep conservative defaults.
|
|
2754
2805
|
return {
|
|
2755
2806
|
maxOutputTokens: 4096,
|
|
2756
2807
|
supportsStructuredOutput: false,
|
|
2757
2808
|
supportsAdaptiveThinking: false,
|
|
2758
2809
|
rejectsSamplingParameters: false,
|
|
2759
2810
|
supportsXhighEffort: false,
|
|
2811
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2760
2812
|
isKnownModel: false,
|
|
2761
2813
|
};
|
|
2762
2814
|
}
|
|
@@ -28,6 +28,9 @@ export type AnthropicUsageIteration = {
|
|
|
28
28
|
export type AnthropicUsage = {
|
|
29
29
|
input_tokens: number;
|
|
30
30
|
output_tokens: number;
|
|
31
|
+
output_tokens_details?: {
|
|
32
|
+
thinking_tokens?: number | null;
|
|
33
|
+
} | null;
|
|
31
34
|
cache_creation_input_tokens?: number | null;
|
|
32
35
|
cache_read_input_tokens?: number | null;
|
|
33
36
|
/**
|
|
@@ -50,6 +53,8 @@ export function convertAnthropicUsage({
|
|
|
50
53
|
}): LanguageModelV4Usage {
|
|
51
54
|
const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
|
|
52
55
|
const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
|
|
56
|
+
const reasoningTokens =
|
|
57
|
+
usage.output_tokens_details?.thinking_tokens ?? undefined;
|
|
53
58
|
|
|
54
59
|
// When iterations is present (compaction or advisor), sum across executor
|
|
55
60
|
// iterations to get the true executor totals. The top-level input_tokens
|
|
@@ -101,8 +106,9 @@ export function convertAnthropicUsage({
|
|
|
101
106
|
},
|
|
102
107
|
outputTokens: {
|
|
103
108
|
total: outputTokens,
|
|
104
|
-
text:
|
|
105
|
-
|
|
109
|
+
text:
|
|
110
|
+
reasoningTokens == null ? undefined : outputTokens - reasoningTokens,
|
|
111
|
+
reasoning: reasoningTokens,
|
|
106
112
|
},
|
|
107
113
|
raw: rawUsage ?? usage,
|
|
108
114
|
};
|
|
@@ -23,12 +23,18 @@ import {
|
|
|
23
23
|
anthropicReasoningMetadataSchema,
|
|
24
24
|
type AnthropicAssistantMessage,
|
|
25
25
|
type AnthropicPrompt,
|
|
26
|
+
type AnthropicSystemMessage,
|
|
27
|
+
type AnthropicTextContent,
|
|
28
|
+
type AnthropicToolChangeContent,
|
|
26
29
|
type AnthropicToolResultContent,
|
|
27
30
|
type AnthropicUserMessage,
|
|
28
31
|
type AnthropicWebFetchToolResultContent,
|
|
29
32
|
type Citation,
|
|
30
33
|
} from './anthropic-api';
|
|
31
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
anthropicFilePartProviderOptions,
|
|
36
|
+
anthropicSystemMessageProviderOptions,
|
|
37
|
+
} from './anthropic-language-model-options';
|
|
32
38
|
import { CacheControlValidator } from './get-cache-control';
|
|
33
39
|
import { advisor_20260301OutputSchema } from './tool/advisor_20260301';
|
|
34
40
|
import { codeExecution_20250522OutputSchema } from './tool/code-execution_20250522';
|
|
@@ -137,20 +143,66 @@ export async function convertToAnthropicPrompt({
|
|
|
137
143
|
|
|
138
144
|
switch (type) {
|
|
139
145
|
case 'system': {
|
|
140
|
-
const content
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
const content: AnthropicSystemMessage['content'] = [];
|
|
147
|
+
let toolChangeCount = 0;
|
|
148
|
+
|
|
149
|
+
for (const { content: text, providerOptions } of block.messages) {
|
|
150
|
+
const systemMessageOptions = await parseProviderOptions({
|
|
151
|
+
provider: 'anthropic',
|
|
152
|
+
providerOptions,
|
|
153
|
+
schema: anthropicSystemMessageProviderOptions,
|
|
154
|
+
});
|
|
155
|
+
const toolChanges = systemMessageOptions?.toolChanges ?? [];
|
|
156
|
+
|
|
157
|
+
// A system message that only carries tool changes may have empty
|
|
158
|
+
// text; do not emit an empty text block for it.
|
|
159
|
+
if (text !== '' || toolChanges.length === 0) {
|
|
160
|
+
content.push({
|
|
161
|
+
type: 'text' as const,
|
|
162
|
+
text,
|
|
163
|
+
cache_control: validator.getCacheControl(providerOptions, {
|
|
164
|
+
type: 'system message',
|
|
165
|
+
canCache: true,
|
|
166
|
+
}),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const toolChange of toolChanges) {
|
|
171
|
+
toolChangeCount++;
|
|
172
|
+
content.push({
|
|
173
|
+
type: toolChange.type,
|
|
174
|
+
tool: {
|
|
175
|
+
type: 'tool_reference',
|
|
176
|
+
name: toolNameMapping.toProviderToolName(toolChange.toolName),
|
|
177
|
+
},
|
|
178
|
+
} satisfies AnthropicToolChangeContent);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// The first block becomes the top-level system prompt. Later system
|
|
183
|
+
// blocks are sent as inline system messages — always when they carry
|
|
184
|
+
// tool changes (which are only valid mid-conversation), and otherwise
|
|
185
|
+
// only when a top-level system prompt already exists (preserving the
|
|
186
|
+
// existing hoisting behavior for plain text).
|
|
187
|
+
if (i === 0 || (system == null && toolChangeCount === 0)) {
|
|
188
|
+
if (toolChangeCount > 0) {
|
|
189
|
+
warnings.push({
|
|
190
|
+
type: 'other',
|
|
191
|
+
message:
|
|
192
|
+
'tool changes on the initial system message are not supported by Anthropic. ' +
|
|
193
|
+
'Configure the initial tool set via the tools option instead. ' +
|
|
194
|
+
'The tool changes have been ignored.',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
system = content.filter(
|
|
198
|
+
(part): part is AnthropicTextContent => part.type === 'text',
|
|
199
|
+
);
|
|
151
200
|
} else {
|
|
152
201
|
messages.push({ role: 'system', content });
|
|
153
202
|
betas.add('mid-conversation-system-2026-04-07');
|
|
203
|
+
if (toolChangeCount > 0) {
|
|
204
|
+
betas.add('mid-conversation-tool-changes-2026-07-01');
|
|
205
|
+
}
|
|
154
206
|
}
|
|
155
207
|
|
|
156
208
|
break;
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type {
|
|
|
6
6
|
AnthropicLanguageModelOptions,
|
|
7
7
|
/** @deprecated Use `AnthropicLanguageModelOptions` instead. */
|
|
8
8
|
AnthropicLanguageModelOptions as AnthropicProviderOptions,
|
|
9
|
+
AnthropicSystemMessageProviderOptions,
|
|
9
10
|
} from './anthropic-language-model-options';
|
|
10
11
|
export type { AnthropicToolOptions } from './anthropic-prepare-tools';
|
|
11
12
|
export { anthropic, createAnthropic } from './anthropic-provider';
|