@ai-sdk/anthropic 3.0.114 → 3.0.116
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 +13 -0
- package/dist/index.d.mts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +109 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -35
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +1 -1
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +108 -34
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +108 -34
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +109 -1
- package/package.json +2 -2
- package/src/anthropic-messages-api.ts +4 -0
- package/src/anthropic-messages-language-model.ts +32 -8
- package/src/anthropic-messages-options.ts +56 -17
- package/src/convert-to-anthropic-messages-prompt.ts +51 -12
package/docs/05-anthropic.mdx
CHANGED
|
@@ -189,9 +189,14 @@ const result = streamText({
|
|
|
189
189
|
});
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
For `claude-fable-5-1`, the default `"auto"` mode uses native structured
|
|
193
|
+
outputs through `output_config.format`. Fable 5.1 rejects forced tool use, so
|
|
194
|
+
do not use `"jsonTool"` or a required or named tool choice to implement
|
|
195
|
+
structured output with this model.
|
|
196
|
+
|
|
192
197
|
### Effort
|
|
193
198
|
|
|
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.
|
|
199
|
+
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`, `claude-fable-5-1`, and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
|
|
195
200
|
|
|
196
201
|
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.
|
|
197
202
|
|
|
@@ -439,6 +444,55 @@ console.log(text);
|
|
|
439
444
|
progress during thinking.
|
|
440
445
|
</Note>
|
|
441
446
|
|
|
447
|
+
##### Thinking Updates
|
|
448
|
+
|
|
449
|
+
Use `display: 'updates'` with `claude-fable-5-1` to stream thinking summaries
|
|
450
|
+
between tool calls:
|
|
451
|
+
|
|
452
|
+
```ts highlight="12-16"
|
|
453
|
+
import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
|
|
454
|
+
import { streamText, tool } from 'ai';
|
|
455
|
+
import { z } from 'zod';
|
|
456
|
+
|
|
457
|
+
const result = streamText({
|
|
458
|
+
model: anthropic('claude-fable-5-1'),
|
|
459
|
+
tools: {
|
|
460
|
+
weather: tool({
|
|
461
|
+
inputSchema: z.object({ city: z.string() }),
|
|
462
|
+
}),
|
|
463
|
+
},
|
|
464
|
+
providerOptions: {
|
|
465
|
+
anthropic: {
|
|
466
|
+
thinking: { type: 'adaptive', display: 'updates' },
|
|
467
|
+
} satisfies AnthropicLanguageModelOptions,
|
|
468
|
+
},
|
|
469
|
+
prompt: 'Compare the weather in San Francisco and New York.',
|
|
470
|
+
});
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
##### Thinking Block Binding
|
|
474
|
+
|
|
475
|
+
Fable 5.1 can recover from a thinking-block prefix mismatch by dropping the
|
|
476
|
+
mismatched block. Set `blockBinding.prefixMismatchBehavior` to `drop_block`.
|
|
477
|
+
You can provide block binding by itself to preserve the model's default
|
|
478
|
+
thinking mode, or combine it with adaptive thinking.
|
|
479
|
+
|
|
480
|
+
```ts highlight="7-11"
|
|
481
|
+
const { text } = await generateText({
|
|
482
|
+
model: anthropic('claude-fable-5-1'),
|
|
483
|
+
prompt: 'Continue from this conversation.',
|
|
484
|
+
providerOptions: {
|
|
485
|
+
anthropic: {
|
|
486
|
+
thinking: {
|
|
487
|
+
blockBinding: {
|
|
488
|
+
prefixMismatchBehavior: 'drop_block',
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
} satisfies AnthropicLanguageModelOptions,
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
```
|
|
495
|
+
|
|
442
496
|
#### Budget-Based Thinking
|
|
443
497
|
|
|
444
498
|
For earlier models (`claude-opus-4-20250514`, `claude-sonnet-4-20250514`, `claude-sonnet-4-5-20250929`),
|
|
@@ -1203,6 +1257,59 @@ const result = await generateText({
|
|
|
1203
1257
|
|
|
1204
1258
|
This sends `tool_reference` blocks to Anthropic, which loads the corresponding deferred tool schemas into Claude's context.
|
|
1205
1259
|
|
|
1260
|
+
### Mid-Conversation System Controls
|
|
1261
|
+
|
|
1262
|
+
With `claude-fable-5-1`, a mid-conversation system message can be cleared
|
|
1263
|
+
before the next user message with `clearAt: 'next_user_message'`, or set the
|
|
1264
|
+
effort for the next turn. The provider adds the required
|
|
1265
|
+
`mid-conversation-system-clear-at-2026-08-21` and
|
|
1266
|
+
`mid-conversation-effort-2026-08-01` beta headers automatically.
|
|
1267
|
+
|
|
1268
|
+
```ts highlight="17-25"
|
|
1269
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
1270
|
+
import { generateText } from 'ai';
|
|
1271
|
+
|
|
1272
|
+
const result = await generateText({
|
|
1273
|
+
model: anthropic('claude-fable-5-1'),
|
|
1274
|
+
allowSystemInMessages: true,
|
|
1275
|
+
messages: [
|
|
1276
|
+
{
|
|
1277
|
+
role: 'user',
|
|
1278
|
+
content: 'Draft a migration plan.',
|
|
1279
|
+
},
|
|
1280
|
+
{
|
|
1281
|
+
role: 'assistant',
|
|
1282
|
+
content: 'First, inventory the public API.',
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
role: 'system',
|
|
1286
|
+
content: 'For the next turn, verify every compatibility claim.',
|
|
1287
|
+
providerOptions: {
|
|
1288
|
+
anthropic: {
|
|
1289
|
+
clearAt: 'next_user_message',
|
|
1290
|
+
effort: 'high',
|
|
1291
|
+
},
|
|
1292
|
+
},
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
role: 'user',
|
|
1296
|
+
content: 'Complete the plan.',
|
|
1297
|
+
},
|
|
1298
|
+
],
|
|
1299
|
+
});
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1302
|
+
An effort-only system message can use an empty content array at the API level;
|
|
1303
|
+
in an AI SDK prompt, set `content: ''`. The provider serializes it as
|
|
1304
|
+
`content: []`.
|
|
1305
|
+
|
|
1306
|
+
<Note>
|
|
1307
|
+
`clearAt` and per-message `effort` apply only to mid-conversation system
|
|
1308
|
+
messages. When used on the initial system message, the provider ignores them
|
|
1309
|
+
and emits a warning. Use the top-level `effort` provider option to configure
|
|
1310
|
+
effort for the full request.
|
|
1311
|
+
</Note>
|
|
1312
|
+
|
|
1206
1313
|
### Mid-Conversation Tool Changes
|
|
1207
1314
|
|
|
1208
1315
|
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.
|
|
@@ -1640,6 +1747,7 @@ and the `mediaType` should be set to `'application/pdf'`.
|
|
|
1640
1747
|
|
|
1641
1748
|
| Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
|
|
1642
1749
|
| ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
1750
|
+
| `claude-fable-5-1` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1643
1751
|
| `claude-opus-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1644
1752
|
| `claude-sonnet-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
1645
1753
|
| `claude-fable-5` | <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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/anthropic",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.116",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@ai-sdk/provider": "3.0.15",
|
|
40
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
40
|
+
"@ai-sdk/provider-utils": "4.0.50"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "20.17.24",
|
|
@@ -24,6 +24,10 @@ export type AnthropicCacheControl = {
|
|
|
24
24
|
export interface AnthropicSystemMessage {
|
|
25
25
|
role: 'system';
|
|
26
26
|
content: Array<AnthropicTextContent | AnthropicToolChangeContent>;
|
|
27
|
+
clear_at?: 'next_user_message';
|
|
28
|
+
output_config?: {
|
|
29
|
+
effort: 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
30
|
+
};
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
/**
|
|
@@ -418,13 +418,17 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
418
418
|
toolNameMapping,
|
|
419
419
|
});
|
|
420
420
|
|
|
421
|
+
const thinking = anthropicOptions?.thinking;
|
|
422
|
+
const thinkingType =
|
|
423
|
+
thinking != null && 'type' in thinking ? thinking.type : undefined;
|
|
424
|
+
|
|
421
425
|
// Newer models only allow disabling thinking at effort levels up to and
|
|
422
426
|
// including `high`; at `xhigh` and `max` the API returns a 400. Lower
|
|
423
427
|
// the effort to `high` to preserve the explicit request to run without
|
|
424
428
|
// thinking.
|
|
425
429
|
if (
|
|
426
430
|
rejectsThinkingDisabledAboveHighEffort &&
|
|
427
|
-
|
|
431
|
+
thinkingType === 'disabled' &&
|
|
428
432
|
(anthropicOptions.effort === 'xhigh' || anthropicOptions.effort === 'max')
|
|
429
433
|
) {
|
|
430
434
|
warnings.push({
|
|
@@ -437,7 +441,6 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
437
441
|
anthropicOptions.effort = 'high';
|
|
438
442
|
}
|
|
439
443
|
|
|
440
|
-
const thinkingType = anthropicOptions?.thinking?.type;
|
|
441
444
|
const isThinking =
|
|
442
445
|
thinkingType === 'enabled' || thinkingType === 'adaptive';
|
|
443
446
|
// `disabled` must still be forwarded to the API: some models (e.g. Sonnet 5)
|
|
@@ -445,13 +448,20 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
445
448
|
// consume the max_tokens budget.
|
|
446
449
|
const sendThinking = isThinking || thinkingType === 'disabled';
|
|
447
450
|
let thinkingBudget =
|
|
448
|
-
thinkingType === 'enabled'
|
|
449
|
-
|
|
451
|
+
thinkingType === 'enabled' &&
|
|
452
|
+
thinking != null &&
|
|
453
|
+
'budgetTokens' in thinking
|
|
454
|
+
? thinking.budgetTokens
|
|
450
455
|
: undefined;
|
|
451
456
|
const thinkingDisplay =
|
|
452
|
-
thinkingType === 'adaptive'
|
|
453
|
-
?
|
|
457
|
+
thinkingType === 'adaptive' && thinking != null && 'display' in thinking
|
|
458
|
+
? thinking.display
|
|
459
|
+
: undefined;
|
|
460
|
+
const thinkingBlockBinding =
|
|
461
|
+
thinking != null && 'blockBinding' in thinking
|
|
462
|
+
? thinking.blockBinding
|
|
454
463
|
: undefined;
|
|
464
|
+
const sendThinkingConfig = sendThinking || thinkingBlockBinding != null;
|
|
455
465
|
|
|
456
466
|
const maxTokens = maxOutputTokens ?? maxOutputTokensForModel;
|
|
457
467
|
|
|
@@ -467,11 +477,17 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
467
477
|
stop_sequences: stopSequences,
|
|
468
478
|
|
|
469
479
|
// provider specific settings:
|
|
470
|
-
...(
|
|
480
|
+
...(sendThinkingConfig && {
|
|
471
481
|
thinking: {
|
|
472
|
-
type: thinkingType,
|
|
482
|
+
...(thinkingType != null && { type: thinkingType }),
|
|
473
483
|
...(thinkingBudget != null && { budget_tokens: thinkingBudget }),
|
|
474
484
|
...(thinkingDisplay != null && { display: thinkingDisplay }),
|
|
485
|
+
...(thinkingBlockBinding != null && {
|
|
486
|
+
block_binding: {
|
|
487
|
+
prefix_mismatch_behavior:
|
|
488
|
+
thinkingBlockBinding.prefixMismatchBehavior,
|
|
489
|
+
},
|
|
490
|
+
}),
|
|
475
491
|
},
|
|
476
492
|
}),
|
|
477
493
|
...((anthropicOptions?.effort ||
|
|
@@ -735,6 +751,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
735
751
|
betas.add('task-budgets-2026-03-13');
|
|
736
752
|
}
|
|
737
753
|
|
|
754
|
+
if (thinkingDisplay === 'updates') {
|
|
755
|
+
betas.add('thinking-display-updates-2026-08-18');
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (thinkingBlockBinding != null) {
|
|
759
|
+
betas.add('thinking-binding-controls-2026-08-01');
|
|
760
|
+
}
|
|
761
|
+
|
|
738
762
|
if (anthropicOptions?.speed === 'fast') {
|
|
739
763
|
betas.add('fast-mode-2026-02-01');
|
|
740
764
|
}
|
|
@@ -21,6 +21,7 @@ export type AnthropicMessagesModelId =
|
|
|
21
21
|
| 'claude-opus-4-8'
|
|
22
22
|
| 'claude-opus-5'
|
|
23
23
|
| 'claude-fable-5'
|
|
24
|
+
| 'claude-fable-5-1'
|
|
24
25
|
| 'claude-sonnet-5'
|
|
25
26
|
| (string & {});
|
|
26
27
|
|
|
@@ -64,6 +65,23 @@ export type AnthropicFilePartProviderOptions = z.infer<
|
|
|
64
65
|
* Anthropic provider options for system messages.
|
|
65
66
|
*/
|
|
66
67
|
export const anthropicSystemMessageProviderOptions = z.object({
|
|
68
|
+
/**
|
|
69
|
+
* Clears this mid-conversation system message after the current turn.
|
|
70
|
+
*
|
|
71
|
+
* Requires the `mid-conversation-system-clear-at-2026-08-21` beta,
|
|
72
|
+
* which is added automatically.
|
|
73
|
+
*/
|
|
74
|
+
clearAt: z.literal('next_user_message').optional(),
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Overrides the effort level for the turn following this
|
|
78
|
+
* mid-conversation system message.
|
|
79
|
+
*
|
|
80
|
+
* Requires the `mid-conversation-effort-2026-08-01` beta,
|
|
81
|
+
* which is added automatically.
|
|
82
|
+
*/
|
|
83
|
+
effort: z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),
|
|
84
|
+
|
|
67
85
|
/**
|
|
68
86
|
* Mid-conversation tool changes. Adds or removes tools from the
|
|
69
87
|
* conversation's tool set between turns without invalidating the prompt
|
|
@@ -98,6 +116,10 @@ export type AnthropicSystemMessageProviderOptions = z.infer<
|
|
|
98
116
|
typeof anthropicSystemMessageProviderOptions
|
|
99
117
|
>;
|
|
100
118
|
|
|
119
|
+
const anthropicThinkingBlockBinding = z.object({
|
|
120
|
+
prefixMismatchBehavior: z.literal('drop_block'),
|
|
121
|
+
});
|
|
122
|
+
|
|
101
123
|
export const anthropicLanguageModelOptions = z.object({
|
|
102
124
|
/**
|
|
103
125
|
* Whether to send reasoning to the model.
|
|
@@ -122,24 +144,41 @@ export const anthropicLanguageModelOptions = z.object({
|
|
|
122
144
|
* Requires a minimum budget of 1,024 tokens and counts towards the `max_tokens` limit.
|
|
123
145
|
*/
|
|
124
146
|
thinking: z
|
|
125
|
-
.
|
|
126
|
-
z.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
147
|
+
.union([
|
|
148
|
+
z.discriminatedUnion('type', [
|
|
149
|
+
z.object({
|
|
150
|
+
/** for Sonnet 4.6, Opus 4.6, and newer models */
|
|
151
|
+
type: z.literal('adaptive'),
|
|
152
|
+
/**
|
|
153
|
+
* Controls whether thinking content is included in the response.
|
|
154
|
+
* - `"omitted"`: Thinking blocks are present but text is empty (default for Opus 4.7+).
|
|
155
|
+
* - `"summarized"`: Thinking content is returned. Required to see reasoning output.
|
|
156
|
+
* - `"updates"`: Thinking updates are returned between tool calls.
|
|
157
|
+
*/
|
|
158
|
+
display: z.enum(['omitted', 'summarized', 'updates']).optional(),
|
|
159
|
+
/**
|
|
160
|
+
* Controls how thinking blocks are bound to an assistant prefix.
|
|
161
|
+
*
|
|
162
|
+
* Requires the `thinking-binding-controls-2026-08-01` beta,
|
|
163
|
+
* which is added automatically.
|
|
164
|
+
*/
|
|
165
|
+
blockBinding: anthropicThinkingBlockBinding.optional(),
|
|
166
|
+
}),
|
|
167
|
+
z.object({
|
|
168
|
+
/** for models before Opus 4.6, except Sonnet 4.6 still supports it */
|
|
169
|
+
type: z.literal('enabled'),
|
|
170
|
+
budgetTokens: z.number().optional(),
|
|
171
|
+
}),
|
|
172
|
+
z.object({
|
|
173
|
+
type: z.literal('disabled'),
|
|
174
|
+
}),
|
|
175
|
+
]),
|
|
176
|
+
/**
|
|
177
|
+
* Configures prefix mismatch recovery without changing the model's
|
|
178
|
+
* default thinking mode.
|
|
179
|
+
*/
|
|
141
180
|
z.object({
|
|
142
|
-
|
|
181
|
+
blockBinding: anthropicThinkingBlockBinding,
|
|
143
182
|
}),
|
|
144
183
|
])
|
|
145
184
|
.optional(),
|
|
@@ -166,8 +166,9 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
166
166
|
|
|
167
167
|
switch (type) {
|
|
168
168
|
case 'system': {
|
|
169
|
-
const
|
|
169
|
+
const systemMessages: AnthropicSystemMessage[] = [];
|
|
170
170
|
let toolChangeCount = 0;
|
|
171
|
+
let hasMidConversationOptions = false;
|
|
171
172
|
|
|
172
173
|
for (const { content: text, providerOptions } of block.messages) {
|
|
173
174
|
const systemMessageOptions = await parseProviderOptions({
|
|
@@ -176,10 +177,16 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
176
177
|
schema: anthropicSystemMessageProviderOptions,
|
|
177
178
|
});
|
|
178
179
|
const toolChanges = systemMessageOptions?.toolChanges ?? [];
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
const clearAt = systemMessageOptions?.clearAt;
|
|
181
|
+
const effort = systemMessageOptions?.effort;
|
|
182
|
+
const content: AnthropicSystemMessage['content'] = [];
|
|
183
|
+
|
|
184
|
+
// A system message that only carries message-level options or tool
|
|
185
|
+
// changes may have empty text; do not emit an empty text block for it.
|
|
186
|
+
if (
|
|
187
|
+
text !== '' ||
|
|
188
|
+
(toolChanges.length === 0 && clearAt == null && effort == null)
|
|
189
|
+
) {
|
|
183
190
|
content.push({
|
|
184
191
|
type: 'text' as const,
|
|
185
192
|
text,
|
|
@@ -200,14 +207,29 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
200
207
|
},
|
|
201
208
|
} satisfies AnthropicToolChangeContent);
|
|
202
209
|
}
|
|
210
|
+
|
|
211
|
+
hasMidConversationOptions ||= clearAt != null || effort != null;
|
|
212
|
+
|
|
213
|
+
systemMessages.push({
|
|
214
|
+
role: 'system',
|
|
215
|
+
content,
|
|
216
|
+
...(clearAt != null && { clear_at: clearAt }),
|
|
217
|
+
...(effort != null && { output_config: { effort } }),
|
|
218
|
+
});
|
|
203
219
|
}
|
|
204
220
|
|
|
205
221
|
// The first block becomes the top-level system prompt. Later system
|
|
206
222
|
// blocks are sent as inline system messages — always when they carry
|
|
207
|
-
// tool changes (which are only valid
|
|
208
|
-
// only when a top-level system prompt
|
|
209
|
-
// existing hoisting behavior for plain
|
|
210
|
-
|
|
223
|
+
// tool changes or per-turn options (which are only valid
|
|
224
|
+
// mid-conversation), and otherwise only when a top-level system prompt
|
|
225
|
+
// already exists (preserving the existing hoisting behavior for plain
|
|
226
|
+
// text).
|
|
227
|
+
if (
|
|
228
|
+
i === 0 ||
|
|
229
|
+
(system == null &&
|
|
230
|
+
toolChangeCount === 0 &&
|
|
231
|
+
!hasMidConversationOptions)
|
|
232
|
+
) {
|
|
211
233
|
if (toolChangeCount > 0) {
|
|
212
234
|
warnings.push({
|
|
213
235
|
type: 'other',
|
|
@@ -217,15 +239,32 @@ export async function convertToAnthropicMessagesPrompt({
|
|
|
217
239
|
'The tool changes have been ignored.',
|
|
218
240
|
});
|
|
219
241
|
}
|
|
220
|
-
|
|
221
|
-
(
|
|
242
|
+
if (hasMidConversationOptions) {
|
|
243
|
+
warnings.push({
|
|
244
|
+
type: 'other',
|
|
245
|
+
message:
|
|
246
|
+
'clearAt and effort on the initial system message are not supported by Anthropic. ' +
|
|
247
|
+
'Configure these options on a mid-conversation system message instead. ' +
|
|
248
|
+
'The options have been ignored.',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
system = systemMessages.flatMap(message =>
|
|
252
|
+
message.content.filter(
|
|
253
|
+
(part): part is AnthropicTextContent => part.type === 'text',
|
|
254
|
+
),
|
|
222
255
|
);
|
|
223
256
|
} else {
|
|
224
|
-
messages.push(
|
|
257
|
+
messages.push(...systemMessages);
|
|
225
258
|
betas.add('mid-conversation-system-2026-04-07');
|
|
226
259
|
if (toolChangeCount > 0) {
|
|
227
260
|
betas.add('mid-conversation-tool-changes-2026-07-01');
|
|
228
261
|
}
|
|
262
|
+
if (systemMessages.some(message => message.clear_at != null)) {
|
|
263
|
+
betas.add('mid-conversation-system-clear-at-2026-08-21');
|
|
264
|
+
}
|
|
265
|
+
if (systemMessages.some(message => message.output_config != null)) {
|
|
266
|
+
betas.add('mid-conversation-effort-2026-08-01');
|
|
267
|
+
}
|
|
229
268
|
}
|
|
230
269
|
|
|
231
270
|
break;
|