@yourgpt/llm-sdk 2.6.0-beta.0 → 2.6.0-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 +77 -0
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +255 -164
- package/dist/adapters/index.mjs +255 -164
- package/dist/{base-C58Dsr9p.d.ts → base-BdTpUAWI.d.ts} +2 -1
- package/dist/{base-tNgbBaSo.d.mts → base-CkeT7u-O.d.mts} +2 -1
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/fallback/index.js +75 -39
- package/dist/fallback/index.mjs +75 -39
- package/dist/index.d.mts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +75 -28
- package/dist/index.mjs +75 -28
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +255 -164
- package/dist/providers/fireworks/index.mjs +255 -164
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +255 -164
- package/dist/providers/google/index.mjs +255 -164
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/openai/index.d.mts +6 -23
- package/dist/providers/openai/index.d.ts +6 -23
- package/dist/providers/openai/index.js +656 -450
- package/dist/providers/openai/index.mjs +656 -450
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +255 -164
- package/dist/providers/openrouter/index.mjs +255 -164
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +255 -164
- package/dist/providers/togetherai/index.mjs +255 -164
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +255 -164
- package/dist/providers/xai/index.mjs +255 -164
- package/dist/{types-BkQCSiIt.d.mts → types-BW3csYo5.d.mts} +22 -1
- package/dist/{types-BkQCSiIt.d.ts → types-BW3csYo5.d.ts} +22 -1
- package/dist/{types-B6dhnguR.d.mts → types-BWRYIvl_.d.mts} +11 -4
- package/dist/{types-CCxPmkmK.d.ts → types-CpXcT-tY.d.ts} +11 -4
- package/dist/{types-BQ31QIsA.d.ts → types-DA54bSmX.d.ts} +3 -11
- package/dist/{types-BSSiJW2o.d.mts → types-NOswlhm9.d.mts} +3 -11
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/package.json +115 -48
- package/LICENSE +0 -21
|
@@ -1,3 +1,96 @@
|
|
|
1
|
+
// src/core/openai-parameters.ts
|
|
2
|
+
function capabilities(model) {
|
|
3
|
+
const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
|
|
4
|
+
const major = Number(gpt?.[1] ?? 0);
|
|
5
|
+
const minor = Number(gpt?.[2] ?? 0);
|
|
6
|
+
const chat = gpt?.[3]?.startsWith("chat") ?? false;
|
|
7
|
+
const reasoning = /^o\d+(?:-|$)/i.test(model) || major >= 5 && !chat;
|
|
8
|
+
const supportsNone = major === 5 && minor >= 1 && !chat || /^gpt-6-(?:sol|luna)(?:-\d{4}-\d{2}-\d{2})?$/i.test(model);
|
|
9
|
+
return { major, minor, reasoning, supportsNone };
|
|
10
|
+
}
|
|
11
|
+
function requiresOpenAIResponses(model, baseUrl, options = {}) {
|
|
12
|
+
if (options.parameterPolicy === "passthrough") return false;
|
|
13
|
+
const c = capabilities(model);
|
|
14
|
+
if (!c.reasoning || options.reasoningEffort === "none") return false;
|
|
15
|
+
if (!(c.major >= 6 || c.major === 5 && c.minor >= 4)) return false;
|
|
16
|
+
if (!baseUrl) return true;
|
|
17
|
+
try {
|
|
18
|
+
return new URL(baseUrl).hostname === "api.openai.com";
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function buildOpenAIParameters(model, maxTokens, temperature, options = {}, api = "chat") {
|
|
24
|
+
const c = capabilities(model ?? "");
|
|
25
|
+
const normalize = options.parameterPolicy !== "passthrough";
|
|
26
|
+
const effort = options.reasoningEffort;
|
|
27
|
+
if (normalize && c.reasoning && effort === "none" && !c.supportsNone) {
|
|
28
|
+
throw new Error(`${model} does not support reasoningEffort: none`);
|
|
29
|
+
}
|
|
30
|
+
if (normalize && c.major >= 6 && effort === "minimal") {
|
|
31
|
+
throw new Error(`${model} does not support reasoningEffort: minimal`);
|
|
32
|
+
}
|
|
33
|
+
const result = {
|
|
34
|
+
[api === "responses" ? "max_output_tokens" : normalize && c.reasoning ? "max_completion_tokens" : "max_tokens"]: maxTokens
|
|
35
|
+
};
|
|
36
|
+
if (effort !== void 0) {
|
|
37
|
+
if (api === "responses") result.reasoning = { effort };
|
|
38
|
+
else result.reasoning_effort = effort;
|
|
39
|
+
}
|
|
40
|
+
if (temperature !== void 0) {
|
|
41
|
+
if (!normalize || !c.reasoning || effort === "none" && c.supportsNone) {
|
|
42
|
+
result.temperature = temperature;
|
|
43
|
+
} else {
|
|
44
|
+
(options.onWarning ?? console.warn)(
|
|
45
|
+
`[llm-sdk] ${model}: omitted temperature because reasoning is enabled.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/core/provider-error.ts
|
|
53
|
+
function providerErrorEvent(error, code) {
|
|
54
|
+
const details = error ?? {};
|
|
55
|
+
const event = {
|
|
56
|
+
type: "error",
|
|
57
|
+
message: error instanceof Error ? error.message : String(error),
|
|
58
|
+
code,
|
|
59
|
+
...typeof details.status === "number" ? { status: details.status } : {},
|
|
60
|
+
...typeof details.code === "string" ? { providerCode: details.code } : {},
|
|
61
|
+
...typeof details.param === "string" ? { param: details.param } : {},
|
|
62
|
+
...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(event, "cause", { value: error, enumerable: false });
|
|
65
|
+
return event;
|
|
66
|
+
}
|
|
67
|
+
function errorFromEvent(event) {
|
|
68
|
+
if (event.cause instanceof Error) return event.cause;
|
|
69
|
+
return Object.assign(new Error(event.message), {
|
|
70
|
+
status: event.status,
|
|
71
|
+
code: event.providerCode ?? event.code,
|
|
72
|
+
param: event.param,
|
|
73
|
+
request_id: event.requestId
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function throwIfAborted(signal) {
|
|
77
|
+
if (!signal?.aborted) return;
|
|
78
|
+
const error = new Error("The operation was aborted");
|
|
79
|
+
error.name = "AbortError";
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/core/utils.ts
|
|
84
|
+
function generateId(prefix = "id") {
|
|
85
|
+
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
86
|
+
}
|
|
87
|
+
function generateMessageId() {
|
|
88
|
+
return generateId("msg");
|
|
89
|
+
}
|
|
90
|
+
function generateToolCallId() {
|
|
91
|
+
return generateId("call");
|
|
92
|
+
}
|
|
93
|
+
|
|
1
94
|
// src/adapters/base.ts
|
|
2
95
|
function stringifyForDebug(value) {
|
|
3
96
|
return JSON.stringify(
|
|
@@ -104,16 +197,6 @@ function normalizeObjectJsonSchema(schema) {
|
|
|
104
197
|
}
|
|
105
198
|
return normalized;
|
|
106
199
|
}
|
|
107
|
-
function isOpenAIReasoningModel(modelId) {
|
|
108
|
-
if (!modelId) return false;
|
|
109
|
-
return /^(o1|o3|o4|gpt-5)/i.test(modelId);
|
|
110
|
-
}
|
|
111
|
-
function buildOpenAITokenParams(modelId, maxTokens, temperature) {
|
|
112
|
-
if (isOpenAIReasoningModel(modelId)) {
|
|
113
|
-
return { max_completion_tokens: maxTokens };
|
|
114
|
-
}
|
|
115
|
-
return { max_tokens: maxTokens, temperature };
|
|
116
|
-
}
|
|
117
200
|
function toOpenAIResponseFormat(rf) {
|
|
118
201
|
if (!rf) return void 0;
|
|
119
202
|
if (rf.type === "json_object") return { type: "json_object" };
|
|
@@ -233,291 +316,6 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
233
316
|
return formatted;
|
|
234
317
|
}
|
|
235
318
|
|
|
236
|
-
// src/providers/openai/provider.ts
|
|
237
|
-
var OPENAI_MODELS = {
|
|
238
|
-
// GPT-4o series
|
|
239
|
-
"gpt-4o": { vision: true, tools: true, jsonMode: true, maxTokens: 128e3 },
|
|
240
|
-
"gpt-5.2": {
|
|
241
|
-
vision: true,
|
|
242
|
-
tools: true,
|
|
243
|
-
jsonMode: true,
|
|
244
|
-
maxTokens: 128e3
|
|
245
|
-
},
|
|
246
|
-
"gpt-4o-2024-11-20": {
|
|
247
|
-
vision: true,
|
|
248
|
-
tools: true,
|
|
249
|
-
jsonMode: true,
|
|
250
|
-
maxTokens: 128e3
|
|
251
|
-
},
|
|
252
|
-
"gpt-4o-2024-08-06": {
|
|
253
|
-
vision: true,
|
|
254
|
-
tools: true,
|
|
255
|
-
jsonMode: true,
|
|
256
|
-
maxTokens: 128e3
|
|
257
|
-
},
|
|
258
|
-
// GPT-4 Turbo
|
|
259
|
-
"gpt-4-turbo": {
|
|
260
|
-
vision: true,
|
|
261
|
-
tools: true,
|
|
262
|
-
jsonMode: true,
|
|
263
|
-
maxTokens: 128e3
|
|
264
|
-
},
|
|
265
|
-
"gpt-4-turbo-preview": {
|
|
266
|
-
vision: false,
|
|
267
|
-
tools: true,
|
|
268
|
-
jsonMode: true,
|
|
269
|
-
maxTokens: 128e3
|
|
270
|
-
},
|
|
271
|
-
// GPT-4
|
|
272
|
-
"gpt-4": { vision: false, tools: true, jsonMode: false, maxTokens: 8192 },
|
|
273
|
-
"gpt-4-32k": {
|
|
274
|
-
vision: false,
|
|
275
|
-
tools: true,
|
|
276
|
-
jsonMode: false,
|
|
277
|
-
maxTokens: 32768
|
|
278
|
-
},
|
|
279
|
-
// GPT-3.5
|
|
280
|
-
"gpt-3.5-turbo": {
|
|
281
|
-
vision: false,
|
|
282
|
-
tools: true,
|
|
283
|
-
jsonMode: true,
|
|
284
|
-
maxTokens: 16385
|
|
285
|
-
},
|
|
286
|
-
// O1 series (reasoning)
|
|
287
|
-
o1: { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
288
|
-
"o1-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
289
|
-
"o1-preview": {
|
|
290
|
-
vision: true,
|
|
291
|
-
tools: false,
|
|
292
|
-
jsonMode: false,
|
|
293
|
-
maxTokens: 128e3
|
|
294
|
-
},
|
|
295
|
-
// O3 series
|
|
296
|
-
"o3-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 }
|
|
297
|
-
};
|
|
298
|
-
function openai(modelId, options = {}) {
|
|
299
|
-
const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
|
|
300
|
-
const baseURL = options.baseURL ?? "https://api.openai.com/v1";
|
|
301
|
-
let client = null;
|
|
302
|
-
async function getClient() {
|
|
303
|
-
if (!client) {
|
|
304
|
-
const { default: OpenAI } = await import('openai');
|
|
305
|
-
client = new OpenAI({
|
|
306
|
-
apiKey,
|
|
307
|
-
baseURL,
|
|
308
|
-
organization: options.organization,
|
|
309
|
-
defaultHeaders: options.headers
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
return client;
|
|
313
|
-
}
|
|
314
|
-
const modelConfig = OPENAI_MODELS[modelId] ?? OPENAI_MODELS["gpt-4o"];
|
|
315
|
-
return {
|
|
316
|
-
provider: "openai",
|
|
317
|
-
modelId,
|
|
318
|
-
capabilities: {
|
|
319
|
-
supportsVision: modelConfig.vision,
|
|
320
|
-
supportsTools: modelConfig.tools,
|
|
321
|
-
supportsStreaming: true,
|
|
322
|
-
supportsJsonMode: modelConfig.jsonMode,
|
|
323
|
-
supportsThinking: false,
|
|
324
|
-
supportsPDF: false,
|
|
325
|
-
maxTokens: modelConfig.maxTokens,
|
|
326
|
-
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
327
|
-
},
|
|
328
|
-
async doGenerate(params) {
|
|
329
|
-
const client2 = await getClient();
|
|
330
|
-
const messages = formatMessagesForOpenAI2(params.messages);
|
|
331
|
-
const response = await client2.chat.completions.create({
|
|
332
|
-
model: modelId,
|
|
333
|
-
messages,
|
|
334
|
-
tools: params.tools,
|
|
335
|
-
...buildOpenAITokenParams(
|
|
336
|
-
modelId,
|
|
337
|
-
params.maxTokens,
|
|
338
|
-
params.temperature
|
|
339
|
-
),
|
|
340
|
-
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
341
|
-
});
|
|
342
|
-
const choice = response.choices[0];
|
|
343
|
-
const message = choice.message;
|
|
344
|
-
const toolCalls = (message.tool_calls ?? []).map(
|
|
345
|
-
(tc) => ({
|
|
346
|
-
id: tc.id,
|
|
347
|
-
name: tc.function.name,
|
|
348
|
-
args: JSON.parse(tc.function.arguments || "{}")
|
|
349
|
-
})
|
|
350
|
-
);
|
|
351
|
-
return {
|
|
352
|
-
text: message.content ?? "",
|
|
353
|
-
toolCalls,
|
|
354
|
-
finishReason: mapFinishReason(choice.finish_reason),
|
|
355
|
-
usage: {
|
|
356
|
-
promptTokens: response.usage?.prompt_tokens ?? 0,
|
|
357
|
-
completionTokens: response.usage?.completion_tokens ?? 0,
|
|
358
|
-
totalTokens: response.usage?.total_tokens ?? 0
|
|
359
|
-
},
|
|
360
|
-
rawResponse: response
|
|
361
|
-
};
|
|
362
|
-
},
|
|
363
|
-
async *doStream(params) {
|
|
364
|
-
const client2 = await getClient();
|
|
365
|
-
const messages = formatMessagesForOpenAI2(params.messages);
|
|
366
|
-
const stream = await client2.chat.completions.create({
|
|
367
|
-
model: modelId,
|
|
368
|
-
messages,
|
|
369
|
-
tools: params.tools,
|
|
370
|
-
...buildOpenAITokenParams(
|
|
371
|
-
modelId,
|
|
372
|
-
params.maxTokens,
|
|
373
|
-
params.temperature
|
|
374
|
-
),
|
|
375
|
-
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
376
|
-
stream: true
|
|
377
|
-
});
|
|
378
|
-
let currentToolCall = null;
|
|
379
|
-
let totalPromptTokens = 0;
|
|
380
|
-
let totalCompletionTokens = 0;
|
|
381
|
-
for await (const chunk of stream) {
|
|
382
|
-
if (params.signal?.aborted) {
|
|
383
|
-
yield { type: "error", error: new Error("Aborted") };
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
const choice = chunk.choices[0];
|
|
387
|
-
const delta = choice?.delta;
|
|
388
|
-
if (delta?.content) {
|
|
389
|
-
yield { type: "text-delta", text: delta.content };
|
|
390
|
-
}
|
|
391
|
-
if (delta?.tool_calls) {
|
|
392
|
-
for (const tc of delta.tool_calls) {
|
|
393
|
-
if (tc.id) {
|
|
394
|
-
if (currentToolCall) {
|
|
395
|
-
yield {
|
|
396
|
-
type: "tool-call",
|
|
397
|
-
toolCall: {
|
|
398
|
-
id: currentToolCall.id,
|
|
399
|
-
name: currentToolCall.name,
|
|
400
|
-
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
401
|
-
}
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
currentToolCall = {
|
|
405
|
-
id: tc.id,
|
|
406
|
-
name: tc.function?.name ?? "",
|
|
407
|
-
arguments: tc.function?.arguments ?? ""
|
|
408
|
-
};
|
|
409
|
-
} else if (currentToolCall && tc.function?.arguments) {
|
|
410
|
-
currentToolCall.arguments += tc.function.arguments;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
if (choice?.finish_reason) {
|
|
415
|
-
if (currentToolCall) {
|
|
416
|
-
yield {
|
|
417
|
-
type: "tool-call",
|
|
418
|
-
toolCall: {
|
|
419
|
-
id: currentToolCall.id,
|
|
420
|
-
name: currentToolCall.name,
|
|
421
|
-
args: JSON.parse(currentToolCall.arguments || "{}")
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
currentToolCall = null;
|
|
425
|
-
}
|
|
426
|
-
if (chunk.usage) {
|
|
427
|
-
totalPromptTokens = chunk.usage.prompt_tokens;
|
|
428
|
-
totalCompletionTokens = chunk.usage.completion_tokens;
|
|
429
|
-
}
|
|
430
|
-
yield {
|
|
431
|
-
type: "finish",
|
|
432
|
-
finishReason: mapFinishReason(choice.finish_reason),
|
|
433
|
-
usage: {
|
|
434
|
-
promptTokens: totalPromptTokens,
|
|
435
|
-
completionTokens: totalCompletionTokens,
|
|
436
|
-
totalTokens: totalPromptTokens + totalCompletionTokens
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
function mapFinishReason(reason) {
|
|
445
|
-
switch (reason) {
|
|
446
|
-
case "stop":
|
|
447
|
-
return "stop";
|
|
448
|
-
case "length":
|
|
449
|
-
return "length";
|
|
450
|
-
case "tool_calls":
|
|
451
|
-
case "function_call":
|
|
452
|
-
return "tool-calls";
|
|
453
|
-
case "content_filter":
|
|
454
|
-
return "content-filter";
|
|
455
|
-
default:
|
|
456
|
-
return "unknown";
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
function formatMessagesForOpenAI2(messages) {
|
|
460
|
-
return messages.map((msg) => {
|
|
461
|
-
switch (msg.role) {
|
|
462
|
-
case "system":
|
|
463
|
-
return { role: "system", content: msg.content };
|
|
464
|
-
case "user":
|
|
465
|
-
if (typeof msg.content === "string") {
|
|
466
|
-
return { role: "user", content: msg.content };
|
|
467
|
-
}
|
|
468
|
-
return {
|
|
469
|
-
role: "user",
|
|
470
|
-
content: msg.content.map((part) => {
|
|
471
|
-
if (part.type === "text") {
|
|
472
|
-
return { type: "text", text: part.text };
|
|
473
|
-
}
|
|
474
|
-
if (part.type === "image") {
|
|
475
|
-
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
476
|
-
const url = imageData.startsWith("data:") ? imageData : `data:${part.mimeType ?? "image/png"};base64,${imageData}`;
|
|
477
|
-
return { type: "image_url", image_url: { url, detail: "auto" } };
|
|
478
|
-
}
|
|
479
|
-
return { type: "text", text: "" };
|
|
480
|
-
})
|
|
481
|
-
};
|
|
482
|
-
case "assistant":
|
|
483
|
-
const assistantMsg = {
|
|
484
|
-
role: "assistant",
|
|
485
|
-
content: msg.content
|
|
486
|
-
};
|
|
487
|
-
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
488
|
-
assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({
|
|
489
|
-
id: tc.id,
|
|
490
|
-
type: "function",
|
|
491
|
-
function: {
|
|
492
|
-
name: tc.name,
|
|
493
|
-
arguments: JSON.stringify(tc.args)
|
|
494
|
-
}
|
|
495
|
-
}));
|
|
496
|
-
}
|
|
497
|
-
return assistantMsg;
|
|
498
|
-
case "tool":
|
|
499
|
-
return {
|
|
500
|
-
role: "tool",
|
|
501
|
-
tool_call_id: msg.toolCallId,
|
|
502
|
-
content: msg.content
|
|
503
|
-
};
|
|
504
|
-
default:
|
|
505
|
-
return msg;
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// src/core/utils.ts
|
|
511
|
-
function generateId(prefix = "id") {
|
|
512
|
-
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
513
|
-
}
|
|
514
|
-
function generateMessageId() {
|
|
515
|
-
return generateId("msg");
|
|
516
|
-
}
|
|
517
|
-
function generateToolCallId() {
|
|
518
|
-
return generateId("call");
|
|
519
|
-
}
|
|
520
|
-
|
|
521
319
|
// src/adapters/openai.ts
|
|
522
320
|
var OpenAIAdapter = class _OpenAIAdapter {
|
|
523
321
|
constructor(config) {
|
|
@@ -538,39 +336,38 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
538
336
|
const { default: OpenAI } = await import('openai');
|
|
539
337
|
this.client = new OpenAI({
|
|
540
338
|
apiKey: this.config.apiKey,
|
|
541
|
-
baseURL: this.config.baseUrl
|
|
339
|
+
baseURL: this.config.baseUrl,
|
|
340
|
+
organization: this.config.organization,
|
|
341
|
+
defaultHeaders: this.config.headers
|
|
542
342
|
});
|
|
543
343
|
}
|
|
544
344
|
return this.client;
|
|
545
345
|
}
|
|
346
|
+
parameterOptions(request) {
|
|
347
|
+
return {
|
|
348
|
+
...this.config,
|
|
349
|
+
reasoningEffort: request.config?.reasoningEffort ?? this.config.reasoningEffort
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
toolDefinitions(request) {
|
|
353
|
+
if (request.toolDefinitions?.length) return request.toolDefinitions;
|
|
354
|
+
return formatTools(request.actions ?? []).map((tool) => ({
|
|
355
|
+
name: tool.function.name,
|
|
356
|
+
description: tool.function.description ?? "",
|
|
357
|
+
location: "server",
|
|
358
|
+
inputSchema: tool.function.parameters
|
|
359
|
+
}));
|
|
360
|
+
}
|
|
546
361
|
shouldUseResponsesApi(request) {
|
|
547
|
-
|
|
548
|
-
if (
|
|
549
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false) {
|
|
362
|
+
if (this.toolDefinitions(request).length === 0) return false;
|
|
363
|
+
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
550
364
|
return true;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
365
|
+
return requiresOpenAIResponses(
|
|
366
|
+
request.config?.model || this.model,
|
|
367
|
+
this.config.baseUrl,
|
|
368
|
+
this.parameterOptions(request)
|
|
554
369
|
);
|
|
555
370
|
}
|
|
556
|
-
/**
|
|
557
|
-
* Whether this model rejects function tools on /v1/chat/completions.
|
|
558
|
-
*
|
|
559
|
-
* Applies to OpenAI proper only — the adapter is reused for OpenAI-compatible
|
|
560
|
-
* providers (Azure, xAI, Google, Fireworks) whose endpoints have no such
|
|
561
|
-
* restriction and may not implement /v1/responses at all.
|
|
562
|
-
*/
|
|
563
|
-
requiresResponsesApiForTools(modelId) {
|
|
564
|
-
if (!modelId) return false;
|
|
565
|
-
if (!/^gpt-5\.(?:[4-9]|\d{2,})/i.test(modelId)) return false;
|
|
566
|
-
const baseUrl = this.config.baseUrl;
|
|
567
|
-
if (!baseUrl) return true;
|
|
568
|
-
try {
|
|
569
|
-
return new URL(baseUrl).hostname === "api.openai.com";
|
|
570
|
-
} catch {
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
371
|
/**
|
|
575
372
|
* Convert one message's content to Responses content parts.
|
|
576
373
|
*
|
|
@@ -601,7 +398,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
601
398
|
});
|
|
602
399
|
}
|
|
603
400
|
buildResponsesInput(request) {
|
|
604
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
|
|
401
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
605
402
|
const input = [];
|
|
606
403
|
for (const message of sourceMessages) {
|
|
607
404
|
if (message.role === "system") {
|
|
@@ -651,6 +448,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
651
448
|
}
|
|
652
449
|
return input;
|
|
653
450
|
}
|
|
451
|
+
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
452
|
+
formatRawMessages(messages) {
|
|
453
|
+
return messages.map((message) => {
|
|
454
|
+
const { attachments, ...rest } = message;
|
|
455
|
+
let content = message.content;
|
|
456
|
+
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
457
|
+
content = null;
|
|
458
|
+
}
|
|
459
|
+
if (Array.isArray(attachments) && attachments.length > 0) {
|
|
460
|
+
const images = attachments.filter((attachment) => attachment && typeof attachment === "object").map(
|
|
461
|
+
(attachment) => attachmentToOpenAIImage(attachment)
|
|
462
|
+
).filter((image) => image !== null);
|
|
463
|
+
if (images.length > 0) {
|
|
464
|
+
const parts = Array.isArray(content) ? content : content ? [{ type: "text", text: content }] : [];
|
|
465
|
+
content = [...parts, ...images];
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return { ...rest, content };
|
|
469
|
+
});
|
|
470
|
+
}
|
|
654
471
|
/**
|
|
655
472
|
* Build the web_search tool for the Responses API, or undefined when web
|
|
656
473
|
* search is off.
|
|
@@ -732,13 +549,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
732
549
|
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => ({
|
|
733
550
|
id: item.call_id ?? item.id ?? generateToolCallId(),
|
|
734
551
|
name: item.name,
|
|
735
|
-
args: (
|
|
736
|
-
try {
|
|
737
|
-
return JSON.parse(item.arguments ?? "{}");
|
|
738
|
-
} catch {
|
|
739
|
-
return {};
|
|
740
|
-
}
|
|
741
|
-
})()
|
|
552
|
+
args: JSON.parse(item.arguments ?? "{}")
|
|
742
553
|
})) : [];
|
|
743
554
|
return {
|
|
744
555
|
content,
|
|
@@ -762,18 +573,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
762
573
|
instructions: request.systemPrompt,
|
|
763
574
|
input: this.buildResponsesInput(request),
|
|
764
575
|
tools: this.buildResponsesTools(
|
|
765
|
-
|
|
576
|
+
this.toolDefinitions(request),
|
|
766
577
|
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true,
|
|
767
578
|
this.buildResponsesWebSearchTool(request)
|
|
768
579
|
),
|
|
769
|
-
tool_choice: openaiToolOptions?.toolChoice
|
|
580
|
+
tool_choice: openaiToolOptions?.toolChoice,
|
|
770
581
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
582
|
+
...buildOpenAIParameters(
|
|
583
|
+
modelIdForPayload,
|
|
584
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
585
|
+
request.config?.temperature ?? this.config.temperature,
|
|
586
|
+
this.parameterOptions(request),
|
|
587
|
+
"responses"
|
|
588
|
+
),
|
|
777
589
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
778
590
|
stream
|
|
779
591
|
};
|
|
@@ -781,10 +593,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
781
593
|
}
|
|
782
594
|
async completeWithResponses(request) {
|
|
783
595
|
const client = await this.getClient();
|
|
596
|
+
throwIfAborted(request.signal);
|
|
784
597
|
const payload = this.buildResponsesPayload(request, false);
|
|
785
598
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
786
|
-
|
|
599
|
+
if (!client.responses?.create)
|
|
600
|
+
throw new Error(
|
|
601
|
+
"This OpenAI client does not support Responses; install an openai version with Responses support."
|
|
602
|
+
);
|
|
603
|
+
const response = await client.responses.create(payload, {
|
|
604
|
+
signal: request.signal
|
|
605
|
+
});
|
|
606
|
+
throwIfAborted(request.signal);
|
|
787
607
|
logProviderPayload("openai", "response payload", response, request.debug);
|
|
608
|
+
if (response.status && response.status !== "completed") {
|
|
609
|
+
throw Object.assign(
|
|
610
|
+
new Error(
|
|
611
|
+
response.error?.message ?? `Responses request ${response.status}`
|
|
612
|
+
),
|
|
613
|
+
response.error
|
|
614
|
+
);
|
|
615
|
+
}
|
|
788
616
|
return this.parseResponsesResult(response);
|
|
789
617
|
}
|
|
790
618
|
/**
|
|
@@ -802,13 +630,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
802
630
|
*/
|
|
803
631
|
async *streamWithResponses(request) {
|
|
804
632
|
const client = await this.getClient();
|
|
633
|
+
throwIfAborted(request.signal);
|
|
805
634
|
const payload = this.buildResponsesPayload(request, true);
|
|
806
635
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
807
|
-
|
|
636
|
+
if (!client.responses?.create)
|
|
637
|
+
throw new Error(
|
|
638
|
+
"This OpenAI client does not support Responses; install an openai version with Responses support."
|
|
639
|
+
);
|
|
640
|
+
const stream = await client.responses.create(payload, {
|
|
641
|
+
signal: request.signal
|
|
642
|
+
});
|
|
808
643
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
809
644
|
let usage;
|
|
810
645
|
const citations = [];
|
|
646
|
+
let completed = false;
|
|
811
647
|
function* flushToolCalls() {
|
|
648
|
+
for (const call of toolCalls.values()) {
|
|
649
|
+
if (!call.name)
|
|
650
|
+
throw new Error("Responses tool call is missing its name");
|
|
651
|
+
JSON.parse(call.arguments || "{}");
|
|
652
|
+
}
|
|
812
653
|
for (const call of toolCalls.values()) {
|
|
813
654
|
yield { type: "action:start", id: call.id, name: call.name };
|
|
814
655
|
yield { type: "action:args", id: call.id, args: call.arguments };
|
|
@@ -817,7 +658,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
817
658
|
toolCalls.clear();
|
|
818
659
|
}
|
|
819
660
|
for await (const event of stream) {
|
|
820
|
-
|
|
661
|
+
throwIfAborted(request.signal);
|
|
821
662
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
822
663
|
const index = event?.output_index ?? 0;
|
|
823
664
|
switch (event?.type) {
|
|
@@ -847,8 +688,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
847
688
|
}
|
|
848
689
|
break;
|
|
849
690
|
}
|
|
850
|
-
case "response.completed":
|
|
851
|
-
|
|
691
|
+
case "response.completed": {
|
|
692
|
+
completed = true;
|
|
852
693
|
const found = this.collectResponsesCitations(
|
|
853
694
|
event.response?.output,
|
|
854
695
|
citations.length
|
|
@@ -864,13 +705,27 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
864
705
|
}
|
|
865
706
|
break;
|
|
866
707
|
}
|
|
867
|
-
case "
|
|
868
|
-
case "response.failed":
|
|
708
|
+
case "response.incomplete":
|
|
869
709
|
throw new Error(
|
|
870
|
-
|
|
710
|
+
`Responses stream incomplete: ${event.response?.incomplete_details?.reason ?? "unknown reason"}`
|
|
871
711
|
);
|
|
712
|
+
case "error":
|
|
713
|
+
case "response.failed": {
|
|
714
|
+
const details = event.response?.error ?? event;
|
|
715
|
+
throw Object.assign(
|
|
716
|
+
new Error(details.message ?? "Responses stream failed"),
|
|
717
|
+
{
|
|
718
|
+
code: details.code,
|
|
719
|
+
param: details.param,
|
|
720
|
+
status: details.status
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
}
|
|
872
724
|
}
|
|
873
725
|
}
|
|
726
|
+
throwIfAborted(request.signal);
|
|
727
|
+
if (!completed)
|
|
728
|
+
throw new Error("Responses stream ended without a completed response");
|
|
874
729
|
yield* flushToolCalls();
|
|
875
730
|
if (citations.length > 0) {
|
|
876
731
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
@@ -879,6 +734,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
879
734
|
yield { type: "done", usage };
|
|
880
735
|
}
|
|
881
736
|
async *stream(request) {
|
|
737
|
+
throwIfAborted(request.signal);
|
|
882
738
|
if (this.shouldUseResponsesApi(request)) {
|
|
883
739
|
const messageId2 = generateMessageId();
|
|
884
740
|
yield { type: "message:start", id: messageId2 };
|
|
@@ -886,47 +742,14 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
886
742
|
yield* this.streamWithResponses(request);
|
|
887
743
|
return;
|
|
888
744
|
} catch (error) {
|
|
889
|
-
yield
|
|
890
|
-
type: "error",
|
|
891
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
892
|
-
code: "OPENAI_RESPONSES_ERROR"
|
|
893
|
-
};
|
|
745
|
+
yield providerErrorEvent(error, "OPENAI_RESPONSES_ERROR");
|
|
894
746
|
return;
|
|
895
747
|
}
|
|
896
748
|
}
|
|
897
749
|
const client = await this.getClient();
|
|
898
750
|
let messages;
|
|
899
751
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
900
|
-
const processedMessages = request.rawMessages
|
|
901
|
-
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
|
|
902
|
-
return { ...msg, content: null };
|
|
903
|
-
}
|
|
904
|
-
const hasAttachments = msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0;
|
|
905
|
-
if (hasAttachments) {
|
|
906
|
-
const content = [];
|
|
907
|
-
if (msg.content) {
|
|
908
|
-
content.push({ type: "text", text: msg.content });
|
|
909
|
-
}
|
|
910
|
-
for (const attachment of msg.attachments) {
|
|
911
|
-
if (attachment.type === "image") {
|
|
912
|
-
let imageUrl;
|
|
913
|
-
if (attachment.url) {
|
|
914
|
-
imageUrl = attachment.url;
|
|
915
|
-
} else if (attachment.data) {
|
|
916
|
-
imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
|
|
917
|
-
} else {
|
|
918
|
-
continue;
|
|
919
|
-
}
|
|
920
|
-
content.push({
|
|
921
|
-
type: "image_url",
|
|
922
|
-
image_url: { url: imageUrl, detail: "auto" }
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
return { ...msg, content, attachments: void 0 };
|
|
927
|
-
}
|
|
928
|
-
return msg;
|
|
929
|
-
});
|
|
752
|
+
const processedMessages = this.formatRawMessages(request.rawMessages);
|
|
930
753
|
if (request.systemPrompt) {
|
|
931
754
|
const hasSystem = processedMessages.some((m) => m.role === "system");
|
|
932
755
|
if (!hasSystem) {
|
|
@@ -946,7 +769,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
946
769
|
request.systemPrompt
|
|
947
770
|
);
|
|
948
771
|
}
|
|
949
|
-
const tools = request.
|
|
772
|
+
const tools = request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
|
|
773
|
+
type: "function",
|
|
774
|
+
function: {
|
|
775
|
+
name: tool.name,
|
|
776
|
+
description: tool.description,
|
|
777
|
+
parameters: normalizeObjectJsonSchema(
|
|
778
|
+
tool.inputSchema
|
|
779
|
+
)
|
|
780
|
+
}
|
|
781
|
+
})) : formatTools(request.actions ?? []);
|
|
950
782
|
const webSearchConfig = request.webSearch ?? this.config.webSearch;
|
|
951
783
|
if (webSearchConfig) {
|
|
952
784
|
const webSearchTool = {
|
|
@@ -975,26 +807,28 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
975
807
|
tools: tools.length > 0 ? tools : void 0,
|
|
976
808
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
977
809
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
978
|
-
...
|
|
810
|
+
...buildOpenAIParameters(
|
|
979
811
|
modelIdForPayload,
|
|
980
812
|
request.config?.maxTokens ?? this.config.maxTokens,
|
|
981
|
-
request.config?.temperature ?? this.config.temperature
|
|
813
|
+
request.config?.temperature ?? this.config.temperature,
|
|
814
|
+
this.parameterOptions(request)
|
|
982
815
|
),
|
|
983
816
|
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
984
817
|
stream: true,
|
|
985
818
|
stream_options: { include_usage: true }
|
|
986
819
|
};
|
|
987
820
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
988
|
-
const stream = await client.chat.completions.create(payload
|
|
989
|
-
|
|
821
|
+
const stream = await client.chat.completions.create(payload, {
|
|
822
|
+
signal: request.signal
|
|
823
|
+
});
|
|
824
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
825
|
+
let finishReason;
|
|
990
826
|
const collectedCitations = [];
|
|
991
827
|
let citationIndex = 0;
|
|
992
828
|
let usage;
|
|
993
829
|
for await (const chunk of stream) {
|
|
994
830
|
logProviderPayload("openai", "stream chunk", chunk, request.debug);
|
|
995
|
-
|
|
996
|
-
break;
|
|
997
|
-
}
|
|
831
|
+
throwIfAborted(request.signal);
|
|
998
832
|
const delta = chunk.choices[0]?.delta;
|
|
999
833
|
const choice = chunk.choices[0];
|
|
1000
834
|
if (delta?.content) {
|
|
@@ -1017,38 +851,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1017
851
|
}
|
|
1018
852
|
}
|
|
1019
853
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
};
|
|
1034
|
-
}
|
|
1035
|
-
const tcExtraContent = toolCall.extra_content;
|
|
1036
|
-
currentToolCall = {
|
|
1037
|
-
id: toolCall.id,
|
|
1038
|
-
name: toolCall.function?.name || "",
|
|
1039
|
-
arguments: toolCall.function?.arguments || "",
|
|
1040
|
-
...tcExtraContent ? { extra_content: tcExtraContent } : {}
|
|
1041
|
-
};
|
|
1042
|
-
yield {
|
|
1043
|
-
type: "action:start",
|
|
1044
|
-
id: currentToolCall.id,
|
|
1045
|
-
name: currentToolCall.name,
|
|
1046
|
-
...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
|
|
1047
|
-
};
|
|
1048
|
-
} else if (currentToolCall && toolCall.function?.arguments) {
|
|
1049
|
-
currentToolCall.arguments += toolCall.function.arguments;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
854
|
+
for (const part of delta?.tool_calls ?? []) {
|
|
855
|
+
const index = part.index ?? 0;
|
|
856
|
+
const call = toolCalls.get(index) ?? {
|
|
857
|
+
id: "",
|
|
858
|
+
name: "",
|
|
859
|
+
arguments: ""
|
|
860
|
+
};
|
|
861
|
+
if (part.id) call.id = part.id;
|
|
862
|
+
if (part.function?.name) call.name += part.function.name;
|
|
863
|
+
if (part.function?.arguments)
|
|
864
|
+
call.arguments += part.function.arguments;
|
|
865
|
+
if (part.extra_content) call.extra_content = part.extra_content;
|
|
866
|
+
toolCalls.set(index, call);
|
|
1052
867
|
}
|
|
1053
868
|
if (chunk.usage) {
|
|
1054
869
|
usage = {
|
|
@@ -1057,21 +872,28 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1057
872
|
total_tokens: chunk.usage.total_tokens
|
|
1058
873
|
};
|
|
1059
874
|
}
|
|
1060
|
-
if (choice?.finish_reason)
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
875
|
+
if (choice?.finish_reason) finishReason = choice.finish_reason;
|
|
876
|
+
}
|
|
877
|
+
throwIfAborted(request.signal);
|
|
878
|
+
if (!finishReason)
|
|
879
|
+
throw new Error("OpenAI stream ended without a finish reason");
|
|
880
|
+
if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
|
|
881
|
+
throw new Error("OpenAI stream ended with incomplete tool calls");
|
|
882
|
+
}
|
|
883
|
+
for (const call of toolCalls.values()) {
|
|
884
|
+
if (!call.id || !call.name)
|
|
885
|
+
throw new Error("OpenAI stream contains an incomplete tool call");
|
|
886
|
+
JSON.parse(call.arguments || "{}");
|
|
887
|
+
}
|
|
888
|
+
for (const call of toolCalls.values()) {
|
|
889
|
+
yield {
|
|
890
|
+
type: "action:start",
|
|
891
|
+
id: call.id,
|
|
892
|
+
name: call.name,
|
|
893
|
+
...call.extra_content ? { extra_content: call.extra_content } : {}
|
|
894
|
+
};
|
|
895
|
+
yield { type: "action:args", id: call.id, args: call.arguments };
|
|
896
|
+
yield { type: "action:end", id: call.id, name: call.name };
|
|
1075
897
|
}
|
|
1076
898
|
if (collectedCitations.length > 0) {
|
|
1077
899
|
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
@@ -1080,26 +902,18 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1080
902
|
yield { type: "message:end" };
|
|
1081
903
|
yield { type: "done", usage };
|
|
1082
904
|
} catch (error) {
|
|
1083
|
-
yield {
|
|
1084
|
-
type: "error",
|
|
1085
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
1086
|
-
code: `${this.provider.toUpperCase()}_ERROR`
|
|
1087
|
-
};
|
|
905
|
+
yield providerErrorEvent(error, `${this.provider.toUpperCase()}_ERROR`);
|
|
1088
906
|
}
|
|
1089
907
|
}
|
|
1090
908
|
async complete(request) {
|
|
909
|
+
throwIfAborted(request.signal);
|
|
1091
910
|
if (this.shouldUseResponsesApi(request)) {
|
|
1092
911
|
return this.completeWithResponses(request);
|
|
1093
912
|
}
|
|
1094
913
|
const client = await this.getClient();
|
|
1095
914
|
let messages;
|
|
1096
915
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
1097
|
-
const sanitized = request.rawMessages
|
|
1098
|
-
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
|
|
1099
|
-
return { ...msg, content: null };
|
|
1100
|
-
}
|
|
1101
|
-
return msg;
|
|
1102
|
-
});
|
|
916
|
+
const sanitized = this.formatRawMessages(request.rawMessages);
|
|
1103
917
|
if (request.systemPrompt && !sanitized.some((message2) => message2.role === "system")) {
|
|
1104
918
|
messages = [
|
|
1105
919
|
{ role: "system", content: request.systemPrompt },
|
|
@@ -1114,7 +928,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1114
928
|
request.systemPrompt
|
|
1115
929
|
);
|
|
1116
930
|
}
|
|
1117
|
-
const tools = request.
|
|
931
|
+
const tools = request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
|
|
932
|
+
type: "function",
|
|
933
|
+
function: {
|
|
934
|
+
name: tool.name,
|
|
935
|
+
description: tool.description,
|
|
936
|
+
parameters: normalizeObjectJsonSchema(
|
|
937
|
+
tool.inputSchema
|
|
938
|
+
)
|
|
939
|
+
}
|
|
940
|
+
})) : formatTools(request.actions ?? []);
|
|
1118
941
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
1119
942
|
const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
|
|
1120
943
|
type: "function",
|
|
@@ -1129,16 +952,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1129
952
|
tools: tools.length > 0 ? tools : void 0,
|
|
1130
953
|
tool_choice: tools.length > 0 ? toolChoice : void 0,
|
|
1131
954
|
parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
|
|
1132
|
-
...
|
|
955
|
+
...buildOpenAIParameters(
|
|
1133
956
|
modelIdForCompletePayload,
|
|
1134
957
|
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1135
|
-
request.config?.temperature ?? this.config.temperature
|
|
958
|
+
request.config?.temperature ?? this.config.temperature,
|
|
959
|
+
this.parameterOptions(request)
|
|
1136
960
|
),
|
|
1137
961
|
response_format: toOpenAIResponseFormat(request.config?.responseFormat),
|
|
1138
962
|
stream: false
|
|
1139
963
|
};
|
|
1140
964
|
logProviderPayload("openai", "request payload", payload, request.debug);
|
|
1141
|
-
const response = await client.chat.completions.create(payload
|
|
965
|
+
const response = await client.chat.completions.create(payload, {
|
|
966
|
+
signal: request.signal
|
|
967
|
+
});
|
|
1142
968
|
logProviderPayload("openai", "response payload", response, request.debug);
|
|
1143
969
|
const choice = response.choices?.[0];
|
|
1144
970
|
const message = choice?.message;
|
|
@@ -1188,6 +1014,383 @@ function createOpenAIAdapter(config) {
|
|
|
1188
1014
|
return new OpenAIAdapter(config);
|
|
1189
1015
|
}
|
|
1190
1016
|
|
|
1017
|
+
// src/providers/openai/provider.ts
|
|
1018
|
+
var OPENAI_MODELS = {
|
|
1019
|
+
// GPT-4o series
|
|
1020
|
+
"gpt-4o": { vision: true, tools: true, jsonMode: true, maxTokens: 128e3 },
|
|
1021
|
+
"gpt-5.2": {
|
|
1022
|
+
vision: true,
|
|
1023
|
+
tools: true,
|
|
1024
|
+
jsonMode: true,
|
|
1025
|
+
maxTokens: 128e3
|
|
1026
|
+
},
|
|
1027
|
+
"gpt-4o-2024-11-20": {
|
|
1028
|
+
vision: true,
|
|
1029
|
+
tools: true,
|
|
1030
|
+
jsonMode: true,
|
|
1031
|
+
maxTokens: 128e3
|
|
1032
|
+
},
|
|
1033
|
+
"gpt-4o-2024-08-06": {
|
|
1034
|
+
vision: true,
|
|
1035
|
+
tools: true,
|
|
1036
|
+
jsonMode: true,
|
|
1037
|
+
maxTokens: 128e3
|
|
1038
|
+
},
|
|
1039
|
+
// GPT-4 Turbo
|
|
1040
|
+
"gpt-4-turbo": {
|
|
1041
|
+
vision: true,
|
|
1042
|
+
tools: true,
|
|
1043
|
+
jsonMode: true,
|
|
1044
|
+
maxTokens: 128e3
|
|
1045
|
+
},
|
|
1046
|
+
"gpt-4-turbo-preview": {
|
|
1047
|
+
vision: false,
|
|
1048
|
+
tools: true,
|
|
1049
|
+
jsonMode: true,
|
|
1050
|
+
maxTokens: 128e3
|
|
1051
|
+
},
|
|
1052
|
+
// GPT-4
|
|
1053
|
+
"gpt-4": { vision: false, tools: true, jsonMode: false, maxTokens: 8192 },
|
|
1054
|
+
"gpt-4-32k": {
|
|
1055
|
+
vision: false,
|
|
1056
|
+
tools: true,
|
|
1057
|
+
jsonMode: false,
|
|
1058
|
+
maxTokens: 32768
|
|
1059
|
+
},
|
|
1060
|
+
// GPT-3.5
|
|
1061
|
+
"gpt-3.5-turbo": {
|
|
1062
|
+
vision: false,
|
|
1063
|
+
tools: true,
|
|
1064
|
+
jsonMode: true,
|
|
1065
|
+
maxTokens: 16385
|
|
1066
|
+
},
|
|
1067
|
+
// O1 series (reasoning)
|
|
1068
|
+
o1: { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
1069
|
+
"o1-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 },
|
|
1070
|
+
"o1-preview": {
|
|
1071
|
+
vision: true,
|
|
1072
|
+
tools: false,
|
|
1073
|
+
jsonMode: false,
|
|
1074
|
+
maxTokens: 128e3
|
|
1075
|
+
},
|
|
1076
|
+
// O3 series
|
|
1077
|
+
"o3-mini": { vision: true, tools: false, jsonMode: false, maxTokens: 128e3 }
|
|
1078
|
+
};
|
|
1079
|
+
function openai(modelId, options = {}) {
|
|
1080
|
+
const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
|
|
1081
|
+
const baseURL = options.baseURL ?? "https://api.openai.com/v1";
|
|
1082
|
+
let client = null;
|
|
1083
|
+
async function getClient() {
|
|
1084
|
+
if (!client) {
|
|
1085
|
+
const { default: OpenAI } = await import('openai');
|
|
1086
|
+
client = new OpenAI({
|
|
1087
|
+
apiKey,
|
|
1088
|
+
baseURL,
|
|
1089
|
+
organization: options.organization,
|
|
1090
|
+
defaultHeaders: options.headers
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
return client;
|
|
1094
|
+
}
|
|
1095
|
+
function parameterOptions(params) {
|
|
1096
|
+
return {
|
|
1097
|
+
...options,
|
|
1098
|
+
reasoningEffort: params.reasoningEffort ?? options.reasoningEffort
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
function useResponses(params) {
|
|
1102
|
+
return !!params.tools?.length && requiresOpenAIResponses(modelId, baseURL, parameterOptions(params));
|
|
1103
|
+
}
|
|
1104
|
+
const responsesAdapter = new OpenAIAdapter({
|
|
1105
|
+
...options,
|
|
1106
|
+
apiKey: apiKey ?? "",
|
|
1107
|
+
model: modelId,
|
|
1108
|
+
baseUrl: baseURL
|
|
1109
|
+
});
|
|
1110
|
+
function responsesRequest(params) {
|
|
1111
|
+
return {
|
|
1112
|
+
messages: [],
|
|
1113
|
+
rawMessages: formatMessagesForOpenAI2(params.messages),
|
|
1114
|
+
toolDefinitions: params.tools?.map((raw) => {
|
|
1115
|
+
const tool = raw;
|
|
1116
|
+
if (tool.type !== "function")
|
|
1117
|
+
throw new Error(
|
|
1118
|
+
"Only function tools are supported by this OpenAI generation path"
|
|
1119
|
+
);
|
|
1120
|
+
return {
|
|
1121
|
+
name: tool.function.name,
|
|
1122
|
+
description: tool.function.description ?? "",
|
|
1123
|
+
location: "server",
|
|
1124
|
+
inputSchema: tool.function.parameters
|
|
1125
|
+
};
|
|
1126
|
+
}),
|
|
1127
|
+
config: {
|
|
1128
|
+
temperature: params.temperature,
|
|
1129
|
+
maxTokens: params.maxTokens,
|
|
1130
|
+
responseFormat: params.responseFormat,
|
|
1131
|
+
reasoningEffort: parameterOptions(params).reasoningEffort
|
|
1132
|
+
},
|
|
1133
|
+
signal: params.signal
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
const modelConfig = OPENAI_MODELS[modelId] ?? OPENAI_MODELS["gpt-4o"];
|
|
1137
|
+
return {
|
|
1138
|
+
provider: "openai",
|
|
1139
|
+
modelId,
|
|
1140
|
+
capabilities: {
|
|
1141
|
+
supportsVision: modelConfig.vision,
|
|
1142
|
+
supportsTools: modelConfig.tools,
|
|
1143
|
+
supportsStreaming: true,
|
|
1144
|
+
supportsJsonMode: modelConfig.jsonMode,
|
|
1145
|
+
supportsThinking: false,
|
|
1146
|
+
supportsPDF: false,
|
|
1147
|
+
maxTokens: modelConfig.maxTokens,
|
|
1148
|
+
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
1149
|
+
},
|
|
1150
|
+
async doGenerate(params) {
|
|
1151
|
+
throwIfAborted(params.signal);
|
|
1152
|
+
if (useResponses(params)) {
|
|
1153
|
+
const result = await responsesAdapter.complete(
|
|
1154
|
+
responsesRequest(params)
|
|
1155
|
+
);
|
|
1156
|
+
return {
|
|
1157
|
+
text: result.content,
|
|
1158
|
+
toolCalls: result.toolCalls,
|
|
1159
|
+
finishReason: result.toolCalls.length ? "tool-calls" : "stop",
|
|
1160
|
+
usage: result.usage ?? {
|
|
1161
|
+
promptTokens: 0,
|
|
1162
|
+
completionTokens: 0,
|
|
1163
|
+
totalTokens: 0
|
|
1164
|
+
},
|
|
1165
|
+
rawResponse: result.rawResponse
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
const client2 = await getClient();
|
|
1169
|
+
const messages = formatMessagesForOpenAI2(params.messages);
|
|
1170
|
+
const response = await client2.chat.completions.create(
|
|
1171
|
+
{
|
|
1172
|
+
model: modelId,
|
|
1173
|
+
messages,
|
|
1174
|
+
tools: params.tools,
|
|
1175
|
+
...buildOpenAIParameters(
|
|
1176
|
+
modelId,
|
|
1177
|
+
params.maxTokens,
|
|
1178
|
+
params.temperature,
|
|
1179
|
+
parameterOptions(params)
|
|
1180
|
+
),
|
|
1181
|
+
response_format: toOpenAIResponseFormat(params.responseFormat)
|
|
1182
|
+
},
|
|
1183
|
+
{ signal: params.signal }
|
|
1184
|
+
);
|
|
1185
|
+
const choice = response.choices[0];
|
|
1186
|
+
const message = choice.message;
|
|
1187
|
+
const toolCalls = (message.tool_calls ?? []).map(
|
|
1188
|
+
(tc) => ({
|
|
1189
|
+
id: tc.id,
|
|
1190
|
+
name: tc.function.name,
|
|
1191
|
+
args: JSON.parse(tc.function.arguments || "{}")
|
|
1192
|
+
})
|
|
1193
|
+
);
|
|
1194
|
+
return {
|
|
1195
|
+
text: message.content ?? "",
|
|
1196
|
+
toolCalls,
|
|
1197
|
+
finishReason: mapFinishReason(choice.finish_reason),
|
|
1198
|
+
usage: {
|
|
1199
|
+
promptTokens: response.usage?.prompt_tokens ?? 0,
|
|
1200
|
+
completionTokens: response.usage?.completion_tokens ?? 0,
|
|
1201
|
+
totalTokens: response.usage?.total_tokens ?? 0
|
|
1202
|
+
},
|
|
1203
|
+
rawResponse: response
|
|
1204
|
+
};
|
|
1205
|
+
},
|
|
1206
|
+
async *doStream(params) {
|
|
1207
|
+
throwIfAborted(params.signal);
|
|
1208
|
+
if (useResponses(params)) {
|
|
1209
|
+
const calls2 = /* @__PURE__ */ new Map();
|
|
1210
|
+
let hasTools = false;
|
|
1211
|
+
for await (const event of responsesAdapter.stream(
|
|
1212
|
+
responsesRequest(params)
|
|
1213
|
+
)) {
|
|
1214
|
+
switch (event.type) {
|
|
1215
|
+
case "message:delta":
|
|
1216
|
+
yield { type: "text-delta", text: event.content };
|
|
1217
|
+
break;
|
|
1218
|
+
case "action:start":
|
|
1219
|
+
calls2.set(event.id, { name: event.name, args: "" });
|
|
1220
|
+
break;
|
|
1221
|
+
case "action:args": {
|
|
1222
|
+
const call = calls2.get(event.id);
|
|
1223
|
+
if (call) call.args += event.args;
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1226
|
+
case "action:end": {
|
|
1227
|
+
const call = calls2.get(event.id);
|
|
1228
|
+
if (!call)
|
|
1229
|
+
throw new Error("Responses tool call has no matching start");
|
|
1230
|
+
hasTools = true;
|
|
1231
|
+
yield {
|
|
1232
|
+
type: "tool-call",
|
|
1233
|
+
toolCall: {
|
|
1234
|
+
id: event.id,
|
|
1235
|
+
name: call.name,
|
|
1236
|
+
args: JSON.parse(call.args || "{}")
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
calls2.delete(event.id);
|
|
1240
|
+
break;
|
|
1241
|
+
}
|
|
1242
|
+
case "error":
|
|
1243
|
+
throw errorFromEvent(event);
|
|
1244
|
+
case "done":
|
|
1245
|
+
yield {
|
|
1246
|
+
type: "finish",
|
|
1247
|
+
finishReason: hasTools ? "tool-calls" : "stop",
|
|
1248
|
+
usage: {
|
|
1249
|
+
promptTokens: event.usage?.prompt_tokens ?? 0,
|
|
1250
|
+
completionTokens: event.usage?.completion_tokens ?? 0,
|
|
1251
|
+
totalTokens: event.usage?.total_tokens ?? 0
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
break;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
const client2 = await getClient();
|
|
1260
|
+
const messages = formatMessagesForOpenAI2(params.messages);
|
|
1261
|
+
const stream = await client2.chat.completions.create(
|
|
1262
|
+
{
|
|
1263
|
+
model: modelId,
|
|
1264
|
+
messages,
|
|
1265
|
+
tools: params.tools,
|
|
1266
|
+
...buildOpenAIParameters(
|
|
1267
|
+
modelId,
|
|
1268
|
+
params.maxTokens,
|
|
1269
|
+
params.temperature,
|
|
1270
|
+
parameterOptions(params)
|
|
1271
|
+
),
|
|
1272
|
+
response_format: toOpenAIResponseFormat(params.responseFormat),
|
|
1273
|
+
stream: true,
|
|
1274
|
+
stream_options: { include_usage: true }
|
|
1275
|
+
},
|
|
1276
|
+
{ signal: params.signal }
|
|
1277
|
+
);
|
|
1278
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
1279
|
+
let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
1280
|
+
let finishReason;
|
|
1281
|
+
for await (const chunk of stream) {
|
|
1282
|
+
throwIfAborted(params.signal);
|
|
1283
|
+
if (chunk.usage) {
|
|
1284
|
+
usage = {
|
|
1285
|
+
promptTokens: chunk.usage.prompt_tokens ?? 0,
|
|
1286
|
+
completionTokens: chunk.usage.completion_tokens ?? 0,
|
|
1287
|
+
totalTokens: chunk.usage.total_tokens ?? (chunk.usage.prompt_tokens ?? 0) + (chunk.usage.completion_tokens ?? 0)
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
const choice = chunk.choices?.[0];
|
|
1291
|
+
if (choice?.delta?.content)
|
|
1292
|
+
yield { type: "text-delta", text: choice.delta.content };
|
|
1293
|
+
for (const part of choice?.delta?.tool_calls ?? []) {
|
|
1294
|
+
const index = part.index ?? 0;
|
|
1295
|
+
const call = toolCalls.get(index) ?? {
|
|
1296
|
+
id: "",
|
|
1297
|
+
name: "",
|
|
1298
|
+
arguments: ""
|
|
1299
|
+
};
|
|
1300
|
+
if (part.id) call.id = part.id;
|
|
1301
|
+
if (part.function?.name) call.name += part.function.name;
|
|
1302
|
+
if (part.function?.arguments)
|
|
1303
|
+
call.arguments += part.function.arguments;
|
|
1304
|
+
toolCalls.set(index, call);
|
|
1305
|
+
}
|
|
1306
|
+
if (choice?.finish_reason)
|
|
1307
|
+
finishReason = mapFinishReason(choice.finish_reason);
|
|
1308
|
+
}
|
|
1309
|
+
throwIfAborted(params.signal);
|
|
1310
|
+
if (!finishReason)
|
|
1311
|
+
throw new Error("OpenAI stream ended without a finish reason");
|
|
1312
|
+
const calls = [...toolCalls.values()].map((call) => {
|
|
1313
|
+
if (!call.id || !call.name)
|
|
1314
|
+
throw new Error("OpenAI stream contains an incomplete tool call");
|
|
1315
|
+
return {
|
|
1316
|
+
id: call.id,
|
|
1317
|
+
name: call.name,
|
|
1318
|
+
args: JSON.parse(call.arguments || "{}")
|
|
1319
|
+
};
|
|
1320
|
+
});
|
|
1321
|
+
if (calls.length && finishReason !== "tool-calls")
|
|
1322
|
+
throw new Error("OpenAI stream ended with incomplete tool calls");
|
|
1323
|
+
for (const toolCall of calls) yield { type: "tool-call", toolCall };
|
|
1324
|
+
yield { type: "finish", finishReason, usage };
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function mapFinishReason(reason) {
|
|
1329
|
+
switch (reason) {
|
|
1330
|
+
case "stop":
|
|
1331
|
+
return "stop";
|
|
1332
|
+
case "length":
|
|
1333
|
+
return "length";
|
|
1334
|
+
case "tool_calls":
|
|
1335
|
+
case "function_call":
|
|
1336
|
+
return "tool-calls";
|
|
1337
|
+
case "content_filter":
|
|
1338
|
+
return "content-filter";
|
|
1339
|
+
default:
|
|
1340
|
+
return "unknown";
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
function formatMessagesForOpenAI2(messages) {
|
|
1344
|
+
return messages.map((msg) => {
|
|
1345
|
+
switch (msg.role) {
|
|
1346
|
+
case "system":
|
|
1347
|
+
return { role: "system", content: msg.content };
|
|
1348
|
+
case "user":
|
|
1349
|
+
if (typeof msg.content === "string") {
|
|
1350
|
+
return { role: "user", content: msg.content };
|
|
1351
|
+
}
|
|
1352
|
+
return {
|
|
1353
|
+
role: "user",
|
|
1354
|
+
content: msg.content.map((part) => {
|
|
1355
|
+
if (part.type === "text") {
|
|
1356
|
+
return { type: "text", text: part.text };
|
|
1357
|
+
}
|
|
1358
|
+
if (part.type === "image") {
|
|
1359
|
+
const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
|
|
1360
|
+
const url = imageData.startsWith("data:") ? imageData : `data:${part.mimeType ?? "image/png"};base64,${imageData}`;
|
|
1361
|
+
return { type: "image_url", image_url: { url, detail: "auto" } };
|
|
1362
|
+
}
|
|
1363
|
+
return { type: "text", text: "" };
|
|
1364
|
+
})
|
|
1365
|
+
};
|
|
1366
|
+
case "assistant":
|
|
1367
|
+
const assistantMsg = {
|
|
1368
|
+
role: "assistant",
|
|
1369
|
+
content: msg.content
|
|
1370
|
+
};
|
|
1371
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
1372
|
+
assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({
|
|
1373
|
+
id: tc.id,
|
|
1374
|
+
type: "function",
|
|
1375
|
+
function: {
|
|
1376
|
+
name: tc.name,
|
|
1377
|
+
arguments: JSON.stringify(tc.args)
|
|
1378
|
+
}
|
|
1379
|
+
}));
|
|
1380
|
+
}
|
|
1381
|
+
return assistantMsg;
|
|
1382
|
+
case "tool":
|
|
1383
|
+
return {
|
|
1384
|
+
role: "tool",
|
|
1385
|
+
tool_call_id: msg.toolCallId,
|
|
1386
|
+
content: msg.content
|
|
1387
|
+
};
|
|
1388
|
+
default:
|
|
1389
|
+
return msg;
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1191
1394
|
// src/providers/types.ts
|
|
1192
1395
|
function createCallableProvider(providerFn, properties) {
|
|
1193
1396
|
Object.defineProperty(providerFn, "name", {
|
|
@@ -1318,7 +1521,10 @@ function createOpenAI(config = {}) {
|
|
|
1318
1521
|
return createOpenAIAdapter({
|
|
1319
1522
|
apiKey,
|
|
1320
1523
|
model: modelId,
|
|
1321
|
-
baseUrl: config.baseUrl
|
|
1524
|
+
baseUrl: config.baseUrl,
|
|
1525
|
+
reasoningEffort: config.reasoningEffort,
|
|
1526
|
+
parameterPolicy: config.parameterPolicy,
|
|
1527
|
+
onWarning: config.onWarning
|
|
1322
1528
|
});
|
|
1323
1529
|
};
|
|
1324
1530
|
const getCapabilities = (modelId) => {
|