@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
@@ -18,22 +18,116 @@ export const MODELS_DIR = join(LLM_ROOT, "models")
18
18
  if (!existsSync(BIN_DIR)) mkdirSync(BIN_DIR, { recursive: true })
19
19
  if (!existsSync(MODELS_DIR)) mkdirSync(MODELS_DIR, { recursive: true })
20
20
 
21
- /** URLs de modelos en HuggingFace (Gemma 4 según GUIA-SERVIDOR.md) */
21
+ /** URLs de modelos en HuggingFace (Gemma 4 y Qwen 3.5 según Unsloth) */
22
22
  export const HF_MODEL_URLS = {
23
+ // mmproj legacy (E4B)
23
24
  mmproj: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/mmproj-BF16.gguf",
25
+ // mmproj Gemma 4
26
+ mmproj_gemma4_12b: "https://huggingface.co/unsloth/gemma-4-12b-it-GGUF/resolve/main/mmproj-BF16.gguf",
27
+ mmproj_gemma4_26b: "https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/mmproj-BF16.gguf",
28
+ mmproj_gemma4_31b: "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/mmproj-BF16.gguf",
29
+ // mmproj Qwen 3.5
30
+ mmproj_qwen3_5_2b: "https://huggingface.co/unsloth/Qwen3.5-2B-GGUF/resolve/main/mmproj-F16.gguf",
31
+ mmproj_qwen3_5_4b: "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/mmproj-F16.gguf",
32
+ mmproj_qwen3_5_9b: "https://huggingface.co/unsloth/Qwen3.5-9B-GGUF/resolve/main/mmproj-F16.gguf",
33
+ mmproj_qwen3_5_27b: "https://huggingface.co/unsloth/Qwen3.5-27B-GGUF/resolve/main/mmproj-F16.gguf",
34
+ mmproj_qwen3_5_35b: "https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/mmproj-F16.gguf",
35
+ // modelos Gemma 4
24
36
  e2b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-UD-Q4_K_XL.gguf",
25
- e4b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-UD-Q4_K_XL.gguf"
37
+ e4b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-UD-Q4_K_XL.gguf",
38
+ gemma4_12b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-12b-it-GGUF/resolve/main/gemma-4-12b-it-UD-Q4_K_XL.gguf",
39
+ gemma4_26b_Q4_K_M: "https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf",
40
+ gemma4_31b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-UD-Q4_K_XL.gguf",
41
+ // modelos Qwen 3.5
42
+ qwen3_5_2b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-2B-GGUF/resolve/main/Qwen3.5-2B-UD-Q4_K_XL.gguf",
43
+ qwen3_5_4b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-UD-Q4_K_XL.gguf",
44
+ qwen3_5_9b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-9B-GGUF/resolve/main/Qwen3.5-9B-UD-Q4_K_XL.gguf",
45
+ qwen3_5_27b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-27B-GGUF/resolve/main/Qwen3.5-27B-UD-Q4_K_XL.gguf",
46
+ qwen3_5_35b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/Qwen3.5-35B-A3B-UD-Q4_K_XL.gguf",
26
47
  }
27
48
 
28
- export type ModelId = "mmproj" | "e2b_Q4_K_XL" | "e4b_Q4_K_XL"
49
+ export type ModelId =
50
+ | "mmproj"
51
+ | "mmproj_gemma4_12b"
52
+ | "mmproj_gemma4_26b"
53
+ | "mmproj_gemma4_31b"
54
+ | "mmproj_qwen3_5_2b"
55
+ | "mmproj_qwen3_5_4b"
56
+ | "mmproj_qwen3_5_9b"
57
+ | "mmproj_qwen3_5_27b"
58
+ | "mmproj_qwen3_5_35b"
59
+ | "e2b_Q4_K_XL"
60
+ | "e4b_Q4_K_XL"
61
+ | "gemma4_12b_Q4_K_XL"
62
+ | "gemma4_26b_Q4_K_M"
63
+ | "gemma4_31b_Q4_K_XL"
64
+ | "qwen3_5_2b_Q4_K_XL"
65
+ | "qwen3_5_4b_Q4_K_XL"
66
+ | "qwen3_5_9b_Q4_K_XL"
67
+ | "qwen3_5_27b_Q4_K_XL"
68
+ | "qwen3_5_35b_Q4_K_XL"
29
69
 
30
70
  /** Modelos que requieren proyector de visión (mmproj) */
31
- export const VISION_MODELS: ModelId[] = ["e4b_Q4_K_XL"]
71
+ export const VISION_MODELS: ModelId[] = [
72
+ "e4b_Q4_K_XL",
73
+ "gemma4_12b_Q4_K_XL",
74
+ "gemma4_26b_Q4_K_M",
75
+ "gemma4_31b_Q4_K_XL",
76
+ "qwen3_5_2b_Q4_K_XL",
77
+ "qwen3_5_4b_Q4_K_XL",
78
+ "qwen3_5_9b_Q4_K_XL",
79
+ "qwen3_5_27b_Q4_K_XL",
80
+ "qwen3_5_35b_Q4_K_XL",
81
+ ]
82
+
83
+ /** Mapeo de cada modelo a su mmproj correspondiente */
84
+ export const MODEL_MMPROJ_MAP: Record<ModelId, ModelId | undefined> = {
85
+ mmproj: undefined,
86
+ mmproj_gemma4_12b: undefined,
87
+ mmproj_gemma4_26b: undefined,
88
+ mmproj_gemma4_31b: undefined,
89
+ mmproj_qwen3_5_2b: undefined,
90
+ mmproj_qwen3_5_4b: undefined,
91
+ mmproj_qwen3_5_9b: undefined,
92
+ mmproj_qwen3_5_27b: undefined,
93
+ mmproj_qwen3_5_35b: undefined,
94
+ e2b_Q4_K_XL: undefined,
95
+ e4b_Q4_K_XL: "mmproj",
96
+ gemma4_12b_Q4_K_XL: "mmproj_gemma4_12b",
97
+ gemma4_26b_Q4_K_M: "mmproj_gemma4_26b",
98
+ gemma4_31b_Q4_K_XL: "mmproj_gemma4_31b",
99
+ qwen3_5_2b_Q4_K_XL: "mmproj_qwen3_5_2b",
100
+ qwen3_5_4b_Q4_K_XL: "mmproj_qwen3_5_4b",
101
+ qwen3_5_9b_Q4_K_XL: "mmproj_qwen3_5_9b",
102
+ qwen3_5_27b_Q4_K_XL: "mmproj_qwen3_5_27b",
103
+ qwen3_5_35b_Q4_K_XL: "mmproj_qwen3_5_35b",
104
+ }
105
+
106
+ /** Devuelve el ID del mmproj asociado a un modelo, o undefined si no requiere visión */
107
+ export function getModelMMProjId(modelId: ModelId): ModelId | undefined {
108
+ return MODEL_MMPROJ_MAP[modelId]
109
+ }
32
110
 
33
111
  export const MODEL_FILES: Record<ModelId, string> = {
34
112
  mmproj: "mmproj-BF16.gguf",
113
+ mmproj_gemma4_12b: "mmproj-gemma4-12b-BF16.gguf",
114
+ mmproj_gemma4_26b: "mmproj-gemma4-26b-BF16.gguf",
115
+ mmproj_gemma4_31b: "mmproj-gemma4-31b-BF16.gguf",
116
+ mmproj_qwen3_5_2b: "mmproj-qwen3.5-2b-F16.gguf",
117
+ mmproj_qwen3_5_4b: "mmproj-qwen3.5-4b-F16.gguf",
118
+ mmproj_qwen3_5_9b: "mmproj-qwen3.5-9b-F16.gguf",
119
+ mmproj_qwen3_5_27b: "mmproj-qwen3.5-27b-F16.gguf",
120
+ mmproj_qwen3_5_35b: "mmproj-qwen3.5-35b-F16.gguf",
35
121
  e2b_Q4_K_XL: "gemma-4-E2B-it-UD-Q4_K_XL.gguf",
36
122
  e4b_Q4_K_XL: "gemma-4-E4B-it-UD-Q4_K_XL.gguf",
123
+ gemma4_12b_Q4_K_XL: "gemma-4-12b-it-UD-Q4_K_XL.gguf",
124
+ gemma4_26b_Q4_K_M: "gemma-4-26B-A4B-it-UD-Q4_K_M.gguf",
125
+ gemma4_31b_Q4_K_XL: "gemma-4-31B-it-UD-Q4_K_XL.gguf",
126
+ qwen3_5_2b_Q4_K_XL: "Qwen3.5-2B-UD-Q4_K_XL.gguf",
127
+ qwen3_5_4b_Q4_K_XL: "Qwen3.5-4B-UD-Q4_K_XL.gguf",
128
+ qwen3_5_9b_Q4_K_XL: "Qwen3.5-9B-UD-Q4_K_XL.gguf",
129
+ qwen3_5_27b_Q4_K_XL: "Qwen3.5-27B-UD-Q4_K_XL.gguf",
130
+ qwen3_5_35b_Q4_K_XL: "Qwen3.5-35B-A3B-UD-Q4_K_XL.gguf",
37
131
  }
38
132
 
39
133
  export function getModelPath(modelId: ModelId): string {
@@ -65,13 +159,14 @@ export async function downloadFile(
65
159
  const { done, value } = await reader.read()
66
160
  if (done) break
67
161
 
68
- writer.write(value)
162
+ await writer.write(value)
69
163
  downloaded += value.byteLength
70
164
  if (onProgress) onProgress(downloaded, total)
71
165
  }
166
+ await writer.flush()
72
167
  await writer.end()
73
168
  } catch (err) {
74
- await writer.end()
169
+ try { await writer.end() } catch { /* ignore */ }
75
170
  throw err
76
171
  }
77
172
  }
@@ -191,9 +286,10 @@ export async function downloadModel(
191
286
  await downloadFile(url, dest, onProgress)
192
287
  console.log(`[hive-local] ✓ Modelo ${modelId} descargado`)
193
288
 
194
- // Advertir si el modelo requiere visión y no tenemos mmproj (NO descargar automáticamente)
195
- if (VISION_MODELS.includes(modelId) && !isModelDownloaded("mmproj")) {
196
- console.warn(`[hive-local] ⚠️ El modelo ${modelId} requiere el proyector de visión (mmproj). Descárgalo manualmente desde la UI.`)
289
+ // Advertir si el modelo requiere visión y no tenemos su mmproj (NO descargar automáticamente)
290
+ const mmprojId = getModelMMProjId(modelId)
291
+ if (mmprojId && !isModelDownloaded(mmprojId)) {
292
+ console.warn(`[hive-local] ⚠️ El modelo ${modelId} requiere el proyector de visión (${mmprojId}). Descárgalo manualmente desde la UI.`)
197
293
  }
198
294
 
199
295
  return dest
@@ -206,11 +302,34 @@ export async function installMMProj(): Promise<string> {
206
302
 
207
303
  /** Lista modelos disponibles localmente (solo modelos de texto/visión finales) */
208
304
  export function listLocalModels(): { id: ModelId; name: string; size: string; downloaded: boolean }[] {
209
- const models: ModelId[] = ["e2b_Q4_K_XL", "e4b_Q4_K_XL"]
305
+ const models: ModelId[] = [
306
+ "e2b_Q4_K_XL",
307
+ "e4b_Q4_K_XL",
308
+ "gemma4_12b_Q4_K_XL",
309
+ "gemma4_26b_Q4_K_M",
310
+ "gemma4_31b_Q4_K_XL",
311
+ "qwen3_5_2b_Q4_K_XL",
312
+ "qwen3_5_4b_Q4_K_XL",
313
+ "qwen3_5_9b_Q4_K_XL",
314
+ "qwen3_5_27b_Q4_K_XL",
315
+ "qwen3_5_35b_Q4_K_XL",
316
+ ]
317
+ const sizeMap: Record<string, string> = {
318
+ e2b_Q4_K_XL: "~3 GB",
319
+ e4b_Q4_K_XL: "~5 GB",
320
+ gemma4_12b_Q4_K_XL: "~7 GB",
321
+ gemma4_26b_Q4_K_M: "~10 GB",
322
+ gemma4_31b_Q4_K_XL: "~14 GB",
323
+ qwen3_5_2b_Q4_K_XL: "~1.2 GB",
324
+ qwen3_5_4b_Q4_K_XL: "~2.5 GB",
325
+ qwen3_5_9b_Q4_K_XL: "~5.4 GB",
326
+ qwen3_5_27b_Q4_K_XL: "~16 GB",
327
+ qwen3_5_35b_Q4_K_XL: "~21 GB",
328
+ }
210
329
  return models.map((id) => ({
211
330
  id,
212
331
  name: MODEL_FILES[id],
213
- size: id.includes("Q4_K_XL") ? "~5-8 GB" : "~2-3 GB",
332
+ size: sizeMap[id] || "~?",
214
333
  downloaded: isModelDownloaded(id),
215
334
  }))
216
335
  }
@@ -15,9 +15,11 @@ export {
15
15
  listLocalModels,
16
16
  isModelDownloaded,
17
17
  getModelPath,
18
+ getModelMMProjId,
18
19
  BIN_DIR,
19
20
  MODELS_DIR,
20
21
  HF_MODEL_URLS,
22
+ MODEL_MMPROJ_MAP,
21
23
  } from "./downloader"
22
24
  export type { ModelId } from "./downloader"
23
25
 
@@ -5,7 +5,7 @@
5
5
 
6
6
 
7
7
  import { existsSync } from "fs"
8
- import { MODELS_DIR, getModelPath, type ModelId } from "./downloader"
8
+ import { MODELS_DIR, getModelPath, getModelMMProjId, type ModelId } from "./downloader"
9
9
 
10
10
  export interface ModelConfig {
11
11
  modelPath: string
@@ -43,8 +43,9 @@ export function getModelConfig(modelId: ModelId, port: number = 8081): ModelConf
43
43
  throw new Error(`Modelo no descargado: ${modelId}. Ejecuta downloadModel("${modelId}") primero.`)
44
44
  }
45
45
 
46
- const mmprojPath = getModelPath("mmproj")
47
- const hasMMProj = existsSync(mmprojPath)
46
+ const mmprojId = getModelMMProjId(modelId)
47
+ const mmprojPath = mmprojId ? getModelPath(mmprojId) : undefined
48
+ const hasMMProj = mmprojPath ? existsSync(mmprojPath) : false
48
49
 
49
50
  return {
50
51
  modelPath,
@@ -1,4 +1,6 @@
1
1
  import type { Config, Binding } from "../config/loader.ts";
2
+ import { homedir } from "node:os";
3
+ import * as path from "node:path";
2
4
 
3
5
  export interface RoutingContext {
4
6
  channel: string;
@@ -113,12 +115,12 @@ export class Router {
113
115
  const agent = agents.find((a) => a.id === agentId);
114
116
 
115
117
  if (agent?.workspace) {
116
- return agent.workspace.replace(/^~/, process.env.HOME ?? "");
118
+ return agent.workspace.replace(/^~/, homedir());
117
119
  }
118
120
 
119
- const baseDir = this.config.agent?.baseDir?.replace(/^~/, process.env.HOME ?? "")
120
- ?? `${process.env.HOME}/.hive/agents`;
121
-
122
- return `${baseDir}/${agentId}/workspace`;
121
+ const baseDir = this.config.agent?.baseDir?.replace(/^~/, homedir())
122
+ ?? path.join(homedir(), ".hive", "agents");
123
+
124
+ return path.join(baseDir, agentId, "workspace");
123
125
  }
124
126
  }
@@ -0,0 +1,16 @@
1
+ import { apiRequestTool } from "../../tools/api/api-request.ts";
2
+
3
+ export async function handleHttpRequest(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
4
+ try {
5
+ const body = await req.json().catch(() => ({}));
6
+
7
+ const result = await apiRequestTool.execute(body, { configurable: {} });
8
+
9
+ return addCorsHeaders(Response.json(result), req);
10
+ } catch (error) {
11
+ return addCorsHeaders(Response.json({
12
+ ok: false,
13
+ error: `Request failed: ${(error as Error).message}`,
14
+ }), req);
15
+ }
16
+ }
@@ -19,6 +19,15 @@ let installing = false
19
19
  let installLogs: string[] = []
20
20
  let downloadingModelId: string | null = null
21
21
 
22
+ interface DownloadProgress {
23
+ modelId: string
24
+ downloaded: number
25
+ total: number
26
+ percent: number
27
+ }
28
+
29
+ let currentDownloadProgress: DownloadProgress | null = null
30
+
22
31
  async function getInstalledStatus() {
23
32
  const { LLAMA_CPP_DEFAULT_VER } = await import("../llm-local/detector")
24
33
  const gpu = await detectGPU()
@@ -183,7 +192,12 @@ export async function handleDownloadLLMModel(
183
192
  ;(async () => {
184
193
  try {
185
194
  await downloadModel(modelId, (d, t) => {
186
- // Opcional: Podríamos emitir eventos por WS si quisiéramos progreso real en UI
195
+ currentDownloadProgress = {
196
+ modelId,
197
+ downloaded: d,
198
+ total: t,
199
+ percent: t > 0 ? Math.round((d / t) * 100) : 0,
200
+ }
187
201
  })
188
202
  installLogs.push(`✓ Modelo ${modelId} descargado exitosamente`)
189
203
  } catch (err) {
@@ -191,6 +205,7 @@ export async function handleDownloadLLMModel(
191
205
  installLogs.push(`[error] Error descargando ${modelId}: ${msg}`)
192
206
  } finally {
193
207
  downloadingModelId = null
208
+ currentDownloadProgress = null
194
209
  }
195
210
  })()
196
211
 
@@ -207,7 +222,15 @@ export async function handleStartLocalLLM(
207
222
  } catch { /* ignore if no body */ }
208
223
 
209
224
  const mode = body.mode || "TEXT"
210
- const modelId = body.modelId || getRecommendedModel(mode.toLowerCase() as any)
225
+ // If no modelId specified, prefer the recommended model; fall back to the
226
+ // first downloaded model so the user doesn't get an error when they only
227
+ // downloaded a non-default model.
228
+ const recommended = getRecommendedModel(mode.toLowerCase() as any)
229
+ const allModels = listLocalModels()
230
+ const downloadedModels = allModels.filter(m => m.downloaded)
231
+ const resolvedModelId: string =
232
+ body.modelId ||
233
+ (downloadedModels.find(m => m.id === recommended) ? recommended : (downloadedModels[0]?.id ?? recommended))
211
234
 
212
235
  const status = await getInstalledStatus()
213
236
  if (!status.installed && !status.binaryExists) {
@@ -217,11 +240,18 @@ export async function handleStartLocalLLM(
217
240
  )
218
241
  }
219
242
 
243
+ if (downloadedModels.length === 0) {
244
+ return addCors(
245
+ Response.json({ started: false, reason: "No hay modelos descargados. Descarga un modelo primero desde la sección de modelos." }, { status: 400 }),
246
+ req
247
+ )
248
+ }
249
+
220
250
  try {
221
- installLogs.push(`[llm-server] Iniciando servidor en modo ${mode} con modelo ${modelId}...`)
222
- await llamaManager.start(mode, modelId as any)
251
+ installLogs.push(`[llm-server] Iniciando servidor en modo ${mode} con modelo ${resolvedModelId}...`)
252
+ await llamaManager.start(mode, resolvedModelId as any)
223
253
  installLogs.push(`[llm-server] Servidor ${mode} iniciado correctamente.`)
224
- return addCors(Response.json({ started: true, mode }), req)
254
+ return addCors(Response.json({ started: true, mode, modelId: resolvedModelId }), req)
225
255
  } catch (err) {
226
256
  const msg = err instanceof Error ? err.message : String(err)
227
257
  installLogs.push(`[error] Servidor LLM falló al iniciar: ${msg}`)
@@ -251,6 +281,22 @@ export async function handleStopLocalLLM(
251
281
  * Verifica el estado del LLM local al iniciar el gateway.
252
282
  * NO auto-inicia el servidor ni descarga nada — el usuario debe hacerlo manualmente.
253
283
  */
284
+ export async function handleGetDownloadProgress(
285
+ req: Request,
286
+ addCors: (r: Response, req: Request) => Response
287
+ ): Promise<Response> {
288
+ if (!currentDownloadProgress) {
289
+ return addCors(Response.json({ active: false }), req)
290
+ }
291
+ return addCors(
292
+ Response.json({
293
+ active: true,
294
+ ...currentDownloadProgress,
295
+ }),
296
+ req
297
+ )
298
+ }
299
+
254
300
  export async function initializeLocalLLM() {
255
301
  try {
256
302
  const status = await getInstalledStatus()
@@ -4,6 +4,11 @@ import {
4
4
  loadProviderApiKey, storeProviderApiKey,
5
5
  loadProviderHeaders, storeProviderHeaders,
6
6
  } from "../../storage/crypto"
7
+ import { listLocalModels } from "../llm-local/downloader"
8
+ import { loadHiveAgentsModel, getHiveAgentsModelStatus } from "../../agent/llm-providers/hiveagents"
9
+ import { logger } from "../../utils/logger"
10
+
11
+ const log = logger.child("gateway")
7
12
 
8
13
  export async function handleGetProviders(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
9
14
  const rawProviders = getDb().query(`
@@ -24,20 +29,60 @@ export async function handleGetProviders(req: Request, addCorsHeaders: (r: Respo
24
29
  })
25
30
  }
26
31
 
32
+ // Inyectar modelos locales descargados dinámicamente para local-llama
33
+ try {
34
+ const localModels = listLocalModels()
35
+ const downloadedLocalModels = localModels.filter(m => m.downloaded)
36
+ if (downloadedLocalModels.length > 0) {
37
+ const existingLocalModels = modelsByProvider["local-llama"] || []
38
+ for (const localModel of downloadedLocalModels) {
39
+ const existingIdx = existingLocalModels.findIndex((m: any) => m.id === localModel.id)
40
+ if (existingIdx === -1) {
41
+ existingLocalModels.push({
42
+ id: localModel.id,
43
+ name: localModel.name,
44
+ provider_id: "local-llama",
45
+ model_type: "llm",
46
+ context_window: 16000,
47
+ capabilities: JSON.stringify(["chat", "local"]),
48
+ enabled: true,
49
+ active: true,
50
+ })
51
+ } else {
52
+ // Modelo del seed ya existe pero está descargado: forzar activo
53
+ existingLocalModels[existingIdx] = {
54
+ ...existingLocalModels[existingIdx],
55
+ enabled: true,
56
+ active: true,
57
+ }
58
+ }
59
+ }
60
+ modelsByProvider["local-llama"] = existingLocalModels
61
+ }
62
+ } catch {
63
+ // Ignorar si no se pueden obtener modelos locales
64
+ }
65
+
27
66
  const providers = await Promise.all(rawProviders.map(async (p) => {
28
67
  const apiKey = await loadProviderApiKey(p.id as string)
29
68
  const headers = await loadProviderHeaders(p.id as string)
69
+ const providerModels = modelsByProvider[p.id as string] || []
70
+ // Auto-activar local-llama si tiene modelos descargados dinámicamente
71
+ let active = p.active
72
+ if (p.id === "local-llama" && providerModels.some((m: any) => m.active || m.enabled)) {
73
+ active = true
74
+ }
30
75
  return {
31
76
  id: p.id,
32
77
  name: p.name,
33
78
  base_url: p.base_url,
34
79
  enabled: p.enabled,
35
- active: p.active,
80
+ active,
36
81
  num_ctx: p.num_ctx ?? null,
37
82
  has_api_key: apiKey ? 1 : 0,
38
83
  has_headers: Object.keys(headers).length > 0 ? 1 : 0,
39
84
  masked_api_key: apiKey ? maskApiKey(apiKey) : null,
40
- models: modelsByProvider[p.id as string] || [],
85
+ models: providerModels,
41
86
  }
42
87
  }))
43
88
 
@@ -218,3 +263,55 @@ export async function handleSyncProviderModels(
218
263
  }, { status: 502 }), req)
219
264
  }
220
265
  }
266
+
267
+ export async function handleLoadHiveAgentsModel(
268
+ req: Request,
269
+ addCorsHeaders: (r: Response, req: Request) => Response
270
+ ): Promise<Response> {
271
+ const body = await req.json().catch(() => ({}))
272
+ const modelId = body.model_id || body.modelId
273
+ const ctx = typeof body.ctx === "number" && body.ctx > 0 ? body.ctx : 50000
274
+ if (!modelId) {
275
+ return addCorsHeaders(Response.json({ error: "model_id is required" }, { status: 400 }), req)
276
+ }
277
+
278
+ const providerRow = getDb().query("SELECT * FROM providers WHERE id = ?").get("hiveagents") as Record<string, unknown> | undefined
279
+ if (!providerRow) {
280
+ return addCorsHeaders(Response.json({ error: "Provider not found" }, { status: 404 }), req)
281
+ }
282
+
283
+ const apiKey = await loadProviderApiKey("hiveagents")
284
+ if (!apiKey) {
285
+ return addCorsHeaders(Response.json({ error: "API key not configured for hiveagents" }, { status: 400 }), req)
286
+ }
287
+
288
+ const baseUrl = providerRow.base_url as string | undefined
289
+ log.info(`[gateway] Loading hiveagents model ${modelId} with ctx=${ctx} via ${baseUrl || "https://llm.hiveagents.io"}`)
290
+
291
+ const result = await loadHiveAgentsModel(modelId as string, apiKey, baseUrl, ctx)
292
+ if (!result.success) {
293
+ log.error(`[gateway] Failed to load hiveagents model ${modelId}: ${result.error}`)
294
+ return addCorsHeaders(Response.json({ error: result.error }, { status: 502 }), req)
295
+ }
296
+ const isLoading = (result as any).loading === true
297
+ log.info(`[gateway] hiveagents load request accepted for ${modelId} with ctx=${ctx}${isLoading ? " (timeout/backend still loading)" : ""}`)
298
+ return addCorsHeaders(Response.json({ success: true, loading: isLoading, model_id: modelId, ctx }), req)
299
+ }
300
+
301
+ export async function handleGetHiveAgentsModelStatus(
302
+ req: Request,
303
+ addCorsHeaders: (r: Response, req: Request) => Response
304
+ ): Promise<Response> {
305
+ const providerRow = getDb().query("SELECT * FROM providers WHERE id = ?").get("hiveagents") as Record<string, unknown> | undefined
306
+ if (!providerRow) {
307
+ return addCorsHeaders(Response.json({ error: "Provider not found" }, { status: 404 }), req)
308
+ }
309
+
310
+ const apiKey = await loadProviderApiKey("hiveagents")
311
+ if (!apiKey) {
312
+ return addCorsHeaders(Response.json({ error: "API key not configured for hiveagents" }, { status: 400 }), req)
313
+ }
314
+
315
+ const status = await getHiveAgentsModelStatus(apiKey, providerRow.base_url as string | undefined)
316
+ return addCorsHeaders(Response.json({ success: true, ...status }), req)
317
+ }