@johpaz/hive-agents 0.0.35 → 0.0.37

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 (441) hide show
  1. package/README.md +64 -39
  2. package/dist/hive.js +3231 -3189
  3. package/dist/tool-worker.js +218406 -0
  4. package/dist/ui/assets/{AgentCreateForm-B4eK7efF.js → AgentCreateForm-tJZv9FZC.js} +1 -1
  5. package/dist/ui/assets/{AgentDetailPage-BD2uoJWk.js → AgentDetailPage-Du-mRcAX.js} +1 -1
  6. package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  7. package/dist/ui/assets/{AgentsPage-4JUZXvkA.js → AgentsPage-YvSgWRiw.js} +6 -6
  8. package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
  9. package/dist/ui/assets/{ChannelsPage-BUn7-nhV.js → ChannelsPage-BdBXWHjj.js} +1 -1
  10. package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
  11. package/dist/ui/assets/{LoginPage-C8j_urUD.js → LoginPage-CAmSI9Vy.js} +1 -1
  12. package/dist/ui/assets/LogsPage-DAPBHkwK.js +1 -0
  13. package/dist/ui/assets/MeetingPage-WjjGOqqU.js +1 -0
  14. package/dist/ui/assets/{NotFound-Drh-sJPN.js → NotFound-BMeQSGcG.js} +1 -1
  15. package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  16. package/dist/ui/assets/{RecoverPage-DNb1Pr8h.js → RecoverPage-DpW3l-yv.js} +1 -1
  17. package/dist/ui/assets/SettingsPage-DBJ7_E6C.js +9 -0
  18. package/dist/ui/assets/SetupPage-DKmLVUaj.js +1 -0
  19. package/dist/ui/assets/{WebChatPage-R-YOwA4F.js → WebChatPage-CVRcKept.js} +2 -2
  20. package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
  21. package/dist/ui/assets/{alert-U8FsgWi7.js → alert-C-NE-P3s.js} +1 -1
  22. package/dist/ui/assets/{alert-dialog-CRdMkkmk.js → alert-dialog-C5mzbHdP.js} +1 -1
  23. package/dist/ui/assets/{badge-Cli1jnH5.js → badge-ChpACfWO.js} +1 -1
  24. package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
  25. package/dist/ui/assets/{dialog-DQ3s-LuO.js → dialog-QnZ0ad8O.js} +1 -1
  26. package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
  27. package/dist/ui/assets/{es-DcMjrpbA.js → es-NQNoaWDx.js} +1 -1
  28. package/dist/ui/assets/index-B2fCYtTS.css +2 -0
  29. package/dist/ui/assets/index-DMCjjdqf.js +116 -0
  30. package/dist/ui/assets/{label-0BvGVXvZ.js → label-D2H1IR_J.js} +1 -1
  31. package/dist/ui/assets/progress-BherYzY6.js +1 -0
  32. package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
  33. package/dist/ui/assets/{slider-D47dOrRa.js → slider-CsiUDxc3.js} +1 -1
  34. package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
  35. package/dist/ui/assets/{table-DhowbNxQ.js → table-CSc8ubon.js} +1 -1
  36. package/dist/ui/assets/terminal-DN38Q456.js +1 -0
  37. package/dist/ui/assets/useProviders-C6_QHsEi.js +1 -0
  38. package/dist/ui/assets/{vendor-radix-JY4ncZrD.js → vendor-radix-cw1bQaVC.js} +4 -4
  39. package/dist/ui/assets/{vendor-react-CscwQerf.js → vendor-react-D4s9E-zj.js} +1 -1
  40. package/dist/ui/dist/assets/AgentCreateForm-tJZv9FZC.js +1 -0
  41. package/dist/ui/dist/assets/AgentDetailPage-Du-mRcAX.js +1 -0
  42. package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  43. package/dist/ui/dist/assets/AgentsPage-YvSgWRiw.js +10 -0
  44. package/dist/ui/dist/assets/CanvasPage-DtMwGvxf.js +33 -0
  45. package/dist/ui/dist/assets/ChannelsPage-BdBXWHjj.js +8 -0
  46. package/dist/ui/dist/assets/DashboardPage-ghl1ZguH.js +6 -0
  47. package/dist/ui/dist/assets/LoginPage-CAmSI9Vy.js +1 -0
  48. package/dist/ui/dist/assets/LogsPage-DAPBHkwK.js +1 -0
  49. package/dist/ui/dist/assets/MeetingPage-WjjGOqqU.js +1 -0
  50. package/dist/ui/dist/assets/NotFound-BMeQSGcG.js +1 -0
  51. package/dist/ui/dist/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  52. package/dist/ui/dist/assets/RecoverPage-DpW3l-yv.js +1 -0
  53. package/dist/ui/dist/assets/SettingsPage-DBJ7_E6C.js +9 -0
  54. package/dist/ui/dist/assets/SetupPage-DKmLVUaj.js +1 -0
  55. package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +16 -0
  56. package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +1 -0
  57. package/dist/ui/dist/assets/activity-c3pNngT_.js +1 -0
  58. package/dist/ui/dist/assets/alert-C-NE-P3s.js +1 -0
  59. package/dist/ui/dist/assets/alert-dialog-C5mzbHdP.js +1 -0
  60. package/dist/ui/dist/assets/arrow-left-CBcbX5EZ.js +1 -0
  61. package/dist/ui/dist/assets/badge-ChpACfWO.js +1 -0
  62. package/dist/ui/dist/assets/calendar-B-KZ9RQO.js +1 -0
  63. package/dist/ui/dist/assets/card-CNf6BS2e.js +1 -0
  64. package/dist/ui/dist/assets/chevron-left-D4U-5A27.js +1 -0
  65. package/dist/ui/dist/assets/chevron-right-CR4Skrf3.js +1 -0
  66. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +1 -0
  67. package/dist/ui/dist/assets/circle-alert-CyHDwUj8.js +1 -0
  68. package/dist/ui/dist/assets/circle-check-Bb54Ebmu.js +1 -0
  69. package/dist/ui/dist/assets/cpu-Cdgc_B1K.js +1 -0
  70. package/dist/ui/dist/assets/dialog-QnZ0ad8O.js +1 -0
  71. package/dist/ui/dist/assets/download-C3ifGMjJ.js +1 -0
  72. package/dist/ui/dist/assets/dropdown-menu-BK-CO3Od.js +1 -0
  73. package/dist/ui/dist/assets/es-NQNoaWDx.js +1 -0
  74. package/dist/ui/dist/assets/external-link-BvxYeTP1.js +1 -0
  75. package/dist/ui/dist/assets/eye-DqNTU_GD.js +1 -0
  76. package/dist/ui/dist/assets/file-text-BT_9S9SM.js +1 -0
  77. package/dist/ui/dist/assets/folder-open-BhH8y9ac.js +1 -0
  78. package/dist/ui/dist/assets/format-GVHeOyWI.js +1 -0
  79. package/dist/ui/dist/assets/gateway-url-COCbW0IR.js +1 -0
  80. package/dist/ui/dist/assets/gauge-D_TMa4i9.js +1 -0
  81. package/dist/ui/dist/assets/globe-DeCQTCDJ.js +1 -0
  82. package/dist/ui/dist/assets/hexagon-DsGOUl-H.js +1 -0
  83. package/dist/ui/dist/assets/history-BSG-Ypqf.js +1 -0
  84. package/dist/ui/dist/assets/index-B2fCYtTS.css +2 -0
  85. package/dist/ui/dist/assets/index-DMCjjdqf.js +116 -0
  86. package/dist/ui/dist/assets/info-NwLoa2Mj.js +1 -0
  87. package/dist/ui/dist/assets/key-3EP0dhkT.js +1 -0
  88. package/dist/ui/dist/assets/label-D2H1IR_J.js +1 -0
  89. package/dist/ui/dist/assets/loader-circle-CZNax6kS.js +1 -0
  90. package/dist/ui/dist/assets/lock-Ei1_J-Nq.js +1 -0
  91. package/dist/ui/dist/assets/pause-BUqah9Bi.js +1 -0
  92. package/dist/ui/dist/assets/play-NcZ4swwL.js +1 -0
  93. package/dist/ui/dist/assets/plus-CX1xyhp5.js +1 -0
  94. package/dist/ui/dist/assets/progress-BherYzY6.js +1 -0
  95. package/dist/ui/dist/assets/refresh-cw-DaYdjQFk.js +1 -0
  96. package/dist/ui/dist/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
  97. package/dist/ui/dist/assets/save-CUdYyHNy.js +1 -0
  98. package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +1 -0
  99. package/dist/ui/dist/assets/send-B0H5SEIE.js +1 -0
  100. package/dist/ui/dist/assets/settings-Ds4SqD8s.js +1 -0
  101. package/dist/ui/dist/assets/slider-CsiUDxc3.js +14 -0
  102. package/dist/ui/dist/assets/sparkles-yUEb-7oH.js +1 -0
  103. package/dist/ui/dist/assets/square-BD81nFtN.js +1 -0
  104. package/dist/ui/dist/assets/switch-BDwN8RYV.js +1 -0
  105. package/dist/ui/dist/assets/table-CSc8ubon.js +1 -0
  106. package/dist/ui/dist/assets/terminal-DN38Q456.js +1 -0
  107. package/dist/ui/dist/assets/textarea-CXgXWKrT.js +1 -0
  108. package/dist/ui/dist/assets/trash-2-CNjMkoq6.js +1 -0
  109. package/dist/ui/dist/assets/triangle-alert-C9Y8Ub4X.js +1 -0
  110. package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +1 -0
  111. package/dist/ui/dist/assets/utils-3pnRFmFe.js +1 -0
  112. package/dist/ui/dist/assets/vendor-charts-Bu2lyBKP.js +65 -0
  113. package/dist/ui/dist/assets/vendor-query-DsWPbQdG.js +1 -0
  114. package/dist/ui/dist/assets/vendor-radix-cw1bQaVC.js +63 -0
  115. package/dist/ui/dist/assets/vendor-react-D4s9E-zj.js +1 -0
  116. package/dist/ui/dist/assets/vendor-router-C9pIYwbJ.js +3 -0
  117. package/dist/ui/dist/assets/volume-2-CeSXNDv4.js +1 -0
  118. package/dist/ui/dist/assets/zap-hlXjpSeA.js +1 -0
  119. package/dist/ui/dist/favicon.ico +0 -0
  120. package/dist/ui/dist/index.html +40 -0
  121. package/dist/ui/dist/placeholder.svg +1 -0
  122. package/dist/ui/index.html +6 -6
  123. package/package.json +138 -13
  124. package/packages/cli/src/adapters/binary.ts +461 -0
  125. package/packages/cli/src/adapters/bun-global.ts +378 -0
  126. package/packages/cli/src/adapters/config.ts +314 -0
  127. package/packages/cli/src/adapters/docker.ts +308 -0
  128. package/packages/cli/src/adapters/factory.ts +168 -0
  129. package/packages/cli/src/adapters/index.ts +80 -0
  130. package/packages/cli/src/adapters/types.ts +218 -0
  131. package/packages/cli/src/commands/agent-run.ts +168 -0
  132. package/packages/cli/src/commands/agents.ts +398 -0
  133. package/packages/cli/src/commands/chat.ts +142 -0
  134. package/packages/cli/src/commands/config.ts +49 -0
  135. package/packages/cli/src/commands/cron.ts +487 -0
  136. package/packages/cli/src/commands/dev.ts +58 -0
  137. package/packages/cli/src/commands/doctor.ts +320 -0
  138. package/packages/cli/src/commands/gateway.ts +719 -0
  139. package/packages/cli/src/commands/logs.ts +57 -0
  140. package/packages/cli/src/commands/mcp.ts +175 -0
  141. package/packages/cli/src/commands/message.ts +77 -0
  142. package/packages/cli/src/commands/migrate.ts +90 -0
  143. package/packages/cli/src/commands/onboard.ts +1656 -0
  144. package/packages/cli/src/commands/security.ts +144 -0
  145. package/packages/cli/src/commands/service.ts +50 -0
  146. package/packages/cli/src/commands/sessions.ts +116 -0
  147. package/packages/cli/src/commands/skills.ts +215 -0
  148. package/packages/cli/src/commands/update.ts +203 -0
  149. package/packages/cli/src/index.ts +210 -0
  150. package/packages/cli/src/ui-bundle.generated.ts +3 -0
  151. package/packages/cli/src/utils/token.ts +6 -0
  152. package/packages/core/src/agent/agent-loop.ts +691 -0
  153. package/packages/core/src/agent/compaction.ts +240 -0
  154. package/packages/core/src/agent/context-compiler.ts +467 -0
  155. package/packages/core/src/agent/context-guard.ts +91 -0
  156. package/packages/core/src/agent/conversation-store.ts +244 -0
  157. package/packages/core/src/agent/curator.ts +158 -0
  158. package/packages/core/src/agent/hooks.ts +166 -0
  159. package/packages/core/src/agent/llm-client.ts +167 -0
  160. package/packages/core/src/agent/llm-providers/anthropic.ts +212 -0
  161. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  162. package/packages/core/src/agent/llm-providers/gemini.ts +215 -0
  163. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  164. package/packages/core/src/agent/llm-providers/interface.ts +195 -0
  165. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  166. package/packages/core/src/agent/llm-providers/local-llama.ts +37 -0
  167. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  168. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  169. package/packages/core/src/agent/llm-providers/ollama.ts +175 -0
  170. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +379 -0
  171. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  172. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  173. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  174. package/packages/core/src/agent/native-tools.ts +31 -0
  175. package/packages/core/src/agent/playbook-selector.ts +147 -0
  176. package/packages/core/src/agent/prompt-builder.ts +169 -0
  177. package/packages/core/src/agent/providers/index.ts +204 -0
  178. package/packages/core/src/agent/providers.ts +1 -0
  179. package/packages/core/src/agent/reflector.ts +200 -0
  180. package/packages/core/src/agent/service.ts +267 -0
  181. package/packages/core/src/agent/skill-selector.ts +479 -0
  182. package/packages/core/src/agent/stuck-loop.ts +133 -0
  183. package/packages/core/src/agent/tool-selector.ts +569 -0
  184. package/packages/core/src/agent/tracer.ts +100 -0
  185. package/packages/core/src/auth/auth.ts +108 -0
  186. package/packages/core/src/auth/index.ts +1 -0
  187. package/packages/core/src/canvas/a2ui-tools.ts +255 -0
  188. package/packages/core/src/canvas/canvas-manager.ts +390 -0
  189. package/packages/core/src/canvas/canvas-tools.ts +448 -0
  190. package/packages/core/src/canvas/emitter.ts +149 -0
  191. package/packages/core/src/canvas/index.ts +3 -0
  192. package/packages/core/src/channels/base.ts +154 -0
  193. package/packages/core/src/channels/discord.ts +273 -0
  194. package/packages/core/src/channels/index.ts +7 -0
  195. package/packages/core/src/channels/manager.ts +450 -0
  196. package/packages/core/src/channels/slack.ts +323 -0
  197. package/packages/core/src/channels/telegram.ts +612 -0
  198. package/packages/core/src/channels/webchat.ts +139 -0
  199. package/packages/core/src/channels/whatsapp.ts +548 -0
  200. package/packages/core/src/config/index.ts +12 -0
  201. package/packages/core/src/config/loader.ts +569 -0
  202. package/packages/core/src/events/agent-bus.ts +460 -0
  203. package/packages/core/src/events/event-bus.ts +169 -0
  204. package/packages/core/src/gateway/channel-notify.ts +64 -0
  205. package/packages/core/src/gateway/helpers/cors.ts +32 -0
  206. package/packages/core/src/gateway/helpers/index.ts +4 -0
  207. package/packages/core/src/gateway/helpers/narration.ts +57 -0
  208. package/packages/core/src/gateway/helpers/path.ts +13 -0
  209. package/packages/core/src/gateway/helpers/redact.ts +61 -0
  210. package/packages/core/src/gateway/index.ts +5 -0
  211. package/packages/core/src/gateway/initializer.ts +363 -0
  212. package/packages/core/src/gateway/lane-queue.ts +169 -0
  213. package/packages/core/src/gateway/llm-local/client.ts +94 -0
  214. package/packages/core/src/gateway/llm-local/detector.ts +321 -0
  215. package/packages/core/src/gateway/llm-local/downloader.ts +216 -0
  216. package/packages/core/src/gateway/llm-local/index.ts +34 -0
  217. package/packages/core/src/gateway/llm-local/manager.ts +186 -0
  218. package/packages/core/src/gateway/llm-local/models.ts +149 -0
  219. package/packages/core/src/gateway/llm-local/server.ts +179 -0
  220. package/packages/core/src/gateway/resolver.ts +108 -0
  221. package/packages/core/src/gateway/router.ts +124 -0
  222. package/packages/core/src/gateway/routes/agents.ts +210 -0
  223. package/packages/core/src/gateway/routes/auth.ts +244 -0
  224. package/packages/core/src/gateway/routes/channels.ts +484 -0
  225. package/packages/core/src/gateway/routes/chat.ts +241 -0
  226. package/packages/core/src/gateway/routes/config.ts +12 -0
  227. package/packages/core/src/gateway/routes/cron-api.ts +544 -0
  228. package/packages/core/src/gateway/routes/ethics.ts +46 -0
  229. package/packages/core/src/gateway/routes/llm-local.ts +271 -0
  230. package/packages/core/src/gateway/routes/mcp.ts +319 -0
  231. package/packages/core/src/gateway/routes/meeting.ts +232 -0
  232. package/packages/core/src/gateway/routes/models.ts +163 -0
  233. package/packages/core/src/gateway/routes/multimodal.ts +93 -0
  234. package/packages/core/src/gateway/routes/providers.ts +220 -0
  235. package/packages/core/src/gateway/routes/setup.ts +441 -0
  236. package/packages/core/src/gateway/routes/skills.ts +115 -0
  237. package/packages/core/src/gateway/routes/system.ts +469 -0
  238. package/packages/core/src/gateway/routes/tasks.ts +44 -0
  239. package/packages/core/src/gateway/routes/tools.ts +59 -0
  240. package/packages/core/src/gateway/routes/tts-local.ts +388 -0
  241. package/packages/core/src/gateway/routes/users.ts +122 -0
  242. package/packages/core/src/gateway/routes/voice.ts +189 -0
  243. package/packages/core/src/gateway/routes/workspace.ts +281 -0
  244. package/packages/core/src/gateway/server.ts +2744 -0
  245. package/packages/core/src/gateway/session.ts +95 -0
  246. package/packages/core/src/gateway/slash-commands.ts +207 -0
  247. package/packages/core/src/gateway/tts/README.md +94 -0
  248. package/packages/core/src/gateway/tts/package.json +25 -0
  249. package/packages/core/src/gateway/tts/src/client.ts +59 -0
  250. package/packages/core/src/gateway/tts/src/detect.ts +42 -0
  251. package/packages/core/src/gateway/tts/src/index.ts +15 -0
  252. package/packages/core/src/gateway/tts/src/install.ts +129 -0
  253. package/packages/core/src/gateway/tts/src/models.ts +50 -0
  254. package/packages/core/src/gateway/tts/src/server.ts +252 -0
  255. package/packages/core/src/gateway/tts/voices/.gitkeep +0 -0
  256. package/packages/core/src/heartbeat/index.ts +157 -0
  257. package/packages/core/src/index.ts +56 -0
  258. package/packages/core/src/mcp/hot-reload.ts +148 -0
  259. package/packages/core/src/mcp/singleton.ts +21 -0
  260. package/packages/core/src/mcp/tool-sync.ts +176 -0
  261. package/packages/core/src/multimodal/index.ts +2 -0
  262. package/packages/core/src/multimodal/types.ts +28 -0
  263. package/packages/core/src/multimodal/vision-service.ts +283 -0
  264. package/packages/core/src/plugins/api.ts +128 -0
  265. package/packages/core/src/plugins/index.ts +2 -0
  266. package/packages/core/src/plugins/loader.ts +365 -0
  267. package/packages/core/src/resilience/circuit-breaker.ts +225 -0
  268. package/packages/core/src/scheduler/CronScheduler.ts +699 -0
  269. package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
  270. package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
  271. package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
  272. package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
  273. package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
  274. package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
  275. package/packages/core/src/scheduler/dag/errors.ts +37 -0
  276. package/packages/core/src/scheduler/dag/index.ts +26 -0
  277. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
  278. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
  279. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
  280. package/packages/core/src/scheduler/index.ts +22 -0
  281. package/packages/core/src/scheduler/integration.ts +237 -0
  282. package/packages/core/src/scheduler/types.ts +164 -0
  283. package/packages/core/src/security/google-chat.ts +269 -0
  284. package/packages/core/src/security/index.ts +192 -0
  285. package/packages/core/src/security/pairing.ts +250 -0
  286. package/packages/core/src/security/rate-limit.ts +270 -0
  287. package/packages/core/src/security/signal.ts +321 -0
  288. package/packages/core/src/state/store.ts +312 -0
  289. package/packages/core/src/storage/crypto.ts +197 -0
  290. package/packages/core/src/storage/migrate.ts +147 -0
  291. package/packages/core/src/storage/onboarding.ts +1506 -0
  292. package/packages/core/src/storage/schema.ts +666 -0
  293. package/packages/core/src/storage/seed.ts +628 -0
  294. package/packages/core/src/storage/sqlite.ts +407 -0
  295. package/packages/core/src/storage/usage.ts +374 -0
  296. package/packages/core/src/tool-runtime/index.ts +502 -0
  297. package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
  298. package/packages/core/src/tools/agents/get-available-models.ts +118 -0
  299. package/packages/core/src/tools/agents/index.ts +610 -0
  300. package/packages/core/src/tools/canvas/index.ts +420 -0
  301. package/packages/core/src/tools/cli/index.ts +142 -0
  302. package/packages/core/src/tools/core/index.ts +478 -0
  303. package/packages/core/src/tools/cron/index.ts +635 -0
  304. package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
  305. package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
  306. package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
  307. package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
  308. package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
  309. package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
  310. package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
  311. package/packages/core/src/tools/filesystem/index.ts +34 -0
  312. package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
  313. package/packages/core/src/tools/index.ts +197 -0
  314. package/packages/core/src/tools/meeting/index.ts +363 -0
  315. package/packages/core/src/tools/office/index.ts +47 -0
  316. package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
  317. package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
  318. package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
  319. package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
  320. package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
  321. package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
  322. package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
  323. package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
  324. package/packages/core/src/tools/types.ts +39 -0
  325. package/packages/core/src/tools/voice/index.ts +104 -0
  326. package/packages/core/src/tools/web/browser-click.ts +78 -0
  327. package/packages/core/src/tools/web/browser-extract.ts +139 -0
  328. package/packages/core/src/tools/web/browser-navigate.ts +106 -0
  329. package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
  330. package/packages/core/src/tools/web/browser-script.ts +88 -0
  331. package/packages/core/src/tools/web/browser-service.ts +554 -0
  332. package/packages/core/src/tools/web/browser-type.ts +101 -0
  333. package/packages/core/src/tools/web/browser-wait.ts +136 -0
  334. package/packages/core/src/tools/web/index.ts +41 -0
  335. package/packages/core/src/tools/web/web-fetch.ts +78 -0
  336. package/packages/core/src/tools/web/web-search.ts +123 -0
  337. package/packages/core/src/utils/benchmark.ts +80 -0
  338. package/packages/core/src/utils/crypto.ts +73 -0
  339. package/packages/core/src/utils/date.ts +42 -0
  340. package/packages/core/src/utils/index.ts +5 -0
  341. package/packages/core/src/utils/logger.ts +389 -0
  342. package/packages/core/src/utils/retry.ts +70 -0
  343. package/packages/core/src/utils/toon.ts +253 -0
  344. package/packages/core/src/voice/index.ts +643 -0
  345. package/packages/mcp/src/config.ts +13 -0
  346. package/packages/mcp/src/index.ts +1 -0
  347. package/packages/mcp/src/logger.ts +47 -0
  348. package/packages/mcp/src/manager.ts +439 -0
  349. package/packages/mcp/src/transports/index.ts +67 -0
  350. package/packages/mcp/src/transports/sse.ts +238 -0
  351. package/packages/mcp/src/transports/websocket.ts +159 -0
  352. package/packages/skills/src/bundled/agents/agent_spawner/SKILL.md +167 -0
  353. package/packages/skills/src/bundled/agents/code_delegator/SKILL.md +156 -0
  354. package/packages/skills/src/bundled/agents/memory_manager/SKILL.md +143 -0
  355. package/packages/skills/src/bundled/agents/research_and_remember/SKILL.md +139 -0
  356. package/packages/skills/src/bundled/agents/task_orchestrator/SKILL.md +198 -0
  357. package/packages/skills/src/bundled/canvas/a2ui_dashboard/SKILL.md +176 -0
  358. package/packages/skills/src/bundled/canvas/a2ui_form/SKILL.md +202 -0
  359. package/packages/skills/src/bundled/canvas/a2ui_interactive/SKILL.md +206 -0
  360. package/packages/skills/src/bundled/canvas/canvas_dashboard/SKILL.md +146 -0
  361. package/packages/skills/src/bundled/canvas/canvas_interact/SKILL.md +148 -0
  362. package/packages/skills/src/bundled/canvas/canvas_report/SKILL.md +146 -0
  363. package/packages/skills/src/bundled/cli/cli_pipeline/SKILL.md +136 -0
  364. package/packages/skills/src/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  365. package/packages/skills/src/bundled/cron_manager/SKILL.md +188 -0
  366. package/packages/skills/src/bundled/cron_reminder/SKILL.md +112 -0
  367. package/packages/skills/src/bundled/filesystem/file_manager/SKILL.md +118 -0
  368. package/packages/skills/src/bundled/filesystem/file_read_and_summarize/SKILL.md +108 -0
  369. package/packages/skills/src/bundled/filesystem/file_writer/SKILL.md +135 -0
  370. package/packages/skills/src/bundled/meeting/meeting_transcription/SKILL.md +213 -0
  371. package/packages/skills/src/bundled/office/office_document_manager/SKILL.md +262 -0
  372. package/packages/skills/src/bundled/search_knowledge/busqueda_fts5/SKILL.md +74 -0
  373. package/packages/skills/src/bundled/voice/voice_assistant/SKILL.md +174 -0
  374. package/packages/skills/src/bundled/voice/voice_input/SKILL.md +146 -0
  375. package/packages/skills/src/bundled/voice/voice_output/SKILL.md +151 -0
  376. package/packages/skills/src/bundled/web/browser_automate/SKILL.md +120 -0
  377. package/packages/skills/src/bundled/web/browser_scrape/SKILL.md +109 -0
  378. package/packages/skills/src/bundled/web/web_monitor/SKILL.md +127 -0
  379. package/packages/skills/src/bundled/web/web_research/SKILL.md +119 -0
  380. package/packages/skills/src/bundled-data.generated.ts +1964 -0
  381. package/packages/skills/src/index.ts +1 -0
  382. package/packages/skills/src/loader.ts +388 -0
  383. package/dist/ui/assets/AgentNewPage-GB-tVN50.js +0 -1
  384. package/dist/ui/assets/BridgePage-DDcDILKu.js +0 -1
  385. package/dist/ui/assets/CanvasPage-oOk2sGOD.js +0 -33
  386. package/dist/ui/assets/DashboardPage-DV_2qWYJ.js +0 -6
  387. package/dist/ui/assets/LogsPage-DayYjh01.js +0 -1
  388. package/dist/ui/assets/MeetingPage-C01uPuqj.js +0 -1
  389. package/dist/ui/assets/ProjectsPage-B8_am_Ib.js +0 -1
  390. package/dist/ui/assets/ProvidersPage-DBzi66e4.js +0 -1
  391. package/dist/ui/assets/SettingsPage-CFA_Tknl.js +0 -9
  392. package/dist/ui/assets/SetupPage-BrUWbhvT.js +0 -1
  393. package/dist/ui/assets/accordion-DdAEfIXR.js +0 -1
  394. package/dist/ui/assets/chevron-down-DIosfU_U.js +0 -1
  395. package/dist/ui/assets/chevron-up-CI-W21Fy.js +0 -1
  396. package/dist/ui/assets/circle-S0-ouLz-.js +0 -1
  397. package/dist/ui/assets/circle-minus-CE0iJrl8.js +0 -1
  398. package/dist/ui/assets/circle-x-jUJ5zZvQ.js +0 -1
  399. package/dist/ui/assets/dropdown-menu-C2CXM1VE.js +0 -1
  400. package/dist/ui/assets/index-BN0875JH.css +0 -2
  401. package/dist/ui/assets/index-CH6sBa3Q.js +0 -116
  402. package/dist/ui/assets/pencil-5VdSj-h5.js +0 -1
  403. package/dist/ui/assets/progress-JN30I5fF.js +0 -1
  404. package/dist/ui/assets/scroll-area-BQQPitM8.js +0 -1
  405. package/dist/ui/assets/search-ChPgnVKj.js +0 -1
  406. package/dist/ui/assets/switch-C7W2-KEx.js +0 -1
  407. package/dist/ui/assets/terminal-C-R5Fckz.js +0 -1
  408. package/dist/ui/assets/useProviders-TBnWn-Hq.js +0 -1
  409. /package/dist/ui/assets/{card-DFKnZ6ky.js → card-CNf6BS2e.js} +0 -0
  410. /package/dist/ui/assets/{circle-alert-KuAm2FWh.js → circle-alert-CyHDwUj8.js} +0 -0
  411. /package/dist/ui/assets/{circle-check-6Ard1-2z.js → circle-check-Bb54Ebmu.js} +0 -0
  412. /package/dist/ui/assets/{cpu-KDy6-FAI.js → cpu-Cdgc_B1K.js} +0 -0
  413. /package/dist/ui/assets/{download-Cjbk4Rek.js → download-C3ifGMjJ.js} +0 -0
  414. /package/dist/ui/assets/{external-link-HtrFM63g.js → external-link-BvxYeTP1.js} +0 -0
  415. /package/dist/ui/assets/{eye-D1dB40_o.js → eye-DqNTU_GD.js} +0 -0
  416. /package/dist/ui/assets/{file-text-CE58EfH0.js → file-text-BT_9S9SM.js} +0 -0
  417. /package/dist/ui/assets/{folder-open-DIPKeiI_.js → folder-open-BhH8y9ac.js} +0 -0
  418. /package/dist/ui/assets/{format-BwdV8bB5.js → format-GVHeOyWI.js} +0 -0
  419. /package/dist/ui/assets/{gateway-url-D5uj6Nxg.js → gateway-url-COCbW0IR.js} +0 -0
  420. /package/dist/ui/assets/{gauge-DmQmJHEg.js → gauge-D_TMa4i9.js} +0 -0
  421. /package/dist/ui/assets/{globe-_hUGxQF4.js → globe-DeCQTCDJ.js} +0 -0
  422. /package/dist/ui/assets/{hexagon-BaNGQlQj.js → hexagon-DsGOUl-H.js} +0 -0
  423. /package/dist/ui/assets/{history-BfZVGlZa.js → history-BSG-Ypqf.js} +0 -0
  424. /package/dist/ui/assets/{info-CBZ5-AlC.js → info-NwLoa2Mj.js} +0 -0
  425. /package/dist/ui/assets/{key-Bv5DdTPh.js → key-3EP0dhkT.js} +0 -0
  426. /package/dist/ui/assets/{loader-circle-C4hhXLgp.js → loader-circle-CZNax6kS.js} +0 -0
  427. /package/dist/ui/assets/{lock-CkZYexqw.js → lock-Ei1_J-Nq.js} +0 -0
  428. /package/dist/ui/assets/{pause-Bpy1_s7y.js → pause-BUqah9Bi.js} +0 -0
  429. /package/dist/ui/assets/{play-Cj4osqJZ.js → play-NcZ4swwL.js} +0 -0
  430. /package/dist/ui/assets/{plus-BQhgZN3A.js → plus-CX1xyhp5.js} +0 -0
  431. /package/dist/ui/assets/{refresh-cw-BfREHVQM.js → refresh-cw-DaYdjQFk.js} +0 -0
  432. /package/dist/ui/assets/{save-FFTD4dMp.js → save-CUdYyHNy.js} +0 -0
  433. /package/dist/ui/assets/{settings-BdHKUL92.js → settings-Ds4SqD8s.js} +0 -0
  434. /package/dist/ui/assets/{sparkles-r4uJbJAl.js → sparkles-yUEb-7oH.js} +0 -0
  435. /package/dist/ui/assets/{square-G7Hyufqm.js → square-BD81nFtN.js} +0 -0
  436. /package/dist/ui/assets/{textarea-5kyuD04X.js → textarea-CXgXWKrT.js} +0 -0
  437. /package/dist/ui/assets/{trash-2-DXVBRWfh.js → trash-2-CNjMkoq6.js} +0 -0
  438. /package/dist/ui/assets/{triangle-alert-Bu5seg9O.js → triangle-alert-C9Y8Ub4X.js} +0 -0
  439. /package/dist/ui/assets/{vendor-router-CCECILJ0.js → vendor-router-C9pIYwbJ.js} +0 -0
  440. /package/dist/ui/assets/{volume-2-s9DuS696.js → volume-2-CeSXNDv4.js} +0 -0
  441. /package/dist/ui/assets/{zap-BPHZzXKV.js → zap-hlXjpSeA.js} +0 -0
@@ -0,0 +1,124 @@
1
+ import type { Config, Binding } from "../config/loader.ts";
2
+
3
+ export interface RoutingContext {
4
+ channel: string;
5
+ accountId?: string;
6
+ peerKind?: "direct" | "group";
7
+ peerId?: string;
8
+ guildId?: string;
9
+ teamId?: string;
10
+ roles?: string[];
11
+ }
12
+
13
+ export function matchBinding(binding: Binding, ctx: RoutingContext): number {
14
+ const match = binding.match;
15
+ let score = 0;
16
+
17
+ if (match.peer?.id && match.peer?.kind) {
18
+ if (ctx.peerId === match.peer.id && ctx.peerKind === match.peer.kind) {
19
+ score += 1000;
20
+ } else {
21
+ return 0;
22
+ }
23
+ } else if (match.peer?.id) {
24
+ if (ctx.peerId === match.peer.id) {
25
+ score += 900;
26
+ } else {
27
+ return 0;
28
+ }
29
+ } else if (match.peer?.kind) {
30
+ if (ctx.peerKind === match.peer.kind) {
31
+ score += 50;
32
+ } else {
33
+ return 0;
34
+ }
35
+ }
36
+
37
+ if (match.guildId && match.roles && match.roles.length > 0) {
38
+ if (ctx.guildId === match.guildId && ctx.roles?.some((r) => match.roles?.includes(r))) {
39
+ score += 800;
40
+ } else {
41
+ return 0;
42
+ }
43
+ } else if (match.guildId) {
44
+ if (ctx.guildId === match.guildId) {
45
+ score += 200;
46
+ } else {
47
+ return 0;
48
+ }
49
+ }
50
+
51
+ if (match.teamId) {
52
+ if (ctx.teamId === match.teamId) {
53
+ score += 300;
54
+ } else {
55
+ return 0;
56
+ }
57
+ }
58
+
59
+ if (match.accountId) {
60
+ if (ctx.accountId === match.accountId) {
61
+ score += 400;
62
+ } else {
63
+ return 0;
64
+ }
65
+ }
66
+
67
+ if (match.channel) {
68
+ if (ctx.channel === match.channel) {
69
+ score += 100;
70
+ } else {
71
+ return 0;
72
+ }
73
+ }
74
+
75
+ return score || 1;
76
+ }
77
+
78
+ export function resolveAgent(
79
+ config: Config,
80
+ ctx: RoutingContext
81
+ ): string {
82
+ const bindings = config.bindings ?? [];
83
+
84
+ if (bindings.length === 0) {
85
+ return config.agent?.defaultAgentId ?? "main";
86
+ }
87
+
88
+ let bestMatch: { agentId: string; score: number } | null = null;
89
+
90
+ for (const binding of bindings) {
91
+ const score = matchBinding(binding, ctx);
92
+ if (score > 0 && (!bestMatch || score > bestMatch.score)) {
93
+ bestMatch = { agentId: binding.agentId, score };
94
+ }
95
+ }
96
+
97
+ if (bestMatch) {
98
+ return bestMatch.agentId;
99
+ }
100
+
101
+ return config.agent?.defaultAgentId ?? "main";
102
+ }
103
+
104
+ export class Router {
105
+ constructor(private config: Config) {}
106
+
107
+ route(ctx: RoutingContext): string {
108
+ return resolveAgent(this.config, ctx);
109
+ }
110
+
111
+ getAgentWorkspace(agentId: string): string {
112
+ const agents = this.config.agents?.list ?? [];
113
+ const agent = agents.find((a) => a.id === agentId);
114
+
115
+ if (agent?.workspace) {
116
+ return agent.workspace.replace(/^~/, process.env.HOME ?? "");
117
+ }
118
+
119
+ const baseDir = this.config.agent?.baseDir?.replace(/^~/, process.env.HOME ?? "")
120
+ ?? `${process.env.HOME}/.hive/agents`;
121
+
122
+ return `${baseDir}/${agentId}/workspace`;
123
+ }
124
+ }
@@ -0,0 +1,210 @@
1
+ import { getDb } from "../../storage/sqlite"
2
+ import { emitCanvas } from "../../canvas/emitter"
3
+ import { storeAgentHeaders, deleteAgentSecrets } from "../../storage/crypto"
4
+
5
+ export async function handleGetAgents(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
6
+ const url = new URL(req.url)
7
+ const typeFilter = url.searchParams.get("type")
8
+
9
+ let whereClause = ""
10
+ if (typeFilter) {
11
+ whereClause = "WHERE a.status = ?"
12
+ }
13
+
14
+ const rows = getDb().query(`
15
+ SELECT a.*, u.notes as user_preferences,
16
+ CASE WHEN a.headers_encrypted IS NOT NULL THEN 1 ELSE 0 END as has_headers
17
+ FROM agents a
18
+ LEFT JOIN users u ON a.user_id = u.id
19
+ ${whereClause}
20
+ ORDER BY a.created_at DESC
21
+ `).all(...(typeFilter ? [typeFilter] : [])) as Record<string, unknown>[]
22
+
23
+ const agents = rows.map(row => ({
24
+ // Basic fields
25
+ id: row.id,
26
+ userId: row.user_id,
27
+ name: row.name,
28
+ description: row.description,
29
+ systemPrompt: row.system_prompt,
30
+ tone: row.tone,
31
+
32
+ // Role & status
33
+ role: row.role as 'coordinator' | 'worker',
34
+ status: row.status,
35
+ enabled: Boolean(row.enabled),
36
+
37
+ // Provider & model
38
+ providerId: row.provider_id,
39
+ modelId: row.model_id,
40
+
41
+ // Tools & skills
42
+ toolsJson: row.tools_json,
43
+ skillsJson: row.skills_json,
44
+
45
+ // Hierarchy
46
+ parentId: row.parent_id,
47
+ maxIterations: row.max_iterations,
48
+
49
+ // Workspace
50
+ workspace: row.workspace,
51
+
52
+ // Headers (encrypted)
53
+ hasHeaders: row.has_headers === 1,
54
+
55
+ // Timestamps
56
+ createdAt: new Date((row.created_at as number) * 1000).toISOString(),
57
+ updatedAt: new Date((row.updated_at as number) * 1000).toISOString(),
58
+
59
+ // Virtual fields (not from DB)
60
+ taskCount: 0,
61
+ successRate: 100,
62
+ }))
63
+
64
+ return addCorsHeaders(Response.json({ agents }), req)
65
+ }
66
+
67
+ export async function handleCreateAgent(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
68
+ const body = await req.json().catch(() => ({}))
69
+ let agentId: string
70
+
71
+ if (body.id) {
72
+ agentId = body.id
73
+ getDb().query(`
74
+ INSERT INTO agents(id, name, description, provider_id, model_id, tone, enabled, workspace)
75
+ VALUES(?, ?, ?, ?, ?, ?, 1, ?)
76
+ `).run(
77
+ agentId,
78
+ body.name,
79
+ body.description || "",
80
+ body.providerId || "openai",
81
+ body.modelId || "gpt-4o",
82
+ body.tone || "friendly",
83
+ body.workspace || null
84
+ )
85
+ } else {
86
+ const result = getDb().query(`
87
+ INSERT INTO agents(name, description, provider_id, model_id, tone, enabled, workspace)
88
+ VALUES(?, ?, ?, ?, ?, 1, ?)
89
+ RETURNING id
90
+ `).get(
91
+ body.name,
92
+ body.description || "",
93
+ body.providerId || "openai",
94
+ body.modelId || "gpt-4o",
95
+ body.tone || "friendly",
96
+ body.workspace || null
97
+ ) as { id: string } | undefined
98
+ agentId = result?.id || ""
99
+ }
100
+
101
+ if (body.headers && agentId) {
102
+ await storeAgentHeaders(agentId, body.headers)
103
+ }
104
+
105
+ emitCanvas("canvas:node_add", {
106
+ node: { id: agentId, name: body.name, status: "idle", type: "agent" }
107
+ })
108
+
109
+ const agent = getDb().query(`
110
+ SELECT id, name, description, provider_id, model_id, tone, status, enabled, active, created_at, workspace
111
+ FROM agents WHERE id = ?
112
+ `).get(agentId) as Record<string, unknown> | undefined
113
+
114
+ if (!agent) {
115
+ return addCorsHeaders(Response.json({ ok: false, error: "Agent not found" }), req)
116
+ }
117
+
118
+ return addCorsHeaders(Response.json({
119
+ ok: true,
120
+ agent: {
121
+ id: agent.id,
122
+ name: agent.name,
123
+ description: agent.description,
124
+ providerId: agent.provider_id,
125
+ modelId: agent.model_id,
126
+ tone: agent.tone,
127
+ status: agent.status,
128
+ enabled: agent.enabled === 1,
129
+ active: agent.active === 1,
130
+ createdAt: new Date((agent.created_at as number) * 1000).toISOString(),
131
+ workspace: agent.workspace,
132
+ }
133
+ }), req)
134
+ }
135
+
136
+ export async function handleUpdateAgent(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
137
+ const url = new URL(req.url)
138
+ const agentId = url.pathname.split("/").pop()
139
+
140
+ if (!agentId) {
141
+ return addCorsHeaders(new Response("Missing ID", { status: 400 }), req)
142
+ }
143
+
144
+ const body = await req.json().catch(() => ({}))
145
+
146
+ const updates: string[] = []
147
+ const params: unknown[] = []
148
+
149
+ // Map: snake_case DB field → camelCase body key
150
+ const fieldMap: Record<string, string> = {
151
+ name: "name",
152
+ description: "description",
153
+ provider_id: "providerId",
154
+ model_id: "modelId",
155
+ system_prompt: "systemPrompt",
156
+ status: "status",
157
+ enabled: "enabled",
158
+ tone: "tone",
159
+ workspace: "workspace",
160
+ role: "role",
161
+ max_iterations: "maxIterations",
162
+ }
163
+
164
+ for (const [dbField, camelKey] of Object.entries(fieldMap)) {
165
+ const val = body[dbField] !== undefined ? body[dbField] : body[camelKey]
166
+ if (val !== undefined) {
167
+ updates.push(`${dbField} = ?`)
168
+ params.push(typeof val === 'object' ? JSON.stringify(val) : val)
169
+ }
170
+ }
171
+
172
+ const agentHeaders = body.headers !== undefined ? body.headers : body.config?.headers
173
+ if (agentHeaders !== undefined) {
174
+ await storeAgentHeaders(agentId, agentHeaders)
175
+ }
176
+
177
+ const userPreferences = body.userPreferences !== undefined ? body.userPreferences : body.user_preferences
178
+ if (userPreferences !== undefined) {
179
+ const agentRow = getDb().query("SELECT user_id FROM agents WHERE id = ?").get(agentId) as { user_id: string } | undefined
180
+ if (agentRow?.user_id) {
181
+ getDb().query(`UPDATE users SET notes = ? WHERE id = ?`).run(userPreferences, agentRow.user_id)
182
+ }
183
+ }
184
+
185
+ if (updates.length > 0) {
186
+ updates.push("updated_at = unixepoch()")
187
+ params.push(agentId)
188
+ getDb().query(`UPDATE agents SET ${updates.join(", ")} WHERE id = ?`).run(...params as any[])
189
+
190
+ emitCanvas("canvas:node_update", { id: agentId, updates: body })
191
+ }
192
+
193
+ return addCorsHeaders(Response.json({ ok: true }), req)
194
+ }
195
+
196
+ export async function handleDeleteAgent(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
197
+ const url = new URL(req.url)
198
+ const agentId = url.pathname.split("/").pop()
199
+
200
+ if (!agentId) {
201
+ return addCorsHeaders(new Response("Missing ID", { status: 400 }), req)
202
+ }
203
+
204
+ getDb().query(`DELETE FROM agents WHERE id = ?`).run(agentId)
205
+ await deleteAgentSecrets(agentId)
206
+
207
+ emitCanvas("canvas:node_remove", { id: agentId })
208
+
209
+ return addCorsHeaders(Response.json({ ok: true }), req)
210
+ }
@@ -0,0 +1,244 @@
1
+ import { getDb } from "../../storage/sqlite";
2
+ import { readFileSync } from "node:fs";
3
+ import { getHiveDir } from "../../config/loader";
4
+ import * as path from "node:path";
5
+ import jwt from "jsonwebtoken";
6
+
7
+ type CorsHelper = (res: Response, req: Request) => Response;
8
+
9
+ interface AuthTokens {
10
+ accessToken: string;
11
+ refreshToken: string;
12
+ expiresIn: number;
13
+ tokenType: 'Bearer';
14
+ }
15
+
16
+ const JWT_SECRET = process.env.HIVE_JWT_SECRET || process.env.HIVE_AUTH_TOKEN || "hive-default-jwt-secret-change-in-production";
17
+ const ACCESS_TOKEN_EXPIRY = "15m";
18
+ const REFRESH_TOKEN_EXPIRY = "7d";
19
+ const ACCESS_TOKEN_EXPIRY_SECONDS = 15 * 60;
20
+
21
+ function hashToken(token: string): string {
22
+ return Bun.hash(token + JWT_SECRET).toString(16);
23
+ }
24
+
25
+ export async function generateTokens(userId: string): Promise<AuthTokens> {
26
+ const accessToken = jwt.sign({ userId, type: "access" }, JWT_SECRET, { expiresIn: ACCESS_TOKEN_EXPIRY });
27
+ const refreshToken = jwt.sign({ userId, type: "refresh", jti: crypto.randomUUID() }, JWT_SECRET, { expiresIn: REFRESH_TOKEN_EXPIRY });
28
+
29
+ const expiresAt = Math.floor(Date.now() / 1000) + (7 * 24 * 60 * 60);
30
+ const tokenHash = hashToken(refreshToken);
31
+
32
+ getDb().query(
33
+ `INSERT INTO refresh_tokens (user_id, token_hash, expires_at) VALUES (?, ?, ?)`
34
+ ).run(userId, tokenHash, expiresAt);
35
+
36
+ return {
37
+ accessToken,
38
+ refreshToken,
39
+ expiresIn: ACCESS_TOKEN_EXPIRY_SECONDS,
40
+ tokenType: "Bearer"
41
+ };
42
+ }
43
+
44
+ export async function refreshAccessToken(refreshToken: string): Promise<AuthTokens | null> {
45
+ try {
46
+ const decoded = jwt.verify(refreshToken, JWT_SECRET) as { userId: string; type: string; jti: string };
47
+ if (decoded.type !== "refresh") return null;
48
+
49
+ const tokenHash = hashToken(refreshToken);
50
+ const stored = getDb().query(
51
+ `SELECT user_id FROM refresh_tokens WHERE token_hash = ? AND revoked = 0 AND expires_at > ?`
52
+ ).get(tokenHash, Math.floor(Date.now() / 1000)) as { user_id: string } | undefined;
53
+
54
+ if (!stored) return null;
55
+
56
+ getDb().query(`DELETE FROM refresh_tokens WHERE token_hash = ?`).run(tokenHash);
57
+
58
+ return generateTokens(stored.user_id);
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ export async function validateAccessToken(token: string): Promise<{ userId: string } | null> {
65
+ try {
66
+ const decoded = jwt.verify(token, JWT_SECRET) as { userId: string; type: string };
67
+ if (decoded.type !== "access") return null;
68
+ return { userId: decoded.userId };
69
+ } catch {
70
+ return null;
71
+ }
72
+ }
73
+
74
+ function getAuthTokenFromFile(): string {
75
+ // The auth token lives in ~/.hive/.auth_token — same value as HIVE_AUTH_TOKEN env var
76
+ try {
77
+ return readFileSync(path.join(getHiveDir(), ".auth_token"), "utf-8").trim();
78
+ } catch {
79
+ return process.env.HIVE_AUTH_TOKEN ?? "";
80
+ }
81
+ }
82
+
83
+ /** GET /api/auth/status — public
84
+ * Returns whether this instance has email+password credentials configured.
85
+ * The UI uses this to decide whether to show the login page or allow direct access.
86
+ */
87
+ export async function handleAuthStatus(
88
+ req: Request,
89
+ cors: CorsHelper
90
+ ): Promise<Response> {
91
+ const user = getDb().query(
92
+ `SELECT email, password_hash FROM users LIMIT 1`
93
+ ).get() as { email: string | null; password_hash: string | null } | null;
94
+
95
+ const hasCredentials = !!(user?.email && user?.password_hash);
96
+ return cors(Response.json({ hasCredentials, email: user?.email ?? null }), req);
97
+ }
98
+
99
+ /** GET /api/auth/recovery-key — requires auth
100
+ * Returns the recovery key (HIVE_AUTH_TOKEN) so the UI can display it.
101
+ */
102
+ export async function handleRecoveryKey(
103
+ req: Request,
104
+ cors: CorsHelper
105
+ ): Promise<Response> {
106
+ const recoveryKey = getAuthTokenFromFile();
107
+ return cors(Response.json({ recoveryKey }), req);
108
+ }
109
+
110
+ /** POST /api/auth/login — public
111
+ * body: { email, password }
112
+ * Returns: { authToken } on success, 401 on failure.
113
+ */
114
+ export async function handleLogin(
115
+ req: Request,
116
+ cors: CorsHelper
117
+ ): Promise<Response> {
118
+ const body = await req.json().catch(() => ({})) as { email?: string; password?: string };
119
+
120
+ if (!body.email || !body.password) {
121
+ return cors(Response.json({ error: "Email y contraseña requeridos" }, { status: 400 }), req);
122
+ }
123
+
124
+ const user = getDb().query(
125
+ `SELECT password_hash FROM users WHERE email = ? LIMIT 1`
126
+ ).get(body.email.toLowerCase().trim()) as { password_hash: string | null } | null;
127
+
128
+ if (!user?.password_hash) {
129
+ return cors(Response.json({ error: "Credenciales inválidas" }, { status: 401 }), req);
130
+ }
131
+
132
+ const valid = await Bun.password.verify(body.password, user.password_hash);
133
+ if (!valid) {
134
+ return cors(Response.json({ error: "Credenciales inválidas" }, { status: 401 }), req);
135
+ }
136
+
137
+ const authToken = process.env.HIVE_AUTH_TOKEN ?? getAuthTokenFromFile();
138
+ return cors(Response.json({ authToken }), req);
139
+ }
140
+
141
+ /** POST /api/auth/setup-credentials — requires existing auth token
142
+ * Sets email + password for the first time (or updates them).
143
+ * body: { email, password }
144
+ */
145
+ export async function handleSetupCredentials(
146
+ req: Request,
147
+ cors: CorsHelper
148
+ ): Promise<Response> {
149
+ const body = await req.json().catch(() => ({})) as { email?: string; password?: string };
150
+
151
+ if (!body.email || !body.password) {
152
+ return cors(Response.json({ error: "Email y contraseña requeridos" }, { status: 400 }), req);
153
+ }
154
+
155
+ if (body.password.length < 8) {
156
+ return cors(Response.json({ error: "La contraseña debe tener al menos 8 caracteres" }, { status: 400 }), req);
157
+ }
158
+
159
+ const passwordHash = await Bun.password.hash(body.password, { algorithm: "bcrypt", cost: 10 });
160
+ const email = body.email.toLowerCase().trim();
161
+
162
+ getDb().query(
163
+ `UPDATE users SET email = ?, password_hash = ?`
164
+ ).run(email, passwordHash);
165
+
166
+ return cors(Response.json({ success: true }), req);
167
+ }
168
+
169
+ /** POST /api/auth/change-password — requires existing auth token
170
+ * body: { currentPassword, newPassword }
171
+ */
172
+ export async function handleChangePassword(
173
+ req: Request,
174
+ cors: CorsHelper
175
+ ): Promise<Response> {
176
+ const body = await req.json().catch(() => ({})) as { currentPassword?: string; newPassword?: string };
177
+
178
+ if (!body.currentPassword || !body.newPassword) {
179
+ return cors(Response.json({ error: "Campos requeridos" }, { status: 400 }), req);
180
+ }
181
+
182
+ if (body.newPassword.length < 8) {
183
+ return cors(Response.json({ error: "La contraseña debe tener al menos 8 caracteres" }, { status: 400 }), req);
184
+ }
185
+
186
+ const user = getDb().query(
187
+ `SELECT password_hash FROM users LIMIT 1`
188
+ ).get() as { password_hash: string | null } | null;
189
+
190
+ if (!user?.password_hash) {
191
+ return cors(Response.json({ error: "No hay contraseña configurada" }, { status: 400 }), req);
192
+ }
193
+
194
+ const valid = await Bun.password.verify(body.currentPassword, user.password_hash);
195
+ if (!valid) {
196
+ return cors(Response.json({ error: "Contraseña actual incorrecta" }, { status: 401 }), req);
197
+ }
198
+
199
+ const newHash = await Bun.password.hash(body.newPassword, { algorithm: "bcrypt", cost: 10 });
200
+ getDb().query(`UPDATE users SET password_hash = ?`).run(newHash);
201
+
202
+ return cors(Response.json({ success: true }), req);
203
+ }
204
+
205
+ /** POST /api/auth/recover — public
206
+ * Resets password using the recovery key (= HIVE_AUTH_TOKEN from ~/.hive/.auth_token).
207
+ * body: { recoveryKey, newPassword }
208
+ */
209
+ export async function handleRecover(
210
+ req: Request,
211
+ cors: CorsHelper
212
+ ): Promise<Response> {
213
+ const body = await req.json().catch(() => ({})) as { recoveryKey?: string; newPassword?: string };
214
+
215
+ if (!body.recoveryKey || !body.newPassword) {
216
+ return cors(Response.json({ error: "Recovery key y nueva contraseña requeridos" }, { status: 400 }), req);
217
+ }
218
+
219
+ if (body.newPassword.length < 8) {
220
+ return cors(Response.json({ error: "La contraseña debe tener al menos 8 caracteres" }, { status: 400 }), req);
221
+ }
222
+
223
+ const storedToken = getAuthTokenFromFile();
224
+ if (!storedToken || body.recoveryKey.trim() !== storedToken) {
225
+ return cors(Response.json({ error: "Recovery key inválido" }, { status: 401 }), req);
226
+ }
227
+
228
+ const newHash = await Bun.password.hash(body.newPassword, { algorithm: "bcrypt", cost: 10 });
229
+ getDb().query(`UPDATE users SET password_hash = ?`).run(newHash);
230
+
231
+ const authToken = process.env.HIVE_AUTH_TOKEN ?? storedToken;
232
+ return cors(Response.json({ success: true, authToken }), req);
233
+ }
234
+
235
+ /** POST /api/auth/disable — requires existing auth token
236
+ * Removes email + password (disables login protection).
237
+ */
238
+ export async function handleDisableAuth(
239
+ req: Request,
240
+ cors: CorsHelper
241
+ ): Promise<Response> {
242
+ getDb().query(`UPDATE users SET email = NULL, password_hash = NULL`).run();
243
+ return cors(Response.json({ success: true }), req);
244
+ }