@yourgpt/llm-sdk 2.5.1-beta.2 → 2.5.1-beta.4
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/dist/adapters/index.js +16 -0
- package/dist/adapters/index.mjs +16 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +25 -4
- package/dist/index.mjs +25 -4
- package/dist/providers/anthropic/index.js +5 -0
- package/dist/providers/anthropic/index.mjs +5 -0
- package/dist/providers/azure/index.js +5 -0
- package/dist/providers/azure/index.mjs +5 -0
- package/dist/providers/fireworks/index.d.mts +66 -1
- package/dist/providers/fireworks/index.d.ts +66 -1
- package/dist/providers/fireworks/index.js +720 -1
- package/dist/providers/fireworks/index.mjs +718 -1
- package/dist/providers/google/index.js +1 -0
- package/dist/providers/google/index.mjs +1 -0
- package/dist/providers/openai/index.js +1 -0
- package/dist/providers/openai/index.mjs +1 -0
- package/dist/providers/openrouter/index.js +1 -0
- package/dist/providers/openrouter/index.mjs +1 -0
- package/dist/providers/togetherai/index.js +1 -0
- package/dist/providers/togetherai/index.mjs +1 -0
- package/dist/providers/xai/index.js +1 -0
- package/dist/providers/xai/index.mjs +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/adapters/base.ts
|
|
4
|
+
function stringifyForDebug(value) {
|
|
5
|
+
return JSON.stringify(
|
|
6
|
+
value,
|
|
7
|
+
(_key, currentValue) => {
|
|
8
|
+
if (typeof currentValue === "bigint") {
|
|
9
|
+
return currentValue.toString();
|
|
10
|
+
}
|
|
11
|
+
if (currentValue instanceof Error) {
|
|
12
|
+
return {
|
|
13
|
+
name: currentValue.name,
|
|
14
|
+
message: currentValue.message,
|
|
15
|
+
stack: currentValue.stack
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return currentValue;
|
|
19
|
+
},
|
|
20
|
+
2
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
function logProviderPayload(provider, label, payload, enabled) {
|
|
24
|
+
if (!enabled) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (label.toLowerCase().includes("stream ")) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
console.log(
|
|
32
|
+
`[llm-sdk:${provider}] ${label}
|
|
33
|
+
${stringifyForDebug(payload)}`
|
|
34
|
+
);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.log(
|
|
37
|
+
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
38
|
+
error
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function parameterToJsonSchema(param) {
|
|
43
|
+
const schema = {
|
|
44
|
+
type: param.type
|
|
45
|
+
};
|
|
46
|
+
if (param.description) {
|
|
47
|
+
schema.description = param.description;
|
|
48
|
+
}
|
|
49
|
+
if (param.enum) {
|
|
50
|
+
schema.enum = param.enum;
|
|
51
|
+
}
|
|
52
|
+
if (param.type === "array" && param.items) {
|
|
53
|
+
schema.items = parameterToJsonSchema(
|
|
54
|
+
param.items
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
if (param.type === "object" && param.properties) {
|
|
58
|
+
schema.properties = Object.fromEntries(
|
|
59
|
+
Object.entries(param.properties).map(([key, prop]) => [
|
|
60
|
+
key,
|
|
61
|
+
parameterToJsonSchema(
|
|
62
|
+
prop
|
|
63
|
+
)
|
|
64
|
+
])
|
|
65
|
+
);
|
|
66
|
+
schema.additionalProperties = false;
|
|
67
|
+
}
|
|
68
|
+
return schema;
|
|
69
|
+
}
|
|
4
70
|
function normalizeObjectJsonSchema(schema) {
|
|
5
71
|
if (!schema || typeof schema !== "object") {
|
|
6
72
|
return {
|
|
@@ -35,6 +101,16 @@ function normalizeObjectJsonSchema(schema) {
|
|
|
35
101
|
}
|
|
36
102
|
return normalized;
|
|
37
103
|
}
|
|
104
|
+
function isOpenAIReasoningModel(modelId) {
|
|
105
|
+
if (!modelId) return false;
|
|
106
|
+
return /^(o1|o3|o4|gpt-5)/i.test(modelId);
|
|
107
|
+
}
|
|
108
|
+
function buildOpenAITokenParams(modelId, maxTokens, temperature) {
|
|
109
|
+
if (isOpenAIReasoningModel(modelId)) {
|
|
110
|
+
return { max_completion_tokens: maxTokens };
|
|
111
|
+
}
|
|
112
|
+
return { max_tokens: maxTokens, temperature };
|
|
113
|
+
}
|
|
38
114
|
function toOpenAIResponseFormat(rf) {
|
|
39
115
|
if (!rf) return void 0;
|
|
40
116
|
if (rf.type === "json_object") return { type: "json_object" };
|
|
@@ -48,6 +124,111 @@ function toOpenAIResponseFormat(rf) {
|
|
|
48
124
|
}
|
|
49
125
|
};
|
|
50
126
|
}
|
|
127
|
+
function toOpenAIResponsesTextFormat(rf) {
|
|
128
|
+
if (!rf || rf.type !== "json_schema") return void 0;
|
|
129
|
+
return {
|
|
130
|
+
type: "json_schema",
|
|
131
|
+
name: rf.json_schema.name,
|
|
132
|
+
schema: normalizeObjectJsonSchema(rf.json_schema.schema),
|
|
133
|
+
strict: rf.json_schema.strict ?? true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function formatTools(actions) {
|
|
137
|
+
return actions.map((action) => ({
|
|
138
|
+
type: "function",
|
|
139
|
+
function: {
|
|
140
|
+
name: action.name,
|
|
141
|
+
description: action.description,
|
|
142
|
+
parameters: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: action.parameters ? Object.fromEntries(
|
|
145
|
+
Object.entries(action.parameters).map(([key, param]) => [
|
|
146
|
+
key,
|
|
147
|
+
parameterToJsonSchema(param)
|
|
148
|
+
])
|
|
149
|
+
) : {},
|
|
150
|
+
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
151
|
+
additionalProperties: false
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
function hasImageAttachments(message) {
|
|
157
|
+
const attachments = message.metadata?.attachments;
|
|
158
|
+
return attachments?.some((a) => a.type === "image") ?? false;
|
|
159
|
+
}
|
|
160
|
+
function attachmentToOpenAIImage(attachment) {
|
|
161
|
+
if (attachment.type !== "image") return null;
|
|
162
|
+
let imageUrl;
|
|
163
|
+
if (attachment.url) {
|
|
164
|
+
imageUrl = attachment.url;
|
|
165
|
+
} else if (attachment.data) {
|
|
166
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
167
|
+
} else {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
type: "image_url",
|
|
172
|
+
image_url: {
|
|
173
|
+
url: imageUrl,
|
|
174
|
+
detail: "auto"
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function messageToOpenAIContent(message) {
|
|
179
|
+
const attachments = message.metadata?.attachments;
|
|
180
|
+
const content = message.content ?? "";
|
|
181
|
+
if (!hasImageAttachments(message)) {
|
|
182
|
+
return content;
|
|
183
|
+
}
|
|
184
|
+
const blocks = [];
|
|
185
|
+
if (content) {
|
|
186
|
+
blocks.push({ type: "text", text: content });
|
|
187
|
+
}
|
|
188
|
+
if (attachments) {
|
|
189
|
+
for (const attachment of attachments) {
|
|
190
|
+
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
191
|
+
if (imageBlock) {
|
|
192
|
+
blocks.push(imageBlock);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return blocks;
|
|
197
|
+
}
|
|
198
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
199
|
+
const formatted = [];
|
|
200
|
+
if (systemPrompt) {
|
|
201
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
202
|
+
}
|
|
203
|
+
for (const msg of messages) {
|
|
204
|
+
if (msg.role === "system") {
|
|
205
|
+
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
206
|
+
} else if (msg.role === "user") {
|
|
207
|
+
formatted.push({
|
|
208
|
+
role: "user",
|
|
209
|
+
content: messageToOpenAIContent(msg)
|
|
210
|
+
});
|
|
211
|
+
} else if (msg.role === "assistant") {
|
|
212
|
+
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
213
|
+
const assistantMsg = {
|
|
214
|
+
role: "assistant",
|
|
215
|
+
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
216
|
+
content: hasToolCalls ? msg.content || null : msg.content
|
|
217
|
+
};
|
|
218
|
+
if (hasToolCalls) {
|
|
219
|
+
assistantMsg.tool_calls = msg.tool_calls;
|
|
220
|
+
}
|
|
221
|
+
formatted.push(assistantMsg);
|
|
222
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
223
|
+
formatted.push({
|
|
224
|
+
role: "tool",
|
|
225
|
+
content: msg.content ?? "",
|
|
226
|
+
tool_call_id: msg.tool_call_id
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return formatted;
|
|
231
|
+
}
|
|
51
232
|
|
|
52
233
|
// src/providers/fireworks/provider.ts
|
|
53
234
|
function fireworks(modelId, options = {}) {
|
|
@@ -256,7 +437,545 @@ function formatMessages(messages) {
|
|
|
256
437
|
});
|
|
257
438
|
}
|
|
258
439
|
|
|
259
|
-
|
|
440
|
+
// src/core/utils.ts
|
|
441
|
+
function generateId(prefix = "id") {
|
|
442
|
+
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
443
|
+
}
|
|
444
|
+
function generateMessageId() {
|
|
445
|
+
return generateId("msg");
|
|
446
|
+
}
|
|
447
|
+
function generateToolCallId() {
|
|
448
|
+
return generateId("call");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/adapters/openai.ts
|
|
452
|
+
var OpenAIAdapter = class _OpenAIAdapter {
|
|
453
|
+
constructor(config) {
|
|
454
|
+
this.config = config;
|
|
455
|
+
this.model = config.model || "gpt-4o";
|
|
456
|
+
this.provider = _OpenAIAdapter.resolveProviderName(config.baseUrl);
|
|
457
|
+
}
|
|
458
|
+
static resolveProviderName(baseUrl) {
|
|
459
|
+
if (!baseUrl) return "openai";
|
|
460
|
+
if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
|
|
461
|
+
if (baseUrl.includes("x.ai")) return "xai";
|
|
462
|
+
if (baseUrl.includes("azure")) return "azure";
|
|
463
|
+
if (baseUrl.includes("fireworks.ai")) return "fireworks";
|
|
464
|
+
return "openai";
|
|
465
|
+
}
|
|
466
|
+
async getClient() {
|
|
467
|
+
if (!this.client) {
|
|
468
|
+
const { default: OpenAI } = await import('openai');
|
|
469
|
+
this.client = new OpenAI({
|
|
470
|
+
apiKey: this.config.apiKey,
|
|
471
|
+
baseURL: this.config.baseUrl
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
return this.client;
|
|
475
|
+
}
|
|
476
|
+
shouldUseResponsesApi(request) {
|
|
477
|
+
return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
|
|
478
|
+
}
|
|
479
|
+
buildResponsesInput(request) {
|
|
480
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
|
|
481
|
+
const input = [];
|
|
482
|
+
for (const message of sourceMessages) {
|
|
483
|
+
if (message.role === "system") {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (message.role === "assistant") {
|
|
487
|
+
const content = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : message.content ? JSON.stringify(message.content) : "";
|
|
488
|
+
if (content) {
|
|
489
|
+
input.push({
|
|
490
|
+
type: "message",
|
|
491
|
+
role: "assistant",
|
|
492
|
+
content
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
496
|
+
for (const toolCall of toolCalls) {
|
|
497
|
+
input.push({
|
|
498
|
+
type: "function_call",
|
|
499
|
+
call_id: toolCall.id,
|
|
500
|
+
name: toolCall.function?.name,
|
|
501
|
+
arguments: toolCall.function?.arguments ?? "{}"
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
if (message.role === "tool") {
|
|
507
|
+
input.push({
|
|
508
|
+
type: "function_call_output",
|
|
509
|
+
call_id: message.tool_call_id,
|
|
510
|
+
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
511
|
+
});
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
input.push({
|
|
515
|
+
type: "message",
|
|
516
|
+
role: message.role === "developer" ? "developer" : "user",
|
|
517
|
+
content: typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : JSON.stringify(message.content ?? "")
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
return input;
|
|
521
|
+
}
|
|
522
|
+
buildResponsesTools(tools) {
|
|
523
|
+
const nativeTools = tools.filter((tool) => tool.available !== false).map((tool) => ({
|
|
524
|
+
type: "function",
|
|
525
|
+
name: tool.name,
|
|
526
|
+
description: tool.description,
|
|
527
|
+
parameters: normalizeObjectJsonSchema(
|
|
528
|
+
tool.inputSchema ?? {
|
|
529
|
+
type: "object",
|
|
530
|
+
properties: {},
|
|
531
|
+
required: []
|
|
532
|
+
}
|
|
533
|
+
),
|
|
534
|
+
strict: true,
|
|
535
|
+
defer_loading: tool.deferLoading === true
|
|
536
|
+
}));
|
|
537
|
+
return [{ type: "tool_search" }, ...nativeTools];
|
|
538
|
+
}
|
|
539
|
+
parseResponsesResult(response) {
|
|
540
|
+
const content = typeof response?.output_text === "string" ? response.output_text : "";
|
|
541
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => ({
|
|
542
|
+
id: item.call_id ?? item.id ?? generateToolCallId(),
|
|
543
|
+
name: item.name,
|
|
544
|
+
args: (() => {
|
|
545
|
+
try {
|
|
546
|
+
return JSON.parse(item.arguments ?? "{}");
|
|
547
|
+
} catch {
|
|
548
|
+
return {};
|
|
549
|
+
}
|
|
550
|
+
})()
|
|
551
|
+
})) : [];
|
|
552
|
+
return {
|
|
553
|
+
content,
|
|
554
|
+
toolCalls,
|
|
555
|
+
usage: response?.usage ? {
|
|
556
|
+
promptTokens: response.usage.input_tokens ?? 0,
|
|
557
|
+
completionTokens: response.usage.output_tokens ?? 0,
|
|
558
|
+
totalTokens: response.usage.total_tokens ?? (response.usage.input_tokens ?? 0) + (response.usage.output_tokens ?? 0)
|
|
559
|
+
} : void 0,
|
|
560
|
+
rawResponse: response
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
async completeWithResponses(request) {
|
|
564
|
+
const client = await this.getClient();
|
|
565
|
+
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
566
|
+
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
567
|
+
request.config?.responseFormat
|
|
568
|
+
);
|
|
569
|
+
const payload = {
|
|
570
|
+
model: request.config?.model || this.model,
|
|
571
|
+
instructions: request.systemPrompt,
|
|
572
|
+
input: this.buildResponsesInput(request),
|
|
573
|
+
tools: this.buildResponsesTools(request.toolDefinitions ?? []),
|
|
574
|
+
tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
|
|
575
|
+
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
576
|
+
temperature: request.config?.temperature ?? this.config.temperature,
|
|
577
|
+
max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
578
|
+
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
579
|
+
stream: false
|
|
580
|
+
};
|
|
581
|
+
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
582
|
+
const response = await client.responses.create(payload);
|
|
583
|
+
logProviderPayload("openai", "response payload", response, request.debug);
|
|
584
|
+
return this.parseResponsesResult(response);
|
|
585
|
+
}
|
|
586
|
+
async *stream(request) {
|
|
587
|
+
if (this.shouldUseResponsesApi(request)) {
|
|
588
|
+
const messageId2 = generateMessageId();
|
|
589
|
+
yield { type: "message:start", id: messageId2 };
|
|
590
|
+
try {
|
|
591
|
+
const result = await this.completeWithResponses(request);
|
|
592
|
+
if (result.content) {
|
|
593
|
+
yield { type: "message:delta", content: result.content };
|
|
594
|
+
}
|
|
595
|
+
for (const toolCall of result.toolCalls) {
|
|
596
|
+
yield {
|
|
597
|
+
type: "action:start",
|
|
598
|
+
id: toolCall.id,
|
|
599
|
+
name: toolCall.name
|
|
600
|
+
};
|
|
601
|
+
yield {
|
|
602
|
+
type: "action:args",
|
|
603
|
+
id: toolCall.id,
|
|
604
|
+
args: JSON.stringify(toolCall.args)
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
yield { type: "message:end" };
|
|
608
|
+
yield {
|
|
609
|
+
type: "done",
|
|
610
|
+
usage: result.usage ? {
|
|
611
|
+
prompt_tokens: result.usage.promptTokens,
|
|
612
|
+
completion_tokens: result.usage.completionTokens,
|
|
613
|
+
total_tokens: result.usage.totalTokens
|
|
614
|
+
} : void 0
|
|
615
|
+
};
|
|
616
|
+
return;
|
|
617
|
+
} catch (error) {
|
|
618
|
+
yield {
|
|
619
|
+
type: "error",
|
|
620
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
621
|
+
code: "OPENAI_RESPONSES_ERROR"
|
|
622
|
+
};
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
const client = await this.getClient();
|
|
627
|
+
let messages;
|
|
628
|
+
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
629
|
+
const processedMessages = request.rawMessages.map((msg) => {
|
|
630
|
+
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
|
|
631
|
+
return { ...msg, content: null };
|
|
632
|
+
}
|
|
633
|
+
const hasAttachments = msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0;
|
|
634
|
+
if (hasAttachments) {
|
|
635
|
+
const content = [];
|
|
636
|
+
if (msg.content) {
|
|
637
|
+
content.push({ type: "text", text: msg.content });
|
|
638
|
+
}
|
|
639
|
+
for (const attachment of msg.attachments) {
|
|
640
|
+
if (attachment.type === "image") {
|
|
641
|
+
let imageUrl;
|
|
642
|
+
if (attachment.url) {
|
|
643
|
+
imageUrl = attachment.url;
|
|
644
|
+
} else if (attachment.data) {
|
|
645
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
646
|
+
} else {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
content.push({
|
|
650
|
+
type: "image_url",
|
|
651
|
+
image_url: { url: imageUrl, detail: "auto" }
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return { ...msg, content, attachments: void 0 };
|
|
656
|
+
}
|
|
657
|
+
return msg;
|
|
658
|
+
});
|
|
659
|
+
if (request.systemPrompt) {
|
|
660
|
+
const hasSystem = processedMessages.some((m) => m.role === "system");
|
|
661
|
+
if (!hasSystem) {
|
|
662
|
+
messages = [
|
|
663
|
+
{ role: "system", content: request.systemPrompt },
|
|
664
|
+
...processedMessages
|
|
665
|
+
];
|
|
666
|
+
} else {
|
|
667
|
+
messages = processedMessages;
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
messages = processedMessages;
|
|
671
|
+
}
|
|
672
|
+
} else {
|
|
673
|
+
messages = formatMessagesForOpenAI(
|
|
674
|
+
request.messages,
|
|
675
|
+
request.systemPrompt
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
const tools = request.actions?.length ? formatTools(request.actions) : [];
|
|
679
|
+
const webSearchConfig = request.webSearch ?? this.config.webSearch;
|
|
680
|
+
if (webSearchConfig) {
|
|
681
|
+
const webSearchTool = {
|
|
682
|
+
type: "web_search_preview"
|
|
683
|
+
};
|
|
684
|
+
const wsConfig = typeof webSearchConfig === "object" ? webSearchConfig : {};
|
|
685
|
+
if (wsConfig.userLocation) {
|
|
686
|
+
webSearchTool.search_context_size = "medium";
|
|
687
|
+
}
|
|
688
|
+
tools.push(webSearchTool);
|
|
689
|
+
}
|
|
690
|
+
const messageId = generateMessageId();
|
|
691
|
+
yield { type: "message:start", id: messageId };
|
|
692
|
+
try {
|
|
693
|
+
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
694
|
+
const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
|
|
695
|
+
type: "function",
|
|
696
|
+
function: {
|
|
697
|
+
name: openaiToolOptions.toolChoice.name
|
|
698
|
+
}
|
|
699
|
+
} : openaiToolOptions?.toolChoice;
|
|
700
|
+
const modelIdForPayload = request.config?.model || this.model;
|
|
701
|
+
const payload = {
|
|
702
|
+
model: modelIdForPayload,
|
|
703
|
+
messages,
|
|
704
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
705
|
+
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
706
|
+
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
707
|
+
...buildOpenAITokenParams(
|
|
708
|
+
modelIdForPayload,
|
|
709
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
710
|
+
request.config?.temperature ?? this.config.temperature
|
|
711
|
+
),
|
|
712
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
713
|
+
stream: true,
|
|
714
|
+
stream_options: { include_usage: true }
|
|
715
|
+
};
|
|
716
|
+
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
717
|
+
const stream = await client.chat.completions.create(payload);
|
|
718
|
+
let currentToolCall = null;
|
|
719
|
+
const collectedCitations = [];
|
|
720
|
+
let citationIndex = 0;
|
|
721
|
+
let usage;
|
|
722
|
+
for await (const chunk of stream) {
|
|
723
|
+
logProviderPayload("openai", "stream chunk", chunk, request.debug);
|
|
724
|
+
if (request.signal?.aborted) {
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
const delta = chunk.choices[0]?.delta;
|
|
728
|
+
const choice = chunk.choices[0];
|
|
729
|
+
if (delta?.content) {
|
|
730
|
+
yield { type: "message:delta", content: delta.content };
|
|
731
|
+
}
|
|
732
|
+
const annotations = delta?.annotations;
|
|
733
|
+
if (annotations && annotations.length > 0) {
|
|
734
|
+
for (const annotation of annotations) {
|
|
735
|
+
if (annotation.type === "url_citation" && annotation.url_citation?.url) {
|
|
736
|
+
citationIndex++;
|
|
737
|
+
const url = annotation.url_citation.url;
|
|
738
|
+
const domain = extractDomain(url);
|
|
739
|
+
collectedCitations.push({
|
|
740
|
+
index: citationIndex,
|
|
741
|
+
url,
|
|
742
|
+
title: annotation.url_citation.title || domain,
|
|
743
|
+
domain,
|
|
744
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (delta?.tool_calls) {
|
|
750
|
+
for (const toolCall of delta.tool_calls) {
|
|
751
|
+
if (toolCall.id) {
|
|
752
|
+
if (currentToolCall) {
|
|
753
|
+
yield {
|
|
754
|
+
type: "action:args",
|
|
755
|
+
id: currentToolCall.id,
|
|
756
|
+
args: currentToolCall.arguments
|
|
757
|
+
};
|
|
758
|
+
yield {
|
|
759
|
+
type: "action:end",
|
|
760
|
+
id: currentToolCall.id,
|
|
761
|
+
name: currentToolCall.name
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
const tcExtraContent = toolCall.extra_content;
|
|
765
|
+
currentToolCall = {
|
|
766
|
+
id: toolCall.id,
|
|
767
|
+
name: toolCall.function?.name || "",
|
|
768
|
+
arguments: toolCall.function?.arguments || "",
|
|
769
|
+
...tcExtraContent ? { extra_content: tcExtraContent } : {}
|
|
770
|
+
};
|
|
771
|
+
yield {
|
|
772
|
+
type: "action:start",
|
|
773
|
+
id: currentToolCall.id,
|
|
774
|
+
name: currentToolCall.name,
|
|
775
|
+
...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
|
|
776
|
+
};
|
|
777
|
+
} else if (currentToolCall && toolCall.function?.arguments) {
|
|
778
|
+
currentToolCall.arguments += toolCall.function.arguments;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (chunk.usage) {
|
|
783
|
+
usage = {
|
|
784
|
+
prompt_tokens: chunk.usage.prompt_tokens,
|
|
785
|
+
completion_tokens: chunk.usage.completion_tokens,
|
|
786
|
+
total_tokens: chunk.usage.total_tokens
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
if (choice?.finish_reason) {
|
|
790
|
+
if (currentToolCall) {
|
|
791
|
+
yield {
|
|
792
|
+
type: "action:args",
|
|
793
|
+
id: currentToolCall.id,
|
|
794
|
+
args: currentToolCall.arguments
|
|
795
|
+
};
|
|
796
|
+
yield {
|
|
797
|
+
type: "action:end",
|
|
798
|
+
id: currentToolCall.id,
|
|
799
|
+
name: currentToolCall.name
|
|
800
|
+
};
|
|
801
|
+
currentToolCall = null;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
if (collectedCitations.length > 0) {
|
|
806
|
+
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
807
|
+
yield { type: "citation", citations: uniqueCitations };
|
|
808
|
+
}
|
|
809
|
+
yield { type: "message:end" };
|
|
810
|
+
yield { type: "done", usage };
|
|
811
|
+
} catch (error) {
|
|
812
|
+
yield {
|
|
813
|
+
type: "error",
|
|
814
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
815
|
+
code: `${this.provider.toUpperCase()}_ERROR`
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
async complete(request) {
|
|
820
|
+
if (this.shouldUseResponsesApi(request)) {
|
|
821
|
+
return this.completeWithResponses(request);
|
|
822
|
+
}
|
|
823
|
+
const client = await this.getClient();
|
|
824
|
+
let messages;
|
|
825
|
+
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
826
|
+
const sanitized = request.rawMessages.map((msg) => {
|
|
827
|
+
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
|
|
828
|
+
return { ...msg, content: null };
|
|
829
|
+
}
|
|
830
|
+
return msg;
|
|
831
|
+
});
|
|
832
|
+
if (request.systemPrompt && !sanitized.some((message2) => message2.role === "system")) {
|
|
833
|
+
messages = [
|
|
834
|
+
{ role: "system", content: request.systemPrompt },
|
|
835
|
+
...sanitized
|
|
836
|
+
];
|
|
837
|
+
} else {
|
|
838
|
+
messages = sanitized;
|
|
839
|
+
}
|
|
840
|
+
} else {
|
|
841
|
+
messages = formatMessagesForOpenAI(
|
|
842
|
+
request.messages,
|
|
843
|
+
request.systemPrompt
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
const tools = request.actions?.length ? formatTools(request.actions) : [];
|
|
847
|
+
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
848
|
+
const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
|
|
849
|
+
type: "function",
|
|
850
|
+
function: {
|
|
851
|
+
name: openaiToolOptions.toolChoice.name
|
|
852
|
+
}
|
|
853
|
+
} : openaiToolOptions?.toolChoice;
|
|
854
|
+
const modelIdForCompletePayload = request.config?.model || this.model;
|
|
855
|
+
const payload = {
|
|
856
|
+
model: modelIdForCompletePayload,
|
|
857
|
+
messages,
|
|
858
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
859
|
+
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
860
|
+
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
861
|
+
...buildOpenAITokenParams(
|
|
862
|
+
modelIdForCompletePayload,
|
|
863
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
864
|
+
request.config?.temperature ?? this.config.temperature
|
|
865
|
+
),
|
|
866
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
867
|
+
stream: false
|
|
868
|
+
};
|
|
869
|
+
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
870
|
+
const response = await client.chat.completions.create(payload);
|
|
871
|
+
logProviderPayload("openai", "response payload", response, request.debug);
|
|
872
|
+
const choice = response.choices?.[0];
|
|
873
|
+
const message = choice?.message;
|
|
874
|
+
return {
|
|
875
|
+
content: message?.content ?? "",
|
|
876
|
+
toolCalls: message?.tool_calls?.map((toolCall) => ({
|
|
877
|
+
id: toolCall.id ?? generateToolCallId(),
|
|
878
|
+
name: toolCall.function?.name ?? "",
|
|
879
|
+
args: (() => {
|
|
880
|
+
try {
|
|
881
|
+
return JSON.parse(toolCall.function?.arguments ?? "{}");
|
|
882
|
+
} catch {
|
|
883
|
+
return {};
|
|
884
|
+
}
|
|
885
|
+
})(),
|
|
886
|
+
...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
|
|
887
|
+
})) ?? [],
|
|
888
|
+
usage: response.usage ? {
|
|
889
|
+
promptTokens: response.usage.prompt_tokens,
|
|
890
|
+
completionTokens: response.usage.completion_tokens,
|
|
891
|
+
totalTokens: response.usage.total_tokens
|
|
892
|
+
} : void 0,
|
|
893
|
+
rawResponse: response
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
function extractDomain(url) {
|
|
898
|
+
try {
|
|
899
|
+
const parsed = new URL(url);
|
|
900
|
+
return parsed.hostname;
|
|
901
|
+
} catch {
|
|
902
|
+
return "";
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
function deduplicateCitations(citations) {
|
|
906
|
+
const seen = /* @__PURE__ */ new Map();
|
|
907
|
+
let index = 0;
|
|
908
|
+
for (const citation of citations) {
|
|
909
|
+
if (!seen.has(citation.url)) {
|
|
910
|
+
index++;
|
|
911
|
+
seen.set(citation.url, { ...citation, index });
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
return Array.from(seen.values());
|
|
915
|
+
}
|
|
916
|
+
function createOpenAIAdapter(config) {
|
|
917
|
+
return new OpenAIAdapter(config);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// src/providers/types.ts
|
|
921
|
+
function createCallableProvider(providerFn, properties) {
|
|
922
|
+
Object.defineProperty(providerFn, "name", {
|
|
923
|
+
value: properties.name,
|
|
924
|
+
writable: false,
|
|
925
|
+
configurable: true
|
|
926
|
+
});
|
|
927
|
+
Object.assign(providerFn, {
|
|
928
|
+
supportedModels: properties.supportedModels,
|
|
929
|
+
languageModel: providerFn,
|
|
930
|
+
getCapabilities: properties.getCapabilities,
|
|
931
|
+
embeddingModel: properties.embeddingModel
|
|
932
|
+
});
|
|
933
|
+
return providerFn;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// src/providers/fireworks/index.ts
|
|
937
|
+
var DEFAULT_CAPABILITIES = {
|
|
938
|
+
vision: false,
|
|
939
|
+
tools: true,
|
|
940
|
+
jsonMode: true,
|
|
941
|
+
maxTokens: 131072
|
|
942
|
+
};
|
|
943
|
+
function createFireworks(config = {}) {
|
|
944
|
+
const apiKey = config.apiKey ?? process.env.FIREWORKS_API_KEY ?? "";
|
|
945
|
+
const baseUrl = config.baseUrl ?? "https://api.fireworks.ai/inference/v1";
|
|
946
|
+
const providerFn = (modelId) => {
|
|
947
|
+
return createOpenAIAdapter({
|
|
948
|
+
apiKey,
|
|
949
|
+
model: modelId,
|
|
950
|
+
baseUrl
|
|
951
|
+
});
|
|
952
|
+
};
|
|
953
|
+
const getCapabilities = (_modelId) => {
|
|
954
|
+
return {
|
|
955
|
+
supportsVision: DEFAULT_CAPABILITIES.vision,
|
|
956
|
+
supportsTools: DEFAULT_CAPABILITIES.tools,
|
|
957
|
+
supportsThinking: false,
|
|
958
|
+
supportsStreaming: true,
|
|
959
|
+
supportsPDF: false,
|
|
960
|
+
supportsAudio: false,
|
|
961
|
+
supportsVideo: false,
|
|
962
|
+
maxTokens: DEFAULT_CAPABILITIES.maxTokens,
|
|
963
|
+
supportedImageTypes: [],
|
|
964
|
+
supportsJsonMode: DEFAULT_CAPABILITIES.jsonMode,
|
|
965
|
+
supportsSystemMessages: true
|
|
966
|
+
};
|
|
967
|
+
};
|
|
968
|
+
return createCallableProvider(providerFn, {
|
|
969
|
+
name: "fireworks",
|
|
970
|
+
supportedModels: [],
|
|
971
|
+
getCapabilities
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
var createFireworksProvider = createFireworks;
|
|
975
|
+
|
|
976
|
+
exports.createFireworks = createFireworks;
|
|
977
|
+
exports.createFireworksModel = fireworks;
|
|
978
|
+
exports.createFireworksProvider = createFireworksProvider;
|
|
260
979
|
exports.fireworks = fireworks;
|
|
261
980
|
//# sourceMappingURL=index.js.map
|
|
262
981
|
//# sourceMappingURL=index.js.map
|