@johpaz/hive-agents 0.0.38 → 0.0.40

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 (263) hide show
  1. package/README.md +31 -71
  2. package/dist/hive.js +4318 -2898
  3. package/dist/tool-worker.js +2691 -1969
  4. package/dist/ui/assets/AgentCreateForm-b7xHyfNc.js +1 -0
  5. package/dist/ui/assets/AgentDetailPage-VHy3M7mI.js +1 -0
  6. package/dist/ui/assets/AgentNewPage-BnWImQMx.js +1 -0
  7. package/dist/ui/{dist/assets/AgentsPage-DGNLDXjR.js → assets/AgentsPage-WFy5abqx.js} +5 -5
  8. package/dist/ui/assets/ApiClientPage-BV7zLIL7.js +3 -0
  9. package/dist/ui/assets/{CanvasPage-CnMO1FN8.js → CanvasPage-B9zuIrTm.js} +7 -7
  10. package/dist/ui/assets/ChannelsPage-DiN3NvIM.js +8 -0
  11. package/dist/ui/{dist/assets/DashboardPage-VyXXp3U1.js → assets/DashboardPage-CHjARjVK.js} +2 -2
  12. package/dist/ui/assets/{LoginPage-DPj2s2Qq.js → LoginPage-Dwd_XxoU.js} +1 -1
  13. package/dist/ui/assets/LogsPage-DW8Nnqe6.js +1 -0
  14. package/dist/ui/assets/MeetingPage-D3bkiKYt.js +1 -0
  15. package/dist/ui/assets/{NotFound-BMeQSGcG.js → NotFound-BIUDlIXU.js} +1 -1
  16. package/dist/ui/assets/ProvidersPage-UqsDAxPQ.js +1 -0
  17. package/dist/ui/{dist/assets/RecoverPage-B-hDZUM2.js → assets/RecoverPage-8hTjr_JU.js} +1 -1
  18. package/dist/ui/assets/SettingsPage-DNa0jOkA.js +9 -0
  19. package/dist/ui/assets/SetupPage-Bdm2irQG.js +1 -0
  20. package/dist/ui/assets/WebChatPage-DElJg6P2.js +16 -0
  21. package/dist/ui/assets/accordion-CnLzKNHK.js +1 -0
  22. package/dist/ui/{dist/assets/alert-Bq6awLlW.js → assets/alert-DylmSCDJ.js} +1 -1
  23. package/dist/ui/{dist/assets/alert-dialog-DQvltYmf.js → assets/alert-dialog-DNNWN_SI.js} +1 -1
  24. package/dist/ui/assets/{badge-DXUDdTed.js → badge-ChENFgkC.js} +1 -1
  25. package/dist/ui/assets/bell-8BqRYmzf.js +1 -0
  26. package/dist/ui/assets/chevron-down-DIosfU_U.js +1 -0
  27. package/dist/ui/assets/chevron-up-CI-W21Fy.js +1 -0
  28. package/dist/ui/assets/circle-x-DjLkFDO8.js +1 -0
  29. package/dist/ui/assets/copy-Bu5d7C-0.js +1 -0
  30. package/dist/ui/{dist/assets/dialog-bI9jImCS.js → assets/dialog-BJ-npIv8.js} +1 -1
  31. package/dist/ui/{dist/assets/dropdown-menu-BK-CO3Od.js → assets/dropdown-menu-DDiaHg5y.js} +1 -1
  32. package/dist/ui/assets/{es-Cg8zdT52.js → es-ecSKCyB6.js} +1 -1
  33. package/dist/ui/assets/index-CawKP29y.js +116 -0
  34. package/dist/ui/assets/index-DIcsEkyd.css +2 -0
  35. package/dist/ui/{dist/assets/label-CrH0Jj3v.js → assets/label-Bi6udtSd.js} +1 -1
  36. package/dist/ui/assets/progress-D5c-Eilm.js +1 -0
  37. package/dist/ui/assets/scroll-area-CihOx0cb.js +1 -0
  38. package/dist/ui/assets/search-DzDptO9s.js +1 -0
  39. package/dist/ui/assets/select-BQCOjM2j.js +1 -0
  40. package/dist/ui/assets/send-BPk9XbIq.js +1 -0
  41. package/dist/ui/assets/shield-CxhcUT39.js +1 -0
  42. package/dist/ui/assets/{slider-CsiUDxc3.js → slider-bcUiUfx0.js} +1 -1
  43. package/dist/ui/assets/switch-BR30E4ej.js +1 -0
  44. package/dist/ui/assets/table-B3aGEaVp.js +1 -0
  45. package/dist/ui/assets/tabs-LQidMKRS.js +1 -0
  46. package/dist/ui/assets/textarea-B6Z1Zc6W.js +1 -0
  47. package/dist/ui/assets/useProviders-Dlizq_8q.js +1 -0
  48. package/dist/ui/{dist/assets/vendor-radix-cw1bQaVC.js → assets/vendor-radix-D6rA7xKY.js} +4 -4
  49. package/dist/ui/assets/{vendor-react-D4s9E-zj.js → vendor-react-BU5iQU4f.js} +1 -1
  50. package/dist/ui/dist/assets/AgentCreateForm-b7xHyfNc.js +1 -0
  51. package/dist/ui/dist/assets/AgentDetailPage-VHy3M7mI.js +1 -0
  52. package/dist/ui/dist/assets/AgentNewPage-BnWImQMx.js +1 -0
  53. package/dist/ui/{assets/AgentsPage-DGNLDXjR.js → dist/assets/AgentsPage-WFy5abqx.js} +5 -5
  54. package/dist/ui/dist/assets/ApiClientPage-BV7zLIL7.js +3 -0
  55. package/dist/ui/dist/assets/{CanvasPage-CnMO1FN8.js → CanvasPage-B9zuIrTm.js} +7 -7
  56. package/dist/ui/dist/assets/ChannelsPage-DiN3NvIM.js +8 -0
  57. package/dist/ui/{assets/DashboardPage-VyXXp3U1.js → dist/assets/DashboardPage-CHjARjVK.js} +2 -2
  58. package/dist/ui/dist/assets/{LoginPage-DPj2s2Qq.js → LoginPage-Dwd_XxoU.js} +1 -1
  59. package/dist/ui/dist/assets/LogsPage-DW8Nnqe6.js +1 -0
  60. package/dist/ui/dist/assets/MeetingPage-D3bkiKYt.js +1 -0
  61. package/dist/ui/dist/assets/{NotFound-BMeQSGcG.js → NotFound-BIUDlIXU.js} +1 -1
  62. package/dist/ui/dist/assets/ProvidersPage-UqsDAxPQ.js +1 -0
  63. package/dist/ui/{assets/RecoverPage-B-hDZUM2.js → dist/assets/RecoverPage-8hTjr_JU.js} +1 -1
  64. package/dist/ui/dist/assets/SettingsPage-DNa0jOkA.js +9 -0
  65. package/dist/ui/dist/assets/SetupPage-Bdm2irQG.js +1 -0
  66. package/dist/ui/dist/assets/WebChatPage-DElJg6P2.js +16 -0
  67. package/dist/ui/dist/assets/accordion-CnLzKNHK.js +1 -0
  68. package/dist/ui/{assets/alert-Bq6awLlW.js → dist/assets/alert-DylmSCDJ.js} +1 -1
  69. package/dist/ui/{assets/alert-dialog-DQvltYmf.js → dist/assets/alert-dialog-DNNWN_SI.js} +1 -1
  70. package/dist/ui/dist/assets/{badge-DXUDdTed.js → badge-ChENFgkC.js} +1 -1
  71. package/dist/ui/dist/assets/bell-8BqRYmzf.js +1 -0
  72. package/dist/ui/dist/assets/chevron-down-DIosfU_U.js +1 -0
  73. package/dist/ui/dist/assets/chevron-up-CI-W21Fy.js +1 -0
  74. package/dist/ui/dist/assets/circle-x-DjLkFDO8.js +1 -0
  75. package/dist/ui/dist/assets/copy-Bu5d7C-0.js +1 -0
  76. package/dist/ui/{assets/dialog-bI9jImCS.js → dist/assets/dialog-BJ-npIv8.js} +1 -1
  77. package/dist/ui/{assets/dropdown-menu-BK-CO3Od.js → dist/assets/dropdown-menu-DDiaHg5y.js} +1 -1
  78. package/dist/ui/dist/assets/{es-Cg8zdT52.js → es-ecSKCyB6.js} +1 -1
  79. package/dist/ui/dist/assets/index-CawKP29y.js +116 -0
  80. package/dist/ui/dist/assets/index-DIcsEkyd.css +2 -0
  81. package/dist/ui/{assets/label-CrH0Jj3v.js → dist/assets/label-Bi6udtSd.js} +1 -1
  82. package/dist/ui/dist/assets/progress-D5c-Eilm.js +1 -0
  83. package/dist/ui/dist/assets/scroll-area-CihOx0cb.js +1 -0
  84. package/dist/ui/dist/assets/search-DzDptO9s.js +1 -0
  85. package/dist/ui/dist/assets/select-BQCOjM2j.js +1 -0
  86. package/dist/ui/dist/assets/send-BPk9XbIq.js +1 -0
  87. package/dist/ui/dist/assets/shield-CxhcUT39.js +1 -0
  88. package/dist/ui/dist/assets/{slider-CsiUDxc3.js → slider-bcUiUfx0.js} +1 -1
  89. package/dist/ui/dist/assets/switch-BR30E4ej.js +1 -0
  90. package/dist/ui/dist/assets/table-B3aGEaVp.js +1 -0
  91. package/dist/ui/dist/assets/tabs-LQidMKRS.js +1 -0
  92. package/dist/ui/dist/assets/textarea-B6Z1Zc6W.js +1 -0
  93. package/dist/ui/dist/assets/useProviders-Dlizq_8q.js +1 -0
  94. package/dist/ui/{assets/vendor-radix-cw1bQaVC.js → dist/assets/vendor-radix-D6rA7xKY.js} +4 -4
  95. package/dist/ui/dist/assets/{vendor-react-D4s9E-zj.js → vendor-react-BU5iQU4f.js} +1 -1
  96. package/dist/ui/dist/index.html +6 -6
  97. package/dist/ui/index.html +6 -6
  98. package/package.json +1 -1
  99. package/packages/cli/src/adapters/binary.ts +8 -4
  100. package/packages/cli/src/adapters/bun-global.ts +5 -1
  101. package/packages/cli/src/adapters/config.ts +4 -3
  102. package/packages/cli/src/adapters/docker.ts +2 -1
  103. package/packages/cli/src/commands/gateway.ts +123 -9
  104. package/packages/cli/src/commands/logs.ts +2 -1
  105. package/packages/cli/src/commands/onboard.ts +27 -1
  106. package/packages/cli/src/commands/sessions.ts +2 -1
  107. package/packages/cli/src/commands/skills.ts +2 -1
  108. package/packages/core/src/agent/agent-loop.ts +104 -2
  109. package/packages/core/src/agent/context-compiler.ts +6 -0
  110. package/packages/core/src/agent/llm-client.ts +6 -0
  111. package/packages/core/src/agent/llm-providers/anthropic.ts +23 -8
  112. package/packages/core/src/agent/llm-providers/hiveagents.ts +248 -0
  113. package/packages/core/src/agent/llm-providers/interface.ts +7 -1
  114. package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
  115. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +49 -25
  116. package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -0
  117. package/packages/core/src/agent/providers/index.ts +3 -2
  118. package/packages/core/src/agent/stuck-loop.ts +90 -14
  119. package/packages/core/src/channels/base.ts +7 -1
  120. package/packages/core/src/channels/whatsapp.ts +13 -1
  121. package/packages/core/src/config/loader.ts +8 -8
  122. package/packages/core/src/gateway/helpers/path.ts +2 -1
  123. package/packages/core/src/gateway/initializer.ts +4 -4
  124. package/packages/core/src/gateway/llm-local/downloader.ts +130 -11
  125. package/packages/core/src/gateway/llm-local/index.ts +2 -0
  126. package/packages/core/src/gateway/llm-local/models.ts +4 -3
  127. package/packages/core/src/gateway/router.ts +7 -5
  128. package/packages/core/src/gateway/routes/http-client.ts +16 -0
  129. package/packages/core/src/gateway/routes/llm-local.ts +51 -5
  130. package/packages/core/src/gateway/routes/providers.ts +99 -2
  131. package/packages/core/src/gateway/server.ts +131 -57
  132. package/packages/core/src/gateway/slash-commands.ts +7 -1
  133. package/packages/core/src/gateway/tts/src/install.ts +17 -9
  134. package/packages/core/src/storage/crypto.ts +152 -20
  135. package/packages/core/src/storage/migrate.ts +51 -18
  136. package/packages/core/src/storage/onboarding.ts +28 -0
  137. package/packages/core/src/storage/seed.ts +52 -2
  138. package/packages/core/src/tool-runtime/index.ts +22 -1
  139. package/packages/core/src/tools/api/api-request.ts +174 -0
  140. package/packages/core/src/tools/api/index.ts +16 -0
  141. package/packages/core/src/tools/index.ts +12 -0
  142. package/packages/core/src/tools/web/browser-click.ts +2 -2
  143. package/packages/core/src/tools/web/browser-extract.ts +22 -6
  144. package/packages/core/src/tools/web/browser-navigate.ts +34 -18
  145. package/packages/core/src/tools/web/browser-screenshot.ts +40 -8
  146. package/packages/core/src/tools/web/browser-script.ts +2 -2
  147. package/packages/core/src/tools/web/browser-service.ts +295 -341
  148. package/packages/core/src/tools/web/browser-type.ts +5 -10
  149. package/packages/core/src/tools/web/browser-wait.ts +2 -2
  150. package/packages/core/src/tools/web/index.ts +1 -1
  151. package/packages/core/src/utils/logger.ts +2 -1
  152. package/packages/mcp/src/manager.ts +2 -1
  153. package/packages/skills/src/bundled/api/api_client/SKILL.md +132 -0
  154. package/packages/skills/src/bundled-data.generated.ts +1191 -1134
  155. package/packages/skills/src/loader.ts +2 -1
  156. package/dist/ui/assets/AgentCreateForm-0oFbN3gj.js +0 -1
  157. package/dist/ui/assets/AgentDetailPage-BJ4L2fNJ.js +0 -1
  158. package/dist/ui/assets/AgentNewPage-B3n0LUck.js +0 -1
  159. package/dist/ui/assets/ChannelsPage-fbF8K4MR.js +0 -8
  160. package/dist/ui/assets/LogsPage-B2lY9maY.js +0 -1
  161. package/dist/ui/assets/MeetingPage-2ky_hKiG.js +0 -1
  162. package/dist/ui/assets/ProvidersPage-CEyUM2tD.js +0 -1
  163. package/dist/ui/assets/SettingsPage-eO0i3g8p.js +0 -9
  164. package/dist/ui/assets/SetupPage-ByYqTELb.js +0 -1
  165. package/dist/ui/assets/WebChatPage-BuGT2AL0.js +0 -16
  166. package/dist/ui/assets/accordion-C5d5Rm5z.js +0 -1
  167. package/dist/ui/assets/chevron-up-BYhk0K2J.js +0 -1
  168. package/dist/ui/assets/globe-DeCQTCDJ.js +0 -1
  169. package/dist/ui/assets/index-B2fCYtTS.css +0 -2
  170. package/dist/ui/assets/index-CQ7fn00w.js +0 -116
  171. package/dist/ui/assets/progress-BherYzY6.js +0 -1
  172. package/dist/ui/assets/scroll-area-DkeyX32e.js +0 -1
  173. package/dist/ui/assets/send-B0H5SEIE.js +0 -1
  174. package/dist/ui/assets/switch-BDwN8RYV.js +0 -1
  175. package/dist/ui/assets/table-CSc8ubon.js +0 -1
  176. package/dist/ui/assets/textarea-CXgXWKrT.js +0 -1
  177. package/dist/ui/assets/useProviders-CnlC_qCS.js +0 -1
  178. package/dist/ui/dist/assets/AgentCreateForm-0oFbN3gj.js +0 -1
  179. package/dist/ui/dist/assets/AgentDetailPage-BJ4L2fNJ.js +0 -1
  180. package/dist/ui/dist/assets/AgentNewPage-B3n0LUck.js +0 -1
  181. package/dist/ui/dist/assets/ChannelsPage-fbF8K4MR.js +0 -8
  182. package/dist/ui/dist/assets/LogsPage-B2lY9maY.js +0 -1
  183. package/dist/ui/dist/assets/MeetingPage-2ky_hKiG.js +0 -1
  184. package/dist/ui/dist/assets/ProvidersPage-CEyUM2tD.js +0 -1
  185. package/dist/ui/dist/assets/SettingsPage-eO0i3g8p.js +0 -9
  186. package/dist/ui/dist/assets/SetupPage-ByYqTELb.js +0 -1
  187. package/dist/ui/dist/assets/WebChatPage-BuGT2AL0.js +0 -16
  188. package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +0 -1
  189. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +0 -1
  190. package/dist/ui/dist/assets/globe-DeCQTCDJ.js +0 -1
  191. package/dist/ui/dist/assets/index-B2fCYtTS.css +0 -2
  192. package/dist/ui/dist/assets/index-CQ7fn00w.js +0 -116
  193. package/dist/ui/dist/assets/progress-BherYzY6.js +0 -1
  194. package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +0 -1
  195. package/dist/ui/dist/assets/send-B0H5SEIE.js +0 -1
  196. package/dist/ui/dist/assets/switch-BDwN8RYV.js +0 -1
  197. package/dist/ui/dist/assets/table-CSc8ubon.js +0 -1
  198. package/dist/ui/dist/assets/textarea-CXgXWKrT.js +0 -1
  199. package/dist/ui/dist/assets/useProviders-CnlC_qCS.js +0 -1
  200. /package/dist/ui/assets/{card-CNf6BS2e.js → card-DFKnZ6ky.js} +0 -0
  201. /package/dist/ui/assets/{circle-alert-CyHDwUj8.js → circle-alert-KuAm2FWh.js} +0 -0
  202. /package/dist/ui/assets/{circle-check-Bb54Ebmu.js → circle-check-6Ard1-2z.js} +0 -0
  203. /package/dist/ui/assets/{cpu-Cdgc_B1K.js → cpu-KDy6-FAI.js} +0 -0
  204. /package/dist/ui/assets/{download-C3ifGMjJ.js → download-Cjbk4Rek.js} +0 -0
  205. /package/dist/ui/assets/{external-link-BvxYeTP1.js → external-link-6sTlRDUR.js} +0 -0
  206. /package/dist/ui/assets/{eye-DqNTU_GD.js → eye-Df8o0tkC.js} +0 -0
  207. /package/dist/ui/assets/{file-text-BT_9S9SM.js → file-text-lnxnjBp0.js} +0 -0
  208. /package/dist/ui/assets/{folder-open-BhH8y9ac.js → folder-open-DJBLDFjv.js} +0 -0
  209. /package/dist/ui/assets/{format-GVHeOyWI.js → format-BwdV8bB5.js} +0 -0
  210. /package/dist/ui/assets/{gateway-url-COCbW0IR.js → gateway-url-DwzPmoc8.js} +0 -0
  211. /package/dist/ui/assets/{gauge-D_TMa4i9.js → gauge-B8Tj43rC.js} +0 -0
  212. /package/dist/ui/assets/{hexagon-DsGOUl-H.js → hexagon-6L79pgVK.js} +0 -0
  213. /package/dist/ui/assets/{history-BSG-Ypqf.js → history-CAF_R34_.js} +0 -0
  214. /package/dist/ui/assets/{info-NwLoa2Mj.js → info-WjromB4Y.js} +0 -0
  215. /package/dist/ui/assets/{key-3EP0dhkT.js → key-DyKOoQh5.js} +0 -0
  216. /package/dist/ui/assets/{loader-circle-CZNax6kS.js → loader-circle-BmBOgYze.js} +0 -0
  217. /package/dist/ui/assets/{lock-Ei1_J-Nq.js → lock-BS6OLXPv.js} +0 -0
  218. /package/dist/ui/assets/{pause-BUqah9Bi.js → pause-VqeUmp2Z.js} +0 -0
  219. /package/dist/ui/assets/{play-NcZ4swwL.js → play-zJpWuhrr.js} +0 -0
  220. /package/dist/ui/assets/{plus-CX1xyhp5.js → plus-BZQX26Dr.js} +0 -0
  221. /package/dist/ui/assets/{refresh-cw-DaYdjQFk.js → refresh-cw-CCzDCAuz.js} +0 -0
  222. /package/dist/ui/assets/{save-CUdYyHNy.js → save-hUmZhceG.js} +0 -0
  223. /package/dist/ui/assets/{settings-Ds4SqD8s.js → settings-BGfrZ_zM.js} +0 -0
  224. /package/dist/ui/assets/{sparkles-yUEb-7oH.js → sparkles-BhwlS1pc.js} +0 -0
  225. /package/dist/ui/assets/{square-BD81nFtN.js → square-DMNWw4Hi.js} +0 -0
  226. /package/dist/ui/assets/{terminal-DN38Q456.js → terminal--7G943As.js} +0 -0
  227. /package/dist/ui/assets/{trash-2-CNjMkoq6.js → trash-2-xD2o4SgX.js} +0 -0
  228. /package/dist/ui/assets/{triangle-alert-C9Y8Ub4X.js → triangle-alert-pVIJGjga.js} +0 -0
  229. /package/dist/ui/assets/{vendor-router-C9pIYwbJ.js → vendor-router-gqiZ7xhx.js} +0 -0
  230. /package/dist/ui/assets/{volume-2-CeSXNDv4.js → volume-2-BekVQl6P.js} +0 -0
  231. /package/dist/ui/assets/{zap-hlXjpSeA.js → zap-B4RaNNO5.js} +0 -0
  232. /package/dist/ui/dist/assets/{card-CNf6BS2e.js → card-DFKnZ6ky.js} +0 -0
  233. /package/dist/ui/dist/assets/{circle-alert-CyHDwUj8.js → circle-alert-KuAm2FWh.js} +0 -0
  234. /package/dist/ui/dist/assets/{circle-check-Bb54Ebmu.js → circle-check-6Ard1-2z.js} +0 -0
  235. /package/dist/ui/dist/assets/{cpu-Cdgc_B1K.js → cpu-KDy6-FAI.js} +0 -0
  236. /package/dist/ui/dist/assets/{download-C3ifGMjJ.js → download-Cjbk4Rek.js} +0 -0
  237. /package/dist/ui/dist/assets/{external-link-BvxYeTP1.js → external-link-6sTlRDUR.js} +0 -0
  238. /package/dist/ui/dist/assets/{eye-DqNTU_GD.js → eye-Df8o0tkC.js} +0 -0
  239. /package/dist/ui/dist/assets/{file-text-BT_9S9SM.js → file-text-lnxnjBp0.js} +0 -0
  240. /package/dist/ui/dist/assets/{folder-open-BhH8y9ac.js → folder-open-DJBLDFjv.js} +0 -0
  241. /package/dist/ui/dist/assets/{format-GVHeOyWI.js → format-BwdV8bB5.js} +0 -0
  242. /package/dist/ui/dist/assets/{gateway-url-COCbW0IR.js → gateway-url-DwzPmoc8.js} +0 -0
  243. /package/dist/ui/dist/assets/{gauge-D_TMa4i9.js → gauge-B8Tj43rC.js} +0 -0
  244. /package/dist/ui/dist/assets/{hexagon-DsGOUl-H.js → hexagon-6L79pgVK.js} +0 -0
  245. /package/dist/ui/dist/assets/{history-BSG-Ypqf.js → history-CAF_R34_.js} +0 -0
  246. /package/dist/ui/dist/assets/{info-NwLoa2Mj.js → info-WjromB4Y.js} +0 -0
  247. /package/dist/ui/dist/assets/{key-3EP0dhkT.js → key-DyKOoQh5.js} +0 -0
  248. /package/dist/ui/dist/assets/{loader-circle-CZNax6kS.js → loader-circle-BmBOgYze.js} +0 -0
  249. /package/dist/ui/dist/assets/{lock-Ei1_J-Nq.js → lock-BS6OLXPv.js} +0 -0
  250. /package/dist/ui/dist/assets/{pause-BUqah9Bi.js → pause-VqeUmp2Z.js} +0 -0
  251. /package/dist/ui/dist/assets/{play-NcZ4swwL.js → play-zJpWuhrr.js} +0 -0
  252. /package/dist/ui/dist/assets/{plus-CX1xyhp5.js → plus-BZQX26Dr.js} +0 -0
  253. /package/dist/ui/dist/assets/{refresh-cw-DaYdjQFk.js → refresh-cw-CCzDCAuz.js} +0 -0
  254. /package/dist/ui/dist/assets/{save-CUdYyHNy.js → save-hUmZhceG.js} +0 -0
  255. /package/dist/ui/dist/assets/{settings-Ds4SqD8s.js → settings-BGfrZ_zM.js} +0 -0
  256. /package/dist/ui/dist/assets/{sparkles-yUEb-7oH.js → sparkles-BhwlS1pc.js} +0 -0
  257. /package/dist/ui/dist/assets/{square-BD81nFtN.js → square-DMNWw4Hi.js} +0 -0
  258. /package/dist/ui/dist/assets/{terminal-DN38Q456.js → terminal--7G943As.js} +0 -0
  259. /package/dist/ui/dist/assets/{trash-2-CNjMkoq6.js → trash-2-xD2o4SgX.js} +0 -0
  260. /package/dist/ui/dist/assets/{triangle-alert-C9Y8Ub4X.js → triangle-alert-pVIJGjga.js} +0 -0
  261. /package/dist/ui/dist/assets/{vendor-router-C9pIYwbJ.js → vendor-router-gqiZ7xhx.js} +0 -0
  262. /package/dist/ui/dist/assets/{volume-2-CeSXNDv4.js → volume-2-BekVQl6P.js} +0 -0
  263. /package/dist/ui/dist/assets/{zap-hlXjpSeA.js → zap-B4RaNNO5.js} +0 -0
@@ -17,6 +17,12 @@ export abstract class OpenAICompatBase implements LLMProvider {
17
17
  /** Override to true for providers running on localhost. */
18
18
  protected isLocalProvider(): boolean { return false }
19
19
 
20
+ /** Override to customize the OpenAI client (e.g. strip unwanted headers, add custom fetch). */
21
+ protected async resolveOpenAIClient(apiKey: string, baseURL: string | undefined): Promise<any> {
22
+ const { default: OpenAI } = await import("openai")
23
+ return new OpenAI({ apiKey, baseURL })
24
+ }
25
+
20
26
  /** Hook called before each request. Override for e.g. auto-starting a local server. */
21
27
  protected async beforeCall(_options: LLMCallOptions): Promise<void> {}
22
28
 
@@ -27,6 +33,9 @@ export abstract class OpenAICompatBase implements LLMProvider {
27
33
  */
28
34
  protected injectToolsIntoPrompt(_body: any, _preparedTools: any[]): void {}
29
35
 
36
+ /** Override to add provider-specific fields to the request body (e.g. extra_body for llama.cpp chat_template_kwargs). */
37
+ protected modifyRequestBody(body: any, _options: LLMCallOptions): any { return body }
38
+
30
39
  private _convertContentPart(part: ContentPart): any {
31
40
  switch (part.type) {
32
41
  case "text":
@@ -51,8 +60,6 @@ export abstract class OpenAICompatBase implements LLMProvider {
51
60
  }
52
61
 
53
62
  async call(options: LLMCallOptions): Promise<LLMResponse> {
54
- const { default: OpenAI } = await import("openai")
55
-
56
63
  const baseURL = options.baseUrl?.trim() || OPENAI_COMPAT_BASE_URLS[this.providerName] || undefined
57
64
  const isLocal = this.isLocalProvider()
58
65
 
@@ -63,7 +70,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
63
70
  throw new Error(`API key missing for provider: ${this.providerName}. Configure it in Settings → Providers.`)
64
71
  }
65
72
 
66
- const client = new OpenAI({ apiKey, baseURL })
73
+ const client = await this.resolveOpenAIClient(apiKey, baseURL)
67
74
 
68
75
  const sanitized = sanitizeMessages(options.messages)
69
76
  const rawMessages = this.needsReasoningRoundtrip()
@@ -121,7 +128,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
121
128
 
122
129
  let response
123
130
  try {
124
- response = await client.chat.completions.create(body)
131
+ response = await client.chat.completions.create(this.modifyRequestBody(body, options))
125
132
  } catch (err: any) {
126
133
  const status = err?.status ?? err?.response?.status
127
134
  const errMsg = (err?.error?.message ?? err?.message ?? "").toLowerCase()
@@ -133,7 +140,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
133
140
  delete bodyNoTools.tools
134
141
  delete bodyNoTools.tool_choice
135
142
  delete bodyNoTools.parallel_tool_calls
136
- response = await client.chat.completions.create(bodyNoTools)
143
+ response = await client.chat.completions.create(this.modifyRequestBody(bodyNoTools, options))
137
144
  }
138
145
  // Retry 2: context overflow — compact messages and retry
139
146
  else if (status === 400 && (errMsg.includes("context length") || errMsg.includes("input_tokens") || errMsg.includes("maximum input length"))) {
@@ -153,7 +160,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
153
160
  if (body.max_tokens) body.max_tokens = Math.min(body.max_tokens, 4096)
154
161
 
155
162
  log.info(`[llm-client] ${this.providerName}: compacted ${compacted.length} msgs → ${body.messages.length} msgs, max_tokens=${body.max_tokens}`)
156
- response = await client.chat.completions.create(body)
163
+ response = await client.chat.completions.create(this.modifyRequestBody(body, options))
157
164
  }
158
165
  else {
159
166
  throw err
@@ -207,7 +214,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
207
214
  ): Promise<LLMResponse> {
208
215
  let stream
209
216
  try {
210
- stream = await client.chat.completions.create({ ...body, stream: true })
217
+ stream = await client.chat.completions.create({ ...this.modifyRequestBody(body, options), stream: true })
211
218
  } catch (err: any) {
212
219
  const status = err?.status ?? err?.response?.status
213
220
  const errMsg = (err?.error?.message ?? err?.message ?? "").toLowerCase()
@@ -218,7 +225,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
218
225
  delete bodyNoTools.tools
219
226
  delete bodyNoTools.tool_choice
220
227
  delete bodyNoTools.parallel_tool_calls
221
- stream = await client.chat.completions.create({ ...bodyNoTools, stream: true })
228
+ stream = await client.chat.completions.create({ ...this.modifyRequestBody(bodyNoTools, options), stream: true })
222
229
  } else if (status === 400 && (errMsg.includes("context length") || errMsg.includes("input_tokens") || errMsg.includes("maximum input length"))) {
223
230
  log.warn(`[llm-client] ${this.providerName}: context overflow — compacting messages and retrying stream`)
224
231
  const compacted = [...body.messages]
@@ -233,7 +240,7 @@ export abstract class OpenAICompatBase implements LLMProvider {
233
240
  body.messages = systemMsg ? [systemMsg, ...trimmed] : trimmed
234
241
  if (body.max_tokens) body.max_tokens = Math.min(body.max_tokens, 4096)
235
242
  log.info(`[llm-client] ${this.providerName}: compacted ${compacted.length} msgs → ${body.messages.length} msgs, max_tokens=${body.max_tokens}`)
236
- stream = await client.chat.completions.create({ ...body, stream: true })
243
+ stream = await client.chat.completions.create({ ...this.modifyRequestBody(body, options), stream: true })
237
244
  } else {
238
245
  throw err
239
246
  }
@@ -325,6 +332,7 @@ export function extractToolCallsFromText(
325
332
  const tool_calls: LLMToolCall[] = []
326
333
  let extractedContent = content
327
334
 
335
+ // Regexes for wrapped tool-call blocks.
328
336
  const regexes = [
329
337
  /<tool_call>\s*({[\s\S]*?})\s*<\/tool_call>/g,
330
338
  /<function_call>\s*({[\s\S]*?})\s*<\/function_call>/g,
@@ -336,13 +344,20 @@ export function extractToolCallsFromText(
336
344
  while ((match = regex.exec(content)) !== null) {
337
345
  try {
338
346
  const json = JSON.parse(match[1])
339
- if (json.name) {
347
+ const calls = Array.isArray(json) ? json : [json]
348
+ for (const call of calls) {
349
+ if (!call) continue
350
+ // Accept both { name, arguments } and { function: { name, arguments } }
351
+ const fn = call.function || call
352
+ const name = fn.name ?? call.name
353
+ let args = fn.arguments ?? call.arguments ?? call.parameters
354
+ if (!name) continue
340
355
  tool_calls.push({
341
356
  id: crypto.randomUUID(),
342
357
  type: "function",
343
358
  function: {
344
- name: toolNameMap.get(json.name) ?? json.name,
345
- arguments: typeof json.arguments === "object" ? JSON.stringify(json.arguments) : (json.arguments || "{}"),
359
+ name: toolNameMap.get(name) ?? name,
360
+ arguments: typeof args === "object" ? JSON.stringify(args) : (args || "{}"),
346
361
  },
347
362
  })
348
363
  extractedContent = extractedContent.replace(match[0], "").trim()
@@ -356,19 +371,28 @@ export function extractToolCallsFromText(
356
371
  // Fallback: entire output is a bare JSON tool call — only if name matches a known tool
357
372
  if (tool_calls.length === 0 && knownToolNames && knownToolNames.size > 0) {
358
373
  try {
359
- const json = JSON.parse(content.trim())
360
- const resolvedName = toolNameMap.get(json.name) ?? json.name
361
- if (json.name && knownToolNames.has(resolvedName) && (json.arguments || json.parameters)) {
362
- const args = json.arguments || json.parameters
363
- tool_calls.push({
364
- id: crypto.randomUUID(),
365
- type: "function",
366
- function: {
367
- name: resolvedName,
368
- arguments: typeof args === "object" ? JSON.stringify(args) : (args || "{}"),
369
- },
370
- })
371
- extractedContent = ""
374
+ const trimmed = content.trim()
375
+ // Strip common markdown fences before parsing.
376
+ const jsonText = trimmed.replace(/^```(?:json|tool_call)?\s*|\s*```$/g, "").trim()
377
+ const json = JSON.parse(jsonText)
378
+ const calls = Array.isArray(json) ? json : [json]
379
+ for (const call of calls) {
380
+ if (!call) continue
381
+ const fn = call.function || call
382
+ const name = fn.name ?? call.name
383
+ let args = fn.arguments ?? call.arguments ?? call.parameters
384
+ const resolvedName = toolNameMap.get(name) ?? name
385
+ if (name && knownToolNames.has(resolvedName) && (args !== undefined || calls.length === 1)) {
386
+ tool_calls.push({
387
+ id: crypto.randomUUID(),
388
+ type: "function",
389
+ function: {
390
+ name: resolvedName,
391
+ arguments: typeof args === "object" ? JSON.stringify(args) : (args || "{}"),
392
+ },
393
+ })
394
+ extractedContent = ""
395
+ }
372
396
  }
373
397
  } catch {
374
398
  // not valid JSON
@@ -0,0 +1,9 @@
1
+ import { OpenAICompatBase } from "./openai-compat-base"
2
+
3
+ export class OpenCodeGoProvider extends OpenAICompatBase {
4
+ static readonly secretKey = "OPENCODE_GO_API_KEY"
5
+
6
+ constructor() {
7
+ super("opencode-go")
8
+ }
9
+ }
@@ -11,7 +11,7 @@ import { getAgentLoop } from "../agent-loop"
11
11
  import { resolveUserId, resolveAgentId } from "../../storage/onboarding"
12
12
  import type { ContentPart } from "../../multimodal/types"
13
13
 
14
- export type Provider = "openai" | "anthropic" | "gemini" | "mistral" | "kimi" | "ollama" | "openrouter" | "deepseek" | "nvidia"
14
+ export type Provider = "openai" | "anthropic" | "gemini" | "mistral" | "kimi" | "ollama" | "openrouter" | "deepseek" | "nvidia" | "hiveagents"
15
15
 
16
16
  export interface StepEvent {
17
17
  type: "text" | "plan" | "tool_call" | "tool_result"
@@ -96,6 +96,7 @@ export class AgentRunner {
96
96
  raw_user_message: options.rawUserMessage,
97
97
  },
98
98
  signal: options.signal,
99
+ onToken: options.onToken,
99
100
  }
100
101
  )
101
102
 
@@ -126,7 +127,7 @@ export class AgentRunner {
126
127
  } else {
127
128
  logger.debug(`[STREAM] Content empty or whitespace only, skipping accumulation`)
128
129
  }
129
- if (options.onToken) options.onToken(content)
130
+ if (options.onToken && !chunk.agent.streamed) options.onToken(content)
130
131
  } else {
131
132
  logger.debug(`[STREAM] No content in chunk, lastMsg.content is falsy`)
132
133
  }
@@ -9,18 +9,26 @@ interface ToolCallRecord {
9
9
  timestamp: number;
10
10
  }
11
11
 
12
- interface StuckLoopState {
12
+ interface ProgressRecord {
13
+ hash: string;
14
+ timestamp: number;
15
+ }
16
+
17
+ export interface StuckLoopState {
13
18
  detected: boolean;
14
19
  toolName: string;
15
20
  count: number;
16
21
  lastError?: string;
22
+ kind: "loop" | "stall";
17
23
  }
18
24
 
19
25
  export class StuckLoopDetector {
20
26
  private log = logger.child("stuck-loop");
21
27
  private history: Map<string, ToolCallRecord[]> = new Map();
28
+ private progressHistory: Map<string, ProgressRecord[]> = new Map();
22
29
  private readonly maxHistoryPerSession = 50;
23
30
  private readonly triggerThreshold = 3;
31
+ private readonly progressThreshold = 3;
24
32
 
25
33
  constructor(_config: Config) {}
26
34
 
@@ -54,9 +62,9 @@ export class StuckLoopDetector {
54
62
 
55
63
  check(sessionId: string): StuckLoopState {
56
64
  const sessionHistory = this.history.get(sessionId) ?? [];
57
-
65
+
58
66
  if (sessionHistory.length < this.triggerThreshold) {
59
- return { detected: false, toolName: "", count: 0 };
67
+ return { detected: false, toolName: "", count: 0, kind: "loop" };
60
68
  }
61
69
 
62
70
  const recent = sessionHistory.slice(-10);
@@ -65,7 +73,7 @@ export class StuckLoopDetector {
65
73
  for (const record of recent) {
66
74
  const key = `${record.toolName}:${record.argsHash}`;
67
75
  const existing = counts.get(key);
68
-
76
+
69
77
  if (existing) {
70
78
  existing.count++;
71
79
  if (record.errorMessage) {
@@ -79,33 +87,73 @@ export class StuckLoopDetector {
79
87
  for (const [key, data] of counts) {
80
88
  if (data.count >= this.triggerThreshold && data.error) {
81
89
  const toolName = key.split(":")[0] ?? "unknown";
82
-
90
+
83
91
  this.log.warn(`Stuck loop detected: ${toolName} called ${data.count} times with same args and error`);
84
-
92
+
85
93
  return {
86
94
  detected: true,
87
95
  toolName,
88
96
  count: data.count,
89
97
  lastError: data.error,
98
+ kind: "loop",
90
99
  };
91
100
  }
92
101
  }
93
102
 
94
- return { detected: false, toolName: "", count: 0 };
103
+ return { detected: false, toolName: "", count: 0, kind: "loop" };
104
+ }
105
+
106
+ /**
107
+ * Record a progress snapshot hash. Use this to detect when the agent is not
108
+ * advancing even though no tool errors are occurring.
109
+ */
110
+ recordProgress(sessionId: string, progressHash: string): void {
111
+ let sessionProgress = this.progressHistory.get(sessionId);
112
+ if (!sessionProgress) {
113
+ sessionProgress = [];
114
+ this.progressHistory.set(sessionId, sessionProgress);
115
+ }
116
+
117
+ sessionProgress.push({ hash: progressHash, timestamp: Date.now() });
118
+
119
+ if (sessionProgress.length > this.maxHistoryPerSession) {
120
+ sessionProgress.shift();
121
+ }
122
+
123
+ this.log.debug(`Recorded progress hash for session ${sessionId}: ${progressHash}`);
95
124
  }
96
125
 
97
- getInterventionMessage(state: StuckLoopState): string | null {
98
- if (!state.detected) return null;
126
+ /**
127
+ * Detect lack of progress when the same hash appears repeatedly.
128
+ */
129
+ checkProgress(sessionId: string, threshold?: number): StuckLoopState {
130
+ const sessionProgress = this.progressHistory.get(sessionId) ?? [];
131
+ const required = threshold ?? this.progressThreshold;
132
+
133
+ if (sessionProgress.length < required) {
134
+ return { detected: false, toolName: "", count: 0, kind: "stall" };
135
+ }
99
136
 
100
- if (state.count >= this.triggerThreshold + 1) {
101
- return `CRITICAL: You have called ${state.toolName} ${state.count} times with the same arguments and it keeps failing with: "${state.lastError}". The user has been notified. You MUST try a completely different approach or ask the user for guidance.`;
137
+ const recent = sessionProgress.slice(-required);
138
+ const firstHash = recent[0]?.hash;
139
+ const allSame = recent.every((r) => r.hash === firstHash);
140
+
141
+ if (allSame && firstHash) {
142
+ this.log.warn(`Stall detected: no progress for ${required} checks (hash ${firstHash})`);
143
+ return {
144
+ detected: true,
145
+ toolName: "NO_PROGRESS",
146
+ count: required,
147
+ kind: "stall",
148
+ };
102
149
  }
103
150
 
104
- return `WARNING: You have called ${state.toolName} ${state.count} times with the same arguments and it keeps failing. You MUST try a completely different approach instead of repeating the same action.`;
151
+ return { detected: false, toolName: "", count: 0, kind: "stall" };
105
152
  }
106
153
 
107
154
  clear(sessionId: string): void {
108
155
  this.history.delete(sessionId);
156
+ this.progressHistory.delete(sessionId);
109
157
  this.log.debug(`Cleared stuck loop history for session ${sessionId}`);
110
158
  }
111
159
 
@@ -114,8 +162,8 @@ export class StuckLoopDetector {
114
162
  let pruned = 0;
115
163
 
116
164
  for (const [sessionId, history] of this.history) {
117
- const filtered = history.filter(r => now - r.timestamp < maxAgeMs);
118
-
165
+ const filtered = history.filter((r) => now - r.timestamp < maxAgeMs);
166
+
119
167
  if (filtered.length === 0) {
120
168
  this.history.delete(sessionId);
121
169
  pruned++;
@@ -124,6 +172,17 @@ export class StuckLoopDetector {
124
172
  }
125
173
  }
126
174
 
175
+ for (const [sessionId, history] of this.progressHistory) {
176
+ const filtered = history.filter((r) => now - r.timestamp < maxAgeMs);
177
+
178
+ if (filtered.length === 0) {
179
+ this.progressHistory.delete(sessionId);
180
+ pruned++;
181
+ } else if (filtered.length !== history.length) {
182
+ this.progressHistory.set(sessionId, filtered);
183
+ }
184
+ }
185
+
127
186
  return pruned;
128
187
  }
129
188
  }
@@ -131,3 +190,20 @@ export class StuckLoopDetector {
131
190
  export function createStuckLoopDetector(config: Config): StuckLoopDetector {
132
191
  return new StuckLoopDetector(config);
133
192
  }
193
+
194
+ /**
195
+ * Build a human-readable intervention message for the model.
196
+ */
197
+ export function getInterventionMessage(state: StuckLoopState): string {
198
+ if (!state.detected) return "";
199
+
200
+ if (state.kind === "stall") {
201
+ return `WARNING: Has estado sin avanzar durante ${state.count} ciclos consecutivos. Revisa tu plan, intenta una herramienta diferente o pide aclaración al usuario en lugar de repetir la misma secuencia.`;
202
+ }
203
+
204
+ if (state.count >= 4) {
205
+ return `CRITICAL: Has llamado ${state.toolName} ${state.count} veces con los mismos argumentos y sigue fallando con: "${state.lastError}". El usuario será notificado. Debes cambiar completamente de estrategia o pedir ayuda.`;
206
+ }
207
+
208
+ return `WARNING: Has llamado ${state.toolName} ${state.count} veces con los mismos argumentos y sigue fallando. Debes probar un enfoque diferente en lugar de repetir la misma acción.`;
209
+ }
@@ -1,12 +1,18 @@
1
1
  export interface OutboundMessage {
2
- type: "message" | "stream" | "status" | "error" | "pong" | "command_result" | "log" | "typing" | "audio";
2
+ type: "message" | "stream" | "status" | "error" | "pong" | "command_result" | "log" | "typing" | "audio" | "process";
3
3
  sessionId: string;
4
4
  id?: string; // Message ID for streaming
5
+ messageId?: string;
5
6
  content?: string;
6
7
  chunk?: string;
7
8
  isChunk?: boolean; // True if this is a streaming chunk
8
9
  isLast?: boolean;
9
10
  isStep?: boolean;
11
+ processKind?: "analysis" | "tool" | "observation" | "writing";
12
+ processStatus?: "thinking" | "done" | "error";
13
+ label?: string;
14
+ detail?: string;
15
+ summary?: string;
10
16
  stepType?: "plan" | "tool_call" | "tool_result" | "text";
11
17
  audio?: {
12
18
  buffer?: Buffer;
@@ -11,6 +11,7 @@ import type { ChannelConfig, IncomingMessage, OutboundMessage } from "./base.ts"
11
11
  import { BaseChannel } from "./base.ts";
12
12
  import { existsSync, mkdirSync, rmSync } from "node:fs";
13
13
  import * as path from "node:path";
14
+ import { homedir } from "node:os";
14
15
  import { logger } from "../utils/logger.ts";
15
16
  import { getDb } from "../storage/sqlite.ts";
16
17
  // @ts-ignore — no type definitions for qrcode-terminal
@@ -69,7 +70,7 @@ export class WhatsAppChannel extends BaseChannel {
69
70
  }
70
71
 
71
72
  private getAuthPath(agentId: string, accountId: string): string {
72
- const baseDir = process.env.HOME ?? "";
73
+ const baseDir = homedir();
73
74
  const authDir = path.join(baseDir, ".hive", "agents", agentId, "whatsapp", accountId);
74
75
 
75
76
  if (!existsSync(authDir)) {
@@ -117,11 +118,22 @@ export class WhatsAppChannel extends BaseChannel {
117
118
  this.connectionState.waVersion = version.join(".");
118
119
  this.log.info(`Using WhatsApp Web v${version.join(".")}`);
119
120
 
121
+ const baileysLogger = {
122
+ level: "silent",
123
+ child: () => baileysLogger,
124
+ trace: () => {},
125
+ debug: () => {},
126
+ info: (msg: unknown) => { if (typeof msg === "object" && msg !== null) this.log.debug((msg as any).msg ?? JSON.stringify(msg)); },
127
+ warn: (msg: unknown) => { if (typeof msg === "object" && msg !== null) this.log.warn((msg as any).msg ?? JSON.stringify(msg)); },
128
+ error: (msg: unknown) => { if (typeof msg === "object" && msg !== null) this.log.error((msg as any).msg ?? JSON.stringify(msg)); },
129
+ };
130
+
120
131
  this.socket = makeWASocket({
121
132
  version,
122
133
  auth: state,
123
134
  printQRInTerminal: false,
124
135
  syncFullHistory: false,
136
+ logger: baileysLogger as any,
125
137
  getMessage: async () => ({ conversation: "" }),
126
138
  });
127
139
 
@@ -1,7 +1,7 @@
1
1
  import * as z from "zod";
2
2
  import { mkdirSync, existsSync, readFileSync } from "node:fs";
3
3
  import * as path from "node:path";
4
- import { availableParallelism } from "node:os";
4
+ import { availableParallelism, homedir } from "node:os";
5
5
 
6
6
  const LogLevelSchema = z.enum(["debug", "info", "warn", "error"]);
7
7
  const DMPolicySchema = z.enum(["open", "pairing", "allowlist"]);
@@ -33,7 +33,7 @@ export function getHiveDir(): string {
33
33
  // Priority 1: HIVE_HOME explicitly set
34
34
  if (process.env.HIVE_HOME) {
35
35
  const hiveDir = process.env.HIVE_HOME.startsWith("~")
36
- ? path.join(process.env.HOME || "", process.env.HIVE_HOME.slice(1))
36
+ ? path.join(homedir(), process.env.HIVE_HOME.slice(1))
37
37
  : process.env.HIVE_HOME;
38
38
  loadEnv(hiveDir);
39
39
  return hiveDir;
@@ -49,7 +49,7 @@ export function getHiveDir(): string {
49
49
  }
50
50
 
51
51
  // Priority 3: Default ~/.hive
52
- const defaultDir = path.join(process.env.HOME || "", ".hive");
52
+ const defaultDir = path.join(homedir(), ".hive");
53
53
  loadEnv(defaultDir);
54
54
  return defaultDir;
55
55
  }
@@ -60,7 +60,7 @@ const expandPath = (p: string): string => {
60
60
  return p.replace("~/.hive", hiveDir);
61
61
  }
62
62
  if (p.startsWith("~")) {
63
- return path.join(process.env.HOME || "", p.slice(1));
63
+ return path.join(homedir(), p.slice(1));
64
64
  }
65
65
  return p;
66
66
  };
@@ -117,9 +117,9 @@ const WebConfigSchema = z.object({
117
117
 
118
118
  const BrowserConfigSchema = z.object({
119
119
  enabled: z.boolean().optional(),
120
- cdpUrl: z.string().optional(),
121
120
  headless: z.boolean().optional(),
122
121
  timeoutMs: z.number().optional(),
122
+ sessionName: z.string().optional(),
123
123
  });
124
124
 
125
125
  const CanvasConfigSchema = z.object({
@@ -290,7 +290,7 @@ const GatewayConfigSchema = z.object({
290
290
  });
291
291
 
292
292
  const ModelsConfigSchema = z.object({
293
- defaultProvider: z.enum(["openai", "anthropic", "gemini", "mistral", "kimi", "ollama", "openrouter", "deepseek"]).optional(),
293
+ defaultProvider: z.enum(["openai", "anthropic", "gemini", "mistral", "kimi", "ollama", "openrouter", "deepseek", "hiveagents"]).optional(),
294
294
  defaults: z.record(z.string(), z.string()).optional(),
295
295
  providers: z.record(z.string(), ProviderConfigSchema).optional(),
296
296
  });
@@ -437,7 +437,7 @@ function buildDefaultConfig(): Config {
437
437
  allowlist: [],
438
438
  denylist: ["rm -rf /", "sudo", "chmod 777", "> /dev/", "mkfs"],
439
439
  timeoutSeconds: 30,
440
- workDir: path.join(process.env.HOME || "", "exec"), // Points to home for exec by default
440
+ workDir: path.join(homedir(), "exec"), // Points to home for exec by default
441
441
  },
442
442
  web: {
443
443
  allowlist: [],
@@ -446,9 +446,9 @@ function buildDefaultConfig(): Config {
446
446
  },
447
447
  browser: {
448
448
  enabled: true,
449
- cdpUrl: "ws://127.0.0.1:9222",
450
449
  headless: true,
451
450
  timeoutMs: 30000,
451
+ sessionName: "hive",
452
452
  },
453
453
  canvas: {
454
454
  enabled: true,
@@ -1,4 +1,5 @@
1
1
  import * as path from "node:path";
2
+ import { homedir } from "node:os";
2
3
 
3
4
  /**
4
5
  * Expands a path that starts with ~ to the user's home directory.
@@ -7,7 +8,7 @@ import * as path from "node:path";
7
8
  */
8
9
  export function expandPath(p: string): string {
9
10
  if (p.startsWith("~")) {
10
- return path.join(process.env.HOME ?? "", p.slice(1));
11
+ return path.join(homedir(), p.slice(1));
11
12
  }
12
13
  return p;
13
14
  }
@@ -250,11 +250,11 @@ export async function initializeGateway(
250
250
  const agent = createAgentService();
251
251
  await agent.initialize();
252
252
 
253
- // 5b. Initialize Browser Service (Chrome via Bun.WebView nativo)
253
+ // 5b. Initialize Browser Service (agent-browser CLI)
254
254
  let browserAvailable = false;
255
255
 
256
256
  try {
257
- log.info("Detecting browser (lazy launch — will open on first agent use)...");
257
+ log.info("Initializing browser automation (agent-browser)...");
258
258
 
259
259
  const browserService = initializeBrowserService(config);
260
260
  browserAvailable = await browserService.start();
@@ -262,8 +262,8 @@ export async function initializeGateway(
262
262
  if (browserAvailable) {
263
263
  activateBrowserTools();
264
264
  } else {
265
- log.warn("⚠️ No se encontró Chrome/Chromium - browser tools desactivadas");
266
- log.warn(" Linux: sudo dnf install chromium | macOS: brew install --cask google-chrome");
265
+ log.warn("⚠️ agent-browser no disponible - browser tools desactivadas");
266
+ log.warn(" Se instalará automáticamente en primer uso o manual: bun add -g agent-browser");
267
267
  }
268
268
  } catch (error) {
269
269
  log.warn(`Browser Service initialization skipped: ${(error as Error).message}`);