@yourgpt/llm-sdk 0.1.0 → 0.1.1
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/README.md +61 -40
- package/dist/adapters/index.d.mts +4 -258
- package/dist/adapters/index.d.ts +4 -258
- package/dist/adapters/index.js +0 -113
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs +1 -112
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/base-D_FyHFKj.d.mts +235 -0
- package/dist/base-D_FyHFKj.d.ts +235 -0
- package/dist/index.d.mts +145 -450
- package/dist/index.d.ts +145 -450
- package/dist/index.js +1837 -307
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1827 -305
- package/dist/index.mjs.map +1 -1
- package/dist/providers/anthropic/index.d.mts +61 -0
- package/dist/providers/anthropic/index.d.ts +61 -0
- package/dist/providers/anthropic/index.js +939 -0
- package/dist/providers/anthropic/index.js.map +1 -0
- package/dist/providers/anthropic/index.mjs +934 -0
- package/dist/providers/anthropic/index.mjs.map +1 -0
- package/dist/providers/azure/index.d.mts +38 -0
- package/dist/providers/azure/index.d.ts +38 -0
- package/dist/providers/azure/index.js +380 -0
- package/dist/providers/azure/index.js.map +1 -0
- package/dist/providers/azure/index.mjs +377 -0
- package/dist/providers/azure/index.mjs.map +1 -0
- package/dist/providers/google/index.d.mts +72 -0
- package/dist/providers/google/index.d.ts +72 -0
- package/dist/providers/google/index.js +790 -0
- package/dist/providers/google/index.js.map +1 -0
- package/dist/providers/google/index.mjs +785 -0
- package/dist/providers/google/index.mjs.map +1 -0
- package/dist/providers/ollama/index.d.mts +24 -0
- package/dist/providers/ollama/index.d.ts +24 -0
- package/dist/providers/ollama/index.js +235 -0
- package/dist/providers/ollama/index.js.map +1 -0
- package/dist/providers/ollama/index.mjs +232 -0
- package/dist/providers/ollama/index.mjs.map +1 -0
- package/dist/providers/openai/index.d.mts +82 -0
- package/dist/providers/openai/index.d.ts +82 -0
- package/dist/providers/openai/index.js +679 -0
- package/dist/providers/openai/index.js.map +1 -0
- package/dist/providers/openai/index.mjs +674 -0
- package/dist/providers/openai/index.mjs.map +1 -0
- package/dist/providers/xai/index.d.mts +78 -0
- package/dist/providers/xai/index.d.ts +78 -0
- package/dist/providers/xai/index.js +671 -0
- package/dist/providers/xai/index.js.map +1 -0
- package/dist/providers/xai/index.mjs +666 -0
- package/dist/providers/xai/index.mjs.map +1 -0
- package/dist/types-BBCZ3Fxy.d.mts +308 -0
- package/dist/types-CdORv1Yu.d.mts +338 -0
- package/dist/types-CdORv1Yu.d.ts +338 -0
- package/dist/types-DcoCaVVC.d.ts +308 -0
- package/package.json +34 -3
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,1694 @@ import { generateMessageId, generateToolCallId, createMessage } from '@yourgpt/c
|
|
|
2
2
|
import { Hono } from 'hono';
|
|
3
3
|
import { cors } from 'hono/cors';
|
|
4
4
|
|
|
5
|
-
// src/
|
|
5
|
+
// src/core/tool.ts
|
|
6
|
+
function tool(config) {
|
|
7
|
+
return {
|
|
8
|
+
description: config.description,
|
|
9
|
+
parameters: config.parameters,
|
|
10
|
+
execute: config.execute
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function toolToJsonSchema(toolDef) {
|
|
14
|
+
const schema = zodToJsonSchema(toolDef.parameters);
|
|
15
|
+
return {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: schema.properties ?? {},
|
|
18
|
+
required: schema.required
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function zodToJsonSchema(schema) {
|
|
22
|
+
const def = schema._def;
|
|
23
|
+
const typeName = def.typeName;
|
|
24
|
+
const description = def.description;
|
|
25
|
+
switch (typeName) {
|
|
26
|
+
case "ZodString":
|
|
27
|
+
return { type: "string", description };
|
|
28
|
+
case "ZodNumber":
|
|
29
|
+
return { type: "number", description };
|
|
30
|
+
case "ZodBoolean":
|
|
31
|
+
return { type: "boolean", description };
|
|
32
|
+
case "ZodEnum": {
|
|
33
|
+
const values = def.values;
|
|
34
|
+
return { type: "string", enum: values, description };
|
|
35
|
+
}
|
|
36
|
+
case "ZodArray": {
|
|
37
|
+
const innerType = def.type;
|
|
38
|
+
return {
|
|
39
|
+
type: "array",
|
|
40
|
+
items: zodToJsonSchema(innerType),
|
|
41
|
+
description
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
case "ZodObject": {
|
|
45
|
+
const shape = def.shape;
|
|
46
|
+
const shapeObj = shape();
|
|
47
|
+
const properties = {};
|
|
48
|
+
const required = [];
|
|
49
|
+
for (const [key, value] of Object.entries(shapeObj)) {
|
|
50
|
+
properties[key] = zodToJsonSchema(value);
|
|
51
|
+
const valueDef = value._def;
|
|
52
|
+
const isOptional = valueDef.typeName === "ZodOptional" || valueDef.typeName === "ZodNullable" || valueDef.typeName === "ZodDefault";
|
|
53
|
+
if (!isOptional) {
|
|
54
|
+
required.push(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties,
|
|
60
|
+
required: required.length > 0 ? required : void 0,
|
|
61
|
+
description
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
case "ZodOptional":
|
|
65
|
+
case "ZodNullable": {
|
|
66
|
+
const innerType = def.innerType;
|
|
67
|
+
return zodToJsonSchema(innerType);
|
|
68
|
+
}
|
|
69
|
+
case "ZodDefault": {
|
|
70
|
+
const innerType = def.innerType;
|
|
71
|
+
return zodToJsonSchema(innerType);
|
|
72
|
+
}
|
|
73
|
+
case "ZodLiteral": {
|
|
74
|
+
const value = def.value;
|
|
75
|
+
if (typeof value === "string") {
|
|
76
|
+
return { type: "string", enum: [value], description };
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === "number") {
|
|
79
|
+
return { type: "number", enum: [value], description };
|
|
80
|
+
}
|
|
81
|
+
if (typeof value === "boolean") {
|
|
82
|
+
return { type: "boolean", enum: [value], description };
|
|
83
|
+
}
|
|
84
|
+
return { description };
|
|
85
|
+
}
|
|
86
|
+
case "ZodUnion": {
|
|
87
|
+
const options = def.options;
|
|
88
|
+
const stringLiterals = [];
|
|
89
|
+
for (const option of options) {
|
|
90
|
+
const optDef = option._def;
|
|
91
|
+
if (optDef.typeName === "ZodLiteral" && typeof optDef.value === "string") {
|
|
92
|
+
stringLiterals.push(optDef.value);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (stringLiterals.length === options.length) {
|
|
96
|
+
return { type: "string", enum: stringLiterals, description };
|
|
97
|
+
}
|
|
98
|
+
return zodToJsonSchema(options[0]);
|
|
99
|
+
}
|
|
100
|
+
default:
|
|
101
|
+
return { type: "string", description };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function formatToolsForOpenAI(tools) {
|
|
105
|
+
return Object.entries(tools).map(([name, toolDef]) => ({
|
|
106
|
+
type: "function",
|
|
107
|
+
function: {
|
|
108
|
+
name,
|
|
109
|
+
description: toolDef.description,
|
|
110
|
+
parameters: toolToJsonSchema(toolDef)
|
|
111
|
+
}
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
function formatToolsForAnthropic(tools) {
|
|
115
|
+
return Object.entries(tools).map(([name, toolDef]) => ({
|
|
116
|
+
name,
|
|
117
|
+
description: toolDef.description,
|
|
118
|
+
input_schema: toolToJsonSchema(toolDef)
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
function formatToolsForGoogle(tools) {
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
functionDeclarations: Object.entries(tools).map(([name, toolDef]) => ({
|
|
125
|
+
name,
|
|
126
|
+
description: toolDef.description,
|
|
127
|
+
parameters: toolToJsonSchema(toolDef)
|
|
128
|
+
}))
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/core/generate-text.ts
|
|
134
|
+
async function generateText(params) {
|
|
135
|
+
const { model, tools, maxSteps = 1, signal } = params;
|
|
136
|
+
let messages = buildMessages(params);
|
|
137
|
+
const steps = [];
|
|
138
|
+
const allToolCalls = [];
|
|
139
|
+
const allToolResults = [];
|
|
140
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
141
|
+
if (signal?.aborted) {
|
|
142
|
+
throw new Error("Generation aborted");
|
|
143
|
+
}
|
|
144
|
+
const formattedTools = tools ? formatToolsForProvider(tools, model.provider) : void 0;
|
|
145
|
+
const result = await model.doGenerate({
|
|
146
|
+
messages,
|
|
147
|
+
tools: formattedTools,
|
|
148
|
+
temperature: params.temperature,
|
|
149
|
+
maxTokens: params.maxTokens,
|
|
150
|
+
signal
|
|
151
|
+
});
|
|
152
|
+
const stepToolResults = [];
|
|
153
|
+
if (result.toolCalls && result.toolCalls.length > 0 && tools) {
|
|
154
|
+
allToolCalls.push(...result.toolCalls);
|
|
155
|
+
for (const call of result.toolCalls) {
|
|
156
|
+
const toolDef = tools[call.name];
|
|
157
|
+
if (!toolDef) {
|
|
158
|
+
const errorResult = {
|
|
159
|
+
toolCallId: call.id,
|
|
160
|
+
result: { error: `Tool not found: ${call.name}` }
|
|
161
|
+
};
|
|
162
|
+
stepToolResults.push(errorResult);
|
|
163
|
+
allToolResults.push(errorResult);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const parsedArgs = toolDef.parameters.parse(call.args);
|
|
168
|
+
const toolResult = await toolDef.execute(parsedArgs, {
|
|
169
|
+
toolCallId: call.id,
|
|
170
|
+
abortSignal: signal,
|
|
171
|
+
messages
|
|
172
|
+
});
|
|
173
|
+
const result2 = {
|
|
174
|
+
toolCallId: call.id,
|
|
175
|
+
result: toolResult
|
|
176
|
+
};
|
|
177
|
+
stepToolResults.push(result2);
|
|
178
|
+
allToolResults.push(result2);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
const errorResult = {
|
|
181
|
+
toolCallId: call.id,
|
|
182
|
+
result: {
|
|
183
|
+
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
stepToolResults.push(errorResult);
|
|
187
|
+
allToolResults.push(errorResult);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
steps.push({
|
|
192
|
+
text: result.text,
|
|
193
|
+
toolCalls: result.toolCalls,
|
|
194
|
+
toolResults: stepToolResults,
|
|
195
|
+
finishReason: result.finishReason,
|
|
196
|
+
usage: result.usage
|
|
197
|
+
});
|
|
198
|
+
if (!result.toolCalls || result.toolCalls.length === 0) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
const assistantMessage = {
|
|
202
|
+
role: "assistant",
|
|
203
|
+
content: result.text || null,
|
|
204
|
+
toolCalls: result.toolCalls
|
|
205
|
+
};
|
|
206
|
+
messages = [...messages, assistantMessage];
|
|
207
|
+
for (const tr of stepToolResults) {
|
|
208
|
+
const toolMessage = {
|
|
209
|
+
role: "tool",
|
|
210
|
+
toolCallId: tr.toolCallId,
|
|
211
|
+
content: JSON.stringify(tr.result)
|
|
212
|
+
};
|
|
213
|
+
messages = [...messages, toolMessage];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const lastStep = steps[steps.length - 1];
|
|
217
|
+
return {
|
|
218
|
+
text: lastStep?.text ?? "",
|
|
219
|
+
usage: sumUsage(steps),
|
|
220
|
+
finishReason: lastStep?.finishReason ?? "stop",
|
|
221
|
+
steps,
|
|
222
|
+
toolCalls: allToolCalls,
|
|
223
|
+
toolResults: allToolResults,
|
|
224
|
+
response: {
|
|
225
|
+
messages
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function buildMessages(params) {
|
|
230
|
+
const messages = [];
|
|
231
|
+
if (params.system) {
|
|
232
|
+
messages.push({ role: "system", content: params.system });
|
|
233
|
+
}
|
|
234
|
+
if (params.messages) {
|
|
235
|
+
messages.push(...params.messages);
|
|
236
|
+
}
|
|
237
|
+
if (params.prompt) {
|
|
238
|
+
messages.push({ role: "user", content: params.prompt });
|
|
239
|
+
}
|
|
240
|
+
return messages;
|
|
241
|
+
}
|
|
242
|
+
function formatToolsForProvider(tools, provider) {
|
|
243
|
+
switch (provider) {
|
|
244
|
+
case "anthropic":
|
|
245
|
+
return formatToolsForAnthropic(tools);
|
|
246
|
+
case "openai":
|
|
247
|
+
case "xai":
|
|
248
|
+
case "azure":
|
|
249
|
+
default:
|
|
250
|
+
return formatToolsForOpenAI(tools);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function sumUsage(steps) {
|
|
254
|
+
return steps.reduce(
|
|
255
|
+
(acc, step) => ({
|
|
256
|
+
promptTokens: acc.promptTokens + (step.usage?.promptTokens ?? 0),
|
|
257
|
+
completionTokens: acc.completionTokens + (step.usage?.completionTokens ?? 0),
|
|
258
|
+
totalTokens: acc.totalTokens + (step.usage?.totalTokens ?? 0)
|
|
259
|
+
}),
|
|
260
|
+
{ promptTokens: 0, completionTokens: 0, totalTokens: 0 }
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/core/stream-text.ts
|
|
265
|
+
async function streamText(params) {
|
|
266
|
+
const { model, tools, maxSteps = 1, signal } = params;
|
|
267
|
+
let fullText = "";
|
|
268
|
+
let finalUsage = {
|
|
269
|
+
promptTokens: 0,
|
|
270
|
+
completionTokens: 0,
|
|
271
|
+
totalTokens: 0
|
|
272
|
+
};
|
|
273
|
+
let finalFinishReason = "stop";
|
|
274
|
+
async function* createFullStream() {
|
|
275
|
+
let messages = buildMessages2(params);
|
|
276
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
277
|
+
yield { type: "step-start", step };
|
|
278
|
+
if (signal?.aborted) {
|
|
279
|
+
yield { type: "error", error: new Error("Stream aborted") };
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const formattedTools = tools ? formatToolsForProvider2(tools, model.provider) : void 0;
|
|
283
|
+
let stepText = "";
|
|
284
|
+
const toolCalls = [];
|
|
285
|
+
let stepFinishReason = "stop";
|
|
286
|
+
try {
|
|
287
|
+
for await (const chunk of model.doStream({
|
|
288
|
+
messages,
|
|
289
|
+
tools: formattedTools,
|
|
290
|
+
temperature: params.temperature,
|
|
291
|
+
maxTokens: params.maxTokens,
|
|
292
|
+
signal
|
|
293
|
+
})) {
|
|
294
|
+
switch (chunk.type) {
|
|
295
|
+
case "text-delta":
|
|
296
|
+
stepText += chunk.text;
|
|
297
|
+
fullText += chunk.text;
|
|
298
|
+
yield { type: "text-delta", text: chunk.text };
|
|
299
|
+
break;
|
|
300
|
+
case "tool-call":
|
|
301
|
+
toolCalls.push(chunk.toolCall);
|
|
302
|
+
yield {
|
|
303
|
+
type: "tool-call-complete",
|
|
304
|
+
toolCall: chunk.toolCall
|
|
305
|
+
};
|
|
306
|
+
break;
|
|
307
|
+
case "finish":
|
|
308
|
+
stepFinishReason = chunk.finishReason;
|
|
309
|
+
finalFinishReason = chunk.finishReason;
|
|
310
|
+
if (chunk.usage) {
|
|
311
|
+
finalUsage = {
|
|
312
|
+
promptTokens: finalUsage.promptTokens + chunk.usage.promptTokens,
|
|
313
|
+
completionTokens: finalUsage.completionTokens + chunk.usage.completionTokens,
|
|
314
|
+
totalTokens: finalUsage.totalTokens + chunk.usage.totalTokens
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
case "error":
|
|
319
|
+
yield { type: "error", error: chunk.error };
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
yield {
|
|
325
|
+
type: "error",
|
|
326
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
327
|
+
};
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
yield { type: "step-finish", step, finishReason: stepFinishReason };
|
|
331
|
+
if (toolCalls.length === 0 || !tools) {
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
const assistantMessage = {
|
|
335
|
+
role: "assistant",
|
|
336
|
+
content: stepText || null,
|
|
337
|
+
toolCalls
|
|
338
|
+
};
|
|
339
|
+
messages = [...messages, assistantMessage];
|
|
340
|
+
for (const call of toolCalls) {
|
|
341
|
+
const toolDef = tools[call.name];
|
|
342
|
+
if (!toolDef) {
|
|
343
|
+
const errorResult = { error: `Tool not found: ${call.name}` };
|
|
344
|
+
yield {
|
|
345
|
+
type: "tool-result",
|
|
346
|
+
toolCallId: call.id,
|
|
347
|
+
result: errorResult
|
|
348
|
+
};
|
|
349
|
+
messages = [
|
|
350
|
+
...messages,
|
|
351
|
+
{
|
|
352
|
+
role: "tool",
|
|
353
|
+
toolCallId: call.id,
|
|
354
|
+
content: JSON.stringify(errorResult)
|
|
355
|
+
}
|
|
356
|
+
];
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const parsedArgs = toolDef.parameters.parse(call.args);
|
|
361
|
+
const result = await toolDef.execute(parsedArgs, {
|
|
362
|
+
toolCallId: call.id,
|
|
363
|
+
abortSignal: signal,
|
|
364
|
+
messages
|
|
365
|
+
});
|
|
366
|
+
yield { type: "tool-result", toolCallId: call.id, result };
|
|
367
|
+
messages = [
|
|
368
|
+
...messages,
|
|
369
|
+
{
|
|
370
|
+
role: "tool",
|
|
371
|
+
toolCallId: call.id,
|
|
372
|
+
content: JSON.stringify(result)
|
|
373
|
+
}
|
|
374
|
+
];
|
|
375
|
+
} catch (error) {
|
|
376
|
+
const errorResult = {
|
|
377
|
+
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
378
|
+
};
|
|
379
|
+
yield {
|
|
380
|
+
type: "tool-result",
|
|
381
|
+
toolCallId: call.id,
|
|
382
|
+
result: errorResult
|
|
383
|
+
};
|
|
384
|
+
messages = [
|
|
385
|
+
...messages,
|
|
386
|
+
{
|
|
387
|
+
role: "tool",
|
|
388
|
+
toolCallId: call.id,
|
|
389
|
+
content: JSON.stringify(errorResult)
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
yield {
|
|
396
|
+
type: "finish",
|
|
397
|
+
finishReason: finalFinishReason,
|
|
398
|
+
usage: finalUsage
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
async function* createTextStream() {
|
|
402
|
+
for await (const part of createFullStream()) {
|
|
403
|
+
if (part.type === "text-delta") {
|
|
404
|
+
yield part.text;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
let textPromise;
|
|
409
|
+
let usagePromise;
|
|
410
|
+
let finishReasonPromise;
|
|
411
|
+
async function consumeStream() {
|
|
412
|
+
for await (const _ of createFullStream()) {
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
textStream: createTextStream(),
|
|
417
|
+
fullStream: createFullStream(),
|
|
418
|
+
get text() {
|
|
419
|
+
if (!textPromise) {
|
|
420
|
+
textPromise = consumeStream().then(() => fullText);
|
|
421
|
+
}
|
|
422
|
+
return textPromise;
|
|
423
|
+
},
|
|
424
|
+
get usage() {
|
|
425
|
+
if (!usagePromise) {
|
|
426
|
+
usagePromise = consumeStream().then(() => finalUsage);
|
|
427
|
+
}
|
|
428
|
+
return usagePromise;
|
|
429
|
+
},
|
|
430
|
+
get finishReason() {
|
|
431
|
+
if (!finishReasonPromise) {
|
|
432
|
+
finishReasonPromise = consumeStream().then(() => finalFinishReason);
|
|
433
|
+
}
|
|
434
|
+
return finishReasonPromise;
|
|
435
|
+
},
|
|
436
|
+
toTextStreamResponse(options) {
|
|
437
|
+
const stream = createTextStreamReadable(createTextStream());
|
|
438
|
+
return new Response(stream, {
|
|
439
|
+
status: options?.status ?? 200,
|
|
440
|
+
headers: {
|
|
441
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
442
|
+
"Cache-Control": "no-cache",
|
|
443
|
+
Connection: "keep-alive",
|
|
444
|
+
...options?.headers
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
},
|
|
448
|
+
toDataStreamResponse(options) {
|
|
449
|
+
const stream = createDataStreamReadable(createFullStream());
|
|
450
|
+
return new Response(stream, {
|
|
451
|
+
status: options?.status ?? 200,
|
|
452
|
+
headers: {
|
|
453
|
+
"Content-Type": "text/event-stream",
|
|
454
|
+
"Cache-Control": "no-cache",
|
|
455
|
+
Connection: "keep-alive",
|
|
456
|
+
...options?.headers
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function buildMessages2(params) {
|
|
463
|
+
const messages = [];
|
|
464
|
+
if (params.system) {
|
|
465
|
+
messages.push({ role: "system", content: params.system });
|
|
466
|
+
}
|
|
467
|
+
if (params.messages) {
|
|
468
|
+
messages.push(...params.messages);
|
|
469
|
+
}
|
|
470
|
+
if (params.prompt) {
|
|
471
|
+
messages.push({ role: "user", content: params.prompt });
|
|
472
|
+
}
|
|
473
|
+
return messages;
|
|
474
|
+
}
|
|
475
|
+
function formatToolsForProvider2(tools, provider) {
|
|
476
|
+
switch (provider) {
|
|
477
|
+
case "anthropic":
|
|
478
|
+
return formatToolsForAnthropic(tools);
|
|
479
|
+
case "openai":
|
|
480
|
+
case "xai":
|
|
481
|
+
case "azure":
|
|
482
|
+
default:
|
|
483
|
+
return formatToolsForOpenAI(tools);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function createTextStreamReadable(textStream) {
|
|
487
|
+
const encoder = new TextEncoder();
|
|
488
|
+
return new ReadableStream({
|
|
489
|
+
async start(controller) {
|
|
490
|
+
try {
|
|
491
|
+
for await (const text of textStream) {
|
|
492
|
+
controller.enqueue(encoder.encode(text));
|
|
493
|
+
}
|
|
494
|
+
controller.close();
|
|
495
|
+
} catch (error) {
|
|
496
|
+
controller.error(error);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
function createDataStreamReadable(fullStream) {
|
|
502
|
+
const encoder = new TextEncoder();
|
|
503
|
+
return new ReadableStream({
|
|
504
|
+
async start(controller) {
|
|
505
|
+
try {
|
|
506
|
+
for await (const part of fullStream) {
|
|
507
|
+
const data = JSON.stringify(part);
|
|
508
|
+
controller.enqueue(encoder.encode(`data: ${data}
|
|
509
|
+
|
|
510
|
+
`));
|
|
511
|
+
}
|
|
512
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
513
|
+
controller.close();
|
|
514
|
+
} catch (error) {
|
|
515
|
+
const errorData = JSON.stringify({
|
|
516
|
+
type: "error",
|
|
517
|
+
error: error instanceof Error ? error.message : String(error)
|
|
518
|
+
});
|
|
519
|
+
controller.enqueue(encoder.encode(`data: ${errorData}
|
|
520
|
+
|
|
521
|
+
`));
|
|
522
|
+
controller.close();
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// src/core/types.ts
|
|
529
|
+
var DEFAULT_CAPABILITIES = {
|
|
530
|
+
supportsVision: false,
|
|
531
|
+
supportsTools: true,
|
|
532
|
+
supportsStreaming: true,
|
|
533
|
+
supportsJsonMode: false,
|
|
534
|
+
supportsThinking: false,
|
|
535
|
+
supportsPDF: false,
|
|
536
|
+
maxTokens: 8192,
|
|
537
|
+
supportedImageTypes: []
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/providers/openai/provider.ts
|
|
541
|
+
var OPENAI_MODELS = {
|
|
542
|
+
// GPT-4o series
|
|
543
|
+
"gpt-4o": { vision: true, tools: true, jsonMode: true, maxTokens: 128e3 },
|
|
544
|
+
"gpt-4o-mini": {
|
|
545
|
+
vision: true,
|
|
546
|
+
tools: true,
|
|
547
|
+
jsonMode: true,
|
|
548
|
+
maxTokens: 128e3
|
|
549
|
+
},
|
|
550
|
+
"gpt-4o-2024-11-20": {
|
|
551
|
+
vision: true,
|
|
552
|
+
tools: true,
|
|
553
|
+
jsonMode: true,
|
|
554
|
+
maxTokens: 128e3
|
|
555
|
+
},
|
|
556
|
+
"gpt-4o-2024-08-06": {
|
|
557
|
+
vision: true,
|
|
558
|
+
tools: true,
|
|
559
|
+
jsonMode: true,
|
|
560
|
+
maxTokens: 128e3
|
|
561
|
+
},
|
|
562
|
+
// GPT-4 Turbo
|
|
563
|
+
"gpt-4-turbo": {
|
|
564
|
+
vision: true,
|
|
565
|
+
tools: true,
|
|
566
|
+
jsonMode: true,
|
|
567
|
+
maxTokens: 128e3
|
|
568
|
+
},
|
|
569
|
+
"gpt-4-turbo-preview": {
|
|
570
|
+
vision: false,
|
|
571
|
+
tools: true,
|
|
572
|
+
jsonMode: true,
|
|
573
|
+
maxTokens: 128e3
|
|
574
|
+
},
|
|
575
|
+
// GPT-4
|
|
576
|
+
"gpt-4": { vision: false, tools: true, jsonMode: false, maxTokens: 8192 },
|
|
577
|
+
"gpt-4-32k": {
|
|
578
|
+
vision: false,
|
|
579
|
+
tools: true,
|
|
580
|
+
jsonMode: false,
|
|
581
|
+
maxTokens: 32768
|
|
582
|
+
},
|
|
583
|
+
// GPT-3.5
|
|
584
|
+
"gpt-3.5-turbo": {
|
|
585
|
+
vision: false,
|
|
586
|
+
tools: true,
|
|
587
|
+
jsonMode: true,
|
|
588
|
+
maxTokens: 16385
|
|
589
|
+
},
|
|
590
|
+
// O1 series (reasoning)
|
|
591
|
+
o1: { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
592
|
+
"o1-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
593
|
+
"o1-preview": {
|
|
594
|
+
vision: true,
|
|
595
|
+
tools: false,
|
|
596
|
+
jsonMode: false,
|
|
597
|
+
maxTokens: 128e3
|
|
598
|
+
},
|
|
599
|
+
// O3 series
|
|
600
|
+
"o3-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 }
|
|
601
|
+
};
|
|
602
|
+
function openai(modelId, options = {}) {
|
|
603
|
+
const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
|
|
604
|
+
const baseURL = options.baseURL ?? "https://api.openai.com/v1";
|
|
605
|
+
let client = null;
|
|
606
|
+
async function getClient() {
|
|
607
|
+
if (!client) {
|
|
608
|
+
const { default: OpenAI } = await import('openai');
|
|
609
|
+
client = new OpenAI({
|
|
610
|
+
apiKey,
|
|
611
|
+
baseURL,
|
|
612
|
+
organization: options.organization,
|
|
613
|
+
defaultHeaders: options.headers
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
return client;
|
|
617
|
+
}
|
|
618
|
+
const modelConfig = OPENAI_MODELS[modelId] ?? OPENAI_MODELS["gpt-4o"];
|
|
619
|
+
return {
|
|
620
|
+
provider: "openai",
|
|
621
|
+
modelId,
|
|
622
|
+
capabilities: {
|
|
623
|
+
supportsVision: modelConfig.vision,
|
|
624
|
+
supportsTools: modelConfig.tools,
|
|
625
|
+
supportsStreaming: true,
|
|
626
|
+
supportsJsonMode: modelConfig.jsonMode,
|
|
627
|
+
supportsThinking: false,
|
|
628
|
+
supportsPDF: false,
|
|
629
|
+
maxTokens: modelConfig.maxTokens,
|
|
630
|
+
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
631
|
+
},
|
|
632
|
+
async doGenerate(params) {
|
|
633
|
+
const client2 = await getClient();
|
|
634
|
+
const messages = formatMessagesForOpenAI(params.messages);
|
|
635
|
+
const response = await client2.chat.completions.create({
|
|
636
|
+
model: modelId,
|
|
637
|
+
messages,
|
|
638
|
+
tools: params.tools,
|
|
639
|
+
temperature: params.temperature,
|
|
640
|
+
max_tokens: params.maxTokens
|
|
641
|
+
});
|
|
642
|
+
const choice = response.choices[0];
|
|
643
|
+
const message = choice.message;
|
|
644
|
+
const toolCalls = (message.tool_calls ?? []).map(
|
|
645
|
+
(tc) => ({
|
|
646
|
+
id: tc.id,
|
|
647
|
+
name: tc.function.name,
|
|
648
|
+
args: JSON.parse(tc.function.arguments || "{}")
|
|
649
|
+
})
|
|
650
|
+
);
|
|
651
|
+
return {
|
|
652
|
+
text: message.content ?? "",
|
|
653
|
+
toolCalls,
|
|
654
|
+
finishReason: mapFinishReason(choice.finish_reason),
|
|
655
|
+
usage: {
|
|
656
|
+
promptTokens: response.usage?.prompt_tokens ?? 0,
|
|
657
|
+
completionTokens: response.usage?.completion_tokens ?? 0,
|
|
658
|
+
totalTokens: response.usage?.total_tokens ?? 0
|
|
659
|
+
},
|
|
660
|
+
rawResponse: response
|
|
661
|
+
};
|
|
662
|
+
},
|
|
663
|
+
async *doStream(params) {
|
|
664
|
+
const client2 = await getClient();
|
|
665
|
+
const messages = formatMessagesForOpenAI(params.messages);
|
|
666
|
+
const stream = await client2.chat.completions.create({
|
|
667
|
+
model: modelId,
|
|
668
|
+
messages,
|
|
669
|
+
tools: params.tools,
|
|
670
|
+
temperature: params.temperature,
|
|
671
|
+
max_tokens: params.maxTokens,
|
|
672
|
+
stream: true
|
|
673
|
+
});
|
|
674
|
+
let currentToolCall = null;
|
|
675
|
+
let totalPromptTokens = 0;
|
|
676
|
+
let totalCompletionTokens = 0;
|
|
677
|
+
for await (const chunk of stream) {
|
|
678
|
+
if (params.signal?.aborted) {
|
|
679
|
+
yield { type: "error", error: new Error("Aborted") };
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const choice = chunk.choices[0];
|
|
683
|
+
const delta = choice?.delta;
|
|
684
|
+
if (delta?.content) {
|
|
685
|
+
yield { type: "text-delta", text: delta.content };
|
|
686
|
+
}
|
|
687
|
+
if (delta?.tool_calls) {
|
|
688
|
+
for (const tc of delta.tool_calls) {
|
|
689
|
+
if (tc.id) {
|
|
690
|
+
if (currentToolCall) {
|
|
691
|
+
yield {
|
|
692
|
+
type: "tool-call",
|
|
693
|
+
toolCall: {
|
|
694
|
+
id: currentToolCall.id,
|
|
695
|
+
name: currentToolCall.name,
|
|
696
|
+
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
currentToolCall = {
|
|
701
|
+
id: tc.id,
|
|
702
|
+
name: tc.function?.name ?? "",
|
|
703
|
+
arguments: tc.function?.arguments ?? ""
|
|
704
|
+
};
|
|
705
|
+
} else if (currentToolCall && tc.function?.arguments) {
|
|
706
|
+
currentToolCall.arguments += tc.function.arguments;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (choice?.finish_reason) {
|
|
711
|
+
if (currentToolCall) {
|
|
712
|
+
yield {
|
|
713
|
+
type: "tool-call",
|
|
714
|
+
toolCall: {
|
|
715
|
+
id: currentToolCall.id,
|
|
716
|
+
name: currentToolCall.name,
|
|
717
|
+
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
currentToolCall = null;
|
|
721
|
+
}
|
|
722
|
+
if (chunk.usage) {
|
|
723
|
+
totalPromptTokens = chunk.usage.prompt_tokens;
|
|
724
|
+
totalCompletionTokens = chunk.usage.completion_tokens;
|
|
725
|
+
}
|
|
726
|
+
yield {
|
|
727
|
+
type: "finish",
|
|
728
|
+
finishReason: mapFinishReason(choice.finish_reason),
|
|
729
|
+
usage: {
|
|
730
|
+
promptTokens: totalPromptTokens,
|
|
731
|
+
completionTokens: totalCompletionTokens,
|
|
732
|
+
totalTokens: totalPromptTokens + totalCompletionTokens
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function mapFinishReason(reason) {
|
|
741
|
+
switch (reason) {
|
|
742
|
+
case "stop":
|
|
743
|
+
return "stop";
|
|
744
|
+
case "length":
|
|
745
|
+
return "length";
|
|
746
|
+
case "tool_calls":
|
|
747
|
+
case "function_call":
|
|
748
|
+
return "tool-calls";
|
|
749
|
+
case "content_filter":
|
|
750
|
+
return "content-filter";
|
|
751
|
+
default:
|
|
752
|
+
return "unknown";
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function formatMessagesForOpenAI(messages) {
|
|
756
|
+
return messages.map((msg) => {
|
|
757
|
+
switch (msg.role) {
|
|
758
|
+
case "system":
|
|
759
|
+
return { role: "system", content: msg.content };
|
|
760
|
+
case "user":
|
|
761
|
+
if (typeof msg.content === "string") {
|
|
762
|
+
return { role: "user", content: msg.content };
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
role: "user",
|
|
766
|
+
content: msg.content.map((part) => {
|
|
767
|
+
if (part.type === "text") {
|
|
768
|
+
return { type: "text", text: part.text };
|
|
769
|
+
}
|
|
770
|
+
if (part.type === "image") {
|
|
771
|
+
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
772
|
+
const url = imageData.startsWith("data:") ? imageData : `data:${part.mimeType ?? "image/png"};base64,${imageData}`;
|
|
773
|
+
return { type: "image_url", image_url: { url, detail: "auto" } };
|
|
774
|
+
}
|
|
775
|
+
return { type: "text", text: "" };
|
|
776
|
+
})
|
|
777
|
+
};
|
|
778
|
+
case "assistant":
|
|
779
|
+
const assistantMsg = {
|
|
780
|
+
role: "assistant",
|
|
781
|
+
content: msg.content
|
|
782
|
+
};
|
|
783
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
784
|
+
assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({
|
|
785
|
+
id: tc.id,
|
|
786
|
+
type: "function",
|
|
787
|
+
function: {
|
|
788
|
+
name: tc.name,
|
|
789
|
+
arguments: JSON.stringify(tc.args)
|
|
790
|
+
}
|
|
791
|
+
}));
|
|
792
|
+
}
|
|
793
|
+
return assistantMsg;
|
|
794
|
+
case "tool":
|
|
795
|
+
return {
|
|
796
|
+
role: "tool",
|
|
797
|
+
tool_call_id: msg.toolCallId,
|
|
798
|
+
content: msg.content
|
|
799
|
+
};
|
|
800
|
+
default:
|
|
801
|
+
return msg;
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// src/providers/anthropic/provider.ts
|
|
807
|
+
var ANTHROPIC_MODELS = {
|
|
808
|
+
// Claude 4 series
|
|
809
|
+
"claude-sonnet-4-20250514": {
|
|
810
|
+
vision: true,
|
|
811
|
+
tools: true,
|
|
812
|
+
thinking: true,
|
|
813
|
+
pdf: true,
|
|
814
|
+
maxTokens: 2e5
|
|
815
|
+
},
|
|
816
|
+
"claude-opus-4-20250514": {
|
|
817
|
+
vision: true,
|
|
818
|
+
tools: true,
|
|
819
|
+
thinking: true,
|
|
820
|
+
pdf: true,
|
|
821
|
+
maxTokens: 2e5
|
|
822
|
+
},
|
|
823
|
+
// Claude 3.7 series
|
|
824
|
+
"claude-3-7-sonnet-20250219": {
|
|
825
|
+
vision: true,
|
|
826
|
+
tools: true,
|
|
827
|
+
thinking: true,
|
|
828
|
+
pdf: true,
|
|
829
|
+
maxTokens: 2e5
|
|
830
|
+
},
|
|
831
|
+
"claude-3-7-sonnet-latest": {
|
|
832
|
+
vision: true,
|
|
833
|
+
tools: true,
|
|
834
|
+
thinking: true,
|
|
835
|
+
pdf: true,
|
|
836
|
+
maxTokens: 2e5
|
|
837
|
+
},
|
|
838
|
+
// Claude 3.5 series
|
|
839
|
+
"claude-3-5-sonnet-20241022": {
|
|
840
|
+
vision: true,
|
|
841
|
+
tools: true,
|
|
842
|
+
thinking: false,
|
|
843
|
+
pdf: true,
|
|
844
|
+
maxTokens: 2e5
|
|
845
|
+
},
|
|
846
|
+
"claude-3-5-sonnet-latest": {
|
|
847
|
+
vision: true,
|
|
848
|
+
tools: true,
|
|
849
|
+
thinking: false,
|
|
850
|
+
pdf: true,
|
|
851
|
+
maxTokens: 2e5
|
|
852
|
+
},
|
|
853
|
+
"claude-3-5-haiku-20241022": {
|
|
854
|
+
vision: true,
|
|
855
|
+
tools: true,
|
|
856
|
+
thinking: false,
|
|
857
|
+
pdf: false,
|
|
858
|
+
maxTokens: 2e5
|
|
859
|
+
},
|
|
860
|
+
"claude-3-5-haiku-latest": {
|
|
861
|
+
vision: true,
|
|
862
|
+
tools: true,
|
|
863
|
+
thinking: false,
|
|
864
|
+
pdf: false,
|
|
865
|
+
maxTokens: 2e5
|
|
866
|
+
},
|
|
867
|
+
// Claude 3 series
|
|
868
|
+
"claude-3-opus-20240229": {
|
|
869
|
+
vision: true,
|
|
870
|
+
tools: true,
|
|
871
|
+
thinking: false,
|
|
872
|
+
pdf: false,
|
|
873
|
+
maxTokens: 2e5
|
|
874
|
+
},
|
|
875
|
+
"claude-3-sonnet-20240229": {
|
|
876
|
+
vision: true,
|
|
877
|
+
tools: true,
|
|
878
|
+
thinking: false,
|
|
879
|
+
pdf: false,
|
|
880
|
+
maxTokens: 2e5
|
|
881
|
+
},
|
|
882
|
+
"claude-3-haiku-20240307": {
|
|
883
|
+
vision: true,
|
|
884
|
+
tools: true,
|
|
885
|
+
thinking: false,
|
|
886
|
+
pdf: false,
|
|
887
|
+
maxTokens: 2e5
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
function anthropic(modelId, options = {}) {
|
|
891
|
+
const apiKey = options.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
892
|
+
let client = null;
|
|
893
|
+
async function getClient() {
|
|
894
|
+
if (!client) {
|
|
895
|
+
const { default: Anthropic } = await import('@anthropic-ai/sdk');
|
|
896
|
+
client = new Anthropic({
|
|
897
|
+
apiKey,
|
|
898
|
+
baseURL: options.baseURL
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
return client;
|
|
902
|
+
}
|
|
903
|
+
const modelConfig = ANTHROPIC_MODELS[modelId] ?? ANTHROPIC_MODELS["claude-3-5-sonnet-latest"];
|
|
904
|
+
return {
|
|
905
|
+
provider: "anthropic",
|
|
906
|
+
modelId,
|
|
907
|
+
capabilities: {
|
|
908
|
+
supportsVision: modelConfig.vision,
|
|
909
|
+
supportsTools: modelConfig.tools,
|
|
910
|
+
supportsStreaming: true,
|
|
911
|
+
supportsJsonMode: false,
|
|
912
|
+
supportsThinking: modelConfig.thinking,
|
|
913
|
+
supportsPDF: modelConfig.pdf,
|
|
914
|
+
maxTokens: modelConfig.maxTokens,
|
|
915
|
+
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
916
|
+
},
|
|
917
|
+
async doGenerate(params) {
|
|
918
|
+
const client2 = await getClient();
|
|
919
|
+
const { system, messages } = formatMessagesForAnthropic(params.messages);
|
|
920
|
+
const requestOptions = {
|
|
921
|
+
model: modelId,
|
|
922
|
+
max_tokens: params.maxTokens ?? 4096,
|
|
923
|
+
system: system || void 0,
|
|
924
|
+
messages,
|
|
925
|
+
tools: params.tools
|
|
926
|
+
};
|
|
927
|
+
if (params.temperature !== void 0) {
|
|
928
|
+
requestOptions.temperature = params.temperature;
|
|
929
|
+
}
|
|
930
|
+
if (options.thinking?.enabled && modelConfig.thinking) {
|
|
931
|
+
requestOptions.thinking = {
|
|
932
|
+
type: "enabled",
|
|
933
|
+
budget_tokens: options.thinking.budgetTokens ?? 1e4
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
const response = await client2.messages.create(requestOptions);
|
|
937
|
+
let text = "";
|
|
938
|
+
const toolCalls = [];
|
|
939
|
+
for (const block of response.content) {
|
|
940
|
+
if (block.type === "text") {
|
|
941
|
+
text += block.text;
|
|
942
|
+
} else if (block.type === "tool_use") {
|
|
943
|
+
toolCalls.push({
|
|
944
|
+
id: block.id,
|
|
945
|
+
name: block.name,
|
|
946
|
+
args: block.input
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return {
|
|
951
|
+
text,
|
|
952
|
+
toolCalls,
|
|
953
|
+
finishReason: mapFinishReason2(response.stop_reason),
|
|
954
|
+
usage: {
|
|
955
|
+
promptTokens: response.usage?.input_tokens ?? 0,
|
|
956
|
+
completionTokens: response.usage?.output_tokens ?? 0,
|
|
957
|
+
totalTokens: (response.usage?.input_tokens ?? 0) + (response.usage?.output_tokens ?? 0)
|
|
958
|
+
},
|
|
959
|
+
rawResponse: response
|
|
960
|
+
};
|
|
961
|
+
},
|
|
962
|
+
async *doStream(params) {
|
|
963
|
+
const client2 = await getClient();
|
|
964
|
+
const { system, messages } = formatMessagesForAnthropic(params.messages);
|
|
965
|
+
const requestOptions = {
|
|
966
|
+
model: modelId,
|
|
967
|
+
max_tokens: params.maxTokens ?? 4096,
|
|
968
|
+
system: system || void 0,
|
|
969
|
+
messages,
|
|
970
|
+
tools: params.tools
|
|
971
|
+
};
|
|
972
|
+
if (params.temperature !== void 0) {
|
|
973
|
+
requestOptions.temperature = params.temperature;
|
|
974
|
+
}
|
|
975
|
+
if (options.thinking?.enabled && modelConfig.thinking) {
|
|
976
|
+
requestOptions.thinking = {
|
|
977
|
+
type: "enabled",
|
|
978
|
+
budget_tokens: options.thinking.budgetTokens ?? 1e4
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
const stream = await client2.messages.stream(requestOptions);
|
|
982
|
+
let currentToolUse = null;
|
|
983
|
+
let inputTokens = 0;
|
|
984
|
+
let outputTokens = 0;
|
|
985
|
+
for await (const event of stream) {
|
|
986
|
+
if (params.signal?.aborted) {
|
|
987
|
+
yield { type: "error", error: new Error("Aborted") };
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
switch (event.type) {
|
|
991
|
+
case "message_start":
|
|
992
|
+
if (event.message?.usage) {
|
|
993
|
+
inputTokens = event.message.usage.input_tokens ?? 0;
|
|
994
|
+
}
|
|
995
|
+
break;
|
|
996
|
+
case "content_block_start":
|
|
997
|
+
if (event.content_block?.type === "tool_use") {
|
|
998
|
+
currentToolUse = {
|
|
999
|
+
id: event.content_block.id,
|
|
1000
|
+
name: event.content_block.name,
|
|
1001
|
+
input: ""
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
break;
|
|
1005
|
+
case "content_block_delta":
|
|
1006
|
+
if (event.delta?.type === "text_delta") {
|
|
1007
|
+
yield { type: "text-delta", text: event.delta.text };
|
|
1008
|
+
} else if (event.delta?.type === "input_json_delta" && currentToolUse) {
|
|
1009
|
+
currentToolUse.input += event.delta.partial_json;
|
|
1010
|
+
}
|
|
1011
|
+
break;
|
|
1012
|
+
case "content_block_stop":
|
|
1013
|
+
if (currentToolUse) {
|
|
1014
|
+
yield {
|
|
1015
|
+
type: "tool-call",
|
|
1016
|
+
toolCall: {
|
|
1017
|
+
id: currentToolUse.id,
|
|
1018
|
+
name: currentToolUse.name,
|
|
1019
|
+
args: JSON.parse(currentToolUse.input || "{}")
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
currentToolUse = null;
|
|
1023
|
+
}
|
|
1024
|
+
break;
|
|
1025
|
+
case "message_delta":
|
|
1026
|
+
if (event.usage) {
|
|
1027
|
+
outputTokens = event.usage.output_tokens ?? 0;
|
|
1028
|
+
}
|
|
1029
|
+
if (event.delta?.stop_reason) {
|
|
1030
|
+
yield {
|
|
1031
|
+
type: "finish",
|
|
1032
|
+
finishReason: mapFinishReason2(event.delta.stop_reason),
|
|
1033
|
+
usage: {
|
|
1034
|
+
promptTokens: inputTokens,
|
|
1035
|
+
completionTokens: outputTokens,
|
|
1036
|
+
totalTokens: inputTokens + outputTokens
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
function mapFinishReason2(reason) {
|
|
1047
|
+
switch (reason) {
|
|
1048
|
+
case "end_turn":
|
|
1049
|
+
case "stop_sequence":
|
|
1050
|
+
return "stop";
|
|
1051
|
+
case "max_tokens":
|
|
1052
|
+
return "length";
|
|
1053
|
+
case "tool_use":
|
|
1054
|
+
return "tool-calls";
|
|
1055
|
+
default:
|
|
1056
|
+
return "unknown";
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
function formatMessagesForAnthropic(messages) {
|
|
1060
|
+
let system = "";
|
|
1061
|
+
const formatted = [];
|
|
1062
|
+
const pendingToolResults = [];
|
|
1063
|
+
for (const msg of messages) {
|
|
1064
|
+
if (msg.role === "system") {
|
|
1065
|
+
system += (system ? "\n" : "") + msg.content;
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (msg.role === "assistant" && pendingToolResults.length > 0) {
|
|
1069
|
+
formatted.push({
|
|
1070
|
+
role: "user",
|
|
1071
|
+
content: pendingToolResults.map((tr) => ({
|
|
1072
|
+
type: "tool_result",
|
|
1073
|
+
tool_use_id: tr.toolCallId,
|
|
1074
|
+
content: tr.content
|
|
1075
|
+
}))
|
|
1076
|
+
});
|
|
1077
|
+
pendingToolResults.length = 0;
|
|
1078
|
+
}
|
|
1079
|
+
if (msg.role === "user") {
|
|
1080
|
+
if (pendingToolResults.length > 0) {
|
|
1081
|
+
formatted.push({
|
|
1082
|
+
role: "user",
|
|
1083
|
+
content: pendingToolResults.map((tr) => ({
|
|
1084
|
+
type: "tool_result",
|
|
1085
|
+
tool_use_id: tr.toolCallId,
|
|
1086
|
+
content: tr.content
|
|
1087
|
+
}))
|
|
1088
|
+
});
|
|
1089
|
+
pendingToolResults.length = 0;
|
|
1090
|
+
}
|
|
1091
|
+
if (typeof msg.content === "string") {
|
|
1092
|
+
formatted.push({ role: "user", content: msg.content });
|
|
1093
|
+
} else {
|
|
1094
|
+
const content = [];
|
|
1095
|
+
for (const part of msg.content) {
|
|
1096
|
+
if (part.type === "text") {
|
|
1097
|
+
content.push({ type: "text", text: part.text });
|
|
1098
|
+
} else if (part.type === "image") {
|
|
1099
|
+
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
1100
|
+
if (imageData.startsWith("http")) {
|
|
1101
|
+
content.push({
|
|
1102
|
+
type: "image",
|
|
1103
|
+
source: { type: "url", url: imageData }
|
|
1104
|
+
});
|
|
1105
|
+
} else {
|
|
1106
|
+
const base64 = imageData.startsWith("data:") ? imageData.split(",")[1] : imageData;
|
|
1107
|
+
content.push({
|
|
1108
|
+
type: "image",
|
|
1109
|
+
source: {
|
|
1110
|
+
type: "base64",
|
|
1111
|
+
media_type: part.mimeType ?? "image/png",
|
|
1112
|
+
data: base64
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
formatted.push({ role: "user", content });
|
|
1119
|
+
}
|
|
1120
|
+
} else if (msg.role === "assistant") {
|
|
1121
|
+
const content = [];
|
|
1122
|
+
if (msg.content) {
|
|
1123
|
+
content.push({ type: "text", text: msg.content });
|
|
1124
|
+
}
|
|
1125
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
1126
|
+
for (const tc of msg.toolCalls) {
|
|
1127
|
+
content.push({
|
|
1128
|
+
type: "tool_use",
|
|
1129
|
+
id: tc.id,
|
|
1130
|
+
name: tc.name,
|
|
1131
|
+
input: tc.args
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
if (content.length > 0) {
|
|
1136
|
+
formatted.push({ role: "assistant", content });
|
|
1137
|
+
}
|
|
1138
|
+
} else if (msg.role === "tool") {
|
|
1139
|
+
pendingToolResults.push({
|
|
1140
|
+
toolCallId: msg.toolCallId,
|
|
1141
|
+
content: msg.content
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
if (pendingToolResults.length > 0) {
|
|
1146
|
+
formatted.push({
|
|
1147
|
+
role: "user",
|
|
1148
|
+
content: pendingToolResults.map((tr) => ({
|
|
1149
|
+
type: "tool_result",
|
|
1150
|
+
tool_use_id: tr.toolCallId,
|
|
1151
|
+
content: tr.content
|
|
1152
|
+
}))
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
return { system, messages: formatted };
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// src/providers/xai/provider.ts
|
|
1159
|
+
var XAI_MODELS = {
|
|
1160
|
+
// Grok 4.1 Fast (Latest - December 2025)
|
|
1161
|
+
"grok-4-1-fast-reasoning": { vision: false, tools: true, maxTokens: 2e6 },
|
|
1162
|
+
"grok-4-1-fast-non-reasoning": {
|
|
1163
|
+
vision: false,
|
|
1164
|
+
tools: true,
|
|
1165
|
+
maxTokens: 2e6
|
|
1166
|
+
},
|
|
1167
|
+
// Grok 4 Fast (September 2025)
|
|
1168
|
+
"grok-4-fast-reasoning": { vision: false, tools: true, maxTokens: 2e6 },
|
|
1169
|
+
"grok-4-fast-non-reasoning": {
|
|
1170
|
+
vision: false,
|
|
1171
|
+
tools: true,
|
|
1172
|
+
maxTokens: 2e6
|
|
1173
|
+
},
|
|
1174
|
+
// Grok 4 (July 2025)
|
|
1175
|
+
"grok-4": { vision: true, tools: true, maxTokens: 256e3 },
|
|
1176
|
+
"grok-4-0709": { vision: true, tools: true, maxTokens: 256e3 },
|
|
1177
|
+
// Grok 3 (February 2025) - Stable
|
|
1178
|
+
"grok-3-beta": { vision: true, tools: true, maxTokens: 131072 },
|
|
1179
|
+
"grok-3-fast-beta": { vision: false, tools: true, maxTokens: 131072 },
|
|
1180
|
+
"grok-3-mini-beta": { vision: false, tools: true, maxTokens: 32768 },
|
|
1181
|
+
"grok-3-mini-fast-beta": { vision: false, tools: true, maxTokens: 32768 },
|
|
1182
|
+
// Grok Code Fast (August 2025)
|
|
1183
|
+
"grok-code-fast-1": { vision: false, tools: true, maxTokens: 256e3 },
|
|
1184
|
+
// Grok 2 (Legacy)
|
|
1185
|
+
"grok-2": { vision: true, tools: true, maxTokens: 131072 },
|
|
1186
|
+
"grok-2-latest": { vision: true, tools: true, maxTokens: 131072 },
|
|
1187
|
+
"grok-2-mini": { vision: false, tools: true, maxTokens: 131072 }
|
|
1188
|
+
};
|
|
1189
|
+
function xai(modelId, options = {}) {
|
|
1190
|
+
const apiKey = options.apiKey ?? process.env.XAI_API_KEY;
|
|
1191
|
+
const baseURL = options.baseURL ?? "https://api.x.ai/v1";
|
|
1192
|
+
let client = null;
|
|
1193
|
+
async function getClient() {
|
|
1194
|
+
if (!client) {
|
|
1195
|
+
const { default: OpenAI } = await import('openai');
|
|
1196
|
+
client = new OpenAI({
|
|
1197
|
+
apiKey,
|
|
1198
|
+
baseURL
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
return client;
|
|
1202
|
+
}
|
|
1203
|
+
const modelConfig = XAI_MODELS[modelId] ?? XAI_MODELS["grok-3-fast-beta"];
|
|
1204
|
+
return {
|
|
1205
|
+
provider: "xai",
|
|
1206
|
+
modelId,
|
|
1207
|
+
capabilities: {
|
|
1208
|
+
supportsVision: modelConfig.vision,
|
|
1209
|
+
supportsTools: modelConfig.tools,
|
|
1210
|
+
supportsStreaming: true,
|
|
1211
|
+
supportsJsonMode: false,
|
|
1212
|
+
// xAI doesn't support JSON mode yet
|
|
1213
|
+
supportsThinking: false,
|
|
1214
|
+
supportsPDF: false,
|
|
1215
|
+
maxTokens: modelConfig.maxTokens,
|
|
1216
|
+
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
1217
|
+
},
|
|
1218
|
+
async doGenerate(params) {
|
|
1219
|
+
const client2 = await getClient();
|
|
1220
|
+
const messages = formatMessagesForXAI(params.messages);
|
|
1221
|
+
const response = await client2.chat.completions.create({
|
|
1222
|
+
model: modelId,
|
|
1223
|
+
messages,
|
|
1224
|
+
tools: params.tools,
|
|
1225
|
+
temperature: params.temperature,
|
|
1226
|
+
max_tokens: params.maxTokens
|
|
1227
|
+
});
|
|
1228
|
+
const choice = response.choices[0];
|
|
1229
|
+
const message = choice.message;
|
|
1230
|
+
const toolCalls = (message.tool_calls ?? []).map(
|
|
1231
|
+
(tc) => ({
|
|
1232
|
+
id: tc.id,
|
|
1233
|
+
name: tc.function.name,
|
|
1234
|
+
args: JSON.parse(tc.function.arguments || "{}")
|
|
1235
|
+
})
|
|
1236
|
+
);
|
|
1237
|
+
return {
|
|
1238
|
+
text: message.content ?? "",
|
|
1239
|
+
toolCalls,
|
|
1240
|
+
finishReason: mapFinishReason3(choice.finish_reason),
|
|
1241
|
+
usage: {
|
|
1242
|
+
promptTokens: response.usage?.prompt_tokens ?? 0,
|
|
1243
|
+
completionTokens: response.usage?.completion_tokens ?? 0,
|
|
1244
|
+
totalTokens: response.usage?.total_tokens ?? 0
|
|
1245
|
+
},
|
|
1246
|
+
rawResponse: response
|
|
1247
|
+
};
|
|
1248
|
+
},
|
|
1249
|
+
async *doStream(params) {
|
|
1250
|
+
const client2 = await getClient();
|
|
1251
|
+
const messages = formatMessagesForXAI(params.messages);
|
|
1252
|
+
const stream = await client2.chat.completions.create({
|
|
1253
|
+
model: modelId,
|
|
1254
|
+
messages,
|
|
1255
|
+
tools: params.tools,
|
|
1256
|
+
temperature: params.temperature,
|
|
1257
|
+
max_tokens: params.maxTokens,
|
|
1258
|
+
stream: true
|
|
1259
|
+
});
|
|
1260
|
+
let currentToolCall = null;
|
|
1261
|
+
let totalPromptTokens = 0;
|
|
1262
|
+
let totalCompletionTokens = 0;
|
|
1263
|
+
for await (const chunk of stream) {
|
|
1264
|
+
if (params.signal?.aborted) {
|
|
1265
|
+
yield { type: "error", error: new Error("Aborted") };
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
const choice = chunk.choices[0];
|
|
1269
|
+
const delta = choice?.delta;
|
|
1270
|
+
if (delta?.content) {
|
|
1271
|
+
yield { type: "text-delta", text: delta.content };
|
|
1272
|
+
}
|
|
1273
|
+
if (delta?.tool_calls) {
|
|
1274
|
+
for (const tc of delta.tool_calls) {
|
|
1275
|
+
if (tc.id) {
|
|
1276
|
+
if (currentToolCall) {
|
|
1277
|
+
yield {
|
|
1278
|
+
type: "tool-call",
|
|
1279
|
+
toolCall: {
|
|
1280
|
+
id: currentToolCall.id,
|
|
1281
|
+
name: currentToolCall.name,
|
|
1282
|
+
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
currentToolCall = {
|
|
1287
|
+
id: tc.id,
|
|
1288
|
+
name: tc.function?.name ?? "",
|
|
1289
|
+
arguments: tc.function?.arguments ?? ""
|
|
1290
|
+
};
|
|
1291
|
+
} else if (currentToolCall && tc.function?.arguments) {
|
|
1292
|
+
currentToolCall.arguments += tc.function.arguments;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
if (choice?.finish_reason) {
|
|
1297
|
+
if (currentToolCall) {
|
|
1298
|
+
yield {
|
|
1299
|
+
type: "tool-call",
|
|
1300
|
+
toolCall: {
|
|
1301
|
+
id: currentToolCall.id,
|
|
1302
|
+
name: currentToolCall.name,
|
|
1303
|
+
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
currentToolCall = null;
|
|
1307
|
+
}
|
|
1308
|
+
if (chunk.usage) {
|
|
1309
|
+
totalPromptTokens = chunk.usage.prompt_tokens;
|
|
1310
|
+
totalCompletionTokens = chunk.usage.completion_tokens;
|
|
1311
|
+
}
|
|
1312
|
+
yield {
|
|
1313
|
+
type: "finish",
|
|
1314
|
+
finishReason: mapFinishReason3(choice.finish_reason),
|
|
1315
|
+
usage: {
|
|
1316
|
+
promptTokens: totalPromptTokens,
|
|
1317
|
+
completionTokens: totalCompletionTokens,
|
|
1318
|
+
totalTokens: totalPromptTokens + totalCompletionTokens
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
function mapFinishReason3(reason) {
|
|
1327
|
+
switch (reason) {
|
|
1328
|
+
case "stop":
|
|
1329
|
+
return "stop";
|
|
1330
|
+
case "length":
|
|
1331
|
+
return "length";
|
|
1332
|
+
case "tool_calls":
|
|
1333
|
+
case "function_call":
|
|
1334
|
+
return "tool-calls";
|
|
1335
|
+
case "content_filter":
|
|
1336
|
+
return "content-filter";
|
|
1337
|
+
default:
|
|
1338
|
+
return "unknown";
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
function formatMessagesForXAI(messages) {
|
|
1342
|
+
return messages.map((msg) => {
|
|
1343
|
+
switch (msg.role) {
|
|
1344
|
+
case "system":
|
|
1345
|
+
return { role: "system", content: msg.content };
|
|
1346
|
+
case "user":
|
|
1347
|
+
if (typeof msg.content === "string") {
|
|
1348
|
+
return { role: "user", content: msg.content };
|
|
1349
|
+
}
|
|
1350
|
+
return {
|
|
1351
|
+
role: "user",
|
|
1352
|
+
content: msg.content.map((part) => {
|
|
1353
|
+
if (part.type === "text") {
|
|
1354
|
+
return { type: "text", text: part.text };
|
|
1355
|
+
}
|
|
1356
|
+
if (part.type === "image") {
|
|
1357
|
+
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
1358
|
+
const url = imageData.startsWith("data:") ? imageData : `data:${part.mimeType ?? "image/png"};base64,${imageData}`;
|
|
1359
|
+
return { type: "image_url", image_url: { url, detail: "auto" } };
|
|
1360
|
+
}
|
|
1361
|
+
return { type: "text", text: "" };
|
|
1362
|
+
})
|
|
1363
|
+
};
|
|
1364
|
+
case "assistant":
|
|
1365
|
+
const assistantMsg = {
|
|
1366
|
+
role: "assistant",
|
|
1367
|
+
content: msg.content
|
|
1368
|
+
};
|
|
1369
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
1370
|
+
assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({
|
|
1371
|
+
id: tc.id,
|
|
1372
|
+
type: "function",
|
|
1373
|
+
function: {
|
|
1374
|
+
name: tc.name,
|
|
1375
|
+
arguments: JSON.stringify(tc.args)
|
|
1376
|
+
}
|
|
1377
|
+
}));
|
|
1378
|
+
}
|
|
1379
|
+
return assistantMsg;
|
|
1380
|
+
case "tool":
|
|
1381
|
+
return {
|
|
1382
|
+
role: "tool",
|
|
1383
|
+
tool_call_id: msg.toolCallId,
|
|
1384
|
+
content: msg.content
|
|
1385
|
+
};
|
|
1386
|
+
default:
|
|
1387
|
+
return msg;
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
// src/providers/google/provider.ts
|
|
1393
|
+
var GOOGLE_MODELS = {
|
|
1394
|
+
// Gemini 2.0
|
|
1395
|
+
"gemini-2.0-flash": {
|
|
1396
|
+
vision: true,
|
|
1397
|
+
tools: true,
|
|
1398
|
+
audio: true,
|
|
1399
|
+
video: true,
|
|
1400
|
+
maxTokens: 1048576
|
|
1401
|
+
},
|
|
1402
|
+
"gemini-2.0-flash-exp": {
|
|
1403
|
+
vision: true,
|
|
1404
|
+
tools: true,
|
|
1405
|
+
audio: true,
|
|
1406
|
+
video: true,
|
|
1407
|
+
maxTokens: 1048576
|
|
1408
|
+
},
|
|
1409
|
+
"gemini-2.0-flash-thinking-exp": {
|
|
1410
|
+
vision: true,
|
|
1411
|
+
tools: false,
|
|
1412
|
+
audio: false,
|
|
1413
|
+
video: false,
|
|
1414
|
+
maxTokens: 32767
|
|
1415
|
+
},
|
|
1416
|
+
// Gemini 1.5
|
|
1417
|
+
"gemini-1.5-pro": {
|
|
1418
|
+
vision: true,
|
|
1419
|
+
tools: true,
|
|
1420
|
+
audio: true,
|
|
1421
|
+
video: true,
|
|
1422
|
+
maxTokens: 2097152
|
|
1423
|
+
},
|
|
1424
|
+
"gemini-1.5-pro-latest": {
|
|
1425
|
+
vision: true,
|
|
1426
|
+
tools: true,
|
|
1427
|
+
audio: true,
|
|
1428
|
+
video: true,
|
|
1429
|
+
maxTokens: 2097152
|
|
1430
|
+
},
|
|
1431
|
+
"gemini-1.5-flash": {
|
|
1432
|
+
vision: true,
|
|
1433
|
+
tools: true,
|
|
1434
|
+
audio: true,
|
|
1435
|
+
video: true,
|
|
1436
|
+
maxTokens: 1048576
|
|
1437
|
+
},
|
|
1438
|
+
"gemini-1.5-flash-latest": {
|
|
1439
|
+
vision: true,
|
|
1440
|
+
tools: true,
|
|
1441
|
+
audio: true,
|
|
1442
|
+
video: true,
|
|
1443
|
+
maxTokens: 1048576
|
|
1444
|
+
},
|
|
1445
|
+
"gemini-1.5-flash-8b": {
|
|
1446
|
+
vision: true,
|
|
1447
|
+
tools: true,
|
|
1448
|
+
audio: false,
|
|
1449
|
+
video: false,
|
|
1450
|
+
maxTokens: 1048576
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
function google(modelId, options = {}) {
|
|
1454
|
+
const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
|
|
1455
|
+
let client = null;
|
|
1456
|
+
async function getClient() {
|
|
1457
|
+
if (!client) {
|
|
1458
|
+
const { GoogleGenerativeAI } = await import('@google/generative-ai');
|
|
1459
|
+
client = new GoogleGenerativeAI(apiKey);
|
|
1460
|
+
}
|
|
1461
|
+
return client;
|
|
1462
|
+
}
|
|
1463
|
+
const modelConfig = GOOGLE_MODELS[modelId] ?? GOOGLE_MODELS["gemini-2.0-flash"];
|
|
1464
|
+
return {
|
|
1465
|
+
provider: "google",
|
|
1466
|
+
modelId,
|
|
1467
|
+
capabilities: {
|
|
1468
|
+
supportsVision: modelConfig.vision,
|
|
1469
|
+
supportsTools: modelConfig.tools,
|
|
1470
|
+
supportsStreaming: true,
|
|
1471
|
+
supportsJsonMode: true,
|
|
1472
|
+
supportsThinking: modelId.includes("thinking"),
|
|
1473
|
+
supportsPDF: true,
|
|
1474
|
+
maxTokens: modelConfig.maxTokens,
|
|
1475
|
+
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
1476
|
+
},
|
|
1477
|
+
async doGenerate(params) {
|
|
1478
|
+
const client2 = await getClient();
|
|
1479
|
+
const model = client2.getGenerativeModel({
|
|
1480
|
+
model: modelId,
|
|
1481
|
+
safetySettings: options.safetySettings
|
|
1482
|
+
});
|
|
1483
|
+
const { systemInstruction, contents } = formatMessagesForGemini(
|
|
1484
|
+
params.messages
|
|
1485
|
+
);
|
|
1486
|
+
const chat = model.startChat({
|
|
1487
|
+
history: contents.slice(0, -1),
|
|
1488
|
+
systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
|
|
1489
|
+
tools: params.tools ? [{ functionDeclarations: formatToolsForGemini(params.tools) }] : void 0,
|
|
1490
|
+
generationConfig: {
|
|
1491
|
+
temperature: params.temperature,
|
|
1492
|
+
maxOutputTokens: params.maxTokens
|
|
1493
|
+
}
|
|
1494
|
+
});
|
|
1495
|
+
const lastMessage = contents[contents.length - 1];
|
|
1496
|
+
const result = await chat.sendMessage(lastMessage.parts);
|
|
1497
|
+
const response = result.response;
|
|
1498
|
+
let text = "";
|
|
1499
|
+
const toolCalls = [];
|
|
1500
|
+
let toolCallIndex = 0;
|
|
1501
|
+
const candidate = response.candidates?.[0];
|
|
1502
|
+
if (candidate?.content?.parts) {
|
|
1503
|
+
for (const part of candidate.content.parts) {
|
|
1504
|
+
if ("text" in part && part.text) {
|
|
1505
|
+
text += part.text;
|
|
1506
|
+
}
|
|
1507
|
+
if ("functionCall" in part && part.functionCall) {
|
|
1508
|
+
toolCalls.push({
|
|
1509
|
+
id: `call_${toolCallIndex++}`,
|
|
1510
|
+
name: part.functionCall.name,
|
|
1511
|
+
args: part.functionCall.args || {}
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return {
|
|
1517
|
+
text,
|
|
1518
|
+
toolCalls,
|
|
1519
|
+
finishReason: mapFinishReason4(candidate?.finishReason),
|
|
1520
|
+
usage: {
|
|
1521
|
+
promptTokens: response.usageMetadata?.promptTokenCount ?? 0,
|
|
1522
|
+
completionTokens: response.usageMetadata?.candidatesTokenCount ?? 0,
|
|
1523
|
+
totalTokens: response.usageMetadata?.totalTokenCount ?? 0
|
|
1524
|
+
},
|
|
1525
|
+
rawResponse: response
|
|
1526
|
+
};
|
|
1527
|
+
},
|
|
1528
|
+
async *doStream(params) {
|
|
1529
|
+
const client2 = await getClient();
|
|
1530
|
+
const model = client2.getGenerativeModel({
|
|
1531
|
+
model: modelId,
|
|
1532
|
+
safetySettings: options.safetySettings
|
|
1533
|
+
});
|
|
1534
|
+
const { systemInstruction, contents } = formatMessagesForGemini(
|
|
1535
|
+
params.messages
|
|
1536
|
+
);
|
|
1537
|
+
const chat = model.startChat({
|
|
1538
|
+
history: contents.slice(0, -1),
|
|
1539
|
+
systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
|
|
1540
|
+
tools: params.tools ? [{ functionDeclarations: formatToolsForGemini(params.tools) }] : void 0,
|
|
1541
|
+
generationConfig: {
|
|
1542
|
+
temperature: params.temperature,
|
|
1543
|
+
maxOutputTokens: params.maxTokens
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
const lastMessage = contents[contents.length - 1];
|
|
1547
|
+
const result = await chat.sendMessageStream(lastMessage.parts);
|
|
1548
|
+
let toolCallIndex = 0;
|
|
1549
|
+
let promptTokens = 0;
|
|
1550
|
+
let completionTokens = 0;
|
|
1551
|
+
try {
|
|
1552
|
+
for await (const chunk of result.stream) {
|
|
1553
|
+
if (params.signal?.aborted) {
|
|
1554
|
+
yield { type: "error", error: new Error("Aborted") };
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const candidate = chunk.candidates?.[0];
|
|
1558
|
+
if (!candidate?.content?.parts) continue;
|
|
1559
|
+
for (const part of candidate.content.parts) {
|
|
1560
|
+
if ("text" in part && part.text) {
|
|
1561
|
+
yield { type: "text-delta", text: part.text };
|
|
1562
|
+
}
|
|
1563
|
+
if ("functionCall" in part && part.functionCall) {
|
|
1564
|
+
yield {
|
|
1565
|
+
type: "tool-call",
|
|
1566
|
+
toolCall: {
|
|
1567
|
+
id: `call_${toolCallIndex++}`,
|
|
1568
|
+
name: part.functionCall.name,
|
|
1569
|
+
args: part.functionCall.args || {}
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (chunk.usageMetadata) {
|
|
1575
|
+
promptTokens = chunk.usageMetadata.promptTokenCount ?? 0;
|
|
1576
|
+
completionTokens = chunk.usageMetadata.candidatesTokenCount ?? 0;
|
|
1577
|
+
}
|
|
1578
|
+
if (candidate.finishReason) {
|
|
1579
|
+
yield {
|
|
1580
|
+
type: "finish",
|
|
1581
|
+
finishReason: mapFinishReason4(candidate.finishReason),
|
|
1582
|
+
usage: {
|
|
1583
|
+
promptTokens,
|
|
1584
|
+
completionTokens,
|
|
1585
|
+
totalTokens: promptTokens + completionTokens
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
} catch (error) {
|
|
1591
|
+
yield {
|
|
1592
|
+
type: "error",
|
|
1593
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
function mapFinishReason4(reason) {
|
|
1600
|
+
switch (reason) {
|
|
1601
|
+
case "STOP":
|
|
1602
|
+
return "stop";
|
|
1603
|
+
case "MAX_TOKENS":
|
|
1604
|
+
return "length";
|
|
1605
|
+
case "SAFETY":
|
|
1606
|
+
return "content-filter";
|
|
1607
|
+
default:
|
|
1608
|
+
return "unknown";
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
function formatMessagesForGemini(messages) {
|
|
1612
|
+
let systemInstruction = "";
|
|
1613
|
+
const contents = [];
|
|
1614
|
+
for (const msg of messages) {
|
|
1615
|
+
if (msg.role === "system") {
|
|
1616
|
+
systemInstruction += (systemInstruction ? "\n" : "") + msg.content;
|
|
1617
|
+
continue;
|
|
1618
|
+
}
|
|
1619
|
+
const parts = [];
|
|
1620
|
+
if (msg.role === "user") {
|
|
1621
|
+
if (typeof msg.content === "string") {
|
|
1622
|
+
parts.push({ text: msg.content });
|
|
1623
|
+
} else {
|
|
1624
|
+
for (const part of msg.content) {
|
|
1625
|
+
if (part.type === "text") {
|
|
1626
|
+
parts.push({ text: part.text });
|
|
1627
|
+
} else if (part.type === "image") {
|
|
1628
|
+
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
1629
|
+
const base64 = imageData.startsWith("data:") ? imageData.split(",")[1] : imageData;
|
|
1630
|
+
parts.push({
|
|
1631
|
+
inlineData: {
|
|
1632
|
+
mimeType: part.mimeType ?? "image/png",
|
|
1633
|
+
data: base64
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
contents.push({ role: "user", parts });
|
|
1640
|
+
} else if (msg.role === "assistant") {
|
|
1641
|
+
if (msg.content) {
|
|
1642
|
+
parts.push({ text: msg.content });
|
|
1643
|
+
}
|
|
1644
|
+
if (msg.toolCalls?.length) {
|
|
1645
|
+
for (const tc of msg.toolCalls) {
|
|
1646
|
+
parts.push({
|
|
1647
|
+
functionCall: {
|
|
1648
|
+
name: tc.name,
|
|
1649
|
+
args: tc.args
|
|
1650
|
+
}
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
if (parts.length > 0) {
|
|
1655
|
+
contents.push({ role: "model", parts });
|
|
1656
|
+
}
|
|
1657
|
+
} else if (msg.role === "tool") {
|
|
1658
|
+
contents.push({
|
|
1659
|
+
role: "user",
|
|
1660
|
+
parts: [
|
|
1661
|
+
{
|
|
1662
|
+
functionResponse: {
|
|
1663
|
+
name: "tool",
|
|
1664
|
+
// Gemini doesn't track by ID
|
|
1665
|
+
response: JSON.parse(msg.content || "{}")
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
]
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
if (contents.length === 0 || contents[0].role !== "user") {
|
|
1673
|
+
contents.unshift({ role: "user", parts: [{ text: "" }] });
|
|
1674
|
+
}
|
|
1675
|
+
const merged = [];
|
|
1676
|
+
for (const content of contents) {
|
|
1677
|
+
const last = merged[merged.length - 1];
|
|
1678
|
+
if (last && last.role === content.role) {
|
|
1679
|
+
last.parts.push(...content.parts);
|
|
1680
|
+
} else {
|
|
1681
|
+
merged.push({ ...content, parts: [...content.parts] });
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
return { systemInstruction, contents: merged };
|
|
1685
|
+
}
|
|
1686
|
+
function formatToolsForGemini(tools) {
|
|
1687
|
+
return tools.map((t) => ({
|
|
1688
|
+
name: t.function.name,
|
|
1689
|
+
description: t.function.description,
|
|
1690
|
+
parameters: t.function.parameters
|
|
1691
|
+
}));
|
|
1692
|
+
}
|
|
6
1693
|
|
|
7
1694
|
// src/adapters/base.ts
|
|
8
1695
|
function formatMessages(messages, systemPrompt) {
|
|
@@ -195,7 +1882,7 @@ function messageToOpenAIContent(message) {
|
|
|
195
1882
|
}
|
|
196
1883
|
return blocks;
|
|
197
1884
|
}
|
|
198
|
-
function
|
|
1885
|
+
function formatMessagesForAnthropic2(messages, systemPrompt) {
|
|
199
1886
|
const formatted = [];
|
|
200
1887
|
for (let i = 0; i < messages.length; i++) {
|
|
201
1888
|
const msg = messages[i];
|
|
@@ -254,7 +1941,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
254
1941
|
messages: formatted
|
|
255
1942
|
};
|
|
256
1943
|
}
|
|
257
|
-
function
|
|
1944
|
+
function formatMessagesForOpenAI2(messages, systemPrompt) {
|
|
258
1945
|
const formatted = [];
|
|
259
1946
|
if (systemPrompt) {
|
|
260
1947
|
formatted.push({ role: "system", content: systemPrompt });
|
|
@@ -347,7 +2034,7 @@ var OpenAIAdapter = class {
|
|
|
347
2034
|
messages = processedMessages;
|
|
348
2035
|
}
|
|
349
2036
|
} else {
|
|
350
|
-
messages =
|
|
2037
|
+
messages = formatMessagesForOpenAI2(
|
|
351
2038
|
request.messages,
|
|
352
2039
|
request.systemPrompt
|
|
353
2040
|
);
|
|
@@ -595,7 +2282,7 @@ var AnthropicAdapter = class {
|
|
|
595
2282
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
596
2283
|
messages = this.convertToAnthropicMessages(request.rawMessages);
|
|
597
2284
|
} else {
|
|
598
|
-
const formatted =
|
|
2285
|
+
const formatted = formatMessagesForAnthropic2(request.messages);
|
|
599
2286
|
messages = formatted.messages;
|
|
600
2287
|
}
|
|
601
2288
|
const tools = request.actions?.map((action) => ({
|
|
@@ -741,117 +2428,6 @@ var AnthropicAdapter = class {
|
|
|
741
2428
|
function createAnthropicAdapter(config) {
|
|
742
2429
|
return new AnthropicAdapter(config);
|
|
743
2430
|
}
|
|
744
|
-
var GroqAdapter = class {
|
|
745
|
-
constructor(config) {
|
|
746
|
-
this.provider = "groq";
|
|
747
|
-
this.config = config;
|
|
748
|
-
this.model = config.model || "llama-3.1-70b-versatile";
|
|
749
|
-
}
|
|
750
|
-
async *stream(request) {
|
|
751
|
-
const messages = formatMessages(request.messages, request.systemPrompt);
|
|
752
|
-
const tools = request.actions?.length ? formatTools(request.actions) : void 0;
|
|
753
|
-
const messageId = generateMessageId();
|
|
754
|
-
yield { type: "message:start", id: messageId };
|
|
755
|
-
try {
|
|
756
|
-
const response = await fetch(
|
|
757
|
-
"https://api.groq.com/openai/v1/chat/completions",
|
|
758
|
-
{
|
|
759
|
-
method: "POST",
|
|
760
|
-
headers: {
|
|
761
|
-
"Content-Type": "application/json",
|
|
762
|
-
Authorization: `Bearer ${this.config.apiKey}`
|
|
763
|
-
},
|
|
764
|
-
body: JSON.stringify({
|
|
765
|
-
model: request.config?.model || this.model,
|
|
766
|
-
messages,
|
|
767
|
-
tools,
|
|
768
|
-
temperature: request.config?.temperature ?? this.config.temperature,
|
|
769
|
-
max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
770
|
-
stream: true
|
|
771
|
-
}),
|
|
772
|
-
signal: request.signal
|
|
773
|
-
}
|
|
774
|
-
);
|
|
775
|
-
if (!response.ok) {
|
|
776
|
-
throw new Error(`Groq API error: ${response.status}`);
|
|
777
|
-
}
|
|
778
|
-
if (!response.body) {
|
|
779
|
-
throw new Error("No response body");
|
|
780
|
-
}
|
|
781
|
-
const reader = response.body.getReader();
|
|
782
|
-
const decoder = new TextDecoder();
|
|
783
|
-
let buffer = "";
|
|
784
|
-
let currentToolCall = null;
|
|
785
|
-
while (true) {
|
|
786
|
-
const { done, value } = await reader.read();
|
|
787
|
-
if (done) break;
|
|
788
|
-
buffer += decoder.decode(value, { stream: true });
|
|
789
|
-
const lines = buffer.split("\n");
|
|
790
|
-
buffer = lines.pop() || "";
|
|
791
|
-
for (const line of lines) {
|
|
792
|
-
if (!line.startsWith("data: ")) continue;
|
|
793
|
-
const data = line.slice(6).trim();
|
|
794
|
-
if (data === "[DONE]") continue;
|
|
795
|
-
try {
|
|
796
|
-
const chunk = JSON.parse(data);
|
|
797
|
-
const delta = chunk.choices?.[0]?.delta;
|
|
798
|
-
if (delta?.content) {
|
|
799
|
-
yield { type: "message:delta", content: delta.content };
|
|
800
|
-
}
|
|
801
|
-
if (delta?.tool_calls) {
|
|
802
|
-
for (const toolCall of delta.tool_calls) {
|
|
803
|
-
if (toolCall.id) {
|
|
804
|
-
if (currentToolCall) {
|
|
805
|
-
yield {
|
|
806
|
-
type: "action:args",
|
|
807
|
-
id: currentToolCall.id,
|
|
808
|
-
args: currentToolCall.arguments
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
currentToolCall = {
|
|
812
|
-
id: toolCall.id,
|
|
813
|
-
name: toolCall.function?.name || "",
|
|
814
|
-
arguments: toolCall.function?.arguments || ""
|
|
815
|
-
};
|
|
816
|
-
yield {
|
|
817
|
-
type: "action:start",
|
|
818
|
-
id: currentToolCall.id,
|
|
819
|
-
name: currentToolCall.name
|
|
820
|
-
};
|
|
821
|
-
} else if (currentToolCall && toolCall.function?.arguments) {
|
|
822
|
-
currentToolCall.arguments += toolCall.function.arguments;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (chunk.choices?.[0]?.finish_reason && currentToolCall) {
|
|
827
|
-
yield {
|
|
828
|
-
type: "action:args",
|
|
829
|
-
id: currentToolCall.id,
|
|
830
|
-
args: currentToolCall.arguments
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
} catch {
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
yield { type: "message:end" };
|
|
838
|
-
yield { type: "done" };
|
|
839
|
-
} catch (error) {
|
|
840
|
-
if (error.name === "AbortError") {
|
|
841
|
-
yield { type: "done" };
|
|
842
|
-
} else {
|
|
843
|
-
yield {
|
|
844
|
-
type: "error",
|
|
845
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
846
|
-
code: "GROQ_ERROR"
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
};
|
|
852
|
-
function createGroqAdapter(config) {
|
|
853
|
-
return new GroqAdapter(config);
|
|
854
|
-
}
|
|
855
2431
|
var OllamaAdapter = class {
|
|
856
2432
|
constructor(config = {}) {
|
|
857
2433
|
this.provider = "ollama";
|
|
@@ -1018,7 +2594,7 @@ function messageToGeminiContent(msg) {
|
|
|
1018
2594
|
parts
|
|
1019
2595
|
};
|
|
1020
2596
|
}
|
|
1021
|
-
function
|
|
2597
|
+
function formatToolsForGemini2(actions) {
|
|
1022
2598
|
if (!actions || actions.length === 0) return void 0;
|
|
1023
2599
|
return {
|
|
1024
2600
|
functionDeclarations: actions.map((action) => ({
|
|
@@ -1104,7 +2680,7 @@ var GoogleAdapter = class {
|
|
|
1104
2680
|
mergedContents.push({ ...content, parts: [...content.parts] });
|
|
1105
2681
|
}
|
|
1106
2682
|
}
|
|
1107
|
-
const tools =
|
|
2683
|
+
const tools = formatToolsForGemini2(request.actions);
|
|
1108
2684
|
const messageId = generateMessageId();
|
|
1109
2685
|
yield { type: "message:start", id: messageId };
|
|
1110
2686
|
try {
|
|
@@ -1210,7 +2786,7 @@ var GoogleAdapter = class {
|
|
|
1210
2786
|
mergedContents.push({ ...content, parts: [...content.parts] });
|
|
1211
2787
|
}
|
|
1212
2788
|
}
|
|
1213
|
-
const tools =
|
|
2789
|
+
const tools = formatToolsForGemini2(request.actions);
|
|
1214
2790
|
const chat = model.startChat({
|
|
1215
2791
|
history: mergedContents.slice(0, -1),
|
|
1216
2792
|
systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
|
|
@@ -1308,7 +2884,7 @@ var XAIAdapter = class {
|
|
|
1308
2884
|
messages = processedMessages;
|
|
1309
2885
|
}
|
|
1310
2886
|
} else {
|
|
1311
|
-
messages =
|
|
2887
|
+
messages = formatMessagesForOpenAI2(
|
|
1312
2888
|
request.messages,
|
|
1313
2889
|
request.systemPrompt
|
|
1314
2890
|
);
|
|
@@ -1397,7 +2973,7 @@ var XAIAdapter = class {
|
|
|
1397
2973
|
}
|
|
1398
2974
|
}
|
|
1399
2975
|
} else {
|
|
1400
|
-
messages =
|
|
2976
|
+
messages = formatMessagesForOpenAI2(
|
|
1401
2977
|
request.messages,
|
|
1402
2978
|
request.systemPrompt
|
|
1403
2979
|
);
|
|
@@ -1494,7 +3070,7 @@ var AzureAdapter = class {
|
|
|
1494
3070
|
messages = processedMessages;
|
|
1495
3071
|
}
|
|
1496
3072
|
} else {
|
|
1497
|
-
messages =
|
|
3073
|
+
messages = formatMessagesForOpenAI2(
|
|
1498
3074
|
request.messages,
|
|
1499
3075
|
request.systemPrompt
|
|
1500
3076
|
);
|
|
@@ -1584,7 +3160,7 @@ var AzureAdapter = class {
|
|
|
1584
3160
|
}
|
|
1585
3161
|
}
|
|
1586
3162
|
} else {
|
|
1587
|
-
messages =
|
|
3163
|
+
messages = formatMessagesForOpenAI2(
|
|
1588
3164
|
request.messages,
|
|
1589
3165
|
request.systemPrompt
|
|
1590
3166
|
);
|
|
@@ -1658,23 +3234,23 @@ function createSSEResponse(generator) {
|
|
|
1658
3234
|
}
|
|
1659
3235
|
|
|
1660
3236
|
// src/server/runtime.ts
|
|
1661
|
-
function buildToolResultForAI(
|
|
3237
|
+
function buildToolResultForAI(tool2, result, args) {
|
|
1662
3238
|
const typedResult = result;
|
|
1663
|
-
const responseMode = typedResult?._aiResponseMode ??
|
|
3239
|
+
const responseMode = typedResult?._aiResponseMode ?? tool2?.aiResponseMode ?? "full";
|
|
1664
3240
|
if (typedResult?._aiContent && typedResult._aiContent.length > 0) {
|
|
1665
3241
|
return typedResult._aiContent;
|
|
1666
3242
|
}
|
|
1667
3243
|
let aiContext;
|
|
1668
3244
|
if (typedResult?._aiContext) {
|
|
1669
3245
|
aiContext = typedResult._aiContext;
|
|
1670
|
-
} else if (
|
|
1671
|
-
aiContext = typeof
|
|
3246
|
+
} else if (tool2?.aiContext) {
|
|
3247
|
+
aiContext = typeof tool2.aiContext === "function" ? tool2.aiContext(typedResult, args) : tool2.aiContext;
|
|
1672
3248
|
}
|
|
1673
3249
|
switch (responseMode) {
|
|
1674
3250
|
case "none":
|
|
1675
3251
|
return aiContext ?? "[Result displayed to user]";
|
|
1676
3252
|
case "brief":
|
|
1677
|
-
return aiContext ?? `[Tool ${
|
|
3253
|
+
return aiContext ?? `[Tool ${tool2?.name ?? "unknown"} executed successfully]`;
|
|
1678
3254
|
case "full":
|
|
1679
3255
|
default:
|
|
1680
3256
|
const fullData = JSON.stringify(result);
|
|
@@ -1743,8 +3319,8 @@ var Runtime = class {
|
|
|
1743
3319
|
}
|
|
1744
3320
|
}
|
|
1745
3321
|
if (config.tools) {
|
|
1746
|
-
for (const
|
|
1747
|
-
this.tools.set(
|
|
3322
|
+
for (const tool2 of config.tools) {
|
|
3323
|
+
this.tools.set(tool2.name, tool2);
|
|
1748
3324
|
}
|
|
1749
3325
|
}
|
|
1750
3326
|
}
|
|
@@ -1774,13 +3350,6 @@ var Runtime = class {
|
|
|
1774
3350
|
temperature: llm.temperature,
|
|
1775
3351
|
maxTokens: llm.maxTokens
|
|
1776
3352
|
});
|
|
1777
|
-
case "groq":
|
|
1778
|
-
return createGroqAdapter({
|
|
1779
|
-
apiKey: llm.apiKey,
|
|
1780
|
-
model: llm.model,
|
|
1781
|
-
temperature: llm.temperature,
|
|
1782
|
-
maxTokens: llm.maxTokens
|
|
1783
|
-
});
|
|
1784
3353
|
case "ollama":
|
|
1785
3354
|
return createOllamaAdapter({
|
|
1786
3355
|
model: llm.model,
|
|
@@ -2012,8 +3581,8 @@ var Runtime = class {
|
|
|
2012
3581
|
/**
|
|
2013
3582
|
* Register a new tool
|
|
2014
3583
|
*/
|
|
2015
|
-
registerTool(
|
|
2016
|
-
this.tools.set(
|
|
3584
|
+
registerTool(tool2) {
|
|
3585
|
+
this.tools.set(tool2.name, tool2);
|
|
2017
3586
|
}
|
|
2018
3587
|
/**
|
|
2019
3588
|
* Unregister a tool
|
|
@@ -2092,12 +3661,12 @@ var Runtime = class {
|
|
|
2092
3661
|
this.config.agentLoop?.maxIterations || 20;
|
|
2093
3662
|
const allTools = [...this.tools.values()];
|
|
2094
3663
|
if (request.tools) {
|
|
2095
|
-
for (const
|
|
3664
|
+
for (const tool2 of request.tools) {
|
|
2096
3665
|
allTools.push({
|
|
2097
|
-
name:
|
|
2098
|
-
description:
|
|
3666
|
+
name: tool2.name,
|
|
3667
|
+
description: tool2.description,
|
|
2099
3668
|
location: "client",
|
|
2100
|
-
inputSchema:
|
|
3669
|
+
inputSchema: tool2.inputSchema
|
|
2101
3670
|
});
|
|
2102
3671
|
}
|
|
2103
3672
|
}
|
|
@@ -2202,8 +3771,8 @@ var Runtime = class {
|
|
|
2202
3771
|
const serverToolCalls = [];
|
|
2203
3772
|
const clientToolCalls = [];
|
|
2204
3773
|
for (const tc of toolCalls) {
|
|
2205
|
-
const
|
|
2206
|
-
if (
|
|
3774
|
+
const tool2 = allTools.find((t) => t.name === tc.name);
|
|
3775
|
+
if (tool2?.location === "server" && tool2.handler) {
|
|
2207
3776
|
serverToolCalls.push(tc);
|
|
2208
3777
|
} else {
|
|
2209
3778
|
clientToolCalls.push(tc);
|
|
@@ -2212,8 +3781,8 @@ var Runtime = class {
|
|
|
2212
3781
|
const serverToolResults = [];
|
|
2213
3782
|
const toolContextData = "toolContext" in this.config ? this.config.toolContext : void 0;
|
|
2214
3783
|
for (const tc of serverToolCalls) {
|
|
2215
|
-
const
|
|
2216
|
-
if (
|
|
3784
|
+
const tool2 = allTools.find((t) => t.name === tc.name);
|
|
3785
|
+
if (tool2?.handler) {
|
|
2217
3786
|
if (debug) {
|
|
2218
3787
|
console.log(`[Copilot SDK] Executing server-side tool: ${tc.name}`);
|
|
2219
3788
|
}
|
|
@@ -2225,13 +3794,13 @@ var Runtime = class {
|
|
|
2225
3794
|
toolContextData
|
|
2226
3795
|
);
|
|
2227
3796
|
try {
|
|
2228
|
-
const result = await
|
|
3797
|
+
const result = await tool2.handler(tc.args, toolContext);
|
|
2229
3798
|
serverToolResults.push({
|
|
2230
3799
|
id: tc.id,
|
|
2231
3800
|
name: tc.name,
|
|
2232
3801
|
args: tc.args,
|
|
2233
3802
|
result,
|
|
2234
|
-
tool
|
|
3803
|
+
tool: tool2
|
|
2235
3804
|
});
|
|
2236
3805
|
yield {
|
|
2237
3806
|
type: "action:end",
|
|
@@ -2248,7 +3817,7 @@ var Runtime = class {
|
|
|
2248
3817
|
name: tc.name,
|
|
2249
3818
|
args: tc.args,
|
|
2250
3819
|
result: errorResult,
|
|
2251
|
-
tool
|
|
3820
|
+
tool: tool2
|
|
2252
3821
|
});
|
|
2253
3822
|
yield {
|
|
2254
3823
|
type: "action:end",
|
|
@@ -2367,12 +3936,12 @@ var Runtime = class {
|
|
|
2367
3936
|
const maxIterations = this.config.agentLoop?.maxIterations || 20;
|
|
2368
3937
|
const allTools = [...this.tools.values()];
|
|
2369
3938
|
if (request.tools) {
|
|
2370
|
-
for (const
|
|
3939
|
+
for (const tool2 of request.tools) {
|
|
2371
3940
|
allTools.push({
|
|
2372
|
-
name:
|
|
2373
|
-
description:
|
|
3941
|
+
name: tool2.name,
|
|
3942
|
+
description: tool2.description,
|
|
2374
3943
|
location: "client",
|
|
2375
|
-
inputSchema:
|
|
3944
|
+
inputSchema: tool2.inputSchema
|
|
2376
3945
|
});
|
|
2377
3946
|
}
|
|
2378
3947
|
}
|
|
@@ -2437,8 +4006,8 @@ var Runtime = class {
|
|
|
2437
4006
|
const serverToolCalls = [];
|
|
2438
4007
|
const clientToolCalls = [];
|
|
2439
4008
|
for (const tc of result.toolCalls) {
|
|
2440
|
-
const
|
|
2441
|
-
if (
|
|
4009
|
+
const tool2 = allTools.find((t) => t.name === tc.name);
|
|
4010
|
+
if (tool2?.location === "server" && tool2.handler) {
|
|
2442
4011
|
serverToolCalls.push(tc);
|
|
2443
4012
|
} else {
|
|
2444
4013
|
clientToolCalls.push({
|
|
@@ -2463,8 +4032,8 @@ var Runtime = class {
|
|
|
2463
4032
|
const serverToolResults = [];
|
|
2464
4033
|
const toolContextData = "toolContext" in this.config ? this.config.toolContext : void 0;
|
|
2465
4034
|
for (const tc of serverToolCalls) {
|
|
2466
|
-
const
|
|
2467
|
-
if (
|
|
4035
|
+
const tool2 = allTools.find((t) => t.name === tc.name);
|
|
4036
|
+
if (tool2?.handler) {
|
|
2468
4037
|
if (debug) {
|
|
2469
4038
|
console.log(`[Copilot SDK] Executing tool: ${tc.name}`);
|
|
2470
4039
|
}
|
|
@@ -2476,13 +4045,13 @@ var Runtime = class {
|
|
|
2476
4045
|
toolContextData
|
|
2477
4046
|
);
|
|
2478
4047
|
try {
|
|
2479
|
-
const toolResult = await
|
|
4048
|
+
const toolResult = await tool2.handler(tc.args, toolContext);
|
|
2480
4049
|
serverToolResults.push({
|
|
2481
4050
|
id: tc.id,
|
|
2482
4051
|
name: tc.name,
|
|
2483
4052
|
args: tc.args,
|
|
2484
4053
|
result: toolResult,
|
|
2485
|
-
tool
|
|
4054
|
+
tool: tool2
|
|
2486
4055
|
});
|
|
2487
4056
|
yield {
|
|
2488
4057
|
type: "action:end",
|
|
@@ -2499,7 +4068,7 @@ var Runtime = class {
|
|
|
2499
4068
|
name: tc.name,
|
|
2500
4069
|
args: tc.args,
|
|
2501
4070
|
result: errorResult,
|
|
2502
|
-
tool
|
|
4071
|
+
tool: tool2
|
|
2503
4072
|
});
|
|
2504
4073
|
yield {
|
|
2505
4074
|
type: "action:end",
|
|
@@ -2606,11 +4175,11 @@ var Runtime = class {
|
|
|
2606
4175
|
* Convert tools to legacy action format (for adapter compatibility)
|
|
2607
4176
|
*/
|
|
2608
4177
|
convertToolsToActions(tools) {
|
|
2609
|
-
return tools.map((
|
|
2610
|
-
name:
|
|
2611
|
-
description:
|
|
2612
|
-
parameters: this.convertInputSchemaToParameters(
|
|
2613
|
-
handler:
|
|
4178
|
+
return tools.map((tool2) => ({
|
|
4179
|
+
name: tool2.name,
|
|
4180
|
+
description: tool2.description,
|
|
4181
|
+
parameters: this.convertInputSchemaToParameters(tool2.inputSchema),
|
|
4182
|
+
handler: tool2.handler || (async () => ({ handled: false }))
|
|
2614
4183
|
}));
|
|
2615
4184
|
}
|
|
2616
4185
|
/**
|
|
@@ -2832,7 +4401,7 @@ function getModelCapabilities(providerName, modelId) {
|
|
|
2832
4401
|
}
|
|
2833
4402
|
|
|
2834
4403
|
// src/providers/openai/index.ts
|
|
2835
|
-
var
|
|
4404
|
+
var OPENAI_MODELS2 = {
|
|
2836
4405
|
// GPT-4o series
|
|
2837
4406
|
"gpt-4o": {
|
|
2838
4407
|
vision: true,
|
|
@@ -2943,7 +4512,7 @@ function createOpenAI(config = {}) {
|
|
|
2943
4512
|
const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY ?? "";
|
|
2944
4513
|
return {
|
|
2945
4514
|
name: "openai",
|
|
2946
|
-
supportedModels: Object.keys(
|
|
4515
|
+
supportedModels: Object.keys(OPENAI_MODELS2),
|
|
2947
4516
|
languageModel(modelId) {
|
|
2948
4517
|
return createOpenAIAdapter({
|
|
2949
4518
|
apiKey,
|
|
@@ -2952,7 +4521,7 @@ function createOpenAI(config = {}) {
|
|
|
2952
4521
|
});
|
|
2953
4522
|
},
|
|
2954
4523
|
getCapabilities(modelId) {
|
|
2955
|
-
const model =
|
|
4524
|
+
const model = OPENAI_MODELS2[modelId] ?? OPENAI_MODELS2["gpt-4o"];
|
|
2956
4525
|
return {
|
|
2957
4526
|
supportsVision: model.vision,
|
|
2958
4527
|
supportsTools: model.tools,
|
|
@@ -2974,7 +4543,7 @@ function createOpenAI(config = {}) {
|
|
|
2974
4543
|
}
|
|
2975
4544
|
|
|
2976
4545
|
// src/providers/anthropic/index.ts
|
|
2977
|
-
var
|
|
4546
|
+
var ANTHROPIC_MODELS2 = {
|
|
2978
4547
|
// Claude 4 series (latest)
|
|
2979
4548
|
"claude-sonnet-4-20250514": {
|
|
2980
4549
|
vision: true,
|
|
@@ -3043,7 +4612,7 @@ function createAnthropic(config = {}) {
|
|
|
3043
4612
|
const apiKey = config.apiKey ?? process.env.ANTHROPIC_API_KEY ?? "";
|
|
3044
4613
|
return {
|
|
3045
4614
|
name: "anthropic",
|
|
3046
|
-
supportedModels: Object.keys(
|
|
4615
|
+
supportedModels: Object.keys(ANTHROPIC_MODELS2),
|
|
3047
4616
|
languageModel(modelId) {
|
|
3048
4617
|
return createAnthropicAdapter({
|
|
3049
4618
|
apiKey,
|
|
@@ -3053,7 +4622,7 @@ function createAnthropic(config = {}) {
|
|
|
3053
4622
|
});
|
|
3054
4623
|
},
|
|
3055
4624
|
getCapabilities(modelId) {
|
|
3056
|
-
const model =
|
|
4625
|
+
const model = ANTHROPIC_MODELS2[modelId] ?? ANTHROPIC_MODELS2["claude-3-5-sonnet-latest"];
|
|
3057
4626
|
return {
|
|
3058
4627
|
supportsVision: model.vision,
|
|
3059
4628
|
supportsTools: model.tools,
|
|
@@ -3078,90 +4647,6 @@ function createAnthropic(config = {}) {
|
|
|
3078
4647
|
};
|
|
3079
4648
|
}
|
|
3080
4649
|
|
|
3081
|
-
// src/providers/groq/index.ts
|
|
3082
|
-
var GROQ_MODELS = {
|
|
3083
|
-
// Llama 3.3 series
|
|
3084
|
-
"llama-3.3-70b-versatile": {
|
|
3085
|
-
vision: false,
|
|
3086
|
-
tools: true,
|
|
3087
|
-
maxTokens: 32768
|
|
3088
|
-
},
|
|
3089
|
-
"llama-3.3-70b-specdec": {
|
|
3090
|
-
vision: false,
|
|
3091
|
-
tools: true,
|
|
3092
|
-
maxTokens: 8192
|
|
3093
|
-
},
|
|
3094
|
-
// Llama 3.2 Vision series
|
|
3095
|
-
"llama-3.2-90b-vision-preview": {
|
|
3096
|
-
vision: true,
|
|
3097
|
-
tools: true,
|
|
3098
|
-
maxTokens: 8192
|
|
3099
|
-
},
|
|
3100
|
-
"llama-3.2-11b-vision-preview": {
|
|
3101
|
-
vision: true,
|
|
3102
|
-
tools: true,
|
|
3103
|
-
maxTokens: 8192
|
|
3104
|
-
},
|
|
3105
|
-
// Llama 3.1 series
|
|
3106
|
-
"llama-3.1-70b-versatile": {
|
|
3107
|
-
vision: false,
|
|
3108
|
-
tools: true,
|
|
3109
|
-
maxTokens: 32768
|
|
3110
|
-
},
|
|
3111
|
-
"llama-3.1-8b-instant": {
|
|
3112
|
-
vision: false,
|
|
3113
|
-
tools: true,
|
|
3114
|
-
maxTokens: 8192
|
|
3115
|
-
},
|
|
3116
|
-
// Mixtral series
|
|
3117
|
-
"mixtral-8x7b-32768": {
|
|
3118
|
-
vision: false,
|
|
3119
|
-
tools: true,
|
|
3120
|
-
maxTokens: 32768
|
|
3121
|
-
},
|
|
3122
|
-
// Gemma series
|
|
3123
|
-
"gemma2-9b-it": {
|
|
3124
|
-
vision: false,
|
|
3125
|
-
tools: false,
|
|
3126
|
-
maxTokens: 8192
|
|
3127
|
-
},
|
|
3128
|
-
// DeepSeek
|
|
3129
|
-
"deepseek-r1-distill-llama-70b": {
|
|
3130
|
-
vision: false,
|
|
3131
|
-
tools: true,
|
|
3132
|
-
maxTokens: 8192
|
|
3133
|
-
}
|
|
3134
|
-
};
|
|
3135
|
-
function createGroq(config = {}) {
|
|
3136
|
-
const apiKey = config.apiKey ?? process.env.GROQ_API_KEY ?? "";
|
|
3137
|
-
return {
|
|
3138
|
-
name: "groq",
|
|
3139
|
-
supportedModels: Object.keys(GROQ_MODELS),
|
|
3140
|
-
languageModel(modelId) {
|
|
3141
|
-
return createGroqAdapter({
|
|
3142
|
-
apiKey,
|
|
3143
|
-
model: modelId
|
|
3144
|
-
});
|
|
3145
|
-
},
|
|
3146
|
-
getCapabilities(modelId) {
|
|
3147
|
-
const model = GROQ_MODELS[modelId] ?? GROQ_MODELS["llama-3.3-70b-versatile"];
|
|
3148
|
-
return {
|
|
3149
|
-
supportsVision: model.vision,
|
|
3150
|
-
supportsTools: model.tools,
|
|
3151
|
-
supportsThinking: false,
|
|
3152
|
-
supportsStreaming: true,
|
|
3153
|
-
supportsPDF: false,
|
|
3154
|
-
supportsAudio: false,
|
|
3155
|
-
supportsVideo: false,
|
|
3156
|
-
maxTokens: model.maxTokens,
|
|
3157
|
-
supportedImageTypes: model.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : [],
|
|
3158
|
-
supportsJsonMode: true,
|
|
3159
|
-
supportsSystemMessages: true
|
|
3160
|
-
};
|
|
3161
|
-
}
|
|
3162
|
-
};
|
|
3163
|
-
}
|
|
3164
|
-
|
|
3165
4650
|
// src/providers/ollama/index.ts
|
|
3166
4651
|
var OLLAMA_MODELS = {
|
|
3167
4652
|
// Llama series
|
|
@@ -3295,7 +4780,7 @@ function createOllama(config = {}) {
|
|
|
3295
4780
|
}
|
|
3296
4781
|
|
|
3297
4782
|
// src/providers/google/index.ts
|
|
3298
|
-
var
|
|
4783
|
+
var GOOGLE_MODELS2 = {
|
|
3299
4784
|
// Gemini 2.0 series (latest)
|
|
3300
4785
|
"gemini-2.0-flash": {
|
|
3301
4786
|
vision: true,
|
|
@@ -3395,7 +4880,7 @@ function createGoogle(config = {}) {
|
|
|
3395
4880
|
const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? "";
|
|
3396
4881
|
return {
|
|
3397
4882
|
name: "google",
|
|
3398
|
-
supportedModels: Object.keys(
|
|
4883
|
+
supportedModels: Object.keys(GOOGLE_MODELS2),
|
|
3399
4884
|
languageModel(modelId) {
|
|
3400
4885
|
return createGoogleAdapter({
|
|
3401
4886
|
apiKey,
|
|
@@ -3405,7 +4890,7 @@ function createGoogle(config = {}) {
|
|
|
3405
4890
|
});
|
|
3406
4891
|
},
|
|
3407
4892
|
getCapabilities(modelId) {
|
|
3408
|
-
const model =
|
|
4893
|
+
const model = GOOGLE_MODELS2[modelId] ?? GOOGLE_MODELS2["gemini-2.0-flash"];
|
|
3409
4894
|
return {
|
|
3410
4895
|
supportsVision: model.vision,
|
|
3411
4896
|
supportsTools: model.tools,
|
|
@@ -3449,56 +4934,95 @@ function createGoogle(config = {}) {
|
|
|
3449
4934
|
}
|
|
3450
4935
|
|
|
3451
4936
|
// src/providers/xai/index.ts
|
|
3452
|
-
var
|
|
3453
|
-
// Grok
|
|
3454
|
-
"grok-
|
|
4937
|
+
var XAI_MODELS2 = {
|
|
4938
|
+
// Grok 4.1 Fast (Latest - December 2025)
|
|
4939
|
+
"grok-4-1-fast-reasoning": {
|
|
4940
|
+
vision: false,
|
|
4941
|
+
tools: true,
|
|
4942
|
+
maxTokens: 2e6,
|
|
4943
|
+
outputTokens: 16384
|
|
4944
|
+
},
|
|
4945
|
+
"grok-4-1-fast-non-reasoning": {
|
|
4946
|
+
vision: false,
|
|
4947
|
+
tools: true,
|
|
4948
|
+
maxTokens: 2e6,
|
|
4949
|
+
outputTokens: 16384
|
|
4950
|
+
},
|
|
4951
|
+
// Grok 4 Fast (September 2025)
|
|
4952
|
+
"grok-4-fast-reasoning": {
|
|
4953
|
+
vision: false,
|
|
4954
|
+
tools: true,
|
|
4955
|
+
maxTokens: 2e6,
|
|
4956
|
+
outputTokens: 16384
|
|
4957
|
+
},
|
|
4958
|
+
"grok-4-fast-non-reasoning": {
|
|
4959
|
+
vision: false,
|
|
4960
|
+
tools: true,
|
|
4961
|
+
maxTokens: 2e6,
|
|
4962
|
+
outputTokens: 16384
|
|
4963
|
+
},
|
|
4964
|
+
// Grok 4 (July 2025)
|
|
4965
|
+
"grok-4": {
|
|
3455
4966
|
vision: true,
|
|
3456
4967
|
tools: true,
|
|
3457
|
-
maxTokens:
|
|
3458
|
-
outputTokens:
|
|
4968
|
+
maxTokens: 256e3,
|
|
4969
|
+
outputTokens: 16384
|
|
3459
4970
|
},
|
|
3460
|
-
"grok-
|
|
4971
|
+
"grok-4-0709": {
|
|
3461
4972
|
vision: true,
|
|
3462
4973
|
tools: true,
|
|
3463
|
-
maxTokens:
|
|
3464
|
-
outputTokens:
|
|
4974
|
+
maxTokens: 256e3,
|
|
4975
|
+
outputTokens: 16384
|
|
3465
4976
|
},
|
|
3466
|
-
|
|
3467
|
-
|
|
4977
|
+
// Grok 3 (February 2025) - Stable
|
|
4978
|
+
"grok-3-beta": {
|
|
4979
|
+
vision: true,
|
|
3468
4980
|
tools: true,
|
|
3469
4981
|
maxTokens: 131072,
|
|
3470
|
-
outputTokens:
|
|
4982
|
+
outputTokens: 8192
|
|
3471
4983
|
},
|
|
3472
|
-
"grok-
|
|
4984
|
+
"grok-3-fast-beta": {
|
|
3473
4985
|
vision: false,
|
|
3474
4986
|
tools: true,
|
|
3475
4987
|
maxTokens: 131072,
|
|
3476
|
-
outputTokens:
|
|
4988
|
+
outputTokens: 8192
|
|
3477
4989
|
},
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
vision: true,
|
|
4990
|
+
"grok-3-mini-beta": {
|
|
4991
|
+
vision: false,
|
|
3481
4992
|
tools: true,
|
|
3482
4993
|
maxTokens: 32768,
|
|
3483
|
-
outputTokens:
|
|
4994
|
+
outputTokens: 8192
|
|
3484
4995
|
},
|
|
3485
|
-
"grok-
|
|
3486
|
-
vision:
|
|
4996
|
+
"grok-3-mini-fast-beta": {
|
|
4997
|
+
vision: false,
|
|
3487
4998
|
tools: true,
|
|
3488
4999
|
maxTokens: 32768,
|
|
3489
|
-
outputTokens:
|
|
5000
|
+
outputTokens: 8192
|
|
3490
5001
|
},
|
|
3491
|
-
// Grok
|
|
3492
|
-
"grok-
|
|
5002
|
+
// Grok Code Fast (August 2025)
|
|
5003
|
+
"grok-code-fast-1": {
|
|
3493
5004
|
vision: false,
|
|
3494
5005
|
tools: true,
|
|
5006
|
+
maxTokens: 256e3,
|
|
5007
|
+
outputTokens: 16384
|
|
5008
|
+
},
|
|
5009
|
+
// Grok 2 (Legacy - for backward compatibility)
|
|
5010
|
+
"grok-2": {
|
|
5011
|
+
vision: true,
|
|
5012
|
+
tools: true,
|
|
3495
5013
|
maxTokens: 131072,
|
|
3496
5014
|
outputTokens: 4096
|
|
3497
5015
|
},
|
|
3498
|
-
"grok-
|
|
5016
|
+
"grok-2-latest": {
|
|
3499
5017
|
vision: true,
|
|
3500
5018
|
tools: true,
|
|
3501
|
-
maxTokens:
|
|
5019
|
+
maxTokens: 131072,
|
|
5020
|
+
outputTokens: 4096
|
|
5021
|
+
},
|
|
5022
|
+
"grok-2-mini": {
|
|
5023
|
+
vision: false,
|
|
5024
|
+
tools: true,
|
|
5025
|
+
maxTokens: 131072,
|
|
3502
5026
|
outputTokens: 4096
|
|
3503
5027
|
}
|
|
3504
5028
|
};
|
|
@@ -3506,7 +5030,7 @@ function createXAI(config = {}) {
|
|
|
3506
5030
|
const apiKey = config.apiKey ?? process.env.XAI_API_KEY ?? "";
|
|
3507
5031
|
return {
|
|
3508
5032
|
name: "xai",
|
|
3509
|
-
supportedModels: Object.keys(
|
|
5033
|
+
supportedModels: Object.keys(XAI_MODELS2),
|
|
3510
5034
|
languageModel(modelId) {
|
|
3511
5035
|
return createXAIAdapter({
|
|
3512
5036
|
apiKey,
|
|
@@ -3515,7 +5039,7 @@ function createXAI(config = {}) {
|
|
|
3515
5039
|
});
|
|
3516
5040
|
},
|
|
3517
5041
|
getCapabilities(modelId) {
|
|
3518
|
-
const model =
|
|
5042
|
+
const model = XAI_MODELS2[modelId] ?? XAI_MODELS2["grok-3-fast-beta"];
|
|
3519
5043
|
return {
|
|
3520
5044
|
supportsVision: model.vision,
|
|
3521
5045
|
supportsTools: model.tools,
|
|
@@ -3594,12 +5118,12 @@ function createAzure(config) {
|
|
|
3594
5118
|
|
|
3595
5119
|
// src/providers/openai.ts
|
|
3596
5120
|
function transformTools(tools) {
|
|
3597
|
-
return tools.map((
|
|
5121
|
+
return tools.map((tool2) => ({
|
|
3598
5122
|
type: "function",
|
|
3599
5123
|
function: {
|
|
3600
|
-
name:
|
|
3601
|
-
description:
|
|
3602
|
-
parameters:
|
|
5124
|
+
name: tool2.name,
|
|
5125
|
+
description: tool2.description,
|
|
5126
|
+
parameters: tool2.inputSchema
|
|
3603
5127
|
}
|
|
3604
5128
|
}));
|
|
3605
5129
|
}
|
|
@@ -3685,10 +5209,10 @@ var openaiFormatter = {
|
|
|
3685
5209
|
|
|
3686
5210
|
// src/providers/anthropic.ts
|
|
3687
5211
|
function transformTools2(tools) {
|
|
3688
|
-
return tools.map((
|
|
3689
|
-
name:
|
|
3690
|
-
description:
|
|
3691
|
-
input_schema:
|
|
5212
|
+
return tools.map((tool2) => ({
|
|
5213
|
+
name: tool2.name,
|
|
5214
|
+
description: tool2.description,
|
|
5215
|
+
input_schema: tool2.inputSchema
|
|
3692
5216
|
}));
|
|
3693
5217
|
}
|
|
3694
5218
|
function parseToolCalls2(response) {
|
|
@@ -3766,10 +5290,10 @@ var anthropicFormatter = {
|
|
|
3766
5290
|
function transformTools3(tools) {
|
|
3767
5291
|
return [
|
|
3768
5292
|
{
|
|
3769
|
-
functionDeclarations: tools.map((
|
|
3770
|
-
name:
|
|
3771
|
-
description:
|
|
3772
|
-
parameters:
|
|
5293
|
+
functionDeclarations: tools.map((tool2) => ({
|
|
5294
|
+
name: tool2.name,
|
|
5295
|
+
description: tool2.description,
|
|
5296
|
+
parameters: tool2.inputSchema
|
|
3773
5297
|
}))
|
|
3774
5298
|
}
|
|
3775
5299
|
];
|
|
@@ -3895,7 +5419,6 @@ var formatters = {
|
|
|
3895
5419
|
gemini: geminiFormatter,
|
|
3896
5420
|
// Alias
|
|
3897
5421
|
// OpenAI-compatible providers use openaiFormatter
|
|
3898
|
-
groq: openaiFormatter,
|
|
3899
5422
|
ollama: openaiFormatter,
|
|
3900
5423
|
xai: openaiFormatter,
|
|
3901
5424
|
azure: openaiFormatter
|
|
@@ -3919,7 +5442,6 @@ function getSupportedProviders() {
|
|
|
3919
5442
|
// src/providers/index.ts
|
|
3920
5443
|
registerProvider("openai", (config) => createOpenAI(config));
|
|
3921
5444
|
registerProvider("anthropic", (config) => createAnthropic(config));
|
|
3922
|
-
registerProvider("groq", (config) => createGroq(config));
|
|
3923
5445
|
registerProvider("ollama", (config) => createOllama(config));
|
|
3924
5446
|
registerProvider("google", (config) => createGoogle(config));
|
|
3925
5447
|
registerProvider("xai", (config) => createXAI(config));
|
|
@@ -4078,8 +5600,8 @@ function buildConversation(messages, systemPrompt) {
|
|
|
4078
5600
|
async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClientToolResult, emitEvent, debug) {
|
|
4079
5601
|
const results = [];
|
|
4080
5602
|
for (const toolCall of toolCalls) {
|
|
4081
|
-
const
|
|
4082
|
-
if (!
|
|
5603
|
+
const tool2 = tools.find((t) => t.name === toolCall.name);
|
|
5604
|
+
if (!tool2) {
|
|
4083
5605
|
if (debug) {
|
|
4084
5606
|
console.warn(`[AgentLoop] Unknown tool: ${toolCall.name}`);
|
|
4085
5607
|
}
|
|
@@ -4106,9 +5628,9 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4106
5628
|
});
|
|
4107
5629
|
try {
|
|
4108
5630
|
let response;
|
|
4109
|
-
if (
|
|
4110
|
-
if (
|
|
4111
|
-
response = await
|
|
5631
|
+
if (tool2.location === "server") {
|
|
5632
|
+
if (tool2.handler) {
|
|
5633
|
+
response = await tool2.handler(toolCall.input);
|
|
4112
5634
|
} else if (executeServerTool) {
|
|
4113
5635
|
response = await executeServerTool(toolCall.name, toolCall.input);
|
|
4114
5636
|
} else {
|
|
@@ -4165,6 +5687,6 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4165
5687
|
return results;
|
|
4166
5688
|
}
|
|
4167
5689
|
|
|
4168
|
-
export { AnthropicAdapter, AzureAdapter, DEFAULT_MAX_ITERATIONS, GoogleAdapter,
|
|
5690
|
+
export { AnthropicAdapter, AzureAdapter, DEFAULT_CAPABILITIES, DEFAULT_MAX_ITERATIONS, GoogleAdapter, OllamaAdapter, OpenAIAdapter, Runtime, XAIAdapter, anthropic, anthropicFormatter, createAnthropic, createAnthropicAdapter, createAzure, createAzureAdapter, createEventStream, createExpressMiddleware, createGoogle, createGoogleAdapter, createHonoApp, createNextHandler, createNodeHandler, createOllama, createOllamaAdapter, createOpenAI, createOpenAIAdapter, createRuntime, createSSEHeaders, createSSEResponse, createXAI, createXAIAdapter, formatSSEData, formatToolsForAnthropic, formatToolsForGoogle, formatToolsForOpenAI, geminiFormatter, generateText, getAvailableProviders, getFormatter, getModelCapabilities, getProvider, getSupportedProviders, google, hasProvider, isProviderSupported, listProviders, openai, openaiFormatter, registerProvider, runAgentLoop, streamText, tool, xai };
|
|
4169
5691
|
//# sourceMappingURL=index.mjs.map
|
|
4170
5692
|
//# sourceMappingURL=index.mjs.map
|