@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,3 +1,259 @@
|
|
|
1
|
+
// src/adapters/base.ts
|
|
2
|
+
function stringifyForDebug(value) {
|
|
3
|
+
return JSON.stringify(
|
|
4
|
+
value,
|
|
5
|
+
(_key, currentValue) => {
|
|
6
|
+
if (typeof currentValue === "bigint") {
|
|
7
|
+
return currentValue.toString();
|
|
8
|
+
}
|
|
9
|
+
if (currentValue instanceof Error) {
|
|
10
|
+
return {
|
|
11
|
+
name: currentValue.name,
|
|
12
|
+
message: currentValue.message,
|
|
13
|
+
stack: currentValue.stack
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return currentValue;
|
|
17
|
+
},
|
|
18
|
+
2
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function logProviderPayload(provider, label, payload, enabled) {
|
|
22
|
+
if (!enabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (label.toLowerCase().includes("stream ")) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
console.log(
|
|
30
|
+
`[llm-sdk:${provider}] ${label}
|
|
31
|
+
${stringifyForDebug(payload)}`
|
|
32
|
+
);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.log(
|
|
35
|
+
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
36
|
+
error
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function parameterToJsonSchema(param) {
|
|
41
|
+
const schema = {
|
|
42
|
+
type: param.type
|
|
43
|
+
};
|
|
44
|
+
if (param.description) {
|
|
45
|
+
schema.description = param.description;
|
|
46
|
+
}
|
|
47
|
+
if (param.enum) {
|
|
48
|
+
schema.enum = param.enum;
|
|
49
|
+
}
|
|
50
|
+
if (param.type === "array" && param.items) {
|
|
51
|
+
schema.items = parameterToJsonSchema(
|
|
52
|
+
param.items
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
if (param.type === "object" && param.properties) {
|
|
56
|
+
schema.properties = Object.fromEntries(
|
|
57
|
+
Object.entries(param.properties).map(([key, prop]) => [
|
|
58
|
+
key,
|
|
59
|
+
parameterToJsonSchema(
|
|
60
|
+
prop
|
|
61
|
+
)
|
|
62
|
+
])
|
|
63
|
+
);
|
|
64
|
+
schema.additionalProperties = false;
|
|
65
|
+
}
|
|
66
|
+
return schema;
|
|
67
|
+
}
|
|
68
|
+
function normalizeObjectJsonSchema(schema) {
|
|
69
|
+
if (!schema || typeof schema !== "object") {
|
|
70
|
+
return {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {},
|
|
73
|
+
required: [],
|
|
74
|
+
additionalProperties: false
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const normalized = { ...schema };
|
|
78
|
+
const type = normalized.type;
|
|
79
|
+
if (type === "object") {
|
|
80
|
+
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
81
|
+
normalized.properties = Object.fromEntries(
|
|
82
|
+
Object.entries(properties).map(([key, value]) => [
|
|
83
|
+
key,
|
|
84
|
+
normalizeObjectJsonSchema(value)
|
|
85
|
+
])
|
|
86
|
+
);
|
|
87
|
+
const propertyKeys = Object.keys(properties);
|
|
88
|
+
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
89
|
+
(value) => typeof value === "string"
|
|
90
|
+
) : [];
|
|
91
|
+
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
92
|
+
if (normalized.additionalProperties === void 0) {
|
|
93
|
+
normalized.additionalProperties = false;
|
|
94
|
+
}
|
|
95
|
+
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
96
|
+
normalized.items = normalizeObjectJsonSchema(
|
|
97
|
+
normalized.items
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return normalized;
|
|
101
|
+
}
|
|
102
|
+
function isOpenAIReasoningModel(modelId) {
|
|
103
|
+
if (!modelId) return false;
|
|
104
|
+
return /^(o1|o3|o4|gpt-5)/i.test(modelId);
|
|
105
|
+
}
|
|
106
|
+
function buildOpenAITokenParams(modelId, maxTokens, temperature) {
|
|
107
|
+
if (isOpenAIReasoningModel(modelId)) {
|
|
108
|
+
return { max_completion_tokens: maxTokens };
|
|
109
|
+
}
|
|
110
|
+
return { max_tokens: maxTokens, temperature };
|
|
111
|
+
}
|
|
112
|
+
function toOpenAIResponseFormat(rf) {
|
|
113
|
+
if (!rf) return void 0;
|
|
114
|
+
if (rf.type === "json_object") return { type: "json_object" };
|
|
115
|
+
return {
|
|
116
|
+
type: "json_schema",
|
|
117
|
+
json_schema: {
|
|
118
|
+
name: rf.json_schema.name,
|
|
119
|
+
schema: normalizeObjectJsonSchema(rf.json_schema.schema),
|
|
120
|
+
strict: rf.json_schema.strict ?? true
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function toOpenAIResponsesTextFormat(rf) {
|
|
125
|
+
if (!rf || rf.type !== "json_schema") return void 0;
|
|
126
|
+
return {
|
|
127
|
+
type: "json_schema",
|
|
128
|
+
name: rf.json_schema.name,
|
|
129
|
+
schema: normalizeObjectJsonSchema(rf.json_schema.schema),
|
|
130
|
+
strict: rf.json_schema.strict ?? true
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function toOpenAIResponsesMcpTools(mcpServers) {
|
|
134
|
+
if (!mcpServers || mcpServers.length === 0) return [];
|
|
135
|
+
return mcpServers.map((mcp) => ({
|
|
136
|
+
type: "mcp",
|
|
137
|
+
server_label: mcp.label,
|
|
138
|
+
server_url: mcp.url,
|
|
139
|
+
...mcp.headers ? { headers: mcp.headers } : {},
|
|
140
|
+
...mcp.allowedTools ? { allowed_tools: mcp.allowedTools } : {},
|
|
141
|
+
require_approval: mcp.requireApproval ?? "never"
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
function isStringEffort(effort) {
|
|
145
|
+
return typeof effort === "string" && (effort === "minimal" || effort === "low" || effort === "medium" || effort === "high");
|
|
146
|
+
}
|
|
147
|
+
function toOpenAIReasoning(effort) {
|
|
148
|
+
if (!effort) return void 0;
|
|
149
|
+
if (typeof effort === "object" && "raw" in effort) return effort.raw;
|
|
150
|
+
if (typeof effort === "object" && "budgetTokens" in effort) {
|
|
151
|
+
const budget = effort.budgetTokens;
|
|
152
|
+
const mapped = budget >= 16e3 ? "high" : budget >= 8e3 ? "medium" : "low";
|
|
153
|
+
return { effort: mapped, summary: "auto" };
|
|
154
|
+
}
|
|
155
|
+
if (isStringEffort(effort)) {
|
|
156
|
+
return { effort, summary: "auto" };
|
|
157
|
+
}
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
function formatTools(actions) {
|
|
161
|
+
return actions.map((action) => ({
|
|
162
|
+
type: "function",
|
|
163
|
+
function: {
|
|
164
|
+
name: action.name,
|
|
165
|
+
description: action.description,
|
|
166
|
+
parameters: {
|
|
167
|
+
type: "object",
|
|
168
|
+
properties: action.parameters ? Object.fromEntries(
|
|
169
|
+
Object.entries(action.parameters).map(([key, param]) => [
|
|
170
|
+
key,
|
|
171
|
+
parameterToJsonSchema(param)
|
|
172
|
+
])
|
|
173
|
+
) : {},
|
|
174
|
+
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
175
|
+
additionalProperties: false
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
function hasImageAttachments(message) {
|
|
181
|
+
const attachments = message.metadata?.attachments;
|
|
182
|
+
return attachments?.some((a) => a.type === "image") ?? false;
|
|
183
|
+
}
|
|
184
|
+
function attachmentToOpenAIImage(attachment) {
|
|
185
|
+
if (attachment.type !== "image") return null;
|
|
186
|
+
let imageUrl;
|
|
187
|
+
if (attachment.url) {
|
|
188
|
+
imageUrl = attachment.url;
|
|
189
|
+
} else if (attachment.data) {
|
|
190
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
191
|
+
} else {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
type: "image_url",
|
|
196
|
+
image_url: {
|
|
197
|
+
url: imageUrl,
|
|
198
|
+
detail: "auto"
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function messageToOpenAIContent(message) {
|
|
203
|
+
const attachments = message.metadata?.attachments;
|
|
204
|
+
const content = message.content ?? "";
|
|
205
|
+
if (!hasImageAttachments(message)) {
|
|
206
|
+
return content;
|
|
207
|
+
}
|
|
208
|
+
const blocks = [];
|
|
209
|
+
if (content) {
|
|
210
|
+
blocks.push({ type: "text", text: content });
|
|
211
|
+
}
|
|
212
|
+
if (attachments) {
|
|
213
|
+
for (const attachment of attachments) {
|
|
214
|
+
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
215
|
+
if (imageBlock) {
|
|
216
|
+
blocks.push(imageBlock);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return blocks;
|
|
221
|
+
}
|
|
222
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
223
|
+
const formatted = [];
|
|
224
|
+
if (systemPrompt) {
|
|
225
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
226
|
+
}
|
|
227
|
+
for (const msg of messages) {
|
|
228
|
+
if (msg.role === "system") {
|
|
229
|
+
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
230
|
+
} else if (msg.role === "user") {
|
|
231
|
+
formatted.push({
|
|
232
|
+
role: "user",
|
|
233
|
+
content: messageToOpenAIContent(msg)
|
|
234
|
+
});
|
|
235
|
+
} else if (msg.role === "assistant") {
|
|
236
|
+
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
237
|
+
const assistantMsg = {
|
|
238
|
+
role: "assistant",
|
|
239
|
+
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
240
|
+
content: hasToolCalls ? msg.content || null : msg.content
|
|
241
|
+
};
|
|
242
|
+
if (hasToolCalls) {
|
|
243
|
+
assistantMsg.tool_calls = msg.tool_calls;
|
|
244
|
+
}
|
|
245
|
+
formatted.push(assistantMsg);
|
|
246
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
247
|
+
formatted.push({
|
|
248
|
+
role: "tool",
|
|
249
|
+
content: msg.content ?? "",
|
|
250
|
+
tool_call_id: msg.tool_call_id
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return formatted;
|
|
255
|
+
}
|
|
256
|
+
|
|
1
257
|
// src/providers/openai/provider.ts
|
|
2
258
|
var OPENAI_MODELS = {
|
|
3
259
|
// GPT-4o series
|
|
@@ -92,13 +348,17 @@ function openai(modelId, options = {}) {
|
|
|
92
348
|
},
|
|
93
349
|
async doGenerate(params) {
|
|
94
350
|
const client2 = await getClient();
|
|
95
|
-
const messages =
|
|
351
|
+
const messages = formatMessagesForOpenAI2(params.messages);
|
|
96
352
|
const response = await client2.chat.completions.create({
|
|
97
353
|
model: modelId,
|
|
98
354
|
messages,
|
|
99
355
|
tools: params.tools,
|
|
100
|
-
|
|
101
|
-
|
|
356
|
+
...buildOpenAITokenParams(
|
|
357
|
+
modelId,
|
|
358
|
+
params.maxTokens,
|
|
359
|
+
params.temperature
|
|
360
|
+
),
|
|
361
|
+
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
102
362
|
});
|
|
103
363
|
const choice = response.choices[0];
|
|
104
364
|
const message = choice.message;
|
|
@@ -123,13 +383,17 @@ function openai(modelId, options = {}) {
|
|
|
123
383
|
},
|
|
124
384
|
async *doStream(params) {
|
|
125
385
|
const client2 = await getClient();
|
|
126
|
-
const messages =
|
|
386
|
+
const messages = formatMessagesForOpenAI2(params.messages);
|
|
127
387
|
const stream = await client2.chat.completions.create({
|
|
128
388
|
model: modelId,
|
|
129
389
|
messages,
|
|
130
390
|
tools: params.tools,
|
|
131
|
-
|
|
132
|
-
|
|
391
|
+
...buildOpenAITokenParams(
|
|
392
|
+
modelId,
|
|
393
|
+
params.maxTokens,
|
|
394
|
+
params.temperature
|
|
395
|
+
),
|
|
396
|
+
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
133
397
|
stream: true
|
|
134
398
|
});
|
|
135
399
|
let currentToolCall = null;
|
|
@@ -213,7 +477,7 @@ function mapFinishReason(reason) {
|
|
|
213
477
|
return "unknown";
|
|
214
478
|
}
|
|
215
479
|
}
|
|
216
|
-
function
|
|
480
|
+
function formatMessagesForOpenAI2(messages) {
|
|
217
481
|
return messages.map((msg) => {
|
|
218
482
|
switch (msg.role) {
|
|
219
483
|
case "system":
|
|
@@ -275,204 +539,6 @@ function generateToolCallId() {
|
|
|
275
539
|
return generateId("call");
|
|
276
540
|
}
|
|
277
541
|
|
|
278
|
-
// src/adapters/base.ts
|
|
279
|
-
function stringifyForDebug(value) {
|
|
280
|
-
return JSON.stringify(
|
|
281
|
-
value,
|
|
282
|
-
(_key, currentValue) => {
|
|
283
|
-
if (typeof currentValue === "bigint") {
|
|
284
|
-
return currentValue.toString();
|
|
285
|
-
}
|
|
286
|
-
if (currentValue instanceof Error) {
|
|
287
|
-
return {
|
|
288
|
-
name: currentValue.name,
|
|
289
|
-
message: currentValue.message,
|
|
290
|
-
stack: currentValue.stack
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
return currentValue;
|
|
294
|
-
},
|
|
295
|
-
2
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
function logProviderPayload(provider, label, payload, enabled) {
|
|
299
|
-
if (!enabled) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
if (label.toLowerCase().includes("stream ")) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
try {
|
|
306
|
-
console.log(
|
|
307
|
-
`[llm-sdk:${provider}] ${label}
|
|
308
|
-
${stringifyForDebug(payload)}`
|
|
309
|
-
);
|
|
310
|
-
} catch (error) {
|
|
311
|
-
console.log(
|
|
312
|
-
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
313
|
-
error
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
function parameterToJsonSchema(param) {
|
|
318
|
-
const schema = {
|
|
319
|
-
type: param.type
|
|
320
|
-
};
|
|
321
|
-
if (param.description) {
|
|
322
|
-
schema.description = param.description;
|
|
323
|
-
}
|
|
324
|
-
if (param.enum) {
|
|
325
|
-
schema.enum = param.enum;
|
|
326
|
-
}
|
|
327
|
-
if (param.type === "array" && param.items) {
|
|
328
|
-
schema.items = parameterToJsonSchema(
|
|
329
|
-
param.items
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
if (param.type === "object" && param.properties) {
|
|
333
|
-
schema.properties = Object.fromEntries(
|
|
334
|
-
Object.entries(param.properties).map(([key, prop]) => [
|
|
335
|
-
key,
|
|
336
|
-
parameterToJsonSchema(
|
|
337
|
-
prop
|
|
338
|
-
)
|
|
339
|
-
])
|
|
340
|
-
);
|
|
341
|
-
schema.additionalProperties = false;
|
|
342
|
-
}
|
|
343
|
-
return schema;
|
|
344
|
-
}
|
|
345
|
-
function normalizeObjectJsonSchema(schema) {
|
|
346
|
-
if (!schema || typeof schema !== "object") {
|
|
347
|
-
return {
|
|
348
|
-
type: "object",
|
|
349
|
-
properties: {},
|
|
350
|
-
required: [],
|
|
351
|
-
additionalProperties: false
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
const normalized = { ...schema };
|
|
355
|
-
const type = normalized.type;
|
|
356
|
-
if (type === "object") {
|
|
357
|
-
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
358
|
-
normalized.properties = Object.fromEntries(
|
|
359
|
-
Object.entries(properties).map(([key, value]) => [
|
|
360
|
-
key,
|
|
361
|
-
normalizeObjectJsonSchema(value)
|
|
362
|
-
])
|
|
363
|
-
);
|
|
364
|
-
const propertyKeys = Object.keys(properties);
|
|
365
|
-
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
366
|
-
(value) => typeof value === "string"
|
|
367
|
-
) : [];
|
|
368
|
-
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
369
|
-
if (normalized.additionalProperties === void 0) {
|
|
370
|
-
normalized.additionalProperties = false;
|
|
371
|
-
}
|
|
372
|
-
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
373
|
-
normalized.items = normalizeObjectJsonSchema(
|
|
374
|
-
normalized.items
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
return normalized;
|
|
378
|
-
}
|
|
379
|
-
function formatTools(actions) {
|
|
380
|
-
return actions.map((action) => ({
|
|
381
|
-
type: "function",
|
|
382
|
-
function: {
|
|
383
|
-
name: action.name,
|
|
384
|
-
description: action.description,
|
|
385
|
-
parameters: {
|
|
386
|
-
type: "object",
|
|
387
|
-
properties: action.parameters ? Object.fromEntries(
|
|
388
|
-
Object.entries(action.parameters).map(([key, param]) => [
|
|
389
|
-
key,
|
|
390
|
-
parameterToJsonSchema(param)
|
|
391
|
-
])
|
|
392
|
-
) : {},
|
|
393
|
-
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
394
|
-
additionalProperties: false
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}));
|
|
398
|
-
}
|
|
399
|
-
function hasImageAttachments(message) {
|
|
400
|
-
const attachments = message.metadata?.attachments;
|
|
401
|
-
return attachments?.some((a) => a.type === "image") ?? false;
|
|
402
|
-
}
|
|
403
|
-
function attachmentToOpenAIImage(attachment) {
|
|
404
|
-
if (attachment.type !== "image") return null;
|
|
405
|
-
let imageUrl;
|
|
406
|
-
if (attachment.url) {
|
|
407
|
-
imageUrl = attachment.url;
|
|
408
|
-
} else if (attachment.data) {
|
|
409
|
-
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
410
|
-
} else {
|
|
411
|
-
return null;
|
|
412
|
-
}
|
|
413
|
-
return {
|
|
414
|
-
type: "image_url",
|
|
415
|
-
image_url: {
|
|
416
|
-
url: imageUrl,
|
|
417
|
-
detail: "auto"
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
function messageToOpenAIContent(message) {
|
|
422
|
-
const attachments = message.metadata?.attachments;
|
|
423
|
-
const content = message.content ?? "";
|
|
424
|
-
if (!hasImageAttachments(message)) {
|
|
425
|
-
return content;
|
|
426
|
-
}
|
|
427
|
-
const blocks = [];
|
|
428
|
-
if (content) {
|
|
429
|
-
blocks.push({ type: "text", text: content });
|
|
430
|
-
}
|
|
431
|
-
if (attachments) {
|
|
432
|
-
for (const attachment of attachments) {
|
|
433
|
-
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
434
|
-
if (imageBlock) {
|
|
435
|
-
blocks.push(imageBlock);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return blocks;
|
|
440
|
-
}
|
|
441
|
-
function formatMessagesForOpenAI2(messages, systemPrompt) {
|
|
442
|
-
const formatted = [];
|
|
443
|
-
if (systemPrompt) {
|
|
444
|
-
formatted.push({ role: "system", content: systemPrompt });
|
|
445
|
-
}
|
|
446
|
-
for (const msg of messages) {
|
|
447
|
-
if (msg.role === "system") {
|
|
448
|
-
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
449
|
-
} else if (msg.role === "user") {
|
|
450
|
-
formatted.push({
|
|
451
|
-
role: "user",
|
|
452
|
-
content: messageToOpenAIContent(msg)
|
|
453
|
-
});
|
|
454
|
-
} else if (msg.role === "assistant") {
|
|
455
|
-
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
456
|
-
const assistantMsg = {
|
|
457
|
-
role: "assistant",
|
|
458
|
-
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
459
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
460
|
-
};
|
|
461
|
-
if (hasToolCalls) {
|
|
462
|
-
assistantMsg.tool_calls = msg.tool_calls;
|
|
463
|
-
}
|
|
464
|
-
formatted.push(assistantMsg);
|
|
465
|
-
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
466
|
-
formatted.push({
|
|
467
|
-
role: "tool",
|
|
468
|
-
content: msg.content ?? "",
|
|
469
|
-
tool_call_id: msg.tool_call_id
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return formatted;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
542
|
// src/adapters/openai.ts
|
|
477
543
|
var OpenAIAdapter = class _OpenAIAdapter {
|
|
478
544
|
constructor(config) {
|
|
@@ -498,10 +564,18 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
498
564
|
return this.client;
|
|
499
565
|
}
|
|
500
566
|
shouldUseResponsesApi(request) {
|
|
567
|
+
if (request.config?.mcpServers && request.config.mcpServers.length > 0 || request.config?.reasoningEffort !== void 0) {
|
|
568
|
+
if (this.provider !== "openai" && this.provider !== "azure") {
|
|
569
|
+
throw new Error(
|
|
570
|
+
`[llm-sdk] Provider "${this.provider}" does not support MCP servers or per-request reasoning effort. Use OpenAI or Anthropic for these features.`
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
501
575
|
return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
|
|
502
576
|
}
|
|
503
577
|
buildResponsesInput(request) {
|
|
504
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages :
|
|
578
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
|
|
505
579
|
const input = [];
|
|
506
580
|
for (const message of sourceMessages) {
|
|
507
581
|
if (message.role === "system") {
|
|
@@ -558,7 +632,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
558
632
|
strict: true,
|
|
559
633
|
defer_loading: tool.deferLoading === true
|
|
560
634
|
}));
|
|
561
|
-
return [{ type: "tool_search" }, ...nativeTools];
|
|
635
|
+
return nativeTools.length > 0 ? [{ type: "tool_search" }, ...nativeTools] : [];
|
|
562
636
|
}
|
|
563
637
|
parseResponsesResult(response) {
|
|
564
638
|
const content = typeof response?.output_text === "string" ? response.output_text : "";
|
|
@@ -587,15 +661,33 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
587
661
|
async completeWithResponses(request) {
|
|
588
662
|
const client = await this.getClient();
|
|
589
663
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
664
|
+
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
665
|
+
request.config?.responseFormat
|
|
666
|
+
);
|
|
667
|
+
const mcpTools = toOpenAIResponsesMcpTools(request.config?.mcpServers);
|
|
668
|
+
const modelId = request.config?.model || this.model;
|
|
669
|
+
const reasoning = isOpenAIReasoningModel(modelId) ? toOpenAIReasoning(request.config?.reasoningEffort) : void 0;
|
|
670
|
+
if (request.config?.reasoningEffort && !isOpenAIReasoningModel(modelId)) {
|
|
671
|
+
console.warn(
|
|
672
|
+
`[llm-sdk] openai/${modelId} is not a reasoning model; \`reasoningEffort\` is ignored. Use o1/o3/o4/gpt-5.x for reasoning.`
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
const functionTools = this.buildResponsesTools(
|
|
676
|
+
request.toolDefinitions ?? []
|
|
677
|
+
);
|
|
678
|
+
const tools = [...functionTools, ...mcpTools];
|
|
590
679
|
const payload = {
|
|
591
680
|
model: request.config?.model || this.model,
|
|
592
681
|
instructions: request.systemPrompt,
|
|
593
682
|
input: this.buildResponsesInput(request),
|
|
594
|
-
tools:
|
|
683
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
595
684
|
tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
|
|
596
685
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
597
686
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
598
687
|
max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
688
|
+
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
689
|
+
...reasoning ? { reasoning } : {},
|
|
690
|
+
store: false,
|
|
599
691
|
stream: false
|
|
600
692
|
};
|
|
601
693
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
@@ -690,7 +782,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
690
782
|
messages = processedMessages;
|
|
691
783
|
}
|
|
692
784
|
} else {
|
|
693
|
-
messages =
|
|
785
|
+
messages = formatMessagesForOpenAI(
|
|
694
786
|
request.messages,
|
|
695
787
|
request.systemPrompt
|
|
696
788
|
);
|
|
@@ -717,14 +809,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
717
809
|
name: openaiToolOptions.toolChoice.name
|
|
718
810
|
}
|
|
719
811
|
} : openaiToolOptions?.toolChoice;
|
|
812
|
+
const modelIdForPayload = request.config?.model || this.model;
|
|
720
813
|
const payload = {
|
|
721
|
-
model:
|
|
814
|
+
model: modelIdForPayload,
|
|
722
815
|
messages,
|
|
723
816
|
tools: tools.length > 0 ? tools : void 0,
|
|
724
817
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
725
818
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
726
|
-
|
|
727
|
-
|
|
819
|
+
...buildOpenAITokenParams(
|
|
820
|
+
modelIdForPayload,
|
|
821
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
822
|
+
request.config?.temperature ?? this.config.temperature
|
|
823
|
+
),
|
|
824
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
728
825
|
stream: true,
|
|
729
826
|
stream_options: { include_usage: true }
|
|
730
827
|
};
|
|
@@ -853,7 +950,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
853
950
|
messages = sanitized;
|
|
854
951
|
}
|
|
855
952
|
} else {
|
|
856
|
-
messages =
|
|
953
|
+
messages = formatMessagesForOpenAI(
|
|
857
954
|
request.messages,
|
|
858
955
|
request.systemPrompt
|
|
859
956
|
);
|
|
@@ -866,14 +963,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
866
963
|
name: openaiToolOptions.toolChoice.name
|
|
867
964
|
}
|
|
868
965
|
} : openaiToolOptions?.toolChoice;
|
|
966
|
+
const modelIdForCompletePayload = request.config?.model || this.model;
|
|
869
967
|
const payload = {
|
|
870
|
-
model:
|
|
968
|
+
model: modelIdForCompletePayload,
|
|
871
969
|
messages,
|
|
872
970
|
tools: tools.length > 0 ? tools : void 0,
|
|
873
971
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
874
972
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
875
|
-
|
|
876
|
-
|
|
973
|
+
...buildOpenAITokenParams(
|
|
974
|
+
modelIdForCompletePayload,
|
|
975
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
976
|
+
request.config?.temperature ?? this.config.temperature
|
|
977
|
+
),
|
|
978
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
877
979
|
stream: false
|
|
878
980
|
};
|
|
879
981
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-D774b0dg.mjs';
|
|
2
|
+
import { A as AIProvider } from '../../types-BvkiJ1dd.mjs';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-BYQKp9TW.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* OpenRouter Provider - Modern Pattern
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-D774b0dg.js';
|
|
2
|
+
import { A as AIProvider } from '../../types-TMilS-Dz.js';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-Cxq3ni0t.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* OpenRouter Provider - Modern Pattern
|