@aituber-onair/chat 0.47.0 → 0.49.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 (165) hide show
  1. package/README.ja.md +128 -23
  2. package/README.md +137 -23
  3. package/dist/cjs/constants/claude.d.ts +15 -0
  4. package/dist/cjs/constants/claude.d.ts.map +1 -1
  5. package/dist/cjs/constants/claude.js +61 -1
  6. package/dist/cjs/constants/claude.js.map +1 -1
  7. package/dist/cjs/constants/gemini.d.ts +17 -0
  8. package/dist/cjs/constants/gemini.d.ts.map +1 -1
  9. package/dist/cjs/constants/gemini.js +67 -1
  10. package/dist/cjs/constants/gemini.js.map +1 -1
  11. package/dist/cjs/constants/kimi.d.ts +14 -0
  12. package/dist/cjs/constants/kimi.d.ts.map +1 -1
  13. package/dist/cjs/constants/kimi.js +27 -1
  14. package/dist/cjs/constants/kimi.js.map +1 -1
  15. package/dist/cjs/constants/openrouter.d.ts +12 -0
  16. package/dist/cjs/constants/openrouter.d.ts.map +1 -1
  17. package/dist/cjs/constants/openrouter.js +24 -1
  18. package/dist/cjs/constants/openrouter.js.map +1 -1
  19. package/dist/cjs/index.d.ts +1 -1
  20. package/dist/cjs/index.d.ts.map +1 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/services/ChatService.d.ts +2 -2
  23. package/dist/cjs/services/ChatService.d.ts.map +1 -1
  24. package/dist/cjs/services/ChatServiceFactory.d.ts.map +1 -1
  25. package/dist/cjs/services/ChatServiceFactory.js +10 -1
  26. package/dist/cjs/services/ChatServiceFactory.js.map +1 -1
  27. package/dist/cjs/services/providers/ChatServiceProvider.d.ts +23 -4
  28. package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
  29. package/dist/cjs/services/providers/claude/ClaudeChatService.d.ts +3 -1
  30. package/dist/cjs/services/providers/claude/ClaudeChatService.d.ts.map +1 -1
  31. package/dist/cjs/services/providers/claude/ClaudeChatService.js +51 -4
  32. package/dist/cjs/services/providers/claude/ClaudeChatService.js.map +1 -1
  33. package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.d.ts.map +1 -1
  34. package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.js +13 -2
  35. package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.js.map +1 -1
  36. package/dist/cjs/services/providers/claude/claudeMessageConverter.d.ts.map +1 -1
  37. package/dist/cjs/services/providers/claude/claudeMessageConverter.js +7 -1
  38. package/dist/cjs/services/providers/claude/claudeMessageConverter.js.map +1 -1
  39. package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts +8 -2
  40. package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  41. package/dist/cjs/services/providers/gemini/GeminiChatService.js +65 -38
  42. package/dist/cjs/services/providers/gemini/GeminiChatService.js.map +1 -1
  43. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
  44. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js +9 -2
  45. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
  46. package/dist/cjs/services/providers/gemini/geminiMessageConverter.d.ts +6 -0
  47. package/dist/cjs/services/providers/gemini/geminiMessageConverter.d.ts.map +1 -1
  48. package/dist/cjs/services/providers/gemini/geminiMessageConverter.js +61 -58
  49. package/dist/cjs/services/providers/gemini/geminiMessageConverter.js.map +1 -1
  50. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts +7 -2
  51. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -1
  52. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js +83 -30
  53. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -1
  54. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -1
  55. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +1 -0
  56. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -1
  57. package/dist/cjs/services/providers/kimi/KimiChatService.d.ts +5 -4
  58. package/dist/cjs/services/providers/kimi/KimiChatService.d.ts.map +1 -1
  59. package/dist/cjs/services/providers/kimi/KimiChatService.js +32 -18
  60. package/dist/cjs/services/providers/kimi/KimiChatService.js.map +1 -1
  61. package/dist/cjs/services/providers/kimi/KimiChatServiceProvider.d.ts +1 -0
  62. package/dist/cjs/services/providers/kimi/KimiChatServiceProvider.d.ts.map +1 -1
  63. package/dist/cjs/services/providers/kimi/KimiChatServiceProvider.js +23 -1
  64. package/dist/cjs/services/providers/kimi/KimiChatServiceProvider.js.map +1 -1
  65. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.d.ts.map +1 -1
  66. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.js +34 -15
  67. package/dist/cjs/services/providers/openrouter/OpenRouterChatService.js.map +1 -1
  68. package/dist/cjs/services/providers/openrouter/OpenRouterChatServiceProvider.d.ts.map +1 -1
  69. package/dist/cjs/services/providers/openrouter/OpenRouterChatServiceProvider.js +13 -0
  70. package/dist/cjs/services/providers/openrouter/OpenRouterChatServiceProvider.js.map +1 -1
  71. package/dist/cjs/types/chat.d.ts +12 -2
  72. package/dist/cjs/types/chat.d.ts.map +1 -1
  73. package/dist/cjs/types/toolChat.d.ts +19 -0
  74. package/dist/cjs/types/toolChat.d.ts.map +1 -1
  75. package/dist/cjs/utils/openaiCompatibleSse.d.ts +2 -0
  76. package/dist/cjs/utils/openaiCompatibleSse.d.ts.map +1 -1
  77. package/dist/cjs/utils/openaiCompatibleSse.js +70 -5
  78. package/dist/cjs/utils/openaiCompatibleSse.js.map +1 -1
  79. package/dist/cjs/utils/processChatFlow.d.ts +2 -2
  80. package/dist/cjs/utils/processChatFlow.d.ts.map +1 -1
  81. package/dist/cjs/utils/processChatFlow.js +8 -3
  82. package/dist/cjs/utils/processChatFlow.js.map +1 -1
  83. package/dist/esm/constants/claude.d.ts +15 -0
  84. package/dist/esm/constants/claude.d.ts.map +1 -1
  85. package/dist/esm/constants/claude.js +56 -0
  86. package/dist/esm/constants/claude.js.map +1 -1
  87. package/dist/esm/constants/gemini.d.ts +17 -0
  88. package/dist/esm/constants/gemini.d.ts.map +1 -1
  89. package/dist/esm/constants/gemini.js +62 -0
  90. package/dist/esm/constants/gemini.js.map +1 -1
  91. package/dist/esm/constants/kimi.d.ts +14 -0
  92. package/dist/esm/constants/kimi.d.ts.map +1 -1
  93. package/dist/esm/constants/kimi.js +23 -0
  94. package/dist/esm/constants/kimi.js.map +1 -1
  95. package/dist/esm/constants/openrouter.d.ts +12 -0
  96. package/dist/esm/constants/openrouter.d.ts.map +1 -1
  97. package/dist/esm/constants/openrouter.js +22 -0
  98. package/dist/esm/constants/openrouter.js.map +1 -1
  99. package/dist/esm/index.d.ts +1 -1
  100. package/dist/esm/index.d.ts.map +1 -1
  101. package/dist/esm/index.js.map +1 -1
  102. package/dist/esm/services/ChatService.d.ts +2 -2
  103. package/dist/esm/services/ChatService.d.ts.map +1 -1
  104. package/dist/esm/services/ChatServiceFactory.d.ts.map +1 -1
  105. package/dist/esm/services/ChatServiceFactory.js +10 -1
  106. package/dist/esm/services/ChatServiceFactory.js.map +1 -1
  107. package/dist/esm/services/providers/ChatServiceProvider.d.ts +23 -4
  108. package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
  109. package/dist/esm/services/providers/claude/ClaudeChatService.d.ts +3 -1
  110. package/dist/esm/services/providers/claude/ClaudeChatService.d.ts.map +1 -1
  111. package/dist/esm/services/providers/claude/ClaudeChatService.js +52 -5
  112. package/dist/esm/services/providers/claude/ClaudeChatService.js.map +1 -1
  113. package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.d.ts.map +1 -1
  114. package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.js +14 -3
  115. package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.js.map +1 -1
  116. package/dist/esm/services/providers/claude/claudeMessageConverter.d.ts.map +1 -1
  117. package/dist/esm/services/providers/claude/claudeMessageConverter.js +7 -1
  118. package/dist/esm/services/providers/claude/claudeMessageConverter.js.map +1 -1
  119. package/dist/esm/services/providers/gemini/GeminiChatService.d.ts +8 -2
  120. package/dist/esm/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  121. package/dist/esm/services/providers/gemini/GeminiChatService.js +66 -39
  122. package/dist/esm/services/providers/gemini/GeminiChatService.js.map +1 -1
  123. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
  124. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js +10 -3
  125. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
  126. package/dist/esm/services/providers/gemini/geminiMessageConverter.d.ts +6 -0
  127. package/dist/esm/services/providers/gemini/geminiMessageConverter.d.ts.map +1 -1
  128. package/dist/esm/services/providers/gemini/geminiMessageConverter.js +61 -58
  129. package/dist/esm/services/providers/gemini/geminiMessageConverter.js.map +1 -1
  130. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts +7 -2
  131. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -1
  132. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js +84 -31
  133. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -1
  134. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -1
  135. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +1 -0
  136. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -1
  137. package/dist/esm/services/providers/kimi/KimiChatService.d.ts +5 -4
  138. package/dist/esm/services/providers/kimi/KimiChatService.d.ts.map +1 -1
  139. package/dist/esm/services/providers/kimi/KimiChatService.js +34 -20
  140. package/dist/esm/services/providers/kimi/KimiChatService.js.map +1 -1
  141. package/dist/esm/services/providers/kimi/KimiChatServiceProvider.d.ts +1 -0
  142. package/dist/esm/services/providers/kimi/KimiChatServiceProvider.d.ts.map +1 -1
  143. package/dist/esm/services/providers/kimi/KimiChatServiceProvider.js +24 -2
  144. package/dist/esm/services/providers/kimi/KimiChatServiceProvider.js.map +1 -1
  145. package/dist/esm/services/providers/openrouter/OpenRouterChatService.d.ts.map +1 -1
  146. package/dist/esm/services/providers/openrouter/OpenRouterChatService.js +35 -16
  147. package/dist/esm/services/providers/openrouter/OpenRouterChatService.js.map +1 -1
  148. package/dist/esm/services/providers/openrouter/OpenRouterChatServiceProvider.d.ts.map +1 -1
  149. package/dist/esm/services/providers/openrouter/OpenRouterChatServiceProvider.js +14 -1
  150. package/dist/esm/services/providers/openrouter/OpenRouterChatServiceProvider.js.map +1 -1
  151. package/dist/esm/types/chat.d.ts +12 -2
  152. package/dist/esm/types/chat.d.ts.map +1 -1
  153. package/dist/esm/types/toolChat.d.ts +19 -0
  154. package/dist/esm/types/toolChat.d.ts.map +1 -1
  155. package/dist/esm/utils/openaiCompatibleSse.d.ts +2 -0
  156. package/dist/esm/utils/openaiCompatibleSse.d.ts.map +1 -1
  157. package/dist/esm/utils/openaiCompatibleSse.js +70 -5
  158. package/dist/esm/utils/openaiCompatibleSse.js.map +1 -1
  159. package/dist/esm/utils/processChatFlow.d.ts +2 -2
  160. package/dist/esm/utils/processChatFlow.d.ts.map +1 -1
  161. package/dist/esm/utils/processChatFlow.js +8 -3
  162. package/dist/esm/utils/processChatFlow.js.map +1 -1
  163. package/dist/umd/aituber-onair-chat.js +621 -177
  164. package/dist/umd/aituber-onair-chat.min.js +9 -11
  165. package/package.json +1 -1
@@ -75,6 +75,7 @@ var AITuberOnAirChat = (() => {
75
75
  MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU: () => MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU,
76
76
  MODEL_ANTHROPIC_CLAUDE_HAIKU_LATEST: () => MODEL_ANTHROPIC_CLAUDE_HAIKU_LATEST,
77
77
  MODEL_ANTHROPIC_CLAUDE_OPUS_4: () => MODEL_ANTHROPIC_CLAUDE_OPUS_4,
78
+ MODEL_ANTHROPIC_CLAUDE_OPUS_5: () => MODEL_ANTHROPIC_CLAUDE_OPUS_5,
78
79
  MODEL_ANTHROPIC_CLAUDE_SONNET_4: () => MODEL_ANTHROPIC_CLAUDE_SONNET_4,
79
80
  MODEL_ANTHROPIC_CLAUDE_SONNET_LATEST: () => MODEL_ANTHROPIC_CLAUDE_SONNET_LATEST,
80
81
  MODEL_CLAUDE_3_5_HAIKU: () => MODEL_CLAUDE_3_5_HAIKU,
@@ -90,6 +91,7 @@ var AITuberOnAirChat = (() => {
90
91
  MODEL_CLAUDE_4_8_OPUS: () => MODEL_CLAUDE_4_8_OPUS,
91
92
  MODEL_CLAUDE_4_OPUS: () => MODEL_CLAUDE_4_OPUS,
92
93
  MODEL_CLAUDE_4_SONNET: () => MODEL_CLAUDE_4_SONNET,
94
+ MODEL_CLAUDE_5_OPUS: () => MODEL_CLAUDE_5_OPUS,
93
95
  MODEL_CLAUDE_5_SONNET: () => MODEL_CLAUDE_5_SONNET,
94
96
  MODEL_DEEPSEEK_CHAT: () => MODEL_DEEPSEEK_CHAT,
95
97
  MODEL_DEEPSEEK_REASONER: () => MODEL_DEEPSEEK_REASONER,
@@ -106,6 +108,8 @@ var AITuberOnAirChat = (() => {
106
108
  MODEL_GEMINI_3_1_FLASH_LITE_PREVIEW: () => MODEL_GEMINI_3_1_FLASH_LITE_PREVIEW,
107
109
  MODEL_GEMINI_3_1_PRO_PREVIEW: () => MODEL_GEMINI_3_1_PRO_PREVIEW,
108
110
  MODEL_GEMINI_3_5_FLASH: () => MODEL_GEMINI_3_5_FLASH,
111
+ MODEL_GEMINI_3_5_FLASH_LITE: () => MODEL_GEMINI_3_5_FLASH_LITE,
112
+ MODEL_GEMINI_3_6_FLASH: () => MODEL_GEMINI_3_6_FLASH,
109
113
  MODEL_GEMINI_3_FLASH_PREVIEW: () => MODEL_GEMINI_3_FLASH_PREVIEW,
110
114
  MODEL_GEMINI_3_PRO_PREVIEW: () => MODEL_GEMINI_3_PRO_PREVIEW,
111
115
  MODEL_GEMINI_NANO: () => MODEL_GEMINI_NANO,
@@ -126,6 +130,8 @@ var AITuberOnAirChat = (() => {
126
130
  MODEL_GOOGLE_GEMINI_2_5_FLASH: () => MODEL_GOOGLE_GEMINI_2_5_FLASH,
127
131
  MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025: () => MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025,
128
132
  MODEL_GOOGLE_GEMINI_2_5_PRO: () => MODEL_GOOGLE_GEMINI_2_5_PRO,
133
+ MODEL_GOOGLE_GEMINI_3_5_FLASH_LITE: () => MODEL_GOOGLE_GEMINI_3_5_FLASH_LITE,
134
+ MODEL_GOOGLE_GEMINI_3_6_FLASH: () => MODEL_GOOGLE_GEMINI_3_6_FLASH,
129
135
  MODEL_GOOGLE_GEMINI_FLASH_LATEST: () => MODEL_GOOGLE_GEMINI_FLASH_LATEST,
130
136
  MODEL_GOOGLE_GEMINI_PRO_LATEST: () => MODEL_GOOGLE_GEMINI_PRO_LATEST,
131
137
  MODEL_GPT_4O: () => MODEL_GPT_4O,
@@ -157,6 +163,9 @@ var AITuberOnAirChat = (() => {
157
163
  MODEL_KIMI_K2_6: () => MODEL_KIMI_K2_6,
158
164
  MODEL_KIMI_K2_7_CODE: () => MODEL_KIMI_K2_7_CODE,
159
165
  MODEL_KIMI_K2_7_CODE_HIGHSPEED: () => MODEL_KIMI_K2_7_CODE_HIGHSPEED,
166
+ MODEL_KIMI_K3: () => MODEL_KIMI_K3,
167
+ MODEL_KWAIPILOT_KAT_CODER_AIR_V2_5: () => MODEL_KWAIPILOT_KAT_CODER_AIR_V2_5,
168
+ MODEL_KWAIPILOT_KAT_CODER_PRO_V2_5: () => MODEL_KWAIPILOT_KAT_CODER_PRO_V2_5,
160
169
  MODEL_MINISTRAL_14B_2512: () => MODEL_MINISTRAL_14B_2512,
161
170
  MODEL_MINISTRAL_3B_2512: () => MODEL_MINISTRAL_3B_2512,
162
171
  MODEL_MINISTRAL_8B_2512: () => MODEL_MINISTRAL_8B_2512,
@@ -168,6 +177,7 @@ var AITuberOnAirChat = (() => {
168
177
  MODEL_MISTRAL_SMALL_LATEST: () => MODEL_MISTRAL_SMALL_LATEST,
169
178
  MODEL_MOONSHOTAI_KIMI_K2_5: () => MODEL_MOONSHOTAI_KIMI_K2_5,
170
179
  MODEL_MOONSHOTAI_KIMI_K2_7_CODE: () => MODEL_MOONSHOTAI_KIMI_K2_7_CODE,
180
+ MODEL_MOONSHOTAI_KIMI_K3: () => MODEL_MOONSHOTAI_KIMI_K3,
171
181
  MODEL_MOONSHOTAI_KIMI_LATEST: () => MODEL_MOONSHOTAI_KIMI_LATEST,
172
182
  MODEL_O1: () => MODEL_O1,
173
183
  MODEL_O1_MINI: () => MODEL_O1_MINI,
@@ -179,14 +189,20 @@ var AITuberOnAirChat = (() => {
179
189
  MODEL_OPENAI_GPT_5_1_CODEX: () => MODEL_OPENAI_GPT_5_1_CODEX,
180
190
  MODEL_OPENAI_GPT_5_5: () => MODEL_OPENAI_GPT_5_5,
181
191
  MODEL_OPENAI_GPT_5_5_PRO: () => MODEL_OPENAI_GPT_5_5_PRO,
192
+ MODEL_OPENAI_GPT_5_6_LUNA: () => MODEL_OPENAI_GPT_5_6_LUNA,
193
+ MODEL_OPENAI_GPT_5_6_SOL: () => MODEL_OPENAI_GPT_5_6_SOL,
194
+ MODEL_OPENAI_GPT_5_6_TERRA: () => MODEL_OPENAI_GPT_5_6_TERRA,
182
195
  MODEL_OPENAI_GPT_5_MINI: () => MODEL_OPENAI_GPT_5_MINI,
183
196
  MODEL_OPENAI_GPT_5_NANO: () => MODEL_OPENAI_GPT_5_NANO,
184
197
  MODEL_OPENAI_GPT_LATEST: () => MODEL_OPENAI_GPT_LATEST,
185
198
  MODEL_OPENAI_GPT_MINI_LATEST: () => MODEL_OPENAI_GPT_MINI_LATEST,
186
199
  MODEL_OPENROUTER_AUTO: () => MODEL_OPENROUTER_AUTO,
200
+ MODEL_OPENROUTER_AUTO_BETA: () => MODEL_OPENROUTER_AUTO_BETA,
187
201
  MODEL_OPENROUTER_FUSION: () => MODEL_OPENROUTER_FUSION,
188
202
  MODEL_PLAMO_2_2_PRIME: () => MODEL_PLAMO_2_2_PRIME,
189
203
  MODEL_PLAMO_3_0_PRIME: () => MODEL_PLAMO_3_0_PRIME,
204
+ MODEL_XAI_GROK_4_5: () => MODEL_XAI_GROK_4_5,
205
+ MODEL_XAI_GROK_LATEST: () => MODEL_XAI_GROK_LATEST,
190
206
  MODEL_ZAI_GLM_4_5_AIR: () => MODEL_ZAI_GLM_4_5_AIR,
191
207
  MODEL_ZAI_GLM_4_5_AIR_FREE: () => MODEL_ZAI_GLM_4_5_AIR_FREE,
192
208
  MODEL_ZAI_GLM_4_7_FLASH: () => MODEL_ZAI_GLM_4_7_FLASH,
@@ -226,11 +242,20 @@ var AITuberOnAirChat = (() => {
226
242
  allowsReasoningNone: () => allowsReasoningNone,
227
243
  allowsReasoningXHigh: () => allowsReasoningXHigh,
228
244
  buildOpenAICompatibleTools: () => buildOpenAICompatibleTools,
245
+ getClaudeSupportedReasoningEfforts: () => getClaudeSupportedReasoningEfforts,
246
+ getDefaultClaudeReasoningEffort: () => getDefaultClaudeReasoningEffort,
247
+ getDefaultGeminiReasoningEffort: () => getDefaultGeminiReasoningEffort,
248
+ getDefaultKimiReasoningEffort: () => getDefaultKimiReasoningEffort,
229
249
  getDefaultReasoningEffortForGPT5Model: () => getDefaultReasoningEffortForGPT5Model,
230
250
  getDefaultXaiReasoningEffort: () => getDefaultXaiReasoningEffort,
251
+ getGeminiSupportedReasoningEfforts: () => getGeminiSupportedReasoningEfforts,
252
+ getKimiSupportedReasoningEfforts: () => getKimiSupportedReasoningEfforts,
231
253
  getMaxTokensForResponseLength: () => getMaxTokensForResponseLength,
232
254
  installGASFetch: () => installGASFetch,
255
+ isClaudeReasoningEffortModel: () => isClaudeReasoningEffortModel,
233
256
  isGPT5Model: () => isGPT5Model,
257
+ isGeminiReasoningEffortModel: () => isGeminiReasoningEffortModel,
258
+ isKimiReasoningEffortModel: () => isKimiReasoningEffortModel,
234
259
  isKimiThinkingRequiredModel: () => isKimiThinkingRequiredModel,
235
260
  isKimiVisionModel: () => isKimiVisionModel,
236
261
  isMistralReasoningEffort: () => isMistralReasoningEffort,
@@ -244,6 +269,8 @@ var AITuberOnAirChat = (() => {
244
269
  isXaiVisionModel: () => isXaiVisionModel,
245
270
  isZaiToolStreamModel: () => isZaiToolStreamModel,
246
271
  isZaiVisionModel: () => isZaiVisionModel,
272
+ normalizeClaudeReasoningEffort: () => normalizeClaudeReasoningEffort,
273
+ normalizeGeminiReasoningEffort: () => normalizeGeminiReasoningEffort,
247
274
  normalizeXaiReasoningEffort: () => normalizeXaiReasoningEffort,
248
275
  parseOpenAICompatibleOneShot: () => parseOpenAICompatibleOneShot,
249
276
  parseOpenAICompatibleTextStream: () => parseOpenAICompatibleTextStream,
@@ -355,7 +382,9 @@ var AITuberOnAirChat = (() => {
355
382
  var ENDPOINT_GEMINI_API = "https://generativelanguage.googleapis.com";
356
383
  var MODEL_GEMMA_4_31B_IT = "gemma-4-31b-it";
357
384
  var MODEL_GEMMA_4_26B_A4B_IT = "gemma-4-26b-a4b-it";
385
+ var MODEL_GEMINI_3_6_FLASH = "gemini-3.6-flash";
358
386
  var MODEL_GEMINI_3_5_FLASH = "gemini-3.5-flash";
387
+ var MODEL_GEMINI_3_5_FLASH_LITE = "gemini-3.5-flash-lite";
359
388
  var MODEL_GEMINI_3_1_PRO_PREVIEW = "gemini-3.1-pro-preview";
360
389
  var MODEL_GEMINI_3_1_FLASH_LITE = "gemini-3.1-flash-lite";
361
390
  var MODEL_GEMINI_3_1_FLASH_LITE_PREVIEW = "gemini-3.1-flash-lite-preview";
@@ -366,7 +395,9 @@ var AITuberOnAirChat = (() => {
366
395
  var MODEL_GEMINI_2_5_FLASH_LITE = "gemini-2.5-flash-lite";
367
396
  var MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17 = "gemini-2.5-flash-lite-preview-06-17";
368
397
  var GEMINI_RECOMMENDED_MODELS = [
398
+ MODEL_GEMINI_3_6_FLASH,
369
399
  MODEL_GEMINI_3_5_FLASH,
400
+ MODEL_GEMINI_3_5_FLASH_LITE,
370
401
  MODEL_GEMINI_3_1_FLASH_LITE,
371
402
  MODEL_GEMINI_3_1_PRO_PREVIEW,
372
403
  MODEL_GEMINI_3_FLASH_PREVIEW,
@@ -385,6 +416,54 @@ var AITuberOnAirChat = (() => {
385
416
  ...GEMINI_RECOMMENDED_MODELS,
386
417
  ...GEMINI_DEPRECATED_MODELS
387
418
  ];
419
+ var GEMINI_FLASH_REASONING_EFFORTS = [
420
+ "minimal",
421
+ "low",
422
+ "medium",
423
+ "high"
424
+ ];
425
+ var GEMINI_PRO_REASONING_EFFORTS = [
426
+ "low",
427
+ "medium",
428
+ "high"
429
+ ];
430
+ var GEMINI_FLASH_REASONING_EFFORT_MODELS = [
431
+ MODEL_GEMINI_3_6_FLASH,
432
+ MODEL_GEMINI_3_5_FLASH,
433
+ MODEL_GEMINI_3_5_FLASH_LITE,
434
+ MODEL_GEMINI_3_1_FLASH_LITE,
435
+ MODEL_GEMINI_3_1_FLASH_LITE_PREVIEW,
436
+ MODEL_GEMINI_3_FLASH_PREVIEW
437
+ ];
438
+ var GEMINI_PRO_REASONING_EFFORT_MODELS = [
439
+ MODEL_GEMINI_3_1_PRO_PREVIEW,
440
+ MODEL_GEMINI_3_PRO_PREVIEW
441
+ ];
442
+ function getGeminiSupportedReasoningEfforts(model) {
443
+ if (GEMINI_FLASH_REASONING_EFFORT_MODELS.includes(model)) {
444
+ return GEMINI_FLASH_REASONING_EFFORTS;
445
+ }
446
+ if (GEMINI_PRO_REASONING_EFFORT_MODELS.includes(model)) {
447
+ return GEMINI_PRO_REASONING_EFFORTS;
448
+ }
449
+ return [];
450
+ }
451
+ function isGeminiReasoningEffortModel(model) {
452
+ return getGeminiSupportedReasoningEfforts(model).length > 0;
453
+ }
454
+ function getDefaultGeminiReasoningEffort(model) {
455
+ return getGeminiSupportedReasoningEfforts(model)[0];
456
+ }
457
+ function normalizeGeminiReasoningEffort(model, effort) {
458
+ const supported = getGeminiSupportedReasoningEfforts(model);
459
+ if (supported.length === 0) {
460
+ return void 0;
461
+ }
462
+ if (effort && supported.includes(effort)) {
463
+ return effort;
464
+ }
465
+ return supported[0];
466
+ }
388
467
 
389
468
  // src/constants/claude.ts
390
469
  var ENDPOINT_CLAUDE_API = "https://api.anthropic.com/v1/messages";
@@ -402,6 +481,30 @@ var AITuberOnAirChat = (() => {
402
481
  var MODEL_CLAUDE_4_7_OPUS = "claude-opus-4-7";
403
482
  var MODEL_CLAUDE_4_8_OPUS = "claude-opus-4-8";
404
483
  var MODEL_CLAUDE_5_SONNET = "claude-sonnet-5";
484
+ var MODEL_CLAUDE_5_OPUS = "claude-opus-5";
485
+ var CLAUDE_STANDARD_REASONING_EFFORTS = [
486
+ "low",
487
+ "medium",
488
+ "high"
489
+ ];
490
+ var CLAUDE_MAX_REASONING_EFFORTS = [
491
+ ...CLAUDE_STANDARD_REASONING_EFFORTS,
492
+ "max"
493
+ ];
494
+ var CLAUDE_XHIGH_REASONING_EFFORTS = [
495
+ ...CLAUDE_STANDARD_REASONING_EFFORTS,
496
+ "xhigh",
497
+ "max"
498
+ ];
499
+ var CLAUDE_REASONING_EFFORTS_BY_MODEL = {
500
+ [MODEL_CLAUDE_4_5_OPUS]: CLAUDE_STANDARD_REASONING_EFFORTS,
501
+ [MODEL_CLAUDE_4_6_SONNET]: CLAUDE_MAX_REASONING_EFFORTS,
502
+ [MODEL_CLAUDE_4_6_OPUS]: CLAUDE_MAX_REASONING_EFFORTS,
503
+ [MODEL_CLAUDE_4_7_OPUS]: CLAUDE_XHIGH_REASONING_EFFORTS,
504
+ [MODEL_CLAUDE_4_8_OPUS]: CLAUDE_XHIGH_REASONING_EFFORTS,
505
+ [MODEL_CLAUDE_5_SONNET]: CLAUDE_XHIGH_REASONING_EFFORTS,
506
+ [MODEL_CLAUDE_5_OPUS]: CLAUDE_XHIGH_REASONING_EFFORTS
507
+ };
405
508
  var CLAUDE_VISION_SUPPORTED_MODELS = [
406
509
  MODEL_CLAUDE_3_HAIKU,
407
510
  MODEL_CLAUDE_4_SONNET,
@@ -413,19 +516,47 @@ var AITuberOnAirChat = (() => {
413
516
  MODEL_CLAUDE_4_6_OPUS,
414
517
  MODEL_CLAUDE_4_7_OPUS,
415
518
  MODEL_CLAUDE_4_8_OPUS,
416
- MODEL_CLAUDE_5_SONNET
519
+ MODEL_CLAUDE_5_SONNET,
520
+ MODEL_CLAUDE_5_OPUS
417
521
  ];
522
+ function getClaudeSupportedReasoningEfforts(model) {
523
+ return CLAUDE_REASONING_EFFORTS_BY_MODEL[model] ?? [];
524
+ }
525
+ function isClaudeReasoningEffortModel(model) {
526
+ return getClaudeSupportedReasoningEfforts(model).length > 0;
527
+ }
528
+ function getDefaultClaudeReasoningEffort(model) {
529
+ return isClaudeReasoningEffortModel(model) ? "high" : void 0;
530
+ }
531
+ function normalizeClaudeReasoningEffort(model, effort) {
532
+ const supported = getClaudeSupportedReasoningEfforts(model);
533
+ if (supported.length === 0) {
534
+ return void 0;
535
+ }
536
+ if (!effort) {
537
+ return getDefaultClaudeReasoningEffort(model);
538
+ }
539
+ if (supported.includes(effort)) {
540
+ return effort;
541
+ }
542
+ return "high";
543
+ }
418
544
 
419
545
  // src/constants/openrouter.ts
420
546
  var ENDPOINT_OPENROUTER_API = "https://openrouter.ai/api/v1/chat/completions";
421
547
  var MODEL_OPENROUTER_AUTO = "openrouter/auto";
548
+ var MODEL_OPENROUTER_AUTO_BETA = "openrouter/auto-beta";
422
549
  var MODEL_OPENROUTER_FUSION = "openrouter/fusion";
423
550
  var MODEL_GPT_OSS_20B_FREE = "openai/gpt-oss-20b:free";
551
+ var MODEL_MOONSHOTAI_KIMI_K3 = "moonshotai/kimi-k3";
424
552
  var MODEL_MOONSHOTAI_KIMI_K2_7_CODE = "moonshotai/kimi-k2.7-code";
425
553
  var MODEL_MOONSHOTAI_KIMI_K2_5 = "moonshotai/kimi-k2.5";
426
554
  var MODEL_MOONSHOTAI_KIMI_LATEST = "~moonshotai/kimi-latest";
427
555
  var MODEL_OPENAI_GPT_LATEST = "~openai/gpt-latest";
428
556
  var MODEL_OPENAI_GPT_MINI_LATEST = "~openai/gpt-mini-latest";
557
+ var MODEL_OPENAI_GPT_5_6_SOL = "openai/gpt-5.6-sol";
558
+ var MODEL_OPENAI_GPT_5_6_TERRA = "openai/gpt-5.6-terra";
559
+ var MODEL_OPENAI_GPT_5_6_LUNA = "openai/gpt-5.6-luna";
429
560
  var MODEL_OPENAI_GPT_5_5_PRO = "openai/gpt-5.5-pro";
430
561
  var MODEL_OPENAI_GPT_5_5 = "openai/gpt-5.5";
431
562
  var MODEL_OPENAI_GPT_5_1_CHAT = "openai/gpt-5.1-chat";
@@ -437,6 +568,7 @@ var AITuberOnAirChat = (() => {
437
568
  var MODEL_OPENAI_GPT_4_1_NANO = "openai/gpt-4.1-nano";
438
569
  var MODEL_ANTHROPIC_CLAUDE_SONNET_LATEST = "~anthropic/claude-sonnet-latest";
439
570
  var MODEL_ANTHROPIC_CLAUDE_HAIKU_LATEST = "~anthropic/claude-haiku-latest";
571
+ var MODEL_ANTHROPIC_CLAUDE_OPUS_5 = "anthropic/claude-opus-5";
440
572
  var MODEL_ANTHROPIC_CLAUDE_OPUS_4 = "anthropic/claude-opus-4";
441
573
  var MODEL_ANTHROPIC_CLAUDE_SONNET_4 = "anthropic/claude-sonnet-4";
442
574
  var MODEL_ANTHROPIC_CLAUDE_3_7_SONNET = "anthropic/claude-3.7-sonnet";
@@ -444,6 +576,8 @@ var AITuberOnAirChat = (() => {
444
576
  var MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU = "anthropic/claude-haiku-4.5";
445
577
  var MODEL_GOOGLE_GEMINI_PRO_LATEST = "~google/gemini-pro-latest";
446
578
  var MODEL_GOOGLE_GEMINI_FLASH_LATEST = "~google/gemini-flash-latest";
579
+ var MODEL_GOOGLE_GEMINI_3_6_FLASH = "google/gemini-3.6-flash";
580
+ var MODEL_GOOGLE_GEMINI_3_5_FLASH_LITE = "google/gemini-3.5-flash-lite";
447
581
  var MODEL_GOOGLE_GEMINI_2_5_PRO = "google/gemini-2.5-pro";
448
582
  var MODEL_GOOGLE_GEMINI_2_5_FLASH = "google/gemini-2.5-flash";
449
583
  var MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025 = "google/gemini-2.5-flash-lite-preview-09-2025";
@@ -451,14 +585,23 @@ var AITuberOnAirChat = (() => {
451
585
  var MODEL_ZAI_GLM_4_7_FLASH = "z-ai/glm-4.7-flash";
452
586
  var MODEL_ZAI_GLM_4_5_AIR = "z-ai/glm-4.5-air";
453
587
  var MODEL_ZAI_GLM_4_5_AIR_FREE = "z-ai/glm-4.5-air:free";
588
+ var MODEL_KWAIPILOT_KAT_CODER_AIR_V2_5 = "kwaipilot/kat-coder-air-v2.5";
589
+ var MODEL_KWAIPILOT_KAT_CODER_PRO_V2_5 = "kwaipilot/kat-coder-pro-v2.5";
590
+ var MODEL_XAI_GROK_LATEST = "~x-ai/grok-latest";
591
+ var MODEL_XAI_GROK_4_5 = "x-ai/grok-4.5";
454
592
  var OPENROUTER_FREE_MODELS = [
455
593
  MODEL_GPT_OSS_20B_FREE,
456
594
  MODEL_ZAI_GLM_4_5_AIR_FREE
457
595
  ];
458
596
  var OPENROUTER_VISION_SUPPORTED_MODELS = [
597
+ MODEL_OPENROUTER_AUTO_BETA,
598
+ MODEL_MOONSHOTAI_KIMI_K3,
459
599
  MODEL_MOONSHOTAI_KIMI_LATEST,
460
600
  MODEL_OPENAI_GPT_LATEST,
461
601
  MODEL_OPENAI_GPT_MINI_LATEST,
602
+ MODEL_OPENAI_GPT_5_6_SOL,
603
+ MODEL_OPENAI_GPT_5_6_TERRA,
604
+ MODEL_OPENAI_GPT_5_6_LUNA,
462
605
  MODEL_OPENAI_GPT_5_5_PRO,
463
606
  MODEL_OPENAI_GPT_5_5,
464
607
  MODEL_OPENAI_GPT_5_1_CHAT,
@@ -470,17 +613,22 @@ var AITuberOnAirChat = (() => {
470
613
  MODEL_OPENAI_GPT_4_1_NANO,
471
614
  MODEL_ANTHROPIC_CLAUDE_SONNET_LATEST,
472
615
  MODEL_ANTHROPIC_CLAUDE_HAIKU_LATEST,
616
+ MODEL_ANTHROPIC_CLAUDE_OPUS_5,
473
617
  MODEL_ANTHROPIC_CLAUDE_OPUS_4,
474
618
  MODEL_ANTHROPIC_CLAUDE_SONNET_4,
475
619
  MODEL_ANTHROPIC_CLAUDE_3_7_SONNET,
476
620
  MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU,
477
621
  MODEL_GOOGLE_GEMINI_PRO_LATEST,
478
622
  MODEL_GOOGLE_GEMINI_FLASH_LATEST,
623
+ MODEL_GOOGLE_GEMINI_3_6_FLASH,
624
+ MODEL_GOOGLE_GEMINI_3_5_FLASH_LITE,
479
625
  MODEL_GOOGLE_GEMINI_2_5_PRO,
480
626
  MODEL_GOOGLE_GEMINI_2_5_FLASH,
481
627
  MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025,
482
628
  MODEL_MOONSHOTAI_KIMI_K2_7_CODE,
483
- MODEL_MOONSHOTAI_KIMI_K2_5
629
+ MODEL_MOONSHOTAI_KIMI_K2_5,
630
+ MODEL_XAI_GROK_LATEST,
631
+ MODEL_XAI_GROK_4_5
484
632
  ];
485
633
  var OPENROUTER_FREE_RATE_LIMIT_PER_MINUTE = 20;
486
634
  var OPENROUTER_FREE_DAILY_LIMIT_LOW_CREDITS = 50;
@@ -565,11 +713,16 @@ var AITuberOnAirChat = (() => {
565
713
 
566
714
  // src/constants/kimi.ts
567
715
  var ENDPOINT_KIMI_CHAT_COMPLETIONS_API = "https://api.moonshot.ai/v1/chat/completions";
716
+ var MODEL_KIMI_K3 = "kimi-k3";
568
717
  var MODEL_KIMI_K2_7_CODE = "kimi-k2.7-code";
569
718
  var MODEL_KIMI_K2_7_CODE_HIGHSPEED = "kimi-k2.7-code-highspeed";
570
719
  var MODEL_KIMI_K2_6 = "kimi-k2.6";
571
720
  var MODEL_KIMI_K2_5 = "kimi-k2.5";
721
+ var KIMI_REASONING_EFFORTS_BY_MODEL = {
722
+ [MODEL_KIMI_K3]: ["low", "high", "max"]
723
+ };
572
724
  var KIMI_VISION_SUPPORTED_MODELS = [
725
+ MODEL_KIMI_K3,
573
726
  MODEL_KIMI_K2_7_CODE,
574
727
  MODEL_KIMI_K2_7_CODE_HIGHSPEED,
575
728
  MODEL_KIMI_K2_6,
@@ -585,6 +738,15 @@ var AITuberOnAirChat = (() => {
585
738
  function isKimiThinkingRequiredModel(model) {
586
739
  return KIMI_THINKING_REQUIRED_MODELS.includes(model);
587
740
  }
741
+ function getKimiSupportedReasoningEfforts(model) {
742
+ return KIMI_REASONING_EFFORTS_BY_MODEL[model] ?? [];
743
+ }
744
+ function getDefaultKimiReasoningEffort(model) {
745
+ return model === MODEL_KIMI_K3 ? "max" : void 0;
746
+ }
747
+ function isKimiReasoningEffortModel(model) {
748
+ return getKimiSupportedReasoningEfforts(model).length > 0;
749
+ }
588
750
 
589
751
  // src/constants/deepseek.ts
590
752
  var DEEPSEEK_API_BASE_URL = "https://api.deepseek.com";
@@ -1018,6 +1180,15 @@ If it's in another language, summarize in that language.
1018
1180
  return "";
1019
1181
  }).join("");
1020
1182
  };
1183
+ var throwIfApiError = (data) => {
1184
+ const choice = data.choices?.[0];
1185
+ const error = data.error ?? choice?.error;
1186
+ if (!error && choice?.finish_reason !== "error") {
1187
+ return;
1188
+ }
1189
+ const message = typeof error === "string" ? error : typeof error?.message === "string" ? error.message : "The provider ended the response with an error.";
1190
+ throw new Error(`Provider response error: ${message}`);
1191
+ };
1021
1192
  var forEachSsePayload = async (res, onPayload) => {
1022
1193
  const reader = res.body?.getReader();
1023
1194
  if (!reader) {
@@ -1050,6 +1221,9 @@ If it's in another language, summarize in that language.
1050
1221
  await forEachSsePayload(res, (payload) => {
1051
1222
  const json = parseJsonPayload(payload, options.onJsonError);
1052
1223
  if (!json) return;
1224
+ if (options.throwOnApiError) {
1225
+ throwIfApiError(json);
1226
+ }
1053
1227
  const content = extractTextContent(json.choices?.[0]?.delta?.content);
1054
1228
  if (content) {
1055
1229
  onPartial(content);
@@ -1061,12 +1235,17 @@ If it's in another language, summarize in that language.
1061
1235
  async function parseOpenAICompatibleToolStream(res, onPartial, options = {}) {
1062
1236
  const textBlocks = [];
1063
1237
  const toolCallsMap = /* @__PURE__ */ new Map();
1238
+ let fullContent = "";
1239
+ let reasoningContent = "";
1064
1240
  let finishReason;
1065
1241
  let usage;
1066
1242
  const appendTextBlock = options.appendTextBlock ?? StreamTextAccumulator.append;
1067
1243
  await forEachSsePayload(res, (payload) => {
1068
1244
  const json = parseJsonPayload(payload, options.onJsonError);
1069
1245
  if (!json) return;
1246
+ if (options.throwOnApiError) {
1247
+ throwIfApiError(json);
1248
+ }
1070
1249
  const choice = json.choices?.[0];
1071
1250
  if (typeof choice?.finish_reason === "string") {
1072
1251
  finishReason = choice.finish_reason;
@@ -1079,14 +1258,23 @@ If it's in another language, summarize in that language.
1079
1258
  if (content) {
1080
1259
  onPartial(content);
1081
1260
  appendTextBlock(textBlocks, content);
1261
+ fullContent += content;
1262
+ }
1263
+ const reasoning = extractTextContent(delta?.reasoning_content);
1264
+ if (reasoning) {
1265
+ reasoningContent += reasoning;
1082
1266
  }
1083
1267
  if (delta?.tool_calls) {
1084
1268
  delta.tool_calls.forEach((c) => {
1085
1269
  const entry = toolCallsMap.get(c.index) ?? {
1086
1270
  id: c.id,
1271
+ type: c.type,
1087
1272
  name: c.function?.name,
1088
1273
  args: ""
1089
1274
  };
1275
+ if (c.id) entry.id = c.id;
1276
+ if (c.type) entry.type = c.type;
1277
+ if (c.function?.name) entry.name = c.function.name;
1090
1278
  entry.args += c.function?.arguments || "";
1091
1279
  toolCallsMap.set(c.index, entry);
1092
1280
  });
@@ -1099,17 +1287,38 @@ If it's in another language, summarize in that language.
1099
1287
  input: safeParseToolCallInput(e.args, options.onJsonError)
1100
1288
  }));
1101
1289
  const blocks = [...textBlocks, ...toolBlocks];
1290
+ const assistantToolCalls = Array.from(
1291
+ toolCallsMap.entries()
1292
+ ).sort((a, b) => a[0] - b[0]).map(([_, entry]) => ({
1293
+ id: entry.id,
1294
+ type: "function",
1295
+ function: {
1296
+ name: entry.name,
1297
+ arguments: entry.args
1298
+ }
1299
+ }));
1300
+ const assistantMessage = {
1301
+ role: "assistant",
1302
+ content: fullContent,
1303
+ ...reasoningContent ? { reasoning_content: reasoningContent } : {},
1304
+ ...assistantToolCalls.length > 0 ? { tool_calls: assistantToolCalls } : {}
1305
+ };
1102
1306
  return {
1103
1307
  blocks,
1104
1308
  stop_reason: toolBlocks.length ? "tool_use" : "end",
1105
1309
  truncated: finishReason === "length",
1106
1310
  finish_reason: finishReason,
1107
- usage
1311
+ usage,
1312
+ ...options.preserveAssistantMessage ? { assistant_message: assistantMessage } : {}
1108
1313
  };
1109
1314
  }
1110
1315
  function parseOpenAICompatibleOneShot(data, options = {}) {
1316
+ if (options.throwOnApiError) {
1317
+ throwIfApiError(data);
1318
+ }
1111
1319
  const choice = data?.choices?.[0];
1112
1320
  const blocks = [];
1321
+ const content = extractTextContent(choice?.message?.content);
1113
1322
  if (choice?.message?.tool_calls?.length) {
1114
1323
  choice.message.tool_calls.forEach(
1115
1324
  (c) => blocks.push({
@@ -1122,18 +1331,21 @@ If it's in another language, summarize in that language.
1122
1331
  )
1123
1332
  })
1124
1333
  );
1125
- } else {
1126
- const content = extractTextContent(choice?.message?.content);
1127
- if (content) {
1128
- blocks.push({ type: "text", text: content });
1129
- }
1130
- }
1334
+ } else if (content) {
1335
+ blocks.push({ type: "text", text: content });
1336
+ }
1337
+ const assistantMessage = choice?.message ? {
1338
+ ...choice.message,
1339
+ role: "assistant",
1340
+ content
1341
+ } : void 0;
1131
1342
  return {
1132
1343
  blocks,
1133
1344
  stop_reason: choice?.finish_reason === "tool_calls" || blocks.some((b) => b.type === "tool_use") ? "tool_use" : "end",
1134
1345
  truncated: choice?.finish_reason === "length",
1135
1346
  finish_reason: choice?.finish_reason,
1136
- usage: data?.usage
1347
+ usage: data?.usage,
1348
+ ...options.preserveAssistantMessage ? { assistant_message: assistantMessage } : {}
1137
1349
  };
1138
1350
  }
1139
1351
 
@@ -1161,8 +1373,15 @@ If it's in another language, summarize in that language.
1161
1373
  // src/utils/processChatFlow.ts
1162
1374
  async function processChatWithOptionalTools(options) {
1163
1375
  if (!options.hasTools) {
1164
- const full = await options.runWithoutTools();
1165
- await options.onCompleteResponse(full);
1376
+ const result2 = await options.runWithoutTools();
1377
+ if (typeof result2 === "string") {
1378
+ await options.onCompleteResponse(result2);
1379
+ return;
1380
+ }
1381
+ const full = StreamTextAccumulator.getFullText(
1382
+ result2.blocks
1383
+ );
1384
+ await options.onCompleteResponse(full, result2);
1166
1385
  return;
1167
1386
  }
1168
1387
  const result = await options.runWithTools();
@@ -1173,7 +1392,7 @@ If it's in another language, summarize in that language.
1173
1392
  const full = StreamTextAccumulator.getFullText(
1174
1393
  result.blocks
1175
1394
  );
1176
- await options.onCompleteResponse(full);
1395
+ await options.onCompleteResponse(full, result);
1177
1396
  return;
1178
1397
  }
1179
1398
  throw new Error(options.toolErrorMessage);
@@ -1404,11 +1623,17 @@ If it's in another language, summarize in that language.
1404
1623
  function convertMessagesToClaudeFormat(messages) {
1405
1624
  return messages.map((msg) => ({
1406
1625
  role: mapRoleToClaude(msg.role),
1407
- content: msg.content
1626
+ content: msg.provider_content ?? msg.content
1408
1627
  }));
1409
1628
  }
1410
1629
  function convertVisionMessagesToClaudeFormat(messages) {
1411
1630
  return messages.map((msg) => {
1631
+ if (msg.provider_content) {
1632
+ return {
1633
+ role: mapRoleToClaude(msg.role),
1634
+ content: msg.provider_content
1635
+ };
1636
+ }
1412
1637
  if (typeof msg.content === "string") {
1413
1638
  return {
1414
1639
  role: mapRoleToClaude(msg.role),
@@ -1499,7 +1724,7 @@ If it's in another language, summarize in that language.
1499
1724
  * @param mcpServers Array of MCP server configurations (optional)
1500
1725
  * @throws Error if the vision model doesn't support vision capabilities
1501
1726
  */
1502
- constructor(apiKey, model = MODEL_CLAUDE_4_5_HAIKU, visionModel = MODEL_CLAUDE_4_5_HAIKU, tools = [], mcpServers = [], responseLength) {
1727
+ constructor(apiKey, model = MODEL_CLAUDE_4_5_HAIKU, visionModel = MODEL_CLAUDE_4_5_HAIKU, tools = [], mcpServers = [], responseLength, reasoningEffort) {
1503
1728
  /** Provider name */
1504
1729
  this.provider = "claude";
1505
1730
  this.apiKey = apiKey;
@@ -1508,6 +1733,7 @@ If it's in another language, summarize in that language.
1508
1733
  this.tools = tools;
1509
1734
  this.mcpServers = mcpServers;
1510
1735
  this.responseLength = responseLength;
1736
+ this.reasoningEffort = reasoningEffort;
1511
1737
  if (!CLAUDE_VISION_SUPPORTED_MODELS.includes(this.visionModel)) {
1512
1738
  throw new Error(
1513
1739
  `Model ${this.visionModel} does not support vision capabilities.`
@@ -1617,6 +1843,9 @@ If it's in another language, summarize in that language.
1617
1843
  stream,
1618
1844
  max_tokens: maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength)
1619
1845
  };
1846
+ if (this.reasoningEffort !== void 0 && getClaudeSupportedReasoningEfforts(model).includes(this.reasoningEffort)) {
1847
+ body.output_config = { effort: this.reasoningEffort };
1848
+ }
1620
1849
  if (this.tools.length) {
1621
1850
  body.tools = this.tools.map((t) => ({
1622
1851
  name: t.name,
@@ -1654,6 +1883,7 @@ If it's in another language, summarize in that language.
1654
1883
  const reader = res.body.getReader();
1655
1884
  const dec = new TextDecoder();
1656
1885
  const textBlocks = [];
1886
+ const providerBlocks = /* @__PURE__ */ new Map();
1657
1887
  const toolCalls = /* @__PURE__ */ new Map();
1658
1888
  let buf = "";
1659
1889
  while (true) {
@@ -1668,9 +1898,28 @@ If it's in another language, summarize in that language.
1668
1898
  const payload = line.slice(5).trim();
1669
1899
  if (payload === "[DONE]") break;
1670
1900
  const ev = JSON.parse(payload);
1671
- if (ev.type === "content_block_delta" && ev.delta?.text) {
1901
+ if (ev.type === "content_block_start" && ev.content_block && typeof ev.index === "number") {
1902
+ providerBlocks.set(ev.index, { ...ev.content_block });
1903
+ }
1904
+ if (ev.type === "content_block_delta" && ev.delta?.type === "text_delta") {
1672
1905
  onPartial(ev.delta.text);
1673
1906
  textBlocks.push({ type: "text", text: ev.delta.text });
1907
+ const block = providerBlocks.get(ev.index);
1908
+ if (block?.type === "text") {
1909
+ block.text = `${block.text ?? ""}${ev.delta.text}`;
1910
+ }
1911
+ }
1912
+ if (ev.type === "content_block_delta" && ev.delta?.type === "thinking_delta") {
1913
+ const block = providerBlocks.get(ev.index);
1914
+ if (block?.type === "thinking") {
1915
+ block.thinking = `${block.thinking ?? ""}${ev.delta.thinking ?? ""}`;
1916
+ }
1917
+ }
1918
+ if (ev.type === "content_block_delta" && ev.delta?.type === "signature_delta") {
1919
+ const block = providerBlocks.get(ev.index);
1920
+ if (block?.type === "thinking") {
1921
+ block.signature = `${block.signature ?? ""}${ev.delta.signature ?? ""}`;
1922
+ }
1674
1923
  }
1675
1924
  if (ev.type === "content_block_start" && ev.content_block?.type === "tool_use") {
1676
1925
  toolCalls.set(ev.index, {
@@ -1706,20 +1955,25 @@ If it's in another language, summarize in that language.
1706
1955
  }
1707
1956
  if (ev.type === "content_block_stop" && toolCalls.has(ev.index)) {
1708
1957
  const { id, name, args, server_name } = toolCalls.get(ev.index);
1958
+ const input = JSON.parse(args || "{}");
1959
+ const providerBlock = providerBlocks.get(ev.index);
1960
+ if (providerBlock) {
1961
+ providerBlock.input = input;
1962
+ }
1709
1963
  if (server_name) {
1710
1964
  textBlocks.push({
1711
1965
  type: "mcp_tool_use",
1712
1966
  id,
1713
1967
  name,
1714
1968
  server_name,
1715
- input: JSON.parse(args || "{}")
1969
+ input
1716
1970
  });
1717
1971
  } else {
1718
1972
  textBlocks.push({
1719
1973
  type: "tool_use",
1720
1974
  id,
1721
1975
  name,
1722
- input: JSON.parse(args || "{}")
1976
+ input
1723
1977
  });
1724
1978
  }
1725
1979
  toolCalls.delete(ev.index);
@@ -1728,6 +1982,7 @@ If it's in another language, summarize in that language.
1728
1982
  }
1729
1983
  return {
1730
1984
  blocks: textBlocks,
1985
+ providerContent: [...providerBlocks.entries()].sort(([a], [b]) => a - b).map(([, block]) => block),
1731
1986
  stop_reason: textBlocks.some(
1732
1987
  (b) => b.type === "tool_use" || b.type === "mcp_tool_use"
1733
1988
  ) ? "tool_use" : "end"
@@ -1774,6 +2029,7 @@ If it's in another language, summarize in that language.
1774
2029
  });
1775
2030
  return {
1776
2031
  blocks,
2032
+ providerContent: (data.content ?? []).map((block) => ({ ...block })),
1777
2033
  stop_reason: blocks.some(
1778
2034
  (b) => b.type === "tool_use" || b.type === "mcp_tool_use"
1779
2035
  ) ? "tool_use" : "end"
@@ -1825,7 +2081,12 @@ If it's in another language, summarize in that language.
1825
2081
  );
1826
2082
  return {
1827
2083
  blocks: standardBlocks,
1828
- stop_reason: completion.stop_reason
2084
+ stop_reason: completion.stop_reason,
2085
+ assistant_message: {
2086
+ role: "assistant",
2087
+ content: standardBlocks.filter((block) => block.type === "text").map((block) => block.text).join(""),
2088
+ provider_content: completion.providerContent
2089
+ }
1829
2090
  };
1830
2091
  }
1831
2092
  };
@@ -1838,21 +2099,30 @@ If it's in another language, summarize in that language.
1838
2099
  * @returns ClaudeChatService instance
1839
2100
  */
1840
2101
  createChatService(options) {
2102
+ const model = options.model || this.getDefaultModel();
2103
+ const supportedReasoningEfforts = getClaudeSupportedReasoningEfforts(model);
2104
+ if (options.reasoning_effort !== void 0 && !supportedReasoningEfforts.includes(options.reasoning_effort)) {
2105
+ const supportedMessage = supportedReasoningEfforts.length > 0 ? `Supported values: ${supportedReasoningEfforts.join(", ")}.` : "This model does not expose configurable effort.";
2106
+ throw new Error(
2107
+ `Model ${model} does not support Claude reasoning_effort: ${options.reasoning_effort}. ${supportedMessage}`
2108
+ );
2109
+ }
1841
2110
  const visionModel = resolveVisionModel({
1842
- model: options.model,
2111
+ model,
1843
2112
  visionModel: options.visionModel,
1844
2113
  defaultModel: this.getDefaultModel(),
1845
2114
  defaultVisionModel: this.getDefaultModel(),
1846
- supportsVisionForModel: (model) => this.supportsVisionForModel(model),
2115
+ supportsVisionForModel: (model2) => this.supportsVisionForModel(model2),
1847
2116
  validate: "resolved"
1848
2117
  });
1849
2118
  return new ClaudeChatService(
1850
2119
  options.apiKey,
1851
- options.model || this.getDefaultModel(),
2120
+ model,
1852
2121
  visionModel,
1853
2122
  options.tools ?? [],
1854
2123
  options.mcpServers ?? [],
1855
- options.responseLength
2124
+ options.responseLength,
2125
+ options.reasoning_effort
1856
2126
  );
1857
2127
  }
1858
2128
  /**
@@ -1878,6 +2148,7 @@ If it's in another language, summarize in that language.
1878
2148
  MODEL_CLAUDE_4_7_OPUS,
1879
2149
  MODEL_CLAUDE_4_8_OPUS,
1880
2150
  MODEL_CLAUDE_5_SONNET,
2151
+ MODEL_CLAUDE_5_OPUS,
1881
2152
  MODEL_CLAUDE_3_HAIKU
1882
2153
  ];
1883
2154
  }
@@ -2732,41 +3003,26 @@ If it's in another language, summarize in that language.
2732
3003
  gemini.push({ role: currentRole, parts: [...currentParts] });
2733
3004
  currentParts = [];
2734
3005
  }
3006
+ currentRole = null;
2735
3007
  };
2736
3008
  for (const msg of messages) {
2737
3009
  const role = mapRoleToGemini(msg.role);
2738
3010
  if (msg.tool_calls) {
2739
3011
  pushCurrent();
2740
- for (const call of msg.tool_calls) {
2741
- options.callIdMap?.set(call.id, call.function.name);
3012
+ const parts = msg.tool_calls.map(
3013
+ (call) => createFunctionCallPart(call, options)
3014
+ );
3015
+ if (parts.length > 0) {
2742
3016
  gemini.push({
2743
3017
  role: "model",
2744
- parts: [
2745
- {
2746
- functionCall: {
2747
- name: call.function.name,
2748
- args: JSON.parse(call.function.arguments || "{}")
2749
- }
2750
- }
2751
- ]
3018
+ parts
2752
3019
  });
2753
3020
  }
2754
3021
  continue;
2755
3022
  }
2756
3023
  if (msg.role === "tool") {
2757
3024
  pushCurrent();
2758
- const funcName = msg.name ?? options.callIdMap?.get(msg.tool_call_id) ?? "result";
2759
- gemini.push({
2760
- role: "user",
2761
- parts: [
2762
- {
2763
- functionResponse: {
2764
- name: funcName,
2765
- response: normalizeToolResult(safeJsonParse2(msg.content))
2766
- }
2767
- }
2768
- ]
2769
- });
3025
+ appendFunctionResponse(gemini, createFunctionResponsePart(msg, options));
2770
3026
  continue;
2771
3027
  }
2772
3028
  if (role !== currentRole) pushCurrent();
@@ -2782,47 +3038,41 @@ If it's in another language, summarize in that language.
2782
3038
  const geminiMessages = [];
2783
3039
  let currentRole = null;
2784
3040
  let currentParts = [];
3041
+ const pushCurrent = () => {
3042
+ if (currentRole && currentParts.length > 0) {
3043
+ geminiMessages.push({
3044
+ role: currentRole,
3045
+ parts: [...currentParts]
3046
+ });
3047
+ currentParts = [];
3048
+ }
3049
+ currentRole = null;
3050
+ };
2785
3051
  for (const msg of messages) {
2786
3052
  const role = mapRoleToGemini(msg.role);
2787
3053
  if (msg.tool_calls) {
2788
- for (const call of msg.tool_calls) {
3054
+ pushCurrent();
3055
+ const parts = msg.tool_calls.map(
3056
+ (call) => createFunctionCallPart(call, options)
3057
+ );
3058
+ if (parts.length > 0) {
2789
3059
  geminiMessages.push({
2790
3060
  role: "model",
2791
- parts: [
2792
- {
2793
- functionCall: {
2794
- name: call.function.name,
2795
- args: JSON.parse(call.function.arguments || "{}")
2796
- }
2797
- }
2798
- ]
3061
+ parts
2799
3062
  });
2800
3063
  }
2801
3064
  continue;
2802
3065
  }
2803
3066
  if (msg.role === "tool") {
2804
- const funcName = msg.name ?? options.callIdMap?.get(msg.tool_call_id) ?? "result";
2805
- geminiMessages.push({
2806
- role: "user",
2807
- parts: [
2808
- {
2809
- functionResponse: {
2810
- name: funcName,
2811
- response: normalizeToolResult(
2812
- safeJsonParse2(msg.content)
2813
- )
2814
- }
2815
- }
2816
- ]
2817
- });
3067
+ pushCurrent();
3068
+ appendFunctionResponse(
3069
+ geminiMessages,
3070
+ createFunctionResponsePart(msg, options)
3071
+ );
2818
3072
  continue;
2819
3073
  }
2820
3074
  if (role !== currentRole && currentParts.length > 0) {
2821
- geminiMessages.push({
2822
- role: currentRole,
2823
- parts: [...currentParts]
2824
- });
2825
- currentParts = [];
3075
+ pushCurrent();
2826
3076
  }
2827
3077
  currentRole = role;
2828
3078
  if (typeof msg.content === "string") {
@@ -2850,14 +3100,43 @@ If it's in another language, summarize in that language.
2850
3100
  }
2851
3101
  }
2852
3102
  }
2853
- if (currentRole && currentParts.length > 0) {
2854
- geminiMessages.push({
2855
- role: currentRole,
2856
- parts: [...currentParts]
2857
- });
2858
- }
3103
+ pushCurrent();
2859
3104
  return geminiMessages;
2860
3105
  }
3106
+ function createFunctionCallPart(call, options) {
3107
+ options.callIdMap?.set(call.id, call.function.name);
3108
+ const context = options.functionCallContextMap?.get(call.id);
3109
+ const part = {
3110
+ functionCall: {
3111
+ ...context?.providerCallId ? { id: context.providerCallId } : {},
3112
+ name: call.function.name,
3113
+ args: JSON.parse(call.function.arguments || "{}")
3114
+ }
3115
+ };
3116
+ if (context?.thoughtSignature) {
3117
+ part.thoughtSignature = context.thoughtSignature;
3118
+ }
3119
+ return part;
3120
+ }
3121
+ function createFunctionResponsePart(msg, options) {
3122
+ const toolCallId = msg.tool_call_id;
3123
+ const context = options.functionCallContextMap?.get(toolCallId);
3124
+ const functionResponse = {
3125
+ ...context?.providerCallId ? { id: context.providerCallId } : {},
3126
+ name: msg.name ?? context?.name ?? options.callIdMap?.get(toolCallId) ?? "result",
3127
+ response: normalizeToolResult(safeJsonParse2(msg.content))
3128
+ };
3129
+ return { functionResponse };
3130
+ }
3131
+ function appendFunctionResponse(messages, part) {
3132
+ const previous = messages[messages.length - 1];
3133
+ const isFunctionResponseGroup = previous?.role === "user" && previous.parts.every((item) => item.functionResponse);
3134
+ if (isFunctionResponseGroup) {
3135
+ previous.parts.push(part);
3136
+ return;
3137
+ }
3138
+ messages.push({ role: "user", parts: [part] });
3139
+ }
2861
3140
  function safeJsonParse2(str) {
2862
3141
  try {
2863
3142
  return JSON.parse(str);
@@ -2935,16 +3214,19 @@ If it's in another language, summarize in that language.
2935
3214
  * @param tools Array of tool definitions
2936
3215
  * @param mcpServers Array of MCP server configurations
2937
3216
  */
2938
- constructor(apiKey, model = MODEL_GEMINI_3_1_FLASH_LITE, visionModel = MODEL_GEMINI_3_1_FLASH_LITE, tools = [], mcpServers = [], responseLength) {
3217
+ constructor(apiKey, model = MODEL_GEMINI_3_1_FLASH_LITE, visionModel = MODEL_GEMINI_3_1_FLASH_LITE, tools = [], mcpServers = [], responseLength, reasoningEffort) {
2939
3218
  /** Provider name */
2940
3219
  this.provider = "gemini";
2941
3220
  this.mcpToolSchemas = [];
2942
3221
  this.mcpSchemasInitialized = false;
2943
3222
  /** id(OpenAI) → name(Gemini) mapping */
2944
3223
  this.callIdMap = /* @__PURE__ */ new Map();
3224
+ /** Common tool id → Gemini function-call metadata required for replay. */
3225
+ this.functionCallContextMap = /* @__PURE__ */ new Map();
2945
3226
  this.apiKey = apiKey;
2946
3227
  this.model = model;
2947
3228
  this.responseLength = responseLength;
3229
+ this.reasoningEffort = reasoningEffort;
2948
3230
  if (!GEMINI_VISION_SUPPORTED_MODELS.includes(visionModel)) {
2949
3231
  throw new Error(
2950
3232
  `Model ${visionModel} does not support vision capabilities.`
@@ -2957,8 +3239,21 @@ If it's in another language, summarize in that language.
2957
3239
  isGemma4Model(model) {
2958
3240
  return /^gemma-4-/.test(model);
2959
3241
  }
2960
- shouldMinimizeThinking(model) {
2961
- return model === MODEL_GEMINI_3_5_FLASH || this.isGemma4Model(model);
3242
+ resolveThinkingConfig(model) {
3243
+ const effort = normalizeGeminiReasoningEffort(model, this.reasoningEffort);
3244
+ if (effort) {
3245
+ return {
3246
+ includeThoughts: false,
3247
+ thinkingLevel: effort.toUpperCase()
3248
+ };
3249
+ }
3250
+ if (this.isGemma4Model(model)) {
3251
+ return {
3252
+ includeThoughts: false,
3253
+ thinkingLevel: "MINIMAL"
3254
+ };
3255
+ }
3256
+ return void 0;
2962
3257
  }
2963
3258
  shouldExposeTextPart(part, model) {
2964
3259
  if (!part.text) return false;
@@ -2976,7 +3271,8 @@ If it's in another language, summarize in that language.
2976
3271
  functionCallingConfig: "function_calling_config",
2977
3272
  functionDeclarations: "function_declarations",
2978
3273
  functionCall: "function_call",
2979
- functionResponse: "function_response"
3274
+ functionResponse: "function_response",
3275
+ thoughtSignature: "thought_signature"
2980
3276
  };
2981
3277
  if (Array.isArray(obj)) return obj.map((v) => this.adaptKeysForApi(v));
2982
3278
  if (obj && typeof obj === "object") {
@@ -3136,10 +3432,12 @@ If it's in another language, summarize in that language.
3136
3432
  const contents = hasVision ? await convertVisionMessagesToGeminiFormat(
3137
3433
  messages,
3138
3434
  {
3139
- callIdMap: this.callIdMap
3435
+ callIdMap: this.callIdMap,
3436
+ functionCallContextMap: this.functionCallContextMap
3140
3437
  }
3141
3438
  ) : convertMessagesToGeminiFormat(messages, {
3142
- callIdMap: this.callIdMap
3439
+ callIdMap: this.callIdMap,
3440
+ functionCallContextMap: this.functionCallContextMap
3143
3441
  });
3144
3442
  const body = {
3145
3443
  contents,
@@ -3147,11 +3445,9 @@ If it's in another language, summarize in that language.
3147
3445
  maxOutputTokens: maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength)
3148
3446
  }
3149
3447
  };
3150
- if (this.shouldMinimizeThinking(model)) {
3151
- body.generationConfig.thinkingConfig = {
3152
- includeThoughts: false,
3153
- thinkingLevel: "MINIMAL"
3154
- };
3448
+ const thinkingConfig = this.resolveThinkingConfig(model);
3449
+ if (thinkingConfig) {
3450
+ body.generationConfig.thinkingConfig = thinkingConfig;
3155
3451
  }
3156
3452
  let activeMCPToolSchemas = [];
3157
3453
  if (this.mcpServers.length > 0) {
@@ -3208,6 +3504,32 @@ If it's in another language, summarize in that language.
3208
3504
  throw error;
3209
3505
  }
3210
3506
  }
3507
+ createFunctionCallBlock(part) {
3508
+ const functionCall = part.functionCall ?? part.function_call;
3509
+ if (!functionCall) return void 0;
3510
+ const toolUseId = functionCall.id ?? this.genUUID();
3511
+ this.callIdMap.set(toolUseId, functionCall.name);
3512
+ this.functionCallContextMap.set(toolUseId, {
3513
+ name: functionCall.name,
3514
+ providerCallId: functionCall.id,
3515
+ thoughtSignature: part.thoughtSignature ?? part.thought_signature
3516
+ });
3517
+ return {
3518
+ type: "tool_use",
3519
+ id: toolUseId,
3520
+ name: functionCall.name,
3521
+ input: functionCall.args ?? {}
3522
+ };
3523
+ }
3524
+ createFunctionResponseBlock(part) {
3525
+ const functionResponse = part.functionResponse ?? part.function_response;
3526
+ if (!functionResponse) return void 0;
3527
+ return {
3528
+ type: "tool_result",
3529
+ tool_use_id: functionResponse.id ?? functionResponse.name,
3530
+ content: JSON.stringify(functionResponse.response)
3531
+ };
3532
+ }
3211
3533
  /* ────────────────────────────────────────────────────────── */
3212
3534
  /* Convert NDJSON stream to common format */
3213
3535
  /* ────────────────────────────────────────────────────────── */
@@ -3231,21 +3553,10 @@ If it's in another language, summarize in that language.
3231
3553
  onPartial(part.text);
3232
3554
  StreamTextAccumulator.addTextBlock(textBlocks, part.text);
3233
3555
  }
3234
- if (part.functionCall) {
3235
- toolBlocks.push({
3236
- type: "tool_use",
3237
- id: this.genUUID(),
3238
- name: part.functionCall.name,
3239
- input: part.functionCall.args ?? {}
3240
- });
3241
- }
3242
- if (part.functionResponse) {
3243
- toolBlocks.push({
3244
- type: "tool_result",
3245
- tool_use_id: part.functionResponse.name,
3246
- content: JSON.stringify(part.functionResponse.response)
3247
- });
3248
- }
3556
+ const functionCallBlock = this.createFunctionCallBlock(part);
3557
+ if (functionCallBlock) toolBlocks.push(functionCallBlock);
3558
+ const functionResponseBlock = this.createFunctionResponseBlock(part);
3559
+ if (functionResponseBlock) toolBlocks.push(functionResponseBlock);
3249
3560
  }
3250
3561
  }
3251
3562
  };
@@ -3285,21 +3596,10 @@ If it's in another language, summarize in that language.
3285
3596
  if (this.shouldExposeTextPart(part, model)) {
3286
3597
  textBlocks.push({ type: "text", text: part.text });
3287
3598
  }
3288
- if (part.functionCall) {
3289
- toolBlocks.push({
3290
- type: "tool_use",
3291
- id: this.genUUID(),
3292
- name: part.functionCall.name,
3293
- input: part.functionCall.args ?? {}
3294
- });
3295
- }
3296
- if (part.functionResponse) {
3297
- toolBlocks.push({
3298
- type: "tool_result",
3299
- tool_use_id: part.functionResponse.name,
3300
- content: JSON.stringify(part.functionResponse.response)
3301
- });
3302
- }
3599
+ const functionCallBlock = this.createFunctionCallBlock(part);
3600
+ if (functionCallBlock) toolBlocks.push(functionCallBlock);
3601
+ const functionResponseBlock = this.createFunctionResponseBlock(part);
3602
+ if (functionResponseBlock) toolBlocks.push(functionResponseBlock);
3303
3603
  }
3304
3604
  }
3305
3605
  const blocks = [...textBlocks, ...toolBlocks];
@@ -3349,21 +3649,28 @@ If it's in another language, summarize in that language.
3349
3649
  * @returns GeminiChatService instance
3350
3650
  */
3351
3651
  createChatService(options) {
3652
+ const model = options.model || this.getDefaultModel();
3653
+ if (options.reasoning_effort !== void 0 && !isGeminiReasoningEffortModel(model)) {
3654
+ throw new Error(
3655
+ `Model ${model} does not support Gemini reasoning_effort. Use it with Gemini 3 thinkingLevel models; Gemini 2.5 models use thinkingBudget instead.`
3656
+ );
3657
+ }
3352
3658
  const visionModel = resolveVisionModel({
3353
- model: options.model,
3659
+ model,
3354
3660
  visionModel: options.visionModel,
3355
3661
  defaultModel: this.getDefaultModel(),
3356
3662
  defaultVisionModel: this.getDefaultModel(),
3357
- supportsVisionForModel: (model) => this.supportsVisionForModel(model),
3663
+ supportsVisionForModel: (model2) => this.supportsVisionForModel(model2),
3358
3664
  validate: "resolved"
3359
3665
  });
3360
3666
  return new GeminiChatService(
3361
3667
  options.apiKey,
3362
- options.model || this.getDefaultModel(),
3668
+ model,
3363
3669
  visionModel,
3364
3670
  options.tools || [],
3365
3671
  options.mcpServers || [],
3366
- options.responseLength
3672
+ options.responseLength,
3673
+ normalizeGeminiReasoningEffort(model, options.reasoning_effort)
3367
3674
  );
3368
3675
  }
3369
3676
  /**
@@ -3420,8 +3727,14 @@ If it's in another language, summarize in that language.
3420
3727
  var GeminiNanoChatService = class {
3421
3728
  constructor(options = {}) {
3422
3729
  this.provider = "gemini-nano";
3423
- this.expectedInputLanguages = options.expectedInputLanguages ?? ["ja"];
3730
+ this.expectedInputLanguages = options.expectedInputLanguages ?? [
3731
+ "ja",
3732
+ "en"
3733
+ ];
3424
3734
  this.expectedOutputLanguages = options.expectedOutputLanguages ?? ["ja"];
3735
+ this.initialPrompts = (options.initialPrompts ?? []).map((prompt) => ({
3736
+ ...prompt
3737
+ }));
3425
3738
  this._responseLength = options.responseLength;
3426
3739
  }
3427
3740
  getModel() {
@@ -3466,7 +3779,8 @@ If it's in another language, summarize in that language.
3466
3779
  "Gemini Nano is not available in this environment. Chrome 138+ with Prompt API enabled is required."
3467
3780
  );
3468
3781
  }
3469
- const availability = await api.availability();
3782
+ const modelOptions = this.getModelOptions();
3783
+ const availability = await api.availability(modelOptions);
3470
3784
  if (availability !== "available" && availability !== "downloadable") {
3471
3785
  throw new Error(
3472
3786
  `Gemini Nano Prompt API is not ready in this environment. LanguageModel.availability() returned "${availability}". Expected "available" or "downloadable".`
@@ -3474,15 +3788,17 @@ If it's in another language, summarize in that language.
3474
3788
  }
3475
3789
  const systemMessages = messages.filter((m) => m.role === "system");
3476
3790
  const systemPrompt = systemMessages.map((m) => m.content).join("\n");
3477
- const conversationMessages = messages.filter((m) => m.role !== "system").slice(-GEMINI_NANO_MAX_CONTEXT_MESSAGES);
3478
- const lastUserMessage = [...conversationMessages].reverse().find((m) => m.role === "user");
3479
- if (!lastUserMessage) {
3791
+ const conversationMessages = messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-GEMINI_NANO_MAX_CONTEXT_MESSAGES);
3792
+ const lastUserMessageIndex = this.findLastUserMessageIndex(conversationMessages);
3793
+ if (lastUserMessageIndex === -1) {
3480
3794
  throw new Error("No user message found in the provided messages.");
3481
3795
  }
3796
+ const lastUserMessage = conversationMessages[lastUserMessageIndex];
3482
3797
  const session = await this.createSession(
3483
3798
  api,
3484
3799
  systemPrompt,
3485
- conversationMessages
3800
+ conversationMessages.slice(0, lastUserMessageIndex),
3801
+ modelOptions
3486
3802
  );
3487
3803
  try {
3488
3804
  return await session.prompt(lastUserMessage.content);
@@ -3494,25 +3810,55 @@ If it's in another language, summarize in that language.
3494
3810
  }
3495
3811
  }
3496
3812
  /**
3497
- * Create a new LanguageModel session with system prompt and context history.
3498
- * Context history (excluding the last user message) is embedded in the system prompt.
3813
+ * Create a new LanguageModel session with structured initial prompts.
3814
+ * System instructions, few-shot examples, and conversation history retain
3815
+ * their roles instead of being flattened into a single string.
3499
3816
  */
3500
- async createSession(api, systemPrompt, contextHistory) {
3501
- let prompt = this.buildSystemPrompt(systemPrompt);
3502
- const historyMessages = contextHistory.slice(0, -1);
3503
- if (historyMessages.length > 0) {
3504
- const history = historyMessages.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n");
3505
- prompt += "\n\nThe following is the prior conversation history. Use it as context for your response:\n" + history;
3506
- }
3507
- return api.create({
3508
- systemPrompt: prompt,
3817
+ async createSession(api, systemPrompt, contextHistory, modelOptions) {
3818
+ const initialPrompts = this.buildInitialPrompts(
3819
+ systemPrompt,
3820
+ contextHistory
3821
+ );
3822
+ const createOptions = {
3823
+ ...modelOptions,
3824
+ ...initialPrompts.length > 0 ? { initialPrompts } : {}
3825
+ };
3826
+ return api.create(createOptions);
3827
+ }
3828
+ getModelOptions() {
3829
+ return {
3509
3830
  expectedInputs: [
3510
3831
  { type: "text", languages: this.expectedInputLanguages }
3511
3832
  ],
3512
3833
  expectedOutputs: [
3513
3834
  { type: "text", languages: this.expectedOutputLanguages }
3514
3835
  ]
3515
- });
3836
+ };
3837
+ }
3838
+ buildInitialPrompts(systemPrompt, contextHistory) {
3839
+ const configuredSystemPrompts = this.initialPrompts.filter((prompt) => prompt.role === "system").map((prompt) => prompt.content);
3840
+ const combinedSystemPrompt = this.buildSystemPrompt(
3841
+ [systemPrompt, ...configuredSystemPrompts].filter(Boolean).join("\n\n")
3842
+ );
3843
+ const prompts = [];
3844
+ if (combinedSystemPrompt) {
3845
+ prompts.push({ role: "system", content: combinedSystemPrompt });
3846
+ }
3847
+ prompts.push(
3848
+ ...this.initialPrompts.filter((prompt) => prompt.role !== "system").map((prompt) => ({ ...prompt })),
3849
+ ...contextHistory.filter(
3850
+ (message) => message.role === "user" || message.role === "assistant"
3851
+ ).map(({ role, content }) => ({ role, content }))
3852
+ );
3853
+ return prompts;
3854
+ }
3855
+ findLastUserMessageIndex(messages) {
3856
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
3857
+ if (messages[index].role === "user") {
3858
+ return index;
3859
+ }
3860
+ }
3861
+ return -1;
3516
3862
  }
3517
3863
  buildSystemPrompt(systemPrompt) {
3518
3864
  const promptParts = [];
@@ -3533,7 +3879,20 @@ If it's in another language, summarize in that language.
3533
3879
  if (!maxTokens) {
3534
3880
  return void 0;
3535
3881
  }
3536
- return `Please keep your response concise, within approximately ${maxTokens} tokens.`;
3882
+ switch (this._responseLength) {
3883
+ case CHAT_RESPONSE_LENGTH.VERY_SHORT:
3884
+ return `Reply in no more than one concise sentence. Do not use a preamble, summary, bullet points, or Markdown. Keep the reaction and answer short enough to read in one breath. Stay within approximately ${maxTokens} tokens.`;
3885
+ case CHAT_RESPONSE_LENGTH.SHORT:
3886
+ return `Reply in no more than two concise sentences. Do not use a preamble, summary, bullet points, or Markdown. Keep the reaction and answer short enough to read in one breath. Use natural conversational language. Stay within approximately ${maxTokens} tokens.`;
3887
+ case CHAT_RESPONSE_LENGTH.MEDIUM:
3888
+ return `Reply in no more than three concise sentences. Answer directly and include only the context needed to understand the answer. Do not use a preamble, summary, bullet points, or Markdown. Use natural conversational language. Stay within approximately ${maxTokens} tokens.`;
3889
+ case CHAT_RESPONSE_LENGTH.LONG:
3890
+ return `Reply in no more than five sentences. Explain the important details clearly, but avoid unnecessary preambles, repetition, bullet points, or Markdown. Use natural conversational language. Stay within approximately ${maxTokens} tokens.`;
3891
+ case CHAT_RESPONSE_LENGTH.VERY_LONG:
3892
+ return `Reply in no more than ten sentences. Give a thorough but focused answer. Use short plain-text paragraphs when helpful, and avoid unnecessary repetition, bullet points, or Markdown. Stay within approximately ${maxTokens} tokens.`;
3893
+ case CHAT_RESPONSE_LENGTH.DEEP:
3894
+ return `Give a detailed response and organize it in the way that best fits the request. No sentence-count limit applies at this level. Stay within approximately ${maxTokens} tokens.`;
3895
+ }
3537
3896
  }
3538
3897
  };
3539
3898
 
@@ -3543,6 +3902,7 @@ If it's in another language, summarize in that language.
3543
3902
  return new GeminiNanoChatService({
3544
3903
  expectedInputLanguages: options.expectedInputLanguages,
3545
3904
  expectedOutputLanguages: options.expectedOutputLanguages,
3905
+ initialPrompts: options.initialPrompts,
3546
3906
  responseLength: options.responseLength
3547
3907
  });
3548
3908
  }
@@ -3571,7 +3931,7 @@ If it's in another language, summarize in that language.
3571
3931
  * @param model Name of the model to use
3572
3932
  * @param visionModel Name of the vision model
3573
3933
  */
3574
- constructor(apiKey, model = MODEL_KIMI_K2_6, visionModel = MODEL_KIMI_K2_6, tools, endpoint = ENDPOINT_KIMI_CHAT_COMPLETIONS_API, responseLength, responseFormat, thinking) {
3934
+ constructor(apiKey, model = MODEL_KIMI_K2_6, visionModel = MODEL_KIMI_K2_6, tools, endpoint = ENDPOINT_KIMI_CHAT_COMPLETIONS_API, responseLength, responseFormat, thinking, reasoningEffort) {
3575
3935
  /** Provider name */
3576
3936
  this.provider = "kimi";
3577
3937
  this.apiKey = apiKey;
@@ -3580,7 +3940,14 @@ If it's in another language, summarize in that language.
3580
3940
  this.endpoint = endpoint;
3581
3941
  this.responseLength = responseLength;
3582
3942
  this.responseFormat = responseFormat;
3583
- this.thinking = thinking ?? { type: "enabled" };
3943
+ this.thinking = thinking;
3944
+ const supportedReasoningEfforts = getKimiSupportedReasoningEfforts(model);
3945
+ if (reasoningEffort !== void 0 && !supportedReasoningEfforts.includes(reasoningEffort)) {
3946
+ throw new Error(
3947
+ `Model ${model} does not support reasoning_effort: ${reasoningEffort}.`
3948
+ );
3949
+ }
3950
+ this.reasoningEffort = reasoningEffort ?? getDefaultKimiReasoningEffort(model);
3584
3951
  this.visionModel = visionModel;
3585
3952
  }
3586
3953
  /**
@@ -3601,10 +3968,7 @@ If it's in another language, summarize in that language.
3601
3968
  async processChat(messages, onPartialResponse, onCompleteResponse) {
3602
3969
  await processChatWithOptionalTools({
3603
3970
  hasTools: this.tools.length > 0,
3604
- runWithoutTools: async () => {
3605
- const res = await this.callKimi(messages, this.model, true);
3606
- return this.handleStream(res, onPartialResponse);
3607
- },
3971
+ runWithoutTools: () => this.chatOnce(messages, true, onPartialResponse),
3608
3972
  runWithTools: () => this.chatOnce(messages, true, onPartialResponse),
3609
3973
  onCompleteResponse,
3610
3974
  toolErrorMessage: "processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."
@@ -3621,10 +3985,7 @@ If it's in another language, summarize in that language.
3621
3985
  }
3622
3986
  await processChatWithOptionalTools({
3623
3987
  hasTools: this.tools.length > 0,
3624
- runWithoutTools: async () => {
3625
- const res = await this.callKimi(messages, this.visionModel, true);
3626
- return this.handleStream(res, onPartialResponse);
3627
- },
3988
+ runWithoutTools: () => this.visionChatOnce(messages, true, onPartialResponse),
3628
3989
  runWithTools: () => this.visionChatOnce(messages, true, onPartialResponse),
3629
3990
  onCompleteResponse,
3630
3991
  toolErrorMessage: "processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."
@@ -3677,11 +4038,18 @@ If it's in another language, summarize in that language.
3677
4038
  };
3678
4039
  const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
3679
4040
  if (tokenLimit !== void 0) {
3680
- body.max_tokens = tokenLimit;
4041
+ if (isKimiReasoningEffortModel(model)) {
4042
+ body.max_completion_tokens = tokenLimit;
4043
+ } else {
4044
+ body.max_tokens = tokenLimit;
4045
+ }
3681
4046
  }
3682
4047
  if (this.responseFormat) {
3683
4048
  body.response_format = this.responseFormat;
3684
4049
  }
4050
+ if (isKimiReasoningEffortModel(model)) {
4051
+ body.reasoning_effort = this.reasoningEffort ?? getDefaultKimiReasoningEffort(model);
4052
+ }
3685
4053
  const effectiveThinking = this.resolveEffectiveThinking(model);
3686
4054
  if (effectiveThinking) {
3687
4055
  if (this.isSelfHostedEndpoint()) {
@@ -3706,6 +4074,14 @@ If it's in another language, summarize in that language.
3706
4074
  return value.replace(/\/+$/, "");
3707
4075
  }
3708
4076
  resolveEffectiveThinking(model) {
4077
+ if (isKimiReasoningEffortModel(model)) {
4078
+ if (this.thinking) {
4079
+ throw new Error(
4080
+ `Model ${model} uses reasoning_effort and does not support the K2.x thinking option.`
4081
+ );
4082
+ }
4083
+ return void 0;
4084
+ }
3709
4085
  if (isKimiThinkingRequiredModel(model)) {
3710
4086
  if (this.thinking?.type === "disabled") {
3711
4087
  throw new Error(
@@ -3717,21 +4093,17 @@ If it's in another language, summarize in that language.
3717
4093
  if (this.tools.length > 0) {
3718
4094
  return { type: "disabled" };
3719
4095
  }
3720
- return this.thinking;
4096
+ return this.thinking ?? { type: "enabled" };
3721
4097
  }
3722
4098
  buildToolsDefinition() {
3723
4099
  return buildOpenAICompatibleTools(this.tools, "chat-completions");
3724
4100
  }
3725
- async handleStream(res, onPartial) {
3726
- return parseOpenAICompatibleTextStream(res, onPartial, {
3727
- onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
3728
- });
3729
- }
3730
4101
  /**
3731
4102
  * Parse streaming response with tool support
3732
4103
  */
3733
4104
  async parseStream(res, onPartial) {
3734
4105
  return parseOpenAICompatibleToolStream(res, onPartial, {
4106
+ preserveAssistantMessage: true,
3735
4107
  onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
3736
4108
  });
3737
4109
  }
@@ -3739,7 +4111,9 @@ If it's in another language, summarize in that language.
3739
4111
  * Parse non-streaming response
3740
4112
  */
3741
4113
  parseOneShot(data) {
3742
- return parseOpenAICompatibleOneShot(data);
4114
+ return parseOpenAICompatibleOneShot(data, {
4115
+ preserveAssistantMessage: true
4116
+ });
3743
4117
  }
3744
4118
  };
3745
4119
 
@@ -3764,6 +4138,10 @@ If it's in another language, summarize in that language.
3764
4138
  });
3765
4139
  const tools = options.tools;
3766
4140
  const thinking = this.resolveThinking(model, tools, options.thinking);
4141
+ const reasoningEffort = this.resolveReasoningEffort(
4142
+ model,
4143
+ options.reasoning_effort
4144
+ );
3767
4145
  return new KimiChatService(
3768
4146
  options.apiKey,
3769
4147
  model,
@@ -3772,7 +4150,8 @@ If it's in another language, summarize in that language.
3772
4150
  endpoint,
3773
4151
  options.responseLength,
3774
4152
  options.responseFormat,
3775
- thinking
4153
+ thinking,
4154
+ reasoningEffort
3776
4155
  );
3777
4156
  }
3778
4157
  /**
@@ -3786,6 +4165,7 @@ If it's in another language, summarize in that language.
3786
4165
  */
3787
4166
  getSupportedModels() {
3788
4167
  return [
4168
+ MODEL_KIMI_K3,
3789
4169
  MODEL_KIMI_K2_7_CODE,
3790
4170
  MODEL_KIMI_K2_7_CODE_HIGHSPEED,
3791
4171
  MODEL_KIMI_K2_6,
@@ -3839,6 +4219,14 @@ If it's in another language, summarize in that language.
3839
4219
  return value.replace(/\/+$/, "");
3840
4220
  }
3841
4221
  resolveThinking(model, tools, thinking) {
4222
+ if (isKimiReasoningEffortModel(model)) {
4223
+ if (thinking) {
4224
+ throw new Error(
4225
+ `Model ${model} uses reasoning_effort and does not support the K2.x thinking option.`
4226
+ );
4227
+ }
4228
+ return void 0;
4229
+ }
3842
4230
  if (isKimiThinkingRequiredModel(model)) {
3843
4231
  if (thinking?.type === "disabled") {
3844
4232
  throw new Error(
@@ -3852,6 +4240,24 @@ If it's in another language, summarize in that language.
3852
4240
  }
3853
4241
  return thinking ?? this.defaultThinking;
3854
4242
  }
4243
+ resolveReasoningEffort(model, reasoningEffort) {
4244
+ const supported = getKimiSupportedReasoningEfforts(model);
4245
+ if (supported.length === 0) {
4246
+ if (reasoningEffort !== void 0) {
4247
+ throw new Error(
4248
+ `Model ${model} does not support the reasoning_effort option.`
4249
+ );
4250
+ }
4251
+ return void 0;
4252
+ }
4253
+ const resolved = reasoningEffort ?? getDefaultKimiReasoningEffort(model) ?? supported[0];
4254
+ if (!supported.includes(resolved)) {
4255
+ throw new Error(
4256
+ `Model ${model} supports reasoning_effort values: ${supported.join(", ")}.`
4257
+ );
4258
+ }
4259
+ return resolved;
4260
+ }
3855
4261
  };
3856
4262
 
3857
4263
  // src/services/providers/mistral/MistralChatService.ts
@@ -4198,8 +4604,19 @@ If it's in another language, summarize in that language.
4198
4604
  };
4199
4605
 
4200
4606
  // src/services/providers/openrouter/OpenRouterChatService.ts
4607
+ var isOpenRouterAutoModel = (model) => [MODEL_OPENROUTER_AUTO, MODEL_OPENROUTER_AUTO_BETA].includes(model.trim());
4201
4608
  var isTokenLimitUnsupportedModel = (model) => [MODEL_GPT_OSS_20B_FREE, MODEL_ZAI_GLM_5_2].includes(model.trim());
4202
4609
  var getDefaultReasoningEffort = (model) => model.trim() === MODEL_ZAI_GLM_5_2 ? "none" : void 0;
4610
+ var ensureAutoRouterOutput = (model, hasVisibleOutput) => {
4611
+ if (isOpenRouterAutoModel(model) && !hasVisibleOutput) {
4612
+ throw new Error(
4613
+ "OpenRouter Auto Router returned no visible content. Please retry."
4614
+ );
4615
+ }
4616
+ };
4617
+ var hasUsableCompletionOutput = (completion) => completion.blocks.some(
4618
+ (block) => block.type !== "text" || block.text.trim().length > 0
4619
+ );
4203
4620
  var OpenRouterChatService = class {
4204
4621
  /**
4205
4622
  * Constructor
@@ -4283,7 +4700,7 @@ If it's in another language, summarize in that language.
4283
4700
  hasTools: this.tools.length > 0,
4284
4701
  runWithoutTools: async () => {
4285
4702
  const res = await this.callOpenRouter(messages, this.model, true);
4286
- return this.handleStream(res, onPartialResponse);
4703
+ return this.handleStream(res, onPartialResponse, this.model);
4287
4704
  },
4288
4705
  runWithTools: () => this.chatOnce(messages, true, onPartialResponse),
4289
4706
  onCompleteResponse,
@@ -4312,7 +4729,7 @@ If it's in another language, summarize in that language.
4312
4729
  this.visionModel,
4313
4730
  true
4314
4731
  );
4315
- return this.handleStream(res, onPartialResponse);
4732
+ return this.handleStream(res, onPartialResponse, this.visionModel);
4316
4733
  },
4317
4734
  runWithTools: () => this.visionChatOnce(messages, true, onPartialResponse),
4318
4735
  onCompleteResponse,
@@ -4340,7 +4757,7 @@ If it's in another language, summarize in that language.
4340
4757
  stream,
4341
4758
  maxTokens
4342
4759
  );
4343
- return stream ? this.parseStream(res, onPartialResponse) : this.parseOneShot(await res.json());
4760
+ return stream ? this.parseStream(res, onPartialResponse, this.model) : this.parseOneShot(await res.json(), this.model);
4344
4761
  }
4345
4762
  /**
4346
4763
  * Process vision chat messages with tools
@@ -4364,7 +4781,7 @@ If it's in another language, summarize in that language.
4364
4781
  stream,
4365
4782
  maxTokens
4366
4783
  );
4367
- return stream ? this.parseStream(res, onPartialResponse) : this.parseOneShot(await res.json());
4784
+ return stream ? this.parseStream(res, onPartialResponse, this.visionModel) : this.parseOneShot(await res.json(), this.visionModel);
4368
4785
  }
4369
4786
  /**
4370
4787
  * Call OpenRouter API
@@ -4393,7 +4810,8 @@ If it's in another language, summarize in that language.
4393
4810
  stream
4394
4811
  };
4395
4812
  const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
4396
- if (tokenLimit && isTokenLimitUnsupportedModel(model)) {
4813
+ const shouldOmitTokenLimit = isTokenLimitUnsupportedModel(model) || isOpenRouterAutoModel(model) && maxTokens === void 0;
4814
+ if (tokenLimit && shouldOmitTokenLimit) {
4397
4815
  console.warn(
4398
4816
  `OpenRouter: Token limits are disabled for ${model} because this model can return empty content when a token limit is set.`
4399
4817
  );
@@ -4428,24 +4846,34 @@ If it's in another language, summarize in that language.
4428
4846
  * Handle streaming response from OpenRouter
4429
4847
  * OpenRouter uses SSE format with potential comment lines
4430
4848
  */
4431
- async handleStream(res, onPartial) {
4432
- return parseOpenAICompatibleTextStream(res, onPartial, {
4433
- onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
4849
+ async handleStream(res, onPartial, model) {
4850
+ const text = await parseOpenAICompatibleTextStream(res, onPartial, {
4851
+ onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload),
4852
+ throwOnApiError: isOpenRouterAutoModel(model)
4434
4853
  });
4854
+ ensureAutoRouterOutput(model, text.trim().length > 0);
4855
+ return text;
4435
4856
  }
4436
4857
  /**
4437
4858
  * Parse streaming response with tool support
4438
4859
  */
4439
- async parseStream(res, onPartial) {
4440
- return parseOpenAICompatibleToolStream(res, onPartial, {
4441
- onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
4860
+ async parseStream(res, onPartial, model) {
4861
+ const completion = await parseOpenAICompatibleToolStream(res, onPartial, {
4862
+ onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload),
4863
+ throwOnApiError: isOpenRouterAutoModel(model)
4442
4864
  });
4865
+ ensureAutoRouterOutput(model, hasUsableCompletionOutput(completion));
4866
+ return completion;
4443
4867
  }
4444
4868
  /**
4445
4869
  * Parse non-streaming response
4446
4870
  */
4447
- parseOneShot(data) {
4448
- return parseOpenAICompatibleOneShot(data);
4871
+ parseOneShot(data, model) {
4872
+ const completion = parseOpenAICompatibleOneShot(data, {
4873
+ throwOnApiError: isOpenRouterAutoModel(model)
4874
+ });
4875
+ ensureAutoRouterOutput(model, hasUsableCompletionOutput(completion));
4876
+ return completion;
4449
4877
  }
4450
4878
  };
4451
4879
 
@@ -4498,6 +4926,7 @@ If it's in another language, summarize in that language.
4498
4926
  return [
4499
4927
  // OpenRouter routing
4500
4928
  MODEL_OPENROUTER_AUTO,
4929
+ MODEL_OPENROUTER_AUTO_BETA,
4501
4930
  MODEL_OPENROUTER_FUSION,
4502
4931
  // Free models
4503
4932
  MODEL_GPT_OSS_20B_FREE,
@@ -4505,6 +4934,9 @@ If it's in another language, summarize in that language.
4505
4934
  // OpenAI models
4506
4935
  MODEL_OPENAI_GPT_LATEST,
4507
4936
  MODEL_OPENAI_GPT_MINI_LATEST,
4937
+ MODEL_OPENAI_GPT_5_6_SOL,
4938
+ MODEL_OPENAI_GPT_5_6_TERRA,
4939
+ MODEL_OPENAI_GPT_5_6_LUNA,
4508
4940
  MODEL_OPENAI_GPT_5_5_PRO,
4509
4941
  MODEL_OPENAI_GPT_5_5,
4510
4942
  MODEL_OPENAI_GPT_5_1_CHAT,
@@ -4517,6 +4949,7 @@ If it's in another language, summarize in that language.
4517
4949
  // Anthropic models
4518
4950
  MODEL_ANTHROPIC_CLAUDE_SONNET_LATEST,
4519
4951
  MODEL_ANTHROPIC_CLAUDE_HAIKU_LATEST,
4952
+ MODEL_ANTHROPIC_CLAUDE_OPUS_5,
4520
4953
  MODEL_ANTHROPIC_CLAUDE_OPUS_4,
4521
4954
  MODEL_ANTHROPIC_CLAUDE_SONNET_4,
4522
4955
  MODEL_ANTHROPIC_CLAUDE_3_7_SONNET,
@@ -4525,6 +4958,8 @@ If it's in another language, summarize in that language.
4525
4958
  // Gemini models
4526
4959
  MODEL_GOOGLE_GEMINI_PRO_LATEST,
4527
4960
  MODEL_GOOGLE_GEMINI_FLASH_LATEST,
4961
+ MODEL_GOOGLE_GEMINI_3_6_FLASH,
4962
+ MODEL_GOOGLE_GEMINI_3_5_FLASH_LITE,
4528
4963
  MODEL_GOOGLE_GEMINI_2_5_PRO,
4529
4964
  MODEL_GOOGLE_GEMINI_2_5_FLASH,
4530
4965
  MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025,
@@ -4532,10 +4967,16 @@ If it's in another language, summarize in that language.
4532
4967
  MODEL_ZAI_GLM_5_2,
4533
4968
  MODEL_ZAI_GLM_4_7_FLASH,
4534
4969
  MODEL_ZAI_GLM_4_5_AIR,
4970
+ // xAI models
4971
+ MODEL_XAI_GROK_LATEST,
4972
+ MODEL_XAI_GROK_4_5,
4535
4973
  // Other models
4536
4974
  MODEL_MOONSHOTAI_KIMI_LATEST,
4975
+ MODEL_MOONSHOTAI_KIMI_K3,
4537
4976
  MODEL_MOONSHOTAI_KIMI_K2_7_CODE,
4538
- MODEL_MOONSHOTAI_KIMI_K2_5
4977
+ MODEL_MOONSHOTAI_KIMI_K2_5,
4978
+ MODEL_KWAIPILOT_KAT_CODER_AIR_V2_5,
4979
+ MODEL_KWAIPILOT_KAT_CODER_PRO_V2_5
4539
4980
  ];
4540
4981
  }
4541
4982
  /**
@@ -5258,7 +5699,10 @@ If it's in another language, summarize in that language.
5258
5699
  ]);
5259
5700
  var REASONING_EFFORT_BY_PROVIDER = {
5260
5701
  openai: ["none", "minimal", "low", "medium", "high", "xhigh", "max"],
5702
+ claude: ["low", "medium", "high", "xhigh", "max"],
5703
+ gemini: ["minimal", "low", "medium", "high"],
5261
5704
  openrouter: ["none", "minimal", "low", "medium", "high"],
5705
+ kimi: ["low", "high", "max"],
5262
5706
  mistral: ["low", "medium", "high"],
5263
5707
  plamo: ["none", "medium"],
5264
5708
  xai: ["none", "low", "medium", "high"]
@@ -5321,7 +5765,7 @@ If it's in another language, summarize in that language.
5321
5765
  mcp: MCP_SUPPORTED_PROVIDERS.has(providerName),
5322
5766
  jsonMode: JSON_MODE_SUPPORTED_PROVIDERS.has(providerName),
5323
5767
  responseLength: true,
5324
- reasoningEffort: REASONING_EFFORT_BY_PROVIDER[providerName] ?? []
5768
+ reasoningEffort: providerName === "claude" && model ? [...getClaudeSupportedReasoningEfforts(model)] : providerName === "kimi" && model ? [...getKimiSupportedReasoningEfforts(model)] : REASONING_EFFORT_BY_PROVIDER[providerName] ?? []
5325
5769
  };
5326
5770
  }
5327
5771
  /**