@ai-sdk/anthropic 3.0.101 → 3.0.103
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.mts +17 -4
- package/dist/index.d.ts +17 -4
- package/dist/index.js +174 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -69
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +2 -1
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal/index.js +173 -68
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +173 -68
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +79 -2
- package/package.json +1 -1
- package/src/anthropic-messages-api.ts +24 -1
- package/src/anthropic-messages-language-model.ts +54 -4
- package/src/anthropic-messages-options.ts +64 -20
- package/src/convert-anthropic-messages-usage.ts +8 -2
- package/src/convert-to-anthropic-messages-prompt.ts +64 -12
- package/src/index.ts +1 -0
package/docs/05-anthropic.mdx
CHANGED
|
@@ -191,7 +191,9 @@ const result = streamText({
|
|
|
191
191
|
|
|
192
192
|
### Effort
|
|
193
193
|
|
|
194
|
-
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` and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
|
|
194
|
+
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-5`, and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
|
|
195
|
+
|
|
196
|
+
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.
|
|
195
197
|
|
|
196
198
|
```ts highlight="8-10"
|
|
197
199
|
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
@@ -317,7 +319,26 @@ A classifier block looks like this:
|
|
|
317
319
|
|
|
318
320
|
Branch on the finish reason rather than on the presence of `stop_details` — the API may return a refusal with no details at all.
|
|
319
321
|
|
|
320
|
-
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
|
|
322
|
+
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.
|
|
323
|
+
|
|
324
|
+
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:
|
|
325
|
+
|
|
326
|
+
```ts highlight="8-10"
|
|
327
|
+
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
328
|
+
import { generateText } from 'ai';
|
|
329
|
+
|
|
330
|
+
const { text } = await generateText({
|
|
331
|
+
model: anthropic('claude-fable-5'),
|
|
332
|
+
prompt: 'Explain the history of cryptography.',
|
|
333
|
+
providerOptions: {
|
|
334
|
+
anthropic: {
|
|
335
|
+
fallbacks: 'default',
|
|
336
|
+
} satisfies AnthropicLanguageModelOptions,
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
You can also pin an explicit fallback chain:
|
|
321
342
|
|
|
322
343
|
```ts highlight="8-10"
|
|
323
344
|
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
@@ -1177,6 +1198,61 @@ const result = await generateText({
|
|
|
1177
1198
|
|
|
1178
1199
|
This sends `tool_reference` blocks to Anthropic, which loads the corresponding deferred tool schemas into Claude's context.
|
|
1179
1200
|
|
|
1201
|
+
### Mid-Conversation Tool Changes
|
|
1202
|
+
|
|
1203
|
+
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.
|
|
1204
|
+
|
|
1205
|
+
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.
|
|
1206
|
+
|
|
1207
|
+
```ts
|
|
1208
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
1209
|
+
import { generateText, tool } from 'ai';
|
|
1210
|
+
import { z } from 'zod';
|
|
1211
|
+
|
|
1212
|
+
const result = await generateText({
|
|
1213
|
+
model: anthropic('claude-opus-4-8'),
|
|
1214
|
+
// required for system messages inside `messages`:
|
|
1215
|
+
allowSystemInMessages: true,
|
|
1216
|
+
tools: {
|
|
1217
|
+
get_weather: tool({
|
|
1218
|
+
description: 'Get weather',
|
|
1219
|
+
inputSchema: z.object({ city: z.string() }),
|
|
1220
|
+
}),
|
|
1221
|
+
get_forecast: tool({
|
|
1222
|
+
description: 'Get 5-day forecast',
|
|
1223
|
+
inputSchema: z.object({ city: z.string() }),
|
|
1224
|
+
providerOptions: {
|
|
1225
|
+
// declared up front but not loaded until a tool_addition surfaces it
|
|
1226
|
+
anthropic: { deferLoading: true },
|
|
1227
|
+
},
|
|
1228
|
+
}),
|
|
1229
|
+
},
|
|
1230
|
+
messages: [
|
|
1231
|
+
{ role: 'user', content: 'What tools do you have for weather in Paris?' },
|
|
1232
|
+
{
|
|
1233
|
+
role: 'system',
|
|
1234
|
+
content: '',
|
|
1235
|
+
providerOptions: {
|
|
1236
|
+
anthropic: {
|
|
1237
|
+
toolChanges: [
|
|
1238
|
+
{ type: 'tool_addition', toolName: 'get_forecast' },
|
|
1239
|
+
{ type: 'tool_removal', toolName: 'get_weather' },
|
|
1240
|
+
],
|
|
1241
|
+
},
|
|
1242
|
+
},
|
|
1243
|
+
},
|
|
1244
|
+
],
|
|
1245
|
+
});
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
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.
|
|
1249
|
+
|
|
1250
|
+
<Note>
|
|
1251
|
+
Tool changes are not supported on the initial system message. The AI SDK
|
|
1252
|
+
ignores them there and emits a warning — configure the initial tool set via
|
|
1253
|
+
the `tools` option instead.
|
|
1254
|
+
</Note>
|
|
1255
|
+
|
|
1180
1256
|
### MCP Connectors
|
|
1181
1257
|
|
|
1182
1258
|
Anthropic supports connecting to [MCP servers](https://docs.claude.com/en/docs/agents-and-tools/mcp-connector) as part of their execution.
|
|
@@ -1559,6 +1635,7 @@ and the `mediaType` should be set to `'application/pdf'`.
|
|
|
1559
1635
|
|
|
1560
1636
|
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
|
|
1561
1637
|
| ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
1638
|
+
| `claude-opus-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1562
1639
|
| `claude-sonnet-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1563
1640
|
| `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1564
1641
|
| `claude-opus-4-8` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
package/package.json
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 {
|
|
@@ -925,6 +938,11 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
925
938
|
usage: z.looseObject({
|
|
926
939
|
input_tokens: z.number(),
|
|
927
940
|
output_tokens: z.number(),
|
|
941
|
+
output_tokens_details: z
|
|
942
|
+
.object({
|
|
943
|
+
thinking_tokens: z.number().nullish(),
|
|
944
|
+
})
|
|
945
|
+
.nullish(),
|
|
928
946
|
cache_creation_input_tokens: z.number().nullish(),
|
|
929
947
|
cache_read_input_tokens: z.number().nullish(),
|
|
930
948
|
iterations: z
|
|
@@ -1403,6 +1421,11 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1403
1421
|
usage: z.looseObject({
|
|
1404
1422
|
input_tokens: z.number().nullish(),
|
|
1405
1423
|
output_tokens: z.number(),
|
|
1424
|
+
output_tokens_details: z
|
|
1425
|
+
.object({
|
|
1426
|
+
thinking_tokens: z.number().nullish(),
|
|
1427
|
+
})
|
|
1428
|
+
.nullish(),
|
|
1406
1429
|
cache_creation_input_tokens: z.number().nullish(),
|
|
1407
1430
|
cache_read_input_tokens: z.number().nullish(),
|
|
1408
1431
|
iterations: z
|
|
@@ -276,6 +276,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
276
276
|
maxOutputTokens: maxOutputTokensForModel,
|
|
277
277
|
supportsStructuredOutput: modelSupportsStructuredOutput,
|
|
278
278
|
rejectsSamplingParameters,
|
|
279
|
+
rejectsThinkingDisabledAboveHighEffort,
|
|
279
280
|
isKnownModel,
|
|
280
281
|
} = getModelCapabilities(this.modelId);
|
|
281
282
|
|
|
@@ -397,6 +398,25 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
397
398
|
toolNameMapping,
|
|
398
399
|
});
|
|
399
400
|
|
|
401
|
+
// Newer models only allow disabling thinking at effort levels up to and
|
|
402
|
+
// including `high`; at `xhigh` and `max` the API returns a 400. Lower
|
|
403
|
+
// the effort to `high` to preserve the explicit request to run without
|
|
404
|
+
// thinking.
|
|
405
|
+
if (
|
|
406
|
+
rejectsThinkingDisabledAboveHighEffort &&
|
|
407
|
+
anthropicOptions?.thinking?.type === 'disabled' &&
|
|
408
|
+
(anthropicOptions.effort === 'xhigh' || anthropicOptions.effort === 'max')
|
|
409
|
+
) {
|
|
410
|
+
warnings.push({
|
|
411
|
+
type: 'unsupported',
|
|
412
|
+
feature: 'providerOptions.anthropic.effort',
|
|
413
|
+
details:
|
|
414
|
+
`effort '${anthropicOptions.effort}' is not supported by ${this.modelId} when thinking is disabled. ` +
|
|
415
|
+
`The effort has been lowered to 'high'.`,
|
|
416
|
+
});
|
|
417
|
+
anthropicOptions.effort = 'high';
|
|
418
|
+
}
|
|
419
|
+
|
|
400
420
|
const thinkingType = anthropicOptions?.thinking?.type;
|
|
401
421
|
const isThinking =
|
|
402
422
|
thinkingType === 'enabled' || thinkingType === 'adaptive';
|
|
@@ -468,8 +488,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
468
488
|
...(anthropicOptions?.inferenceGeo && {
|
|
469
489
|
inference_geo: anthropicOptions.inferenceGeo,
|
|
470
490
|
}),
|
|
471
|
-
...(anthropicOptions?.fallbacks &&
|
|
472
|
-
anthropicOptions.fallbacks
|
|
491
|
+
...(anthropicOptions?.fallbacks != null &&
|
|
492
|
+
(anthropicOptions.fallbacks === 'default' ||
|
|
493
|
+
anthropicOptions.fallbacks.length > 0) && {
|
|
473
494
|
fallbacks: anthropicOptions.fallbacks,
|
|
474
495
|
}),
|
|
475
496
|
...(anthropicOptions?.cacheControl && {
|
|
@@ -698,7 +719,12 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
698
719
|
betas.add('fast-mode-2026-02-01');
|
|
699
720
|
}
|
|
700
721
|
|
|
701
|
-
if (anthropicOptions?.fallbacks
|
|
722
|
+
if (anthropicOptions?.fallbacks === 'default') {
|
|
723
|
+
betas.add('server-side-fallback-2026-07-01');
|
|
724
|
+
} else if (
|
|
725
|
+
anthropicOptions?.fallbacks &&
|
|
726
|
+
anthropicOptions.fallbacks.length > 0
|
|
727
|
+
) {
|
|
702
728
|
betas.add('server-side-fallback-2026-06-01');
|
|
703
729
|
}
|
|
704
730
|
|
|
@@ -2429,6 +2455,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2429
2455
|
usage.input_tokens = value.usage.input_tokens;
|
|
2430
2456
|
}
|
|
2431
2457
|
usage.output_tokens = value.usage.output_tokens;
|
|
2458
|
+
if (value.usage.output_tokens_details != null) {
|
|
2459
|
+
usage.output_tokens_details = value.usage.output_tokens_details;
|
|
2460
|
+
}
|
|
2432
2461
|
|
|
2433
2462
|
if (value.usage.cache_read_input_tokens != null) {
|
|
2434
2463
|
usage.cache_read_input_tokens =
|
|
@@ -2602,9 +2631,18 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2602
2631
|
maxOutputTokens: number;
|
|
2603
2632
|
supportsStructuredOutput: boolean;
|
|
2604
2633
|
rejectsSamplingParameters: boolean;
|
|
2634
|
+
rejectsThinkingDisabledAboveHighEffort: boolean;
|
|
2605
2635
|
isKnownModel: boolean;
|
|
2606
2636
|
} {
|
|
2607
|
-
if (
|
|
2637
|
+
if (modelId.includes('claude-opus-5')) {
|
|
2638
|
+
return {
|
|
2639
|
+
maxOutputTokens: 128000,
|
|
2640
|
+
supportsStructuredOutput: true,
|
|
2641
|
+
rejectsSamplingParameters: true,
|
|
2642
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2643
|
+
isKnownModel: true,
|
|
2644
|
+
};
|
|
2645
|
+
} else if (
|
|
2608
2646
|
modelId.includes('claude-opus-4-8') ||
|
|
2609
2647
|
modelId.includes('claude-opus-4-7') ||
|
|
2610
2648
|
modelId.includes('claude-fable-5') ||
|
|
@@ -2614,6 +2652,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2614
2652
|
maxOutputTokens: 128000,
|
|
2615
2653
|
supportsStructuredOutput: true,
|
|
2616
2654
|
rejectsSamplingParameters: true,
|
|
2655
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2617
2656
|
isKnownModel: true,
|
|
2618
2657
|
};
|
|
2619
2658
|
} else if (
|
|
@@ -2624,6 +2663,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2624
2663
|
maxOutputTokens: 128000,
|
|
2625
2664
|
supportsStructuredOutput: true,
|
|
2626
2665
|
rejectsSamplingParameters: false,
|
|
2666
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2627
2667
|
isKnownModel: true,
|
|
2628
2668
|
};
|
|
2629
2669
|
} else if (
|
|
@@ -2635,6 +2675,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2635
2675
|
maxOutputTokens: 64000,
|
|
2636
2676
|
supportsStructuredOutput: true,
|
|
2637
2677
|
rejectsSamplingParameters: false,
|
|
2678
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2638
2679
|
isKnownModel: true,
|
|
2639
2680
|
};
|
|
2640
2681
|
} else if (modelId.includes('claude-opus-4-1')) {
|
|
@@ -2642,6 +2683,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2642
2683
|
maxOutputTokens: 32000,
|
|
2643
2684
|
supportsStructuredOutput: true,
|
|
2644
2685
|
rejectsSamplingParameters: false,
|
|
2686
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2645
2687
|
isKnownModel: true,
|
|
2646
2688
|
};
|
|
2647
2689
|
} else if (modelId.includes('claude-sonnet-4-')) {
|
|
@@ -2649,6 +2691,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2649
2691
|
maxOutputTokens: 64000,
|
|
2650
2692
|
supportsStructuredOutput: false,
|
|
2651
2693
|
rejectsSamplingParameters: false,
|
|
2694
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2652
2695
|
isKnownModel: true,
|
|
2653
2696
|
};
|
|
2654
2697
|
} else if (modelId.includes('claude-opus-4-')) {
|
|
@@ -2656,6 +2699,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2656
2699
|
maxOutputTokens: 32000,
|
|
2657
2700
|
supportsStructuredOutput: false,
|
|
2658
2701
|
rejectsSamplingParameters: false,
|
|
2702
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2659
2703
|
isKnownModel: true,
|
|
2660
2704
|
};
|
|
2661
2705
|
} else if (modelId.includes('claude-3-haiku')) {
|
|
@@ -2663,6 +2707,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2663
2707
|
maxOutputTokens: 4096,
|
|
2664
2708
|
supportsStructuredOutput: false,
|
|
2665
2709
|
rejectsSamplingParameters: false,
|
|
2710
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2666
2711
|
isKnownModel: true,
|
|
2667
2712
|
};
|
|
2668
2713
|
} else if (
|
|
@@ -2672,6 +2717,7 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2672
2717
|
maxOutputTokens: 4096,
|
|
2673
2718
|
supportsStructuredOutput: false,
|
|
2674
2719
|
rejectsSamplingParameters: false,
|
|
2720
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2675
2721
|
isKnownModel: false,
|
|
2676
2722
|
};
|
|
2677
2723
|
} else if (modelId.includes('claude-')) {
|
|
@@ -2682,13 +2728,17 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2682
2728
|
maxOutputTokens: 128000,
|
|
2683
2729
|
supportsStructuredOutput: true,
|
|
2684
2730
|
rejectsSamplingParameters: true,
|
|
2731
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2685
2732
|
isKnownModel: false,
|
|
2686
2733
|
};
|
|
2687
2734
|
} else {
|
|
2735
|
+
// Non-Claude models (e.g. served through Anthropic-compatible APIs)
|
|
2736
|
+
// keep conservative defaults.
|
|
2688
2737
|
return {
|
|
2689
2738
|
maxOutputTokens: 4096,
|
|
2690
2739
|
supportsStructuredOutput: false,
|
|
2691
2740
|
rejectsSamplingParameters: false,
|
|
2741
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2692
2742
|
isKnownModel: false,
|
|
2693
2743
|
};
|
|
2694
2744
|
}
|
|
@@ -19,6 +19,7 @@ export type AnthropicMessagesModelId =
|
|
|
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 & {});
|
|
@@ -59,6 +60,44 @@ export type AnthropicFilePartProviderOptions = z.infer<
|
|
|
59
60
|
typeof anthropicFilePartProviderOptions
|
|
60
61
|
>;
|
|
61
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Anthropic provider options for system messages.
|
|
65
|
+
*/
|
|
66
|
+
export const anthropicSystemMessageProviderOptions = z.object({
|
|
67
|
+
/**
|
|
68
|
+
* Mid-conversation tool changes. Adds or removes tools from the
|
|
69
|
+
* conversation's tool set between turns without invalidating the prompt
|
|
70
|
+
* cache.
|
|
71
|
+
*
|
|
72
|
+
* Only supported on system messages that appear mid-conversation (not the
|
|
73
|
+
* initial system prompt). A system message carrying tool changes must come
|
|
74
|
+
* right before an assistant message or at the end of the messages.
|
|
75
|
+
*
|
|
76
|
+
* Tools referenced by a `tool_addition` must be declared in the `tools`
|
|
77
|
+
* option (typically with `deferLoading: true` so they are not loaded until
|
|
78
|
+
* the addition surfaces them). The required
|
|
79
|
+
* `mid-conversation-tool-changes-2026-07-01` beta is added automatically.
|
|
80
|
+
*/
|
|
81
|
+
toolChanges: z
|
|
82
|
+
.array(
|
|
83
|
+
z.discriminatedUnion('type', [
|
|
84
|
+
z.object({
|
|
85
|
+
type: z.literal('tool_addition'),
|
|
86
|
+
toolName: z.string(),
|
|
87
|
+
}),
|
|
88
|
+
z.object({
|
|
89
|
+
type: z.literal('tool_removal'),
|
|
90
|
+
toolName: z.string(),
|
|
91
|
+
}),
|
|
92
|
+
]),
|
|
93
|
+
)
|
|
94
|
+
.optional(),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export type AnthropicSystemMessageProviderOptions = z.infer<
|
|
98
|
+
typeof anthropicSystemMessageProviderOptions
|
|
99
|
+
>;
|
|
100
|
+
|
|
62
101
|
export const anthropicLanguageModelOptions = z.object({
|
|
63
102
|
/**
|
|
64
103
|
* Whether to send reasoning to the model.
|
|
@@ -227,31 +266,36 @@ export const anthropicLanguageModelOptions = z.object({
|
|
|
227
266
|
inferenceGeo: z.enum(['us', 'global']).optional(),
|
|
228
267
|
|
|
229
268
|
/**
|
|
230
|
-
* Server-side fallback
|
|
269
|
+
* Server-side fallback configuration.
|
|
231
270
|
*
|
|
232
271
|
* When the primary model's safety classifiers block a turn, the API
|
|
233
|
-
* automatically retries it on
|
|
234
|
-
* `content-filter` finish reason means the
|
|
272
|
+
* automatically retries it server-side on a fallback model. A
|
|
273
|
+
* `content-filter` finish reason means the fallback(s) refused as well.
|
|
235
274
|
*
|
|
236
|
-
*
|
|
237
|
-
* model
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
275
|
+
* - `'default'` (recommended): the API routes the retry to Anthropic's
|
|
276
|
+
* recommended fallback model based on the refusal category. Requires the
|
|
277
|
+
* `server-side-fallback-2026-07-01` beta, which is added automatically.
|
|
278
|
+
* - Array form: an explicit fallback chain. Each entry is merged into the
|
|
279
|
+
* request as a direct request to that entry's model, so it must be
|
|
280
|
+
* formatted accordingly: `model` is required, and an entry may
|
|
281
|
+
* additionally override `max_tokens`, `thinking`, `output_config`, and
|
|
282
|
+
* `speed` for that attempt only (`speed` additionally requires the speed
|
|
283
|
+
* beta). The value is passed through to the API as-is, and the
|
|
284
|
+
* `server-side-fallback-2026-06-01` beta is added automatically.
|
|
244
285
|
*/
|
|
245
286
|
fallbacks: z
|
|
246
|
-
.
|
|
247
|
-
z.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
287
|
+
.union([
|
|
288
|
+
z.literal('default'),
|
|
289
|
+
z.array(
|
|
290
|
+
z.object({
|
|
291
|
+
model: z.string(),
|
|
292
|
+
max_tokens: z.number().int().optional(),
|
|
293
|
+
thinking: z.record(z.string(), z.unknown()).optional(),
|
|
294
|
+
output_config: z.record(z.string(), z.unknown()).optional(),
|
|
295
|
+
speed: z.enum(['fast', 'standard']).optional(),
|
|
296
|
+
}),
|
|
297
|
+
),
|
|
298
|
+
])
|
|
255
299
|
.optional(),
|
|
256
300
|
|
|
257
301
|
/**
|
|
@@ -28,6 +28,9 @@ export type AnthropicUsageIteration = {
|
|
|
28
28
|
export type AnthropicMessagesUsage = {
|
|
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 convertAnthropicMessagesUsage({
|
|
|
50
53
|
}): LanguageModelV3Usage {
|
|
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 convertAnthropicMessagesUsage({
|
|
|
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
|
};
|
|
@@ -20,12 +20,18 @@ import {
|
|
|
20
20
|
anthropicReasoningMetadataSchema,
|
|
21
21
|
type AnthropicAssistantMessage,
|
|
22
22
|
type AnthropicMessagesPrompt,
|
|
23
|
+
type AnthropicSystemMessage,
|
|
24
|
+
type AnthropicTextContent,
|
|
25
|
+
type AnthropicToolChangeContent,
|
|
23
26
|
type AnthropicToolResultContent,
|
|
24
27
|
type AnthropicUserMessage,
|
|
25
28
|
type AnthropicWebFetchToolResultContent,
|
|
26
29
|
type Citation,
|
|
27
30
|
} from './anthropic-messages-api';
|
|
28
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
anthropicFilePartProviderOptions,
|
|
33
|
+
anthropicSystemMessageProviderOptions,
|
|
34
|
+
} from './anthropic-messages-options';
|
|
29
35
|
import { CacheControlValidator } from './get-cache-control';
|
|
30
36
|
import { advisor_20260301OutputSchema } from './tool/advisor_20260301';
|
|
31
37
|
import { codeExecution_20250522OutputSchema } from './tool/code-execution_20250522';
|
|
@@ -159,20 +165,66 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
159
165
|
|
|
160
166
|
switch (type) {
|
|
161
167
|
case 'system': {
|
|
162
|
-
const content
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
const content: AnthropicSystemMessage['content'] = [];
|
|
169
|
+
let toolChangeCount = 0;
|
|
170
|
+
|
|
171
|
+
for (const { content: text, providerOptions } of block.messages) {
|
|
172
|
+
const systemMessageOptions = await parseProviderOptions({
|
|
173
|
+
provider: 'anthropic',
|
|
174
|
+
providerOptions,
|
|
175
|
+
schema: anthropicSystemMessageProviderOptions,
|
|
176
|
+
});
|
|
177
|
+
const toolChanges = systemMessageOptions?.toolChanges ?? [];
|
|
178
|
+
|
|
179
|
+
// A system message that only carries tool changes may have empty
|
|
180
|
+
// text; do not emit an empty text block for it.
|
|
181
|
+
if (text !== '' || toolChanges.length === 0) {
|
|
182
|
+
content.push({
|
|
183
|
+
type: 'text' as const,
|
|
184
|
+
text,
|
|
185
|
+
cache_control: validator.getCacheControl(providerOptions, {
|
|
186
|
+
type: 'system message',
|
|
187
|
+
canCache: true,
|
|
188
|
+
}),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
for (const toolChange of toolChanges) {
|
|
193
|
+
toolChangeCount++;
|
|
194
|
+
content.push({
|
|
195
|
+
type: toolChange.type,
|
|
196
|
+
tool: {
|
|
197
|
+
type: 'tool_reference',
|
|
198
|
+
name: toolNameMapping.toProviderToolName(toolChange.toolName),
|
|
199
|
+
},
|
|
200
|
+
} satisfies AnthropicToolChangeContent);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// The first block becomes the top-level system prompt. Later system
|
|
205
|
+
// blocks are sent as inline system messages — always when they carry
|
|
206
|
+
// tool changes (which are only valid mid-conversation), and otherwise
|
|
207
|
+
// only when a top-level system prompt already exists (preserving the
|
|
208
|
+
// existing hoisting behavior for plain text).
|
|
209
|
+
if (i === 0 || (system == null && toolChangeCount === 0)) {
|
|
210
|
+
if (toolChangeCount > 0) {
|
|
211
|
+
warnings.push({
|
|
212
|
+
type: 'other',
|
|
213
|
+
message:
|
|
214
|
+
'tool changes on the initial system message are not supported by Anthropic. ' +
|
|
215
|
+
'Configure the initial tool set via the tools option instead. ' +
|
|
216
|
+
'The tool changes have been ignored.',
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
system = content.filter(
|
|
220
|
+
(part): part is AnthropicTextContent => part.type === 'text',
|
|
221
|
+
);
|
|
173
222
|
} else {
|
|
174
223
|
messages.push({ role: 'system', content });
|
|
175
224
|
betas.add('mid-conversation-system-2026-04-07');
|
|
225
|
+
if (toolChangeCount > 0) {
|
|
226
|
+
betas.add('mid-conversation-tool-changes-2026-07-01');
|
|
227
|
+
}
|
|
176
228
|
}
|
|
177
229
|
|
|
178
230
|
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-messages-options';
|
|
10
11
|
export type { AnthropicToolOptions } from './anthropic-prepare-tools';
|
|
11
12
|
export { anthropic, createAnthropic } from './anthropic-provider';
|