@johpaz/hive-agents 0.0.39 → 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 (202) hide show
  1. package/README.md +29 -69
  2. package/dist/hive.js +2522 -1927
  3. package/dist/tool-worker.js +1791 -1334
  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-C-GSRk-N.js → assets/AgentsPage-WFy5abqx.js} +1 -1
  8. package/dist/ui/assets/ApiClientPage-BV7zLIL7.js +3 -0
  9. package/dist/ui/assets/{CanvasPage-Cvs5ctza.js → CanvasPage-B9zuIrTm.js} +1 -1
  10. package/dist/ui/assets/{ChannelsPage-C5m_L7P9.js → ChannelsPage-DiN3NvIM.js} +1 -1
  11. package/dist/ui/assets/{DashboardPage-CztbRQdm.js → DashboardPage-CHjARjVK.js} +1 -1
  12. package/dist/ui/assets/{LoginPage-OMsrx5oj.js → LoginPage-Dwd_XxoU.js} +1 -1
  13. package/dist/ui/{dist/assets/LogsPage-CcYYwjgF.js → assets/LogsPage-DW8Nnqe6.js} +1 -1
  14. package/dist/ui/assets/MeetingPage-D3bkiKYt.js +1 -0
  15. package/dist/ui/assets/{NotFound-GbAJDgoD.js → NotFound-BIUDlIXU.js} +1 -1
  16. package/dist/ui/assets/ProvidersPage-UqsDAxPQ.js +1 -0
  17. package/dist/ui/{dist/assets/RecoverPage-CwB2ByCU.js → assets/RecoverPage-8hTjr_JU.js} +1 -1
  18. package/dist/ui/assets/SettingsPage-DNa0jOkA.js +9 -0
  19. package/dist/ui/assets/{SetupPage-DOVh1ldK.js → SetupPage-Bdm2irQG.js} +1 -1
  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-D_2Y3qjL.js → assets/alert-DylmSCDJ.js} +1 -1
  23. package/dist/ui/{dist/assets/alert-dialog-CpMxaNcu.js → assets/alert-dialog-DNNWN_SI.js} +1 -1
  24. package/dist/ui/assets/{badge-CxTPR6_t.js → badge-ChENFgkC.js} +1 -1
  25. package/dist/ui/assets/chevron-down-DIosfU_U.js +1 -0
  26. package/dist/ui/assets/chevron-up-CI-W21Fy.js +1 -0
  27. package/dist/ui/{dist/assets/dialog-DfS3idb3.js → assets/dialog-BJ-npIv8.js} +1 -1
  28. package/dist/ui/assets/{dropdown-menu-BdCbAW1z.js → dropdown-menu-DDiaHg5y.js} +1 -1
  29. package/dist/ui/assets/{es-Cz5h9_84.js → es-ecSKCyB6.js} +1 -1
  30. package/dist/ui/assets/index-CawKP29y.js +116 -0
  31. package/dist/ui/assets/index-DIcsEkyd.css +2 -0
  32. package/dist/ui/{dist/assets/label-byJkqOYq.js → assets/label-Bi6udtSd.js} +1 -1
  33. package/dist/ui/assets/select-BQCOjM2j.js +1 -0
  34. package/dist/ui/assets/useProviders-Dlizq_8q.js +1 -0
  35. package/dist/ui/dist/assets/AgentCreateForm-b7xHyfNc.js +1 -0
  36. package/dist/ui/dist/assets/AgentDetailPage-VHy3M7mI.js +1 -0
  37. package/dist/ui/dist/assets/AgentNewPage-BnWImQMx.js +1 -0
  38. package/dist/ui/{assets/AgentsPage-C-GSRk-N.js → dist/assets/AgentsPage-WFy5abqx.js} +1 -1
  39. package/dist/ui/dist/assets/ApiClientPage-BV7zLIL7.js +3 -0
  40. package/dist/ui/dist/assets/{CanvasPage-Cvs5ctza.js → CanvasPage-B9zuIrTm.js} +1 -1
  41. package/dist/ui/dist/assets/{ChannelsPage-C5m_L7P9.js → ChannelsPage-DiN3NvIM.js} +1 -1
  42. package/dist/ui/dist/assets/{DashboardPage-CztbRQdm.js → DashboardPage-CHjARjVK.js} +1 -1
  43. package/dist/ui/dist/assets/{LoginPage-OMsrx5oj.js → LoginPage-Dwd_XxoU.js} +1 -1
  44. package/dist/ui/{assets/LogsPage-CcYYwjgF.js → dist/assets/LogsPage-DW8Nnqe6.js} +1 -1
  45. package/dist/ui/dist/assets/MeetingPage-D3bkiKYt.js +1 -0
  46. package/dist/ui/dist/assets/{NotFound-GbAJDgoD.js → NotFound-BIUDlIXU.js} +1 -1
  47. package/dist/ui/dist/assets/ProvidersPage-UqsDAxPQ.js +1 -0
  48. package/dist/ui/{assets/RecoverPage-CwB2ByCU.js → dist/assets/RecoverPage-8hTjr_JU.js} +1 -1
  49. package/dist/ui/dist/assets/SettingsPage-DNa0jOkA.js +9 -0
  50. package/dist/ui/dist/assets/{SetupPage-DOVh1ldK.js → SetupPage-Bdm2irQG.js} +1 -1
  51. package/dist/ui/dist/assets/WebChatPage-DElJg6P2.js +16 -0
  52. package/dist/ui/dist/assets/accordion-CnLzKNHK.js +1 -0
  53. package/dist/ui/{assets/alert-D_2Y3qjL.js → dist/assets/alert-DylmSCDJ.js} +1 -1
  54. package/dist/ui/{assets/alert-dialog-CpMxaNcu.js → dist/assets/alert-dialog-DNNWN_SI.js} +1 -1
  55. package/dist/ui/dist/assets/{badge-CxTPR6_t.js → badge-ChENFgkC.js} +1 -1
  56. package/dist/ui/dist/assets/chevron-down-DIosfU_U.js +1 -0
  57. package/dist/ui/dist/assets/chevron-up-CI-W21Fy.js +1 -0
  58. package/dist/ui/{assets/dialog-DfS3idb3.js → dist/assets/dialog-BJ-npIv8.js} +1 -1
  59. package/dist/ui/dist/assets/{dropdown-menu-BdCbAW1z.js → dropdown-menu-DDiaHg5y.js} +1 -1
  60. package/dist/ui/dist/assets/{es-Cz5h9_84.js → es-ecSKCyB6.js} +1 -1
  61. package/dist/ui/dist/assets/index-CawKP29y.js +116 -0
  62. package/dist/ui/dist/assets/index-DIcsEkyd.css +2 -0
  63. package/dist/ui/{assets/label-byJkqOYq.js → dist/assets/label-Bi6udtSd.js} +1 -1
  64. package/dist/ui/dist/assets/select-BQCOjM2j.js +1 -0
  65. package/dist/ui/dist/assets/useProviders-Dlizq_8q.js +1 -0
  66. package/dist/ui/dist/index.html +4 -4
  67. package/dist/ui/index.html +4 -4
  68. package/package.json +1 -1
  69. package/packages/cli/src/commands/gateway.ts +1 -1
  70. package/packages/cli/src/commands/onboard.ts +27 -1
  71. package/packages/core/src/agent/agent-loop.ts +104 -2
  72. package/packages/core/src/agent/context-compiler.ts +6 -0
  73. package/packages/core/src/agent/llm-client.ts +2 -0
  74. package/packages/core/src/agent/llm-providers/hiveagents.ts +248 -0
  75. package/packages/core/src/agent/llm-providers/interface.ts +2 -0
  76. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +49 -25
  77. package/packages/core/src/agent/providers/index.ts +3 -2
  78. package/packages/core/src/agent/stuck-loop.ts +90 -14
  79. package/packages/core/src/channels/base.ts +7 -1
  80. package/packages/core/src/config/loader.ts +1 -1
  81. package/packages/core/src/gateway/routes/providers.ts +56 -0
  82. package/packages/core/src/gateway/server.ts +120 -55
  83. package/packages/core/src/gateway/slash-commands.ts +7 -1
  84. package/packages/core/src/storage/onboarding.ts +28 -0
  85. package/packages/core/src/storage/seed.ts +14 -0
  86. package/packages/skills/src/bundled-data.generated.ts +1357 -1357
  87. package/dist/ui/assets/AgentCreateForm-BTCzFbca.js +0 -1
  88. package/dist/ui/assets/AgentDetailPage-o27TRSVw.js +0 -1
  89. package/dist/ui/assets/AgentNewPage-400cCpYt.js +0 -1
  90. package/dist/ui/assets/ApiClientPage-BOTpz6oP.js +0 -3
  91. package/dist/ui/assets/MeetingPage-CrKVAfe6.js +0 -1
  92. package/dist/ui/assets/ProvidersPage-uqPcZUSV.js +0 -1
  93. package/dist/ui/assets/SettingsPage-DKLlye0z.js +0 -9
  94. package/dist/ui/assets/WebChatPage-c-7S9jnT.js +0 -16
  95. package/dist/ui/assets/accordion-DAbcVQCn.js +0 -1
  96. package/dist/ui/assets/chevron-up-BYhk0K2J.js +0 -1
  97. package/dist/ui/assets/index-CmGm_r89.js +0 -116
  98. package/dist/ui/assets/index-T7HgphSn.css +0 -2
  99. package/dist/ui/assets/select-Cl16QYa_.js +0 -1
  100. package/dist/ui/assets/useProviders-eEri6BAc.js +0 -1
  101. package/dist/ui/dist/assets/AgentCreateForm-BTCzFbca.js +0 -1
  102. package/dist/ui/dist/assets/AgentDetailPage-o27TRSVw.js +0 -1
  103. package/dist/ui/dist/assets/AgentNewPage-400cCpYt.js +0 -1
  104. package/dist/ui/dist/assets/ApiClientPage-BOTpz6oP.js +0 -3
  105. package/dist/ui/dist/assets/MeetingPage-CrKVAfe6.js +0 -1
  106. package/dist/ui/dist/assets/ProvidersPage-uqPcZUSV.js +0 -1
  107. package/dist/ui/dist/assets/SettingsPage-DKLlye0z.js +0 -9
  108. package/dist/ui/dist/assets/WebChatPage-c-7S9jnT.js +0 -16
  109. package/dist/ui/dist/assets/accordion-DAbcVQCn.js +0 -1
  110. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +0 -1
  111. package/dist/ui/dist/assets/index-CmGm_r89.js +0 -116
  112. package/dist/ui/dist/assets/index-T7HgphSn.css +0 -2
  113. package/dist/ui/dist/assets/select-Cl16QYa_.js +0 -1
  114. package/dist/ui/dist/assets/useProviders-eEri6BAc.js +0 -1
  115. /package/dist/ui/assets/{card-CXAm46at.js → card-DFKnZ6ky.js} +0 -0
  116. /package/dist/ui/assets/{circle-alert-CyHDwUj8.js → circle-alert-KuAm2FWh.js} +0 -0
  117. /package/dist/ui/assets/{circle-check-Bb54Ebmu.js → circle-check-6Ard1-2z.js} +0 -0
  118. /package/dist/ui/assets/{circle-x-Bv6WrUJo.js → circle-x-DjLkFDO8.js} +0 -0
  119. /package/dist/ui/assets/{copy-dU94ZGsi.js → copy-Bu5d7C-0.js} +0 -0
  120. /package/dist/ui/assets/{cpu-DSpPVLAz.js → cpu-KDy6-FAI.js} +0 -0
  121. /package/dist/ui/assets/{download-D9ZyUZZR.js → download-Cjbk4Rek.js} +0 -0
  122. /package/dist/ui/assets/{external-link-CHPbUorN.js → external-link-6sTlRDUR.js} +0 -0
  123. /package/dist/ui/assets/{eye-epHJZ_nQ.js → eye-Df8o0tkC.js} +0 -0
  124. /package/dist/ui/assets/{file-text-BEjEmgby.js → file-text-lnxnjBp0.js} +0 -0
  125. /package/dist/ui/assets/{folder-open-iQMHVEqS.js → folder-open-DJBLDFjv.js} +0 -0
  126. /package/dist/ui/assets/{format-oFACFaca.js → format-BwdV8bB5.js} +0 -0
  127. /package/dist/ui/assets/{gateway-url-iG-C6Agn.js → gateway-url-DwzPmoc8.js} +0 -0
  128. /package/dist/ui/assets/{gauge-D0_GMEcq.js → gauge-B8Tj43rC.js} +0 -0
  129. /package/dist/ui/assets/{hexagon-DsGOUl-H.js → hexagon-6L79pgVK.js} +0 -0
  130. /package/dist/ui/assets/{history-BSG-Ypqf.js → history-CAF_R34_.js} +0 -0
  131. /package/dist/ui/assets/{info-NwLoa2Mj.js → info-WjromB4Y.js} +0 -0
  132. /package/dist/ui/assets/{key-3EP0dhkT.js → key-DyKOoQh5.js} +0 -0
  133. /package/dist/ui/assets/{loader-circle-CZNax6kS.js → loader-circle-BmBOgYze.js} +0 -0
  134. /package/dist/ui/assets/{lock-Ei1_J-Nq.js → lock-BS6OLXPv.js} +0 -0
  135. /package/dist/ui/assets/{pause-BUqah9Bi.js → pause-VqeUmp2Z.js} +0 -0
  136. /package/dist/ui/assets/{play-NcZ4swwL.js → play-zJpWuhrr.js} +0 -0
  137. /package/dist/ui/assets/{plus-CX1xyhp5.js → plus-BZQX26Dr.js} +0 -0
  138. /package/dist/ui/assets/{progress-Dtz-Mzys.js → progress-D5c-Eilm.js} +0 -0
  139. /package/dist/ui/assets/{refresh-cw-DaYdjQFk.js → refresh-cw-CCzDCAuz.js} +0 -0
  140. /package/dist/ui/assets/{save-CUdYyHNy.js → save-hUmZhceG.js} +0 -0
  141. /package/dist/ui/assets/{scroll-area-BXtLsE9E.js → scroll-area-CihOx0cb.js} +0 -0
  142. /package/dist/ui/assets/{search-BGmPJ-6L.js → search-DzDptO9s.js} +0 -0
  143. /package/dist/ui/assets/{send-BuQcUO-R.js → send-BPk9XbIq.js} +0 -0
  144. /package/dist/ui/assets/{settings-CcMGI1iU.js → settings-BGfrZ_zM.js} +0 -0
  145. /package/dist/ui/assets/{shield-C-05qB-2.js → shield-CxhcUT39.js} +0 -0
  146. /package/dist/ui/assets/{slider-D2I0qven.js → slider-bcUiUfx0.js} +0 -0
  147. /package/dist/ui/assets/{sparkles-D6fx8JC5.js → sparkles-BhwlS1pc.js} +0 -0
  148. /package/dist/ui/assets/{square-BD81nFtN.js → square-DMNWw4Hi.js} +0 -0
  149. /package/dist/ui/assets/{switch-h2SfQX4B.js → switch-BR30E4ej.js} +0 -0
  150. /package/dist/ui/assets/{table-CVkIRJKK.js → table-B3aGEaVp.js} +0 -0
  151. /package/dist/ui/assets/{tabs-C619jxbO.js → tabs-LQidMKRS.js} +0 -0
  152. /package/dist/ui/assets/{terminal-DN38Q456.js → terminal--7G943As.js} +0 -0
  153. /package/dist/ui/assets/{textarea-wvA-FDjO.js → textarea-B6Z1Zc6W.js} +0 -0
  154. /package/dist/ui/assets/{trash-2-BHRa5ft9.js → trash-2-xD2o4SgX.js} +0 -0
  155. /package/dist/ui/assets/{triangle-alert-D4nwAVbc.js → triangle-alert-pVIJGjga.js} +0 -0
  156. /package/dist/ui/assets/{vendor-router-pCP7sjma.js → vendor-router-gqiZ7xhx.js} +0 -0
  157. /package/dist/ui/assets/{volume-2-B6tkRy2u.js → volume-2-BekVQl6P.js} +0 -0
  158. /package/dist/ui/assets/{zap-QO7iWMRg.js → zap-B4RaNNO5.js} +0 -0
  159. /package/dist/ui/dist/assets/{card-CXAm46at.js → card-DFKnZ6ky.js} +0 -0
  160. /package/dist/ui/dist/assets/{circle-alert-CyHDwUj8.js → circle-alert-KuAm2FWh.js} +0 -0
  161. /package/dist/ui/dist/assets/{circle-check-Bb54Ebmu.js → circle-check-6Ard1-2z.js} +0 -0
  162. /package/dist/ui/dist/assets/{circle-x-Bv6WrUJo.js → circle-x-DjLkFDO8.js} +0 -0
  163. /package/dist/ui/dist/assets/{copy-dU94ZGsi.js → copy-Bu5d7C-0.js} +0 -0
  164. /package/dist/ui/dist/assets/{cpu-DSpPVLAz.js → cpu-KDy6-FAI.js} +0 -0
  165. /package/dist/ui/dist/assets/{download-D9ZyUZZR.js → download-Cjbk4Rek.js} +0 -0
  166. /package/dist/ui/dist/assets/{external-link-CHPbUorN.js → external-link-6sTlRDUR.js} +0 -0
  167. /package/dist/ui/dist/assets/{eye-epHJZ_nQ.js → eye-Df8o0tkC.js} +0 -0
  168. /package/dist/ui/dist/assets/{file-text-BEjEmgby.js → file-text-lnxnjBp0.js} +0 -0
  169. /package/dist/ui/dist/assets/{folder-open-iQMHVEqS.js → folder-open-DJBLDFjv.js} +0 -0
  170. /package/dist/ui/dist/assets/{format-oFACFaca.js → format-BwdV8bB5.js} +0 -0
  171. /package/dist/ui/dist/assets/{gateway-url-iG-C6Agn.js → gateway-url-DwzPmoc8.js} +0 -0
  172. /package/dist/ui/dist/assets/{gauge-D0_GMEcq.js → gauge-B8Tj43rC.js} +0 -0
  173. /package/dist/ui/dist/assets/{hexagon-DsGOUl-H.js → hexagon-6L79pgVK.js} +0 -0
  174. /package/dist/ui/dist/assets/{history-BSG-Ypqf.js → history-CAF_R34_.js} +0 -0
  175. /package/dist/ui/dist/assets/{info-NwLoa2Mj.js → info-WjromB4Y.js} +0 -0
  176. /package/dist/ui/dist/assets/{key-3EP0dhkT.js → key-DyKOoQh5.js} +0 -0
  177. /package/dist/ui/dist/assets/{loader-circle-CZNax6kS.js → loader-circle-BmBOgYze.js} +0 -0
  178. /package/dist/ui/dist/assets/{lock-Ei1_J-Nq.js → lock-BS6OLXPv.js} +0 -0
  179. /package/dist/ui/dist/assets/{pause-BUqah9Bi.js → pause-VqeUmp2Z.js} +0 -0
  180. /package/dist/ui/dist/assets/{play-NcZ4swwL.js → play-zJpWuhrr.js} +0 -0
  181. /package/dist/ui/dist/assets/{plus-CX1xyhp5.js → plus-BZQX26Dr.js} +0 -0
  182. /package/dist/ui/dist/assets/{progress-Dtz-Mzys.js → progress-D5c-Eilm.js} +0 -0
  183. /package/dist/ui/dist/assets/{refresh-cw-DaYdjQFk.js → refresh-cw-CCzDCAuz.js} +0 -0
  184. /package/dist/ui/dist/assets/{save-CUdYyHNy.js → save-hUmZhceG.js} +0 -0
  185. /package/dist/ui/dist/assets/{scroll-area-BXtLsE9E.js → scroll-area-CihOx0cb.js} +0 -0
  186. /package/dist/ui/dist/assets/{search-BGmPJ-6L.js → search-DzDptO9s.js} +0 -0
  187. /package/dist/ui/dist/assets/{send-BuQcUO-R.js → send-BPk9XbIq.js} +0 -0
  188. /package/dist/ui/dist/assets/{settings-CcMGI1iU.js → settings-BGfrZ_zM.js} +0 -0
  189. /package/dist/ui/dist/assets/{shield-C-05qB-2.js → shield-CxhcUT39.js} +0 -0
  190. /package/dist/ui/dist/assets/{slider-D2I0qven.js → slider-bcUiUfx0.js} +0 -0
  191. /package/dist/ui/dist/assets/{sparkles-D6fx8JC5.js → sparkles-BhwlS1pc.js} +0 -0
  192. /package/dist/ui/dist/assets/{square-BD81nFtN.js → square-DMNWw4Hi.js} +0 -0
  193. /package/dist/ui/dist/assets/{switch-h2SfQX4B.js → switch-BR30E4ej.js} +0 -0
  194. /package/dist/ui/dist/assets/{table-CVkIRJKK.js → table-B3aGEaVp.js} +0 -0
  195. /package/dist/ui/dist/assets/{tabs-C619jxbO.js → tabs-LQidMKRS.js} +0 -0
  196. /package/dist/ui/dist/assets/{terminal-DN38Q456.js → terminal--7G943As.js} +0 -0
  197. /package/dist/ui/dist/assets/{textarea-wvA-FDjO.js → textarea-B6Z1Zc6W.js} +0 -0
  198. /package/dist/ui/dist/assets/{trash-2-BHRa5ft9.js → trash-2-xD2o4SgX.js} +0 -0
  199. /package/dist/ui/dist/assets/{triangle-alert-D4nwAVbc.js → triangle-alert-pVIJGjga.js} +0 -0
  200. /package/dist/ui/dist/assets/{vendor-router-pCP7sjma.js → vendor-router-gqiZ7xhx.js} +0 -0
  201. /package/dist/ui/dist/assets/{volume-2-B6tkRy2u.js → volume-2-BekVQl6P.js} +0 -0
  202. /package/dist/ui/dist/assets/{zap-QO7iWMRg.js → zap-B4RaNNO5.js} +0 -0
@@ -41,7 +41,7 @@ import { handleSetupStatus, handleVerifyProvider, handleCompleteSetup, handleSet
41
41
  import { handleAuthStatus, handleLogin, handleSetupCredentials, handleChangePassword, handleRecover, handleDisableAuth, handleRecoveryKey } from "./routes/auth";
42
42
  import { resolveUserId } from "../storage/onboarding";
43
43
  import { handleGetAgents, handleCreateAgent, handleUpdateAgent, handleDeleteAgent } from "./routes/agents";
44
- import { handleGetProviders, handleCreateProvider, handleToggleProvider, handleUpdateProvider, handleSyncProviderModels } from "./routes/providers";
44
+ import { handleGetProviders, handleCreateProvider, handleToggleProvider, handleUpdateProvider, handleSyncProviderModels, handleLoadHiveAgentsModel, handleGetHiveAgentsModelStatus } from "./routes/providers";
45
45
  import { handleGetUsers, handleCreateUser, handleUpdateUserSettings, handleGetUserChannels, handleLinkUserChannel } from "./routes/users";
46
46
  import { handleGetSkills, handleActivateSkill, handleUpdateSkill, handleDeleteSkill, handleCreateSkill } from "./routes/skills";
47
47
  import { handleGetEthics, handleActivateEthics, handleDeleteEthics } from "./routes/ethics";
@@ -257,6 +257,82 @@ export async function startGateway(config: Config): Promise<void> {
257
257
  return undefined;
258
258
  }
259
259
 
260
+ type WebChatProcessKind = "analysis" | "tool" | "observation" | "writing";
261
+ type WebChatProcessStatus = "thinking" | "done" | "error";
262
+
263
+ function createWebChatProcessReporter(ws: { send: (payload: string) => void }, sessionId: string, messageId: string) {
264
+ const sent = new Set<string>();
265
+
266
+ const send = (event: {
267
+ kind?: WebChatProcessKind;
268
+ label?: string;
269
+ detail?: string;
270
+ status?: WebChatProcessStatus;
271
+ summary?: string;
272
+ }) => {
273
+ ws.send(JSON.stringify({
274
+ type: "process",
275
+ sessionId,
276
+ id: messageId,
277
+ messageId,
278
+ processKind: event.kind,
279
+ processStatus: event.status,
280
+ label: event.label,
281
+ detail: event.detail,
282
+ summary: event.summary,
283
+ timestamp: new Date().toISOString(),
284
+ } as OutboundMessage));
285
+ };
286
+
287
+ const sendOnce = (key: string, event: Parameters<typeof send>[0]) => {
288
+ if (sent.has(key)) return;
289
+ sent.add(key);
290
+ send(event);
291
+ };
292
+
293
+ return {
294
+ start(label = "Revisando tu solicitud") {
295
+ sendOnce("start", { kind: "analysis", label, status: "thinking" });
296
+ },
297
+ writing() {
298
+ sendOnce("writing", { kind: "writing", label: "Preparando la respuesta", status: "thinking" });
299
+ },
300
+ step(step: { type: string; message?: string; toolName?: string }) {
301
+ if (step.type === "tool_call" && step.toolName) {
302
+ sendOnce(`tool:${step.toolName}`, {
303
+ kind: "tool",
304
+ label: getNarration(step.toolName),
305
+ status: "thinking",
306
+ });
307
+ return;
308
+ }
309
+
310
+ if (step.type === "tool_result") {
311
+ sendOnce(`tool_result:${sent.size}`, {
312
+ kind: "observation",
313
+ label: "Revisando la informacion obtenida",
314
+ status: "thinking",
315
+ });
316
+ return;
317
+ }
318
+
319
+ if (step.type === "text") {
320
+ sendOnce("analysis:text", {
321
+ kind: "analysis",
322
+ label: "Organizando la informacion",
323
+ status: "thinking",
324
+ });
325
+ }
326
+ },
327
+ done(summary = "Proceso completado") {
328
+ send({ status: "done", summary });
329
+ },
330
+ error(summary = "No se pudo completar el proceso") {
331
+ send({ status: "error", summary });
332
+ },
333
+ };
334
+ }
335
+
260
336
  // Set up hot reload watchers
261
337
  const watchers: Array<() => void> = [];
262
338
 
@@ -1162,6 +1238,14 @@ export async function startGateway(config: Config): Promise<void> {
1162
1238
  return await handleUpdateProvider(req, addCorsHeaders)
1163
1239
  }
1164
1240
 
1241
+ // ── HiveAgents model loading ───────────────────────────────────────
1242
+ if (url.pathname === "/api/providers/hiveagents/load-model" && req.method === "POST") {
1243
+ return await handleLoadHiveAgentsModel(req, addCorsHeaders)
1244
+ }
1245
+ if (url.pathname === "/api/providers/hiveagents/model-status" && req.method === "GET") {
1246
+ return await handleGetHiveAgentsModelStatus(req, addCorsHeaders)
1247
+ }
1248
+
1165
1249
  // ── Models API ───────────────────────────────────────────────────
1166
1250
  // GET /api/models?provider_id=xxx - Get models filtered by provider
1167
1251
  if (url.pathname === "/api/models" && req.method === "GET") {
@@ -2159,6 +2243,7 @@ export async function startGateway(config: Config): Promise<void> {
2159
2243
  } as OutboundMessage));
2160
2244
 
2161
2245
  laneQueue.enqueue(msg.sessionId, async (_task, signal) => {
2246
+ let processReporter: ReturnType<typeof createWebChatProcessReporter> | null = null;
2162
2247
  if (signal.aborted) {
2163
2248
  ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: msg.sessionId } as OutboundMessage));
2164
2249
  ws.send(JSON.stringify({ type: "error", sessionId: msg.sessionId, error: "Task cancelled" } as OutboundMessage));
@@ -2173,11 +2258,14 @@ export async function startGateway(config: Config): Promise<void> {
2173
2258
  const unifiedSessionId = conversationThreadId;
2174
2259
  const routingSessionId = msg.sessionId;
2175
2260
  const messages = [{ role: "user" as const, content: messageContent }];
2261
+ const messageId = crypto.randomUUID();
2262
+ processReporter = createWebChatProcessReporter(ws, routingSessionId, messageId);
2263
+ processReporter.start("Revisando la transcripcion");
2176
2264
  log.info(`Generating response for session ${unifiedSessionId}...`);
2177
2265
 
2178
2266
  // Streaming: send tokens as they arrive
2179
2267
  let streamedContent = "";
2180
- let messageId = crypto.randomUUID();
2268
+ let reportedWriting = false;
2181
2269
 
2182
2270
  const response = await runner.generate({
2183
2271
  provider: dbProvider as any,
@@ -2189,6 +2277,10 @@ export async function startGateway(config: Config): Promise<void> {
2189
2277
  userId,
2190
2278
  onToken: async (token: string) => {
2191
2279
  if (signal.aborted) return;
2280
+ if (!reportedWriting && token.trim()) {
2281
+ reportedWriting = true;
2282
+ processReporter?.writing();
2283
+ }
2192
2284
  streamedContent += token;
2193
2285
  // Send chunk to client
2194
2286
  ws.send(JSON.stringify({
@@ -2202,30 +2294,7 @@ export async function startGateway(config: Config): Promise<void> {
2202
2294
  },
2203
2295
  onStep: async (step) => {
2204
2296
  if (signal.aborted) return;
2205
-
2206
- // "text" = el agente narra lo que esta pensando/haciendo
2207
- if (step.type === "text" && step.message) {
2208
- const trimmedMessage = (typeof step.message === "string" ? step.message : "").trim();
2209
- if (trimmedMessage) {
2210
- ws.send(JSON.stringify({
2211
- type: "progress",
2212
- sessionId: routingSessionId,
2213
- content: trimmedMessage,
2214
- } as OutboundMessage));
2215
- }
2216
- return;
2217
- }
2218
-
2219
- // "tool_call" = el agente va a ejecutar una herramienta → narrar al usuario
2220
- if (step.type === "tool_call" && step.toolName) {
2221
- const narration = getNarration(step.toolName);
2222
- ws.send(JSON.stringify({
2223
- type: "progress",
2224
- sessionId: routingSessionId,
2225
- content: narration,
2226
- } as OutboundMessage));
2227
- return;
2228
- }
2297
+ processReporter?.step(step);
2229
2298
 
2230
2299
  // "tool_result" = resultado de herramienta → solo si pide enviarse al usuario
2231
2300
  if (step.type === "tool_result" && step.message) {
@@ -2267,6 +2336,7 @@ export async function startGateway(config: Config): Promise<void> {
2267
2336
  if (!voiceCfg.ttsProvider) {
2268
2337
  ws.send(JSON.stringify({
2269
2338
  type: "message",
2339
+ id: messageId,
2270
2340
  sessionId: routingSessionId,
2271
2341
  content: `${content}\n\n🔊 Para recibir respuestas en audio, configura el proveedor TTS en Configuración > Canales > WebChat (ej: elevenlabs)`,
2272
2342
  isStep: false,
@@ -2282,6 +2352,7 @@ export async function startGateway(config: Config): Promise<void> {
2282
2352
  log.info(`Audio generated: ${base64Audio.length} bytes, mimeType: ${audioOutput.mimeType}`);
2283
2353
  ws.send(JSON.stringify({
2284
2354
  type: "message",
2355
+ id: messageId,
2285
2356
  sessionId: routingSessionId,
2286
2357
  content,
2287
2358
  audio: base64Audio,
@@ -2290,11 +2361,11 @@ export async function startGateway(config: Config): Promise<void> {
2290
2361
  } as OutboundMessage));
2291
2362
  } catch (ttsError) {
2292
2363
  log.error(`TTS failed: ${(ttsError as Error).message}), sending text instead`);
2293
- ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2364
+ ws.send(JSON.stringify({ type: "message", id: messageId, sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2294
2365
  }
2295
2366
  }
2296
2367
  } else {
2297
- ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2368
+ ws.send(JSON.stringify({ type: "message", id: messageId, sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2298
2369
  }
2299
2370
  } else if (alreadyStreamed && shouldSpeak && voiceCfg.ttsProvider) {
2300
2371
  try {
@@ -2304,6 +2375,7 @@ export async function startGateway(config: Config): Promise<void> {
2304
2375
  log.info(`Audio generated after streaming: ${base64Audio.length} bytes`);
2305
2376
  ws.send(JSON.stringify({
2306
2377
  type: "message",
2378
+ id: messageId,
2307
2379
  sessionId: routingSessionId,
2308
2380
  content,
2309
2381
  audio: base64Audio,
@@ -2314,7 +2386,9 @@ export async function startGateway(config: Config): Promise<void> {
2314
2386
  log.error(`TTS after streaming failed: ${(ttsError as Error).message}), skipping audio`);
2315
2387
  }
2316
2388
  }
2389
+ processReporter.done("Listo");
2317
2390
  } catch (error) {
2391
+ processReporter?.error("No se pudo completar la respuesta");
2318
2392
  ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: msg.sessionId } as OutboundMessage));
2319
2393
  ws.send(JSON.stringify({
2320
2394
  type: "error",
@@ -2351,6 +2425,7 @@ export async function startGateway(config: Config): Promise<void> {
2351
2425
  } as OutboundMessage));
2352
2426
 
2353
2427
  laneQueue.enqueue(msg.sessionId, async (_task, signal) => {
2428
+ let processReporter: ReturnType<typeof createWebChatProcessReporter> | null = null;
2354
2429
  if (signal.aborted) {
2355
2430
  ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: msg.sessionId } as OutboundMessage));
2356
2431
  ws.send(JSON.stringify({ type: "error", sessionId: msg.sessionId, error: "Task cancelled" } as OutboundMessage));
@@ -2364,6 +2439,9 @@ export async function startGateway(config: Config): Promise<void> {
2364
2439
  });
2365
2440
  const unifiedSessionId = conversationThreadId;
2366
2441
  const routingSessionId = msg.sessionId;
2442
+ const messageId = crypto.randomUUID();
2443
+ processReporter = createWebChatProcessReporter(ws, routingSessionId, messageId);
2444
+ processReporter.start(msg.image || msg.document ? "Revisando tu solicitud y adjuntos" : "Revisando tu solicitud");
2367
2445
 
2368
2446
  // Multimodal: process image/document if present
2369
2447
  let finalMessageContent = msg.content;
@@ -2372,6 +2450,7 @@ export async function startGateway(config: Config): Promise<void> {
2372
2450
 
2373
2451
  if (msg.image || msg.document) {
2374
2452
  log.info(`🖼️ Multimodal content detected from WebChat session ${unifiedSessionId}`);
2453
+ processReporter.step({ type: "tool_result" });
2375
2454
 
2376
2455
  if (msg.image) {
2377
2456
  try {
@@ -2434,7 +2513,7 @@ export async function startGateway(config: Config): Promise<void> {
2434
2513
 
2435
2514
  // Streaming: send tokens as they arrive
2436
2515
  let streamedContent = "";
2437
- let messageId = crypto.randomUUID();
2516
+ let reportedWriting = false;
2438
2517
 
2439
2518
  const response = await runner.generate({
2440
2519
  provider: dbProvider as any,
@@ -2447,6 +2526,10 @@ export async function startGateway(config: Config): Promise<void> {
2447
2526
  signal,
2448
2527
  onToken: async (token: string) => {
2449
2528
  if (signal.aborted) return;
2529
+ if (!reportedWriting && token.trim()) {
2530
+ reportedWriting = true;
2531
+ processReporter?.writing();
2532
+ }
2450
2533
  streamedContent += token;
2451
2534
  // Send chunk to client
2452
2535
  ws.send(JSON.stringify({
@@ -2460,30 +2543,7 @@ export async function startGateway(config: Config): Promise<void> {
2460
2543
  },
2461
2544
  onStep: async (step) => {
2462
2545
  if (signal.aborted) return;
2463
-
2464
- // "text" = el agente narra lo que esta pensando/haciendo
2465
- if (step.type === "text" && step.message) {
2466
- const trimmedMessage = (typeof step.message === "string" ? step.message : "").trim();
2467
- if (trimmedMessage) {
2468
- ws.send(JSON.stringify({
2469
- type: "progress",
2470
- sessionId: routingSessionId,
2471
- content: trimmedMessage,
2472
- } as OutboundMessage));
2473
- }
2474
- return;
2475
- }
2476
-
2477
- // "tool_call" = el agente va a ejecutar una herramienta → narrar al usuario
2478
- if (step.type === "tool_call" && step.toolName) {
2479
- const narration = getNarration(step.toolName);
2480
- ws.send(JSON.stringify({
2481
- type: "progress",
2482
- sessionId: routingSessionId,
2483
- content: narration,
2484
- } as OutboundMessage));
2485
- return;
2486
- }
2546
+ processReporter?.step(step);
2487
2547
 
2488
2548
  // "tool_result" = resultado de herramienta → solo si pide enviarse al usuario
2489
2549
  if (step.type === "tool_result" && step.message) {
@@ -2525,6 +2585,7 @@ export async function startGateway(config: Config): Promise<void> {
2525
2585
  if (!voiceConfig.ttsProvider) {
2526
2586
  ws.send(JSON.stringify({
2527
2587
  type: "message",
2588
+ id: messageId,
2528
2589
  sessionId: routingSessionId,
2529
2590
  content: `${content}\n\n🔊 Para recibir respuestas en audio, configura el proveedor TTS en Configuración > Canales > WebChat (ej: elevenlabs)`,
2530
2591
  isStep: false
@@ -2539,6 +2600,7 @@ export async function startGateway(config: Config): Promise<void> {
2539
2600
  const base64Audio = (audioOutput.data as Buffer).toString("base64");
2540
2601
  ws.send(JSON.stringify({
2541
2602
  type: "message",
2603
+ id: messageId,
2542
2604
  sessionId: routingSessionId,
2543
2605
  content,
2544
2606
  audio: base64Audio,
@@ -2547,11 +2609,11 @@ export async function startGateway(config: Config): Promise<void> {
2547
2609
  } as OutboundMessage));
2548
2610
  } catch (ttsError) {
2549
2611
  log.error(`TTS failed: ${(ttsError as Error).message}), sending text instead`);
2550
- ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2612
+ ws.send(JSON.stringify({ type: "message", id: messageId, sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2551
2613
  }
2552
2614
  }
2553
2615
  } else {
2554
- ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2616
+ ws.send(JSON.stringify({ type: "message", id: messageId, sessionId: routingSessionId, content, isStep: false } as OutboundMessage));
2555
2617
  }
2556
2618
  } else if (alreadyStreamed && shouldSpeak && voiceConfig.ttsProvider) {
2557
2619
  try {
@@ -2561,6 +2623,7 @@ export async function startGateway(config: Config): Promise<void> {
2561
2623
  log.info(`Audio generated after streaming: ${base64Audio.length} bytes`);
2562
2624
  ws.send(JSON.stringify({
2563
2625
  type: "message",
2626
+ id: messageId,
2564
2627
  sessionId: routingSessionId,
2565
2628
  content,
2566
2629
  audio: base64Audio,
@@ -2571,7 +2634,9 @@ export async function startGateway(config: Config): Promise<void> {
2571
2634
  log.error(`TTS after streaming failed: ${(ttsError as Error).message}), skipping audio`);
2572
2635
  }
2573
2636
  }
2637
+ processReporter.done("Listo");
2574
2638
  } catch (error) {
2639
+ processReporter?.error("No se pudo completar la respuesta");
2575
2640
  // Detener typing aunque falle — nunca dejar el spinner infinito
2576
2641
  ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: msg.sessionId } as OutboundMessage));
2577
2642
  ws.send(JSON.stringify({
@@ -27,15 +27,21 @@ export interface InboundMessage {
27
27
  }
28
28
 
29
29
  export interface OutboundMessage {
30
- type: "message" | "stream" | "status" | "error" | "pong" | "command_result" | "joined" | "typing" | "audio" | "welcome" | "progress";
30
+ type: "message" | "stream" | "status" | "error" | "pong" | "command_result" | "joined" | "typing" | "audio" | "welcome" | "progress" | "process";
31
31
  sessionId: string;
32
32
  id?: string; // Message ID for streaming
33
+ messageId?: string;
33
34
  content?: string;
34
35
  chunk?: string;
35
36
  isChunk?: boolean; // True if this is a streaming chunk
36
37
  isLast?: boolean;
37
38
  isTyping?: boolean;
38
39
  isStep?: boolean;
40
+ processKind?: "analysis" | "tool" | "observation" | "writing";
41
+ processStatus?: "thinking" | "done" | "error";
42
+ label?: string;
43
+ detail?: string;
44
+ summary?: string;
39
45
  stepType?: "plan" | "tool_call" | "tool_result" | "text";
40
46
  status?: {
41
47
  state: string;
@@ -1500,6 +1500,34 @@ export function runStartupMigrations(): void {
1500
1500
  markApplied("v0.0.32");
1501
1501
  log.info("✅ Migration v0.0.32: vision columns added to channels");
1502
1502
  }
1503
+
1504
+ // v0.0.33 — add HiveAgents LLM provider + 5 local GGUF models
1505
+ if (!applied("v0.0.33")) {
1506
+ const db = getDb();
1507
+ log.info("[migration v0.0.33] Adding HiveAgents LLM provider and models...");
1508
+
1509
+ db.query(`
1510
+ INSERT OR IGNORE INTO providers (id, name, base_url, category, enabled, active)
1511
+ VALUES ('hiveagents', 'HiveAgents LLM (Cloudflare)', 'https://llm.hiveagents.io/v1', 'llm', 1, 1)
1512
+ `).run();
1513
+
1514
+ const hiveModels = [
1515
+ { id: "Qwen3.6-35B-A3B-UD-Q6_K.gguf", name: "Qwen3.6 35B MoE (Recomendado)", ctx: 8192, caps: '["chat","streaming","reasoning"]' },
1516
+ { id: "gemma-4-26B-A4B-it-UD-Q6_K_XL.gguf", name: "Gemma 4 26B MoE", ctx: 8192, caps: '["chat","streaming"]' },
1517
+ { id: "gemma-4-12b-it-UD-Q4_K_XL.gguf", name: "Gemma 4 12B Dense", ctx: 8192, caps: '["chat","streaming"]' },
1518
+ { id: "Qwen3.6-27B-UD-Q6_K_XL.gguf", name: "Qwen3.6 27B + MTP", ctx: 8192, caps: '["chat","streaming","reasoning"]' },
1519
+ { id: "gemma-4-31B-it-UD-Q6_K_XL.gguf", name: "Gemma 4 31B Dense", ctx: 8192, caps: '["chat","streaming"]' },
1520
+ ];
1521
+ for (const m of hiveModels) {
1522
+ db.query(`
1523
+ INSERT OR IGNORE INTO models (id, provider_id, name, model_type, context_window, capabilities, enabled, active)
1524
+ VALUES (?, 'hiveagents', ?, 'llm', ?, ?, 1, 1)
1525
+ `).run(m.id, m.name, m.ctx, m.caps);
1526
+ }
1527
+
1528
+ markApplied("v0.0.33");
1529
+ log.info("✅ Migration v0.0.33: HiveAgents LLM provider + 5 models added");
1530
+ }
1503
1531
  } catch (e) {
1504
1532
  log.error("⚠️ runStartupMigrations failed:", { error: (e as Error).message });
1505
1533
  }
@@ -142,6 +142,7 @@ export const SEED_DATA: SeedData = {
142
142
  { id: "minimax", name: "MiniMax", baseUrl: "https://api.minimaxi.com/v1" },
143
143
  { id: "opencode-go", name: "OpenCode Go", baseUrl: "https://opencode.ai/zen/go/v1" },
144
144
  { id: "piper", name: "Piper (Local TTS)" },
145
+ { id: "hiveagents", name: "HiveAgents LLM (Cloudflare)", baseUrl: "https://llm.hiveagents.io/v1", category: "llm" },
145
146
  ],
146
147
 
147
148
  models: [
@@ -315,6 +316,19 @@ export const SEED_DATA: SeedData = {
315
316
  { id: "opencode-go/mimo-v2.5-pro", providerId: "opencode-go", name: "MiMo-V2.5 Pro", modelType: "llm", contextWindow: 128000, capabilities: JSON.stringify(["chat", "code", "function_calling", "streaming", "reasoning"]) },
316
317
  { id: "opencode-go/mimo-v2.5", providerId: "opencode-go", name: "MiMo-V2.5", modelType: "llm", contextWindow: 128000, capabilities: JSON.stringify(["chat", "code", "function_calling", "streaming"]) },
317
318
  { id: "opencode-go/hy3-preview", providerId: "opencode-go", name: "Hunyuan 3 Preview", modelType: "llm", contextWindow: 128000, capabilities: JSON.stringify(["chat", "code", "function_calling", "streaming"]) },
319
+
320
+ // ── HiveAgents (llama.cpp local, acceso vía Cloudflare) ──
321
+ // IDs actualizados según modelos disponibles en https://llm.hiveagents.io
322
+ // contextWindow = 50000 porque así se cargan en el backend.
323
+ { id: "Qwen3.6-35B-A3B-UD-Q6_K.gguf", providerId: "hiveagents", name: "Qwen3.6 35B MoE (Recomendado)", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "reasoning"]) },
324
+ { id: "Qwen3.6-35B-A3B-UD-Q4_K_M.gguf", providerId: "hiveagents", name: "Qwen3.6 35B MoE (Q4_K_M)", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "reasoning"]) },
325
+ { id: "Qwen3.6-27B-UD-Q4_K_XL.gguf", providerId: "hiveagents", name: "Qwen3.6 27B + MTP", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "reasoning"]) },
326
+ { id: "Qwen3-Coder-Next-UD-Q4_K_M.gguf", providerId: "hiveagents", name: "Qwen3 Coder Next", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "code"]) },
327
+ { id: "Qwopus3.6-27B-v2-MTP-Q6_K.gguf", providerId: "hiveagents", name: "Qwopus3.6 27B v2 (Q6_K)", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "reasoning"]) },
328
+ { id: "Qwopus3.6-27B-v2-MTP-Q4_K_S.gguf", providerId: "hiveagents", name: "Qwopus3.6 27B v2 (Q4_K_S)", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming", "reasoning"]) },
329
+ { id: "gemma-4-31B-it-UD-Q4_K_XL.gguf", providerId: "hiveagents", name: "Gemma 4 31B Dense", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming"]) },
330
+ { id: "gemma-4-26B-A4B-it-UD-Q4_K_M.gguf", providerId: "hiveagents", name: "Gemma 4 26B MoE", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming"]) },
331
+ { id: "gemma-4-12b-it-UD-Q4_K_XL.gguf", providerId: "hiveagents", name: "Gemma 4 12B Dense", modelType: "llm", contextWindow: 50000, capabilities: JSON.stringify(["chat", "streaming"]) },
318
332
  ],
319
333
 
320
334