@ai-sdk/anthropic 3.0.119 → 3.0.121
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 +20 -0
- package/dist/index.d.mts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +834 -458
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +826 -446
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +74 -2
- package/dist/internal/index.d.ts +74 -2
- package/dist/internal/index.js +827 -451
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +825 -445
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +125 -14
- package/package.json +3 -3
- package/src/anthropic-messages-api.ts +23 -0
- package/src/anthropic-messages-language-model.ts +264 -6
- package/src/anthropic-messages-options.ts +12 -2
- package/src/anthropic-prepare-tools.ts +76 -0
- package/src/anthropic-tools.ts +25 -0
- package/src/convert-to-anthropic-messages-prompt.ts +77 -1
- package/src/tool/computer-toolset_20260801.ts +165 -0
|
@@ -138,6 +138,48 @@ function getAnthropicCallerMetadata(
|
|
|
138
138
|
: { providerMetadata: { anthropic: { caller: callerInfo } } };
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Maps the custom tool names of toolset tools (e.g. the computer toolset) to
|
|
143
|
+
* the toolset name that the Anthropic API uses in `toolset_name`.
|
|
144
|
+
*/
|
|
145
|
+
function getAnthropicToolsetNames(
|
|
146
|
+
tools: LanguageModelV3CallOptions['tools'],
|
|
147
|
+
): Record<string, string> {
|
|
148
|
+
const toolsetNames: Record<string, string> = {};
|
|
149
|
+
|
|
150
|
+
for (const tool of tools ?? []) {
|
|
151
|
+
if (
|
|
152
|
+
tool.type === 'provider' &&
|
|
153
|
+
tool.id === 'anthropic.computer_toolset_20260801'
|
|
154
|
+
) {
|
|
155
|
+
toolsetNames[tool.name] = 'computer';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return toolsetNames;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Toolset member calls (e.g. `left_click` from the computer toolset) are
|
|
164
|
+
* exposed as a single tool call on the toolset tool. The member name is
|
|
165
|
+
* injected as the `action` property, matching the input shape of the older
|
|
166
|
+
* computer tool versions.
|
|
167
|
+
*/
|
|
168
|
+
function toToolsetMemberInput({
|
|
169
|
+
memberName,
|
|
170
|
+
input,
|
|
171
|
+
}: {
|
|
172
|
+
memberName: string;
|
|
173
|
+
input: unknown;
|
|
174
|
+
}): JSONObject {
|
|
175
|
+
return {
|
|
176
|
+
action: memberName,
|
|
177
|
+
...(typeof input === 'object' && input !== null && !Array.isArray(input)
|
|
178
|
+
? (input as JSONObject)
|
|
179
|
+
: {}),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
141
183
|
type AnthropicMessagesConfig = {
|
|
142
184
|
provider: string;
|
|
143
185
|
baseURL: string;
|
|
@@ -297,6 +339,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
297
339
|
supportsStructuredOutput: modelSupportsStructuredOutput,
|
|
298
340
|
rejectsSamplingParameters,
|
|
299
341
|
rejectsThinkingDisabledAboveHighEffort,
|
|
342
|
+
rejectsThinkingDisabled,
|
|
343
|
+
rejectsForcedToolUse,
|
|
300
344
|
isKnownModel,
|
|
301
345
|
} = getModelCapabilities(this.modelId);
|
|
302
346
|
|
|
@@ -350,10 +394,30 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
350
394
|
|
|
351
395
|
const structureOutputMode =
|
|
352
396
|
anthropicOptions?.structuredOutputMode ?? 'auto';
|
|
353
|
-
|
|
397
|
+
let useStructuredOutput =
|
|
354
398
|
structureOutputMode === 'outputFormat' ||
|
|
355
399
|
(structureOutputMode === 'auto' && supportsStructuredOutput);
|
|
356
400
|
|
|
401
|
+
// The JSON response tool relies on forced tool use, which some models
|
|
402
|
+
// reject (e.g. Opus 5.5, Fable 5.1). Fall back to native structured
|
|
403
|
+
// outputs when the model supports them.
|
|
404
|
+
if (
|
|
405
|
+
!useStructuredOutput &&
|
|
406
|
+
rejectsForcedToolUse &&
|
|
407
|
+
supportsStructuredOutput &&
|
|
408
|
+
responseFormat?.type === 'json' &&
|
|
409
|
+
responseFormat.schema != null
|
|
410
|
+
) {
|
|
411
|
+
warnings.push({
|
|
412
|
+
type: 'unsupported',
|
|
413
|
+
feature: 'providerOptions.anthropic.structuredOutputMode',
|
|
414
|
+
details:
|
|
415
|
+
`structuredOutputMode 'jsonTool' is not supported by ${this.modelId} because it rejects forced tool use. ` +
|
|
416
|
+
`Using 'outputFormat' instead.`,
|
|
417
|
+
});
|
|
418
|
+
useStructuredOutput = true;
|
|
419
|
+
}
|
|
420
|
+
|
|
357
421
|
const jsonResponseTool: LanguageModelV3FunctionTool | undefined =
|
|
358
422
|
responseFormat?.type === 'json' &&
|
|
359
423
|
responseFormat.schema != null &&
|
|
@@ -392,6 +456,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
392
456
|
'anthropic.code_execution_20260120': 'code_execution',
|
|
393
457
|
'anthropic.computer_20241022': 'computer',
|
|
394
458
|
'anthropic.computer_20250124': 'computer',
|
|
459
|
+
'anthropic.computer_20251124': 'computer',
|
|
460
|
+
'anthropic.computer_toolset_20260801': 'computer',
|
|
395
461
|
'anthropic.text_editor_20241022': 'str_replace_editor',
|
|
396
462
|
'anthropic.text_editor_20250124': 'str_replace_editor',
|
|
397
463
|
'anthropic.text_editor_20250429': 'str_replace_based_edit_tool',
|
|
@@ -409,6 +475,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
409
475
|
},
|
|
410
476
|
});
|
|
411
477
|
|
|
478
|
+
const toolsetNames = getAnthropicToolsetNames(tools);
|
|
479
|
+
|
|
412
480
|
const { prompt: messagesPrompt, betas } =
|
|
413
481
|
await convertToAnthropicMessagesPrompt({
|
|
414
482
|
prompt,
|
|
@@ -416,8 +484,38 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
416
484
|
warnings,
|
|
417
485
|
cacheControlValidator,
|
|
418
486
|
toolNameMapping,
|
|
487
|
+
toolsetNames,
|
|
419
488
|
});
|
|
420
489
|
|
|
490
|
+
// Some models always run adaptive thinking and reject `disabled` and
|
|
491
|
+
// budget-based `enabled` thinking with a 400. Drop the unsupported
|
|
492
|
+
// setting and keep the request adaptive so it still succeeds.
|
|
493
|
+
if (rejectsThinkingDisabled && anthropicOptions?.thinking != null) {
|
|
494
|
+
const requestedThinking = anthropicOptions.thinking;
|
|
495
|
+
const requestedType =
|
|
496
|
+
'type' in requestedThinking ? requestedThinking.type : undefined;
|
|
497
|
+
|
|
498
|
+
if (requestedType === 'disabled') {
|
|
499
|
+
warnings.push({
|
|
500
|
+
type: 'unsupported',
|
|
501
|
+
feature: 'providerOptions.anthropic.thinking',
|
|
502
|
+
details:
|
|
503
|
+
`thinking cannot be disabled for ${this.modelId}; it always uses adaptive thinking. ` +
|
|
504
|
+
`The thinking setting has been removed. Lower 'effort' to reduce thinking.`,
|
|
505
|
+
});
|
|
506
|
+
anthropicOptions.thinking = undefined;
|
|
507
|
+
} else if (requestedType === 'enabled') {
|
|
508
|
+
warnings.push({
|
|
509
|
+
type: 'unsupported',
|
|
510
|
+
feature: 'providerOptions.anthropic.thinking',
|
|
511
|
+
details:
|
|
512
|
+
`budget-based thinking is not supported by ${this.modelId}; it always uses adaptive thinking. ` +
|
|
513
|
+
`Using adaptive thinking instead. Use 'effort' to control how much the model thinks.`,
|
|
514
|
+
});
|
|
515
|
+
anthropicOptions.thinking = { type: 'adaptive' };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
421
519
|
const thinking = anthropicOptions?.thinking;
|
|
422
520
|
const thinkingType =
|
|
423
521
|
thinking != null && 'type' in thinking ? thinking.type : undefined;
|
|
@@ -790,6 +888,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
790
888
|
supportsStructuredOutput: false,
|
|
791
889
|
supportsStrictTools,
|
|
792
890
|
defaultEagerInputStreaming,
|
|
891
|
+
rejectsForcedToolUse,
|
|
793
892
|
}
|
|
794
893
|
: {
|
|
795
894
|
tools: tools ?? [],
|
|
@@ -799,6 +898,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
799
898
|
supportsStructuredOutput,
|
|
800
899
|
supportsStrictTools,
|
|
801
900
|
defaultEagerInputStreaming,
|
|
901
|
+
rejectsForcedToolUse,
|
|
802
902
|
},
|
|
803
903
|
);
|
|
804
904
|
|
|
@@ -1049,6 +1149,27 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1049
1149
|
type: 'text',
|
|
1050
1150
|
text: JSON.stringify(part.input),
|
|
1051
1151
|
});
|
|
1152
|
+
} else if (part.toolset_name != null) {
|
|
1153
|
+
// toolset member calls (e.g. the computer toolset) are mapped to
|
|
1154
|
+
// the toolset tool with the member name as the `action`:
|
|
1155
|
+
content.push({
|
|
1156
|
+
type: 'tool-call',
|
|
1157
|
+
toolCallId: part.id,
|
|
1158
|
+
toolName: toolNameMapping.toCustomToolName(part.toolset_name),
|
|
1159
|
+
input: JSON.stringify(
|
|
1160
|
+
toToolsetMemberInput({
|
|
1161
|
+
memberName: part.name,
|
|
1162
|
+
input: part.input,
|
|
1163
|
+
}),
|
|
1164
|
+
),
|
|
1165
|
+
providerMetadata: {
|
|
1166
|
+
anthropic: {
|
|
1167
|
+
toolsetName: part.toolset_name,
|
|
1168
|
+
...getAnthropicCallerMetadata(part.caller).providerMetadata
|
|
1169
|
+
?.anthropic,
|
|
1170
|
+
},
|
|
1171
|
+
},
|
|
1172
|
+
});
|
|
1052
1173
|
} else {
|
|
1053
1174
|
content.push({
|
|
1054
1175
|
type: 'tool-call',
|
|
@@ -1554,6 +1675,12 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1554
1675
|
firstDelta: boolean;
|
|
1555
1676
|
providerToolName?: string;
|
|
1556
1677
|
providerToolInputType?: string;
|
|
1678
|
+
/**
|
|
1679
|
+
* Set for toolset member calls (e.g. the computer toolset). The raw
|
|
1680
|
+
* member input is accumulated and emitted as a single delta with the
|
|
1681
|
+
* member name injected as `action` when the block completes.
|
|
1682
|
+
*/
|
|
1683
|
+
toolset?: { name: string; memberName: string };
|
|
1557
1684
|
caller?: {
|
|
1558
1685
|
type:
|
|
1559
1686
|
| 'code_execution_20250825'
|
|
@@ -1720,6 +1847,34 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
1720
1847
|
type: 'text-start',
|
|
1721
1848
|
id: String(value.index),
|
|
1722
1849
|
});
|
|
1850
|
+
} else if (part.toolset_name != null) {
|
|
1851
|
+
const callerInfo = getAnthropicCallerInfo(part.caller);
|
|
1852
|
+
const customToolName = toolNameMapping.toCustomToolName(
|
|
1853
|
+
part.toolset_name,
|
|
1854
|
+
);
|
|
1855
|
+
const hasNonEmptyInput =
|
|
1856
|
+
part.input && Object.keys(part.input).length > 0;
|
|
1857
|
+
|
|
1858
|
+
// toolset member input is accumulated and emitted when the
|
|
1859
|
+
// block completes (see content_block_stop):
|
|
1860
|
+
contentBlocks[value.index] = {
|
|
1861
|
+
type: 'tool-call',
|
|
1862
|
+
toolCallId: part.id,
|
|
1863
|
+
toolName: customToolName,
|
|
1864
|
+
input: hasNonEmptyInput ? JSON.stringify(part.input) : '',
|
|
1865
|
+
firstDelta: true,
|
|
1866
|
+
toolset: {
|
|
1867
|
+
name: part.toolset_name,
|
|
1868
|
+
memberName: part.name,
|
|
1869
|
+
},
|
|
1870
|
+
...(callerInfo && { caller: callerInfo }),
|
|
1871
|
+
};
|
|
1872
|
+
|
|
1873
|
+
controller.enqueue({
|
|
1874
|
+
type: 'tool-input-start',
|
|
1875
|
+
id: part.id,
|
|
1876
|
+
toolName: customToolName,
|
|
1877
|
+
});
|
|
1723
1878
|
} else {
|
|
1724
1879
|
const callerInfo = getAnthropicCallerInfo(part.caller);
|
|
1725
1880
|
|
|
@@ -2200,6 +2355,37 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2200
2355
|
usesJsonResponseTool && contentBlock.toolName === 'json';
|
|
2201
2356
|
|
|
2202
2357
|
if (!isJsonResponseTool) {
|
|
2358
|
+
// toolset member calls: emit the accumulated input with
|
|
2359
|
+
// the member name injected as `action` in one delta.
|
|
2360
|
+
if (contentBlock.toolset != null) {
|
|
2361
|
+
let memberInput: unknown = {};
|
|
2362
|
+
try {
|
|
2363
|
+
memberInput =
|
|
2364
|
+
contentBlock.input === ''
|
|
2365
|
+
? {}
|
|
2366
|
+
: secureJsonParse(contentBlock.input);
|
|
2367
|
+
} catch {
|
|
2368
|
+
// ignore parse errors, fall back to the raw input
|
|
2369
|
+
memberInput = undefined;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
contentBlock.input =
|
|
2373
|
+
memberInput === undefined
|
|
2374
|
+
? contentBlock.input
|
|
2375
|
+
: JSON.stringify(
|
|
2376
|
+
toToolsetMemberInput({
|
|
2377
|
+
memberName: contentBlock.toolset.memberName,
|
|
2378
|
+
input: memberInput,
|
|
2379
|
+
}),
|
|
2380
|
+
);
|
|
2381
|
+
|
|
2382
|
+
controller.enqueue({
|
|
2383
|
+
type: 'tool-input-delta',
|
|
2384
|
+
id: contentBlock.toolCallId,
|
|
2385
|
+
delta: contentBlock.input,
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2203
2389
|
controller.enqueue({
|
|
2204
2390
|
type: 'tool-input-end',
|
|
2205
2391
|
id: contentBlock.toolCallId,
|
|
@@ -2242,10 +2428,15 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2242
2428
|
contentBlock.providerToolName === 'code_execution'
|
|
2243
2429
|
? { dynamic: true }
|
|
2244
2430
|
: {}),
|
|
2245
|
-
...(contentBlock.caller && {
|
|
2431
|
+
...((contentBlock.caller || contentBlock.toolset) && {
|
|
2246
2432
|
providerMetadata: {
|
|
2247
2433
|
anthropic: {
|
|
2248
|
-
|
|
2434
|
+
...(contentBlock.toolset && {
|
|
2435
|
+
toolsetName: contentBlock.toolset.name,
|
|
2436
|
+
}),
|
|
2437
|
+
...(contentBlock.caller && {
|
|
2438
|
+
caller: contentBlock.caller,
|
|
2439
|
+
}),
|
|
2249
2440
|
},
|
|
2250
2441
|
},
|
|
2251
2442
|
}),
|
|
@@ -2347,6 +2538,13 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
|
|
|
2347
2538
|
return;
|
|
2348
2539
|
}
|
|
2349
2540
|
|
|
2541
|
+
// toolset member input is emitted as a single delta once
|
|
2542
|
+
// the block is complete (the member name is injected):
|
|
2543
|
+
if (contentBlock.toolset != null) {
|
|
2544
|
+
contentBlock.input += delta;
|
|
2545
|
+
return;
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2350
2548
|
// for the code execution 20250825, we need to add
|
|
2351
2549
|
// the type to the delta and change the tool name.
|
|
2352
2550
|
if (
|
|
@@ -2710,20 +2908,60 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2710
2908
|
supportsStructuredOutput: boolean;
|
|
2711
2909
|
rejectsSamplingParameters: boolean;
|
|
2712
2910
|
rejectsThinkingDisabledAboveHighEffort: boolean;
|
|
2911
|
+
/**
|
|
2912
|
+
* Thinking is always adaptive: `thinking.type` `disabled` and `enabled`
|
|
2913
|
+
* are rejected with a 400.
|
|
2914
|
+
*/
|
|
2915
|
+
rejectsThinkingDisabled: boolean;
|
|
2916
|
+
/**
|
|
2917
|
+
* Forced tool use (`tool_choice` `any` or a named tool) is rejected with a 400.
|
|
2918
|
+
*/
|
|
2919
|
+
rejectsForcedToolUse: boolean;
|
|
2713
2920
|
isKnownModel: boolean;
|
|
2714
2921
|
} {
|
|
2715
|
-
if (modelId.includes('claude-opus-5')) {
|
|
2922
|
+
if (modelId.includes('claude-opus-5-5')) {
|
|
2716
2923
|
return {
|
|
2717
2924
|
maxOutputTokens: 128000,
|
|
2718
2925
|
supportsStructuredOutput: true,
|
|
2719
2926
|
rejectsSamplingParameters: true,
|
|
2720
2927
|
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2928
|
+
rejectsThinkingDisabled: true,
|
|
2929
|
+
rejectsForcedToolUse: true,
|
|
2930
|
+
isKnownModel: true,
|
|
2931
|
+
};
|
|
2932
|
+
} else if (modelId.includes('claude-opus-5')) {
|
|
2933
|
+
return {
|
|
2934
|
+
maxOutputTokens: 128000,
|
|
2935
|
+
supportsStructuredOutput: true,
|
|
2936
|
+
rejectsSamplingParameters: true,
|
|
2937
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
2938
|
+
rejectsThinkingDisabled: false,
|
|
2939
|
+
rejectsForcedToolUse: false,
|
|
2940
|
+
isKnownModel: true,
|
|
2941
|
+
};
|
|
2942
|
+
} else if (modelId.includes('claude-fable-5-1')) {
|
|
2943
|
+
return {
|
|
2944
|
+
maxOutputTokens: 128000,
|
|
2945
|
+
supportsStructuredOutput: true,
|
|
2946
|
+
rejectsSamplingParameters: true,
|
|
2947
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2948
|
+
rejectsThinkingDisabled: true,
|
|
2949
|
+
rejectsForcedToolUse: true,
|
|
2950
|
+
isKnownModel: true,
|
|
2951
|
+
};
|
|
2952
|
+
} else if (modelId.includes('claude-fable-5')) {
|
|
2953
|
+
return {
|
|
2954
|
+
maxOutputTokens: 128000,
|
|
2955
|
+
supportsStructuredOutput: true,
|
|
2956
|
+
rejectsSamplingParameters: true,
|
|
2957
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2958
|
+
rejectsThinkingDisabled: true,
|
|
2959
|
+
rejectsForcedToolUse: false,
|
|
2721
2960
|
isKnownModel: true,
|
|
2722
2961
|
};
|
|
2723
2962
|
} else if (
|
|
2724
2963
|
modelId.includes('claude-opus-4-8') ||
|
|
2725
2964
|
modelId.includes('claude-opus-4-7') ||
|
|
2726
|
-
modelId.includes('claude-fable-5') ||
|
|
2727
2965
|
modelId.includes('claude-sonnet-5')
|
|
2728
2966
|
) {
|
|
2729
2967
|
return {
|
|
@@ -2731,6 +2969,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2731
2969
|
supportsStructuredOutput: true,
|
|
2732
2970
|
rejectsSamplingParameters: true,
|
|
2733
2971
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2972
|
+
rejectsThinkingDisabled: false,
|
|
2973
|
+
rejectsForcedToolUse: false,
|
|
2734
2974
|
isKnownModel: true,
|
|
2735
2975
|
};
|
|
2736
2976
|
} else if (
|
|
@@ -2742,6 +2982,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2742
2982
|
supportsStructuredOutput: true,
|
|
2743
2983
|
rejectsSamplingParameters: false,
|
|
2744
2984
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2985
|
+
rejectsThinkingDisabled: false,
|
|
2986
|
+
rejectsForcedToolUse: false,
|
|
2745
2987
|
isKnownModel: true,
|
|
2746
2988
|
};
|
|
2747
2989
|
} else if (
|
|
@@ -2754,6 +2996,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2754
2996
|
supportsStructuredOutput: true,
|
|
2755
2997
|
rejectsSamplingParameters: false,
|
|
2756
2998
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
2999
|
+
rejectsThinkingDisabled: false,
|
|
3000
|
+
rejectsForcedToolUse: false,
|
|
2757
3001
|
isKnownModel: true,
|
|
2758
3002
|
};
|
|
2759
3003
|
} else if (modelId.includes('claude-opus-4-1')) {
|
|
@@ -2762,6 +3006,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2762
3006
|
supportsStructuredOutput: true,
|
|
2763
3007
|
rejectsSamplingParameters: false,
|
|
2764
3008
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3009
|
+
rejectsThinkingDisabled: false,
|
|
3010
|
+
rejectsForcedToolUse: false,
|
|
2765
3011
|
isKnownModel: true,
|
|
2766
3012
|
};
|
|
2767
3013
|
} else if (modelId.includes('claude-sonnet-4-')) {
|
|
@@ -2770,6 +3016,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2770
3016
|
supportsStructuredOutput: false,
|
|
2771
3017
|
rejectsSamplingParameters: false,
|
|
2772
3018
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3019
|
+
rejectsThinkingDisabled: false,
|
|
3020
|
+
rejectsForcedToolUse: false,
|
|
2773
3021
|
isKnownModel: true,
|
|
2774
3022
|
};
|
|
2775
3023
|
} else if (modelId.includes('claude-opus-4-')) {
|
|
@@ -2778,6 +3026,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2778
3026
|
supportsStructuredOutput: false,
|
|
2779
3027
|
rejectsSamplingParameters: false,
|
|
2780
3028
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3029
|
+
rejectsThinkingDisabled: false,
|
|
3030
|
+
rejectsForcedToolUse: false,
|
|
2781
3031
|
isKnownModel: true,
|
|
2782
3032
|
};
|
|
2783
3033
|
} else if (modelId.includes('claude-3-haiku')) {
|
|
@@ -2786,6 +3036,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2786
3036
|
supportsStructuredOutput: false,
|
|
2787
3037
|
rejectsSamplingParameters: false,
|
|
2788
3038
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3039
|
+
rejectsThinkingDisabled: false,
|
|
3040
|
+
rejectsForcedToolUse: false,
|
|
2789
3041
|
isKnownModel: true,
|
|
2790
3042
|
};
|
|
2791
3043
|
} else if (
|
|
@@ -2796,6 +3048,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2796
3048
|
supportsStructuredOutput: false,
|
|
2797
3049
|
rejectsSamplingParameters: false,
|
|
2798
3050
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3051
|
+
rejectsThinkingDisabled: false,
|
|
3052
|
+
rejectsForcedToolUse: false,
|
|
2799
3053
|
isKnownModel: false,
|
|
2800
3054
|
};
|
|
2801
3055
|
} else if (modelId.includes('claude-')) {
|
|
@@ -2807,6 +3061,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2807
3061
|
supportsStructuredOutput: true,
|
|
2808
3062
|
rejectsSamplingParameters: true,
|
|
2809
3063
|
rejectsThinkingDisabledAboveHighEffort: true,
|
|
3064
|
+
rejectsThinkingDisabled: false,
|
|
3065
|
+
rejectsForcedToolUse: false,
|
|
2810
3066
|
isKnownModel: false,
|
|
2811
3067
|
};
|
|
2812
3068
|
} else {
|
|
@@ -2817,6 +3073,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2817
3073
|
supportsStructuredOutput: false,
|
|
2818
3074
|
rejectsSamplingParameters: false,
|
|
2819
3075
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3076
|
+
rejectsThinkingDisabled: false,
|
|
3077
|
+
rejectsForcedToolUse: false,
|
|
2820
3078
|
isKnownModel: false,
|
|
2821
3079
|
};
|
|
2822
3080
|
}
|
|
@@ -2839,7 +3097,7 @@ function hasWebTool20260209WithoutCodeExecution(
|
|
|
2839
3097
|
hasWebTool20260209 = true;
|
|
2840
3098
|
continue;
|
|
2841
3099
|
}
|
|
2842
|
-
if (tool.name === 'code_execution') {
|
|
3100
|
+
if ('name' in tool && tool.name === 'code_execution') {
|
|
2843
3101
|
hasCodeExecutionTool = true;
|
|
2844
3102
|
break;
|
|
2845
3103
|
}
|
|
@@ -20,6 +20,7 @@ export type AnthropicMessagesModelId =
|
|
|
20
20
|
| 'claude-opus-4-7'
|
|
21
21
|
| 'claude-opus-4-8'
|
|
22
22
|
| 'claude-opus-5'
|
|
23
|
+
| 'claude-opus-5-5'
|
|
23
24
|
| 'claude-fable-5'
|
|
24
25
|
| 'claude-fable-5-1'
|
|
25
26
|
| 'claude-sonnet-5'
|
|
@@ -77,7 +78,7 @@ export const anthropicSystemMessageProviderOptions = z.object({
|
|
|
77
78
|
* Overrides the effort level for the turn following this
|
|
78
79
|
* mid-conversation system message.
|
|
79
80
|
*
|
|
80
|
-
* Requires the `mid-conversation-
|
|
81
|
+
* Requires the `mid-conversation-output-config-2026-07-01` beta,
|
|
81
82
|
* which is added automatically.
|
|
82
83
|
*/
|
|
83
84
|
effort: z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),
|
|
@@ -142,6 +143,11 @@ export const anthropicLanguageModelOptions = z.object({
|
|
|
142
143
|
*
|
|
143
144
|
* When enabled, responses include thinking content blocks showing Claude's thinking process before the final answer.
|
|
144
145
|
* Requires a minimum budget of 1,024 tokens and counts towards the `max_tokens` limit.
|
|
146
|
+
*
|
|
147
|
+
* Models that always use adaptive thinking (e.g. `claude-opus-5-5`,
|
|
148
|
+
* `claude-fable-5-1`) reject `enabled` and `disabled`. For those models the
|
|
149
|
+
* provider drops the unsupported setting, emits a warning, and sends an
|
|
150
|
+
* adaptive thinking request. Use `effort` to control how much they think.
|
|
145
151
|
*/
|
|
146
152
|
thinking: z
|
|
147
153
|
.union([
|
|
@@ -269,7 +275,11 @@ export const anthropicLanguageModelOptions = z.object({
|
|
|
269
275
|
toolStreaming: z.boolean().optional(),
|
|
270
276
|
|
|
271
277
|
/**
|
|
272
|
-
*
|
|
278
|
+
* Controls how much effort the model spends on thinking, text responses,
|
|
279
|
+
* and tool calls. On models that always use adaptive thinking
|
|
280
|
+
* (e.g. `claude-opus-5-5`), effort is the main lever for latency and cost.
|
|
281
|
+
*
|
|
282
|
+
* The API default is `high` for most models and `medium` for `claude-opus-5-5`.
|
|
273
283
|
*/
|
|
274
284
|
effort: z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),
|
|
275
285
|
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
} from './anthropic-messages-api';
|
|
10
10
|
import { CacheControlValidator } from './get-cache-control';
|
|
11
11
|
import { advisor_20260301ArgsSchema } from './tool/advisor_20260301';
|
|
12
|
+
import { computerToolset_20260801ArgsSchema } from './tool/computer-toolset_20260801';
|
|
12
13
|
import { textEditor_20250728ArgsSchema } from './tool/text-editor_20250728';
|
|
13
14
|
import { webSearch_20260209ArgsSchema } from './tool/web-search_20260209';
|
|
14
15
|
import { webSearch_20250305ArgsSchema } from './tool/web-search_20250305';
|
|
@@ -32,6 +33,7 @@ export async function prepareTools({
|
|
|
32
33
|
supportsStructuredOutput,
|
|
33
34
|
supportsStrictTools,
|
|
34
35
|
defaultEagerInputStreaming = false,
|
|
36
|
+
rejectsForcedToolUse = false,
|
|
35
37
|
}: {
|
|
36
38
|
tools: LanguageModelV3CallOptions['tools'];
|
|
37
39
|
toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined;
|
|
@@ -53,6 +55,13 @@ export async function prepareTools({
|
|
|
53
55
|
* it explicitly. Driven by the model-level `toolStreaming` option.
|
|
54
56
|
*/
|
|
55
57
|
defaultEagerInputStreaming?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Whether the model rejects forced tool use (`tool_choice` `any` or a
|
|
61
|
+
* named tool). When true, `required` and `tool` tool choices fall back to
|
|
62
|
+
* `auto` with a warning.
|
|
63
|
+
*/
|
|
64
|
+
rejectsForcedToolUse?: boolean;
|
|
56
65
|
}): Promise<{
|
|
57
66
|
tools: Array<AnthropicTool> | undefined;
|
|
58
67
|
toolChoice: AnthropicToolChoice | undefined;
|
|
@@ -186,6 +195,34 @@ export async function prepareTools({
|
|
|
186
195
|
});
|
|
187
196
|
break;
|
|
188
197
|
}
|
|
198
|
+
case 'anthropic.computer_toolset_20260801': {
|
|
199
|
+
const args = await validateTypes({
|
|
200
|
+
value: tool.args,
|
|
201
|
+
schema: computerToolset_20260801ArgsSchema,
|
|
202
|
+
});
|
|
203
|
+
const configs =
|
|
204
|
+
args.configs != null
|
|
205
|
+
? Object.fromEntries(
|
|
206
|
+
Object.entries(args.configs).map(([member, config]) => [
|
|
207
|
+
member,
|
|
208
|
+
{
|
|
209
|
+
...(config?.enabled != null && {
|
|
210
|
+
enabled: config.enabled,
|
|
211
|
+
}),
|
|
212
|
+
...(config?.deferLoading != null && {
|
|
213
|
+
defer_loading: config.deferLoading,
|
|
214
|
+
}),
|
|
215
|
+
},
|
|
216
|
+
]),
|
|
217
|
+
)
|
|
218
|
+
: undefined;
|
|
219
|
+
anthropicTools.push({
|
|
220
|
+
type: 'computer_toolset_20260801',
|
|
221
|
+
...(configs != null && { configs }),
|
|
222
|
+
cache_control: undefined,
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
189
226
|
case 'anthropic.computer_20241022': {
|
|
190
227
|
betas.add('computer-use-2024-10-22');
|
|
191
228
|
anthropicTools.push({
|
|
@@ -412,6 +449,24 @@ export async function prepareTools({
|
|
|
412
449
|
betas,
|
|
413
450
|
};
|
|
414
451
|
case 'required':
|
|
452
|
+
if (rejectsForcedToolUse) {
|
|
453
|
+
toolWarnings.push({
|
|
454
|
+
type: 'unsupported',
|
|
455
|
+
feature: 'toolChoice',
|
|
456
|
+
details:
|
|
457
|
+
`toolChoice 'required' is not supported by this model because it rejects forced tool use. ` +
|
|
458
|
+
`Using 'auto' instead. Instruct the model to use a tool in the prompt and verify that a tool call was made.`,
|
|
459
|
+
});
|
|
460
|
+
return {
|
|
461
|
+
tools: anthropicTools,
|
|
462
|
+
toolChoice: {
|
|
463
|
+
type: 'auto',
|
|
464
|
+
disable_parallel_tool_use: disableParallelToolUse,
|
|
465
|
+
},
|
|
466
|
+
toolWarnings,
|
|
467
|
+
betas,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
415
470
|
return {
|
|
416
471
|
tools: anthropicTools,
|
|
417
472
|
toolChoice: {
|
|
@@ -425,6 +480,27 @@ export async function prepareTools({
|
|
|
425
480
|
// Anthropic does not support 'none' tool choice, so we remove the tools:
|
|
426
481
|
return { tools: undefined, toolChoice: undefined, toolWarnings, betas };
|
|
427
482
|
case 'tool':
|
|
483
|
+
if (rejectsForcedToolUse) {
|
|
484
|
+
toolWarnings.push({
|
|
485
|
+
type: 'unsupported',
|
|
486
|
+
feature: 'toolChoice',
|
|
487
|
+
details:
|
|
488
|
+
`toolChoice 'tool' is not supported by this model because it rejects forced tool use. ` +
|
|
489
|
+
`Only the '${toolChoice.toolName}' tool is sent with 'auto' tool choice. ` +
|
|
490
|
+
`Instruct the model to use the tool in the prompt and verify that a tool call was made.`,
|
|
491
|
+
});
|
|
492
|
+
return {
|
|
493
|
+
tools: anthropicTools.filter(
|
|
494
|
+
tool => 'name' in tool && tool.name === toolChoice.toolName,
|
|
495
|
+
),
|
|
496
|
+
toolChoice: {
|
|
497
|
+
type: 'auto',
|
|
498
|
+
disable_parallel_tool_use: disableParallelToolUse,
|
|
499
|
+
},
|
|
500
|
+
toolWarnings,
|
|
501
|
+
betas,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
428
504
|
return {
|
|
429
505
|
tools: anthropicTools,
|
|
430
506
|
toolChoice: {
|
package/src/anthropic-tools.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { codeExecution_20260120 } from './tool/code-execution_20260120';
|
|
|
7
7
|
import { computer_20241022 } from './tool/computer_20241022';
|
|
8
8
|
import { computer_20250124 } from './tool/computer_20250124';
|
|
9
9
|
import { computer_20251124 } from './tool/computer_20251124';
|
|
10
|
+
import { computerToolset_20260801 } from './tool/computer-toolset_20260801';
|
|
10
11
|
import { memory_20250818 } from './tool/memory_20250818';
|
|
11
12
|
import { textEditor_20241022 } from './tool/text-editor_20241022';
|
|
12
13
|
import { textEditor_20250124 } from './tool/text-editor_20250124';
|
|
@@ -143,6 +144,30 @@ export const anthropicTools = {
|
|
|
143
144
|
*/
|
|
144
145
|
computer_20251124,
|
|
145
146
|
|
|
147
|
+
/**
|
|
148
|
+
* The computer toolset lets Claude control a computer through screenshots,
|
|
149
|
+
* mouse, and keyboard. It replaces the versioned computer tools
|
|
150
|
+
* (`computer_20251124` and earlier) on newer models.
|
|
151
|
+
*
|
|
152
|
+
* The API returns each computer action as its own `tool_use` block with
|
|
153
|
+
* `toolset_name: 'computer'`. The AI SDK maps every member call to this tool
|
|
154
|
+
* and exposes the member name as `action`, so `execute` receives the same
|
|
155
|
+
* input shape as the older computer tools. Claude may return several actions
|
|
156
|
+
* in one turn.
|
|
157
|
+
*
|
|
158
|
+
* Coordinates are always in the pixel space of the screenshots you return;
|
|
159
|
+
* there are no display size parameters. Zoom is enabled by default.
|
|
160
|
+
*
|
|
161
|
+
* Does not require a beta header.
|
|
162
|
+
*
|
|
163
|
+
* Supported models: Claude Opus 5.5 (required; older computer tool types
|
|
164
|
+
* are rejected), Opus 5, Sonnet 5, Fable 5, Fable 5.1, Opus 4.8.
|
|
165
|
+
*
|
|
166
|
+
* @param configs - Per-member settings keyed by member name, e.g.
|
|
167
|
+
* `{ zoom: { enabled: false } }`. Omitted members keep their defaults.
|
|
168
|
+
*/
|
|
169
|
+
computerToolset_20260801,
|
|
170
|
+
|
|
146
171
|
/**
|
|
147
172
|
* The memory tool enables Claude to store and retrieve information across conversations through a memory file directory.
|
|
148
173
|
* Claude can create, read, update, and delete files that persist between sessions,
|