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,175 @@
1
+ /**
2
+ * Qoder COSY (hybrid RSA+AES+MD5) signing, ported from CLIProxyAPIPlus
3
+ * qoder-provider branch (internal/auth/qoder/cosy.go).
4
+ *
5
+ * Every signed request carries:
6
+ * - an AES-128-CBC payload of the user info, the AES key wrapped in RSA
7
+ * - an MD5 signature over `payload || cosyKey || timestamp || body || sigPath`
8
+ * - the body's MD5 hash + length so the server can validate integrity
9
+ * - 17 Cosy-* / X-* headers fingerprinting the client (machine id, IDE
10
+ * version, organization id, etc.)
11
+ *
12
+ * The on-the-wire header keys use the same casing as qodercli:
13
+ * Cosy-Machineid, not Cosy-MachineID.
14
+ */
15
+
16
+ import crypto from "crypto";
17
+ import { v4 as uuidv4 } from "uuid";
18
+
19
+ import {
20
+ QODER_CLIENT_TYPE,
21
+ QODER_DATA_POLICY,
22
+ QODER_IDE_VERSION,
23
+ QODER_LOGIN_VERSION,
24
+ QODER_MACHINE_OS,
25
+ QODER_MACHINE_TYPE,
26
+ QODER_RSA_PUBLIC_KEY,
27
+ } from "./constants.js";
28
+
29
+ // AES-128 wants a 16-byte key. Match qodercli/Veria: take the first 16 chars
30
+ // of a fresh UUID's canonical string (hyphens included). The key is fresh
31
+ // per request so even though the IV reuses the key bytes, each request still
32
+ // has a unique IV.
33
+ function generateAesKey() {
34
+ return uuidv4().slice(0, 16);
35
+ }
36
+
37
+ function pkcs7Pad(data, blockSize) {
38
+ const padding = blockSize - (data.length % blockSize);
39
+ const padded = Buffer.alloc(data.length + padding, padding);
40
+ data.copy(padded, 0);
41
+ return padded;
42
+ }
43
+
44
+ function aesEncryptCbcBase64(plaintext, keyStr) {
45
+ const keyBytes = Buffer.from(keyStr, "utf8");
46
+ if (keyBytes.length !== 16) {
47
+ throw new Error(`aes key must be 16 bytes, got ${keyBytes.length}`);
48
+ }
49
+ const iv = keyBytes.subarray(0, 16);
50
+ const cipher = crypto.createCipheriv("aes-128-cbc", keyBytes, iv);
51
+ cipher.setAutoPadding(false);
52
+ const padded = pkcs7Pad(Buffer.from(plaintext, "utf8"), 16);
53
+ const encrypted = Buffer.concat([cipher.update(padded), cipher.final()]);
54
+ return encrypted.toString("base64");
55
+ }
56
+
57
+ function rsaEncryptBase64(data) {
58
+ const encrypted = crypto.publicEncrypt(
59
+ { key: QODER_RSA_PUBLIC_KEY, padding: crypto.constants.RSA_PKCS1_PADDING },
60
+ Buffer.from(data, "utf8"),
61
+ );
62
+ return encrypted.toString("base64");
63
+ }
64
+
65
+ function encryptUserInfo(userInfo) {
66
+ const aesKey = generateAesKey();
67
+ const plaintext = JSON.stringify(userInfo);
68
+ const infoB64 = aesEncryptCbcBase64(plaintext, aesKey);
69
+ const cosyKeyB64 = rsaEncryptBase64(aesKey);
70
+ return { cosyKey: cosyKeyB64, info: infoB64 };
71
+ }
72
+
73
+ function md5Hex(input) {
74
+ return crypto.createHash("md5").update(input).digest("hex");
75
+ }
76
+
77
+ /**
78
+ * Strip the leading "/algo" prefix from the request path. Matches qodercli
79
+ * convention. Empty input returns "".
80
+ */
81
+ function computeSigPath(requestUrl) {
82
+ let pathname;
83
+ try {
84
+ pathname = new URL(requestUrl).pathname || "";
85
+ } catch {
86
+ return "";
87
+ }
88
+ if (pathname.startsWith("/algo")) {
89
+ return pathname.slice("/algo".length);
90
+ }
91
+ return pathname;
92
+ }
93
+
94
+ /**
95
+ * Generate a fresh machine UUID. Persisted on the connection record so
96
+ * every request from the same auth carries the same machineId.
97
+ */
98
+ export function generateMachineId() {
99
+ return uuidv4();
100
+ }
101
+
102
+ /**
103
+ * Build the full Cosy-* header set for a single Qoder request.
104
+ *
105
+ * @param {Buffer|Uint8Array|string} body The exact bytes that will be sent.
106
+ * For GET requests pass an empty Buffer / "".
107
+ * @param {string} requestUrl Full request URL (used for sigPath).
108
+ * @param {object} creds
109
+ * @param {string} creds.userId Stable Qoder user id.
110
+ * @param {string} creds.authToken Device access token (`dt-...`).
111
+ * @param {string} [creds.name] Display name (optional).
112
+ * @param {string} [creds.email] Email (optional, can be empty).
113
+ * @param {string} [creds.machineId] Persisted machine UUID.
114
+ * @returns {Record<string, string>} Header map ready to merge onto fetch().
115
+ */
116
+ export function buildCosyHeaders(body, requestUrl, creds) {
117
+ if (!creds?.userId) throw new Error("cosy: user id is empty");
118
+ if (!creds?.authToken) throw new Error("cosy: auth token is empty");
119
+
120
+ const bodyBuf = Buffer.isBuffer(body)
121
+ ? body
122
+ : typeof body === "string"
123
+ ? Buffer.from(body, "latin1")
124
+ : Buffer.from(body || []);
125
+
126
+ const { cosyKey, info } = encryptUserInfo({
127
+ uid: creds.userId,
128
+ security_oauth_token: creds.authToken,
129
+ name: creds.name || "",
130
+ aid: "",
131
+ email: creds.email || "",
132
+ });
133
+
134
+ const timestamp = String(Math.floor(Date.now() / 1000));
135
+ const requestId = uuidv4();
136
+
137
+ const payloadJson = JSON.stringify({
138
+ version: "v1",
139
+ requestId,
140
+ info,
141
+ cosyVersion: QODER_IDE_VERSION,
142
+ ideVersion: "",
143
+ });
144
+ const payloadB64 = Buffer.from(payloadJson, "utf8").toString("base64");
145
+
146
+ const sigPath = computeSigPath(requestUrl);
147
+ const sigInput = `${payloadB64}\n${cosyKey}\n${timestamp}\n${bodyBuf.toString("latin1")}\n${sigPath}`;
148
+ const sig = md5Hex(Buffer.from(sigInput, "latin1"));
149
+
150
+ const machineId = creds.machineId || generateMachineId();
151
+ const bodyHash = md5Hex(bodyBuf);
152
+ const bodyLength = String(bodyBuf.length);
153
+
154
+ return {
155
+ Authorization: `Bearer COSY.${payloadB64}.${sig}`,
156
+ "Cosy-Key": cosyKey,
157
+ "Cosy-User": creds.userId,
158
+ "Cosy-Date": timestamp,
159
+ "Cosy-Version": QODER_IDE_VERSION,
160
+ "Cosy-Machineid": machineId,
161
+ "Cosy-Machinetoken": machineId,
162
+ "Cosy-Machinetype": QODER_MACHINE_TYPE,
163
+ "Cosy-Machineos": QODER_MACHINE_OS,
164
+ "Cosy-Clienttype": QODER_CLIENT_TYPE,
165
+ "Cosy-Clientip": "127.0.0.1",
166
+ "Cosy-Bodyhash": bodyHash,
167
+ "Cosy-Bodylength": bodyLength,
168
+ "Cosy-Sigpath": sigPath,
169
+ "Cosy-Data-Policy": QODER_DATA_POLICY,
170
+ "Cosy-Organization-Id": "",
171
+ "Cosy-Organization-Tags": "",
172
+ "Login-Version": QODER_LOGIN_VERSION,
173
+ "X-Request-Id": uuidv4(),
174
+ };
175
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Qoder body encoding ported from qoder2api's QoderEncoding.java (via the
3
+ * CLIProxyAPIPlus qoder-provider branch).
4
+ *
5
+ * Algorithm:
6
+ * 1. base64-encode the plaintext bytes (standard alphabet).
7
+ * 2. Rearrange: split into thirds, reorder as [tail][mid][head].
8
+ * 3. Substitute each character via a custom alphabet mapping.
9
+ *
10
+ * The encoded body must be sent with `&Encode=1` appended to the URL so the
11
+ * server decodes in reverse. The obfuscation prevents Alibaba Cloud WAF from
12
+ * pattern-matching the plaintext request body.
13
+ */
14
+
15
+ const QODER_STD_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
16
+ const QODER_CUSTOM_ALPHABET = "_doRTgHZBKcGVjlvpC,@aFSx#DPuNJme&i*MzLOEn)sUrthbf%Y^w.(kIQyXqWA!";
17
+
18
+ const QODER_S2C = (() => {
19
+ const table = new Int16Array(128).fill(-1);
20
+ for (let i = 0; i < 64; i++) {
21
+ table[QODER_STD_ALPHABET.charCodeAt(i)] = QODER_CUSTOM_ALPHABET.charCodeAt(i);
22
+ }
23
+ table["=".charCodeAt(0)] = "$".charCodeAt(0);
24
+ return table;
25
+ })();
26
+
27
+ /**
28
+ * Encode plaintext bytes/string using Qoder's WAF-bypass scheme.
29
+ * @param {Buffer|Uint8Array|string} plaintext
30
+ * @returns {string} encoded string
31
+ */
32
+ export function qoderEncodeBody(plaintext) {
33
+ const buf = Buffer.isBuffer(plaintext)
34
+ ? plaintext
35
+ : typeof plaintext === "string"
36
+ ? Buffer.from(plaintext, "utf8")
37
+ : Buffer.from(plaintext);
38
+
39
+ const std = buf.toString("base64");
40
+ const n = std.length;
41
+ const a = Math.floor(n / 3);
42
+ // [tail][mid][head]
43
+ const rearranged = std.slice(n - a) + std.slice(a, n - a) + std.slice(0, a);
44
+
45
+ const out = Buffer.alloc(n);
46
+ for (let i = 0; i < n; i++) {
47
+ const c = rearranged.charCodeAt(i);
48
+ if (c < 128 && QODER_S2C[c] >= 0) {
49
+ out[i] = QODER_S2C[c];
50
+ } else {
51
+ out[i] = c;
52
+ }
53
+ }
54
+ return out.toString("latin1");
55
+ }
@@ -0,0 +1,4 @@
1
+ // Shim → re-export from new SQLite-based DB layer (src/lib/db/)
2
+ export {
3
+ saveRequestDetail, getRequestDetails, getRequestDetailById,
4
+ } from "@/lib/db/index.js";
@@ -0,0 +1,449 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import https from "https";
4
+ import os from "os";
5
+ import { execSync, spawn } from "child_process";
6
+ import { savePid, loadPid, clearPid } from "./pid.js";
7
+ import { DATA_DIR } from "@/lib/dataDir.js";
8
+
9
+ const BIN_DIR = path.join(DATA_DIR, "bin");
10
+ const BINARY_NAME = "cloudflared";
11
+ const IS_WINDOWS = os.platform() === "win32";
12
+ const BIN_NAME = IS_WINDOWS ? `${BINARY_NAME}.exe` : BINARY_NAME;
13
+ const BIN_PATH = path.join(BIN_DIR, BIN_NAME);
14
+ const POWERSHELL_HIDDEN_COMMAND = "powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command";
15
+ const DEFAULT_QUICK_TUNNEL_PROTOCOL = "http2";
16
+ const QUICK_TUNNEL_PROTOCOLS = new Set(["http2", "quic", "auto"]);
17
+
18
+ const GITHUB_BASE_URL = "https://github.com/cloudflare/cloudflared/releases/latest/download";
19
+
20
+ const PLATFORM_MAPPINGS = {
21
+ darwin: {
22
+ x64: "cloudflared-darwin-amd64.tgz",
23
+ arm64: "cloudflared-darwin-arm64.tgz"
24
+ },
25
+ win32: {
26
+ x64: "cloudflared-windows-amd64.exe",
27
+ ia32: "cloudflared-windows-386.exe",
28
+ arm64: "cloudflared-windows-386.exe"
29
+ },
30
+ linux: {
31
+ x64: "cloudflared-linux-amd64",
32
+ arm64: "cloudflared-linux-arm64"
33
+ }
34
+ };
35
+
36
+ // Fallback order: prefer smallest/most-compatible binary per platform
37
+ const PLATFORM_FALLBACK = {
38
+ darwin: "cloudflared-darwin-amd64.tgz",
39
+ win32: "cloudflared-windows-386.exe",
40
+ linux: "cloudflared-linux-amd64"
41
+ };
42
+
43
+ function getDownloadUrl() {
44
+ const platform = os.platform();
45
+ const arch = os.arch();
46
+
47
+ const platformMapping = PLATFORM_MAPPINGS[platform];
48
+ if (!platformMapping) {
49
+ throw new Error(`Unsupported platform: ${platform}`);
50
+ }
51
+
52
+ const binaryName = platformMapping[arch] || PLATFORM_FALLBACK[platform];
53
+ return `${GITHUB_BASE_URL}/${binaryName}`;
54
+ }
55
+
56
+ // Download state — shared so status API can read it
57
+ const dlState = { downloading: false, progress: 0 };
58
+
59
+ export function getDownloadStatus() {
60
+ return { downloading: dlState.downloading, progress: dlState.progress };
61
+ }
62
+
63
+ function downloadFile(url, dest) {
64
+ return new Promise((resolve, reject) => {
65
+ const file = fs.createWriteStream(dest);
66
+
67
+ https.get(url, (response) => {
68
+ if ([301, 302, 303, 307, 308].includes(response.statusCode)) {
69
+ file.close();
70
+ fs.unlinkSync(dest);
71
+ downloadFile(response.headers.location, dest).then(resolve).catch(reject);
72
+ return;
73
+ }
74
+
75
+ if (response.statusCode !== 200) {
76
+ file.close();
77
+ fs.unlinkSync(dest);
78
+ reject(new Error(`Download failed with status ${response.statusCode}`));
79
+ return;
80
+ }
81
+
82
+ const totalBytes = parseInt(response.headers["content-length"], 10) || 0;
83
+ let receivedBytes = 0;
84
+ dlState.downloading = true;
85
+ dlState.progress = 0;
86
+
87
+ response.on("data", (chunk) => {
88
+ receivedBytes += chunk.length;
89
+ if (totalBytes > 0) dlState.progress = Math.round((receivedBytes / totalBytes) * 100);
90
+ });
91
+
92
+ response.pipe(file);
93
+
94
+ file.on("finish", () => {
95
+ dlState.downloading = false;
96
+ dlState.progress = 100;
97
+ file.close(() => resolve(dest));
98
+ });
99
+
100
+ file.on("error", (err) => {
101
+ dlState.downloading = false;
102
+ dlState.progress = 0;
103
+ file.close();
104
+ fs.unlinkSync(dest);
105
+ reject(err);
106
+ });
107
+ }).on("error", (err) => {
108
+ dlState.downloading = false;
109
+ dlState.progress = 0;
110
+ file.close();
111
+ if (fs.existsSync(dest)) fs.unlinkSync(dest);
112
+ reject(err);
113
+ });
114
+ });
115
+ }
116
+
117
+ const MIN_BINARY_SIZE = 1024 * 1024; // 1MB - cloudflared is ~30MB+
118
+
119
+ // Validate binary is executable on current platform and not truncated
120
+ function isValidBinary(filePath) {
121
+ try {
122
+ const stat = fs.statSync(filePath);
123
+ if (stat.size < MIN_BINARY_SIZE) return false;
124
+ const fd = fs.openSync(filePath, "r");
125
+ const buf = Buffer.alloc(4);
126
+ fs.readSync(fd, buf, 0, 4, 0);
127
+ fs.closeSync(fd);
128
+ const magic = buf.toString("hex");
129
+ if (IS_WINDOWS) return magic.startsWith("4d5a"); // PE (MZ)
130
+ if (os.platform() === "darwin") return magic.startsWith("cffaedfe") || magic.startsWith("cefaedfe");
131
+ return magic.startsWith("7f454c46"); // ELF (Linux)
132
+ } catch {
133
+ return false;
134
+ }
135
+ }
136
+
137
+ let downloadPromise = null;
138
+
139
+ export async function ensureCloudflared() {
140
+ if (downloadPromise) return downloadPromise;
141
+ downloadPromise = _ensureCloudflared().finally(() => { downloadPromise = null; });
142
+ return downloadPromise;
143
+ }
144
+
145
+ async function _ensureCloudflared() {
146
+ if (!fs.existsSync(BIN_DIR)) {
147
+ fs.mkdirSync(BIN_DIR, { recursive: true });
148
+ }
149
+
150
+ // Clean up incomplete downloads from previous runs
151
+ const tmpPath = `${BIN_PATH}.tmp`;
152
+ if (fs.existsSync(tmpPath)) {
153
+ try { fs.unlinkSync(tmpPath); } catch { /* ignore */ }
154
+ }
155
+
156
+ if (fs.existsSync(BIN_PATH)) {
157
+ if (!isValidBinary(BIN_PATH)) {
158
+ console.log("[cloudflared] Invalid binary detected, re-downloading...");
159
+ fs.unlinkSync(BIN_PATH);
160
+ } else {
161
+ if (!IS_WINDOWS) fs.chmodSync(BIN_PATH, "755");
162
+ return BIN_PATH;
163
+ }
164
+ }
165
+
166
+ const url = getDownloadUrl();
167
+ const isArchive = url.endsWith(".tgz");
168
+ const downloadDest = isArchive ? path.join(BIN_DIR, "cloudflared.tgz.tmp") : tmpPath;
169
+
170
+ await downloadFile(url, downloadDest);
171
+
172
+ if (isArchive) {
173
+ execSync(`tar -xzf "${downloadDest}" -C "${BIN_DIR}"`, { stdio: "pipe", windowsHide: true });
174
+ fs.unlinkSync(downloadDest);
175
+ } else {
176
+ fs.renameSync(downloadDest, BIN_PATH);
177
+ }
178
+
179
+ if (!IS_WINDOWS) {
180
+ fs.chmodSync(BIN_PATH, "755");
181
+ }
182
+
183
+ return BIN_PATH;
184
+ }
185
+
186
+ let cloudflaredProcess = null;
187
+ let unexpectedExitHandler = null;
188
+ let intentionalKill = false; // suppress unexpected-exit callback during deliberate kill
189
+
190
+ /** Register a callback to be called when cloudflared exits unexpectedly after connecting */
191
+ export function setUnexpectedExitHandler(handler) {
192
+ unexpectedExitHandler = handler;
193
+ }
194
+
195
+ export async function spawnCloudflared(tunnelToken) {
196
+ const binaryPath = await ensureCloudflared();
197
+
198
+ const child = spawn(binaryPath, ["tunnel", "run", "--dns-resolver-addrs", "1.1.1.1:53", "--token", tunnelToken], {
199
+ detached: false,
200
+ windowsHide: true,
201
+ cwd: os.tmpdir(),
202
+ stdio: ["ignore", "pipe", "pipe"]
203
+ });
204
+
205
+ cloudflaredProcess = child;
206
+ savePid(child.pid);
207
+
208
+ return new Promise((resolve, reject) => {
209
+ let connectionCount = 0;
210
+ let resolved = false;
211
+ const timeout = setTimeout(() => {
212
+ resolved = true;
213
+ resolve(child);
214
+ }, 90000);
215
+
216
+ const handleLog = (data) => {
217
+ const msg = data.toString();
218
+ // Count exact occurrences in this chunk (each chunk may contain multiple lines)
219
+ const matches = msg.match(/Registered tunnel connection/g);
220
+ if (matches) {
221
+ connectionCount += matches.length;
222
+ if (connectionCount >= 4 && !resolved) {
223
+ resolved = true;
224
+ clearTimeout(timeout);
225
+ resolve(child);
226
+ }
227
+ }
228
+ };
229
+
230
+ child.stdout.on("data", handleLog);
231
+ child.stderr.on("data", handleLog);
232
+
233
+ child.on("error", (err) => {
234
+ if (!resolved) {
235
+ resolved = true;
236
+ clearTimeout(timeout);
237
+ reject(err);
238
+ }
239
+ });
240
+
241
+ child.on("exit", (code, signal) => {
242
+ cloudflaredProcess = null;
243
+ clearPid();
244
+ const wasConnected = resolved; // true = already connected successfully
245
+ if (!resolved) {
246
+ resolved = true;
247
+ clearTimeout(timeout);
248
+ // Collect stderr output for better error diagnosis
249
+ let stderrOutput = "";
250
+ if (child.stderr && !child.stderr.destroyed) {
251
+ // Try to read any buffered stderr (may not have all output but helps with common errors)
252
+ stderrOutput = " Check cloudflared logs for details.";
253
+ }
254
+ if (code === 1) {
255
+ // Common exit code 1 issues: invalid token, auth failure, network issues
256
+ reject(new Error(`cloudflared exited with code ${code}${stderrOutput} Ensure your tunnel token is valid and network is reachable.`));
257
+ } else if (code === 2) {
258
+ reject(new Error(`cloudflared exited with code ${code}${stderrOutput} Check if required arguments are correct.`));
259
+ } else {
260
+ reject(new Error(`cloudflared exited with code ${code}${stderrOutput}`));
261
+ }
262
+ return;
263
+ }
264
+ // Watchdog (initializeApp) handles recovery — no auto-reconnect here
265
+ if (intentionalKill) { intentionalKill = false; return; }
266
+ if (wasConnected && unexpectedExitHandler) unexpectedExitHandler();
267
+ });
268
+ });
269
+ }
270
+
271
+ /**
272
+ * Spawn cloudflared quick tunnel (no account needed)
273
+ * Returns the generated trycloudflare.com URL
274
+ */
275
+ export async function spawnQuickTunnel(localPort, onUrlUpdate) {
276
+ const binaryPath = await ensureCloudflared();
277
+
278
+ const configDir = fs.mkdtempSync(path.join(os.tmpdir(), "cloudflared-quick-"));
279
+ const configPath = path.join(configDir, "config.yml");
280
+ // Avoid using default ~/.cloudflared/config.yml, which can conflict with quick tunnel behavior.
281
+ fs.writeFileSync(configPath, "# quick-tunnel config placeholder\n", "utf8");
282
+
283
+ let isCleaned = false;
284
+ const cleanup = () => {
285
+ if (isCleaned) return;
286
+ isCleaned = true;
287
+ try {
288
+ fs.rmSync(configDir, { recursive: true, force: true });
289
+ } catch (e) { /* ignore */ }
290
+ };
291
+
292
+ const requestedProtocol = String(process.env.TUNNEL_TRANSPORT_PROTOCOL || process.env.CLOUDFLARED_PROTOCOL || DEFAULT_QUICK_TUNNEL_PROTOCOL).trim().toLowerCase();
293
+ const tunnelProtocol = QUICK_TUNNEL_PROTOCOLS.has(requestedProtocol) ? requestedProtocol : DEFAULT_QUICK_TUNNEL_PROTOCOL;
294
+ const child = spawn(binaryPath, ["tunnel", "--url", `http://127.0.0.1:${localPort}`, "--config", configPath, "--no-autoupdate", "--retries", "99"], {
295
+ detached: false,
296
+ windowsHide: true,
297
+ cwd: os.tmpdir(),
298
+ env: {
299
+ ...process.env,
300
+ TUNNEL_TRANSPORT_PROTOCOL: tunnelProtocol,
301
+ },
302
+ stdio: ["ignore", "pipe", "pipe"],
303
+ });
304
+
305
+ cloudflaredProcess = child;
306
+ savePid(child.pid);
307
+
308
+ return new Promise((resolve, reject) => {
309
+ let resolved = false;
310
+ // Keep a small tail of raw cloudflared logs to surface real failure causes
311
+ let logTail = "";
312
+
313
+ function getQuickTunnelUrlFromLog(message) {
314
+ // cloudflared logs may contain "api.trycloudflare.com" as well,
315
+ // but that is NOT the quick-tunnel endpoint we need.
316
+ const regex = /https:\/\/([a-z0-9-]+)\.trycloudflare\.com/gi;
317
+ const candidates = [];
318
+
319
+ for (const match of message.matchAll(regex)) {
320
+ const host = match[1];
321
+ if (host === "api") continue;
322
+ candidates.push(`https://${host}.trycloudflare.com`);
323
+ }
324
+
325
+ if (!candidates.length) return null;
326
+ return candidates[candidates.length - 1];
327
+ }
328
+
329
+ const timeout = setTimeout(() => {
330
+ if (resolved) return;
331
+ resolved = true;
332
+ cleanup();
333
+ reject(new Error(`Quick tunnel timed out. Last log: ${logTail.slice(-800) || "(empty)"}`));
334
+ }, 90000);
335
+
336
+ let lastUrl = null;
337
+
338
+ const handleLog = (data) => {
339
+ const msg = data.toString();
340
+ logTail = (logTail + msg).slice(-4000);
341
+ const tunnelUrl = getQuickTunnelUrlFromLog(msg);
342
+ if (!tunnelUrl) return;
343
+
344
+ if (!resolved) {
345
+ // First URL — resolve the promise, do NOT call onUrlUpdate (caller handles initial register)
346
+ resolved = true;
347
+ lastUrl = tunnelUrl;
348
+ clearTimeout(timeout);
349
+ cleanup();
350
+ console.log(`[Tunnel] cloudflared URL: ${tunnelUrl}`);
351
+ resolve({ child, tunnelUrl });
352
+ return;
353
+ }
354
+
355
+ // URL changed after initial connect — notify caller to re-register
356
+ if (tunnelUrl !== lastUrl) {
357
+ console.log(`[Tunnel] cloudflared URL changed: ${tunnelUrl}`);
358
+ lastUrl = tunnelUrl;
359
+ if (onUrlUpdate) onUrlUpdate(tunnelUrl);
360
+ }
361
+ };
362
+
363
+ child.stdout.on("data", handleLog);
364
+ child.stderr.on("data", handleLog);
365
+
366
+ child.on("error", (err) => {
367
+ if (resolved) return;
368
+ resolved = true;
369
+ clearTimeout(timeout);
370
+ cleanup();
371
+ reject(err);
372
+ });
373
+
374
+ child.on("exit", (code, signal) => {
375
+ cloudflaredProcess = null;
376
+ clearPid();
377
+ // Deliberate kill (restart/disable) — exit silently, no error noise
378
+ if (intentionalKill) {
379
+ intentionalKill = false;
380
+ clearTimeout(timeout);
381
+ cleanup();
382
+ if (!resolved) { resolved = true; reject(new Error("cloudflared killed")); }
383
+ return;
384
+ }
385
+ console.log(`[Tunnel] cloudflared exit code=${code} signal=${signal}`);
386
+ if (!resolved) {
387
+ resolved = true;
388
+ clearTimeout(timeout);
389
+ cleanup();
390
+ const tail = logTail.slice(-600).trim() || "(empty)";
391
+ if (code === 1) {
392
+ reject(new Error(`cloudflared quick tunnel exited (code 1). Common causes: (1) outbound port 7844 (TCP/UDP) blocked, (2) TryCloudflare service issue, (3) cannot reach 127.0.0.1:${localPort}, (4) protocol (http2/quic) blocked by network. Last log: ${tail}`));
393
+ } else if (code === 2) {
394
+ reject(new Error(`cloudflared exited (code 2). Bad arguments. Last log: ${tail}`));
395
+ } else {
396
+ reject(new Error(`cloudflared exited (code ${code}). Last log: ${tail}`));
397
+ }
398
+ return;
399
+ }
400
+ if (unexpectedExitHandler) unexpectedExitHandler();
401
+ cleanup();
402
+ });
403
+ });
404
+ }
405
+
406
+ // Kill cloudflared processes whose command line targets the given port (any host).
407
+ // Boundary check ensures :20128 doesn't match :201280 or :202128.
408
+ function killCloudflaredByPort(port) {
409
+ if (!port) return;
410
+ try {
411
+ if (IS_WINDOWS) {
412
+ const psCmd = `Get-CimInstance Win32_Process -Filter \\"Name='cloudflared.exe'\\" | Where-Object { $_.CommandLine -match ':${port}(\\D|$)' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }`;
413
+ execSync(`${POWERSHELL_HIDDEN_COMMAND} "${psCmd}"`, { stdio: "ignore", windowsHide: true });
414
+ } else {
415
+ execSync(`pkill -f "cloudflared.*:${port}([^0-9]|$)" 2>/dev/null || true`, { stdio: "ignore", windowsHide: true });
416
+ }
417
+ } catch (e) { /* ignore */ }
418
+ }
419
+
420
+ export function killCloudflared(localPort) {
421
+ intentionalKill = true;
422
+ if (cloudflaredProcess) {
423
+ try {
424
+ cloudflaredProcess.kill();
425
+ } catch (e) { /* ignore */ }
426
+ cloudflaredProcess = null;
427
+ }
428
+
429
+ const pid = loadPid();
430
+ if (pid) {
431
+ try {
432
+ process.kill(pid);
433
+ } catch (e) { /* ignore */ }
434
+ clearPid();
435
+ }
436
+
437
+ killCloudflaredByPort(localPort);
438
+ }
439
+
440
+ export function isCloudflaredRunning() {
441
+ const pid = loadPid();
442
+ if (!pid) return false;
443
+ try {
444
+ process.kill(pid, 0);
445
+ return true;
446
+ } catch (e) {
447
+ return false;
448
+ }
449
+ }
@@ -0,0 +1,9 @@
1
+ // Cloudflare quick tunnel: DNS propagates fast, short timeouts OK
2
+ export const HEALTH_CHECK = {
3
+ intervalMs: 2000,
4
+ timeoutMs: 60000,
5
+ fetchTimeoutMs: 5000,
6
+ dnsTimeoutMs: 2000,
7
+ };
8
+
9
+ export const WORKER_URL = process.env.TUNNEL_WORKER_URL || "https://abc-tunnel.us";