@johpaz/hive-agents 0.0.35 → 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 (440) hide show
  1. package/README.md +64 -39
  2. package/dist/hive.js +3127 -3104
  3. package/dist/ui/assets/{AgentCreateForm-B4eK7efF.js → AgentCreateForm-tJZv9FZC.js} +1 -1
  4. package/dist/ui/assets/{AgentDetailPage-BD2uoJWk.js → AgentDetailPage-Du-mRcAX.js} +1 -1
  5. package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  6. package/dist/ui/assets/{AgentsPage-4JUZXvkA.js → AgentsPage-YvSgWRiw.js} +6 -6
  7. package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
  8. package/dist/ui/assets/{ChannelsPage-BUn7-nhV.js → ChannelsPage-BdBXWHjj.js} +1 -1
  9. package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
  10. package/dist/ui/assets/{LoginPage-C8j_urUD.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-Drh-sJPN.js → NotFound-BMeQSGcG.js} +1 -1
  14. package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  15. package/dist/ui/assets/{RecoverPage-DNb1Pr8h.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-R-YOwA4F.js → WebChatPage-CVRcKept.js} +2 -2
  19. package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
  20. package/dist/ui/assets/{alert-U8FsgWi7.js → alert-C-NE-P3s.js} +1 -1
  21. package/dist/ui/assets/{alert-dialog-CRdMkkmk.js → alert-dialog-C5mzbHdP.js} +1 -1
  22. package/dist/ui/assets/{badge-Cli1jnH5.js → badge-ChpACfWO.js} +1 -1
  23. package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
  24. package/dist/ui/assets/{dialog-DQ3s-LuO.js → dialog-QnZ0ad8O.js} +1 -1
  25. package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
  26. package/dist/ui/assets/{es-DcMjrpbA.js → es-NQNoaWDx.js} +1 -1
  27. package/dist/ui/assets/index-B2fCYtTS.css +2 -0
  28. package/dist/ui/assets/index-DMCjjdqf.js +116 -0
  29. package/dist/ui/assets/{label-0BvGVXvZ.js → label-D2H1IR_J.js} +1 -1
  30. package/dist/ui/assets/progress-BherYzY6.js +1 -0
  31. package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
  32. package/dist/ui/assets/{slider-D47dOrRa.js → slider-CsiUDxc3.js} +1 -1
  33. package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
  34. package/dist/ui/assets/{table-DhowbNxQ.js → table-CSc8ubon.js} +1 -1
  35. package/dist/ui/assets/terminal-DN38Q456.js +1 -0
  36. package/dist/ui/assets/useProviders-C6_QHsEi.js +1 -0
  37. package/dist/ui/assets/{vendor-radix-JY4ncZrD.js → vendor-radix-cw1bQaVC.js} +4 -4
  38. package/dist/ui/assets/{vendor-react-CscwQerf.js → vendor-react-D4s9E-zj.js} +1 -1
  39. package/dist/ui/dist/assets/AgentCreateForm-tJZv9FZC.js +1 -0
  40. package/dist/ui/dist/assets/AgentDetailPage-Du-mRcAX.js +1 -0
  41. package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  42. package/dist/ui/dist/assets/AgentsPage-YvSgWRiw.js +10 -0
  43. package/dist/ui/dist/assets/CanvasPage-DtMwGvxf.js +33 -0
  44. package/dist/ui/dist/assets/ChannelsPage-BdBXWHjj.js +8 -0
  45. package/dist/ui/dist/assets/DashboardPage-ghl1ZguH.js +6 -0
  46. package/dist/ui/dist/assets/LoginPage-CAmSI9Vy.js +1 -0
  47. package/dist/ui/dist/assets/LogsPage-DAPBHkwK.js +1 -0
  48. package/dist/ui/dist/assets/MeetingPage-WjjGOqqU.js +1 -0
  49. package/dist/ui/dist/assets/NotFound-BMeQSGcG.js +1 -0
  50. package/dist/ui/dist/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  51. package/dist/ui/dist/assets/RecoverPage-DpW3l-yv.js +1 -0
  52. package/dist/ui/dist/assets/SettingsPage-DBJ7_E6C.js +9 -0
  53. package/dist/ui/dist/assets/SetupPage-DKmLVUaj.js +1 -0
  54. package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +16 -0
  55. package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +1 -0
  56. package/dist/ui/dist/assets/activity-c3pNngT_.js +1 -0
  57. package/dist/ui/dist/assets/alert-C-NE-P3s.js +1 -0
  58. package/dist/ui/dist/assets/alert-dialog-C5mzbHdP.js +1 -0
  59. package/dist/ui/dist/assets/arrow-left-CBcbX5EZ.js +1 -0
  60. package/dist/ui/dist/assets/badge-ChpACfWO.js +1 -0
  61. package/dist/ui/dist/assets/calendar-B-KZ9RQO.js +1 -0
  62. package/dist/ui/dist/assets/card-CNf6BS2e.js +1 -0
  63. package/dist/ui/dist/assets/chevron-left-D4U-5A27.js +1 -0
  64. package/dist/ui/dist/assets/chevron-right-CR4Skrf3.js +1 -0
  65. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +1 -0
  66. package/dist/ui/dist/assets/circle-alert-CyHDwUj8.js +1 -0
  67. package/dist/ui/dist/assets/circle-check-Bb54Ebmu.js +1 -0
  68. package/dist/ui/dist/assets/cpu-Cdgc_B1K.js +1 -0
  69. package/dist/ui/dist/assets/dialog-QnZ0ad8O.js +1 -0
  70. package/dist/ui/dist/assets/download-C3ifGMjJ.js +1 -0
  71. package/dist/ui/dist/assets/dropdown-menu-BK-CO3Od.js +1 -0
  72. package/dist/ui/dist/assets/es-NQNoaWDx.js +1 -0
  73. package/dist/ui/dist/assets/external-link-BvxYeTP1.js +1 -0
  74. package/dist/ui/dist/assets/eye-DqNTU_GD.js +1 -0
  75. package/dist/ui/dist/assets/file-text-BT_9S9SM.js +1 -0
  76. package/dist/ui/dist/assets/folder-open-BhH8y9ac.js +1 -0
  77. package/dist/ui/dist/assets/format-GVHeOyWI.js +1 -0
  78. package/dist/ui/dist/assets/gateway-url-COCbW0IR.js +1 -0
  79. package/dist/ui/dist/assets/gauge-D_TMa4i9.js +1 -0
  80. package/dist/ui/dist/assets/globe-DeCQTCDJ.js +1 -0
  81. package/dist/ui/dist/assets/hexagon-DsGOUl-H.js +1 -0
  82. package/dist/ui/dist/assets/history-BSG-Ypqf.js +1 -0
  83. package/dist/ui/dist/assets/index-B2fCYtTS.css +2 -0
  84. package/dist/ui/dist/assets/index-DMCjjdqf.js +116 -0
  85. package/dist/ui/dist/assets/info-NwLoa2Mj.js +1 -0
  86. package/dist/ui/dist/assets/key-3EP0dhkT.js +1 -0
  87. package/dist/ui/dist/assets/label-D2H1IR_J.js +1 -0
  88. package/dist/ui/dist/assets/loader-circle-CZNax6kS.js +1 -0
  89. package/dist/ui/dist/assets/lock-Ei1_J-Nq.js +1 -0
  90. package/dist/ui/dist/assets/pause-BUqah9Bi.js +1 -0
  91. package/dist/ui/dist/assets/play-NcZ4swwL.js +1 -0
  92. package/dist/ui/dist/assets/plus-CX1xyhp5.js +1 -0
  93. package/dist/ui/dist/assets/progress-BherYzY6.js +1 -0
  94. package/dist/ui/dist/assets/refresh-cw-DaYdjQFk.js +1 -0
  95. package/dist/ui/dist/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
  96. package/dist/ui/dist/assets/save-CUdYyHNy.js +1 -0
  97. package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +1 -0
  98. package/dist/ui/dist/assets/send-B0H5SEIE.js +1 -0
  99. package/dist/ui/dist/assets/settings-Ds4SqD8s.js +1 -0
  100. package/dist/ui/dist/assets/slider-CsiUDxc3.js +14 -0
  101. package/dist/ui/dist/assets/sparkles-yUEb-7oH.js +1 -0
  102. package/dist/ui/dist/assets/square-BD81nFtN.js +1 -0
  103. package/dist/ui/dist/assets/switch-BDwN8RYV.js +1 -0
  104. package/dist/ui/dist/assets/table-CSc8ubon.js +1 -0
  105. package/dist/ui/dist/assets/terminal-DN38Q456.js +1 -0
  106. package/dist/ui/dist/assets/textarea-CXgXWKrT.js +1 -0
  107. package/dist/ui/dist/assets/trash-2-CNjMkoq6.js +1 -0
  108. package/dist/ui/dist/assets/triangle-alert-C9Y8Ub4X.js +1 -0
  109. package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +1 -0
  110. package/dist/ui/dist/assets/utils-3pnRFmFe.js +1 -0
  111. package/dist/ui/dist/assets/vendor-charts-Bu2lyBKP.js +65 -0
  112. package/dist/ui/dist/assets/vendor-query-DsWPbQdG.js +1 -0
  113. package/dist/ui/dist/assets/vendor-radix-cw1bQaVC.js +63 -0
  114. package/dist/ui/dist/assets/vendor-react-D4s9E-zj.js +1 -0
  115. package/dist/ui/dist/assets/vendor-router-C9pIYwbJ.js +3 -0
  116. package/dist/ui/dist/assets/volume-2-CeSXNDv4.js +1 -0
  117. package/dist/ui/dist/assets/zap-hlXjpSeA.js +1 -0
  118. package/dist/ui/dist/favicon.ico +0 -0
  119. package/dist/ui/dist/index.html +40 -0
  120. package/dist/ui/dist/placeholder.svg +1 -0
  121. package/dist/ui/index.html +6 -6
  122. package/package.json +137 -13
  123. package/packages/cli/src/adapters/binary.ts +461 -0
  124. package/packages/cli/src/adapters/bun-global.ts +378 -0
  125. package/packages/cli/src/adapters/config.ts +314 -0
  126. package/packages/cli/src/adapters/docker.ts +308 -0
  127. package/packages/cli/src/adapters/factory.ts +168 -0
  128. package/packages/cli/src/adapters/index.ts +80 -0
  129. package/packages/cli/src/adapters/types.ts +218 -0
  130. package/packages/cli/src/commands/agent-run.ts +168 -0
  131. package/packages/cli/src/commands/agents.ts +398 -0
  132. package/packages/cli/src/commands/chat.ts +142 -0
  133. package/packages/cli/src/commands/config.ts +49 -0
  134. package/packages/cli/src/commands/cron.ts +487 -0
  135. package/packages/cli/src/commands/dev.ts +58 -0
  136. package/packages/cli/src/commands/doctor.ts +320 -0
  137. package/packages/cli/src/commands/gateway.ts +719 -0
  138. package/packages/cli/src/commands/logs.ts +57 -0
  139. package/packages/cli/src/commands/mcp.ts +175 -0
  140. package/packages/cli/src/commands/message.ts +77 -0
  141. package/packages/cli/src/commands/migrate.ts +90 -0
  142. package/packages/cli/src/commands/onboard.ts +1656 -0
  143. package/packages/cli/src/commands/security.ts +144 -0
  144. package/packages/cli/src/commands/service.ts +50 -0
  145. package/packages/cli/src/commands/sessions.ts +116 -0
  146. package/packages/cli/src/commands/skills.ts +215 -0
  147. package/packages/cli/src/commands/update.ts +203 -0
  148. package/packages/cli/src/index.ts +210 -0
  149. package/packages/cli/src/ui-bundle.generated.ts +3 -0
  150. package/packages/cli/src/utils/token.ts +6 -0
  151. package/packages/core/src/agent/agent-loop.ts +691 -0
  152. package/packages/core/src/agent/compaction.ts +240 -0
  153. package/packages/core/src/agent/context-compiler.ts +467 -0
  154. package/packages/core/src/agent/context-guard.ts +91 -0
  155. package/packages/core/src/agent/conversation-store.ts +244 -0
  156. package/packages/core/src/agent/curator.ts +158 -0
  157. package/packages/core/src/agent/hooks.ts +166 -0
  158. package/packages/core/src/agent/llm-client.ts +167 -0
  159. package/packages/core/src/agent/llm-providers/anthropic.ts +212 -0
  160. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  161. package/packages/core/src/agent/llm-providers/gemini.ts +215 -0
  162. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  163. package/packages/core/src/agent/llm-providers/interface.ts +195 -0
  164. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  165. package/packages/core/src/agent/llm-providers/local-llama.ts +37 -0
  166. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  167. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  168. package/packages/core/src/agent/llm-providers/ollama.ts +175 -0
  169. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +379 -0
  170. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  171. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  172. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  173. package/packages/core/src/agent/native-tools.ts +31 -0
  174. package/packages/core/src/agent/playbook-selector.ts +147 -0
  175. package/packages/core/src/agent/prompt-builder.ts +169 -0
  176. package/packages/core/src/agent/providers/index.ts +204 -0
  177. package/packages/core/src/agent/providers.ts +1 -0
  178. package/packages/core/src/agent/reflector.ts +200 -0
  179. package/packages/core/src/agent/service.ts +267 -0
  180. package/packages/core/src/agent/skill-selector.ts +479 -0
  181. package/packages/core/src/agent/stuck-loop.ts +133 -0
  182. package/packages/core/src/agent/tool-selector.ts +569 -0
  183. package/packages/core/src/agent/tracer.ts +100 -0
  184. package/packages/core/src/auth/auth.ts +108 -0
  185. package/packages/core/src/auth/index.ts +1 -0
  186. package/packages/core/src/canvas/a2ui-tools.ts +255 -0
  187. package/packages/core/src/canvas/canvas-manager.ts +390 -0
  188. package/packages/core/src/canvas/canvas-tools.ts +448 -0
  189. package/packages/core/src/canvas/emitter.ts +149 -0
  190. package/packages/core/src/canvas/index.ts +3 -0
  191. package/packages/core/src/channels/base.ts +154 -0
  192. package/packages/core/src/channels/discord.ts +273 -0
  193. package/packages/core/src/channels/index.ts +7 -0
  194. package/packages/core/src/channels/manager.ts +450 -0
  195. package/packages/core/src/channels/slack.ts +323 -0
  196. package/packages/core/src/channels/telegram.ts +612 -0
  197. package/packages/core/src/channels/webchat.ts +139 -0
  198. package/packages/core/src/channels/whatsapp.ts +548 -0
  199. package/packages/core/src/config/index.ts +12 -0
  200. package/packages/core/src/config/loader.ts +569 -0
  201. package/packages/core/src/events/agent-bus.ts +460 -0
  202. package/packages/core/src/events/event-bus.ts +169 -0
  203. package/packages/core/src/gateway/channel-notify.ts +64 -0
  204. package/packages/core/src/gateway/helpers/cors.ts +32 -0
  205. package/packages/core/src/gateway/helpers/index.ts +4 -0
  206. package/packages/core/src/gateway/helpers/narration.ts +57 -0
  207. package/packages/core/src/gateway/helpers/path.ts +13 -0
  208. package/packages/core/src/gateway/helpers/redact.ts +61 -0
  209. package/packages/core/src/gateway/index.ts +5 -0
  210. package/packages/core/src/gateway/initializer.ts +363 -0
  211. package/packages/core/src/gateway/lane-queue.ts +169 -0
  212. package/packages/core/src/gateway/llm-local/client.ts +94 -0
  213. package/packages/core/src/gateway/llm-local/detector.ts +321 -0
  214. package/packages/core/src/gateway/llm-local/downloader.ts +216 -0
  215. package/packages/core/src/gateway/llm-local/index.ts +34 -0
  216. package/packages/core/src/gateway/llm-local/manager.ts +186 -0
  217. package/packages/core/src/gateway/llm-local/models.ts +149 -0
  218. package/packages/core/src/gateway/llm-local/server.ts +179 -0
  219. package/packages/core/src/gateway/resolver.ts +108 -0
  220. package/packages/core/src/gateway/router.ts +124 -0
  221. package/packages/core/src/gateway/routes/agents.ts +210 -0
  222. package/packages/core/src/gateway/routes/auth.ts +244 -0
  223. package/packages/core/src/gateway/routes/channels.ts +484 -0
  224. package/packages/core/src/gateway/routes/chat.ts +241 -0
  225. package/packages/core/src/gateway/routes/config.ts +12 -0
  226. package/packages/core/src/gateway/routes/cron-api.ts +544 -0
  227. package/packages/core/src/gateway/routes/ethics.ts +46 -0
  228. package/packages/core/src/gateway/routes/llm-local.ts +271 -0
  229. package/packages/core/src/gateway/routes/mcp.ts +319 -0
  230. package/packages/core/src/gateway/routes/meeting.ts +232 -0
  231. package/packages/core/src/gateway/routes/models.ts +163 -0
  232. package/packages/core/src/gateway/routes/multimodal.ts +93 -0
  233. package/packages/core/src/gateway/routes/providers.ts +220 -0
  234. package/packages/core/src/gateway/routes/setup.ts +441 -0
  235. package/packages/core/src/gateway/routes/skills.ts +115 -0
  236. package/packages/core/src/gateway/routes/system.ts +469 -0
  237. package/packages/core/src/gateway/routes/tasks.ts +44 -0
  238. package/packages/core/src/gateway/routes/tools.ts +59 -0
  239. package/packages/core/src/gateway/routes/tts-local.ts +388 -0
  240. package/packages/core/src/gateway/routes/users.ts +122 -0
  241. package/packages/core/src/gateway/routes/voice.ts +189 -0
  242. package/packages/core/src/gateway/routes/workspace.ts +281 -0
  243. package/packages/core/src/gateway/server.ts +2744 -0
  244. package/packages/core/src/gateway/session.ts +95 -0
  245. package/packages/core/src/gateway/slash-commands.ts +207 -0
  246. package/packages/core/src/gateway/tts/README.md +94 -0
  247. package/packages/core/src/gateway/tts/package.json +25 -0
  248. package/packages/core/src/gateway/tts/src/client.ts +59 -0
  249. package/packages/core/src/gateway/tts/src/detect.ts +42 -0
  250. package/packages/core/src/gateway/tts/src/index.ts +15 -0
  251. package/packages/core/src/gateway/tts/src/install.ts +129 -0
  252. package/packages/core/src/gateway/tts/src/models.ts +50 -0
  253. package/packages/core/src/gateway/tts/src/server.ts +252 -0
  254. package/packages/core/src/gateway/tts/voices/.gitkeep +0 -0
  255. package/packages/core/src/heartbeat/index.ts +157 -0
  256. package/packages/core/src/index.ts +56 -0
  257. package/packages/core/src/mcp/hot-reload.ts +148 -0
  258. package/packages/core/src/mcp/singleton.ts +21 -0
  259. package/packages/core/src/mcp/tool-sync.ts +176 -0
  260. package/packages/core/src/multimodal/index.ts +2 -0
  261. package/packages/core/src/multimodal/types.ts +28 -0
  262. package/packages/core/src/multimodal/vision-service.ts +283 -0
  263. package/packages/core/src/plugins/api.ts +128 -0
  264. package/packages/core/src/plugins/index.ts +2 -0
  265. package/packages/core/src/plugins/loader.ts +365 -0
  266. package/packages/core/src/resilience/circuit-breaker.ts +225 -0
  267. package/packages/core/src/scheduler/CronScheduler.ts +699 -0
  268. package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
  269. package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
  270. package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
  271. package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
  272. package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
  273. package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
  274. package/packages/core/src/scheduler/dag/errors.ts +37 -0
  275. package/packages/core/src/scheduler/dag/index.ts +26 -0
  276. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
  277. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
  278. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
  279. package/packages/core/src/scheduler/index.ts +22 -0
  280. package/packages/core/src/scheduler/integration.ts +237 -0
  281. package/packages/core/src/scheduler/types.ts +164 -0
  282. package/packages/core/src/security/google-chat.ts +269 -0
  283. package/packages/core/src/security/index.ts +192 -0
  284. package/packages/core/src/security/pairing.ts +250 -0
  285. package/packages/core/src/security/rate-limit.ts +270 -0
  286. package/packages/core/src/security/signal.ts +321 -0
  287. package/packages/core/src/state/store.ts +312 -0
  288. package/packages/core/src/storage/crypto.ts +197 -0
  289. package/packages/core/src/storage/migrate.ts +147 -0
  290. package/packages/core/src/storage/onboarding.ts +1506 -0
  291. package/packages/core/src/storage/schema.ts +666 -0
  292. package/packages/core/src/storage/seed.ts +628 -0
  293. package/packages/core/src/storage/sqlite.ts +407 -0
  294. package/packages/core/src/storage/usage.ts +374 -0
  295. package/packages/core/src/tool-runtime/index.ts +476 -0
  296. package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
  297. package/packages/core/src/tools/agents/get-available-models.ts +118 -0
  298. package/packages/core/src/tools/agents/index.ts +610 -0
  299. package/packages/core/src/tools/canvas/index.ts +420 -0
  300. package/packages/core/src/tools/cli/index.ts +142 -0
  301. package/packages/core/src/tools/core/index.ts +478 -0
  302. package/packages/core/src/tools/cron/index.ts +635 -0
  303. package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
  304. package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
  305. package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
  306. package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
  307. package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
  308. package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
  309. package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
  310. package/packages/core/src/tools/filesystem/index.ts +34 -0
  311. package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
  312. package/packages/core/src/tools/index.ts +197 -0
  313. package/packages/core/src/tools/meeting/index.ts +363 -0
  314. package/packages/core/src/tools/office/index.ts +47 -0
  315. package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
  316. package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
  317. package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
  318. package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
  319. package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
  320. package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
  321. package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
  322. package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
  323. package/packages/core/src/tools/types.ts +39 -0
  324. package/packages/core/src/tools/voice/index.ts +104 -0
  325. package/packages/core/src/tools/web/browser-click.ts +78 -0
  326. package/packages/core/src/tools/web/browser-extract.ts +139 -0
  327. package/packages/core/src/tools/web/browser-navigate.ts +106 -0
  328. package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
  329. package/packages/core/src/tools/web/browser-script.ts +88 -0
  330. package/packages/core/src/tools/web/browser-service.ts +554 -0
  331. package/packages/core/src/tools/web/browser-type.ts +101 -0
  332. package/packages/core/src/tools/web/browser-wait.ts +136 -0
  333. package/packages/core/src/tools/web/index.ts +41 -0
  334. package/packages/core/src/tools/web/web-fetch.ts +78 -0
  335. package/packages/core/src/tools/web/web-search.ts +123 -0
  336. package/packages/core/src/utils/benchmark.ts +80 -0
  337. package/packages/core/src/utils/crypto.ts +73 -0
  338. package/packages/core/src/utils/date.ts +42 -0
  339. package/packages/core/src/utils/index.ts +5 -0
  340. package/packages/core/src/utils/logger.ts +389 -0
  341. package/packages/core/src/utils/retry.ts +70 -0
  342. package/packages/core/src/utils/toon.ts +253 -0
  343. package/packages/core/src/voice/index.ts +643 -0
  344. package/packages/mcp/src/config.ts +13 -0
  345. package/packages/mcp/src/index.ts +1 -0
  346. package/packages/mcp/src/logger.ts +47 -0
  347. package/packages/mcp/src/manager.ts +439 -0
  348. package/packages/mcp/src/transports/index.ts +67 -0
  349. package/packages/mcp/src/transports/sse.ts +238 -0
  350. package/packages/mcp/src/transports/websocket.ts +159 -0
  351. package/packages/skills/src/bundled/agents/agent_spawner/SKILL.md +167 -0
  352. package/packages/skills/src/bundled/agents/code_delegator/SKILL.md +156 -0
  353. package/packages/skills/src/bundled/agents/memory_manager/SKILL.md +143 -0
  354. package/packages/skills/src/bundled/agents/research_and_remember/SKILL.md +139 -0
  355. package/packages/skills/src/bundled/agents/task_orchestrator/SKILL.md +198 -0
  356. package/packages/skills/src/bundled/canvas/a2ui_dashboard/SKILL.md +176 -0
  357. package/packages/skills/src/bundled/canvas/a2ui_form/SKILL.md +202 -0
  358. package/packages/skills/src/bundled/canvas/a2ui_interactive/SKILL.md +206 -0
  359. package/packages/skills/src/bundled/canvas/canvas_dashboard/SKILL.md +146 -0
  360. package/packages/skills/src/bundled/canvas/canvas_interact/SKILL.md +148 -0
  361. package/packages/skills/src/bundled/canvas/canvas_report/SKILL.md +146 -0
  362. package/packages/skills/src/bundled/cli/cli_pipeline/SKILL.md +136 -0
  363. package/packages/skills/src/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  364. package/packages/skills/src/bundled/cron_manager/SKILL.md +188 -0
  365. package/packages/skills/src/bundled/cron_reminder/SKILL.md +112 -0
  366. package/packages/skills/src/bundled/filesystem/file_manager/SKILL.md +118 -0
  367. package/packages/skills/src/bundled/filesystem/file_read_and_summarize/SKILL.md +108 -0
  368. package/packages/skills/src/bundled/filesystem/file_writer/SKILL.md +135 -0
  369. package/packages/skills/src/bundled/meeting/meeting_transcription/SKILL.md +213 -0
  370. package/packages/skills/src/bundled/office/office_document_manager/SKILL.md +262 -0
  371. package/packages/skills/src/bundled/search_knowledge/busqueda_fts5/SKILL.md +74 -0
  372. package/packages/skills/src/bundled/voice/voice_assistant/SKILL.md +174 -0
  373. package/packages/skills/src/bundled/voice/voice_input/SKILL.md +146 -0
  374. package/packages/skills/src/bundled/voice/voice_output/SKILL.md +151 -0
  375. package/packages/skills/src/bundled/web/browser_automate/SKILL.md +120 -0
  376. package/packages/skills/src/bundled/web/browser_scrape/SKILL.md +109 -0
  377. package/packages/skills/src/bundled/web/web_monitor/SKILL.md +127 -0
  378. package/packages/skills/src/bundled/web/web_research/SKILL.md +119 -0
  379. package/packages/skills/src/bundled-data.generated.ts +1964 -0
  380. package/packages/skills/src/index.ts +1 -0
  381. package/packages/skills/src/loader.ts +388 -0
  382. package/dist/ui/assets/AgentNewPage-GB-tVN50.js +0 -1
  383. package/dist/ui/assets/BridgePage-DDcDILKu.js +0 -1
  384. package/dist/ui/assets/CanvasPage-oOk2sGOD.js +0 -33
  385. package/dist/ui/assets/DashboardPage-DV_2qWYJ.js +0 -6
  386. package/dist/ui/assets/LogsPage-DayYjh01.js +0 -1
  387. package/dist/ui/assets/MeetingPage-C01uPuqj.js +0 -1
  388. package/dist/ui/assets/ProjectsPage-B8_am_Ib.js +0 -1
  389. package/dist/ui/assets/ProvidersPage-DBzi66e4.js +0 -1
  390. package/dist/ui/assets/SettingsPage-CFA_Tknl.js +0 -9
  391. package/dist/ui/assets/SetupPage-BrUWbhvT.js +0 -1
  392. package/dist/ui/assets/accordion-DdAEfIXR.js +0 -1
  393. package/dist/ui/assets/chevron-down-DIosfU_U.js +0 -1
  394. package/dist/ui/assets/chevron-up-CI-W21Fy.js +0 -1
  395. package/dist/ui/assets/circle-S0-ouLz-.js +0 -1
  396. package/dist/ui/assets/circle-minus-CE0iJrl8.js +0 -1
  397. package/dist/ui/assets/circle-x-jUJ5zZvQ.js +0 -1
  398. package/dist/ui/assets/dropdown-menu-C2CXM1VE.js +0 -1
  399. package/dist/ui/assets/index-BN0875JH.css +0 -2
  400. package/dist/ui/assets/index-CH6sBa3Q.js +0 -116
  401. package/dist/ui/assets/pencil-5VdSj-h5.js +0 -1
  402. package/dist/ui/assets/progress-JN30I5fF.js +0 -1
  403. package/dist/ui/assets/scroll-area-BQQPitM8.js +0 -1
  404. package/dist/ui/assets/search-ChPgnVKj.js +0 -1
  405. package/dist/ui/assets/switch-C7W2-KEx.js +0 -1
  406. package/dist/ui/assets/terminal-C-R5Fckz.js +0 -1
  407. package/dist/ui/assets/useProviders-TBnWn-Hq.js +0 -1
  408. /package/dist/ui/assets/{card-DFKnZ6ky.js → card-CNf6BS2e.js} +0 -0
  409. /package/dist/ui/assets/{circle-alert-KuAm2FWh.js → circle-alert-CyHDwUj8.js} +0 -0
  410. /package/dist/ui/assets/{circle-check-6Ard1-2z.js → circle-check-Bb54Ebmu.js} +0 -0
  411. /package/dist/ui/assets/{cpu-KDy6-FAI.js → cpu-Cdgc_B1K.js} +0 -0
  412. /package/dist/ui/assets/{download-Cjbk4Rek.js → download-C3ifGMjJ.js} +0 -0
  413. /package/dist/ui/assets/{external-link-HtrFM63g.js → external-link-BvxYeTP1.js} +0 -0
  414. /package/dist/ui/assets/{eye-D1dB40_o.js → eye-DqNTU_GD.js} +0 -0
  415. /package/dist/ui/assets/{file-text-CE58EfH0.js → file-text-BT_9S9SM.js} +0 -0
  416. /package/dist/ui/assets/{folder-open-DIPKeiI_.js → folder-open-BhH8y9ac.js} +0 -0
  417. /package/dist/ui/assets/{format-BwdV8bB5.js → format-GVHeOyWI.js} +0 -0
  418. /package/dist/ui/assets/{gateway-url-D5uj6Nxg.js → gateway-url-COCbW0IR.js} +0 -0
  419. /package/dist/ui/assets/{gauge-DmQmJHEg.js → gauge-D_TMa4i9.js} +0 -0
  420. /package/dist/ui/assets/{globe-_hUGxQF4.js → globe-DeCQTCDJ.js} +0 -0
  421. /package/dist/ui/assets/{hexagon-BaNGQlQj.js → hexagon-DsGOUl-H.js} +0 -0
  422. /package/dist/ui/assets/{history-BfZVGlZa.js → history-BSG-Ypqf.js} +0 -0
  423. /package/dist/ui/assets/{info-CBZ5-AlC.js → info-NwLoa2Mj.js} +0 -0
  424. /package/dist/ui/assets/{key-Bv5DdTPh.js → key-3EP0dhkT.js} +0 -0
  425. /package/dist/ui/assets/{loader-circle-C4hhXLgp.js → loader-circle-CZNax6kS.js} +0 -0
  426. /package/dist/ui/assets/{lock-CkZYexqw.js → lock-Ei1_J-Nq.js} +0 -0
  427. /package/dist/ui/assets/{pause-Bpy1_s7y.js → pause-BUqah9Bi.js} +0 -0
  428. /package/dist/ui/assets/{play-Cj4osqJZ.js → play-NcZ4swwL.js} +0 -0
  429. /package/dist/ui/assets/{plus-BQhgZN3A.js → plus-CX1xyhp5.js} +0 -0
  430. /package/dist/ui/assets/{refresh-cw-BfREHVQM.js → refresh-cw-DaYdjQFk.js} +0 -0
  431. /package/dist/ui/assets/{save-FFTD4dMp.js → save-CUdYyHNy.js} +0 -0
  432. /package/dist/ui/assets/{settings-BdHKUL92.js → settings-Ds4SqD8s.js} +0 -0
  433. /package/dist/ui/assets/{sparkles-r4uJbJAl.js → sparkles-yUEb-7oH.js} +0 -0
  434. /package/dist/ui/assets/{square-G7Hyufqm.js → square-BD81nFtN.js} +0 -0
  435. /package/dist/ui/assets/{textarea-5kyuD04X.js → textarea-CXgXWKrT.js} +0 -0
  436. /package/dist/ui/assets/{trash-2-DXVBRWfh.js → trash-2-CNjMkoq6.js} +0 -0
  437. /package/dist/ui/assets/{triangle-alert-Bu5seg9O.js → triangle-alert-C9Y8Ub4X.js} +0 -0
  438. /package/dist/ui/assets/{vendor-router-CCECILJ0.js → vendor-router-C9pIYwbJ.js} +0 -0
  439. /package/dist/ui/assets/{volume-2-s9DuS696.js → volume-2-CeSXNDv4.js} +0 -0
  440. /package/dist/ui/assets/{zap-BPHZzXKV.js → zap-hlXjpSeA.js} +0 -0
@@ -0,0 +1,691 @@
1
+ /**
2
+ * Agent Loop — native implementation, no LangGraph.
3
+ *
4
+ * Replaces supervisor.ts + graph.ts.
5
+ *
6
+ * Pattern:
7
+ * user message → context compiler → model call → [tool call → model call]* → response
8
+ *
9
+ * Exposes an async generator compatible with the existing providers/index.ts stream API:
10
+ * yield { agent: { messages: [AIMessage] } }
11
+ * yield { tools: { messages: [ToolMessage] } }
12
+ *
13
+ * Also used directly by runAgentIsolated() for worker tasks.
14
+ */
15
+
16
+ import { logger } from "../utils/logger"
17
+ import { getDb } from "../storage/sqlite"
18
+ import { callLLM, resolveProviderConfig, type LLMMessage } from "./llm-client"
19
+ import { addMessage } from "./conversation-store"
20
+ import { saveTrace, recordLLMUsage } from "./tracer"
21
+ import { maybeCompact, clearOldToolResults } from "./compaction"
22
+ import { emitCanvas } from "../canvas/emitter"
23
+ import type { MCPClientManager } from "@johpaz/hive-agents-mcp"
24
+ import { compileContext } from "./context-compiler"
25
+ import { formatToolResult } from "../utils/toon"
26
+ import { getAverageTokenCost } from "../storage/usage"
27
+ import { resolveUserId, resolveAgentId } from "../storage/onboarding"
28
+ import type { ContentPart } from "../multimodal/types"
29
+ import { loadConfig } from "../config/loader"
30
+ import { executeToolBatch } from "../tool-runtime"
31
+
32
+ const log = logger.child("agent-loop")
33
+
34
+ // ─── Types ────────────────────────────────────────────────────────────────────
35
+
36
+ export interface AgentLoopOptions {
37
+ agentId: string
38
+ userMessage: string | ContentPart[]
39
+ threadId: string
40
+ channel?: string
41
+ mcpManager?: MCPClientManager | null
42
+ /** System prompt override (from server.ts config) */
43
+ systemPromptOverride?: string
44
+ /** Worker mode: isolated context + single-task execution */
45
+ isolated?: boolean
46
+ taskContext?: string | ContentPart[]
47
+ onStep?: (step: StepEvent) => Promise<void>
48
+ /** User ID for context propagation */
49
+ userId?: string
50
+ /** Abort signal to stop generation mid-execution */
51
+ signal?: AbortSignal
52
+ /** Clean text for FTS5 and tracing (extracted from userMessage if multimodal) */
53
+ rawUserMessage?: string
54
+ }
55
+
56
+ export interface StepEvent {
57
+ type: "text" | "tool_call" | "tool_result"
58
+ message: string
59
+ toolName?: string
60
+ isError?: boolean
61
+ }
62
+
63
+ // ─── Stream chunk types (compatible with providers/index.ts) ─────────────────
64
+
65
+ export interface StreamChunk {
66
+ agent?: { messages: any[] }
67
+ tools?: { messages: any[] }
68
+ usage?: { input_tokens: number; output_tokens: number }
69
+ }
70
+
71
+ // ─── Main agent loop ──────────────────────────────────────────────────────────
72
+
73
+ export async function* runAgent(
74
+ opts: AgentLoopOptions
75
+ ): AsyncGenerator<StreamChunk> {
76
+ const t0 = performance.now()
77
+ const db = getDb()
78
+
79
+ // Load agent config from DB
80
+ const agent = db.query<any, [string]>("SELECT * FROM agents WHERE id = ?").get(opts.agentId)
81
+ if (!agent) throw new Error(`Agent not found: ${opts.agentId}`)
82
+
83
+ const agentName = agent.name || opts.agentId
84
+ const maxIterations = agent.max_iterations || 10
85
+
86
+ // Resolve LLM provider config
87
+ const providerCfg = await resolveProviderConfig(
88
+ agent.provider_id || "openai",
89
+ agent.model_id || "gpt-4o-mini"
90
+ )
91
+
92
+ const cleanModel = providerCfg.model.replace(new RegExp(`^${providerCfg.provider}\\/`), "")
93
+ log.info(`[agent-loop] Starting: agent=${agentName} thread=${opts.threadId} provider=${providerCfg.provider}/${cleanModel}`)
94
+
95
+ emitCanvas("canvas:node_update", {
96
+ nodeId: opts.agentId,
97
+ changes: { status: "thinking" },
98
+ })
99
+
100
+ // Store the user message in conversation history
101
+ if (!opts.isolated) {
102
+ // If userMessage is multimodal, addMessage extracts text for history storage
103
+ addMessage(opts.threadId, "user", opts.userMessage, { channel: opts.channel })
104
+ // Run compaction if conversation history is getting large
105
+ await maybeCompact(
106
+ opts.threadId,
107
+ opts.channel && opts.userId
108
+ ? { channel: opts.channel, userId: opts.userId }
109
+ : undefined
110
+ )
111
+ }
112
+
113
+ // Compile context (system prompt + history + tools)
114
+ const ctx = await compileContext({
115
+ agentId: opts.agentId,
116
+ threadId: opts.threadId,
117
+ userMessage: opts.userMessage,
118
+ channel: opts.channel,
119
+ mcpManager: opts.mcpManager,
120
+ isolated: opts.isolated,
121
+ taskContext: opts.taskContext,
122
+ userId: opts.userId,
123
+ })
124
+
125
+ const systemPrompt = opts.systemPromptOverride || ctx.systemPrompt
126
+
127
+ // Build initial messages array for the model
128
+ let messages: LLMMessage[] = [
129
+ { role: "system", content: systemPrompt },
130
+ ...ctx.messages,
131
+ ]
132
+
133
+ // For isolated workers the user message is the task context, not from history
134
+ if (opts.isolated) {
135
+ messages.push({ role: "user", content: opts.userMessage })
136
+ }
137
+
138
+ let iterations = 0
139
+ let totalInputTokens = 0
140
+ let totalOutputTokens = 0
141
+ let finalContent = ""
142
+ // Loop detection: track last tool call signature to break identical consecutive calls
143
+ let lastToolSignature = ""
144
+ let consecutiveRepeat = 0
145
+ let loopDetected = false
146
+
147
+ // ── The loop ────────────────────────────────────────────────────────────
148
+ while (iterations < maxIterations) {
149
+ if (opts.signal?.aborted) {
150
+ log.info(`[agent-loop] Aborted by signal at iteration ${iterations}`)
151
+ finalContent = "Generación detenida."
152
+ break
153
+ }
154
+
155
+ iterations++
156
+
157
+ const response = await callLLM({
158
+ ...providerCfg,
159
+ messages: clearOldToolResults(messages) as LLMMessage[],
160
+ tools: ctx.tools.length > 0 ? ctx.tools : undefined,
161
+ })
162
+
163
+ // Accumulate usage
164
+ if (response.usage) {
165
+ totalInputTokens += response.usage.input_tokens
166
+ totalOutputTokens += response.usage.output_tokens
167
+ }
168
+
169
+ // Emit agent chunk (compatible with providers/index.ts)
170
+ const agentMsg: any = { content: response.content }
171
+ if (response.tool_calls?.length) agentMsg.tool_calls = response.tool_calls
172
+ yield { agent: { messages: [agentMsg] } }
173
+
174
+ // Notify onStep for narration text
175
+ if (opts.onStep && response.content) {
176
+ await opts.onStep({ type: "text", message: response.content })
177
+ }
178
+
179
+ // ── No tool calls → final response ──────────────────────────────────
180
+ if (!response.tool_calls?.length || response.stop_reason !== "tool_calls") {
181
+ finalContent = response.content?.trim() || ""
182
+ // Only save to history if we have real content; empty → synthesis block will handle it
183
+ if (finalContent && !opts.isolated) {
184
+ addMessage(opts.threadId, "assistant", finalContent)
185
+ }
186
+ break
187
+ }
188
+
189
+ // ── Tool calls → execute each tool ──────────────────────────────────
190
+ // Add assistant message with tool_calls to local messages array AND persist
191
+ messages.push({
192
+ role: "assistant",
193
+ content: response.content,
194
+ tool_calls: response.tool_calls,
195
+ reasoning_content: response.reasoning_content,
196
+ })
197
+ if (!opts.isolated) {
198
+ addMessage(opts.threadId, "assistant", response.content || "", {
199
+ channel: opts.channel,
200
+ tool_calls: response.tool_calls,
201
+ reasoning_content: response.reasoning_content,
202
+ })
203
+ }
204
+
205
+ for (const tc of response.tool_calls) {
206
+ const toolName = tc.function.name
207
+
208
+ emitCanvas("canvas:node_update", {
209
+ nodeId: opts.agentId,
210
+ changes: { status: "tool_call", currentTool: toolName },
211
+ })
212
+
213
+ if (opts.onStep) {
214
+ if (response.content) {
215
+ await opts.onStep({ type: "text", message: response.content })
216
+ }
217
+ await opts.onStep({
218
+ type: "tool_call",
219
+ toolName,
220
+ message: `Calling tool: \`${toolName}\``,
221
+ })
222
+ }
223
+ }
224
+
225
+ const hiveConfig = loadConfig()
226
+ const toolResults = await executeToolBatch({
227
+ toolCalls: response.tool_calls,
228
+ allTools: ctx.allTools,
229
+ toolConfig: {
230
+ user_id: opts.userId,
231
+ thread_id: opts.threadId,
232
+ channel: opts.channel,
233
+ workspace: agent.workspace ?? null,
234
+ },
235
+ hiveConfig,
236
+ workerPool: hiveConfig.tools?.workerPool,
237
+ signal: opts.signal,
238
+ })
239
+
240
+ for (const batchResult of toolResults) {
241
+ const tc = batchResult.toolCall
242
+ const toolName = batchResult.toolName
243
+ const toolResultJS = batchResult.result
244
+ const toolMs = batchResult.durationMs
245
+
246
+ // Encode TOON only for LLM consumption (with cost calculation)
247
+ const toolResultLLM = formatToolResult(toolResultJS, cleanModel)
248
+
249
+ log.info(`[agent-loop] Tool ${toolName} completed in ${toolMs}ms`)
250
+
251
+ // Log tool result preview (truncated to avoid flooding logs)
252
+ const resultPreview = toolResultLLM.length > 500
253
+ ? toolResultLLM.substring(0, 500) + `… (+${toolResultLLM.length - 500} chars)`
254
+ : toolResultLLM
255
+ log.info(`[agent-loop] Tool result [${toolName}]: ${resultPreview}`)
256
+
257
+ // Extract text for trace summary
258
+ const textMessage = typeof opts.userMessage === "string"
259
+ ? opts.userMessage
260
+ : Array.isArray(opts.userMessage)
261
+ ? opts.userMessage.filter(p => p.type === "text").map(p => (p as any).text).join("\n")
262
+ : String(opts.userMessage)
263
+
264
+ // Clean timestamp from message for trace
265
+ const cleanMessage = textMessage.replace(/^\[Timestamp:.*?\]\n/, "")
266
+
267
+ // Save tool call trace
268
+ saveTrace({
269
+ threadId: opts.threadId,
270
+ agentId: opts.agentId,
271
+ agentName,
272
+ toolUsed: toolName,
273
+ inputSummary: `${cleanMessage.substring(0, 200)} → ${toolName}`,
274
+ outputSummary: toolResultLLM.substring(0, 300),
275
+ success: !toolResultLLM.startsWith("[Tool Error]"),
276
+ errorMessage: toolResultLLM.startsWith("[Tool Error]") ? toolResultLLM : null,
277
+ durationMs: toolMs,
278
+ })
279
+
280
+ // Emit tool chunk (TOON encoded for LLM)
281
+ yield { tools: { messages: [{ content: toolResultLLM, tool_call_id: tc.id }] } }
282
+
283
+ if (opts.onStep) {
284
+ await opts.onStep({ type: "tool_result", message: toolResultLLM })
285
+ }
286
+
287
+ // Add tool result to messages for next model call AND persist (TOON encoded)
288
+ messages.push({
289
+ role: "tool",
290
+ content: toolResultLLM,
291
+ tool_call_id: tc.id,
292
+ })
293
+ if (!opts.isolated) {
294
+ addMessage(opts.threadId, "tool", toolResultLLM, {
295
+ channel: opts.channel,
296
+ tool_call_id: tc.id,
297
+ })
298
+ }
299
+
300
+ // Dynamic tool injection: when search_knowledge finds tools (native or MCP), add them to ctx.tools
301
+ if (toolName === "search_knowledge") {
302
+ // Use JS object directly (no parse needed)
303
+ try {
304
+ const result = toolResultJS as any
305
+ const foundTools: Array<{ name: string }> = result?.tools ?? []
306
+ const foundMcpTools: Array<{ tool_name: string; full_name?: string; id?: string }> = result?.toolsmcp ?? []
307
+ const currentToolNames = new Set(ctx.tools.map((t: any) => t.function?.name))
308
+
309
+ // Track which tools were injected for skill lookup
310
+ const injectedTools: string[] = []
311
+
312
+ // Inject native tools
313
+ for (const found of foundTools) {
314
+ if (!currentToolNames.has(found.name)) {
315
+ let nativeTool = ctx.allTools.find(t => t.name === found.name)
316
+ // Fallback: try alternative naming (dots ↔ underscores for legacy DB names)
317
+ if (!nativeTool) {
318
+ const altName = found.name.includes(".")
319
+ ? found.name.replace(/\./g, "_")
320
+ : found.name.replace(/_/g, ".")
321
+ nativeTool = ctx.allTools.find(t => t.name === altName)
322
+ if (nativeTool) {
323
+ log.info(`[agent-loop] Resolved legacy tool name "${found.name}" → "${nativeTool.name}"`)
324
+ }
325
+ }
326
+ if (nativeTool) {
327
+ ctx.tools.push({
328
+ type: "function",
329
+ function: {
330
+ name: nativeTool.name,
331
+ description: (nativeTool as any).description ?? "",
332
+ parameters: (nativeTool as any).parameters ?? { type: "object", properties: {} },
333
+ },
334
+ })
335
+ log.info(`[agent-loop] Injected discovered native tool into loadout: ${nativeTool.name}`)
336
+ currentToolNames.add(found.name)
337
+ injectedTools.push(nativeTool.name)
338
+ } else {
339
+ log.warn(`[agent-loop] search_knowledge returned tool "${found.name}" but no matching executor found in allTools`)
340
+ }
341
+ }
342
+ }
343
+
344
+ // Inject MCP tools discovered via search_knowledge(type="mcp")
345
+ for (const found of foundMcpTools) {
346
+ // Use full_name (sanitized compound id) because ctx.allTools stores MCP tools
347
+ // under the sanitized name (e.g. "Instagram__mis_estadisticas_de_instagram"),
348
+ // NOT the original tool_name (e.g. "mis estadisticas de instagram").
349
+ const mcpFullName = found.full_name || found.id
350
+ log.debug(`[agent-loop] MCP discovery candidate: tool_name="${found.tool_name}", full_name="${found.full_name}", id="${found.id}", resolved="${mcpFullName}"`)
351
+ if (!currentToolNames.has(mcpFullName)) {
352
+ const mcpTool = ctx.allTools.find(t => t.name === mcpFullName)
353
+ if (mcpTool) {
354
+ ctx.tools.push({
355
+ type: "function",
356
+ function: {
357
+ name: mcpTool.name,
358
+ description: (mcpTool as any).description ?? "",
359
+ parameters: (mcpTool as any).parameters ?? { type: "object", properties: {} },
360
+ },
361
+ })
362
+ log.info(`[agent-loop] Injected discovered MCP tool into loadout: ${mcpTool.name}`)
363
+ currentToolNames.add(mcpFullName)
364
+ } else {
365
+ log.warn(`[agent-loop] MCP tool "${mcpFullName}" not found in allTools (available MCP: ${ctx.allTools.filter(t => t.name.includes('__')).map(t => t.name).join(', ')})`)
366
+ }
367
+ }
368
+ }
369
+
370
+ // Inject skills associated with the injected tools
371
+ if (injectedTools.length > 0) {
372
+ try {
373
+ const db = getDb()
374
+ // Find skills that use any of the injected tools
375
+ const placeholders = injectedTools.map(() => "?").join(",")
376
+ const skillsWithTools = db.query(`
377
+ SELECT DISTINCT s.name, s.body, s.tools
378
+ FROM skills s
379
+ WHERE s.active = 1
380
+ AND (
381
+ ${injectedTools.map(() => `s.tools LIKE ?`).join(" OR ")}
382
+ )
383
+ `).all(...injectedTools.map(t => `%${t}%`)) as Array<{ name: string; body: string; tools: string }>
384
+
385
+ // Filter to only skills that actually contain the tools (not partial matches)
386
+ const matchingSkills = skillsWithTools.filter(s => {
387
+ const skillTools = s.tools?.split(",").map(t => t.trim()) ?? []
388
+ return injectedTools.some(injected => skillTools.includes(injected))
389
+ })
390
+
391
+ if (matchingSkills.length > 0) {
392
+ const skillSection = matchingSkills
393
+ .map(s => `## Skill: ${s.name}\n${s.body}`)
394
+ .join("\n\n")
395
+
396
+ // Add skill instructions to system prompt (first message)
397
+ const systemMsg = messages.find(m => m.role === "system")
398
+ if (systemMsg && typeof systemMsg.content === "string") {
399
+ // Check if we already added this skill
400
+ const existingSkillNames = new Set(
401
+ (systemMsg.content.match(/## Skill: ([^\n]+)/g) || [])
402
+ .map(m => m.replace("## Skill: ", "").trim())
403
+ )
404
+
405
+ const newSkills = matchingSkills.filter(s => !existingSkillNames.has(s.name))
406
+ if (newSkills.length > 0) {
407
+ const newSkillSection = newSkills
408
+ .map(s => `## Skill: ${s.name}\n${s.body}`)
409
+ .join("\n\n")
410
+
411
+ systemMsg.content += `\n\n--- SKILL INSTRUCTIONS (Auto-loaded) ---\n${newSkillSection}`
412
+ log.info(`[agent-loop] Injected ${newSkills.length} skill(s) for tools: ${newSkills.map(s => s.name).join(", ")}`)
413
+ }
414
+ }
415
+ }
416
+ } catch (skillErr) {
417
+ log.warn(`[agent-loop] Failed to inject skills for tools: ${(skillErr as Error).message}`)
418
+ }
419
+ }
420
+ } catch (err) {
421
+ log.warn(`[agent-loop] search_knowledge tool injection failed: ${(err as Error).message}`)
422
+ }
423
+
424
+ // Enrich the tool result with skill instructions and playbook rules
425
+ try {
426
+ const result = toolResultJS as any
427
+ const foundSkills: Array<{ name: string; body?: string }> = result?.skills ?? []
428
+ const foundPlaybook: Array<{ rule: string; category?: string }> = result?.playbook ?? []
429
+
430
+ if (foundSkills.length > 0 || foundPlaybook.length > 0) {
431
+ const extras: string[] = []
432
+
433
+ if (foundSkills.some((s: any) => s.body)) {
434
+ const section = foundSkills
435
+ .filter((s: any) => s.body)
436
+ .map((s: any) => `## Skill: ${s.name}\n${s.body}`)
437
+ .join("\n\n")
438
+ extras.push(`\n\n--- SKILL INSTRUCTIONS ---\n${section}`)
439
+ }
440
+
441
+ if (foundPlaybook.length > 0) {
442
+ const section = foundPlaybook.map((p: any) => `- [${p.category ?? "general"}] ${p.rule}`).join("\n")
443
+ extras.push(`\n\n--- PLAYBOOK RULES ---\n${section}`)
444
+ }
445
+
446
+ if (extras.length > 0) {
447
+ const lastMsg = messages[messages.length - 1]
448
+ if (lastMsg?.role === "tool") {
449
+ lastMsg.content += extras.join("")
450
+ log.info(`[agent-loop] Enriched search_knowledge result with ${foundSkills.length} skill(s) and ${foundPlaybook.length} rule(s)`)
451
+ }
452
+ }
453
+ }
454
+ } catch (err) {
455
+ log.warn(`[agent-loop] search_knowledge enrichment failed: ${(err as Error).message}`)
456
+ }
457
+ }
458
+
459
+ // Loop detection: same tool + same args called consecutively → break
460
+ const sig = `${toolName}:${JSON.stringify(tc.function.arguments)}`
461
+ if (sig === lastToolSignature) {
462
+ consecutiveRepeat++
463
+ if (consecutiveRepeat >= 2) {
464
+ log.warn(`[agent-loop] Loop detected: "${toolName}" x${consecutiveRepeat + 1} with same args. Breaking.`)
465
+ finalContent = "No pude completar la tarea porque no encontré las herramientas necesarias para ello."
466
+ loopDetected = true
467
+ }
468
+ } else {
469
+ lastToolSignature = sig
470
+ consecutiveRepeat = 0
471
+ }
472
+ }
473
+
474
+ if (loopDetected) break
475
+
476
+ emitCanvas("canvas:node_update", {
477
+ nodeId: opts.agentId,
478
+ changes: { status: "thinking", currentTool: null },
479
+ })
480
+ }
481
+
482
+ // ── Synthesis call when max iterations hit without a text response ────────
483
+ // The agent spent all iterations on tool calls and never produced a final message.
484
+ // Make one extra call without tools so it summarizes what it did.
485
+ if (!finalContent) {
486
+ log.info(`[agent-loop] Max iterations hit with no text response — requesting synthesis (isolated=${!!opts.isolated})`)
487
+ try {
488
+ messages.push({
489
+ role: "user",
490
+ content: "Basándote en lo que hiciste hasta ahora, responde al usuario con un resumen claro de lo que completaste o del estado actual. Sé conciso.",
491
+ })
492
+ const synthesis = await callLLM({
493
+ ...providerCfg,
494
+ messages: clearOldToolResults(messages) as LLMMessage[],
495
+ tools: undefined, // no tools — force text response
496
+ })
497
+ if (synthesis.usage) {
498
+ totalInputTokens += synthesis.usage.input_tokens
499
+ totalOutputTokens += synthesis.usage.output_tokens
500
+ }
501
+ finalContent = synthesis.content?.trim() || "He completado las tareas solicitadas."
502
+ if (!opts.isolated) {
503
+ addMessage(opts.threadId, "assistant", finalContent)
504
+ }
505
+ yield { agent: { messages: [{ content: finalContent }] } }
506
+ } catch (err) {
507
+ log.warn(`[agent-loop] Synthesis call failed: ${(err as Error).message}`)
508
+ finalContent = "He completado las tareas solicitadas."
509
+ if (!opts.isolated) {
510
+ addMessage(opts.threadId, "assistant", finalContent)
511
+ }
512
+ yield { agent: { messages: [{ content: finalContent }] } }
513
+ }
514
+ }
515
+
516
+ // Emit final usage so consumers (e.g. AgentRunner) can surface real token counts
517
+ if (totalInputTokens > 0 || totalOutputTokens > 0) {
518
+ yield { usage: { input_tokens: totalInputTokens, output_tokens: totalOutputTokens } }
519
+ }
520
+
521
+ // ── Post-loop ────────────────────────────────────────────────────────────
522
+ const durationMs = Math.round(performance.now() - t0)
523
+
524
+ emitCanvas("canvas:node_update", {
525
+ nodeId: opts.agentId,
526
+ changes: { status: "idle", currentTool: null },
527
+ })
528
+
529
+ // Record usage
530
+ recordLLMUsage({
531
+ provider: providerCfg.provider,
532
+ model: providerCfg.model,
533
+ inputTokens: totalInputTokens,
534
+ outputTokens: totalOutputTokens,
535
+ })
536
+
537
+ // Extract text for trace summary
538
+ const textMessageFinal = opts.rawUserMessage || (typeof opts.userMessage === "string"
539
+ ? opts.userMessage
540
+ : Array.isArray(opts.userMessage)
541
+ ? opts.userMessage.filter(p => p.type === "text").map(p => (p as any).text).join("\n")
542
+ : String(opts.userMessage))
543
+
544
+ // Save overall trace
545
+ const cleanMessageFinal = textMessageFinal.replace(/^\[Timestamp:.*?\]\n/, "")
546
+ saveTrace({
547
+ threadId: opts.threadId,
548
+ agentId: opts.agentId,
549
+ agentName,
550
+ inputSummary: cleanMessageFinal.substring(0, 300),
551
+ outputSummary: finalContent.substring(0, 300),
552
+ success: true,
553
+ durationMs,
554
+ tokensUsed: totalInputTokens + totalOutputTokens,
555
+ })
556
+
557
+ log.info(
558
+ `[agent-loop] Done: agent=${agentName} iterations=${iterations} ` +
559
+ `tokens=${totalInputTokens + totalOutputTokens} elapsed=${durationMs}ms`
560
+ )
561
+ }
562
+
563
+ // ─── Isolated worker execution (Fase 4.4) ───────────────────────────────────
564
+
565
+ /**
566
+ * Run a worker agent in an isolated context.
567
+ * Returns the final response string.
568
+ */
569
+ export async function runAgentIsolated(opts: {
570
+ agentId: string
571
+ taskDescription: string | ContentPart[]
572
+ threadId: string
573
+ mcpManager?: MCPClientManager | null
574
+ }): Promise<string> {
575
+ let lastContent = ""
576
+ for await (const chunk of runAgent({
577
+ agentId: opts.agentId,
578
+ userMessage: opts.taskDescription,
579
+ threadId: opts.threadId,
580
+ isolated: true,
581
+ taskContext: opts.taskDescription,
582
+ mcpManager: opts.mcpManager,
583
+ })) {
584
+ if (chunk.agent?.messages?.[0]?.content) {
585
+ lastContent = chunk.agent.messages[0].content
586
+ }
587
+ }
588
+ return lastContent
589
+ }
590
+
591
+ // ─── Shim: AgentLoop class with stream() compatible with providers/index.ts ──
592
+
593
+ export class AgentLoop {
594
+ private mcpManager: MCPClientManager | null = null
595
+
596
+ setMCPManager(m: MCPClientManager) {
597
+ this.mcpManager = m
598
+ }
599
+
600
+ /**
601
+ * Returns an async iterable that emits chunks compatible with
602
+ * the existing providers/index.ts stream consumer.
603
+ */
604
+ stream(
605
+ input: { messages: Array<{ role: string; content: string | ContentPart[] }> },
606
+ config: {
607
+ configurable?: {
608
+ thread_id?: string
609
+ agent_id?: string
610
+ user_id?: string
611
+ system_prompt?: string
612
+ channel?: string
613
+ raw_user_message?: string
614
+ }
615
+ signal?: AbortSignal
616
+ }
617
+ ): AsyncIterable<StreamChunk> {
618
+ // Resolve from database with priority: explicit param → DB lookup → single user/agent
619
+ const threadId = config.configurable?.thread_id || resolveUserId({}) || "default"
620
+ const agentId = config.configurable?.agent_id || resolveAgentId(config.configurable?.agent_id) || this._resolveCoordinatorId() || "main"
621
+ const systemPromptOverride = config.configurable?.system_prompt
622
+ const channel = config.configurable?.channel
623
+ const userId = config.configurable?.user_id || resolveUserId({
624
+ channel: config.configurable?.channel ? (config.configurable?.channel as string).split(':')[0] : null,
625
+ channelUserId: config.configurable?.thread_id
626
+ })
627
+
628
+ // Log MCP Manager status
629
+ log.info(`[AgentLoop.stream] MCP Manager available: ${this.mcpManager !== null}`)
630
+ if (this.mcpManager) {
631
+ try {
632
+ const servers = this.mcpManager.listServers?.() || []
633
+ log.info(`[AgentLoop.stream] MCP servers: ${servers.length} registered`)
634
+ for (const s of servers) {
635
+ log.info(` - ${s.name}: ${s.status} (${s.tools?.length || 0} tools)`)
636
+ }
637
+ } catch (e) {
638
+ log.warn(`[AgentLoop.stream] Failed to list MCP servers: ${(e as Error).message}`)
639
+ }
640
+ }
641
+
642
+ // Extract the last user message from the input
643
+ const lastUserMsg = [...input.messages].reverse().find((m) => m.role === "user")
644
+ const userMessage = lastUserMsg?.content || ""
645
+
646
+ // Use clean message (without timestamp) for FTS5 selectors
647
+ const rawUserMessage = config.configurable?.raw_user_message ||
648
+ (typeof userMessage === "string" ? userMessage : userMessage.filter(p => p.type === "text").map(p => (p as any).text).join("\n"))
649
+
650
+ return runAgent({
651
+ agentId,
652
+ userMessage, // FULL MULTIMODAL MESSAGE
653
+ rawUserMessage, // CLEAN TEXT for FTS5
654
+ threadId,
655
+ channel,
656
+ systemPromptOverride,
657
+ mcpManager: this.mcpManager,
658
+ userId,
659
+ signal: config.signal,
660
+ })
661
+ }
662
+
663
+ private _resolveCoordinatorId(): string {
664
+ // Use the storage helper to get coordinator agent ID from database
665
+ const coordinatorId = resolveAgentId(null);
666
+ return coordinatorId || "main";
667
+ }
668
+ }
669
+
670
+ // Singleton
671
+ let _agentLoop: AgentLoop | null = null
672
+
673
+ export function getAgentLoop(): AgentLoop | null {
674
+ return _agentLoop
675
+ }
676
+
677
+ export function buildAgentLoop(opts: { mcpManager?: MCPClientManager | null } = {}): AgentLoop {
678
+ _agentLoop = new AgentLoop()
679
+ if (opts.mcpManager) {
680
+ _agentLoop.setMCPManager(opts.mcpManager)
681
+ log.info("[buildAgentLoop] MCP Manager set successfully")
682
+ } else {
683
+ log.warn("[buildAgentLoop] No MCP Manager provided, agent will not have MCP tools")
684
+ }
685
+ return _agentLoop
686
+ }
687
+
688
+ export async function rebuildAgentLoop(opts: { mcpManager?: MCPClientManager | null } = {}): Promise<AgentLoop> {
689
+ _agentLoop = null
690
+ return buildAgentLoop(opts)
691
+ }