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