@johpaz/hive 1.7.2 → 1.7.3

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 (427) hide show
  1. package/README.md +178 -36
  2. package/dist/hive.js +315124 -0
  3. package/package.json +11 -3
  4. package/packages/core/src/index.ts +0 -1
  5. package/.dockerignore +0 -9
  6. package/CONTRIBUTING.md +0 -44
  7. package/Dockerfile +0 -67
  8. package/docker-compose.yml +0 -19
  9. package/packages/cli/package.json +0 -28
  10. package/packages/cli/src/commands/agent-run.ts +0 -168
  11. package/packages/cli/src/commands/agents.ts +0 -398
  12. package/packages/cli/src/commands/chat.ts +0 -142
  13. package/packages/cli/src/commands/config.ts +0 -50
  14. package/packages/cli/src/commands/cron.ts +0 -161
  15. package/packages/cli/src/commands/dev.ts +0 -95
  16. package/packages/cli/src/commands/doctor.ts +0 -133
  17. package/packages/cli/src/commands/gateway.ts +0 -422
  18. package/packages/cli/src/commands/logs.ts +0 -57
  19. package/packages/cli/src/commands/mcp.ts +0 -175
  20. package/packages/cli/src/commands/message.ts +0 -77
  21. package/packages/cli/src/commands/onboard.ts +0 -1696
  22. package/packages/cli/src/commands/security.ts +0 -144
  23. package/packages/cli/src/commands/service.ts +0 -50
  24. package/packages/cli/src/commands/sessions.ts +0 -116
  25. package/packages/cli/src/commands/skills.ts +0 -187
  26. package/packages/cli/src/commands/update.ts +0 -25
  27. package/packages/cli/src/index.ts +0 -190
  28. package/packages/cli/src/utils/token.ts +0 -6
  29. package/packages/code-bridge/README.md +0 -78
  30. package/packages/code-bridge/package.json +0 -18
  31. package/packages/code-bridge/src/index.ts +0 -95
  32. package/packages/code-bridge/src/process-manager.ts +0 -212
  33. package/packages/code-bridge/src/schemas.ts +0 -133
  34. package/packages/core/package.json +0 -55
  35. package/packages/core/src/agent/agent-loop.ts +0 -520
  36. package/packages/core/src/agent/compaction.ts +0 -183
  37. package/packages/core/src/agent/context-compiler.ts +0 -544
  38. package/packages/core/src/agent/context-guard.ts +0 -91
  39. package/packages/core/src/agent/conversation-store.ts +0 -193
  40. package/packages/core/src/agent/curator.ts +0 -158
  41. package/packages/core/src/agent/hooks.ts +0 -166
  42. package/packages/core/src/agent/llm-client.ts +0 -503
  43. package/packages/core/src/agent/native-tools.ts +0 -31
  44. package/packages/core/src/agent/playbook-selector.ts +0 -143
  45. package/packages/core/src/agent/prompt-builder.ts +0 -167
  46. package/packages/core/src/agent/providers/index.ts +0 -186
  47. package/packages/core/src/agent/providers.ts +0 -1
  48. package/packages/core/src/agent/reflector.ts +0 -200
  49. package/packages/core/src/agent/service.ts +0 -266
  50. package/packages/core/src/agent/skill-selector.ts +0 -413
  51. package/packages/core/src/agent/stuck-loop.ts +0 -133
  52. package/packages/core/src/agent/tool-selector.ts +0 -623
  53. package/packages/core/src/agent/tracer.ts +0 -102
  54. package/packages/core/src/canvas/canvas-manager.ts +0 -319
  55. package/packages/core/src/canvas/canvas-tools.ts +0 -420
  56. package/packages/core/src/canvas/emitter.ts +0 -119
  57. package/packages/core/src/canvas/index.ts +0 -2
  58. package/packages/core/src/channels/base.ts +0 -140
  59. package/packages/core/src/channels/discord.ts +0 -260
  60. package/packages/core/src/channels/index.ts +0 -7
  61. package/packages/core/src/channels/manager.ts +0 -383
  62. package/packages/core/src/channels/slack.ts +0 -287
  63. package/packages/core/src/channels/telegram.ts +0 -552
  64. package/packages/core/src/channels/webchat.ts +0 -139
  65. package/packages/core/src/channels/whatsapp.ts +0 -375
  66. package/packages/core/src/config/index.ts +0 -12
  67. package/packages/core/src/config/loader.ts +0 -529
  68. package/packages/core/src/events/agent-bus.ts +0 -460
  69. package/packages/core/src/events/event-bus.ts +0 -169
  70. package/packages/core/src/gateway/helpers/cors.ts +0 -32
  71. package/packages/core/src/gateway/helpers/index.ts +0 -4
  72. package/packages/core/src/gateway/helpers/narration.ts +0 -60
  73. package/packages/core/src/gateway/helpers/path.ts +0 -13
  74. package/packages/core/src/gateway/helpers/redact.ts +0 -61
  75. package/packages/core/src/gateway/index.ts +0 -5
  76. package/packages/core/src/gateway/initializer.ts +0 -332
  77. package/packages/core/src/gateway/lane-queue.ts +0 -169
  78. package/packages/core/src/gateway/resolver.ts +0 -108
  79. package/packages/core/src/gateway/router.ts +0 -124
  80. package/packages/core/src/gateway/routes/agents.ts +0 -187
  81. package/packages/core/src/gateway/routes/channels.ts +0 -203
  82. package/packages/core/src/gateway/routes/chat.ts +0 -241
  83. package/packages/core/src/gateway/routes/config.ts +0 -12
  84. package/packages/core/src/gateway/routes/cron.ts +0 -42
  85. package/packages/core/src/gateway/routes/ethics.ts +0 -46
  86. package/packages/core/src/gateway/routes/mcp.ts +0 -346
  87. package/packages/core/src/gateway/routes/models.ts +0 -93
  88. package/packages/core/src/gateway/routes/projects.ts +0 -179
  89. package/packages/core/src/gateway/routes/providers.ts +0 -192
  90. package/packages/core/src/gateway/routes/setup.ts +0 -267
  91. package/packages/core/src/gateway/routes/skills.ts +0 -70
  92. package/packages/core/src/gateway/routes/system.ts +0 -165
  93. package/packages/core/src/gateway/routes/tasks.ts +0 -44
  94. package/packages/core/src/gateway/routes/tools.ts +0 -35
  95. package/packages/core/src/gateway/routes/users.ts +0 -118
  96. package/packages/core/src/gateway/routes/voice.ts +0 -73
  97. package/packages/core/src/gateway/routes/workspace.ts +0 -281
  98. package/packages/core/src/gateway/server.ts +0 -1978
  99. package/packages/core/src/gateway/session.ts +0 -95
  100. package/packages/core/src/gateway/slash-commands.ts +0 -193
  101. package/packages/core/src/heartbeat/index.ts +0 -157
  102. package/packages/core/src/mcp/hot-reload.ts +0 -213
  103. package/packages/core/src/mcp/singleton.ts +0 -21
  104. package/packages/core/src/memory/index.ts +0 -1
  105. package/packages/core/src/memory/notes.ts +0 -68
  106. package/packages/core/src/plugins/api.ts +0 -128
  107. package/packages/core/src/plugins/index.ts +0 -2
  108. package/packages/core/src/plugins/loader.ts +0 -365
  109. package/packages/core/src/resilience/circuit-breaker.ts +0 -225
  110. package/packages/core/src/security/google-chat.ts +0 -269
  111. package/packages/core/src/security/index.ts +0 -192
  112. package/packages/core/src/security/pairing.ts +0 -250
  113. package/packages/core/src/security/rate-limit.ts +0 -270
  114. package/packages/core/src/security/signal.ts +0 -321
  115. package/packages/core/src/state/store.ts +0 -312
  116. package/packages/core/src/storage/crypto.ts +0 -101
  117. package/packages/core/src/storage/onboarding.ts +0 -1609
  118. package/packages/core/src/storage/schema.ts +0 -567
  119. package/packages/core/src/storage/seed.ts +0 -608
  120. package/packages/core/src/storage/sqlite.ts +0 -363
  121. package/packages/core/src/storage/usage.ts +0 -270
  122. package/packages/core/src/tools/agents/index.ts +0 -607
  123. package/packages/core/src/tools/bridge-events.ts +0 -26
  124. package/packages/core/src/tools/canvas/index.ts +0 -281
  125. package/packages/core/src/tools/cli/index.ts +0 -142
  126. package/packages/core/src/tools/codebridge/index.ts +0 -179
  127. package/packages/core/src/tools/core/index.ts +0 -257
  128. package/packages/core/src/tools/cron/index.ts +0 -373
  129. package/packages/core/src/tools/filesystem/fs-delete.ts +0 -78
  130. package/packages/core/src/tools/filesystem/fs-edit.ts +0 -106
  131. package/packages/core/src/tools/filesystem/fs-exists.ts +0 -63
  132. package/packages/core/src/tools/filesystem/fs-glob.ts +0 -108
  133. package/packages/core/src/tools/filesystem/fs-list.ts +0 -129
  134. package/packages/core/src/tools/filesystem/fs-read.ts +0 -72
  135. package/packages/core/src/tools/filesystem/fs-write.ts +0 -67
  136. package/packages/core/src/tools/filesystem/index.ts +0 -34
  137. package/packages/core/src/tools/filesystem/workspace-guard.ts +0 -62
  138. package/packages/core/src/tools/index.ts +0 -197
  139. package/packages/core/src/tools/projects/index.ts +0 -37
  140. package/packages/core/src/tools/projects/project-create.ts +0 -94
  141. package/packages/core/src/tools/projects/project-done.ts +0 -66
  142. package/packages/core/src/tools/projects/project-fail.ts +0 -66
  143. package/packages/core/src/tools/projects/project-list.ts +0 -96
  144. package/packages/core/src/tools/projects/project-update.ts +0 -72
  145. package/packages/core/src/tools/projects/task-create.ts +0 -68
  146. package/packages/core/src/tools/projects/task-evaluate.ts +0 -93
  147. package/packages/core/src/tools/projects/task-update.ts +0 -93
  148. package/packages/core/src/tools/search-knowledge/search-knowledge.ts +0 -155
  149. package/packages/core/src/tools/types.ts +0 -39
  150. package/packages/core/src/tools/voice/index.ts +0 -104
  151. package/packages/core/src/tools/web/browser-click.ts +0 -54
  152. package/packages/core/src/tools/web/browser-navigate.ts +0 -84
  153. package/packages/core/src/tools/web/browser-screenshot.ts +0 -54
  154. package/packages/core/src/tools/web/browser-type.ts +0 -60
  155. package/packages/core/src/tools/web/index.ts +0 -31
  156. package/packages/core/src/tools/web/web-fetch.ts +0 -78
  157. package/packages/core/src/tools/web/web-search.ts +0 -123
  158. package/packages/core/src/utils/benchmark.ts +0 -80
  159. package/packages/core/src/utils/crypto.ts +0 -73
  160. package/packages/core/src/utils/date.ts +0 -42
  161. package/packages/core/src/utils/index.ts +0 -5
  162. package/packages/core/src/utils/logger.ts +0 -389
  163. package/packages/core/src/utils/retry.ts +0 -70
  164. package/packages/core/src/utils/toon.ts +0 -356
  165. package/packages/core/src/voice/index.ts +0 -583
  166. package/packages/hive-ui/README.md +0 -52
  167. package/packages/hive-ui/components.json +0 -20
  168. package/packages/hive-ui/index.html +0 -30
  169. package/packages/hive-ui/package.json +0 -90
  170. package/packages/hive-ui/public/favicon.ico +0 -0
  171. package/packages/hive-ui/public/placeholder.svg +0 -1
  172. package/packages/hive-ui/src/App.tsx +0 -115
  173. package/packages/hive-ui/src/components/CronJobsPanel.tsx +0 -200
  174. package/packages/hive-ui/src/components/NavLink.tsx +0 -34
  175. package/packages/hive-ui/src/components/NotesPanel.tsx +0 -79
  176. package/packages/hive-ui/src/components/SystemMonitor.tsx +0 -270
  177. package/packages/hive-ui/src/components/UsageStatsPanel.tsx +0 -334
  178. package/packages/hive-ui/src/components/WelcomeDialog.tsx +0 -279
  179. package/packages/hive-ui/src/components/ui/accordion.tsx +0 -52
  180. package/packages/hive-ui/src/components/ui/alert-dialog.tsx +0 -104
  181. package/packages/hive-ui/src/components/ui/alert.tsx +0 -45
  182. package/packages/hive-ui/src/components/ui/aspect-ratio.tsx +0 -5
  183. package/packages/hive-ui/src/components/ui/avatar.tsx +0 -38
  184. package/packages/hive-ui/src/components/ui/badge.tsx +0 -29
  185. package/packages/hive-ui/src/components/ui/bee-loader.tsx +0 -68
  186. package/packages/hive-ui/src/components/ui/breadcrumb.tsx +0 -90
  187. package/packages/hive-ui/src/components/ui/button.tsx +0 -47
  188. package/packages/hive-ui/src/components/ui/calendar.tsx +0 -54
  189. package/packages/hive-ui/src/components/ui/card.tsx +0 -45
  190. package/packages/hive-ui/src/components/ui/carousel.tsx +0 -224
  191. package/packages/hive-ui/src/components/ui/chart.tsx +0 -303
  192. package/packages/hive-ui/src/components/ui/checkbox.tsx +0 -26
  193. package/packages/hive-ui/src/components/ui/collapsible.tsx +0 -9
  194. package/packages/hive-ui/src/components/ui/command.tsx +0 -133
  195. package/packages/hive-ui/src/components/ui/context-menu.tsx +0 -178
  196. package/packages/hive-ui/src/components/ui/dialog.tsx +0 -95
  197. package/packages/hive-ui/src/components/ui/drawer.tsx +0 -87
  198. package/packages/hive-ui/src/components/ui/dropdown-menu.tsx +0 -179
  199. package/packages/hive-ui/src/components/ui/form.tsx +0 -129
  200. package/packages/hive-ui/src/components/ui/hover-card.tsx +0 -27
  201. package/packages/hive-ui/src/components/ui/input-otp.tsx +0 -61
  202. package/packages/hive-ui/src/components/ui/input.tsx +0 -22
  203. package/packages/hive-ui/src/components/ui/label.tsx +0 -17
  204. package/packages/hive-ui/src/components/ui/menubar.tsx +0 -207
  205. package/packages/hive-ui/src/components/ui/navigation-menu.tsx +0 -120
  206. package/packages/hive-ui/src/components/ui/pagination.tsx +0 -80
  207. package/packages/hive-ui/src/components/ui/popover.tsx +0 -29
  208. package/packages/hive-ui/src/components/ui/progress.tsx +0 -23
  209. package/packages/hive-ui/src/components/ui/radio-group.tsx +0 -36
  210. package/packages/hive-ui/src/components/ui/resizable.tsx +0 -37
  211. package/packages/hive-ui/src/components/ui/scroll-area.tsx +0 -38
  212. package/packages/hive-ui/src/components/ui/select.tsx +0 -143
  213. package/packages/hive-ui/src/components/ui/separator.tsx +0 -20
  214. package/packages/hive-ui/src/components/ui/sheet.tsx +0 -107
  215. package/packages/hive-ui/src/components/ui/sidebar.tsx +0 -636
  216. package/packages/hive-ui/src/components/ui/skeleton.tsx +0 -7
  217. package/packages/hive-ui/src/components/ui/slider.tsx +0 -23
  218. package/packages/hive-ui/src/components/ui/sonner.tsx +0 -27
  219. package/packages/hive-ui/src/components/ui/switch.tsx +0 -27
  220. package/packages/hive-ui/src/components/ui/table.tsx +0 -72
  221. package/packages/hive-ui/src/components/ui/tabs.tsx +0 -53
  222. package/packages/hive-ui/src/components/ui/textarea.tsx +0 -21
  223. package/packages/hive-ui/src/components/ui/toast.tsx +0 -111
  224. package/packages/hive-ui/src/components/ui/toaster.tsx +0 -24
  225. package/packages/hive-ui/src/components/ui/toggle-group.tsx +0 -49
  226. package/packages/hive-ui/src/components/ui/toggle.tsx +0 -37
  227. package/packages/hive-ui/src/components/ui/tooltip.tsx +0 -28
  228. package/packages/hive-ui/src/components/ui/use-toast.ts +0 -3
  229. package/packages/hive-ui/src/hooks/use-mobile.tsx +0 -19
  230. package/packages/hive-ui/src/hooks/use-toast.ts +0 -186
  231. package/packages/hive-ui/src/hooks/useAgentConfig.ts +0 -25
  232. package/packages/hive-ui/src/hooks/useAgents.ts +0 -38
  233. package/packages/hive-ui/src/hooks/useBridge.ts +0 -38
  234. package/packages/hive-ui/src/hooks/useCanvas.ts +0 -24
  235. package/packages/hive-ui/src/hooks/useChannels.ts +0 -2
  236. package/packages/hive-ui/src/hooks/useEthics.ts +0 -51
  237. package/packages/hive-ui/src/hooks/useProviders.ts +0 -14
  238. package/packages/hive-ui/src/hooks/useTheme.ts +0 -29
  239. package/packages/hive-ui/src/hooks/useUserConfig.ts +0 -17
  240. package/packages/hive-ui/src/hooks/useWebSocket.ts +0 -12
  241. package/packages/hive-ui/src/index.css +0 -620
  242. package/packages/hive-ui/src/lib/api.ts +0 -100
  243. package/packages/hive-ui/src/lib/constants.ts +0 -6
  244. package/packages/hive-ui/src/lib/models.ts +0 -64
  245. package/packages/hive-ui/src/lib/swal.ts +0 -30
  246. package/packages/hive-ui/src/lib/utils.ts +0 -6
  247. package/packages/hive-ui/src/lib/websocket.ts +0 -7
  248. package/packages/hive-ui/src/main.tsx +0 -5
  249. package/packages/hive-ui/src/modules/agent-config/details/AgentDetailsEditor.tsx +0 -524
  250. package/packages/hive-ui/src/modules/agent-config/ethics/EthicsConflictDetector.tsx +0 -18
  251. package/packages/hive-ui/src/modules/agent-config/ethics/EthicsEditor.tsx +0 -19
  252. package/packages/hive-ui/src/modules/agent-config/ethics/EthicsRulesList.tsx +0 -36
  253. package/packages/hive-ui/src/modules/agent-config/ethics/EthicsTemplateGallery.tsx +0 -361
  254. package/packages/hive-ui/src/modules/agent-config/ethics/index.ts +0 -4
  255. package/packages/hive-ui/src/modules/agent-config/index.ts +0 -6
  256. package/packages/hive-ui/src/modules/agent-config/mcp/MCPServerAdd.tsx +0 -322
  257. package/packages/hive-ui/src/modules/agent-config/mcp/MCPServerCard.tsx +0 -93
  258. package/packages/hive-ui/src/modules/agent-config/mcp/MCPServerConfig.tsx +0 -427
  259. package/packages/hive-ui/src/modules/agent-config/mcp/MCPServerList.tsx +0 -85
  260. package/packages/hive-ui/src/modules/agent-config/mcp/MCPToolExplorer.tsx +0 -79
  261. package/packages/hive-ui/src/modules/agent-config/mcp/index.ts +0 -5
  262. package/packages/hive-ui/src/modules/agent-config/shared/ConfigEditorLayout.tsx +0 -30
  263. package/packages/hive-ui/src/modules/agent-config/shared/ConfigExporter.tsx +0 -26
  264. package/packages/hive-ui/src/modules/agent-config/shared/ConfigImporter.tsx +0 -25
  265. package/packages/hive-ui/src/modules/agent-config/shared/DiffViewer.tsx +0 -31
  266. package/packages/hive-ui/src/modules/agent-config/shared/MarkdownEditor.tsx +0 -32
  267. package/packages/hive-ui/src/modules/agent-config/shared/SaveStatusIndicator.tsx +0 -23
  268. package/packages/hive-ui/src/modules/agent-config/shared/ValidationPanel.tsx +0 -36
  269. package/packages/hive-ui/src/modules/agent-config/shared/index.ts +0 -7
  270. package/packages/hive-ui/src/modules/agent-config/skills/SkillCard.tsx +0 -81
  271. package/packages/hive-ui/src/modules/agent-config/skills/SkillConfigEditor.tsx +0 -22
  272. package/packages/hive-ui/src/modules/agent-config/skills/SkillCreator.tsx +0 -60
  273. package/packages/hive-ui/src/modules/agent-config/skills/SkillInstaller.tsx +0 -23
  274. package/packages/hive-ui/src/modules/agent-config/skills/SkillList.tsx +0 -72
  275. package/packages/hive-ui/src/modules/agent-config/skills/SkillsTab.tsx +0 -202
  276. package/packages/hive-ui/src/modules/agent-config/skills/index.ts +0 -5
  277. package/packages/hive-ui/src/modules/agent-config/tools/ToolCard.tsx +0 -27
  278. package/packages/hive-ui/src/modules/agent-config/tools/ToolConfigPanel.tsx +0 -22
  279. package/packages/hive-ui/src/modules/agent-config/tools/ToolManager.tsx +0 -266
  280. package/packages/hive-ui/src/modules/agent-config/tools/ToolPermissions.tsx +0 -287
  281. package/packages/hive-ui/src/modules/agent-config/tools/ToolRegistry.tsx +0 -84
  282. package/packages/hive-ui/src/modules/agent-config/tools/ToolUsageStats.tsx +0 -52
  283. package/packages/hive-ui/src/modules/agent-config/tools/index.ts +0 -4
  284. package/packages/hive-ui/src/modules/agent-config/user/ActiveAgentsList.tsx +0 -109
  285. package/packages/hive-ui/src/modules/agent-config/user/GlobalConfigOverview.tsx +0 -119
  286. package/packages/hive-ui/src/modules/agent-config/user/UserMemoryManager.tsx +0 -54
  287. package/packages/hive-ui/src/modules/agent-config/user/UserPreferencesForm.tsx +0 -163
  288. package/packages/hive-ui/src/modules/agent-config/user/UserProfileEditor.tsx +0 -261
  289. package/packages/hive-ui/src/modules/agent-config/user/index.ts +0 -3
  290. package/packages/hive-ui/src/modules/agents/AgentActivityLog.tsx +0 -25
  291. package/packages/hive-ui/src/modules/agents/AgentCard.tsx +0 -305
  292. package/packages/hive-ui/src/modules/agents/AgentCreateForm.tsx +0 -446
  293. package/packages/hive-ui/src/modules/agents/AgentDetail.tsx +0 -28
  294. package/packages/hive-ui/src/modules/agents/AgentInternalCard.tsx +0 -162
  295. package/packages/hive-ui/src/modules/agents/AgentList.tsx +0 -29
  296. package/packages/hive-ui/src/modules/agents/AgentStatusBadge.tsx +0 -34
  297. package/packages/hive-ui/src/modules/agents/ModelSelector.tsx +0 -151
  298. package/packages/hive-ui/src/modules/bridge/BridgeLogViewer.tsx +0 -61
  299. package/packages/hive-ui/src/modules/bridge/BridgeProcessList.tsx +0 -77
  300. package/packages/hive-ui/src/modules/bridge/BridgeStatus.tsx +0 -23
  301. package/packages/hive-ui/src/modules/bridge/BridgeTerminal.tsx +0 -7
  302. package/packages/hive-ui/src/modules/canvas/CanvasButton.tsx +0 -3
  303. package/packages/hive-ui/src/modules/canvas/CanvasChart.tsx +0 -3
  304. package/packages/hive-ui/src/modules/canvas/CanvasComponentMap.tsx +0 -605
  305. package/packages/hive-ui/src/modules/canvas/CanvasContainer.tsx +0 -360
  306. package/packages/hive-ui/src/modules/canvas/CanvasForm.tsx +0 -3
  307. package/packages/hive-ui/src/modules/canvas/CanvasMarkdown.tsx +0 -3
  308. package/packages/hive-ui/src/modules/canvas/CanvasTable.tsx +0 -3
  309. package/packages/hive-ui/src/modules/canvas/ComponentRenderer.tsx +0 -30
  310. package/packages/hive-ui/src/modules/canvas/DynamicRenderer.tsx +0 -3
  311. package/packages/hive-ui/src/modules/channels/available/AvailableChannelsGrid.tsx +0 -89
  312. package/packages/hive-ui/src/modules/channels/available/ChannelAuthForm.tsx +0 -33
  313. package/packages/hive-ui/src/modules/channels/available/ChannelSetupWizard.tsx +0 -48
  314. package/packages/hive-ui/src/modules/channels/available/ChannelTestConnection.tsx +0 -37
  315. package/packages/hive-ui/src/modules/channels/available/ChannelTypeCard.tsx +0 -30
  316. package/packages/hive-ui/src/modules/channels/available/ChannelWebhookConfig.tsx +0 -30
  317. package/packages/hive-ui/src/modules/channels/available/index.ts +0 -6
  318. package/packages/hive-ui/src/modules/channels/connected/ChannelCard.tsx +0 -95
  319. package/packages/hive-ui/src/modules/channels/connected/ChannelConfigPanel.tsx +0 -260
  320. package/packages/hive-ui/src/modules/channels/connected/ChannelDisconnectButton.tsx +0 -21
  321. package/packages/hive-ui/src/modules/channels/connected/ChannelLogsViewer.tsx +0 -42
  322. package/packages/hive-ui/src/modules/channels/connected/ChannelQRCode.tsx +0 -32
  323. package/packages/hive-ui/src/modules/channels/connected/ChannelReconnectButton.tsx +0 -16
  324. package/packages/hive-ui/src/modules/channels/connected/ChannelStatusBadge.tsx +0 -26
  325. package/packages/hive-ui/src/modules/channels/connected/ConnectedChannelsList.tsx +0 -40
  326. package/packages/hive-ui/src/modules/channels/connected/index.ts +0 -8
  327. package/packages/hive-ui/src/modules/channels/shared/ChannelCard.tsx +0 -84
  328. package/packages/hive-ui/src/modules/channels/shared/ChannelConfigDialog.tsx +0 -279
  329. package/packages/hive-ui/src/modules/channels/shared/ChannelIcon.tsx +0 -40
  330. package/packages/hive-ui/src/modules/channels/shared/ChannelStats.tsx +0 -37
  331. package/packages/hive-ui/src/modules/channels/shared/ChannelTypeBadge.tsx +0 -23
  332. package/packages/hive-ui/src/modules/channels/shared/ConnectionHealthIndicator.tsx +0 -20
  333. package/packages/hive-ui/src/modules/channels/shared/MessagePreview.tsx +0 -19
  334. package/packages/hive-ui/src/modules/channels/shared/index.ts +0 -5
  335. package/packages/hive-ui/src/modules/chat/ChatContainer.tsx +0 -268
  336. package/packages/hive-ui/src/modules/chat/ChatHistory.tsx +0 -101
  337. package/packages/hive-ui/src/modules/chat/ChatInput.tsx +0 -108
  338. package/packages/hive-ui/src/modules/chat/ChatMessage.tsx +0 -137
  339. package/packages/hive-ui/src/modules/chat/ThinkingIndicator.tsx +0 -10
  340. package/packages/hive-ui/src/modules/layout/AppLayout.tsx +0 -45
  341. package/packages/hive-ui/src/modules/layout/ConnectionStatus.tsx +0 -19
  342. package/packages/hive-ui/src/modules/layout/Header.tsx +0 -20
  343. package/packages/hive-ui/src/modules/layout/HiveSidebar.tsx +0 -173
  344. package/packages/hive-ui/src/modules/layout/ThemeToggle.tsx +0 -18
  345. package/packages/hive-ui/src/modules/providers/ProviderCard.tsx +0 -319
  346. package/packages/hive-ui/src/modules/providers/ProviderConfigForm.tsx +0 -146
  347. package/packages/hive-ui/src/modules/providers/ProviderFailoverConfig.tsx +0 -110
  348. package/packages/hive-ui/src/modules/providers/ProviderList.tsx +0 -33
  349. package/packages/hive-ui/src/modules/providers/ProviderStatusIndicator.tsx +0 -23
  350. package/packages/hive-ui/src/modules/providers/configs/ProviderAPIKeyManager.tsx +0 -39
  351. package/packages/hive-ui/src/modules/providers/configs/ProviderEndpointConfig.tsx +0 -27
  352. package/packages/hive-ui/src/modules/providers/configs/ProviderRateLimits.tsx +0 -37
  353. package/packages/hive-ui/src/modules/providers/configs/ProviderRetryPolicy.tsx +0 -46
  354. package/packages/hive-ui/src/modules/providers/configs/index.ts +0 -4
  355. package/packages/hive-ui/src/modules/providers/index.ts +0 -5
  356. package/packages/hive-ui/src/modules/providers/models/ModelBenchmarkBadge.tsx +0 -21
  357. package/packages/hive-ui/src/modules/providers/models/ModelCapabilities.tsx +0 -44
  358. package/packages/hive-ui/src/modules/providers/models/ModelCard.tsx +0 -36
  359. package/packages/hive-ui/src/modules/providers/models/ModelComparisonTable.tsx +0 -47
  360. package/packages/hive-ui/src/modules/providers/models/ModelList.tsx +0 -51
  361. package/packages/hive-ui/src/modules/providers/models/ModelPricingInfo.tsx +0 -17
  362. package/packages/hive-ui/src/modules/providers/models/ModelSelector.tsx +0 -32
  363. package/packages/hive-ui/src/modules/providers/models/index.ts +0 -7
  364. package/packages/hive-ui/src/pages/AgentDetailPage.tsx +0 -74
  365. package/packages/hive-ui/src/pages/AgentNewPage.tsx +0 -5
  366. package/packages/hive-ui/src/pages/AgentsPage.tsx +0 -147
  367. package/packages/hive-ui/src/pages/BridgePage.tsx +0 -83
  368. package/packages/hive-ui/src/pages/CanvasPage.tsx +0 -32
  369. package/packages/hive-ui/src/pages/ChannelsPage.tsx +0 -176
  370. package/packages/hive-ui/src/pages/DashboardPage.tsx +0 -321
  371. package/packages/hive-ui/src/pages/Index.tsx +0 -14
  372. package/packages/hive-ui/src/pages/LogsPage.tsx +0 -252
  373. package/packages/hive-ui/src/pages/NotFound.tsx +0 -24
  374. package/packages/hive-ui/src/pages/ProjectsPage.tsx +0 -241
  375. package/packages/hive-ui/src/pages/ProvidersPage.tsx +0 -111
  376. package/packages/hive-ui/src/pages/SettingsPage.tsx +0 -147
  377. package/packages/hive-ui/src/pages/SetupPage.tsx +0 -1177
  378. package/packages/hive-ui/src/pages/WebChatPage.tsx +0 -15
  379. package/packages/hive-ui/src/stores/agentConfigStore.ts +0 -32
  380. package/packages/hive-ui/src/stores/agentStore.ts +0 -5
  381. package/packages/hive-ui/src/stores/bridgeStore.ts +0 -237
  382. package/packages/hive-ui/src/stores/canvasStore.ts +0 -250
  383. package/packages/hive-ui/src/stores/channelStore.ts +0 -5
  384. package/packages/hive-ui/src/stores/chatStore.ts +0 -42
  385. package/packages/hive-ui/src/stores/ethicsStore.ts +0 -141
  386. package/packages/hive-ui/src/stores/mcpStore.ts +0 -5
  387. package/packages/hive-ui/src/stores/modelStore.ts +0 -2
  388. package/packages/hive-ui/src/stores/projectsStore.ts +0 -141
  389. package/packages/hive-ui/src/stores/providerStore.ts +0 -2
  390. package/packages/hive-ui/src/stores/skillStore.ts +0 -5
  391. package/packages/hive-ui/src/stores/toolStore.ts +0 -5
  392. package/packages/hive-ui/src/stores/useGlobalConfigStore.ts +0 -937
  393. package/packages/hive-ui/src/stores/useLoaderStore.ts +0 -21
  394. package/packages/hive-ui/src/stores/useNotesAndCronsStore.ts +0 -144
  395. package/packages/hive-ui/src/stores/useWebSocketStore.ts +0 -152
  396. package/packages/hive-ui/src/stores/useWelcomeStore.ts +0 -37
  397. package/packages/hive-ui/src/stores/userConfigStore.ts +0 -23
  398. package/packages/hive-ui/src/stores/userStore.ts +0 -82
  399. package/packages/hive-ui/src/test/setup.ts +0 -15
  400. package/packages/hive-ui/src/types/agent-config.ts +0 -33
  401. package/packages/hive-ui/src/types/agent.ts +0 -65
  402. package/packages/hive-ui/src/types/bridge.ts +0 -27
  403. package/packages/hive-ui/src/types/canvas.ts +0 -76
  404. package/packages/hive-ui/src/types/channels.ts +0 -109
  405. package/packages/hive-ui/src/types/chat.ts +0 -25
  406. package/packages/hive-ui/src/types/connections.ts +0 -17
  407. package/packages/hive-ui/src/types/ethics.ts +0 -41
  408. package/packages/hive-ui/src/types/index.ts +0 -15
  409. package/packages/hive-ui/src/types/mcp.ts +0 -36
  410. package/packages/hive-ui/src/types/notes-crons.ts +0 -31
  411. package/packages/hive-ui/src/types/providers.ts +0 -145
  412. package/packages/hive-ui/src/types/skill.ts +0 -12
  413. package/packages/hive-ui/src/types/tool.ts +0 -44
  414. package/packages/hive-ui/src/types/user.ts +0 -26
  415. package/packages/hive-ui/src/types/websocket.ts +0 -14
  416. package/packages/hive-ui/src/vite-env.d.ts +0 -1
  417. package/packages/mcp/package.json +0 -26
  418. package/packages/mcp/src/config.ts +0 -13
  419. package/packages/mcp/src/index.ts +0 -1
  420. package/packages/mcp/src/logger.ts +0 -42
  421. package/packages/mcp/src/manager.ts +0 -439
  422. package/packages/mcp/src/transports/index.ts +0 -67
  423. package/packages/mcp/src/transports/sse.ts +0 -241
  424. package/packages/mcp/src/transports/websocket.ts +0 -159
  425. package/packages/skills/package.json +0 -21
  426. package/packages/skills/src/index.ts +0 -1
  427. package/packages/skills/src/loader.ts +0 -346
@@ -1,1696 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import * as fs from "fs";
3
- import * as path from "path";
4
- import {
5
- initOnboardingDb,
6
- saveUserProfile,
7
- saveProviderConfig,
8
- saveAgentConfig,
9
- saveOnboardingProgress,
10
- activateChannel,
11
- activateEthics,
12
- activateCodeBridge,
13
- getAllEthics,
14
- getAllCodeBridge,
15
- saveVoiceConfig,
16
- } from "@johpaz/hive-core/storage/onboarding";
17
- import { generateAuthToken } from "../utils/token";
18
- import { getHiveDir } from "../../../core/src/config/loader";
19
-
20
- // Log helper for @clack/prompts v0.5.1 (log export not available)
21
- const log = {
22
- success: (msg: string) => console.log(`\x1b[32m✔\x1b[0m ${msg}`),
23
- error: (msg: string) => console.log(`\x1b[31m✖\x1b[0m ${msg}`),
24
- warn: (msg: string) => console.log(`\x1b[33m⚠\x1b[0m ${msg}`),
25
- info: (msg: string) => console.log(`\x1b[36mℹ\x1b[0m ${msg}`),
26
- step: (msg: string) => console.log(`\n\x1b[36m›\x1b[0m ${msg}`),
27
- };
28
-
29
- function getEnvApiKey(keyName: string): string | null {
30
- const hiveDir = getHiveDir();
31
- const envPath = path.join(hiveDir, ".env");
32
- if (!fs.existsSync(envPath)) return null;
33
-
34
- const envContent = fs.readFileSync(envPath, "utf-8");
35
- const match = envContent.match(new RegExp(`${keyName}=(.+)`));
36
- return match ? match[1].trim() : null;
37
- }
38
-
39
- function reloadEnvToProcess(hiveDir: string): void {
40
- const envPath = path.join(hiveDir, ".env");
41
- if (!fs.existsSync(envPath)) return;
42
-
43
- const envContent = fs.readFileSync(envPath, "utf-8");
44
- const lines = envContent.split("\n");
45
- for (const line of lines) {
46
- const trimmed = line.trim();
47
- if (!trimmed || trimmed.startsWith("#")) continue;
48
- const [key, ...valueParts] = trimmed.split("=");
49
- if (key && valueParts.length > 0) {
50
- process.env[key] = valueParts.join("=").trim();
51
- }
52
- }
53
- }
54
-
55
- const VERSION = "1.7.2";
56
-
57
- const DEFAULT_MODELS: Record<string, string> = {
58
- anthropic: "claude-sonnet-4-6",
59
- openai: "gpt-5.2",
60
- gemini: "gemini-3.1-flash-preview",
61
- mistral: "mistral-large-latest",
62
- deepseek: "deepseek-chat",
63
- kimi: "kimi-k2.5",
64
- openrouter: "meta-llama/llama-3.3-70b-instruct",
65
- ollama: "llama3.3:8b",
66
- };
67
-
68
- const PROVIDER_BASE_URLS: Record<string, string> = {
69
- anthropic: "https://api.anthropic.com",
70
- openai: "https://api.openai.com",
71
- gemini: "https://generativelanguage.googleapis.com",
72
- mistral: "https://api.mistral.ai/v1",
73
- deepseek: "https://api.deepseek.com",
74
- kimi: "https://api.moonshot.cn",
75
- openrouter: "https://openrouter.ai/api",
76
- ollama: "http://localhost:11434",
77
- };
78
-
79
- const API_KEY_PLACEHOLDERS: Record<string, string> = {
80
- anthropic: "sk-ant-...",
81
- openai: "sk-...",
82
- gemini: "AIza...",
83
- mistral: "sk-...",
84
- deepseek: "sk-...",
85
- kimi: "sk-...",
86
- openrouter: "sk-or-...",
87
- ollama: "",
88
- };
89
-
90
- const API_KEY_LINKS: Record<string, string> = {
91
- anthropic: "https://console.anthropic.com/keys",
92
- openai: "https://platform.openai.com/api-keys",
93
- gemini: "https://aistudio.google.com/app/apikey",
94
- mistral: "https://console.mistral.ai/api-keys",
95
- deepseek: "https://platform.deepseek.com/api_keys",
96
- kimi: "https://platform.moonshot.cn/console/api-keys",
97
- openrouter: "https://openrouter.ai/keys",
98
- ollama: "",
99
- };
100
-
101
- const AVAILABLE_MODELS: Record<string, Array<{ value: string; label: string; hint?: string }>> = {
102
- anthropic: [
103
- { value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", hint: "Recomendado — mejor equilibrio, 1M contexto" },
104
- { value: "claude-opus-4-6", label: "Claude Opus 4.6", hint: "Más potente — agentic coding, 1M contexto" },
105
- { value: "claude-haiku-4-6", label: "Claude Haiku 4.6", hint: "Más rápido y económico" },
106
- ],
107
- openai: [
108
- { value: "gpt-5.2", label: "GPT-5.2", hint: "Recomendado — 400K contexto, latest" },
109
- { value: "gpt-5.1", label: "GPT-5.1", hint: "Versión anterior estable" },
110
- { value: "gpt-5.2-codex", label: "GPT-5.2 Codex", hint: "Especializado en código" },
111
- { value: "o4-mini", label: "o4-mini", hint: "Razonamiento avanzado, económico" },
112
- ],
113
- gemini: [
114
- { value: "gemini-3.1-flash-lite-preview", label: "Gemini 3.1 Flash (Preview)", hint: "Frontier-class, muy económico" },
115
- { value: "gemini-3-flash-preview", label: "Gemini 3 Flash (Preview)", hint: "Frontier-class, muy económico" },
116
- { value: "gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "Recomendado — estable, rápido" },
117
- { value: "gemini-2.5-pro", label: "Gemini 2.5 Pro", hint: "Más potente — razonamiento profundo" },
118
- { value: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro (Preview)", hint: "Latest — tareas complejas" },
119
- ],
120
- mistral: [
121
- { value: "mistral-large-latest", label: "Mistral Large", hint: "Recomendado — potente, 1M contexto" },
122
- { value: "mistral-small-latest", label: "Mistral Small", hint: "Económico y rápido" },
123
- { value: "pixtral-large-latest", label: "Pixtral Large", hint: "Multimodal — visión" },
124
- ],
125
- deepseek: [
126
- { value: "deepseek-chat", label: "DeepSeek-V3", hint: "Recomendado — muy económico, capaz" },
127
- { value: "deepseek-reasoner", label: "DeepSeek-R1", hint: "Razonamiento profundo" },
128
- { value: "deepseek-coder", label: "DeepSeek Coder", hint: "Especializado en código" },
129
- ],
130
- kimi: [
131
- { value: "kimi-k2.5", label: "Kimi K2.5", hint: "Recomendado — multimodal, agentic, 1T params" },
132
- { value: "kimi-k2-thinking", label: "Kimi K2 Thinking", hint: "Largo razonamiento" },
133
- { value: "kimi-k2-turbo-preview", label: "Kimi K2 Turbo", hint: "Rápido, preview" },
134
- ],
135
- openrouter: [
136
- { value: "meta-llama/llama-3.3-70b-instruct", label: "Llama 3.3 70B", hint: "Gratis — GPT-4 level" },
137
- { value: "google/gemini-2.0-flash-exp:free", label: "Gemini 2.0 Flash", hint: "Gratis — 1M contexto" },
138
- { value: "deepseek/deepseek-r1:free", label: "DeepSeek R1", hint: "Gratis — razonamiento fuerte" },
139
- { value: "anthropic/claude-sonnet-4-6", label: "Claude Sonnet 4.6", hint: "Vía OpenRouter" },
140
- ],
141
- ollama: [
142
- { value: "llama3.3:8b", label: "Llama 3.3 8B", hint: "Recomendado — general, ~5GB RAM" },
143
- { value: "qwen2.5:7b", label: "Qwen 2.5 7B", hint: "Multilingual, código, ~4.5GB RAM" },
144
- { value: "mistral:7b", label: "Mistral 7B", hint: "Rápido, ~4GB RAM" },
145
- { value: "phi4:14b", label: "Phi-4 14B", hint: "Mejor calidad, ~8GB RAM" },
146
- ],
147
- };
148
-
149
- const BUNDLED_SKILLS = [
150
- { name: "web_search", label: "Web Search", hint: "Buscar en la web", default: true },
151
- { name: "shell", label: "Shell", hint: "Ejecutar comandos", default: true },
152
- { name: "file_manager", label: "File Manager", hint: "Operaciones de archivos", default: true },
153
- { name: "http_client", label: "HTTP Client", hint: "Peticiones HTTP", default: true },
154
- { name: "memory", label: "Memory", hint: "Memoria persistente", default: true },
155
- { name: "cron_manager", label: "Cron Manager", hint: "Tareas programadas", default: false },
156
- { name: "system_notify", label: "System Notify", hint: "Notificaciones desktop", default: false },
157
- { name: "browser_automation", label: "Browser Automation", hint: "Automatizar navegador", default: false },
158
- { name: "context_compact", label: "Context Compact", hint: "Compactar contexto", default: false },
159
- ];
160
-
161
- type NavAction = "next" | "prev" | "cancel";
162
-
163
- async function askNavigation(): Promise<NavAction> {
164
- const action = await p.select({
165
- message: "Acciones:",
166
- options: [
167
- { value: "next", label: "➡️ Siguiente", hint: "Continuar" },
168
- { value: "prev", label: "⬅️ Anterior", hint: "Volver atrás" },
169
- { value: "cancel", label: "❌ Cancelar", hint: "Salir del onboarding" },
170
- ],
171
- });
172
-
173
- if (p.isCancel(action) || action === "cancel") {
174
- return "cancel";
175
- }
176
- return action as NavAction;
177
- }
178
-
179
- function showProgress(current: number, total: number, title: string): void {
180
- const filled = "█".repeat(current);
181
- const empty = "░".repeat(total - current);
182
- p.note(`${filled}${empty} Sección ${current}/${total}: ${title}`, "Progreso");
183
- }
184
-
185
- interface OnboardConfig {
186
- agentName: string;
187
- agentId: string;
188
- userName: string;
189
- userId: string;
190
- provider: string;
191
- model: string;
192
- apiKey: string;
193
- channel: string;
194
- channelToken: string;
195
- workspace: string;
196
- tools: string[];
197
- mcp?: { servers: Record<string, unknown> };
198
- agentTone: "formal" | "friendly" | "direct";
199
-
200
- codeBridge: {
201
- enabled: boolean;
202
- clis: string[];
203
- port: number;
204
- };
205
- userLanguage?: string;
206
- userTimezone?: string;
207
- userOccupation?: string;
208
- userNotes?: string;
209
- ethicsChoice?: string;
210
- agentDescription: string;
211
- }
212
-
213
- async function checkCommand(cmd: string): Promise<boolean> {
214
- const proc = Bun.spawn(["which", cmd], { stdout: "pipe", stderr: "pipe" })
215
- const code = await proc.exited
216
- return code === 0
217
- }
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
- function generateToken(): string {
228
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
229
- let token = "";
230
- for (let i = 0; i < 32; i++) {
231
- token += chars.charAt(Math.floor(Math.random() * chars.length));
232
- }
233
- return token;
234
- }
235
-
236
- async function verifyTelegramToken(token: string): Promise<{ ok: boolean; username?: string }> {
237
- try {
238
- const res = await fetch(
239
- `https://api.telegram.org/bot${token}/getMe`,
240
- { signal: AbortSignal.timeout(5000) }
241
- );
242
- const data = (await res.json()) as {
243
- ok: boolean;
244
- result?: { username: string; first_name: string };
245
- };
246
- return {
247
- ok: data.ok,
248
- username: data.result?.username,
249
- };
250
- } catch {
251
- return { ok: false };
252
- }
253
- }
254
-
255
- function validateDiscordToken(token: string): boolean {
256
- return token.length >= 50;
257
- }
258
-
259
- function validateSlackToken(token: string): boolean {
260
- return token.startsWith("xoxb-") || token.startsWith("xoxp-");
261
- }
262
-
263
- async function testLLMConnection(provider: string, apiKey: string, model: string): Promise<boolean> {
264
- if (provider === "ollama") {
265
- try {
266
- const response = await fetch("http://localhost:11434/api/tags");
267
- return response.ok;
268
- } catch {
269
- return false;
270
- }
271
- }
272
-
273
- const testMessages = [{ role: "user" as const, content: "Say 'ok' if you can read this." }];
274
-
275
- try {
276
- if (provider === "anthropic") {
277
- const response = await fetch("https://api.anthropic.com/v1/messages", {
278
- method: "POST",
279
- headers: {
280
- "Content-Type": "application/json",
281
- "x-api-key": apiKey,
282
- "anthropic-version": "2023-06-01",
283
- "anthropic-dangerous-direct-browser-access": "true",
284
- },
285
- body: JSON.stringify({
286
- model: model,
287
- max_tokens: 10,
288
- messages: testMessages,
289
- }),
290
- });
291
- return response.ok;
292
- }
293
-
294
- if (provider === "openai") {
295
- const response = await fetch("https://api.openai.com/v1/chat/completions", {
296
- method: "POST",
297
- headers: {
298
- "Content-Type": "application/json",
299
- Authorization: `Bearer ${apiKey}`,
300
- },
301
- body: JSON.stringify({
302
- model: model,
303
- max_tokens: 10,
304
- messages: testMessages,
305
- }),
306
- });
307
- return response.ok;
308
- }
309
-
310
- if (provider === "gemini") {
311
- const response = await fetch(
312
- `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`,
313
- {
314
- method: "POST",
315
- headers: { "Content-Type": "application/json" },
316
- body: JSON.stringify({
317
- contents: [{ parts: [{ text: "Say ok" }] }],
318
- }),
319
- }
320
- );
321
- return response.ok;
322
- }
323
-
324
- if (provider === "deepseek") {
325
- const response = await fetch("https://api.deepseek.com/v1/chat/completions", {
326
- method: "POST",
327
- headers: {
328
- "Content-Type": "application/json",
329
- Authorization: `Bearer ${apiKey}`,
330
- },
331
- body: JSON.stringify({
332
- model: model,
333
- max_tokens: 10,
334
- messages: testMessages,
335
- }),
336
- });
337
- return response.ok;
338
- }
339
-
340
- if (provider === "kimi") {
341
- const response = await fetch("https://api.moonshot.cn/v1/chat/completions", {
342
- method: "POST",
343
- headers: {
344
- "Content-Type": "application/json",
345
- Authorization: `Bearer ${apiKey}`,
346
- },
347
- body: JSON.stringify({
348
- model: model,
349
- max_tokens: 10,
350
- messages: testMessages,
351
- }),
352
- });
353
- return response.ok;
354
- }
355
-
356
- if (provider === "openrouter") {
357
- const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
358
- method: "POST",
359
- headers: {
360
- "Content-Type": "application/json",
361
- Authorization: `Bearer ${apiKey}`,
362
- },
363
- body: JSON.stringify({
364
- model: model,
365
- max_tokens: 10,
366
- messages: testMessages,
367
- }),
368
- });
369
- return response.ok;
370
- }
371
-
372
- return false;
373
- } catch {
374
- return false;
375
- }
376
- }
377
-
378
- async function generateWorkspace(workspace: string, agentName: string, userName: string, userId: string, userLanguage: string, userTimezone: string, ethicsChoice: string): Promise<void> {
379
- // Create workspace directory - .md files are now stored in SQLite
380
- if (!fs.existsSync(workspace)) {
381
- fs.mkdirSync(workspace, { recursive: true });
382
- }
383
-
384
- // Files are loaded from SQLite via the agent service
385
- // Workspace directory is created but .md files are not generated here
386
- // The system will use default prompts from the database
387
- }
388
-
389
- async function installSystemdService(): Promise<void> {
390
- const home = process.env.HOME || "";
391
- const systemdDir = path.join(home, ".config", "systemd", "user");
392
-
393
- if (!fs.existsSync(systemdDir)) {
394
- fs.mkdirSync(systemdDir, { recursive: true });
395
- }
396
-
397
- const serviceContent = `[Unit]
398
- Description=Hive Personal AI Gateway
399
- After=network-online.target
400
- Wants=network-online.target
401
-
402
- [Service]
403
- Type=simple
404
- ExecStart=${home}/.bun/bin/hive start
405
- ExecStop=${home}/.bun/bin/hive stop
406
- Restart=on-failure
407
- RestartSec=5
408
- Environment=PATH=${home}/.bun/bin:${home}/.npm-global/bin:/usr/local/bin:/usr/bin:/bin
409
- WorkingDirectory=${home}
410
-
411
- [Install]
412
- WantedBy=default.target
413
- `;
414
-
415
- const servicePath = path.join(systemdDir, "hive.service");
416
- fs.writeFileSync(servicePath, serviceContent, "utf-8");
417
-
418
- const { spawnSync } = require("child_process");
419
- spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
420
- spawnSync("systemctl", ["--user", "enable", "hive"], { stdio: "inherit" });
421
- }
422
-
423
- async function isGatewayRunning(): Promise<boolean> {
424
- const pidFile = path.join(getHiveDir(), "gateway.pid");
425
- if (!fs.existsSync(pidFile)) return false;
426
-
427
- try {
428
- const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
429
- process.kill(pid, 0);
430
- return true;
431
- } catch {
432
- return false;
433
- }
434
- }
435
-
436
- async function reloadGateway(): Promise<void> {
437
- const pidFile = path.join(getHiveDir(), "gateway.pid");
438
- if (!fs.existsSync(pidFile)) return;
439
-
440
- try {
441
- const pid = parseInt(fs.readFileSync(pidFile, "utf-8").trim(), 10);
442
- process.kill(pid, "SIGHUP");
443
- } catch {
444
- // Gateway not running
445
- }
446
- }
447
-
448
- interface ExistingConfig {
449
- agentName: string;
450
- provider: string;
451
- model: string;
452
- channels: string[];
453
- apiKey: string;
454
- workspace: string;
455
- skills: string[];
456
- raw: Record<string, unknown>;
457
- }
458
-
459
- function parseExistingConfig(raw: Record<string, unknown>): ExistingConfig {
460
- const agents = (raw.agents as Record<string, unknown>)?.list as Array<Record<string, unknown>> | undefined;
461
- const models = raw.models as Record<string, unknown> | undefined;
462
- const providers = models?.providers as Record<string, Record<string, unknown>> | undefined;
463
- const defaultProvider = models?.defaultProvider as string | undefined;
464
- const providerConfig = providers?.[defaultProvider || ""] as Record<string, unknown> | undefined;
465
-
466
- return {
467
- agentName: (agents?.[0]?.name as string) ?? "Hive",
468
- provider: defaultProvider ?? "gemini",
469
- model: (models?.defaults as Record<string, string>)?.[defaultProvider || ""] ?? "",
470
- channels: Object.keys((raw.channels as Record<string, unknown>) ?? {}),
471
- apiKey: (providerConfig?.apiKey as string) ?? "",
472
- workspace: (agents?.[0]?.workspace as string) ?? path.join(getHiveDir(), "workspace"),
473
- skills: ((raw.skills as Record<string, unknown>)?.allowBundled as string[]) ?? [],
474
- raw,
475
- };
476
- }
477
-
478
- async function runUpdateWizard(existing: ExistingConfig): Promise<void> {
479
- p.note(
480
- "Presiona Enter para mantener el valor actual de cada campo.",
481
- "✏️ Modo actualización"
482
- );
483
-
484
- // Nombre del agente
485
- const agentName = await p.text({
486
- message: "Nombre del agente:",
487
- placeholder: existing.agentName,
488
- defaultValue: existing.agentName,
489
- });
490
-
491
- if (p.isCancel(agentName)) {
492
- p.cancel("Actualización cancelada.");
493
- process.exit(0);
494
- }
495
-
496
- // Proveedor LLM
497
- const changeProvider = await p.confirm({
498
- message: `Proveedor actual: ${existing.provider} (${existing.model || "no configurado"}). ¿Cambiar?`,
499
- initialValue: false,
500
- });
501
-
502
- if (p.isCancel(changeProvider)) {
503
- p.cancel("Actualización cancelada.");
504
- process.exit(0);
505
- }
506
-
507
- let provider = existing.provider;
508
- let model = existing.model;
509
- let apiKey = existing.apiKey;
510
-
511
- if (changeProvider) {
512
- provider = await p.select({
513
- message: "Nuevo proveedor LLM:",
514
- options: [
515
- { value: "anthropic", label: "Anthropic (Claude)", hint: "Recomendado — Claude 4.6" },
516
- { value: "openai", label: "OpenAI (GPT-5)", hint: "GPT-5.2" },
517
- { value: "gemini", label: "Google Gemini", hint: "Gemini 3 Flash" },
518
- { value: "mistral", label: "Mistral AI", hint: "Mistral Large" },
519
- { value: "deepseek", label: "DeepSeek", hint: "Muy económico" },
520
- { value: "kimi", label: "Kimi (Moonshot AI)", hint: "Contexto largo" },
521
- { value: "openrouter", label: "OpenRouter", hint: "Multi-modelo" },
522
- { value: "ollama", label: "Ollama (local)", hint: "Sin costo" },
523
- ],
524
- }) as string;
525
-
526
- if (p.isCancel(provider)) {
527
- p.cancel("Actualización cancelada.");
528
- process.exit(0);
529
- }
530
-
531
- const models = AVAILABLE_MODELS[provider] || [{ value: DEFAULT_MODELS[provider], label: DEFAULT_MODELS[provider] }];
532
-
533
- if (models.length > 1) {
534
- model = await p.select({
535
- message: `Modelo de ${provider}:`,
536
- options: models,
537
- }) as string;
538
-
539
- if (p.isCancel(model)) {
540
- p.cancel("Actualización cancelada.");
541
- process.exit(0);
542
- }
543
- } else {
544
- model = models[0].value;
545
- }
546
-
547
- if (provider !== "ollama") {
548
- const link = API_KEY_LINKS[provider];
549
- if (link) {
550
- p.note(`Obtén tu API key en:\n${link}`, `API key de ${provider}`);
551
- }
552
-
553
- const keyResult = await p.password({
554
- message: `API key de ${provider}:`,
555
- validate: (v) => (!v || v.length < 10 ? "La key parece muy corta" : undefined),
556
- });
557
-
558
- if (p.isCancel(keyResult)) {
559
- p.cancel("Actualización cancelada.");
560
- process.exit(0);
561
- }
562
- apiKey = keyResult;
563
-
564
- const spinner = p.spinner();
565
- spinner.start(`Verificando conexión con ${provider}...`);
566
-
567
- const connected = await testLLMConnection(provider, apiKey, model as string);
568
-
569
- if (!connected) {
570
- spinner.stop(`❌ Error conectando con ${provider}`);
571
- p.outro("API key inválida. Ejecuta 'hive onboard' de nuevo con la key correcta.");
572
- process.exit(1);
573
- }
574
-
575
- spinner.stop(`✅ Conexión con ${provider} verificada`);
576
- }
577
- }
578
-
579
- // Canales
580
- const currentChannels = existing.channels.length > 0 ? existing.channels.join(", ") : "ninguno";
581
- const changeChannel = await p.confirm({
582
- message: `Canales configurados: ${currentChannels}. ¿Añadir o cambiar?`,
583
- initialValue: false,
584
- });
585
-
586
- if (p.isCancel(changeChannel)) {
587
- p.cancel("Actualización cancelada.");
588
- process.exit(0);
589
- }
590
-
591
- let channels = existing.raw.channels as Record<string, unknown> | undefined;
592
-
593
- if (changeChannel) {
594
- const channel = await p.select({
595
- message: "Canal a configurar:",
596
- options: [
597
- { value: "telegram", label: "Telegram", hint: "Recomendado" },
598
- { value: "discord", label: "Discord" },
599
- { value: "webchat", label: "WebChat (local)" },
600
- { value: "none", label: "Ninguno" },
601
- ],
602
- }) as string;
603
-
604
- if (p.isCancel(channel)) {
605
- p.cancel("Actualización cancelada.");
606
- process.exit(0);
607
- }
608
-
609
- if (channel === "telegram") {
610
- p.note(
611
- "1. Abre Telegram y busca @BotFather\n" +
612
- "2. Escribe /newbot y sigue las instrucciones\n" +
613
- "3. Copia el token que te da BotFather",
614
- "Cómo obtener el token de Telegram"
615
- );
616
-
617
- const tokenResult = await p.password({
618
- message: "Token de Telegram BotFather:",
619
- validate: (v) => (!v?.trim() ? "El token no puede estar vacío" : undefined),
620
- });
621
-
622
- if (p.isCancel(tokenResult)) {
623
- p.cancel("Actualización cancelada.");
624
- process.exit(0);
625
- }
626
-
627
- const spinner = p.spinner();
628
- spinner.start("Verificando token de Telegram...");
629
- const tg = await verifyTelegramToken(tokenResult as string);
630
- if (tg.ok && tg.username) {
631
- spinner.stop(`✅ Bot verificado: @${tg.username}`);
632
- } else {
633
- spinner.stop("⚠️ Token no verificado — se guardará de todas formas");
634
- p.note(
635
- "El token se guardó pero no pudo verificarse.\n" +
636
- "Si es incorrecto, ejecuta: hive onboard (opción actualizar)",
637
- "Aviso"
638
- );
639
- }
640
-
641
- const telegramAccount: Record<string, unknown> = {
642
- botToken: tokenResult,
643
- dmPolicy: "open",
644
- };
645
-
646
- channels = {
647
- telegram: {
648
- accounts: {
649
- default: telegramAccount,
650
- },
651
- },
652
- };
653
- } else if (channel === "discord") {
654
- p.note(
655
- "1. Ve a https://discord.com/developers/applications\n" +
656
- "2. Crea una nueva aplicación\n" +
657
- "3. Ve a Bot → Reset Token\n" +
658
- "4. Habilita 'Message Content Intent'",
659
- "Cómo obtener el token de Discord"
660
- );
661
-
662
- const tokenResult = await p.password({
663
- message: "Token del bot de Discord:",
664
- validate: (v) => (!v?.trim() ? "El token no puede estar vacío" : undefined),
665
- });
666
-
667
- if (p.isCancel(tokenResult)) {
668
- p.cancel("Actualización cancelada.");
669
- process.exit(0);
670
- }
671
-
672
- channels = {
673
- discord: {
674
- accounts: {
675
- default: {
676
- token: tokenResult,
677
- },
678
- },
679
- },
680
- };
681
- }
682
- }
683
-
684
- // Guardar cambios
685
- const spinner = p.spinner();
686
- spinner.start("Guardando cambios...");
687
-
688
- const baseUrlMap: Record<string, string> = {
689
- gemini: "https://generativelanguage.googleapis.com/v1beta",
690
- deepseek: "https://api.deepseek.com/v1",
691
- kimi: "https://api.moonshot.cn/v1",
692
- ollama: "http://localhost:11434/api",
693
- };
694
-
695
- const providersConfig: Record<string, Record<string, unknown>> = {};
696
- if (provider !== "ollama" && apiKey) {
697
- providersConfig[provider] = { apiKey };
698
- if (baseUrlMap[provider]) {
699
- providersConfig[provider].baseUrl = baseUrlMap[provider];
700
- }
701
- }
702
-
703
- const updatedConfig: Record<string, unknown> = {
704
- ...existing.raw,
705
- name: agentName,
706
- agents: {
707
- list: [
708
- {
709
- id: "main",
710
- default: true,
711
- name: agentName,
712
- workspace: existing.workspace,
713
- agentDir: path.join(getHiveDir(), "agents", "main", "agent"),
714
- },
715
- ],
716
- },
717
- models: {
718
- defaultProvider: provider,
719
- defaults: {
720
- [provider]: model,
721
- },
722
- providers: providersConfig,
723
- },
724
- };
725
-
726
- if (channels) {
727
- updatedConfig.channels = channels;
728
- }
729
-
730
- log.success("✅ Configuración actualizada en BD");
731
- // Also update SQLite
732
- try {
733
- const { initializeDatabase, getDb } = await import("../../../core/src/storage/sqlite");
734
- initializeDatabase();
735
- const sqliteDb = getDb();
736
-
737
- const apiKeyVal = (providersConfig[provider]?.apiKey as string) || null;
738
- const baseUrlVal = (providersConfig[provider]?.baseUrl as string) || null;
739
-
740
- sqliteDb.query(`
741
- UPDATE providers SET api_key = ?, base_url = ?
742
- WHERE id = ?
743
- `).run(apiKeyVal, baseUrlVal, provider);
744
-
745
- sqliteDb.query(`
746
- UPDATE agents SET name = ?, provider_id = ?, model_id = ?
747
- WHERE id = 'main'
748
- `).run(agentName, provider, model);
749
-
750
- console.log("✅ SQLite actualizado");
751
- } catch (error) {
752
- console.log("⚠️ Error actualizando SQLite:", (error as Error).message);
753
- }
754
-
755
- spinner.stop("Cambios guardados ✅");
756
-
757
- // Recargar Gateway si está corriendo
758
- const running = await isGatewayRunning();
759
- if (running) {
760
- const reload = await p.confirm({
761
- message: "El Gateway está corriendo. ¿Recargar configuración ahora?",
762
- initialValue: true,
763
- });
764
-
765
- if (reload) {
766
- await reloadGateway();
767
- log.success("Configuración recargada ✅");
768
- }
769
- }
770
-
771
- const channelDisplay = channels ? Object.keys(channels).join(", ") || "ninguno" : existing.channels.join(", ") || "ninguno";
772
-
773
- p.outro(
774
- `✅ Configuración actualizada.\n\n` +
775
- ` Agente: ${agentName}\n` +
776
- ` Proveedor: ${provider} (${model})\n` +
777
- ` Canales: ${channelDisplay}\n\n` +
778
- ` hive status → ver estado actual\n` +
779
- ` hive reload → recargar manualmente`
780
- );
781
- }
782
-
783
- async function runFullWizard(): Promise<void> {
784
- p.intro("🐝 Bienvenido a Hive — Personal AI Gateway");
785
-
786
- // Initialize DB at start
787
- initOnboardingDb();
788
-
789
- const TOTAL_STEPS = 8;
790
- let step = 1;
791
-
792
- // Shared wizard state — pre-populated with defaults
793
- const state = {
794
- // Step 1: User Profile
795
- agentName: "Hive",
796
- userName: "Usuario",
797
- userId: "", // Se genera automáticamente en la BD
798
- userLanguage: "Spanish",
799
- userTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone || "America/Bogota",
800
- userOccupation: "",
801
- userNotes: "",
802
- sessionToken: "", // For webchat user_identity
803
- // Step 2: Agent Profile
804
- agentId: "", // Se genera automáticamente en la BD
805
- agentTone: "friendly" as "formal" | "friendly" | "direct",
806
- agentDescription: "Asistente personal inteligente y desarrollador senior.",
807
- // Step 3: Ethics
808
- ethicsId: "default",
809
- // Step 4: Tools
810
- tools: [] as string[],
811
- // Step 5: Provider
812
- provider: "gemini",
813
- model: "gemini-2.5-flash",
814
- apiKey: "",
815
- // Voice config
816
- voiceEnabled: false,
817
- sttProvider: "",
818
- ttsProvider: "",
819
- ttsVoiceId: "",
820
- elevenlabsApiKey: "",
821
- // Step 6: Channel
822
- channel: "webchat",
823
- channelToken: "",
824
- // Step 7: Code Bridge
825
- codeBridgeEnabled: false,
826
- codeBridgeClis: [] as string[],
827
- };
828
-
829
- const hiveDir = getHiveDir();
830
-
831
- // ─────────────────────────────────────
832
- // Step machine: 9 steps in correct order
833
- // ─────────────────────────────────────
834
-
835
- while (step <= TOTAL_STEPS) {
836
- switch (step) {
837
-
838
- // ═══════════════════════════════════
839
- // STEP 1: User Profile
840
- // ═══════════════════════════════════
841
- case 1: {
842
- showProgress(step, TOTAL_STEPS, "Tu perfil");
843
-
844
- const userName = await p.text({
845
- message: "👤 ¿Cómo te llamas?",
846
- placeholder: "Usuario",
847
- defaultValue: state.userName,
848
- });
849
- if (p.isCancel(userName)) { p.cancel("Onboarding cancelado."); process.exit(0); }
850
- state.userName = userName;
851
-
852
- const userLanguage = await p.select({
853
- message: "🌐 ¿En qué idioma prefieres que te responda?",
854
- options: [
855
- { value: "Spanish", label: "Español" },
856
- { value: "English", label: "English" },
857
- { value: "Spanish, English", label: "Ambos / Both" },
858
- ],
859
- initialValue: state.userLanguage,
860
- });
861
- if (p.isCancel(userLanguage)) { p.cancel("Onboarding cancelado."); process.exit(0); }
862
- state.userLanguage = userLanguage as string;
863
-
864
- const userTimezone = await p.text({
865
- message: "🕐 ¿Cuál es tu zona horaria?",
866
- placeholder: "America/Bogota",
867
- defaultValue: state.userTimezone,
868
- });
869
- if (p.isCancel(userTimezone)) { p.cancel("Onboarding cancelado."); process.exit(0); }
870
- state.userTimezone = userTimezone as string;
871
-
872
- const userOccupation = await p.text({
873
- message: "💼 ¿A qué te dedicas?",
874
- placeholder: "desarrollador de software",
875
- defaultValue: state.userOccupation || undefined,
876
- });
877
- if (p.isCancel(userOccupation)) { p.cancel("Onboarding cancelado."); process.exit(0); }
878
- state.userOccupation = userOccupation || "";
879
-
880
- const userNotes = await p.text({
881
- message: "💡 ¿Algo importante que el agente deba recordar de ti?",
882
- placeholder: "Prefiero respuestas directas.",
883
- defaultValue: state.userNotes || undefined,
884
- });
885
- if (p.isCancel(userNotes)) { p.cancel("Onboarding cancelado."); process.exit(0); }
886
- state.userNotes = userNotes || "";
887
-
888
- // Generate session token for webchat (user_identity)
889
- state.sessionToken = generateAuthToken();
890
-
891
- // ✅ Save user to DB (agent will be saved in Step 2)
892
- // userId se genera automáticamente en la BD (randomblob)
893
- state.userId = saveUserProfile({
894
- userName: state.userName,
895
- userLanguage: state.userLanguage,
896
- userTimezone: state.userTimezone,
897
- userOccupation: state.userOccupation,
898
- userNotes: state.userNotes,
899
- channelUserId: state.sessionToken, // For webchat user_identity
900
- });
901
-
902
- saveOnboardingProgress({
903
- step: "user",
904
- userId: state.userId,
905
- data: { userName: state.userName, userLanguage: state.userLanguage, userTimezone: state.userTimezone, userOccupation: state.userOccupation, userNotes: state.userNotes },
906
- });
907
-
908
- log.success(`✅ Usuario guardado con ID: ${state.userId}`);
909
-
910
- const nav = await askNavigation();
911
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
912
- if (nav === "prev") { step = 1; break; }
913
- step = 2;
914
- break;
915
- }
916
-
917
- // ═══════════════════════════════════
918
- // STEP 2: Perfil del Agente
919
- // ═══════════════════════════════════
920
- case 2: {
921
- showProgress(step, TOTAL_STEPS, "Tu agente");
922
-
923
- const agentName = await p.text({
924
- message: "🤖 ¿Cómo se llamará tu agente?",
925
- placeholder: "Bee",
926
- defaultValue: state.agentName,
927
- });
928
- if (p.isCancel(agentName)) { p.cancel("Onboarding cancelado."); process.exit(0); }
929
- state.agentName = agentName;
930
-
931
- const agentDescription = await p.text({
932
- message: "📝 ¿Qué quieres que haga este agente? (Su objetivo principal)",
933
- placeholder: "Ser un asistente personal inteligente y experto en desarrollo.",
934
- defaultValue: state.agentDescription,
935
- });
936
- if (p.isCancel(agentDescription)) { p.cancel("Onboarding cancelado."); process.exit(0); }
937
- state.agentDescription = agentDescription;
938
-
939
- const agentTone = await p.select({
940
- message: "🎭 Elige el tono de comunicación del agente:",
941
- options: [
942
- { value: "friendly", label: "Amigable y cercano" },
943
- { value: "professional", label: "Profesional y formal" },
944
- { value: "direct", label: "Directo y conciso" },
945
- { value: "casual", label: "Casual y relajado" },
946
- ],
947
- initialValue: state.agentTone,
948
- });
949
- if (p.isCancel(agentTone)) { p.cancel("Onboarding cancelado."); process.exit(0); }
950
- state.agentTone = agentTone as "formal" | "friendly" | "direct";
951
-
952
- // ✅ Save agent to DB (agentId se genera automáticamente)
953
- state.agentId = saveAgentConfig({
954
- userId: state.userId,
955
- agentName: state.agentName,
956
- description: state.agentDescription,
957
- tone: state.agentTone,
958
- providerId: "",
959
- modelId: "",
960
- });
961
-
962
- // Activate default ethics
963
- activateEthics(state.userId, "default");
964
-
965
- saveOnboardingProgress({
966
- step: "agent",
967
- userId: state.userId,
968
- data: { agentName: state.agentName, agentDescription: state.agentDescription, agentTone: state.agentTone, agentId: state.agentId },
969
- });
970
-
971
- log.success(`✅ Agente creado con ID: ${state.agentId}`);
972
-
973
- const nav = await askNavigation();
974
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
975
- if (nav === "prev") { step = 1; break; }
976
- step = 3;
977
- break;
978
- }
979
-
980
- // ═══════════════════════════════════
981
- // STEP 3: Ethics
982
- // ═══════════════════════════════════
983
- case 3: {
984
- showProgress(step, TOTAL_STEPS, "Ética");
985
-
986
- p.note("Los lineamientos éticos tienen MÁXIMA prioridad.", "Ética del agente");
987
-
988
- const ethicsOptions = getAllEthics();
989
- console.log("📋 Ethics options:", ethicsOptions);
990
-
991
- if (ethicsOptions.length === 0) {
992
- log.warn("No hay éticas disponibles en la BD. Usando ética por defecto.");
993
- state.ethicsId = "default";
994
- } else {
995
- const selectedEthics = await p.select({
996
- message: "¿Qué lineamientos éticos prefieres?",
997
- options: ethicsOptions.map(e => ({
998
- value: e.id,
999
- label: e.name,
1000
- hint: e.isDefault ? "Recomendado" : e.description,
1001
- })),
1002
- initialValue: state.ethicsId,
1003
- });
1004
- if (p.isCancel(selectedEthics)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1005
- state.ethicsId = selectedEthics as string;
1006
- }
1007
-
1008
- // ✅ Activate ethics in DB
1009
- activateEthics(state.userId, state.ethicsId);
1010
-
1011
- saveOnboardingProgress({
1012
- step: "ethics",
1013
- userId: state.userId,
1014
- data: { ethicsId: state.ethicsId },
1015
- });
1016
-
1017
- const nav = await askNavigation();
1018
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
1019
- if (nav === "prev") { step = 2; break; }
1020
- step = 4;
1021
- break;
1022
- }
1023
-
1024
- // ═══════════════════════════════════
1025
- // STEP 4: Provider & Model
1026
- // ═══════════════════════════════════
1027
- case 4: {
1028
- showProgress(step, TOTAL_STEPS, "Proveedor LLM");
1029
-
1030
- const provider = await p.select({
1031
- message: "¿Qué proveedor de LLM quieres usar?",
1032
- options: [
1033
- { value: "gemini", label: "Google Gemini", hint: "Recomendado — económico, gran contexto" },
1034
- { value: "anthropic", label: "Anthropic Claude", hint: "Premium — mejor calidad" },
1035
- { value: "openai", label: "OpenAI", hint: "Estándar de la industria" },
1036
- { value: "ollama", label: "Ollama (Local)", hint: "Gratis, corre localmente" },
1037
- { value: "openrouter", label: "OpenRouter", hint: "Múltiples proveedores" },
1038
- ],
1039
- initialValue: state.provider,
1040
- });
1041
- if (p.isCancel(provider)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1042
- state.provider = provider as string;
1043
-
1044
- const models = AVAILABLE_MODELS[state.provider] || [];
1045
- const model = await p.select({
1046
- message: `¿Qué modelo de ${provider}?`,
1047
- options: models,
1048
- initialValue: DEFAULT_MODELS[state.provider],
1049
- });
1050
- if (p.isCancel(model)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1051
- state.model = model as string;
1052
-
1053
- let apiKey = "";
1054
- if (state.provider !== "ollama") {
1055
- const link = API_KEY_LINKS[state.provider];
1056
- if (link) {
1057
- p.note(`Obtén tu API key en: ${link}`, "API Key");
1058
- }
1059
- const keyResult = await p.password({
1060
- message: `API key de ${state.provider}:`,
1061
- validate: (v) => (!v || v.length < 10 ? "La key parece muy corta" : undefined),
1062
- });
1063
- if (p.isCancel(keyResult)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1064
- apiKey = keyResult;
1065
- }
1066
- state.apiKey = apiKey;
1067
-
1068
- // ✅ Save provider & activate model in DB
1069
- await saveProviderConfig({
1070
- userId: state.userId,
1071
- provider: state.provider,
1072
- model: state.model,
1073
- apiKey: state.apiKey,
1074
- baseUrl: PROVIDER_BASE_URLS[state.provider],
1075
- });
1076
-
1077
- saveOnboardingProgress({
1078
- step: "provider",
1079
- userId: state.userId,
1080
- data: { provider: state.provider, model: state.model },
1081
- });
1082
-
1083
- const nav = await askNavigation();
1084
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
1085
- if (nav === "prev") { step = 3; break; }
1086
- step = 5;
1087
- break;
1088
- }
1089
-
1090
- // ═══════════════════════════════════
1091
- // STEP 5: Voice Configuration
1092
- // ═══════════════════════════════════
1093
- case 5: {
1094
- showProgress(step, TOTAL_STEPS, "Voz");
1095
-
1096
- p.note("Configura el reconocimiento de voz y síntesis de audio.", "Voz");
1097
-
1098
- const wantsVoice = await p.confirm({
1099
- message: "¿Quieres habilitar voz en tu agente?",
1100
- initialValue: false,
1101
- });
1102
- if (p.isCancel(wantsVoice)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1103
-
1104
- state.voiceEnabled = wantsVoice as boolean;
1105
-
1106
- if (wantsVoice) {
1107
- // Variables to store API keys for saving to DB later
1108
- let sttApiKeyValue: string | null = null;
1109
- let ttsApiKeyValue: string | null = null;
1110
-
1111
- // Ask for STT provider (speech-to-text)
1112
- const sttProvider = await p.select({
1113
- message: "¿Qué servicio de transcripción de voz (STT)?",
1114
- options: [
1115
- { value: "whisper-large-v3-turbo", label: "Groq Whisper Large V3 Turbo", hint: "Recomendado - rápido" },
1116
- { value: "whisper-large-v3", label: "Groq Whisper Large V3", hint: "Máxima precisión" },
1117
- { value: "distil-whisper-large-v3-en", label: "Groq Distil Whisper Large V3", hint: "Solo inglés" },
1118
- { value: "whisper-1", label: "OpenAI Whisper 1", hint: "Alternativa" },
1119
- ],
1120
- initialValue: state.sttProvider || "whisper-large-v3-turbo",
1121
- });
1122
- if (p.isCancel(sttProvider)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1123
- state.sttProvider = sttProvider as string;
1124
-
1125
- // Ask for API key based on STT provider
1126
- const isGroqStt = ["whisper-large-v3", "whisper-large-v3-turbo", "distil-whisper-large-v3-en"].includes(sttProvider);
1127
- const isOpenAiStt = sttProvider === "whisper-1";
1128
-
1129
- if (isGroqStt) {
1130
- const existingGroqKey = getEnvApiKey("GROQ_API_KEY");
1131
- let groqKey: string | null = existingGroqKey;
1132
-
1133
- if (!groqKey) {
1134
- const groqKeyInput = await p.password({
1135
- message: "Ingresa tu GROQ_API_KEY:",
1136
- validate: (value) => {
1137
- if (!value || value.length < 10) return "API key inválida";
1138
- },
1139
- });
1140
- if (p.isCancel(groqKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1141
- groqKey = groqKeyInput as string;
1142
- sttApiKeyValue = groqKey;
1143
-
1144
- // Save Groq API key to .env
1145
- const hiveDir = getHiveDir();
1146
- const envPath = path.join(hiveDir, ".env");
1147
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1148
- const newEnv = envContent.includes("GROQ_API_KEY")
1149
- ? envContent.replace(/GROQ_API_KEY=.*/g, `GROQ_API_KEY=${groqKey}`)
1150
- : envContent + `\nGROQ_API_KEY=${groqKey}`;
1151
- fs.writeFileSync(envPath, newEnv);
1152
- reloadEnvToProcess(hiveDir);
1153
- log.success("✅ API key de Groq guardada en .env");
1154
- } else {
1155
- log.info("✅ GROQ_API_KEY ya configurada en .env");
1156
- sttApiKeyValue = groqKey;
1157
- }
1158
- } else if (isOpenAiStt) {
1159
- const existingOpenAiKey = getEnvApiKey("OPENAI_API_KEY");
1160
- let openaiKey: string | null = existingOpenAiKey;
1161
-
1162
- if (!openaiKey) {
1163
- const openaiKeyInput = await p.password({
1164
- message: "Ingresa tu OPENAI_API_KEY:",
1165
- validate: (value) => {
1166
- if (!value || value.length < 10) return "API key inválida";
1167
- },
1168
- });
1169
- if (p.isCancel(openaiKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1170
- openaiKey = openaiKeyInput as string;
1171
- sttApiKeyValue = openaiKey;
1172
-
1173
- // Save OpenAI API key to .env
1174
- const hiveDir = getHiveDir();
1175
- const envPath = path.join(hiveDir, ".env");
1176
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1177
- const newEnv = envContent.includes("OPENAI_API_KEY")
1178
- ? envContent.replace(/OPENAI_API_KEY=.*/g, `OPENAI_API_KEY=${openaiKey}`)
1179
- : envContent + `\nOPENAI_API_KEY=${openaiKey}`;
1180
- fs.writeFileSync(envPath, newEnv);
1181
- reloadEnvToProcess(hiveDir);
1182
- log.success("✅ API key de OpenAI guardada en .env");
1183
- } else {
1184
- log.info("✅ OPENAI_API_KEY ya configurada en .env");
1185
- sttApiKeyValue = openaiKey;
1186
- }
1187
- }
1188
-
1189
- // Ask for TTS provider (text-to-speech)
1190
- const ttsProvider = await p.select({
1191
- message: "¿Qué servicio de síntesis de voz (TTS)?",
1192
- options: [
1193
- { value: "eleven_flash_v2_5", label: "ElevenLabs Flash V2.5", hint: "Tiempo real - recomendado" },
1194
- { value: "eleven_turbo_v2_5", label: "ElevenLabs Turbo V2.5", hint: "Balance calidad/velocidad" },
1195
- { value: "eleven_multilingual_v2", label: "ElevenLabs Multilingual V2", hint: "Alta calidad" },
1196
- { value: "eleven_v3", label: "ElevenLabs V3", hint: "Más expresivo" },
1197
- { value: "qwen3-tts-instruct-flash", label: "Qwen TTS Flash", hint: "Gratis - recomendado" },
1198
- { value: "gpt-4o-mini-tts", label: "OpenAI GPT-4o Mini TTS", hint: "Usa tu API key" },
1199
- { value: "tts-1", label: "OpenAI TTS-1", hint: "Estándar" },
1200
- { value: "tts-1-hd", label: "OpenAI TTS-1 HD", hint: "Alta calidad" },
1201
- { value: "gemini-2.5-flash-preview-tts", label: "Gemini 2.5 Flash TTS", hint: "Google" },
1202
- { value: "gemini-2.5-pro-preview-tts", label: "Gemini 2.5 Pro TTS", hint: "Google Pro" },
1203
- ],
1204
- initialValue: state.ttsProvider || "eleven_flash_v2_5",
1205
- });
1206
- if (p.isCancel(ttsProvider)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1207
- state.ttsProvider = ttsProvider as string;
1208
-
1209
- // Ask for API key based on TTS provider
1210
- const isElevenLabs = ["eleven_flash_v2_5", "eleven_turbo_v2_5", "eleven_multilingual_v2", "eleven_v3"].includes(ttsProvider);
1211
- const isOpenAI = ["gpt-4o-mini-tts", "tts-1", "tts-1-hd"].includes(ttsProvider);
1212
- const isGemini = ["gemini-2.5-flash-preview-tts", "gemini-2.5-pro-preview-tts"].includes(ttsProvider);
1213
- const isQwen = ["qwen3-tts-instruct-flash", "qwen3-tts-flash", "qwen-tts"].includes(ttsProvider);
1214
-
1215
- if (isElevenLabs) {
1216
- const existingElevenKey = getEnvApiKey("ELEVENLABS_API_KEY");
1217
- let elevenKey: string | null = existingElevenKey;
1218
-
1219
- if (!elevenKey) {
1220
- const elevenKeyInput = await p.password({
1221
- message: "Ingresa tu ELEVENLABS_API_KEY:",
1222
- validate: (value) => {
1223
- if (!value || value.length < 10) return "API key inválida";
1224
- },
1225
- });
1226
- if (p.isCancel(elevenKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1227
- elevenKey = elevenKeyInput as string;
1228
- state.elevenlabsApiKey = elevenKey;
1229
-
1230
- // Save to .env
1231
- const hiveDir = getHiveDir();
1232
- const envPath = path.join(hiveDir, ".env");
1233
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1234
- const newEnv = envContent.includes("ELEVENLABS_API_KEY")
1235
- ? envContent.replace(/ELEVENLABS_API_KEY=.*/g, `ELEVENLABS_API_KEY=${elevenKey}`)
1236
- : envContent + `\nELEVENLABS_API_KEY=${elevenKey}`;
1237
- fs.writeFileSync(envPath, newEnv);
1238
- reloadEnvToProcess(hiveDir);
1239
- log.success("✅ API key de ElevenLabs guardada en .env");
1240
- } else {
1241
- log.info("✅ ELEVENLABS_API_KEY ya configurada en .env");
1242
- state.elevenlabsApiKey = elevenKey;
1243
- }
1244
- ttsApiKeyValue = elevenKey;
1245
- } else if (isOpenAI) {
1246
- const existingOpenAiKey = getEnvApiKey("OPENAI_API_KEY");
1247
- let openaiKey: string | null = existingOpenAiKey;
1248
-
1249
- if (!openaiKey) {
1250
- const openaiKeyInput = await p.password({
1251
- message: "Ingresa tu OPENAI_API_KEY:",
1252
- validate: (value) => {
1253
- if (!value || value.length < 10) return "API key inválida";
1254
- },
1255
- });
1256
- if (p.isCancel(openaiKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1257
- openaiKey = openaiKeyInput as string;
1258
-
1259
- // Save to .env
1260
- const hiveDir = getHiveDir();
1261
- const envPath = path.join(hiveDir, ".env");
1262
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1263
- const newEnv = envContent.includes("OPENAI_API_KEY")
1264
- ? envContent.replace(/OPENAI_API_KEY=.*/g, `OPENAI_API_KEY=${openaiKey}`)
1265
- : envContent + `\nOPENAI_API_KEY=${openaiKey}`;
1266
- fs.writeFileSync(envPath, newEnv);
1267
- reloadEnvToProcess(hiveDir);
1268
- log.success("✅ API key de OpenAI guardada en .env");
1269
- } else {
1270
- log.info("✅ OPENAI_API_KEY ya configurada en .env");
1271
- }
1272
- ttsApiKeyValue = openaiKey;
1273
- } else if (isGemini) {
1274
- const existingGeminiKey = getEnvApiKey("GEMINI_API_KEY");
1275
- let geminiKey: string | null = existingGeminiKey;
1276
-
1277
- if (!geminiKey) {
1278
- const geminiKeyInput = await p.password({
1279
- message: "Ingresa tu GEMINI_API_KEY:",
1280
- validate: (value) => {
1281
- if (!value || value.length < 10) return "API key inválida";
1282
- },
1283
- });
1284
- if (p.isCancel(geminiKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1285
- geminiKey = geminiKeyInput as string;
1286
-
1287
- // Save to .env
1288
- const hiveDir = getHiveDir();
1289
- const envPath = path.join(hiveDir, ".env");
1290
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1291
- const newEnv = envContent.includes("GEMINI_API_KEY")
1292
- ? envContent.replace(/GEMINI_API_KEY=.*/g, `GEMINI_API_KEY=${geminiKey}`)
1293
- : envContent + `\nGEMINI_API_KEY=${geminiKey}`;
1294
- fs.writeFileSync(envPath, newEnv);
1295
- reloadEnvToProcess(hiveDir);
1296
- log.success("✅ API key de Gemini guardada en .env");
1297
- } else {
1298
- log.info("✅ GEMINI_API_KEY ya configurada en .env");
1299
- }
1300
- ttsApiKeyValue = geminiKey;
1301
- } else if (isQwen) {
1302
- const existingQwenKey = getEnvApiKey("DASHSCOPE_API_KEY");
1303
- let qwenKey: string | null = existingQwenKey;
1304
-
1305
- if (!qwenKey) {
1306
- const qwenKeyInput = await p.password({
1307
- message: "Ingresa tu DASHSCOPE_API_KEY (Qwen/Alibaba):",
1308
- validate: (value) => {
1309
- if (!value || value.length < 10) return "API key inválida";
1310
- },
1311
- });
1312
- if (p.isCancel(qwenKeyInput)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1313
- qwenKey = qwenKeyInput as string;
1314
-
1315
- // Save to .env
1316
- const hiveDir = getHiveDir();
1317
- const envPath = path.join(hiveDir, ".env");
1318
- const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
1319
- const newEnv = envContent.includes("DASHSCOPE_API_KEY")
1320
- ? envContent.replace(/DASHSCOPE_API_KEY=.*/g, `DASHSCOPE_API_KEY=${qwenKey}`)
1321
- : envContent + `\nDASHSCOPE_API_KEY=${qwenKey}`;
1322
- fs.writeFileSync(envPath, newEnv);
1323
- reloadEnvToProcess(hiveDir);
1324
- log.success("✅ API key de Qwen guardada en .env");
1325
- } else {
1326
- log.info("✅ DASHSCOPE_API_KEY ya configurada en .env");
1327
- }
1328
- ttsApiKeyValue = qwenKey;
1329
- }
1330
-
1331
- // Save voice config to channel (for webchat as default)
1332
- // API keys are saved in .env and encrypted in BD
1333
- await saveVoiceConfig({
1334
- userId: state.userId,
1335
- channelId: "webchat",
1336
- voiceEnabled: true,
1337
- sttProvider: sttProvider as string,
1338
- ttsProvider: ttsProvider as string,
1339
- sttApiKey: sttApiKeyValue || undefined,
1340
- ttsApiKey: ttsApiKeyValue || undefined,
1341
- });
1342
- log.success("✅ Configuración de voz guardada en BD");
1343
- }
1344
-
1345
- const nav2 = await askNavigation();
1346
- if (nav2 === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
1347
- if (nav2 === "prev") { step = 4; break; }
1348
- step = 6;
1349
- break;
1350
- }
1351
-
1352
- // ═══════════════════════════════════
1353
- // STEP 6: Channels
1354
- // ═══════════════════════════════════
1355
- case 6: {
1356
- showProgress(step, TOTAL_STEPS, "Canales");
1357
-
1358
- // WebChat siempre activado por defecto
1359
- state.channel = "webchat";
1360
-
1361
- // ✅ Activar WebChat en BD (UPDATE del seed)
1362
- await activateChannel(state.userId, {
1363
- channelId: "webchat",
1364
- channelUserId: state.sessionToken,
1365
- });
1366
-
1367
- log.success("✅ WebChat activado por defecto (http://localhost:18790/ui)");
1368
-
1369
- // Preguntar si quiere activar Telegram (recomendado)
1370
- const activateTelegram = await p.confirm({
1371
- message: "¿Quieres activar Telegram? (recomendado para notificaciones)",
1372
- initialValue: false,
1373
- });
1374
- if (p.isCancel(activateTelegram)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1375
-
1376
- if (activateTelegram) {
1377
- p.note(
1378
- "1. Abre Telegram y busca @BotFather\n" +
1379
- "2. Escribe /newbot y sigue las instrucciones\n" +
1380
- "3. Copia el token",
1381
- "Cómo obtener token de Telegram"
1382
- );
1383
- const tokenResult = await p.password({
1384
- message: "Token de Telegram:",
1385
- validate: (v) => (!v?.trim() ? "El token no puede estar vacío" : undefined),
1386
- });
1387
- if (p.isCancel(tokenResult)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1388
- state.channelToken = tokenResult;
1389
-
1390
- // ✅ Activar Telegram en BD (UPDATE del seed)
1391
- await activateChannel(state.userId, {
1392
- channelId: "telegram",
1393
- config: { botToken: state.channelToken, dmPolicy: "open" },
1394
- });
1395
-
1396
- log.success("✅ Telegram activado");
1397
- }
1398
-
1399
- saveOnboardingProgress({
1400
- step: "channel",
1401
- userId: state.userId,
1402
- data: { channel: "webchat", telegram: activateTelegram },
1403
- });
1404
-
1405
- const nav = await askNavigation();
1406
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
1407
- if (nav === "prev") { step = 4; break; }
1408
- step = 7;
1409
- break;
1410
- }
1411
-
1412
- // ═══════════════════════════════════
1413
- // STEP 7: Code Bridge
1414
- // ═══════════════════════════════════
1415
- case 7: {
1416
- showProgress(step, TOTAL_STEPS, "Code Bridge");
1417
-
1418
- const codeBridgeEnabled = await p.confirm({
1419
- message: "¿Quieres delegar tareas de código a CLIs externos? (claude-code, gemini, qwen, opencode)",
1420
- initialValue: state.codeBridgeEnabled,
1421
- });
1422
- if (p.isCancel(codeBridgeEnabled)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1423
- state.codeBridgeEnabled = codeBridgeEnabled as boolean;
1424
-
1425
- let codeBridgeClis: string[] = [];
1426
- if (state.codeBridgeEnabled) {
1427
- const availableClis = getAllCodeBridge();
1428
-
1429
- if (availableClis.length === 0) {
1430
- log.warn("⚠️ No hay CLIs de code bridge configurados. Puedes agregar más desde el dashboard.");
1431
- } else {
1432
- log.info("Selecciona los CLIs que tengas instalados (presiona Espacio para seleccionar, Enter para continuar):");
1433
- const selectedClis = await p.multiselect({
1434
- message: "¿Qué CLIs tienes instalados?",
1435
- options: availableClis.map(cb => ({
1436
- value: cb.id,
1437
- label: cb.name,
1438
- hint: cb.cliCommand,
1439
- })),
1440
- required: false,
1441
- });
1442
- if (p.isCancel(selectedClis)) { p.cancel("Onboarding cancelado."); process.exit(0); }
1443
- codeBridgeClis = (selectedClis as string[]) || [];
1444
- }
1445
- }
1446
- state.codeBridgeClis = codeBridgeClis;
1447
-
1448
- // ✅ Save code bridge config in DB
1449
- const codeBridgeConfig = getAllCodeBridge().map(cb => ({
1450
- id: cb.id,
1451
- enabled: codeBridgeClis.includes(cb.id),
1452
- port: cb.port,
1453
- }));
1454
- activateCodeBridge(state.userId, codeBridgeConfig);
1455
-
1456
- // ✅ MCP servers se agregan desactivados (se configuran desde el dashboard)
1457
- log.info("ℹ️ MCP servers disponibles (configura desde el dashboard)");
1458
-
1459
- saveOnboardingProgress({
1460
- step: "codebridge",
1461
- userId: state.userId,
1462
- data: { enabled: state.codeBridgeEnabled, clis: codeBridgeClis },
1463
- });
1464
-
1465
- const nav = await askNavigation();
1466
- if (nav === "cancel") { p.cancel("Onboarding cancelado."); process.exit(0); }
1467
- if (nav === "prev") { step = 5; break; }
1468
- step = 8;
1469
- break;
1470
- }
1471
-
1472
- // ═══════════════════════════════════
1473
- // STEP 8: Resumen Final
1474
- // ═══════════════════════════════════
1475
- case 8: {
1476
- showProgress(step, TOTAL_STEPS, "Resumen final");
1477
-
1478
-
1479
- // Show summary
1480
- p.note(
1481
- ` Agente: ${state.agentName}\n` +
1482
- ` Usuario: ${state.userName}\n` +
1483
- ` Idioma: ${state.userLanguage}\n` +
1484
- ` Proveedor: ${state.provider} (${state.model})\n` +
1485
- ` Voz: ${state.voiceEnabled ? `STT: ${state.sttProvider}, TTS: ${state.ttsProvider}` : "no"}\n` +
1486
- ` Canal: ${state.channel}${state.channelToken ? ' (Telegram configurado)' : ''}\n` +
1487
- ` Code Bridge: ${state.codeBridgeEnabled ? state.codeBridgeClis.join(", ") : "no"}`,
1488
- "📋 Resumen final"
1489
- );
1490
-
1491
- const confirm = await p.select({
1492
- message: "¿Confirmar configuración?",
1493
- options: [
1494
- { value: "confirm", label: "✅ Confirmar", hint: "Crear agente" },
1495
- { value: "prev", label: "⬅️ Atrás", hint: "Editar" },
1496
- { value: "cancel", label: "❌ Cancelar", hint: "Salir" },
1497
- ],
1498
- });
1499
-
1500
- if (p.isCancel(confirm) || confirm === "cancel") {
1501
- p.cancel("Onboarding cancelado.");
1502
- process.exit(0);
1503
- }
1504
-
1505
- if (confirm === "prev") {
1506
- step = 7;
1507
- break;
1508
- }
1509
-
1510
- // ✅ Create agent in DB (FINAL STEP)
1511
- saveAgentConfig({
1512
- userId: state.userId,
1513
- agentId: state.agentId,
1514
- agentName: state.agentName,
1515
- providerId: state.provider,
1516
- modelId: state.model,
1517
- tone: state.agentTone,
1518
- description: state.agentDescription,
1519
- });
1520
-
1521
- saveOnboardingProgress({
1522
- step: "agent",
1523
- userId: state.userId,
1524
- data: { agentId: state.agentId, agentName: state.agentName },
1525
- });
1526
-
1527
- // 📝 Guardar IDs en .env
1528
- const envPath = path.join(hiveDir, ".env");
1529
- let envContent = "";
1530
- if (fs.existsSync(envPath)) {
1531
- envContent = fs.readFileSync(envPath, "utf-8");
1532
- }
1533
-
1534
- const envVars = {
1535
- HIVE_USER_ID: state.userId,
1536
- HIVE_AGENT_ID: state.agentId,
1537
- };
1538
-
1539
- let newEnvContent = envContent;
1540
- for (const [key, value] of Object.entries(envVars)) {
1541
- const regex = new RegExp(`^${key}=.*`, "m");
1542
- if (regex.test(newEnvContent)) {
1543
- newEnvContent = newEnvContent.replace(regex, `${key}=${value}`);
1544
- } else {
1545
- newEnvContent += `\n${key}=${value}`;
1546
- }
1547
- }
1548
- fs.writeFileSync(envPath, newEnvContent.trim() + "\n");
1549
- log.info(`IDs de identidad persistidos en ${envPath}`);
1550
-
1551
- step = TOTAL_STEPS + 1;
1552
- break;
1553
- }
1554
- }
1555
- }
1556
-
1557
- // ═══════════════════════════════════
1558
- // FINAL: Show success message
1559
- // ═══════════════════════════════════
1560
-
1561
- p.outro(
1562
- `✅ ¡Configuración completada!\n\n` +
1563
- ` 🤖 Agente: ${state.agentName}\n` +
1564
- ` 👤 Usuario: ${state.userName}\n` +
1565
- ` 🧠 Provider: ${state.provider}/${state.model}\n` +
1566
- ` 📢 Canal: WebChat (UI web)\n` +
1567
- `${state.channelToken ? ` ✈️ Telegram: Configurado\n` : ''}` +
1568
- `${state.voiceEnabled ? ` 🎤 Voz: STT (${state.sttProvider}) + TTS (${state.ttsProvider})\n` : ''}` +
1569
- `${state.codeBridgeEnabled ? ` 🔧 Code Bridge: ${state.codeBridgeClis.join(', ')}\n` : ''}` +
1570
- `\n` +
1571
- `🌐 ABRE TU DASHBOARD:\n` +
1572
- ` 👉 http://localhost:5173\n\n` +
1573
- `📋 COMANDOS:\n` +
1574
- ` hive start → Arrancar gateway\n` +
1575
- ` hive chat → Chatear en terminal\n\n` +
1576
- `💡 DESDE EL DASHBOARD puedes activar:\n` +
1577
- ` • Canales adicionales (Discord, Slack, WhatsApp, etc.)\n` +
1578
- ` • Voz (STT/TTS) para audio en tiempo real\n` +
1579
- ` • Code Bridge para delegar tareas de código\n` +
1580
- ` • MCP servers para herramientas externas\n` +
1581
- ` • Tools y funciones personalizadas\n` +
1582
- `\n` +
1583
- `🎉 ¡Gracias por configurar Hive!`
1584
- );
1585
-
1586
- // Ask if user wants to start the gateway
1587
- const shouldStart = await p.confirm({
1588
- message: "¿Quieres iniciar el gateway ahora?",
1589
- initialValue: true,
1590
- });
1591
-
1592
- if (p.isCancel(shouldStart) || !shouldStart) {
1593
- log.info("¡Perfecto! Ejecuta 'hive start' cuando quieras iniciar.");
1594
- return;
1595
- }
1596
-
1597
- log.info("🚀 Iniciando Hive gateway...");
1598
- }
1599
-
1600
- export async function onboard(): Promise<void> {
1601
- const hiveDir = getHiveDir();
1602
-
1603
- // Create Hive directory if it doesn't exist
1604
- if (!fs.existsSync(hiveDir)) {
1605
- log.info(`📁 Creando carpeta de configuración: ${hiveDir}`);
1606
- fs.mkdirSync(hiveDir, { recursive: true });
1607
- }
1608
-
1609
- // Initialize DB first to check existing configuration
1610
- initOnboardingDb();
1611
-
1612
- // Check if there's already an agent in the database
1613
- const { getDb } = await import("../../../core/src/storage/sqlite");
1614
- const db = getDb();
1615
- // We look for the coordinator agent. In a personal gateway, there is usually only one.
1616
- const existingAgent = db.query("SELECT id, name, provider_id, model_id, status FROM agents WHERE role = 'coordinator' ORDER BY created_at DESC LIMIT 1").get() as any;
1617
-
1618
- // If agent exists and is completed (status = 'idle'), don't show onboarding menu
1619
- if (existingAgent && existingAgent.status === 'idle') {
1620
- p.intro("✅ Configuración completada detectada");
1621
-
1622
- p.note(
1623
- ` Agente: ${existingAgent.name}\n` +
1624
- ` ID: ${existingAgent.id}\n` +
1625
- ` Provider: ${existingAgent.provider_id || "no configurado"}\n` +
1626
- ` Model: ${existingAgent.model_id || "no configurado"}\n` +
1627
- ` Status: idle (listo para usar)`,
1628
- "Config actual en BD"
1629
- );
1630
-
1631
- console.log("\n💡 Para iniciar el gateway: hive start\n");
1632
- return;
1633
- }
1634
-
1635
- if (existingAgent) {
1636
- p.intro("🔍 Configuración existente detectada");
1637
-
1638
- p.note(
1639
- ` Agente: ${existingAgent.name}\n` +
1640
- ` ID: ${existingAgent.id}\n` +
1641
- ` Provider: ${existingAgent.provider_id || "no configurado"}\n` +
1642
- ` Model: ${existingAgent.model_id || "no configurado"}\n` +
1643
- ` Status: ${existingAgent.status}`,
1644
- "Config actual en BD"
1645
- );
1646
-
1647
- const action = await p.select({
1648
- message: "¿Qué quieres hacer?",
1649
- options: [
1650
- { value: "update", label: "Actualizar", hint: "Modificar configuración" },
1651
- { value: "reset", label: "Reiniciar", hint: "Borrar BD y crear desde cero" },
1652
- { value: "cancel", label: "Cancelar", hint: "Salir sin cambios" },
1653
- ],
1654
- });
1655
-
1656
- if (p.isCancel(action) || action === "cancel") {
1657
- p.cancel("Operación cancelada.");
1658
- process.exit(0);
1659
- }
1660
-
1661
- if (action === "reset") {
1662
- const confirm = await p.confirm({
1663
- message: "⚠️ Esto BORRARÁ toda la base de datos y reiniciará la configuración. ¿Continuar?",
1664
- initialValue: false,
1665
- });
1666
-
1667
- if (p.isCancel(confirm) || !confirm) {
1668
- p.cancel("Operación cancelada.");
1669
- process.exit(0);
1670
- }
1671
-
1672
- // Backup and delete database
1673
- const dbPath = path.join(hiveDir, "data", "hive.db");
1674
- if (fs.existsSync(dbPath)) {
1675
- const backupPath = path.join(hiveDir, `hive.db.backup.${Date.now()}`);
1676
- fs.copyFileSync(dbPath, backupPath);
1677
- log.info(`Backup BD creado: ${backupPath}`);
1678
-
1679
- // Delete the database file
1680
- fs.unlinkSync(dbPath);
1681
- log.info("Base de datos eliminada");
1682
- }
1683
-
1684
- // Reinitialize DB (creates fresh with seed)
1685
- initOnboardingDb();
1686
-
1687
- log.success("BD reiniciada con datos del sistema");
1688
- }
1689
-
1690
- // After reset or update, run the wizard
1691
- await runFullWizard();
1692
- } else {
1693
- // No existing configuration - run full wizard
1694
- await runFullWizard();
1695
- }
1696
- }