@aituber-onair/chat 0.36.0 → 0.38.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 (83) hide show
  1. package/README.ja.md +49 -5
  2. package/README.md +49 -7
  3. package/dist/cjs/constants/gemini.d.ts +0 -7
  4. package/dist/cjs/constants/gemini.d.ts.map +1 -1
  5. package/dist/cjs/constants/gemini.js +1 -10
  6. package/dist/cjs/constants/gemini.js.map +1 -1
  7. package/dist/cjs/constants/openai.d.ts +2 -1
  8. package/dist/cjs/constants/openai.d.ts.map +1 -1
  9. package/dist/cjs/constants/openai.js +3 -4
  10. package/dist/cjs/constants/openai.js.map +1 -1
  11. package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts +5 -0
  12. package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  13. package/dist/cjs/services/providers/gemini/GeminiChatService.js +22 -6
  14. package/dist/cjs/services/providers/gemini/GeminiChatService.js.map +1 -1
  15. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.d.ts +6 -0
  16. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  17. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js +17 -7
  18. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  19. package/dist/cjs/services/providers/openai/responsesParser.d.ts +7 -2
  20. package/dist/cjs/services/providers/openai/responsesParser.d.ts.map +1 -1
  21. package/dist/cjs/services/providers/openai/responsesParser.js +9 -7
  22. package/dist/cjs/services/providers/openai/responsesParser.js.map +1 -1
  23. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.d.ts.map +1 -1
  24. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.js +7 -5
  25. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.js.map +1 -1
  26. package/dist/cjs/utils/index.d.ts +1 -0
  27. package/dist/cjs/utils/index.d.ts.map +1 -1
  28. package/dist/cjs/utils/index.js +1 -0
  29. package/dist/cjs/utils/index.js.map +1 -1
  30. package/dist/cjs/utils/mcpSchemaFetcher.d.ts +20 -0
  31. package/dist/cjs/utils/mcpSchemaFetcher.d.ts.map +1 -1
  32. package/dist/cjs/utils/mcpSchemaFetcher.js +60 -44
  33. package/dist/cjs/utils/mcpSchemaFetcher.js.map +1 -1
  34. package/dist/cjs/utils/openaiCompatibleSse.d.ts +3 -2
  35. package/dist/cjs/utils/openaiCompatibleSse.d.ts.map +1 -1
  36. package/dist/cjs/utils/openaiCompatibleSse.js +4 -3
  37. package/dist/cjs/utils/openaiCompatibleSse.js.map +1 -1
  38. package/dist/cjs/utils/safeJsonParse.d.ts +4 -0
  39. package/dist/cjs/utils/safeJsonParse.d.ts.map +1 -0
  40. package/dist/cjs/utils/safeJsonParse.js +21 -0
  41. package/dist/cjs/utils/safeJsonParse.js.map +1 -0
  42. package/dist/esm/constants/gemini.d.ts +0 -7
  43. package/dist/esm/constants/gemini.d.ts.map +1 -1
  44. package/dist/esm/constants/gemini.js +0 -9
  45. package/dist/esm/constants/gemini.js.map +1 -1
  46. package/dist/esm/constants/openai.d.ts +2 -1
  47. package/dist/esm/constants/openai.d.ts.map +1 -1
  48. package/dist/esm/constants/openai.js +3 -4
  49. package/dist/esm/constants/openai.js.map +1 -1
  50. package/dist/esm/services/providers/gemini/GeminiChatService.d.ts +5 -0
  51. package/dist/esm/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  52. package/dist/esm/services/providers/gemini/GeminiChatService.js +22 -6
  53. package/dist/esm/services/providers/gemini/GeminiChatService.js.map +1 -1
  54. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.d.ts +6 -0
  55. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  56. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js +17 -7
  57. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  58. package/dist/esm/services/providers/openai/responsesParser.d.ts +7 -2
  59. package/dist/esm/services/providers/openai/responsesParser.d.ts.map +1 -1
  60. package/dist/esm/services/providers/openai/responsesParser.js +9 -7
  61. package/dist/esm/services/providers/openai/responsesParser.js.map +1 -1
  62. package/dist/esm/services/providers/openrouter/OpenRouterChatService.d.ts.map +1 -1
  63. package/dist/esm/services/providers/openrouter/OpenRouterChatService.js +7 -5
  64. package/dist/esm/services/providers/openrouter/OpenRouterChatService.js.map +1 -1
  65. package/dist/esm/utils/index.d.ts +1 -0
  66. package/dist/esm/utils/index.d.ts.map +1 -1
  67. package/dist/esm/utils/index.js +1 -0
  68. package/dist/esm/utils/index.js.map +1 -1
  69. package/dist/esm/utils/mcpSchemaFetcher.d.ts +20 -0
  70. package/dist/esm/utils/mcpSchemaFetcher.d.ts.map +1 -1
  71. package/dist/esm/utils/mcpSchemaFetcher.js +60 -44
  72. package/dist/esm/utils/mcpSchemaFetcher.js.map +1 -1
  73. package/dist/esm/utils/openaiCompatibleSse.d.ts +3 -2
  74. package/dist/esm/utils/openaiCompatibleSse.d.ts.map +1 -1
  75. package/dist/esm/utils/openaiCompatibleSse.js +4 -3
  76. package/dist/esm/utils/openaiCompatibleSse.js.map +1 -1
  77. package/dist/esm/utils/safeJsonParse.d.ts +4 -0
  78. package/dist/esm/utils/safeJsonParse.d.ts.map +1 -0
  79. package/dist/esm/utils/safeJsonParse.js +16 -0
  80. package/dist/esm/utils/safeJsonParse.js.map +1 -0
  81. package/dist/umd/aituber-onair-chat.js +143 -79
  82. package/dist/umd/aituber-onair-chat.min.js +10 -10
  83. package/package.json +1 -1
@@ -91,8 +91,6 @@ var AITuberOnAirChat = (() => {
91
91
  MODEL_DEEPSEEK_REASONER: () => MODEL_DEEPSEEK_REASONER,
92
92
  MODEL_DEEPSEEK_V4_FLASH: () => MODEL_DEEPSEEK_V4_FLASH,
93
93
  MODEL_DEEPSEEK_V4_PRO: () => MODEL_DEEPSEEK_V4_PRO,
94
- MODEL_GEMINI_2_0_FLASH: () => MODEL_GEMINI_2_0_FLASH,
95
- MODEL_GEMINI_2_0_FLASH_LITE: () => MODEL_GEMINI_2_0_FLASH_LITE,
96
94
  MODEL_GEMINI_2_5_FLASH: () => MODEL_GEMINI_2_5_FLASH,
97
95
  MODEL_GEMINI_2_5_FLASH_LITE: () => MODEL_GEMINI_2_5_FLASH_LITE,
98
96
  MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17: () => MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17,
@@ -215,6 +213,8 @@ var AITuberOnAirChat = (() => {
215
213
  refreshOpenRouterFreeModels: () => refreshOpenRouterFreeModels,
216
214
  resolveVisionModel: () => resolveVisionModel,
217
215
  runOnceText: () => runOnceText,
216
+ safeJsonParse: () => safeJsonParse,
217
+ safeParseToolCallInput: () => safeParseToolCallInput,
218
218
  screenplayToText: () => screenplayToText,
219
219
  textToScreenplay: () => textToScreenplay,
220
220
  textsToScreenplay: () => textsToScreenplay
@@ -288,7 +288,7 @@ var AITuberOnAirChat = (() => {
288
288
  return model !== MODEL_GPT_5_4_PRO;
289
289
  }
290
290
  function getDefaultReasoningEffortForGPT5Model(model) {
291
- if (model === MODEL_GPT_5_1 || model === MODEL_GPT_5_4 || model === MODEL_GPT_5_5) {
291
+ if (allowsReasoningNone(model)) {
292
292
  return "none";
293
293
  }
294
294
  return "medium";
@@ -308,8 +308,6 @@ var AITuberOnAirChat = (() => {
308
308
  var MODEL_GEMINI_2_5_FLASH = "gemini-2.5-flash";
309
309
  var MODEL_GEMINI_2_5_FLASH_LITE = "gemini-2.5-flash-lite";
310
310
  var MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17 = "gemini-2.5-flash-lite-preview-06-17";
311
- var MODEL_GEMINI_2_0_FLASH = "gemini-2.0-flash";
312
- var MODEL_GEMINI_2_0_FLASH_LITE = "gemini-2.0-flash-lite";
313
311
  var GEMINI_RECOMMENDED_MODELS = [
314
312
  MODEL_GEMINI_3_5_FLASH,
315
313
  MODEL_GEMINI_3_1_FLASH_LITE,
@@ -324,9 +322,7 @@ var AITuberOnAirChat = (() => {
324
322
  var GEMINI_DEPRECATED_MODELS = [
325
323
  MODEL_GEMINI_3_1_FLASH_LITE_PREVIEW,
326
324
  MODEL_GEMINI_3_PRO_PREVIEW,
327
- MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17,
328
- MODEL_GEMINI_2_0_FLASH,
329
- MODEL_GEMINI_2_0_FLASH_LITE
325
+ MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17
330
326
  ];
331
327
  var GEMINI_VISION_SUPPORTED_MODELS = [
332
328
  ...GEMINI_RECOMMENDED_MODELS,
@@ -842,6 +838,22 @@ If it's in another language, summarize in that language.
842
838
  return StreamTextAccumulator.getFullText(blocks);
843
839
  }
844
840
 
841
+ // src/utils/safeJsonParse.ts
842
+ var safeJsonParse = (payload, fallback, onJsonError) => {
843
+ try {
844
+ return JSON.parse(payload);
845
+ } catch (error) {
846
+ onJsonError?.(payload, error);
847
+ return fallback;
848
+ }
849
+ };
850
+ var safeParseToolCallInput = (payload, onJsonError) => {
851
+ if (!payload) {
852
+ return {};
853
+ }
854
+ return safeJsonParse(payload, {}, onJsonError);
855
+ };
856
+
845
857
  // src/utils/openaiCompatibleSse.ts
846
858
  var parseJsonPayload = (payload, onJsonError) => {
847
859
  try {
@@ -949,7 +961,7 @@ If it's in another language, summarize in that language.
949
961
  type: "tool_use",
950
962
  id: e.id,
951
963
  name: e.name,
952
- input: JSON.parse(e.args || "{}")
964
+ input: safeParseToolCallInput(e.args, options.onJsonError)
953
965
  }));
954
966
  const blocks = [...textBlocks, ...toolBlocks];
955
967
  return {
@@ -960,7 +972,7 @@ If it's in another language, summarize in that language.
960
972
  usage
961
973
  };
962
974
  }
963
- function parseOpenAICompatibleOneShot(data) {
975
+ function parseOpenAICompatibleOneShot(data, options = {}) {
964
976
  const choice = data?.choices?.[0];
965
977
  const blocks = [];
966
978
  if (choice?.message?.tool_calls?.length) {
@@ -969,7 +981,10 @@ If it's in another language, summarize in that language.
969
981
  type: "tool_use",
970
982
  id: c.id,
971
983
  name: c.function?.name,
972
- input: JSON.parse(c.function?.arguments || "{}")
984
+ input: safeParseToolCallInput(
985
+ c.function?.arguments,
986
+ options.onJsonError
987
+ )
973
988
  })
974
989
  );
975
990
  } else {
@@ -1761,7 +1776,7 @@ If it's in another language, summarize in that language.
1761
1776
  };
1762
1777
 
1763
1778
  // src/services/providers/openai/responsesParser.ts
1764
- async function parseOpenAIResponsesStream(res, onPartial) {
1779
+ async function parseOpenAIResponsesStream(res, onPartial, options = {}) {
1765
1780
  const reader = res.body.getReader();
1766
1781
  const dec = new TextDecoder();
1767
1782
  const textBlocks = [];
@@ -1793,6 +1808,7 @@ If it's in another language, summarize in that language.
1793
1808
  onPartial,
1794
1809
  textBlocks,
1795
1810
  toolCallsMap,
1811
+ options,
1796
1812
  (metadata) => {
1797
1813
  if (metadata.responseStatus !== void 0) {
1798
1814
  responseStatus = metadata.responseStatus;
@@ -1805,7 +1821,8 @@ If it's in another language, summarize in that language.
1805
1821
  }
1806
1822
  }
1807
1823
  );
1808
- } catch {
1824
+ } catch (error) {
1825
+ options.onJsonError?.(eventData, error);
1809
1826
  console.warn("Failed to parse SSE data:", eventData);
1810
1827
  }
1811
1828
  eventType = "";
@@ -1830,7 +1847,7 @@ If it's in another language, summarize in that language.
1830
1847
  usage
1831
1848
  };
1832
1849
  }
1833
- function handleResponsesSSEEvent(eventType, data, onPartial, textBlocks, toolCallsMap, onMetadata) {
1850
+ function handleResponsesSSEEvent(eventType, data, onPartial, textBlocks, toolCallsMap, options, onMetadata) {
1834
1851
  switch (eventType) {
1835
1852
  case "response.output_item.added":
1836
1853
  if (data.item?.type === "message" && Array.isArray(data.item.content)) {
@@ -1844,7 +1861,10 @@ If it's in another language, summarize in that language.
1844
1861
  toolCallsMap.set(data.item.id, {
1845
1862
  id: data.item.id,
1846
1863
  name: data.item.name,
1847
- input: data.item.arguments ? JSON.parse(data.item.arguments) : {}
1864
+ input: safeParseToolCallInput(
1865
+ data.item.arguments,
1866
+ options.onJsonError
1867
+ )
1848
1868
  });
1849
1869
  }
1850
1870
  break;
@@ -1887,7 +1907,7 @@ If it's in another language, summarize in that language.
1887
1907
  usage: response?.usage
1888
1908
  };
1889
1909
  }
1890
- function parseOpenAIResponsesOneShot(data) {
1910
+ function parseOpenAIResponsesOneShot(data, options = {}) {
1891
1911
  const blocks = [];
1892
1912
  if (data.output && Array.isArray(data.output)) {
1893
1913
  data.output.forEach((outputItem) => {
@@ -1903,7 +1923,10 @@ If it's in another language, summarize in that language.
1903
1923
  type: "tool_use",
1904
1924
  id: outputItem.id,
1905
1925
  name: outputItem.name,
1906
- input: outputItem.arguments ? JSON.parse(outputItem.arguments) : {}
1926
+ input: safeParseToolCallInput(
1927
+ outputItem.arguments,
1928
+ options.onJsonError
1929
+ )
1907
1930
  });
1908
1931
  }
1909
1932
  });
@@ -2420,6 +2443,20 @@ If it's in another language, summarize in that language.
2420
2443
  };
2421
2444
 
2422
2445
  // src/utils/mcpSchemaFetcher.ts
2446
+ var createGenericSearchTool = (serverConfig, reason) => ({
2447
+ name: `mcp_${serverConfig.name}_search`,
2448
+ description: reason === "schema-fetch-failed" ? `Search using ${serverConfig.name} MCP server (schema fetch failed)` : `Search using ${serverConfig.name} MCP server`,
2449
+ parameters: {
2450
+ type: "object",
2451
+ properties: {
2452
+ query: {
2453
+ type: "string",
2454
+ description: "Search query"
2455
+ }
2456
+ },
2457
+ required: ["query"]
2458
+ }
2459
+ });
2423
2460
  var MCPSchemaFetcher = class {
2424
2461
  /**
2425
2462
  * Fetch tool schemas from MCP server
@@ -2427,6 +2464,15 @@ If it's in another language, summarize in that language.
2427
2464
  * @returns Array of tool definitions
2428
2465
  */
2429
2466
  static async fetchToolSchemas(serverConfig) {
2467
+ const result = await this.fetchToolSchemasWithStatus(serverConfig);
2468
+ return result.schemas;
2469
+ }
2470
+ /**
2471
+ * Fetch tool schemas from MCP server with failure metadata.
2472
+ * @param serverConfig MCP server configuration
2473
+ * @returns Tool schemas and failure metadata if fallback was used
2474
+ */
2475
+ static async fetchToolSchemasWithStatus(serverConfig) {
2430
2476
  try {
2431
2477
  const headers = {
2432
2478
  "Content-Type": "application/json"
@@ -2441,53 +2487,32 @@ If it's in another language, summarize in that language.
2441
2487
  );
2442
2488
  const toolsData = await response.json();
2443
2489
  if (Array.isArray(toolsData.tools)) {
2444
- return toolsData.tools.map((tool) => ({
2445
- name: `mcp_${serverConfig.name}_${tool.name}`,
2446
- description: tool.description || `Tool from ${serverConfig.name} MCP server`,
2447
- parameters: tool.inputSchema || {
2448
- type: "object",
2449
- properties: {},
2450
- required: []
2451
- }
2452
- }));
2490
+ return {
2491
+ schemas: toolsData.tools.map((tool) => ({
2492
+ name: `mcp_${serverConfig.name}_${tool.name}`,
2493
+ description: tool.description || `Tool from ${serverConfig.name} MCP server`,
2494
+ parameters: tool.inputSchema || {
2495
+ type: "object",
2496
+ properties: {},
2497
+ required: []
2498
+ }
2499
+ })),
2500
+ failures: []
2501
+ };
2453
2502
  }
2454
- return [
2455
- {
2456
- name: `mcp_${serverConfig.name}_search`,
2457
- description: `Search using ${serverConfig.name} MCP server`,
2458
- parameters: {
2459
- type: "object",
2460
- properties: {
2461
- query: {
2462
- type: "string",
2463
- description: "Search query"
2464
- }
2465
- },
2466
- required: ["query"]
2467
- }
2468
- }
2469
- ];
2503
+ return {
2504
+ schemas: [createGenericSearchTool(serverConfig)],
2505
+ failures: []
2506
+ };
2470
2507
  } catch (error) {
2471
2508
  console.warn(
2472
2509
  `Failed to fetch MCP schemas from ${serverConfig.name}:`,
2473
2510
  error
2474
2511
  );
2475
- return [
2476
- {
2477
- name: `mcp_${serverConfig.name}_search`,
2478
- description: `Search using ${serverConfig.name} MCP server (schema fetch failed)`,
2479
- parameters: {
2480
- type: "object",
2481
- properties: {
2482
- query: {
2483
- type: "string",
2484
- description: "Search query"
2485
- }
2486
- },
2487
- required: ["query"]
2488
- }
2489
- }
2490
- ];
2512
+ return {
2513
+ schemas: [createGenericSearchTool(serverConfig, "schema-fetch-failed")],
2514
+ failures: [{ server: serverConfig, error }]
2515
+ };
2491
2516
  }
2492
2517
  }
2493
2518
  /**
@@ -2496,16 +2521,28 @@ If it's in another language, summarize in that language.
2496
2521
  * @returns Array of all tool definitions
2497
2522
  */
2498
2523
  static async fetchAllToolSchemas(mcpServers) {
2524
+ const result = await this.fetchAllToolSchemasWithStatus(mcpServers);
2525
+ return result.schemas;
2526
+ }
2527
+ /**
2528
+ * Fetch all tool schemas from multiple MCP servers with failure metadata.
2529
+ * @param mcpServers Array of MCP server configurations
2530
+ * @returns Array of all tool definitions and failures
2531
+ */
2532
+ static async fetchAllToolSchemasWithStatus(mcpServers) {
2499
2533
  const allSchemas = [];
2534
+ const failures = [];
2500
2535
  for (const server of mcpServers) {
2501
2536
  try {
2502
- const schemas = await this.fetchToolSchemas(server);
2503
- allSchemas.push(...schemas);
2537
+ const result = await this.fetchToolSchemasWithStatus(server);
2538
+ allSchemas.push(...result.schemas);
2539
+ failures.push(...result.failures);
2504
2540
  } catch (error) {
2505
2541
  console.error(`Failed to fetch schemas from ${server.name}:`, error);
2542
+ failures.push({ server, error });
2506
2543
  }
2507
2544
  }
2508
- return allSchemas;
2545
+ return { schemas: allSchemas, failures };
2509
2546
  }
2510
2547
  };
2511
2548
 
@@ -2561,7 +2598,7 @@ If it's in another language, summarize in that language.
2561
2598
  {
2562
2599
  functionResponse: {
2563
2600
  name: funcName,
2564
- response: normalizeToolResult(safeJsonParse(msg.content))
2601
+ response: normalizeToolResult(safeJsonParse2(msg.content))
2565
2602
  }
2566
2603
  }
2567
2604
  ]
@@ -2608,7 +2645,7 @@ If it's in another language, summarize in that language.
2608
2645
  functionResponse: {
2609
2646
  name: funcName,
2610
2647
  response: normalizeToolResult(
2611
- safeJsonParse(msg.content)
2648
+ safeJsonParse2(msg.content)
2612
2649
  )
2613
2650
  }
2614
2651
  }
@@ -2657,7 +2694,7 @@ If it's in another language, summarize in that language.
2657
2694
  }
2658
2695
  return geminiMessages;
2659
2696
  }
2660
- function safeJsonParse(str) {
2697
+ function safeJsonParse2(str) {
2661
2698
  try {
2662
2699
  return JSON.parse(str);
2663
2700
  } catch {
@@ -2816,6 +2853,7 @@ If it's in another language, summarize in that language.
2816
2853
  addMCPServer(serverConfig) {
2817
2854
  this.mcpServers.push(serverConfig);
2818
2855
  this.mcpSchemasInitialized = false;
2856
+ this.mcpSchemaInitializationError = void 0;
2819
2857
  }
2820
2858
  /**
2821
2859
  * Remove MCP server by name
@@ -2826,6 +2864,7 @@ If it's in another language, summarize in that language.
2826
2864
  (server) => server.name !== serverName
2827
2865
  );
2828
2866
  this.mcpSchemasInitialized = false;
2867
+ this.mcpSchemaInitializationError = void 0;
2829
2868
  }
2830
2869
  /**
2831
2870
  * Check if MCP servers are configured
@@ -2834,6 +2873,12 @@ If it's in another language, summarize in that language.
2834
2873
  hasMCPServers() {
2835
2874
  return this.mcpServers.length > 0;
2836
2875
  }
2876
+ /**
2877
+ * Get the last MCP schema initialization error, if schema fallback was used.
2878
+ */
2879
+ getMCPSchemaInitializationError() {
2880
+ return this.mcpSchemaInitializationError;
2881
+ }
2837
2882
  /**
2838
2883
  * Initialize MCP tool schemas by fetching from servers
2839
2884
  * @private
@@ -2846,16 +2891,16 @@ If it's in another language, summarize in that language.
2846
2891
  const timeoutPromise = new Promise(
2847
2892
  (_, reject) => setTimeout(() => reject(new Error("MCP schema fetch timeout")), 5e3)
2848
2893
  );
2849
- const schemasPromise = MCPSchemaFetcher.fetchAllToolSchemas(
2894
+ const schemasPromise = MCPSchemaFetcher.fetchAllToolSchemasWithStatus(
2850
2895
  this.mcpServers
2851
2896
  );
2852
- this.mcpToolSchemas = await Promise.race([
2853
- schemasPromise,
2854
- timeoutPromise
2855
- ]);
2897
+ const result = await Promise.race([schemasPromise, timeoutPromise]);
2898
+ this.mcpToolSchemas = result.schemas;
2856
2899
  this.mcpSchemasInitialized = true;
2900
+ this.mcpSchemaInitializationError = result.failures[0]?.error;
2857
2901
  } catch (error) {
2858
2902
  console.warn("Failed to initialize MCP schemas, using fallback:", error);
2903
+ this.mcpSchemaInitializationError = error;
2859
2904
  this.mcpToolSchemas = createFallbackMCPToolSchemas(this.mcpServers);
2860
2905
  this.mcpSchemasInitialized = true;
2861
2906
  }
@@ -2976,7 +3021,14 @@ If it's in another language, summarize in that language.
2976
3021
  } catch (e) {
2977
3022
  const looksLikeVersionMismatch = /Unknown name|Cannot find field|404/.test(e?.message || "") || e?.status === 404;
2978
3023
  if (!requiresV1beta && looksLikeVersionMismatch) {
2979
- return await fetchOnce("v1beta", this.adaptKeysForApi(body));
3024
+ try {
3025
+ return await fetchOnce("v1beta", this.adaptKeysForApi(body));
3026
+ } catch (fallbackError) {
3027
+ if (fallbackError instanceof Error) {
3028
+ fallbackError.cause = e;
3029
+ }
3030
+ throw fallbackError;
3031
+ }
2980
3032
  }
2981
3033
  throw e;
2982
3034
  }
@@ -3901,28 +3953,38 @@ If it's in another language, summarize in that language.
3901
3953
  }
3902
3954
  /**
3903
3955
  * Normalize reasoning effort to a model-supported value
3956
+ *
3957
+ * Unsupported values are rounded to the nearest supported level instead of
3958
+ * resetting to the model default, so a low-latency request stays low
3959
+ * (e.g. 'minimal' on GPT-5.4 resolves to 'none', not 'medium') and a
3960
+ * high-effort request stays high (e.g. 'xhigh' on GPT-5.1 resolves to
3961
+ * 'high', not 'none').
3904
3962
  */
3905
3963
  normalizeReasoningEffort(modelName, effort) {
3906
3964
  if (!effort) {
3907
3965
  return void 0;
3908
3966
  }
3909
- if (effort === "none" && !allowsReasoningNone(modelName)) {
3910
- return getDefaultReasoningEffortForGPT5Model(modelName);
3911
- }
3912
- if (effort === "minimal" && !allowsReasoningMinimal(modelName)) {
3913
- return getDefaultReasoningEffortForGPT5Model(modelName);
3967
+ if (effort === "none" && !allowsReasoningNone(modelName) || effort === "minimal" && !allowsReasoningMinimal(modelName)) {
3968
+ if (effort === "minimal" && allowsReasoningNone(modelName)) {
3969
+ return "none";
3970
+ }
3971
+ if (effort === "none" && allowsReasoningMinimal(modelName)) {
3972
+ return "minimal";
3973
+ }
3974
+ return allowsReasoningLow(modelName) ? "low" : "medium";
3914
3975
  }
3915
3976
  if (effort === "low" && !allowsReasoningLow(modelName)) {
3916
- return getDefaultReasoningEffortForGPT5Model(modelName);
3977
+ return "medium";
3917
3978
  }
3918
3979
  if (effort === "xhigh" && !allowsReasoningXHigh(modelName)) {
3919
- return getDefaultReasoningEffortForGPT5Model(modelName);
3980
+ return "high";
3920
3981
  }
3921
3982
  return effort;
3922
3983
  }
3923
3984
  };
3924
3985
 
3925
3986
  // src/services/providers/openrouter/OpenRouterChatService.ts
3987
+ var isTokenLimitUnsupportedModel = (model) => model.trim() === MODEL_GPT_OSS_20B_FREE;
3926
3988
  var OpenRouterChatService = class {
3927
3989
  /**
3928
3990
  * Constructor
@@ -4116,10 +4178,12 @@ If it's in another language, summarize in that language.
4116
4178
  stream
4117
4179
  };
4118
4180
  const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
4119
- if (tokenLimit) {
4181
+ if (tokenLimit && isTokenLimitUnsupportedModel(model)) {
4120
4182
  console.warn(
4121
- `OpenRouter: Token limits are not supported for gpt-oss-20b model due to known issues. Using unlimited tokens instead.`
4183
+ `OpenRouter: Token limits are not supported for ${model} due to known issues. Using unlimited tokens instead.`
4122
4184
  );
4185
+ } else if (tokenLimit) {
4186
+ body.max_tokens = tokenLimit;
4123
4187
  }
4124
4188
  if (this.reasoning_effort !== void 0 || this.includeReasoning !== void 0 || this.reasoningMaxTokens) {
4125
4189
  body.reasoning = {};