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