@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,3 +1,232 @@
|
|
|
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 formatTools(actions) {
|
|
134
|
+
return actions.map((action) => ({
|
|
135
|
+
type: "function",
|
|
136
|
+
function: {
|
|
137
|
+
name: action.name,
|
|
138
|
+
description: action.description,
|
|
139
|
+
parameters: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: action.parameters ? Object.fromEntries(
|
|
142
|
+
Object.entries(action.parameters).map(([key, param]) => [
|
|
143
|
+
key,
|
|
144
|
+
parameterToJsonSchema(param)
|
|
145
|
+
])
|
|
146
|
+
) : {},
|
|
147
|
+
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
148
|
+
additionalProperties: false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
function hasImageAttachments(message) {
|
|
154
|
+
const attachments = message.metadata?.attachments;
|
|
155
|
+
return attachments?.some((a) => a.type === "image") ?? false;
|
|
156
|
+
}
|
|
157
|
+
function attachmentToOpenAIImage(attachment) {
|
|
158
|
+
if (attachment.type !== "image") return null;
|
|
159
|
+
let imageUrl;
|
|
160
|
+
if (attachment.url) {
|
|
161
|
+
imageUrl = attachment.url;
|
|
162
|
+
} else if (attachment.data) {
|
|
163
|
+
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
164
|
+
} else {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
type: "image_url",
|
|
169
|
+
image_url: {
|
|
170
|
+
url: imageUrl,
|
|
171
|
+
detail: "auto"
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function messageToOpenAIContent(message) {
|
|
176
|
+
const attachments = message.metadata?.attachments;
|
|
177
|
+
const content = message.content ?? "";
|
|
178
|
+
if (!hasImageAttachments(message)) {
|
|
179
|
+
return content;
|
|
180
|
+
}
|
|
181
|
+
const blocks = [];
|
|
182
|
+
if (content) {
|
|
183
|
+
blocks.push({ type: "text", text: content });
|
|
184
|
+
}
|
|
185
|
+
if (attachments) {
|
|
186
|
+
for (const attachment of attachments) {
|
|
187
|
+
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
188
|
+
if (imageBlock) {
|
|
189
|
+
blocks.push(imageBlock);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return blocks;
|
|
194
|
+
}
|
|
195
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
196
|
+
const formatted = [];
|
|
197
|
+
if (systemPrompt) {
|
|
198
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
199
|
+
}
|
|
200
|
+
for (const msg of messages) {
|
|
201
|
+
if (msg.role === "system") {
|
|
202
|
+
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
203
|
+
} else if (msg.role === "user") {
|
|
204
|
+
formatted.push({
|
|
205
|
+
role: "user",
|
|
206
|
+
content: messageToOpenAIContent(msg)
|
|
207
|
+
});
|
|
208
|
+
} else if (msg.role === "assistant") {
|
|
209
|
+
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
210
|
+
const assistantMsg = {
|
|
211
|
+
role: "assistant",
|
|
212
|
+
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
213
|
+
content: hasToolCalls ? msg.content || null : msg.content
|
|
214
|
+
};
|
|
215
|
+
if (hasToolCalls) {
|
|
216
|
+
assistantMsg.tool_calls = msg.tool_calls;
|
|
217
|
+
}
|
|
218
|
+
formatted.push(assistantMsg);
|
|
219
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
220
|
+
formatted.push({
|
|
221
|
+
role: "tool",
|
|
222
|
+
content: msg.content ?? "",
|
|
223
|
+
tool_call_id: msg.tool_call_id
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return formatted;
|
|
228
|
+
}
|
|
229
|
+
|
|
1
230
|
// src/providers/google/provider.ts
|
|
2
231
|
var GOOGLE_MODELS = {
|
|
3
232
|
// Gemini 2.5 (Experimental)
|
|
@@ -117,7 +346,8 @@ function google(modelId, options = {}) {
|
|
|
117
346
|
messages,
|
|
118
347
|
tools: params.tools,
|
|
119
348
|
temperature: params.temperature,
|
|
120
|
-
max_tokens: params.maxTokens
|
|
349
|
+
max_tokens: params.maxTokens,
|
|
350
|
+
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
121
351
|
});
|
|
122
352
|
const choice = response.choices[0];
|
|
123
353
|
const message = choice.message;
|
|
@@ -149,6 +379,7 @@ function google(modelId, options = {}) {
|
|
|
149
379
|
tools: params.tools,
|
|
150
380
|
temperature: params.temperature,
|
|
151
381
|
max_tokens: params.maxTokens,
|
|
382
|
+
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
152
383
|
stream: true
|
|
153
384
|
});
|
|
154
385
|
let currentToolCall = null;
|
|
@@ -294,204 +525,6 @@ function generateToolCallId() {
|
|
|
294
525
|
return generateId("call");
|
|
295
526
|
}
|
|
296
527
|
|
|
297
|
-
// src/adapters/base.ts
|
|
298
|
-
function stringifyForDebug(value) {
|
|
299
|
-
return JSON.stringify(
|
|
300
|
-
value,
|
|
301
|
-
(_key, currentValue) => {
|
|
302
|
-
if (typeof currentValue === "bigint") {
|
|
303
|
-
return currentValue.toString();
|
|
304
|
-
}
|
|
305
|
-
if (currentValue instanceof Error) {
|
|
306
|
-
return {
|
|
307
|
-
name: currentValue.name,
|
|
308
|
-
message: currentValue.message,
|
|
309
|
-
stack: currentValue.stack
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
return currentValue;
|
|
313
|
-
},
|
|
314
|
-
2
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
function logProviderPayload(provider, label, payload, enabled) {
|
|
318
|
-
if (!enabled) {
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (label.toLowerCase().includes("stream ")) {
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
try {
|
|
325
|
-
console.log(
|
|
326
|
-
`[llm-sdk:${provider}] ${label}
|
|
327
|
-
${stringifyForDebug(payload)}`
|
|
328
|
-
);
|
|
329
|
-
} catch (error) {
|
|
330
|
-
console.log(
|
|
331
|
-
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
332
|
-
error
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
function parameterToJsonSchema(param) {
|
|
337
|
-
const schema = {
|
|
338
|
-
type: param.type
|
|
339
|
-
};
|
|
340
|
-
if (param.description) {
|
|
341
|
-
schema.description = param.description;
|
|
342
|
-
}
|
|
343
|
-
if (param.enum) {
|
|
344
|
-
schema.enum = param.enum;
|
|
345
|
-
}
|
|
346
|
-
if (param.type === "array" && param.items) {
|
|
347
|
-
schema.items = parameterToJsonSchema(
|
|
348
|
-
param.items
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
if (param.type === "object" && param.properties) {
|
|
352
|
-
schema.properties = Object.fromEntries(
|
|
353
|
-
Object.entries(param.properties).map(([key, prop]) => [
|
|
354
|
-
key,
|
|
355
|
-
parameterToJsonSchema(
|
|
356
|
-
prop
|
|
357
|
-
)
|
|
358
|
-
])
|
|
359
|
-
);
|
|
360
|
-
schema.additionalProperties = false;
|
|
361
|
-
}
|
|
362
|
-
return schema;
|
|
363
|
-
}
|
|
364
|
-
function normalizeObjectJsonSchema(schema) {
|
|
365
|
-
if (!schema || typeof schema !== "object") {
|
|
366
|
-
return {
|
|
367
|
-
type: "object",
|
|
368
|
-
properties: {},
|
|
369
|
-
required: [],
|
|
370
|
-
additionalProperties: false
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
const normalized = { ...schema };
|
|
374
|
-
const type = normalized.type;
|
|
375
|
-
if (type === "object") {
|
|
376
|
-
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
|
|
377
|
-
normalized.properties = Object.fromEntries(
|
|
378
|
-
Object.entries(properties).map(([key, value]) => [
|
|
379
|
-
key,
|
|
380
|
-
normalizeObjectJsonSchema(value)
|
|
381
|
-
])
|
|
382
|
-
);
|
|
383
|
-
const propertyKeys = Object.keys(properties);
|
|
384
|
-
const required = Array.isArray(normalized.required) ? normalized.required.filter(
|
|
385
|
-
(value) => typeof value === "string"
|
|
386
|
-
) : [];
|
|
387
|
-
normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
|
|
388
|
-
if (normalized.additionalProperties === void 0) {
|
|
389
|
-
normalized.additionalProperties = false;
|
|
390
|
-
}
|
|
391
|
-
} else if (type === "array" && normalized.items && typeof normalized.items === "object") {
|
|
392
|
-
normalized.items = normalizeObjectJsonSchema(
|
|
393
|
-
normalized.items
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
return normalized;
|
|
397
|
-
}
|
|
398
|
-
function formatTools(actions) {
|
|
399
|
-
return actions.map((action) => ({
|
|
400
|
-
type: "function",
|
|
401
|
-
function: {
|
|
402
|
-
name: action.name,
|
|
403
|
-
description: action.description,
|
|
404
|
-
parameters: {
|
|
405
|
-
type: "object",
|
|
406
|
-
properties: action.parameters ? Object.fromEntries(
|
|
407
|
-
Object.entries(action.parameters).map(([key, param]) => [
|
|
408
|
-
key,
|
|
409
|
-
parameterToJsonSchema(param)
|
|
410
|
-
])
|
|
411
|
-
) : {},
|
|
412
|
-
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
|
|
413
|
-
additionalProperties: false
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}));
|
|
417
|
-
}
|
|
418
|
-
function hasImageAttachments(message) {
|
|
419
|
-
const attachments = message.metadata?.attachments;
|
|
420
|
-
return attachments?.some((a) => a.type === "image") ?? false;
|
|
421
|
-
}
|
|
422
|
-
function attachmentToOpenAIImage(attachment) {
|
|
423
|
-
if (attachment.type !== "image") return null;
|
|
424
|
-
let imageUrl;
|
|
425
|
-
if (attachment.url) {
|
|
426
|
-
imageUrl = attachment.url;
|
|
427
|
-
} else if (attachment.data) {
|
|
428
|
-
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
429
|
-
} else {
|
|
430
|
-
return null;
|
|
431
|
-
}
|
|
432
|
-
return {
|
|
433
|
-
type: "image_url",
|
|
434
|
-
image_url: {
|
|
435
|
-
url: imageUrl,
|
|
436
|
-
detail: "auto"
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
function messageToOpenAIContent(message) {
|
|
441
|
-
const attachments = message.metadata?.attachments;
|
|
442
|
-
const content = message.content ?? "";
|
|
443
|
-
if (!hasImageAttachments(message)) {
|
|
444
|
-
return content;
|
|
445
|
-
}
|
|
446
|
-
const blocks = [];
|
|
447
|
-
if (content) {
|
|
448
|
-
blocks.push({ type: "text", text: content });
|
|
449
|
-
}
|
|
450
|
-
if (attachments) {
|
|
451
|
-
for (const attachment of attachments) {
|
|
452
|
-
const imageBlock = attachmentToOpenAIImage(attachment);
|
|
453
|
-
if (imageBlock) {
|
|
454
|
-
blocks.push(imageBlock);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
return blocks;
|
|
459
|
-
}
|
|
460
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
461
|
-
const formatted = [];
|
|
462
|
-
if (systemPrompt) {
|
|
463
|
-
formatted.push({ role: "system", content: systemPrompt });
|
|
464
|
-
}
|
|
465
|
-
for (const msg of messages) {
|
|
466
|
-
if (msg.role === "system") {
|
|
467
|
-
formatted.push({ role: "system", content: msg.content ?? "" });
|
|
468
|
-
} else if (msg.role === "user") {
|
|
469
|
-
formatted.push({
|
|
470
|
-
role: "user",
|
|
471
|
-
content: messageToOpenAIContent(msg)
|
|
472
|
-
});
|
|
473
|
-
} else if (msg.role === "assistant") {
|
|
474
|
-
const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
|
|
475
|
-
const assistantMsg = {
|
|
476
|
-
role: "assistant",
|
|
477
|
-
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
478
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
479
|
-
};
|
|
480
|
-
if (hasToolCalls) {
|
|
481
|
-
assistantMsg.tool_calls = msg.tool_calls;
|
|
482
|
-
}
|
|
483
|
-
formatted.push(assistantMsg);
|
|
484
|
-
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
485
|
-
formatted.push({
|
|
486
|
-
role: "tool",
|
|
487
|
-
content: msg.content ?? "",
|
|
488
|
-
tool_call_id: msg.tool_call_id
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return formatted;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
528
|
// src/adapters/openai.ts
|
|
496
529
|
var OpenAIAdapter = class _OpenAIAdapter {
|
|
497
530
|
constructor(config) {
|
|
@@ -504,7 +537,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
504
537
|
if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
|
|
505
538
|
if (baseUrl.includes("x.ai")) return "xai";
|
|
506
539
|
if (baseUrl.includes("azure")) return "azure";
|
|
507
|
-
if (baseUrl.includes("openrouter.ai")) return "openrouter";
|
|
508
540
|
return "openai";
|
|
509
541
|
}
|
|
510
542
|
async getClient() {
|
|
@@ -604,259 +636,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
604
636
|
rawResponse: response
|
|
605
637
|
};
|
|
606
638
|
}
|
|
607
|
-
/**
|
|
608
|
-
* OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
|
|
609
|
-
* reasoning content on the chat-completions endpoint. To surface reasoning
|
|
610
|
-
* SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
|
|
611
|
-
* Responses API, which streams `response.reasoning_summary_text.delta` events.
|
|
612
|
-
*
|
|
613
|
-
* Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
|
|
614
|
-
* openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
|
|
615
|
-
*/
|
|
616
|
-
isOpenAIReasoningModelOnOpenRouter(activeModel) {
|
|
617
|
-
if (this.provider !== "openrouter") return false;
|
|
618
|
-
return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* Convert ActionDefinition[] (the chat-completions tool shape used by the
|
|
622
|
-
* adapter) to the Responses API tool shape.
|
|
623
|
-
*/
|
|
624
|
-
buildResponsesToolsFromActions(actions) {
|
|
625
|
-
if (!actions || actions.length === 0) return void 0;
|
|
626
|
-
const formatted = formatTools(actions);
|
|
627
|
-
return formatted.map((t) => ({
|
|
628
|
-
type: "function",
|
|
629
|
-
name: t.function.name,
|
|
630
|
-
description: t.function.description,
|
|
631
|
-
parameters: t.function.parameters
|
|
632
|
-
}));
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Streaming Responses API path for OpenAI reasoning models on OpenRouter.
|
|
636
|
-
*
|
|
637
|
-
* Maps Responses API SSE events back to the same StreamEvent shapes the
|
|
638
|
-
* chat-completions path emits, so downstream consumers (processChunk.ts,
|
|
639
|
-
* frontend tool handlers, plan approval, specialist delegations) see
|
|
640
|
-
* identical events regardless of which path produced them.
|
|
641
|
-
*
|
|
642
|
-
* response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
|
|
643
|
-
* response.output_text.delta → message:delta
|
|
644
|
-
* response.output_item.added (function_call) → action:start (queued buffer)
|
|
645
|
-
* response.function_call_arguments.delta → action:args (progressive)
|
|
646
|
-
* response.output_item.done (function_call) → final action:args + action:end
|
|
647
|
-
* response.completed → message:end + done(usage)
|
|
648
|
-
* response.error → error
|
|
649
|
-
*/
|
|
650
|
-
async *streamWithResponsesAPI(request, activeModel, messageId) {
|
|
651
|
-
const client = await this.getClient();
|
|
652
|
-
const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
|
|
653
|
-
const payload = {
|
|
654
|
-
model: activeModel,
|
|
655
|
-
input: this.buildResponsesInput(request),
|
|
656
|
-
stream: true,
|
|
657
|
-
reasoning: {
|
|
658
|
-
effort: request.config?.reasoningEffort ?? "medium",
|
|
659
|
-
summary: "auto"
|
|
660
|
-
}
|
|
661
|
-
};
|
|
662
|
-
if (request.systemPrompt) payload.instructions = request.systemPrompt;
|
|
663
|
-
if (typeof maxTokensValue === "number")
|
|
664
|
-
payload.max_output_tokens = maxTokensValue;
|
|
665
|
-
const tools = this.buildResponsesToolsFromActions(request.actions);
|
|
666
|
-
if (tools && tools.length > 0) payload.tools = tools;
|
|
667
|
-
logProviderPayload(
|
|
668
|
-
"openai",
|
|
669
|
-
"responses-api request payload",
|
|
670
|
-
payload,
|
|
671
|
-
request.debug
|
|
672
|
-
);
|
|
673
|
-
let stream;
|
|
674
|
-
try {
|
|
675
|
-
stream = await client.responses.create(payload);
|
|
676
|
-
} catch (error) {
|
|
677
|
-
yield {
|
|
678
|
-
type: "error",
|
|
679
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
680
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
681
|
-
};
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
const toolBuffers = /* @__PURE__ */ new Map();
|
|
685
|
-
const itemIdToCallId = /* @__PURE__ */ new Map();
|
|
686
|
-
let usage;
|
|
687
|
-
let reasoningStarted = false;
|
|
688
|
-
let textStarted = false;
|
|
689
|
-
let finishEmitted = false;
|
|
690
|
-
const resolveCallId = (evt) => {
|
|
691
|
-
if (evt?.call_id) return evt.call_id;
|
|
692
|
-
if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
|
|
693
|
-
if (evt?.item?.call_id) return evt.item.call_id;
|
|
694
|
-
if (evt?.item?.id) return evt.item.id;
|
|
695
|
-
return "";
|
|
696
|
-
};
|
|
697
|
-
try {
|
|
698
|
-
for await (const evt of stream) {
|
|
699
|
-
logProviderPayload(
|
|
700
|
-
"openai",
|
|
701
|
-
"responses-api stream chunk",
|
|
702
|
-
evt,
|
|
703
|
-
request.debug
|
|
704
|
-
);
|
|
705
|
-
if (request.signal?.aborted) break;
|
|
706
|
-
const t = evt?.type ?? "";
|
|
707
|
-
if (t === "response.reasoning_summary_text.delta") {
|
|
708
|
-
const delta = evt.delta ?? "";
|
|
709
|
-
if (!delta) continue;
|
|
710
|
-
if (!reasoningStarted) {
|
|
711
|
-
yield { type: "thinking:start" };
|
|
712
|
-
reasoningStarted = true;
|
|
713
|
-
}
|
|
714
|
-
yield { type: "thinking:delta", content: delta };
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
|
|
718
|
-
continue;
|
|
719
|
-
}
|
|
720
|
-
if (t === "response.output_text.delta") {
|
|
721
|
-
const text = evt.delta ?? "";
|
|
722
|
-
if (!text) continue;
|
|
723
|
-
if (reasoningStarted && !textStarted) {
|
|
724
|
-
yield { type: "thinking:end" };
|
|
725
|
-
textStarted = true;
|
|
726
|
-
}
|
|
727
|
-
yield { type: "message:delta", content: text };
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
if (t === "response.output_item.added") {
|
|
731
|
-
const item = evt.item;
|
|
732
|
-
if (item?.type === "function_call") {
|
|
733
|
-
const callId = item.call_id ?? item.id ?? "";
|
|
734
|
-
const itemId = item.id ?? callId;
|
|
735
|
-
if (callId) {
|
|
736
|
-
if (itemId && itemId !== callId) {
|
|
737
|
-
itemIdToCallId.set(itemId, callId);
|
|
738
|
-
}
|
|
739
|
-
if (!toolBuffers.has(callId)) {
|
|
740
|
-
toolBuffers.set(callId, {
|
|
741
|
-
id: callId,
|
|
742
|
-
name: item.name ?? "",
|
|
743
|
-
arguments: item.arguments ?? "",
|
|
744
|
-
emittedStart: false
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
const buf = toolBuffers.get(callId);
|
|
748
|
-
if (buf.name && !buf.emittedStart) {
|
|
749
|
-
yield { type: "action:start", id: buf.id, name: buf.name };
|
|
750
|
-
buf.emittedStart = true;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
continue;
|
|
755
|
-
}
|
|
756
|
-
if (t === "response.function_call_arguments.delta") {
|
|
757
|
-
const callId = resolveCallId(evt);
|
|
758
|
-
const delta = evt.delta ?? "";
|
|
759
|
-
if (!callId || !delta) continue;
|
|
760
|
-
let buf = toolBuffers.get(callId);
|
|
761
|
-
if (!buf) {
|
|
762
|
-
buf = { id: callId, name: "", arguments: "", emittedStart: false };
|
|
763
|
-
toolBuffers.set(callId, buf);
|
|
764
|
-
}
|
|
765
|
-
buf.arguments += delta;
|
|
766
|
-
if (buf.emittedStart) {
|
|
767
|
-
yield {
|
|
768
|
-
type: "action:args",
|
|
769
|
-
id: buf.id,
|
|
770
|
-
args: buf.arguments
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
continue;
|
|
774
|
-
}
|
|
775
|
-
if (t === "response.output_item.done") {
|
|
776
|
-
const item = evt.item;
|
|
777
|
-
if (item?.type === "function_call") {
|
|
778
|
-
const callId = item.call_id ?? item.id ?? "";
|
|
779
|
-
const buf = toolBuffers.get(callId);
|
|
780
|
-
const name = buf?.name || item.name || "";
|
|
781
|
-
const argsStr = buf?.arguments || item.arguments || "{}";
|
|
782
|
-
if (callId && name) {
|
|
783
|
-
if (!buf?.emittedStart) {
|
|
784
|
-
yield { type: "action:start", id: callId, name };
|
|
785
|
-
}
|
|
786
|
-
yield {
|
|
787
|
-
type: "action:args",
|
|
788
|
-
id: callId,
|
|
789
|
-
args: argsStr
|
|
790
|
-
};
|
|
791
|
-
yield {
|
|
792
|
-
type: "action:end",
|
|
793
|
-
id: callId,
|
|
794
|
-
name
|
|
795
|
-
};
|
|
796
|
-
}
|
|
797
|
-
toolBuffers.delete(callId);
|
|
798
|
-
}
|
|
799
|
-
continue;
|
|
800
|
-
}
|
|
801
|
-
if (t === "response.completed") {
|
|
802
|
-
const u = evt.response?.usage;
|
|
803
|
-
if (u) {
|
|
804
|
-
usage = {
|
|
805
|
-
prompt_tokens: u.input_tokens ?? 0,
|
|
806
|
-
completion_tokens: u.output_tokens ?? 0,
|
|
807
|
-
total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
for (const buf of toolBuffers.values()) {
|
|
811
|
-
if (!buf.id || !buf.name) continue;
|
|
812
|
-
if (!buf.emittedStart) {
|
|
813
|
-
yield { type: "action:start", id: buf.id, name: buf.name };
|
|
814
|
-
}
|
|
815
|
-
yield {
|
|
816
|
-
type: "action:args",
|
|
817
|
-
id: buf.id,
|
|
818
|
-
args: buf.arguments || "{}"
|
|
819
|
-
};
|
|
820
|
-
yield { type: "action:end", id: buf.id, name: buf.name };
|
|
821
|
-
}
|
|
822
|
-
toolBuffers.clear();
|
|
823
|
-
if (reasoningStarted && !textStarted) {
|
|
824
|
-
yield { type: "thinking:end" };
|
|
825
|
-
}
|
|
826
|
-
yield { type: "message:end" };
|
|
827
|
-
yield { type: "done", usage };
|
|
828
|
-
finishEmitted = true;
|
|
829
|
-
continue;
|
|
830
|
-
}
|
|
831
|
-
if (t === "response.error" || t === "error") {
|
|
832
|
-
const msg = evt.error?.message || evt.message || "Responses API error";
|
|
833
|
-
yield {
|
|
834
|
-
type: "error",
|
|
835
|
-
message: msg,
|
|
836
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
837
|
-
};
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
} catch (error) {
|
|
842
|
-
yield {
|
|
843
|
-
type: "error",
|
|
844
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
845
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
846
|
-
};
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
if (!finishEmitted) {
|
|
850
|
-
if (reasoningStarted && !textStarted) {
|
|
851
|
-
yield { type: "thinking:end" };
|
|
852
|
-
}
|
|
853
|
-
yield { type: "message:end" };
|
|
854
|
-
yield { type: "done", usage };
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
639
|
async completeWithResponses(request) {
|
|
858
640
|
const client = await this.getClient();
|
|
859
641
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
642
|
+
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
643
|
+
request.config?.responseFormat
|
|
644
|
+
);
|
|
860
645
|
const payload = {
|
|
861
646
|
model: request.config?.model || this.model,
|
|
862
647
|
instructions: request.systemPrompt,
|
|
@@ -866,6 +651,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
866
651
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
867
652
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
868
653
|
max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
654
|
+
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
869
655
|
stream: false
|
|
870
656
|
};
|
|
871
657
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
@@ -987,37 +773,21 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
987
773
|
name: openaiToolOptions.toolChoice.name
|
|
988
774
|
}
|
|
989
775
|
} : openaiToolOptions?.toolChoice;
|
|
990
|
-
const
|
|
991
|
-
const activeModel = request.config?.model || this.model;
|
|
992
|
-
const modelSlug = activeModel.replace("openai/", "");
|
|
993
|
-
const isOSeries = /^o[1-9]/.test(modelSlug);
|
|
994
|
-
const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
|
|
995
|
-
if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
|
|
996
|
-
yield* this.streamWithResponsesAPI(request, activeModel, messageId);
|
|
997
|
-
return;
|
|
998
|
-
}
|
|
999
|
-
const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
|
|
776
|
+
const modelIdForPayload = request.config?.model || this.model;
|
|
1000
777
|
const payload = {
|
|
1001
|
-
model:
|
|
778
|
+
model: modelIdForPayload,
|
|
1002
779
|
messages,
|
|
1003
780
|
tools: tools.length > 0 ? tools : void 0,
|
|
1004
781
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
1005
782
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
783
|
+
...buildOpenAITokenParams(
|
|
784
|
+
modelIdForPayload,
|
|
785
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
786
|
+
request.config?.temperature ?? this.config.temperature
|
|
787
|
+
),
|
|
788
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
1006
789
|
stream: true,
|
|
1007
|
-
stream_options: { include_usage: true }
|
|
1008
|
-
// o-series: use max_completion_tokens + reasoning_effort, no temperature
|
|
1009
|
-
// regular models: use max_tokens + temperature
|
|
1010
|
-
...isOSeries ? {
|
|
1011
|
-
max_completion_tokens: maxTokensValue,
|
|
1012
|
-
reasoning_effort: request.config?.reasoningEffort ?? "medium"
|
|
1013
|
-
} : {
|
|
1014
|
-
temperature: request.config?.temperature ?? this.config.temperature,
|
|
1015
|
-
max_tokens: maxTokensValue
|
|
1016
|
-
},
|
|
1017
|
-
// Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
|
|
1018
|
-
// When disableThinking=true we must explicitly send include_reasoning:false because
|
|
1019
|
-
// models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
|
|
1020
|
-
...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
|
|
790
|
+
stream_options: { include_usage: true }
|
|
1021
791
|
};
|
|
1022
792
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
1023
793
|
const stream = await client.chat.completions.create(payload);
|
|
@@ -1025,7 +795,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1025
795
|
const collectedCitations = [];
|
|
1026
796
|
let citationIndex = 0;
|
|
1027
797
|
let usage;
|
|
1028
|
-
let adapterReasoningStarted = false;
|
|
1029
798
|
for await (const chunk of stream) {
|
|
1030
799
|
logProviderPayload("openai", "stream chunk", chunk, request.debug);
|
|
1031
800
|
if (request.signal?.aborted) {
|
|
@@ -1036,22 +805,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1036
805
|
if (delta?.content) {
|
|
1037
806
|
yield { type: "message:delta", content: delta.content };
|
|
1038
807
|
}
|
|
1039
|
-
if (isOpenRouter) {
|
|
1040
|
-
const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
|
|
1041
|
-
if (rc) {
|
|
1042
|
-
const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
|
|
1043
|
-
if (rcText) {
|
|
1044
|
-
if (!adapterReasoningStarted) {
|
|
1045
|
-
yield { type: "thinking:start" };
|
|
1046
|
-
adapterReasoningStarted = true;
|
|
1047
|
-
}
|
|
1048
|
-
yield { type: "thinking:delta", content: rcText };
|
|
1049
|
-
}
|
|
1050
|
-
} else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
|
|
1051
|
-
yield { type: "thinking:end" };
|
|
1052
|
-
adapterReasoningStarted = false;
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
808
|
const annotations = delta?.annotations;
|
|
1056
809
|
if (annotations && annotations.length > 0) {
|
|
1057
810
|
for (const annotation of annotations) {
|
|
@@ -1099,11 +852,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1099
852
|
};
|
|
1100
853
|
} else if (currentToolCall && toolCall.function?.arguments) {
|
|
1101
854
|
currentToolCall.arguments += toolCall.function.arguments;
|
|
1102
|
-
yield {
|
|
1103
|
-
type: "action:args",
|
|
1104
|
-
id: currentToolCall.id,
|
|
1105
|
-
args: currentToolCall.arguments
|
|
1106
|
-
};
|
|
1107
855
|
}
|
|
1108
856
|
}
|
|
1109
857
|
}
|
|
@@ -1179,24 +927,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1179
927
|
name: openaiToolOptions.toolChoice.name
|
|
1180
928
|
}
|
|
1181
929
|
} : openaiToolOptions?.toolChoice;
|
|
1182
|
-
const
|
|
1183
|
-
const modelSlug2 = activeModel2.replace("openai/", "");
|
|
1184
|
-
const isOSeries2 = /^o[1-9]/.test(modelSlug2);
|
|
1185
|
-
const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
|
|
930
|
+
const modelIdForCompletePayload = request.config?.model || this.model;
|
|
1186
931
|
const payload = {
|
|
1187
|
-
model:
|
|
932
|
+
model: modelIdForCompletePayload,
|
|
1188
933
|
messages,
|
|
1189
934
|
tools: tools.length > 0 ? tools : void 0,
|
|
1190
935
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
1191
936
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
}
|
|
937
|
+
...buildOpenAITokenParams(
|
|
938
|
+
modelIdForCompletePayload,
|
|
939
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
940
|
+
request.config?.temperature ?? this.config.temperature
|
|
941
|
+
),
|
|
942
|
+
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
943
|
+
stream: false
|
|
1200
944
|
};
|
|
1201
945
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
1202
946
|
const response = await client.chat.completions.create(payload);
|