@ai-sdk/anthropic 4.0.0-beta.2 → 4.0.0-beta.21

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.
@@ -112,6 +112,23 @@ export const anthropicLanguageModelOptions = z.object({
112
112
  })
113
113
  .optional(),
114
114
 
115
+ /**
116
+ * Metadata to include with the request.
117
+ *
118
+ * See https://platform.claude.com/docs/en/api/messages/create for details.
119
+ */
120
+ metadata: z
121
+ .object({
122
+ /**
123
+ * An external identifier for the user associated with the request.
124
+ *
125
+ * Should be a UUID, hash value, or other opaque identifier.
126
+ * Must not contain PII (name, email, phone number, etc.).
127
+ */
128
+ userId: z.string().optional(),
129
+ })
130
+ .optional(),
131
+
115
132
  /**
116
133
  * MCP servers to be utilized in this request.
117
134
  */
@@ -142,11 +159,18 @@ export const anthropicLanguageModelOptions = z.object({
142
159
  id: z.string().optional(),
143
160
  skills: z
144
161
  .array(
145
- z.object({
146
- type: z.union([z.literal('anthropic'), z.literal('custom')]),
147
- skillId: z.string(),
148
- version: z.string().optional(),
149
- }),
162
+ z.discriminatedUnion('type', [
163
+ z.object({
164
+ type: z.literal('anthropic'),
165
+ skillId: z.string(),
166
+ version: z.string().optional(),
167
+ }),
168
+ z.object({
169
+ type: z.literal('custom'),
170
+ providerReference: z.record(z.string(), z.string()),
171
+ version: z.string().optional(),
172
+ }),
173
+ ]),
150
174
  )
151
175
  .optional(),
152
176
  })
@@ -1,6 +1,6 @@
1
1
  import {
2
- LanguageModelV3CallOptions,
3
- SharedV3Warning,
2
+ LanguageModelV4CallOptions,
3
+ SharedV4Warning,
4
4
  UnsupportedFunctionalityError,
5
5
  } from '@ai-sdk/provider';
6
6
  import { AnthropicTool, AnthropicToolChoice } from './anthropic-messages-api';
@@ -26,26 +26,32 @@ export async function prepareTools({
26
26
  disableParallelToolUse,
27
27
  cacheControlValidator,
28
28
  supportsStructuredOutput,
29
+ supportsStrictTools,
29
30
  }: {
30
- tools: LanguageModelV3CallOptions['tools'];
31
- toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined;
31
+ tools: LanguageModelV4CallOptions['tools'];
32
+ toolChoice: LanguageModelV4CallOptions['toolChoice'] | undefined;
32
33
  disableParallelToolUse?: boolean;
33
34
  cacheControlValidator?: CacheControlValidator;
34
35
 
35
36
  /**
36
- * Whether the model supports structured output.
37
+ * Whether the model supports native structured output response format.
37
38
  */
38
39
  supportsStructuredOutput: boolean;
40
+
41
+ /**
42
+ * Whether the model supports strict mode on tool definitions.
43
+ */
44
+ supportsStrictTools: boolean;
39
45
  }): Promise<{
40
46
  tools: Array<AnthropicTool> | undefined;
41
47
  toolChoice: AnthropicToolChoice | undefined;
42
- toolWarnings: SharedV3Warning[];
48
+ toolWarnings: SharedV4Warning[];
43
49
  betas: Set<string>;
44
50
  }> {
45
51
  // when the tools array is empty, change it to undefined to prevent errors:
46
52
  tools = tools?.length ? tools : undefined;
47
53
 
48
- const toolWarnings: SharedV3Warning[] = [];
54
+ const toolWarnings: SharedV4Warning[] = [];
49
55
  const betas = new Set<string>();
50
56
  const validator = cacheControlValidator || new CacheControlValidator();
51
57
 
@@ -72,13 +78,21 @@ export async function prepareTools({
72
78
  const deferLoading = anthropicOptions?.deferLoading;
73
79
  const allowedCallers = anthropicOptions?.allowedCallers;
74
80
 
81
+ if (!supportsStrictTools && tool.strict != null) {
82
+ toolWarnings.push({
83
+ type: 'unsupported',
84
+ feature: 'strict',
85
+ details: `Tool '${tool.name}' has strict: ${tool.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`,
86
+ });
87
+ }
88
+
75
89
  anthropicTools.push({
76
90
  name: tool.name,
77
91
  description: tool.description,
78
92
  input_schema: tool.inputSchema,
79
93
  cache_control: cacheControl,
80
94
  ...(eagerInputStreaming ? { eager_input_streaming: true } : {}),
81
- ...(supportsStructuredOutput === true && tool.strict != null
95
+ ...(supportsStrictTools === true && tool.strict != null
82
96
  ? { strict: tool.strict }
83
97
  : {}),
84
98
  ...(deferLoading != null ? { defer_loading: deferLoading } : {}),
@@ -308,7 +322,6 @@ export async function prepareTools({
308
322
  }
309
323
 
310
324
  case 'anthropic.tool_search_regex_20251119': {
311
- betas.add('advanced-tool-use-2025-11-20');
312
325
  anthropicTools.push({
313
326
  type: 'tool_search_tool_regex_20251119',
314
327
  name: 'tool_search_tool_regex',
@@ -317,7 +330,6 @@ export async function prepareTools({
317
330
  }
318
331
 
319
332
  case 'anthropic.tool_search_bm25_20251119': {
320
- betas.add('advanced-tool-use-2025-11-20');
321
333
  anthropicTools.push({
322
334
  type: 'tool_search_tool_bm25_20251119',
323
335
  name: 'tool_search_tool_bm25',
@@ -1,8 +1,10 @@
1
1
  import {
2
+ FilesV4,
2
3
  InvalidArgumentError,
3
- LanguageModelV3,
4
+ LanguageModelV4,
4
5
  NoSuchModelError,
5
- ProviderV3,
6
+ ProviderV4,
7
+ SkillsV4,
6
8
  } from '@ai-sdk/provider';
7
9
  import {
8
10
  FetchFunction,
@@ -12,31 +14,40 @@ 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
- export interface AnthropicProvider extends ProviderV3 {
24
+ export interface AnthropicProvider extends ProviderV4 {
21
25
  /**
22
26
  * Creates a model for text generation.
23
27
  */
24
- (modelId: AnthropicMessagesModelId): LanguageModelV3;
28
+ (modelId: AnthropicMessagesModelId): LanguageModelV4;
25
29
 
26
30
  /**
27
31
  * Creates a model for text generation.
28
32
  */
29
- languageModel(modelId: AnthropicMessagesModelId): LanguageModelV3;
33
+ languageModel(modelId: AnthropicMessagesModelId): LanguageModelV4;
30
34
 
31
- chat(modelId: AnthropicMessagesModelId): LanguageModelV3;
35
+ chat(modelId: AnthropicMessagesModelId): LanguageModelV4;
32
36
 
33
- messages(modelId: AnthropicMessagesModelId): LanguageModelV3;
37
+ messages(modelId: AnthropicMessagesModelId): LanguageModelV4;
34
38
 
35
39
  /**
36
40
  * @deprecated Use `embeddingModel` instead.
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(
@@ -153,7 +172,7 @@ export function createAnthropic(
153
172
  return createChatModel(modelId);
154
173
  };
155
174
 
156
- provider.specificationVersion = 'v3' as const;
175
+ provider.specificationVersion = 'v4' as const;
157
176
  provider.languageModel = createChatModel;
158
177
  provider.chat = createChatModel;
159
178
  provider.messages = createChatModel;
@@ -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;
@@ -1,4 +1,4 @@
1
- import { JSONObject, LanguageModelV3Usage } from '@ai-sdk/provider';
1
+ import { JSONObject, LanguageModelV4Usage } from '@ai-sdk/provider';
2
2
 
3
3
  /**
4
4
  * Represents a single iteration in the usage breakdown.
@@ -31,7 +31,7 @@ export function convertAnthropicMessagesUsage({
31
31
  }: {
32
32
  usage: AnthropicMessagesUsage;
33
33
  rawUsage?: JSONObject;
34
- }): LanguageModelV3Usage {
34
+ }): LanguageModelV4Usage {
35
35
  const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
36
36
  const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
37
37
 
@@ -1,15 +1,17 @@
1
1
  import {
2
- SharedV3Warning,
3
- LanguageModelV3DataContent,
4
- LanguageModelV3Message,
5
- LanguageModelV3Prompt,
6
- SharedV3ProviderMetadata,
2
+ SharedV4Warning,
3
+ LanguageModelV4DataContent,
4
+ LanguageModelV4Message,
5
+ LanguageModelV4Prompt,
6
+ SharedV4ProviderMetadata,
7
7
  UnsupportedFunctionalityError,
8
8
  } from '@ai-sdk/provider';
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,
@@ -31,7 +33,7 @@ import { toolSearchRegex_20251119OutputSchema as toolSearchOutputSchema } from '
31
33
  import { webFetch_20250910OutputSchema } from './tool/web-fetch-20250910';
32
34
  import { webSearch_20250305OutputSchema } from './tool/web-search_20250305';
33
35
 
34
- function convertToString(data: LanguageModelV3DataContent): string {
36
+ function convertToString(data: LanguageModelV4DataContent): string {
35
37
  if (typeof data === 'string') {
36
38
  return new TextDecoder().decode(convertBase64ToUint8Array(data));
37
39
  }
@@ -55,16 +57,16 @@ function convertToString(data: LanguageModelV3DataContent): string {
55
57
  * Checks if data is a URL (either a URL object or a URL string).
56
58
  */
57
59
  function isUrlData(
58
- data: LanguageModelV3DataContent,
60
+ data: LanguageModelV4DataContent,
59
61
  ): data is URL | (string & { __brand: 'url-string' }) {
60
62
  return data instanceof URL || isUrlString(data);
61
63
  }
62
64
 
63
- function isUrlString(data: LanguageModelV3DataContent): boolean {
65
+ function isUrlString(data: LanguageModelV4DataContent): boolean {
64
66
  return typeof data === 'string' && /^https?:\/\//i.test(data);
65
67
  }
66
68
 
67
- function getUrlString(data: LanguageModelV3DataContent): string {
69
+ function getUrlString(data: LanguageModelV4DataContent): string {
68
70
  return data instanceof URL ? data.toString() : (data as string);
69
71
  }
70
72
 
@@ -75,9 +77,9 @@ export async function convertToAnthropicMessagesPrompt({
75
77
  cacheControlValidator,
76
78
  toolNameMapping,
77
79
  }: {
78
- prompt: LanguageModelV3Prompt;
80
+ prompt: LanguageModelV4Prompt;
79
81
  sendReasoning: boolean;
80
- warnings: SharedV3Warning[];
82
+ warnings: SharedV4Warning[];
81
83
  cacheControlValidator?: CacheControlValidator;
82
84
  toolNameMapping: ToolNameMapping;
83
85
  }): Promise<{
@@ -92,7 +94,7 @@ export async function convertToAnthropicMessagesPrompt({
92
94
  const messages: AnthropicMessagesPrompt['messages'] = [];
93
95
 
94
96
  async function shouldEnableCitations(
95
- providerMetadata: SharedV3ProviderMetadata | undefined,
97
+ providerMetadata: SharedV4ProviderMetadata | undefined,
96
98
  ): Promise<boolean> {
97
99
  const anthropicOptions = await parseProviderOptions({
98
100
  provider: 'anthropic',
@@ -104,7 +106,7 @@ export async function convertToAnthropicMessagesPrompt({
104
106
  }
105
107
 
106
108
  async function getDocumentMetadata(
107
- providerMetadata: SharedV3ProviderMetadata | undefined,
109
+ providerMetadata: SharedV4ProviderMetadata | undefined,
108
110
  ): Promise<{ title?: string; context?: string }> {
109
111
  const anthropicOptions = await parseProviderOptions({
110
112
  provider: 'anthropic',
@@ -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)
@@ -1051,19 +1073,19 @@ export async function convertToAnthropicMessagesPrompt({
1051
1073
 
1052
1074
  type SystemBlock = {
1053
1075
  type: 'system';
1054
- messages: Array<LanguageModelV3Message & { role: 'system' }>;
1076
+ messages: Array<LanguageModelV4Message & { role: 'system' }>;
1055
1077
  };
1056
1078
  type AssistantBlock = {
1057
1079
  type: 'assistant';
1058
- messages: Array<LanguageModelV3Message & { role: 'assistant' }>;
1080
+ messages: Array<LanguageModelV4Message & { role: 'assistant' }>;
1059
1081
  };
1060
1082
  type UserBlock = {
1061
1083
  type: 'user';
1062
- messages: Array<LanguageModelV3Message & { role: 'user' | 'tool' }>;
1084
+ messages: Array<LanguageModelV4Message & { role: 'user' | 'tool' }>;
1063
1085
  };
1064
1086
 
1065
1087
  function groupIntoBlocks(
1066
- prompt: LanguageModelV3Prompt,
1088
+ prompt: LanguageModelV4Prompt,
1067
1089
  ): Array<SystemBlock | AssistantBlock | UserBlock> {
1068
1090
  const blocks: Array<SystemBlock | AssistantBlock | UserBlock> = [];
1069
1091
  let currentBlock: SystemBlock | AssistantBlock | UserBlock | undefined =
@@ -1,4 +1,4 @@
1
- import { SharedV3Warning, SharedV3ProviderMetadata } from '@ai-sdk/provider';
1
+ import { SharedV4Warning, SharedV4ProviderMetadata } from '@ai-sdk/provider';
2
2
  import { AnthropicCacheControl } from './anthropic-messages-api';
3
3
 
4
4
  // Anthropic allows a maximum of 4 cache breakpoints per request
@@ -7,7 +7,7 @@ const MAX_CACHE_BREAKPOINTS = 4;
7
7
  // Helper function to extract cache_control from provider metadata
8
8
  // Allows both cacheControl and cache_control for flexibility
9
9
  function getCacheControl(
10
- providerMetadata: SharedV3ProviderMetadata | undefined,
10
+ providerMetadata: SharedV4ProviderMetadata | undefined,
11
11
  ): AnthropicCacheControl | undefined {
12
12
  const anthropic = providerMetadata?.anthropic;
13
13
 
@@ -21,10 +21,10 @@ function getCacheControl(
21
21
 
22
22
  export class CacheControlValidator {
23
23
  private breakpointCount = 0;
24
- private warnings: SharedV3Warning[] = [];
24
+ private warnings: SharedV4Warning[] = [];
25
25
 
26
26
  getCacheControl(
27
- providerMetadata: SharedV3ProviderMetadata | undefined,
27
+ providerMetadata: SharedV4ProviderMetadata | undefined,
28
28
  context: { type: string; canCache: boolean },
29
29
  ): AnthropicCacheControl | undefined {
30
30
  const cacheControlValue = getCacheControl(providerMetadata);
@@ -57,7 +57,7 @@ export class CacheControlValidator {
57
57
  return cacheControlValue;
58
58
  }
59
59
 
60
- getWarnings(): SharedV3Warning[] {
60
+ getWarnings(): SharedV4Warning[] {
61
61
  return this.warnings;
62
62
  }
63
63
  }
@@ -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';
@@ -1,4 +1,4 @@
1
- import { LanguageModelV3FinishReason } from '@ai-sdk/provider';
1
+ import { LanguageModelV4FinishReason } from '@ai-sdk/provider';
2
2
 
3
3
  /**
4
4
  * @see https://docs.anthropic.com/en/api/messages#response-stop-reason
@@ -9,7 +9,7 @@ export function mapAnthropicStopReason({
9
9
  }: {
10
10
  finishReason: string | null | undefined;
11
11
  isJsonResponseFromTool?: boolean;
12
- }): LanguageModelV3FinishReason['unified'] {
12
+ }): LanguageModelV4FinishReason['unified'] {
13
13
  switch (finishReason) {
14
14
  case 'pause_turn':
15
15
  case 'end_turn':
@@ -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 upload(
68
+ params: Parameters<SkillsV4['upload']>[0],
69
+ ): Promise<Awaited<ReturnType<SkillsV4['upload']>>> {
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
+ }