@yourgpt/llm-sdk 2.1.10-alpha.0 → 2.5.1-beta.0
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.d.mts +4 -38
- package/dist/adapters/index.d.ts +4 -38
- package/dist/adapters/index.js +158 -325
- package/dist/adapters/index.mjs +158 -325
- package/dist/base-C58Dsr9p.d.ts +259 -0
- package/dist/base-tNgbBaSo.d.mts +259 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/index.d.mts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +35 -43
- package/dist/index.mjs +35 -43
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +271 -212
- package/dist/providers/anthropic/index.mjs +271 -212
- 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 +254 -510
- package/dist/providers/google/index.mjs +254 -510
- 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 +269 -529
- package/dist/providers/openai/index.mjs +269 -529
- package/dist/providers/openrouter/index.d.mts +3 -7
- package/dist/providers/openrouter/index.d.ts +3 -7
- package/dist/providers/openrouter/index.js +365 -902
- package/dist/providers/openrouter/index.mjs +365 -902
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +259 -509
- package/dist/providers/togetherai/index.mjs +259 -509
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +258 -513
- package/dist/providers/xai/index.mjs +258 -513
- package/dist/{types-BNCmlJMs.d.mts → types-B6dhnguR.d.mts} +1 -1
- package/dist/{types-DhktekQ3.d.ts → types-BQ31QIsA.d.ts} +2 -1
- package/dist/{types-CMMQ8s2O.d.mts → types-BSSiJW2o.d.mts} +2 -1
- package/dist/{base-DN1EfKnE.d.mts → types-BkQCSiIt.d.mts} +388 -214
- package/dist/{base-DuUNxtVg.d.ts → types-BkQCSiIt.d.ts} +388 -214
- package/dist/{types-Pj-vpmoT.d.ts → types-CCxPmkmK.d.ts} +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/types-CMvvDo-E.d.mts +0 -428
- package/dist/types-CMvvDo-E.d.ts +0 -428
|
@@ -1,5 +1,234 @@
|
|
|
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 formatTools(actions) {
|
|
136
|
+
return actions.map((action) => ({
|
|
137
|
+
type: "function",
|
|
138
|
+
function: {
|
|
139
|
+
name: action.name,
|
|
140
|
+
description: action.description,
|
|
141
|
+
parameters: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: action.parameters ? Object.fromEntries(
|
|
144
|
+
Object.entries(action.parameters).map(([key, param]) => [
|
|
145
|
+
key,
|
|
146
|
+
parameterToJsonSchema(param)
|
|
147
|
+
])
|
|
148
|
+
) : {},
|
|
149
|
+
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
150
|
+
additionalProperties: false
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
function hasImageAttachments(message) {
|
|
156
|
+
const attachments = message.metadata?.attachments;
|
|
157
|
+
return attachments?.some((a) => a.type === "image") ?? false;
|
|
158
|
+
}
|
|
159
|
+
function attachmentToOpenAIImage(attachment) {
|
|
160
|
+
if (attachment.type !== "image") return null;
|
|
161
|
+
let imageUrl;
|
|
162
|
+
if (attachment.url) {
|
|
163
|
+
imageUrl = attachment.url;
|
|
164
|
+
} else if (attachment.data) {
|
|
165
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
166
|
+
} else {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
type: "image_url",
|
|
171
|
+
image_url: {
|
|
172
|
+
url: imageUrl,
|
|
173
|
+
detail: "auto"
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function messageToOpenAIContent(message) {
|
|
178
|
+
const attachments = message.metadata?.attachments;
|
|
179
|
+
const content = message.content ?? "";
|
|
180
|
+
if (!hasImageAttachments(message)) {
|
|
181
|
+
return content;
|
|
182
|
+
}
|
|
183
|
+
const blocks = [];
|
|
184
|
+
if (content) {
|
|
185
|
+
blocks.push({ type: "text", text: content });
|
|
186
|
+
}
|
|
187
|
+
if (attachments) {
|
|
188
|
+
for (const attachment of attachments) {
|
|
189
|
+
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
190
|
+
if (imageBlock) {
|
|
191
|
+
blocks.push(imageBlock);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return blocks;
|
|
196
|
+
}
|
|
197
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
198
|
+
const formatted = [];
|
|
199
|
+
if (systemPrompt) {
|
|
200
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
201
|
+
}
|
|
202
|
+
for (const msg of messages) {
|
|
203
|
+
if (msg.role === "system") {
|
|
204
|
+
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
205
|
+
} else if (msg.role === "user") {
|
|
206
|
+
formatted.push({
|
|
207
|
+
role: "user",
|
|
208
|
+
content: messageToOpenAIContent(msg)
|
|
209
|
+
});
|
|
210
|
+
} else if (msg.role === "assistant") {
|
|
211
|
+
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
212
|
+
const assistantMsg = {
|
|
213
|
+
role: "assistant",
|
|
214
|
+
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
215
|
+
content: hasToolCalls ? msg.content || null : msg.content
|
|
216
|
+
};
|
|
217
|
+
if (hasToolCalls) {
|
|
218
|
+
assistantMsg.tool_calls = msg.tool_calls;
|
|
219
|
+
}
|
|
220
|
+
formatted.push(assistantMsg);
|
|
221
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
222
|
+
formatted.push({
|
|
223
|
+
role: "tool",
|
|
224
|
+
content: msg.content ?? "",
|
|
225
|
+
tool_call_id: msg.tool_call_id
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return formatted;
|
|
230
|
+
}
|
|
231
|
+
|
|
3
232
|
// src/providers/xai/provider.ts
|
|
4
233
|
var XAI_MODELS = {
|
|
5
234
|
// Grok 4.1 Fast (Latest - December 2025)
|
|
@@ -53,8 +282,8 @@ function xai(modelId, options = {}) {
|
|
|
53
282
|
supportsVision: modelConfig.vision,
|
|
54
283
|
supportsTools: modelConfig.tools,
|
|
55
284
|
supportsStreaming: true,
|
|
56
|
-
supportsJsonMode:
|
|
57
|
-
//
|
|
285
|
+
supportsJsonMode: true,
|
|
286
|
+
// OpenAI-compatible `response_format`
|
|
58
287
|
supportsThinking: false,
|
|
59
288
|
supportsPDF: false,
|
|
60
289
|
maxTokens: modelConfig.maxTokens,
|
|
@@ -68,7 +297,8 @@ function xai(modelId, options = {}) {
|
|
|
68
297
|
messages,
|
|
69
298
|
tools: params.tools,
|
|
70
299
|
temperature: params.temperature,
|
|
71
|
-
max_tokens: params.maxTokens
|
|
300
|
+
max_tokens: params.maxTokens,
|
|
301
|
+
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
72
302
|
});
|
|
73
303
|
const choice = response.choices[0];
|
|
74
304
|
const message = choice.message;
|
|
@@ -100,6 +330,7 @@ function xai(modelId, options = {}) {
|
|
|
100
330
|
tools: params.tools,
|
|
101
331
|
temperature: params.temperature,
|
|
102
332
|
max_tokens: params.maxTokens,
|
|
333
|
+
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
103
334
|
stream: true
|
|
104
335
|
});
|
|
105
336
|
let currentToolCall = null;
|
|
@@ -245,204 +476,6 @@ function generateToolCallId() {
|
|
|
245
476
|
return generateId("call");
|
|
246
477
|
}
|
|
247
478
|
|
|
248
|
-
// src/adapters/base.ts
|
|
249
|
-
function stringifyForDebug(value) {
|
|
250
|
-
return JSON.stringify(
|
|
251
|
-
value,
|
|
252
|
-
(_key, currentValue) => {
|
|
253
|
-
if (typeof currentValue === "bigint") {
|
|
254
|
-
return currentValue.toString();
|
|
255
|
-
}
|
|
256
|
-
if (currentValue instanceof Error) {
|
|
257
|
-
return {
|
|
258
|
-
name: currentValue.name,
|
|
259
|
-
message: currentValue.message,
|
|
260
|
-
stack: currentValue.stack
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
return currentValue;
|
|
264
|
-
},
|
|
265
|
-
2
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
function logProviderPayload(provider, label, payload, enabled) {
|
|
269
|
-
if (!enabled) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (label.toLowerCase().includes("stream ")) {
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
console.log(
|
|
277
|
-
`[llm-sdk:${provider}] ${label}
|
|
278
|
-
${stringifyForDebug(payload)}`
|
|
279
|
-
);
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.log(
|
|
282
|
-
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
283
|
-
error
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
function parameterToJsonSchema(param) {
|
|
288
|
-
const schema = {
|
|
289
|
-
type: param.type
|
|
290
|
-
};
|
|
291
|
-
if (param.description) {
|
|
292
|
-
schema.description = param.description;
|
|
293
|
-
}
|
|
294
|
-
if (param.enum) {
|
|
295
|
-
schema.enum = param.enum;
|
|
296
|
-
}
|
|
297
|
-
if (param.type === "array" && param.items) {
|
|
298
|
-
schema.items = parameterToJsonSchema(
|
|
299
|
-
param.items
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
if (param.type === "object" && param.properties) {
|
|
303
|
-
schema.properties = Object.fromEntries(
|
|
304
|
-
Object.entries(param.properties).map(([key, prop]) => [
|
|
305
|
-
key,
|
|
306
|
-
parameterToJsonSchema(
|
|
307
|
-
prop
|
|
308
|
-
)
|
|
309
|
-
])
|
|
310
|
-
);
|
|
311
|
-
schema.additionalProperties = false;
|
|
312
|
-
}
|
|
313
|
-
return schema;
|
|
314
|
-
}
|
|
315
|
-
function normalizeObjectJsonSchema(schema) {
|
|
316
|
-
if (!schema || typeof schema !== "object") {
|
|
317
|
-
return {
|
|
318
|
-
type: "object",
|
|
319
|
-
properties: {},
|
|
320
|
-
required: [],
|
|
321
|
-
additionalProperties: false
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
const normalized = { ...schema };
|
|
325
|
-
const type = normalized.type;
|
|
326
|
-
if (type === "object") {
|
|
327
|
-
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
328
|
-
normalized.properties = Object.fromEntries(
|
|
329
|
-
Object.entries(properties).map(([key, value]) => [
|
|
330
|
-
key,
|
|
331
|
-
normalizeObjectJsonSchema(value)
|
|
332
|
-
])
|
|
333
|
-
);
|
|
334
|
-
const propertyKeys = Object.keys(properties);
|
|
335
|
-
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
336
|
-
(value) => typeof value === "string"
|
|
337
|
-
) : [];
|
|
338
|
-
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
339
|
-
if (normalized.additionalProperties === void 0) {
|
|
340
|
-
normalized.additionalProperties = false;
|
|
341
|
-
}
|
|
342
|
-
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
343
|
-
normalized.items = normalizeObjectJsonSchema(
|
|
344
|
-
normalized.items
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
return normalized;
|
|
348
|
-
}
|
|
349
|
-
function formatTools(actions) {
|
|
350
|
-
return actions.map((action) => ({
|
|
351
|
-
type: "function",
|
|
352
|
-
function: {
|
|
353
|
-
name: action.name,
|
|
354
|
-
description: action.description,
|
|
355
|
-
parameters: {
|
|
356
|
-
type: "object",
|
|
357
|
-
properties: action.parameters ? Object.fromEntries(
|
|
358
|
-
Object.entries(action.parameters).map(([key, param]) => [
|
|
359
|
-
key,
|
|
360
|
-
parameterToJsonSchema(param)
|
|
361
|
-
])
|
|
362
|
-
) : {},
|
|
363
|
-
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
364
|
-
additionalProperties: false
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}));
|
|
368
|
-
}
|
|
369
|
-
function hasImageAttachments(message) {
|
|
370
|
-
const attachments = message.metadata?.attachments;
|
|
371
|
-
return attachments?.some((a) => a.type === "image") ?? false;
|
|
372
|
-
}
|
|
373
|
-
function attachmentToOpenAIImage(attachment) {
|
|
374
|
-
if (attachment.type !== "image") return null;
|
|
375
|
-
let imageUrl;
|
|
376
|
-
if (attachment.url) {
|
|
377
|
-
imageUrl = attachment.url;
|
|
378
|
-
} else if (attachment.data) {
|
|
379
|
-
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
380
|
-
} else {
|
|
381
|
-
return null;
|
|
382
|
-
}
|
|
383
|
-
return {
|
|
384
|
-
type: "image_url",
|
|
385
|
-
image_url: {
|
|
386
|
-
url: imageUrl,
|
|
387
|
-
detail: "auto"
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
function messageToOpenAIContent(message) {
|
|
392
|
-
const attachments = message.metadata?.attachments;
|
|
393
|
-
const content = message.content ?? "";
|
|
394
|
-
if (!hasImageAttachments(message)) {
|
|
395
|
-
return content;
|
|
396
|
-
}
|
|
397
|
-
const blocks = [];
|
|
398
|
-
if (content) {
|
|
399
|
-
blocks.push({ type: "text", text: content });
|
|
400
|
-
}
|
|
401
|
-
if (attachments) {
|
|
402
|
-
for (const attachment of attachments) {
|
|
403
|
-
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
404
|
-
if (imageBlock) {
|
|
405
|
-
blocks.push(imageBlock);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
return blocks;
|
|
410
|
-
}
|
|
411
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
412
|
-
const formatted = [];
|
|
413
|
-
if (systemPrompt) {
|
|
414
|
-
formatted.push({ role: "system", content: systemPrompt });
|
|
415
|
-
}
|
|
416
|
-
for (const msg of messages) {
|
|
417
|
-
if (msg.role === "system") {
|
|
418
|
-
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
419
|
-
} else if (msg.role === "user") {
|
|
420
|
-
formatted.push({
|
|
421
|
-
role: "user",
|
|
422
|
-
content: messageToOpenAIContent(msg)
|
|
423
|
-
});
|
|
424
|
-
} else if (msg.role === "assistant") {
|
|
425
|
-
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
426
|
-
const assistantMsg = {
|
|
427
|
-
role: "assistant",
|
|
428
|
-
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
429
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
430
|
-
};
|
|
431
|
-
if (hasToolCalls) {
|
|
432
|
-
assistantMsg.tool_calls = msg.tool_calls;
|
|
433
|
-
}
|
|
434
|
-
formatted.push(assistantMsg);
|
|
435
|
-
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
436
|
-
formatted.push({
|
|
437
|
-
role: "tool",
|
|
438
|
-
content: msg.content ?? "",
|
|
439
|
-
tool_call_id: msg.tool_call_id
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
return formatted;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
479
|
// src/adapters/openai.ts
|
|
447
480
|
var OpenAIAdapter = class _OpenAIAdapter {
|
|
448
481
|
constructor(config) {
|
|
@@ -455,7 +488,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
455
488
|
if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
|
|
456
489
|
if (baseUrl.includes("x.ai")) return "xai";
|
|
457
490
|
if (baseUrl.includes("azure")) return "azure";
|
|
458
|
-
if (baseUrl.includes("openrouter.ai")) return "openrouter";
|
|
459
491
|
return "openai";
|
|
460
492
|
}
|
|
461
493
|
async getClient() {
|
|
@@ -555,259 +587,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
555
587
|
rawResponse: response
|
|
556
588
|
};
|
|
557
589
|
}
|
|
558
|
-
/**
|
|
559
|
-
* OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
|
|
560
|
-
* reasoning content on the chat-completions endpoint. To surface reasoning
|
|
561
|
-
* SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
|
|
562
|
-
* Responses API, which streams `response.reasoning_summary_text.delta` events.
|
|
563
|
-
*
|
|
564
|
-
* Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
|
|
565
|
-
* openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
|
|
566
|
-
*/
|
|
567
|
-
isOpenAIReasoningModelOnOpenRouter(activeModel) {
|
|
568
|
-
if (this.provider !== "openrouter") return false;
|
|
569
|
-
return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* Convert ActionDefinition[] (the chat-completions tool shape used by the
|
|
573
|
-
* adapter) to the Responses API tool shape.
|
|
574
|
-
*/
|
|
575
|
-
buildResponsesToolsFromActions(actions) {
|
|
576
|
-
if (!actions || actions.length === 0) return void 0;
|
|
577
|
-
const formatted = formatTools(actions);
|
|
578
|
-
return formatted.map((t) => ({
|
|
579
|
-
type: "function",
|
|
580
|
-
name: t.function.name,
|
|
581
|
-
description: t.function.description,
|
|
582
|
-
parameters: t.function.parameters
|
|
583
|
-
}));
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Streaming Responses API path for OpenAI reasoning models on OpenRouter.
|
|
587
|
-
*
|
|
588
|
-
* Maps Responses API SSE events back to the same StreamEvent shapes the
|
|
589
|
-
* chat-completions path emits, so downstream consumers (processChunk.ts,
|
|
590
|
-
* frontend tool handlers, plan approval, specialist delegations) see
|
|
591
|
-
* identical events regardless of which path produced them.
|
|
592
|
-
*
|
|
593
|
-
* response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
|
|
594
|
-
* response.output_text.delta → message:delta
|
|
595
|
-
* response.output_item.added (function_call) → action:start (queued buffer)
|
|
596
|
-
* response.function_call_arguments.delta → action:args (progressive)
|
|
597
|
-
* response.output_item.done (function_call) → final action:args + action:end
|
|
598
|
-
* response.completed → message:end + done(usage)
|
|
599
|
-
* response.error → error
|
|
600
|
-
*/
|
|
601
|
-
async *streamWithResponsesAPI(request, activeModel, messageId) {
|
|
602
|
-
const client = await this.getClient();
|
|
603
|
-
const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
|
|
604
|
-
const payload = {
|
|
605
|
-
model: activeModel,
|
|
606
|
-
input: this.buildResponsesInput(request),
|
|
607
|
-
stream: true,
|
|
608
|
-
reasoning: {
|
|
609
|
-
effort: request.config?.reasoningEffort ?? "medium",
|
|
610
|
-
summary: "auto"
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
if (request.systemPrompt) payload.instructions = request.systemPrompt;
|
|
614
|
-
if (typeof maxTokensValue === "number")
|
|
615
|
-
payload.max_output_tokens = maxTokensValue;
|
|
616
|
-
const tools = this.buildResponsesToolsFromActions(request.actions);
|
|
617
|
-
if (tools && tools.length > 0) payload.tools = tools;
|
|
618
|
-
logProviderPayload(
|
|
619
|
-
"openai",
|
|
620
|
-
"responses-api request payload",
|
|
621
|
-
payload,
|
|
622
|
-
request.debug
|
|
623
|
-
);
|
|
624
|
-
let stream;
|
|
625
|
-
try {
|
|
626
|
-
stream = await client.responses.create(payload);
|
|
627
|
-
} catch (error) {
|
|
628
|
-
yield {
|
|
629
|
-
type: "error",
|
|
630
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
631
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
632
|
-
};
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
const toolBuffers = /* @__PURE__ */ new Map();
|
|
636
|
-
const itemIdToCallId = /* @__PURE__ */ new Map();
|
|
637
|
-
let usage;
|
|
638
|
-
let reasoningStarted = false;
|
|
639
|
-
let textStarted = false;
|
|
640
|
-
let finishEmitted = false;
|
|
641
|
-
const resolveCallId = (evt) => {
|
|
642
|
-
if (evt?.call_id) return evt.call_id;
|
|
643
|
-
if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
|
|
644
|
-
if (evt?.item?.call_id) return evt.item.call_id;
|
|
645
|
-
if (evt?.item?.id) return evt.item.id;
|
|
646
|
-
return "";
|
|
647
|
-
};
|
|
648
|
-
try {
|
|
649
|
-
for await (const evt of stream) {
|
|
650
|
-
logProviderPayload(
|
|
651
|
-
"openai",
|
|
652
|
-
"responses-api stream chunk",
|
|
653
|
-
evt,
|
|
654
|
-
request.debug
|
|
655
|
-
);
|
|
656
|
-
if (request.signal?.aborted) break;
|
|
657
|
-
const t = evt?.type ?? "";
|
|
658
|
-
if (t === "response.reasoning_summary_text.delta") {
|
|
659
|
-
const delta = evt.delta ?? "";
|
|
660
|
-
if (!delta) continue;
|
|
661
|
-
if (!reasoningStarted) {
|
|
662
|
-
yield { type: "thinking:start" };
|
|
663
|
-
reasoningStarted = true;
|
|
664
|
-
}
|
|
665
|
-
yield { type: "thinking:delta", content: delta };
|
|
666
|
-
continue;
|
|
667
|
-
}
|
|
668
|
-
if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
|
|
669
|
-
continue;
|
|
670
|
-
}
|
|
671
|
-
if (t === "response.output_text.delta") {
|
|
672
|
-
const text = evt.delta ?? "";
|
|
673
|
-
if (!text) continue;
|
|
674
|
-
if (reasoningStarted && !textStarted) {
|
|
675
|
-
yield { type: "thinking:end" };
|
|
676
|
-
textStarted = true;
|
|
677
|
-
}
|
|
678
|
-
yield { type: "message:delta", content: text };
|
|
679
|
-
continue;
|
|
680
|
-
}
|
|
681
|
-
if (t === "response.output_item.added") {
|
|
682
|
-
const item = evt.item;
|
|
683
|
-
if (item?.type === "function_call") {
|
|
684
|
-
const callId = item.call_id ?? item.id ?? "";
|
|
685
|
-
const itemId = item.id ?? callId;
|
|
686
|
-
if (callId) {
|
|
687
|
-
if (itemId && itemId !== callId) {
|
|
688
|
-
itemIdToCallId.set(itemId, callId);
|
|
689
|
-
}
|
|
690
|
-
if (!toolBuffers.has(callId)) {
|
|
691
|
-
toolBuffers.set(callId, {
|
|
692
|
-
id: callId,
|
|
693
|
-
name: item.name ?? "",
|
|
694
|
-
arguments: item.arguments ?? "",
|
|
695
|
-
emittedStart: false
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
const buf = toolBuffers.get(callId);
|
|
699
|
-
if (buf.name && !buf.emittedStart) {
|
|
700
|
-
yield { type: "action:start", id: buf.id, name: buf.name };
|
|
701
|
-
buf.emittedStart = true;
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
continue;
|
|
706
|
-
}
|
|
707
|
-
if (t === "response.function_call_arguments.delta") {
|
|
708
|
-
const callId = resolveCallId(evt);
|
|
709
|
-
const delta = evt.delta ?? "";
|
|
710
|
-
if (!callId || !delta) continue;
|
|
711
|
-
let buf = toolBuffers.get(callId);
|
|
712
|
-
if (!buf) {
|
|
713
|
-
buf = { id: callId, name: "", arguments: "", emittedStart: false };
|
|
714
|
-
toolBuffers.set(callId, buf);
|
|
715
|
-
}
|
|
716
|
-
buf.arguments += delta;
|
|
717
|
-
if (buf.emittedStart) {
|
|
718
|
-
yield {
|
|
719
|
-
type: "action:args",
|
|
720
|
-
id: buf.id,
|
|
721
|
-
args: buf.arguments
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
continue;
|
|
725
|
-
}
|
|
726
|
-
if (t === "response.output_item.done") {
|
|
727
|
-
const item = evt.item;
|
|
728
|
-
if (item?.type === "function_call") {
|
|
729
|
-
const callId = item.call_id ?? item.id ?? "";
|
|
730
|
-
const buf = toolBuffers.get(callId);
|
|
731
|
-
const name = buf?.name || item.name || "";
|
|
732
|
-
const argsStr = buf?.arguments || item.arguments || "{}";
|
|
733
|
-
if (callId && name) {
|
|
734
|
-
if (!buf?.emittedStart) {
|
|
735
|
-
yield { type: "action:start", id: callId, name };
|
|
736
|
-
}
|
|
737
|
-
yield {
|
|
738
|
-
type: "action:args",
|
|
739
|
-
id: callId,
|
|
740
|
-
args: argsStr
|
|
741
|
-
};
|
|
742
|
-
yield {
|
|
743
|
-
type: "action:end",
|
|
744
|
-
id: callId,
|
|
745
|
-
name
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
toolBuffers.delete(callId);
|
|
749
|
-
}
|
|
750
|
-
continue;
|
|
751
|
-
}
|
|
752
|
-
if (t === "response.completed") {
|
|
753
|
-
const u = evt.response?.usage;
|
|
754
|
-
if (u) {
|
|
755
|
-
usage = {
|
|
756
|
-
prompt_tokens: u.input_tokens ?? 0,
|
|
757
|
-
completion_tokens: u.output_tokens ?? 0,
|
|
758
|
-
total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
|
|
759
|
-
};
|
|
760
|
-
}
|
|
761
|
-
for (const buf of toolBuffers.values()) {
|
|
762
|
-
if (!buf.id || !buf.name) continue;
|
|
763
|
-
if (!buf.emittedStart) {
|
|
764
|
-
yield { type: "action:start", id: buf.id, name: buf.name };
|
|
765
|
-
}
|
|
766
|
-
yield {
|
|
767
|
-
type: "action:args",
|
|
768
|
-
id: buf.id,
|
|
769
|
-
args: buf.arguments || "{}"
|
|
770
|
-
};
|
|
771
|
-
yield { type: "action:end", id: buf.id, name: buf.name };
|
|
772
|
-
}
|
|
773
|
-
toolBuffers.clear();
|
|
774
|
-
if (reasoningStarted && !textStarted) {
|
|
775
|
-
yield { type: "thinking:end" };
|
|
776
|
-
}
|
|
777
|
-
yield { type: "message:end" };
|
|
778
|
-
yield { type: "done", usage };
|
|
779
|
-
finishEmitted = true;
|
|
780
|
-
continue;
|
|
781
|
-
}
|
|
782
|
-
if (t === "response.error" || t === "error") {
|
|
783
|
-
const msg = evt.error?.message || evt.message || "Responses API error";
|
|
784
|
-
yield {
|
|
785
|
-
type: "error",
|
|
786
|
-
message: msg,
|
|
787
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
788
|
-
};
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
} catch (error) {
|
|
793
|
-
yield {
|
|
794
|
-
type: "error",
|
|
795
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
796
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
797
|
-
};
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
if (!finishEmitted) {
|
|
801
|
-
if (reasoningStarted && !textStarted) {
|
|
802
|
-
yield { type: "thinking:end" };
|
|
803
|
-
}
|
|
804
|
-
yield { type: "message:end" };
|
|
805
|
-
yield { type: "done", usage };
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
590
|
async completeWithResponses(request) {
|
|
809
591
|
const client = await this.getClient();
|
|
810
592
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
593
|
+
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
594
|
+
request.config?.responseFormat
|
|
595
|
+
);
|
|
811
596
|
const payload = {
|
|
812
597
|
model: request.config?.model || this.model,
|
|
813
598
|
instructions: request.systemPrompt,
|
|
@@ -817,6 +602,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
817
602
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
818
603
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
819
604
|
max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
605
|
+
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
820
606
|
stream: false
|
|
821
607
|
};
|
|
822
608
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
@@ -938,37 +724,21 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
938
724
|
name: openaiToolOptions.toolChoice.name
|
|
939
725
|
}
|
|
940
726
|
} : openaiToolOptions?.toolChoice;
|
|
941
|
-
const
|
|
942
|
-
const activeModel = request.config?.model || this.model;
|
|
943
|
-
const modelSlug = activeModel.replace("openai/", "");
|
|
944
|
-
const isOSeries = /^o[1-9]/.test(modelSlug);
|
|
945
|
-
const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
|
|
946
|
-
if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
|
|
947
|
-
yield* this.streamWithResponsesAPI(request, activeModel, messageId);
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
|
|
727
|
+
const modelIdForPayload = request.config?.model || this.model;
|
|
951
728
|
const payload = {
|
|
952
|
-
model:
|
|
729
|
+
model: modelIdForPayload,
|
|
953
730
|
messages,
|
|
954
731
|
tools: tools.length > 0 ? tools : void 0,
|
|
955
732
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
956
733
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
734
|
+
...buildOpenAITokenParams(
|
|
735
|
+
modelIdForPayload,
|
|
736
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
737
|
+
request.config?.temperature ?? this.config.temperature
|
|
738
|
+
),
|
|
739
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
957
740
|
stream: true,
|
|
958
|
-
stream_options: { include_usage: true }
|
|
959
|
-
// o-series: use max_completion_tokens + reasoning_effort, no temperature
|
|
960
|
-
// regular models: use max_tokens + temperature
|
|
961
|
-
...isOSeries ? {
|
|
962
|
-
max_completion_tokens: maxTokensValue,
|
|
963
|
-
reasoning_effort: request.config?.reasoningEffort ?? "medium"
|
|
964
|
-
} : {
|
|
965
|
-
temperature: request.config?.temperature ?? this.config.temperature,
|
|
966
|
-
max_tokens: maxTokensValue
|
|
967
|
-
},
|
|
968
|
-
// Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
|
|
969
|
-
// When disableThinking=true we must explicitly send include_reasoning:false because
|
|
970
|
-
// models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
|
|
971
|
-
...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
|
|
741
|
+
stream_options: { include_usage: true }
|
|
972
742
|
};
|
|
973
743
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
974
744
|
const stream = await client.chat.completions.create(payload);
|
|
@@ -976,7 +746,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
976
746
|
const collectedCitations = [];
|
|
977
747
|
let citationIndex = 0;
|
|
978
748
|
let usage;
|
|
979
|
-
let adapterReasoningStarted = false;
|
|
980
749
|
for await (const chunk of stream) {
|
|
981
750
|
logProviderPayload("openai", "stream chunk", chunk, request.debug);
|
|
982
751
|
if (request.signal?.aborted) {
|
|
@@ -987,22 +756,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
987
756
|
if (delta?.content) {
|
|
988
757
|
yield { type: "message:delta", content: delta.content };
|
|
989
758
|
}
|
|
990
|
-
if (isOpenRouter) {
|
|
991
|
-
const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
|
|
992
|
-
if (rc) {
|
|
993
|
-
const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
|
|
994
|
-
if (rcText) {
|
|
995
|
-
if (!adapterReasoningStarted) {
|
|
996
|
-
yield { type: "thinking:start" };
|
|
997
|
-
adapterReasoningStarted = true;
|
|
998
|
-
}
|
|
999
|
-
yield { type: "thinking:delta", content: rcText };
|
|
1000
|
-
}
|
|
1001
|
-
} else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
|
|
1002
|
-
yield { type: "thinking:end" };
|
|
1003
|
-
adapterReasoningStarted = false;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
759
|
const annotations = delta?.annotations;
|
|
1007
760
|
if (annotations && annotations.length > 0) {
|
|
1008
761
|
for (const annotation of annotations) {
|
|
@@ -1050,11 +803,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1050
803
|
};
|
|
1051
804
|
} else if (currentToolCall && toolCall.function?.arguments) {
|
|
1052
805
|
currentToolCall.arguments += toolCall.function.arguments;
|
|
1053
|
-
yield {
|
|
1054
|
-
type: "action:args",
|
|
1055
|
-
id: currentToolCall.id,
|
|
1056
|
-
args: currentToolCall.arguments
|
|
1057
|
-
};
|
|
1058
806
|
}
|
|
1059
807
|
}
|
|
1060
808
|
}
|
|
@@ -1130,24 +878,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1130
878
|
name: openaiToolOptions.toolChoice.name
|
|
1131
879
|
}
|
|
1132
880
|
} : openaiToolOptions?.toolChoice;
|
|
1133
|
-
const
|
|
1134
|
-
const modelSlug2 = activeModel2.replace("openai/", "");
|
|
1135
|
-
const isOSeries2 = /^o[1-9]/.test(modelSlug2);
|
|
1136
|
-
const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
|
|
881
|
+
const modelIdForCompletePayload = request.config?.model || this.model;
|
|
1137
882
|
const payload = {
|
|
1138
|
-
model:
|
|
883
|
+
model: modelIdForCompletePayload,
|
|
1139
884
|
messages,
|
|
1140
885
|
tools: tools.length > 0 ? tools : void 0,
|
|
1141
886
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
1142
887
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
}
|
|
888
|
+
...buildOpenAITokenParams(
|
|
889
|
+
modelIdForCompletePayload,
|
|
890
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
891
|
+
request.config?.temperature ?? this.config.temperature
|
|
892
|
+
),
|
|
893
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
894
|
+
stream: false
|
|
1151
895
|
};
|
|
1152
896
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
1153
897
|
const response = await client.chat.completions.create(payload);
|
|
@@ -1342,7 +1086,8 @@ function createXAI(config = {}) {
|
|
|
1342
1086
|
supportsVideo: false,
|
|
1343
1087
|
maxTokens: model.maxTokens,
|
|
1344
1088
|
supportedImageTypes: model.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : [],
|
|
1345
|
-
|
|
1089
|
+
// xAI accepts OpenAI-compatible `response_format` on grok-2-1212+.
|
|
1090
|
+
supportsJsonMode: true,
|
|
1346
1091
|
supportsSystemMessages: true
|
|
1347
1092
|
};
|
|
1348
1093
|
};
|