@ai-sdk/anthropic 4.0.92 → 4.0.93

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.
@@ -0,0 +1,406 @@
1
+ import type {
2
+ ModelCapabilities,
3
+ ModelCapability,
4
+ ModelEntry,
5
+ ProviderOptionDefinition,
6
+ ProviderOptionDefinitions,
7
+ } from '@ai-sdk/provider';
8
+ import type { AnthropicLanguageModelOptions } from './anthropic-language-model-options';
9
+
10
+ type AnthropicLanguageProviderOption = keyof AnthropicLanguageModelOptions;
11
+
12
+ /**
13
+ * Options accepted under `providerOptions.anthropic`. The `satisfies` check
14
+ * keeps this list in sync with the option schema.
15
+ */
16
+ export const anthropicProviderOptions = {
17
+ language: {
18
+ sendReasoning: { description: 'Whether to send reasoning to the model.' },
19
+ structuredOutputMode: {
20
+ description: 'How structured outputs are generated.',
21
+ },
22
+ thinking: { description: 'Extended thinking configuration.' },
23
+ disableParallelToolUse: {
24
+ description: 'Use at most one tool per response.',
25
+ },
26
+ cacheControl: { description: 'Prompt cache control settings.' },
27
+ metadata: { description: 'Request metadata, such as a user ID.' },
28
+ mcpServers: { description: 'MCP servers to use in the request.' },
29
+ container: { description: 'Container and Agent Skills configuration.' },
30
+ toolStreaming: {
31
+ description: 'Fine-grained streaming of tool inputs and outputs.',
32
+ },
33
+ effort: {
34
+ description: 'Effort spent on thinking, text, and tool calls.',
35
+ },
36
+ taskBudget: { description: 'Advisory token budget for an agentic task.' },
37
+ speed: { description: 'Fast mode for faster output token speeds.' },
38
+ serviceTier: { description: 'Service tier for the request.' },
39
+ inferenceGeo: { description: 'Where model inference runs.' },
40
+ fallbacks: { description: 'Server-side fallback models.' },
41
+ anthropicBeta: { description: 'Additional beta features to enable.' },
42
+ safeguards: { description: 'Server-side safeguards to run.' },
43
+ compaction: { description: 'On-demand conversation summary.' },
44
+ contextManagement: { description: 'Server-side context management.' },
45
+ } satisfies Record<AnthropicLanguageProviderOption, ProviderOptionDefinition>,
46
+ } as const satisfies ProviderOptionDefinitions;
47
+
48
+ type AnthropicLanguageCapabilities = NonNullable<
49
+ ModelCapabilities['language']
50
+ > & {
51
+ tools: NonNullable<ModelCapabilities['language']>['tools'] & {
52
+ forcedChoice: boolean;
53
+ computerUse: ModelCapability;
54
+ webSearch: ModelCapability;
55
+ toolSearch: ModelCapability;
56
+ };
57
+ reasoning: NonNullable<ModelCapabilities['language']>['reasoning'] & {
58
+ adaptive: boolean;
59
+ budget: boolean;
60
+ canDisable: boolean;
61
+ canDisableAboveHighEffort: boolean;
62
+ supportsXhighEffort: boolean;
63
+ betweenTools: boolean;
64
+ };
65
+ sampling: NonNullable<ModelCapabilities['language']>['sampling'] & {
66
+ topK: ModelCapability;
67
+ };
68
+ structuredOutput: {
69
+ native: boolean;
70
+ };
71
+ compaction: ModelCapability;
72
+ };
73
+
74
+ type AnthropicLanguageRequestConfig = {
75
+ maxOutputTokens: number;
76
+ knownModel: boolean;
77
+ };
78
+
79
+ export type AnthropicLanguageModelEntry = ModelEntry<{
80
+ language: AnthropicLanguageRequestConfig;
81
+ }> & {
82
+ capabilities: { language: AnthropicLanguageCapabilities };
83
+ providerOptions: {
84
+ language: Record<AnthropicLanguageProviderOption, ModelCapability>;
85
+ };
86
+ requestConfig: { language: AnthropicLanguageRequestConfig };
87
+ };
88
+
89
+ type RuntimeDefinition = {
90
+ maxOutputTokens: number;
91
+ nativeStructuredOutput: boolean;
92
+ adaptiveThinking: boolean;
93
+ samplingParameters: boolean;
94
+ xhighEffort: boolean;
95
+ thinkingCanBeDisabledAboveHighEffort: boolean;
96
+ thinkingCanBeDisabled: boolean;
97
+ budgetThinking: boolean;
98
+ forcedToolUse: boolean;
99
+ betweenToolsThinking: boolean;
100
+ knownModel: boolean;
101
+ };
102
+
103
+ type DocumentedCapabilities = {
104
+ toolSearch: boolean;
105
+ compaction: boolean;
106
+ /** `effort` was introduced with claude-opus-4-5. */
107
+ effort: boolean;
108
+ };
109
+
110
+ const legacyClaude = defineRuntime({});
111
+ const currentClaude = defineRuntime({
112
+ maxOutputTokens: 128000,
113
+ nativeStructuredOutput: true,
114
+ adaptiveThinking: true,
115
+ });
116
+ const currentClaudeWithoutSampling = defineRuntime({
117
+ ...currentClaude,
118
+ samplingParameters: false,
119
+ xhighEffort: true,
120
+ });
121
+
122
+ function defineRuntime(
123
+ overrides: Partial<RuntimeDefinition>,
124
+ ): RuntimeDefinition {
125
+ return {
126
+ maxOutputTokens: 4096,
127
+ nativeStructuredOutput: false,
128
+ adaptiveThinking: false,
129
+ samplingParameters: true,
130
+ xhighEffort: false,
131
+ thinkingCanBeDisabledAboveHighEffort: true,
132
+ thinkingCanBeDisabled: true,
133
+ budgetThinking: true,
134
+ forcedToolUse: true,
135
+ betweenToolsThinking: false,
136
+ knownModel: true,
137
+ ...overrides,
138
+ };
139
+ }
140
+
141
+ const runtimeRules: readonly {
142
+ matches: (modelId: string) => boolean;
143
+ definition: RuntimeDefinition;
144
+ }[] = [
145
+ {
146
+ matches: modelId => modelId.includes('claude-sonnet-5-5'),
147
+ definition: defineRuntime({
148
+ ...currentClaudeWithoutSampling,
149
+ thinkingCanBeDisabledAboveHighEffort: false,
150
+ thinkingCanBeDisabled: false,
151
+ budgetThinking: false,
152
+ forcedToolUse: false,
153
+ betweenToolsThinking: true,
154
+ }),
155
+ },
156
+ {
157
+ matches: modelId => modelId.includes('claude-opus-5-5'),
158
+ definition: defineRuntime({
159
+ ...currentClaudeWithoutSampling,
160
+ thinkingCanBeDisabledAboveHighEffort: false,
161
+ thinkingCanBeDisabled: false,
162
+ budgetThinking: false,
163
+ forcedToolUse: false,
164
+ }),
165
+ },
166
+ {
167
+ matches: modelId => modelId.includes('claude-haiku-5-5'),
168
+ definition: defineRuntime({
169
+ ...currentClaudeWithoutSampling,
170
+ thinkingCanBeDisabledAboveHighEffort: false,
171
+ budgetThinking: false,
172
+ }),
173
+ },
174
+ {
175
+ matches: modelId => modelId.includes('claude-opus-5'),
176
+ definition: defineRuntime({
177
+ ...currentClaudeWithoutSampling,
178
+ thinkingCanBeDisabledAboveHighEffort: false,
179
+ }),
180
+ },
181
+ {
182
+ matches: modelId => modelId.includes('claude-fable-5-1'),
183
+ definition: defineRuntime({
184
+ ...currentClaudeWithoutSampling,
185
+ thinkingCanBeDisabled: false,
186
+ budgetThinking: false,
187
+ forcedToolUse: false,
188
+ }),
189
+ },
190
+ {
191
+ matches: modelId => modelId.includes('claude-fable-5'),
192
+ definition: defineRuntime({
193
+ ...currentClaudeWithoutSampling,
194
+ thinkingCanBeDisabled: false,
195
+ budgetThinking: false,
196
+ }),
197
+ },
198
+ {
199
+ matches: modelId =>
200
+ modelId.includes('claude-opus-4-8') ||
201
+ modelId.includes('claude-opus-4-7') ||
202
+ modelId.includes('claude-sonnet-5'),
203
+ definition: currentClaudeWithoutSampling,
204
+ },
205
+ {
206
+ matches: modelId =>
207
+ modelId.includes('claude-sonnet-4-6') ||
208
+ modelId.includes('claude-opus-4-6'),
209
+ definition: currentClaude,
210
+ },
211
+ {
212
+ matches: modelId =>
213
+ modelId.includes('claude-sonnet-4-5') ||
214
+ modelId.includes('claude-opus-4-5') ||
215
+ modelId.includes('claude-haiku-4-5'),
216
+ definition: defineRuntime({
217
+ maxOutputTokens: 64000,
218
+ nativeStructuredOutput: true,
219
+ }),
220
+ },
221
+ {
222
+ matches: modelId => modelId.includes('claude-opus-4-1'),
223
+ definition: defineRuntime({
224
+ maxOutputTokens: 32000,
225
+ nativeStructuredOutput: true,
226
+ }),
227
+ },
228
+ {
229
+ matches: modelId => /claude-sonnet-4(?:-|@)/.test(modelId),
230
+ definition: defineRuntime({ maxOutputTokens: 64000 }),
231
+ },
232
+ {
233
+ matches: modelId => /claude-opus-4(?:-|@)/.test(modelId),
234
+ definition: defineRuntime({ maxOutputTokens: 32000 }),
235
+ },
236
+ {
237
+ matches: modelId => modelId.includes('claude-3-haiku'),
238
+ definition: legacyClaude,
239
+ },
240
+ {
241
+ matches: modelId =>
242
+ /claude-(?:instant(?:-|$)|v?2(?=$|[-.:])|3(?=$|[-.]))/.test(modelId),
243
+ definition: defineRuntime({ knownModel: false }),
244
+ },
245
+ ];
246
+
247
+ const documentedModels: Readonly<Record<string, DocumentedCapabilities>> = {
248
+ 'claude-opus-5-5': { toolSearch: true, compaction: true, effort: true },
249
+ 'claude-opus-5': { toolSearch: true, compaction: true, effort: true },
250
+ 'claude-sonnet-5-5': { toolSearch: true, compaction: true, effort: true },
251
+ 'claude-sonnet-5': { toolSearch: true, compaction: true, effort: true },
252
+ 'claude-haiku-5-5': { toolSearch: true, compaction: true, effort: true },
253
+ 'claude-fable-5-1': { toolSearch: true, compaction: true, effort: true },
254
+ 'claude-fable-5': { toolSearch: true, compaction: true, effort: true },
255
+ 'claude-opus-4-8': { toolSearch: true, compaction: true, effort: true },
256
+ 'claude-opus-4-7': { toolSearch: true, compaction: true, effort: true },
257
+ 'claude-opus-4-6': { toolSearch: true, compaction: true, effort: true },
258
+ 'claude-sonnet-4-6': { toolSearch: true, compaction: true, effort: true },
259
+ 'claude-opus-4-5': { toolSearch: true, compaction: false, effort: true },
260
+ 'claude-haiku-4-5': { toolSearch: true, compaction: false, effort: false },
261
+ 'claude-sonnet-4-5': { toolSearch: true, compaction: false, effort: false },
262
+ 'claude-opus-4-1': { toolSearch: false, compaction: false, effort: false },
263
+ 'claude-opus-4-0': { toolSearch: false, compaction: false, effort: false },
264
+ 'claude-sonnet-4-0': { toolSearch: false, compaction: false, effort: false },
265
+ };
266
+
267
+ export const anthropicModelCatalog: Readonly<
268
+ Record<string, AnthropicLanguageModelEntry>
269
+ > = Object.fromEntries(
270
+ Object.entries(documentedModels).map(([modelId, capabilities]) => [
271
+ modelId,
272
+ createAnthropicLanguageModelEntry(modelId, capabilities),
273
+ ]),
274
+ );
275
+
276
+ export function getAnthropicLanguageModelEntry(
277
+ modelId: string,
278
+ ): AnthropicLanguageModelEntry {
279
+ return Object.prototype.hasOwnProperty.call(anthropicModelCatalog, modelId)
280
+ ? anthropicModelCatalog[modelId]
281
+ : createAnthropicLanguageModelEntry(modelId);
282
+ }
283
+
284
+ function createAnthropicLanguageModelEntry(
285
+ modelId: string,
286
+ documented?: DocumentedCapabilities,
287
+ ): AnthropicLanguageModelEntry {
288
+ const runtime = resolveRuntimeDefinition(modelId);
289
+ const declared = documented != null;
290
+ const samplingSupport = runtime.samplingParameters
291
+ ? true
292
+ : { condition: 'Only supported when thinking is disabled.' };
293
+ const reasoningSupport = runtime.adaptiveThinking || runtime.budgetThinking;
294
+
295
+ return {
296
+ capabilities: {
297
+ language: {
298
+ inputs: {
299
+ image: declared ? true : 'unknown',
300
+ audio: declared ? false : 'unknown',
301
+ },
302
+ objectGeneration: declared ? true : 'unknown',
303
+ tools: {
304
+ usage: declared ? true : 'unknown',
305
+ streaming: declared ? true : 'unknown',
306
+ forcedChoice: runtime.forcedToolUse,
307
+ computerUse: declared ? true : 'unknown',
308
+ webSearch: declared ? true : 'unknown',
309
+ toolSearch: documented?.toolSearch ?? 'unknown',
310
+ },
311
+ reasoning: {
312
+ support: reasoningSupport,
313
+ efforts: runtime.xhighEffort
314
+ ? ['low', 'medium', 'high', 'xhigh', 'max']
315
+ : undefined,
316
+ adaptive: runtime.adaptiveThinking,
317
+ budget: runtime.budgetThinking,
318
+ canDisable: runtime.thinkingCanBeDisabled,
319
+ canDisableAboveHighEffort:
320
+ runtime.thinkingCanBeDisabledAboveHighEffort,
321
+ supportsXhighEffort: runtime.xhighEffort,
322
+ betweenTools: runtime.betweenToolsThinking,
323
+ },
324
+ sampling: {
325
+ temperature: samplingSupport,
326
+ topP: samplingSupport,
327
+ topK: samplingSupport,
328
+ logprobs: false,
329
+ },
330
+ structuredOutput: { native: runtime.nativeStructuredOutput },
331
+ compaction: documented?.compaction ?? 'unknown',
332
+ },
333
+ },
334
+ providerOptions: {
335
+ language: declareProviderOptions(
336
+ anthropicProviderOptions.language,
337
+ declared ? true : 'unknown',
338
+ {
339
+ thinking: reasoningSupport,
340
+ effort: documented?.effort ?? 'unknown',
341
+ // Fast mode is documented for claude-opus-4-6 only.
342
+ speed: declared ? modelId === 'claude-opus-4-6' : 'unknown',
343
+ // Task budgets are documented for claude-opus-4-7; other models are
344
+ // not documented either way.
345
+ taskBudget: modelId === 'claude-opus-4-7' ? true : 'unknown',
346
+ },
347
+ ),
348
+ },
349
+ requestConfig: {
350
+ language: {
351
+ maxOutputTokens: runtime.maxOutputTokens,
352
+ knownModel: runtime.knownModel,
353
+ },
354
+ },
355
+ };
356
+ }
357
+
358
+ /** Applies one default support value to every option, except the listed ones. */
359
+ function declareProviderOptions<Option extends string>(
360
+ definitions: Readonly<Record<Option, ProviderOptionDefinition>>,
361
+ support: ModelCapability,
362
+ exceptions: Partial<Record<Option, ModelCapability>>,
363
+ ): Record<Option, ModelCapability> {
364
+ return Object.fromEntries(
365
+ (Object.keys(definitions) as Option[]).map(option => [
366
+ option,
367
+ exceptions[option] ?? support,
368
+ ]),
369
+ ) as Record<Option, ModelCapability>;
370
+ }
371
+
372
+ function resolveRuntimeDefinition(modelId: string): RuntimeDefinition {
373
+ const rule = runtimeRules.find(rule => rule.matches(modelId));
374
+ if (rule != null) return rule.definition;
375
+
376
+ return modelId.includes('claude-')
377
+ ? defineRuntime({
378
+ ...currentClaudeWithoutSampling,
379
+ thinkingCanBeDisabledAboveHighEffort: false,
380
+ knownModel: false,
381
+ })
382
+ : defineRuntime({ knownModel: false });
383
+ }
384
+
385
+ /** Compatibility projection for the provider's existing request preparation. */
386
+ export function getAnthropicModelCapabilities(modelId: string) {
387
+ const {
388
+ capabilities: { language },
389
+ requestConfig: { language: requestConfig },
390
+ } = getAnthropicLanguageModelEntry(modelId);
391
+
392
+ return {
393
+ maxOutputTokens: requestConfig.maxOutputTokens,
394
+ supportsStructuredOutput: language.structuredOutput.native,
395
+ supportsAdaptiveThinking: language.reasoning.adaptive,
396
+ rejectsSamplingParameters: language.sampling.temperature !== true,
397
+ supportsXhighEffort: language.reasoning.supportsXhighEffort,
398
+ rejectsThinkingDisabledAboveHighEffort:
399
+ !language.reasoning.canDisableAboveHighEffort,
400
+ rejectsThinkingDisabled: !language.reasoning.canDisable,
401
+ rejectsBudgetThinking: !language.reasoning.budget,
402
+ rejectsForcedToolUse: !language.tools.forcedChoice,
403
+ supportsBetweenToolsThinking: language.reasoning.betweenTools,
404
+ isKnownModel: requestConfig.knownModel,
405
+ };
406
+ }