@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.
Files changed (59) hide show
  1. package/dist/adapters/index.d.mts +4 -38
  2. package/dist/adapters/index.d.ts +4 -38
  3. package/dist/adapters/index.js +158 -325
  4. package/dist/adapters/index.mjs +158 -325
  5. package/dist/base-C58Dsr9p.d.ts +259 -0
  6. package/dist/base-tNgbBaSo.d.mts +259 -0
  7. package/dist/fallback/index.d.mts +4 -4
  8. package/dist/fallback/index.d.ts +4 -4
  9. package/dist/index.d.mts +8 -7
  10. package/dist/index.d.ts +8 -7
  11. package/dist/index.js +35 -43
  12. package/dist/index.mjs +35 -43
  13. package/dist/providers/anthropic/index.d.mts +3 -3
  14. package/dist/providers/anthropic/index.d.ts +3 -3
  15. package/dist/providers/anthropic/index.js +271 -212
  16. package/dist/providers/anthropic/index.mjs +271 -212
  17. package/dist/providers/azure/index.d.mts +3 -3
  18. package/dist/providers/azure/index.d.ts +3 -3
  19. package/dist/providers/azure/index.js +49 -1
  20. package/dist/providers/azure/index.mjs +49 -1
  21. package/dist/providers/fireworks/index.d.mts +1 -1
  22. package/dist/providers/fireworks/index.d.ts +1 -1
  23. package/dist/providers/fireworks/index.js +56 -0
  24. package/dist/providers/fireworks/index.mjs +56 -0
  25. package/dist/providers/google/index.d.mts +3 -3
  26. package/dist/providers/google/index.d.ts +3 -3
  27. package/dist/providers/google/index.js +254 -510
  28. package/dist/providers/google/index.mjs +254 -510
  29. package/dist/providers/ollama/index.d.mts +4 -4
  30. package/dist/providers/ollama/index.d.ts +4 -4
  31. package/dist/providers/ollama/index.js +10 -2
  32. package/dist/providers/ollama/index.mjs +10 -2
  33. package/dist/providers/openai/index.d.mts +3 -3
  34. package/dist/providers/openai/index.d.ts +3 -3
  35. package/dist/providers/openai/index.js +269 -529
  36. package/dist/providers/openai/index.mjs +269 -529
  37. package/dist/providers/openrouter/index.d.mts +3 -7
  38. package/dist/providers/openrouter/index.d.ts +3 -7
  39. package/dist/providers/openrouter/index.js +365 -902
  40. package/dist/providers/openrouter/index.mjs +365 -902
  41. package/dist/providers/togetherai/index.d.mts +3 -3
  42. package/dist/providers/togetherai/index.d.ts +3 -3
  43. package/dist/providers/togetherai/index.js +259 -509
  44. package/dist/providers/togetherai/index.mjs +259 -509
  45. package/dist/providers/xai/index.d.mts +3 -3
  46. package/dist/providers/xai/index.d.ts +3 -3
  47. package/dist/providers/xai/index.js +258 -513
  48. package/dist/providers/xai/index.mjs +258 -513
  49. package/dist/{types-BNCmlJMs.d.mts → types-B6dhnguR.d.mts} +1 -1
  50. package/dist/{types-DhktekQ3.d.ts → types-BQ31QIsA.d.ts} +2 -1
  51. package/dist/{types-CMMQ8s2O.d.mts → types-BSSiJW2o.d.mts} +2 -1
  52. package/dist/{base-DN1EfKnE.d.mts → types-BkQCSiIt.d.mts} +388 -214
  53. package/dist/{base-DuUNxtVg.d.ts → types-BkQCSiIt.d.ts} +388 -214
  54. package/dist/{types-Pj-vpmoT.d.ts → types-CCxPmkmK.d.ts} +1 -1
  55. package/dist/yourgpt/index.d.mts +1 -1
  56. package/dist/yourgpt/index.d.ts +1 -1
  57. package/package.json +1 -1
  58. package/dist/types-CMvvDo-E.d.mts +0 -428
  59. package/dist/types-CMvvDo-E.d.ts +0 -428
@@ -1,5 +1,234 @@
1
1
  'use strict';
2
2
 
3
+ // src/adapters/base.ts
4
+ function stringifyForDebug(value) {
5
+ return JSON.stringify(
6
+ value,
7
+ (_key, currentValue) => {
8
+ if (typeof currentValue === "bigint") {
9
+ return currentValue.toString();
10
+ }
11
+ if (currentValue instanceof Error) {
12
+ return {
13
+ name: currentValue.name,
14
+ message: currentValue.message,
15
+ stack: currentValue.stack
16
+ };
17
+ }
18
+ return currentValue;
19
+ },
20
+ 2
21
+ );
22
+ }
23
+ function logProviderPayload(provider, label, payload, enabled) {
24
+ if (!enabled) {
25
+ return;
26
+ }
27
+ if (label.toLowerCase().includes("stream ")) {
28
+ return;
29
+ }
30
+ try {
31
+ console.log(
32
+ `[llm-sdk:${provider}] ${label}
33
+ ${stringifyForDebug(payload)}`
34
+ );
35
+ } catch (error) {
36
+ console.log(
37
+ `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
38
+ error
39
+ );
40
+ }
41
+ }
42
+ function parameterToJsonSchema(param) {
43
+ const schema = {
44
+ type: param.type
45
+ };
46
+ if (param.description) {
47
+ schema.description = param.description;
48
+ }
49
+ if (param.enum) {
50
+ schema.enum = param.enum;
51
+ }
52
+ if (param.type === "array" && param.items) {
53
+ schema.items = parameterToJsonSchema(
54
+ param.items
55
+ );
56
+ }
57
+ if (param.type === "object" && param.properties) {
58
+ schema.properties = Object.fromEntries(
59
+ Object.entries(param.properties).map(([key, prop]) => [
60
+ key,
61
+ parameterToJsonSchema(
62
+ prop
63
+ )
64
+ ])
65
+ );
66
+ schema.additionalProperties = false;
67
+ }
68
+ return schema;
69
+ }
70
+ function normalizeObjectJsonSchema(schema) {
71
+ if (!schema || typeof schema !== "object") {
72
+ return {
73
+ type: "object",
74
+ properties: {},
75
+ required: [],
76
+ additionalProperties: false
77
+ };
78
+ }
79
+ const normalized = { ...schema };
80
+ const type = normalized.type;
81
+ if (type === "object") {
82
+ const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
83
+ normalized.properties = Object.fromEntries(
84
+ Object.entries(properties).map(([key, value]) => [
85
+ key,
86
+ normalizeObjectJsonSchema(value)
87
+ ])
88
+ );
89
+ const propertyKeys = Object.keys(properties);
90
+ const required = Array.isArray(normalized.required) ? normalized.required.filter(
91
+ (value) => typeof value === "string"
92
+ ) : [];
93
+ normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
94
+ if (normalized.additionalProperties === void 0) {
95
+ normalized.additionalProperties = false;
96
+ }
97
+ } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
98
+ normalized.items = normalizeObjectJsonSchema(
99
+ normalized.items
100
+ );
101
+ }
102
+ return normalized;
103
+ }
104
+ function isOpenAIReasoningModel(modelId) {
105
+ if (!modelId) return false;
106
+ return /^(o1|o3|o4|gpt-5)/i.test(modelId);
107
+ }
108
+ function buildOpenAITokenParams(modelId, maxTokens, temperature) {
109
+ if (isOpenAIReasoningModel(modelId)) {
110
+ return { max_completion_tokens: maxTokens };
111
+ }
112
+ return { max_tokens: maxTokens, temperature };
113
+ }
114
+ function toOpenAIResponseFormat(rf) {
115
+ if (!rf) return void 0;
116
+ if (rf.type === "json_object") return { type: "json_object" };
117
+ return {
118
+ type: "json_schema",
119
+ json_schema: {
120
+ name: rf.json_schema.name,
121
+ schema: normalizeObjectJsonSchema(rf.json_schema.schema),
122
+ strict: rf.json_schema.strict ?? true
123
+ }
124
+ };
125
+ }
126
+ function toOpenAIResponsesTextFormat(rf) {
127
+ if (!rf || rf.type !== "json_schema") return void 0;
128
+ return {
129
+ type: "json_schema",
130
+ name: rf.json_schema.name,
131
+ schema: normalizeObjectJsonSchema(rf.json_schema.schema),
132
+ strict: rf.json_schema.strict ?? true
133
+ };
134
+ }
135
+ function formatTools(actions) {
136
+ return actions.map((action) => ({
137
+ type: "function",
138
+ function: {
139
+ name: action.name,
140
+ description: action.description,
141
+ parameters: {
142
+ type: "object",
143
+ properties: action.parameters ? Object.fromEntries(
144
+ Object.entries(action.parameters).map(([key, param]) => [
145
+ key,
146
+ parameterToJsonSchema(param)
147
+ ])
148
+ ) : {},
149
+ required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
150
+ additionalProperties: false
151
+ }
152
+ }
153
+ }));
154
+ }
155
+ function hasImageAttachments(message) {
156
+ const attachments = message.metadata?.attachments;
157
+ return attachments?.some((a) => a.type === "image") ?? false;
158
+ }
159
+ function attachmentToOpenAIImage(attachment) {
160
+ if (attachment.type !== "image") return null;
161
+ let imageUrl;
162
+ if (attachment.url) {
163
+ imageUrl = attachment.url;
164
+ } else if (attachment.data) {
165
+ imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
166
+ } else {
167
+ return null;
168
+ }
169
+ return {
170
+ type: "image_url",
171
+ image_url: {
172
+ url: imageUrl,
173
+ detail: "auto"
174
+ }
175
+ };
176
+ }
177
+ function messageToOpenAIContent(message) {
178
+ const attachments = message.metadata?.attachments;
179
+ const content = message.content ?? "";
180
+ if (!hasImageAttachments(message)) {
181
+ return content;
182
+ }
183
+ const blocks = [];
184
+ if (content) {
185
+ blocks.push({ type: "text", text: content });
186
+ }
187
+ if (attachments) {
188
+ for (const attachment of attachments) {
189
+ const imageBlock = attachmentToOpenAIImage(attachment);
190
+ if (imageBlock) {
191
+ blocks.push(imageBlock);
192
+ }
193
+ }
194
+ }
195
+ return blocks;
196
+ }
197
+ function formatMessagesForOpenAI(messages, systemPrompt) {
198
+ const formatted = [];
199
+ if (systemPrompt) {
200
+ formatted.push({ role: "system", content: systemPrompt });
201
+ }
202
+ for (const msg of messages) {
203
+ if (msg.role === "system") {
204
+ formatted.push({ role: "system", content: msg.content ?? "" });
205
+ } else if (msg.role === "user") {
206
+ formatted.push({
207
+ role: "user",
208
+ content: messageToOpenAIContent(msg)
209
+ });
210
+ } else if (msg.role === "assistant") {
211
+ const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
212
+ const assistantMsg = {
213
+ role: "assistant",
214
+ // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
215
+ content: hasToolCalls ? msg.content || null : msg.content
216
+ };
217
+ if (hasToolCalls) {
218
+ assistantMsg.tool_calls = msg.tool_calls;
219
+ }
220
+ formatted.push(assistantMsg);
221
+ } else if (msg.role === "tool" && msg.tool_call_id) {
222
+ formatted.push({
223
+ role: "tool",
224
+ content: msg.content ?? "",
225
+ tool_call_id: msg.tool_call_id
226
+ });
227
+ }
228
+ }
229
+ return formatted;
230
+ }
231
+
3
232
  // src/providers/openai/provider.ts
4
233
  var OPENAI_MODELS = {
5
234
  // GPT-4o series
@@ -94,13 +323,17 @@ function openai(modelId, options = {}) {
94
323
  },
95
324
  async doGenerate(params) {
96
325
  const client2 = await getClient();
97
- const messages = formatMessagesForOpenAI(params.messages);
326
+ const messages = formatMessagesForOpenAI2(params.messages);
98
327
  const response = await client2.chat.completions.create({
99
328
  model: modelId,
100
329
  messages,
101
330
  tools: params.tools,
102
- temperature: params.temperature,
103
- max_tokens: params.maxTokens
331
+ ...buildOpenAITokenParams(
332
+ modelId,
333
+ params.maxTokens,
334
+ params.temperature
335
+ ),
336
+ response_format: toOpenAIResponseFormat(params.responseFormat)
104
337
  });
105
338
  const choice = response.choices[0];
106
339
  const message = choice.message;
@@ -125,13 +358,17 @@ function openai(modelId, options = {}) {
125
358
  },
126
359
  async *doStream(params) {
127
360
  const client2 = await getClient();
128
- const messages = formatMessagesForOpenAI(params.messages);
361
+ const messages = formatMessagesForOpenAI2(params.messages);
129
362
  const stream = await client2.chat.completions.create({
130
363
  model: modelId,
131
364
  messages,
132
365
  tools: params.tools,
133
- temperature: params.temperature,
134
- max_tokens: params.maxTokens,
366
+ ...buildOpenAITokenParams(
367
+ modelId,
368
+ params.maxTokens,
369
+ params.temperature
370
+ ),
371
+ response_format: toOpenAIResponseFormat(params.responseFormat),
135
372
  stream: true
136
373
  });
137
374
  let currentToolCall = null;
@@ -165,18 +402,8 @@ function openai(modelId, options = {}) {
165
402
  name: tc.function?.name ?? "",
166
403
  arguments: tc.function?.arguments ?? ""
167
404
  };
168
- yield {
169
- type: "tool-call-start",
170
- toolCallId: tc.id,
171
- toolName: tc.function?.name ?? ""
172
- };
173
405
  } else if (currentToolCall && tc.function?.arguments) {
174
406
  currentToolCall.arguments += tc.function.arguments;
175
- yield {
176
- type: "tool-call-delta",
177
- toolCallId: currentToolCall.id,
178
- argsText: currentToolCall.arguments
179
- };
180
407
  }
181
408
  }
182
409
  }
@@ -225,7 +452,7 @@ function mapFinishReason(reason) {
225
452
  return "unknown";
226
453
  }
227
454
  }
228
- function formatMessagesForOpenAI(messages) {
455
+ function formatMessagesForOpenAI2(messages) {
229
456
  return messages.map((msg) => {
230
457
  switch (msg.role) {
231
458
  case "system":
@@ -287,204 +514,6 @@ function generateToolCallId() {
287
514
  return generateId("call");
288
515
  }
289
516
 
290
- // src/adapters/base.ts
291
- function stringifyForDebug(value) {
292
- return JSON.stringify(
293
- value,
294
- (_key, currentValue) => {
295
- if (typeof currentValue === "bigint") {
296
- return currentValue.toString();
297
- }
298
- if (currentValue instanceof Error) {
299
- return {
300
- name: currentValue.name,
301
- message: currentValue.message,
302
- stack: currentValue.stack
303
- };
304
- }
305
- return currentValue;
306
- },
307
- 2
308
- );
309
- }
310
- function logProviderPayload(provider, label, payload, enabled) {
311
- if (!enabled) {
312
- return;
313
- }
314
- if (label.toLowerCase().includes("stream ")) {
315
- return;
316
- }
317
- try {
318
- console.log(
319
- `[llm-sdk:${provider}] ${label}
320
- ${stringifyForDebug(payload)}`
321
- );
322
- } catch (error) {
323
- console.log(
324
- `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
325
- error
326
- );
327
- }
328
- }
329
- function parameterToJsonSchema(param) {
330
- const schema = {
331
- type: param.type
332
- };
333
- if (param.description) {
334
- schema.description = param.description;
335
- }
336
- if (param.enum) {
337
- schema.enum = param.enum;
338
- }
339
- if (param.type === "array" && param.items) {
340
- schema.items = parameterToJsonSchema(
341
- param.items
342
- );
343
- }
344
- if (param.type === "object" && param.properties) {
345
- schema.properties = Object.fromEntries(
346
- Object.entries(param.properties).map(([key, prop]) => [
347
- key,
348
- parameterToJsonSchema(
349
- prop
350
- )
351
- ])
352
- );
353
- schema.additionalProperties = false;
354
- }
355
- return schema;
356
- }
357
- function normalizeObjectJsonSchema(schema) {
358
- if (!schema || typeof schema !== "object") {
359
- return {
360
- type: "object",
361
- properties: {},
362
- required: [],
363
- additionalProperties: false
364
- };
365
- }
366
- const normalized = { ...schema };
367
- const type = normalized.type;
368
- if (type === "object") {
369
- const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
370
- normalized.properties = Object.fromEntries(
371
- Object.entries(properties).map(([key, value]) => [
372
- key,
373
- normalizeObjectJsonSchema(value)
374
- ])
375
- );
376
- const propertyKeys = Object.keys(properties);
377
- const required = Array.isArray(normalized.required) ? normalized.required.filter(
378
- (value) => typeof value === "string"
379
- ) : [];
380
- normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
381
- if (normalized.additionalProperties === void 0) {
382
- normalized.additionalProperties = false;
383
- }
384
- } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
385
- normalized.items = normalizeObjectJsonSchema(
386
- normalized.items
387
- );
388
- }
389
- return normalized;
390
- }
391
- function formatTools(actions) {
392
- return actions.map((action) => ({
393
- type: "function",
394
- function: {
395
- name: action.name,
396
- description: action.description,
397
- parameters: {
398
- type: "object",
399
- properties: action.parameters ? Object.fromEntries(
400
- Object.entries(action.parameters).map(([key, param]) => [
401
- key,
402
- parameterToJsonSchema(param)
403
- ])
404
- ) : {},
405
- required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
406
- additionalProperties: false
407
- }
408
- }
409
- }));
410
- }
411
- function hasImageAttachments(message) {
412
- const attachments = message.metadata?.attachments;
413
- return attachments?.some((a) => a.type === "image") ?? false;
414
- }
415
- function attachmentToOpenAIImage(attachment) {
416
- if (attachment.type !== "image") return null;
417
- let imageUrl;
418
- if (attachment.url) {
419
- imageUrl = attachment.url;
420
- } else if (attachment.data) {
421
- imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
422
- } else {
423
- return null;
424
- }
425
- return {
426
- type: "image_url",
427
- image_url: {
428
- url: imageUrl,
429
- detail: "auto"
430
- }
431
- };
432
- }
433
- function messageToOpenAIContent(message) {
434
- const attachments = message.metadata?.attachments;
435
- const content = message.content ?? "";
436
- if (!hasImageAttachments(message)) {
437
- return content;
438
- }
439
- const blocks = [];
440
- if (content) {
441
- blocks.push({ type: "text", text: content });
442
- }
443
- if (attachments) {
444
- for (const attachment of attachments) {
445
- const imageBlock = attachmentToOpenAIImage(attachment);
446
- if (imageBlock) {
447
- blocks.push(imageBlock);
448
- }
449
- }
450
- }
451
- return blocks;
452
- }
453
- function formatMessagesForOpenAI2(messages, systemPrompt) {
454
- const formatted = [];
455
- if (systemPrompt) {
456
- formatted.push({ role: "system", content: systemPrompt });
457
- }
458
- for (const msg of messages) {
459
- if (msg.role === "system") {
460
- formatted.push({ role: "system", content: msg.content ?? "" });
461
- } else if (msg.role === "user") {
462
- formatted.push({
463
- role: "user",
464
- content: messageToOpenAIContent(msg)
465
- });
466
- } else if (msg.role === "assistant") {
467
- const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
468
- const assistantMsg = {
469
- role: "assistant",
470
- // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
471
- content: hasToolCalls ? msg.content || null : msg.content
472
- };
473
- if (hasToolCalls) {
474
- assistantMsg.tool_calls = msg.tool_calls;
475
- }
476
- formatted.push(assistantMsg);
477
- } else if (msg.role === "tool" && msg.tool_call_id) {
478
- formatted.push({
479
- role: "tool",
480
- content: msg.content ?? "",
481
- tool_call_id: msg.tool_call_id
482
- });
483
- }
484
- }
485
- return formatted;
486
- }
487
-
488
517
  // src/adapters/openai.ts
489
518
  var OpenAIAdapter = class _OpenAIAdapter {
490
519
  constructor(config) {
@@ -497,7 +526,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
497
526
  if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
498
527
  if (baseUrl.includes("x.ai")) return "xai";
499
528
  if (baseUrl.includes("azure")) return "azure";
500
- if (baseUrl.includes("openrouter.ai")) return "openrouter";
501
529
  return "openai";
502
530
  }
503
531
  async getClient() {
@@ -514,7 +542,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
514
542
  return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
515
543
  }
516
544
  buildResponsesInput(request) {
517
- const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI2(request.messages, void 0);
545
+ const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
518
546
  const input = [];
519
547
  for (const message of sourceMessages) {
520
548
  if (message.role === "system") {
@@ -597,259 +625,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
597
625
  rawResponse: response
598
626
  };
599
627
  }
600
- /**
601
- * OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
602
- * reasoning content on the chat-completions endpoint. To surface reasoning
603
- * SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
604
- * Responses API, which streams `response.reasoning_summary_text.delta` events.
605
- *
606
- * Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
607
- * openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
608
- */
609
- isOpenAIReasoningModelOnOpenRouter(activeModel) {
610
- if (this.provider !== "openrouter") return false;
611
- return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
612
- }
613
- /**
614
- * Convert ActionDefinition[] (the chat-completions tool shape used by the
615
- * adapter) to the Responses API tool shape.
616
- */
617
- buildResponsesToolsFromActions(actions) {
618
- if (!actions || actions.length === 0) return void 0;
619
- const formatted = formatTools(actions);
620
- return formatted.map((t) => ({
621
- type: "function",
622
- name: t.function.name,
623
- description: t.function.description,
624
- parameters: t.function.parameters
625
- }));
626
- }
627
- /**
628
- * Streaming Responses API path for OpenAI reasoning models on OpenRouter.
629
- *
630
- * Maps Responses API SSE events back to the same StreamEvent shapes the
631
- * chat-completions path emits, so downstream consumers (processChunk.ts,
632
- * frontend tool handlers, plan approval, specialist delegations) see
633
- * identical events regardless of which path produced them.
634
- *
635
- * response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
636
- * response.output_text.delta → message:delta
637
- * response.output_item.added (function_call) → action:start (queued buffer)
638
- * response.function_call_arguments.delta → action:args (progressive)
639
- * response.output_item.done (function_call) → final action:args + action:end
640
- * response.completed → message:end + done(usage)
641
- * response.error → error
642
- */
643
- async *streamWithResponsesAPI(request, activeModel, messageId) {
644
- const client = await this.getClient();
645
- const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
646
- const payload = {
647
- model: activeModel,
648
- input: this.buildResponsesInput(request),
649
- stream: true,
650
- reasoning: {
651
- effort: request.config?.reasoningEffort ?? "medium",
652
- summary: "auto"
653
- }
654
- };
655
- if (request.systemPrompt) payload.instructions = request.systemPrompt;
656
- if (typeof maxTokensValue === "number")
657
- payload.max_output_tokens = maxTokensValue;
658
- const tools = this.buildResponsesToolsFromActions(request.actions);
659
- if (tools && tools.length > 0) payload.tools = tools;
660
- logProviderPayload(
661
- "openai",
662
- "responses-api request payload",
663
- payload,
664
- request.debug
665
- );
666
- let stream;
667
- try {
668
- stream = await client.responses.create(payload);
669
- } catch (error) {
670
- yield {
671
- type: "error",
672
- message: error instanceof Error ? error.message : "Unknown error",
673
- code: "OPENAI_RESPONSES_ERROR"
674
- };
675
- return;
676
- }
677
- const toolBuffers = /* @__PURE__ */ new Map();
678
- const itemIdToCallId = /* @__PURE__ */ new Map();
679
- let usage;
680
- let reasoningStarted = false;
681
- let textStarted = false;
682
- let finishEmitted = false;
683
- const resolveCallId = (evt) => {
684
- if (evt?.call_id) return evt.call_id;
685
- if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
686
- if (evt?.item?.call_id) return evt.item.call_id;
687
- if (evt?.item?.id) return evt.item.id;
688
- return "";
689
- };
690
- try {
691
- for await (const evt of stream) {
692
- logProviderPayload(
693
- "openai",
694
- "responses-api stream chunk",
695
- evt,
696
- request.debug
697
- );
698
- if (request.signal?.aborted) break;
699
- const t = evt?.type ?? "";
700
- if (t === "response.reasoning_summary_text.delta") {
701
- const delta = evt.delta ?? "";
702
- if (!delta) continue;
703
- if (!reasoningStarted) {
704
- yield { type: "thinking:start" };
705
- reasoningStarted = true;
706
- }
707
- yield { type: "thinking:delta", content: delta };
708
- continue;
709
- }
710
- if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
711
- continue;
712
- }
713
- if (t === "response.output_text.delta") {
714
- const text = evt.delta ?? "";
715
- if (!text) continue;
716
- if (reasoningStarted && !textStarted) {
717
- yield { type: "thinking:end" };
718
- textStarted = true;
719
- }
720
- yield { type: "message:delta", content: text };
721
- continue;
722
- }
723
- if (t === "response.output_item.added") {
724
- const item = evt.item;
725
- if (item?.type === "function_call") {
726
- const callId = item.call_id ?? item.id ?? "";
727
- const itemId = item.id ?? callId;
728
- if (callId) {
729
- if (itemId && itemId !== callId) {
730
- itemIdToCallId.set(itemId, callId);
731
- }
732
- if (!toolBuffers.has(callId)) {
733
- toolBuffers.set(callId, {
734
- id: callId,
735
- name: item.name ?? "",
736
- arguments: item.arguments ?? "",
737
- emittedStart: false
738
- });
739
- }
740
- const buf = toolBuffers.get(callId);
741
- if (buf.name && !buf.emittedStart) {
742
- yield { type: "action:start", id: buf.id, name: buf.name };
743
- buf.emittedStart = true;
744
- }
745
- }
746
- }
747
- continue;
748
- }
749
- if (t === "response.function_call_arguments.delta") {
750
- const callId = resolveCallId(evt);
751
- const delta = evt.delta ?? "";
752
- if (!callId || !delta) continue;
753
- let buf = toolBuffers.get(callId);
754
- if (!buf) {
755
- buf = { id: callId, name: "", arguments: "", emittedStart: false };
756
- toolBuffers.set(callId, buf);
757
- }
758
- buf.arguments += delta;
759
- if (buf.emittedStart) {
760
- yield {
761
- type: "action:args",
762
- id: buf.id,
763
- args: buf.arguments
764
- };
765
- }
766
- continue;
767
- }
768
- if (t === "response.output_item.done") {
769
- const item = evt.item;
770
- if (item?.type === "function_call") {
771
- const callId = item.call_id ?? item.id ?? "";
772
- const buf = toolBuffers.get(callId);
773
- const name = buf?.name || item.name || "";
774
- const argsStr = buf?.arguments || item.arguments || "{}";
775
- if (callId && name) {
776
- if (!buf?.emittedStart) {
777
- yield { type: "action:start", id: callId, name };
778
- }
779
- yield {
780
- type: "action:args",
781
- id: callId,
782
- args: argsStr
783
- };
784
- yield {
785
- type: "action:end",
786
- id: callId,
787
- name
788
- };
789
- }
790
- toolBuffers.delete(callId);
791
- }
792
- continue;
793
- }
794
- if (t === "response.completed") {
795
- const u = evt.response?.usage;
796
- if (u) {
797
- usage = {
798
- prompt_tokens: u.input_tokens ?? 0,
799
- completion_tokens: u.output_tokens ?? 0,
800
- total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
801
- };
802
- }
803
- for (const buf of toolBuffers.values()) {
804
- if (!buf.id || !buf.name) continue;
805
- if (!buf.emittedStart) {
806
- yield { type: "action:start", id: buf.id, name: buf.name };
807
- }
808
- yield {
809
- type: "action:args",
810
- id: buf.id,
811
- args: buf.arguments || "{}"
812
- };
813
- yield { type: "action:end", id: buf.id, name: buf.name };
814
- }
815
- toolBuffers.clear();
816
- if (reasoningStarted && !textStarted) {
817
- yield { type: "thinking:end" };
818
- }
819
- yield { type: "message:end" };
820
- yield { type: "done", usage };
821
- finishEmitted = true;
822
- continue;
823
- }
824
- if (t === "response.error" || t === "error") {
825
- const msg = evt.error?.message || evt.message || "Responses API error";
826
- yield {
827
- type: "error",
828
- message: msg,
829
- code: "OPENAI_RESPONSES_ERROR"
830
- };
831
- return;
832
- }
833
- }
834
- } catch (error) {
835
- yield {
836
- type: "error",
837
- message: error instanceof Error ? error.message : "Unknown error",
838
- code: "OPENAI_RESPONSES_ERROR"
839
- };
840
- return;
841
- }
842
- if (!finishEmitted) {
843
- if (reasoningStarted && !textStarted) {
844
- yield { type: "thinking:end" };
845
- }
846
- yield { type: "message:end" };
847
- yield { type: "done", usage };
848
- }
849
- }
850
628
  async completeWithResponses(request) {
851
629
  const client = await this.getClient();
852
630
  const openaiToolOptions = request.providerToolOptions?.openai;
631
+ const responsesTextFormat = toOpenAIResponsesTextFormat(
632
+ request.config?.responseFormat
633
+ );
853
634
  const payload = {
854
635
  model: request.config?.model || this.model,
855
636
  instructions: request.systemPrompt,
@@ -859,6 +640,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
859
640
  parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
860
641
  temperature: request.config?.temperature ?? this.config.temperature,
861
642
  max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
643
+ ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
862
644
  stream: false
863
645
  };
864
646
  logProviderPayload("openai", "request payload", payload, request.debug);
@@ -953,7 +735,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
953
735
  messages = processedMessages;
954
736
  }
955
737
  } else {
956
- messages = formatMessagesForOpenAI2(
738
+ messages = formatMessagesForOpenAI(
957
739
  request.messages,
958
740
  request.systemPrompt
959
741
  );
@@ -980,37 +762,21 @@ var OpenAIAdapter = class _OpenAIAdapter {
980
762
  name: openaiToolOptions.toolChoice.name
981
763
  }
982
764
  } : openaiToolOptions?.toolChoice;
983
- const isOpenRouter = this.provider === "openrouter";
984
- const activeModel = request.config?.model || this.model;
985
- const modelSlug = activeModel.replace("openai/", "");
986
- const isOSeries = /^o[1-9]/.test(modelSlug);
987
- const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
988
- if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
989
- yield* this.streamWithResponsesAPI(request, activeModel, messageId);
990
- return;
991
- }
992
- const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
765
+ const modelIdForPayload = request.config?.model || this.model;
993
766
  const payload = {
994
- model: activeModel,
767
+ model: modelIdForPayload,
995
768
  messages,
996
769
  tools: tools.length > 0 ? tools : void 0,
997
770
  tool_choice: tools.length > 0 ? toolChoice : void 0,
998
771
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
772
+ ...buildOpenAITokenParams(
773
+ modelIdForPayload,
774
+ request.config?.maxTokens ?? this.config.maxTokens,
775
+ request.config?.temperature ?? this.config.temperature
776
+ ),
777
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
999
778
  stream: true,
1000
- stream_options: { include_usage: true },
1001
- // o-series: use max_completion_tokens + reasoning_effort, no temperature
1002
- // regular models: use max_tokens + temperature
1003
- ...isOSeries ? {
1004
- max_completion_tokens: maxTokensValue,
1005
- reasoning_effort: request.config?.reasoningEffort ?? "medium"
1006
- } : {
1007
- temperature: request.config?.temperature ?? this.config.temperature,
1008
- max_tokens: maxTokensValue
1009
- },
1010
- // Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
1011
- // When disableThinking=true we must explicitly send include_reasoning:false because
1012
- // models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
1013
- ...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
779
+ stream_options: { include_usage: true }
1014
780
  };
1015
781
  logProviderPayload("openai", "request payload", payload, request.debug);
1016
782
  const stream = await client.chat.completions.create(payload);
@@ -1018,7 +784,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
1018
784
  const collectedCitations = [];
1019
785
  let citationIndex = 0;
1020
786
  let usage;
1021
- let adapterReasoningStarted = false;
1022
787
  for await (const chunk of stream) {
1023
788
  logProviderPayload("openai", "stream chunk", chunk, request.debug);
1024
789
  if (request.signal?.aborted) {
@@ -1029,22 +794,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
1029
794
  if (delta?.content) {
1030
795
  yield { type: "message:delta", content: delta.content };
1031
796
  }
1032
- if (isOpenRouter) {
1033
- const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
1034
- if (rc) {
1035
- const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
1036
- if (rcText) {
1037
- if (!adapterReasoningStarted) {
1038
- yield { type: "thinking:start" };
1039
- adapterReasoningStarted = true;
1040
- }
1041
- yield { type: "thinking:delta", content: rcText };
1042
- }
1043
- } else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
1044
- yield { type: "thinking:end" };
1045
- adapterReasoningStarted = false;
1046
- }
1047
- }
1048
797
  const annotations = delta?.annotations;
1049
798
  if (annotations && annotations.length > 0) {
1050
799
  for (const annotation of annotations) {
@@ -1092,11 +841,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
1092
841
  };
1093
842
  } else if (currentToolCall && toolCall.function?.arguments) {
1094
843
  currentToolCall.arguments += toolCall.function.arguments;
1095
- yield {
1096
- type: "action:args",
1097
- id: currentToolCall.id,
1098
- args: currentToolCall.arguments
1099
- };
1100
844
  }
1101
845
  }
1102
846
  }
@@ -1159,7 +903,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
1159
903
  messages = sanitized;
1160
904
  }
1161
905
  } else {
1162
- messages = formatMessagesForOpenAI2(
906
+ messages = formatMessagesForOpenAI(
1163
907
  request.messages,
1164
908
  request.systemPrompt
1165
909
  );
@@ -1172,24 +916,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1172
916
  name: openaiToolOptions.toolChoice.name
1173
917
  }
1174
918
  } : openaiToolOptions?.toolChoice;
1175
- const activeModel2 = request.config?.model || this.model;
1176
- const modelSlug2 = activeModel2.replace("openai/", "");
1177
- const isOSeries2 = /^o[1-9]/.test(modelSlug2);
1178
- const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
919
+ const modelIdForCompletePayload = request.config?.model || this.model;
1179
920
  const payload = {
1180
- model: activeModel2,
921
+ model: modelIdForCompletePayload,
1181
922
  messages,
1182
923
  tools: tools.length > 0 ? tools : void 0,
1183
924
  tool_choice: tools.length > 0 ? toolChoice : void 0,
1184
925
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
1185
- stream: false,
1186
- ...isOSeries2 ? {
1187
- max_completion_tokens: maxTokensValue2,
1188
- reasoning_effort: request.config?.reasoningEffort ?? "medium"
1189
- } : {
1190
- temperature: request.config?.temperature ?? this.config.temperature,
1191
- max_tokens: maxTokensValue2
1192
- }
926
+ ...buildOpenAITokenParams(
927
+ modelIdForCompletePayload,
928
+ request.config?.maxTokens ?? this.config.maxTokens,
929
+ request.config?.temperature ?? this.config.temperature
930
+ ),
931
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
932
+ stream: false
1193
933
  };
1194
934
  logProviderPayload("openai", "request payload", payload, request.debug);
1195
935
  const response = await client.chat.completions.create(payload);