ai.libx.js 0.2.9 → 0.2.10
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.
|
@@ -3,6 +3,8 @@ import { ChatOptions, ChatResponse, StreamChunk } from '../types';
|
|
|
3
3
|
export declare class AnthropicAdapter extends BaseAdapter {
|
|
4
4
|
get name(): string;
|
|
5
5
|
chat(options: ChatOptions): Promise<ChatResponse | AsyncIterable<StreamChunk>>;
|
|
6
|
+
private transformTools;
|
|
7
|
+
private transformToolChoice;
|
|
6
8
|
private transformMessages;
|
|
7
9
|
private handleNonStreamResponse;
|
|
8
10
|
private handleStreamResponse;
|
|
@@ -55,6 +55,12 @@ class AnthropicAdapter extends BaseAdapter_1.BaseAdapter {
|
|
|
55
55
|
if (systemMessage) {
|
|
56
56
|
request.system = (0, content_helpers_1.contentToString)(systemMessage.content);
|
|
57
57
|
}
|
|
58
|
+
if (options.tools && options.tools.length > 0) {
|
|
59
|
+
request.tools = this.transformTools(options.tools);
|
|
60
|
+
}
|
|
61
|
+
if (options.toolChoice !== undefined) {
|
|
62
|
+
request.tool_choice = this.transformToolChoice(options.toolChoice);
|
|
63
|
+
}
|
|
58
64
|
if (options.temperature !== undefined)
|
|
59
65
|
request.temperature = options.temperature;
|
|
60
66
|
if (options.topP !== undefined)
|
|
@@ -86,18 +92,104 @@ class AnthropicAdapter extends BaseAdapter_1.BaseAdapter {
|
|
|
86
92
|
}
|
|
87
93
|
});
|
|
88
94
|
}
|
|
89
|
-
|
|
90
|
-
return
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
transformTools(tools) {
|
|
96
|
+
return tools.map((tool) => ({
|
|
97
|
+
name: tool.function.name,
|
|
98
|
+
description: tool.function.description,
|
|
99
|
+
input_schema: tool.function.parameters,
|
|
93
100
|
}));
|
|
94
101
|
}
|
|
102
|
+
transformToolChoice(toolChoice) {
|
|
103
|
+
var _a;
|
|
104
|
+
if (toolChoice === 'auto') {
|
|
105
|
+
return { type: 'auto' };
|
|
106
|
+
}
|
|
107
|
+
if (toolChoice === 'none') {
|
|
108
|
+
return { type: 'none' };
|
|
109
|
+
}
|
|
110
|
+
if (toolChoice === 'required') {
|
|
111
|
+
return { type: 'any' };
|
|
112
|
+
}
|
|
113
|
+
if (typeof toolChoice === 'object' && ((_a = toolChoice.function) === null || _a === void 0 ? void 0 : _a.name)) {
|
|
114
|
+
return { type: 'tool', name: toolChoice.function.name };
|
|
115
|
+
}
|
|
116
|
+
return { type: 'auto' };
|
|
117
|
+
}
|
|
118
|
+
transformMessages(messages) {
|
|
119
|
+
const result = [];
|
|
120
|
+
for (const msg of messages) {
|
|
121
|
+
if (msg.role === 'tool') {
|
|
122
|
+
const lastMsg = result[result.length - 1];
|
|
123
|
+
if (lastMsg && lastMsg.role === 'user' && Array.isArray(lastMsg.content)) {
|
|
124
|
+
lastMsg.content.push({
|
|
125
|
+
type: 'tool_result',
|
|
126
|
+
tool_use_id: msg.tool_call_id,
|
|
127
|
+
content: (0, content_helpers_1.contentToString)(msg.content),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
result.push({
|
|
132
|
+
role: 'user',
|
|
133
|
+
content: [{
|
|
134
|
+
type: 'tool_result',
|
|
135
|
+
tool_use_id: msg.tool_call_id,
|
|
136
|
+
content: (0, content_helpers_1.contentToString)(msg.content),
|
|
137
|
+
}],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (msg.role === 'assistant' && msg.tool_calls && msg.tool_calls.length > 0) {
|
|
142
|
+
const content = [];
|
|
143
|
+
const textContent = (0, content_helpers_1.contentToString)(msg.content);
|
|
144
|
+
if (textContent) {
|
|
145
|
+
content.push({ type: 'text', text: textContent });
|
|
146
|
+
}
|
|
147
|
+
for (const tc of msg.tool_calls) {
|
|
148
|
+
content.push({
|
|
149
|
+
type: 'tool_use',
|
|
150
|
+
id: tc.id,
|
|
151
|
+
name: tc.function.name,
|
|
152
|
+
input: JSON.parse(tc.function.arguments || '{}'),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
result.push({ role: 'assistant', content });
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
result.push({
|
|
159
|
+
role: msg.role === 'user' ? 'user' : 'assistant',
|
|
160
|
+
content: (0, content_helpers_1.contentToString)(msg.content),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
95
166
|
handleNonStreamResponse(data, model) {
|
|
96
|
-
|
|
97
|
-
const
|
|
167
|
+
let textContent = '';
|
|
168
|
+
const toolCalls = [];
|
|
169
|
+
if (Array.isArray(data.content)) {
|
|
170
|
+
for (const block of data.content) {
|
|
171
|
+
if (block.type === 'text') {
|
|
172
|
+
textContent += block.text || '';
|
|
173
|
+
}
|
|
174
|
+
else if (block.type === 'tool_use') {
|
|
175
|
+
toolCalls.push({
|
|
176
|
+
id: block.id,
|
|
177
|
+
type: 'function',
|
|
178
|
+
function: {
|
|
179
|
+
name: block.name,
|
|
180
|
+
arguments: JSON.stringify(block.input || {}),
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (typeof data.content === 'string') {
|
|
187
|
+
textContent = data.content;
|
|
188
|
+
}
|
|
98
189
|
return {
|
|
99
|
-
content,
|
|
100
|
-
finishReason: data.stop_reason,
|
|
190
|
+
content: textContent,
|
|
191
|
+
finishReason: data.stop_reason === 'tool_use' ? 'tool_calls' : data.stop_reason,
|
|
192
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
101
193
|
usage: data.usage ? {
|
|
102
194
|
promptTokens: data.usage.input_tokens,
|
|
103
195
|
completionTokens: data.usage.output_tokens,
|
|
@@ -110,14 +202,17 @@ class AnthropicAdapter extends BaseAdapter_1.BaseAdapter {
|
|
|
110
202
|
handleStreamResponse(response, model) {
|
|
111
203
|
return __asyncGenerator(this, arguments, function* handleStreamResponse_1() {
|
|
112
204
|
var _a, e_1, _b, _c;
|
|
113
|
-
var _d, _e;
|
|
205
|
+
var _d, _e, _f;
|
|
114
206
|
if (!response.body) {
|
|
115
207
|
throw new Error('No response body for streaming');
|
|
116
208
|
}
|
|
209
|
+
const toolCallsInProgress = new Map();
|
|
210
|
+
let currentBlockIndex = -1;
|
|
211
|
+
let currentBlockType = null;
|
|
117
212
|
try {
|
|
118
|
-
for (var
|
|
119
|
-
_c =
|
|
120
|
-
|
|
213
|
+
for (var _g = true, _h = __asyncValues((0, stream_1.streamLines)(response.body)), _j; _j = yield __await(_h.next()), _a = _j.done, !_a; _g = true) {
|
|
214
|
+
_c = _j.value;
|
|
215
|
+
_g = false;
|
|
121
216
|
const line = _c;
|
|
122
217
|
if (!line.startsWith('data: '))
|
|
123
218
|
continue;
|
|
@@ -126,21 +221,58 @@ class AnthropicAdapter extends BaseAdapter_1.BaseAdapter {
|
|
|
126
221
|
break;
|
|
127
222
|
try {
|
|
128
223
|
const chunk = JSON.parse(data);
|
|
129
|
-
if (chunk.type === '
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
224
|
+
if (chunk.type === 'content_block_start') {
|
|
225
|
+
currentBlockIndex = chunk.index;
|
|
226
|
+
const block = chunk.content_block;
|
|
227
|
+
currentBlockType = block === null || block === void 0 ? void 0 : block.type;
|
|
228
|
+
if ((block === null || block === void 0 ? void 0 : block.type) === 'tool_use') {
|
|
229
|
+
toolCallsInProgress.set(currentBlockIndex, {
|
|
230
|
+
id: block.id,
|
|
231
|
+
name: block.name,
|
|
232
|
+
arguments: '',
|
|
135
233
|
});
|
|
136
234
|
}
|
|
137
235
|
}
|
|
236
|
+
else if (chunk.type === 'content_block_delta') {
|
|
237
|
+
if (currentBlockType === 'text') {
|
|
238
|
+
const content = ((_d = chunk.delta) === null || _d === void 0 ? void 0 : _d.text) || '';
|
|
239
|
+
if (content) {
|
|
240
|
+
yield yield __await({ content, index: chunk.index });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else if (currentBlockType === 'tool_use') {
|
|
244
|
+
const tc = toolCallsInProgress.get(currentBlockIndex);
|
|
245
|
+
if (tc && ((_e = chunk.delta) === null || _e === void 0 ? void 0 : _e.partial_json)) {
|
|
246
|
+
tc.arguments += chunk.delta.partial_json;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (chunk.type === 'content_block_stop') {
|
|
251
|
+
currentBlockType = null;
|
|
252
|
+
}
|
|
138
253
|
else if (chunk.type === 'message_delta') {
|
|
139
|
-
if ((
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
254
|
+
if ((_f = chunk.delta) === null || _f === void 0 ? void 0 : _f.stop_reason) {
|
|
255
|
+
if (toolCallsInProgress.size > 0) {
|
|
256
|
+
const toolCalls = Array.from(toolCallsInProgress.values()).map(tc => ({
|
|
257
|
+
id: tc.id,
|
|
258
|
+
type: 'function',
|
|
259
|
+
function: {
|
|
260
|
+
name: tc.name,
|
|
261
|
+
arguments: tc.arguments,
|
|
262
|
+
},
|
|
263
|
+
}));
|
|
264
|
+
yield yield __await({
|
|
265
|
+
content: '',
|
|
266
|
+
finishReason: chunk.delta.stop_reason === 'tool_use' ? 'tool_calls' : chunk.delta.stop_reason,
|
|
267
|
+
toolCalls,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
yield yield __await({
|
|
272
|
+
content: '',
|
|
273
|
+
finishReason: chunk.delta.stop_reason,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
144
276
|
}
|
|
145
277
|
}
|
|
146
278
|
}
|
|
@@ -152,7 +284,7 @@ class AnthropicAdapter extends BaseAdapter_1.BaseAdapter {
|
|
|
152
284
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
153
285
|
finally {
|
|
154
286
|
try {
|
|
155
|
-
if (!
|
|
287
|
+
if (!_g && !_a && (_b = _h.return)) yield __await(_b.call(_h));
|
|
156
288
|
}
|
|
157
289
|
finally { if (e_1) throw e_1.error; }
|
|
158
290
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseAdapter } from './base/BaseAdapter';\nimport { ChatOptions, ChatResponse, StreamChunk, Message } from '../types';\nimport { streamLines } from '../utils/stream';\nimport { handleProviderError } from '../utils/errors';\nimport { contentToString } from '../utils/content-helpers';\n\ninterface AnthropicMessage {\n\trole: 'user' | 'assistant';\n\tcontent: string;\n}\n\ninterface AnthropicRequest {\n\tmodel: string;\n\tmessages: AnthropicMessage[];\n\tmax_tokens: number;\n\ttemperature?: number;\n\ttop_p?: number;\n\ttop_k?: number;\n\tstop_sequences?: string[];\n\tstream?: boolean;\n\tsystem?: string;\n}\n\n/**\n * Anthropic Claude API adapter\n */\nexport class AnthropicAdapter extends BaseAdapter {\n\tget name(): string {\n\t\treturn 'anthropic';\n\t}\n\n\tasync chat(options: ChatOptions): Promise<ChatResponse | AsyncIterable<StreamChunk>> {\n\t\ttry {\n\t\t\tconst apiKey = this.getApiKey(options);\n\t\t\tconst baseUrl = this.getBaseUrl('https://api.anthropic.com/v1');\n\n\t\t\t// Strip provider prefix from model if present\n\t\t\tconst model = options.model.replace(/^anthropic\\//, '');\n\n\t\t\t// Extract system message if present\n\t\t\tconst systemMessage = options.messages.find((m) => m.role === 'system');\n\t\t\tconst nonSystemMessages = options.messages.filter((m) => m.role !== 'system');\n\n\t\t\tconst request: AnthropicRequest = {\n\t\t\t\tmodel,\n\t\t\t\tmessages: this.transformMessages(nonSystemMessages),\n\t\t\t\tmax_tokens: options.maxTokens || 4096,\n\t\t\t\tstream: options.stream || false,\n\t\t\t};\n\n\t\t\t// Add system prompt\n\t\t\tif (systemMessage) {\n\t\t\t\trequest.system = contentToString(systemMessage.content);\n\t\t\t}\n\n\t\t\t// Add optional parameters\n\t\t\tif (options.temperature !== undefined) request.temperature = options.temperature;\n\t\t\tif (options.topP !== undefined) request.top_p = options.topP;\n\t\t\tif (options.topK !== undefined) request.top_k = options.topK;\n\t\t\tif (options.stop && Array.isArray(options.stop)) {\n\t\t\t\trequest.stop_sequences = options.stop;\n\t\t\t}\n\n\t\t\t// Merge provider-specific options\n\t\t\tif (options.providerOptions) {\n\t\t\t\tObject.assign(request, options.providerOptions);\n\t\t\t}\n\n\t\t\tconst response = await this.fetchWithErrorHandling(\n\t\t\t\t`${baseUrl}/messages`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t'x-api-key': apiKey,\n\t\t\t\t\t\t'anthropic-version': '2023-06-01',\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\t},\n\t\t\t\tthis.name\n\t\t\t);\n\n\t\t\tif (options.stream) {\n\t\t\t\treturn this.handleStreamResponse(response, model);\n\t\t\t}\n\n\t\t\treturn this.handleNonStreamResponse(await response.json(), model);\n\t\t} catch (error) {\n\t\t\thandleProviderError(error, this.name);\n\t\t}\n\t}\n\n\tprivate transformMessages(messages: Message[]): AnthropicMessage[] {\n\t\treturn messages.map((msg) => ({\n\t\t\trole: msg.role === 'user' ? 'user' : 'assistant',\n\t\t\tcontent: contentToString(msg.content),\n\t\t}));\n\t}\n\n\tprivate handleNonStreamResponse(data: any, model: string): ChatResponse {\n\t\tconst content = data.content?.[0]?.text || '';\n\n\t\treturn {\n\t\t\tcontent,\n\t\t\tfinishReason: data.stop_reason,\n\t\t\tusage: data.usage ? {\n\t\t\t\tpromptTokens: data.usage.input_tokens,\n\t\t\t\tcompletionTokens: data.usage.output_tokens,\n\t\t\t\ttotalTokens: data.usage.input_tokens + data.usage.output_tokens,\n\t\t\t} : undefined,\n\t\t\tmodel,\n\t\t\traw: data,\n\t\t};\n\t}\n\n\tprivate async *handleStreamResponse(response: Response, model: string): AsyncIterable<StreamChunk> {\n\t\tif (!response.body) {\n\t\t\tthrow new Error('No response body for streaming');\n\t\t}\n\n\t\tfor await (const line of streamLines(response.body)) {\n\t\t\tif (!line.startsWith('data: ')) continue;\n\n\t\t\tconst data = line.slice(6).trim();\n\t\t\tif (data === '[DONE]') break;\n\n\t\t\ttry {\n\t\t\t\tconst chunk = JSON.parse(data);\n\n\t\t\t\tif (chunk.type === 'content_block_delta') {\n\t\t\t\t\tconst content = chunk.delta?.text || '';\n\t\t\t\t\tif (content) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tindex: chunk.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else if (chunk.type === 'message_delta') {\n\t\t\t\t\tif (chunk.delta?.stop_reason) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\tcontent: '',\n\t\t\t\t\t\t\tfinishReason: chunk.delta.stop_reason,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Skip invalid JSON\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseAdapter } from './base/BaseAdapter';\nimport { ChatOptions, ChatResponse, StreamChunk, Message, Tool, ToolCall, ToolChoice } from '../types';\nimport { streamLines } from '../utils/stream';\nimport { handleProviderError } from '../utils/errors';\nimport { contentToString } from '../utils/content-helpers';\n\n// Anthropic-specific types\ninterface AnthropicContentBlock {\n\ttype: 'text' | 'tool_use' | 'tool_result';\n\ttext?: string;\n\tid?: string;\n\tname?: string;\n\tinput?: Record<string, unknown>;\n\ttool_use_id?: string;\n\tcontent?: string;\n}\n\ninterface AnthropicMessage {\n\trole: 'user' | 'assistant';\n\tcontent: string | AnthropicContentBlock[];\n}\n\ninterface AnthropicTool {\n\tname: string;\n\tdescription?: string;\n\tinput_schema: object;\n}\n\ninterface AnthropicToolChoice {\n\ttype: 'auto' | 'any' | 'tool' | 'none';\n\tname?: string;\n\tdisable_parallel_tool_use?: boolean;\n}\n\ninterface AnthropicRequest {\n\tmodel: string;\n\tmessages: AnthropicMessage[];\n\tmax_tokens: number;\n\ttemperature?: number;\n\ttop_p?: number;\n\ttop_k?: number;\n\tstop_sequences?: string[];\n\tstream?: boolean;\n\tsystem?: string;\n\ttools?: AnthropicTool[];\n\ttool_choice?: AnthropicToolChoice;\n}\n\n/**\n * Anthropic Claude API adapter with full tool support\n */\nexport class AnthropicAdapter extends BaseAdapter {\n\tget name(): string {\n\t\treturn 'anthropic';\n\t}\n\n\tasync chat(options: ChatOptions): Promise<ChatResponse | AsyncIterable<StreamChunk>> {\n\t\ttry {\n\t\t\tconst apiKey = this.getApiKey(options);\n\t\t\tconst baseUrl = this.getBaseUrl('https://api.anthropic.com/v1');\n\n\t\t\t// Strip provider prefix from model if present\n\t\t\tconst model = options.model.replace(/^anthropic\\//, '');\n\n\t\t\t// Extract system message if present\n\t\t\tconst systemMessage = options.messages.find((m) => m.role === 'system');\n\t\t\tconst nonSystemMessages = options.messages.filter((m) => m.role !== 'system');\n\n\t\t\tconst request: AnthropicRequest = {\n\t\t\t\tmodel,\n\t\t\t\tmessages: this.transformMessages(nonSystemMessages),\n\t\t\t\tmax_tokens: options.maxTokens || 4096,\n\t\t\t\tstream: options.stream || false,\n\t\t\t};\n\n\t\t\t// Add system prompt\n\t\t\tif (systemMessage) {\n\t\t\t\trequest.system = contentToString(systemMessage.content);\n\t\t\t}\n\n\t\t\t// Add tools if provided\n\t\t\tif (options.tools && options.tools.length > 0) {\n\t\t\t\trequest.tools = this.transformTools(options.tools);\n\t\t\t}\n\n\t\t\t// Add tool_choice if provided\n\t\t\tif (options.toolChoice !== undefined) {\n\t\t\t\trequest.tool_choice = this.transformToolChoice(options.toolChoice);\n\t\t\t}\n\n\t\t\t// Add optional parameters\n\t\t\tif (options.temperature !== undefined) request.temperature = options.temperature;\n\t\t\tif (options.topP !== undefined) request.top_p = options.topP;\n\t\t\tif (options.topK !== undefined) request.top_k = options.topK;\n\t\t\tif (options.stop && Array.isArray(options.stop)) {\n\t\t\t\trequest.stop_sequences = options.stop;\n\t\t\t}\n\n\t\t\t// Merge provider-specific options\n\t\t\tif (options.providerOptions) {\n\t\t\t\tObject.assign(request, options.providerOptions);\n\t\t\t}\n\n\t\t\tconst response = await this.fetchWithErrorHandling(\n\t\t\t\t`${baseUrl}/messages`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t'x-api-key': apiKey,\n\t\t\t\t\t\t'anthropic-version': '2023-06-01',\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify(request),\n\t\t\t\t},\n\t\t\t\tthis.name\n\t\t\t);\n\n\t\t\tif (options.stream) {\n\t\t\t\treturn this.handleStreamResponse(response, model);\n\t\t\t}\n\n\t\t\treturn this.handleNonStreamResponse(await response.json(), model);\n\t\t} catch (error) {\n\t\t\thandleProviderError(error, this.name);\n\t\t}\n\t}\n\n\t/**\n\t * Transform OpenAI-style tools to Anthropic format\n\t */\n\tprivate transformTools(tools: Tool[]): AnthropicTool[] {\n\t\treturn tools.map((tool) => ({\n\t\t\tname: tool.function.name,\n\t\t\tdescription: tool.function.description,\n\t\t\tinput_schema: tool.function.parameters,\n\t\t}));\n\t}\n\n\t/**\n\t * Transform tool choice from OpenAI format to Anthropic format\n\t */\n\tprivate transformToolChoice(toolChoice: ToolChoice): AnthropicToolChoice {\n\t\tif (toolChoice === 'auto') {\n\t\t\treturn { type: 'auto' };\n\t\t}\n\t\tif (toolChoice === 'none') {\n\t\t\treturn { type: 'none' };\n\t\t}\n\t\tif (toolChoice === 'required') {\n\t\t\treturn { type: 'any' };\n\t\t}\n\t\tif (typeof toolChoice === 'object' && toolChoice.function?.name) {\n\t\t\treturn { type: 'tool', name: toolChoice.function.name };\n\t\t}\n\t\treturn { type: 'auto' };\n\t}\n\n\t/**\n\t * Transform messages to Anthropic format, handling tool calls and results\n\t */\n\tprivate transformMessages(messages: Message[]): AnthropicMessage[] {\n\t\tconst result: AnthropicMessage[] = [];\n\n\t\tfor (const msg of messages) {\n\t\t\tif (msg.role === 'tool') {\n\t\t\t\t// Tool result - needs to be a user message with tool_result content\n\t\t\t\t// Find or create the user message to attach this to\n\t\t\t\tconst lastMsg = result[result.length - 1];\n\t\t\t\tif (lastMsg && lastMsg.role === 'user' && Array.isArray(lastMsg.content)) {\n\t\t\t\t\t// Append to existing user message with tool results\n\t\t\t\t\tlastMsg.content.push({\n\t\t\t\t\t\ttype: 'tool_result',\n\t\t\t\t\t\ttool_use_id: msg.tool_call_id!,\n\t\t\t\t\t\tcontent: contentToString(msg.content),\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Create new user message with tool result\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\tcontent: [{\n\t\t\t\t\t\t\ttype: 'tool_result',\n\t\t\t\t\t\t\ttool_use_id: msg.tool_call_id!,\n\t\t\t\t\t\t\tcontent: contentToString(msg.content),\n\t\t\t\t\t\t}],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (msg.role === 'assistant' && msg.tool_calls && msg.tool_calls.length > 0) {\n\t\t\t\t// Assistant message with tool calls\n\t\t\t\tconst content: AnthropicContentBlock[] = [];\n\n\t\t\t\t// Add text content if present\n\t\t\t\tconst textContent = contentToString(msg.content);\n\t\t\t\tif (textContent) {\n\t\t\t\t\tcontent.push({ type: 'text', text: textContent });\n\t\t\t\t}\n\n\t\t\t\t// Add tool_use blocks\n\t\t\t\tfor (const tc of msg.tool_calls) {\n\t\t\t\t\tcontent.push({\n\t\t\t\t\t\ttype: 'tool_use',\n\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\t\tinput: JSON.parse(tc.function.arguments || '{}'),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tresult.push({ role: 'assistant', content });\n\t\t\t} else {\n\t\t\t\t// Regular message\n\t\t\t\tresult.push({\n\t\t\t\t\trole: msg.role === 'user' ? 'user' : 'assistant',\n\t\t\t\t\tcontent: contentToString(msg.content),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Handle non-streaming response, extracting tool calls if present\n\t */\n\tprivate handleNonStreamResponse(data: any, model: string): ChatResponse {\n\t\tlet textContent = '';\n\t\tconst toolCalls: ToolCall[] = [];\n\n\t\t// Parse content array\n\t\tif (Array.isArray(data.content)) {\n\t\t\tfor (const block of data.content) {\n\t\t\t\tif (block.type === 'text') {\n\t\t\t\t\ttextContent += block.text || '';\n\t\t\t\t} else if (block.type === 'tool_use') {\n\t\t\t\t\ttoolCalls.push({\n\t\t\t\t\t\tid: block.id,\n\t\t\t\t\t\ttype: 'function',\n\t\t\t\t\t\tfunction: {\n\t\t\t\t\t\t\tname: block.name,\n\t\t\t\t\t\t\targuments: JSON.stringify(block.input || {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (typeof data.content === 'string') {\n\t\t\ttextContent = data.content;\n\t\t}\n\n\t\treturn {\n\t\t\tcontent: textContent,\n\t\t\tfinishReason: data.stop_reason === 'tool_use' ? 'tool_calls' : data.stop_reason,\n\t\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\t\tusage: data.usage ? {\n\t\t\t\tpromptTokens: data.usage.input_tokens,\n\t\t\t\tcompletionTokens: data.usage.output_tokens,\n\t\t\t\ttotalTokens: data.usage.input_tokens + data.usage.output_tokens,\n\t\t\t} : undefined,\n\t\t\tmodel,\n\t\t\traw: data,\n\t\t};\n\t}\n\n\t/**\n\t * Handle streaming response with tool call support\n\t */\n\tprivate async *handleStreamResponse(response: Response, model: string): AsyncIterable<StreamChunk> {\n\t\tif (!response.body) {\n\t\t\tthrow new Error('No response body for streaming');\n\t\t}\n\n\t\t// Track tool calls being built\n\t\tconst toolCallsInProgress: Map<number, { id: string; name: string; arguments: string }> = new Map();\n\t\tlet currentBlockIndex = -1;\n\t\tlet currentBlockType: string | null = null;\n\n\t\tfor await (const line of streamLines(response.body)) {\n\t\t\tif (!line.startsWith('data: ')) continue;\n\n\t\t\tconst data = line.slice(6).trim();\n\t\t\tif (data === '[DONE]') break;\n\n\t\t\ttry {\n\t\t\t\tconst chunk = JSON.parse(data);\n\n\t\t\t\tif (chunk.type === 'content_block_start') {\n\t\t\t\t\tcurrentBlockIndex = chunk.index;\n\t\t\t\t\tconst block = chunk.content_block;\n\t\t\t\t\tcurrentBlockType = block?.type;\n\n\t\t\t\t\tif (block?.type === 'tool_use') {\n\t\t\t\t\t\t// Start of a tool call\n\t\t\t\t\t\ttoolCallsInProgress.set(currentBlockIndex, {\n\t\t\t\t\t\t\tid: block.id,\n\t\t\t\t\t\t\tname: block.name,\n\t\t\t\t\t\t\targuments: '',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (chunk.type === 'content_block_delta') {\n\t\t\t\t\tif (currentBlockType === 'text') {\n\t\t\t\t\t\tconst content = chunk.delta?.text || '';\n\t\t\t\t\t\tif (content) {\n\t\t\t\t\t\t\tyield { content, index: chunk.index };\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (currentBlockType === 'tool_use') {\n\t\t\t\t\t\t// Accumulate tool input JSON\n\t\t\t\t\t\tconst tc = toolCallsInProgress.get(currentBlockIndex);\n\t\t\t\t\t\tif (tc && chunk.delta?.partial_json) {\n\t\t\t\t\t\t\ttc.arguments += chunk.delta.partial_json;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (chunk.type === 'content_block_stop') {\n\t\t\t\t\t// Block finished - nothing special needed\n\t\t\t\t\tcurrentBlockType = null;\n\t\t\t\t} else if (chunk.type === 'message_delta') {\n\t\t\t\t\tif (chunk.delta?.stop_reason) {\n\t\t\t\t\t\t// Emit tool calls if any were accumulated\n\t\t\t\t\t\tif (toolCallsInProgress.size > 0) {\n\t\t\t\t\t\t\tconst toolCalls: ToolCall[] = Array.from(toolCallsInProgress.values()).map(tc => ({\n\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\ttype: 'function' as const,\n\t\t\t\t\t\t\t\tfunction: {\n\t\t\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\t\t\targuments: tc.arguments,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}));\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\tcontent: '',\n\t\t\t\t\t\t\t\tfinishReason: chunk.delta.stop_reason === 'tool_use' ? 'tool_calls' : chunk.delta.stop_reason,\n\t\t\t\t\t\t\t\ttoolCalls,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\tcontent: '',\n\t\t\t\t\t\t\t\tfinishReason: chunk.delta.stop_reason,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Skip invalid JSON\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
import { BaseAdapter } from './base/BaseAdapter';
|
|
2
|
-
import { ChatOptions, ChatResponse, StreamChunk, Message } from '../types';
|
|
2
|
+
import { ChatOptions, ChatResponse, StreamChunk, Message, Tool, ToolCall, ToolChoice } from '../types';
|
|
3
3
|
import { streamLines } from '../utils/stream';
|
|
4
4
|
import { handleProviderError } from '../utils/errors';
|
|
5
5
|
import { contentToString } from '../utils/content-helpers';
|
|
6
6
|
|
|
7
|
+
// Anthropic-specific types
|
|
8
|
+
interface AnthropicContentBlock {
|
|
9
|
+
type: 'text' | 'tool_use' | 'tool_result';
|
|
10
|
+
text?: string;
|
|
11
|
+
id?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
input?: Record<string, unknown>;
|
|
14
|
+
tool_use_id?: string;
|
|
15
|
+
content?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
interface AnthropicMessage {
|
|
8
19
|
role: 'user' | 'assistant';
|
|
9
|
-
content: string;
|
|
20
|
+
content: string | AnthropicContentBlock[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AnthropicTool {
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
input_schema: object;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface AnthropicToolChoice {
|
|
30
|
+
type: 'auto' | 'any' | 'tool' | 'none';
|
|
31
|
+
name?: string;
|
|
32
|
+
disable_parallel_tool_use?: boolean;
|
|
10
33
|
}
|
|
11
34
|
|
|
12
35
|
interface AnthropicRequest {
|
|
@@ -19,10 +42,12 @@ interface AnthropicRequest {
|
|
|
19
42
|
stop_sequences?: string[];
|
|
20
43
|
stream?: boolean;
|
|
21
44
|
system?: string;
|
|
45
|
+
tools?: AnthropicTool[];
|
|
46
|
+
tool_choice?: AnthropicToolChoice;
|
|
22
47
|
}
|
|
23
48
|
|
|
24
49
|
/**
|
|
25
|
-
* Anthropic Claude API adapter
|
|
50
|
+
* Anthropic Claude API adapter with full tool support
|
|
26
51
|
*/
|
|
27
52
|
export class AnthropicAdapter extends BaseAdapter {
|
|
28
53
|
get name(): string {
|
|
@@ -53,6 +78,16 @@ export class AnthropicAdapter extends BaseAdapter {
|
|
|
53
78
|
request.system = contentToString(systemMessage.content);
|
|
54
79
|
}
|
|
55
80
|
|
|
81
|
+
// Add tools if provided
|
|
82
|
+
if (options.tools && options.tools.length > 0) {
|
|
83
|
+
request.tools = this.transformTools(options.tools);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Add tool_choice if provided
|
|
87
|
+
if (options.toolChoice !== undefined) {
|
|
88
|
+
request.tool_choice = this.transformToolChoice(options.toolChoice);
|
|
89
|
+
}
|
|
90
|
+
|
|
56
91
|
// Add optional parameters
|
|
57
92
|
if (options.temperature !== undefined) request.temperature = options.temperature;
|
|
58
93
|
if (options.topP !== undefined) request.top_p = options.topP;
|
|
@@ -90,19 +125,129 @@ export class AnthropicAdapter extends BaseAdapter {
|
|
|
90
125
|
}
|
|
91
126
|
}
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Transform OpenAI-style tools to Anthropic format
|
|
130
|
+
*/
|
|
131
|
+
private transformTools(tools: Tool[]): AnthropicTool[] {
|
|
132
|
+
return tools.map((tool) => ({
|
|
133
|
+
name: tool.function.name,
|
|
134
|
+
description: tool.function.description,
|
|
135
|
+
input_schema: tool.function.parameters,
|
|
97
136
|
}));
|
|
98
137
|
}
|
|
99
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Transform tool choice from OpenAI format to Anthropic format
|
|
141
|
+
*/
|
|
142
|
+
private transformToolChoice(toolChoice: ToolChoice): AnthropicToolChoice {
|
|
143
|
+
if (toolChoice === 'auto') {
|
|
144
|
+
return { type: 'auto' };
|
|
145
|
+
}
|
|
146
|
+
if (toolChoice === 'none') {
|
|
147
|
+
return { type: 'none' };
|
|
148
|
+
}
|
|
149
|
+
if (toolChoice === 'required') {
|
|
150
|
+
return { type: 'any' };
|
|
151
|
+
}
|
|
152
|
+
if (typeof toolChoice === 'object' && toolChoice.function?.name) {
|
|
153
|
+
return { type: 'tool', name: toolChoice.function.name };
|
|
154
|
+
}
|
|
155
|
+
return { type: 'auto' };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Transform messages to Anthropic format, handling tool calls and results
|
|
160
|
+
*/
|
|
161
|
+
private transformMessages(messages: Message[]): AnthropicMessage[] {
|
|
162
|
+
const result: AnthropicMessage[] = [];
|
|
163
|
+
|
|
164
|
+
for (const msg of messages) {
|
|
165
|
+
if (msg.role === 'tool') {
|
|
166
|
+
// Tool result - needs to be a user message with tool_result content
|
|
167
|
+
// Find or create the user message to attach this to
|
|
168
|
+
const lastMsg = result[result.length - 1];
|
|
169
|
+
if (lastMsg && lastMsg.role === 'user' && Array.isArray(lastMsg.content)) {
|
|
170
|
+
// Append to existing user message with tool results
|
|
171
|
+
lastMsg.content.push({
|
|
172
|
+
type: 'tool_result',
|
|
173
|
+
tool_use_id: msg.tool_call_id!,
|
|
174
|
+
content: contentToString(msg.content),
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
// Create new user message with tool result
|
|
178
|
+
result.push({
|
|
179
|
+
role: 'user',
|
|
180
|
+
content: [{
|
|
181
|
+
type: 'tool_result',
|
|
182
|
+
tool_use_id: msg.tool_call_id!,
|
|
183
|
+
content: contentToString(msg.content),
|
|
184
|
+
}],
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
} else if (msg.role === 'assistant' && msg.tool_calls && msg.tool_calls.length > 0) {
|
|
188
|
+
// Assistant message with tool calls
|
|
189
|
+
const content: AnthropicContentBlock[] = [];
|
|
190
|
+
|
|
191
|
+
// Add text content if present
|
|
192
|
+
const textContent = contentToString(msg.content);
|
|
193
|
+
if (textContent) {
|
|
194
|
+
content.push({ type: 'text', text: textContent });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Add tool_use blocks
|
|
198
|
+
for (const tc of msg.tool_calls) {
|
|
199
|
+
content.push({
|
|
200
|
+
type: 'tool_use',
|
|
201
|
+
id: tc.id,
|
|
202
|
+
name: tc.function.name,
|
|
203
|
+
input: JSON.parse(tc.function.arguments || '{}'),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
result.push({ role: 'assistant', content });
|
|
208
|
+
} else {
|
|
209
|
+
// Regular message
|
|
210
|
+
result.push({
|
|
211
|
+
role: msg.role === 'user' ? 'user' : 'assistant',
|
|
212
|
+
content: contentToString(msg.content),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Handle non-streaming response, extracting tool calls if present
|
|
222
|
+
*/
|
|
100
223
|
private handleNonStreamResponse(data: any, model: string): ChatResponse {
|
|
101
|
-
|
|
224
|
+
let textContent = '';
|
|
225
|
+
const toolCalls: ToolCall[] = [];
|
|
226
|
+
|
|
227
|
+
// Parse content array
|
|
228
|
+
if (Array.isArray(data.content)) {
|
|
229
|
+
for (const block of data.content) {
|
|
230
|
+
if (block.type === 'text') {
|
|
231
|
+
textContent += block.text || '';
|
|
232
|
+
} else if (block.type === 'tool_use') {
|
|
233
|
+
toolCalls.push({
|
|
234
|
+
id: block.id,
|
|
235
|
+
type: 'function',
|
|
236
|
+
function: {
|
|
237
|
+
name: block.name,
|
|
238
|
+
arguments: JSON.stringify(block.input || {}),
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} else if (typeof data.content === 'string') {
|
|
244
|
+
textContent = data.content;
|
|
245
|
+
}
|
|
102
246
|
|
|
103
247
|
return {
|
|
104
|
-
content,
|
|
105
|
-
finishReason: data.stop_reason,
|
|
248
|
+
content: textContent,
|
|
249
|
+
finishReason: data.stop_reason === 'tool_use' ? 'tool_calls' : data.stop_reason,
|
|
250
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
106
251
|
usage: data.usage ? {
|
|
107
252
|
promptTokens: data.usage.input_tokens,
|
|
108
253
|
completionTokens: data.usage.output_tokens,
|
|
@@ -113,11 +258,19 @@ export class AnthropicAdapter extends BaseAdapter {
|
|
|
113
258
|
};
|
|
114
259
|
}
|
|
115
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Handle streaming response with tool call support
|
|
263
|
+
*/
|
|
116
264
|
private async *handleStreamResponse(response: Response, model: string): AsyncIterable<StreamChunk> {
|
|
117
265
|
if (!response.body) {
|
|
118
266
|
throw new Error('No response body for streaming');
|
|
119
267
|
}
|
|
120
268
|
|
|
269
|
+
// Track tool calls being built
|
|
270
|
+
const toolCallsInProgress: Map<number, { id: string; name: string; arguments: string }> = new Map();
|
|
271
|
+
let currentBlockIndex = -1;
|
|
272
|
+
let currentBlockType: string | null = null;
|
|
273
|
+
|
|
121
274
|
for await (const line of streamLines(response.body)) {
|
|
122
275
|
if (!line.startsWith('data: ')) continue;
|
|
123
276
|
|
|
@@ -127,20 +280,59 @@ export class AnthropicAdapter extends BaseAdapter {
|
|
|
127
280
|
try {
|
|
128
281
|
const chunk = JSON.parse(data);
|
|
129
282
|
|
|
130
|
-
if (chunk.type === '
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
283
|
+
if (chunk.type === 'content_block_start') {
|
|
284
|
+
currentBlockIndex = chunk.index;
|
|
285
|
+
const block = chunk.content_block;
|
|
286
|
+
currentBlockType = block?.type;
|
|
287
|
+
|
|
288
|
+
if (block?.type === 'tool_use') {
|
|
289
|
+
// Start of a tool call
|
|
290
|
+
toolCallsInProgress.set(currentBlockIndex, {
|
|
291
|
+
id: block.id,
|
|
292
|
+
name: block.name,
|
|
293
|
+
arguments: '',
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
} else if (chunk.type === 'content_block_delta') {
|
|
297
|
+
if (currentBlockType === 'text') {
|
|
298
|
+
const content = chunk.delta?.text || '';
|
|
299
|
+
if (content) {
|
|
300
|
+
yield { content, index: chunk.index };
|
|
301
|
+
}
|
|
302
|
+
} else if (currentBlockType === 'tool_use') {
|
|
303
|
+
// Accumulate tool input JSON
|
|
304
|
+
const tc = toolCallsInProgress.get(currentBlockIndex);
|
|
305
|
+
if (tc && chunk.delta?.partial_json) {
|
|
306
|
+
tc.arguments += chunk.delta.partial_json;
|
|
307
|
+
}
|
|
137
308
|
}
|
|
309
|
+
} else if (chunk.type === 'content_block_stop') {
|
|
310
|
+
// Block finished - nothing special needed
|
|
311
|
+
currentBlockType = null;
|
|
138
312
|
} else if (chunk.type === 'message_delta') {
|
|
139
313
|
if (chunk.delta?.stop_reason) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
314
|
+
// Emit tool calls if any were accumulated
|
|
315
|
+
if (toolCallsInProgress.size > 0) {
|
|
316
|
+
const toolCalls: ToolCall[] = Array.from(toolCallsInProgress.values()).map(tc => ({
|
|
317
|
+
id: tc.id,
|
|
318
|
+
type: 'function' as const,
|
|
319
|
+
function: {
|
|
320
|
+
name: tc.name,
|
|
321
|
+
arguments: tc.arguments,
|
|
322
|
+
},
|
|
323
|
+
}));
|
|
324
|
+
|
|
325
|
+
yield {
|
|
326
|
+
content: '',
|
|
327
|
+
finishReason: chunk.delta.stop_reason === 'tool_use' ? 'tool_calls' : chunk.delta.stop_reason,
|
|
328
|
+
toolCalls,
|
|
329
|
+
};
|
|
330
|
+
} else {
|
|
331
|
+
yield {
|
|
332
|
+
content: '',
|
|
333
|
+
finishReason: chunk.delta.stop_reason,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
144
336
|
}
|
|
145
337
|
}
|
|
146
338
|
} catch (e) {
|
|
@@ -150,4 +342,3 @@ export class AnthropicAdapter extends BaseAdapter {
|
|
|
150
342
|
}
|
|
151
343
|
}
|
|
152
344
|
}
|
|
153
|
-
|