@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/togetherai/provider.ts
4
233
  function togetherai(modelId, options = {}) {
5
234
  const apiKey = options.apiKey ?? process.env.TOGETHER_API_KEY;
@@ -42,6 +271,10 @@ function togetherai(modelId, options = {}) {
42
271
  if (params.tools) {
43
272
  requestBody.tools = params.tools;
44
273
  }
274
+ const responseFormat = toOpenAIResponseFormat(params.responseFormat);
275
+ if (responseFormat) {
276
+ requestBody.response_format = responseFormat;
277
+ }
45
278
  const response = await client2.chat.completions.create(requestBody);
46
279
  const choice = response.choices[0];
47
280
  const message = choice.message;
@@ -77,6 +310,10 @@ function togetherai(modelId, options = {}) {
77
310
  if (params.tools) {
78
311
  requestBody.tools = params.tools;
79
312
  }
313
+ const responseFormat = toOpenAIResponseFormat(params.responseFormat);
314
+ if (responseFormat) {
315
+ requestBody.response_format = responseFormat;
316
+ }
80
317
  const stream = await client2.chat.completions.create(requestBody);
81
318
  const toolCallMap = /* @__PURE__ */ new Map();
82
319
  let totalPromptTokens = 0;
@@ -215,204 +452,6 @@ function generateToolCallId() {
215
452
  return generateId("call");
216
453
  }
217
454
 
218
- // src/adapters/base.ts
219
- function stringifyForDebug(value) {
220
- return JSON.stringify(
221
- value,
222
- (_key, currentValue) => {
223
- if (typeof currentValue === "bigint") {
224
- return currentValue.toString();
225
- }
226
- if (currentValue instanceof Error) {
227
- return {
228
- name: currentValue.name,
229
- message: currentValue.message,
230
- stack: currentValue.stack
231
- };
232
- }
233
- return currentValue;
234
- },
235
- 2
236
- );
237
- }
238
- function logProviderPayload(provider, label, payload, enabled) {
239
- if (!enabled) {
240
- return;
241
- }
242
- if (label.toLowerCase().includes("stream ")) {
243
- return;
244
- }
245
- try {
246
- console.log(
247
- `[llm-sdk:${provider}] ${label}
248
- ${stringifyForDebug(payload)}`
249
- );
250
- } catch (error) {
251
- console.log(
252
- `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
253
- error
254
- );
255
- }
256
- }
257
- function parameterToJsonSchema(param) {
258
- const schema = {
259
- type: param.type
260
- };
261
- if (param.description) {
262
- schema.description = param.description;
263
- }
264
- if (param.enum) {
265
- schema.enum = param.enum;
266
- }
267
- if (param.type === "array" && param.items) {
268
- schema.items = parameterToJsonSchema(
269
- param.items
270
- );
271
- }
272
- if (param.type === "object" && param.properties) {
273
- schema.properties = Object.fromEntries(
274
- Object.entries(param.properties).map(([key, prop]) => [
275
- key,
276
- parameterToJsonSchema(
277
- prop
278
- )
279
- ])
280
- );
281
- schema.additionalProperties = false;
282
- }
283
- return schema;
284
- }
285
- function normalizeObjectJsonSchema(schema) {
286
- if (!schema || typeof schema !== "object") {
287
- return {
288
- type: "object",
289
- properties: {},
290
- required: [],
291
- additionalProperties: false
292
- };
293
- }
294
- const normalized = { ...schema };
295
- const type = normalized.type;
296
- if (type === "object") {
297
- const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
298
- normalized.properties = Object.fromEntries(
299
- Object.entries(properties).map(([key, value]) => [
300
- key,
301
- normalizeObjectJsonSchema(value)
302
- ])
303
- );
304
- const propertyKeys = Object.keys(properties);
305
- const required = Array.isArray(normalized.required) ? normalized.required.filter(
306
- (value) => typeof value === "string"
307
- ) : [];
308
- normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
309
- if (normalized.additionalProperties === void 0) {
310
- normalized.additionalProperties = false;
311
- }
312
- } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
313
- normalized.items = normalizeObjectJsonSchema(
314
- normalized.items
315
- );
316
- }
317
- return normalized;
318
- }
319
- function formatTools(actions) {
320
- return actions.map((action) => ({
321
- type: "function",
322
- function: {
323
- name: action.name,
324
- description: action.description,
325
- parameters: {
326
- type: "object",
327
- properties: action.parameters ? Object.fromEntries(
328
- Object.entries(action.parameters).map(([key, param]) => [
329
- key,
330
- parameterToJsonSchema(param)
331
- ])
332
- ) : {},
333
- required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
334
- additionalProperties: false
335
- }
336
- }
337
- }));
338
- }
339
- function hasImageAttachments(message) {
340
- const attachments = message.metadata?.attachments;
341
- return attachments?.some((a) => a.type === "image") ?? false;
342
- }
343
- function attachmentToOpenAIImage(attachment) {
344
- if (attachment.type !== "image") return null;
345
- let imageUrl;
346
- if (attachment.url) {
347
- imageUrl = attachment.url;
348
- } else if (attachment.data) {
349
- imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
350
- } else {
351
- return null;
352
- }
353
- return {
354
- type: "image_url",
355
- image_url: {
356
- url: imageUrl,
357
- detail: "auto"
358
- }
359
- };
360
- }
361
- function messageToOpenAIContent(message) {
362
- const attachments = message.metadata?.attachments;
363
- const content = message.content ?? "";
364
- if (!hasImageAttachments(message)) {
365
- return content;
366
- }
367
- const blocks = [];
368
- if (content) {
369
- blocks.push({ type: "text", text: content });
370
- }
371
- if (attachments) {
372
- for (const attachment of attachments) {
373
- const imageBlock = attachmentToOpenAIImage(attachment);
374
- if (imageBlock) {
375
- blocks.push(imageBlock);
376
- }
377
- }
378
- }
379
- return blocks;
380
- }
381
- function formatMessagesForOpenAI(messages, systemPrompt) {
382
- const formatted = [];
383
- if (systemPrompt) {
384
- formatted.push({ role: "system", content: systemPrompt });
385
- }
386
- for (const msg of messages) {
387
- if (msg.role === "system") {
388
- formatted.push({ role: "system", content: msg.content ?? "" });
389
- } else if (msg.role === "user") {
390
- formatted.push({
391
- role: "user",
392
- content: messageToOpenAIContent(msg)
393
- });
394
- } else if (msg.role === "assistant") {
395
- const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
396
- const assistantMsg = {
397
- role: "assistant",
398
- // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
399
- content: hasToolCalls ? msg.content || null : msg.content
400
- };
401
- if (hasToolCalls) {
402
- assistantMsg.tool_calls = msg.tool_calls;
403
- }
404
- formatted.push(assistantMsg);
405
- } else if (msg.role === "tool" && msg.tool_call_id) {
406
- formatted.push({
407
- role: "tool",
408
- content: msg.content ?? "",
409
- tool_call_id: msg.tool_call_id
410
- });
411
- }
412
- }
413
- return formatted;
414
- }
415
-
416
455
  // src/adapters/openai.ts
417
456
  var OpenAIAdapter = class _OpenAIAdapter {
418
457
  constructor(config) {
@@ -425,7 +464,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
425
464
  if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
426
465
  if (baseUrl.includes("x.ai")) return "xai";
427
466
  if (baseUrl.includes("azure")) return "azure";
428
- if (baseUrl.includes("openrouter.ai")) return "openrouter";
429
467
  return "openai";
430
468
  }
431
469
  async getClient() {
@@ -525,259 +563,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
525
563
  rawResponse: response
526
564
  };
527
565
  }
528
- /**
529
- * OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
530
- * reasoning content on the chat-completions endpoint. To surface reasoning
531
- * SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
532
- * Responses API, which streams `response.reasoning_summary_text.delta` events.
533
- *
534
- * Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
535
- * openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
536
- */
537
- isOpenAIReasoningModelOnOpenRouter(activeModel) {
538
- if (this.provider !== "openrouter") return false;
539
- return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
540
- }
541
- /**
542
- * Convert ActionDefinition[] (the chat-completions tool shape used by the
543
- * adapter) to the Responses API tool shape.
544
- */
545
- buildResponsesToolsFromActions(actions) {
546
- if (!actions || actions.length === 0) return void 0;
547
- const formatted = formatTools(actions);
548
- return formatted.map((t) => ({
549
- type: "function",
550
- name: t.function.name,
551
- description: t.function.description,
552
- parameters: t.function.parameters
553
- }));
554
- }
555
- /**
556
- * Streaming Responses API path for OpenAI reasoning models on OpenRouter.
557
- *
558
- * Maps Responses API SSE events back to the same StreamEvent shapes the
559
- * chat-completions path emits, so downstream consumers (processChunk.ts,
560
- * frontend tool handlers, plan approval, specialist delegations) see
561
- * identical events regardless of which path produced them.
562
- *
563
- * response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
564
- * response.output_text.delta → message:delta
565
- * response.output_item.added (function_call) → action:start (queued buffer)
566
- * response.function_call_arguments.delta → action:args (progressive)
567
- * response.output_item.done (function_call) → final action:args + action:end
568
- * response.completed → message:end + done(usage)
569
- * response.error → error
570
- */
571
- async *streamWithResponsesAPI(request, activeModel, messageId) {
572
- const client = await this.getClient();
573
- const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
574
- const payload = {
575
- model: activeModel,
576
- input: this.buildResponsesInput(request),
577
- stream: true,
578
- reasoning: {
579
- effort: request.config?.reasoningEffort ?? "medium",
580
- summary: "auto"
581
- }
582
- };
583
- if (request.systemPrompt) payload.instructions = request.systemPrompt;
584
- if (typeof maxTokensValue === "number")
585
- payload.max_output_tokens = maxTokensValue;
586
- const tools = this.buildResponsesToolsFromActions(request.actions);
587
- if (tools && tools.length > 0) payload.tools = tools;
588
- logProviderPayload(
589
- "openai",
590
- "responses-api request payload",
591
- payload,
592
- request.debug
593
- );
594
- let stream;
595
- try {
596
- stream = await client.responses.create(payload);
597
- } catch (error) {
598
- yield {
599
- type: "error",
600
- message: error instanceof Error ? error.message : "Unknown error",
601
- code: "OPENAI_RESPONSES_ERROR"
602
- };
603
- return;
604
- }
605
- const toolBuffers = /* @__PURE__ */ new Map();
606
- const itemIdToCallId = /* @__PURE__ */ new Map();
607
- let usage;
608
- let reasoningStarted = false;
609
- let textStarted = false;
610
- let finishEmitted = false;
611
- const resolveCallId = (evt) => {
612
- if (evt?.call_id) return evt.call_id;
613
- if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
614
- if (evt?.item?.call_id) return evt.item.call_id;
615
- if (evt?.item?.id) return evt.item.id;
616
- return "";
617
- };
618
- try {
619
- for await (const evt of stream) {
620
- logProviderPayload(
621
- "openai",
622
- "responses-api stream chunk",
623
- evt,
624
- request.debug
625
- );
626
- if (request.signal?.aborted) break;
627
- const t = evt?.type ?? "";
628
- if (t === "response.reasoning_summary_text.delta") {
629
- const delta = evt.delta ?? "";
630
- if (!delta) continue;
631
- if (!reasoningStarted) {
632
- yield { type: "thinking:start" };
633
- reasoningStarted = true;
634
- }
635
- yield { type: "thinking:delta", content: delta };
636
- continue;
637
- }
638
- if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
639
- continue;
640
- }
641
- if (t === "response.output_text.delta") {
642
- const text = evt.delta ?? "";
643
- if (!text) continue;
644
- if (reasoningStarted && !textStarted) {
645
- yield { type: "thinking:end" };
646
- textStarted = true;
647
- }
648
- yield { type: "message:delta", content: text };
649
- continue;
650
- }
651
- if (t === "response.output_item.added") {
652
- const item = evt.item;
653
- if (item?.type === "function_call") {
654
- const callId = item.call_id ?? item.id ?? "";
655
- const itemId = item.id ?? callId;
656
- if (callId) {
657
- if (itemId && itemId !== callId) {
658
- itemIdToCallId.set(itemId, callId);
659
- }
660
- if (!toolBuffers.has(callId)) {
661
- toolBuffers.set(callId, {
662
- id: callId,
663
- name: item.name ?? "",
664
- arguments: item.arguments ?? "",
665
- emittedStart: false
666
- });
667
- }
668
- const buf = toolBuffers.get(callId);
669
- if (buf.name && !buf.emittedStart) {
670
- yield { type: "action:start", id: buf.id, name: buf.name };
671
- buf.emittedStart = true;
672
- }
673
- }
674
- }
675
- continue;
676
- }
677
- if (t === "response.function_call_arguments.delta") {
678
- const callId = resolveCallId(evt);
679
- const delta = evt.delta ?? "";
680
- if (!callId || !delta) continue;
681
- let buf = toolBuffers.get(callId);
682
- if (!buf) {
683
- buf = { id: callId, name: "", arguments: "", emittedStart: false };
684
- toolBuffers.set(callId, buf);
685
- }
686
- buf.arguments += delta;
687
- if (buf.emittedStart) {
688
- yield {
689
- type: "action:args",
690
- id: buf.id,
691
- args: buf.arguments
692
- };
693
- }
694
- continue;
695
- }
696
- if (t === "response.output_item.done") {
697
- const item = evt.item;
698
- if (item?.type === "function_call") {
699
- const callId = item.call_id ?? item.id ?? "";
700
- const buf = toolBuffers.get(callId);
701
- const name = buf?.name || item.name || "";
702
- const argsStr = buf?.arguments || item.arguments || "{}";
703
- if (callId && name) {
704
- if (!buf?.emittedStart) {
705
- yield { type: "action:start", id: callId, name };
706
- }
707
- yield {
708
- type: "action:args",
709
- id: callId,
710
- args: argsStr
711
- };
712
- yield {
713
- type: "action:end",
714
- id: callId,
715
- name
716
- };
717
- }
718
- toolBuffers.delete(callId);
719
- }
720
- continue;
721
- }
722
- if (t === "response.completed") {
723
- const u = evt.response?.usage;
724
- if (u) {
725
- usage = {
726
- prompt_tokens: u.input_tokens ?? 0,
727
- completion_tokens: u.output_tokens ?? 0,
728
- total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
729
- };
730
- }
731
- for (const buf of toolBuffers.values()) {
732
- if (!buf.id || !buf.name) continue;
733
- if (!buf.emittedStart) {
734
- yield { type: "action:start", id: buf.id, name: buf.name };
735
- }
736
- yield {
737
- type: "action:args",
738
- id: buf.id,
739
- args: buf.arguments || "{}"
740
- };
741
- yield { type: "action:end", id: buf.id, name: buf.name };
742
- }
743
- toolBuffers.clear();
744
- if (reasoningStarted && !textStarted) {
745
- yield { type: "thinking:end" };
746
- }
747
- yield { type: "message:end" };
748
- yield { type: "done", usage };
749
- finishEmitted = true;
750
- continue;
751
- }
752
- if (t === "response.error" || t === "error") {
753
- const msg = evt.error?.message || evt.message || "Responses API error";
754
- yield {
755
- type: "error",
756
- message: msg,
757
- code: "OPENAI_RESPONSES_ERROR"
758
- };
759
- return;
760
- }
761
- }
762
- } catch (error) {
763
- yield {
764
- type: "error",
765
- message: error instanceof Error ? error.message : "Unknown error",
766
- code: "OPENAI_RESPONSES_ERROR"
767
- };
768
- return;
769
- }
770
- if (!finishEmitted) {
771
- if (reasoningStarted && !textStarted) {
772
- yield { type: "thinking:end" };
773
- }
774
- yield { type: "message:end" };
775
- yield { type: "done", usage };
776
- }
777
- }
778
566
  async completeWithResponses(request) {
779
567
  const client = await this.getClient();
780
568
  const openaiToolOptions = request.providerToolOptions?.openai;
569
+ const responsesTextFormat = toOpenAIResponsesTextFormat(
570
+ request.config?.responseFormat
571
+ );
781
572
  const payload = {
782
573
  model: request.config?.model || this.model,
783
574
  instructions: request.systemPrompt,
@@ -787,6 +578,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
787
578
  parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
788
579
  temperature: request.config?.temperature ?? this.config.temperature,
789
580
  max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
581
+ ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
790
582
  stream: false
791
583
  };
792
584
  logProviderPayload("openai", "request payload", payload, request.debug);
@@ -908,37 +700,21 @@ var OpenAIAdapter = class _OpenAIAdapter {
908
700
  name: openaiToolOptions.toolChoice.name
909
701
  }
910
702
  } : openaiToolOptions?.toolChoice;
911
- const isOpenRouter = this.provider === "openrouter";
912
- const activeModel = request.config?.model || this.model;
913
- const modelSlug = activeModel.replace("openai/", "");
914
- const isOSeries = /^o[1-9]/.test(modelSlug);
915
- const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
916
- if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
917
- yield* this.streamWithResponsesAPI(request, activeModel, messageId);
918
- return;
919
- }
920
- const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
703
+ const modelIdForPayload = request.config?.model || this.model;
921
704
  const payload = {
922
- model: activeModel,
705
+ model: modelIdForPayload,
923
706
  messages,
924
707
  tools: tools.length > 0 ? tools : void 0,
925
708
  tool_choice: tools.length > 0 ? toolChoice : void 0,
926
709
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
710
+ ...buildOpenAITokenParams(
711
+ modelIdForPayload,
712
+ request.config?.maxTokens ?? this.config.maxTokens,
713
+ request.config?.temperature ?? this.config.temperature
714
+ ),
715
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
927
716
  stream: true,
928
- stream_options: { include_usage: true },
929
- // o-series: use max_completion_tokens + reasoning_effort, no temperature
930
- // regular models: use max_tokens + temperature
931
- ...isOSeries ? {
932
- max_completion_tokens: maxTokensValue,
933
- reasoning_effort: request.config?.reasoningEffort ?? "medium"
934
- } : {
935
- temperature: request.config?.temperature ?? this.config.temperature,
936
- max_tokens: maxTokensValue
937
- },
938
- // Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
939
- // When disableThinking=true we must explicitly send include_reasoning:false because
940
- // models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
941
- ...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
717
+ stream_options: { include_usage: true }
942
718
  };
943
719
  logProviderPayload("openai", "request payload", payload, request.debug);
944
720
  const stream = await client.chat.completions.create(payload);
@@ -946,7 +722,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
946
722
  const collectedCitations = [];
947
723
  let citationIndex = 0;
948
724
  let usage;
949
- let adapterReasoningStarted = false;
950
725
  for await (const chunk of stream) {
951
726
  logProviderPayload("openai", "stream chunk", chunk, request.debug);
952
727
  if (request.signal?.aborted) {
@@ -957,22 +732,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
957
732
  if (delta?.content) {
958
733
  yield { type: "message:delta", content: delta.content };
959
734
  }
960
- if (isOpenRouter) {
961
- const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
962
- if (rc) {
963
- const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
964
- if (rcText) {
965
- if (!adapterReasoningStarted) {
966
- yield { type: "thinking:start" };
967
- adapterReasoningStarted = true;
968
- }
969
- yield { type: "thinking:delta", content: rcText };
970
- }
971
- } else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
972
- yield { type: "thinking:end" };
973
- adapterReasoningStarted = false;
974
- }
975
- }
976
735
  const annotations = delta?.annotations;
977
736
  if (annotations && annotations.length > 0) {
978
737
  for (const annotation of annotations) {
@@ -1020,11 +779,6 @@ var OpenAIAdapter = class _OpenAIAdapter {
1020
779
  };
1021
780
  } else if (currentToolCall && toolCall.function?.arguments) {
1022
781
  currentToolCall.arguments += toolCall.function.arguments;
1023
- yield {
1024
- type: "action:args",
1025
- id: currentToolCall.id,
1026
- args: currentToolCall.arguments
1027
- };
1028
782
  }
1029
783
  }
1030
784
  }
@@ -1100,24 +854,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1100
854
  name: openaiToolOptions.toolChoice.name
1101
855
  }
1102
856
  } : openaiToolOptions?.toolChoice;
1103
- const activeModel2 = request.config?.model || this.model;
1104
- const modelSlug2 = activeModel2.replace("openai/", "");
1105
- const isOSeries2 = /^o[1-9]/.test(modelSlug2);
1106
- const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
857
+ const modelIdForCompletePayload = request.config?.model || this.model;
1107
858
  const payload = {
1108
- model: activeModel2,
859
+ model: modelIdForCompletePayload,
1109
860
  messages,
1110
861
  tools: tools.length > 0 ? tools : void 0,
1111
862
  tool_choice: tools.length > 0 ? toolChoice : void 0,
1112
863
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
1113
- stream: false,
1114
- ...isOSeries2 ? {
1115
- max_completion_tokens: maxTokensValue2,
1116
- reasoning_effort: request.config?.reasoningEffort ?? "medium"
1117
- } : {
1118
- temperature: request.config?.temperature ?? this.config.temperature,
1119
- max_tokens: maxTokensValue2
1120
- }
864
+ ...buildOpenAITokenParams(
865
+ modelIdForCompletePayload,
866
+ request.config?.maxTokens ?? this.config.maxTokens,
867
+ request.config?.temperature ?? this.config.temperature
868
+ ),
869
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
870
+ stream: false
1121
871
  };
1122
872
  logProviderPayload("openai", "request payload", payload, request.debug);
1123
873
  const response = await client.chat.completions.create(payload);