@ai-sdk/anthropic 4.0.0-beta.3 → 4.0.0-beta.32

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.
@@ -1,8 +1,10 @@
1
1
  import {
2
+ FilesV4,
2
3
  InvalidArgumentError,
3
4
  LanguageModelV4,
4
5
  NoSuchModelError,
5
6
  ProviderV4,
7
+ SkillsV4,
6
8
  } from '@ai-sdk/provider';
7
9
  import {
8
10
  FetchFunction,
@@ -12,10 +14,12 @@ import {
12
14
  withoutTrailingSlash,
13
15
  withUserAgentSuffix,
14
16
  } from '@ai-sdk/provider-utils';
15
- import { VERSION } from './version';
17
+ import { AnthropicFiles } from './anthropic-files';
16
18
  import { AnthropicMessagesLanguageModel } from './anthropic-messages-language-model';
17
19
  import { AnthropicMessagesModelId } from './anthropic-messages-options';
18
20
  import { anthropicTools } from './anthropic-tools';
21
+ import { AnthropicSkills } from './skills/anthropic-skills';
22
+ import { VERSION } from './version';
19
23
 
20
24
  export interface AnthropicProvider extends ProviderV4 {
21
25
  /**
@@ -37,6 +41,13 @@ export interface AnthropicProvider extends ProviderV4 {
37
41
  */
38
42
  textEmbeddingModel(modelId: string): never;
39
43
 
44
+ files(): FilesV4;
45
+
46
+ /**
47
+ * Returns a SkillsV4 interface for uploading skills to Anthropic.
48
+ */
49
+ skills(): SkillsV4;
50
+
40
51
  /**
41
52
  * Anthropic-specific computer use tool.
42
53
  */
@@ -143,6 +154,14 @@ export function createAnthropic(
143
154
  }),
144
155
  });
145
156
 
157
+ const createSkills = () =>
158
+ new AnthropicSkills({
159
+ provider: `${providerName.replace('.messages', '')}.skills`,
160
+ baseURL,
161
+ headers: getHeaders,
162
+ fetch: options.fetch,
163
+ });
164
+
146
165
  const provider = function (modelId: AnthropicMessagesModelId) {
147
166
  if (new.target) {
148
167
  throw new Error(
@@ -166,6 +185,16 @@ export function createAnthropic(
166
185
  throw new NoSuchModelError({ modelId, modelType: 'imageModel' });
167
186
  };
168
187
 
188
+ provider.files = () =>
189
+ new AnthropicFiles({
190
+ provider: providerName,
191
+ baseURL,
192
+ headers: getHeaders,
193
+ fetch: options.fetch,
194
+ });
195
+
196
+ provider.skills = createSkills;
197
+
169
198
  provider.tools = anthropicTools;
170
199
 
171
200
  return provider;
@@ -9,7 +9,9 @@ import {
9
9
  import {
10
10
  convertBase64ToUint8Array,
11
11
  convertToBase64,
12
+ isProviderReference,
12
13
  parseProviderOptions,
14
+ resolveProviderReference,
13
15
  validateTypes,
14
16
  isNonNullable,
15
17
  ToolNameMapping,
@@ -183,7 +185,27 @@ export async function convertToAnthropicMessagesPrompt({
183
185
  }
184
186
 
185
187
  case 'file': {
186
- if (part.mediaType.startsWith('image/')) {
188
+ if (isProviderReference(part.data)) {
189
+ const fileId = resolveProviderReference({
190
+ reference: part.data,
191
+ provider: 'anthropic',
192
+ });
193
+ betas.add('files-api-2025-04-14');
194
+
195
+ if (part.mediaType.startsWith('image/')) {
196
+ anthropicContent.push({
197
+ type: 'image',
198
+ source: { type: 'file', file_id: fileId },
199
+ cache_control: cacheControl,
200
+ });
201
+ } else {
202
+ anthropicContent.push({
203
+ type: 'document',
204
+ source: { type: 'file', file_id: fileId },
205
+ cache_control: cacheControl,
206
+ });
207
+ }
208
+ } else if (part.mediaType.startsWith('image/')) {
187
209
  anthropicContent.push({
188
210
  type: 'image',
189
211
  source: isUrlData(part.data)
@@ -309,26 +331,16 @@ export async function convertToAnthropicMessagesPrompt({
309
331
  type: 'text' as const,
310
332
  text: contentPart.text,
311
333
  };
312
- case 'image-data': {
313
- return {
314
- type: 'image' as const,
315
- source: {
316
- type: 'base64' as const,
317
- media_type: contentPart.mediaType,
318
- data: contentPart.data,
319
- },
320
- };
321
- }
322
- case 'image-url': {
323
- return {
324
- type: 'image' as const,
325
- source: {
326
- type: 'url' as const,
327
- url: contentPart.url,
328
- },
329
- };
330
- }
331
334
  case 'file-url': {
335
+ if (contentPart.mediaType.startsWith('image/')) {
336
+ return {
337
+ type: 'image' as const,
338
+ source: {
339
+ type: 'url' as const,
340
+ url: contentPart.url,
341
+ },
342
+ };
343
+ }
332
344
  return {
333
345
  type: 'document' as const,
334
346
  source: {
@@ -338,6 +350,16 @@ export async function convertToAnthropicMessagesPrompt({
338
350
  };
339
351
  }
340
352
  case 'file-data': {
353
+ if (contentPart.mediaType.startsWith('image/')) {
354
+ return {
355
+ type: 'image' as const,
356
+ source: {
357
+ type: 'base64' as const,
358
+ media_type: contentPart.mediaType,
359
+ data: contentPart.data,
360
+ },
361
+ };
362
+ }
341
363
  if (contentPart.mediaType === 'application/pdf') {
342
364
  betas.add('pdfs-2024-09-25');
343
365
  return {
@@ -1,4 +1,7 @@
1
- export { AnthropicMessagesLanguageModel } from '../anthropic-messages-language-model';
1
+ export {
2
+ AnthropicMessagesLanguageModel,
3
+ getModelCapabilities,
4
+ } from '../anthropic-messages-language-model';
2
5
  export { anthropicTools } from '../anthropic-tools';
3
6
  export type { AnthropicMessagesModelId } from '../anthropic-messages-options';
4
7
  export { prepareTools } from '../anthropic-prepare-tools';
@@ -0,0 +1,44 @@
1
+ import { lazySchema, zodSchema } from '@ai-sdk/provider-utils';
2
+ import { z } from 'zod/v4';
3
+
4
+ export const anthropicSkillResponseSchema = lazySchema(() =>
5
+ zodSchema(
6
+ z.object({
7
+ id: z.string(),
8
+ display_title: z.string().nullish(),
9
+ name: z.string().nullish(),
10
+ description: z.string().nullish(),
11
+ latest_version: z.string().nullish(),
12
+ source: z.string(),
13
+ created_at: z.string(),
14
+ updated_at: z.string(),
15
+ }),
16
+ ),
17
+ );
18
+
19
+ export type AnthropicSkillResponse = ReturnType<
20
+ typeof anthropicSkillResponseSchema
21
+ >['_type'];
22
+
23
+ export const anthropicSkillVersionListResponseSchema = lazySchema(() =>
24
+ zodSchema(
25
+ z.object({
26
+ data: z.array(
27
+ z.object({
28
+ version: z.string(),
29
+ }),
30
+ ),
31
+ }),
32
+ ),
33
+ );
34
+
35
+ export const anthropicSkillVersionResponseSchema = lazySchema(() =>
36
+ zodSchema(
37
+ z.object({
38
+ type: z.string(),
39
+ skill_id: z.string(),
40
+ name: z.string().nullish(),
41
+ description: z.string().nullish(),
42
+ }),
43
+ ),
44
+ );
@@ -0,0 +1,136 @@
1
+ import { SkillsV4, SharedV4Warning } from '@ai-sdk/provider';
2
+ import {
3
+ combineHeaders,
4
+ convertBase64ToUint8Array,
5
+ createJsonResponseHandler,
6
+ FetchFunction,
7
+ getFromApi,
8
+ postFormDataToApi,
9
+ Resolvable,
10
+ resolve,
11
+ } from '@ai-sdk/provider-utils';
12
+ import { anthropicFailedResponseHandler } from '../anthropic-error';
13
+ import {
14
+ anthropicSkillResponseSchema,
15
+ anthropicSkillVersionResponseSchema,
16
+ } from './anthropic-skills-api';
17
+
18
+ interface AnthropicSkillsConfig {
19
+ provider: string;
20
+ baseURL: string;
21
+ headers: Resolvable<Record<string, string | undefined>>;
22
+ fetch?: FetchFunction;
23
+ }
24
+
25
+ export class AnthropicSkills implements SkillsV4 {
26
+ readonly specificationVersion = 'v4';
27
+
28
+ get provider(): string {
29
+ return this.config.provider;
30
+ }
31
+
32
+ constructor(private readonly config: AnthropicSkillsConfig) {}
33
+
34
+ private async getHeaders(): Promise<Record<string, string | undefined>> {
35
+ return combineHeaders(await resolve(this.config.headers), {
36
+ 'anthropic-beta': 'skills-2025-10-02',
37
+ });
38
+ }
39
+
40
+ private async fetchVersionMetadata({
41
+ skillId,
42
+ version,
43
+ headers,
44
+ }: {
45
+ skillId: string;
46
+ version: string;
47
+ headers: Record<string, string | undefined>;
48
+ }): Promise<{ name?: string; description?: string }> {
49
+ const { value: versionResponse } = await getFromApi({
50
+ url: `${this.config.baseURL}/skills/${skillId}/versions/${version}`,
51
+ headers,
52
+ failedResponseHandler: anthropicFailedResponseHandler,
53
+ successfulResponseHandler: createJsonResponseHandler(
54
+ anthropicSkillVersionResponseSchema,
55
+ ),
56
+ fetch: this.config.fetch,
57
+ });
58
+
59
+ return {
60
+ ...(versionResponse.name != null ? { name: versionResponse.name } : {}),
61
+ ...(versionResponse.description != null
62
+ ? { description: versionResponse.description }
63
+ : {}),
64
+ };
65
+ }
66
+
67
+ async uploadSkill(
68
+ params: Parameters<SkillsV4['uploadSkill']>[0],
69
+ ): Promise<Awaited<ReturnType<SkillsV4['uploadSkill']>>> {
70
+ const warnings: SharedV4Warning[] = [];
71
+
72
+ const formData = new FormData();
73
+
74
+ if (params.displayTitle != null) {
75
+ formData.append('display_title', params.displayTitle);
76
+ }
77
+
78
+ for (const file of params.files) {
79
+ const content =
80
+ typeof file.content === 'string'
81
+ ? convertBase64ToUint8Array(file.content)
82
+ : file.content;
83
+
84
+ formData.append('files[]', new Blob([content]), file.path);
85
+ }
86
+
87
+ const headers = await this.getHeaders();
88
+
89
+ const { value: response } = await postFormDataToApi({
90
+ url: `${this.config.baseURL}/skills`,
91
+ headers,
92
+ formData,
93
+ failedResponseHandler: anthropicFailedResponseHandler,
94
+ successfulResponseHandler: createJsonResponseHandler(
95
+ anthropicSkillResponseSchema,
96
+ ),
97
+ fetch: this.config.fetch,
98
+ });
99
+
100
+ const versionMetadata =
101
+ response.latest_version != null
102
+ ? await this.fetchVersionMetadata({
103
+ skillId: response.id,
104
+ version: response.latest_version,
105
+ headers,
106
+ })
107
+ : {};
108
+
109
+ const name = versionMetadata.name ?? response.name;
110
+ const description = versionMetadata.description ?? response.description;
111
+
112
+ return {
113
+ providerReference: { anthropic: response.id },
114
+ ...(response.display_title != null
115
+ ? { displayTitle: response.display_title }
116
+ : {}),
117
+ ...(name != null ? { name } : {}),
118
+ ...(description != null ? { description } : {}),
119
+ ...(response.latest_version != null
120
+ ? { latestVersion: response.latest_version }
121
+ : {}),
122
+ providerMetadata: {
123
+ anthropic: {
124
+ ...(response.source != null ? { source: response.source } : {}),
125
+ ...(response.created_at != null
126
+ ? { createdAt: response.created_at }
127
+ : {}),
128
+ ...(response.updated_at != null
129
+ ? { updatedAt: response.updated_at }
130
+ : {}),
131
+ },
132
+ },
133
+ warnings,
134
+ };
135
+ }
136
+ }