@fudrouter/fsrouter 0.6.72 → 0.6.74

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 (314) hide show
  1. package/dist/lib/headroom/detect.js +97 -7
  2. package/dist/lib/headroom/process.js +136 -4
  3. package/dist/open-sse/config/appConstants.js +23 -79
  4. package/dist/open-sse/config/cliFingerprints.js +1 -1
  5. package/dist/open-sse/config/errorConfig.js +0 -11
  6. package/dist/open-sse/config/grokCli.js +10 -0
  7. package/dist/open-sse/config/kiroConstants.js +99 -46
  8. package/dist/open-sse/config/runtimeConfig.js +2 -0
  9. package/dist/open-sse/config/ttsModels.js +2 -0
  10. package/dist/open-sse/executors/antigravity.js +250 -164
  11. package/dist/open-sse/executors/base.js +16 -11
  12. package/dist/open-sse/executors/codex.js +269 -1108
  13. package/dist/open-sse/executors/commandCode.js +1 -1
  14. package/dist/open-sse/executors/commandcode.js +10 -4
  15. package/dist/open-sse/executors/cursor.js +96 -203
  16. package/dist/open-sse/executors/default.js +146 -244
  17. package/dist/open-sse/executors/github.js +128 -73
  18. package/dist/open-sse/executors/grok-cli.js +527 -94
  19. package/dist/open-sse/executors/grok-web.js +5 -7
  20. package/dist/open-sse/executors/index.js +12 -0
  21. package/dist/open-sse/executors/kiro.js +150 -61
  22. package/dist/open-sse/executors/opencode-go.js +12 -4
  23. package/dist/open-sse/executors/opencode.js +1 -1
  24. package/dist/open-sse/executors/perplexity-web.js +20 -96
  25. package/dist/open-sse/executors/qoder.js +28 -18
  26. package/dist/open-sse/executors/vertex.js +53 -7
  27. package/dist/open-sse/executors/xiaomi-tokenplan.js +6 -5
  28. package/dist/open-sse/handlers/chatCore/nonStreamingHandler.js +97 -85
  29. package/dist/open-sse/handlers/chatCore/requestDetail.js +32 -8
  30. package/dist/open-sse/handlers/chatCore/sseToJsonHandler.js +13 -7
  31. package/dist/open-sse/handlers/chatCore/streamingHandler.js +74 -25
  32. package/dist/open-sse/handlers/chatCore.js +35 -41
  33. package/dist/open-sse/handlers/embeddingProviders/index.js +1 -0
  34. package/dist/open-sse/handlers/embeddingProviders/openai.js +8 -16
  35. package/dist/open-sse/handlers/imageProviders/blackForestLabs.js +2 -21
  36. package/dist/open-sse/handlers/imageProviders/cloudflareAi.js +2 -30
  37. package/dist/open-sse/handlers/imageProviders/codex.js +2 -20
  38. package/dist/open-sse/handlers/imageProviders/comfyui.js +5 -18
  39. package/dist/open-sse/handlers/imageProviders/falAi.js +2 -22
  40. package/dist/open-sse/handlers/imageProviders/gemini.js +2 -16
  41. package/dist/open-sse/handlers/imageProviders/huggingface.js +2 -17
  42. package/dist/open-sse/handlers/imageProviders/index.js +3 -4
  43. package/dist/open-sse/handlers/imageProviders/leonardo.js +1 -1
  44. package/dist/open-sse/handlers/imageProviders/nanobanana.js +4 -23
  45. package/dist/open-sse/handlers/imageProviders/openai.js +15 -43
  46. package/dist/open-sse/handlers/imageProviders/runwayml.js +2 -26
  47. package/dist/open-sse/handlers/imageProviders/sdwebui.js +4 -20
  48. package/dist/open-sse/handlers/imageProviders/stabilityAi.js +2 -26
  49. package/dist/open-sse/handlers/imageProviders/weavy.js +1 -1
  50. package/dist/open-sse/handlers/search/chatSearch.js +60 -14
  51. package/dist/open-sse/handlers/ttsProviders/gemini.js +14 -3
  52. package/dist/open-sse/handlers/ttsProviders/index.js +4 -2
  53. package/dist/open-sse/handlers/ttsProviders/openai.js +4 -1
  54. package/dist/open-sse/handlers/ttsProviders/openrouter.js +7 -4
  55. package/dist/open-sse/handlers/videoCore.js +166 -0
  56. package/dist/open-sse/handlers/videoProviders/weavy.js +1 -1
  57. package/dist/open-sse/mcp-server/catalog.js +1 -1
  58. package/dist/open-sse/mcp-server/server.js +2 -2
  59. package/dist/open-sse/mcp-server/tools/advancedTools.js +2 -2
  60. package/dist/open-sse/mcp-server/tools/agentSkillTools.js +1 -1
  61. package/dist/open-sse/mcp-server/tools/compressionTools.js +4 -4
  62. package/dist/open-sse/mcp-server/tools/gamificationTools.js +10 -10
  63. package/dist/open-sse/mcp-server/tools/githubSkillTools.js +1 -1
  64. package/dist/open-sse/mcp-server/tools/memoryTools.js +3 -3
  65. package/dist/open-sse/mcp-server/tools/notionTools.js +2 -2
  66. package/dist/open-sse/mcp-server/tools/obsidianTools.js +2 -2
  67. package/dist/open-sse/mcp-server/tools/pickFastestModel.js +1 -1
  68. package/dist/open-sse/mcp-server/tools/pluginTools.js +4 -4
  69. package/dist/open-sse/mcp-server/tools/skillTools.js +2 -2
  70. package/dist/open-sse/providers/capabilities.js +24 -4
  71. package/dist/open-sse/providers/registry/alicode-intl.js +1 -1
  72. package/dist/open-sse/providers/registry/anthropic.js +1 -8
  73. package/dist/open-sse/providers/registry/codex.js +0 -9
  74. package/dist/open-sse/providers/registry/cohere.js +0 -2
  75. package/dist/open-sse/providers/registry/gemini.js +0 -2
  76. package/dist/open-sse/providers/registry/github.js +9 -6
  77. package/dist/open-sse/providers/registry/grok-cli.js +28 -18
  78. package/dist/open-sse/providers/registry/index.js +74 -80
  79. package/dist/open-sse/providers/registry/kiro.js +12 -0
  80. package/dist/open-sse/providers/registry/mistral.js +0 -3
  81. package/dist/open-sse/providers/registry/openai.js +0 -3
  82. package/dist/open-sse/providers/registry/perplexity.js +0 -2
  83. package/dist/open-sse/providers/registry/xai.js +5 -3
  84. package/dist/open-sse/rtk/autodetect.js +10 -2
  85. package/dist/open-sse/rtk/caveman.js +2 -93
  86. package/dist/open-sse/rtk/cavemanPrompts.js +34 -2
  87. package/dist/open-sse/rtk/constants.js +7 -2
  88. package/dist/open-sse/rtk/headroom.js +133 -0
  89. package/dist/open-sse/rtk/ponytail.js +1 -1
  90. package/dist/open-sse/rtk/registry.js +2 -0
  91. package/dist/open-sse/services/accountFallback.js +0 -108
  92. package/dist/open-sse/services/combo/quotaExhaustionCutoff.js +2 -2
  93. package/dist/open-sse/services/combo/quotaShareStrategy.js +1 -1
  94. package/dist/open-sse/services/combo/resolveAutoStrategy.js +1 -1
  95. package/dist/open-sse/services/combo/sessionStickiness.js +1 -1
  96. package/dist/open-sse/services/combo/targetSorters.js +2 -2
  97. package/dist/open-sse/services/combo/validateQuality.js +1 -1
  98. package/dist/open-sse/services/comboConfig.js +1 -1
  99. package/dist/open-sse/services/emergencyFallback.js +1 -1
  100. package/dist/open-sse/services/grokCliModels.js +127 -0
  101. package/dist/open-sse/services/model.js +7 -1
  102. package/dist/open-sse/services/provider.js +1 -1
  103. package/dist/open-sse/services/proxyAutoSelector.js +1 -1
  104. package/dist/open-sse/services/tokenRefresh/providers.js +3 -3
  105. package/dist/open-sse/services/usage/codex.js +148 -214
  106. package/dist/open-sse/services/usage/grok-cli.js +61 -7
  107. package/dist/open-sse/services/usage/misc.js +0 -19
  108. package/dist/open-sse/services/usage.js +0 -2
  109. package/dist/open-sse/translator/concerns/paramSupport.js +2 -2
  110. package/dist/open-sse/translator/concerns/thinkingUnified.js +6 -0
  111. package/dist/open-sse/translator/index.js +97 -59
  112. package/dist/open-sse/translator/request/claude-to-kiro.js +67 -40
  113. package/dist/open-sse/translator/request/openai-responses.js +1 -0
  114. package/dist/open-sse/translator/request/openai-to-commandcode.js +0 -4
  115. package/dist/open-sse/translator/request/openai-to-kiro.js +49 -20
  116. package/dist/open-sse/translator/response/commandcode-to-openai.js +0 -4
  117. package/dist/open-sse/utils/bypassHandler.js +18 -3
  118. package/dist/open-sse/utils/claudeCloaking.js +15 -5
  119. package/dist/open-sse/utils/cursorImages.js +1 -1
  120. package/dist/open-sse/utils/error.js +0 -17
  121. package/dist/open-sse/utils/keepaliveThreshold.js +4 -4
  122. package/dist/open-sse/utils/kiroSessionReplay.js +125 -0
  123. package/dist/open-sse/utils/noThinkingAlias.js +1 -1
  124. package/dist/open-sse/utils/proxyFetch.js +0 -1
  125. package/dist/open-sse/utils/reasoningContentInjector.js +4 -7
  126. package/dist/open-sse/utils/responsesStatePolicy.js +1 -1
  127. package/dist/open-sse/utils/responsesStreamHelpers.js +1 -0
  128. package/dist/open-sse/utils/sessionManager.js +49 -22
  129. package/dist/open-sse/utils/stream.js +54 -77
  130. package/dist/open-sse/utils/streamHandler.js +19 -15
  131. package/dist/open-sse/utils/streamHelpers.js +2 -17
  132. package/dist/open-sse/utils/usageTracking.js +103 -12
  133. package/dist/routes/headroom/extras/route.js +58 -0
  134. package/dist/routes/headroom/restart/route.js +33 -0
  135. package/open-sse/config/appConstants.js +23 -79
  136. package/open-sse/config/errorConfig.js +0 -11
  137. package/open-sse/config/grokCli.js +10 -0
  138. package/open-sse/config/kiroConstants.js +99 -46
  139. package/open-sse/config/runtimeConfig.js +2 -0
  140. package/open-sse/config/ttsModels.js +2 -0
  141. package/open-sse/executors/antigravity.js +250 -164
  142. package/open-sse/executors/base.js +16 -11
  143. package/open-sse/executors/codex.js +269 -1108
  144. package/open-sse/executors/commandcode.js +10 -4
  145. package/open-sse/executors/cursor.js +96 -203
  146. package/open-sse/executors/default.js +146 -244
  147. package/open-sse/executors/github.js +128 -73
  148. package/open-sse/executors/grok-cli.js +527 -94
  149. package/open-sse/executors/grok-web.js +5 -7
  150. package/open-sse/executors/index.js +12 -0
  151. package/open-sse/executors/kiro.js +150 -61
  152. package/open-sse/executors/opencode-go.js +12 -4
  153. package/open-sse/executors/opencode.js +1 -1
  154. package/open-sse/executors/perplexity-web.js +20 -96
  155. package/open-sse/executors/qoder.js +28 -18
  156. package/open-sse/executors/vertex.js +53 -7
  157. package/open-sse/executors/xiaomi-tokenplan.js +6 -5
  158. package/open-sse/handlers/chatCore/nonStreamingHandler.js +97 -85
  159. package/open-sse/handlers/chatCore/requestDetail.js +32 -8
  160. package/open-sse/handlers/chatCore/sseToJsonHandler.js +13 -7
  161. package/open-sse/handlers/chatCore/streamingHandler.js +74 -25
  162. package/open-sse/handlers/chatCore.js +35 -41
  163. package/open-sse/handlers/embeddingProviders/index.js +1 -0
  164. package/open-sse/handlers/embeddingProviders/openai.js +8 -16
  165. package/open-sse/handlers/imageProviders/blackForestLabs.js +2 -21
  166. package/open-sse/handlers/imageProviders/cloudflareAi.js +2 -30
  167. package/open-sse/handlers/imageProviders/codex.js +2 -20
  168. package/open-sse/handlers/imageProviders/comfyui.js +5 -18
  169. package/open-sse/handlers/imageProviders/falAi.js +2 -22
  170. package/open-sse/handlers/imageProviders/gemini.js +2 -16
  171. package/open-sse/handlers/imageProviders/huggingface.js +2 -17
  172. package/open-sse/handlers/imageProviders/index.js +3 -4
  173. package/open-sse/handlers/imageProviders/leonardo.js +1 -1
  174. package/open-sse/handlers/imageProviders/nanobanana.js +4 -23
  175. package/open-sse/handlers/imageProviders/openai.js +15 -43
  176. package/open-sse/handlers/imageProviders/runwayml.js +2 -26
  177. package/open-sse/handlers/imageProviders/sdwebui.js +4 -20
  178. package/open-sse/handlers/imageProviders/stabilityAi.js +2 -26
  179. package/open-sse/handlers/imageProviders/weavy.js +1 -1
  180. package/open-sse/handlers/search/chatSearch.js +60 -14
  181. package/open-sse/handlers/ttsProviders/gemini.js +14 -3
  182. package/open-sse/handlers/ttsProviders/index.js +4 -2
  183. package/open-sse/handlers/ttsProviders/openai.js +4 -1
  184. package/open-sse/handlers/ttsProviders/openrouter.js +7 -4
  185. package/open-sse/handlers/videoCore.js +166 -0
  186. package/open-sse/handlers/videoProviders/weavy.js +1 -1
  187. package/open-sse/mcp-server/audit.js +1 -1
  188. package/open-sse/mcp-server/catalog.js +2 -2
  189. package/open-sse/mcp-server/descriptionCompressor.js +1 -1
  190. package/open-sse/mcp-server/mcpCallerIdentity.js +1 -1
  191. package/open-sse/mcp-server/schemas/tools.js +1 -1
  192. package/open-sse/mcp-server/server.js +4 -4
  193. package/open-sse/mcp-server/tools/advancedTools.js +5 -5
  194. package/open-sse/mcp-server/tools/agentSkillTools.js +1 -1
  195. package/open-sse/mcp-server/tools/compressionTools.js +4 -4
  196. package/open-sse/mcp-server/tools/gamificationTools.js +10 -10
  197. package/open-sse/mcp-server/tools/githubSkillTools.js +1 -1
  198. package/open-sse/mcp-server/tools/memoryTools.js +3 -3
  199. package/open-sse/mcp-server/tools/notionTools.js +2 -2
  200. package/open-sse/mcp-server/tools/obsidianTools.js +2 -2
  201. package/open-sse/mcp-server/tools/pickFastestModel.js +3 -3
  202. package/open-sse/mcp-server/tools/pluginTools.js +4 -4
  203. package/open-sse/mcp-server/tools/skillTools.js +2 -2
  204. package/open-sse/providers/capabilities.js +24 -4
  205. package/open-sse/providers/registry/alicode-intl.js +1 -1
  206. package/open-sse/providers/registry/anthropic.js +1 -8
  207. package/open-sse/providers/registry/codex.js +0 -9
  208. package/open-sse/providers/registry/cohere.js +0 -2
  209. package/open-sse/providers/registry/gemini.js +0 -2
  210. package/open-sse/providers/registry/github.js +9 -6
  211. package/open-sse/providers/registry/grok-cli.js +28 -18
  212. package/open-sse/providers/registry/index.js +74 -80
  213. package/open-sse/providers/registry/kiro.js +12 -0
  214. package/open-sse/providers/registry/mistral.js +0 -3
  215. package/open-sse/providers/registry/openai.js +0 -3
  216. package/open-sse/providers/registry/perplexity.js +0 -2
  217. package/open-sse/providers/registry/xai.js +5 -3
  218. package/open-sse/rtk/autodetect.js +10 -2
  219. package/open-sse/rtk/caveman.js +2 -93
  220. package/open-sse/rtk/cavemanPrompts.js +34 -2
  221. package/open-sse/rtk/constants.js +7 -2
  222. package/open-sse/rtk/headroom.js +133 -0
  223. package/open-sse/rtk/ponytail.js +1 -1
  224. package/open-sse/rtk/registry.js +2 -0
  225. package/open-sse/services/accountFallback.js +0 -108
  226. package/open-sse/services/combo/quotaExhaustionCutoff.js +2 -2
  227. package/open-sse/services/combo/quotaShareStrategy.js +1 -1
  228. package/open-sse/services/combo/resolveAutoStrategy.js +1 -1
  229. package/open-sse/services/combo/sessionStickiness.js +1 -1
  230. package/open-sse/services/combo/shadowRouting.js +1 -1
  231. package/open-sse/services/combo/targetSorters.js +4 -4
  232. package/open-sse/services/combo/validateQuality.js +1 -1
  233. package/open-sse/services/evalRouting.js +1 -1
  234. package/open-sse/services/grokCliModels.js +127 -0
  235. package/open-sse/services/model.js +7 -1
  236. package/open-sse/services/modelCapabilities.js +1 -1
  237. package/open-sse/services/modelFamilyFallback.js +1 -1
  238. package/open-sse/services/provider.js +1 -1
  239. package/open-sse/services/providerCooldownTracker.js +1 -1
  240. package/open-sse/services/rateLimitManager.js +1 -1
  241. package/open-sse/services/tokenRefresh/providers.js +3 -3
  242. package/open-sse/services/usage/codex.js +148 -214
  243. package/open-sse/services/usage/grok-cli.js +61 -7
  244. package/open-sse/services/usage/misc.js +0 -19
  245. package/open-sse/services/usage.js +0 -2
  246. package/open-sse/translator/concerns/paramSupport.js +2 -2
  247. package/open-sse/translator/concerns/thinkingUnified.js +6 -0
  248. package/open-sse/translator/index.js +97 -59
  249. package/open-sse/translator/request/claude-to-kiro.js +67 -40
  250. package/open-sse/translator/request/openai-responses.js +1 -0
  251. package/open-sse/translator/request/openai-to-commandcode.js +0 -4
  252. package/open-sse/translator/request/openai-to-kiro.js +49 -20
  253. package/open-sse/translator/response/commandcode-to-openai.js +0 -4
  254. package/open-sse/utils/bypassHandler.js +18 -3
  255. package/open-sse/utils/claudeCloaking.js +15 -5
  256. package/open-sse/utils/error.js +0 -17
  257. package/open-sse/utils/kiroSessionReplay.js +125 -0
  258. package/open-sse/utils/logger.js +1 -1
  259. package/open-sse/utils/proxyFetch.js +0 -1
  260. package/open-sse/utils/reasoningContentInjector.js +4 -7
  261. package/open-sse/utils/responsesStreamHelpers.js +1 -0
  262. package/open-sse/utils/sessionManager.js +49 -22
  263. package/open-sse/utils/stream.js +54 -77
  264. package/open-sse/utils/streamHandler.js +19 -15
  265. package/open-sse/utils/streamHelpers.js +2 -17
  266. package/open-sse/utils/usageTracking.js +103 -12
  267. package/package.json +4 -7
  268. package/public/assets/EndpointPageClient.C2WMTYy0.js +6 -0
  269. package/public/assets/{Loading.Bj-WGl4k.js → Loading.BHPtQ9vj.js} +1 -1
  270. package/public/assets/{NoAuthProxyCard.qAv57b-0.js → NoAuthProxyCard.BDcXaWvM.js} +1 -1
  271. package/public/assets/index.Be3gbrBl.js +89 -0
  272. package/public/assets/index.COMgQZYj.css +1 -0
  273. package/public/assets/{page.CbkENBd5.js → page.-lpNgYAw.js} +1 -1
  274. package/public/assets/{page.CssmrzTT.js → page.11hpNKmq.js} +1 -1
  275. package/public/assets/{page.C72FTTJr.js → page.B-LxsnqU.js} +1 -1
  276. package/public/assets/{page.sOFOrxqq.js → page.B-dzeIUC.js} +1 -1
  277. package/public/assets/{page.CsxWmPoI.js → page.B-nBR75u.js} +1 -1
  278. package/public/assets/{page.Dx_GRRdT.js → page.B3QqvLep.js} +1 -1
  279. package/public/assets/{page.DPyOkPVo.js → page.B8xdkCWA.js} +1 -1
  280. package/public/assets/{page.DUI8kqOY.js → page.BFb7yUd8.js} +1 -1
  281. package/public/assets/page.BbPPdoas.js +1 -0
  282. package/public/assets/page.BdS20a1O.js +1 -0
  283. package/public/assets/{page.DibhF7f-.js → page.BfmI9KYe.js} +1 -1
  284. package/public/assets/{page.DX4Nno6M.js → page.BgGJovOg.js} +1 -1
  285. package/public/assets/{page.BnmTC5jG.js → page.C0gBvR4O.js} +1 -1
  286. package/public/assets/{page.D5gj98Oe.js → page.C6bYizL7.js} +1 -1
  287. package/public/assets/{page.vla5Mzki.js → page.C8sLEMa6.js} +1 -1
  288. package/public/assets/{page.CXd_R9yU.js → page.CCNsZBXp.js} +1 -1
  289. package/public/assets/{page.CQlVGoXg.js → page.CF_YSLwP.js} +1 -1
  290. package/public/assets/{page.BbO1pspY.js → page.CPTtRDxw.js} +1 -1
  291. package/public/assets/{page.D1oKew1j.js → page.CdMmlUEm.js} +1 -1
  292. package/public/assets/{page.DxMDTbSx.js → page.Cged1bOZ.js} +1 -1
  293. package/public/assets/{page.Cj5h09Zo.js → page.Ch647dVk.js} +1 -1
  294. package/public/assets/{page.DVIHRbxB.js → page.CpvXDkQF.js} +1 -1
  295. package/public/assets/{page.i4KDuWcM.js → page.CrBl7f8N.js} +1 -1
  296. package/public/assets/{page.BSLJ4tx5.js → page.CrP7niA2.js} +1 -1
  297. package/public/assets/{page.CnTop8Zt.js → page.CvUFZzXr.js} +1 -1
  298. package/public/assets/{page.O2ddJYoT.js → page.CyUqJPmx.js} +1 -1
  299. package/public/assets/{page.DBhu4Arl.js → page.D8Rp8fFR.js} +1 -1
  300. package/public/assets/{page.CPZav1_c.js → page.Df9qtrdG.js} +1 -1
  301. package/public/assets/{page.Qkkv8roc.js → page.DiL4Gwqe.js} +1 -1
  302. package/public/assets/{page.BdmJ3yY3.js → page.Dl1apZE2.js} +1 -1
  303. package/public/assets/{page.1qjqvrwX.js → page.HV0w1d5C.js} +1 -1
  304. package/public/assets/{page.ChX1NqmC.js → page.N1x4YL8_.js} +1 -1
  305. package/public/assets/{page.Dh5f0XJC.js → page.P2Ny5veR.js} +1 -1
  306. package/public/assets/{page.CSs3-gdt.js → page.fOOCr18J.js} +1 -1
  307. package/public/assets/{page.Ir7KvKcF.js → page.sUIPWIiF.js} +1 -1
  308. package/public/assets/{page.CzlQTyAL.js → page.tE7PpWYW.js} +1 -1
  309. package/public/assets/{page.DzZLqI5Q.js → page.uziaGZsT.js} +1 -1
  310. package/public/index.html +2 -2
  311. package/public/assets/EndpointPageClient.LyNNvZ4z.js +0 -6
  312. package/public/assets/index.BuPfZebu.css +0 -1
  313. package/public/assets/index.CShjRV_B.js +0 -89
  314. package/public/assets/page.DD_czjjP.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { isVisionModelId } from '../../../dist/shared/constants/visionModels.js';
2
+ import { isVisionModelId } from '../../dist/shared/constants/visionModels.js';
3
3
  import { REGISTRY } from "../config/providerRegistry.ts";
4
4
  import { BaseExecutor, mergeUpstreamExtraHeaders } from "./base.ts";
5
5
  const COMMAND_CODE_VERSION = process.env.COMMAND_CODE_VERSION?.trim() || "0.33.2";
@@ -1,7 +1,8 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { BaseExecutor } from "./base.js";
3
3
  import { PROVIDERS } from "../config/providers.js";
4
- import { convertCommandCodeToOpenAI } from "../translator/response/commandcode-to-openai.js";
4
+ import { commandCodeToOpenAIResponse } from "../translator/response/commandcode-to-openai.js";
5
+ import { SSE_DONE } from "../utils/sseConstants.js";
5
6
 
6
7
  /**
7
8
  * CommandCodeExecutor — talks to https://api.commandcode.ai/alpha/generate
@@ -19,6 +20,11 @@ export class CommandCodeExecutor extends BaseExecutor {
19
20
  super("commandcode", PROVIDERS.commandcode);
20
21
  }
21
22
 
23
+ transformRequest(model, body, stream, credentials) {
24
+ body.stream = true;
25
+ return body;
26
+ }
27
+
22
28
  buildHeaders(credentials, stream = true) {
23
29
  const headers = {
24
30
  "Content-Type": "application/json",
@@ -65,15 +71,15 @@ function wrapNdjsonAsOpenAISse(originalResponse, model) {
65
71
  const trimmed = line.trim();
66
72
  if (!trimmed) continue;
67
73
  // Translate AI SDK v5 NDJSON line to one or more OpenAI chunks
68
- emitChunks(convertCommandCodeToOpenAI(trimmed, state), controller);
74
+ emitChunks(commandCodeToOpenAIResponse(trimmed, state), controller);
69
75
  }
70
76
  },
71
77
  flush(controller) {
72
78
  const trimmed = buffer.trim();
73
79
  if (trimmed) {
74
- emitChunks(convertCommandCodeToOpenAI(trimmed, state), controller);
80
+ emitChunks(commandCodeToOpenAIResponse(trimmed, state), controller);
75
81
  }
76
- controller.enqueue(encoder.encode("data: [DONE]\n\n"));
82
+ controller.enqueue(encoder.encode(SSE_DONE));
77
83
  },
78
84
  });
79
85
 
@@ -8,6 +8,8 @@ import {
8
8
  } from "../utils/cursorProtobuf.js";
9
9
  import { buildCursorHeaders } from "../utils/cursorChecksum.js";
10
10
  import { estimateUsage } from "../utils/usageTracking.js";
11
+ import { SSE_DONE, SSE_HEADERS } from "../utils/sseConstants.js";
12
+ import { chatChunkSse } from "../utils/sse.js";
11
13
  import { FORMATS } from "../translator/formats.js";
12
14
  import { proxyAwareFetch } from "../utils/proxyFetch.js";
13
15
  import zlib from "zlib";
@@ -98,6 +100,32 @@ function decompressPayload(payload, flags) {
98
100
  return payload;
99
101
  }
100
102
 
103
+ // Read one cursor protobuf frame: header + bounds + decompress. Returns status + payload + new offset.
104
+ function readCursorFrame(buffer, offset, frameNum, tag) {
105
+ if (offset + 5 > buffer.length) {
106
+ debugLog(`[CURSOR BUFFER${tag}] Reached end, offset=${offset}, remaining=${buffer.length - offset}`);
107
+ return { status: "done" };
108
+ }
109
+
110
+ const flags = buffer[offset];
111
+ const length = buffer.readUInt32BE(offset + 1);
112
+ debugLog(`[CURSOR BUFFER${tag}] Frame ${frameNum + 1}: flags=0x${flags.toString(16).padStart(2, "0")}, length=${length}`);
113
+
114
+ if (offset + 5 + length > buffer.length) {
115
+ debugLog(`[CURSOR BUFFER${tag}] Incomplete frame, offset=${offset}, length=${length}, buffer.length=${buffer.length}`);
116
+ return { status: "done" };
117
+ }
118
+
119
+ let payload = buffer.slice(offset + 5, offset + 5 + length);
120
+ const newOffset = offset + 5 + length;
121
+ payload = decompressPayload(payload, flags);
122
+ if (!payload) {
123
+ debugLog(`[CURSOR BUFFER${tag}] Frame ${frameNum + 1}: decompression failed, skipping`);
124
+ return { status: "skip", offset: newOffset };
125
+ }
126
+ return { status: "ok", payload, offset: newOffset };
127
+ }
128
+
101
129
  function createErrorResponse(jsonError) {
102
130
  const errorMsg = jsonError?.error?.details?.[0]?.debug?.details?.title
103
131
  || jsonError?.error?.details?.[0]?.debug?.details?.detail
@@ -141,7 +169,7 @@ export class CursorExecutor extends BaseExecutor {
141
169
 
142
170
  transformRequest(model, body, stream, credentials) {
143
171
  // Messages are already translated by chatCore (claude→openai→cursor)
144
- // Do NOT call buildCursorRequest again — double-translation drops tool_results
172
+ // Do NOT call openaiToCursorRequest again — double-translation drops tool_results
145
173
  const messages = body.messages || [];
146
174
  const tools = body.tools || [];
147
175
  const reasoningEffort = body.reasoning_effort || null;
@@ -286,36 +314,12 @@ export class CursorExecutor extends BaseExecutor {
286
314
  debugLog(`[CURSOR BUFFER] Total length: ${buffer.length} bytes`);
287
315
 
288
316
  while (offset < buffer.length) {
289
- if (offset + 5 > buffer.length) {
290
- debugLog(
291
- `[CURSOR BUFFER] Reached end, offset=${offset}, remaining=${buffer.length - offset}`
292
- );
293
- break;
294
- }
295
-
296
- const flags = buffer[offset];
297
- const length = buffer.readUInt32BE(offset + 1);
298
-
299
- debugLog(
300
- `[CURSOR BUFFER] Frame ${frameCount + 1}: flags=0x${flags.toString(16).padStart(2, "0")}, length=${length}`
301
- );
302
-
303
- if (offset + 5 + length > buffer.length) {
304
- debugLog(
305
- `[CURSOR BUFFER] Incomplete frame, offset=${offset}, length=${length}, buffer.length=${buffer.length}`
306
- );
307
- break;
308
- }
309
-
310
- let payload = buffer.slice(offset + 5, offset + 5 + length);
311
- offset += 5 + length;
317
+ const frame = readCursorFrame(buffer, offset, frameCount, "");
318
+ if (frame.status === "done") break;
319
+ offset = frame.offset;
312
320
  frameCount++;
313
-
314
- payload = decompressPayload(payload, flags);
315
- if (!payload) {
316
- debugLog(`[CURSOR BUFFER] Frame ${frameCount}: decompression failed, skipping`);
317
- continue;
318
- }
321
+ if (frame.status === "skip") continue;
322
+ const payload = frame.payload;
319
323
 
320
324
  // Check for JSON error frames (byte guard: skip toString on non-JSON frames)
321
325
  if (payload.length > 0 && payload[0] === 0x7b) {
@@ -466,36 +470,12 @@ export class CursorExecutor extends BaseExecutor {
466
470
  debugLog(`[CURSOR BUFFER SSE] Total length: ${buffer.length} bytes`);
467
471
 
468
472
  while (offset < buffer.length) {
469
- if (offset + 5 > buffer.length) {
470
- debugLog(
471
- `[CURSOR BUFFER SSE] Reached end, offset=${offset}, remaining=${buffer.length - offset}`
472
- );
473
- break;
474
- }
475
-
476
- const flags = buffer[offset];
477
- const length = buffer.readUInt32BE(offset + 1);
478
-
479
- debugLog(
480
- `[CURSOR BUFFER SSE] Frame ${frameCount + 1}: flags=0x${flags.toString(16).padStart(2, "0")}, length=${length}`
481
- );
482
-
483
- if (offset + 5 + length > buffer.length) {
484
- debugLog(
485
- `[CURSOR BUFFER SSE] Incomplete frame, offset=${offset}, length=${length}, buffer.length=${buffer.length}`
486
- );
487
- break;
488
- }
489
-
490
- let payload = buffer.slice(offset + 5, offset + 5 + length);
491
- offset += 5 + length;
473
+ const frame = readCursorFrame(buffer, offset, frameCount, " SSE");
474
+ if (frame.status === "done") break;
475
+ offset = frame.offset;
492
476
  frameCount++;
493
-
494
- payload = decompressPayload(payload, flags);
495
- if (!payload) {
496
- debugLog(`[CURSOR BUFFER SSE] Frame ${frameCount}: decompression failed, skipping`);
497
- continue;
498
- }
477
+ if (frame.status === "skip") continue;
478
+ const payload = frame.payload;
499
479
 
500
480
  // Check for JSON error frames (byte-guard: only decode if starts with '{')
501
481
  if (payload[0] === 0x7b) {
@@ -542,21 +522,7 @@ export class CursorExecutor extends BaseExecutor {
542
522
  const tc = result.toolCall;
543
523
 
544
524
  if (chunks.length === 0) {
545
- chunks.push(
546
- `data: ${JSON.stringify({
547
- id: responseId,
548
- object: "chat.completion.chunk",
549
- created,
550
- model,
551
- choices: [
552
- {
553
- index: 0,
554
- delta: { role: "assistant", content: "" },
555
- finish_reason: null
556
- }
557
- ]
558
- })}\n\n`
559
- );
525
+ chunks.push(chatChunkSse({ id: responseId, created, model, delta: { role: "assistant", content: "" } }));
560
526
  }
561
527
 
562
528
  if (toolCallsMap.has(tc.id)) {
@@ -569,33 +535,22 @@ export class CursorExecutor extends BaseExecutor {
569
535
  // Stream the delta arguments
570
536
  if (tc.function.arguments) {
571
537
  emittedToolCallIds.add(tc.id);
572
- chunks.push(
573
- `data: ${JSON.stringify({
574
- id: responseId,
575
- object: "chat.completion.chunk",
576
- created,
577
- model,
578
- choices: [
538
+ chunks.push(chatChunkSse({
539
+ id: responseId, created, model,
540
+ delta: {
541
+ tool_calls: [
579
542
  {
580
- index: 0,
581
- delta: {
582
- tool_calls: [
583
- {
584
- index: existing.index,
585
- id: tc.id,
586
- type: "function",
587
- function: {
588
- name: tc.function.name,
589
- arguments: tc.function.arguments
590
- }
591
- }
592
- ]
593
- },
594
- finish_reason: null
543
+ index: existing.index,
544
+ id: tc.id,
545
+ type: "function",
546
+ function: {
547
+ name: tc.function.name,
548
+ arguments: tc.function.arguments
549
+ }
595
550
  }
596
551
  ]
597
- })}\n\n`
598
- );
552
+ }
553
+ }));
599
554
  }
600
555
  } else {
601
556
  // New tool call - assign index and add to map
@@ -606,56 +561,34 @@ export class CursorExecutor extends BaseExecutor {
606
561
 
607
562
  // Stream initial tool call with name
608
563
  emittedToolCallIds.add(tc.id);
609
- chunks.push(
610
- `data: ${JSON.stringify({
611
- id: responseId,
612
- object: "chat.completion.chunk",
613
- created,
614
- model,
615
- choices: [
564
+ chunks.push(chatChunkSse({
565
+ id: responseId, created, model,
566
+ delta: {
567
+ tool_calls: [
616
568
  {
617
- index: 0,
618
- delta: {
619
- tool_calls: [
620
- {
621
- index: toolCallIndex,
622
- id: tc.id,
623
- type: "function",
624
- function: {
625
- name: tc.function.name,
626
- arguments: tc.function.arguments
627
- }
628
- }
629
- ]
630
- },
631
- finish_reason: null
569
+ index: toolCallIndex,
570
+ id: tc.id,
571
+ type: "function",
572
+ function: {
573
+ name: tc.function.name,
574
+ arguments: tc.function.arguments
575
+ }
632
576
  }
633
577
  ]
634
- })}\n\n`
635
- );
578
+ }
579
+ }));
636
580
  }
637
581
  }
638
582
 
639
583
  if (result.text) {
640
584
  totalContent += result.text;
641
- chunks.push(
642
- `data: ${JSON.stringify({
643
- id: responseId,
644
- object: "chat.completion.chunk",
645
- created,
646
- model,
647
- choices: [
648
- {
649
- index: 0,
650
- delta:
651
- chunks.length === 0 && toolCalls.length === 0
652
- ? { role: "assistant", content: result.text }
653
- : { content: result.text },
654
- finish_reason: null
655
- }
656
- ]
657
- })}\n\n`
658
- );
585
+ chunks.push(chatChunkSse({
586
+ id: responseId, created, model,
587
+ delta:
588
+ chunks.length === 0 && toolCalls.length === 0
589
+ ? { role: "assistant", content: result.text }
590
+ : { content: result.text }
591
+ }));
659
592
  }
660
593
 
661
594
  if (isComposerModel(model) && result.thinking) {
@@ -665,24 +598,13 @@ export class CursorExecutor extends BaseExecutor {
665
598
  const deltaContent = visibleContent.slice(emittedComposerThinkingContentLength);
666
599
  emittedComposerThinkingContentLength = visibleContent.length;
667
600
  totalContent += deltaContent;
668
- chunks.push(
669
- `data: ${JSON.stringify({
670
- id: responseId,
671
- object: "chat.completion.chunk",
672
- created,
673
- model,
674
- choices: [
675
- {
676
- index: 0,
677
- delta:
678
- chunks.length === 0 && toolCalls.length === 0
679
- ? { role: "assistant", content: deltaContent }
680
- : { content: deltaContent },
681
- finish_reason: null
682
- }
683
- ]
684
- })}\n\n`
685
- );
601
+ chunks.push(chatChunkSse({
602
+ id: responseId, created, model,
603
+ delta:
604
+ chunks.length === 0 && toolCalls.length === 0
605
+ ? { role: "assistant", content: deltaContent }
606
+ : { content: deltaContent }
607
+ }));
686
608
  }
687
609
  }
688
610
  }
@@ -708,53 +630,28 @@ export class CursorExecutor extends BaseExecutor {
708
630
 
709
631
  // Emit SSE chunk for the finalized tool call if not already emitted
710
632
  if (!emittedToolCallIds.has(tc.id)) {
711
- chunks.push(
712
- `data: ${JSON.stringify({
713
- id: responseId,
714
- object: "chat.completion.chunk",
715
- created,
716
- model,
717
- choices: [
633
+ chunks.push(chatChunkSse({
634
+ id: responseId, created, model,
635
+ delta: {
636
+ tool_calls: [
718
637
  {
719
- index: 0,
720
- delta: {
721
- tool_calls: [
722
- {
723
- index: toolCallIndex,
724
- id: tc.id,
725
- type: "function",
726
- function: {
727
- name: tc.function.name,
728
- arguments: tc.function.arguments
729
- }
730
- }
731
- ]
732
- },
733
- finish_reason: null
638
+ index: toolCallIndex,
639
+ id: tc.id,
640
+ type: "function",
641
+ function: {
642
+ name: tc.function.name,
643
+ arguments: tc.function.arguments
644
+ }
734
645
  }
735
646
  ]
736
- })}\n\n`
737
- );
647
+ }
648
+ }));
738
649
  }
739
650
  }
740
651
  }
741
652
 
742
653
  if (chunks.length === 0 && toolCalls.length === 0) {
743
- chunks.push(
744
- `data: ${JSON.stringify({
745
- id: responseId,
746
- object: "chat.completion.chunk",
747
- created,
748
- model,
749
- choices: [
750
- {
751
- index: 0,
752
- delta: { role: "assistant", content: "" },
753
- finish_reason: null
754
- }
755
- ]
756
- })}\n\n`
757
- );
654
+ chunks.push(chatChunkSse({ id: responseId, created, model, delta: { role: "assistant", content: "" } }));
758
655
  }
759
656
 
760
657
  const usage = estimateUsage(body, totalContent.length, FORMATS.OPENAI);
@@ -775,15 +672,11 @@ export class CursorExecutor extends BaseExecutor {
775
672
  usage
776
673
  })}\n\n`
777
674
  );
778
- chunks.push("data: [DONE]\n\n");
675
+ chunks.push(SSE_DONE);
779
676
 
780
677
  return new Response(chunks.join(""), {
781
678
  status: 200,
782
- headers: {
783
- "Content-Type": "text/event-stream",
784
- "Cache-Control": "no-cache",
785
- "Connection": "keep-alive"
786
- }
679
+ headers: { ...SSE_HEADERS }
787
680
  });
788
681
  }
789
682