@ai-sdk/anthropic 3.0.80 → 3.0.82
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 +12 -0
- package/dist/index.d.mts +57 -32
- package/dist/index.d.ts +57 -32
- package/dist/index.js +123 -75
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +123 -75
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +2 -2
- package/dist/internal/index.d.ts +2 -2
- package/dist/internal/index.js +122 -74
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +122 -74
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +63 -4
- package/package.json +1 -1
- package/src/anthropic-message-metadata.ts +67 -54
- package/src/anthropic-messages-api.ts +57 -38
- package/src/anthropic-messages-language-model.ts +93 -73
- package/src/anthropic-messages-options.ts +30 -0
- package/src/anthropic-tools.ts +1 -1
- package/src/convert-anthropic-messages-usage.ts +28 -20
- package/src/convert-to-anthropic-messages-prompt.ts +9 -9
- package/src/tool/advisor_20260301.ts +1 -1
package/docs/05-anthropic.mdx
CHANGED
|
@@ -243,7 +243,7 @@ import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
|
243
243
|
import { generateText } from 'ai';
|
|
244
244
|
|
|
245
245
|
const { text } = await generateText({
|
|
246
|
-
model: anthropic('claude-opus-4-
|
|
246
|
+
model: anthropic('claude-opus-4-8'),
|
|
247
247
|
prompt: 'Research the pros and cons of Rust vs Go for building CLI tools.',
|
|
248
248
|
providerOptions: {
|
|
249
249
|
anthropic: {
|
|
@@ -293,6 +293,63 @@ const { text } = await generateText({
|
|
|
293
293
|
|
|
294
294
|
The `inferenceGeo` option accepts `'us'` (US-only infrastructure) or `'global'` (default, any available geography).
|
|
295
295
|
|
|
296
|
+
### Safety Classifiers and Fallbacks
|
|
297
|
+
|
|
298
|
+
Claude Fable 5 has safeguards that limit its performance in certain areas like cybersecurity, biology, and chemistry, and automated safety checks are run on every request.
|
|
299
|
+
|
|
300
|
+
When one of these checks blocks a request, the API does not answer it. Instead it returns a classifier block: a `200` response with a `refusal` stop reason and an optional `stop_details` object describing the category that triggered the block. The AI SDK surfaces this as a `content-filter` finish reason, with the details available on `providerMetadata.anthropic.stopDetails`.
|
|
301
|
+
|
|
302
|
+
A classifier block looks like this:
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"type": "message",
|
|
307
|
+
"model": "claude-fable-5",
|
|
308
|
+
"content": [],
|
|
309
|
+
"stop_reason": "refusal",
|
|
310
|
+
"stop_details": {
|
|
311
|
+
"type": "refusal",
|
|
312
|
+
"category": "cyber",
|
|
313
|
+
"explanation": "This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy."
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
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
|
+
|
|
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 the next model in the chain and returns that model's answer. The required beta header is added for you.
|
|
321
|
+
|
|
322
|
+
```ts highlight="8-10"
|
|
323
|
+
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
324
|
+
import { generateText } from 'ai';
|
|
325
|
+
|
|
326
|
+
const { text } = await generateText({
|
|
327
|
+
model: anthropic('claude-fable-5'),
|
|
328
|
+
prompt: 'Explain the history of cryptography.',
|
|
329
|
+
providerOptions: {
|
|
330
|
+
anthropic: {
|
|
331
|
+
fallbacks: [{ model: 'claude-fable-5' }],
|
|
332
|
+
} satisfies AnthropicLanguageModelOptions,
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Each fallback entry requires a `model` and may additionally override `max_tokens`, `thinking`, `output_config`, and `speed` for that attempt only.
|
|
338
|
+
|
|
339
|
+
When a fallback serves the turn, it is recorded in the per-model usage breakdown (`usage.iterations`) as a `fallback_message` entry. The AI SDK exposes this breakdown on `providerMetadata.anthropic.iterations`, so you can detect whether a fallback ran:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
// set up `result` with a `streamText` call passing `fallbacks` as shown
|
|
343
|
+
// above, then consume the stream
|
|
344
|
+
|
|
345
|
+
const { iterations } = (await result.providerMetadata)?.anthropic ?? {};
|
|
346
|
+
const servedByFallback = iterations?.some(
|
|
347
|
+
iteration => iteration.type === 'fallback_message',
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
console.log('Served by fallback:', servedByFallback);
|
|
351
|
+
```
|
|
352
|
+
|
|
296
353
|
### Reasoning
|
|
297
354
|
|
|
298
355
|
Anthropic models support extended thinking, where Claude shows its reasoning process before providing a final answer.
|
|
@@ -342,7 +399,7 @@ Starting with `claude-opus-4-7`, thinking content is omitted from the response b
|
|
|
342
399
|
|
|
343
400
|
```ts highlight="5"
|
|
344
401
|
const { text, reasoningText } = await generateText({
|
|
345
|
-
model: anthropic('claude-opus-4-
|
|
402
|
+
model: anthropic('claude-opus-4-8'),
|
|
346
403
|
providerOptions: {
|
|
347
404
|
anthropic: {
|
|
348
405
|
thinking: { type: 'adaptive', display: 'summarized' },
|
|
@@ -971,7 +1028,7 @@ const result = await generateText({
|
|
|
971
1028
|
'Build a concurrent worker pool in Go with graceful shutdown. Outline the design first.',
|
|
972
1029
|
tools: {
|
|
973
1030
|
advisor: anthropic.tools.advisor_20260301({
|
|
974
|
-
model: 'claude-opus-4-
|
|
1031
|
+
model: 'claude-opus-4-8',
|
|
975
1032
|
maxUses: 3,
|
|
976
1033
|
}),
|
|
977
1034
|
},
|
|
@@ -989,7 +1046,7 @@ The advisor tool supports the following configuration options:
|
|
|
989
1046
|
|
|
990
1047
|
- **model** _string_
|
|
991
1048
|
|
|
992
|
-
Required. The advisor model ID, such as `claude-opus-4-
|
|
1049
|
+
Required. The advisor model ID, such as `claude-opus-4-8`. The advisor model must be at least as capable as the executor model.
|
|
993
1050
|
|
|
994
1051
|
- **maxUses** _number_
|
|
995
1052
|
|
|
@@ -1502,6 +1559,8 @@ and the `mediaType` should be set to `'application/pdf'`.
|
|
|
1502
1559
|
|
|
1503
1560
|
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
|
|
1504
1561
|
| ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
1562
|
+
| `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1563
|
+
| `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} /> |
|
|
1505
1564
|
| `claude-opus-4-7` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1506
1565
|
| `claude-opus-4-6` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1507
1566
|
| `claude-sonnet-4-6` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
package/package.json
CHANGED
|
@@ -8,66 +8,43 @@ import type { JSONObject } from '@ai-sdk/provider';
|
|
|
8
8
|
* - `compaction`: a context compaction step (billed at executor rates).
|
|
9
9
|
* - `message`: an executor sampling iteration (billed at executor rates).
|
|
10
10
|
* - `advisor_message`: an advisor sub-inference (billed at the advisor
|
|
11
|
-
* model's rates
|
|
12
|
-
* usage
|
|
13
|
-
*
|
|
11
|
+
* model's rates). Advisor token usage is NOT rolled into the top-level
|
|
12
|
+
* usage totals because it bills at a different rate; inspect this array
|
|
13
|
+
* directly for advisor billing.
|
|
14
|
+
* - `fallback_message`: a server-side fallback attempt that served the turn.
|
|
15
|
+
* Inspect this array for exact per-model attribution on a turn that fell
|
|
16
|
+
* back.
|
|
14
17
|
*/
|
|
15
|
-
export type AnthropicUsageIteration =
|
|
16
|
-
|
|
|
17
|
-
type: 'compaction' | 'message';
|
|
18
|
+
export type AnthropicUsageIteration = {
|
|
19
|
+
type: 'compaction' | 'message' | 'advisor_message' | 'fallback_message';
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* Number of output tokens generated in this iteration.
|
|
26
|
-
*/
|
|
27
|
-
outputTokens: number;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Number of cache-creation input tokens consumed in this iteration.
|
|
31
|
-
*/
|
|
32
|
-
cacheCreationInputTokens?: number;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Number of cache-read input tokens consumed in this iteration.
|
|
36
|
-
*/
|
|
37
|
-
cacheReadInputTokens?: number;
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
type: 'advisor_message';
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The advisor model that produced this iteration.
|
|
44
|
-
*/
|
|
45
|
-
model: string;
|
|
21
|
+
/**
|
|
22
|
+
* The model that produced this iteration. Populated for the per-model
|
|
23
|
+
* attribution cases (the fallback chain and advisor sub-inferences) and
|
|
24
|
+
* absent otherwise.
|
|
25
|
+
*/
|
|
26
|
+
model?: string;
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Number of input tokens consumed in this iteration.
|
|
30
|
+
*/
|
|
31
|
+
inputTokens: number;
|
|
51
32
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Number of output tokens generated in this iteration.
|
|
35
|
+
*/
|
|
36
|
+
outputTokens: number;
|
|
56
37
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*/
|
|
62
|
-
cacheCreationInputTokens?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Number of cache-creation input tokens consumed in this iteration.
|
|
40
|
+
*/
|
|
41
|
+
cacheCreationInputTokens?: number;
|
|
63
42
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
cacheReadInputTokens?: number;
|
|
70
|
-
};
|
|
43
|
+
/**
|
|
44
|
+
* Number of cache-read input tokens consumed in this iteration.
|
|
45
|
+
*/
|
|
46
|
+
cacheReadInputTokens?: number;
|
|
47
|
+
};
|
|
71
48
|
|
|
72
49
|
export interface AnthropicMessageMetadata {
|
|
73
50
|
usage: JSONObject;
|
|
@@ -76,6 +53,42 @@ export interface AnthropicMessageMetadata {
|
|
|
76
53
|
cacheCreationInputTokens: number | null;
|
|
77
54
|
stopSequence: string | null;
|
|
78
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Details about why the request stopped. Present only when the API returns
|
|
58
|
+
* a `refusal` stop reason together with a `stop_details` object (a
|
|
59
|
+
* classifier block or a model refusal).
|
|
60
|
+
*
|
|
61
|
+
* Branch on the finish reason (`content-filter`), not on this object: the
|
|
62
|
+
* API may return a refusal with no details at all, so this field can be
|
|
63
|
+
* absent even on a refusal and should not be relied upon being present.
|
|
64
|
+
*/
|
|
65
|
+
stopDetails?: {
|
|
66
|
+
/**
|
|
67
|
+
* The kind of stop detail. `'refusal'` for classifier blocks and model
|
|
68
|
+
* refusals.
|
|
69
|
+
*/
|
|
70
|
+
type: string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The classifier category that triggered the block, e.g. `'cyber'` or
|
|
74
|
+
* `'bio'`. Absent for model refusals and other cases.
|
|
75
|
+
*/
|
|
76
|
+
category?: string;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Human-readable explanation of why the request was blocked. May be
|
|
80
|
+
* absent even on a refusal.
|
|
81
|
+
*/
|
|
82
|
+
explanation?: string;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The canonical id of a model to retry directly. Populated only when the
|
|
86
|
+
* request included fallbacks and the fallback attempt could not be made
|
|
87
|
+
* (e.g. the fallback model was rate limited or overloaded).
|
|
88
|
+
*/
|
|
89
|
+
recommendedModel?: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
79
92
|
/**
|
|
80
93
|
* Usage breakdown by iteration when compaction is triggered.
|
|
81
94
|
*
|
|
@@ -11,13 +11,21 @@ export type AnthropicMessagesPrompt = {
|
|
|
11
11
|
messages: AnthropicMessage[];
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export type AnthropicMessage =
|
|
14
|
+
export type AnthropicMessage =
|
|
15
|
+
| AnthropicUserMessage
|
|
16
|
+
| AnthropicAssistantMessage
|
|
17
|
+
| AnthropicSystemMessage;
|
|
15
18
|
|
|
16
19
|
export type AnthropicCacheControl = {
|
|
17
20
|
type: 'ephemeral';
|
|
18
21
|
ttl?: '5m' | '1h';
|
|
19
22
|
};
|
|
20
23
|
|
|
24
|
+
export interface AnthropicSystemMessage {
|
|
25
|
+
role: 'system';
|
|
26
|
+
content: Array<AnthropicTextContent>;
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
export interface AnthropicUserMessage {
|
|
22
30
|
role: 'user';
|
|
23
31
|
content: Array<
|
|
@@ -593,6 +601,15 @@ export type AnthropicResponseContextManagement = {
|
|
|
593
601
|
applied_edits: AnthropicResponseContextManagementEdit[];
|
|
594
602
|
};
|
|
595
603
|
|
|
604
|
+
const anthropicStopDetailsSchema = z.object({
|
|
605
|
+
type: z.string(),
|
|
606
|
+
category: z.string().nullish(),
|
|
607
|
+
explanation: z.string().nullish(),
|
|
608
|
+
recommended_model: z.string().nullish(),
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
export type AnthropicStopDetails = z.infer<typeof anthropicStopDetailsSchema>;
|
|
612
|
+
|
|
596
613
|
// limited version of the schema, focussed on what is needed for the implementation
|
|
597
614
|
// this approach limits breakages when the API changes and increases efficiency
|
|
598
615
|
export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
@@ -893,10 +910,17 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
893
910
|
}),
|
|
894
911
|
]),
|
|
895
912
|
}),
|
|
913
|
+
// Server-side fallback marker. Parsed so the response validates, but
|
|
914
|
+
// dropped from the content output (the AI SDK has no model-hop
|
|
915
|
+
// primitive). The hop remains observable via usage.iterations.
|
|
916
|
+
z.object({
|
|
917
|
+
type: z.literal('fallback'),
|
|
918
|
+
}),
|
|
896
919
|
]),
|
|
897
920
|
),
|
|
898
921
|
stop_reason: z.string().nullish(),
|
|
899
922
|
stop_sequence: z.string().nullish(),
|
|
923
|
+
stop_details: anthropicStopDetailsSchema.nullish(),
|
|
900
924
|
usage: z.looseObject({
|
|
901
925
|
input_tokens: z.number(),
|
|
902
926
|
output_tokens: z.number(),
|
|
@@ -904,23 +928,19 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
904
928
|
cache_read_input_tokens: z.number().nullish(),
|
|
905
929
|
iterations: z
|
|
906
930
|
.array(
|
|
907
|
-
z.
|
|
908
|
-
z.
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
z.
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
cache_creation_input_tokens: z.number().nullish(),
|
|
921
|
-
cache_read_input_tokens: z.number().nullish(),
|
|
922
|
-
}),
|
|
923
|
-
]),
|
|
931
|
+
z.object({
|
|
932
|
+
type: z.union([
|
|
933
|
+
z.literal('compaction'),
|
|
934
|
+
z.literal('message'),
|
|
935
|
+
z.literal('advisor_message'),
|
|
936
|
+
z.literal('fallback_message'),
|
|
937
|
+
]),
|
|
938
|
+
model: z.string().nullish(),
|
|
939
|
+
input_tokens: z.number(),
|
|
940
|
+
output_tokens: z.number(),
|
|
941
|
+
cache_creation_input_tokens: z.number().nullish(),
|
|
942
|
+
cache_read_input_tokens: z.number().nullish(),
|
|
943
|
+
}),
|
|
924
944
|
)
|
|
925
945
|
.nullish(),
|
|
926
946
|
}),
|
|
@@ -1282,6 +1302,11 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1282
1302
|
}),
|
|
1283
1303
|
]),
|
|
1284
1304
|
}),
|
|
1305
|
+
// Server-side fallback marker; dropped from content output (see the
|
|
1306
|
+
// response schema). The hop remains observable via usage.iterations.
|
|
1307
|
+
z.object({
|
|
1308
|
+
type: z.literal('fallback'),
|
|
1309
|
+
}),
|
|
1285
1310
|
]),
|
|
1286
1311
|
}),
|
|
1287
1312
|
z.object({
|
|
@@ -1354,6 +1379,7 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1354
1379
|
delta: z.object({
|
|
1355
1380
|
stop_reason: z.string().nullish(),
|
|
1356
1381
|
stop_sequence: z.string().nullish(),
|
|
1382
|
+
stop_details: anthropicStopDetailsSchema.nullish(),
|
|
1357
1383
|
container: z
|
|
1358
1384
|
.object({
|
|
1359
1385
|
expires_at: z.string(),
|
|
@@ -1380,26 +1406,19 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1380
1406
|
cache_read_input_tokens: z.number().nullish(),
|
|
1381
1407
|
iterations: z
|
|
1382
1408
|
.array(
|
|
1383
|
-
z.
|
|
1384
|
-
z.
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
z.
|
|
1395
|
-
|
|
1396
|
-
model: z.string(),
|
|
1397
|
-
input_tokens: z.number(),
|
|
1398
|
-
output_tokens: z.number(),
|
|
1399
|
-
cache_creation_input_tokens: z.number().nullish(),
|
|
1400
|
-
cache_read_input_tokens: z.number().nullish(),
|
|
1401
|
-
}),
|
|
1402
|
-
]),
|
|
1409
|
+
z.object({
|
|
1410
|
+
type: z.union([
|
|
1411
|
+
z.literal('compaction'),
|
|
1412
|
+
z.literal('message'),
|
|
1413
|
+
z.literal('advisor_message'),
|
|
1414
|
+
z.literal('fallback_message'),
|
|
1415
|
+
]),
|
|
1416
|
+
model: z.string().nullish(),
|
|
1417
|
+
input_tokens: z.number(),
|
|
1418
|
+
output_tokens: z.number(),
|
|
1419
|
+
cache_creation_input_tokens: z.number().nullish(),
|
|
1420
|
+
cache_read_input_tokens: z.number().nullish(),
|
|
1421
|
+
}),
|
|
1403
1422
|
)
|
|
1404
1423
|
.nullish(),
|
|
1405
1424
|
}),
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
type AnthropicContainer,
|
|
41
41
|
type AnthropicReasoningMetadata,
|
|
42
42
|
type AnthropicResponseContextManagement,
|
|
43
|
+
type AnthropicStopDetails,
|
|
43
44
|
type AnthropicTool,
|
|
44
45
|
type Citation,
|
|
45
46
|
} from './anthropic-messages-api';
|
|
@@ -438,6 +439,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
438
439
|
...(anthropicOptions?.inferenceGeo && {
|
|
439
440
|
inference_geo: anthropicOptions.inferenceGeo,
|
|
440
441
|
}),
|
|
442
|
+
...(anthropicOptions?.fallbacks &&
|
|
443
|
+
anthropicOptions.fallbacks.length > 0 && {
|
|
444
|
+
fallbacks: anthropicOptions.fallbacks,
|
|
445
|
+
}),
|
|
441
446
|
...(anthropicOptions?.cacheControl && {
|
|
442
447
|
cache_control: anthropicOptions.cacheControl,
|
|
443
448
|
}),
|
|
@@ -664,6 +669,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
664
669
|
betas.add('fast-mode-2026-02-01');
|
|
665
670
|
}
|
|
666
671
|
|
|
672
|
+
if (anthropicOptions?.fallbacks && anthropicOptions.fallbacks.length > 0) {
|
|
673
|
+
betas.add('server-side-fallback-2026-06-01');
|
|
674
|
+
}
|
|
675
|
+
|
|
667
676
|
const defaultEagerInputStreaming =
|
|
668
677
|
stream && (anthropicOptions?.toolStreaming ?? true);
|
|
669
678
|
|
|
@@ -1281,6 +1290,13 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1281
1290
|
}
|
|
1282
1291
|
break;
|
|
1283
1292
|
}
|
|
1293
|
+
|
|
1294
|
+
// Server-side fallback marker: the AI SDK has no content primitive for
|
|
1295
|
+
// a model hop, so drop it. The hop is still observable via
|
|
1296
|
+
// usage.iterations.
|
|
1297
|
+
case 'fallback': {
|
|
1298
|
+
break;
|
|
1299
|
+
}
|
|
1284
1300
|
}
|
|
1285
1301
|
}
|
|
1286
1302
|
|
|
@@ -1303,48 +1319,35 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1303
1319
|
},
|
|
1304
1320
|
warnings,
|
|
1305
1321
|
providerMetadata: (() => {
|
|
1322
|
+
const stopDetails = mapAnthropicStopDetails(response.stop_details);
|
|
1323
|
+
|
|
1306
1324
|
const anthropicMetadata = {
|
|
1307
1325
|
usage: response.usage as JSONObject,
|
|
1308
1326
|
cacheCreationInputTokens:
|
|
1309
1327
|
response.usage.cache_creation_input_tokens ?? null,
|
|
1310
1328
|
stopSequence: response.stop_sequence ?? null,
|
|
1329
|
+
...(stopDetails != null ? { stopDetails } : {}),
|
|
1311
1330
|
|
|
1312
1331
|
iterations: response.usage.iterations
|
|
1313
|
-
? response.usage.iterations.map(
|
|
1314
|
-
iter
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
: ({
|
|
1333
|
-
type: iter.type,
|
|
1334
|
-
inputTokens: iter.input_tokens,
|
|
1335
|
-
outputTokens: iter.output_tokens,
|
|
1336
|
-
...(iter.cache_creation_input_tokens
|
|
1337
|
-
? {
|
|
1338
|
-
cacheCreationInputTokens:
|
|
1339
|
-
iter.cache_creation_input_tokens,
|
|
1340
|
-
}
|
|
1341
|
-
: {}),
|
|
1342
|
-
...(iter.cache_read_input_tokens
|
|
1343
|
-
? {
|
|
1344
|
-
cacheReadInputTokens: iter.cache_read_input_tokens,
|
|
1345
|
-
}
|
|
1346
|
-
: {}),
|
|
1347
|
-
} satisfies AnthropicUsageIteration),
|
|
1332
|
+
? response.usage.iterations.map(
|
|
1333
|
+
iter =>
|
|
1334
|
+
({
|
|
1335
|
+
type: iter.type,
|
|
1336
|
+
...(iter.model != null ? { model: iter.model } : {}),
|
|
1337
|
+
inputTokens: iter.input_tokens,
|
|
1338
|
+
outputTokens: iter.output_tokens,
|
|
1339
|
+
...(iter.cache_creation_input_tokens
|
|
1340
|
+
? {
|
|
1341
|
+
cacheCreationInputTokens:
|
|
1342
|
+
iter.cache_creation_input_tokens,
|
|
1343
|
+
}
|
|
1344
|
+
: {}),
|
|
1345
|
+
...(iter.cache_read_input_tokens
|
|
1346
|
+
? {
|
|
1347
|
+
cacheReadInputTokens: iter.cache_read_input_tokens,
|
|
1348
|
+
}
|
|
1349
|
+
: {}),
|
|
1350
|
+
}) satisfies AnthropicUsageIteration,
|
|
1348
1351
|
)
|
|
1349
1352
|
: null,
|
|
1350
1353
|
container: response.container
|
|
@@ -1458,6 +1461,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1458
1461
|
let rawUsage: JSONObject | undefined = undefined;
|
|
1459
1462
|
let cacheCreationInputTokens: number | null = null;
|
|
1460
1463
|
let stopSequence: string | null = null;
|
|
1464
|
+
let stopDetails: AnthropicMessageMetadata['stopDetails'] = undefined;
|
|
1461
1465
|
let container: AnthropicMessageMetadata['container'] | null = null;
|
|
1462
1466
|
let isJsonResponseFromTool = false;
|
|
1463
1467
|
|
|
@@ -1510,6 +1514,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1510
1514
|
case 'content_block_start': {
|
|
1511
1515
|
const part = value.content_block;
|
|
1512
1516
|
const contentBlockType = part.type;
|
|
1517
|
+
|
|
1518
|
+
// Server-side fallback marker: the AI SDK has no content
|
|
1519
|
+
// primitive for a model hop, so drop it. The hop is still
|
|
1520
|
+
// observable via usage.iterations.
|
|
1521
|
+
if (contentBlockType === 'fallback') {
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1513
1525
|
blockType = contentBlockType;
|
|
1514
1526
|
|
|
1515
1527
|
switch (contentBlockType) {
|
|
@@ -2362,6 +2374,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2362
2374
|
};
|
|
2363
2375
|
|
|
2364
2376
|
stopSequence = value.delta.stop_sequence ?? null;
|
|
2377
|
+
stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
|
|
2365
2378
|
container =
|
|
2366
2379
|
value.delta.container != null
|
|
2367
2380
|
? {
|
|
@@ -2395,44 +2408,28 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2395
2408
|
usage: (rawUsage as JSONObject) ?? null,
|
|
2396
2409
|
cacheCreationInputTokens,
|
|
2397
2410
|
stopSequence,
|
|
2411
|
+
...(stopDetails != null ? { stopDetails } : {}),
|
|
2398
2412
|
iterations: usage.iterations
|
|
2399
|
-
? usage.iterations.map(
|
|
2400
|
-
iter
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
: ({
|
|
2420
|
-
type: iter.type,
|
|
2421
|
-
inputTokens: iter.input_tokens,
|
|
2422
|
-
outputTokens: iter.output_tokens,
|
|
2423
|
-
...(iter.cache_creation_input_tokens
|
|
2424
|
-
? {
|
|
2425
|
-
cacheCreationInputTokens:
|
|
2426
|
-
iter.cache_creation_input_tokens,
|
|
2427
|
-
}
|
|
2428
|
-
: {}),
|
|
2429
|
-
...(iter.cache_read_input_tokens
|
|
2430
|
-
? {
|
|
2431
|
-
cacheReadInputTokens:
|
|
2432
|
-
iter.cache_read_input_tokens,
|
|
2433
|
-
}
|
|
2434
|
-
: {}),
|
|
2435
|
-
} satisfies AnthropicUsageIteration),
|
|
2413
|
+
? usage.iterations.map(
|
|
2414
|
+
iter =>
|
|
2415
|
+
({
|
|
2416
|
+
type: iter.type,
|
|
2417
|
+
...(iter.model != null ? { model: iter.model } : {}),
|
|
2418
|
+
inputTokens: iter.input_tokens,
|
|
2419
|
+
outputTokens: iter.output_tokens,
|
|
2420
|
+
...(iter.cache_creation_input_tokens
|
|
2421
|
+
? {
|
|
2422
|
+
cacheCreationInputTokens:
|
|
2423
|
+
iter.cache_creation_input_tokens,
|
|
2424
|
+
}
|
|
2425
|
+
: {}),
|
|
2426
|
+
...(iter.cache_read_input_tokens
|
|
2427
|
+
? {
|
|
2428
|
+
cacheReadInputTokens:
|
|
2429
|
+
iter.cache_read_input_tokens,
|
|
2430
|
+
}
|
|
2431
|
+
: {}),
|
|
2432
|
+
}) satisfies AnthropicUsageIteration,
|
|
2436
2433
|
)
|
|
2437
2434
|
: null,
|
|
2438
2435
|
container,
|
|
@@ -2528,7 +2525,11 @@ function getModelCapabilities(modelId: string): {
|
|
|
2528
2525
|
rejectsSamplingParameters: boolean;
|
|
2529
2526
|
isKnownModel: boolean;
|
|
2530
2527
|
} {
|
|
2531
|
-
if (
|
|
2528
|
+
if (
|
|
2529
|
+
modelId.includes('claude-opus-4-8') ||
|
|
2530
|
+
modelId.includes('claude-opus-4-7') ||
|
|
2531
|
+
modelId.includes('claude-fable-5')
|
|
2532
|
+
) {
|
|
2532
2533
|
return {
|
|
2533
2534
|
maxOutputTokens: 128000,
|
|
2534
2535
|
supportsStructuredOutput: true,
|
|
@@ -2653,3 +2654,22 @@ function mapAnthropicResponseContextManagement(
|
|
|
2653
2654
|
}
|
|
2654
2655
|
: null;
|
|
2655
2656
|
}
|
|
2657
|
+
|
|
2658
|
+
function mapAnthropicStopDetails(
|
|
2659
|
+
stopDetails: AnthropicStopDetails | null | undefined,
|
|
2660
|
+
): AnthropicMessageMetadata['stopDetails'] | undefined {
|
|
2661
|
+
if (stopDetails == null) {
|
|
2662
|
+
return undefined;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
return {
|
|
2666
|
+
type: stopDetails.type,
|
|
2667
|
+
...(stopDetails.category != null ? { category: stopDetails.category } : {}),
|
|
2668
|
+
...(stopDetails.explanation != null
|
|
2669
|
+
? { explanation: stopDetails.explanation }
|
|
2670
|
+
: {}),
|
|
2671
|
+
...(stopDetails.recommended_model != null
|
|
2672
|
+
? { recommendedModel: stopDetails.recommended_model }
|
|
2673
|
+
: {}),
|
|
2674
|
+
};
|
|
2675
|
+
}
|