@johpaz/hive-agents 0.0.34 → 0.0.36

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 (466) hide show
  1. package/README.md +64 -39
  2. package/dist/hive.js +4539 -4586
  3. package/dist/ui/assets/AgentCreateForm-tJZv9FZC.js +1 -0
  4. package/dist/ui/assets/AgentDetailPage-Du-mRcAX.js +1 -0
  5. package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  6. package/dist/ui/assets/{AgentsPage-DhCjvDNa.js → AgentsPage-YvSgWRiw.js} +7 -7
  7. package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
  8. package/dist/ui/assets/ChannelsPage-BdBXWHjj.js +8 -0
  9. package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
  10. package/dist/ui/assets/{LoginPage-B30OrEBy.js → LoginPage-CAmSI9Vy.js} +1 -1
  11. package/dist/ui/assets/LogsPage-DAPBHkwK.js +1 -0
  12. package/dist/ui/assets/MeetingPage-WjjGOqqU.js +1 -0
  13. package/dist/ui/assets/{NotFound-HD1Yp9yK.js → NotFound-BMeQSGcG.js} +1 -1
  14. package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  15. package/dist/ui/assets/{RecoverPage-CLF6buGP.js → RecoverPage-DpW3l-yv.js} +1 -1
  16. package/dist/ui/assets/SettingsPage-DBJ7_E6C.js +9 -0
  17. package/dist/ui/assets/SetupPage-DKmLVUaj.js +1 -0
  18. package/dist/ui/assets/{WebChatPage-Um3VANzn.js → WebChatPage-CVRcKept.js} +2 -2
  19. package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
  20. package/dist/ui/assets/{activity-SfJ6UDF2.js → activity-c3pNngT_.js} +1 -1
  21. package/dist/ui/assets/alert-C-NE-P3s.js +1 -0
  22. package/dist/ui/assets/{alert-dialog-M893TdvF.js → alert-dialog-C5mzbHdP.js} +1 -1
  23. package/dist/ui/assets/arrow-left-CBcbX5EZ.js +1 -0
  24. package/dist/ui/assets/badge-ChpACfWO.js +1 -0
  25. package/dist/ui/assets/{calendar-CMMeWsP-.js → calendar-B-KZ9RQO.js} +1 -1
  26. package/dist/ui/assets/{card-C7P3W6_y.js → card-CNf6BS2e.js} +1 -1
  27. package/dist/ui/assets/chevron-left-D4U-5A27.js +1 -0
  28. package/dist/ui/assets/chevron-right-CR4Skrf3.js +1 -0
  29. package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
  30. package/dist/ui/assets/{circle-alert-7koABcbO.js → circle-alert-CyHDwUj8.js} +1 -1
  31. package/dist/ui/assets/circle-check-Bb54Ebmu.js +1 -0
  32. package/dist/ui/assets/{cpu-mBJgRJzM.js → cpu-Cdgc_B1K.js} +1 -1
  33. package/dist/ui/assets/dialog-QnZ0ad8O.js +1 -0
  34. package/dist/ui/assets/{download-oaofq4K1.js → download-C3ifGMjJ.js} +1 -1
  35. package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
  36. package/dist/ui/assets/{es-eUrU2hyB.js → es-NQNoaWDx.js} +1 -1
  37. package/dist/ui/assets/{external-link-SkkF2Z7B.js → external-link-BvxYeTP1.js} +1 -1
  38. package/dist/ui/assets/{eye-B8lq7sWG.js → eye-DqNTU_GD.js} +1 -1
  39. package/dist/ui/assets/{file-text-0oYol8Bb.js → file-text-BT_9S9SM.js} +1 -1
  40. package/dist/ui/assets/{folder-open-DVYu2lgk.js → folder-open-BhH8y9ac.js} +1 -1
  41. package/dist/ui/assets/gauge-D_TMa4i9.js +1 -0
  42. package/dist/ui/assets/{globe-BVPd5DRa.js → globe-DeCQTCDJ.js} +1 -1
  43. package/dist/ui/assets/{hexagon-BIAFUAlQ.js → hexagon-DsGOUl-H.js} +1 -1
  44. package/dist/ui/assets/{history-BUAnaMQo.js → history-BSG-Ypqf.js} +1 -1
  45. package/dist/ui/assets/index-B2fCYtTS.css +2 -0
  46. package/dist/ui/assets/index-DMCjjdqf.js +116 -0
  47. package/dist/ui/assets/{info-DWioleen.js → info-NwLoa2Mj.js} +1 -1
  48. package/dist/ui/assets/{key-BCGwSKKc.js → key-3EP0dhkT.js} +1 -1
  49. package/dist/ui/assets/label-D2H1IR_J.js +1 -0
  50. package/dist/ui/assets/loader-circle-CZNax6kS.js +1 -0
  51. package/dist/ui/assets/{lock-D7PCO7GC.js → lock-Ei1_J-Nq.js} +1 -1
  52. package/dist/ui/assets/{pause-CI1JFH6r.js → pause-BUqah9Bi.js} +1 -1
  53. package/dist/ui/assets/play-NcZ4swwL.js +1 -0
  54. package/dist/ui/assets/plus-CX1xyhp5.js +1 -0
  55. package/dist/ui/assets/progress-BherYzY6.js +1 -0
  56. package/dist/ui/assets/{refresh-cw-BLmKlO4J.js → refresh-cw-DaYdjQFk.js} +1 -1
  57. package/dist/ui/assets/{save-M1nv6H3P.js → save-CUdYyHNy.js} +1 -1
  58. package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
  59. package/dist/ui/assets/{send-ijRfR0gp.js → send-B0H5SEIE.js} +1 -1
  60. package/dist/ui/assets/{settings-BvXhlJCF.js → settings-Ds4SqD8s.js} +1 -1
  61. package/dist/ui/assets/{slider-DrDFLwXh.js → slider-CsiUDxc3.js} +1 -1
  62. package/dist/ui/assets/{sparkles-C4MACMbE.js → sparkles-yUEb-7oH.js} +1 -1
  63. package/dist/ui/assets/{square-D_-gRT1l.js → square-BD81nFtN.js} +1 -1
  64. package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
  65. package/dist/ui/assets/{table-DWEJJiuF.js → table-CSc8ubon.js} +1 -1
  66. package/dist/ui/assets/terminal-DN38Q456.js +1 -0
  67. package/dist/ui/assets/{textarea-CwPvQVAG.js → textarea-CXgXWKrT.js} +1 -1
  68. package/dist/ui/assets/{trash-2-Blkv31Dz.js → trash-2-CNjMkoq6.js} +1 -1
  69. package/dist/ui/assets/{triangle-alert-BKgbd30k.js → triangle-alert-C9Y8Ub4X.js} +1 -1
  70. package/dist/ui/assets/useProviders-C6_QHsEi.js +1 -0
  71. package/dist/ui/assets/{vendor-radix-JY4ncZrD.js → vendor-radix-cw1bQaVC.js} +4 -4
  72. package/dist/ui/assets/{vendor-react-CscwQerf.js → vendor-react-D4s9E-zj.js} +1 -1
  73. package/dist/ui/assets/{volume-2-BiUgObeI.js → volume-2-CeSXNDv4.js} +1 -1
  74. package/dist/ui/assets/{zap-CpyuQJEC.js → zap-hlXjpSeA.js} +1 -1
  75. package/dist/ui/dist/assets/AgentCreateForm-tJZv9FZC.js +1 -0
  76. package/dist/ui/dist/assets/AgentDetailPage-Du-mRcAX.js +1 -0
  77. package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  78. package/dist/ui/dist/assets/AgentsPage-YvSgWRiw.js +10 -0
  79. package/dist/ui/dist/assets/CanvasPage-DtMwGvxf.js +33 -0
  80. package/dist/ui/dist/assets/ChannelsPage-BdBXWHjj.js +8 -0
  81. package/dist/ui/dist/assets/DashboardPage-ghl1ZguH.js +6 -0
  82. package/dist/ui/dist/assets/LoginPage-CAmSI9Vy.js +1 -0
  83. package/dist/ui/dist/assets/LogsPage-DAPBHkwK.js +1 -0
  84. package/dist/ui/dist/assets/MeetingPage-WjjGOqqU.js +1 -0
  85. package/dist/ui/dist/assets/NotFound-BMeQSGcG.js +1 -0
  86. package/dist/ui/dist/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  87. package/dist/ui/dist/assets/RecoverPage-DpW3l-yv.js +1 -0
  88. package/dist/ui/dist/assets/SettingsPage-DBJ7_E6C.js +9 -0
  89. package/dist/ui/dist/assets/SetupPage-DKmLVUaj.js +1 -0
  90. package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +16 -0
  91. package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +1 -0
  92. package/dist/ui/dist/assets/activity-c3pNngT_.js +1 -0
  93. package/dist/ui/dist/assets/alert-C-NE-P3s.js +1 -0
  94. package/dist/ui/dist/assets/alert-dialog-C5mzbHdP.js +1 -0
  95. package/dist/ui/dist/assets/arrow-left-CBcbX5EZ.js +1 -0
  96. package/dist/ui/dist/assets/badge-ChpACfWO.js +1 -0
  97. package/dist/ui/dist/assets/calendar-B-KZ9RQO.js +1 -0
  98. package/dist/ui/dist/assets/card-CNf6BS2e.js +1 -0
  99. package/dist/ui/dist/assets/chevron-left-D4U-5A27.js +1 -0
  100. package/dist/ui/dist/assets/chevron-right-CR4Skrf3.js +1 -0
  101. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +1 -0
  102. package/dist/ui/dist/assets/circle-alert-CyHDwUj8.js +1 -0
  103. package/dist/ui/dist/assets/circle-check-Bb54Ebmu.js +1 -0
  104. package/dist/ui/dist/assets/cpu-Cdgc_B1K.js +1 -0
  105. package/dist/ui/dist/assets/dialog-QnZ0ad8O.js +1 -0
  106. package/dist/ui/dist/assets/download-C3ifGMjJ.js +1 -0
  107. package/dist/ui/dist/assets/dropdown-menu-BK-CO3Od.js +1 -0
  108. package/dist/ui/dist/assets/es-NQNoaWDx.js +1 -0
  109. package/dist/ui/dist/assets/external-link-BvxYeTP1.js +1 -0
  110. package/dist/ui/dist/assets/eye-DqNTU_GD.js +1 -0
  111. package/dist/ui/dist/assets/file-text-BT_9S9SM.js +1 -0
  112. package/dist/ui/dist/assets/folder-open-BhH8y9ac.js +1 -0
  113. package/dist/ui/dist/assets/format-GVHeOyWI.js +1 -0
  114. package/dist/ui/dist/assets/gateway-url-COCbW0IR.js +1 -0
  115. package/dist/ui/dist/assets/gauge-D_TMa4i9.js +1 -0
  116. package/dist/ui/dist/assets/globe-DeCQTCDJ.js +1 -0
  117. package/dist/ui/dist/assets/hexagon-DsGOUl-H.js +1 -0
  118. package/dist/ui/dist/assets/history-BSG-Ypqf.js +1 -0
  119. package/dist/ui/dist/assets/index-B2fCYtTS.css +2 -0
  120. package/dist/ui/dist/assets/index-DMCjjdqf.js +116 -0
  121. package/dist/ui/dist/assets/info-NwLoa2Mj.js +1 -0
  122. package/dist/ui/dist/assets/key-3EP0dhkT.js +1 -0
  123. package/dist/ui/dist/assets/label-D2H1IR_J.js +1 -0
  124. package/dist/ui/dist/assets/loader-circle-CZNax6kS.js +1 -0
  125. package/dist/ui/dist/assets/lock-Ei1_J-Nq.js +1 -0
  126. package/dist/ui/dist/assets/pause-BUqah9Bi.js +1 -0
  127. package/dist/ui/dist/assets/play-NcZ4swwL.js +1 -0
  128. package/dist/ui/dist/assets/plus-CX1xyhp5.js +1 -0
  129. package/dist/ui/dist/assets/progress-BherYzY6.js +1 -0
  130. package/dist/ui/dist/assets/refresh-cw-DaYdjQFk.js +1 -0
  131. package/dist/ui/dist/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
  132. package/dist/ui/dist/assets/save-CUdYyHNy.js +1 -0
  133. package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +1 -0
  134. package/dist/ui/dist/assets/send-B0H5SEIE.js +1 -0
  135. package/dist/ui/dist/assets/settings-Ds4SqD8s.js +1 -0
  136. package/dist/ui/dist/assets/slider-CsiUDxc3.js +14 -0
  137. package/dist/ui/dist/assets/sparkles-yUEb-7oH.js +1 -0
  138. package/dist/ui/dist/assets/square-BD81nFtN.js +1 -0
  139. package/dist/ui/dist/assets/switch-BDwN8RYV.js +1 -0
  140. package/dist/ui/dist/assets/table-CSc8ubon.js +1 -0
  141. package/dist/ui/dist/assets/terminal-DN38Q456.js +1 -0
  142. package/dist/ui/dist/assets/textarea-CXgXWKrT.js +1 -0
  143. package/dist/ui/dist/assets/trash-2-CNjMkoq6.js +1 -0
  144. package/dist/ui/dist/assets/triangle-alert-C9Y8Ub4X.js +1 -0
  145. package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +1 -0
  146. package/dist/ui/dist/assets/utils-3pnRFmFe.js +1 -0
  147. package/dist/ui/dist/assets/vendor-charts-Bu2lyBKP.js +65 -0
  148. package/dist/ui/dist/assets/vendor-query-DsWPbQdG.js +1 -0
  149. package/dist/ui/dist/assets/vendor-radix-cw1bQaVC.js +63 -0
  150. package/dist/ui/dist/assets/vendor-react-D4s9E-zj.js +1 -0
  151. package/dist/ui/dist/assets/vendor-router-C9pIYwbJ.js +3 -0
  152. package/dist/ui/dist/assets/volume-2-CeSXNDv4.js +1 -0
  153. package/dist/ui/dist/assets/zap-hlXjpSeA.js +1 -0
  154. package/dist/ui/dist/favicon.ico +0 -0
  155. package/dist/ui/dist/index.html +40 -0
  156. package/dist/ui/dist/placeholder.svg +1 -0
  157. package/dist/ui/index.html +7 -11
  158. package/package.json +137 -15
  159. package/packages/cli/src/adapters/binary.ts +461 -0
  160. package/packages/cli/src/adapters/bun-global.ts +378 -0
  161. package/packages/cli/src/adapters/config.ts +314 -0
  162. package/packages/cli/src/adapters/docker.ts +308 -0
  163. package/packages/cli/src/adapters/factory.ts +168 -0
  164. package/packages/cli/src/adapters/index.ts +80 -0
  165. package/packages/cli/src/adapters/types.ts +218 -0
  166. package/packages/cli/src/commands/agent-run.ts +168 -0
  167. package/packages/cli/src/commands/agents.ts +398 -0
  168. package/packages/cli/src/commands/chat.ts +142 -0
  169. package/packages/cli/src/commands/config.ts +49 -0
  170. package/packages/cli/src/commands/cron.ts +487 -0
  171. package/packages/cli/src/commands/dev.ts +58 -0
  172. package/packages/cli/src/commands/doctor.ts +320 -0
  173. package/packages/cli/src/commands/gateway.ts +719 -0
  174. package/packages/cli/src/commands/logs.ts +57 -0
  175. package/packages/cli/src/commands/mcp.ts +175 -0
  176. package/packages/cli/src/commands/message.ts +77 -0
  177. package/packages/cli/src/commands/migrate.ts +90 -0
  178. package/packages/cli/src/commands/onboard.ts +1656 -0
  179. package/packages/cli/src/commands/security.ts +144 -0
  180. package/packages/cli/src/commands/service.ts +50 -0
  181. package/packages/cli/src/commands/sessions.ts +116 -0
  182. package/packages/cli/src/commands/skills.ts +215 -0
  183. package/packages/cli/src/commands/update.ts +203 -0
  184. package/packages/cli/src/index.ts +210 -0
  185. package/packages/cli/src/ui-bundle.generated.ts +3 -0
  186. package/packages/cli/src/utils/token.ts +6 -0
  187. package/packages/core/src/agent/agent-loop.ts +691 -0
  188. package/packages/core/src/agent/compaction.ts +240 -0
  189. package/packages/core/src/agent/context-compiler.ts +467 -0
  190. package/packages/core/src/agent/context-guard.ts +91 -0
  191. package/packages/core/src/agent/conversation-store.ts +244 -0
  192. package/packages/core/src/agent/curator.ts +158 -0
  193. package/packages/core/src/agent/hooks.ts +166 -0
  194. package/packages/core/src/agent/llm-client.ts +167 -0
  195. package/packages/core/src/agent/llm-providers/anthropic.ts +212 -0
  196. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  197. package/packages/core/src/agent/llm-providers/gemini.ts +215 -0
  198. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  199. package/packages/core/src/agent/llm-providers/interface.ts +195 -0
  200. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  201. package/packages/core/src/agent/llm-providers/local-llama.ts +37 -0
  202. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  203. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  204. package/packages/core/src/agent/llm-providers/ollama.ts +175 -0
  205. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +379 -0
  206. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  207. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  208. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  209. package/packages/core/src/agent/native-tools.ts +31 -0
  210. package/packages/core/src/agent/playbook-selector.ts +147 -0
  211. package/packages/core/src/agent/prompt-builder.ts +169 -0
  212. package/packages/core/src/agent/providers/index.ts +204 -0
  213. package/packages/core/src/agent/providers.ts +1 -0
  214. package/packages/core/src/agent/reflector.ts +200 -0
  215. package/packages/core/src/agent/service.ts +267 -0
  216. package/packages/core/src/agent/skill-selector.ts +479 -0
  217. package/packages/core/src/agent/stuck-loop.ts +133 -0
  218. package/packages/core/src/agent/tool-selector.ts +569 -0
  219. package/packages/core/src/agent/tracer.ts +100 -0
  220. package/packages/core/src/auth/auth.ts +108 -0
  221. package/packages/core/src/auth/index.ts +1 -0
  222. package/packages/core/src/canvas/a2ui-tools.ts +255 -0
  223. package/packages/core/src/canvas/canvas-manager.ts +390 -0
  224. package/packages/core/src/canvas/canvas-tools.ts +448 -0
  225. package/packages/core/src/canvas/emitter.ts +149 -0
  226. package/packages/core/src/canvas/index.ts +3 -0
  227. package/packages/core/src/channels/base.ts +154 -0
  228. package/packages/core/src/channels/discord.ts +273 -0
  229. package/packages/core/src/channels/index.ts +7 -0
  230. package/packages/core/src/channels/manager.ts +450 -0
  231. package/packages/core/src/channels/slack.ts +323 -0
  232. package/packages/core/src/channels/telegram.ts +612 -0
  233. package/packages/core/src/channels/webchat.ts +139 -0
  234. package/packages/core/src/channels/whatsapp.ts +548 -0
  235. package/packages/core/src/config/index.ts +12 -0
  236. package/packages/core/src/config/loader.ts +569 -0
  237. package/packages/core/src/events/agent-bus.ts +460 -0
  238. package/packages/core/src/events/event-bus.ts +169 -0
  239. package/packages/core/src/gateway/channel-notify.ts +64 -0
  240. package/packages/core/src/gateway/helpers/cors.ts +32 -0
  241. package/packages/core/src/gateway/helpers/index.ts +4 -0
  242. package/packages/core/src/gateway/helpers/narration.ts +57 -0
  243. package/packages/core/src/gateway/helpers/path.ts +13 -0
  244. package/packages/core/src/gateway/helpers/redact.ts +61 -0
  245. package/packages/core/src/gateway/index.ts +5 -0
  246. package/packages/core/src/gateway/initializer.ts +363 -0
  247. package/packages/core/src/gateway/lane-queue.ts +169 -0
  248. package/packages/core/src/gateway/llm-local/client.ts +94 -0
  249. package/packages/core/src/gateway/llm-local/detector.ts +321 -0
  250. package/packages/core/src/gateway/llm-local/downloader.ts +216 -0
  251. package/packages/core/src/gateway/llm-local/index.ts +34 -0
  252. package/packages/core/src/gateway/llm-local/manager.ts +186 -0
  253. package/packages/core/src/gateway/llm-local/models.ts +149 -0
  254. package/packages/core/src/gateway/llm-local/server.ts +179 -0
  255. package/packages/core/src/gateway/resolver.ts +108 -0
  256. package/packages/core/src/gateway/router.ts +124 -0
  257. package/packages/core/src/gateway/routes/agents.ts +210 -0
  258. package/packages/core/src/gateway/routes/auth.ts +244 -0
  259. package/packages/core/src/gateway/routes/channels.ts +484 -0
  260. package/packages/core/src/gateway/routes/chat.ts +241 -0
  261. package/packages/core/src/gateway/routes/config.ts +12 -0
  262. package/packages/core/src/gateway/routes/cron-api.ts +544 -0
  263. package/packages/core/src/gateway/routes/ethics.ts +46 -0
  264. package/packages/core/src/gateway/routes/llm-local.ts +271 -0
  265. package/packages/core/src/gateway/routes/mcp.ts +319 -0
  266. package/packages/core/src/gateway/routes/meeting.ts +232 -0
  267. package/packages/core/src/gateway/routes/models.ts +163 -0
  268. package/packages/core/src/gateway/routes/multimodal.ts +93 -0
  269. package/packages/core/src/gateway/routes/providers.ts +220 -0
  270. package/packages/core/src/gateway/routes/setup.ts +441 -0
  271. package/packages/core/src/gateway/routes/skills.ts +115 -0
  272. package/packages/core/src/gateway/routes/system.ts +469 -0
  273. package/packages/core/src/gateway/routes/tasks.ts +44 -0
  274. package/packages/core/src/gateway/routes/tools.ts +59 -0
  275. package/packages/core/src/gateway/routes/tts-local.ts +388 -0
  276. package/packages/core/src/gateway/routes/users.ts +122 -0
  277. package/packages/core/src/gateway/routes/voice.ts +189 -0
  278. package/packages/core/src/gateway/routes/workspace.ts +281 -0
  279. package/packages/core/src/gateway/server.ts +2744 -0
  280. package/packages/core/src/gateway/session.ts +95 -0
  281. package/packages/core/src/gateway/slash-commands.ts +207 -0
  282. package/packages/core/src/gateway/tts/README.md +94 -0
  283. package/packages/core/src/gateway/tts/package.json +25 -0
  284. package/packages/core/src/gateway/tts/src/client.ts +59 -0
  285. package/packages/core/src/gateway/tts/src/detect.ts +42 -0
  286. package/packages/core/src/gateway/tts/src/index.ts +15 -0
  287. package/packages/core/src/gateway/tts/src/install.ts +129 -0
  288. package/packages/core/src/gateway/tts/src/models.ts +50 -0
  289. package/packages/core/src/gateway/tts/src/server.ts +252 -0
  290. package/packages/core/src/gateway/tts/voices/.gitkeep +0 -0
  291. package/packages/core/src/heartbeat/index.ts +157 -0
  292. package/packages/core/src/index.ts +56 -0
  293. package/packages/core/src/mcp/hot-reload.ts +148 -0
  294. package/packages/core/src/mcp/singleton.ts +21 -0
  295. package/packages/core/src/mcp/tool-sync.ts +176 -0
  296. package/packages/core/src/multimodal/index.ts +2 -0
  297. package/packages/core/src/multimodal/types.ts +28 -0
  298. package/packages/core/src/multimodal/vision-service.ts +283 -0
  299. package/packages/core/src/plugins/api.ts +128 -0
  300. package/packages/core/src/plugins/index.ts +2 -0
  301. package/packages/core/src/plugins/loader.ts +365 -0
  302. package/packages/core/src/resilience/circuit-breaker.ts +225 -0
  303. package/packages/core/src/scheduler/CronScheduler.ts +699 -0
  304. package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
  305. package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
  306. package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
  307. package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
  308. package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
  309. package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
  310. package/packages/core/src/scheduler/dag/errors.ts +37 -0
  311. package/packages/core/src/scheduler/dag/index.ts +26 -0
  312. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
  313. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
  314. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
  315. package/packages/core/src/scheduler/index.ts +22 -0
  316. package/packages/core/src/scheduler/integration.ts +237 -0
  317. package/packages/core/src/scheduler/types.ts +164 -0
  318. package/packages/core/src/security/google-chat.ts +269 -0
  319. package/packages/core/src/security/index.ts +192 -0
  320. package/packages/core/src/security/pairing.ts +250 -0
  321. package/packages/core/src/security/rate-limit.ts +270 -0
  322. package/packages/core/src/security/signal.ts +321 -0
  323. package/packages/core/src/state/store.ts +312 -0
  324. package/packages/core/src/storage/crypto.ts +197 -0
  325. package/packages/core/src/storage/migrate.ts +147 -0
  326. package/packages/core/src/storage/onboarding.ts +1506 -0
  327. package/packages/core/src/storage/schema.ts +666 -0
  328. package/packages/core/src/storage/seed.ts +628 -0
  329. package/packages/core/src/storage/sqlite.ts +407 -0
  330. package/packages/core/src/storage/usage.ts +374 -0
  331. package/packages/core/src/tool-runtime/index.ts +476 -0
  332. package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
  333. package/packages/core/src/tools/agents/get-available-models.ts +118 -0
  334. package/packages/core/src/tools/agents/index.ts +610 -0
  335. package/packages/core/src/tools/canvas/index.ts +420 -0
  336. package/packages/core/src/tools/cli/index.ts +142 -0
  337. package/packages/core/src/tools/core/index.ts +478 -0
  338. package/packages/core/src/tools/cron/index.ts +635 -0
  339. package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
  340. package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
  341. package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
  342. package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
  343. package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
  344. package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
  345. package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
  346. package/packages/core/src/tools/filesystem/index.ts +34 -0
  347. package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
  348. package/packages/core/src/tools/index.ts +197 -0
  349. package/packages/core/src/tools/meeting/index.ts +363 -0
  350. package/packages/core/src/tools/office/index.ts +47 -0
  351. package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
  352. package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
  353. package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
  354. package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
  355. package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
  356. package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
  357. package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
  358. package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
  359. package/packages/core/src/tools/types.ts +39 -0
  360. package/packages/core/src/tools/voice/index.ts +104 -0
  361. package/packages/core/src/tools/web/browser-click.ts +78 -0
  362. package/packages/core/src/tools/web/browser-extract.ts +139 -0
  363. package/packages/core/src/tools/web/browser-navigate.ts +106 -0
  364. package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
  365. package/packages/core/src/tools/web/browser-script.ts +88 -0
  366. package/packages/core/src/tools/web/browser-service.ts +554 -0
  367. package/packages/core/src/tools/web/browser-type.ts +101 -0
  368. package/packages/core/src/tools/web/browser-wait.ts +136 -0
  369. package/packages/core/src/tools/web/index.ts +41 -0
  370. package/packages/core/src/tools/web/web-fetch.ts +78 -0
  371. package/packages/core/src/tools/web/web-search.ts +123 -0
  372. package/packages/core/src/utils/benchmark.ts +80 -0
  373. package/packages/core/src/utils/crypto.ts +73 -0
  374. package/packages/core/src/utils/date.ts +42 -0
  375. package/packages/core/src/utils/index.ts +5 -0
  376. package/packages/core/src/utils/logger.ts +389 -0
  377. package/packages/core/src/utils/retry.ts +70 -0
  378. package/packages/core/src/utils/toon.ts +253 -0
  379. package/packages/core/src/voice/index.ts +643 -0
  380. package/packages/mcp/src/config.ts +13 -0
  381. package/packages/mcp/src/index.ts +1 -0
  382. package/packages/mcp/src/logger.ts +47 -0
  383. package/packages/mcp/src/manager.ts +439 -0
  384. package/packages/mcp/src/transports/index.ts +67 -0
  385. package/packages/mcp/src/transports/sse.ts +238 -0
  386. package/packages/mcp/src/transports/websocket.ts +159 -0
  387. package/packages/skills/src/bundled/agents/agent_spawner/SKILL.md +167 -0
  388. package/packages/skills/src/bundled/agents/code_delegator/SKILL.md +156 -0
  389. package/packages/skills/src/bundled/agents/memory_manager/SKILL.md +143 -0
  390. package/packages/skills/src/bundled/agents/research_and_remember/SKILL.md +139 -0
  391. package/packages/skills/src/bundled/agents/task_orchestrator/SKILL.md +198 -0
  392. package/packages/skills/src/bundled/canvas/a2ui_dashboard/SKILL.md +176 -0
  393. package/packages/skills/src/bundled/canvas/a2ui_form/SKILL.md +202 -0
  394. package/packages/skills/src/bundled/canvas/a2ui_interactive/SKILL.md +206 -0
  395. package/packages/skills/src/bundled/canvas/canvas_dashboard/SKILL.md +146 -0
  396. package/packages/skills/src/bundled/canvas/canvas_interact/SKILL.md +148 -0
  397. package/packages/skills/src/bundled/canvas/canvas_report/SKILL.md +146 -0
  398. package/packages/skills/src/bundled/cli/cli_pipeline/SKILL.md +136 -0
  399. package/packages/skills/src/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  400. package/packages/skills/src/bundled/cron_manager/SKILL.md +188 -0
  401. package/packages/skills/src/bundled/cron_reminder/SKILL.md +112 -0
  402. package/packages/skills/src/bundled/filesystem/file_manager/SKILL.md +118 -0
  403. package/packages/skills/src/bundled/filesystem/file_read_and_summarize/SKILL.md +108 -0
  404. package/packages/skills/src/bundled/filesystem/file_writer/SKILL.md +135 -0
  405. package/packages/skills/src/bundled/meeting/meeting_transcription/SKILL.md +213 -0
  406. package/packages/skills/src/bundled/office/office_document_manager/SKILL.md +262 -0
  407. package/packages/skills/src/bundled/search_knowledge/busqueda_fts5/SKILL.md +74 -0
  408. package/packages/skills/src/bundled/voice/voice_assistant/SKILL.md +174 -0
  409. package/packages/skills/src/bundled/voice/voice_input/SKILL.md +146 -0
  410. package/packages/skills/src/bundled/voice/voice_output/SKILL.md +151 -0
  411. package/packages/skills/src/bundled/web/browser_automate/SKILL.md +120 -0
  412. package/packages/skills/src/bundled/web/browser_scrape/SKILL.md +109 -0
  413. package/packages/skills/src/bundled/web/web_monitor/SKILL.md +127 -0
  414. package/packages/skills/src/bundled/web/web_research/SKILL.md +119 -0
  415. package/packages/skills/src/bundled-data.generated.ts +1964 -0
  416. package/packages/skills/src/index.ts +1 -0
  417. package/packages/skills/src/loader.ts +388 -0
  418. package/dist/ui/assets/AgentCreateForm-DS6yXjGV.js +0 -1
  419. package/dist/ui/assets/AgentDetailPage-Ud552U7_.js +0 -1
  420. package/dist/ui/assets/AgentNewPage-DWWs1P7s.js +0 -1
  421. package/dist/ui/assets/BridgePage-BD93aBKM.js +0 -1
  422. package/dist/ui/assets/CanvasPage-CM35yj0Q.js +0 -33
  423. package/dist/ui/assets/ChannelsPage-CtsWtJdc.js +0 -8
  424. package/dist/ui/assets/DashboardPage-BpiwR5Jg.js +0 -6
  425. package/dist/ui/assets/LogsPage-DqUsG3MW.js +0 -1
  426. package/dist/ui/assets/MeetingPage-C5B8-IzE.js +0 -1
  427. package/dist/ui/assets/ProjectsPage-zic2sjUf.js +0 -1
  428. package/dist/ui/assets/ProvidersPage-BxyIGKzh.js +0 -1
  429. package/dist/ui/assets/SettingsPage-CNFm3nun.js +0 -9
  430. package/dist/ui/assets/SetupPage-RBcjQtv7.js +0 -1
  431. package/dist/ui/assets/accordion-BEVqJf2A.js +0 -1
  432. package/dist/ui/assets/alert-BeGcM0nb.js +0 -1
  433. package/dist/ui/assets/api-q5Ax-vD2.js +0 -63
  434. package/dist/ui/assets/arrow-left-B_jlw8X_.js +0 -1
  435. package/dist/ui/assets/badge-pNhtItyt.js +0 -1
  436. package/dist/ui/assets/chevron-down-B16UVNlu.js +0 -1
  437. package/dist/ui/assets/chevron-left-_8ly7Fz0.js +0 -1
  438. package/dist/ui/assets/chevron-right-yzZLjezG.js +0 -1
  439. package/dist/ui/assets/chevron-up-CxKDQEE5.js +0 -1
  440. package/dist/ui/assets/circle-CFKiO9Ds.js +0 -1
  441. package/dist/ui/assets/circle-check-E2u7ZS2r.js +0 -1
  442. package/dist/ui/assets/circle-minus-1-TZF2pu.js +0 -1
  443. package/dist/ui/assets/circle-x-Cm3Sr-xb.js +0 -1
  444. package/dist/ui/assets/dialog-BaJbZsQF.js +0 -1
  445. package/dist/ui/assets/dist-DB-fE0Co.js +0 -1
  446. package/dist/ui/assets/dropdown-menu-DJoOchfz.js +0 -1
  447. package/dist/ui/assets/gauge-BTpFKuAj.js +0 -1
  448. package/dist/ui/assets/index-BN0875JH.css +0 -2
  449. package/dist/ui/assets/index-D4pdc0Uw.js +0 -54
  450. package/dist/ui/assets/label-C6tqnnKd.js +0 -1
  451. package/dist/ui/assets/loader-circle-CK3qRV3f.js +0 -1
  452. package/dist/ui/assets/pencil-BF2_XX-i.js +0 -1
  453. package/dist/ui/assets/play-DidATMfT.js +0 -1
  454. package/dist/ui/assets/plus-DXm1XDhQ.js +0 -1
  455. package/dist/ui/assets/progress-B1HC9cB_.js +0 -1
  456. package/dist/ui/assets/scroll-area-DKNpYkRA.js +0 -1
  457. package/dist/ui/assets/search-Co6mulZS.js +0 -1
  458. package/dist/ui/assets/switch-7AuR7x2g.js +0 -1
  459. package/dist/ui/assets/terminal-CjZu0OZ0.js +0 -1
  460. package/dist/ui/assets/useProviders-Bxsnav4y.js +0 -1
  461. package/dist/ui/assets/useWebSocketStore-ZCW_Nt1w.js +0 -1
  462. package/dist/ui/assets/x-5cXW_1ZS.js +0 -1
  463. /package/dist/ui/assets/{format-C0EOLKvf.js → format-GVHeOyWI.js} +0 -0
  464. /package/dist/ui/assets/{gateway-url-OqLaEDK-.js → gateway-url-COCbW0IR.js} +0 -0
  465. /package/dist/ui/assets/{utils-_qMjiZaF.js → utils-3pnRFmFe.js} +0 -0
  466. /package/dist/ui/assets/{vendor-router-DhLEd920.js → vendor-router-C9pIYwbJ.js} +0 -0
@@ -0,0 +1,699 @@
1
+ /**
2
+ * Hive CronScheduler
3
+ *
4
+ * Croner-based scheduler for Hive with SQLite persistence.
5
+ * Manages recurring and one-shot cron jobs that execute through the agent pipeline.
6
+ */
7
+
8
+ import { Cron } from "croner";
9
+ import type { Database } from "bun:sqlite";
10
+ import { logger } from "../utils/logger";
11
+ import { notifyTaskCompletion } from "./integration";
12
+ import type {
13
+ CronJob,
14
+ TaskRun,
15
+ CreateCronJobInput,
16
+ UpdateCronJobInput,
17
+ CronJobStatus,
18
+ CronJobExecutionHandler,
19
+ } from "./types";
20
+
21
+ const log = logger.child("CronScheduler");
22
+
23
+ export class CronScheduler {
24
+ private jobs: Map<string, Cron> = new Map();
25
+ private db: Database;
26
+ private handler: CronJobExecutionHandler;
27
+ private cleanupTaskId: string | null = null;
28
+
29
+ constructor(db: Database, handler: CronJobExecutionHandler) {
30
+ this.db = db;
31
+ this.handler = handler;
32
+ }
33
+
34
+ /**
35
+ * Boot the scheduler - load all active jobs from DB and activate them
36
+ */
37
+ boot(): void {
38
+ const tasks = this.db.query(`
39
+ SELECT * FROM cron_jobs WHERE status = 'active'
40
+ `).all() as CronJob[];
41
+
42
+ for (const task of tasks) {
43
+ this.activate(task);
44
+ }
45
+
46
+ log.info(`[boot] Loaded ${tasks.length} active job(s)`);
47
+
48
+ this.ensureCleanupTask();
49
+ }
50
+
51
+ /**
52
+ * Activate a cron job - create or recreate its Croner instance
53
+ */
54
+ activate(task: CronJob): void {
55
+ const existingJob = this.jobs.get(task.id);
56
+ if (existingJob) {
57
+ existingJob.stop();
58
+ this.jobs.delete(task.id);
59
+ log.debug(`[activate] Stopped existing job for task "${task.name}" (${task.id})`);
60
+ }
61
+
62
+ if (task.status === "paused" || task.status === "completed" || task.status === "cancelled") {
63
+ log.debug(`[activate] Skipping job "${task.name}" (${task.id}) - status: ${task.status}`);
64
+ return;
65
+ }
66
+
67
+ // Fix 2A: auto-pause jobs that exceeded the error threshold
68
+ const MAX_ERRORS = 5;
69
+ if (task.error_count >= MAX_ERRORS) {
70
+ this.db.query(
71
+ "UPDATE cron_jobs SET status = 'paused', last_error = ?, updated_at = ? WHERE id = ?"
72
+ ).run(`Auto-paused after ${MAX_ERRORS} consecutive errors`, new Date().toISOString(), task.id);
73
+ log.warn(`[activate] Job "${task.name}" (${task.id}) auto-paused (error_count=${task.error_count})`);
74
+ return;
75
+ }
76
+
77
+ try {
78
+ let pattern: string;
79
+ if (task.task_type === "recurring") {
80
+ if (!task.cron_expression) {
81
+ log.error(`[activate] Job "${task.name}" (${task.id}) is recurring but has no cron_expression`);
82
+ return;
83
+ }
84
+ pattern = task.cron_expression;
85
+ } else {
86
+ if (!task.fire_at) {
87
+ log.error(`[activate] Job "${task.name}" (${task.id}) is one_shot but has no fire_at`);
88
+ return;
89
+ }
90
+ pattern = task.fire_at;
91
+ }
92
+
93
+ try {
94
+ new Cron(pattern);
95
+ } catch (err) {
96
+ log.error(`[activate] Invalid cron pattern "${pattern}" for job "${task.name}": ${(err as Error).message}`);
97
+ return;
98
+ }
99
+
100
+ const options: any = {
101
+ timezone: task.timezone,
102
+ protect: task.protect === 1,
103
+ catch: (error: Error) => this.handleError(task, error),
104
+ name: task.name,
105
+ domAndDow: task.dom_and_dow === 1,
106
+ };
107
+
108
+ if (task.max_runs !== null && task.max_runs !== undefined) {
109
+ options.maxRuns = task.max_runs;
110
+ }
111
+
112
+ if (task.interval_sec !== null && task.interval_sec !== undefined) {
113
+ options.interval = task.interval_sec;
114
+ }
115
+
116
+ if (task.start_at) {
117
+ options.startAt = task.start_at;
118
+ }
119
+
120
+ if (task.stop_at) {
121
+ options.stopAt = task.stop_at;
122
+ }
123
+
124
+ // Fix 1: pass only the ID so execute always reads fresh data from DB
125
+ const cron = new Cron(
126
+ pattern,
127
+ options,
128
+ () => this.execute(task.id)
129
+ );
130
+
131
+ this.jobs.set(task.id, cron);
132
+
133
+ const nextRun = cron.nextRun();
134
+ if (nextRun) {
135
+ const nextRunIso = nextRun.toISOString();
136
+ // Fix 4: also update updated_at when writing next_run_at
137
+ this.db.query(
138
+ "UPDATE cron_jobs SET next_run_at = ?, updated_at = ? WHERE id = ?"
139
+ ).run(nextRunIso, new Date().toISOString(), task.id);
140
+ log.info(`[activate] Job "${task.name}" (${task.id}) scheduled - next: ${nextRunIso}`);
141
+ } else {
142
+ log.warn(`[activate] Job "${task.name}" (${task.id}) has no next run date`);
143
+ }
144
+ } catch (err) {
145
+ log.error(`[activate] Failed to activate job "${task.name}" (${task.id}): ${(err as Error).message}`);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Execute a cron job - run it through the agent pipeline
151
+ */
152
+ private async execute(taskId: string): Promise<void> {
153
+ // Fix 1: read fresh task data from DB to avoid stale closure snapshots
154
+ const task = this.db.query("SELECT * FROM cron_jobs WHERE id = ?").get(taskId) as CronJob | null;
155
+ if (!task) {
156
+ log.warn(`[execute] Job "${taskId}" not found in DB — skipping`);
157
+ return;
158
+ }
159
+
160
+ const runId = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
161
+ const startedAt = new Date().toISOString();
162
+ const startTime = performance.now();
163
+
164
+ log.info(`[execute] Starting job "${task.name}" (${task.id}) run #${runId}`);
165
+
166
+ try {
167
+ this.db.query(`
168
+ INSERT INTO task_runs (id, task_id, status, started_at, payload_snapshot)
169
+ VALUES (?, ?, 'running', ?, ?)
170
+ `).run(runId, task.id, startedAt, task.payload);
171
+ } catch (err) {
172
+ log.error(`[execute] Failed to create task_run record: ${(err as Error).message}`);
173
+ }
174
+
175
+ try {
176
+ const result = await this.handler(task);
177
+ const duration = performance.now() - startTime;
178
+ const finishedAt = new Date().toISOString();
179
+
180
+ if (result.success) {
181
+ this.db.query(`
182
+ UPDATE task_runs
183
+ SET status = 'success', finished_at = ?, duration_ms = ?, agent_response = ?
184
+ WHERE id = ?
185
+ `).run(finishedAt, Math.round(duration), result.response?.slice(0, 1000) || null, runId);
186
+
187
+ this.db.query(`
188
+ UPDATE cron_jobs
189
+ SET run_count = run_count + 1, last_run_at = ?, last_error = NULL
190
+ WHERE id = ?
191
+ `).run(finishedAt, task.id);
192
+
193
+ const job = this.jobs.get(task.id);
194
+ if (job) {
195
+ const nextRun = job.nextRun();
196
+ if (nextRun) {
197
+ this.db.query(
198
+ "UPDATE cron_jobs SET next_run_at = ? WHERE id = ?"
199
+ ).run(nextRun.toISOString(), task.id);
200
+ }
201
+ }
202
+
203
+ await notifyTaskCompletion(task.id, task.name, true, result.response);
204
+
205
+ if (task.task_type === "one_shot") {
206
+ this.db.query(`
207
+ UPDATE cron_jobs
208
+ SET status = 'completed', completed_at = ?
209
+ WHERE id = ?
210
+ `).run(finishedAt, task.id);
211
+ this.deactivate(task.id);
212
+ log.info(`[execute] One-shot job "${task.name}" (${task.id}) completed`);
213
+ } else {
214
+ log.info(`[execute] Job "${task.name}" (${task.id}) completed in ${Math.round(duration)}ms`);
215
+ }
216
+ } else {
217
+ throw new Error(result.error || "Handler reported failure");
218
+ }
219
+ } catch (err) {
220
+ const duration = performance.now() - startTime;
221
+ const finishedAt = new Date().toISOString();
222
+ const errorMessage = (err as Error).message;
223
+
224
+ this.db.query(`
225
+ UPDATE task_runs
226
+ SET status = 'failed', finished_at = ?, duration_ms = ?, error_message = ?
227
+ WHERE id = ?
228
+ `).run(finishedAt, Math.round(duration), errorMessage, runId);
229
+
230
+ this.db.query(`
231
+ UPDATE cron_jobs
232
+ SET error_count = error_count + 1, last_error = ?
233
+ WHERE id = ?
234
+ `).run(errorMessage, task.id);
235
+
236
+ log.error(`[execute] Job "${task.name}" (${task.id}) failed: ${errorMessage}`);
237
+
238
+ // Fix 2B: auto-pause if error threshold reached
239
+ const MAX_ERRORS = 5;
240
+ const updated = this.db.query(
241
+ "SELECT error_count FROM cron_jobs WHERE id = ?"
242
+ ).get(task.id) as { error_count: number } | null;
243
+
244
+ if (updated && updated.error_count >= MAX_ERRORS) {
245
+ this.db.query(
246
+ "UPDATE cron_jobs SET status = 'paused', updated_at = ? WHERE id = ?"
247
+ ).run(new Date().toISOString(), task.id);
248
+ this.deactivate(task.id);
249
+ log.warn(`[execute] Job "${task.name}" (${task.id}) auto-paused after ${MAX_ERRORS} errors`);
250
+ }
251
+
252
+ await notifyTaskCompletion(task.id, task.name, false, undefined, errorMessage);
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Handle errors from Croner
258
+ */
259
+ private handleError(task: CronJob, error: Error): void {
260
+ log.error(`[error] Job "${task.name}" (${task.id}) error: ${error.message}`);
261
+
262
+ // Fix 3: record Croner-level errors in task_runs for full history
263
+ const runId = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
264
+ const now = new Date().toISOString();
265
+ try {
266
+ this.db.query(`
267
+ INSERT INTO task_runs (id, task_id, status, started_at, finished_at, duration_ms, error_message)
268
+ VALUES (?, ?, 'failed', ?, ?, 0, ?)
269
+ `).run(runId, task.id, now, now, error.message);
270
+ } catch (e) {
271
+ log.warn(`[handleError] Failed to insert task_run: ${(e as Error).message}`);
272
+ }
273
+
274
+ this.db.query(`
275
+ UPDATE cron_jobs
276
+ SET error_count = error_count + 1, last_error = ?
277
+ WHERE id = ?
278
+ `).run(error.message, task.id);
279
+ }
280
+
281
+ /**
282
+ * Pause a cron job
283
+ */
284
+ pause(taskId: string): boolean {
285
+ const job = this.jobs.get(taskId);
286
+ if (job) {
287
+ job.pause();
288
+ }
289
+
290
+ const result = this.db.query(
291
+ "UPDATE cron_jobs SET status = 'paused' WHERE id = ?"
292
+ ).run(taskId);
293
+
294
+ if (result.changes > 0) {
295
+ log.info(`[pause] Job "${taskId}" paused`);
296
+ return true;
297
+ }
298
+
299
+ log.warn(`[pause] Job "${taskId}" not found`);
300
+ return false;
301
+ }
302
+
303
+ /**
304
+ * Resume a paused cron job
305
+ */
306
+ resume(taskId: string): boolean {
307
+ const task = this.db.query(
308
+ "SELECT * FROM cron_jobs WHERE id = ?"
309
+ ).get(taskId) as CronJob | undefined;
310
+
311
+ if (!task) {
312
+ log.warn(`[resume] Job "${taskId}" not found`);
313
+ return false;
314
+ }
315
+
316
+ this.db.query(
317
+ "UPDATE cron_jobs SET status = 'active' WHERE id = ?"
318
+ ).run(taskId);
319
+
320
+ this.activate(task);
321
+ log.info(`[resume] Job "${taskId}" resumed`);
322
+ return true;
323
+ }
324
+
325
+ /**
326
+ * Deactivate a cron job - stop Croner instance but keep in DB
327
+ */
328
+ deactivate(taskId: string): void {
329
+ const job = this.jobs.get(taskId);
330
+ if (job) {
331
+ job.stop();
332
+ this.jobs.delete(taskId);
333
+ log.debug(`[deactivate] Job "${taskId}" deactivated`);
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Delete a cron job - deactivate and remove from DB
339
+ */
340
+ delete(taskId: string): boolean {
341
+ this.deactivate(taskId);
342
+
343
+ const result = this.db.query(
344
+ "DELETE FROM cron_jobs WHERE id = ?"
345
+ ).run(taskId);
346
+
347
+ if (result.changes > 0) {
348
+ log.info(`[delete] Job "${taskId}" deleted`);
349
+ return true;
350
+ }
351
+
352
+ log.warn(`[delete] Job "${taskId}" not found`);
353
+ return false;
354
+ }
355
+
356
+ /**
357
+ * Create a new cron job
358
+ */
359
+ create(input: CreateCronJobInput): { id: string; nextRun?: string } {
360
+ const id = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
361
+ const now = new Date().toISOString();
362
+
363
+ if (input.task_type === "recurring") {
364
+ if (!input.cron_expression) {
365
+ throw new Error("recurring task requires cron_expression");
366
+ }
367
+ try {
368
+ new Cron(input.cron_expression);
369
+ } catch (err) {
370
+ throw new Error(`Invalid cron expression: ${(err as Error).message}`);
371
+ }
372
+ }
373
+
374
+ if (input.task_type === "one_shot") {
375
+ if (!input.fire_at) {
376
+ throw new Error("one_shot task requires fire_at");
377
+ }
378
+ const fireAt = new Date(input.fire_at);
379
+ if (fireAt.getTime() <= Date.now()) {
380
+ throw new Error("fire_at must be in the future");
381
+ }
382
+ }
383
+
384
+ try {
385
+ new Intl.DateTimeFormat(undefined, { timeZone: input.timezone });
386
+ } catch (err) {
387
+ throw new Error(`Invalid timezone: ${input.timezone}`);
388
+ }
389
+
390
+ const payloadJson = input.payload ? JSON.stringify(input.payload) : "{}";
391
+ try {
392
+ JSON.parse(payloadJson);
393
+ } catch (err) {
394
+ throw new Error("Invalid payload JSON");
395
+ }
396
+
397
+ this.db.query(`
398
+ INSERT INTO cron_jobs (
399
+ id, name, task, task_type, cron_expression, fire_at, timezone,
400
+ start_at, stop_at, dom_and_dow,
401
+ max_runs, protect, interval_sec, agent_id, channel, payload, tool_name,
402
+ status, created_at, updated_at
403
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?)
404
+ `).run(
405
+ id,
406
+ input.name,
407
+ input.task,
408
+ input.task_type,
409
+ input.cron_expression || null,
410
+ input.fire_at || null,
411
+ input.timezone,
412
+ input.start_at || null,
413
+ input.stop_at || null,
414
+ input.dom_and_dow ? 1 : 0,
415
+ input.max_runs || null,
416
+ input.protect !== false ? 1 : 0,
417
+ input.interval_sec || null,
418
+ input.agent_id || null,
419
+ input.channel || "system",
420
+ payloadJson,
421
+ input.tool_name || null,
422
+ now,
423
+ now
424
+ );
425
+
426
+ const task = this.db.query(
427
+ "SELECT * FROM cron_jobs WHERE id = ?"
428
+ ).get(id) as CronJob;
429
+
430
+ this.activate(task);
431
+
432
+ const job = this.jobs.get(id);
433
+ const nextRun = job?.nextRun()?.toISOString();
434
+
435
+ log.info(`[create] Job "${input.name}" (${id}) created`);
436
+
437
+ return { id, nextRun };
438
+ }
439
+
440
+ /**
441
+ * Update an existing cron job
442
+ */
443
+ update(taskId: string, changes: UpdateCronJobInput): boolean {
444
+ const task = this.db.query(
445
+ "SELECT * FROM cron_jobs WHERE id = ?"
446
+ ).get(taskId) as CronJob | undefined;
447
+
448
+ if (!task) {
449
+ log.warn(`[update] Job "${taskId}" not found`);
450
+ return false;
451
+ }
452
+
453
+ const fields: string[] = [];
454
+ const values: any[] = [];
455
+
456
+ if (changes.name !== undefined) {
457
+ fields.push("name = ?");
458
+ values.push(changes.name);
459
+ }
460
+ if (changes.task !== undefined) {
461
+ fields.push("task = ?");
462
+ values.push(changes.task);
463
+ }
464
+ if (changes.task_type !== undefined) {
465
+ fields.push("task_type = ?");
466
+ values.push(changes.task_type);
467
+ }
468
+ if (changes.cron_expression !== undefined) {
469
+ fields.push("cron_expression = ?");
470
+ values.push(changes.cron_expression);
471
+ }
472
+ if (changes.fire_at !== undefined) {
473
+ fields.push("fire_at = ?");
474
+ values.push(changes.fire_at);
475
+ }
476
+ if (changes.timezone !== undefined) {
477
+ fields.push("timezone = ?");
478
+ values.push(changes.timezone);
479
+ }
480
+ if (changes.start_at !== undefined) {
481
+ fields.push("start_at = ?");
482
+ values.push(changes.start_at);
483
+ }
484
+ if (changes.stop_at !== undefined) {
485
+ fields.push("stop_at = ?");
486
+ values.push(changes.stop_at);
487
+ }
488
+ if (changes.dom_and_dow !== undefined) {
489
+ fields.push("dom_and_dow = ?");
490
+ values.push(changes.dom_and_dow ? 1 : 0);
491
+ }
492
+ if (changes.agent_id !== undefined) {
493
+ fields.push("agent_id = ?");
494
+ values.push(changes.agent_id);
495
+ }
496
+ if (changes.channel !== undefined) {
497
+ fields.push("channel = ?");
498
+ values.push(changes.channel);
499
+ }
500
+ if (changes.payload !== undefined) {
501
+ fields.push("payload = ?");
502
+ values.push(JSON.stringify(changes.payload));
503
+ }
504
+ if (changes.tool_name !== undefined) {
505
+ fields.push("tool_name = ?");
506
+ values.push(changes.tool_name);
507
+ }
508
+ if (changes.max_runs !== undefined) {
509
+ fields.push("max_runs = ?");
510
+ values.push(changes.max_runs);
511
+ }
512
+ if (changes.protect !== undefined) {
513
+ fields.push("protect = ?");
514
+ values.push(changes.protect ? 1 : 0);
515
+ }
516
+ if (changes.interval_sec !== undefined) {
517
+ fields.push("interval_sec = ?");
518
+ values.push(changes.interval_sec);
519
+ }
520
+ if (changes.status !== undefined) {
521
+ fields.push("status = ?");
522
+ values.push(changes.status);
523
+ }
524
+
525
+ if (fields.length === 0) {
526
+ return true;
527
+ }
528
+
529
+ values.push(taskId);
530
+ this.db.query(`UPDATE cron_jobs SET ${fields.join(", ")} WHERE id = ?`).run(...values);
531
+
532
+ const updatedTask = this.db.query(
533
+ "SELECT * FROM cron_jobs WHERE id = ?"
534
+ ).get(taskId) as CronJob;
535
+
536
+ this.activate(updatedTask);
537
+
538
+ log.info(`[update] Job "${taskId}" updated`);
539
+ return true;
540
+ }
541
+
542
+ /**
543
+ * Get status of all cron jobs
544
+ */
545
+ getStatus(): CronJobStatus[] {
546
+ const tasks = this.db.query(
547
+ "SELECT id, name, status FROM cron_jobs ORDER BY id"
548
+ ).all() as Array<{ id: string; name: string; status: string }>;
549
+
550
+ return tasks.map((task) => {
551
+ const job = this.jobs.get(task.id);
552
+ return {
553
+ id: task.id,
554
+ name: task.name,
555
+ nextRun: job?.nextRun() || null,
556
+ isBusy: job?.isBusy() || false,
557
+ status: task.status as any,
558
+ };
559
+ });
560
+ }
561
+
562
+ /**
563
+ * Manually trigger a cron job execution
564
+ */
565
+ trigger(taskId: string): boolean {
566
+ const task = this.db.query(
567
+ "SELECT * FROM cron_jobs WHERE id = ?"
568
+ ).get(taskId) as CronJob | undefined;
569
+
570
+ if (!task) {
571
+ log.warn(`[trigger] Job "${taskId}" not found`);
572
+ return false;
573
+ }
574
+
575
+ const job = this.jobs.get(taskId);
576
+ if (!job) {
577
+ log.warn(`[trigger] Job "${taskId}" has no active job`);
578
+ return false;
579
+ }
580
+
581
+ job.trigger();
582
+ log.info(`[trigger] Job "${taskId}" manually triggered`);
583
+ return true;
584
+ }
585
+
586
+ /**
587
+ * Shutdown the scheduler - stop all jobs
588
+ */
589
+ shutdown(): void {
590
+ for (const [id, job] of this.jobs.entries()) {
591
+ job.stop();
592
+ }
593
+ this.jobs.clear();
594
+ log.info("[shutdown] All jobs stopped");
595
+ }
596
+
597
+ /**
598
+ * Ensure the cleanup job exists
599
+ */
600
+ private ensureCleanupTask(): void {
601
+ const existing = this.db.query(
602
+ "SELECT id FROM cron_jobs WHERE name = '_hive_cleanup_runs'"
603
+ ).get() as { id: string } | undefined;
604
+
605
+ if (existing) {
606
+ this.cleanupTaskId = existing.id;
607
+ log.debug("[ensureCleanupTask] Cleanup job already exists");
608
+ return;
609
+ }
610
+
611
+ try {
612
+ const result = this.create({
613
+ name: "_hive_cleanup_runs",
614
+ task: "Automatic cleanup of old task_runs and completed one_shot jobs",
615
+ task_type: "recurring",
616
+ cron_expression: "0 4 * * *",
617
+ timezone: "UTC",
618
+ payload: { _internal: true, action: "cleanup" },
619
+ protect: true,
620
+ });
621
+
622
+ this.cleanupTaskId = result.id;
623
+ log.info("[ensureCleanupTask] Cleanup job created");
624
+ } catch (err) {
625
+ log.error(`[ensureCleanupTask] Failed to create cleanup job: ${(err as Error).message}`);
626
+ }
627
+ }
628
+
629
+ /**
630
+ * Run cleanup - called by the internal cleanup job
631
+ */
632
+ runCleanup(): void {
633
+ const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
634
+ this.db.query(`
635
+ DELETE FROM task_runs
636
+ WHERE status IN ('success', 'failed') AND started_at < ?
637
+ `).run(thirtyDaysAgo);
638
+
639
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
640
+ this.db.query(`
641
+ UPDATE cron_jobs
642
+ SET status = 'cancelled'
643
+ WHERE task_type = 'one_shot' AND status = 'completed' AND completed_at < ?
644
+ `).run(sevenDaysAgo);
645
+
646
+ const tasks = this.db.query(`
647
+ SELECT DISTINCT task_id FROM task_runs
648
+ `).all() as { task_id: string }[];
649
+
650
+ for (const { task_id } of tasks) {
651
+ this.db.query(`
652
+ DELETE FROM task_runs
653
+ WHERE task_id = ? AND id NOT IN (
654
+ SELECT id FROM task_runs
655
+ WHERE task_id = ?
656
+ ORDER BY started_at DESC
657
+ LIMIT 1000
658
+ )
659
+ `).run(task_id, task_id);
660
+ }
661
+
662
+ log.info("[runCleanup] Cleanup completed");
663
+ }
664
+
665
+ /**
666
+ * Get task run history
667
+ */
668
+ getHistory(taskId: string, limit = 50): TaskRun[] {
669
+ return this.db.query(`
670
+ SELECT * FROM task_runs
671
+ WHERE task_id = ?
672
+ ORDER BY started_at DESC
673
+ LIMIT ?
674
+ `).all(taskId, limit) as TaskRun[];
675
+ }
676
+
677
+ /**
678
+ * Get a single cron job by ID
679
+ */
680
+ getTask(taskId: string): CronJob | null {
681
+ return this.db.query(
682
+ "SELECT * FROM cron_jobs WHERE id = ?"
683
+ ).get(taskId) as CronJob | null;
684
+ }
685
+
686
+ /**
687
+ * List all cron jobs
688
+ */
689
+ listTasks(status?: string): CronJob[] {
690
+ if (status) {
691
+ return this.db.query(
692
+ "SELECT * FROM cron_jobs WHERE status = ? ORDER BY next_run_at"
693
+ ).all(status) as CronJob[];
694
+ }
695
+ return this.db.query(
696
+ "SELECT * FROM cron_jobs ORDER BY next_run_at"
697
+ ).all() as CronJob[];
698
+ }
699
+ }