vansrouter 0.91.21 → 0.91.22

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 (626) hide show
  1. package/app/.next-cli-build/BUILD_ID +1 -1
  2. package/app/.next-cli-build/app-path-routes-manifest.json +17 -17
  3. package/app/.next-cli-build/build-manifest.json +3 -3
  4. package/app/.next-cli-build/prerender-manifest.json +3 -3
  5. package/app/.next-cli-build/react-loadable-manifest.json +6 -6
  6. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
  7. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  8. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
  9. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  10. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  11. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  12. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
  13. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  14. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
  15. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  16. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  17. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  18. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js.nft.json +1 -1
  19. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  20. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js.nft.json +1 -1
  21. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  22. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js.nft.json +1 -1
  23. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  24. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page.js.nft.json +1 -1
  25. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  26. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
  27. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  28. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  29. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  30. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
  31. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  32. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
  33. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  34. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
  35. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  36. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
  37. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  38. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-fitness/page.js.nft.json +1 -1
  39. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-fitness/page_client-reference-manifest.js +1 -1
  40. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
  41. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  42. package/app/.next-cli-build/server/app/(dashboard)/dashboard/pxpipe/page.js.nft.json +1 -1
  43. package/app/.next-cli-build/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
  44. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
  45. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  46. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page.js.nft.json +1 -1
  47. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  48. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page.js.nft.json +1 -1
  49. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  50. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
  51. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  52. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
  53. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  54. package/app/.next-cli-build/server/app/_global-error/page.js.nft.json +1 -1
  55. package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  56. package/app/.next-cli-build/server/app/_global-error.html +1 -1
  57. package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  58. package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  59. package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  60. package/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  61. package/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
  62. package/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
  63. package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  64. package/app/.next-cli-build/server/app/_not-found/page.js.nft.json +1 -1
  65. package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  66. package/app/.next-cli-build/server/app/_not-found.html +1 -1
  67. package/app/.next-cli-build/server/app/_not-found.rsc +3 -3
  68. package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +3 -3
  69. package/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
  70. package/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +3 -3
  71. package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  72. package/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  73. package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  74. package/app/.next-cli-build/server/app/api/auth/check/route.js.nft.json +1 -1
  75. package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
  76. package/app/.next-cli-build/server/app/api/auth/logout/route.js +1 -1
  77. package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
  78. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js +1 -1
  79. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
  80. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js +1 -1
  81. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
  82. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js +1 -1
  83. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
  84. package/app/.next-cli-build/server/app/api/auth/reset-password/route.js.nft.json +1 -1
  85. package/app/.next-cli-build/server/app/api/auth/status/route.js +1 -1
  86. package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
  87. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js +5 -5
  88. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
  89. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js +1 -1
  90. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
  91. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
  92. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js +2 -2
  93. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js.nft.json +1 -1
  94. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js +2 -2
  95. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js.nft.json +1 -1
  96. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js +1 -1
  97. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js.nft.json +1 -1
  98. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js +1 -1
  99. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
  100. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js +2 -2
  101. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js.nft.json +1 -1
  102. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js +2 -2
  103. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js.nft.json +1 -1
  104. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js +1 -1
  105. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
  106. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js +1 -1
  107. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js.nft.json +1 -1
  108. package/app/.next-cli-build/server/app/api/cli-tools/devin-settings/route.js +2 -2
  109. package/app/.next-cli-build/server/app/api/cli-tools/devin-settings/route.js.nft.json +1 -1
  110. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js +1 -1
  111. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js.nft.json +1 -1
  112. package/app/.next-cli-build/server/app/api/cli-tools/grok-build-settings/route.js +1 -1
  113. package/app/.next-cli-build/server/app/api/cli-tools/grok-build-settings/route.js.nft.json +1 -1
  114. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js +2 -2
  115. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js.nft.json +1 -1
  116. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js +1 -1
  117. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js.nft.json +1 -1
  118. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js +2 -2
  119. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js.nft.json +1 -1
  120. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
  121. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js.nft.json +1 -1
  122. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js +1 -1
  123. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js.nft.json +1 -1
  124. package/app/.next-cli-build/server/app/api/combos/[id]/route.js +1 -1
  125. package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
  126. package/app/.next-cli-build/server/app/api/combos/route.js +1 -1
  127. package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
  128. package/app/.next-cli-build/server/app/api/headroom/extras/route.js.nft.json +1 -1
  129. package/app/.next-cli-build/server/app/api/headroom/proxy/[...path]/route.js.nft.json +1 -1
  130. package/app/.next-cli-build/server/app/api/headroom/restart/route.js.nft.json +1 -1
  131. package/app/.next-cli-build/server/app/api/headroom/start/route.js.nft.json +1 -1
  132. package/app/.next-cli-build/server/app/api/headroom/status/route.js.nft.json +1 -1
  133. package/app/.next-cli-build/server/app/api/headroom/stop/route.js.nft.json +1 -1
  134. package/app/.next-cli-build/server/app/api/health/route.js.nft.json +1 -1
  135. package/app/.next-cli-build/server/app/api/init/route.js.nft.json +1 -1
  136. package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
  137. package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
  138. package/app/.next-cli-build/server/app/api/locale/route.js.nft.json +1 -1
  139. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
  140. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
  141. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
  142. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
  143. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
  144. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
  145. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route.js +1 -1
  146. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route.js.nft.json +1 -1
  147. package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
  148. package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
  149. package/app/.next-cli-build/server/app/api/models/catalog-sync/route.js.nft.json +1 -1
  150. package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
  151. package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
  152. package/app/.next-cli-build/server/app/api/models/route.js +1 -1
  153. package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
  154. package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
  155. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js +1 -1
  156. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  157. package/app/.next-cli-build/server/app/api/oauth/codex/bulk-import/route.js +1 -1
  158. package/app/.next-cli-build/server/app/api/oauth/codex/bulk-import/route.js.nft.json +1 -1
  159. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js +1 -1
  160. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
  161. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  162. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  163. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
  164. package/app/.next-cli-build/server/app/api/oauth/grok-cli/bulk-import/route.js.nft.json +1 -1
  165. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
  166. package/app/.next-cli-build/server/app/api/oauth/kiro/api-key/route.js.nft.json +1 -1
  167. package/app/.next-cli-build/server/app/api/oauth/kiro/auto-import/route.js.nft.json +1 -1
  168. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  169. package/app/.next-cli-build/server/app/api/oauth/kiro/import-cli-proxy/route.js.nft.json +1 -1
  170. package/app/.next-cli-build/server/app/api/oauth/kiro/social-authorize/route.js.nft.json +1 -1
  171. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  172. package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
  173. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
  174. package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
  175. package/app/.next-cli-build/server/app/api/provider-nodes/validate/route.js.nft.json +1 -1
  176. package/app/.next-cli-build/server/app/api/providers/[id]/gcp-projects/route.js.nft.json +1 -1
  177. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js +1 -1
  178. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  179. package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
  180. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js +1 -1
  181. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  182. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  183. package/app/.next-cli-build/server/app/api/providers/bulk/route.js +1 -1
  184. package/app/.next-cli-build/server/app/api/providers/bulk/route.js.nft.json +1 -1
  185. package/app/.next-cli-build/server/app/api/providers/circuit-breakers/[name]/reset/route.js.nft.json +1 -1
  186. package/app/.next-cli-build/server/app/api/providers/circuit-breakers/route.js.nft.json +1 -1
  187. package/app/.next-cli-build/server/app/api/providers/client/route.js +1 -1
  188. package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
  189. package/app/.next-cli-build/server/app/api/providers/kilo/free-models/route.js.nft.json +1 -1
  190. package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  191. package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
  192. package/app/.next-cli-build/server/app/api/providers/suggested-models/route.js.nft.json +1 -1
  193. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js +1 -1
  194. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  195. package/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
  196. package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
  197. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/fitness/clear/route.js +1 -1
  198. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/fitness/clear/route.js.nft.json +1 -1
  199. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js +1 -1
  200. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
  201. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js +1 -1
  202. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
  203. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js +1 -1
  204. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
  205. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js +1 -1
  206. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
  207. package/app/.next-cli-build/server/app/api/proxy-pools/fitness/clear-all/route.js +1 -1
  208. package/app/.next-cli-build/server/app/api/proxy-pools/fitness/clear-all/route.js.nft.json +1 -1
  209. package/app/.next-cli-build/server/app/api/proxy-pools/fitness/route.js +1 -1
  210. package/app/.next-cli-build/server/app/api/proxy-pools/fitness/route.js.nft.json +1 -1
  211. package/app/.next-cli-build/server/app/api/proxy-pools/route.js +1 -1
  212. package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
  213. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js +1 -1
  214. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
  215. package/app/.next-cli-build/server/app/api/pxpipe/health/route.js.nft.json +1 -1
  216. package/app/.next-cli-build/server/app/api/pxpipe/install/route.js.nft.json +1 -1
  217. package/app/.next-cli-build/server/app/api/pxpipe/logs/route.js.nft.json +1 -1
  218. package/app/.next-cli-build/server/app/api/pxpipe/restart/route.js.nft.json +1 -1
  219. package/app/.next-cli-build/server/app/api/pxpipe/start/route.js.nft.json +1 -1
  220. package/app/.next-cli-build/server/app/api/pxpipe/stats/route.js.nft.json +1 -1
  221. package/app/.next-cli-build/server/app/api/pxpipe/status/route.js.nft.json +1 -1
  222. package/app/.next-cli-build/server/app/api/pxpipe/stop/route.js.nft.json +1 -1
  223. package/app/.next-cli-build/server/app/api/settings/database/route.js +1 -1
  224. package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
  225. package/app/.next-cli-build/server/app/api/settings/proxy-test/route.js.nft.json +1 -1
  226. package/app/.next-cli-build/server/app/api/settings/require-login/route.js.nft.json +1 -1
  227. package/app/.next-cli-build/server/app/api/settings/route.js +1 -1
  228. package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
  229. package/app/.next-cli-build/server/app/api/shutdown/route.js.nft.json +1 -1
  230. package/app/.next-cli-build/server/app/api/tags/route.js.nft.json +1 -1
  231. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js.nft.json +1 -1
  232. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js.nft.json +1 -1
  233. package/app/.next-cli-build/server/app/api/translator/load/route.js.nft.json +1 -1
  234. package/app/.next-cli-build/server/app/api/translator/save/route.js.nft.json +1 -1
  235. package/app/.next-cli-build/server/app/api/translator/send/route.js +1 -1
  236. package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
  237. package/app/.next-cli-build/server/app/api/translator/translate/route.js +1 -1
  238. package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
  239. package/app/.next-cli-build/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  240. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  241. package/app/.next-cli-build/server/app/api/tunnel/status/route.js.nft.json +1 -1
  242. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js.nft.json +1 -1
  243. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
  244. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
  245. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js +2 -2
  246. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js.nft.json +1 -1
  247. package/app/.next-cli-build/server/app/api/usage/[connectionId]/codex-reset-credits/route.js +1 -1
  248. package/app/.next-cli-build/server/app/api/usage/[connectionId]/codex-reset-credits/route.js.nft.json +1 -1
  249. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js +1 -1
  250. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  251. package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
  252. package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
  253. package/app/.next-cli-build/server/app/api/usage/logs/route.js.nft.json +1 -1
  254. package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
  255. package/app/.next-cli-build/server/app/api/usage/request-details/[id]/route.js.nft.json +1 -1
  256. package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
  257. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
  258. package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
  259. package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
  260. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js +1 -1
  261. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  262. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js +1 -1
  263. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  264. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js +1 -1
  265. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  266. package/app/.next-cli-build/server/app/api/v1/audio/voices/route.js.nft.json +1 -1
  267. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js +1 -1
  268. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  269. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js +1 -1
  270. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  271. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js +2 -2
  272. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  273. package/app/.next-cli-build/server/app/api/v1/messages/count_tokens/route.js.nft.json +1 -1
  274. package/app/.next-cli-build/server/app/api/v1/messages/route.js +1 -1
  275. package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
  276. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js +1 -1
  277. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
  278. package/app/.next-cli-build/server/app/api/v1/models/info/route.js.nft.json +1 -1
  279. package/app/.next-cli-build/server/app/api/v1/models/route.js +1 -1
  280. package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
  281. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js +1 -1
  282. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
  283. package/app/.next-cli-build/server/app/api/v1/responses/route.js +1 -1
  284. package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
  285. package/app/.next-cli-build/server/app/api/v1/route.js +1 -1
  286. package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
  287. package/app/.next-cli-build/server/app/api/v1/search/route.js +1 -1
  288. package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
  289. package/app/.next-cli-build/server/app/api/v1/videos/[id]/route.js +1 -1
  290. package/app/.next-cli-build/server/app/api/v1/videos/[id]/route.js.nft.json +1 -1
  291. package/app/.next-cli-build/server/app/api/v1/videos/edits/route.js +1 -1
  292. package/app/.next-cli-build/server/app/api/v1/videos/edits/route.js.nft.json +1 -1
  293. package/app/.next-cli-build/server/app/api/v1/videos/extensions/route.js +1 -1
  294. package/app/.next-cli-build/server/app/api/v1/videos/extensions/route.js.nft.json +1 -1
  295. package/app/.next-cli-build/server/app/api/v1/videos/generations/route.js +1 -1
  296. package/app/.next-cli-build/server/app/api/v1/videos/generations/route.js.nft.json +1 -1
  297. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js +1 -1
  298. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
  299. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js +1 -1
  300. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  301. package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
  302. package/app/.next-cli-build/server/app/api/version/route.js +1 -1
  303. package/app/.next-cli-build/server/app/api/version/route.js.nft.json +1 -1
  304. package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
  305. package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
  306. package/app/.next-cli-build/server/app/callback/page.js.nft.json +1 -1
  307. package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  308. package/app/.next-cli-build/server/app/callback.html +1 -1
  309. package/app/.next-cli-build/server/app/callback.rsc +3 -3
  310. package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +3 -3
  311. package/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
  312. package/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +3 -3
  313. package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
  314. package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  315. package/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
  316. package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
  317. package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +5 -5
  318. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
  319. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
  320. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  321. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  322. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +5 -5
  323. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
  324. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
  325. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
  326. package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
  327. package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +6 -6
  328. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  329. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  330. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  331. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  332. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +6 -6
  333. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  334. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
  335. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
  336. package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
  337. package/app/.next-cli-build/server/app/dashboard/combos.rsc +5 -5
  338. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  339. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  340. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  341. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  342. package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
  343. package/app/.next-cli-build/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  344. package/app/.next-cli-build/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
  345. package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
  346. package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
  347. package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +6 -6
  348. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  349. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  350. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  351. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  352. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +6 -6
  353. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  354. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
  355. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
  356. package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
  357. package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +5 -5
  358. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
  359. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
  360. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
  361. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  362. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  363. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +5 -5
  364. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
  365. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +3 -3
  366. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
  367. package/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
  368. package/app/.next-cli-build/server/app/dashboard/mitm.rsc +5 -5
  369. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  370. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  371. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  372. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  373. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
  374. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  375. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
  376. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
  377. package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
  378. package/app/.next-cli-build/server/app/dashboard/profile.rsc +5 -5
  379. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  380. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  381. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  382. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  383. package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
  384. package/app/.next-cli-build/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  385. package/app/.next-cli-build/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
  386. package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
  387. package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
  388. package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +5 -5
  389. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  390. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  391. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  392. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  393. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  394. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
  395. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  396. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
  397. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
  398. package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
  399. package/app/.next-cli-build/server/app/dashboard/providers.rsc +5 -5
  400. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  401. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  402. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  403. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  404. package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
  405. package/app/.next-cli-build/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  406. package/app/.next-cli-build/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
  407. package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
  408. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.html +1 -1
  409. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.rsc +5 -5
  410. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/!KGRhc2hib2FyZCk/dashboard/proxy-fitness/__PAGE__.segment.rsc +2 -2
  411. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/!KGRhc2hib2FyZCk/dashboard/proxy-fitness.segment.rsc +1 -1
  412. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  413. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  414. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/_full.segment.rsc +5 -5
  415. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/_head.segment.rsc +1 -1
  416. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/_index.segment.rsc +3 -3
  417. package/app/.next-cli-build/server/app/dashboard/proxy-fitness.segments/_tree.segment.rsc +1 -1
  418. package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
  419. package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +5 -5
  420. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  421. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  422. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  423. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  424. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
  425. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  426. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
  427. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
  428. package/app/.next-cli-build/server/app/dashboard/pxpipe.html +1 -1
  429. package/app/.next-cli-build/server/app/dashboard/pxpipe.rsc +5 -5
  430. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +2 -2
  431. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe.segment.rsc +1 -1
  432. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  433. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  434. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_full.segment.rsc +5 -5
  435. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_head.segment.rsc +1 -1
  436. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_index.segment.rsc +3 -3
  437. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +1 -1
  438. package/app/.next-cli-build/server/app/dashboard/quota.html +2 -2
  439. package/app/.next-cli-build/server/app/dashboard/quota.rsc +6 -6
  440. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
  441. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  442. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  443. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  444. package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
  445. package/app/.next-cli-build/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  446. package/app/.next-cli-build/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
  447. package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
  448. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
  449. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  450. package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  451. package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +3 -3
  452. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
  453. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  454. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
  455. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
  456. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  457. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  458. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  459. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  460. package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
  461. package/app/.next-cli-build/server/app/dashboard/skills.rsc +5 -5
  462. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
  463. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
  464. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  465. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  466. package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +5 -5
  467. package/app/.next-cli-build/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
  468. package/app/.next-cli-build/server/app/dashboard/skills.segments/_index.segment.rsc +3 -3
  469. package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +1 -1
  470. package/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
  471. package/app/.next-cli-build/server/app/dashboard/token-saver.rsc +5 -5
  472. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +2 -2
  473. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver.segment.rsc +1 -1
  474. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  475. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  476. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +5 -5
  477. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_head.segment.rsc +1 -1
  478. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_index.segment.rsc +3 -3
  479. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +1 -1
  480. package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
  481. package/app/.next-cli-build/server/app/dashboard/translator.rsc +5 -5
  482. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  483. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  484. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  485. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  486. package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
  487. package/app/.next-cli-build/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  488. package/app/.next-cli-build/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
  489. package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
  490. package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
  491. package/app/.next-cli-build/server/app/dashboard/usage.rsc +5 -5
  492. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  493. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  494. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  495. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  496. package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
  497. package/app/.next-cli-build/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  498. package/app/.next-cli-build/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
  499. package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
  500. package/app/.next-cli-build/server/app/dashboard.html +1 -1
  501. package/app/.next-cli-build/server/app/dashboard.rsc +5 -5
  502. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  503. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  504. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  505. package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +5 -5
  506. package/app/.next-cli-build/server/app/dashboard.segments/_head.segment.rsc +1 -1
  507. package/app/.next-cli-build/server/app/dashboard.segments/_index.segment.rsc +3 -3
  508. package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
  509. package/app/.next-cli-build/server/app/favicon.ico/route.js.nft.json +1 -1
  510. package/app/.next-cli-build/server/app/landing/page.js.nft.json +1 -1
  511. package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  512. package/app/.next-cli-build/server/app/landing.html +1 -1
  513. package/app/.next-cli-build/server/app/landing.rsc +3 -3
  514. package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +3 -3
  515. package/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
  516. package/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +3 -3
  517. package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
  518. package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  519. package/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
  520. package/app/.next-cli-build/server/app/login/page.js.nft.json +1 -1
  521. package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  522. package/app/.next-cli-build/server/app/login.html +1 -1
  523. package/app/.next-cli-build/server/app/login.rsc +4 -4
  524. package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +4 -4
  525. package/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
  526. package/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +3 -3
  527. package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
  528. package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  529. package/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
  530. package/app/.next-cli-build/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  531. package/app/.next-cli-build/server/app/masuk/page.js +1 -1
  532. package/app/.next-cli-build/server/app/masuk/page.js.nft.json +1 -1
  533. package/app/.next-cli-build/server/app/masuk/page_client-reference-manifest.js +1 -1
  534. package/app/.next-cli-build/server/app-paths-manifest.json +17 -17
  535. package/app/.next-cli-build/server/chunks/1685.js +2 -2
  536. package/app/.next-cli-build/server/chunks/1688.js +2 -2
  537. package/app/.next-cli-build/server/chunks/2411.js +1 -1
  538. package/app/.next-cli-build/server/chunks/2445.js +1 -1
  539. package/app/.next-cli-build/server/chunks/2549.js +1 -0
  540. package/app/.next-cli-build/server/chunks/2557.js +4 -10
  541. package/app/.next-cli-build/server/chunks/2764.js +1 -1
  542. package/app/.next-cli-build/server/chunks/2927.js +2 -2
  543. package/app/.next-cli-build/server/chunks/3040.js +2 -2
  544. package/app/.next-cli-build/server/chunks/32.js +2 -2
  545. package/app/.next-cli-build/server/chunks/3405.js +1 -1
  546. package/app/.next-cli-build/server/chunks/3519.js +1 -1
  547. package/app/.next-cli-build/server/chunks/3736.js +1 -1
  548. package/app/.next-cli-build/server/chunks/3787.js +1 -1
  549. package/app/.next-cli-build/server/chunks/4004.js +1 -1
  550. package/app/.next-cli-build/server/chunks/4029.js +2 -2
  551. package/app/.next-cli-build/server/chunks/4105.js +1 -1
  552. package/app/.next-cli-build/server/chunks/4502.js +13 -13
  553. package/app/.next-cli-build/server/chunks/4539.js +2 -2
  554. package/app/.next-cli-build/server/chunks/4574.js +44 -44
  555. package/app/.next-cli-build/server/chunks/4836.js +1 -1
  556. package/app/.next-cli-build/server/chunks/5006.js +1 -1
  557. package/app/.next-cli-build/server/chunks/5009.js +1 -1
  558. package/app/.next-cli-build/server/chunks/5050.js +1 -1
  559. package/app/.next-cli-build/server/chunks/5198.js +1 -1
  560. package/app/.next-cli-build/server/chunks/5302.js +1 -1
  561. package/app/.next-cli-build/server/chunks/5538.js +1 -0
  562. package/app/.next-cli-build/server/chunks/5598.js +1 -1
  563. package/app/.next-cli-build/server/chunks/6165.js +1 -1
  564. package/app/.next-cli-build/server/chunks/622.js +1 -0
  565. package/app/.next-cli-build/server/chunks/635.js +1 -0
  566. package/app/.next-cli-build/server/chunks/6385.js +1 -1
  567. package/app/.next-cli-build/server/chunks/6723.js +1 -1
  568. package/app/.next-cli-build/server/chunks/7006.js +2 -2
  569. package/app/.next-cli-build/server/chunks/7104.js +1 -1
  570. package/app/.next-cli-build/server/chunks/7425.js +1 -1
  571. package/app/.next-cli-build/server/chunks/7693.js +2 -2
  572. package/app/.next-cli-build/server/chunks/7938.js +2 -2
  573. package/app/.next-cli-build/server/chunks/7950.js +1 -1
  574. package/app/.next-cli-build/server/chunks/8691.js +2 -2
  575. package/app/.next-cli-build/server/chunks/8695.js +1 -1
  576. package/app/.next-cli-build/server/chunks/8772.js +1 -0
  577. package/app/.next-cli-build/server/chunks/912.js +1 -1
  578. package/app/.next-cli-build/server/chunks/9770.js +1 -0
  579. package/app/.next-cli-build/server/chunks/9784.js +1 -1
  580. package/app/.next-cli-build/server/chunks/9808.js +7 -0
  581. package/app/.next-cli-build/server/chunks/9974.js +1 -1
  582. package/app/.next-cli-build/server/chunks/9984.js +1 -1
  583. package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  584. package/app/.next-cli-build/server/middleware-react-loadable-manifest.js +1 -1
  585. package/app/.next-cli-build/server/middleware.js +3 -3
  586. package/app/.next-cli-build/server/pages/404.html +1 -1
  587. package/app/.next-cli-build/server/pages/500.html +1 -1
  588. package/app/.next-cli-build/server/server-reference-manifest.js +1 -1
  589. package/app/.next-cli-build/server/server-reference-manifest.json +1 -1
  590. package/app/.next-cli-build/static/chunks/1049.aa4f733370082c0d.js +7 -0
  591. package/app/.next-cli-build/static/chunks/{2940-b6dd0c5879412cea.js → 2940-0706a20a7c56dae1.js} +1 -1
  592. package/app/.next-cli-build/static/chunks/4385-8a145d343c888113.js +1 -0
  593. package/app/.next-cli-build/static/chunks/4964.6c8742ba86d45244.js +7 -0
  594. package/app/.next-cli-build/static/chunks/{5331.049b1512362de1f4.js → 5331.6cd97e3af09b08eb.js} +1 -1
  595. package/app/.next-cli-build/static/chunks/5479-0397a316e918cfaf.js +1 -0
  596. package/app/.next-cli-build/static/chunks/{9131-f4afa0414d45c1d1.js → 9131-e475ca6f20af6320.js} +1 -1
  597. package/app/.next-cli-build/static/chunks/{webpack-81a7adaed327dd6b.js → webpack-092d669f441fbd84.js} +1 -1
  598. package/app/custom-server.js +37 -37
  599. package/app/package.json +1 -3
  600. package/app/src/lib/db/adapters/betterSqliteAdapter.js +12 -4
  601. package/app/src/lib/db/adapters/nodeSqliteAdapter.js +12 -3
  602. package/app/src/lib/db/adapters/sqljsAdapter.js +13 -6
  603. package/app/src/lib/db/migrate.js +299 -299
  604. package/app/src/shared/services/quotaAutoPing.js +313 -313
  605. package/hooks/sqliteRuntime.js +188 -188
  606. package/package.json +1 -1
  607. package/src/cli/api/client.js +556 -556
  608. package/src/cli/commands/xaiVideo.js +300 -300
  609. package/src/cli/menus/combos.js +0 -103
  610. package/src/cli/menus/providers.js +868 -858
  611. package/src/cli/menus/settings.js +204 -204
  612. package/src/cli/utils/modelSelector.js +189 -51
  613. package/app/.next-cli-build/server/chunks/2732.js +0 -1
  614. package/app/.next-cli-build/server/chunks/3539.js +0 -1
  615. package/app/.next-cli-build/server/chunks/4816.js +0 -1
  616. package/app/.next-cli-build/server/chunks/6793.js +0 -1
  617. package/app/.next-cli-build/server/chunks/6931.js +0 -1
  618. package/app/.next-cli-build/server/chunks/9162.js +0 -1
  619. package/app/.next-cli-build/server/chunks/9614.js +0 -7
  620. package/app/.next-cli-build/server/chunks/9787.js +0 -1
  621. package/app/.next-cli-build/static/chunks/1049.adc9916d5a6b95f8.js +0 -7
  622. package/app/.next-cli-build/static/chunks/4385-ce7b55264de51d47.js +0 -1
  623. package/app/.next-cli-build/static/chunks/5479-20746781c1de7eb2.js +0 -1
  624. package/app/.next-cli-build/static/chunks/9078.ea6aeb4af0c25e5d.js +0 -7
  625. /package/app/.next-cli-build/static/{yvUSImiXUeMIOPHHzKVq_ → 4VmP0yWnLncSA5CQqLYsu}/_buildManifest.js +0 -0
  626. /package/app/.next-cli-build/static/{yvUSImiXUeMIOPHHzKVq_ → 4VmP0yWnLncSA5CQqLYsu}/_ssgManifest.js +0 -0
@@ -1,858 +1,868 @@
1
- const api = require("../api/client");
2
- const { prompt, confirm, pause } = require("../utils/input");
3
- const { clearScreen, showStatus, showHeader } = require("../utils/display");
4
- const { formatDate, getRelativeTime } = require("../utils/format");
5
- const { showMenuWithBack } = require("../utils/menuHelper");
6
- const { copyToClipboard } = require("../utils/clipboard");
7
-
8
- // ANSI colors for styling
9
- const COLORS = {
10
- reset: "\x1b[0m",
11
- bold: "\x1b[1m",
12
- cyan: "\x1b[36m",
13
- dim: "\x1b[2m"
14
- };
15
-
16
- // Provider models - static config (synced from open-sse/config/providerModels.js)
17
- const PROVIDER_MODELS = {
18
- cc: [
19
- { id: "claude-opus-4-5-20251101" },
20
- { id: "claude-sonnet-4-5-20250929" },
21
- { id: "claude-haiku-4-5-20251001" },
22
- ],
23
- cx: [
24
- { id: "gpt-5.2-codex" },
25
- { id: "gpt-5.2" },
26
- { id: "gpt-5.1-codex-max" },
27
- { id: "gpt-5.1-codex" },
28
- { id: "gpt-5.1-codex-mini" },
29
- { id: "gpt-5.1" },
30
- { id: "gpt-5-codex" },
31
- { id: "gpt-5-codex-mini" },
32
- ],
33
- gc: [
34
- { id: "gemini-3-flash-preview" },
35
- { id: "gemini-3-pro-preview" },
36
- { id: "gemini-2.5-pro" },
37
- { id: "gemini-2.5-flash" },
38
- { id: "gemini-2.5-flash-lite" },
39
- ],
40
- qw: [
41
- { id: "qwen3-coder-plus" },
42
- { id: "qwen3-coder-flash" },
43
- { id: "vision-model" },
44
- ],
45
- if: [
46
- { id: "qwen3-coder-plus" },
47
- { id: "kimi-k2" },
48
- { id: "kimi-k2-thinking" },
49
- { id: "deepseek-r1" },
50
- { id: "deepseek-v3.2-chat" },
51
- { id: "deepseek-v3.2-reasoner" },
52
- { id: "minimax-m2" },
53
- { id: "glm-4.7" },
54
- ],
55
- ag: [
56
- { id: "gemini-3.8-flash-high" },
57
- { id: "gemini-3.8-flash-medium" },
58
- { id: "gemini-3.8-flash-low" },
59
- { id: "gemini-3.7-flash-high" },
60
- { id: "gemini-3.7-flash-medium" },
61
- { id: "gemini-3.7-flash-low" },
62
- { id: "gemini-3.6-flash-high" },
63
- { id: "gemini-3.6-flash-medium" },
64
- { id: "gemini-3.6-flash-low" },
65
- { id: "gemini-3-flash-agent" },
66
- { id: "gemini-3.5-flash-low" },
67
- { id: "gemini-3.5-flash-extra-low" },
68
- { id: "gemini-pro-agent" },
69
- { id: "gemini-3.1-pro-low" },
70
- { id: "claude-sonnet-4-6" },
71
- { id: "claude-opus-4-6-thinking" },
72
- { id: "gpt-oss-120b-medium" },
73
- { id: "gemini-3-flash" },
74
- ],
75
- gh: [
76
- { id: "gpt-5" },
77
- { id: "gpt-5-mini" },
78
- { id: "gpt-5.1-codex" },
79
- { id: "gpt-5.1-codex-max" },
80
- { id: "gpt-4.1" },
81
- { id: "claude-4.5-sonnet" },
82
- { id: "claude-4.5-opus" },
83
- { id: "claude-4.5-haiku" },
84
- { id: "gemini-3-pro" },
85
- { id: "gemini-3-flash" },
86
- { id: "gemini-2.5-pro" },
87
- { id: "grok-code-fast-1" },
88
- ],
89
- kr: [
90
- { id: "claude-sonnet-5" },
91
- { id: "claude-sonnet-4.5" },
92
- { id: "claude-haiku-4.5" },
93
- ],
94
- openai: [
95
- { id: "gpt-4o" },
96
- { id: "gpt-4o-mini" },
97
- { id: "gpt-4-turbo" },
98
- { id: "o1" },
99
- { id: "o1-mini" },
100
- ],
101
- anthropic: [
102
- { id: "claude-sonnet-4-20250514" },
103
- { id: "claude-opus-4-20250514" },
104
- { id: "claude-3-5-sonnet-20241022" },
105
- ],
106
- gemini: [
107
- { id: "gemini-3.8-flash" },
108
- { id: "gemini-3.7-flash" },
109
- { id: "gemini-3-pro-preview" },
110
- { id: "gemini-2.5-pro" },
111
- { id: "gemini-2.5-flash" },
112
- { id: "gemini-2.5-flash-lite" },
113
- ],
114
- openrouter: [
115
- { id: "auto" },
116
- ],
117
- glm: [
118
- { id: "glm-4.7" },
119
- { id: "glm-4.6v" },
120
- ],
121
- kimi: [
122
- { id: "kimi-latest" },
123
- ],
124
- minimax: [
125
- { id: "MiniMax-M2.1" },
126
- ],
127
- };
128
-
129
- // Provider definitions
130
- const OAUTH_PROVIDERS = {
131
- claude: { id: "claude", alias: "cc", name: "Claude Code" },
132
- codex: { id: "codex", alias: "cx", name: "OpenAI Codex" },
133
- "gemini-cli": { id: "gemini-cli", alias: "gc", name: "Gemini CLI" },
134
- github: { id: "github", alias: "gh", name: "GitHub Copilot" },
135
- antigravity: { id: "antigravity", alias: "ag", name: "Antigravity" },
136
- iflow: { id: "iflow", alias: "if", name: "iFlow AI" },
137
- qwen: { id: "qwen", alias: "qw", name: "Qwen Code" },
138
- kiro: { id: "kiro", alias: "kr", name: "Kiro AI" },
139
- };
140
-
141
- const APIKEY_PROVIDERS = {
142
- openrouter: { id: "openrouter", name: "OpenRouter" },
143
- glm: { id: "glm", name: "GLM Coding" },
144
- minimax: { id: "minimax", name: "Minimax Coding" },
145
- kimi: { id: "kimi", name: "Kimi" },
146
- openai: { id: "openai", name: "OpenAI" },
147
- anthropic: { id: "anthropic", name: "Anthropic" },
148
- gemini: { id: "gemini", name: "Gemini" },
149
- };
150
-
151
- const ALL_PROVIDERS = { ...OAUTH_PROVIDERS, ...APIKEY_PROVIDERS };
152
-
153
- /**
154
- * Get auth type for provider
155
- * @param {string} providerId - Provider ID
156
- * @returns {string} "oauth" or "apikey"
157
- */
158
- function getAuthType(providerId) {
159
- return OAUTH_PROVIDERS[providerId] ? "oauth" : "apikey";
160
- }
161
-
162
- /**
163
- * Count connections by provider
164
- * @param {Array} connections - Array of connection objects
165
- * @returns {Object} Map of providerId -> count
166
- */
167
- function countConnectionsByProvider(connections) {
168
- const counts = {};
169
- connections.forEach(conn => {
170
- const providerId = conn.provider || conn.providerId;
171
- counts[providerId] = (counts[providerId] || 0) + 1;
172
- });
173
- return counts;
174
- }
175
-
176
- /**
177
- * Show main providers menu
178
- * @param {Array<string>} breadcrumb - Breadcrumb path
179
- */
180
- async function showProvidersMenu(breadcrumb = []) {
181
- // Build provider items list
182
- const providerItems = [];
183
-
184
- Object.values(OAUTH_PROVIDERS).forEach(provider => {
185
- providerItems.push({
186
- provider,
187
- authType: "oauth",
188
- label: (data) => {
189
- const count = data.counts[provider.id] || 0;
190
- return `${provider.name} (OAuth) - ${count} Connected`;
191
- },
192
- action: async (data) => {
193
- await showProviderDetail(provider.id, "oauth", data.connections, [...breadcrumb, provider.name]);
194
- return true;
195
- }
196
- });
197
- });
198
-
199
- Object.values(APIKEY_PROVIDERS).forEach(provider => {
200
- providerItems.push({
201
- provider,
202
- authType: "apikey",
203
- label: (data) => {
204
- const count = data.counts[provider.id] || 0;
205
- return `${provider.name} (API) - ${count} Connected`;
206
- },
207
- action: async (data) => {
208
- await showProviderDetail(provider.id, "apikey", data.connections, [...breadcrumb, provider.name]);
209
- return true;
210
- }
211
- });
212
- });
213
-
214
- // Custom provider nodes section
215
- providerItems.push({
216
- label: () => `${COLORS.dim}── Custom Providers ──${COLORS.reset}`,
217
- action: async () => true, // separator, no-op
218
- isSeparator: true,
219
- });
220
- providerItems.push({
221
- label: (data) => {
222
- const count = data.nodeCount || 0;
223
- return `Custom Providers - ${count} Configured`;
224
- },
225
- action: async () => {
226
- await showCustomProvidersMenu([...breadcrumb, "Custom Providers"]);
227
- return true;
228
- }
229
- });
230
-
231
- await showMenuWithBack({
232
- title: "šŸ”Œ Providers Management",
233
- breadcrumb,
234
- refresh: async () => {
235
- const [provRes, nodeRes] = await Promise.all([api.getProviders(), api.getProviderNodes()]);
236
- if (!provRes.success) {
237
- showStatus(`Failed to fetch providers: ${provRes.error}`, "error");
238
- await pause();
239
- return null;
240
- }
241
- const connections = provRes.data.connections || [];
242
- const nodes = nodeRes.success ? (nodeRes.data.nodes || nodeRes.data || []) : [];
243
- return {
244
- connections,
245
- counts: countConnectionsByProvider(connections),
246
- nodeCount: nodes.length,
247
- };
248
- },
249
- items: providerItems
250
- });
251
- }
252
-
253
- /**
254
- * Build provider header with alias and models
255
- * @param {string} providerId - Provider ID
256
- * @returns {string}
257
- */
258
- function buildProviderHeader(providerId) {
259
- const provider = ALL_PROVIDERS[providerId];
260
- const alias = provider.alias || providerId;
261
-
262
- const lines = [];
263
- lines.push(`Alias: ${COLORS.cyan}${alias}${COLORS.reset}`);
264
-
265
- // Get models from static config
266
- const models = PROVIDER_MODELS[alias] || [];
267
- if (models.length > 0) {
268
- const modelList = models
269
- .slice(0, 5)
270
- .map(m => `${alias}/${m.id}`)
271
- .join(", ");
272
- const more = models.length > 5 ? ` (+${models.length - 5} more)` : "";
273
- lines.push(`Models: ${COLORS.dim}${modelList}${more}${COLORS.reset}`);
274
- } else {
275
- lines.push(`Models: ${COLORS.dim}No models configured${COLORS.reset}`);
276
- }
277
-
278
- return lines.join("\n");
279
- }
280
-
281
- /**
282
- * Show provider detail with connections and actions
283
- * @param {string} providerId - Provider ID
284
- * @param {string} authType - "oauth" or "apikey"
285
- * @param {Array} allConnections - All connections
286
- * @param {Array<string>} breadcrumb - Breadcrumb path
287
- */
288
- async function showProviderDetail(providerId, authType, allConnections, breadcrumb = []) {
289
- const provider = ALL_PROVIDERS[providerId];
290
- const { showListMenu } = require("../utils/menuHelper");
291
-
292
- await showListMenu({
293
- title: `šŸ”Œ ${provider.name} (${authType.toUpperCase()})`,
294
- breadcrumb,
295
- backLabel: "← Back to Providers",
296
- headerContent: buildProviderHeader(providerId),
297
- fetchItems: async () => {
298
- const response = await api.getProviders();
299
- if (response.success) {
300
- allConnections.length = 0;
301
- allConnections.push(...(response.data.connections || []));
302
- }
303
- const providerConns = allConnections.filter(conn =>
304
- (conn.provider || conn.providerId) === providerId
305
- );
306
- return { items: providerConns };
307
- },
308
- formatItem: (conn) => {
309
- const status = conn.testStatus === "active" ? "āœ“" : conn.testStatus === "error" ? "āœ—" : "?";
310
- const name = conn.name || conn.email || conn.displayName || "Unnamed";
311
- return `${name} (${status})`;
312
- },
313
- onSelect: async (conn) => {
314
- await showConnectionActions(conn, providerId, breadcrumb);
315
- },
316
- createAction: {
317
- label: "Add New Connection",
318
- action: async () => {
319
- await handleAddConnection(providerId, authType);
320
- }
321
- }
322
- });
323
- }
324
-
325
- /**
326
- * Show actions for a specific connection
327
- * @param {Object} connection - Connection object
328
- * @param {string} providerId - Provider ID
329
- * @param {Array<string>} breadcrumb - Breadcrumb path
330
- */
331
- async function showConnectionActions(connection, providerId, breadcrumb = []) {
332
- const name = connection.name || connection.email || connection.displayName || "Unnamed";
333
- const status = connection.testStatus === "active" ? "āœ“ Active" :
334
- connection.testStatus === "error" ? "āœ— Error" : "? Unknown";
335
-
336
- await showMenuWithBack({
337
- title: `šŸ”Œ ${name}`,
338
- breadcrumb: [...breadcrumb, name],
339
- headerContent: `Connection: ${name}\nStatus: ${status}`,
340
- items: [
341
- {
342
- label: "Rename Connection",
343
- action: async () => {
344
- const newName = await prompt(`New name (current: ${name}): `);
345
- if (newName && newName.trim()) {
346
- showStatus("Renaming connection...", "info");
347
- const result = await api.updateConnection(connection.id, { name: newName.trim() });
348
- if (result.success) {
349
- showStatus("Connection renamed!", "success");
350
- connection.name = newName.trim();
351
- } else {
352
- showStatus(`Rename failed: ${result.error}`, "error");
353
- }
354
- await pause();
355
- }
356
- return true;
357
- }
358
- },
359
- {
360
- label: "Test Connection",
361
- action: async () => {
362
- showStatus("Testing connection...", "info");
363
- const result = await api.testConnection(connection.id);
364
- if (result.success) {
365
- showStatus("Connection is working!", "success");
366
- } else {
367
- showStatus(`Test failed: ${result.error}`, "error");
368
- }
369
- await pause();
370
- return true;
371
- }
372
- },
373
- {
374
- label: "Delete Connection",
375
- action: async () => {
376
- const confirmed = await confirm(`Delete connection "${name}"?`);
377
- if (confirmed) {
378
- const result = await api.deleteConnection(connection.id);
379
- if (result.success) {
380
- showStatus("Connection deleted!", "success");
381
- } else {
382
- showStatus(`Delete failed: ${result.error}`, "error");
383
- }
384
- await pause();
385
- return false; // Exit menu after delete
386
- }
387
- return true;
388
- }
389
- }
390
- ]
391
- });
392
- }
393
-
394
- /**
395
- * Handle adding new connection
396
- * @param {string} providerId - Provider ID
397
- * @param {string} authType - "oauth" or "apikey"
398
- */
399
- // Providers that use Device Code Flow (terminal-based polling)
400
- const DEVICE_CODE_PROVIDERS = ["github", "qwen", "kiro"];
401
-
402
- /**
403
- * Handle adding new connection - auto-detect flow type
404
- * @param {string} providerId - Provider ID
405
- * @param {string} authType - "oauth" or "apikey"
406
- */
407
- async function handleAddConnection(providerId, authType) {
408
- if (authType === "apikey") {
409
- await handleAddApiKeyConnection(providerId);
410
- } else {
411
- // OAuth: auto-detect flow type based on provider
412
- if (DEVICE_CODE_PROVIDERS.includes(providerId)) {
413
- // Device Code Flow for GitHub, Qwen, Kiro
414
- await handleAddDeviceCodeConnection(providerId);
415
- } else {
416
- // Authorization Code Flow for Claude, Codex, Gemini, etc.
417
- await handleAddOAuthConnection(providerId);
418
- }
419
- }
420
- }
421
-
422
- /**
423
- * Handle adding API Key connection
424
- * @param {string} providerId - Provider ID
425
- */
426
- async function handleAddApiKeyConnection(providerId) {
427
- clearScreen();
428
- const provider = ALL_PROVIDERS[providerId];
429
- console.log(`\nāž• Add ${provider.name} API Key Connection\n`);
430
-
431
- const name = await prompt("Connection Name: ");
432
- if (!name) {
433
- showStatus("Cancelled", "warning");
434
- await pause();
435
- return;
436
- }
437
-
438
- const apiKey = await prompt("API Key: ");
439
- if (!apiKey) {
440
- showStatus("Cancelled", "warning");
441
- await pause();
442
- return;
443
- }
444
-
445
- showStatus("Creating connection...", "info");
446
-
447
- const result = await api.createApiKeyProvider({
448
- provider: providerId,
449
- name,
450
- apiKey
451
- });
452
-
453
- if (result.success) {
454
- showStatus("āœ“ Connection created successfully!", "success");
455
- } else {
456
- showStatus(`āœ— Failed: ${result.error}`, "error");
457
- }
458
-
459
- await pause();
460
- }
461
-
462
- /**
463
- * Handle adding OAuth Authorization Code connection
464
- * User opens URL manually and pastes callback URL
465
- * @param {string} providerId - Provider ID
466
- */
467
- async function handleAddOAuthConnection(providerId) {
468
- clearScreen();
469
- const provider = ALL_PROVIDERS[providerId];
470
-
471
- // Step 1: Get auth URL
472
- showStatus("Requesting authorization URL...", "info");
473
- const authResult = await api.getOAuthAuthUrl(providerId);
474
-
475
- if (!authResult.success) {
476
- showStatus(`Failed: ${authResult.error}`, "error");
477
- await pause();
478
- return;
479
- }
480
-
481
- const authData = authResult.data || authResult;
482
- const authUrl = authData.authUrl;
483
- const codeVerifier = authData.codeVerifier;
484
- const state = authData.state;
485
- const redirectUri = authData.redirectUri;
486
-
487
- if (!authUrl) {
488
- showStatus("Failed: No auth URL received", "error");
489
- await pause();
490
- return;
491
- }
492
-
493
- // Step 2: Show URL and instructions
494
- clearScreen();
495
- showHeader("šŸ” OAuth Login", `Providers > ${provider.name} > Add Connection`);
496
-
497
- console.log(` ${COLORS.bold}${COLORS.cyan}1.${COLORS.reset} Open this URL in your browser:`);
498
- console.log(` ${COLORS.dim}${authUrl}${COLORS.reset}`);
499
- if (copyToClipboard(authUrl)) {
500
- console.log(` \x1b[32māœ“ Link copied to clipboard!\x1b[0m`);
501
- }
502
- console.log();
503
- console.log(` ${COLORS.bold}${COLORS.cyan}2.${COLORS.reset} Complete authorization in browser`);
504
- console.log();
505
- console.log(` ${COLORS.bold}${COLORS.cyan}3.${COLORS.reset} Copy the callback URL from address bar`);
506
- console.log(` ${COLORS.dim}(looks like: http://localhost:20128/callback?code=...)${COLORS.reset}`);
507
- console.log();
508
-
509
- const callbackUrl = await prompt(" Paste callback URL: ");
510
- if (!callbackUrl) {
511
- showStatus("Cancelled", "warning");
512
- await pause();
513
- return;
514
- }
515
-
516
- // Step 3: Parse callback URL and extract code
517
- let code, urlState, error;
518
- try {
519
- const url = new URL(callbackUrl.trim());
520
- code = url.searchParams.get("code");
521
- urlState = url.searchParams.get("state");
522
- error = url.searchParams.get("error");
523
-
524
- if (error) {
525
- const errorDesc = url.searchParams.get("error_description") || error;
526
- showStatus(`Authorization failed: ${errorDesc}`, "error");
527
- await pause();
528
- return;
529
- }
530
-
531
- if (!code) {
532
- showStatus("No authorization code found in URL", "error");
533
- await pause();
534
- return;
535
- }
536
- } catch (err) {
537
- showStatus("Invalid URL format", "error");
538
- await pause();
539
- return;
540
- }
541
-
542
- // Step 4: Exchange code for tokens
543
- console.log();
544
- showStatus("Exchanging code for tokens...", "info");
545
- const exchangeResult = await api.exchangeOAuthCode(providerId, {
546
- code,
547
- redirectUri,
548
- codeVerifier,
549
- state: urlState || state
550
- });
551
-
552
- if (exchangeResult.success) {
553
- showStatus("Connection created successfully!", "success");
554
- } else {
555
- showStatus(`Failed: ${exchangeResult.error}`, "error");
556
- }
557
-
558
- await pause();
559
- }
560
-
561
- /**
562
- * Handle adding OAuth Device Code connection
563
- * @param {string} providerId - Provider ID
564
- */
565
- async function handleAddDeviceCodeConnection(providerId) {
566
- clearScreen();
567
- const provider = ALL_PROVIDERS[providerId];
568
-
569
- // Step 1: Request device code
570
- showStatus("Requesting device code...", "info");
571
- const deviceResult = await api.getOAuthDeviceCode(providerId);
572
-
573
- if (!deviceResult.success) {
574
- showStatus(`Failed: ${deviceResult.error}`, "error");
575
- await pause();
576
- return;
577
- }
578
-
579
- const deviceData = deviceResult.data || deviceResult;
580
- const device_code = deviceData.device_code;
581
- const user_code = deviceData.user_code;
582
- const verification_uri = deviceData.verification_uri;
583
- const verification_uri_complete = deviceData.verification_uri_complete;
584
- const codeVerifier = deviceData.codeVerifier;
585
- const extraData = deviceData.extraData || deviceData;
586
-
587
- if (!device_code) {
588
- showStatus("Failed: No device code received", "error");
589
- await pause();
590
- return;
591
- }
592
-
593
- // Step 2: Show instructions
594
- clearScreen();
595
- const deviceUrl = verification_uri_complete || verification_uri;
596
- showHeader("šŸ“± Device Login", `Providers > ${provider.name} > Add Connection`);
597
-
598
- console.log(` ${COLORS.bold}${COLORS.cyan}1.${COLORS.reset} Open: ${COLORS.dim}${deviceUrl}${COLORS.reset}`);
599
- if (copyToClipboard(deviceUrl)) {
600
- console.log(` \x1b[32māœ“ Link copied to clipboard!\x1b[0m`);
601
- }
602
- console.log();
603
- if (!verification_uri_complete && user_code) {
604
- console.log(` ${COLORS.bold}${COLORS.cyan}2.${COLORS.reset} Enter code: ${COLORS.bold}${user_code}${COLORS.reset}`);
605
- console.log();
606
- }
607
- console.log(` ${COLORS.dim}Waiting for authorization...${COLORS.reset}`);
608
- console.log();
609
-
610
- // Step 3: Poll for token
611
- const maxAttempts = 60; // 5 minutes (5s interval)
612
- for (let i = 0; i < maxAttempts; i++) {
613
- await new Promise(resolve => setTimeout(resolve, 5000));
614
-
615
- const pollResult = await api.pollOAuthToken(providerId, {
616
- deviceCode: device_code,
617
- codeVerifier,
618
- extraData
619
- });
620
-
621
- if (pollResult.success) {
622
- showStatus("\nConnection created successfully!", "success");
623
- await pause();
624
- return;
625
- }
626
-
627
- // Check if still pending (pending flag is at root level, not in data)
628
- const isPending = pollResult.pending || pollResult.error === "authorization_pending" || pollResult.error === "slow_down";
629
- if (!isPending) {
630
- showStatus(`\nFailed: ${pollResult.error || "Unknown error"}`, "error");
631
- await pause();
632
- return;
633
- }
634
-
635
- process.stdout.write(".");
636
- }
637
-
638
- showStatus("\nTimeout waiting for authorization", "error");
639
- await pause();
640
- }
641
-
642
- // ============================================================================
643
- // CUSTOM PROVIDERS (provider nodes)
644
- // ============================================================================
645
-
646
- const CUSTOM_NODE_TYPES = ["openai-compatible", "anthropic-compatible"];
647
- const OPENAI_API_TYPES = ["chat", "responses"];
648
-
649
- /**
650
- * Show custom providers section in main providers menu
651
- * @param {Array} nodes - List of provider nodes
652
- * @param {Array} connections - All connections
653
- * @param {Array<string>} breadcrumb
654
- */
655
- async function showCustomProvidersMenu(breadcrumb = []) {
656
- const { showListMenu } = require("../utils/menuHelper");
657
-
658
- await showListMenu({
659
- title: "šŸ”§ Custom Providers",
660
- breadcrumb,
661
- backLabel: "← Back to Providers",
662
- fetchItems: async () => {
663
- const res = await api.getProviderNodes();
664
- if (!res.success) return { items: [] };
665
- return { items: res.data.nodes || res.data || [] };
666
- },
667
- formatItem: (node) => `[${node.prefix}] ${node.name} (${node.type})`,
668
- onSelect: async (node) => {
669
- await showCustomNodeDetail(node, [...breadcrumb, node.name]);
670
- },
671
- createAction: {
672
- label: "āž• Add Custom Provider",
673
- action: async () => {
674
- await handleAddCustomNode();
675
- }
676
- }
677
- });
678
- }
679
-
680
- /**
681
- * Show detail menu for a custom provider node
682
- */
683
- async function showCustomNodeDetail(node, breadcrumb = []) {
684
- await showMenuWithBack({
685
- title: `šŸ”§ ${node.name}`,
686
- breadcrumb,
687
- headerContent: [
688
- `Type: ${node.type}`,
689
- `Prefix: ${COLORS.cyan}${node.prefix}${COLORS.reset}`,
690
- `Base URL: ${COLORS.dim}${node.baseUrl}${COLORS.reset}`,
691
- ].join("\n"),
692
- items: [
693
- {
694
- label: "Connections",
695
- action: async () => {
696
- await showCustomNodeConnections(node, breadcrumb);
697
- return true;
698
- }
699
- },
700
- {
701
- label: "Edit Node",
702
- action: async () => {
703
- await handleEditCustomNode(node);
704
- return true;
705
- }
706
- },
707
- {
708
- label: "Delete Node",
709
- action: async () => {
710
- const confirmed = await confirm(`Delete "${node.name}" and all its connections?`);
711
- if (confirmed) {
712
- const res = await api.deleteProviderNode(node.id);
713
- if (res.success) {
714
- showStatus("Node deleted!", "success");
715
- } else {
716
- showStatus(`Delete failed: ${res.error}`, "error");
717
- }
718
- await pause();
719
- return false;
720
- }
721
- return true;
722
- }
723
- }
724
- ]
725
- });
726
- }
727
-
728
- /**
729
- * Show connections for a custom provider node
730
- */
731
- async function showCustomNodeConnections(node, breadcrumb = []) {
732
- const { showListMenu } = require("../utils/menuHelper");
733
-
734
- await showListMenu({
735
- title: `šŸ”Œ ${node.name} – Connections`,
736
- breadcrumb,
737
- backLabel: "← Back",
738
- fetchItems: async () => {
739
- const res = await api.getProviders();
740
- if (!res.success) return { items: [] };
741
- const all = res.data.connections || [];
742
- const items = all.filter(c => c.provider === node.id);
743
- return { items };
744
- },
745
- formatItem: (conn) => {
746
- const status = conn.testStatus === "active" ? "āœ“" : conn.testStatus === "error" ? "āœ—" : "?";
747
- return `${conn.name || "Unnamed"} (${status})`;
748
- },
749
- onSelect: async (conn) => {
750
- await showConnectionActions(conn, node.id, breadcrumb);
751
- },
752
- createAction: {
753
- label: "Add API Key Connection",
754
- action: async () => {
755
- await handleAddCustomNodeConnection(node);
756
- }
757
- }
758
- });
759
- }
760
-
761
- /**
762
- * Add API key connection to a custom provider node
763
- */
764
- async function handleAddCustomNodeConnection(node) {
765
- clearScreen();
766
- console.log(`\nāž• Add Connection to ${node.name}\n`);
767
-
768
- const name = await prompt("Connection Name: ");
769
- if (!name) { showStatus("Cancelled", "warning"); await pause(); return; }
770
-
771
- const apiKey = await prompt("API Key: ");
772
- if (!apiKey) { showStatus("Cancelled", "warning"); await pause(); return; }
773
-
774
- showStatus("Creating connection...", "info");
775
- const res = await api.createApiKeyProvider({ provider: node.id, name, apiKey });
776
-
777
- showStatus(res.success ? "āœ“ Connection created!" : `āœ— Failed: ${res.error}`, res.success ? "success" : "error");
778
- await pause();
779
- }
780
-
781
- /**
782
- * Handle adding a new custom provider node
783
- */
784
- async function handleAddCustomNode() {
785
- clearScreen();
786
- console.log("\nāž• Add Custom Provider\n");
787
-
788
- // Step 1: Select type
789
- const typeChoices = CUSTOM_NODE_TYPES.map((t, i) => ` ${i + 1}. ${t}`).join("\n");
790
- console.log(`Select type:\n${typeChoices}\n`);
791
- const typeInput = await prompt("Type (1/2): ");
792
- const typeIdx = parseInt(typeInput) - 1;
793
- if (isNaN(typeIdx) || !CUSTOM_NODE_TYPES[typeIdx]) {
794
- showStatus("Cancelled", "warning"); await pause(); return;
795
- }
796
- const type = CUSTOM_NODE_TYPES[typeIdx];
797
-
798
- // Step 2: Inputs
799
- const name = await prompt("Name: ");
800
- if (!name) { showStatus("Cancelled", "warning"); await pause(); return; }
801
-
802
- const prefix = await prompt("Prefix (used in model IDs, e.g. myapi): ");
803
- if (!prefix) { showStatus("Cancelled", "warning"); await pause(); return; }
804
-
805
- const baseUrl = await prompt("Base URL (e.g. https://api.example.com/v1): ");
806
- if (!baseUrl) { showStatus("Cancelled", "warning"); await pause(); return; }
807
-
808
- // Step 3: API type (OpenAI only)
809
- let apiType;
810
- if (type === "openai-compatible") {
811
- const apiTypeChoices = OPENAI_API_TYPES.map((t, i) => ` ${i + 1}. ${t}`).join("\n");
812
- console.log(`\nAPI Type:\n${apiTypeChoices}\n`);
813
- const apiTypeInput = await prompt("API Type (1/2, default 1): ");
814
- const apiTypeIdx = parseInt(apiTypeInput) - 1;
815
- apiType = OPENAI_API_TYPES[apiTypeIdx] || "chat";
816
- }
817
-
818
- showStatus("Creating provider node...", "info");
819
- const body = { name, prefix, baseUrl, type, ...(apiType && { apiType }) };
820
- const res = await api.createProviderNode(body);
821
-
822
- showStatus(res.success ? "āœ“ Provider created!" : `āœ— Failed: ${res.error}`, res.success ? "success" : "error");
823
- await pause();
824
- }
825
-
826
- /**
827
- * Handle editing a custom provider node
828
- */
829
- async function handleEditCustomNode(node) {
830
- clearScreen();
831
- console.log(`\nāœļø Edit ${node.name}\n`);
832
- console.log(`${COLORS.dim}Leave blank to keep current value${COLORS.reset}\n`);
833
-
834
- const name = await prompt(`Name (${node.name}): `);
835
- const baseUrl = await prompt(`Base URL (${node.baseUrl}): `);
836
- const prefix = await prompt(`Prefix (${node.prefix}): `);
837
-
838
- const updates = {};
839
- if (name && name.trim()) updates.name = name.trim();
840
- if (baseUrl && baseUrl.trim()) updates.baseUrl = baseUrl.trim();
841
- if (prefix && prefix.trim()) updates.prefix = prefix.trim();
842
-
843
- if (!Object.keys(updates).length) {
844
- showStatus("No changes", "warning"); await pause(); return;
845
- }
846
-
847
- showStatus("Updating...", "info");
848
- const res = await api.updateProviderNode(node.id, updates);
849
- if (res.success) {
850
- Object.assign(node, updates);
851
- showStatus("āœ“ Updated!", "success");
852
- } else {
853
- showStatus(`āœ— Failed: ${res.error}`, "error");
854
- }
855
- await pause();
856
- }
857
-
858
- module.exports = { showProvidersMenu };
1
+ const api = require("../api/client");
2
+ const { prompt, confirm, pause } = require("../utils/input");
3
+ const { clearScreen, showStatus, showHeader } = require("../utils/display");
4
+ const { formatDate, getRelativeTime } = require("../utils/format");
5
+ const { showMenuWithBack } = require("../utils/menuHelper");
6
+ const { copyToClipboard } = require("../utils/clipboard");
7
+
8
+ // ANSI colors for styling
9
+ const COLORS = {
10
+ reset: "\x1b[0m",
11
+ bold: "\x1b[1m",
12
+ cyan: "\x1b[36m",
13
+ dim: "\x1b[2m"
14
+ };
15
+
16
+ // Provider models - static config (synced from open-sse/config/providerModels.js)
17
+ const PROVIDER_MODELS = {
18
+ cc: [
19
+ { id: "claude-opus-4-5-20251101" },
20
+ { id: "claude-sonnet-4-5-20250929" },
21
+ { id: "claude-haiku-4-5-20251001" },
22
+ ],
23
+ cx: [
24
+ { id: "gpt-5.2-codex" },
25
+ { id: "gpt-5.2" },
26
+ { id: "gpt-5.1-codex-max" },
27
+ { id: "gpt-5.1-codex" },
28
+ { id: "gpt-5.1-codex-mini" },
29
+ { id: "gpt-5.1" },
30
+ { id: "gpt-5-codex" },
31
+ { id: "gpt-5-codex-mini" },
32
+ ],
33
+ gc: [
34
+ { id: "gemini-3-flash-preview" },
35
+ { id: "gemini-3-pro-preview" },
36
+ { id: "gemini-2.5-pro" },
37
+ { id: "gemini-2.5-flash" },
38
+ { id: "gemini-2.5-flash-lite" },
39
+ ],
40
+ qw: [
41
+ { id: "qwen3-coder-plus" },
42
+ { id: "qwen3-coder-flash" },
43
+ { id: "vision-model" },
44
+ ],
45
+ if: [
46
+ { id: "qwen3-coder-plus" },
47
+ { id: "kimi-k2" },
48
+ { id: "kimi-k2-thinking" },
49
+ { id: "deepseek-r1" },
50
+ { id: "deepseek-v3.2-chat" },
51
+ { id: "deepseek-v3.2-reasoner" },
52
+ { id: "minimax-m2" },
53
+ { id: "glm-4.7" },
54
+ ],
55
+ ag: [
56
+ { id: "gemini-3.8-flash-high" },
57
+ { id: "gemini-3.8-flash-medium" },
58
+ { id: "gemini-3.8-flash-low" },
59
+ { id: "gemini-3.7-flash-high" },
60
+ { id: "gemini-3.7-flash-medium" },
61
+ { id: "gemini-3.7-flash-low" },
62
+ { id: "gemini-3.6-flash-high" },
63
+ { id: "gemini-3.6-flash-medium" },
64
+ { id: "gemini-3.6-flash-low" },
65
+ { id: "gemini-3-flash-agent" },
66
+ { id: "gemini-3.5-flash-low" },
67
+ { id: "gemini-3.5-flash-extra-low" },
68
+ { id: "gemini-pro-agent" },
69
+ { id: "gemini-3.1-pro-low" },
70
+ { id: "claude-sonnet-4-6" },
71
+ { id: "claude-opus-4-6-thinking" },
72
+ { id: "gpt-oss-120b-medium" },
73
+ { id: "gemini-3-flash" },
74
+ ],
75
+ gh: [
76
+ { id: "gpt-5" },
77
+ { id: "gpt-5-mini" },
78
+ { id: "gpt-5.1-codex" },
79
+ { id: "gpt-5.1-codex-max" },
80
+ { id: "gpt-4.1" },
81
+ { id: "claude-4.5-sonnet" },
82
+ { id: "claude-4.5-opus" },
83
+ { id: "claude-4.5-haiku" },
84
+ { id: "gemini-3-pro" },
85
+ { id: "gemini-3-flash" },
86
+ { id: "gemini-2.5-pro" },
87
+ { id: "grok-code-fast-1" },
88
+ ],
89
+ kr: [
90
+ { id: "claude-sonnet-5" },
91
+ { id: "claude-sonnet-4.5" },
92
+ { id: "claude-haiku-4.5" },
93
+ ],
94
+ openai: [
95
+ { id: "gpt-4o" },
96
+ { id: "gpt-4o-mini" },
97
+ { id: "gpt-4-turbo" },
98
+ { id: "o1" },
99
+ { id: "o1-mini" },
100
+ ],
101
+ anthropic: [
102
+ { id: "claude-sonnet-4-20250514" },
103
+ { id: "claude-opus-4-20250514" },
104
+ { id: "claude-3-5-sonnet-20241022" },
105
+ ],
106
+ gemini: [
107
+ { id: "gemini-3.8-flash" },
108
+ { id: "gemini-3.7-flash" },
109
+ { id: "gemini-3-pro-preview" },
110
+ { id: "gemini-2.5-pro" },
111
+ { id: "gemini-2.5-flash" },
112
+ { id: "gemini-2.5-flash-lite" },
113
+ ],
114
+ "opencode-go": [
115
+ { id: "minimax-m3" },
116
+ { id: "kimi-k3" },
117
+ { id: "kimi-k2.7-code" },
118
+ { id: "glm-5.3" },
119
+ { id: "deepseek-v4-pro" },
120
+ { id: "deepseek-v4-flash" },
121
+ { id: "qwen3.8-max" },
122
+ ],
123
+ openrouter: [
124
+ { id: "auto" },
125
+ ],
126
+ glm: [
127
+ { id: "glm-4.7" },
128
+ { id: "glm-4.6v" },
129
+ ],
130
+ kimi: [
131
+ { id: "kimi-latest" },
132
+ ],
133
+ minimax: [
134
+ { id: "MiniMax-M2.1" },
135
+ ],
136
+ };
137
+
138
+ // Provider definitions
139
+ const OAUTH_PROVIDERS = {
140
+ claude: { id: "claude", alias: "cc", name: "Claude Code" },
141
+ codex: { id: "codex", alias: "cx", name: "OpenAI Codex" },
142
+ "gemini-cli": { id: "gemini-cli", alias: "gc", name: "Gemini CLI" },
143
+ github: { id: "github", alias: "gh", name: "GitHub Copilot" },
144
+ antigravity: { id: "antigravity", alias: "ag", name: "Antigravity" },
145
+ iflow: { id: "iflow", alias: "if", name: "iFlow AI" },
146
+ qwen: { id: "qwen", alias: "qw", name: "Qwen Code" },
147
+ kiro: { id: "kiro", alias: "kr", name: "Kiro AI" },
148
+ };
149
+
150
+ const APIKEY_PROVIDERS = {
151
+ openrouter: { id: "openrouter", name: "OpenRouter" },
152
+ glm: { id: "glm", name: "GLM Coding" },
153
+ minimax: { id: "minimax", name: "Minimax Coding" },
154
+ kimi: { id: "kimi", name: "Kimi" },
155
+ openai: { id: "openai", name: "OpenAI" },
156
+ anthropic: { id: "anthropic", name: "Anthropic" },
157
+ gemini: { id: "gemini", name: "Gemini" },
158
+ "opencode-go": { id: "opencode-go", name: "OpenCode Go" },
159
+ };
160
+
161
+ const ALL_PROVIDERS = { ...OAUTH_PROVIDERS, ...APIKEY_PROVIDERS };
162
+
163
+ /**
164
+ * Get auth type for provider
165
+ * @param {string} providerId - Provider ID
166
+ * @returns {string} "oauth" or "apikey"
167
+ */
168
+ function getAuthType(providerId) {
169
+ return OAUTH_PROVIDERS[providerId] ? "oauth" : "apikey";
170
+ }
171
+
172
+ /**
173
+ * Count connections by provider
174
+ * @param {Array} connections - Array of connection objects
175
+ * @returns {Object} Map of providerId -> count
176
+ */
177
+ function countConnectionsByProvider(connections) {
178
+ const counts = {};
179
+ connections.forEach(conn => {
180
+ const providerId = conn.provider || conn.providerId;
181
+ counts[providerId] = (counts[providerId] || 0) + 1;
182
+ });
183
+ return counts;
184
+ }
185
+
186
+ /**
187
+ * Show main providers menu
188
+ * @param {Array<string>} breadcrumb - Breadcrumb path
189
+ */
190
+ async function showProvidersMenu(breadcrumb = []) {
191
+ // Build provider items list
192
+ const providerItems = [];
193
+
194
+ Object.values(OAUTH_PROVIDERS).forEach(provider => {
195
+ providerItems.push({
196
+ provider,
197
+ authType: "oauth",
198
+ label: (data) => {
199
+ const count = data.counts[provider.id] || 0;
200
+ return `${provider.name} (OAuth) - ${count} Connected`;
201
+ },
202
+ action: async (data) => {
203
+ await showProviderDetail(provider.id, "oauth", data.connections, [...breadcrumb, provider.name]);
204
+ return true;
205
+ }
206
+ });
207
+ });
208
+
209
+ Object.values(APIKEY_PROVIDERS).forEach(provider => {
210
+ providerItems.push({
211
+ provider,
212
+ authType: "apikey",
213
+ label: (data) => {
214
+ const count = data.counts[provider.id] || 0;
215
+ return `${provider.name} (API) - ${count} Connected`;
216
+ },
217
+ action: async (data) => {
218
+ await showProviderDetail(provider.id, "apikey", data.connections, [...breadcrumb, provider.name]);
219
+ return true;
220
+ }
221
+ });
222
+ });
223
+
224
+ // Custom provider nodes section
225
+ providerItems.push({
226
+ label: () => `${COLORS.dim}── Custom Providers ──${COLORS.reset}`,
227
+ action: async () => true, // separator, no-op
228
+ isSeparator: true,
229
+ });
230
+ providerItems.push({
231
+ label: (data) => {
232
+ const count = data.nodeCount || 0;
233
+ return `Custom Providers - ${count} Configured`;
234
+ },
235
+ action: async () => {
236
+ await showCustomProvidersMenu([...breadcrumb, "Custom Providers"]);
237
+ return true;
238
+ }
239
+ });
240
+
241
+ await showMenuWithBack({
242
+ title: "šŸ”Œ Providers Management",
243
+ breadcrumb,
244
+ refresh: async () => {
245
+ const [provRes, nodeRes] = await Promise.all([api.getProviders(), api.getProviderNodes()]);
246
+ if (!provRes.success) {
247
+ showStatus(`Failed to fetch providers: ${provRes.error}`, "error");
248
+ await pause();
249
+ return null;
250
+ }
251
+ const connections = provRes.data.connections || [];
252
+ const nodes = nodeRes.success ? (nodeRes.data.nodes || nodeRes.data || []) : [];
253
+ return {
254
+ connections,
255
+ counts: countConnectionsByProvider(connections),
256
+ nodeCount: nodes.length,
257
+ };
258
+ },
259
+ items: providerItems
260
+ });
261
+ }
262
+
263
+ /**
264
+ * Build provider header with alias and models
265
+ * @param {string} providerId - Provider ID
266
+ * @returns {string}
267
+ */
268
+ function buildProviderHeader(providerId) {
269
+ const provider = ALL_PROVIDERS[providerId];
270
+ const alias = provider.alias || providerId;
271
+
272
+ const lines = [];
273
+ lines.push(`Alias: ${COLORS.cyan}${alias}${COLORS.reset}`);
274
+
275
+ // Get models from static config
276
+ const models = PROVIDER_MODELS[alias] || [];
277
+ if (models.length > 0) {
278
+ const modelList = models
279
+ .slice(0, 5)
280
+ .map(m => `${alias}/${m.id}`)
281
+ .join(", ");
282
+ const more = models.length > 5 ? ` (+${models.length - 5} more)` : "";
283
+ lines.push(`Models: ${COLORS.dim}${modelList}${more}${COLORS.reset}`);
284
+ } else {
285
+ lines.push(`Models: ${COLORS.dim}No models configured${COLORS.reset}`);
286
+ }
287
+
288
+ return lines.join("\n");
289
+ }
290
+
291
+ /**
292
+ * Show provider detail with connections and actions
293
+ * @param {string} providerId - Provider ID
294
+ * @param {string} authType - "oauth" or "apikey"
295
+ * @param {Array} allConnections - All connections
296
+ * @param {Array<string>} breadcrumb - Breadcrumb path
297
+ */
298
+ async function showProviderDetail(providerId, authType, allConnections, breadcrumb = []) {
299
+ const provider = ALL_PROVIDERS[providerId];
300
+ const { showListMenu } = require("../utils/menuHelper");
301
+
302
+ await showListMenu({
303
+ title: `šŸ”Œ ${provider.name} (${authType.toUpperCase()})`,
304
+ breadcrumb,
305
+ backLabel: "← Back to Providers",
306
+ headerContent: buildProviderHeader(providerId),
307
+ fetchItems: async () => {
308
+ const response = await api.getProviders();
309
+ if (response.success) {
310
+ allConnections.length = 0;
311
+ allConnections.push(...(response.data.connections || []));
312
+ }
313
+ const providerConns = allConnections.filter(conn =>
314
+ (conn.provider || conn.providerId) === providerId
315
+ );
316
+ return { items: providerConns };
317
+ },
318
+ formatItem: (conn) => {
319
+ const status = conn.testStatus === "active" ? "āœ“" : conn.testStatus === "error" ? "āœ—" : "?";
320
+ const name = conn.name || conn.email || conn.displayName || "Unnamed";
321
+ return `${name} (${status})`;
322
+ },
323
+ onSelect: async (conn) => {
324
+ await showConnectionActions(conn, providerId, breadcrumb);
325
+ },
326
+ createAction: {
327
+ label: "Add New Connection",
328
+ action: async () => {
329
+ await handleAddConnection(providerId, authType);
330
+ }
331
+ }
332
+ });
333
+ }
334
+
335
+ /**
336
+ * Show actions for a specific connection
337
+ * @param {Object} connection - Connection object
338
+ * @param {string} providerId - Provider ID
339
+ * @param {Array<string>} breadcrumb - Breadcrumb path
340
+ */
341
+ async function showConnectionActions(connection, providerId, breadcrumb = []) {
342
+ const name = connection.name || connection.email || connection.displayName || "Unnamed";
343
+ const status = connection.testStatus === "active" ? "āœ“ Active" :
344
+ connection.testStatus === "error" ? "āœ— Error" : "? Unknown";
345
+
346
+ await showMenuWithBack({
347
+ title: `šŸ”Œ ${name}`,
348
+ breadcrumb: [...breadcrumb, name],
349
+ headerContent: `Connection: ${name}\nStatus: ${status}`,
350
+ items: [
351
+ {
352
+ label: "Rename Connection",
353
+ action: async () => {
354
+ const newName = await prompt(`New name (current: ${name}): `);
355
+ if (newName && newName.trim()) {
356
+ showStatus("Renaming connection...", "info");
357
+ const result = await api.updateConnection(connection.id, { name: newName.trim() });
358
+ if (result.success) {
359
+ showStatus("Connection renamed!", "success");
360
+ connection.name = newName.trim();
361
+ } else {
362
+ showStatus(`Rename failed: ${result.error}`, "error");
363
+ }
364
+ await pause();
365
+ }
366
+ return true;
367
+ }
368
+ },
369
+ {
370
+ label: "Test Connection",
371
+ action: async () => {
372
+ showStatus("Testing connection...", "info");
373
+ const result = await api.testConnection(connection.id);
374
+ if (result.success) {
375
+ showStatus("Connection is working!", "success");
376
+ } else {
377
+ showStatus(`Test failed: ${result.error}`, "error");
378
+ }
379
+ await pause();
380
+ return true;
381
+ }
382
+ },
383
+ {
384
+ label: "Delete Connection",
385
+ action: async () => {
386
+ const confirmed = await confirm(`Delete connection "${name}"?`);
387
+ if (confirmed) {
388
+ const result = await api.deleteConnection(connection.id);
389
+ if (result.success) {
390
+ showStatus("Connection deleted!", "success");
391
+ } else {
392
+ showStatus(`Delete failed: ${result.error}`, "error");
393
+ }
394
+ await pause();
395
+ return false; // Exit menu after delete
396
+ }
397
+ return true;
398
+ }
399
+ }
400
+ ]
401
+ });
402
+ }
403
+
404
+ /**
405
+ * Handle adding new connection
406
+ * @param {string} providerId - Provider ID
407
+ * @param {string} authType - "oauth" or "apikey"
408
+ */
409
+ // Providers that use Device Code Flow (terminal-based polling)
410
+ const DEVICE_CODE_PROVIDERS = ["github", "qwen", "kiro"];
411
+
412
+ /**
413
+ * Handle adding new connection - auto-detect flow type
414
+ * @param {string} providerId - Provider ID
415
+ * @param {string} authType - "oauth" or "apikey"
416
+ */
417
+ async function handleAddConnection(providerId, authType) {
418
+ if (authType === "apikey") {
419
+ await handleAddApiKeyConnection(providerId);
420
+ } else {
421
+ // OAuth: auto-detect flow type based on provider
422
+ if (DEVICE_CODE_PROVIDERS.includes(providerId)) {
423
+ // Device Code Flow for GitHub, Qwen, Kiro
424
+ await handleAddDeviceCodeConnection(providerId);
425
+ } else {
426
+ // Authorization Code Flow for Claude, Codex, Gemini, etc.
427
+ await handleAddOAuthConnection(providerId);
428
+ }
429
+ }
430
+ }
431
+
432
+ /**
433
+ * Handle adding API Key connection
434
+ * @param {string} providerId - Provider ID
435
+ */
436
+ async function handleAddApiKeyConnection(providerId) {
437
+ clearScreen();
438
+ const provider = ALL_PROVIDERS[providerId];
439
+ console.log(`\nāž• Add ${provider.name} API Key Connection\n`);
440
+
441
+ const name = await prompt("Connection Name: ");
442
+ if (!name) {
443
+ showStatus("Cancelled", "warning");
444
+ await pause();
445
+ return;
446
+ }
447
+
448
+ const apiKey = await prompt("API Key: ");
449
+ if (!apiKey) {
450
+ showStatus("Cancelled", "warning");
451
+ await pause();
452
+ return;
453
+ }
454
+
455
+ showStatus("Creating connection...", "info");
456
+
457
+ const result = await api.createApiKeyProvider({
458
+ provider: providerId,
459
+ name,
460
+ apiKey
461
+ });
462
+
463
+ if (result.success) {
464
+ showStatus("āœ“ Connection created successfully!", "success");
465
+ } else {
466
+ showStatus(`āœ— Failed: ${result.error}`, "error");
467
+ }
468
+
469
+ await pause();
470
+ }
471
+
472
+ /**
473
+ * Handle adding OAuth Authorization Code connection
474
+ * User opens URL manually and pastes callback URL
475
+ * @param {string} providerId - Provider ID
476
+ */
477
+ async function handleAddOAuthConnection(providerId) {
478
+ clearScreen();
479
+ const provider = ALL_PROVIDERS[providerId];
480
+
481
+ // Step 1: Get auth URL
482
+ showStatus("Requesting authorization URL...", "info");
483
+ const authResult = await api.getOAuthAuthUrl(providerId);
484
+
485
+ if (!authResult.success) {
486
+ showStatus(`Failed: ${authResult.error}`, "error");
487
+ await pause();
488
+ return;
489
+ }
490
+
491
+ const authData = authResult.data || authResult;
492
+ const authUrl = authData.authUrl;
493
+ const codeVerifier = authData.codeVerifier;
494
+ const state = authData.state;
495
+ const redirectUri = authData.redirectUri;
496
+
497
+ if (!authUrl) {
498
+ showStatus("Failed: No auth URL received", "error");
499
+ await pause();
500
+ return;
501
+ }
502
+
503
+ // Step 2: Show URL and instructions
504
+ clearScreen();
505
+ showHeader("šŸ” OAuth Login", `Providers > ${provider.name} > Add Connection`);
506
+
507
+ console.log(` ${COLORS.bold}${COLORS.cyan}1.${COLORS.reset} Open this URL in your browser:`);
508
+ console.log(` ${COLORS.dim}${authUrl}${COLORS.reset}`);
509
+ if (copyToClipboard(authUrl)) {
510
+ console.log(` \x1b[32māœ“ Link copied to clipboard!\x1b[0m`);
511
+ }
512
+ console.log();
513
+ console.log(` ${COLORS.bold}${COLORS.cyan}2.${COLORS.reset} Complete authorization in browser`);
514
+ console.log();
515
+ console.log(` ${COLORS.bold}${COLORS.cyan}3.${COLORS.reset} Copy the callback URL from address bar`);
516
+ console.log(` ${COLORS.dim}(looks like: http://localhost:20128/callback?code=...)${COLORS.reset}`);
517
+ console.log();
518
+
519
+ const callbackUrl = await prompt(" Paste callback URL: ");
520
+ if (!callbackUrl) {
521
+ showStatus("Cancelled", "warning");
522
+ await pause();
523
+ return;
524
+ }
525
+
526
+ // Step 3: Parse callback URL and extract code
527
+ let code, urlState, error;
528
+ try {
529
+ const url = new URL(callbackUrl.trim());
530
+ code = url.searchParams.get("code");
531
+ urlState = url.searchParams.get("state");
532
+ error = url.searchParams.get("error");
533
+
534
+ if (error) {
535
+ const errorDesc = url.searchParams.get("error_description") || error;
536
+ showStatus(`Authorization failed: ${errorDesc}`, "error");
537
+ await pause();
538
+ return;
539
+ }
540
+
541
+ if (!code) {
542
+ showStatus("No authorization code found in URL", "error");
543
+ await pause();
544
+ return;
545
+ }
546
+ } catch (err) {
547
+ showStatus("Invalid URL format", "error");
548
+ await pause();
549
+ return;
550
+ }
551
+
552
+ // Step 4: Exchange code for tokens
553
+ console.log();
554
+ showStatus("Exchanging code for tokens...", "info");
555
+ const exchangeResult = await api.exchangeOAuthCode(providerId, {
556
+ code,
557
+ redirectUri,
558
+ codeVerifier,
559
+ state: urlState || state
560
+ });
561
+
562
+ if (exchangeResult.success) {
563
+ showStatus("Connection created successfully!", "success");
564
+ } else {
565
+ showStatus(`Failed: ${exchangeResult.error}`, "error");
566
+ }
567
+
568
+ await pause();
569
+ }
570
+
571
+ /**
572
+ * Handle adding OAuth Device Code connection
573
+ * @param {string} providerId - Provider ID
574
+ */
575
+ async function handleAddDeviceCodeConnection(providerId) {
576
+ clearScreen();
577
+ const provider = ALL_PROVIDERS[providerId];
578
+
579
+ // Step 1: Request device code
580
+ showStatus("Requesting device code...", "info");
581
+ const deviceResult = await api.getOAuthDeviceCode(providerId);
582
+
583
+ if (!deviceResult.success) {
584
+ showStatus(`Failed: ${deviceResult.error}`, "error");
585
+ await pause();
586
+ return;
587
+ }
588
+
589
+ const deviceData = deviceResult.data || deviceResult;
590
+ const device_code = deviceData.device_code;
591
+ const user_code = deviceData.user_code;
592
+ const verification_uri = deviceData.verification_uri;
593
+ const verification_uri_complete = deviceData.verification_uri_complete;
594
+ const codeVerifier = deviceData.codeVerifier;
595
+ const extraData = deviceData.extraData || deviceData;
596
+
597
+ if (!device_code) {
598
+ showStatus("Failed: No device code received", "error");
599
+ await pause();
600
+ return;
601
+ }
602
+
603
+ // Step 2: Show instructions
604
+ clearScreen();
605
+ const deviceUrl = verification_uri_complete || verification_uri;
606
+ showHeader("šŸ“± Device Login", `Providers > ${provider.name} > Add Connection`);
607
+
608
+ console.log(` ${COLORS.bold}${COLORS.cyan}1.${COLORS.reset} Open: ${COLORS.dim}${deviceUrl}${COLORS.reset}`);
609
+ if (copyToClipboard(deviceUrl)) {
610
+ console.log(` \x1b[32māœ“ Link copied to clipboard!\x1b[0m`);
611
+ }
612
+ console.log();
613
+ if (!verification_uri_complete && user_code) {
614
+ console.log(` ${COLORS.bold}${COLORS.cyan}2.${COLORS.reset} Enter code: ${COLORS.bold}${user_code}${COLORS.reset}`);
615
+ console.log();
616
+ }
617
+ console.log(` ${COLORS.dim}Waiting for authorization...${COLORS.reset}`);
618
+ console.log();
619
+
620
+ // Step 3: Poll for token
621
+ const maxAttempts = 60; // 5 minutes (5s interval)
622
+ for (let i = 0; i < maxAttempts; i++) {
623
+ await new Promise(resolve => setTimeout(resolve, 5000));
624
+
625
+ const pollResult = await api.pollOAuthToken(providerId, {
626
+ deviceCode: device_code,
627
+ codeVerifier,
628
+ extraData
629
+ });
630
+
631
+ if (pollResult.success) {
632
+ showStatus("\nConnection created successfully!", "success");
633
+ await pause();
634
+ return;
635
+ }
636
+
637
+ // Check if still pending (pending flag is at root level, not in data)
638
+ const isPending = pollResult.pending || pollResult.error === "authorization_pending" || pollResult.error === "slow_down";
639
+ if (!isPending) {
640
+ showStatus(`\nFailed: ${pollResult.error || "Unknown error"}`, "error");
641
+ await pause();
642
+ return;
643
+ }
644
+
645
+ process.stdout.write(".");
646
+ }
647
+
648
+ showStatus("\nTimeout waiting for authorization", "error");
649
+ await pause();
650
+ }
651
+
652
+ // ============================================================================
653
+ // CUSTOM PROVIDERS (provider nodes)
654
+ // ============================================================================
655
+
656
+ const CUSTOM_NODE_TYPES = ["openai-compatible", "anthropic-compatible"];
657
+ const OPENAI_API_TYPES = ["chat", "responses"];
658
+
659
+ /**
660
+ * Show custom providers section in main providers menu
661
+ * @param {Array} nodes - List of provider nodes
662
+ * @param {Array} connections - All connections
663
+ * @param {Array<string>} breadcrumb
664
+ */
665
+ async function showCustomProvidersMenu(breadcrumb = []) {
666
+ const { showListMenu } = require("../utils/menuHelper");
667
+
668
+ await showListMenu({
669
+ title: "šŸ”§ Custom Providers",
670
+ breadcrumb,
671
+ backLabel: "← Back to Providers",
672
+ fetchItems: async () => {
673
+ const res = await api.getProviderNodes();
674
+ if (!res.success) return { items: [] };
675
+ return { items: res.data.nodes || res.data || [] };
676
+ },
677
+ formatItem: (node) => `[${node.prefix}] ${node.name} (${node.type})`,
678
+ onSelect: async (node) => {
679
+ await showCustomNodeDetail(node, [...breadcrumb, node.name]);
680
+ },
681
+ createAction: {
682
+ label: "āž• Add Custom Provider",
683
+ action: async () => {
684
+ await handleAddCustomNode();
685
+ }
686
+ }
687
+ });
688
+ }
689
+
690
+ /**
691
+ * Show detail menu for a custom provider node
692
+ */
693
+ async function showCustomNodeDetail(node, breadcrumb = []) {
694
+ await showMenuWithBack({
695
+ title: `šŸ”§ ${node.name}`,
696
+ breadcrumb,
697
+ headerContent: [
698
+ `Type: ${node.type}`,
699
+ `Prefix: ${COLORS.cyan}${node.prefix}${COLORS.reset}`,
700
+ `Base URL: ${COLORS.dim}${node.baseUrl}${COLORS.reset}`,
701
+ ].join("\n"),
702
+ items: [
703
+ {
704
+ label: "Connections",
705
+ action: async () => {
706
+ await showCustomNodeConnections(node, breadcrumb);
707
+ return true;
708
+ }
709
+ },
710
+ {
711
+ label: "Edit Node",
712
+ action: async () => {
713
+ await handleEditCustomNode(node);
714
+ return true;
715
+ }
716
+ },
717
+ {
718
+ label: "Delete Node",
719
+ action: async () => {
720
+ const confirmed = await confirm(`Delete "${node.name}" and all its connections?`);
721
+ if (confirmed) {
722
+ const res = await api.deleteProviderNode(node.id);
723
+ if (res.success) {
724
+ showStatus("Node deleted!", "success");
725
+ } else {
726
+ showStatus(`Delete failed: ${res.error}`, "error");
727
+ }
728
+ await pause();
729
+ return false;
730
+ }
731
+ return true;
732
+ }
733
+ }
734
+ ]
735
+ });
736
+ }
737
+
738
+ /**
739
+ * Show connections for a custom provider node
740
+ */
741
+ async function showCustomNodeConnections(node, breadcrumb = []) {
742
+ const { showListMenu } = require("../utils/menuHelper");
743
+
744
+ await showListMenu({
745
+ title: `šŸ”Œ ${node.name} – Connections`,
746
+ breadcrumb,
747
+ backLabel: "← Back",
748
+ fetchItems: async () => {
749
+ const res = await api.getProviders();
750
+ if (!res.success) return { items: [] };
751
+ const all = res.data.connections || [];
752
+ const items = all.filter(c => c.provider === node.id);
753
+ return { items };
754
+ },
755
+ formatItem: (conn) => {
756
+ const status = conn.testStatus === "active" ? "āœ“" : conn.testStatus === "error" ? "āœ—" : "?";
757
+ return `${conn.name || "Unnamed"} (${status})`;
758
+ },
759
+ onSelect: async (conn) => {
760
+ await showConnectionActions(conn, node.id, breadcrumb);
761
+ },
762
+ createAction: {
763
+ label: "Add API Key Connection",
764
+ action: async () => {
765
+ await handleAddCustomNodeConnection(node);
766
+ }
767
+ }
768
+ });
769
+ }
770
+
771
+ /**
772
+ * Add API key connection to a custom provider node
773
+ */
774
+ async function handleAddCustomNodeConnection(node) {
775
+ clearScreen();
776
+ console.log(`\nāž• Add Connection to ${node.name}\n`);
777
+
778
+ const name = await prompt("Connection Name: ");
779
+ if (!name) { showStatus("Cancelled", "warning"); await pause(); return; }
780
+
781
+ const apiKey = await prompt("API Key: ");
782
+ if (!apiKey) { showStatus("Cancelled", "warning"); await pause(); return; }
783
+
784
+ showStatus("Creating connection...", "info");
785
+ const res = await api.createApiKeyProvider({ provider: node.id, name, apiKey });
786
+
787
+ showStatus(res.success ? "āœ“ Connection created!" : `āœ— Failed: ${res.error}`, res.success ? "success" : "error");
788
+ await pause();
789
+ }
790
+
791
+ /**
792
+ * Handle adding a new custom provider node
793
+ */
794
+ async function handleAddCustomNode() {
795
+ clearScreen();
796
+ console.log("\nāž• Add Custom Provider\n");
797
+
798
+ // Step 1: Select type
799
+ const typeChoices = CUSTOM_NODE_TYPES.map((t, i) => ` ${i + 1}. ${t}`).join("\n");
800
+ console.log(`Select type:\n${typeChoices}\n`);
801
+ const typeInput = await prompt("Type (1/2): ");
802
+ const typeIdx = parseInt(typeInput) - 1;
803
+ if (isNaN(typeIdx) || !CUSTOM_NODE_TYPES[typeIdx]) {
804
+ showStatus("Cancelled", "warning"); await pause(); return;
805
+ }
806
+ const type = CUSTOM_NODE_TYPES[typeIdx];
807
+
808
+ // Step 2: Inputs
809
+ const name = await prompt("Name: ");
810
+ if (!name) { showStatus("Cancelled", "warning"); await pause(); return; }
811
+
812
+ const prefix = await prompt("Prefix (used in model IDs, e.g. myapi): ");
813
+ if (!prefix) { showStatus("Cancelled", "warning"); await pause(); return; }
814
+
815
+ const baseUrl = await prompt("Base URL (e.g. https://api.example.com/v1): ");
816
+ if (!baseUrl) { showStatus("Cancelled", "warning"); await pause(); return; }
817
+
818
+ // Step 3: API type (OpenAI only)
819
+ let apiType;
820
+ if (type === "openai-compatible") {
821
+ const apiTypeChoices = OPENAI_API_TYPES.map((t, i) => ` ${i + 1}. ${t}`).join("\n");
822
+ console.log(`\nAPI Type:\n${apiTypeChoices}\n`);
823
+ const apiTypeInput = await prompt("API Type (1/2, default 1): ");
824
+ const apiTypeIdx = parseInt(apiTypeInput) - 1;
825
+ apiType = OPENAI_API_TYPES[apiTypeIdx] || "chat";
826
+ }
827
+
828
+ showStatus("Creating provider node...", "info");
829
+ const body = { name, prefix, baseUrl, type, ...(apiType && { apiType }) };
830
+ const res = await api.createProviderNode(body);
831
+
832
+ showStatus(res.success ? "āœ“ Provider created!" : `āœ— Failed: ${res.error}`, res.success ? "success" : "error");
833
+ await pause();
834
+ }
835
+
836
+ /**
837
+ * Handle editing a custom provider node
838
+ */
839
+ async function handleEditCustomNode(node) {
840
+ clearScreen();
841
+ console.log(`\nāœļø Edit ${node.name}\n`);
842
+ console.log(`${COLORS.dim}Leave blank to keep current value${COLORS.reset}\n`);
843
+
844
+ const name = await prompt(`Name (${node.name}): `);
845
+ const baseUrl = await prompt(`Base URL (${node.baseUrl}): `);
846
+ const prefix = await prompt(`Prefix (${node.prefix}): `);
847
+
848
+ const updates = {};
849
+ if (name && name.trim()) updates.name = name.trim();
850
+ if (baseUrl && baseUrl.trim()) updates.baseUrl = baseUrl.trim();
851
+ if (prefix && prefix.trim()) updates.prefix = prefix.trim();
852
+
853
+ if (!Object.keys(updates).length) {
854
+ showStatus("No changes", "warning"); await pause(); return;
855
+ }
856
+
857
+ showStatus("Updating...", "info");
858
+ const res = await api.updateProviderNode(node.id, updates);
859
+ if (res.success) {
860
+ Object.assign(node, updates);
861
+ showStatus("āœ“ Updated!", "success");
862
+ } else {
863
+ showStatus(`āœ— Failed: ${res.error}`, "error");
864
+ }
865
+ await pause();
866
+ }
867
+
868
+ module.exports = { showProvidersMenu };