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