@yourgpt/llm-sdk 2.1.8 → 2.1.10-alpha.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 (51) hide show
  1. package/dist/adapters/index.d.mts +38 -4
  2. package/dist/adapters/index.d.ts +38 -4
  3. package/dist/adapters/index.js +318 -8
  4. package/dist/adapters/index.mjs +318 -8
  5. package/dist/{base-iGi9Va6Z.d.ts → base-DN1EfKnE.d.mts} +2 -1
  6. package/dist/{base-D-U61JaB.d.mts → base-DuUNxtVg.d.ts} +2 -1
  7. package/dist/fallback/index.d.mts +4 -4
  8. package/dist/fallback/index.d.ts +4 -4
  9. package/dist/index.d.mts +7 -7
  10. package/dist/index.d.ts +7 -7
  11. package/dist/index.js +43 -23
  12. package/dist/index.mjs +43 -23
  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 +17 -0
  16. package/dist/providers/anthropic/index.mjs +17 -0
  17. package/dist/providers/azure/index.d.mts +3 -3
  18. package/dist/providers/azure/index.d.ts +3 -3
  19. package/dist/providers/fireworks/index.d.mts +1 -1
  20. package/dist/providers/fireworks/index.d.ts +1 -1
  21. package/dist/providers/google/index.d.mts +3 -3
  22. package/dist/providers/google/index.d.ts +3 -3
  23. package/dist/providers/google/index.js +311 -8
  24. package/dist/providers/google/index.mjs +311 -8
  25. package/dist/providers/ollama/index.d.mts +4 -4
  26. package/dist/providers/ollama/index.d.ts +4 -4
  27. package/dist/providers/openai/index.d.mts +3 -3
  28. package/dist/providers/openai/index.d.ts +3 -3
  29. package/dist/providers/openai/index.js +321 -8
  30. package/dist/providers/openai/index.mjs +321 -8
  31. package/dist/providers/openrouter/index.d.mts +7 -3
  32. package/dist/providers/openrouter/index.d.ts +7 -3
  33. package/dist/providers/openrouter/index.js +601 -11
  34. package/dist/providers/openrouter/index.mjs +601 -11
  35. package/dist/providers/togetherai/index.d.mts +61 -2
  36. package/dist/providers/togetherai/index.d.ts +61 -2
  37. package/dist/providers/togetherai/index.js +1030 -2
  38. package/dist/providers/togetherai/index.mjs +1029 -2
  39. package/dist/providers/xai/index.d.mts +3 -3
  40. package/dist/providers/xai/index.d.ts +3 -3
  41. package/dist/providers/xai/index.js +311 -8
  42. package/dist/providers/xai/index.mjs +311 -8
  43. package/dist/{types-D4YfrQJR.d.mts → types-BNCmlJMs.d.mts} +1 -1
  44. package/dist/{types-DRqxMIjF.d.mts → types-CMMQ8s2O.d.mts} +1 -1
  45. package/dist/{types-CR8mi9I0.d.ts → types-CMvvDo-E.d.mts} +12 -1
  46. package/dist/{types-CR8mi9I0.d.mts → types-CMvvDo-E.d.ts} +12 -1
  47. package/dist/{types-BctsnC3g.d.ts → types-DhktekQ3.d.ts} +1 -1
  48. package/dist/{types-38yolWJn.d.ts → types-Pj-vpmoT.d.ts} +1 -1
  49. package/dist/yourgpt/index.d.mts +1 -1
  50. package/dist/yourgpt/index.d.ts +1 -1
  51. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -297,6 +297,20 @@ async function streamText(params) {
297
297
  fullText += chunk.text;
298
298
  yield { type: "text-delta", text: chunk.text };
299
299
  break;
300
+ case "tool-call-start":
301
+ yield {
302
+ type: "tool-call-start",
303
+ toolCallId: chunk.toolCallId,
304
+ toolName: chunk.toolName
305
+ };
306
+ break;
307
+ case "tool-call-delta":
308
+ yield {
309
+ type: "tool-call-delta",
310
+ toolCallId: chunk.toolCallId,
311
+ argsText: chunk.argsText
312
+ };
313
+ break;
300
314
  case "tool-call":
301
315
  toolCalls.push(chunk.toolCall);
302
316
  yield {
@@ -1595,7 +1609,7 @@ var Runtime = class {
1595
1609
  const completionRequest = {
1596
1610
  messages,
1597
1611
  actions: allActions.length > 0 ? allActions : void 0,
1598
- systemPrompt: request.systemPrompt || this.config.systemPrompt,
1612
+ systemPrompt: this.config.systemPrompt ?? request.systemPrompt,
1599
1613
  config: request.config,
1600
1614
  signal,
1601
1615
  webSearch: this.getWebSearchConfig(),
@@ -2159,7 +2173,7 @@ var Runtime = class {
2159
2173
  }
2160
2174
  }
2161
2175
  }
2162
- const systemPrompt = request.systemPrompt || this.config.systemPrompt || "";
2176
+ const systemPrompt = this.config.systemPrompt ?? request.systemPrompt ?? "";
2163
2177
  let accumulatedText = "";
2164
2178
  const toolCalls = [];
2165
2179
  let currentToolCall = null;
@@ -2206,38 +2220,44 @@ var Runtime = class {
2206
2220
  break;
2207
2221
  case "action:args":
2208
2222
  if (currentToolCall) {
2223
+ currentToolCall.args = event.args || currentToolCall.args;
2209
2224
  try {
2210
- const parsedArgs = JSON.parse(event.args || "{}");
2225
+ const parsedArgs = JSON.parse(currentToolCall.args || "{}");
2226
+ const existingIdx = toolCalls.findIndex(
2227
+ (t) => t.id === currentToolCall.id
2228
+ );
2229
+ const entry = {
2230
+ id: currentToolCall.id,
2231
+ name: currentToolCall.name,
2232
+ args: parsedArgs,
2233
+ ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
2234
+ };
2235
+ if (existingIdx >= 0) {
2236
+ toolCalls[existingIdx] = entry;
2237
+ } else {
2238
+ toolCalls.push(entry);
2239
+ }
2211
2240
  if (debug) {
2212
2241
  console.log(
2213
2242
  `[Copilot SDK] Tool args for ${currentToolCall.name}:`,
2214
2243
  parsedArgs
2215
2244
  );
2216
2245
  }
2217
- toolCalls.push({
2218
- id: currentToolCall.id,
2219
- name: currentToolCall.name,
2220
- args: parsedArgs,
2221
- ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
2222
- });
2223
- } catch (e) {
2224
- console.error(
2225
- "[Copilot SDK] Failed to parse tool args:",
2226
- event.args,
2227
- e
2228
- );
2229
- toolCalls.push({
2230
- id: currentToolCall.id,
2231
- name: currentToolCall.name,
2232
- args: {},
2233
- ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
2234
- });
2246
+ } catch {
2247
+ if (!toolCalls.find((t) => t.id === currentToolCall.id)) {
2248
+ toolCalls.push({
2249
+ id: currentToolCall.id,
2250
+ name: currentToolCall.name,
2251
+ args: {},
2252
+ ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
2253
+ });
2254
+ }
2235
2255
  }
2236
- currentToolCall = null;
2237
2256
  }
2238
2257
  yield event;
2239
2258
  break;
2240
2259
  case "action:end": {
2260
+ currentToolCall = null;
2241
2261
  const toolName = event.name;
2242
2262
  const tool2 = toolName ? selectedToolMap.get(toolName) : void 0;
2243
2263
  if (tool2?.location === "server" && tool2.handler) {
@@ -2447,7 +2467,7 @@ var Runtime = class {
2447
2467
  const allTools = this.collectToolsForRequest(request);
2448
2468
  const nativeToolSearch = this.resolveNativeToolSearchForRequest(request);
2449
2469
  let toolSearchState = _toolSearchState;
2450
- const systemPrompt = request.systemPrompt || this.config.systemPrompt || "";
2470
+ const systemPrompt = this.config.systemPrompt ?? request.systemPrompt ?? "";
2451
2471
  let iteration = 0;
2452
2472
  let conversationMessages = request.messages;
2453
2473
  while (iteration < maxIterations) {
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.mjs';
2
- import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-DRqxMIjF.mjs';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.mjs';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-CMMQ8s2O.mjs';
3
3
  import 'zod';
4
- import '../../base-D-U61JaB.mjs';
4
+ import '../../base-DN1EfKnE.mjs';
5
5
 
6
6
  /**
7
7
  * Anthropic Provider - Modern Pattern
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.js';
2
- import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-BctsnC3g.js';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.js';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-DhktekQ3.js';
3
3
  import 'zod';
4
- import '../../base-iGi9Va6Z.js';
4
+ import '../../base-DuUNxtVg.js';
5
5
 
6
6
  /**
7
7
  * Anthropic Provider - Modern Pattern
@@ -197,6 +197,11 @@ function anthropic(modelId, options = {}) {
197
197
  name: event.content_block.name,
198
198
  input: ""
199
199
  };
200
+ yield {
201
+ type: "tool-call-start",
202
+ toolCallId: event.content_block.id,
203
+ toolName: event.content_block.name
204
+ };
200
205
  }
201
206
  break;
202
207
  case "content_block_delta":
@@ -204,6 +209,11 @@ function anthropic(modelId, options = {}) {
204
209
  yield { type: "text-delta", text: event.delta.text };
205
210
  } else if (event.delta?.type === "input_json_delta" && currentToolUse) {
206
211
  currentToolUse.input += event.delta.partial_json;
212
+ yield {
213
+ type: "tool-call-delta",
214
+ toolCallId: currentToolUse.id,
215
+ argsText: currentToolUse.input
216
+ };
207
217
  }
208
218
  break;
209
219
  case "content_block_stop":
@@ -1007,6 +1017,13 @@ var AnthropicAdapter = class {
1007
1017
  yield { type: "thinking:delta", content: event.delta.thinking };
1008
1018
  } else if (event.delta.type === "input_json_delta" && currentToolUse) {
1009
1019
  currentToolUse.input += event.delta.partial_json;
1020
+ if (currentToolUse.name !== "web_search") {
1021
+ yield {
1022
+ type: "action:args",
1023
+ id: currentToolUse.id,
1024
+ args: currentToolUse.input
1025
+ };
1026
+ }
1010
1027
  }
1011
1028
  break;
1012
1029
  case "content_block_stop":
@@ -195,6 +195,11 @@ function anthropic(modelId, options = {}) {
195
195
  name: event.content_block.name,
196
196
  input: ""
197
197
  };
198
+ yield {
199
+ type: "tool-call-start",
200
+ toolCallId: event.content_block.id,
201
+ toolName: event.content_block.name
202
+ };
198
203
  }
199
204
  break;
200
205
  case "content_block_delta":
@@ -202,6 +207,11 @@ function anthropic(modelId, options = {}) {
202
207
  yield { type: "text-delta", text: event.delta.text };
203
208
  } else if (event.delta?.type === "input_json_delta" && currentToolUse) {
204
209
  currentToolUse.input += event.delta.partial_json;
210
+ yield {
211
+ type: "tool-call-delta",
212
+ toolCallId: currentToolUse.id,
213
+ argsText: currentToolUse.input
214
+ };
205
215
  }
206
216
  break;
207
217
  case "content_block_stop":
@@ -1005,6 +1015,13 @@ var AnthropicAdapter = class {
1005
1015
  yield { type: "thinking:delta", content: event.delta.thinking };
1006
1016
  } else if (event.delta.type === "input_json_delta" && currentToolUse) {
1007
1017
  currentToolUse.input += event.delta.partial_json;
1018
+ if (currentToolUse.name !== "web_search") {
1019
+ yield {
1020
+ type: "action:args",
1021
+ id: currentToolUse.id,
1022
+ args: currentToolUse.input
1023
+ };
1024
+ }
1008
1025
  }
1009
1026
  break;
1010
1027
  case "content_block_stop":
@@ -1,6 +1,6 @@
1
- import { b as AzureProviderConfig, A as AIProvider } from '../../types-DRqxMIjF.mjs';
2
- import '../../base-D-U61JaB.mjs';
3
- import '../../types-CR8mi9I0.mjs';
1
+ import { b as AzureProviderConfig, A as AIProvider } from '../../types-CMMQ8s2O.mjs';
2
+ import '../../base-DN1EfKnE.mjs';
3
+ import '../../types-CMvvDo-E.mjs';
4
4
  import 'zod';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
- import { b as AzureProviderConfig, A as AIProvider } from '../../types-BctsnC3g.js';
2
- import '../../base-iGi9Va6Z.js';
3
- import '../../types-CR8mi9I0.js';
1
+ import { b as AzureProviderConfig, A as AIProvider } from '../../types-DhktekQ3.js';
2
+ import '../../base-DuUNxtVg.js';
3
+ import '../../types-CMvvDo-E.js';
4
4
  import 'zod';
5
5
 
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.mjs';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.mjs';
2
2
  import 'zod';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.js';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.mjs';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-DRqxMIjF.mjs';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.mjs';
2
+ import { G as GoogleProviderConfig, A as AIProvider } from '../../types-CMMQ8s2O.mjs';
3
3
  import 'zod';
4
- import '../../base-D-U61JaB.mjs';
4
+ import '../../base-DN1EfKnE.mjs';
5
5
 
6
6
  /**
7
7
  * Google Provider - OpenAI-Compatible
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-CR8mi9I0.js';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-BctsnC3g.js';
1
+ import { L as LanguageModel } from '../../types-CMvvDo-E.js';
2
+ import { G as GoogleProviderConfig, A as AIProvider } from '../../types-DhktekQ3.js';
3
3
  import 'zod';
4
- import '../../base-iGi9Va6Z.js';
4
+ import '../../base-DuUNxtVg.js';
5
5
 
6
6
  /**
7
7
  * Google Provider - OpenAI-Compatible
@@ -506,6 +506,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
506
506
  if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
507
507
  if (baseUrl.includes("x.ai")) return "xai";
508
508
  if (baseUrl.includes("azure")) return "azure";
509
+ if (baseUrl.includes("openrouter.ai")) return "openrouter";
509
510
  return "openai";
510
511
  }
511
512
  async getClient() {
@@ -605,6 +606,256 @@ var OpenAIAdapter = class _OpenAIAdapter {
605
606
  rawResponse: response
606
607
  };
607
608
  }
609
+ /**
610
+ * OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
611
+ * reasoning content on the chat-completions endpoint. To surface reasoning
612
+ * SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
613
+ * Responses API, which streams `response.reasoning_summary_text.delta` events.
614
+ *
615
+ * Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
616
+ * openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
617
+ */
618
+ isOpenAIReasoningModelOnOpenRouter(activeModel) {
619
+ if (this.provider !== "openrouter") return false;
620
+ return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
621
+ }
622
+ /**
623
+ * Convert ActionDefinition[] (the chat-completions tool shape used by the
624
+ * adapter) to the Responses API tool shape.
625
+ */
626
+ buildResponsesToolsFromActions(actions) {
627
+ if (!actions || actions.length === 0) return void 0;
628
+ const formatted = formatTools(actions);
629
+ return formatted.map((t) => ({
630
+ type: "function",
631
+ name: t.function.name,
632
+ description: t.function.description,
633
+ parameters: t.function.parameters
634
+ }));
635
+ }
636
+ /**
637
+ * Streaming Responses API path for OpenAI reasoning models on OpenRouter.
638
+ *
639
+ * Maps Responses API SSE events back to the same StreamEvent shapes the
640
+ * chat-completions path emits, so downstream consumers (processChunk.ts,
641
+ * frontend tool handlers, plan approval, specialist delegations) see
642
+ * identical events regardless of which path produced them.
643
+ *
644
+ * response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
645
+ * response.output_text.delta → message:delta
646
+ * response.output_item.added (function_call) → action:start (queued buffer)
647
+ * response.function_call_arguments.delta → action:args (progressive)
648
+ * response.output_item.done (function_call) → final action:args + action:end
649
+ * response.completed → message:end + done(usage)
650
+ * response.error → error
651
+ */
652
+ async *streamWithResponsesAPI(request, activeModel, messageId) {
653
+ const client = await this.getClient();
654
+ const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
655
+ const payload = {
656
+ model: activeModel,
657
+ input: this.buildResponsesInput(request),
658
+ stream: true,
659
+ reasoning: {
660
+ effort: request.config?.reasoningEffort ?? "medium",
661
+ summary: "auto"
662
+ }
663
+ };
664
+ if (request.systemPrompt) payload.instructions = request.systemPrompt;
665
+ if (typeof maxTokensValue === "number")
666
+ payload.max_output_tokens = maxTokensValue;
667
+ const tools = this.buildResponsesToolsFromActions(request.actions);
668
+ if (tools && tools.length > 0) payload.tools = tools;
669
+ logProviderPayload(
670
+ "openai",
671
+ "responses-api request payload",
672
+ payload,
673
+ request.debug
674
+ );
675
+ let stream;
676
+ try {
677
+ stream = await client.responses.create(payload);
678
+ } catch (error) {
679
+ yield {
680
+ type: "error",
681
+ message: error instanceof Error ? error.message : "Unknown error",
682
+ code: "OPENAI_RESPONSES_ERROR"
683
+ };
684
+ return;
685
+ }
686
+ const toolBuffers = /* @__PURE__ */ new Map();
687
+ const itemIdToCallId = /* @__PURE__ */ new Map();
688
+ let usage;
689
+ let reasoningStarted = false;
690
+ let textStarted = false;
691
+ let finishEmitted = false;
692
+ const resolveCallId = (evt) => {
693
+ if (evt?.call_id) return evt.call_id;
694
+ if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
695
+ if (evt?.item?.call_id) return evt.item.call_id;
696
+ if (evt?.item?.id) return evt.item.id;
697
+ return "";
698
+ };
699
+ try {
700
+ for await (const evt of stream) {
701
+ logProviderPayload(
702
+ "openai",
703
+ "responses-api stream chunk",
704
+ evt,
705
+ request.debug
706
+ );
707
+ if (request.signal?.aborted) break;
708
+ const t = evt?.type ?? "";
709
+ if (t === "response.reasoning_summary_text.delta") {
710
+ const delta = evt.delta ?? "";
711
+ if (!delta) continue;
712
+ if (!reasoningStarted) {
713
+ yield { type: "thinking:start" };
714
+ reasoningStarted = true;
715
+ }
716
+ yield { type: "thinking:delta", content: delta };
717
+ continue;
718
+ }
719
+ if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
720
+ continue;
721
+ }
722
+ if (t === "response.output_text.delta") {
723
+ const text = evt.delta ?? "";
724
+ if (!text) continue;
725
+ if (reasoningStarted && !textStarted) {
726
+ yield { type: "thinking:end" };
727
+ textStarted = true;
728
+ }
729
+ yield { type: "message:delta", content: text };
730
+ continue;
731
+ }
732
+ if (t === "response.output_item.added") {
733
+ const item = evt.item;
734
+ if (item?.type === "function_call") {
735
+ const callId = item.call_id ?? item.id ?? "";
736
+ const itemId = item.id ?? callId;
737
+ if (callId) {
738
+ if (itemId && itemId !== callId) {
739
+ itemIdToCallId.set(itemId, callId);
740
+ }
741
+ if (!toolBuffers.has(callId)) {
742
+ toolBuffers.set(callId, {
743
+ id: callId,
744
+ name: item.name ?? "",
745
+ arguments: item.arguments ?? "",
746
+ emittedStart: false
747
+ });
748
+ }
749
+ const buf = toolBuffers.get(callId);
750
+ if (buf.name && !buf.emittedStart) {
751
+ yield { type: "action:start", id: buf.id, name: buf.name };
752
+ buf.emittedStart = true;
753
+ }
754
+ }
755
+ }
756
+ continue;
757
+ }
758
+ if (t === "response.function_call_arguments.delta") {
759
+ const callId = resolveCallId(evt);
760
+ const delta = evt.delta ?? "";
761
+ if (!callId || !delta) continue;
762
+ let buf = toolBuffers.get(callId);
763
+ if (!buf) {
764
+ buf = { id: callId, name: "", arguments: "", emittedStart: false };
765
+ toolBuffers.set(callId, buf);
766
+ }
767
+ buf.arguments += delta;
768
+ if (buf.emittedStart) {
769
+ yield {
770
+ type: "action:args",
771
+ id: buf.id,
772
+ args: buf.arguments
773
+ };
774
+ }
775
+ continue;
776
+ }
777
+ if (t === "response.output_item.done") {
778
+ const item = evt.item;
779
+ if (item?.type === "function_call") {
780
+ const callId = item.call_id ?? item.id ?? "";
781
+ const buf = toolBuffers.get(callId);
782
+ const name = buf?.name || item.name || "";
783
+ const argsStr = buf?.arguments || item.arguments || "{}";
784
+ if (callId && name) {
785
+ if (!buf?.emittedStart) {
786
+ yield { type: "action:start", id: callId, name };
787
+ }
788
+ yield {
789
+ type: "action:args",
790
+ id: callId,
791
+ args: argsStr
792
+ };
793
+ yield {
794
+ type: "action:end",
795
+ id: callId,
796
+ name
797
+ };
798
+ }
799
+ toolBuffers.delete(callId);
800
+ }
801
+ continue;
802
+ }
803
+ if (t === "response.completed") {
804
+ const u = evt.response?.usage;
805
+ if (u) {
806
+ usage = {
807
+ prompt_tokens: u.input_tokens ?? 0,
808
+ completion_tokens: u.output_tokens ?? 0,
809
+ total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
810
+ };
811
+ }
812
+ for (const buf of toolBuffers.values()) {
813
+ if (!buf.id || !buf.name) continue;
814
+ if (!buf.emittedStart) {
815
+ yield { type: "action:start", id: buf.id, name: buf.name };
816
+ }
817
+ yield {
818
+ type: "action:args",
819
+ id: buf.id,
820
+ args: buf.arguments || "{}"
821
+ };
822
+ yield { type: "action:end", id: buf.id, name: buf.name };
823
+ }
824
+ toolBuffers.clear();
825
+ if (reasoningStarted && !textStarted) {
826
+ yield { type: "thinking:end" };
827
+ }
828
+ yield { type: "message:end" };
829
+ yield { type: "done", usage };
830
+ finishEmitted = true;
831
+ continue;
832
+ }
833
+ if (t === "response.error" || t === "error") {
834
+ const msg = evt.error?.message || evt.message || "Responses API error";
835
+ yield {
836
+ type: "error",
837
+ message: msg,
838
+ code: "OPENAI_RESPONSES_ERROR"
839
+ };
840
+ return;
841
+ }
842
+ }
843
+ } catch (error) {
844
+ yield {
845
+ type: "error",
846
+ message: error instanceof Error ? error.message : "Unknown error",
847
+ code: "OPENAI_RESPONSES_ERROR"
848
+ };
849
+ return;
850
+ }
851
+ if (!finishEmitted) {
852
+ if (reasoningStarted && !textStarted) {
853
+ yield { type: "thinking:end" };
854
+ }
855
+ yield { type: "message:end" };
856
+ yield { type: "done", usage };
857
+ }
858
+ }
608
859
  async completeWithResponses(request) {
609
860
  const client = await this.getClient();
610
861
  const openaiToolOptions = request.providerToolOptions?.openai;
@@ -738,16 +989,37 @@ var OpenAIAdapter = class _OpenAIAdapter {
738
989
  name: openaiToolOptions.toolChoice.name
739
990
  }
740
991
  } : openaiToolOptions?.toolChoice;
992
+ const isOpenRouter = this.provider === "openrouter";
993
+ const activeModel = request.config?.model || this.model;
994
+ const modelSlug = activeModel.replace("openai/", "");
995
+ const isOSeries = /^o[1-9]/.test(modelSlug);
996
+ const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
997
+ if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
998
+ yield* this.streamWithResponsesAPI(request, activeModel, messageId);
999
+ return;
1000
+ }
1001
+ const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
741
1002
  const payload = {
742
- model: request.config?.model || this.model,
1003
+ model: activeModel,
743
1004
  messages,
744
1005
  tools: tools.length > 0 ? tools : void 0,
745
1006
  tool_choice: tools.length > 0 ? toolChoice : void 0,
746
1007
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
747
- temperature: request.config?.temperature ?? this.config.temperature,
748
- max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
749
1008
  stream: true,
750
- stream_options: { include_usage: true }
1009
+ stream_options: { include_usage: true },
1010
+ // o-series: use max_completion_tokens + reasoning_effort, no temperature
1011
+ // regular models: use max_tokens + temperature
1012
+ ...isOSeries ? {
1013
+ max_completion_tokens: maxTokensValue,
1014
+ reasoning_effort: request.config?.reasoningEffort ?? "medium"
1015
+ } : {
1016
+ temperature: request.config?.temperature ?? this.config.temperature,
1017
+ max_tokens: maxTokensValue
1018
+ },
1019
+ // Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
1020
+ // When disableThinking=true we must explicitly send include_reasoning:false because
1021
+ // models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
1022
+ ...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
751
1023
  };
752
1024
  logProviderPayload("openai", "request payload", payload, request.debug);
753
1025
  const stream = await client.chat.completions.create(payload);
@@ -755,6 +1027,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
755
1027
  const collectedCitations = [];
756
1028
  let citationIndex = 0;
757
1029
  let usage;
1030
+ let adapterReasoningStarted = false;
758
1031
  for await (const chunk of stream) {
759
1032
  logProviderPayload("openai", "stream chunk", chunk, request.debug);
760
1033
  if (request.signal?.aborted) {
@@ -765,6 +1038,22 @@ var OpenAIAdapter = class _OpenAIAdapter {
765
1038
  if (delta?.content) {
766
1039
  yield { type: "message:delta", content: delta.content };
767
1040
  }
1041
+ if (isOpenRouter) {
1042
+ const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
1043
+ if (rc) {
1044
+ const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
1045
+ if (rcText) {
1046
+ if (!adapterReasoningStarted) {
1047
+ yield { type: "thinking:start" };
1048
+ adapterReasoningStarted = true;
1049
+ }
1050
+ yield { type: "thinking:delta", content: rcText };
1051
+ }
1052
+ } else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
1053
+ yield { type: "thinking:end" };
1054
+ adapterReasoningStarted = false;
1055
+ }
1056
+ }
768
1057
  const annotations = delta?.annotations;
769
1058
  if (annotations && annotations.length > 0) {
770
1059
  for (const annotation of annotations) {
@@ -812,6 +1101,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
812
1101
  };
813
1102
  } else if (currentToolCall && toolCall.function?.arguments) {
814
1103
  currentToolCall.arguments += toolCall.function.arguments;
1104
+ yield {
1105
+ type: "action:args",
1106
+ id: currentToolCall.id,
1107
+ args: currentToolCall.arguments
1108
+ };
815
1109
  }
816
1110
  }
817
1111
  }
@@ -887,15 +1181,24 @@ var OpenAIAdapter = class _OpenAIAdapter {
887
1181
  name: openaiToolOptions.toolChoice.name
888
1182
  }
889
1183
  } : openaiToolOptions?.toolChoice;
1184
+ const activeModel2 = request.config?.model || this.model;
1185
+ const modelSlug2 = activeModel2.replace("openai/", "");
1186
+ const isOSeries2 = /^o[1-9]/.test(modelSlug2);
1187
+ const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
890
1188
  const payload = {
891
- model: request.config?.model || this.model,
1189
+ model: activeModel2,
892
1190
  messages,
893
1191
  tools: tools.length > 0 ? tools : void 0,
894
1192
  tool_choice: tools.length > 0 ? toolChoice : void 0,
895
1193
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
896
- temperature: request.config?.temperature ?? this.config.temperature,
897
- max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
898
- stream: false
1194
+ stream: false,
1195
+ ...isOSeries2 ? {
1196
+ max_completion_tokens: maxTokensValue2,
1197
+ reasoning_effort: request.config?.reasoningEffort ?? "medium"
1198
+ } : {
1199
+ temperature: request.config?.temperature ?? this.config.temperature,
1200
+ max_tokens: maxTokensValue2
1201
+ }
899
1202
  };
900
1203
  logProviderPayload("openai", "request payload", payload, request.debug);
901
1204
  const response = await client.chat.completions.create(payload);