@ai-sdk/anthropic 4.0.58 → 4.0.60

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.
@@ -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: {
@@ -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,
@@ -81,12 +81,20 @@ export async function convertToAnthropicPrompt({
81
81
  warnings,
82
82
  cacheControlValidator,
83
83
  toolNameMapping,
84
+ toolsetNames = {},
84
85
  }: {
85
86
  prompt: LanguageModelV4Prompt;
86
87
  sendReasoning: boolean;
87
88
  warnings: SharedV4Warning[];
88
89
  cacheControlValidator?: CacheControlValidator;
89
90
  toolNameMapping: ToolNameMapping;
91
+
92
+ /**
93
+ * Maps custom tool names of toolset tools (e.g. the computer toolset) to
94
+ * the Anthropic `toolset_name`. Tool calls and results of these tools are
95
+ * serialized as toolset member calls.
96
+ */
97
+ toolsetNames?: Record<string, string>;
90
98
  }): Promise<{
91
99
  prompt: AnthropicPrompt;
92
100
  betas: Set<string>;
@@ -258,7 +266,7 @@ export async function convertToAnthropicPrompt({
258
266
  betas.add('mid-conversation-system-clear-at-2026-08-21');
259
267
  }
260
268
  if (message.effort != null) {
261
- betas.add('mid-conversation-effort-2026-08-01');
269
+ betas.add('mid-conversation-output-config-2026-07-01');
262
270
  }
263
271
  }
264
272
  }
@@ -636,9 +644,16 @@ export async function convertToAnthropicPrompt({
636
644
  break;
637
645
  }
638
646
 
647
+ const toolsetName = getAnthropicToolsetName({
648
+ toolName: part.toolName,
649
+ providerOptions: part.providerOptions,
650
+ toolsetNames,
651
+ });
652
+
639
653
  anthropicContent.push({
640
654
  type: 'tool_result',
641
655
  tool_use_id: part.toolCallId,
656
+ ...(toolsetName != null && { toolset_name: toolsetName }),
642
657
  content: contentValue,
643
658
  is_error:
644
659
  output.type === 'error-text' || output.type === 'error-json'
@@ -902,6 +917,38 @@ export async function convertToAnthropicPrompt({
902
917
  break;
903
918
  }
904
919
 
920
+ const toolsetName = getAnthropicToolsetName({
921
+ toolName: part.toolName,
922
+ providerOptions: part.providerOptions,
923
+ toolsetNames,
924
+ });
925
+
926
+ if (toolsetName != null) {
927
+ // toolset member call: the `action` is the member tool name
928
+ const { action, ...memberInput } = toAnthropicToolInput(
929
+ part.input,
930
+ );
931
+
932
+ if (typeof action !== 'string') {
933
+ warnings.push({
934
+ type: 'other',
935
+ message: `toolset tool call for tool ${part.toolName} is missing the action`,
936
+ });
937
+ break;
938
+ }
939
+
940
+ anthropicContent.push({
941
+ type: 'tool_use',
942
+ id: part.toolCallId,
943
+ name: action,
944
+ toolset_name: toolsetName,
945
+ input: memberInput,
946
+ ...(caller && { caller }),
947
+ cache_control: cacheControl,
948
+ });
949
+ break;
950
+ }
951
+
905
952
  anthropicContent.push({
906
953
  type: 'tool_use',
907
954
  id: part.toolCallId,
@@ -1457,6 +1504,32 @@ function moveToolUseBlocksToEnd(
1457
1504
  return result;
1458
1505
  }
1459
1506
 
1507
+ /**
1508
+ * Resolves the Anthropic `toolset_name` for a tool call or tool result. The
1509
+ * toolset is identified either through the tools passed to the request or
1510
+ * through the `toolsetName` provider metadata of a previous response.
1511
+ */
1512
+ function getAnthropicToolsetName({
1513
+ toolName,
1514
+ providerOptions,
1515
+ toolsetNames,
1516
+ }: {
1517
+ toolName: string;
1518
+ providerOptions: SharedV4ProviderMetadata | undefined;
1519
+ toolsetNames: Record<string, string>;
1520
+ }): string | undefined {
1521
+ const fromTools = toolsetNames[toolName];
1522
+ if (fromTools != null) {
1523
+ return fromTools;
1524
+ }
1525
+
1526
+ const fromMetadata = (
1527
+ providerOptions?.anthropic as { toolsetName?: unknown } | undefined
1528
+ )?.toolsetName;
1529
+
1530
+ return typeof fromMetadata === 'string' ? fromMetadata : undefined;
1531
+ }
1532
+
1460
1533
  function getAnthropicCaller(
1461
1534
  providerOptions: SharedV4ProviderMetadata | undefined,
1462
1535
  ): AnthropicToolCallCaller | undefined {
@@ -0,0 +1,165 @@
1
+ import {
2
+ createProviderDefinedToolFactory,
3
+ lazySchema,
4
+ zodSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ /**
9
+ * Member tools of the computer toolset. Each member is returned by the API as
10
+ * its own `tool_use` block; the AI SDK exposes it as the `action` of a single
11
+ * computer tool call.
12
+ */
13
+ export const computerToolset_20260801Members = [
14
+ 'screenshot',
15
+ 'zoom',
16
+ 'left_click',
17
+ 'right_click',
18
+ 'middle_click',
19
+ 'double_click',
20
+ 'triple_click',
21
+ 'left_click_drag',
22
+ 'mouse_move',
23
+ 'left_mouse_down',
24
+ 'left_mouse_up',
25
+ 'cursor_position',
26
+ 'scroll',
27
+ 'type',
28
+ 'key',
29
+ 'hold_key',
30
+ 'wait',
31
+ ] as const;
32
+
33
+ export type ComputerToolset_20260801Member =
34
+ (typeof computerToolset_20260801Members)[number];
35
+
36
+ const computerToolset_20260801InputSchema = lazySchema(() =>
37
+ zodSchema(
38
+ z.object({
39
+ action: z.enum(computerToolset_20260801Members),
40
+ coordinate: z.tuple([z.number().int(), z.number().int()]).optional(),
41
+ duration: z.number().optional(),
42
+ region: z
43
+ .tuple([
44
+ z.number().int(),
45
+ z.number().int(),
46
+ z.number().int(),
47
+ z.number().int(),
48
+ ])
49
+ .optional(),
50
+ repeat: z.number().int().optional(),
51
+ scroll_amount: z.number().optional(),
52
+ scroll_direction: z.enum(['up', 'down', 'left', 'right']).optional(),
53
+ start_coordinate: z
54
+ .tuple([z.number().int(), z.number().int()])
55
+ .optional(),
56
+ text: z.string().optional(),
57
+ }),
58
+ ),
59
+ );
60
+
61
+ export const computerToolset_20260801ArgsSchema = lazySchema(() =>
62
+ zodSchema(
63
+ z.object({
64
+ configs: z
65
+ .partialRecord(
66
+ z.enum(computerToolset_20260801Members),
67
+ z.object({
68
+ enabled: z.boolean().optional(),
69
+ deferLoading: z.boolean().optional(),
70
+ }),
71
+ )
72
+ .optional(),
73
+ }),
74
+ ),
75
+ );
76
+
77
+ export const computerToolset_20260801 = createProviderDefinedToolFactory<
78
+ {
79
+ /**
80
+ * The member tool that Claude invoked. Each member is returned by the API
81
+ * as a separate `tool_use` block; the AI SDK maps it to the `action`.
82
+ *
83
+ * - `screenshot`: Capture the full display as an image.
84
+ * - `zoom`: Capture a `region` of the screen at full resolution.
85
+ * - `left_click`, `right_click`, `middle_click`, `double_click`, `triple_click`: Click at `coordinate`. `text` may hold modifier keys to hold while clicking.
86
+ * - `left_click_drag`: Drag from `start_coordinate` to `coordinate`.
87
+ * - `mouse_move`: Move the cursor to `coordinate` without clicking.
88
+ * - `left_mouse_down`, `left_mouse_up`: Press or release the left mouse button at the current position.
89
+ * - `cursor_position`: Report the current cursor position as text.
90
+ * - `scroll`: Scroll `scroll_amount` clicks in `scroll_direction` at `coordinate`.
91
+ * - `type`: Type the literal `text`.
92
+ * - `key`: Press a key or key combination (`text`), optionally `repeat` times.
93
+ * - `hold_key`: Hold a key or key combination (`text`) for `duration` seconds.
94
+ * - `wait`: Pause for `duration` seconds.
95
+ */
96
+ action: ComputerToolset_20260801Member;
97
+
98
+ /**
99
+ * (x, y): Pixel coordinates in the space of the screenshots you return.
100
+ */
101
+ coordinate?: [number, number];
102
+
103
+ /**
104
+ * Duration in seconds. Used by `hold_key` and `wait`.
105
+ */
106
+ duration?: number;
107
+
108
+ /**
109
+ * [x1, y1, x2, y2]: The region to zoom into. Used by `zoom`.
110
+ */
111
+ region?: [number, number, number, number];
112
+
113
+ /**
114
+ * How many times to press the key. Used by `key`.
115
+ */
116
+ repeat?: number;
117
+
118
+ /**
119
+ * The number of scroll wheel clicks. Used by `scroll`.
120
+ */
121
+ scroll_amount?: number;
122
+
123
+ /**
124
+ * The direction to scroll. Used by `scroll`.
125
+ */
126
+ scroll_direction?: 'up' | 'down' | 'left' | 'right';
127
+
128
+ /**
129
+ * (x, y): Where a drag starts. Used by `left_click_drag`.
130
+ */
131
+ start_coordinate?: [number, number];
132
+
133
+ /**
134
+ * Text to type, a key combination to press or hold, or modifier keys to
135
+ * hold during click and scroll actions.
136
+ */
137
+ text?: string;
138
+ },
139
+ {
140
+ /**
141
+ * Per-member configuration. Members you omit keep their defaults
142
+ * (all members enabled, including `zoom`).
143
+ */
144
+ configs?: Partial<
145
+ Record<
146
+ ComputerToolset_20260801Member,
147
+ {
148
+ /**
149
+ * Whether Claude can use this member tool. Default: true.
150
+ */
151
+ enabled?: boolean;
152
+
153
+ /**
154
+ * Whether this member tool is only loaded once discovered through
155
+ * tool search. Default: false.
156
+ */
157
+ deferLoading?: boolean;
158
+ }
159
+ >
160
+ >;
161
+ }
162
+ >({
163
+ id: 'anthropic.computer_toolset_20260801',
164
+ inputSchema: computerToolset_20260801InputSchema,
165
+ });