vansrouter 0.91.20 → 0.91.21

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