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,23 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { DATA_DIR } from "@/lib/dataDir.js";
4
+
5
+ export const DB_DIR = path.join(DATA_DIR, "db");
6
+ export const DATA_FILE = path.join(DB_DIR, "data.sqlite");
7
+ export const BACKUPS_DIR = path.join(DB_DIR, "backups");
8
+ export const LEGACY_FILES = {
9
+ main: path.join(DATA_DIR, "db.json"),
10
+ usage: path.join(DATA_DIR, "usage.json"),
11
+ disabled: path.join(DATA_DIR, "disabledModels.json"),
12
+ details: path.join(DATA_DIR, "request-details.json"),
13
+ };
14
+ export function ensureDirs() {
15
+ for (const dir of [DATA_DIR, DB_DIR, BACKUPS_DIR]) {
16
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
17
+ if (process.platform !== "win32") {
18
+ try { fs.chmodSync(dir, 0o700); } catch (error) {
19
+ if (process.env.NODE_ENV === "production") throw error;
20
+ }
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,74 @@
1
+ import { getAdapter } from "../driver.js";
2
+
3
+ export const LOCK_MODEL_ALL = "__all";
4
+
5
+ export function lockModelId(model) {
6
+ return model ? String(model) : LOCK_MODEL_ALL;
7
+ }
8
+
9
+ export async function recordLock(connectionId, model, { tier, reason, expiresAt } = {}) {
10
+ if (!connectionId) return;
11
+ const db = await getAdapter();
12
+ const modelId = lockModelId(model);
13
+ const now = new Date().toISOString();
14
+ db.run(
15
+ `INSERT INTO account_model_locks(connectionId, modelId, tier, reason, expiresAt, createdAt, updatedAt)
16
+ VALUES(?, ?, ?, ?, ?, ?, ?)
17
+ ON CONFLICT(connectionId, modelId) DO UPDATE SET
18
+ tier = excluded.tier, reason = excluded.reason,
19
+ expiresAt = excluded.expiresAt, updatedAt = excluded.updatedAt`,
20
+ [connectionId, modelId, tier || null, reason || null, expiresAt, now, now]
21
+ );
22
+ }
23
+
24
+ export async function clearLock(connectionId, model) {
25
+ if (!connectionId) return;
26
+ const db = await getAdapter();
27
+ db.run(`DELETE FROM account_model_locks WHERE connectionId = ? AND modelId = ?`,
28
+ [connectionId, lockModelId(model)]);
29
+ }
30
+
31
+ export async function clearAllLocksForConnection(connectionId) {
32
+ if (!connectionId) return;
33
+ const db = await getAdapter();
34
+ db.run(`DELETE FROM account_model_locks WHERE connectionId = ?`, [connectionId]);
35
+ }
36
+
37
+ export async function getActiveLocks(filter = {}) {
38
+ const db = await getAdapter();
39
+ const now = new Date().toISOString();
40
+ const where = ["expiresAt > ?"];
41
+ const params = [now];
42
+ if (filter.connectionId) { where.push("connectionId = ?"); params.push(filter.connectionId); }
43
+ if (filter.model !== undefined) { where.push("modelId = ?"); params.push(lockModelId(filter.model)); }
44
+ const rows = db.all(
45
+ `SELECT connectionId, modelId, tier, reason, expiresAt FROM account_model_locks WHERE ${where.join(" AND ")} ORDER BY expiresAt ASC`,
46
+ params
47
+ );
48
+ return rows || [];
49
+ }
50
+
51
+ export async function isLocked(connectionId, model) {
52
+ const db = await getAdapter();
53
+ const now = new Date().toISOString();
54
+
55
+ const row = db.get(
56
+ `SELECT 1 FROM account_model_locks
57
+ WHERE connectionId = ? AND modelId IN (?, ?) AND expiresAt > ? LIMIT 1`,
58
+ [connectionId, lockModelId(model), LOCK_MODEL_ALL, now]
59
+ );
60
+ return !!row;
61
+ }
62
+
63
+ export async function countActiveLocks() {
64
+ const db = await getAdapter();
65
+ const now = new Date().toISOString();
66
+ const row = db.get(`SELECT COUNT(*) AS c FROM account_model_locks WHERE expiresAt > ?`, [now]);
67
+ return row?.c || 0;
68
+ }
69
+
70
+ export async function reapExpired() {
71
+ const db = await getAdapter();
72
+ const now = new Date().toISOString();
73
+ db.run(`DELETE FROM account_model_locks WHERE expiresAt <= ?`, [now]);
74
+ }
@@ -0,0 +1,108 @@
1
+ import { getAdapter } from "../driver.js";
2
+ import { parseJson, stringifyJson } from "../helpers/jsonCol.js";
3
+ import { makeKv } from "../helpers/kvStore.js";
4
+ import { getConfigCache, bumpConfigCacheVersion } from "../../cache/ttlCache.js";
5
+
6
+ const customKv = makeKv("customModels");
7
+
8
+ const customCache = getConfigCache("customModels", { ttlMs: 5000 });
9
+
10
+ function isClinePassProvider(providerAlias) {
11
+ const value = String(providerAlias || "").trim().toLowerCase();
12
+ return value === "clinepass" || value === "cline-pass";
13
+ }
14
+
15
+ function canonicalModelId(providerAlias, id) {
16
+ const value = String(id || "").trim();
17
+ if (!isClinePassProvider(providerAlias)) return value;
18
+ return value.replace(/^(?:clinepass|cline-pass)\//i, "");
19
+ }
20
+
21
+ function canonicalProviderAlias(providerAlias) {
22
+ return isClinePassProvider(providerAlias) ? "clinepass" : String(providerAlias || "").trim();
23
+ }
24
+
25
+ function customKey(providerAlias, id, type) {
26
+ return `${canonicalProviderAlias(providerAlias)}|${canonicalModelId(providerAlias, id)}|${type}`;
27
+ }
28
+
29
+ function legacyCustomKeys(providerAlias, id, type) {
30
+ const providerValue = String(providerAlias || "").trim();
31
+ const provider = canonicalProviderAlias(providerValue);
32
+ const value = String(id || "").trim();
33
+ const canonical = canonicalModelId(providerValue, value);
34
+ const keys = new Set([
35
+ customKey(provider, canonical, type),
36
+ `${provider}|${canonical}|${type}`,
37
+ `${providerValue}|${value}|${type}`,
38
+ ]);
39
+ if (isClinePassProvider(providerValue)) {
40
+ keys.add(`${provider}|cline-pass/${canonical}|${type}`);
41
+ keys.add(`${provider}|clinepass/${canonical}|${type}`);
42
+ keys.add(`cline-pass|${canonical}|${type}`);
43
+ keys.add(`cline-pass|cline-pass/${canonical}|${type}`);
44
+ keys.add(`cline-pass|clinepass/${canonical}|${type}`);
45
+ }
46
+ return [...keys];
47
+ }
48
+
49
+ export async function getCustomModels() {
50
+ const all = await customCache.get("all", () => customKv.getAll());
51
+ const deduped = new Map();
52
+ for (const raw of Object.values(all)) {
53
+ if (!raw?.id || !raw?.providerAlias) continue;
54
+ const providerAlias = canonicalProviderAlias(raw.providerAlias);
55
+ const id = canonicalModelId(providerAlias, raw.id);
56
+ const type = raw.type || "llm";
57
+ const key = `${providerAlias}|${id}|${type}`;
58
+ const existing = deduped.get(key);
59
+ if (!existing) {
60
+ deduped.set(key, { ...raw, providerAlias, id, type });
61
+ } else if (!existing.capabilities && raw.capabilities) {
62
+ deduped.set(key, { ...existing, capabilities: raw.capabilities });
63
+ }
64
+ }
65
+ return [...deduped.values()];
66
+ }
67
+
68
+ export async function addCustomModel({ providerAlias, id, type = "llm", name, capabilities }) {
69
+ const provider = canonicalProviderAlias(providerAlias);
70
+ const modelId = canonicalModelId(provider, id);
71
+ const key = customKey(provider, modelId, type);
72
+ const db = await getAdapter();
73
+ let changed = false;
74
+ db.transaction(() => {
75
+ const existing = legacyCustomKeys(provider, id, type)
76
+ .map((candidate) => db.get(`SELECT key, value FROM kv WHERE scope = 'customModels' AND key = ?`, [candidate]))
77
+ .find(Boolean);
78
+ const parsedExisting = existing ? parseJson(existing.value, {}) : {};
79
+ const value = stringifyJson({
80
+ ...parsedExisting,
81
+ providerAlias: provider,
82
+ id: modelId,
83
+ type,
84
+ name: name || parsedExisting.name || modelId,
85
+ ...(capabilities && typeof capabilities === "object" ? { capabilities } : {}),
86
+ });
87
+ if (existing) {
88
+ if (existing.key !== key) db.run(`DELETE FROM kv WHERE scope = 'customModels' AND key = ?`, [key]);
89
+ if (existing.key !== key || value !== existing.value) {
90
+ db.run(`UPDATE kv SET key = ?, value = ? WHERE scope = 'customModels' AND key = ?`, [key, value, existing.key]);
91
+ changed = true;
92
+ }
93
+ return;
94
+ }
95
+ db.run(`INSERT INTO kv(scope, key, value) VALUES('customModels', ?, ?)`, [key, value]);
96
+ changed = true;
97
+ });
98
+ if (changed) await bumpConfigCacheVersion().catch(() => {});
99
+ return changed;
100
+ }
101
+
102
+ export async function deleteCustomModel({ providerAlias, id, type = "llm" }) {
103
+ const db = await getAdapter();
104
+ for (const key of legacyCustomKeys(providerAlias, id, type)) {
105
+ db.run(`DELETE FROM kv WHERE scope = 'customModels' AND key = ?`, [key]);
106
+ }
107
+ await bumpConfigCacheVersion().catch(() => {});
108
+ }
@@ -0,0 +1,204 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { getAdapter } from "../driver.js";
3
+ import { getConfigCache, bumpConfigCacheVersion } from "../../cache/ttlCache.js";
4
+
5
+ const apiKeysCache = getConfigCache("apiKeys", { ttlMs: 5000 });
6
+ let defaultApiKeyPromise = null;
7
+
8
+ async function readAllKeys() {
9
+ const db = await getAdapter();
10
+ await ensureDefaultApiKey(db);
11
+ const rows = db.all(`SELECT * FROM apiKeys ORDER BY isDefault DESC, createdAt ASC`);
12
+ return rows.map(rowToKey);
13
+ }
14
+
15
+ async function ensureDefaultApiKey(db) {
16
+ const existing = db.get(`SELECT id FROM apiKeys WHERE isDefault = 1 ORDER BY createdAt ASC LIMIT 1`);
17
+ if (existing?.id) {
18
+ db.run(`UPDATE apiKeys SET isDefault = 0 WHERE id <> ? AND isDefault = 1`, [existing.id]);
19
+ return existing.id;
20
+ }
21
+ const first = db.get(`SELECT id FROM apiKeys ORDER BY createdAt ASC LIMIT 1`);
22
+ if (first?.id) {
23
+ db.run(`UPDATE apiKeys SET isDefault = 0`);
24
+ db.run(`UPDATE apiKeys SET isDefault = 1 WHERE id = ?`, [first.id]);
25
+ return first.id;
26
+ }
27
+
28
+ if (!defaultApiKeyPromise) {
29
+ defaultApiKeyPromise = (async () => {
30
+
31
+ const currentDefault = db.get(`SELECT id FROM apiKeys WHERE isDefault = 1 ORDER BY createdAt ASC LIMIT 1`);
32
+ if (currentDefault?.id) return currentDefault.id;
33
+ const currentFirst = db.get(`SELECT id FROM apiKeys ORDER BY createdAt ASC LIMIT 1`);
34
+ if (currentFirst?.id) {
35
+ db.run(`UPDATE apiKeys SET isDefault = 0`);
36
+ db.run(`UPDATE apiKeys SET isDefault = 1 WHERE id = ?`, [currentFirst.id]);
37
+ return currentFirst.id;
38
+ }
39
+
40
+ const [{ getConsistentMachineId }, { generateApiKeyWithMachine }] = await Promise.all([
41
+ import("@/shared/utils/machineId"),
42
+ import("@/shared/utils/apiKey"),
43
+ ]);
44
+ const machineId = await getConsistentMachineId();
45
+ const generated = generateApiKeyWithMachine(machineId);
46
+ const id = uuidv4();
47
+ const createdAt = new Date().toISOString();
48
+ db.run(
49
+ `INSERT INTO apiKeys(id, key, name, machineId, isActive, isDefault, createdAt) VALUES(?, ?, ?, ?, ?, ?, ?)`,
50
+ [id, generated.key, "Primary", machineId, 1, 1, createdAt]
51
+ );
52
+ return id;
53
+ })().finally(() => {
54
+ defaultApiKeyPromise = null;
55
+ });
56
+ }
57
+
58
+ return defaultApiKeyPromise;
59
+ }
60
+
61
+ async function readKeyMap() {
62
+
63
+ const db = await getAdapter();
64
+ const rows = db.all(`SELECT key, isActive FROM apiKeys`);
65
+ const map = {};
66
+ for (const r of rows) map[r.key] = r.isActive === 1 || r.isActive === true;
67
+ return map;
68
+ }
69
+
70
+ function rowToKey(row, includeSecret = false) {
71
+ if (!row) return null;
72
+ const result = {
73
+ id: row.id,
74
+ name: row.name,
75
+ machineId: row.machineId,
76
+ prefix: maskApiKeyPrefix(row.key),
77
+ isActive: row.isActive === 1 || row.isActive === true,
78
+ isDefault: row.isDefault === 1 || row.isDefault === true,
79
+ createdAt: row.createdAt,
80
+ };
81
+ if (includeSecret) result.key = row.key;
82
+ return result;
83
+ }
84
+
85
+ function maskApiKeyPrefix(key) {
86
+ const trimmed = typeof key === "string" ? key.trim() : "";
87
+ if (!trimmed) return undefined;
88
+ const match = trimmed.match(/^[^-]+-/);
89
+ return `${match?.[0] || trimmed.slice(0, 3)}••••`;
90
+ }
91
+
92
+ export function mergeApiKeyUpdate(row, data = {}) {
93
+ return {
94
+ key: row.key,
95
+ name: data.name !== undefined ? data.name : row.name,
96
+ machineId: data.machineId !== undefined ? data.machineId : row.machineId,
97
+ isActive: data.isActive !== undefined ? data.isActive : row.isActive === 1 || row.isActive === true,
98
+ };
99
+ }
100
+
101
+ async function readActiveKey() {
102
+ const db = await getAdapter();
103
+ await ensureDefaultApiKey(db);
104
+ const row = db.get(`SELECT key FROM apiKeys WHERE isActive = 1 ORDER BY isDefault DESC, createdAt ASC LIMIT 1`);
105
+ return row?.key || null;
106
+ }
107
+
108
+ export async function getActiveApiKey() {
109
+ return await apiKeysCache.get("active", readActiveKey);
110
+ }
111
+
112
+ export async function getApiKeySecretById(id) {
113
+ const db = await getAdapter();
114
+ const row = db.get(`SELECT key FROM apiKeys WHERE id = ?`, [id]);
115
+ return row?.key || null;
116
+ }
117
+
118
+ export async function getApiKeys() {
119
+ return await apiKeysCache.get("all", readAllKeys);
120
+ }
121
+
122
+ export async function getApiKeyById(id) {
123
+ const db = await getAdapter();
124
+ await ensureDefaultApiKey(db);
125
+ const row = db.get(`SELECT * FROM apiKeys WHERE id = ?`, [id]);
126
+ return rowToKey(row);
127
+ }
128
+
129
+ export async function createApiKey(name, machineId) {
130
+ if (!machineId) throw new Error("machineId is required");
131
+ const db = await getAdapter();
132
+ await ensureDefaultApiKey(db);
133
+ const { generateApiKeyWithMachine } = await import("@/shared/utils/apiKey");
134
+ const result = generateApiKeyWithMachine(machineId);
135
+ const isDefault = !db.get(`SELECT id FROM apiKeys WHERE isDefault = 1 LIMIT 1`);
136
+ const apiKey = {
137
+ id: uuidv4(),
138
+ name,
139
+ key: result.key,
140
+ machineId,
141
+ isActive: true,
142
+ isDefault,
143
+ createdAt: new Date().toISOString(),
144
+ };
145
+ db.run(
146
+ `INSERT INTO apiKeys(id, key, name, machineId, isActive, isDefault, createdAt) VALUES(?, ?, ?, ?, ?, ?, ?)`,
147
+ [apiKey.id, apiKey.key, apiKey.name, apiKey.machineId, 1, isDefault ? 1 : 0, apiKey.createdAt]
148
+ );
149
+ await bumpConfigCacheVersion().catch(() => {});
150
+ return apiKey;
151
+ }
152
+
153
+ export async function updateApiKey(id, data) {
154
+ const db = await getAdapter();
155
+ await ensureDefaultApiKey(db);
156
+ let result = null;
157
+ db.transaction(() => {
158
+ const row = db.get(`SELECT * FROM apiKeys WHERE id = ?`, [id]);
159
+ if (!row) return;
160
+
161
+ const merged = mergeApiKeyUpdate(row, data);
162
+ db.run(
163
+ `UPDATE apiKeys SET key = ?, name = ?, machineId = ?, isActive = ? WHERE id = ?`,
164
+ [merged.key, merged.name, merged.machineId, merged.isActive ? 1 : 0, id]
165
+ );
166
+ result = rowToKey({ ...row, ...merged });
167
+ });
168
+ if (result) await bumpConfigCacheVersion().catch(() => {});
169
+ return result;
170
+ }
171
+
172
+ export async function deleteApiKey(id) {
173
+ const db = await getAdapter();
174
+ await ensureDefaultApiKey(db);
175
+ const row = db.get(`SELECT isDefault FROM apiKeys WHERE id = ?`, [id]);
176
+ if (!row) return false;
177
+ if (row.isDefault === 1 || row.isDefault === true) {
178
+ const error = new Error("The default API key cannot be deleted. Revoke or rotate it instead.");
179
+ error.code = "DEFAULT_API_KEY";
180
+ throw error;
181
+ }
182
+ const res = db.run(`DELETE FROM apiKeys WHERE id = ?`, [id]);
183
+ const deleted = (res?.changes ?? 0) > 0;
184
+ if (deleted) await bumpConfigCacheVersion().catch(() => {});
185
+ return deleted;
186
+ }
187
+
188
+ export async function rotateApiKey(id) {
189
+ const db = await getAdapter();
190
+ const row = db.get(`SELECT * FROM apiKeys WHERE id = ?`, [id]);
191
+ if (!row) return null;
192
+ if (!row.machineId) throw new Error("This API key has no machine id and cannot be rotated.");
193
+ const { generateApiKeyWithMachine } = await import("@/shared/utils/apiKey");
194
+ const generated = generateApiKeyWithMachine(row.machineId);
195
+ db.run(`UPDATE apiKeys SET key = ? WHERE id = ?`, [generated.key, id]);
196
+ await bumpConfigCacheVersion().catch(() => {});
197
+ return rowToKey({ ...row, key: generated.key }, true);
198
+ }
199
+
200
+ export async function validateApiKey(key) {
201
+ if (!key) return false;
202
+ const map = await apiKeysCache.get("map", readKeyMap);
203
+ return !!map[key];
204
+ }
@@ -0,0 +1,85 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { getAdapter } from "../driver.js";
3
+ import { parseJson, stringifyJson } from "../helpers/jsonCol.js";
4
+ import { getConfigCache, bumpConfigCacheVersion } from "../../cache/ttlCache.js";
5
+
6
+ const combosCache = getConfigCache("combos", { ttlMs: 5000 });
7
+
8
+ async function readAllCombos() {
9
+ const db = await getAdapter();
10
+ const rows = db.all(`SELECT * FROM combos ORDER BY createdAt ASC`);
11
+ return rows.map(rowToCombo);
12
+ }
13
+
14
+ function rowToCombo(row) {
15
+ if (!row) return null;
16
+ return {
17
+ id: row.id,
18
+ name: row.name,
19
+ kind: row.kind,
20
+ models: parseJson(row.models, []),
21
+ createdAt: row.createdAt,
22
+ updatedAt: row.updatedAt,
23
+ };
24
+ }
25
+
26
+ export async function getCombos() {
27
+ return await combosCache.get("all", readAllCombos);
28
+ }
29
+
30
+ export async function getComboById(id) {
31
+ const db = await getAdapter();
32
+ const row = db.get(`SELECT * FROM combos WHERE id = ?`, [id]);
33
+ return rowToCombo(row);
34
+ }
35
+
36
+ export async function getComboByName(name) {
37
+ if (!name) return null;
38
+
39
+ const all = await getCombos();
40
+ return all.find((c) => c.name === name) ?? null;
41
+ }
42
+
43
+ export async function createCombo(data) {
44
+ const db = await getAdapter();
45
+ const now = new Date().toISOString();
46
+ const combo = {
47
+ id: uuidv4(),
48
+ name: data.name,
49
+ kind: data.kind || null,
50
+ models: data.models || [],
51
+ createdAt: now,
52
+ updatedAt: now,
53
+ };
54
+ db.run(
55
+ `INSERT INTO combos(id, name, kind, models, createdAt, updatedAt) VALUES(?, ?, ?, ?, ?, ?)`,
56
+ [combo.id, combo.name, combo.kind, stringifyJson(combo.models), combo.createdAt, combo.updatedAt]
57
+ );
58
+ await bumpConfigCacheVersion().catch(() => {});
59
+ return combo;
60
+ }
61
+
62
+ export async function updateCombo(id, data) {
63
+ const db = await getAdapter();
64
+ let result = null;
65
+ db.transaction(() => {
66
+ const row = db.get(`SELECT * FROM combos WHERE id = ?`, [id]);
67
+ if (!row) return;
68
+ const merged = { ...rowToCombo(row), ...data, updatedAt: new Date().toISOString() };
69
+ db.run(
70
+ `UPDATE combos SET name = ?, kind = ?, models = ?, updatedAt = ? WHERE id = ?`,
71
+ [merged.name, merged.kind, stringifyJson(merged.models || []), merged.updatedAt, id]
72
+ );
73
+ result = merged;
74
+ });
75
+ if (result) await bumpConfigCacheVersion().catch(() => {});
76
+ return result;
77
+ }
78
+
79
+ export async function deleteCombo(id) {
80
+ const db = await getAdapter();
81
+ const res = db.run(`DELETE FROM combos WHERE id = ?`, [id]);
82
+ const deleted = (res?.changes ?? 0) > 0;
83
+ if (deleted) await bumpConfigCacheVersion().catch(() => {});
84
+ return deleted;
85
+ }