@ai-sdk/anthropic 4.0.59 → 4.0.61
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 +21 -0
- package/dist/index.d.ts +47 -1
- package/dist/index.js +971 -561
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +85 -3
- package/dist/internal/index.js +919 -512
- package/dist/internal/index.js.map +1 -1
- package/docs/05-anthropic.mdx +125 -14
- package/package.json +3 -3
- package/src/anthropic-api.ts +24 -1
- package/src/anthropic-batch.ts +4 -0
- package/src/anthropic-language-model-options.ts +13 -3
- package/src/anthropic-language-model.ts +291 -5
- package/src/anthropic-prepare-tools.ts +76 -0
- package/src/anthropic-tools.ts +25 -0
- package/src/convert-to-anthropic-prompt.ts +84 -5
- package/src/tool/computer-toolset_20260801.ts +165 -0
|
@@ -195,6 +195,48 @@ function getAnthropicCallerMetadata(
|
|
|
195
195
|
: { providerMetadata: { anthropic: { caller: callerInfo } } };
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Maps the custom tool names of toolset tools (e.g. the computer toolset) to
|
|
200
|
+
* the toolset name that the Anthropic API uses in `toolset_name`.
|
|
201
|
+
*/
|
|
202
|
+
function getAnthropicToolsetNames(
|
|
203
|
+
tools: LanguageModelV4CallOptions['tools'],
|
|
204
|
+
): Record<string, string> {
|
|
205
|
+
const toolsetNames: Record<string, string> = {};
|
|
206
|
+
|
|
207
|
+
for (const tool of tools ?? []) {
|
|
208
|
+
if (
|
|
209
|
+
tool.type === 'provider' &&
|
|
210
|
+
tool.id === 'anthropic.computer_toolset_20260801'
|
|
211
|
+
) {
|
|
212
|
+
toolsetNames[tool.name] = 'computer';
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return toolsetNames;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Toolset member calls (e.g. `left_click` from the computer toolset) are
|
|
221
|
+
* exposed as a single tool call on the toolset tool. The member name is
|
|
222
|
+
* injected as the `action` property, matching the input shape of the older
|
|
223
|
+
* computer tool versions.
|
|
224
|
+
*/
|
|
225
|
+
function toToolsetMemberInput({
|
|
226
|
+
memberName,
|
|
227
|
+
input,
|
|
228
|
+
}: {
|
|
229
|
+
memberName: string;
|
|
230
|
+
input: unknown;
|
|
231
|
+
}): JSONObject {
|
|
232
|
+
return {
|
|
233
|
+
action: memberName,
|
|
234
|
+
...(typeof input === 'object' && input !== null && !Array.isArray(input)
|
|
235
|
+
? (input as JSONObject)
|
|
236
|
+
: {}),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
198
240
|
function getProviderOptionsName(provider: string): string {
|
|
199
241
|
const dotIndex = provider.indexOf('.');
|
|
200
242
|
return dotIndex === -1 ? provider : provider.substring(0, dotIndex);
|
|
@@ -362,6 +404,8 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
362
404
|
rejectsSamplingParameters,
|
|
363
405
|
supportsXhighEffort,
|
|
364
406
|
rejectsThinkingDisabledAboveHighEffort,
|
|
407
|
+
rejectsThinkingDisabled,
|
|
408
|
+
rejectsForcedToolUse,
|
|
365
409
|
isKnownModel,
|
|
366
410
|
} = getModelCapabilities(modelId);
|
|
367
411
|
|
|
@@ -414,10 +458,30 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
414
458
|
|
|
415
459
|
const structureOutputMode =
|
|
416
460
|
anthropicOptions?.structuredOutputMode ?? 'auto';
|
|
417
|
-
|
|
461
|
+
let useStructuredOutput =
|
|
418
462
|
structureOutputMode === 'outputFormat' ||
|
|
419
463
|
(structureOutputMode === 'auto' && supportsStructuredOutput);
|
|
420
464
|
|
|
465
|
+
// The JSON response tool relies on forced tool use, which some models
|
|
466
|
+
// reject (e.g. Opus 5.5, Fable 5.1). Fall back to native structured
|
|
467
|
+
// outputs when the model supports them.
|
|
468
|
+
if (
|
|
469
|
+
!useStructuredOutput &&
|
|
470
|
+
rejectsForcedToolUse &&
|
|
471
|
+
supportsStructuredOutput &&
|
|
472
|
+
responseFormat?.type === 'json' &&
|
|
473
|
+
responseFormat.schema != null
|
|
474
|
+
) {
|
|
475
|
+
warnings.push({
|
|
476
|
+
type: 'unsupported',
|
|
477
|
+
feature: 'providerOptions.anthropic.structuredOutputMode',
|
|
478
|
+
details:
|
|
479
|
+
`structuredOutputMode 'jsonTool' is not supported by ${modelId} because it rejects forced tool use. ` +
|
|
480
|
+
`Using 'outputFormat' instead.`,
|
|
481
|
+
});
|
|
482
|
+
useStructuredOutput = true;
|
|
483
|
+
}
|
|
484
|
+
|
|
421
485
|
const jsonResponseTool: LanguageModelV4FunctionTool | undefined =
|
|
422
486
|
responseFormat?.type === 'json' &&
|
|
423
487
|
responseFormat.schema != null &&
|
|
@@ -456,6 +520,8 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
456
520
|
'anthropic.code_execution_20260120': 'code_execution',
|
|
457
521
|
'anthropic.computer_20241022': 'computer',
|
|
458
522
|
'anthropic.computer_20250124': 'computer',
|
|
523
|
+
'anthropic.computer_20251124': 'computer',
|
|
524
|
+
'anthropic.computer_toolset_20260801': 'computer',
|
|
459
525
|
'anthropic.text_editor_20241022': 'str_replace_editor',
|
|
460
526
|
'anthropic.text_editor_20250124': 'str_replace_editor',
|
|
461
527
|
'anthropic.text_editor_20250429': 'str_replace_based_edit_tool',
|
|
@@ -475,12 +541,15 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
475
541
|
},
|
|
476
542
|
});
|
|
477
543
|
|
|
544
|
+
const toolsetNames = getAnthropicToolsetNames(tools);
|
|
545
|
+
|
|
478
546
|
const { prompt: messagesPrompt, betas } = await convertToAnthropicPrompt({
|
|
479
547
|
prompt,
|
|
480
548
|
sendReasoning: anthropicOptions?.sendReasoning ?? true,
|
|
481
549
|
warnings,
|
|
482
550
|
cacheControlValidator,
|
|
483
551
|
toolNameMapping,
|
|
552
|
+
toolsetNames,
|
|
484
553
|
});
|
|
485
554
|
|
|
486
555
|
/*
|
|
@@ -490,8 +559,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
490
559
|
if (isCustomReasoning(reasoning) && anthropicOptions?.effort == null) {
|
|
491
560
|
const reasoningConfig = resolveAnthropicReasoningConfig({
|
|
492
561
|
reasoning,
|
|
562
|
+
modelId,
|
|
493
563
|
supportsAdaptiveThinking,
|
|
494
564
|
supportsXhighEffort,
|
|
565
|
+
rejectsThinkingDisabled,
|
|
495
566
|
maxOutputTokensForModel,
|
|
496
567
|
warnings,
|
|
497
568
|
});
|
|
@@ -508,6 +579,33 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
508
579
|
}
|
|
509
580
|
}
|
|
510
581
|
|
|
582
|
+
// Some models always run adaptive thinking and reject `disabled` and
|
|
583
|
+
// budget-based `enabled` thinking with a 400. Drop the unsupported
|
|
584
|
+
// setting and keep the request adaptive so it still succeeds.
|
|
585
|
+
if (rejectsThinkingDisabled && anthropicOptions?.thinking != null) {
|
|
586
|
+
const thinking = anthropicOptions.thinking;
|
|
587
|
+
|
|
588
|
+
if (thinking.type === 'disabled') {
|
|
589
|
+
warnings.push({
|
|
590
|
+
type: 'unsupported',
|
|
591
|
+
feature: 'providerOptions.anthropic.thinking',
|
|
592
|
+
details:
|
|
593
|
+
`thinking cannot be disabled for ${modelId}; it always uses adaptive thinking. ` +
|
|
594
|
+
`The thinking setting has been removed. Lower 'effort' to reduce thinking.`,
|
|
595
|
+
});
|
|
596
|
+
anthropicOptions.thinking = undefined;
|
|
597
|
+
} else if (thinking.type === 'enabled') {
|
|
598
|
+
warnings.push({
|
|
599
|
+
type: 'unsupported',
|
|
600
|
+
feature: 'providerOptions.anthropic.thinking',
|
|
601
|
+
details:
|
|
602
|
+
`budget-based thinking is not supported by ${modelId}; it always uses adaptive thinking. ` +
|
|
603
|
+
`Using adaptive thinking instead. Use 'effort' to control how much the model thinks.`,
|
|
604
|
+
});
|
|
605
|
+
anthropicOptions.thinking = { type: 'adaptive' };
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
511
609
|
// Newer models only allow disabling thinking at effort levels up to and
|
|
512
610
|
// including `high`; at `xhigh` and `max` the API returns a 400. Lower
|
|
513
611
|
// the effort to `high` to preserve the explicit request to run without
|
|
@@ -903,6 +1001,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
903
1001
|
supportsStructuredOutput: false,
|
|
904
1002
|
supportsStrictTools,
|
|
905
1003
|
defaultEagerInputStreaming,
|
|
1004
|
+
rejectsForcedToolUse,
|
|
906
1005
|
}
|
|
907
1006
|
: {
|
|
908
1007
|
tools: tools ?? [],
|
|
@@ -912,6 +1011,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
912
1011
|
supportsStructuredOutput,
|
|
913
1012
|
supportsStrictTools,
|
|
914
1013
|
defaultEagerInputStreaming,
|
|
1014
|
+
rejectsForcedToolUse,
|
|
915
1015
|
},
|
|
916
1016
|
);
|
|
917
1017
|
|
|
@@ -1161,6 +1261,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1161
1261
|
break;
|
|
1162
1262
|
}
|
|
1163
1263
|
case 'compaction': {
|
|
1264
|
+
if (!part.content) {
|
|
1265
|
+
break;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1164
1268
|
content.push({
|
|
1165
1269
|
type: 'text',
|
|
1166
1270
|
text: part.content,
|
|
@@ -1184,6 +1288,27 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1184
1288
|
type: 'text',
|
|
1185
1289
|
text: JSON.stringify(part.input),
|
|
1186
1290
|
});
|
|
1291
|
+
} else if (part.toolset_name != null) {
|
|
1292
|
+
// toolset member calls (e.g. the computer toolset) are mapped to
|
|
1293
|
+
// the toolset tool with the member name as the `action`:
|
|
1294
|
+
content.push({
|
|
1295
|
+
type: 'tool-call',
|
|
1296
|
+
toolCallId: part.id,
|
|
1297
|
+
toolName: toolNameMapping.toCustomToolName(part.toolset_name),
|
|
1298
|
+
input: JSON.stringify(
|
|
1299
|
+
toToolsetMemberInput({
|
|
1300
|
+
memberName: part.name,
|
|
1301
|
+
input: part.input,
|
|
1302
|
+
}),
|
|
1303
|
+
),
|
|
1304
|
+
providerMetadata: {
|
|
1305
|
+
anthropic: {
|
|
1306
|
+
toolsetName: part.toolset_name,
|
|
1307
|
+
...getAnthropicCallerMetadata(part.caller).providerMetadata
|
|
1308
|
+
?.anthropic,
|
|
1309
|
+
},
|
|
1310
|
+
},
|
|
1311
|
+
});
|
|
1187
1312
|
} else {
|
|
1188
1313
|
content.push({
|
|
1189
1314
|
type: 'tool-call',
|
|
@@ -1696,6 +1821,12 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1696
1821
|
firstDelta: boolean;
|
|
1697
1822
|
providerToolName?: string;
|
|
1698
1823
|
providerToolInputType?: string;
|
|
1824
|
+
/**
|
|
1825
|
+
* Set for toolset member calls (e.g. the computer toolset). The raw
|
|
1826
|
+
* member input is accumulated and emitted as a single delta with the
|
|
1827
|
+
* member name injected as `action` when the block completes.
|
|
1828
|
+
*/
|
|
1829
|
+
toolset?: { name: string; memberName: string };
|
|
1699
1830
|
caller?: {
|
|
1700
1831
|
type:
|
|
1701
1832
|
| 'code_execution_20250825'
|
|
@@ -1862,6 +1993,34 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1862
1993
|
type: 'text-start',
|
|
1863
1994
|
id: String(value.index),
|
|
1864
1995
|
});
|
|
1996
|
+
} else if (part.toolset_name != null) {
|
|
1997
|
+
const callerInfo = getAnthropicCallerInfo(part.caller);
|
|
1998
|
+
const customToolName = toolNameMapping.toCustomToolName(
|
|
1999
|
+
part.toolset_name,
|
|
2000
|
+
);
|
|
2001
|
+
const hasNonEmptyInput =
|
|
2002
|
+
part.input && Object.keys(part.input).length > 0;
|
|
2003
|
+
|
|
2004
|
+
// toolset member input is accumulated and emitted when the
|
|
2005
|
+
// block completes (see content_block_stop):
|
|
2006
|
+
contentBlocks[value.index] = {
|
|
2007
|
+
type: 'tool-call',
|
|
2008
|
+
toolCallId: part.id,
|
|
2009
|
+
toolName: customToolName,
|
|
2010
|
+
input: hasNonEmptyInput ? JSON.stringify(part.input) : '',
|
|
2011
|
+
firstDelta: true,
|
|
2012
|
+
toolset: {
|
|
2013
|
+
name: part.toolset_name,
|
|
2014
|
+
memberName: part.name,
|
|
2015
|
+
},
|
|
2016
|
+
...(callerInfo && { caller: callerInfo }),
|
|
2017
|
+
};
|
|
2018
|
+
|
|
2019
|
+
controller.enqueue({
|
|
2020
|
+
type: 'tool-input-start',
|
|
2021
|
+
id: part.id,
|
|
2022
|
+
toolName: customToolName,
|
|
2023
|
+
});
|
|
1865
2024
|
} else {
|
|
1866
2025
|
const callerInfo = getAnthropicCallerInfo(part.caller);
|
|
1867
2026
|
|
|
@@ -2352,6 +2511,37 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
2352
2511
|
usesJsonResponseTool && contentBlock.toolName === 'json';
|
|
2353
2512
|
|
|
2354
2513
|
if (!isJsonResponseTool) {
|
|
2514
|
+
// toolset member calls: emit the accumulated input with
|
|
2515
|
+
// the member name injected as `action` in one delta.
|
|
2516
|
+
if (contentBlock.toolset != null) {
|
|
2517
|
+
let memberInput: unknown = {};
|
|
2518
|
+
try {
|
|
2519
|
+
memberInput =
|
|
2520
|
+
contentBlock.input === ''
|
|
2521
|
+
? {}
|
|
2522
|
+
: secureJsonParse(contentBlock.input);
|
|
2523
|
+
} catch {
|
|
2524
|
+
// ignore parse errors, fall back to the raw input
|
|
2525
|
+
memberInput = undefined;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
contentBlock.input =
|
|
2529
|
+
memberInput === undefined
|
|
2530
|
+
? contentBlock.input
|
|
2531
|
+
: JSON.stringify(
|
|
2532
|
+
toToolsetMemberInput({
|
|
2533
|
+
memberName: contentBlock.toolset.memberName,
|
|
2534
|
+
input: memberInput,
|
|
2535
|
+
}),
|
|
2536
|
+
);
|
|
2537
|
+
|
|
2538
|
+
controller.enqueue({
|
|
2539
|
+
type: 'tool-input-delta',
|
|
2540
|
+
id: contentBlock.toolCallId,
|
|
2541
|
+
delta: contentBlock.input,
|
|
2542
|
+
});
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2355
2545
|
controller.enqueue({
|
|
2356
2546
|
type: 'tool-input-end',
|
|
2357
2547
|
id: contentBlock.toolCallId,
|
|
@@ -2394,10 +2584,15 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
2394
2584
|
contentBlock.providerToolName === 'code_execution'
|
|
2395
2585
|
? { dynamic: true }
|
|
2396
2586
|
: {}),
|
|
2397
|
-
...(contentBlock.caller && {
|
|
2587
|
+
...((contentBlock.caller || contentBlock.toolset) && {
|
|
2398
2588
|
providerMetadata: {
|
|
2399
2589
|
anthropic: {
|
|
2400
|
-
|
|
2590
|
+
...(contentBlock.toolset && {
|
|
2591
|
+
toolsetName: contentBlock.toolset.name,
|
|
2592
|
+
}),
|
|
2593
|
+
...(contentBlock.caller && {
|
|
2594
|
+
caller: contentBlock.caller,
|
|
2595
|
+
}),
|
|
2401
2596
|
},
|
|
2402
2597
|
},
|
|
2403
2598
|
}),
|
|
@@ -2499,6 +2694,13 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
2499
2694
|
return;
|
|
2500
2695
|
}
|
|
2501
2696
|
|
|
2697
|
+
// toolset member input is emitted as a single delta once
|
|
2698
|
+
// the block is complete (the member name is injected):
|
|
2699
|
+
if (contentBlock.toolset != null) {
|
|
2700
|
+
contentBlock.input += delta;
|
|
2701
|
+
return;
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2502
2704
|
// for the code execution 20250825, we need to add
|
|
2503
2705
|
// the type to the delta and change the tool name.
|
|
2504
2706
|
if (
|
|
@@ -2872,9 +3074,18 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2872
3074
|
rejectsSamplingParameters: boolean;
|
|
2873
3075
|
supportsXhighEffort: boolean;
|
|
2874
3076
|
rejectsThinkingDisabledAboveHighEffort: boolean;
|
|
3077
|
+
/**
|
|
3078
|
+
* Thinking is always adaptive: `thinking.type` `disabled` and `enabled`
|
|
3079
|
+
* are rejected with a 400.
|
|
3080
|
+
*/
|
|
3081
|
+
rejectsThinkingDisabled: boolean;
|
|
3082
|
+
/**
|
|
3083
|
+
* Forced tool use (`tool_choice` `any` or a named tool) is rejected with a 400.
|
|
3084
|
+
*/
|
|
3085
|
+
rejectsForcedToolUse: boolean;
|
|
2875
3086
|
isKnownModel: boolean;
|
|
2876
3087
|
} {
|
|
2877
|
-
if (modelId.includes('claude-opus-5')) {
|
|
3088
|
+
if (modelId.includes('claude-opus-5-5')) {
|
|
2878
3089
|
return {
|
|
2879
3090
|
maxOutputTokens: 128000,
|
|
2880
3091
|
supportsStructuredOutput: true,
|
|
@@ -2882,12 +3093,49 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2882
3093
|
rejectsSamplingParameters: true,
|
|
2883
3094
|
supportsXhighEffort: true,
|
|
2884
3095
|
rejectsThinkingDisabledAboveHighEffort: true,
|
|
3096
|
+
rejectsThinkingDisabled: true,
|
|
3097
|
+
rejectsForcedToolUse: true,
|
|
3098
|
+
isKnownModel: true,
|
|
3099
|
+
};
|
|
3100
|
+
} else if (modelId.includes('claude-opus-5')) {
|
|
3101
|
+
return {
|
|
3102
|
+
maxOutputTokens: 128000,
|
|
3103
|
+
supportsStructuredOutput: true,
|
|
3104
|
+
supportsAdaptiveThinking: true,
|
|
3105
|
+
rejectsSamplingParameters: true,
|
|
3106
|
+
supportsXhighEffort: true,
|
|
3107
|
+
rejectsThinkingDisabledAboveHighEffort: true,
|
|
3108
|
+
rejectsThinkingDisabled: false,
|
|
3109
|
+
rejectsForcedToolUse: false,
|
|
3110
|
+
isKnownModel: true,
|
|
3111
|
+
};
|
|
3112
|
+
} else if (modelId.includes('claude-fable-5-1')) {
|
|
3113
|
+
return {
|
|
3114
|
+
maxOutputTokens: 128000,
|
|
3115
|
+
supportsStructuredOutput: true,
|
|
3116
|
+
supportsAdaptiveThinking: true,
|
|
3117
|
+
rejectsSamplingParameters: true,
|
|
3118
|
+
supportsXhighEffort: true,
|
|
3119
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3120
|
+
rejectsThinkingDisabled: true,
|
|
3121
|
+
rejectsForcedToolUse: true,
|
|
3122
|
+
isKnownModel: true,
|
|
3123
|
+
};
|
|
3124
|
+
} else if (modelId.includes('claude-fable-5')) {
|
|
3125
|
+
return {
|
|
3126
|
+
maxOutputTokens: 128000,
|
|
3127
|
+
supportsStructuredOutput: true,
|
|
3128
|
+
supportsAdaptiveThinking: true,
|
|
3129
|
+
rejectsSamplingParameters: true,
|
|
3130
|
+
supportsXhighEffort: true,
|
|
3131
|
+
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3132
|
+
rejectsThinkingDisabled: true,
|
|
3133
|
+
rejectsForcedToolUse: false,
|
|
2885
3134
|
isKnownModel: true,
|
|
2886
3135
|
};
|
|
2887
3136
|
} else if (
|
|
2888
3137
|
modelId.includes('claude-opus-4-8') ||
|
|
2889
3138
|
modelId.includes('claude-opus-4-7') ||
|
|
2890
|
-
modelId.includes('claude-fable-5') ||
|
|
2891
3139
|
modelId.includes('claude-sonnet-5')
|
|
2892
3140
|
) {
|
|
2893
3141
|
return {
|
|
@@ -2897,6 +3145,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2897
3145
|
rejectsSamplingParameters: true,
|
|
2898
3146
|
supportsXhighEffort: true,
|
|
2899
3147
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3148
|
+
rejectsThinkingDisabled: false,
|
|
3149
|
+
rejectsForcedToolUse: false,
|
|
2900
3150
|
isKnownModel: true,
|
|
2901
3151
|
};
|
|
2902
3152
|
} else if (
|
|
@@ -2910,6 +3160,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2910
3160
|
rejectsSamplingParameters: false,
|
|
2911
3161
|
supportsXhighEffort: false,
|
|
2912
3162
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3163
|
+
rejectsThinkingDisabled: false,
|
|
3164
|
+
rejectsForcedToolUse: false,
|
|
2913
3165
|
isKnownModel: true,
|
|
2914
3166
|
};
|
|
2915
3167
|
} else if (
|
|
@@ -2924,6 +3176,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2924
3176
|
rejectsSamplingParameters: false,
|
|
2925
3177
|
supportsXhighEffort: false,
|
|
2926
3178
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3179
|
+
rejectsThinkingDisabled: false,
|
|
3180
|
+
rejectsForcedToolUse: false,
|
|
2927
3181
|
isKnownModel: true,
|
|
2928
3182
|
};
|
|
2929
3183
|
} else if (modelId.includes('claude-opus-4-1')) {
|
|
@@ -2934,6 +3188,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2934
3188
|
rejectsSamplingParameters: false,
|
|
2935
3189
|
supportsXhighEffort: false,
|
|
2936
3190
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3191
|
+
rejectsThinkingDisabled: false,
|
|
3192
|
+
rejectsForcedToolUse: false,
|
|
2937
3193
|
isKnownModel: true,
|
|
2938
3194
|
};
|
|
2939
3195
|
} else if (/claude-sonnet-4(?:-|@)/.test(modelId)) {
|
|
@@ -2944,6 +3200,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2944
3200
|
rejectsSamplingParameters: false,
|
|
2945
3201
|
supportsXhighEffort: false,
|
|
2946
3202
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3203
|
+
rejectsThinkingDisabled: false,
|
|
3204
|
+
rejectsForcedToolUse: false,
|
|
2947
3205
|
isKnownModel: true,
|
|
2948
3206
|
};
|
|
2949
3207
|
} else if (/claude-opus-4(?:-|@)/.test(modelId)) {
|
|
@@ -2954,6 +3212,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2954
3212
|
rejectsSamplingParameters: false,
|
|
2955
3213
|
supportsXhighEffort: false,
|
|
2956
3214
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3215
|
+
rejectsThinkingDisabled: false,
|
|
3216
|
+
rejectsForcedToolUse: false,
|
|
2957
3217
|
isKnownModel: true,
|
|
2958
3218
|
};
|
|
2959
3219
|
} else if (modelId.includes('claude-3-haiku')) {
|
|
@@ -2964,6 +3224,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2964
3224
|
rejectsSamplingParameters: false,
|
|
2965
3225
|
supportsXhighEffort: false,
|
|
2966
3226
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3227
|
+
rejectsThinkingDisabled: false,
|
|
3228
|
+
rejectsForcedToolUse: false,
|
|
2967
3229
|
isKnownModel: true,
|
|
2968
3230
|
};
|
|
2969
3231
|
} else if (
|
|
@@ -2976,6 +3238,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2976
3238
|
rejectsSamplingParameters: false,
|
|
2977
3239
|
supportsXhighEffort: false,
|
|
2978
3240
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3241
|
+
rejectsThinkingDisabled: false,
|
|
3242
|
+
rejectsForcedToolUse: false,
|
|
2979
3243
|
isKnownModel: false,
|
|
2980
3244
|
};
|
|
2981
3245
|
} else if (modelId.includes('claude-')) {
|
|
@@ -2989,6 +3253,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
2989
3253
|
rejectsSamplingParameters: true,
|
|
2990
3254
|
supportsXhighEffort: true,
|
|
2991
3255
|
rejectsThinkingDisabledAboveHighEffort: true,
|
|
3256
|
+
rejectsThinkingDisabled: false,
|
|
3257
|
+
rejectsForcedToolUse: false,
|
|
2992
3258
|
isKnownModel: false,
|
|
2993
3259
|
};
|
|
2994
3260
|
} else {
|
|
@@ -3001,6 +3267,8 @@ export function getModelCapabilities(modelId: string): {
|
|
|
3001
3267
|
rejectsSamplingParameters: false,
|
|
3002
3268
|
supportsXhighEffort: false,
|
|
3003
3269
|
rejectsThinkingDisabledAboveHighEffort: false,
|
|
3270
|
+
rejectsThinkingDisabled: false,
|
|
3271
|
+
rejectsForcedToolUse: false,
|
|
3004
3272
|
isKnownModel: false,
|
|
3005
3273
|
};
|
|
3006
3274
|
}
|
|
@@ -3040,14 +3308,18 @@ export function hasDynamicFilteringWebToolWithoutCodeExecution(
|
|
|
3040
3308
|
|
|
3041
3309
|
function resolveAnthropicReasoningConfig({
|
|
3042
3310
|
reasoning,
|
|
3311
|
+
modelId,
|
|
3043
3312
|
supportsAdaptiveThinking,
|
|
3044
3313
|
supportsXhighEffort,
|
|
3314
|
+
rejectsThinkingDisabled,
|
|
3045
3315
|
maxOutputTokensForModel,
|
|
3046
3316
|
warnings,
|
|
3047
3317
|
}: {
|
|
3048
3318
|
reasoning: LanguageModelV4CallOptions['reasoning'];
|
|
3319
|
+
modelId: string;
|
|
3049
3320
|
supportsAdaptiveThinking: boolean;
|
|
3050
3321
|
supportsXhighEffort: boolean;
|
|
3322
|
+
rejectsThinkingDisabled: boolean;
|
|
3051
3323
|
maxOutputTokensForModel: number;
|
|
3052
3324
|
warnings: SharedV4Warning[];
|
|
3053
3325
|
}): Pick<AnthropicLanguageModelOptions, 'thinking' | 'effort'> | undefined {
|
|
@@ -3056,6 +3328,20 @@ function resolveAnthropicReasoningConfig({
|
|
|
3056
3328
|
}
|
|
3057
3329
|
|
|
3058
3330
|
if (reasoning === 'none') {
|
|
3331
|
+
// Models that always run adaptive thinking cannot disable it. Use low
|
|
3332
|
+
// effort to keep thinking short instead of sending a request that the
|
|
3333
|
+
// API would reject.
|
|
3334
|
+
if (rejectsThinkingDisabled) {
|
|
3335
|
+
warnings.push({
|
|
3336
|
+
type: 'compatibility',
|
|
3337
|
+
feature: 'reasoning',
|
|
3338
|
+
details:
|
|
3339
|
+
`reasoning 'none' is not supported by ${modelId}; it always uses adaptive thinking. ` +
|
|
3340
|
+
`Using effort 'low' to minimize thinking instead.`,
|
|
3341
|
+
});
|
|
3342
|
+
return { effort: 'low' };
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3059
3345
|
return { thinking: { type: 'disabled' } };
|
|
3060
3346
|
}
|
|
3061
3347
|
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import type { AnthropicTool, AnthropicToolChoice } from './anthropic-api';
|
|
7
7
|
import { CacheControlValidator } from './get-cache-control';
|
|
8
8
|
import { advisor_20260301ArgsSchema } from './tool/advisor_20260301';
|
|
9
|
+
import { computerToolset_20260801ArgsSchema } from './tool/computer-toolset_20260801';
|
|
9
10
|
import { textEditor_20250728ArgsSchema } from './tool/text-editor_20250728';
|
|
10
11
|
import { webSearch_20260318ArgsSchema } from './tool/web-search_20260318';
|
|
11
12
|
import { webSearch_20260209ArgsSchema } from './tool/web-search_20260209';
|
|
@@ -31,6 +32,7 @@ export async function prepareTools({
|
|
|
31
32
|
supportsStructuredOutput,
|
|
32
33
|
supportsStrictTools,
|
|
33
34
|
defaultEagerInputStreaming = false,
|
|
35
|
+
rejectsForcedToolUse = false,
|
|
34
36
|
}: {
|
|
35
37
|
tools: LanguageModelV4CallOptions['tools'];
|
|
36
38
|
toolChoice: LanguageModelV4CallOptions['toolChoice'] | undefined;
|
|
@@ -52,6 +54,13 @@ export async function prepareTools({
|
|
|
52
54
|
* it explicitly. Driven by the model-level `toolStreaming` option.
|
|
53
55
|
*/
|
|
54
56
|
defaultEagerInputStreaming?: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether the model rejects forced tool use (`tool_choice` `any` or a
|
|
60
|
+
* named tool). When true, `required` and `tool` tool choices fall back to
|
|
61
|
+
* `auto` with a warning.
|
|
62
|
+
*/
|
|
63
|
+
rejectsForcedToolUse?: boolean;
|
|
55
64
|
}): Promise<{
|
|
56
65
|
tools: Array<AnthropicTool> | undefined;
|
|
57
66
|
toolChoice: AnthropicToolChoice | undefined;
|
|
@@ -185,6 +194,34 @@ export async function prepareTools({
|
|
|
185
194
|
});
|
|
186
195
|
break;
|
|
187
196
|
}
|
|
197
|
+
case 'anthropic.computer_toolset_20260801': {
|
|
198
|
+
const args = await validateTypes({
|
|
199
|
+
value: tool.args,
|
|
200
|
+
schema: computerToolset_20260801ArgsSchema,
|
|
201
|
+
});
|
|
202
|
+
const configs =
|
|
203
|
+
args.configs != null
|
|
204
|
+
? Object.fromEntries(
|
|
205
|
+
Object.entries(args.configs).map(([member, config]) => [
|
|
206
|
+
member,
|
|
207
|
+
{
|
|
208
|
+
...(config?.enabled != null && {
|
|
209
|
+
enabled: config.enabled,
|
|
210
|
+
}),
|
|
211
|
+
...(config?.deferLoading != null && {
|
|
212
|
+
defer_loading: config.deferLoading,
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
]),
|
|
216
|
+
)
|
|
217
|
+
: undefined;
|
|
218
|
+
anthropicTools.push({
|
|
219
|
+
type: 'computer_toolset_20260801',
|
|
220
|
+
...(configs != null && { configs }),
|
|
221
|
+
cache_control: undefined,
|
|
222
|
+
});
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
188
225
|
case 'anthropic.computer_20241022': {
|
|
189
226
|
betas.add('computer-use-2024-10-22');
|
|
190
227
|
anthropicTools.push({
|
|
@@ -450,6 +487,24 @@ export async function prepareTools({
|
|
|
450
487
|
betas,
|
|
451
488
|
};
|
|
452
489
|
case 'required':
|
|
490
|
+
if (rejectsForcedToolUse) {
|
|
491
|
+
toolWarnings.push({
|
|
492
|
+
type: 'unsupported',
|
|
493
|
+
feature: 'toolChoice',
|
|
494
|
+
details:
|
|
495
|
+
`toolChoice 'required' is not supported by this model because it rejects forced tool use. ` +
|
|
496
|
+
`Using 'auto' instead. Instruct the model to use a tool in the prompt and verify that a tool call was made.`,
|
|
497
|
+
});
|
|
498
|
+
return {
|
|
499
|
+
tools: anthropicTools,
|
|
500
|
+
toolChoice: {
|
|
501
|
+
type: 'auto',
|
|
502
|
+
disable_parallel_tool_use: disableParallelToolUse,
|
|
503
|
+
},
|
|
504
|
+
toolWarnings,
|
|
505
|
+
betas,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
453
508
|
return {
|
|
454
509
|
tools: anthropicTools,
|
|
455
510
|
toolChoice: {
|
|
@@ -463,6 +518,27 @@ export async function prepareTools({
|
|
|
463
518
|
// Anthropic does not support 'none' tool choice, so we remove the tools:
|
|
464
519
|
return { tools: undefined, toolChoice: undefined, toolWarnings, betas };
|
|
465
520
|
case 'tool':
|
|
521
|
+
if (rejectsForcedToolUse) {
|
|
522
|
+
toolWarnings.push({
|
|
523
|
+
type: 'unsupported',
|
|
524
|
+
feature: 'toolChoice',
|
|
525
|
+
details:
|
|
526
|
+
`toolChoice 'tool' is not supported by this model because it rejects forced tool use. ` +
|
|
527
|
+
`Only the '${toolChoice.toolName}' tool is sent with 'auto' tool choice. ` +
|
|
528
|
+
`Instruct the model to use the tool in the prompt and verify that a tool call was made.`,
|
|
529
|
+
});
|
|
530
|
+
return {
|
|
531
|
+
tools: anthropicTools.filter(
|
|
532
|
+
tool => 'name' in tool && tool.name === toolChoice.toolName,
|
|
533
|
+
),
|
|
534
|
+
toolChoice: {
|
|
535
|
+
type: 'auto',
|
|
536
|
+
disable_parallel_tool_use: disableParallelToolUse,
|
|
537
|
+
},
|
|
538
|
+
toolWarnings,
|
|
539
|
+
betas,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
466
542
|
return {
|
|
467
543
|
tools: anthropicTools,
|
|
468
544
|
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';
|
|
@@ -147,6 +148,30 @@ export const anthropicTools = {
|
|
|
147
148
|
*/
|
|
148
149
|
computer_20251124,
|
|
149
150
|
|
|
151
|
+
/**
|
|
152
|
+
* The computer toolset lets Claude control a computer through screenshots,
|
|
153
|
+
* mouse, and keyboard. It replaces the versioned computer tools
|
|
154
|
+
* (`computer_20251124` and earlier) on newer models.
|
|
155
|
+
*
|
|
156
|
+
* The API returns each computer action as its own `tool_use` block with
|
|
157
|
+
* `toolset_name: 'computer'`. The AI SDK maps every member call to this tool
|
|
158
|
+
* and exposes the member name as `action`, so `execute` receives the same
|
|
159
|
+
* input shape as the older computer tools. Claude may return several actions
|
|
160
|
+
* in one turn.
|
|
161
|
+
*
|
|
162
|
+
* Coordinates are always in the pixel space of the screenshots you return;
|
|
163
|
+
* there are no display size parameters. Zoom is enabled by default.
|
|
164
|
+
*
|
|
165
|
+
* Does not require a beta header.
|
|
166
|
+
*
|
|
167
|
+
* Supported models: Claude Opus 5.5 (required; older computer tool types
|
|
168
|
+
* are rejected), Opus 5, Sonnet 5, Fable 5, Fable 5.1, Opus 4.8.
|
|
169
|
+
*
|
|
170
|
+
* @param configs - Per-member settings keyed by member name, e.g.
|
|
171
|
+
* `{ zoom: { enabled: false } }`. Omitted members keep their defaults.
|
|
172
|
+
*/
|
|
173
|
+
computerToolset_20260801,
|
|
174
|
+
|
|
150
175
|
/**
|
|
151
176
|
* The memory tool enables Claude to store and retrieve information across conversations through a memory file directory.
|
|
152
177
|
* Claude can create, read, update, and delete files that persist between sessions,
|