@yourgpt/llm-sdk 2.5.0 → 2.5.1-beta.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 +19 -1
- package/dist/adapters/index.d.mts +4 -4
- package/dist/adapters/index.d.ts +4 -4
- package/dist/adapters/index.js +293 -23
- package/dist/adapters/index.mjs +293 -23
- package/dist/base-BYQKp9TW.d.mts +263 -0
- package/dist/base-Cxq3ni0t.d.ts +263 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/index.d.mts +61 -8
- package/dist/index.d.ts +61 -8
- package/dist/index.js +71 -0
- package/dist/index.mjs +71 -0
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +360 -203
- package/dist/providers/anthropic/index.mjs +360 -203
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +49 -1
- package/dist/providers/azure/index.mjs +49 -1
- package/dist/providers/fireworks/index.d.mts +1 -1
- package/dist/providers/fireworks/index.d.ts +1 -1
- package/dist/providers/fireworks/index.js +56 -0
- package/dist/providers/fireworks/index.mjs +56 -0
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +303 -207
- package/dist/providers/google/index.mjs +303 -207
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/ollama/index.js +10 -2
- package/dist/providers/ollama/index.mjs +10 -2
- package/dist/providers/openai/index.d.mts +3 -3
- package/dist/providers/openai/index.d.ts +3 -3
- package/dist/providers/openai/index.js +318 -216
- package/dist/providers/openai/index.mjs +318 -216
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +308 -206
- package/dist/providers/openrouter/index.mjs +308 -206
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +308 -206
- package/dist/providers/togetherai/index.mjs +308 -206
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +307 -210
- package/dist/providers/xai/index.mjs +307 -210
- package/dist/{types-BctsnC3g.d.ts → types-BvkiJ1dd.d.mts} +2 -1
- package/dist/{types-38yolWJn.d.ts → types-ChORafYS.d.ts} +1 -1
- package/dist/types-D774b0dg.d.mts +1018 -0
- package/dist/types-D774b0dg.d.ts +1018 -0
- package/dist/{types-DRqxMIjF.d.mts → types-TMilS-Dz.d.ts} +2 -1
- package/dist/{types-D4YfrQJR.d.mts → types-mwMhCwOq.d.mts} +1 -1
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/base-D-U61JaB.d.mts +0 -788
- package/dist/base-iGi9Va6Z.d.ts +0 -788
- package/dist/types-CR8mi9I0.d.mts +0 -417
- package/dist/types-CR8mi9I0.d.ts +0 -417
|
@@ -1,5 +1,261 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
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
|
+
}
|
|
70
|
+
function normalizeObjectJsonSchema(schema) {
|
|
71
|
+
if (!schema || typeof schema !== "object") {
|
|
72
|
+
return {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {},
|
|
75
|
+
required: [],
|
|
76
|
+
additionalProperties: false
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const normalized = { ...schema };
|
|
80
|
+
const type = normalized.type;
|
|
81
|
+
if (type === "object") {
|
|
82
|
+
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
83
|
+
normalized.properties = Object.fromEntries(
|
|
84
|
+
Object.entries(properties).map(([key, value]) => [
|
|
85
|
+
key,
|
|
86
|
+
normalizeObjectJsonSchema(value)
|
|
87
|
+
])
|
|
88
|
+
);
|
|
89
|
+
const propertyKeys = Object.keys(properties);
|
|
90
|
+
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
91
|
+
(value) => typeof value === "string"
|
|
92
|
+
) : [];
|
|
93
|
+
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
94
|
+
if (normalized.additionalProperties === void 0) {
|
|
95
|
+
normalized.additionalProperties = false;
|
|
96
|
+
}
|
|
97
|
+
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
98
|
+
normalized.items = normalizeObjectJsonSchema(
|
|
99
|
+
normalized.items
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
return normalized;
|
|
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
|
+
}
|
|
114
|
+
function toOpenAIResponseFormat(rf) {
|
|
115
|
+
if (!rf) return void 0;
|
|
116
|
+
if (rf.type === "json_object") return { type: "json_object" };
|
|
117
|
+
return {
|
|
118
|
+
type: "json_schema",
|
|
119
|
+
json_schema: {
|
|
120
|
+
name: rf.json_schema.name,
|
|
121
|
+
schema: normalizeObjectJsonSchema(rf.json_schema.schema),
|
|
122
|
+
strict: rf.json_schema.strict ?? true
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function toOpenAIResponsesTextFormat(rf) {
|
|
127
|
+
if (!rf || rf.type !== "json_schema") return void 0;
|
|
128
|
+
return {
|
|
129
|
+
type: "json_schema",
|
|
130
|
+
name: rf.json_schema.name,
|
|
131
|
+
schema: normalizeObjectJsonSchema(rf.json_schema.schema),
|
|
132
|
+
strict: rf.json_schema.strict ?? true
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function toOpenAIResponsesMcpTools(mcpServers) {
|
|
136
|
+
if (!mcpServers || mcpServers.length === 0) return [];
|
|
137
|
+
return mcpServers.map((mcp) => ({
|
|
138
|
+
type: "mcp",
|
|
139
|
+
server_label: mcp.label,
|
|
140
|
+
server_url: mcp.url,
|
|
141
|
+
...mcp.headers ? { headers: mcp.headers } : {},
|
|
142
|
+
...mcp.allowedTools ? { allowed_tools: mcp.allowedTools } : {},
|
|
143
|
+
require_approval: mcp.requireApproval ?? "never"
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
function isStringEffort(effort) {
|
|
147
|
+
return typeof effort === "string" && (effort === "minimal" || effort === "low" || effort === "medium" || effort === "high");
|
|
148
|
+
}
|
|
149
|
+
function toOpenAIReasoning(effort) {
|
|
150
|
+
if (!effort) return void 0;
|
|
151
|
+
if (typeof effort === "object" && "raw" in effort) return effort.raw;
|
|
152
|
+
if (typeof effort === "object" && "budgetTokens" in effort) {
|
|
153
|
+
const budget = effort.budgetTokens;
|
|
154
|
+
const mapped = budget >= 16e3 ? "high" : budget >= 8e3 ? "medium" : "low";
|
|
155
|
+
return { effort: mapped, summary: "auto" };
|
|
156
|
+
}
|
|
157
|
+
if (isStringEffort(effort)) {
|
|
158
|
+
return { effort, summary: "auto" };
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
function formatTools(actions) {
|
|
163
|
+
return actions.map((action) => ({
|
|
164
|
+
type: "function",
|
|
165
|
+
function: {
|
|
166
|
+
name: action.name,
|
|
167
|
+
description: action.description,
|
|
168
|
+
parameters: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: action.parameters ? Object.fromEntries(
|
|
171
|
+
Object.entries(action.parameters).map(([key, param]) => [
|
|
172
|
+
key,
|
|
173
|
+
parameterToJsonSchema(param)
|
|
174
|
+
])
|
|
175
|
+
) : {},
|
|
176
|
+
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
177
|
+
additionalProperties: false
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
function hasImageAttachments(message) {
|
|
183
|
+
const attachments = message.metadata?.attachments;
|
|
184
|
+
return attachments?.some((a) => a.type === "image") ?? false;
|
|
185
|
+
}
|
|
186
|
+
function attachmentToOpenAIImage(attachment) {
|
|
187
|
+
if (attachment.type !== "image") return null;
|
|
188
|
+
let imageUrl;
|
|
189
|
+
if (attachment.url) {
|
|
190
|
+
imageUrl = attachment.url;
|
|
191
|
+
} else if (attachment.data) {
|
|
192
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
193
|
+
} else {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
type: "image_url",
|
|
198
|
+
image_url: {
|
|
199
|
+
url: imageUrl,
|
|
200
|
+
detail: "auto"
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function messageToOpenAIContent(message) {
|
|
205
|
+
const attachments = message.metadata?.attachments;
|
|
206
|
+
const content = message.content ?? "";
|
|
207
|
+
if (!hasImageAttachments(message)) {
|
|
208
|
+
return content;
|
|
209
|
+
}
|
|
210
|
+
const blocks = [];
|
|
211
|
+
if (content) {
|
|
212
|
+
blocks.push({ type: "text", text: content });
|
|
213
|
+
}
|
|
214
|
+
if (attachments) {
|
|
215
|
+
for (const attachment of attachments) {
|
|
216
|
+
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
217
|
+
if (imageBlock) {
|
|
218
|
+
blocks.push(imageBlock);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return blocks;
|
|
223
|
+
}
|
|
224
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
225
|
+
const formatted = [];
|
|
226
|
+
if (systemPrompt) {
|
|
227
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
228
|
+
}
|
|
229
|
+
for (const msg of messages) {
|
|
230
|
+
if (msg.role === "system") {
|
|
231
|
+
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
232
|
+
} else if (msg.role === "user") {
|
|
233
|
+
formatted.push({
|
|
234
|
+
role: "user",
|
|
235
|
+
content: messageToOpenAIContent(msg)
|
|
236
|
+
});
|
|
237
|
+
} else if (msg.role === "assistant") {
|
|
238
|
+
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
239
|
+
const assistantMsg = {
|
|
240
|
+
role: "assistant",
|
|
241
|
+
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
242
|
+
content: hasToolCalls ? msg.content || null : msg.content
|
|
243
|
+
};
|
|
244
|
+
if (hasToolCalls) {
|
|
245
|
+
assistantMsg.tool_calls = msg.tool_calls;
|
|
246
|
+
}
|
|
247
|
+
formatted.push(assistantMsg);
|
|
248
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
249
|
+
formatted.push({
|
|
250
|
+
role: "tool",
|
|
251
|
+
content: msg.content ?? "",
|
|
252
|
+
tool_call_id: msg.tool_call_id
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return formatted;
|
|
257
|
+
}
|
|
258
|
+
|
|
3
259
|
// src/providers/google/provider.ts
|
|
4
260
|
var GOOGLE_MODELS = {
|
|
5
261
|
// Gemini 2.5 (Experimental)
|
|
@@ -119,7 +375,8 @@ function google(modelId, options = {}) {
|
|
|
119
375
|
messages,
|
|
120
376
|
tools: params.tools,
|
|
121
377
|
temperature: params.temperature,
|
|
122
|
-
max_tokens: params.maxTokens
|
|
378
|
+
max_tokens: params.maxTokens,
|
|
379
|
+
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
123
380
|
});
|
|
124
381
|
const choice = response.choices[0];
|
|
125
382
|
const message = choice.message;
|
|
@@ -151,6 +408,7 @@ function google(modelId, options = {}) {
|
|
|
151
408
|
tools: params.tools,
|
|
152
409
|
temperature: params.temperature,
|
|
153
410
|
max_tokens: params.maxTokens,
|
|
411
|
+
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
154
412
|
stream: true
|
|
155
413
|
});
|
|
156
414
|
let currentToolCall = null;
|
|
@@ -296,204 +554,6 @@ function generateToolCallId() {
|
|
|
296
554
|
return generateId("call");
|
|
297
555
|
}
|
|
298
556
|
|
|
299
|
-
// src/adapters/base.ts
|
|
300
|
-
function stringifyForDebug(value) {
|
|
301
|
-
return JSON.stringify(
|
|
302
|
-
value,
|
|
303
|
-
(_key, currentValue) => {
|
|
304
|
-
if (typeof currentValue === "bigint") {
|
|
305
|
-
return currentValue.toString();
|
|
306
|
-
}
|
|
307
|
-
if (currentValue instanceof Error) {
|
|
308
|
-
return {
|
|
309
|
-
name: currentValue.name,
|
|
310
|
-
message: currentValue.message,
|
|
311
|
-
stack: currentValue.stack
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
return currentValue;
|
|
315
|
-
},
|
|
316
|
-
2
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
function logProviderPayload(provider, label, payload, enabled) {
|
|
320
|
-
if (!enabled) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (label.toLowerCase().includes("stream ")) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
try {
|
|
327
|
-
console.log(
|
|
328
|
-
`[llm-sdk:${provider}] ${label}
|
|
329
|
-
${stringifyForDebug(payload)}`
|
|
330
|
-
);
|
|
331
|
-
} catch (error) {
|
|
332
|
-
console.log(
|
|
333
|
-
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
334
|
-
error
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
function parameterToJsonSchema(param) {
|
|
339
|
-
const schema = {
|
|
340
|
-
type: param.type
|
|
341
|
-
};
|
|
342
|
-
if (param.description) {
|
|
343
|
-
schema.description = param.description;
|
|
344
|
-
}
|
|
345
|
-
if (param.enum) {
|
|
346
|
-
schema.enum = param.enum;
|
|
347
|
-
}
|
|
348
|
-
if (param.type === "array" && param.items) {
|
|
349
|
-
schema.items = parameterToJsonSchema(
|
|
350
|
-
param.items
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
if (param.type === "object" && param.properties) {
|
|
354
|
-
schema.properties = Object.fromEntries(
|
|
355
|
-
Object.entries(param.properties).map(([key, prop]) => [
|
|
356
|
-
key,
|
|
357
|
-
parameterToJsonSchema(
|
|
358
|
-
prop
|
|
359
|
-
)
|
|
360
|
-
])
|
|
361
|
-
);
|
|
362
|
-
schema.additionalProperties = false;
|
|
363
|
-
}
|
|
364
|
-
return schema;
|
|
365
|
-
}
|
|
366
|
-
function normalizeObjectJsonSchema(schema) {
|
|
367
|
-
if (!schema || typeof schema !== "object") {
|
|
368
|
-
return {
|
|
369
|
-
type: "object",
|
|
370
|
-
properties: {},
|
|
371
|
-
required: [],
|
|
372
|
-
additionalProperties: false
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
const normalized = { ...schema };
|
|
376
|
-
const type = normalized.type;
|
|
377
|
-
if (type === "object") {
|
|
378
|
-
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
379
|
-
normalized.properties = Object.fromEntries(
|
|
380
|
-
Object.entries(properties).map(([key, value]) => [
|
|
381
|
-
key,
|
|
382
|
-
normalizeObjectJsonSchema(value)
|
|
383
|
-
])
|
|
384
|
-
);
|
|
385
|
-
const propertyKeys = Object.keys(properties);
|
|
386
|
-
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
387
|
-
(value) => typeof value === "string"
|
|
388
|
-
) : [];
|
|
389
|
-
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
390
|
-
if (normalized.additionalProperties === void 0) {
|
|
391
|
-
normalized.additionalProperties = false;
|
|
392
|
-
}
|
|
393
|
-
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
394
|
-
normalized.items = normalizeObjectJsonSchema(
|
|
395
|
-
normalized.items
|
|
396
|
-
);
|
|
397
|
-
}
|
|
398
|
-
return normalized;
|
|
399
|
-
}
|
|
400
|
-
function formatTools(actions) {
|
|
401
|
-
return actions.map((action) => ({
|
|
402
|
-
type: "function",
|
|
403
|
-
function: {
|
|
404
|
-
name: action.name,
|
|
405
|
-
description: action.description,
|
|
406
|
-
parameters: {
|
|
407
|
-
type: "object",
|
|
408
|
-
properties: action.parameters ? Object.fromEntries(
|
|
409
|
-
Object.entries(action.parameters).map(([key, param]) => [
|
|
410
|
-
key,
|
|
411
|
-
parameterToJsonSchema(param)
|
|
412
|
-
])
|
|
413
|
-
) : {},
|
|
414
|
-
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
415
|
-
additionalProperties: false
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}));
|
|
419
|
-
}
|
|
420
|
-
function hasImageAttachments(message) {
|
|
421
|
-
const attachments = message.metadata?.attachments;
|
|
422
|
-
return attachments?.some((a) => a.type === "image") ?? false;
|
|
423
|
-
}
|
|
424
|
-
function attachmentToOpenAIImage(attachment) {
|
|
425
|
-
if (attachment.type !== "image") return null;
|
|
426
|
-
let imageUrl;
|
|
427
|
-
if (attachment.url) {
|
|
428
|
-
imageUrl = attachment.url;
|
|
429
|
-
} else if (attachment.data) {
|
|
430
|
-
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
431
|
-
} else {
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
return {
|
|
435
|
-
type: "image_url",
|
|
436
|
-
image_url: {
|
|
437
|
-
url: imageUrl,
|
|
438
|
-
detail: "auto"
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
function messageToOpenAIContent(message) {
|
|
443
|
-
const attachments = message.metadata?.attachments;
|
|
444
|
-
const content = message.content ?? "";
|
|
445
|
-
if (!hasImageAttachments(message)) {
|
|
446
|
-
return content;
|
|
447
|
-
}
|
|
448
|
-
const blocks = [];
|
|
449
|
-
if (content) {
|
|
450
|
-
blocks.push({ type: "text", text: content });
|
|
451
|
-
}
|
|
452
|
-
if (attachments) {
|
|
453
|
-
for (const attachment of attachments) {
|
|
454
|
-
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
455
|
-
if (imageBlock) {
|
|
456
|
-
blocks.push(imageBlock);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
return blocks;
|
|
461
|
-
}
|
|
462
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
463
|
-
const formatted = [];
|
|
464
|
-
if (systemPrompt) {
|
|
465
|
-
formatted.push({ role: "system", content: systemPrompt });
|
|
466
|
-
}
|
|
467
|
-
for (const msg of messages) {
|
|
468
|
-
if (msg.role === "system") {
|
|
469
|
-
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
470
|
-
} else if (msg.role === "user") {
|
|
471
|
-
formatted.push({
|
|
472
|
-
role: "user",
|
|
473
|
-
content: messageToOpenAIContent(msg)
|
|
474
|
-
});
|
|
475
|
-
} else if (msg.role === "assistant") {
|
|
476
|
-
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
477
|
-
const assistantMsg = {
|
|
478
|
-
role: "assistant",
|
|
479
|
-
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
480
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
481
|
-
};
|
|
482
|
-
if (hasToolCalls) {
|
|
483
|
-
assistantMsg.tool_calls = msg.tool_calls;
|
|
484
|
-
}
|
|
485
|
-
formatted.push(assistantMsg);
|
|
486
|
-
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
487
|
-
formatted.push({
|
|
488
|
-
role: "tool",
|
|
489
|
-
content: msg.content ?? "",
|
|
490
|
-
tool_call_id: msg.tool_call_id
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
return formatted;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
557
|
// src/adapters/openai.ts
|
|
498
558
|
var OpenAIAdapter = class _OpenAIAdapter {
|
|
499
559
|
constructor(config) {
|
|
@@ -519,6 +579,14 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
519
579
|
return this.client;
|
|
520
580
|
}
|
|
521
581
|
shouldUseResponsesApi(request) {
|
|
582
|
+
if (request.config?.mcpServers && request.config.mcpServers.length > 0 || request.config?.reasoningEffort !== void 0) {
|
|
583
|
+
if (this.provider !== "openai" && this.provider !== "azure") {
|
|
584
|
+
throw new Error(
|
|
585
|
+
`[llm-sdk] Provider "${this.provider}" does not support MCP servers or per-request reasoning effort. Use OpenAI or Anthropic for these features.`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
522
590
|
return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
|
|
523
591
|
}
|
|
524
592
|
buildResponsesInput(request) {
|
|
@@ -579,7 +647,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
579
647
|
strict: true,
|
|
580
648
|
defer_loading: tool.deferLoading === true
|
|
581
649
|
}));
|
|
582
|
-
return [{ type: "tool_search" }, ...nativeTools];
|
|
650
|
+
return nativeTools.length > 0 ? [{ type: "tool_search" }, ...nativeTools] : [];
|
|
583
651
|
}
|
|
584
652
|
parseResponsesResult(response) {
|
|
585
653
|
const content = typeof response?.output_text === "string" ? response.output_text : "";
|
|
@@ -608,15 +676,33 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
608
676
|
async completeWithResponses(request) {
|
|
609
677
|
const client = await this.getClient();
|
|
610
678
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
679
|
+
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
680
|
+
request.config?.responseFormat
|
|
681
|
+
);
|
|
682
|
+
const mcpTools = toOpenAIResponsesMcpTools(request.config?.mcpServers);
|
|
683
|
+
const modelId = request.config?.model || this.model;
|
|
684
|
+
const reasoning = isOpenAIReasoningModel(modelId) ? toOpenAIReasoning(request.config?.reasoningEffort) : void 0;
|
|
685
|
+
if (request.config?.reasoningEffort && !isOpenAIReasoningModel(modelId)) {
|
|
686
|
+
console.warn(
|
|
687
|
+
`[llm-sdk] openai/${modelId} is not a reasoning model; \`reasoningEffort\` is ignored. Use o1/o3/o4/gpt-5.x for reasoning.`
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
const functionTools = this.buildResponsesTools(
|
|
691
|
+
request.toolDefinitions ?? []
|
|
692
|
+
);
|
|
693
|
+
const tools = [...functionTools, ...mcpTools];
|
|
611
694
|
const payload = {
|
|
612
695
|
model: request.config?.model || this.model,
|
|
613
696
|
instructions: request.systemPrompt,
|
|
614
697
|
input: this.buildResponsesInput(request),
|
|
615
|
-
tools:
|
|
698
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
616
699
|
tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
|
|
617
700
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
618
701
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
619
702
|
max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
703
|
+
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
704
|
+
...reasoning ? { reasoning } : {},
|
|
705
|
+
store: false,
|
|
620
706
|
stream: false
|
|
621
707
|
};
|
|
622
708
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
@@ -738,14 +824,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
738
824
|
name: openaiToolOptions.toolChoice.name
|
|
739
825
|
}
|
|
740
826
|
} : openaiToolOptions?.toolChoice;
|
|
827
|
+
const modelIdForPayload = request.config?.model || this.model;
|
|
741
828
|
const payload = {
|
|
742
|
-
model:
|
|
829
|
+
model: modelIdForPayload,
|
|
743
830
|
messages,
|
|
744
831
|
tools: tools.length > 0 ? tools : void 0,
|
|
745
832
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
746
833
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
747
|
-
|
|
748
|
-
|
|
834
|
+
...buildOpenAITokenParams(
|
|
835
|
+
modelIdForPayload,
|
|
836
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
837
|
+
request.config?.temperature ?? this.config.temperature
|
|
838
|
+
),
|
|
839
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
749
840
|
stream: true,
|
|
750
841
|
stream_options: { include_usage: true }
|
|
751
842
|
};
|
|
@@ -887,14 +978,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
887
978
|
name: openaiToolOptions.toolChoice.name
|
|
888
979
|
}
|
|
889
980
|
} : openaiToolOptions?.toolChoice;
|
|
981
|
+
const modelIdForCompletePayload = request.config?.model || this.model;
|
|
890
982
|
const payload = {
|
|
891
|
-
model:
|
|
983
|
+
model: modelIdForCompletePayload,
|
|
892
984
|
messages,
|
|
893
985
|
tools: tools.length > 0 ? tools : void 0,
|
|
894
986
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
895
987
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
896
|
-
|
|
897
|
-
|
|
988
|
+
...buildOpenAITokenParams(
|
|
989
|
+
modelIdForCompletePayload,
|
|
990
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
991
|
+
request.config?.temperature ?? this.config.temperature
|
|
992
|
+
),
|
|
993
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
898
994
|
stream: false
|
|
899
995
|
};
|
|
900
996
|
logProviderPayload("openai", "request payload", payload, request.debug);
|