wyxrouter 0.4.71

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 (763) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSE +21 -0
  3. package/README.md +96 -0
  4. package/README.zh-CN.md +1311 -0
  5. package/assets/pixel-router-2d.png +0 -0
  6. package/cli/LICENSE +42 -0
  7. package/cli/README.md +125 -0
  8. package/cli/app/package.json +58 -0
  9. package/cli/cli.js +806 -0
  10. package/cli/package.json +48 -0
  11. package/i18n/README.ja-JP.md +1209 -0
  12. package/i18n/README.ru.md +1311 -0
  13. package/i18n/README.vi.md +1310 -0
  14. package/i18n/README.zh-CN.md +1306 -0
  15. package/images/9router.png +0 -0
  16. package/jsconfig.json +12 -0
  17. package/next.config.mjs +71 -0
  18. package/open-sse/config/appConstants.js +203 -0
  19. package/open-sse/config/codexInstructions.js +119 -0
  20. package/open-sse/config/constants.js +4 -0
  21. package/open-sse/config/defaultThinkingSignature.js +12 -0
  22. package/open-sse/config/errorConfig.js +85 -0
  23. package/open-sse/config/googleTtsLanguages.js +62 -0
  24. package/open-sse/config/kiroConstants.js +322 -0
  25. package/open-sse/config/models.js +13 -0
  26. package/open-sse/config/ollamaModels.js +19 -0
  27. package/open-sse/config/providerModels.js +944 -0
  28. package/open-sse/config/providers.js +458 -0
  29. package/open-sse/config/runtimeConfig.js +72 -0
  30. package/open-sse/config/ttsModels.js +129 -0
  31. package/open-sse/executors/antigravity.js +504 -0
  32. package/open-sse/executors/azure.js +57 -0
  33. package/open-sse/executors/base.js +185 -0
  34. package/open-sse/executors/codex.js +469 -0
  35. package/open-sse/executors/commandcode.js +88 -0
  36. package/open-sse/executors/cursor.js +795 -0
  37. package/open-sse/executors/default.js +497 -0
  38. package/open-sse/executors/gemini-cli.js +89 -0
  39. package/open-sse/executors/github.js +379 -0
  40. package/open-sse/executors/grok-web.js +345 -0
  41. package/open-sse/executors/iflow.js +108 -0
  42. package/open-sse/executors/index.js +75 -0
  43. package/open-sse/executors/kiro.js +508 -0
  44. package/open-sse/executors/ollama-local.js +14 -0
  45. package/open-sse/executors/opencode-go.js +41 -0
  46. package/open-sse/executors/opencode.js +32 -0
  47. package/open-sse/executors/perplexity-web.js +507 -0
  48. package/open-sse/executors/qoder.js +450 -0
  49. package/open-sse/executors/qwen.js +129 -0
  50. package/open-sse/executors/vertex.js +131 -0
  51. package/open-sse/executors/xiaomi-tokenplan.js +19 -0
  52. package/open-sse/handlers/chatCore/nonStreamingHandler.js +230 -0
  53. package/open-sse/handlers/chatCore/requestDetail.js +102 -0
  54. package/open-sse/handlers/chatCore/sseToJsonHandler.js +231 -0
  55. package/open-sse/handlers/chatCore/streamingHandler.js +103 -0
  56. package/open-sse/handlers/chatCore.js +287 -0
  57. package/open-sse/handlers/embeddingProviders/_base.js +4 -0
  58. package/open-sse/handlers/embeddingProviders/gemini.js +54 -0
  59. package/open-sse/handlers/embeddingProviders/index.js +23 -0
  60. package/open-sse/handlers/embeddingProviders/openai.js +39 -0
  61. package/open-sse/handlers/embeddingProviders/openaiCompatNode.js +13 -0
  62. package/open-sse/handlers/embeddingsCore.js +126 -0
  63. package/open-sse/handlers/fetch/index.js +237 -0
  64. package/open-sse/handlers/imageGenerationCore.js +189 -0
  65. package/open-sse/handlers/imageProviders/_base.js +31 -0
  66. package/open-sse/handlers/imageProviders/blackForestLabs.js +43 -0
  67. package/open-sse/handlers/imageProviders/cloudflareAi.js +178 -0
  68. package/open-sse/handlers/imageProviders/codex.js +198 -0
  69. package/open-sse/handlers/imageProviders/comfyui.js +8 -0
  70. package/open-sse/handlers/imageProviders/falAi.js +41 -0
  71. package/open-sse/handlers/imageProviders/gemini.js +25 -0
  72. package/open-sse/handlers/imageProviders/huggingface.js +22 -0
  73. package/open-sse/handlers/imageProviders/index.js +40 -0
  74. package/open-sse/handlers/imageProviders/nanobanana.js +58 -0
  75. package/open-sse/handlers/imageProviders/openai.js +40 -0
  76. package/open-sse/handlers/imageProviders/runwayml.js +47 -0
  77. package/open-sse/handlers/imageProviders/sdwebui.js +17 -0
  78. package/open-sse/handlers/imageProviders/stabilityAi.js +34 -0
  79. package/open-sse/handlers/responsesHandler.js +103 -0
  80. package/open-sse/handlers/search/callers.js +371 -0
  81. package/open-sse/handlers/search/chatSearch.js +409 -0
  82. package/open-sse/handlers/search/index.js +201 -0
  83. package/open-sse/handlers/search/normalizers.js +223 -0
  84. package/open-sse/handlers/sttCore.js +194 -0
  85. package/open-sse/handlers/ttsCore.js +74 -0
  86. package/open-sse/handlers/ttsProviders/_base.js +39 -0
  87. package/open-sse/handlers/ttsProviders/edgeTts.js +89 -0
  88. package/open-sse/handlers/ttsProviders/elevenlabs.js +48 -0
  89. package/open-sse/handlers/ttsProviders/gemini.js +117 -0
  90. package/open-sse/handlers/ttsProviders/genericFormats.js +169 -0
  91. package/open-sse/handlers/ttsProviders/googleTts.js +54 -0
  92. package/open-sse/handlers/ttsProviders/index.js +50 -0
  93. package/open-sse/handlers/ttsProviders/localDevice.js +87 -0
  94. package/open-sse/handlers/ttsProviders/minimax.js +59 -0
  95. package/open-sse/handlers/ttsProviders/openai.js +30 -0
  96. package/open-sse/handlers/ttsProviders/openrouter.js +70 -0
  97. package/open-sse/index.js +82 -0
  98. package/open-sse/rtk/applyFilter.js +15 -0
  99. package/open-sse/rtk/autodetect.js +111 -0
  100. package/open-sse/rtk/caveman.js +100 -0
  101. package/open-sse/rtk/cavemanPrompts.js +78 -0
  102. package/open-sse/rtk/constants.js +55 -0
  103. package/open-sse/rtk/filters/buildOutput.js +127 -0
  104. package/open-sse/rtk/filters/dedupLog.js +44 -0
  105. package/open-sse/rtk/filters/find.js +49 -0
  106. package/open-sse/rtk/filters/gitDiff.js +92 -0
  107. package/open-sse/rtk/filters/gitStatus.js +117 -0
  108. package/open-sse/rtk/filters/grep.js +48 -0
  109. package/open-sse/rtk/filters/ls.js +79 -0
  110. package/open-sse/rtk/filters/readNumbered.js +27 -0
  111. package/open-sse/rtk/filters/searchList.js +52 -0
  112. package/open-sse/rtk/filters/smartTruncate.js +15 -0
  113. package/open-sse/rtk/filters/tree.js +32 -0
  114. package/open-sse/rtk/index.js +155 -0
  115. package/open-sse/rtk/registry.js +38 -0
  116. package/open-sse/services/accountFallback.js +238 -0
  117. package/open-sse/services/combo.js +198 -0
  118. package/open-sse/services/compact.js +71 -0
  119. package/open-sse/services/kiroModels.js +332 -0
  120. package/open-sse/services/model.js +261 -0
  121. package/open-sse/services/oauthCredentialManager.js +151 -0
  122. package/open-sse/services/projectId.js +306 -0
  123. package/open-sse/services/provider.js +356 -0
  124. package/open-sse/services/qoderModels.js +214 -0
  125. package/open-sse/services/tokenRefresh.js +939 -0
  126. package/open-sse/services/usage.js +1496 -0
  127. package/open-sse/transformer/responsesTransformer.js +439 -0
  128. package/open-sse/transformer/streamToJsonConverter.js +103 -0
  129. package/open-sse/translator/formats.js +36 -0
  130. package/open-sse/translator/helpers/claudeHelper.js +216 -0
  131. package/open-sse/translator/helpers/geminiHelper.js +372 -0
  132. package/open-sse/translator/helpers/imageHelper.js +34 -0
  133. package/open-sse/translator/helpers/maxTokensHelper.js +27 -0
  134. package/open-sse/translator/helpers/openaiHelper.js +130 -0
  135. package/open-sse/translator/helpers/responsesApiHelper.js +139 -0
  136. package/open-sse/translator/helpers/toolCallHelper.js +148 -0
  137. package/open-sse/translator/index.js +251 -0
  138. package/open-sse/translator/request/antigravity-to-openai.js +229 -0
  139. package/open-sse/translator/request/claude-to-openai.js +232 -0
  140. package/open-sse/translator/request/gemini-to-openai.js +147 -0
  141. package/open-sse/translator/request/openai-responses.js +318 -0
  142. package/open-sse/translator/request/openai-to-claude.js +401 -0
  143. package/open-sse/translator/request/openai-to-commandcode.js +170 -0
  144. package/open-sse/translator/request/openai-to-cursor.js +183 -0
  145. package/open-sse/translator/request/openai-to-gemini.js +470 -0
  146. package/open-sse/translator/request/openai-to-kiro.js +629 -0
  147. package/open-sse/translator/request/openai-to-kiro.old.js +278 -0
  148. package/open-sse/translator/request/openai-to-ollama.js +192 -0
  149. package/open-sse/translator/request/openai-to-vertex.js +42 -0
  150. package/open-sse/translator/response/claude-to-openai.js +206 -0
  151. package/open-sse/translator/response/commandcode-to-openai.js +197 -0
  152. package/open-sse/translator/response/cursor-to-openai.js +30 -0
  153. package/open-sse/translator/response/gemini-to-openai.js +245 -0
  154. package/open-sse/translator/response/kiro-to-openai.js +195 -0
  155. package/open-sse/translator/response/ollama-to-openai.js +152 -0
  156. package/open-sse/translator/response/openai-responses.js +590 -0
  157. package/open-sse/translator/response/openai-to-antigravity.js +122 -0
  158. package/open-sse/translator/response/openai-to-claude.js +266 -0
  159. package/open-sse/utils/bypassHandler.js +298 -0
  160. package/open-sse/utils/claudeCloaking.js +155 -0
  161. package/open-sse/utils/claudeHeaderCache.js +70 -0
  162. package/open-sse/utils/clientDetector.js +63 -0
  163. package/open-sse/utils/cursorChecksum.js +149 -0
  164. package/open-sse/utils/cursorProtobuf.js +904 -0
  165. package/open-sse/utils/debugLog.js +14 -0
  166. package/open-sse/utils/error.js +147 -0
  167. package/open-sse/utils/ollamaTransform.js +85 -0
  168. package/open-sse/utils/proxyFetch.js +368 -0
  169. package/open-sse/utils/reasoningContentInjector.js +79 -0
  170. package/open-sse/utils/requestLogger.js +260 -0
  171. package/open-sse/utils/responsesStreamHelpers.js +49 -0
  172. package/open-sse/utils/sessionManager.js +82 -0
  173. package/open-sse/utils/stream.js +462 -0
  174. package/open-sse/utils/streamHandler.js +250 -0
  175. package/open-sse/utils/streamHelpers.js +122 -0
  176. package/open-sse/utils/toolDeduper.js +49 -0
  177. package/open-sse/utils/usageTracking.js +347 -0
  178. package/package.json +100 -0
  179. package/postcss.config.mjs +12 -0
  180. package/public/favicon.svg +11 -0
  181. package/public/file.svg +1 -0
  182. package/public/globe.svg +1 -0
  183. package/public/i18n/literals/ar.json +195 -0
  184. package/public/i18n/literals/bn.json +195 -0
  185. package/public/i18n/literals/cs.json +195 -0
  186. package/public/i18n/literals/da.json +195 -0
  187. package/public/i18n/literals/de.json +195 -0
  188. package/public/i18n/literals/el.json +195 -0
  189. package/public/i18n/literals/es.json +195 -0
  190. package/public/i18n/literals/fi.json +195 -0
  191. package/public/i18n/literals/fr.json +195 -0
  192. package/public/i18n/literals/he.json +195 -0
  193. package/public/i18n/literals/hi.json +195 -0
  194. package/public/i18n/literals/hu.json +195 -0
  195. package/public/i18n/literals/id.json +195 -0
  196. package/public/i18n/literals/it.json +195 -0
  197. package/public/i18n/literals/ja.json +195 -0
  198. package/public/i18n/literals/ko.json +195 -0
  199. package/public/i18n/literals/nl.json +195 -0
  200. package/public/i18n/literals/no.json +195 -0
  201. package/public/i18n/literals/pl.json +195 -0
  202. package/public/i18n/literals/pt-BR.json +195 -0
  203. package/public/i18n/literals/pt-PT.json +195 -0
  204. package/public/i18n/literals/ro.json +195 -0
  205. package/public/i18n/literals/ru.json +195 -0
  206. package/public/i18n/literals/sv.json +195 -0
  207. package/public/i18n/literals/th.json +195 -0
  208. package/public/i18n/literals/tl.json +195 -0
  209. package/public/i18n/literals/tr.json +195 -0
  210. package/public/i18n/literals/uk.json +195 -0
  211. package/public/i18n/literals/ur.json +195 -0
  212. package/public/i18n/literals/vi.json +195 -0
  213. package/public/i18n/literals/zh-CN.json +772 -0
  214. package/public/i18n/literals/zh-TW.json +195 -0
  215. package/public/icons/discord.svg +4 -0
  216. package/public/icons/icon-192.svg +4 -0
  217. package/public/icons/icon-512.svg +4 -0
  218. package/public/next.svg +1 -0
  219. package/public/providers/alicode-intl.png +0 -0
  220. package/public/providers/alicode.png +0 -0
  221. package/public/providers/amp.png +0 -0
  222. package/public/providers/anthropic-m.png +0 -0
  223. package/public/providers/anthropic.png +0 -0
  224. package/public/providers/antigravity.png +0 -0
  225. package/public/providers/assemblyai.png +0 -0
  226. package/public/providers/aws-polly.png +0 -0
  227. package/public/providers/azure.png +0 -0
  228. package/public/providers/black-forest-labs.png +0 -0
  229. package/public/providers/blackbox.png +0 -0
  230. package/public/providers/brave-search.png +0 -0
  231. package/public/providers/byteplus.png +0 -0
  232. package/public/providers/cartesia.png +0 -0
  233. package/public/providers/cerebras.png +0 -0
  234. package/public/providers/chutes.png +0 -0
  235. package/public/providers/claude.png +0 -0
  236. package/public/providers/cline.png +0 -0
  237. package/public/providers/cloudflare-ai.png +0 -0
  238. package/public/providers/codebuddy.svg +37 -0
  239. package/public/providers/codex.png +0 -0
  240. package/public/providers/cohere.png +0 -0
  241. package/public/providers/comfyui.png +0 -0
  242. package/public/providers/commandcode.png +0 -0
  243. package/public/providers/continue.png +0 -0
  244. package/public/providers/copilot.png +0 -0
  245. package/public/providers/coqui.png +0 -0
  246. package/public/providers/cursor.png +0 -0
  247. package/public/providers/deepgram.png +0 -0
  248. package/public/providers/deepseek-tui.png +0 -0
  249. package/public/providers/deepseek.png +0 -0
  250. package/public/providers/droid.png +0 -0
  251. package/public/providers/edge-tts.png +0 -0
  252. package/public/providers/elevenlabs.png +0 -0
  253. package/public/providers/exa.png +0 -0
  254. package/public/providers/fal-ai.png +0 -0
  255. package/public/providers/firecrawl.png +0 -0
  256. package/public/providers/fireworks.png +0 -0
  257. package/public/providers/gemini-cli.png +0 -0
  258. package/public/providers/gemini.png +0 -0
  259. package/public/providers/github.png +0 -0
  260. package/public/providers/glm-cn.png +0 -0
  261. package/public/providers/glm.png +0 -0
  262. package/public/providers/google-pse.png +0 -0
  263. package/public/providers/google-tts.png +0 -0
  264. package/public/providers/grok-web.png +0 -0
  265. package/public/providers/groq.png +0 -0
  266. package/public/providers/hermes.png +0 -0
  267. package/public/providers/huggingface.png +0 -0
  268. package/public/providers/hyperbolic.png +0 -0
  269. package/public/providers/iflow.png +0 -0
  270. package/public/providers/inworld.png +0 -0
  271. package/public/providers/jcode.png +0 -0
  272. package/public/providers/jina-ai.png +0 -0
  273. package/public/providers/jina-reader.png +0 -0
  274. package/public/providers/kilocode.png +0 -0
  275. package/public/providers/kimi-coding.png +0 -0
  276. package/public/providers/kimi.png +0 -0
  277. package/public/providers/kiro.png +0 -0
  278. package/public/providers/linkup.png +0 -0
  279. package/public/providers/local-device.png +0 -0
  280. package/public/providers/minimax-cn.png +0 -0
  281. package/public/providers/minimax.png +0 -0
  282. package/public/providers/mistral.png +0 -0
  283. package/public/providers/nanobanana.png +0 -0
  284. package/public/providers/nebius.png +0 -0
  285. package/public/providers/nvidia.png +0 -0
  286. package/public/providers/oai-cc.png +0 -0
  287. package/public/providers/oai-r.png +0 -0
  288. package/public/providers/ollama-local.png +0 -0
  289. package/public/providers/ollama.png +0 -0
  290. package/public/providers/openai.png +0 -0
  291. package/public/providers/openclaw.png +0 -0
  292. package/public/providers/opencode-go.png +0 -0
  293. package/public/providers/opencode.png +0 -0
  294. package/public/providers/openrouter.png +0 -0
  295. package/public/providers/perplexity-web.png +0 -0
  296. package/public/providers/perplexity.png +0 -0
  297. package/public/providers/playht.png +0 -0
  298. package/public/providers/qoder.png +0 -0
  299. package/public/providers/qwen.png +0 -0
  300. package/public/providers/recraft.png +0 -0
  301. package/public/providers/roo.png +0 -0
  302. package/public/providers/runwayml.png +0 -0
  303. package/public/providers/sdwebui.png +0 -0
  304. package/public/providers/searchapi.png +0 -0
  305. package/public/providers/searxng.png +0 -0
  306. package/public/providers/serper.png +0 -0
  307. package/public/providers/siliconflow.png +0 -0
  308. package/public/providers/stability-ai.png +0 -0
  309. package/public/providers/tavily.png +0 -0
  310. package/public/providers/together.png +0 -0
  311. package/public/providers/topaz.png +0 -0
  312. package/public/providers/tortoise.png +0 -0
  313. package/public/providers/vertex-partner.png +0 -0
  314. package/public/providers/vertex.png +0 -0
  315. package/public/providers/volcengine-ark.png +0 -0
  316. package/public/providers/voyage-ai.png +0 -0
  317. package/public/providers/xai.png +0 -0
  318. package/public/providers/xiaomi-mimo.png +0 -0
  319. package/public/providers/xiaomi-tokenplan.png +0 -0
  320. package/public/providers/youcom.png +0 -0
  321. package/public/sw.js +22 -0
  322. package/public/vercel.svg +1 -0
  323. package/public/window.svg +1 -0
  324. package/scripts/compact-request-details.mjs +71 -0
  325. package/scripts/import-codex-gptjson.mjs +342 -0
  326. package/scripts/start-standalone.mjs +25 -0
  327. package/scripts/translate-readme.js +201 -0
  328. package/src/app/(dashboard)/dashboard/automation/page.js +294 -0
  329. package/src/app/(dashboard)/dashboard/basic-chat/BasicChatPageClient.js +967 -0
  330. package/src/app/(dashboard)/dashboard/basic-chat/page.js +5 -0
  331. package/src/app/(dashboard)/dashboard/cli-tools/CLIToolsPageClient.js +66 -0
  332. package/src/app/(dashboard)/dashboard/cli-tools/[toolId]/ToolDetailClient.js +173 -0
  333. package/src/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js +11 -0
  334. package/src/app/(dashboard)/dashboard/cli-tools/components/AntigravityToolCard.js +481 -0
  335. package/src/app/(dashboard)/dashboard/cli-tools/components/ApiKeySelect.js +66 -0
  336. package/src/app/(dashboard)/dashboard/cli-tools/components/BaseUrlSelect.js +174 -0
  337. package/src/app/(dashboard)/dashboard/cli-tools/components/ClaudeToolCard.js +390 -0
  338. package/src/app/(dashboard)/dashboard/cli-tools/components/ClineToolCard.js +301 -0
  339. package/src/app/(dashboard)/dashboard/cli-tools/components/CodexToolCard.js +458 -0
  340. package/src/app/(dashboard)/dashboard/cli-tools/components/CopilotToolCard.js +323 -0
  341. package/src/app/(dashboard)/dashboard/cli-tools/components/CoworkToolCard.js +640 -0
  342. package/src/app/(dashboard)/dashboard/cli-tools/components/DeepSeekTuiToolCard.js +338 -0
  343. package/src/app/(dashboard)/dashboard/cli-tools/components/DefaultToolCard.js +271 -0
  344. package/src/app/(dashboard)/dashboard/cli-tools/components/DroidToolCard.js +410 -0
  345. package/src/app/(dashboard)/dashboard/cli-tools/components/EndpointPresetControl.js +128 -0
  346. package/src/app/(dashboard)/dashboard/cli-tools/components/HermesToolCard.js +317 -0
  347. package/src/app/(dashboard)/dashboard/cli-tools/components/JcodeToolCard.js +380 -0
  348. package/src/app/(dashboard)/dashboard/cli-tools/components/KiloToolCard.js +275 -0
  349. package/src/app/(dashboard)/dashboard/cli-tools/components/MitmLinkCard.js +40 -0
  350. package/src/app/(dashboard)/dashboard/cli-tools/components/MitmServerCard.js +329 -0
  351. package/src/app/(dashboard)/dashboard/cli-tools/components/MitmToolCard.js +318 -0
  352. package/src/app/(dashboard)/dashboard/cli-tools/components/OpenClawToolCard.js +388 -0
  353. package/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js +500 -0
  354. package/src/app/(dashboard)/dashboard/cli-tools/components/ToolSummaryCard.js +39 -0
  355. package/src/app/(dashboard)/dashboard/cli-tools/components/cliEndpointMatch.js +13 -0
  356. package/src/app/(dashboard)/dashboard/cli-tools/components/index.js +19 -0
  357. package/src/app/(dashboard)/dashboard/cli-tools/page.js +7 -0
  358. package/src/app/(dashboard)/dashboard/combos/page.js +612 -0
  359. package/src/app/(dashboard)/dashboard/console-log/ConsoleLogClient.js +91 -0
  360. package/src/app/(dashboard)/dashboard/console-log/page.js +8 -0
  361. package/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.js +1555 -0
  362. package/src/app/(dashboard)/dashboard/endpoint/page.js +7 -0
  363. package/src/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +1903 -0
  364. package/src/app/(dashboard)/dashboard/media-providers/[kind]/page.js +289 -0
  365. package/src/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js +410 -0
  366. package/src/app/(dashboard)/dashboard/media-providers/web/page.js +209 -0
  367. package/src/app/(dashboard)/dashboard/mitm/MitmPageClient.js +117 -0
  368. package/src/app/(dashboard)/dashboard/mitm/page.js +5 -0
  369. package/src/app/(dashboard)/dashboard/page.js +7 -0
  370. package/src/app/(dashboard)/dashboard/profile/page.js +1140 -0
  371. package/src/app/(dashboard)/dashboard/providers/[id]/AddApiKeyModal.js +389 -0
  372. package/src/app/(dashboard)/dashboard/providers/[id]/AddCustomModelModal.js +125 -0
  373. package/src/app/(dashboard)/dashboard/providers/[id]/CompatibleModelsSection.js +250 -0
  374. package/src/app/(dashboard)/dashboard/providers/[id]/ConnectionRow.js +299 -0
  375. package/src/app/(dashboard)/dashboard/providers/[id]/CooldownTimer.js +42 -0
  376. package/src/app/(dashboard)/dashboard/providers/[id]/EditCompatibleNodeModal.js +161 -0
  377. package/src/app/(dashboard)/dashboard/providers/[id]/ModelRow.js +95 -0
  378. package/src/app/(dashboard)/dashboard/providers/[id]/PassthroughModelsSection.js +183 -0
  379. package/src/app/(dashboard)/dashboard/providers/[id]/page.js +2053 -0
  380. package/src/app/(dashboard)/dashboard/providers/[id]/page.new.js +1724 -0
  381. package/src/app/(dashboard)/dashboard/providers/components/ConnectionsCard.js +497 -0
  382. package/src/app/(dashboard)/dashboard/providers/components/ModelAvailabilityBadge.js +185 -0
  383. package/src/app/(dashboard)/dashboard/providers/components/ModelsCard.js +294 -0
  384. package/src/app/(dashboard)/dashboard/providers/new/page.js +220 -0
  385. package/src/app/(dashboard)/dashboard/providers/page.js +1365 -0
  386. package/src/app/(dashboard)/dashboard/proxy-pools/page.js +1092 -0
  387. package/src/app/(dashboard)/dashboard/quota/page.js +11 -0
  388. package/src/app/(dashboard)/dashboard/skills/page.js +112 -0
  389. package/src/app/(dashboard)/dashboard/translator/page.js +303 -0
  390. package/src/app/(dashboard)/dashboard/usage/components/OverviewCards.js +35 -0
  391. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/ProviderLimitCard.js +185 -0
  392. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/QuotaProgressBar.js +127 -0
  393. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/QuotaTable.js +259 -0
  394. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.js +1394 -0
  395. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.js +244 -0
  396. package/src/app/(dashboard)/dashboard/usage/components/ProviderTopology.js +327 -0
  397. package/src/app/(dashboard)/dashboard/usage/components/RequestDetailsTab.js +433 -0
  398. package/src/app/(dashboard)/dashboard/usage/components/UsageChart.js +141 -0
  399. package/src/app/(dashboard)/dashboard/usage/components/UsageTable.js +247 -0
  400. package/src/app/(dashboard)/dashboard/usage/page.js +75 -0
  401. package/src/app/(dashboard)/layout.js +6 -0
  402. package/src/app/api/auth/login/route.js +76 -0
  403. package/src/app/api/auth/logout/route.js +12 -0
  404. package/src/app/api/auth/oidc/callback/route.js +87 -0
  405. package/src/app/api/auth/oidc/start/route.js +52 -0
  406. package/src/app/api/auth/oidc/test/route.js +84 -0
  407. package/src/app/api/auth/status/route.js +45 -0
  408. package/src/app/api/cli-tools/all-statuses/route.js +46 -0
  409. package/src/app/api/cli-tools/antigravity-mitm/alias/route.js +53 -0
  410. package/src/app/api/cli-tools/antigravity-mitm/route.js +202 -0
  411. package/src/app/api/cli-tools/claude-settings/route.js +203 -0
  412. package/src/app/api/cli-tools/cline-settings/route.js +133 -0
  413. package/src/app/api/cli-tools/codex-gateway/accounts/route.js +16 -0
  414. package/src/app/api/cli-tools/codex-settings/route.js +239 -0
  415. package/src/app/api/cli-tools/copilot-settings/route.js +148 -0
  416. package/src/app/api/cli-tools/cowork-mcp-registry/route.js +77 -0
  417. package/src/app/api/cli-tools/cowork-mcp-tools/route.js +95 -0
  418. package/src/app/api/cli-tools/cowork-settings/route.js +412 -0
  419. package/src/app/api/cli-tools/deepseek-tui-settings/route.js +164 -0
  420. package/src/app/api/cli-tools/droid-settings/route.js +213 -0
  421. package/src/app/api/cli-tools/hermes-settings/route.js +175 -0
  422. package/src/app/api/cli-tools/jcode-settings/route.js +216 -0
  423. package/src/app/api/cli-tools/kilo-settings/route.js +131 -0
  424. package/src/app/api/cli-tools/openclaw-settings/route.js +292 -0
  425. package/src/app/api/cli-tools/opencode-settings/route.js +259 -0
  426. package/src/app/api/combos/[id]/route.js +81 -0
  427. package/src/app/api/combos/route.js +48 -0
  428. package/src/app/api/health/route.js +15 -0
  429. package/src/app/api/init/route.js +4 -0
  430. package/src/app/api/keys/[id]/route.js +58 -0
  431. package/src/app/api/keys/route.js +42 -0
  432. package/src/app/api/locale/route.js +30 -0
  433. package/src/app/api/mcp/[plugin]/message/route.js +21 -0
  434. package/src/app/api/mcp/[plugin]/sse/route.js +37 -0
  435. package/src/app/api/media-providers/tts/deepgram/voices/route.js +65 -0
  436. package/src/app/api/media-providers/tts/elevenlabs/voices/route.js +71 -0
  437. package/src/app/api/media-providers/tts/inworld/voices/route.js +61 -0
  438. package/src/app/api/media-providers/tts/minimax/voices/route.js +113 -0
  439. package/src/app/api/media-providers/tts/voices/route.js +99 -0
  440. package/src/app/api/models/alias/route.js +53 -0
  441. package/src/app/api/models/availability/route.js +103 -0
  442. package/src/app/api/models/custom/route.js +48 -0
  443. package/src/app/api/models/disabled/route.js +50 -0
  444. package/src/app/api/models/route.js +64 -0
  445. package/src/app/api/models/test/ping.js +191 -0
  446. package/src/app/api/models/test/route.js +14 -0
  447. package/src/app/api/oauth/[provider]/[action]/route.js +343 -0
  448. package/src/app/api/oauth/codebuddy/bulk-import/[jobId]/cancel/route.js +19 -0
  449. package/src/app/api/oauth/codebuddy/bulk-import/[jobId]/manual/[workerId]/route.js +30 -0
  450. package/src/app/api/oauth/codebuddy/bulk-import/[jobId]/route.js +23 -0
  451. package/src/app/api/oauth/codebuddy/bulk-import/latest/route.js +25 -0
  452. package/src/app/api/oauth/codebuddy/bulk-import/route.js +49 -0
  453. package/src/app/api/oauth/codebuddy/quota-cookie/route.js +133 -0
  454. package/src/app/api/oauth/codex/import-token/route.js +96 -0
  455. package/src/app/api/oauth/cursor/auto-import/route.js +258 -0
  456. package/src/app/api/oauth/cursor/import/route.js +100 -0
  457. package/src/app/api/oauth/gitlab/pat/route.js +62 -0
  458. package/src/app/api/oauth/iflow/cookie/route.js +137 -0
  459. package/src/app/api/oauth/kiro/auto-import/route.js +85 -0
  460. package/src/app/api/oauth/kiro/bulk-import/[jobId]/cancel/route.js +18 -0
  461. package/src/app/api/oauth/kiro/bulk-import/[jobId]/manual/[workerId]/route.js +29 -0
  462. package/src/app/api/oauth/kiro/bulk-import/[jobId]/route.js +22 -0
  463. package/src/app/api/oauth/kiro/bulk-import/latest/route.js +25 -0
  464. package/src/app/api/oauth/kiro/bulk-import/route.js +49 -0
  465. package/src/app/api/oauth/kiro/import/route.js +110 -0
  466. package/src/app/api/oauth/kiro/social-authorize/route.js +27 -0
  467. package/src/app/api/oauth/kiro/social-exchange/route.js +41 -0
  468. package/src/app/api/pricing/route.js +134 -0
  469. package/src/app/api/provider-nodes/[id]/route.js +101 -0
  470. package/src/app/api/provider-nodes/route.js +104 -0
  471. package/src/app/api/provider-nodes/validate/route.js +201 -0
  472. package/src/app/api/providers/[id]/models/route.js +526 -0
  473. package/src/app/api/providers/[id]/route.js +189 -0
  474. package/src/app/api/providers/[id]/test/route.js +23 -0
  475. package/src/app/api/providers/[id]/test/testUtils.js +714 -0
  476. package/src/app/api/providers/[id]/test-models/route.js +66 -0
  477. package/src/app/api/providers/client/route.js +126 -0
  478. package/src/app/api/providers/kilo/free-models/route.js +55 -0
  479. package/src/app/api/providers/route.js +206 -0
  480. package/src/app/api/providers/suggested-models/filters.js +20 -0
  481. package/src/app/api/providers/suggested-models/route.js +32 -0
  482. package/src/app/api/providers/test-batch/route.js +131 -0
  483. package/src/app/api/providers/validate/route.js +637 -0
  484. package/src/app/api/proxy-pools/[id]/route.js +123 -0
  485. package/src/app/api/proxy-pools/[id]/test/route.js +70 -0
  486. package/src/app/api/proxy-pools/cloudflare-deploy/route.js +145 -0
  487. package/src/app/api/proxy-pools/deno-deploy/route.js +175 -0
  488. package/src/app/api/proxy-pools/route.js +93 -0
  489. package/src/app/api/proxy-pools/vercel-deploy/route.js +142 -0
  490. package/src/app/api/settings/database/route.js +36 -0
  491. package/src/app/api/settings/proxy-test/route.js +23 -0
  492. package/src/app/api/settings/require-login/route.js +15 -0
  493. package/src/app/api/settings/route.js +100 -0
  494. package/src/app/api/shutdown/route.js +24 -0
  495. package/src/app/api/tags/route.js +18 -0
  496. package/src/app/api/translator/console-logs/route.js +24 -0
  497. package/src/app/api/translator/console-logs/stream/route.js +79 -0
  498. package/src/app/api/translator/load/route.js +45 -0
  499. package/src/app/api/translator/save/route.js +44 -0
  500. package/src/app/api/translator/send/route.js +94 -0
  501. package/src/app/api/translator/translate/route.js +90 -0
  502. package/src/app/api/tunnel/disable/route.js +12 -0
  503. package/src/app/api/tunnel/enable/route.js +16 -0
  504. package/src/app/api/tunnel/status/route.js +13 -0
  505. package/src/app/api/tunnel/tailscale-check/route.js +50 -0
  506. package/src/app/api/tunnel/tailscale-disable/route.js +12 -0
  507. package/src/app/api/tunnel/tailscale-enable/route.js +12 -0
  508. package/src/app/api/tunnel/tailscale-install/route.js +72 -0
  509. package/src/app/api/usage/[connectionId]/route.js +188 -0
  510. package/src/app/api/usage/chart/route.js +21 -0
  511. package/src/app/api/usage/history/route.js +12 -0
  512. package/src/app/api/usage/logs/route.js +12 -0
  513. package/src/app/api/usage/providers/route.js +42 -0
  514. package/src/app/api/usage/request-details/route.js +57 -0
  515. package/src/app/api/usage/request-logs/route.js +13 -0
  516. package/src/app/api/usage/stats/route.js +23 -0
  517. package/src/app/api/usage/stream/route.js +79 -0
  518. package/src/app/api/v1/api/chat/route.js +37 -0
  519. package/src/app/api/v1/audio/speech/route.js +16 -0
  520. package/src/app/api/v1/audio/transcriptions/route.js +19 -0
  521. package/src/app/api/v1/audio/voices/route.js +68 -0
  522. package/src/app/api/v1/chat/completions/route.js +35 -0
  523. package/src/app/api/v1/embeddings/route.js +21 -0
  524. package/src/app/api/v1/images/generations/route.js +16 -0
  525. package/src/app/api/v1/messages/count_tokens/route.js +52 -0
  526. package/src/app/api/v1/messages/route.js +36 -0
  527. package/src/app/api/v1/models/[kind]/route.js +55 -0
  528. package/src/app/api/v1/models/info/route.js +110 -0
  529. package/src/app/api/v1/models/route.js +451 -0
  530. package/src/app/api/v1/responses/compact/route.js +37 -0
  531. package/src/app/api/v1/responses/route.js +30 -0
  532. package/src/app/api/v1/route.js +1 -0
  533. package/src/app/api/v1/search/route.js +21 -0
  534. package/src/app/api/v1/web/fetch/route.js +21 -0
  535. package/src/app/api/v1beta/models/[...path]/route.js +328 -0
  536. package/src/app/api/v1beta/models/route.js +44 -0
  537. package/src/app/api/version/route.js +45 -0
  538. package/src/app/api/version/shutdown/route.js +15 -0
  539. package/src/app/api/version/update/route.js +21 -0
  540. package/src/app/callback/page.js +148 -0
  541. package/src/app/dashboard/settings/pricing/page.js +173 -0
  542. package/src/app/favicon.ico +0 -0
  543. package/src/app/globals.css +496 -0
  544. package/src/app/landing/components/AnimatedBackground.js +57 -0
  545. package/src/app/landing/components/Features.js +133 -0
  546. package/src/app/landing/components/FlowAnimation.js +175 -0
  547. package/src/app/landing/components/Footer.js +61 -0
  548. package/src/app/landing/components/GetStarted.js +97 -0
  549. package/src/app/landing/components/HeroSection.js +47 -0
  550. package/src/app/landing/components/HowItWorks.js +66 -0
  551. package/src/app/landing/components/Navigation.js +72 -0
  552. package/src/app/landing/page.js +106 -0
  553. package/src/app/layout.js +49 -0
  554. package/src/app/login/page.js +197 -0
  555. package/src/app/manifest.js +30 -0
  556. package/src/app/page.js +5 -0
  557. package/src/dashboardGuard.js +242 -0
  558. package/src/i18n/RuntimeI18nProvider.js +27 -0
  559. package/src/i18n/config.js +146 -0
  560. package/src/i18n/runtime.js +162 -0
  561. package/src/lib/appUpdater.js +200 -0
  562. package/src/lib/auth/dashboardSession.js +68 -0
  563. package/src/lib/auth/loginLimiter.js +52 -0
  564. package/src/lib/auth/oidc.js +234 -0
  565. package/src/lib/consoleLogBuffer.js +79 -0
  566. package/src/lib/dataDir.js +29 -0
  567. package/src/lib/db/adapters/betterSqliteAdapter.js +55 -0
  568. package/src/lib/db/adapters/bunSqliteAdapter.js +63 -0
  569. package/src/lib/db/adapters/nodeSqliteAdapter.js +84 -0
  570. package/src/lib/db/adapters/sqljsAdapter.js +115 -0
  571. package/src/lib/db/backup.js +35 -0
  572. package/src/lib/db/driver.js +85 -0
  573. package/src/lib/db/helpers/jsonCol.js +9 -0
  574. package/src/lib/db/helpers/kvStore.js +39 -0
  575. package/src/lib/db/helpers/metaStore.js +22 -0
  576. package/src/lib/db/index.js +171 -0
  577. package/src/lib/db/migrate.js +286 -0
  578. package/src/lib/db/migrations/001-initial.js +14 -0
  579. package/src/lib/db/migrations/index.js +10 -0
  580. package/src/lib/db/paths.js +18 -0
  581. package/src/lib/db/repos/aliasRepo.js +62 -0
  582. package/src/lib/db/repos/apiKeysRepo.js +75 -0
  583. package/src/lib/db/repos/combosRepo.js +73 -0
  584. package/src/lib/db/repos/connectionsRepo.js +226 -0
  585. package/src/lib/db/repos/disabledModelsRepo.js +56 -0
  586. package/src/lib/db/repos/nodesRepo.js +95 -0
  587. package/src/lib/db/repos/pricingRepo.js +108 -0
  588. package/src/lib/db/repos/proxyPoolsRepo.js +103 -0
  589. package/src/lib/db/repos/requestDetailsRepo.js +259 -0
  590. package/src/lib/db/repos/settingsRepo.js +104 -0
  591. package/src/lib/db/repos/usageRepo.js +731 -0
  592. package/src/lib/db/schema.js +157 -0
  593. package/src/lib/db/version.js +21 -0
  594. package/src/lib/disabledModelsDb.js +4 -0
  595. package/src/lib/localDb.js +21 -0
  596. package/src/lib/mcp/stdioSseBridge.js +198 -0
  597. package/src/lib/mitmAliasCache.js +46 -0
  598. package/src/lib/network/connectionProxy.js +160 -0
  599. package/src/lib/network/initOutboundProxy.js +25 -0
  600. package/src/lib/network/outboundProxy.js +68 -0
  601. package/src/lib/network/proxyTest.js +91 -0
  602. package/src/lib/oauth/constants/oauth.js +284 -0
  603. package/src/lib/oauth/constants/xai.js +61 -0
  604. package/src/lib/oauth/providers.js +1506 -0
  605. package/src/lib/oauth/services/antigravity.js +321 -0
  606. package/src/lib/oauth/services/claude.js +136 -0
  607. package/src/lib/oauth/services/codebuddyBulkImportManager.js +454 -0
  608. package/src/lib/oauth/services/codex.js +144 -0
  609. package/src/lib/oauth/services/cursor.js +179 -0
  610. package/src/lib/oauth/services/gemini.js +240 -0
  611. package/src/lib/oauth/services/github.js +225 -0
  612. package/src/lib/oauth/services/iflow.js +202 -0
  613. package/src/lib/oauth/services/index.js +17 -0
  614. package/src/lib/oauth/services/kiro.js +334 -0
  615. package/src/lib/oauth/services/kiroBulkImportManager.js +778 -0
  616. package/src/lib/oauth/services/kiroConnections.js +93 -0
  617. package/src/lib/oauth/services/kiroGoogleAutomation.js +1136 -0
  618. package/src/lib/oauth/services/oauth.js +157 -0
  619. package/src/lib/oauth/services/openai.js +123 -0
  620. package/src/lib/oauth/services/qoder.js +216 -0
  621. package/src/lib/oauth/services/qwen.js +170 -0
  622. package/src/lib/oauth/services/xai.js +238 -0
  623. package/src/lib/oauth/utils/banner.js +63 -0
  624. package/src/lib/oauth/utils/pkce.js +39 -0
  625. package/src/lib/oauth/utils/server.js +415 -0
  626. package/src/lib/oauth/utils/ui.js +48 -0
  627. package/src/lib/providerNormalization.js +45 -0
  628. package/src/lib/qoder/constants.js +64 -0
  629. package/src/lib/qoder/cosy.js +175 -0
  630. package/src/lib/qoder/encoding.js +55 -0
  631. package/src/lib/requestDetailsDb.js +4 -0
  632. package/src/lib/tunnel/cloudflare/cloudflared.js +449 -0
  633. package/src/lib/tunnel/cloudflare/config.js +9 -0
  634. package/src/lib/tunnel/cloudflare/healthCheck.js +29 -0
  635. package/src/lib/tunnel/cloudflare/manager.js +151 -0
  636. package/src/lib/tunnel/cloudflare/pid.js +23 -0
  637. package/src/lib/tunnel/index.js +48 -0
  638. package/src/lib/tunnel/shared/dnsResolver.js +17 -0
  639. package/src/lib/tunnel/shared/internetCheck.js +26 -0
  640. package/src/lib/tunnel/shared/state.js +41 -0
  641. package/src/lib/tunnel/shared/watchdogConfig.js +8 -0
  642. package/src/lib/tunnel/tailscale/config.js +7 -0
  643. package/src/lib/tunnel/tailscale/healthCheck.js +29 -0
  644. package/src/lib/tunnel/tailscale/manager.js +129 -0
  645. package/src/lib/tunnel/tailscale/tailscale.js +790 -0
  646. package/src/lib/updater/updater.js +235 -0
  647. package/src/lib/usage/fetcher.js +208 -0
  648. package/src/lib/usageDb.js +7 -0
  649. package/src/mitm/antigravityIdeVersion.js +50 -0
  650. package/src/mitm/cert/generate.js +32 -0
  651. package/src/mitm/cert/install.js +269 -0
  652. package/src/mitm/cert/rootCA.js +173 -0
  653. package/src/mitm/config.js +87 -0
  654. package/src/mitm/dbReader.js +22 -0
  655. package/src/mitm/dns/dnsConfig.js +266 -0
  656. package/src/mitm/handlers/antigravity.js +33 -0
  657. package/src/mitm/handlers/base.js +226 -0
  658. package/src/mitm/handlers/copilot.js +35 -0
  659. package/src/mitm/handlers/cursor.js +15 -0
  660. package/src/mitm/handlers/kiro.js +526 -0
  661. package/src/mitm/logger.js +106 -0
  662. package/src/mitm/manager.js +851 -0
  663. package/src/mitm/paths.js +32 -0
  664. package/src/mitm/server.js +435 -0
  665. package/src/mitm/winElevated.js +81 -0
  666. package/src/models/index.js +38 -0
  667. package/src/proxy.js +5 -0
  668. package/src/shared/components/AddCustomEmbeddingModal.js +183 -0
  669. package/src/shared/components/Avatar.js +88 -0
  670. package/src/shared/components/Badge.js +54 -0
  671. package/src/shared/components/BulkAccountAutomationModal.js +508 -0
  672. package/src/shared/components/Button.js +56 -0
  673. package/src/shared/components/Card.js +116 -0
  674. package/src/shared/components/ChangelogModal.js +97 -0
  675. package/src/shared/components/CodeBuddyQuotaCookieModal.js +109 -0
  676. package/src/shared/components/ComboFormModal.js +176 -0
  677. package/src/shared/components/CursorAuthModal.js +212 -0
  678. package/src/shared/components/DonateModal.js +136 -0
  679. package/src/shared/components/Drawer.js +82 -0
  680. package/src/shared/components/EditConnectionModal.js +286 -0
  681. package/src/shared/components/Footer.js +132 -0
  682. package/src/shared/components/GitLabAuthModal.js +194 -0
  683. package/src/shared/components/Header.js +380 -0
  684. package/src/shared/components/HeaderLanguage.js +46 -0
  685. package/src/shared/components/HeaderMenu.js +126 -0
  686. package/src/shared/components/IFlowCookieModal.js +132 -0
  687. package/src/shared/components/Input.js +65 -0
  688. package/src/shared/components/KiroAuthModal.js +1171 -0
  689. package/src/shared/components/KiroOAuthWrapper.js +149 -0
  690. package/src/shared/components/KiroSocialOAuthModal.js +205 -0
  691. package/src/shared/components/LanguageSwitcher.js +190 -0
  692. package/src/shared/components/Loading.js +75 -0
  693. package/src/shared/components/ManualConfigModal.js +44 -0
  694. package/src/shared/components/McpMarketplaceModal.js +255 -0
  695. package/src/shared/components/Modal.js +146 -0
  696. package/src/shared/components/ModelSelectModal.js +537 -0
  697. package/src/shared/components/NineRemoteButton.js +23 -0
  698. package/src/shared/components/NineRemotePromoModal.js +99 -0
  699. package/src/shared/components/NoAuthProxyCard.js +86 -0
  700. package/src/shared/components/OAuthModal.js +682 -0
  701. package/src/shared/components/Pagination.js +150 -0
  702. package/src/shared/components/PricingModal.js +208 -0
  703. package/src/shared/components/ProviderIcon.js +63 -0
  704. package/src/shared/components/ProviderInfoCard.js +82 -0
  705. package/src/shared/components/RequestLogger.js +121 -0
  706. package/src/shared/components/SegmentedControl.js +48 -0
  707. package/src/shared/components/Select.js +67 -0
  708. package/src/shared/components/Sidebar.js +441 -0
  709. package/src/shared/components/ThemeProvider.js +15 -0
  710. package/src/shared/components/ThemeToggle.js +42 -0
  711. package/src/shared/components/Toggle.js +69 -0
  712. package/src/shared/components/Tooltip.js +25 -0
  713. package/src/shared/components/UsageStats.js +505 -0
  714. package/src/shared/components/index.js +46 -0
  715. package/src/shared/components/layouts/AuthLayout.js +29 -0
  716. package/src/shared/components/layouts/DashboardLayout.js +104 -0
  717. package/src/shared/components/layouts/index.js +4 -0
  718. package/src/shared/constants/cliTools.js +397 -0
  719. package/src/shared/constants/colors.js +77 -0
  720. package/src/shared/constants/config.js +99 -0
  721. package/src/shared/constants/coworkPlugins.js +75 -0
  722. package/src/shared/constants/index.js +4 -0
  723. package/src/shared/constants/locales.js +36 -0
  724. package/src/shared/constants/mitmToolHosts.js +12 -0
  725. package/src/shared/constants/models.js +38 -0
  726. package/src/shared/constants/pricing.js +303 -0
  727. package/src/shared/constants/providers.js +289 -0
  728. package/src/shared/constants/skills.js +78 -0
  729. package/src/shared/constants/ttsProviders.js +138 -0
  730. package/src/shared/hooks/index.js +2 -0
  731. package/src/shared/hooks/useCopyToClipboard.js +43 -0
  732. package/src/shared/hooks/useTheme.js +60 -0
  733. package/src/shared/services/bootstrap.js +12 -0
  734. package/src/shared/services/initializeApp.js +268 -0
  735. package/src/shared/utils/api.js +93 -0
  736. package/src/shared/utils/apiKey.js +98 -0
  737. package/src/shared/utils/clineAuth.js +37 -0
  738. package/src/shared/utils/cn.js +11 -0
  739. package/src/shared/utils/connectionStatus.js +162 -0
  740. package/src/shared/utils/index.js +40 -0
  741. package/src/shared/utils/machine.js +6 -0
  742. package/src/shared/utils/machineId.js +66 -0
  743. package/src/shared/utils/providerModelsFetcher.js +30 -0
  744. package/src/sse/handlers/chat.js +261 -0
  745. package/src/sse/handlers/embeddings.js +141 -0
  746. package/src/sse/handlers/fetch.js +213 -0
  747. package/src/sse/handlers/imageGeneration.js +142 -0
  748. package/src/sse/handlers/search.js +206 -0
  749. package/src/sse/handlers/stt.js +88 -0
  750. package/src/sse/handlers/tts.js +114 -0
  751. package/src/sse/services/auth.js +346 -0
  752. package/src/sse/services/codexGateway.js +215 -0
  753. package/src/sse/services/model.js +99 -0
  754. package/src/sse/services/tokenRefresh.js +319 -0
  755. package/src/sse/utils/logger.js +75 -0
  756. package/src/store/headerSearchStore.js +19 -0
  757. package/src/store/index.js +6 -0
  758. package/src/store/notificationStore.js +45 -0
  759. package/src/store/providerStore.js +55 -0
  760. package/src/store/settingsStore.js +51 -0
  761. package/src/store/themeStore.js +54 -0
  762. package/src/store/userStore.js +20 -0
  763. package/start.sh +4 -0
@@ -0,0 +1,185 @@
1
+ import { HTTP_STATUS, RETRY_CONFIG, DEFAULT_RETRY_CONFIG, resolveRetryEntry, FETCH_CONNECT_TIMEOUT_MS } from "../config/runtimeConfig.js";
2
+ import { shouldRefreshCredentials } from "../services/oauthCredentialManager.js";
3
+ import { proxyAwareFetch } from "../utils/proxyFetch.js";
4
+ import { dbg } from "../utils/debugLog.js";
5
+
6
+ /**
7
+ * BaseExecutor - Base class for provider executors
8
+ */
9
+ export class BaseExecutor {
10
+ constructor(provider, config) {
11
+ this.provider = provider;
12
+ this.config = config;
13
+ this.noAuth = config?.noAuth || false;
14
+ }
15
+
16
+ getProvider() {
17
+ return this.provider;
18
+ }
19
+
20
+ getBaseUrls() {
21
+ return this.config.baseUrls || (this.config.baseUrl ? [this.config.baseUrl] : []);
22
+ }
23
+
24
+ getFallbackCount() {
25
+ return this.getBaseUrls().length || 1;
26
+ }
27
+
28
+ buildUrl(model, stream, urlIndex = 0, credentials = null) {
29
+ if (this.provider?.startsWith?.("openai-compatible-")) {
30
+ const baseUrl = credentials?.providerSpecificData?.baseUrl || "https://api.openai.com/v1";
31
+ const normalized = baseUrl.replace(/\/$/, "");
32
+ const path = this.provider.includes("responses") ? "/responses" : "/chat/completions";
33
+ return `${normalized}${path}`;
34
+ }
35
+ if (this.provider?.startsWith?.("anthropic-compatible-")) {
36
+ const baseUrl = credentials?.providerSpecificData?.baseUrl || "https://api.anthropic.com/v1";
37
+ const normalized = baseUrl.replace(/\/$/, "");
38
+ return `${normalized}/messages`;
39
+ }
40
+ const baseUrls = this.getBaseUrls();
41
+ return baseUrls[urlIndex] || baseUrls[0] || this.config.baseUrl;
42
+ }
43
+
44
+ buildHeaders(credentials, stream = true) {
45
+ const headers = {
46
+ "Content-Type": "application/json",
47
+ ...this.config.headers
48
+ };
49
+
50
+ if (this.provider?.startsWith?.("anthropic-compatible-")) {
51
+ // Anthropic-compatible providers use x-api-key header
52
+ if (credentials.apiKey) {
53
+ headers["x-api-key"] = credentials.apiKey;
54
+ } else if (credentials.accessToken) {
55
+ headers["Authorization"] = `Bearer ${credentials.accessToken}`;
56
+ }
57
+ if (!headers["anthropic-version"]) {
58
+ headers["anthropic-version"] = "2023-06-01";
59
+ }
60
+ } else {
61
+ // Standard Bearer token auth for other providers
62
+ if (credentials.accessToken) {
63
+ headers["Authorization"] = `Bearer ${credentials.accessToken}`;
64
+ } else if (credentials.apiKey) {
65
+ headers["Authorization"] = `Bearer ${credentials.apiKey}`;
66
+ }
67
+ }
68
+
69
+ if (stream) {
70
+ headers["Accept"] = "text/event-stream";
71
+ }
72
+
73
+ return headers;
74
+ }
75
+
76
+ // Override in subclass for provider-specific transformations
77
+ transformRequest(model, body, stream, credentials) {
78
+ return body;
79
+ }
80
+
81
+ // Override in subclass for providers that need encoded/binary request bodies.
82
+ prepareRequestBody(transformedBody, headers) {
83
+ return JSON.stringify(transformedBody);
84
+ }
85
+
86
+ shouldRetry(status, urlIndex) {
87
+ return status === HTTP_STATUS.RATE_LIMITED && urlIndex + 1 < this.getFallbackCount();
88
+ }
89
+
90
+ // Override in subclass for provider-specific refresh
91
+ async refreshCredentials(credentials, log, proxyOptions = null) {
92
+ return null;
93
+ }
94
+
95
+ needsRefresh(credentials) {
96
+ return shouldRefreshCredentials(this.provider, credentials);
97
+ }
98
+
99
+ parseError(response, bodyText) {
100
+ return { status: response.status, message: bodyText || `HTTP ${response.status}` };
101
+ }
102
+
103
+ async execute({ model, body, stream, credentials, signal, log, proxyOptions = null }) {
104
+ const fallbackCount = this.getFallbackCount();
105
+ let lastError = null;
106
+ let lastStatus = 0;
107
+ const retryAttemptsByUrl = {};
108
+
109
+ // Merge default retry config with provider-specific config
110
+ const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
111
+
112
+ // Schedule retry via retryConfig[statusKey]. Returns true when caller should `urlIndex--; continue`
113
+ const tryRetry = async (urlIndex, statusKey, reason) => {
114
+ const { attempts, delayMs } = resolveRetryEntry(retryConfig[statusKey]);
115
+ if (attempts <= 0 || retryAttemptsByUrl[urlIndex] >= attempts) return false;
116
+ retryAttemptsByUrl[urlIndex]++;
117
+ log?.debug?.("RETRY", `${reason} retry ${retryAttemptsByUrl[urlIndex]}/${attempts} after ${delayMs / 1000}s`);
118
+ await new Promise(resolve => setTimeout(resolve, delayMs));
119
+ return true;
120
+ };
121
+
122
+ for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
123
+ const url = this.buildUrl(model, stream, urlIndex, credentials);
124
+ const transformedBody = this.transformRequest(model, body, stream, credentials);
125
+ const headers = this.buildHeaders(credentials, stream);
126
+
127
+ if (!retryAttemptsByUrl[urlIndex]) retryAttemptsByUrl[urlIndex] = 0;
128
+
129
+ // Abort if upstream doesn't return response headers within connection timeout
130
+ const connectCtrl = new AbortController();
131
+ const timeoutMs = this.config?.timeoutMs || FETCH_CONNECT_TIMEOUT_MS;
132
+ const connectTimer = setTimeout(() => connectCtrl.abort(new Error("fetch connect timeout")), timeoutMs);
133
+ const mergedSignal = signal ? AbortSignal.any([signal, connectCtrl.signal]) : connectCtrl.signal;
134
+
135
+ try {
136
+ const requestBody = this.prepareRequestBody(transformedBody, headers);
137
+ const requestBodySize = typeof requestBody === "string"
138
+ ? requestBody.length
139
+ : requestBody?.byteLength ?? requestBody?.length ?? "?";
140
+ const fetchT0 = Date.now();
141
+ dbg("FETCH", `${this.provider.toUpperCase()} → ${url} | body=${requestBodySize}B | connectTimeout=${timeoutMs}ms`);
142
+ const response = await proxyAwareFetch(url, {
143
+ method: "POST",
144
+ headers,
145
+ body: requestBody,
146
+ signal: mergedSignal
147
+ }, proxyOptions);
148
+ clearTimeout(connectTimer);
149
+ const ct = response.headers?.get?.("content-type") || "";
150
+ const cl = response.headers?.get?.("content-length") || "?";
151
+ dbg("FETCH", `${this.provider.toUpperCase()} ← ${response.status} | ttft=${Date.now() - fetchT0}ms | ct=${ct} | cl=${cl}`);
152
+
153
+ if (await tryRetry(urlIndex, response.status, `status ${response.status}`)) { urlIndex--; continue; }
154
+
155
+ if (this.shouldRetry(response.status, urlIndex)) {
156
+ log?.debug?.("RETRY", `${response.status} on ${url}, trying fallback ${urlIndex + 1}`);
157
+ lastStatus = response.status;
158
+ continue;
159
+ }
160
+
161
+ return { response, url, headers, transformedBody };
162
+ } catch (error) {
163
+ clearTimeout(connectTimer);
164
+ lastError = error;
165
+ const isConnectTimeout = connectCtrl.signal.aborted && error.name === "AbortError";
166
+ dbg("FETCH", `${this.provider.toUpperCase()} ✖ ${error.name}: ${error.message}${isConnectTimeout ? " (connect timeout)" : ""}`);
167
+ // Connect timeout is internal — convert to retryable network error, don't propagate AbortError
168
+ if (error.name === "AbortError" && !isConnectTimeout) throw error;
169
+
170
+ // Map network/fetch exceptions to 502 retry config
171
+ if (await tryRetry(urlIndex, HTTP_STATUS.BAD_GATEWAY, `network "${error.message}"`)) { urlIndex--; continue; }
172
+
173
+ if (urlIndex + 1 < fallbackCount) {
174
+ log?.debug?.("RETRY", `Error on ${url}, trying fallback ${urlIndex + 1}`);
175
+ continue;
176
+ }
177
+ throw error;
178
+ }
179
+ }
180
+
181
+ throw lastError || new Error(`All ${fallbackCount} URLs failed with status ${lastStatus}`);
182
+ }
183
+ }
184
+
185
+ export default BaseExecutor;
@@ -0,0 +1,469 @@
1
+ import { createHash } from "crypto";
2
+ import { BaseExecutor } from "./base.js";
3
+ import { CODEX_DEFAULT_INSTRUCTIONS } from "../config/codexInstructions.js";
4
+ import { PROVIDERS } from "../config/providers.js";
5
+ import {
6
+ refreshProviderCredentials,
7
+ shouldRefreshCredentials,
8
+ } from "../services/oauthCredentialManager.js";
9
+ import { normalizeResponsesInput } from "../translator/helpers/responsesApiHelper.js";
10
+ import { fetchImageAsBase64 } from "../translator/helpers/imageHelper.js";
11
+ import { getModelUpstreamId } from "../config/providerModels.js";
12
+ import { getConsistentMachineId } from "../../src/shared/utils/machineId.js";
13
+ import { DEFAULT_RETRY_CONFIG, resolveRetryEntry } from "../config/runtimeConfig.js";
14
+ import { dbg } from "../utils/debugLog.js";
15
+
16
+ // SSE error patterns inside 200-OK body that should trigger retry as if 503
17
+ const CODEX_SSE_OVERLOADED_PATTERNS = ["server_is_overloaded", "service_unavailable_error"];
18
+ const CODEX_SSE_PEEK_BYTES = 4096;
19
+
20
+ // In-memory map: hash(machineId + first assistant content) → { sessionId, lastUsed }
21
+ const SESSION_TTL_MS = 60 * 60 * 1000; // 1 hour
22
+ const assistantSessionMap = new Map();
23
+
24
+ // Server-generated item id prefixes that Codex /responses cannot resolve when store=false
25
+ const SERVER_ID_PATTERN = /^(rs|fc|resp|msg)_/;
26
+
27
+ // Hosted tool types that Codex/OpenAI Responses executes server-side
28
+ const CODEX_HOSTED_TOOL_TYPES = new Set([
29
+ "image_generation", "web_search", "web_search_preview", "file_search",
30
+ "computer", "computer_use_preview", "code_interpreter", "mcp", "local_shell"
31
+ ]);
32
+
33
+ // Allowlist of fields accepted by Codex Responses API — anything else is stripped
34
+ const RESPONSES_API_ALLOWLIST = new Set([
35
+ "model", "input", "instructions", "tools", "tool_choice", "stream", "store",
36
+ "reasoning", "service_tier", "include", "prompt_cache_key", "client_metadata"
37
+ ]);
38
+
39
+ // Convert role=system → role=developer in body.input (keeps content in cacheable prefix)
40
+ function convertSystemToDeveloperRole(body) {
41
+ if (!Array.isArray(body.input)) return;
42
+ for (const item of body.input) {
43
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
44
+ const isSystemMsg = item.role === "system" && (!item.type || item.type === "message");
45
+ if (isSystemMsg) item.role = "developer";
46
+ }
47
+ }
48
+
49
+ // Strip server-generated item IDs (rs_/fc_/resp_/msg_) from input — avoids 404 with store=false
50
+ function stripStoredItemReferences(body) {
51
+ if (!Array.isArray(body.input)) return;
52
+ body.input = body.input.filter((item) => {
53
+ if (typeof item === "string" && SERVER_ID_PATTERN.test(item)) return false;
54
+ if (item && typeof item === "object" && !Array.isArray(item)) {
55
+ if (item.type === "item_reference") return false;
56
+ if (typeof item.id === "string" && SERVER_ID_PATTERN.test(item.id)) delete item.id;
57
+ }
58
+ return true;
59
+ });
60
+ }
61
+
62
+ // Flatten Chat-Completions tool shape into Responses flat format + filter unsupported tools
63
+ function normalizeCodexTools(body) {
64
+ if (!Array.isArray(body.tools)) return;
65
+ const validNames = new Set();
66
+ body.tools = body.tools.filter((tool) => {
67
+ if (!tool || typeof tool !== "object" || Array.isArray(tool)) return false;
68
+ const type = typeof tool.type === "string" ? tool.type : "";
69
+ if (type === "namespace") {
70
+ if (Array.isArray(tool.tools)) {
71
+ for (const st of tool.tools) {
72
+ const n = typeof st?.name === "string" ? st.name.trim().slice(0, 128) : "";
73
+ if (n) validNames.add(n);
74
+ }
75
+ }
76
+ return true;
77
+ }
78
+ if (type !== "function") {
79
+ if (!type || tool.function || typeof tool.name === "string") return false;
80
+ return CODEX_HOSTED_TOOL_TYPES.has(type);
81
+ }
82
+ const fn = tool.function && typeof tool.function === "object" && !Array.isArray(tool.function) ? tool.function : null;
83
+ const rawName = typeof tool.name === "string" ? tool.name : (typeof fn?.name === "string" ? fn.name : "");
84
+ const name = rawName.trim();
85
+ if (!name) return false;
86
+ const description = typeof tool.description === "string" ? tool.description : (typeof fn?.description === "string" ? fn.description : "");
87
+ const parameters = (tool.parameters && typeof tool.parameters === "object" && !Array.isArray(tool.parameters))
88
+ ? tool.parameters
89
+ : (fn?.parameters && typeof fn.parameters === "object" && !Array.isArray(fn.parameters) ? fn.parameters : { type: "object", properties: {} });
90
+ for (const k of Object.keys(tool)) delete tool[k];
91
+ tool.type = "function";
92
+ tool.name = name.slice(0, 128);
93
+ if (description) tool.description = description;
94
+ tool.parameters = parameters;
95
+ validNames.add(name);
96
+ return true;
97
+ });
98
+ // Drop tool_choice if it references an unknown function name
99
+ if (body.tool_choice && typeof body.tool_choice === "object" && !Array.isArray(body.tool_choice)) {
100
+ if (body.tool_choice.type === "function") {
101
+ const n = typeof body.tool_choice.name === "string" ? body.tool_choice.name.trim() : "";
102
+ if (!n || !validNames.has(n)) delete body.tool_choice;
103
+ }
104
+ }
105
+ }
106
+
107
+ // Cache machine ID at module level (resolved once)
108
+ let cachedMachineId = null;
109
+ getConsistentMachineId().then(id => { cachedMachineId = id; });
110
+
111
+ function hashContent(text) {
112
+ return createHash("sha256").update(text).digest("hex").slice(0, 16);
113
+ }
114
+
115
+ function generateSessionId() {
116
+ return `sess_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
117
+ }
118
+
119
+ // Extract text content from an input item
120
+ function extractItemText(item) {
121
+ if (!item) return "";
122
+ if (typeof item.content === "string") return item.content;
123
+ if (Array.isArray(item.content)) {
124
+ return item.content.map(c => c.text || c.output || "").filter(Boolean).join("");
125
+ }
126
+ return "";
127
+ }
128
+
129
+ // Normalize a session id candidate (trim, length cap)
130
+ function normalizeSessionId(value) {
131
+ if (typeof value !== "string") return null;
132
+ const v = value.trim();
133
+ if (!v || v.length > 256) return null;
134
+ return v;
135
+ }
136
+
137
+ // Resolve prompt-cache session id with priority: body → assistant-text-hash → workspaceId → machineId
138
+ function resolveCacheSessionId(body, credentials, machineId) {
139
+ // 1. Client-provided session/conversation id (highest priority — stable per conversation)
140
+ const fromBody =
141
+ normalizeSessionId(body?.prompt_cache_key) ||
142
+ normalizeSessionId(body?.session_id) ||
143
+ normalizeSessionId(body?.conversation_id);
144
+ if (fromBody) return fromBody;
145
+
146
+ // 2. Hash accumulated assistant text (≥50 chars) — sticky session across turns
147
+ if (Array.isArray(body?.input) && body.input.length > 0) {
148
+ let text = "";
149
+ const MIN_LEN = 50;
150
+ const CAP_LEN = 200;
151
+ for (const item of body.input) {
152
+ if (item?.role !== "assistant") continue;
153
+ const t = extractItemText(item);
154
+ if (!t) continue;
155
+ text += t;
156
+ if (text.length >= CAP_LEN) break;
157
+ }
158
+ if (text.length >= MIN_LEN) {
159
+ const hash = hashContent((machineId || "") + text.slice(0, CAP_LEN));
160
+ const entry = assistantSessionMap.get(hash);
161
+ if (entry) {
162
+ entry.lastUsed = Date.now();
163
+ return entry.sessionId;
164
+ }
165
+ const sessionId = generateSessionId();
166
+ assistantSessionMap.set(hash, { sessionId, lastUsed: Date.now() });
167
+ return sessionId;
168
+ }
169
+ }
170
+
171
+ // 3. Account-wide fallback (workspaceId from connection)
172
+ const workspaceId = normalizeSessionId(credentials?.providerSpecificData?.workspaceId);
173
+ if (workspaceId) return workspaceId;
174
+
175
+ // 4. Last resort — stable per-machine id
176
+ return machineId ? `sess_${hashContent(machineId)}` : generateSessionId();
177
+ }
178
+
179
+ // Cleanup expired entries periodically
180
+ setInterval(() => {
181
+ const now = Date.now();
182
+ for (const [key, entry] of assistantSessionMap) {
183
+ if (now - entry.lastUsed > SESSION_TTL_MS) assistantSessionMap.delete(key);
184
+ }
185
+ }, 10 * 60 * 1000);
186
+
187
+ /**
188
+ * Codex Executor - handles OpenAI Codex API (Responses API format)
189
+ * Automatically injects default instructions if missing
190
+ */
191
+ export class CodexExecutor extends BaseExecutor {
192
+ constructor() {
193
+ super("codex", PROVIDERS.codex);
194
+ this._currentSessionId = null;
195
+ }
196
+
197
+ /**
198
+ * Override headers to add codex-specific identity headers.
199
+ * transformRequest runs BEFORE buildHeaders, sets this._currentSessionId.
200
+ */
201
+ buildHeaders(credentials, stream = true) {
202
+ const headers = super.buildHeaders(credentials, stream);
203
+ headers["session_id"] = this._currentSessionId || credentials?.connectionId || "default";
204
+ // Identify client type to Codex backend (matches official codex CLI)
205
+ if (!headers["originator"]) headers["originator"] = "codex_cli_rs";
206
+ // Workspace binding header — improves account scope + cache affinity
207
+ const workspaceId = credentials?.providerSpecificData?.workspaceId;
208
+ if (typeof workspaceId === "string" && workspaceId && !headers["chatgpt-account-id"]) {
209
+ headers["chatgpt-account-id"] = workspaceId;
210
+ }
211
+ return headers;
212
+ }
213
+
214
+ buildUrl(model, stream, urlIndex = 0, credentials = null) {
215
+ const base = super.buildUrl(model, stream, urlIndex, credentials);
216
+ return this._isCompact ? `${base}/compact` : base;
217
+ }
218
+
219
+ async refreshCredentials(credentials, log) {
220
+ if (!credentials?.refreshToken) return null;
221
+ return refreshProviderCredentials("codex", credentials, log);
222
+ }
223
+
224
+ needsRefresh(credentials) {
225
+ return shouldRefreshCredentials("codex", credentials);
226
+ }
227
+
228
+ /**
229
+ * Prefetch remote image URLs and inline them as base64 data URIs.
230
+ * Runs before execute() because Codex backend cannot fetch remote images.
231
+ * Mutates body.input in place.
232
+ */
233
+ async prefetchImages(body) {
234
+ if (!Array.isArray(body?.input)) return;
235
+ for (const item of body.input) {
236
+ if (!Array.isArray(item.content)) continue;
237
+ const pending = item.content.map(async (c) => {
238
+ if (c.type !== "image_url") return c;
239
+ const url = typeof c.image_url === "string" ? c.image_url : c.image_url?.url;
240
+ const detail = c.image_url?.detail || "auto";
241
+ if (!url) return c;
242
+ if (url.startsWith("data:")) return { type: "input_image", image_url: url, detail };
243
+ const fetched = await fetchImageAsBase64(url, { timeoutMs: 15000 });
244
+ return { type: "input_image", image_url: fetched?.url || url, detail };
245
+ });
246
+ item.content = await Promise.all(pending);
247
+ }
248
+ }
249
+
250
+ async execute(args) {
251
+ const imgCount = Array.isArray(args.body?.input) ? args.body.input.reduce((n, it) => n + (Array.isArray(it.content) ? it.content.filter(c => c.type === "image_url").length : 0), 0) : 0;
252
+ const inputLen = Array.isArray(args.body?.input) ? args.body.input.length : 0;
253
+ dbg("CODEX", `execute start | inputItems=${inputLen} | images=${imgCount} | sessionId=${this._currentSessionId || "pending"}`);
254
+ if (imgCount > 0) {
255
+ const t0 = Date.now();
256
+ await this.prefetchImages(args.body);
257
+ dbg("CODEX", `prefetchImages done | ${Date.now() - t0}ms`);
258
+ } else {
259
+ await this.prefetchImages(args.body);
260
+ }
261
+
262
+ // Retry loop for SSE-level overloaded errors (200 OK body contains event: error)
263
+ // Reuses 503 retry config — same semantic: upstream temporarily unavailable
264
+ const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
265
+ const { attempts, delayMs } = resolveRetryEntry(retryConfig[503]);
266
+ let attempt = 0;
267
+ while (true) {
268
+ const result = await super.execute(args);
269
+ const peek = await this._peekSseOverloaded(result.response);
270
+ if (!peek.matched) {
271
+ // Replace body with re-assembled stream (prefix bytes already read + rest)
272
+ if (peek.replacementBody) {
273
+ result.response = new Response(peek.replacementBody, {
274
+ status: result.response.status,
275
+ statusText: result.response.statusText,
276
+ headers: result.response.headers,
277
+ });
278
+ }
279
+ return result;
280
+ }
281
+ if (attempt >= attempts) {
282
+ args.log?.warn?.("RETRY", `CODEX | SSE overloaded "${peek.matched}" — retries exhausted (${attempt}/${attempts})`);
283
+ // Out of retries → return with replacement body so client gets the error
284
+ if (peek.replacementBody) {
285
+ result.response = new Response(peek.replacementBody, {
286
+ status: result.response.status,
287
+ statusText: result.response.statusText,
288
+ headers: result.response.headers,
289
+ });
290
+ }
291
+ return result;
292
+ }
293
+ attempt++;
294
+ args.log?.debug?.("RETRY", `CODEX | SSE "${peek.matched}" retry ${attempt}/${attempts} after ${delayMs / 1000}s`);
295
+ dbg("CODEX", `SSE overloaded "${peek.matched}" → retry ${attempt}/${attempts} in ${delayMs}ms`);
296
+ try { await result.response.body?.cancel?.(); } catch { /* noop */ }
297
+ await new Promise(r => setTimeout(r, delayMs));
298
+ }
299
+ }
300
+
301
+ // Peek first N bytes of SSE body to detect upstream "overloaded" errors.
302
+ // Returns { matched: string|null, replacementBody: ReadableStream|null }.
303
+ // Caller MUST use replacementBody (original body has been read).
304
+ async _peekSseOverloaded(response) {
305
+ if (!response || !response.ok || !response.body) return { matched: null, replacementBody: null };
306
+ const reader = response.body.getReader();
307
+ const decoder = new TextDecoder();
308
+ const chunks = [];
309
+ let text = "";
310
+ let matched = null;
311
+ try {
312
+ while (text.length < CODEX_SSE_PEEK_BYTES) {
313
+ const { done, value } = await reader.read();
314
+ if (done) break;
315
+ chunks.push(value);
316
+ text += decoder.decode(value, { stream: true });
317
+ const hit = CODEX_SSE_OVERLOADED_PATTERNS.find(p => text.includes(p));
318
+ if (hit) { matched = hit; break; }
319
+ }
320
+ } catch (e) {
321
+ dbg("CODEX", `peek read error: ${e.message}`);
322
+ }
323
+ reader.releaseLock();
324
+
325
+ // Re-assemble stream: prefix chunks + remaining upstream body
326
+ const upstream = response.body;
327
+ let upstreamReader = null;
328
+ const replacementBody = new ReadableStream({
329
+ start(controller) {
330
+ for (const c of chunks) controller.enqueue(c);
331
+ upstreamReader = upstream.getReader();
332
+ },
333
+ async pull(controller) {
334
+ try {
335
+ const { done, value } = await upstreamReader.read();
336
+ if (done) { controller.close(); return; }
337
+ controller.enqueue(value);
338
+ } catch (e) { controller.error(e); }
339
+ },
340
+ cancel(reason) {
341
+ try { upstreamReader?.cancel(reason); } catch { /* noop */ }
342
+ },
343
+ });
344
+ return { matched, replacementBody };
345
+ }
346
+
347
+ // Parse Codex usage_limit_reached to extract precise resetsAtMs; fallback to default otherwise
348
+ parseError(response, bodyText) {
349
+ if (response.status === 429 && bodyText) {
350
+ try {
351
+ const json = JSON.parse(bodyText);
352
+ const err = json?.error;
353
+ if (err?.type === "usage_limit_reached") {
354
+ const now = Date.now();
355
+ let resetsAtMs = null;
356
+ if (typeof err.resets_at === "number" && err.resets_at > 0) {
357
+ const ms = err.resets_at * 1000;
358
+ if (ms > now) resetsAtMs = ms;
359
+ }
360
+ if (!resetsAtMs && typeof err.resets_in_seconds === "number" && err.resets_in_seconds > 0) {
361
+ resetsAtMs = now + err.resets_in_seconds * 1000;
362
+ }
363
+ if (resetsAtMs) {
364
+ return { status: 429, message: err.message || bodyText, resetsAtMs };
365
+ }
366
+ }
367
+ } catch { /* fall through to default */ }
368
+ }
369
+ return super.parseError(response, bodyText);
370
+ }
371
+
372
+ /**
373
+ * Transform request before sending - inject default instructions if missing.
374
+ * Image fetching is handled separately in prefetchImages() so this stays sync.
375
+ */
376
+ transformRequest(model, body, stream, credentials) {
377
+ this._isCompact = !!body._compact;
378
+ delete body._compact;
379
+ // Resolve conversation-stable session_id (priority: body → assistant-text → workspace → machine)
380
+ this._currentSessionId = resolveCacheSessionId(body, credentials, cachedMachineId);
381
+ // Convert string input to array format (Codex API requires input as array)
382
+ const normalized = normalizeResponsesInput(body.input);
383
+ if (normalized) body.input = normalized;
384
+
385
+ // Ensure input is present and non-empty (Codex API rejects empty input)
386
+ if (!body.input || (Array.isArray(body.input) && body.input.length === 0)) {
387
+ body.input = [{ type: "message", role: "user", content: [{ type: "input_text", text: "..." }] }];
388
+ }
389
+
390
+ // Keep system prompts in body.input as role=developer so they stay in the cacheable prefix
391
+ convertSystemToDeveloperRole(body);
392
+ // Strip server-generated item IDs (rs_/fc_/resp_/msg_) — Codex /responses can't resolve when store=false
393
+ stripStoredItemReferences(body);
394
+ // Flatten function tools + drop unsupported types
395
+ normalizeCodexTools(body);
396
+
397
+ // Ensure streaming is enabled (Codex API requires it)
398
+ body.stream = true;
399
+
400
+ // If no instructions provided, inject default Codex instructions
401
+ if (!body.instructions || body.instructions.trim() === "") {
402
+ body.instructions = CODEX_DEFAULT_INSTRUCTIONS;
403
+ }
404
+
405
+ // Ensure store is false (Codex requirement)
406
+ body.store = false;
407
+
408
+ // Inject prompt_cache_key for stable Codex prompt caching
409
+ if (!body.prompt_cache_key && this._currentSessionId) {
410
+ body.prompt_cache_key = this._currentSessionId;
411
+ }
412
+
413
+ // Map virtual Codex review models to the upstream Codex model before suffix parsing.
414
+ body.model = getModelUpstreamId("cx", body.model || model);
415
+
416
+ // Extract thinking level from model name suffix
417
+ // e.g., gpt-5.3-codex-high → high, gpt-5.3-codex → medium (default)
418
+ const effortLevels = ['none', 'low', 'medium', 'high', 'xhigh'];
419
+ let modelEffort = null;
420
+ for (const level of effortLevels) {
421
+ if (body.model.endsWith(`-${level}`)) {
422
+ modelEffort = level;
423
+ // Strip suffix from model name for actual API call
424
+ body.model = body.model.replace(`-${level}`, '');
425
+ break;
426
+ }
427
+ }
428
+
429
+ // Priority: explicit reasoning.effort > reasoning_effort param > model suffix > default (medium)
430
+ if (!body.reasoning) {
431
+ const effort = body.reasoning_effort || modelEffort || 'low';
432
+ body.reasoning = { effort, summary: "auto" };
433
+ } else if (!body.reasoning.summary) {
434
+ body.reasoning.summary = "auto";
435
+ }
436
+ delete body.reasoning_effort;
437
+
438
+ // Include reasoning encrypted content (required by Codex backend for reasoning models)
439
+ if (body.reasoning && body.reasoning.effort && body.reasoning.effort !== 'none') {
440
+ body.include = ["reasoning.encrypted_content"];
441
+ }
442
+
443
+ // Remove unsupported parameters for Codex API
444
+ delete body.temperature;
445
+ delete body.top_p;
446
+ delete body.frequency_penalty;
447
+ delete body.presence_penalty;
448
+ delete body.logprobs;
449
+ delete body.top_logprobs;
450
+ delete body.n;
451
+ delete body.seed;
452
+ delete body.max_tokens;
453
+ delete body.max_completion_tokens;
454
+ delete body.max_output_tokens; // Responses API clients send this but Codex rejects it
455
+ delete body.user; // Cursor sends this but Codex doesn't support it
456
+ delete body.prompt_cache_retention; // Cursor sends this but Codex doesn't support it
457
+ delete body.metadata; // Cursor sends this but Codex doesn't support it
458
+ delete body.stream_options; // Cursor sends this but Codex doesn't support it
459
+ delete body.safety_identifier; // Droid CLI sends this but Codex doesn't support it
460
+ delete body.previous_response_id; // store=false → backend can't resolve previous resp; avoid 404
461
+
462
+ // Final allowlist filter — strip any unknown field that could trigger upstream "routing_unsupported"
463
+ for (const k of Object.keys(body)) {
464
+ if (!RESPONSES_API_ALLOWLIST.has(k)) delete body[k];
465
+ }
466
+
467
+ return body;
468
+ }
469
+ }