@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,139 @@
1
+ import type { ServerWebSocket } from "bun";
2
+ import { BaseChannel, type ChannelConfig, type IncomingMessage, type OutboundMessage } from "./base.ts";
3
+ import { logger } from "../utils/logger.ts";
4
+ import { resolveUserId } from "../storage/onboarding";
5
+
6
+ export interface WebChatConfig extends ChannelConfig {
7
+ accountId?: string;
8
+ // WebChat doesn't need extra config, it's served from the gateway
9
+ }
10
+
11
+ interface WebSocketData {
12
+ sessionId: string;
13
+ peerId: string;
14
+ authenticatedAt: number;
15
+ }
16
+
17
+ export class WebChatChannel extends BaseChannel {
18
+ name = "webchat";
19
+ accountId: string;
20
+ config: WebChatConfig;
21
+
22
+ private connections: Map<string, ServerWebSocket<WebSocketData>> = new Map();
23
+ private log = logger.child("webchat");
24
+
25
+ constructor(config: WebChatConfig) {
26
+ super();
27
+ this.config = config;
28
+ // Resolve accountId from database (single user) or use fallback
29
+ this.accountId = config.accountId || resolveUserId({}) || "webchat";
30
+ }
31
+
32
+ async start(): Promise<void> {
33
+ this.running = true;
34
+ this.log.info("WebChat channel ready");
35
+ }
36
+
37
+ async stop(): Promise<void> {
38
+ this.connections.clear();
39
+ this.running = false;
40
+ this.log.info("WebChat channel stopped");
41
+ }
42
+
43
+ registerConnection(ws: ServerWebSocket<WebSocketData>): void {
44
+ const data = ws.data as WebSocketData;
45
+ this.connections.set(data.sessionId, ws);
46
+ this.log.debug(`WebChat connection registered: ${data.sessionId}`);
47
+ }
48
+
49
+ unregisterConnection(sessionId: string): void {
50
+ this.connections.delete(sessionId);
51
+ this.log.debug(`WebChat connection unregistered: ${sessionId}`);
52
+ }
53
+
54
+ /** Returns the first active WebChat session ID, or undefined if no one is connected */
55
+ getAnyActiveSession(): string | undefined {
56
+ return this.connections.keys().next().value;
57
+ }
58
+
59
+ hasSession(sessionId: string): boolean {
60
+ return this.connections.has(sessionId);
61
+ }
62
+
63
+ async startTyping(sessionId: string): Promise<void> {
64
+ const ws = this.connections.get(sessionId);
65
+ if (!ws) return;
66
+
67
+ try {
68
+ ws.send(JSON.stringify({ type: "typing", isTyping: true }));
69
+ } catch {
70
+ // Connection closed
71
+ }
72
+ }
73
+
74
+ async stopTyping(sessionId: string): Promise<void> {
75
+ const ws = this.connections.get(sessionId);
76
+ if (!ws) return;
77
+
78
+ try {
79
+ ws.send(JSON.stringify({ type: "typing", isTyping: false }));
80
+ } catch {
81
+ // Connection closed
82
+ }
83
+ }
84
+
85
+ async send(sessionId: string, message: OutboundMessage): Promise<void> {
86
+ const ws = this.connections.get(sessionId);
87
+
88
+ if (!ws) {
89
+ this.log.warn(`No WebChat connection for session: ${sessionId}`);
90
+ return;
91
+ }
92
+
93
+ try {
94
+ ws.send(JSON.stringify(message));
95
+ } catch (error) {
96
+ this.log.error(`Failed to send WebChat message: ${(error as Error).message}`);
97
+ }
98
+ }
99
+
100
+ async sendAudio(sessionId: string, audio: Buffer, mimeType: string): Promise<void> {
101
+ const ws = this.connections.get(sessionId);
102
+
103
+ if (!ws) {
104
+ this.log.warn(`No WebChat connection for session: ${sessionId}`);
105
+ return;
106
+ }
107
+
108
+ try {
109
+ const base64Audio = audio.toString("base64");
110
+ ws.send(JSON.stringify({
111
+ type: "audio",
112
+ sessionId,
113
+ audio: base64Audio,
114
+ mimeType,
115
+ }));
116
+ } catch (error) {
117
+ this.log.error(`Failed to send WebChat audio: ${(error as Error).message}`);
118
+ }
119
+ }
120
+
121
+ createIncomingMessage(
122
+ sessionId: string,
123
+ content: string,
124
+ peerId: string
125
+ ): IncomingMessage {
126
+ return {
127
+ sessionId,
128
+ channel: "webchat",
129
+ accountId: this.accountId,
130
+ peerId,
131
+ peerKind: "direct",
132
+ content,
133
+ };
134
+ }
135
+ }
136
+
137
+ export function createWebChatChannel(config: WebChatConfig): WebChatChannel {
138
+ return new WebChatChannel(config);
139
+ }
@@ -0,0 +1,548 @@
1
+ import makeWASocket, {
2
+ DisconnectReason,
3
+ useMultiFileAuthState,
4
+ fetchLatestBaileysVersion,
5
+ downloadMediaMessage,
6
+ type WASocket,
7
+ type ConnectionState,
8
+ type WAMessage,
9
+ } from "@whiskeysockets/baileys";
10
+ import type { ChannelConfig, IncomingMessage, OutboundMessage } from "./base.ts";
11
+ import { BaseChannel } from "./base.ts";
12
+ import { existsSync, mkdirSync, rmSync } from "node:fs";
13
+ import * as path from "node:path";
14
+ import { logger } from "../utils/logger.ts";
15
+ import { getDb } from "../storage/sqlite.ts";
16
+ // @ts-ignore — no type definitions for qrcode-terminal
17
+ import qrcodeTerminal from "qrcode-terminal";
18
+
19
+ // Baileys uses the `ws` npm package which triggers "[bun] Warning: ws.WebSocket 'upgrade'
20
+ // event is not implemented in bun" etc. Bun writes these directly to stderr from native
21
+ // code, bypassing process.emitWarning. Patch process.stderr.write to filter them out.
22
+ const _origStderrWrite = process.stderr.write.bind(process.stderr);
23
+ (process.stderr as any).write = function (chunk: string | Buffer, ...args: unknown[]) {
24
+ const str = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString() : "";
25
+ if (str.includes("[bun] Warning:") && str.includes("not implemented in bun")) return true;
26
+ return _origStderrWrite(chunk, ...(args as any[]));
27
+ };
28
+
29
+ export interface WhatsAppConfig extends ChannelConfig {
30
+ accountId: string;
31
+ agentId: string;
32
+ acceptGroups?: boolean;
33
+ selfMessagesOnly?: boolean;
34
+ reconnectMaxAttempts?: number;
35
+ reconnectBaseDelayMs?: number;
36
+ }
37
+
38
+ export interface WhatsAppConnectionState {
39
+ status: "connecting" | "connected" | "disconnected" | "qr" | "error";
40
+ qrCode?: string;
41
+ lastConnected?: Date;
42
+ reconnectAttempts: number;
43
+ error?: string;
44
+ phoneNumber?: string;
45
+ waVersion?: string;
46
+ }
47
+
48
+ export class WhatsAppChannel extends BaseChannel {
49
+ name = "whatsapp";
50
+ accountId: string;
51
+ config: WhatsAppConfig;
52
+
53
+ private socket: WASocket | null = null;
54
+ private connectionState: WhatsAppConnectionState = {
55
+ status: "disconnected",
56
+ reconnectAttempts: 0,
57
+ };
58
+ private authPath: string;
59
+ private reconnectTimeout: Timer | null = null;
60
+ private log: ReturnType<typeof logger.child>;
61
+ private jidCache: Map<string, string> = new Map();
62
+
63
+ constructor(config: WhatsAppConfig) {
64
+ super();
65
+ this.config = config;
66
+ this.accountId = config.accountId;
67
+ this.authPath = this.getAuthPath(config.agentId, config.accountId);
68
+ this.log = logger.child("whatsapp");
69
+ }
70
+
71
+ private getAuthPath(agentId: string, accountId: string): string {
72
+ const baseDir = process.env.HOME ?? "";
73
+ const authDir = path.join(baseDir, ".hive", "agents", agentId, "whatsapp", accountId);
74
+
75
+ if (!existsSync(authDir)) {
76
+ mkdirSync(authDir, { recursive: true });
77
+ }
78
+
79
+ return authDir;
80
+ }
81
+
82
+ async start(): Promise<void> {
83
+ this.running = true;
84
+ await this.connect();
85
+ }
86
+
87
+ async stop(): Promise<void> {
88
+ this.running = false;
89
+
90
+ if (this.reconnectTimeout) {
91
+ clearTimeout(this.reconnectTimeout);
92
+ this.reconnectTimeout = null;
93
+ }
94
+
95
+ if (this.socket) {
96
+ try {
97
+ await this.socket.end(undefined);
98
+ } catch {
99
+ // Ignore close errors
100
+ }
101
+ this.socket = null;
102
+ }
103
+
104
+ this.connectionState.status = "disconnected";
105
+ this.log.info("WhatsApp channel stopped");
106
+ }
107
+
108
+ private async connect(): Promise<void> {
109
+ if (!this.running) return;
110
+
111
+ this.connectionState.status = "connecting";
112
+ this.log.info("Connecting to WhatsApp...");
113
+
114
+ try {
115
+ const { state, saveCreds } = await useMultiFileAuthState(this.authPath);
116
+ const { version } = await fetchLatestBaileysVersion();
117
+ this.connectionState.waVersion = version.join(".");
118
+ this.log.info(`Using WhatsApp Web v${version.join(".")}`);
119
+
120
+ this.socket = makeWASocket({
121
+ version,
122
+ auth: state,
123
+ printQRInTerminal: false,
124
+ syncFullHistory: false,
125
+ getMessage: async () => ({ conversation: "" }),
126
+ });
127
+
128
+ this.socket.ev.on("connection.update", async (update) => {
129
+ await this.handleConnectionUpdate(update, saveCreds);
130
+ });
131
+
132
+ this.socket.ev.on("messages.upsert", async (update) => {
133
+ await this.handleMessages(update);
134
+ });
135
+
136
+ this.socket.ev.on("creds.update", saveCreds);
137
+
138
+ // Baileys v7: handle LID ↔ phone-number mapping updates
139
+ this.socket.ev.on("lid-mapping.update" as any, () => {
140
+ // LID mappings are persisted automatically via useMultiFileAuthState
141
+ });
142
+
143
+ } catch (error) {
144
+ this.connectionState.status = "error";
145
+ this.connectionState.error = (error as Error).message;
146
+ this.log.error(`WhatsApp connection error: ${(error as Error).message}`);
147
+ this.scheduleReconnect();
148
+ }
149
+ }
150
+
151
+ private async handleConnectionUpdate(
152
+ update: Partial<ConnectionState>,
153
+ saveCreds: () => Promise<void>
154
+ ): Promise<void> {
155
+ const { connection, lastDisconnect, qr } = update;
156
+
157
+ if (qr) {
158
+ this.connectionState.status = "qr";
159
+ this.connectionState.qrCode = qr;
160
+ this.printQR(qr);
161
+ this.log.info("Scan the QR code above with WhatsApp");
162
+ }
163
+
164
+ if (connection === "close") {
165
+ const statusCode = (lastDisconnect?.error as { output?: { statusCode: number } })?.output?.statusCode;
166
+ const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
167
+
168
+ this.connectionState.status = "disconnected";
169
+ this.log.warn(`WhatsApp disconnected: ${statusCode}`);
170
+
171
+ try {
172
+ getDb().query(`UPDATE channels SET status = ? WHERE id = ?`)
173
+ .run(shouldReconnect ? "connecting" : "disconnected", this.accountId);
174
+ } catch { /* ignore DB errors */ }
175
+
176
+ const needsSessionClear =
177
+ statusCode === DisconnectReason.loggedOut ||
178
+ statusCode === DisconnectReason.badSession;
179
+ // NOTE: 515 (restartRequired) is sent by WhatsApp AFTER a successful pairing
180
+ // to signal Baileys to reconnect with the new credentials — do NOT clear session.
181
+
182
+ if (needsSessionClear) {
183
+ this.log.info("Clearing WhatsApp session files for fresh QR scan.");
184
+ rmSync(this.authPath, { recursive: true, force: true });
185
+ mkdirSync(this.authPath, { recursive: true });
186
+ }
187
+
188
+ if (shouldReconnect && this.running) {
189
+ this.scheduleReconnect();
190
+ }
191
+ }
192
+
193
+ if (connection === "open") {
194
+ this.connectionState.status = "connected";
195
+ this.connectionState.lastConnected = new Date();
196
+ this.connectionState.reconnectAttempts = 0;
197
+ this.connectionState.qrCode = undefined;
198
+ void saveCreds();
199
+ this.log.info("WhatsApp connected successfully");
200
+
201
+ // Extract phone number from socket user ID
202
+ const rawUserId = this.socket?.user?.id ?? "";
203
+ if (rawUserId) {
204
+ const phoneNumber = rawUserId.split(":")[0]?.replace("@s.whatsapp.net", "") ?? "";
205
+ this.connectionState.phoneNumber = phoneNumber;
206
+ this.log.info(`Linked phone: ${phoneNumber}`);
207
+ }
208
+
209
+ try {
210
+ getDb().query(`UPDATE channels SET status = 'connected', last_active = ? WHERE id = ?`)
211
+ .run(Date.now(), this.accountId);
212
+ } catch { /* ignore DB errors */ }
213
+ }
214
+ }
215
+
216
+ hasCredentials(): boolean {
217
+ const credsFile = path.join(this.authPath, "creds.json");
218
+ return existsSync(credsFile);
219
+ }
220
+
221
+ getConnectionState(): WhatsAppConnectionState {
222
+ return { ...this.connectionState };
223
+ }
224
+
225
+ private printQR(qr: string): void {
226
+ this.log.info("\n" + "=".repeat(50));
227
+ this.log.info(" WHATSAPP QR CODE - Scan with your phone");
228
+ this.log.info("=".repeat(50) + "\n");
229
+
230
+ qrcodeTerminal.generate(qr, { small: false }, (qrString: string) => {
231
+ this.log.info(qrString);
232
+ });
233
+
234
+ this.log.info("\n" + "=".repeat(50));
235
+ this.log.info(" Open WhatsApp > Settings > Linked Devices");
236
+ this.log.info("=".repeat(50) + "\n");
237
+ }
238
+
239
+ private async handleMessages(update: { messages: unknown[]; type: string }): Promise<void> {
240
+ if (update.type !== "notify") return;
241
+
242
+ for (const msg of update.messages) {
243
+ const typedMsg = msg as {
244
+ key: { fromMe?: boolean; remoteJid?: string; id?: string };
245
+ message?: Record<string, unknown>;
246
+ messageTimestamp?: number;
247
+ pushName?: string;
248
+ };
249
+
250
+ const from = typedMsg.key.remoteJid;
251
+ if (!from) continue;
252
+
253
+ const isGroup = from.includes("@g.us");
254
+
255
+ if (isGroup && !this.config.acceptGroups) {
256
+ this.log.info(`[filter] Group message skipped (acceptGroups=false): ${from}`);
257
+ continue;
258
+ }
259
+
260
+ const selfMessagesOnly = this.config.selfMessagesOnly !== false;
261
+
262
+ if (!isGroup) {
263
+ const fromNumber = from.split("@")[0];
264
+ const ownJid = this.socket?.user?.id ?? "";
265
+ const ownLid = this.socket?.user?.lid ?? "";
266
+ const ownNumber = ownJid.split(":")[0].split("@")[0];
267
+ const ownLidNumber = ownLid.split(":")[0].split("@")[0];
268
+ const isToSelf = fromNumber === ownNumber || fromNumber === ownLidNumber;
269
+ const isSelfMessage = !!typedMsg.key.fromMe && isToSelf;
270
+
271
+ this.log.info(`[filter] DM from=${fromNumber} ownNumber=${ownNumber} ownLid=${ownLidNumber} fromMe=${typedMsg.key.fromMe} selfMessagesOnly=${selfMessagesOnly} isSelfMessage=${isSelfMessage}`);
272
+
273
+ if (selfMessagesOnly) {
274
+ if (!isSelfMessage) {
275
+ this.log.info(`[filter] DM skipped (selfMessagesOnly=true, not self)`);
276
+ continue;
277
+ }
278
+ } else {
279
+ if (!isSelfMessage && !this.isUserAllowed(fromNumber)) {
280
+ this.log.info(`[filter] DM skipped (not in allowlist): ${fromNumber}`);
281
+ continue;
282
+ }
283
+ }
284
+ }
285
+
286
+ const { content, hasAudio, hasImage, hasDocument } = this.extractMessageContent(typedMsg.message);
287
+ if (!content && !hasAudio && !hasImage && !hasDocument) continue;
288
+
289
+ let audioBuffer: Buffer | null = null;
290
+ let imageBuffer: Buffer | null = null;
291
+ let documentBuffer: Buffer | null = null;
292
+ let imageMime: string | undefined;
293
+ let documentMime: string | undefined;
294
+ let documentName: string | undefined;
295
+ let imageCaption: string | undefined;
296
+
297
+ if (hasAudio && this.socket) {
298
+ try {
299
+ audioBuffer = await downloadMediaMessage(
300
+ typedMsg as unknown as WAMessage,
301
+ "buffer",
302
+ {},
303
+ { reuploadRequest: this.socket.updateMediaMessage, logger: this.log as any }
304
+ ) as Buffer;
305
+ } catch (err) {
306
+ this.log.warn(`Failed to download WhatsApp audio: ${(err as Error).message}`);
307
+ }
308
+ }
309
+
310
+ if (hasImage && this.socket) {
311
+ try {
312
+ imageBuffer = await downloadMediaMessage(
313
+ typedMsg as unknown as WAMessage,
314
+ "buffer",
315
+ {},
316
+ { reuploadRequest: this.socket.updateMediaMessage, logger: this.log as any }
317
+ ) as Buffer;
318
+ const imgMsg = typedMsg.message?.imageMessage as { mimetype?: string; caption?: string } | undefined;
319
+ imageMime = imgMsg?.mimetype || "image/jpeg";
320
+ imageCaption = imgMsg?.caption || undefined;
321
+ } catch (err) {
322
+ this.log.warn(`Failed to download WhatsApp image: ${(err as Error).message}`);
323
+ }
324
+ }
325
+
326
+ if (hasDocument && this.socket) {
327
+ try {
328
+ documentBuffer = await downloadMediaMessage(
329
+ typedMsg as unknown as WAMessage,
330
+ "buffer",
331
+ {},
332
+ { reuploadRequest: this.socket.updateMediaMessage, logger: this.log as any }
333
+ ) as Buffer;
334
+ const docMsg = typedMsg.message?.documentMessage as { mimetype?: string; fileName?: string } | undefined;
335
+ documentMime = docMsg?.mimetype || "application/pdf";
336
+ documentName = docMsg?.fileName || undefined;
337
+ } catch (err) {
338
+ this.log.warn(`Failed to download WhatsApp document: ${(err as Error).message}`);
339
+ }
340
+ }
341
+
342
+ const peerId = isGroup ? from : from.replace("@s.whatsapp.net", "");
343
+
344
+ const incoming: IncomingMessage = {
345
+ sessionId: this.formatSessionId(peerId, isGroup ? "group" : "direct"),
346
+ channel: "whatsapp",
347
+ accountId: this.accountId,
348
+ peerId,
349
+ peerKind: isGroup ? "group" : "direct",
350
+ content: content || (hasAudio ? "[Audio message]" : ""),
351
+ audio: audioBuffer ? { buffer: audioBuffer, mimeType: "audio/ogg" } : undefined,
352
+ image: imageBuffer ? { buffer: imageBuffer, mimeType: imageMime, caption: imageCaption } : undefined,
353
+ document: documentBuffer ? { buffer: documentBuffer, mimeType: documentMime || "application/octet-stream", fileName: documentName } : undefined,
354
+ metadata: {
355
+ messageId: typedMsg.key.id,
356
+ timestamp: typedMsg.messageTimestamp,
357
+ pushName: typedMsg.pushName,
358
+ },
359
+ };
360
+
361
+ await this.handleMessage(incoming);
362
+ }
363
+ }
364
+
365
+ private extractMessageContent(message?: Record<string, unknown>): { content: string | null; hasAudio: boolean; hasImage: boolean; hasDocument: boolean } {
366
+ if (!message) return { content: null, hasAudio: false, hasImage: false, hasDocument: false };
367
+
368
+ if (message.conversation) {
369
+ return { content: message.conversation as string, hasAudio: false, hasImage: false, hasDocument: false };
370
+ }
371
+
372
+ const extendedText = message.extendedTextMessage as { text?: string } | undefined;
373
+ if (extendedText?.text) {
374
+ return { content: extendedText.text, hasAudio: false, hasImage: false, hasDocument: false };
375
+ }
376
+
377
+ const imageMsg = message.imageMessage as { caption?: string } | undefined;
378
+ if (imageMsg) {
379
+ return { content: imageMsg.caption || "", hasAudio: false, hasImage: true, hasDocument: false };
380
+ }
381
+
382
+ const videoMsg = message.videoMessage as { caption?: string } | undefined;
383
+ if (videoMsg?.caption) {
384
+ return { content: `[Video] ${videoMsg.caption}`, hasAudio: false, hasImage: false, hasDocument: false };
385
+ }
386
+
387
+ const docMsg = message.documentMessage as { caption?: string } | undefined;
388
+ if (docMsg) {
389
+ return { content: docMsg.caption || "", hasAudio: false, hasImage: false, hasDocument: true };
390
+ }
391
+
392
+ if (message.audioMessage) {
393
+ return { content: null, hasAudio: true, hasImage: false, hasDocument: false };
394
+ }
395
+
396
+ return { content: null, hasAudio: false, hasImage: false, hasDocument: false };
397
+ }
398
+
399
+ private scheduleReconnect(): void {
400
+ if (!this.running) return;
401
+
402
+ const maxAttempts = this.config.reconnectMaxAttempts ?? 10;
403
+ const baseDelay = this.config.reconnectBaseDelayMs ?? 5000;
404
+ const attempts = this.connectionState.reconnectAttempts;
405
+
406
+ if (attempts >= maxAttempts) {
407
+ this.log.error(`Max reconnection attempts (${maxAttempts}) reached`);
408
+ this.connectionState.status = "error";
409
+ this.connectionState.error = "Max reconnection attempts reached";
410
+ return;
411
+ }
412
+
413
+ const delay = Math.min(baseDelay * Math.pow(2, attempts), 60000);
414
+ this.connectionState.reconnectAttempts++;
415
+
416
+ this.log.info(`Reconnecting in ${delay / 1000}s (attempt ${attempts + 1}/${maxAttempts})`);
417
+
418
+ this.reconnectTimeout = setTimeout(async () => {
419
+ await this.connect();
420
+ }, delay);
421
+ }
422
+
423
+ private getJid(sessionId: string): string {
424
+ const cached = this.jidCache.get(sessionId);
425
+ if (cached) return cached;
426
+
427
+ const peerId = this.extractPeerId(sessionId);
428
+ const jid = peerId.includes("@") ? peerId : `${peerId}@s.whatsapp.net`;
429
+ this.jidCache.set(sessionId, jid);
430
+ return jid;
431
+ }
432
+
433
+ async startTyping(sessionId: string): Promise<void> {
434
+ if (!this.socket || this.connectionState.status !== "connected") return;
435
+
436
+ const jid = this.getJid(sessionId);
437
+ try {
438
+ await this.socket.sendPresenceUpdate("composing", jid);
439
+ } catch {
440
+ // Ignore typing errors
441
+ }
442
+ }
443
+
444
+ async stopTyping(sessionId: string): Promise<void> {
445
+ if (!this.socket || this.connectionState.status !== "connected") return;
446
+
447
+ const jid = this.getJid(sessionId);
448
+ try {
449
+ await this.socket.sendPresenceUpdate("paused", jid);
450
+ } catch {
451
+ // Ignore typing errors
452
+ }
453
+ }
454
+
455
+ async markAsRead(sessionId: string, messageId?: string): Promise<void> {
456
+ if (!this.socket || this.connectionState.status !== "connected") return;
457
+ if (!messageId) return;
458
+
459
+ const jid = this.getJid(sessionId);
460
+ try {
461
+ await this.socket.readMessages([
462
+ { remoteJid: jid, id: messageId, fromMe: false }
463
+ ]);
464
+ } catch {
465
+ // Ignore read receipt errors
466
+ }
467
+ }
468
+
469
+ async send(sessionId: string, message: OutboundMessage): Promise<void> {
470
+ if (!this.socket || this.connectionState.status !== "connected") {
471
+ throw new Error("WhatsApp not connected");
472
+ }
473
+
474
+ await this.stopTyping(sessionId);
475
+
476
+ const text = message.content ?? message.chunk ?? "";
477
+ if (!text) return;
478
+
479
+ const jid = this.getJid(sessionId);
480
+
481
+ await this.socket.sendMessage(jid, { text });
482
+ this.log.debug(`Sent message to ${jid}`);
483
+ }
484
+
485
+ async sendAudio(sessionId: string, audio: Buffer, mimeType: string): Promise<void> {
486
+ if (!this.socket || this.connectionState.status !== "connected") {
487
+ throw new Error("WhatsApp not connected");
488
+ }
489
+
490
+ const jid = this.getJid(sessionId);
491
+
492
+ try {
493
+ await this.socket.sendMessage(jid, {
494
+ audio: audio,
495
+ mimetype: mimeType,
496
+ });
497
+ this.log.debug(`Sent audio to ${jid}`);
498
+ } catch (error) {
499
+ this.log.error(`Failed to send WhatsApp audio: ${(error as Error).message}`);
500
+ throw error;
501
+ }
502
+ }
503
+
504
+ private extractPeerId(sessionId: string): string {
505
+ const parts = sessionId.split(":");
506
+ return parts[parts.length - 1] ?? "";
507
+ }
508
+
509
+ getState(): WhatsAppConnectionState {
510
+ return { ...this.connectionState };
511
+ }
512
+
513
+ getConfig(): WhatsAppConfig {
514
+ return { ...this.config };
515
+ }
516
+
517
+ async disconnect(clearSession: boolean = false): Promise<void> {
518
+ this.running = false;
519
+
520
+ if (this.reconnectTimeout) {
521
+ clearTimeout(this.reconnectTimeout);
522
+ this.reconnectTimeout = null;
523
+ }
524
+
525
+ if (this.socket) {
526
+ try {
527
+ await this.socket.end(undefined);
528
+ } catch {
529
+ // Ignore close errors
530
+ }
531
+ this.socket = null;
532
+ }
533
+
534
+ this.connectionState.status = "disconnected";
535
+ this.connectionState.phoneNumber = undefined;
536
+ this.log.info("WhatsApp channel disconnected");
537
+
538
+ if (clearSession) {
539
+ this.log.info("Clearing WhatsApp session files.");
540
+ rmSync(this.authPath, { recursive: true, force: true });
541
+ mkdirSync(this.authPath, { recursive: true });
542
+ }
543
+ }
544
+ }
545
+
546
+ export function createWhatsAppChannel(config: WhatsAppConfig): WhatsAppChannel {
547
+ return new WhatsAppChannel(config);
548
+ }
@@ -0,0 +1,12 @@
1
+ export {
2
+ getHiveDir,
3
+ loadConfig,
4
+ expandConfigPath,
5
+ expandPath,
6
+ type Config,
7
+ type ProviderConfig,
8
+ type MCPServerConfig,
9
+ type AgentEntry,
10
+ type Binding,
11
+ type UserConfig as ConfigUserConfig
12
+ } from "./loader.ts";