@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.
- package/CHANGELOG.md +148 -4
- package/README.md +2 -0
- package/dist/index.d.mts +50 -38
- package/dist/index.d.ts +50 -38
- package/dist/index.js +1403 -1075
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1440 -1091
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +64 -43
- package/dist/internal/index.d.ts +64 -43
- package/dist/internal/index.js +143 -25
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +146 -23
- package/dist/internal/index.mjs.map +1 -1
- package/docs/05-anthropic.mdx +53 -6
- package/package.json +3 -5
- package/src/anthropic-files.ts +106 -0
- package/src/anthropic-messages-api.ts +4 -0
- package/src/anthropic-messages-language-model.ts +147 -38
- package/src/anthropic-messages-options.ts +29 -5
- package/src/anthropic-prepare-tools.ts +22 -10
- package/src/anthropic-provider.ts +38 -9
- package/src/convert-anthropic-messages-usage.ts +2 -2
- package/src/convert-to-anthropic-messages-prompt.ts +40 -18
- package/src/get-cache-control.ts +5 -5
- package/src/internal/index.ts +4 -1
- package/src/map-anthropic-stop-reason.ts +2 -2
- package/src/skills/anthropic-skills-api.ts +44 -0
- package/src/skills/anthropic-skills.ts +136 -0
|
@@ -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.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
3
|
-
|
|
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:
|
|
31
|
-
toolChoice:
|
|
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:
|
|
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:
|
|
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
|
-
...(
|
|
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
|
-
|
|
4
|
+
LanguageModelV4,
|
|
4
5
|
NoSuchModelError,
|
|
5
|
-
|
|
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 {
|
|
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
|
|
24
|
+
export interface AnthropicProvider extends ProviderV4 {
|
|
21
25
|
/**
|
|
22
26
|
* Creates a model for text generation.
|
|
23
27
|
*/
|
|
24
|
-
(modelId: AnthropicMessagesModelId):
|
|
28
|
+
(modelId: AnthropicMessagesModelId): LanguageModelV4;
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* Creates a model for text generation.
|
|
28
32
|
*/
|
|
29
|
-
languageModel(modelId: AnthropicMessagesModelId):
|
|
33
|
+
languageModel(modelId: AnthropicMessagesModelId): LanguageModelV4;
|
|
30
34
|
|
|
31
|
-
chat(modelId: AnthropicMessagesModelId):
|
|
35
|
+
chat(modelId: AnthropicMessagesModelId): LanguageModelV4;
|
|
32
36
|
|
|
33
|
-
messages(modelId: AnthropicMessagesModelId):
|
|
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 = '
|
|
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,
|
|
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
|
-
}):
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
65
|
+
function isUrlString(data: LanguageModelV4DataContent): boolean {
|
|
64
66
|
return typeof data === 'string' && /^https?:\/\//i.test(data);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
function getUrlString(data:
|
|
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:
|
|
80
|
+
prompt: LanguageModelV4Prompt;
|
|
79
81
|
sendReasoning: boolean;
|
|
80
|
-
warnings:
|
|
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:
|
|
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:
|
|
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.
|
|
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<
|
|
1076
|
+
messages: Array<LanguageModelV4Message & { role: 'system' }>;
|
|
1055
1077
|
};
|
|
1056
1078
|
type AssistantBlock = {
|
|
1057
1079
|
type: 'assistant';
|
|
1058
|
-
messages: Array<
|
|
1080
|
+
messages: Array<LanguageModelV4Message & { role: 'assistant' }>;
|
|
1059
1081
|
};
|
|
1060
1082
|
type UserBlock = {
|
|
1061
1083
|
type: 'user';
|
|
1062
|
-
messages: Array<
|
|
1084
|
+
messages: Array<LanguageModelV4Message & { role: 'user' | 'tool' }>;
|
|
1063
1085
|
};
|
|
1064
1086
|
|
|
1065
1087
|
function groupIntoBlocks(
|
|
1066
|
-
prompt:
|
|
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 =
|
package/src/get-cache-control.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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:
|
|
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:
|
|
24
|
+
private warnings: SharedV4Warning[] = [];
|
|
25
25
|
|
|
26
26
|
getCacheControl(
|
|
27
|
-
providerMetadata:
|
|
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():
|
|
60
|
+
getWarnings(): SharedV4Warning[] {
|
|
61
61
|
return this.warnings;
|
|
62
62
|
}
|
|
63
63
|
}
|
package/src/internal/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export {
|
|
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 {
|
|
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
|
-
}):
|
|
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
|
+
}
|