@ai-sdk/anthropic 3.0.39 → 3.0.41
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 +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +166 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +166 -30
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +165 -29
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +165 -29
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +106 -11
- package/package.json +1 -1
- package/src/anthropic-message-metadata.ts +38 -0
- package/src/anthropic-messages-api.ts +58 -2
- package/src/anthropic-messages-language-model.ts +82 -2
- package/src/anthropic-messages-options.ts +11 -0
- package/src/convert-anthropic-messages-usage.ts +48 -7
- package/src/convert-to-anthropic-messages-prompt.ts +24 -11
- package/src/index.ts +4 -1
- package/src/map-anthropic-stop-reason.ts +2 -0
package/docs/05-anthropic.mdx
CHANGED
|
@@ -290,6 +290,98 @@ const result = await generateText({
|
|
|
290
290
|
});
|
|
291
291
|
```
|
|
292
292
|
|
|
293
|
+
#### Compaction
|
|
294
|
+
|
|
295
|
+
The `compact_20260112` edit type automatically summarizes earlier conversation context when token limits are reached. This is useful for long-running conversations where you want to preserve the essence of earlier exchanges while staying within token limits.
|
|
296
|
+
|
|
297
|
+
```ts highlight="7-19"
|
|
298
|
+
import { anthropic, AnthropicProviderOptions } from '@ai-sdk/anthropic';
|
|
299
|
+
import { streamText } from 'ai';
|
|
300
|
+
|
|
301
|
+
const result = streamText({
|
|
302
|
+
model: anthropic('claude-opus-4-6'),
|
|
303
|
+
messages: conversationHistory,
|
|
304
|
+
providerOptions: {
|
|
305
|
+
anthropic: {
|
|
306
|
+
contextManagement: {
|
|
307
|
+
edits: [
|
|
308
|
+
{
|
|
309
|
+
type: 'compact_20260112',
|
|
310
|
+
trigger: {
|
|
311
|
+
type: 'input_tokens',
|
|
312
|
+
value: 50000, // trigger compaction when input exceeds 50k tokens
|
|
313
|
+
},
|
|
314
|
+
instructions:
|
|
315
|
+
'Summarize the conversation concisely, preserving key decisions and context.',
|
|
316
|
+
pauseAfterCompaction: false,
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
} satisfies AnthropicProviderOptions,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Configuration:**
|
|
326
|
+
|
|
327
|
+
- **trigger** - Condition that triggers compaction (e.g., `{ type: 'input_tokens', value: 50000 }`)
|
|
328
|
+
- **instructions** - Custom instructions for how the model should summarize the conversation. Use this to guide the compaction summary towards specific aspects of the conversation you want to preserve.
|
|
329
|
+
- **pauseAfterCompaction** - When `true`, the model will pause after generating the compaction summary, allowing you to inspect or process it before continuing. Defaults to `false`.
|
|
330
|
+
|
|
331
|
+
When compaction occurs, the model generates a summary of the earlier context. This summary appears as a text block with special provider metadata.
|
|
332
|
+
|
|
333
|
+
##### Detecting Compaction in Streams
|
|
334
|
+
|
|
335
|
+
When using `streamText`, you can detect compaction summaries by checking the `providerMetadata` on `text-start` events:
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
for await (const part of result.fullStream) {
|
|
339
|
+
switch (part.type) {
|
|
340
|
+
case 'text-start': {
|
|
341
|
+
const isCompaction =
|
|
342
|
+
part.providerMetadata?.anthropic?.type === 'compaction';
|
|
343
|
+
if (isCompaction) {
|
|
344
|
+
console.log('[COMPACTION SUMMARY START]');
|
|
345
|
+
}
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
case 'text-delta': {
|
|
349
|
+
process.stdout.write(part.text);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
##### Compaction in UI Applications
|
|
357
|
+
|
|
358
|
+
When using `useChat` or other UI hooks, compaction summaries appear as regular text parts with `providerMetadata`. You can style them differently in your UI:
|
|
359
|
+
|
|
360
|
+
```tsx
|
|
361
|
+
{
|
|
362
|
+
message.parts.map((part, index) => {
|
|
363
|
+
if (part.type === 'text') {
|
|
364
|
+
const isCompaction =
|
|
365
|
+
(part.providerMetadata?.anthropic as { type?: string } | undefined)
|
|
366
|
+
?.type === 'compaction';
|
|
367
|
+
|
|
368
|
+
if (isCompaction) {
|
|
369
|
+
return (
|
|
370
|
+
<div
|
|
371
|
+
key={index}
|
|
372
|
+
className="bg-yellow-100 border-l-4 border-yellow-500 p-2"
|
|
373
|
+
>
|
|
374
|
+
<span className="font-bold">[Compaction Summary]</span>
|
|
375
|
+
<div>{part.text}</div>
|
|
376
|
+
</div>
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
return <div key={index}>{part.text}</div>;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
293
385
|
#### Applied Edits Metadata
|
|
294
386
|
|
|
295
387
|
After generation, you can check which edits were applied in the provider metadata:
|
|
@@ -305,6 +397,9 @@ if (metadata?.appliedEdits) {
|
|
|
305
397
|
} else if (edit.type === 'clear_thinking_20251015') {
|
|
306
398
|
console.log(`Cleared ${edit.clearedThinkingTurns} thinking turns`);
|
|
307
399
|
console.log(`Freed ${edit.clearedInputTokens} tokens`);
|
|
400
|
+
} else if (edit.type === 'compact_20260112') {
|
|
401
|
+
console.log('Compaction was applied');
|
|
402
|
+
console.log(`Freed ${edit.clearedInputTokens} tokens`);
|
|
308
403
|
}
|
|
309
404
|
});
|
|
310
405
|
}
|
|
@@ -1174,17 +1269,17 @@ and the `mediaType` should be set to `'application/pdf'`.
|
|
|
1174
1269
|
|
|
1175
1270
|
### Model Capabilities
|
|
1176
1271
|
|
|
1177
|
-
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search |
|
|
1178
|
-
| -------------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
1179
|
-
| `claude-opus-4-6` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1180
|
-
| `claude-opus-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1181
|
-
| `claude-haiku-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1182
|
-
| `claude-sonnet-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1183
|
-
| `claude-opus-4-1` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1184
|
-
| `claude-opus-4-0` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1185
|
-
| `claude-sonnet-4-0` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1186
|
-
| `claude-3-7-sonnet-latest` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1187
|
-
| `claude-3-5-haiku-latest` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1272
|
+
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
|
|
1273
|
+
| -------------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
1274
|
+
| `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} /> |
|
|
1275
|
+
| `claude-opus-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1276
|
+
| `claude-haiku-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1277
|
+
| `claude-sonnet-4-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | |
|
|
1278
|
+
| `claude-opus-4-1` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1279
|
+
| `claude-opus-4-0` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1280
|
+
| `claude-sonnet-4-0` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1281
|
+
| `claude-3-7-sonnet-latest` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1282
|
+
| `claude-3-5-haiku-latest` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | | |
|
|
1188
1283
|
|
|
1189
1284
|
<Note>
|
|
1190
1285
|
The table above lists popular models. Please see the [Anthropic
|
package/package.json
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { JSONObject } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Represents a single iteration in the usage breakdown.
|
|
5
|
+
* When compaction occurs, the API returns an iterations array showing
|
|
6
|
+
* usage for each sampling iteration (compaction + message).
|
|
7
|
+
*/
|
|
8
|
+
export interface AnthropicUsageIteration {
|
|
9
|
+
type: 'compaction' | 'message';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Number of input tokens consumed in this iteration.
|
|
13
|
+
*/
|
|
14
|
+
inputTokens: number;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Number of output tokens generated in this iteration.
|
|
18
|
+
*/
|
|
19
|
+
outputTokens: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
3
22
|
export interface AnthropicMessageMetadata {
|
|
4
23
|
usage: JSONObject;
|
|
5
24
|
// TODO remove cacheCreationInputTokens in AI SDK 6
|
|
@@ -7,6 +26,15 @@ export interface AnthropicMessageMetadata {
|
|
|
7
26
|
cacheCreationInputTokens: number | null;
|
|
8
27
|
stopSequence: string | null;
|
|
9
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Usage breakdown by iteration when compaction is triggered.
|
|
31
|
+
*
|
|
32
|
+
* When compaction occurs, this array contains usage for each sampling iteration.
|
|
33
|
+
* The first iteration is typically the compaction step, followed by the main
|
|
34
|
+
* message iteration.
|
|
35
|
+
*/
|
|
36
|
+
iterations: AnthropicUsageIteration[] | null;
|
|
37
|
+
|
|
10
38
|
/**
|
|
11
39
|
* Information about the container used in this request.
|
|
12
40
|
*
|
|
@@ -100,6 +128,16 @@ export interface AnthropicMessageMetadata {
|
|
|
100
128
|
*/
|
|
101
129
|
clearedInputTokens: number;
|
|
102
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Represents a compaction edit where the conversation context was summarized.
|
|
133
|
+
*/
|
|
134
|
+
| {
|
|
135
|
+
/**
|
|
136
|
+
* The type of context management edit applied.
|
|
137
|
+
* Possible value: 'compact_20260112'
|
|
138
|
+
*/
|
|
139
|
+
type: 'compact_20260112';
|
|
140
|
+
}
|
|
103
141
|
>;
|
|
104
142
|
} | null;
|
|
105
143
|
}
|
|
@@ -40,9 +40,16 @@ export interface AnthropicAssistantMessage {
|
|
|
40
40
|
| AnthropicTextEditorCodeExecutionToolResultContent
|
|
41
41
|
| AnthropicMcpToolUseContent
|
|
42
42
|
| AnthropicMcpToolResultContent
|
|
43
|
+
| AnthropicCompactionContent
|
|
43
44
|
>;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
export interface AnthropicCompactionContent {
|
|
48
|
+
type: 'compaction';
|
|
49
|
+
content: string;
|
|
50
|
+
cache_control?: AnthropicCacheControl;
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
export interface AnthropicTextContent {
|
|
47
54
|
type: 'text';
|
|
48
55
|
text: string;
|
|
@@ -479,9 +486,17 @@ export type AnthropicClearThinkingBlockEdit = {
|
|
|
479
486
|
keep?: 'all' | { type: 'thinking_turns'; value: number };
|
|
480
487
|
};
|
|
481
488
|
|
|
489
|
+
export type AnthropicCompactEdit = {
|
|
490
|
+
type: 'compact_20260112';
|
|
491
|
+
trigger?: AnthropicInputTokensTrigger;
|
|
492
|
+
pause_after_compaction?: boolean;
|
|
493
|
+
instructions?: string;
|
|
494
|
+
};
|
|
495
|
+
|
|
482
496
|
export type AnthropicContextManagementEdit =
|
|
483
497
|
| AnthropicClearToolUsesEdit
|
|
484
|
-
| AnthropicClearThinkingBlockEdit
|
|
498
|
+
| AnthropicClearThinkingBlockEdit
|
|
499
|
+
| AnthropicCompactEdit;
|
|
485
500
|
|
|
486
501
|
export type AnthropicContextManagementConfig = {
|
|
487
502
|
edits: AnthropicContextManagementEdit[];
|
|
@@ -499,9 +514,14 @@ export type AnthropicResponseClearThinkingBlockEdit = {
|
|
|
499
514
|
cleared_input_tokens: number;
|
|
500
515
|
};
|
|
501
516
|
|
|
517
|
+
export type AnthropicResponseCompactEdit = {
|
|
518
|
+
type: 'compact_20260112';
|
|
519
|
+
};
|
|
520
|
+
|
|
502
521
|
export type AnthropicResponseContextManagementEdit =
|
|
503
522
|
| AnthropicResponseClearToolUsesEdit
|
|
504
|
-
| AnthropicResponseClearThinkingBlockEdit
|
|
523
|
+
| AnthropicResponseClearThinkingBlockEdit
|
|
524
|
+
| AnthropicResponseCompactEdit;
|
|
505
525
|
|
|
506
526
|
export type AnthropicResponseContextManagement = {
|
|
507
527
|
applied_edits: AnthropicResponseContextManagementEdit[];
|
|
@@ -559,6 +579,10 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
559
579
|
type: z.literal('redacted_thinking'),
|
|
560
580
|
data: z.string(),
|
|
561
581
|
}),
|
|
582
|
+
z.object({
|
|
583
|
+
type: z.literal('compaction'),
|
|
584
|
+
content: z.string(),
|
|
585
|
+
}),
|
|
562
586
|
z.object({
|
|
563
587
|
type: z.literal('tool_use'),
|
|
564
588
|
id: z.string(),
|
|
@@ -763,6 +787,15 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
763
787
|
output_tokens: z.number(),
|
|
764
788
|
cache_creation_input_tokens: z.number().nullish(),
|
|
765
789
|
cache_read_input_tokens: z.number().nullish(),
|
|
790
|
+
iterations: z
|
|
791
|
+
.array(
|
|
792
|
+
z.object({
|
|
793
|
+
type: z.union([z.literal('compaction'), z.literal('message')]),
|
|
794
|
+
input_tokens: z.number(),
|
|
795
|
+
output_tokens: z.number(),
|
|
796
|
+
}),
|
|
797
|
+
)
|
|
798
|
+
.nullish(),
|
|
766
799
|
}),
|
|
767
800
|
container: z
|
|
768
801
|
.object({
|
|
@@ -793,6 +826,9 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
|
|
|
793
826
|
cleared_thinking_turns: z.number(),
|
|
794
827
|
cleared_input_tokens: z.number(),
|
|
795
828
|
}),
|
|
829
|
+
z.object({
|
|
830
|
+
type: z.literal('compact_20260112'),
|
|
831
|
+
}),
|
|
796
832
|
]),
|
|
797
833
|
),
|
|
798
834
|
})
|
|
@@ -885,6 +921,10 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
885
921
|
type: z.literal('redacted_thinking'),
|
|
886
922
|
data: z.string(),
|
|
887
923
|
}),
|
|
924
|
+
z.object({
|
|
925
|
+
type: z.literal('compaction'),
|
|
926
|
+
content: z.string().nullish(),
|
|
927
|
+
}),
|
|
888
928
|
z.object({
|
|
889
929
|
type: z.literal('server_tool_use'),
|
|
890
930
|
id: z.string(),
|
|
@@ -1084,6 +1124,10 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1084
1124
|
type: z.literal('signature_delta'),
|
|
1085
1125
|
signature: z.string(),
|
|
1086
1126
|
}),
|
|
1127
|
+
z.object({
|
|
1128
|
+
type: z.literal('compaction_delta'),
|
|
1129
|
+
content: z.string(),
|
|
1130
|
+
}),
|
|
1087
1131
|
z.object({
|
|
1088
1132
|
type: z.literal('citations_delta'),
|
|
1089
1133
|
citation: z.discriminatedUnion('type', [
|
|
@@ -1154,6 +1198,15 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1154
1198
|
output_tokens: z.number(),
|
|
1155
1199
|
cache_creation_input_tokens: z.number().nullish(),
|
|
1156
1200
|
cache_read_input_tokens: z.number().nullish(),
|
|
1201
|
+
iterations: z
|
|
1202
|
+
.array(
|
|
1203
|
+
z.object({
|
|
1204
|
+
type: z.union([z.literal('compaction'), z.literal('message')]),
|
|
1205
|
+
input_tokens: z.number(),
|
|
1206
|
+
output_tokens: z.number(),
|
|
1207
|
+
}),
|
|
1208
|
+
)
|
|
1209
|
+
.nullish(),
|
|
1157
1210
|
}),
|
|
1158
1211
|
context_management: z
|
|
1159
1212
|
.object({
|
|
@@ -1169,6 +1222,9 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
|
|
|
1169
1222
|
cleared_thinking_turns: z.number(),
|
|
1170
1223
|
cleared_input_tokens: z.number(),
|
|
1171
1224
|
}),
|
|
1225
|
+
z.object({
|
|
1226
|
+
type: z.literal('compact_20260112'),
|
|
1227
|
+
}),
|
|
1172
1228
|
]),
|
|
1173
1229
|
),
|
|
1174
1230
|
})
|
|
@@ -433,6 +433,20 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
433
433
|
...(edit.keep !== undefined && { keep: edit.keep }),
|
|
434
434
|
};
|
|
435
435
|
|
|
436
|
+
case 'compact_20260112':
|
|
437
|
+
return {
|
|
438
|
+
type: edit.type,
|
|
439
|
+
...(edit.trigger !== undefined && {
|
|
440
|
+
trigger: edit.trigger,
|
|
441
|
+
}),
|
|
442
|
+
...(edit.pauseAfterCompaction !== undefined && {
|
|
443
|
+
pause_after_compaction: edit.pauseAfterCompaction,
|
|
444
|
+
}),
|
|
445
|
+
...(edit.instructions !== undefined && {
|
|
446
|
+
instructions: edit.instructions,
|
|
447
|
+
}),
|
|
448
|
+
};
|
|
449
|
+
|
|
436
450
|
default:
|
|
437
451
|
warnings.push({
|
|
438
452
|
type: 'other',
|
|
@@ -528,6 +542,11 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
528
542
|
|
|
529
543
|
if (contextManagement) {
|
|
530
544
|
betas.add('context-management-2025-06-27');
|
|
545
|
+
|
|
546
|
+
// Add compaction beta if compact edit is present
|
|
547
|
+
if (contextManagement.edits.some(e => e.type === 'compact_20260112')) {
|
|
548
|
+
betas.add('compact-2026-01-12');
|
|
549
|
+
}
|
|
531
550
|
}
|
|
532
551
|
|
|
533
552
|
if (
|
|
@@ -796,6 +815,18 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
796
815
|
});
|
|
797
816
|
break;
|
|
798
817
|
}
|
|
818
|
+
case 'compaction': {
|
|
819
|
+
content.push({
|
|
820
|
+
type: 'text',
|
|
821
|
+
text: part.content,
|
|
822
|
+
providerMetadata: {
|
|
823
|
+
anthropic: {
|
|
824
|
+
type: 'compaction',
|
|
825
|
+
},
|
|
826
|
+
},
|
|
827
|
+
});
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
799
830
|
case 'tool_use': {
|
|
800
831
|
const isJsonResponseTool =
|
|
801
832
|
usesJsonResponseTool && part.name === 'json';
|
|
@@ -1098,7 +1129,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1098
1129
|
}),
|
|
1099
1130
|
raw: response.stop_reason ?? undefined,
|
|
1100
1131
|
},
|
|
1101
|
-
usage: convertAnthropicMessagesUsage(response.usage),
|
|
1132
|
+
usage: convertAnthropicMessagesUsage({ usage: response.usage }),
|
|
1102
1133
|
request: { body: args },
|
|
1103
1134
|
response: {
|
|
1104
1135
|
id: response.id ?? undefined,
|
|
@@ -1113,6 +1144,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1113
1144
|
cacheCreationInputTokens:
|
|
1114
1145
|
response.usage.cache_creation_input_tokens ?? null,
|
|
1115
1146
|
stopSequence: response.stop_sequence ?? null,
|
|
1147
|
+
|
|
1148
|
+
iterations: response.usage.iterations
|
|
1149
|
+
? response.usage.iterations.map(iter => ({
|
|
1150
|
+
type: iter.type,
|
|
1151
|
+
inputTokens: iter.input_tokens,
|
|
1152
|
+
outputTokens: iter.output_tokens,
|
|
1153
|
+
}))
|
|
1154
|
+
: null,
|
|
1116
1155
|
container: response.container
|
|
1117
1156
|
? {
|
|
1118
1157
|
expiresAt: response.container.expires_at,
|
|
@@ -1188,6 +1227,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1188
1227
|
output_tokens: 0,
|
|
1189
1228
|
cache_creation_input_tokens: 0,
|
|
1190
1229
|
cache_read_input_tokens: 0,
|
|
1230
|
+
iterations: null,
|
|
1191
1231
|
};
|
|
1192
1232
|
|
|
1193
1233
|
const contentBlocks: Record<
|
|
@@ -1233,6 +1273,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1233
1273
|
| 'tool_search_tool_result'
|
|
1234
1274
|
| 'mcp_tool_use'
|
|
1235
1275
|
| 'mcp_tool_result'
|
|
1276
|
+
| 'compaction'
|
|
1236
1277
|
| undefined = undefined;
|
|
1237
1278
|
|
|
1238
1279
|
const generateId = this.generateId;
|
|
@@ -1307,6 +1348,20 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1307
1348
|
return;
|
|
1308
1349
|
}
|
|
1309
1350
|
|
|
1351
|
+
case 'compaction': {
|
|
1352
|
+
contentBlocks[value.index] = { type: 'text' };
|
|
1353
|
+
controller.enqueue({
|
|
1354
|
+
type: 'text-start',
|
|
1355
|
+
id: String(value.index),
|
|
1356
|
+
providerMetadata: {
|
|
1357
|
+
anthropic: {
|
|
1358
|
+
type: 'compaction',
|
|
1359
|
+
},
|
|
1360
|
+
},
|
|
1361
|
+
});
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1310
1365
|
case 'tool_use': {
|
|
1311
1366
|
const isJsonResponseTool =
|
|
1312
1367
|
usesJsonResponseTool && part.name === 'json';
|
|
@@ -1784,6 +1839,16 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1784
1839
|
return;
|
|
1785
1840
|
}
|
|
1786
1841
|
|
|
1842
|
+
case 'compaction_delta': {
|
|
1843
|
+
controller.enqueue({
|
|
1844
|
+
type: 'text-delta',
|
|
1845
|
+
id: String(value.index),
|
|
1846
|
+
delta: value.delta.content,
|
|
1847
|
+
});
|
|
1848
|
+
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1787
1852
|
case 'input_json_delta': {
|
|
1788
1853
|
const contentBlock = contentBlocks[value.index];
|
|
1789
1854
|
let delta = value.delta.partial_json;
|
|
@@ -1972,6 +2037,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1972
2037
|
cacheCreationInputTokens =
|
|
1973
2038
|
value.usage.cache_creation_input_tokens;
|
|
1974
2039
|
}
|
|
2040
|
+
if (value.usage.iterations != null) {
|
|
2041
|
+
usage.iterations = value.usage.iterations;
|
|
2042
|
+
}
|
|
1975
2043
|
|
|
1976
2044
|
finishReason = {
|
|
1977
2045
|
unified: mapAnthropicStopReason({
|
|
@@ -2015,6 +2083,13 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2015
2083
|
usage: (rawUsage as JSONObject) ?? null,
|
|
2016
2084
|
cacheCreationInputTokens,
|
|
2017
2085
|
stopSequence,
|
|
2086
|
+
iterations: usage.iterations
|
|
2087
|
+
? usage.iterations.map(iter => ({
|
|
2088
|
+
type: iter.type,
|
|
2089
|
+
inputTokens: iter.input_tokens,
|
|
2090
|
+
outputTokens: iter.output_tokens,
|
|
2091
|
+
}))
|
|
2092
|
+
: null,
|
|
2018
2093
|
container,
|
|
2019
2094
|
contextManagement,
|
|
2020
2095
|
} satisfies AnthropicMessageMetadata;
|
|
@@ -2033,7 +2108,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2033
2108
|
controller.enqueue({
|
|
2034
2109
|
type: 'finish',
|
|
2035
2110
|
finishReason,
|
|
2036
|
-
usage: convertAnthropicMessagesUsage(usage),
|
|
2111
|
+
usage: convertAnthropicMessagesUsage({ usage, rawUsage }),
|
|
2037
2112
|
providerMetadata,
|
|
2038
2113
|
});
|
|
2039
2114
|
return;
|
|
@@ -2188,6 +2263,11 @@ function mapAnthropicResponseContextManagement(
|
|
|
2188
2263
|
clearedThinkingTurns: edit.cleared_thinking_turns,
|
|
2189
2264
|
clearedInputTokens: edit.cleared_input_tokens,
|
|
2190
2265
|
};
|
|
2266
|
+
|
|
2267
|
+
case 'compact_20260112':
|
|
2268
|
+
return {
|
|
2269
|
+
type: edit.type,
|
|
2270
|
+
};
|
|
2191
2271
|
}
|
|
2192
2272
|
})
|
|
2193
2273
|
.filter(edit => edit !== undefined),
|
|
@@ -221,6 +221,17 @@ export const anthropicProviderOptions = z.object({
|
|
|
221
221
|
])
|
|
222
222
|
.optional(),
|
|
223
223
|
}),
|
|
224
|
+
z.object({
|
|
225
|
+
type: z.literal('compact_20260112'),
|
|
226
|
+
trigger: z
|
|
227
|
+
.object({
|
|
228
|
+
type: z.literal('input_tokens'),
|
|
229
|
+
value: z.number(),
|
|
230
|
+
})
|
|
231
|
+
.optional(),
|
|
232
|
+
pauseAfterCompaction: z.boolean().optional(),
|
|
233
|
+
instructions: z.string().optional(),
|
|
234
|
+
}),
|
|
224
235
|
]),
|
|
225
236
|
),
|
|
226
237
|
})
|
|
@@ -1,20 +1,61 @@
|
|
|
1
|
-
import { LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
1
|
+
import { JSONObject, LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a single iteration in the usage breakdown.
|
|
5
|
+
* When compaction occurs, the API returns an iterations array showing
|
|
6
|
+
* usage for each sampling iteration (compaction + message).
|
|
7
|
+
*/
|
|
8
|
+
export type AnthropicUsageIteration = {
|
|
9
|
+
type: 'compaction' | 'message';
|
|
10
|
+
input_tokens: number;
|
|
11
|
+
output_tokens: number;
|
|
12
|
+
};
|
|
2
13
|
|
|
3
14
|
export type AnthropicMessagesUsage = {
|
|
4
15
|
input_tokens: number;
|
|
5
16
|
output_tokens: number;
|
|
6
17
|
cache_creation_input_tokens?: number | null;
|
|
7
18
|
cache_read_input_tokens?: number | null;
|
|
19
|
+
/**
|
|
20
|
+
* When compaction is triggered, this array contains usage for each
|
|
21
|
+
* sampling iteration. The top-level input_tokens and output_tokens
|
|
22
|
+
* do NOT include compaction iteration usage - to get total tokens
|
|
23
|
+
* consumed and billed, sum across all entries in this array.
|
|
24
|
+
*/
|
|
25
|
+
iterations?: AnthropicUsageIteration[] | null;
|
|
8
26
|
};
|
|
9
27
|
|
|
10
|
-
export function convertAnthropicMessagesUsage(
|
|
11
|
-
usage
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
export function convertAnthropicMessagesUsage({
|
|
29
|
+
usage,
|
|
30
|
+
rawUsage,
|
|
31
|
+
}: {
|
|
32
|
+
usage: AnthropicMessagesUsage;
|
|
33
|
+
rawUsage?: JSONObject;
|
|
34
|
+
}): LanguageModelV3Usage {
|
|
15
35
|
const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
|
|
16
36
|
const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
|
|
17
37
|
|
|
38
|
+
// When iterations is present (compaction occurred), sum across all iterations
|
|
39
|
+
// to get the true total tokens consumed/billed. The top-level input_tokens
|
|
40
|
+
// and output_tokens exclude compaction iteration usage.
|
|
41
|
+
let inputTokens: number;
|
|
42
|
+
let outputTokens: number;
|
|
43
|
+
|
|
44
|
+
if (usage.iterations && usage.iterations.length > 0) {
|
|
45
|
+
const totals = usage.iterations.reduce(
|
|
46
|
+
(acc, iter) => ({
|
|
47
|
+
input: acc.input + iter.input_tokens,
|
|
48
|
+
output: acc.output + iter.output_tokens,
|
|
49
|
+
}),
|
|
50
|
+
{ input: 0, output: 0 },
|
|
51
|
+
);
|
|
52
|
+
inputTokens = totals.input;
|
|
53
|
+
outputTokens = totals.output;
|
|
54
|
+
} else {
|
|
55
|
+
inputTokens = usage.input_tokens;
|
|
56
|
+
outputTokens = usage.output_tokens;
|
|
57
|
+
}
|
|
58
|
+
|
|
18
59
|
return {
|
|
19
60
|
inputTokens: {
|
|
20
61
|
total: inputTokens + cacheCreationTokens + cacheReadTokens,
|
|
@@ -27,6 +68,6 @@ export function convertAnthropicMessagesUsage(
|
|
|
27
68
|
text: undefined,
|
|
28
69
|
reasoning: undefined,
|
|
29
70
|
},
|
|
30
|
-
raw: usage,
|
|
71
|
+
raw: rawUsage ?? usage,
|
|
31
72
|
};
|
|
32
73
|
}
|
|
@@ -456,18 +456,31 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
456
456
|
|
|
457
457
|
switch (part.type) {
|
|
458
458
|
case 'text': {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
// because Anthropic does not allow trailing whitespace
|
|
464
|
-
// in pre-filled assistant responses
|
|
465
|
-
isLastBlock && isLastMessage && isLastContentPart
|
|
466
|
-
? part.text.trim()
|
|
467
|
-
: part.text,
|
|
459
|
+
// Check if this is a compaction block (via providerMetadata)
|
|
460
|
+
const textMetadata = part.providerOptions?.anthropic as
|
|
461
|
+
| { type?: string }
|
|
462
|
+
| undefined;
|
|
468
463
|
|
|
469
|
-
|
|
470
|
-
|
|
464
|
+
if (textMetadata?.type === 'compaction') {
|
|
465
|
+
anthropicContent.push({
|
|
466
|
+
type: 'compaction',
|
|
467
|
+
content: part.text,
|
|
468
|
+
cache_control: cacheControl,
|
|
469
|
+
});
|
|
470
|
+
} else {
|
|
471
|
+
anthropicContent.push({
|
|
472
|
+
type: 'text',
|
|
473
|
+
text:
|
|
474
|
+
// trim the last text part if it's the last message in the block
|
|
475
|
+
// because Anthropic does not allow trailing whitespace
|
|
476
|
+
// in pre-filled assistant responses
|
|
477
|
+
isLastBlock && isLastMessage && isLastContentPart
|
|
478
|
+
? part.text.trim()
|
|
479
|
+
: part.text,
|
|
480
|
+
|
|
481
|
+
cache_control: cacheControl,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
471
484
|
break;
|
|
472
485
|
}
|
|
473
486
|
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type {
|
|
2
|
+
AnthropicMessageMetadata,
|
|
3
|
+
AnthropicUsageIteration,
|
|
4
|
+
} from './anthropic-message-metadata';
|
|
2
5
|
export type { AnthropicProviderOptions } from './anthropic-messages-options';
|
|
3
6
|
export type { AnthropicToolOptions } from './anthropic-prepare-tools';
|
|
4
7
|
export { anthropic, createAnthropic } from './anthropic-provider';
|