swayrouter 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (643) hide show
  1. package/.env.example +43 -0
  2. package/CHANGELOG.md +132 -0
  3. package/LICENSE +30 -0
  4. package/README.id.md +633 -0
  5. package/README.md +628 -0
  6. package/cli/cli.js +388 -0
  7. package/cli/package.json +4 -0
  8. package/cli/src/cli/commands/xaiVideo.js +280 -0
  9. package/cli/src/cli/tray/SwayAvatar.svg +20 -0
  10. package/cli/src/cli/tray/autostart.js +351 -0
  11. package/cli/src/cli/tray/icon.ico +0 -0
  12. package/cli/src/cli/tray/icon.png +0 -0
  13. package/cli/src/cli/tray/tray.js +258 -0
  14. package/cli/src/cli/tray/tray.ps1 +129 -0
  15. package/cli/src/cli/tray/trayHost.js +157 -0
  16. package/cli/src/cli/tray/trayWin.js +83 -0
  17. package/cli/src/cli/utils/display.js +123 -0
  18. package/cli/src/cli/utils/input.js +138 -0
  19. package/cli/src/runtime/discover.js +153 -0
  20. package/cli/src/runtime/lifecycle.js +333 -0
  21. package/cli/src/runtime/runMenu.js +250 -0
  22. package/cli/src/runtime/uiAdapters.js +12 -0
  23. package/cli/src/runtime/update.js +130 -0
  24. package/dashboard/dist/assets/CliTools-Ch3gKuNw.js +24 -0
  25. package/dashboard/dist/assets/Combo-BBCldjWi.js +1 -0
  26. package/dashboard/dist/assets/ConsoleLog-wywAYcPT.js +6 -0
  27. package/dashboard/dist/assets/Dashboard-DxzyF41b.js +1 -0
  28. package/dashboard/dist/assets/Header-C_9Su9BF.js +1 -0
  29. package/dashboard/dist/assets/Keys-D0ufgcsc.js +1 -0
  30. package/dashboard/dist/assets/Login-BeKpipS_.js +1 -0
  31. package/dashboard/dist/assets/ManageApiKey-CVXsmW2B.js +1 -0
  32. package/dashboard/dist/assets/OAuthCallback-D_UZYcF6.js +1 -0
  33. package/dashboard/dist/assets/Provider-BU7JfTqm.js +4 -0
  34. package/dashboard/dist/assets/ProviderModelAccordion-BAifkfVR.js +1 -0
  35. package/dashboard/dist/assets/Proxy-CU15VJ--.js +1 -0
  36. package/dashboard/dist/assets/QuotaMonitor-HzGK7bcc.js +1 -0
  37. package/dashboard/dist/assets/Settings-Dt4y2dC0.js +1 -0
  38. package/dashboard/dist/assets/Setup-DSDUwU7N.js +1 -0
  39. package/dashboard/dist/assets/StatusBadge-1nAOyHU2.js +1 -0
  40. package/dashboard/dist/assets/SwayChat-Bup7up6D.js +10 -0
  41. package/dashboard/dist/assets/Usage-eWnrPQ_v.js +4 -0
  42. package/dashboard/dist/assets/accordion-DOOPDDgt.js +1 -0
  43. package/dashboard/dist/assets/admin-extras-api-CCdu5TFM.js +1 -0
  44. package/dashboard/dist/assets/api-keys-api-ifAC2Ok3.js +1 -0
  45. package/dashboard/dist/assets/card-CC0Omjcv.js +1 -0
  46. package/dashboard/dist/assets/chatStudio-C0zPz_Z_.js +2 -0
  47. package/dashboard/dist/assets/checkbox-7SZBrmbN.js +1 -0
  48. package/dashboard/dist/assets/connections-api-_N54UD3S.js +1 -0
  49. package/dashboard/dist/assets/copy-button-qBvM6H9z.js +1 -0
  50. package/dashboard/dist/assets/currency-api-SV9CBf5e.js +1 -0
  51. package/dashboard/dist/assets/flip-button-BGgkjtl0.js +1 -0
  52. package/dashboard/dist/assets/frame-cUiti6Lq.js +1 -0
  53. package/dashboard/dist/assets/icons-vendor-CUx7SB5V.js +541 -0
  54. package/dashboard/dist/assets/index-B6j-9zHy.js +10 -0
  55. package/dashboard/dist/assets/index-C-_l0yYz.css +1 -0
  56. package/dashboard/dist/assets/live-mode-CHShLY4E.js +1 -0
  57. package/dashboard/dist/assets/markdown-vendor-BY8e1gQ8.js +29 -0
  58. package/dashboard/dist/assets/motion-vendor-g5fpGzmJ.js +9 -0
  59. package/dashboard/dist/assets/oauth-callback-CqYQzyd7.js +1 -0
  60. package/dashboard/dist/assets/query-vendor-DVevaSVS.js +1 -0
  61. package/dashboard/dist/assets/react-vendor-xnYrwzsL.js +61 -0
  62. package/dashboard/dist/assets/ripple-button-l8aMiVVG.js +1 -0
  63. package/dashboard/dist/assets/segmented-CqmEnQjZ.js +1 -0
  64. package/dashboard/dist/assets/select-D8pUtMXp.js +1 -0
  65. package/dashboard/dist/assets/skeleton-7uJDiIXe.js +1 -0
  66. package/dashboard/dist/assets/table-D0M60Tu1.js +1 -0
  67. package/dashboard/dist/assets/tabs-C6YkuulG.js +1 -0
  68. package/dashboard/dist/assets/tunnel-api-DDPsBaDV.js +1 -0
  69. package/dashboard/dist/assets/ui-vendor-BuM9f2NY.js +17 -0
  70. package/dashboard/dist/image2/SwayAvatar.svg +20 -0
  71. package/dashboard/dist/index.html +32 -0
  72. package/dashboard/dist/logo/avatar.svg +1 -0
  73. package/dashboard/dist/logo/sway.svg +20 -0
  74. package/dashboard/dist/logo/swaychat.svg +20 -0
  75. package/dashboard/dist/providers/SwayCustom.svg +19 -0
  76. package/dashboard/dist/providers/alicode.svg +12 -0
  77. package/dashboard/dist/providers/anthropic.svg +11 -0
  78. package/dashboard/dist/providers/antigravity.svg +3 -0
  79. package/dashboard/dist/providers/azure.svg +5 -0
  80. package/dashboard/dist/providers/baidu.svg +3 -0
  81. package/dashboard/dist/providers/blackbox.svg +5 -0
  82. package/dashboard/dist/providers/byteplus.svg +3 -0
  83. package/dashboard/dist/providers/cerebras.svg +4 -0
  84. package/dashboard/dist/providers/chutes.svg +4 -0
  85. package/dashboard/dist/providers/claude.svg +3 -0
  86. package/dashboard/dist/providers/cline.svg +11 -0
  87. package/dashboard/dist/providers/cloudflare-ai.svg +4 -0
  88. package/dashboard/dist/providers/codebuddy.svg +11 -0
  89. package/dashboard/dist/providers/codex.svg +10 -0
  90. package/dashboard/dist/providers/commandcode.svg +3 -0
  91. package/dashboard/dist/providers/cursor.svg +3 -0
  92. package/dashboard/dist/providers/deepseek.svg +10 -0
  93. package/dashboard/dist/providers/featherless.svg +3 -0
  94. package/dashboard/dist/providers/fireworks.svg +3 -0
  95. package/dashboard/dist/providers/gemini.svg +3 -0
  96. package/dashboard/dist/providers/geminicli.svg +11 -0
  97. package/dashboard/dist/providers/github.svg +3 -0
  98. package/dashboard/dist/providers/grok.svg +3 -0
  99. package/dashboard/dist/providers/groq.svg +3 -0
  100. package/dashboard/dist/providers/hermesagent.svg +1 -0
  101. package/dashboard/dist/providers/kilocode.svg +15 -0
  102. package/dashboard/dist/providers/kimchi.svg +3 -0
  103. package/dashboard/dist/providers/kimi.svg +4 -0
  104. package/dashboard/dist/providers/kiro.svg +10 -0
  105. package/dashboard/dist/providers/meta.svg +3 -0
  106. package/dashboard/dist/providers/mimo.svg +10 -0
  107. package/dashboard/dist/providers/minimax.svg +3 -0
  108. package/dashboard/dist/providers/mistral.svg +3 -0
  109. package/dashboard/dist/providers/morph.svg +3 -0
  110. package/dashboard/dist/providers/nebius.svg +4 -0
  111. package/dashboard/dist/providers/nvidia.svg +3 -0
  112. package/dashboard/dist/providers/ollama.svg +3 -0
  113. package/dashboard/dist/providers/omp.svg +5 -0
  114. package/dashboard/dist/providers/openai.svg +3 -0
  115. package/dashboard/dist/providers/opencode.svg +3 -0
  116. package/dashboard/dist/providers/openrouter.svg +3 -0
  117. package/dashboard/dist/providers/perplexity.svg +3 -0
  118. package/dashboard/dist/providers/poolside.svg +36 -0
  119. package/dashboard/dist/providers/qoder.svg +11 -0
  120. package/dashboard/dist/providers/sumopod.svg +3 -0
  121. package/dashboard/dist/providers/tencent.svg +5 -0
  122. package/dashboard/dist/providers/together.svg +12 -0
  123. package/dashboard/dist/providers/trae.svg +3 -0
  124. package/dashboard/dist/providers/venice.svg +4 -0
  125. package/dashboard/dist/providers/vercel.svg +3 -0
  126. package/dashboard/dist/providers/vertex.svg +17 -0
  127. package/dashboard/dist/providers/windsurf.svg +10 -0
  128. package/dashboard/dist/providers/zai.svg +3 -0
  129. package/dashboard/tsconfig.json +13 -0
  130. package/package.json +87 -0
  131. package/src/config/appConstants.js +153 -0
  132. package/src/config/defaultThinkingSignature.js +7 -0
  133. package/src/config/errorConfig.js +117 -0
  134. package/src/config/grokCli.js +9 -0
  135. package/src/config/kiroConstants.js +235 -0
  136. package/src/config/mediaConfig.js +20 -0
  137. package/src/config/ollamaModels.js +18 -0
  138. package/src/config/providerModels.js +109 -0
  139. package/src/config/providers.js +17 -0
  140. package/src/config/runtimeConfig.js +84 -0
  141. package/src/dashboardGuard.js +254 -0
  142. package/src/executors/antigravity.js +389 -0
  143. package/src/executors/azure.js +49 -0
  144. package/src/executors/base.js +225 -0
  145. package/src/executors/codebuddy-cn.js +23 -0
  146. package/src/executors/codebuddy-intl.js +60 -0
  147. package/src/executors/codex.js +436 -0
  148. package/src/executors/commandcode.js +83 -0
  149. package/src/executors/cursor.js +1075 -0
  150. package/src/executors/default.js +294 -0
  151. package/src/executors/gemini-cli.js +88 -0
  152. package/src/executors/github.js +393 -0
  153. package/src/executors/grok-cli.js +510 -0
  154. package/src/executors/grok-web.js +342 -0
  155. package/src/executors/index.js +86 -0
  156. package/src/executors/kimchi.js +116 -0
  157. package/src/executors/kiro.js +1155 -0
  158. package/src/executors/ollama-local.js +14 -0
  159. package/src/executors/opencode-go.js +47 -0
  160. package/src/executors/opencode.js +31 -0
  161. package/src/executors/qoder.js +433 -0
  162. package/src/executors/trae.js +318 -0
  163. package/src/executors/vertex.js +151 -0
  164. package/src/executors/windsurf.js +555 -0
  165. package/src/executors/xiaomi-tokenplan.js +16 -0
  166. package/src/handlers/chatCore/nonStreamingHandler.js +370 -0
  167. package/src/handlers/chatCore/requestDetail.js +130 -0
  168. package/src/handlers/chatCore/sseToJsonHandler.js +318 -0
  169. package/src/handlers/chatCore/streamingHandler.js +250 -0
  170. package/src/handlers/chatCore.js +652 -0
  171. package/src/lib/auth/dashboardSession.js +83 -0
  172. package/src/lib/auth/loginLimiter.js +99 -0
  173. package/src/lib/cache/ttlCache.js +153 -0
  174. package/src/lib/consoleLogBuffer.js +127 -0
  175. package/src/lib/dataDir.js +45 -0
  176. package/src/lib/db/adapters/betterSqliteAdapter.js +36 -0
  177. package/src/lib/db/adapters/bunSqliteAdapter.js +47 -0
  178. package/src/lib/db/adapters/nodeSqliteAdapter.js +65 -0
  179. package/src/lib/db/adapters/runtimeHelpers.js +23 -0
  180. package/src/lib/db/adapters/sqljsAdapter.js +103 -0
  181. package/src/lib/db/backup.js +75 -0
  182. package/src/lib/db/driver.js +110 -0
  183. package/src/lib/db/helpers/jsonCol.js +18 -0
  184. package/src/lib/db/helpers/kvStore.js +48 -0
  185. package/src/lib/db/helpers/metaStore.js +32 -0
  186. package/src/lib/db/index.js +473 -0
  187. package/src/lib/db/migrate.js +267 -0
  188. package/src/lib/db/migrations/001-initial.js +12 -0
  189. package/src/lib/db/migrations/002-prune-headroom-pxpipe-settings.js +32 -0
  190. package/src/lib/db/migrations/004-request-details-trace-id.js +12 -0
  191. package/src/lib/db/migrations/005-request-details-payload-capture.js +11 -0
  192. package/src/lib/db/migrations/007-headroom-readd-settings.js +35 -0
  193. package/src/lib/db/migrations/008-account-model-locks.js +22 -0
  194. package/src/lib/db/migrations/009-warp-pool-lifecycle.js +5 -0
  195. package/src/lib/db/migrations/010-api-key-file-permissions.js +7 -0
  196. package/src/lib/db/migrations/011-remove-upstream-user-agent-profile.js +41 -0
  197. package/src/lib/db/migrations/012-remove-headroom-settings.js +33 -0
  198. package/src/lib/db/migrations/013-default-fill-first-routing.js +20 -0
  199. package/src/lib/db/migrations/014-normalize-fill-first-routing.js +37 -0
  200. package/src/lib/db/migrations/015-remove-ip-ban-tables.js +8 -0
  201. package/src/lib/db/migrations/016-prune-legacy-codebuddy-intl-models.js +25 -0
  202. package/src/lib/db/migrations/index.js +20 -0
  203. package/src/lib/db/nineRouterMigration.js +785 -0
  204. package/src/lib/db/paths.js +23 -0
  205. package/src/lib/db/repos/accountModelLocksRepo.js +74 -0
  206. package/src/lib/db/repos/aliasRepo.js +108 -0
  207. package/src/lib/db/repos/apiKeysRepo.js +204 -0
  208. package/src/lib/db/repos/combosRepo.js +85 -0
  209. package/src/lib/db/repos/connectionsRepo.js +522 -0
  210. package/src/lib/db/repos/disabledModelsRepo.js +63 -0
  211. package/src/lib/db/repos/nodesRepo.js +127 -0
  212. package/src/lib/db/repos/pricingRepo.js +108 -0
  213. package/src/lib/db/repos/proxyPoolsRepo.js +104 -0
  214. package/src/lib/db/repos/requestDetailsRepo.js +345 -0
  215. package/src/lib/db/repos/settingsRepo.js +135 -0
  216. package/src/lib/db/repos/usageRepo.js +1335 -0
  217. package/src/lib/db/schema.js +179 -0
  218. package/src/lib/db/version.js +32 -0
  219. package/src/lib/db/writeBehind.js +174 -0
  220. package/src/lib/disabledModelsDb.js +3 -0
  221. package/src/lib/env.ts +175 -0
  222. package/src/lib/errors/publicError.js +18 -0
  223. package/src/lib/grokBuildConfig.js +243 -0
  224. package/src/lib/guardRequest.js +51 -0
  225. package/src/lib/localDb.js +21 -0
  226. package/src/lib/mcp/stdioSseBridge.js +174 -0
  227. package/src/lib/network/connectionProxy.js +200 -0
  228. package/src/lib/network/proxyTest.js +158 -0
  229. package/src/lib/network/proxyUrl.js +76 -0
  230. package/src/lib/network/relay.js +71 -0
  231. package/src/lib/oauth/constants/oauth.js +152 -0
  232. package/src/lib/oauth/constants/xai.js +43 -0
  233. package/src/lib/oauth/kiroExternalIdp.js +167 -0
  234. package/src/lib/oauth/providerHelpers.js +90 -0
  235. package/src/lib/oauth/providers/_shared.js +12 -0
  236. package/src/lib/oauth/providers/antigravity.js +126 -0
  237. package/src/lib/oauth/providers/claude.js +60 -0
  238. package/src/lib/oauth/providers/cline.js +62 -0
  239. package/src/lib/oauth/providers/clinepass.js +62 -0
  240. package/src/lib/oauth/providers/codebuddy-cn.js +75 -0
  241. package/src/lib/oauth/providers/codebuddy-intl.js +73 -0
  242. package/src/lib/oauth/providers/codex.js +72 -0
  243. package/src/lib/oauth/providers/cursor.js +18 -0
  244. package/src/lib/oauth/providers/gemini-cli.js +84 -0
  245. package/src/lib/oauth/providers/github.js +96 -0
  246. package/src/lib/oauth/providers/grok-cli.js +123 -0
  247. package/src/lib/oauth/providers/index.js +233 -0
  248. package/src/lib/oauth/providers/kilocode.js +60 -0
  249. package/src/lib/oauth/providers/kimchi.js +79 -0
  250. package/src/lib/oauth/providers/kimi.js +79 -0
  251. package/src/lib/oauth/providers/kiro.js +147 -0
  252. package/src/lib/oauth/providers/qoder.js +90 -0
  253. package/src/lib/oauth/providers/trae.js +244 -0
  254. package/src/lib/oauth/providers/windsurf.js +123 -0
  255. package/src/lib/oauth/providers/xai.js +95 -0
  256. package/src/lib/oauth/providers.js +16 -0
  257. package/src/lib/oauth/services/cursor.js +132 -0
  258. package/src/lib/oauth/services/kiro.js +351 -0
  259. package/src/lib/oauth/services/oauth.js +135 -0
  260. package/src/lib/oauth/services/qoder.js +151 -0
  261. package/src/lib/oauth/services/xai.js +204 -0
  262. package/src/lib/oauth/utils/ideDetect.js +55 -0
  263. package/src/lib/oauth/utils/pkce.js +25 -0
  264. package/src/lib/oauth/utils/server.js +732 -0
  265. package/src/lib/oauth/utils/ui.js +43 -0
  266. package/src/lib/providerNormalization.js +40 -0
  267. package/src/lib/qoder/constants.js +1 -0
  268. package/src/lib/requestDetailsDb.js +3 -0
  269. package/src/lib/resourceProfile.ts +124 -0
  270. package/src/lib/runtimeSecrets.ts +130 -0
  271. package/src/lib/security/payloadCapture.js +87 -0
  272. package/src/lib/tunnel/cloudflare/cloudflared.js +436 -0
  273. package/src/lib/tunnel/cloudflare/config.js +8 -0
  274. package/src/lib/tunnel/cloudflare/healthCheck.js +37 -0
  275. package/src/lib/tunnel/cloudflare/manager.js +149 -0
  276. package/src/lib/tunnel/cloudflare/pid.js +31 -0
  277. package/src/lib/tunnel/cloudflare/publicUrl.js +41 -0
  278. package/src/lib/tunnel/cloudflare/requirements.js +12 -0
  279. package/src/lib/tunnel/index.js +26 -0
  280. package/src/lib/tunnel/shared/dnsResolver.js +16 -0
  281. package/src/lib/tunnel/shared/internetCheck.js +30 -0
  282. package/src/lib/tunnel/shared/state.js +45 -0
  283. package/src/lib/tunnel/shared/watchdogConfig.js +6 -0
  284. package/src/lib/update/installer.js +52 -0
  285. package/src/lib/update/version.js +116 -0
  286. package/src/lib/usageDb.js +6 -0
  287. package/src/lib/usageRefresh.js +88 -0
  288. package/src/lifecycle/appLifecycle.ts +99 -0
  289. package/src/models.js +36 -0
  290. package/src/next/headers.js +12 -0
  291. package/src/next/server.js +74 -0
  292. package/src/observability/metrics.js +439 -0
  293. package/src/observability/tracing.js +107 -0
  294. package/src/open-sse-index.js +70 -0
  295. package/src/providers/capabilities.js +299 -0
  296. package/src/providers/display.ts +142 -0
  297. package/src/providers/index.js +27 -0
  298. package/src/providers/models/helpers.js +19 -0
  299. package/src/providers/models/namePatterns.js +27 -0
  300. package/src/providers/models/schema.js +32 -0
  301. package/src/providers/pricing.js +248 -0
  302. package/src/providers/registry/agentrouter.js +52 -0
  303. package/src/providers/registry/alicode-intl.js +32 -0
  304. package/src/providers/registry/alicode.js +33 -0
  305. package/src/providers/registry/alims-intl.js +30 -0
  306. package/src/providers/registry/anthropic.js +29 -0
  307. package/src/providers/registry/antigravity.js +139 -0
  308. package/src/providers/registry/azure.js +23 -0
  309. package/src/providers/registry/baidu.js +35 -0
  310. package/src/providers/registry/blackbox.js +41 -0
  311. package/src/providers/registry/byteplus.js +36 -0
  312. package/src/providers/registry/cerebras.js +33 -0
  313. package/src/providers/registry/chutes.js +26 -0
  314. package/src/providers/registry/claude.js +80 -0
  315. package/src/providers/registry/cline.js +53 -0
  316. package/src/providers/registry/clinepass.js +62 -0
  317. package/src/providers/registry/cloudflare-ai.js +84 -0
  318. package/src/providers/registry/codebuddy-cn.js +95 -0
  319. package/src/providers/registry/codebuddy-intl.js +91 -0
  320. package/src/providers/registry/codex.js +145 -0
  321. package/src/providers/registry/commandcode.js +45 -0
  322. package/src/providers/registry/cursor.js +61 -0
  323. package/src/providers/registry/deepseek.js +55 -0
  324. package/src/providers/registry/featherless.js +36 -0
  325. package/src/providers/registry/fireworks.js +34 -0
  326. package/src/providers/registry/gemini-cli.js +59 -0
  327. package/src/providers/registry/gemini.js +76 -0
  328. package/src/providers/registry/github.js +131 -0
  329. package/src/providers/registry/glm-cn.js +35 -0
  330. package/src/providers/registry/glm.js +58 -0
  331. package/src/providers/registry/grok-cli.js +87 -0
  332. package/src/providers/registry/grok-web.js +41 -0
  333. package/src/providers/registry/groq.js +38 -0
  334. package/src/providers/registry/index.js +77 -0
  335. package/src/providers/registry/kilo-gateway.js +34 -0
  336. package/src/providers/registry/kilocode.js +48 -0
  337. package/src/providers/registry/kimchi.js +49 -0
  338. package/src/providers/registry/kimi.js +82 -0
  339. package/src/providers/registry/kiro.js +132 -0
  340. package/src/providers/registry/meta.js +34 -0
  341. package/src/providers/registry/minimax-cn.js +90 -0
  342. package/src/providers/registry/minimax.js +90 -0
  343. package/src/providers/registry/mistral.js +36 -0
  344. package/src/providers/registry/morph.js +31 -0
  345. package/src/providers/registry/nebius.js +26 -0
  346. package/src/providers/registry/nvidia.js +55 -0
  347. package/src/providers/registry/ollama-local.js +18 -0
  348. package/src/providers/registry/ollama.js +38 -0
  349. package/src/providers/registry/openai.js +114 -0
  350. package/src/providers/registry/opencode-go.js +41 -0
  351. package/src/providers/registry/opencode.js +26 -0
  352. package/src/providers/registry/openrouter.js +36 -0
  353. package/src/providers/registry/perplexity.js +56 -0
  354. package/src/providers/registry/poolside.js +30 -0
  355. package/src/providers/registry/qoder.js +58 -0
  356. package/src/providers/registry/sumopod.js +84 -0
  357. package/src/providers/registry/tencent.js +29 -0
  358. package/src/providers/registry/together.js +38 -0
  359. package/src/providers/registry/trae.js +71 -0
  360. package/src/providers/registry/venice.js +69 -0
  361. package/src/providers/registry/vercel-ai-gateway.js +37 -0
  362. package/src/providers/registry/vertex-partner.js +31 -0
  363. package/src/providers/registry/vertex.js +33 -0
  364. package/src/providers/registry/windsurf.js +129 -0
  365. package/src/providers/registry/xai.js +46 -0
  366. package/src/providers/registry/xiaomi-mimo.js +66 -0
  367. package/src/providers/registry/xiaomi-tokenplan.js +58 -0
  368. package/src/providers/registryEntry.js +3 -0
  369. package/src/providers/schema.js +33 -0
  370. package/src/providers/shared.js +114 -0
  371. package/src/providers/thinkingLevels.js +49 -0
  372. package/src/routes/api/auth/login/route.js +82 -0
  373. package/src/routes/api/auth/logout/route.js +9 -0
  374. package/src/routes/api/auth/reset-password/route.js +12 -0
  375. package/src/routes/api/auth/status/route.js +33 -0
  376. package/src/routes/api/auth/verify-password/route.js +39 -0
  377. package/src/routes/api/chat/tools/curl/route.js +100 -0
  378. package/src/routes/api/chat/tools/router/route.js +215 -0
  379. package/src/routes/api/chat/tools/search/route.js +362 -0
  380. package/src/routes/api/chat/tools/shell/route.js +228 -0
  381. package/src/routes/api/cli-tools/all-statuses/route.js +37 -0
  382. package/src/routes/api/cli-tools/claude-settings/route.js +261 -0
  383. package/src/routes/api/cli-tools/codex-settings/route.js +220 -0
  384. package/src/routes/api/cli-tools/cowork-mcp-registry/route.js +80 -0
  385. package/src/routes/api/cli-tools/cowork-mcp-tools/route.js +96 -0
  386. package/src/routes/api/cli-tools/cowork-settings/route.js +380 -0
  387. package/src/routes/api/cli-tools/grok-build-settings/route.js +152 -0
  388. package/src/routes/api/cli-tools/hermes-settings/route.js +169 -0
  389. package/src/routes/api/cli-tools/kilo-settings/route.js +131 -0
  390. package/src/routes/api/cli-tools/model-mappings/route.js +43 -0
  391. package/src/routes/api/cli-tools/omp-settings/route.js +266 -0
  392. package/src/routes/api/cli-tools/opencode-settings/route.js +243 -0
  393. package/src/routes/api/combos/[id]/route.js +73 -0
  394. package/src/routes/api/combos/route.js +43 -0
  395. package/src/routes/api/health/live/route.js +7 -0
  396. package/src/routes/api/health/ready/route.js +19 -0
  397. package/src/routes/api/health/route.js +17 -0
  398. package/src/routes/api/inflight/stream/route.js +24 -0
  399. package/src/routes/api/init/route.js +3 -0
  400. package/src/routes/api/keys/[id]/route.js +71 -0
  401. package/src/routes/api/keys/route.js +41 -0
  402. package/src/routes/api/logs/route.js +19 -0
  403. package/src/routes/api/mcp/[plugin]/message/route.js +23 -0
  404. package/src/routes/api/mcp/[plugin]/sse/route.js +35 -0
  405. package/src/routes/api/models/availability/route.js +104 -0
  406. package/src/routes/api/models/custom/route.js +58 -0
  407. package/src/routes/api/models/disabled/route.js +47 -0
  408. package/src/routes/api/models/route.js +64 -0
  409. package/src/routes/api/models/test/ping.js +236 -0
  410. package/src/routes/api/models/test/route.js +14 -0
  411. package/src/routes/api/oauth/[provider]/[action]/route.js +491 -0
  412. package/src/routes/api/oauth/codex/bulk-import/route.js +105 -0
  413. package/src/routes/api/oauth/codex/import-token/route.js +82 -0
  414. package/src/routes/api/oauth/cursor/auto-import/route.js +250 -0
  415. package/src/routes/api/oauth/cursor/import/route.js +86 -0
  416. package/src/routes/api/oauth/kiro/api-key/route.js +60 -0
  417. package/src/routes/api/oauth/kiro/auto-import/route.js +120 -0
  418. package/src/routes/api/oauth/kiro/import/route.js +72 -0
  419. package/src/routes/api/oauth/kiro/import-cli-proxy/route.js +42 -0
  420. package/src/routes/api/oauth/kiro/social-authorize/route.js +40 -0
  421. package/src/routes/api/oauth/kiro/social-exchange/route.js +62 -0
  422. package/src/routes/api/pricing/route.js +96 -0
  423. package/src/routes/api/provider-nodes/[id]/route.js +106 -0
  424. package/src/routes/api/provider-nodes/route.js +110 -0
  425. package/src/routes/api/provider-nodes/validate/route.js +197 -0
  426. package/src/routes/api/providers/[id]/models/route.js +716 -0
  427. package/src/routes/api/providers/[id]/route.js +195 -0
  428. package/src/routes/api/providers/[id]/test/route.js +27 -0
  429. package/src/routes/api/providers/[id]/test/testUtils.js +912 -0
  430. package/src/routes/api/providers/[id]/test-models/route.js +211 -0
  431. package/src/routes/api/providers/catalog/route.js +58 -0
  432. package/src/routes/api/providers/client/route.js +133 -0
  433. package/src/routes/api/providers/counts/route.js +43 -0
  434. package/src/routes/api/providers/kilo/free-models/route.js +58 -0
  435. package/src/routes/api/providers/route.js +361 -0
  436. package/src/routes/api/providers/suggested-models/filters.js +24 -0
  437. package/src/routes/api/providers/suggested-models/route.js +34 -0
  438. package/src/routes/api/providers/test-batch/route.js +145 -0
  439. package/src/routes/api/providers/validate/route.js +633 -0
  440. package/src/routes/api/proxy-pools/[id]/route.js +129 -0
  441. package/src/routes/api/proxy-pools/[id]/test/route.js +64 -0
  442. package/src/routes/api/proxy-pools/cloudflare-deploy/route.js +183 -0
  443. package/src/routes/api/proxy-pools/route.js +85 -0
  444. package/src/routes/api/proxy-pools/vercel-deploy/route.js +181 -0
  445. package/src/routes/api/settings/currency/route.js +29 -0
  446. package/src/routes/api/settings/database/path/route.js +8 -0
  447. package/src/routes/api/settings/database/route.js +89 -0
  448. package/src/routes/api/settings/migrate-9router/route.js +81 -0
  449. package/src/routes/api/settings/require-login/route.js +14 -0
  450. package/src/routes/api/settings/route.js +186 -0
  451. package/src/routes/api/shutdown/route.js +25 -0
  452. package/src/routes/api/tags/route.js +17 -0
  453. package/src/routes/api/translator/console-logs/route.js +28 -0
  454. package/src/routes/api/translator/console-logs/stream/route.js +95 -0
  455. package/src/routes/api/tunnel/disable/route.js +18 -0
  456. package/src/routes/api/tunnel/enable/route.js +32 -0
  457. package/src/routes/api/tunnel/status/route.js +23 -0
  458. package/src/routes/api/update/route.js +42 -0
  459. package/src/routes/api/usage/[connectionId]/codex-reset-credits/route.js +169 -0
  460. package/src/routes/api/usage/[connectionId]/route.js +222 -0
  461. package/src/routes/api/usage/chart/route.js +27 -0
  462. package/src/routes/api/usage/history/route.js +94 -0
  463. package/src/routes/api/usage/logs/route.js +14 -0
  464. package/src/routes/api/usage/providers/route.js +36 -0
  465. package/src/routes/api/usage/request-details/route.js +61 -0
  466. package/src/routes/api/usage/request-logs/route.js +15 -0
  467. package/src/routes/api/usage/stats/route.js +23 -0
  468. package/src/routes/api/usage/stream/route.js +78 -0
  469. package/src/routes/api/v1/api/chat/route.js +36 -0
  470. package/src/routes/api/v1/chat/completions/route.js +28 -0
  471. package/src/routes/api/v1/images/edits/route.js +70 -0
  472. package/src/routes/api/v1/images/generations/route.js +50 -0
  473. package/src/routes/api/v1/images/imageValidation.js +45 -0
  474. package/src/routes/api/v1/messages/count_tokens/route.js +87 -0
  475. package/src/routes/api/v1/messages/route.js +26 -0
  476. package/src/routes/api/v1/models/route.js +440 -0
  477. package/src/routes/api/v1/responses/compact/route.js +34 -0
  478. package/src/routes/api/v1/responses/route.js +26 -0
  479. package/src/routes/api/v1/route.js +1 -0
  480. package/src/routes/api/version/route.js +11 -0
  481. package/src/routes/table.js +1141 -0
  482. package/src/rtk/applyFilter.js +13 -0
  483. package/src/rtk/autodetect.js +104 -0
  484. package/src/rtk/caveman.js +6 -0
  485. package/src/rtk/cavemanPrompts.js +107 -0
  486. package/src/rtk/constants.js +51 -0
  487. package/src/rtk/filters/buildOutput.js +120 -0
  488. package/src/rtk/filters/dedupLog.js +43 -0
  489. package/src/rtk/filters/find.js +47 -0
  490. package/src/rtk/filters/gitDiff.js +90 -0
  491. package/src/rtk/filters/gitLog.js +88 -0
  492. package/src/rtk/filters/gitStatus.js +101 -0
  493. package/src/rtk/filters/grep.js +45 -0
  494. package/src/rtk/filters/ls.js +73 -0
  495. package/src/rtk/filters/readNumbered.js +22 -0
  496. package/src/rtk/filters/searchList.js +49 -0
  497. package/src/rtk/filters/smartTruncate.js +13 -0
  498. package/src/rtk/filters/tree.js +28 -0
  499. package/src/rtk/index.js +143 -0
  500. package/src/rtk/ponytail.js +6 -0
  501. package/src/rtk/ponytailPrompt.js +49 -0
  502. package/src/rtk/systemInject.js +89 -0
  503. package/src/server.ts +474 -0
  504. package/src/services/accountFallback.js +241 -0
  505. package/src/services/accountPool.js +389 -0
  506. package/src/services/capacityAdapter.js +140 -0
  507. package/src/services/cliModelMapping.js +84 -0
  508. package/src/services/clinepassModels.js +60 -0
  509. package/src/services/codebuddyModels.js +250 -0
  510. package/src/services/combo.js +482 -0
  511. package/src/services/copilotModels.js +126 -0
  512. package/src/services/currencyRate.js +56 -0
  513. package/src/services/cursorModels.js +197 -0
  514. package/src/services/grokCliModels.js +130 -0
  515. package/src/services/kimchiModels.js +175 -0
  516. package/src/services/kiroModels.js +246 -0
  517. package/src/services/model.js +83 -0
  518. package/src/services/oauthCredentialManager.js +153 -0
  519. package/src/services/projectId.js +240 -0
  520. package/src/services/provider.js +145 -0
  521. package/src/services/qoderModels.js +274 -0
  522. package/src/services/tokenRefresh/dedup.js +70 -0
  523. package/src/services/tokenRefresh/providers.js +626 -0
  524. package/src/services/tokenRefresh.js +274 -0
  525. package/src/services/usage/claude.js +134 -0
  526. package/src/services/usage/codebuddy-cn.js +212 -0
  527. package/src/services/usage/codex.js +193 -0
  528. package/src/services/usage/deepseek.js +103 -0
  529. package/src/services/usage/github.js +94 -0
  530. package/src/services/usage/google.js +218 -0
  531. package/src/services/usage/grok-cli.js +368 -0
  532. package/src/services/usage/grokCliQuotaFrame.js +170 -0
  533. package/src/services/usage/kimi.js +185 -0
  534. package/src/services/usage/kiro.js +172 -0
  535. package/src/services/usage/minimax.js +215 -0
  536. package/src/services/usage/misc.js +264 -0
  537. package/src/services/usage/shared.js +59 -0
  538. package/src/services/usage.js +56 -0
  539. package/src/shared/clineAuth.js +37 -0
  540. package/src/shared/constants/config.js +80 -0
  541. package/src/shared/constants/coworkPlugins.js +69 -0
  542. package/src/shared/constants/models.js +41 -0
  543. package/src/shared/constants/providers.js +128 -0
  544. package/src/shared/constants/providersDisplay.js +1 -0
  545. package/src/shared/qoder/constants.js +50 -0
  546. package/src/shared/qoder/cosy.js +134 -0
  547. package/src/shared/qoder/encoding.js +36 -0
  548. package/src/shared/services/initializeApp.js +226 -0
  549. package/src/shared/services/quotaAutoPing.js +310 -0
  550. package/src/shared/utils/apiKey.js +65 -0
  551. package/src/shared/utils/clineAuth.js +1 -0
  552. package/src/shared/utils/index.js +3 -0
  553. package/src/shared/utils/machineId.js +60 -0
  554. package/src/shared/utils/ssrfGuard.js +280 -0
  555. package/src/sse/handlers/chat.js +426 -0
  556. package/src/sse/oauthLease.js +32 -0
  557. package/src/sse/recovery.js +235 -0
  558. package/src/sse/services/auth.js +489 -0
  559. package/src/sse/services/backgroundTokenRefresh.js +173 -0
  560. package/src/sse/services/model.js +129 -0
  561. package/src/sse/services/requestCancellation.js +4 -0
  562. package/src/sse/services/tokenRefresh.js +264 -0
  563. package/src/sse/utils/logger.js +142 -0
  564. package/src/staticServe.ts +95 -0
  565. package/src/transformer/streamToJsonConverter.js +87 -0
  566. package/src/translator/canonical.js +81 -0
  567. package/src/translator/concerns/chunk.js +9 -0
  568. package/src/translator/concerns/compatFallback.js +147 -0
  569. package/src/translator/concerns/finishReason.js +59 -0
  570. package/src/translator/concerns/image.js +105 -0
  571. package/src/translator/concerns/json.js +4 -0
  572. package/src/translator/concerns/kiroConversation.js +428 -0
  573. package/src/translator/concerns/message.js +5 -0
  574. package/src/translator/concerns/modality.js +134 -0
  575. package/src/translator/concerns/paramSupport.js +97 -0
  576. package/src/translator/concerns/prefetch.js +86 -0
  577. package/src/translator/concerns/reasoning.js +18 -0
  578. package/src/translator/concerns/thinking.js +40 -0
  579. package/src/translator/concerns/thinkingUnified.js +319 -0
  580. package/src/translator/concerns/toolCall.js +134 -0
  581. package/src/translator/concerns/usage.js +61 -0
  582. package/src/translator/detection.js +42 -0
  583. package/src/translator/formats/claude.js +323 -0
  584. package/src/translator/formats/gemini.js +366 -0
  585. package/src/translator/formats/maxTokens.js +19 -0
  586. package/src/translator/formats/openai.js +116 -0
  587. package/src/translator/formats/responsesApi.js +117 -0
  588. package/src/translator/formats.js +28 -0
  589. package/src/translator/index.js +237 -0
  590. package/src/translator/request/antigravity-to-openai.js +217 -0
  591. package/src/translator/request/claude-to-kiro.js +288 -0
  592. package/src/translator/request/claude-to-openai.js +199 -0
  593. package/src/translator/request/gemini-to-openai.js +142 -0
  594. package/src/translator/request/openai-responses.js +373 -0
  595. package/src/translator/request/openai-to-claude.js +260 -0
  596. package/src/translator/request/openai-to-commandcode.js +161 -0
  597. package/src/translator/request/openai-to-cursor.js +175 -0
  598. package/src/translator/request/openai-to-gemini.js +422 -0
  599. package/src/translator/request/openai-to-kiro.js +360 -0
  600. package/src/translator/request/openai-to-ollama.js +152 -0
  601. package/src/translator/request/openai-to-vertex.js +36 -0
  602. package/src/translator/response/claude-to-openai.js +185 -0
  603. package/src/translator/response/commandcode-to-openai.js +164 -0
  604. package/src/translator/response/cursor-to-openai.js +18 -0
  605. package/src/translator/response/gemini-to-openai.js +127 -0
  606. package/src/translator/response/kiro-to-claude.js +230 -0
  607. package/src/translator/response/kiro-to-openai.js +136 -0
  608. package/src/translator/response/ollama-to-openai.js +106 -0
  609. package/src/translator/response/openai-responses.js +534 -0
  610. package/src/translator/response/openai-to-antigravity.js +107 -0
  611. package/src/translator/response/openai-to-claude.js +231 -0
  612. package/src/translator/schema/blocks.js +40 -0
  613. package/src/translator/schema/defaults.js +3 -0
  614. package/src/translator/schema/finishReasons.js +22 -0
  615. package/src/translator/schema/index.js +7 -0
  616. package/src/translator/schema/roles.js +12 -0
  617. package/src/transport/requestBoundary.ts +223 -0
  618. package/src/transport/routerAdmission.ts +380 -0
  619. package/src/types/provider.ts +59 -0
  620. package/src/utils/bypassHandler.js +272 -0
  621. package/src/utils/claudeCloaking.js +10 -0
  622. package/src/utils/claudeSignature.js +35 -0
  623. package/src/utils/clientDetector.js +183 -0
  624. package/src/utils/cursorChecksum.js +104 -0
  625. package/src/utils/cursorProtobuf.js +801 -0
  626. package/src/utils/debugLog.js +12 -0
  627. package/src/utils/error.js +120 -0
  628. package/src/utils/inflight.js +127 -0
  629. package/src/utils/kiroSessionReplay.js +139 -0
  630. package/src/utils/ollamaTransform.js +83 -0
  631. package/src/utils/proxyFetch.js +308 -0
  632. package/src/utils/reasoningContentInjector.js +71 -0
  633. package/src/utils/requestLogger.js +272 -0
  634. package/src/utils/responsesStreamHelpers.js +46 -0
  635. package/src/utils/sessionManager.js +205 -0
  636. package/src/utils/sse.js +13 -0
  637. package/src/utils/sseConstants.js +21 -0
  638. package/src/utils/stream.js +511 -0
  639. package/src/utils/streamHandler.js +256 -0
  640. package/src/utils/streamHelpers.js +113 -0
  641. package/src/utils/toolDeduper.js +44 -0
  642. package/src/utils/usageTracking.js +329 -0
  643. package/tsconfig.json +45 -0
@@ -0,0 +1,380 @@
1
+ "use server";
2
+
3
+ import { NextResponse } from "next/server";
4
+ import fs from "fs/promises";
5
+ import path from "path";
6
+ import os from "os";
7
+ import crypto from "crypto";
8
+ import { DEFAULT_PLUGINS, LOCAL_STDIO_PLUGINS, buildManagedMcpServers } from "@/shared/constants/coworkPlugins";
9
+ import { RUNTIME_CONFIG } from "@/shared/constants/config";
10
+ import { getConsistentMachineId } from "@/shared/utils/machineId";
11
+ import { logRouteError, publicError } from "@/lib/errors/publicError";
12
+
13
+ const COWORK_ERROR = publicError("provider", "Failed to apply Cowork settings");
14
+
15
+ const APP_PORT = RUNTIME_CONFIG.appPort;
16
+ const CLI_TOKEN_HEADER = "x-swayrouter-cli-token";
17
+ const CLI_TOKEN_SALT = "swayrouter-cli-auth";
18
+ const LOCAL_MCP_PREFIX = `http://localhost:${APP_PORT}/api/mcp/`;
19
+
20
+ let cachedCliToken = null;
21
+ const getCliToken = async () => {
22
+ if (!cachedCliToken) cachedCliToken = await getConsistentMachineId(CLI_TOKEN_SALT);
23
+ return cachedCliToken;
24
+ };
25
+
26
+ const injectAuthHeaders = async (entries) => {
27
+ const token = await getCliToken();
28
+ for (const e of entries) {
29
+ if (typeof e?.url === "string" && e.url.startsWith(LOCAL_MCP_PREFIX)) {
30
+ e.headers = { ...(e.headers || {}), [CLI_TOKEN_HEADER]: token };
31
+ }
32
+ }
33
+ return entries;
34
+ };
35
+
36
+ const PROVIDER = "gateway";
37
+
38
+ const SECURITY_RELAX = {
39
+ coworkEgressAllowedHosts: ["*"],
40
+ disabledBuiltinTools: [],
41
+ isLocalDevMcpEnabled: true,
42
+ isDesktopExtensionEnabled: true,
43
+ isDesktopExtensionDirectoryEnabled: true,
44
+ isDesktopExtensionSignatureRequired: false,
45
+ isClaudeCodeForDesktopEnabled: true,
46
+ disableEssentialTelemetry: true,
47
+ disableNonessentialTelemetry: true,
48
+ disableNonessentialServices: true,
49
+ };
50
+
51
+ const getCandidateRoots = () => {
52
+ if (os.platform() === "darwin") {
53
+ const base = path.join(os.homedir(), "Library", "Application Support");
54
+ return [path.join(base, "Claude-3p"), path.join(base, "Claude")];
55
+ }
56
+ if (os.platform() === "win32") {
57
+ const localApp = process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
58
+ const roaming = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
59
+ return [
60
+ path.join(localApp, "Claude-3p"),
61
+ path.join(roaming, "Claude-3p"),
62
+ path.join(localApp, "Claude"),
63
+ path.join(roaming, "Claude"),
64
+ ];
65
+ }
66
+ return [
67
+ path.join(os.homedir(), ".config", "Claude-3p"),
68
+ path.join(os.homedir(), ".config", "Claude"),
69
+ ];
70
+ };
71
+
72
+ const getAppInstallPaths = () => {
73
+ if (os.platform() === "darwin") {
74
+ return ["/Applications/Claude.app", path.join(os.homedir(), "Applications", "Claude.app")];
75
+ }
76
+ if (os.platform() === "win32") {
77
+ const localApp = process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
78
+ const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
79
+ return [
80
+ path.join(localApp, "AnthropicClaude"),
81
+ path.join(programFiles, "Claude"),
82
+ path.join(programFiles, "AnthropicClaude"),
83
+ ];
84
+ }
85
+ return [];
86
+ };
87
+
88
+ const resolveAppRootForRead = async () => {
89
+ const candidates = getCandidateRoots();
90
+ for (const dir of candidates) {
91
+ try {
92
+ await fs.access(path.join(dir, "configLibrary"));
93
+ return dir;
94
+ } catch { }
95
+ }
96
+ return candidates[0];
97
+ };
98
+
99
+ const getWriteRoot = () => getCandidateRoots()[0];
100
+ const getConfigDir = async () => path.join(await resolveAppRootForRead(), "configLibrary");
101
+ const getWriteConfigDir = () => path.join(getWriteRoot(), "configLibrary");
102
+ const getMetaPath = async () => path.join(await getConfigDir(), "_meta.json");
103
+ const getWriteMetaPath = () => path.join(getWriteConfigDir(), "_meta.json");
104
+
105
+ const get1pRoot = () => {
106
+ if (os.platform() === "darwin") return path.join(os.homedir(), "Library", "Application Support", "Claude");
107
+ if (os.platform() === "win32") {
108
+ const roaming = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
109
+ return path.join(roaming, "Claude");
110
+ }
111
+ return path.join(os.homedir(), ".config", "Claude");
112
+ };
113
+
114
+ const get1pConfigPath = () => path.join(get1pRoot(), "claude_desktop_config.json");
115
+
116
+ const read1pConfig = async () => {
117
+ try {
118
+ const content = await fs.readFile(get1pConfigPath(), "utf-8");
119
+
120
+ const stripped = content.replace(/,(\s*[}\]])/g, "$1");
121
+ return JSON.parse(stripped) || {};
122
+ } catch (error) {
123
+ return {};
124
+ }
125
+ };
126
+
127
+ const write1pConfig = async (cfg) => {
128
+ await fs.mkdir(get1pRoot(), { recursive: true });
129
+ await fs.writeFile(get1pConfigPath(), JSON.stringify(cfg, null, 2));
130
+ };
131
+
132
+ const bootstrapDeploymentMode = async () => {
133
+ const cfg = await read1pConfig();
134
+ if (cfg.deploymentMode === "3p") return false;
135
+ cfg.deploymentMode = "3p";
136
+ await write1pConfig(cfg);
137
+ return true;
138
+ };
139
+
140
+ const cleanup1pLegacy = async () => {
141
+ const cfg = await read1pConfig();
142
+ if (!cfg.mcpServers || typeof cfg.mcpServers !== "object") return;
143
+ const managedNames = new Set(LOCAL_STDIO_PLUGINS.map((p) => p.name));
144
+ for (const k of Object.keys(cfg.mcpServers)) {
145
+ if (managedNames.has(k)) delete cfg.mcpServers[k];
146
+ }
147
+ if (Object.keys(cfg.mcpServers).length === 0) delete cfg.mcpServers;
148
+ await write1pConfig(cfg);
149
+ };
150
+
151
+ const buildLocalBridgeEntries = (localPluginNames) => {
152
+ const names = Array.isArray(localPluginNames) ? localPluginNames : [];
153
+ const out = [];
154
+ for (const n of names) {
155
+ const def = LOCAL_STDIO_PLUGINS.find((p) => p.name === n);
156
+ if (!def) continue;
157
+ const entry = {
158
+ name: def.name,
159
+ url: `http://localhost:${APP_PORT}/api/mcp/${def.name}/sse`,
160
+ transport: "sse",
161
+ };
162
+ if (Array.isArray(def.toolNames) && def.toolNames.length > 0) {
163
+ const prefix = `${def.name}-`;
164
+ const policy = {};
165
+ for (const t of def.toolNames) {
166
+ policy[t] = "allow";
167
+ policy[`${prefix}${t}`] = "allow";
168
+ }
169
+ entry.toolPolicy = policy;
170
+ }
171
+ out.push(entry);
172
+ }
173
+ return out;
174
+ };
175
+
176
+ const buildCustomEntries = (customPlugins) => {
177
+ if (!Array.isArray(customPlugins)) return [];
178
+ const out = [];
179
+ for (const p of customPlugins) {
180
+ if (!p?.name || !p?.url) continue;
181
+ out.push({ name: p.name, url: p.url, transport: p.transport || "sse", custom: true });
182
+ }
183
+ return out;
184
+ };
185
+
186
+ const checkInstalled = async () => {
187
+ for (const dir of [...getCandidateRoots(), ...getAppInstallPaths()]) {
188
+ try { await fs.access(dir); return true; } catch { }
189
+ }
190
+ return false;
191
+ };
192
+
193
+ const readJson = async (filePath) => {
194
+ try {
195
+ const content = await fs.readFile(filePath, "utf-8");
196
+
197
+ const stripped = content.replace(/,(\s*[}\]])/g, "$1");
198
+ return JSON.parse(stripped);
199
+ } catch (error) {
200
+ return null;
201
+ }
202
+ };
203
+
204
+ const ensureMeta = async () => {
205
+ const writeMetaPath = getWriteMetaPath();
206
+ let meta = await readJson(writeMetaPath);
207
+ if (!meta || !meta.appliedId) {
208
+ const existingRead = await readJson(await getMetaPath());
209
+ if (existingRead?.appliedId) {
210
+ meta = existingRead;
211
+ } else {
212
+ const newId = crypto.randomUUID();
213
+ meta = { appliedId: newId, entries: [{ id: newId, name: "Default" }] };
214
+ }
215
+ await fs.mkdir(getWriteConfigDir(), { recursive: true });
216
+ await fs.writeFile(writeMetaPath, JSON.stringify(meta, null, 2));
217
+ }
218
+ return meta;
219
+ };
220
+
221
+ async function writeSkipApprovals(managedServers) {
222
+ const cfgPath = path.join(getWriteRoot(), "config.json");
223
+ let cfg = {};
224
+ try { cfg = JSON.parse(await fs.readFile(cfgPath, "utf-8")) || {}; }
225
+ catch (e) { if (e.code !== "ENOENT") return { error: e.code }; }
226
+ const skip = {};
227
+ for (const srv of managedServers) {
228
+ if (srv?.name) skip[srv.name] = true;
229
+ }
230
+ cfg.operonSkipMcpApprovals = skip;
231
+ await fs.mkdir(getWriteRoot(), { recursive: true });
232
+ await fs.writeFile(cfgPath, JSON.stringify(cfg, null, 2));
233
+ return { written: Object.keys(skip).length };
234
+ }
235
+
236
+ export async function GET() {
237
+ try {
238
+ const installed = await checkInstalled();
239
+ if (!installed) {
240
+ return NextResponse.json({ installed: false, config: null, message: "Claude Desktop (Cowork mode) not detected" });
241
+ }
242
+ const meta = await readJson(await getMetaPath());
243
+ const appliedId = meta?.appliedId || null;
244
+ const configDir = await getConfigDir();
245
+ const configPath = appliedId ? path.join(configDir, `${appliedId}.json`) : null;
246
+ const config = configPath ? await readJson(configPath) : null;
247
+
248
+ const baseUrl = config?.inferenceGatewayBaseUrl || null;
249
+ const models = Array.isArray(config?.inferenceModels)
250
+ ? config.inferenceModels.map((m) => (typeof m === "string" ? m : m?.name)).filter(Boolean)
251
+ : [];
252
+ const managedMcp = Array.isArray(config?.managedMcpServers) ? config.managedMcpServers : [];
253
+ const hasSwayRouter = !!(config?.inferenceProvider === PROVIDER && baseUrl);
254
+
255
+ const stdioNames = new Set(LOCAL_STDIO_PLUGINS.map((p) => p.name));
256
+ const activeLocalNames = managedMcp
257
+ .filter((m) => stdioNames.has(m.name) && typeof m.url === "string" && m.url.includes("/api/mcp/"))
258
+ .map((m) => m.name);
259
+
260
+ const activeCustomPlugins = managedMcp
261
+ .filter((m) => m.custom || (!stdioNames.has(m.name) && typeof m.url === "string" && m.url.includes("/api/mcp/")))
262
+ .map((m) => ({ name: m.name, url: m.url, transport: m.transport, custom: true }));
263
+
264
+ return NextResponse.json({
265
+ installed: true,
266
+ config,
267
+ hasSwayRouter,
268
+ configPath,
269
+ cowork: {
270
+ appliedId,
271
+ baseUrl,
272
+ models,
273
+ provider: config?.inferenceProvider || null,
274
+ plugins: managedMcp.filter((m) => !m.custom && !(stdioNames.has(m.name) && typeof m.url === "string" && m.url.includes("/api/mcp/"))).map((m) => {
275
+
276
+ const keys = m.toolPolicy ? Object.keys(m.toolPolicy) : [];
277
+ const prefix = `${m.name}-`;
278
+ const bare = new Set();
279
+ for (const k of keys) {
280
+ let t = k;
281
+ while (t.startsWith(prefix)) t = t.slice(prefix.length);
282
+ bare.add(t);
283
+ }
284
+
285
+ const def = DEFAULT_PLUGINS.find((d) => d.name === m.name);
286
+ const toolNames = def && Array.isArray(def.toolNames) ? def.toolNames : Array.from(bare);
287
+ return { name: m.name, url: m.url, transport: m.transport, oauth: !!m.oauth, toolNames };
288
+ }),
289
+ localPlugins: activeLocalNames,
290
+ customPlugins: activeCustomPlugins,
291
+ },
292
+ defaultPlugins: DEFAULT_PLUGINS,
293
+ localStdioPlugins: LOCAL_STDIO_PLUGINS,
294
+ });
295
+ } catch (error) {
296
+ console.log("Error reading cowork settings:", error);
297
+ return NextResponse.json({ error: "Failed to read cowork settings" }, { status: 500 });
298
+ }
299
+ }
300
+
301
+ export async function POST(request) {
302
+ try {
303
+ const { baseUrl, apiKey, models, plugins, localPlugins, customPlugins } = await request.json();
304
+
305
+ if (!baseUrl || !apiKey) {
306
+ return NextResponse.json({ error: "baseUrl and apiKey are required" }, { status: 400 });
307
+ }
308
+ const modelsArray = Array.isArray(models) ? models.filter((m) => typeof m === "string" && m.trim()) : [];
309
+ if (modelsArray.length === 0) {
310
+ return NextResponse.json({ error: "At least one model is required" }, { status: 400 });
311
+ }
312
+
313
+ const pluginsArray = Array.isArray(plugins) ? plugins : DEFAULT_PLUGINS;
314
+ const localPluginNames = Array.isArray(localPlugins) ? localPlugins : [];
315
+
316
+ const customPluginsArray = (Array.isArray(customPlugins) ? customPlugins : []).filter((p) => p?.url);
317
+
318
+ const bridgeEntries = await injectAuthHeaders(buildLocalBridgeEntries(localPluginNames));
319
+ const customEntries = await injectAuthHeaders(buildCustomEntries(customPluginsArray));
320
+ const managedMcpServers = [...buildManagedMcpServers(pluginsArray), ...bridgeEntries, ...customEntries];
321
+
322
+ const bootstrapped = await bootstrapDeploymentMode();
323
+ const meta = await ensureMeta();
324
+ const configPath = path.join(getWriteConfigDir(), `${meta.appliedId}.json`);
325
+
326
+ const newConfig = {
327
+ ...SECURITY_RELAX,
328
+ inferenceProvider: PROVIDER,
329
+ inferenceGatewayBaseUrl: baseUrl,
330
+ inferenceGatewayApiKey: apiKey,
331
+ inferenceModels: modelsArray.map((name) => ({ name })),
332
+ };
333
+ if (managedMcpServers.length > 0) newConfig.managedMcpServers = managedMcpServers;
334
+
335
+ await fs.writeFile(configPath, JSON.stringify(newConfig, null, 2));
336
+
337
+ let skipResult = null;
338
+ try {
339
+ skipResult = await writeSkipApprovals(managedMcpServers);
340
+ } catch (e) {
341
+ logRouteError("CoworkSettings][SkipApprovals", e);
342
+ skipResult = { error: COWORK_ERROR };
343
+ }
344
+
345
+ let localMcpResult = { applied: localPluginNames, via: "3p-sse-bridge" };
346
+ try { await cleanup1pLegacy(); } catch { }
347
+
348
+ return NextResponse.json({
349
+ success: true,
350
+ bootstrapped,
351
+ message: bootstrapped
352
+ ? "Cowork enabled (3p mode set). Quit & reopen Claude Desktop."
353
+ : "Cowork settings applied. Quit & reopen Claude Desktop.",
354
+ configPath,
355
+ skipApprovals: skipResult,
356
+ localMcp: localMcpResult,
357
+ });
358
+ } catch (error) {
359
+ console.log("Error applying cowork settings:", error);
360
+ return NextResponse.json({ error: "Failed to apply cowork settings" }, { status: 500 });
361
+ }
362
+ }
363
+
364
+ export async function DELETE() {
365
+ try {
366
+ const meta = await readJson(await getMetaPath());
367
+ if (!meta?.appliedId) {
368
+ return NextResponse.json({ success: true, message: "No active config to reset" });
369
+ }
370
+ const configPath = path.join(await getConfigDir(), `${meta.appliedId}.json`);
371
+ try { await fs.writeFile(configPath, JSON.stringify({}, null, 2)); }
372
+ catch (error) { if (error.code !== "ENOENT") throw error; }
373
+ try { await writeSkipApprovals([]); } catch { }
374
+ try { await cleanup1pLegacy(); } catch { }
375
+ return NextResponse.json({ success: true, message: "Cowork config reset" });
376
+ } catch (error) {
377
+ console.log("Error resetting cowork settings:", error);
378
+ return NextResponse.json({ error: "Failed to reset cowork settings" }, { status: 500 });
379
+ }
380
+ }
@@ -0,0 +1,152 @@
1
+ "use server";
2
+
3
+ import { NextResponse } from "next/server";
4
+ import { exec } from "child_process";
5
+ import { promisify } from "util";
6
+ import fs from "fs/promises";
7
+ import path from "path";
8
+ import os from "os";
9
+ import { getCapabilitiesForModel } from "open-sse/providers/capabilities.js";
10
+ import {
11
+ applyGrokBuildConfig,
12
+ GROK_SUBAGENT_TYPES,
13
+ parseGrokBuildConfig,
14
+ resetGrokBuildConfig,
15
+ } from "@/lib/grokBuildConfig";
16
+
17
+ const execAsync = promisify(exec);
18
+
19
+ const getGrokDir = () => path.join(os.homedir(), ".grok");
20
+ const getGrokConfigPath = () => path.join(getGrokDir(), "config.toml");
21
+ const getGrokBinPath = () => path.join(getGrokDir(), "bin", "grok");
22
+
23
+ const checkGrokInstalled = async () => {
24
+ try {
25
+ const isWindows = os.platform() === "win32";
26
+ await execAsync(isWindows ? "where grok" : "which grok", { windowsHide: true });
27
+ return true;
28
+ } catch {
29
+ for (const candidate of [getGrokBinPath(), getGrokConfigPath()]) {
30
+ try {
31
+ await fs.access(candidate);
32
+ return true;
33
+ } catch { }
34
+ }
35
+ return false;
36
+ }
37
+ };
38
+
39
+ const readConfigToml = async () => {
40
+ try {
41
+ return await fs.readFile(getGrokConfigPath(), "utf-8");
42
+ } catch (error) {
43
+ if (error.code === "ENOENT") return "";
44
+ throw error;
45
+ }
46
+ };
47
+
48
+ const normalizeContextWindow = (value, model) => {
49
+ const explicit = Number(value);
50
+ if (Number.isFinite(explicit) && explicit > 0) return Math.floor(explicit);
51
+ const slash = model.indexOf("/");
52
+ const provider = slash > 0 ? model.slice(0, slash) : null;
53
+ const modelId = slash > 0 ? model.slice(slash + 1) : model;
54
+ return getCapabilitiesForModel(provider, modelId).contextWindow;
55
+ };
56
+
57
+ const normalizeSubagentModels = (value) => {
58
+ if (value === undefined) return undefined;
59
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
60
+ const result = {};
61
+ for (const type of GROK_SUBAGENT_TYPES) {
62
+ const entry = value[type];
63
+ const model = typeof entry === "string" ? entry.trim() : entry?.model?.trim();
64
+ if (!model) continue;
65
+ result[type] = {
66
+ model,
67
+ contextWindow: normalizeContextWindow(entry?.contextWindow, model),
68
+ };
69
+ }
70
+ return result;
71
+ };
72
+
73
+ const hasSwayRouterConfig = (settings) => Boolean(settings?.model?.base_url);
74
+
75
+ export async function GET() {
76
+ try {
77
+ const installed = await checkGrokInstalled();
78
+ if (!installed) {
79
+ return NextResponse.json({
80
+ installed: false,
81
+ settings: null,
82
+ message: "Grok Build is not installed",
83
+ });
84
+ }
85
+
86
+ const settings = parseGrokBuildConfig(await readConfigToml());
87
+ return NextResponse.json({
88
+ installed: true,
89
+ settings,
90
+ hasSwayRouter: hasSwayRouterConfig(settings),
91
+ configPath: getGrokConfigPath(),
92
+ });
93
+ } catch (error) {
94
+ console.log("Error checking grok-build settings:", error);
95
+ return NextResponse.json({ error: "Failed to check grok-build settings" }, { status: 500 });
96
+ }
97
+ }
98
+
99
+ export async function POST(request) {
100
+ try {
101
+ const { baseUrl, apiKey, model, contextWindow, subagentModels } = await request.json();
102
+ const selectedModel = typeof model === "string" ? model.trim() : "";
103
+ if (!baseUrl || !selectedModel) {
104
+ return NextResponse.json({ error: "baseUrl and model are required" }, { status: 400 });
105
+ }
106
+
107
+ await fs.mkdir(getGrokDir(), { recursive: true });
108
+ const normalizedBaseUrl = baseUrl.endsWith("/v1") ? baseUrl : `${baseUrl}/v1`;
109
+ const toml = applyGrokBuildConfig(await readConfigToml(), {
110
+ baseUrl: normalizedBaseUrl,
111
+ apiKey: apiKey || "sk_swayrouter",
112
+ model: selectedModel,
113
+ contextWindow: normalizeContextWindow(contextWindow, selectedModel),
114
+ subagentModels: normalizeSubagentModels(subagentModels),
115
+ });
116
+ await fs.writeFile(getGrokConfigPath(), toml);
117
+
118
+ return NextResponse.json({
119
+ success: true,
120
+ message: "Grok Build settings applied successfully!",
121
+ configPath: getGrokConfigPath(),
122
+ modelSlot: "swayrouter",
123
+ });
124
+ } catch (error) {
125
+ console.log("Error updating grok-build settings:", error);
126
+ return NextResponse.json({ error: "Failed to update grok-build settings" }, { status: 500 });
127
+ }
128
+ }
129
+
130
+ export async function DELETE() {
131
+ try {
132
+ const configPath = getGrokConfigPath();
133
+ let toml;
134
+ try {
135
+ toml = await fs.readFile(configPath, "utf-8");
136
+ } catch (error) {
137
+ if (error.code === "ENOENT") {
138
+ return NextResponse.json({ success: true, message: "No config file to reset" });
139
+ }
140
+ throw error;
141
+ }
142
+
143
+ await fs.writeFile(configPath, resetGrokBuildConfig(toml));
144
+ return NextResponse.json({
145
+ success: true,
146
+ message: "Sway Router model slots removed from Grok Build",
147
+ });
148
+ } catch (error) {
149
+ console.log("Error resetting grok-build settings:", error);
150
+ return NextResponse.json({ error: "Failed to reset grok-build settings" }, { status: 500 });
151
+ }
152
+ }
@@ -0,0 +1,169 @@
1
+ "use server";
2
+
3
+ import { NextResponse } from "next/server";
4
+ import { exec } from "child_process";
5
+ import { promisify } from "util";
6
+ import fs from "fs/promises";
7
+ import path from "path";
8
+ import os from "os";
9
+
10
+ const execAsync = promisify(exec);
11
+
12
+ const PROVIDER_NAME = "swayrouter";
13
+ const API_KEY_ENV = "OPENAI_API_KEY";
14
+
15
+ const getHermesDir = () => path.join(os.homedir(), ".hermes");
16
+ const getHermesConfigPath = () => path.join(getHermesDir(), "config.yaml");
17
+ const getHermesEnvPath = () => path.join(getHermesDir(), ".env");
18
+
19
+ const MODEL_BLOCK_RE = /^model:[ \t]*\r?\n((?:[ \t]+.*\r?\n?|[ \t]*\r?\n)*)/m;
20
+
21
+ const buildModelBlock = (model, baseUrl) =>
22
+ `model:\n default: "${model}"\n provider: "custom"\n base_url: "${baseUrl}"\n`;
23
+
24
+ const parseModelBlock = (yaml) => {
25
+ const match = yaml.match(MODEL_BLOCK_RE);
26
+ if (!match) return null;
27
+ const body = match[1] || "";
28
+ const get = (key) => {
29
+ const m = body.match(new RegExp(`^[ \\t]+${key}:[ \\t]*["']?([^"'\\r\\n]+)["']?`, "m"));
30
+ return m ? m[1].trim() : null;
31
+ };
32
+ return {
33
+ default: get("default"),
34
+ provider: get("provider"),
35
+ base_url: get("base_url"),
36
+ };
37
+ };
38
+
39
+ const upsertModelBlock = (yaml, newBlock) => {
40
+ if (MODEL_BLOCK_RE.test(yaml)) return yaml.replace(MODEL_BLOCK_RE, newBlock);
41
+ return yaml.length > 0 ? `${newBlock}\n${yaml}` : newBlock;
42
+ };
43
+
44
+ const removeModelBlock = (yaml) => yaml.replace(MODEL_BLOCK_RE, "").replace(/^\n+/, "");
45
+
46
+ const upsertEnvVar = (envText, key, value) => {
47
+ const re = new RegExp(`^${key}=.*$`, "m");
48
+ const line = `${key}=${value}`;
49
+ if (re.test(envText)) return envText.replace(re, line);
50
+ return envText.length > 0 && !envText.endsWith("\n") ? `${envText}\n${line}\n` : `${envText}${line}\n`;
51
+ };
52
+
53
+ const removeEnvVar = (envText, key) => {
54
+ const re = new RegExp(`^${key}=.*\\r?\\n?`, "m");
55
+ return envText.replace(re, "");
56
+ };
57
+
58
+ const checkHermesInstalled = async () => {
59
+ try {
60
+ const isWindows = os.platform() === "win32";
61
+ const command = isWindows ? "where hermes" : "which hermes";
62
+ await execAsync(command, { windowsHide: true });
63
+ return true;
64
+ } catch {
65
+ try {
66
+ await fs.access(getHermesConfigPath());
67
+ return true;
68
+ } catch {
69
+ return false;
70
+ }
71
+ }
72
+ };
73
+
74
+ const readConfigYaml = async () => {
75
+ try {
76
+ return await fs.readFile(getHermesConfigPath(), "utf-8");
77
+ } catch (error) {
78
+ if (error.code === "ENOENT") return "";
79
+ throw error;
80
+ }
81
+ };
82
+
83
+ const readEnvFile = async () => {
84
+ try {
85
+ return await fs.readFile(getHermesEnvPath(), "utf-8");
86
+ } catch (error) {
87
+ if (error.code === "ENOENT") return "";
88
+ throw error;
89
+ }
90
+ };
91
+
92
+ const hasSwayRouterConfig = (modelCfg) => {
93
+ if (!modelCfg?.base_url) return false;
94
+ return modelCfg.provider === "custom" && /localhost|127\.0\.0\.1|0\.0\.0\.0/.test(modelCfg.base_url);
95
+ };
96
+
97
+ export async function GET() {
98
+ try {
99
+ const installed = await checkHermesInstalled();
100
+ if (!installed) {
101
+ return NextResponse.json({ installed: false, settings: null, message: "Hermes Agent is not installed" });
102
+ }
103
+ const yaml = await readConfigYaml();
104
+ const model = parseModelBlock(yaml);
105
+ return NextResponse.json({
106
+ installed: true,
107
+ settings: { model },
108
+ hasSwayRouter: hasSwayRouterConfig(model),
109
+ configPath: getHermesConfigPath(),
110
+ });
111
+ } catch (error) {
112
+ console.log("Error checking hermes settings:", error);
113
+ return NextResponse.json({ error: "Failed to check hermes settings" }, { status: 500 });
114
+ }
115
+ }
116
+
117
+ export async function POST(request) {
118
+ try {
119
+ const { baseUrl, apiKey, model } = await request.json();
120
+ if (!baseUrl || !model) {
121
+ return NextResponse.json({ error: "baseUrl and model are required" }, { status: 400 });
122
+ }
123
+
124
+ const dir = getHermesDir();
125
+ await fs.mkdir(dir, { recursive: true });
126
+
127
+ const normalizedBaseUrl = baseUrl.endsWith("/v1") ? baseUrl : `${baseUrl}/v1`;
128
+
129
+ const existingYaml = await readConfigYaml();
130
+ const newYaml = upsertModelBlock(existingYaml, buildModelBlock(model, normalizedBaseUrl));
131
+ await fs.writeFile(getHermesConfigPath(), newYaml);
132
+
133
+ if (apiKey) {
134
+ const existingEnv = await readEnvFile();
135
+ const newEnv = upsertEnvVar(existingEnv, API_KEY_ENV, apiKey);
136
+ await fs.writeFile(getHermesEnvPath(), newEnv);
137
+ }
138
+
139
+ return NextResponse.json({
140
+ success: true,
141
+ message: "Hermes settings applied successfully!",
142
+ configPath: getHermesConfigPath(),
143
+ });
144
+ } catch (error) {
145
+ console.log("Error updating hermes settings:", error);
146
+ return NextResponse.json({ error: "Failed to update hermes settings" }, { status: 500 });
147
+ }
148
+ }
149
+
150
+ export async function DELETE() {
151
+ try {
152
+ const configPath = getHermesConfigPath();
153
+ let yaml = "";
154
+ try {
155
+ yaml = await fs.readFile(configPath, "utf-8");
156
+ } catch (error) {
157
+ if (error.code === "ENOENT") {
158
+ return NextResponse.json({ success: true, message: "No config file to reset" });
159
+ }
160
+ throw error;
161
+ }
162
+ const newYaml = removeModelBlock(yaml);
163
+ await fs.writeFile(configPath, newYaml);
164
+ return NextResponse.json({ success: true, message: `${PROVIDER_NAME} model block removed` });
165
+ } catch (error) {
166
+ console.log("Error resetting hermes settings:", error);
167
+ return NextResponse.json({ error: "Failed to reset hermes settings" }, { status: 500 });
168
+ }
169
+ }