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
- transformMessages(messages) {
90
- return messages.map((msg) => ({
91
- role: msg.role === 'user' ? 'user' : 'assistant',
92
- content: (0, content_helpers_1.contentToString)(msg.content),
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
- var _a, _b;
97
- const content = ((_b = (_a = data.content) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text) || '';
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 _f = true, _g = __asyncValues((0, stream_1.streamLines)(response.body)), _h; _h = yield __await(_g.next()), _a = _h.done, !_a; _f = true) {
119
- _c = _h.value;
120
- _f = false;
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 === 'content_block_delta') {
130
- const content = ((_d = chunk.delta) === null || _d === void 0 ? void 0 : _d.text) || '';
131
- if (content) {
132
- yield yield __await({
133
- content,
134
- index: chunk.index,
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 ((_e = chunk.delta) === null || _e === void 0 ? void 0 : _e.stop_reason) {
140
- yield yield __await({
141
- content: '',
142
- finishReason: chunk.delta.stop_reason,
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 (!_f && !_a && (_b = _g.return)) yield __await(_b.call(_g));
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,6 +1,6 @@
1
1
  {
2
2
  "name": "ai.libx.js",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Unified API bridge for various AI models (LLMs, image/video generation, TTS, STT) - stateless, edge-compatible",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -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
- private transformMessages(messages: Message[]): AnthropicMessage[] {
94
- return messages.map((msg) => ({
95
- role: msg.role === 'user' ? 'user' : 'assistant',
96
- content: contentToString(msg.content),
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
- const content = data.content?.[0]?.text || '';
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 === 'content_block_delta') {
131
- const content = chunk.delta?.text || '';
132
- if (content) {
133
- yield {
134
- content,
135
- index: chunk.index,
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
- yield {
141
- content: '',
142
- finishReason: chunk.delta.stop_reason,
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
-