@johpaz/hive-agents 0.0.35 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/README.md +64 -39
  2. package/dist/hive.js +3127 -3104
  3. package/dist/ui/assets/{AgentCreateForm-B4eK7efF.js → AgentCreateForm-tJZv9FZC.js} +1 -1
  4. package/dist/ui/assets/{AgentDetailPage-BD2uoJWk.js → AgentDetailPage-Du-mRcAX.js} +1 -1
  5. package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  6. package/dist/ui/assets/{AgentsPage-4JUZXvkA.js → AgentsPage-YvSgWRiw.js} +6 -6
  7. package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
  8. package/dist/ui/assets/{ChannelsPage-BUn7-nhV.js → ChannelsPage-BdBXWHjj.js} +1 -1
  9. package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
  10. package/dist/ui/assets/{LoginPage-C8j_urUD.js → LoginPage-CAmSI9Vy.js} +1 -1
  11. package/dist/ui/assets/LogsPage-DAPBHkwK.js +1 -0
  12. package/dist/ui/assets/MeetingPage-WjjGOqqU.js +1 -0
  13. package/dist/ui/assets/{NotFound-Drh-sJPN.js → NotFound-BMeQSGcG.js} +1 -1
  14. package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  15. package/dist/ui/assets/{RecoverPage-DNb1Pr8h.js → RecoverPage-DpW3l-yv.js} +1 -1
  16. package/dist/ui/assets/SettingsPage-DBJ7_E6C.js +9 -0
  17. package/dist/ui/assets/SetupPage-DKmLVUaj.js +1 -0
  18. package/dist/ui/assets/{WebChatPage-R-YOwA4F.js → WebChatPage-CVRcKept.js} +2 -2
  19. package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
  20. package/dist/ui/assets/{alert-U8FsgWi7.js → alert-C-NE-P3s.js} +1 -1
  21. package/dist/ui/assets/{alert-dialog-CRdMkkmk.js → alert-dialog-C5mzbHdP.js} +1 -1
  22. package/dist/ui/assets/{badge-Cli1jnH5.js → badge-ChpACfWO.js} +1 -1
  23. package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
  24. package/dist/ui/assets/{dialog-DQ3s-LuO.js → dialog-QnZ0ad8O.js} +1 -1
  25. package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
  26. package/dist/ui/assets/{es-DcMjrpbA.js → es-NQNoaWDx.js} +1 -1
  27. package/dist/ui/assets/index-B2fCYtTS.css +2 -0
  28. package/dist/ui/assets/index-DMCjjdqf.js +116 -0
  29. package/dist/ui/assets/{label-0BvGVXvZ.js → label-D2H1IR_J.js} +1 -1
  30. package/dist/ui/assets/progress-BherYzY6.js +1 -0
  31. package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
  32. package/dist/ui/assets/{slider-D47dOrRa.js → slider-CsiUDxc3.js} +1 -1
  33. package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
  34. package/dist/ui/assets/{table-DhowbNxQ.js → table-CSc8ubon.js} +1 -1
  35. package/dist/ui/assets/terminal-DN38Q456.js +1 -0
  36. package/dist/ui/assets/useProviders-C6_QHsEi.js +1 -0
  37. package/dist/ui/assets/{vendor-radix-JY4ncZrD.js → vendor-radix-cw1bQaVC.js} +4 -4
  38. package/dist/ui/assets/{vendor-react-CscwQerf.js → vendor-react-D4s9E-zj.js} +1 -1
  39. package/dist/ui/dist/assets/AgentCreateForm-tJZv9FZC.js +1 -0
  40. package/dist/ui/dist/assets/AgentDetailPage-Du-mRcAX.js +1 -0
  41. package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +1 -0
  42. package/dist/ui/dist/assets/AgentsPage-YvSgWRiw.js +10 -0
  43. package/dist/ui/dist/assets/CanvasPage-DtMwGvxf.js +33 -0
  44. package/dist/ui/dist/assets/ChannelsPage-BdBXWHjj.js +8 -0
  45. package/dist/ui/dist/assets/DashboardPage-ghl1ZguH.js +6 -0
  46. package/dist/ui/dist/assets/LoginPage-CAmSI9Vy.js +1 -0
  47. package/dist/ui/dist/assets/LogsPage-DAPBHkwK.js +1 -0
  48. package/dist/ui/dist/assets/MeetingPage-WjjGOqqU.js +1 -0
  49. package/dist/ui/dist/assets/NotFound-BMeQSGcG.js +1 -0
  50. package/dist/ui/dist/assets/ProvidersPage-Ct6HsAi1.js +1 -0
  51. package/dist/ui/dist/assets/RecoverPage-DpW3l-yv.js +1 -0
  52. package/dist/ui/dist/assets/SettingsPage-DBJ7_E6C.js +9 -0
  53. package/dist/ui/dist/assets/SetupPage-DKmLVUaj.js +1 -0
  54. package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +16 -0
  55. package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +1 -0
  56. package/dist/ui/dist/assets/activity-c3pNngT_.js +1 -0
  57. package/dist/ui/dist/assets/alert-C-NE-P3s.js +1 -0
  58. package/dist/ui/dist/assets/alert-dialog-C5mzbHdP.js +1 -0
  59. package/dist/ui/dist/assets/arrow-left-CBcbX5EZ.js +1 -0
  60. package/dist/ui/dist/assets/badge-ChpACfWO.js +1 -0
  61. package/dist/ui/dist/assets/calendar-B-KZ9RQO.js +1 -0
  62. package/dist/ui/dist/assets/card-CNf6BS2e.js +1 -0
  63. package/dist/ui/dist/assets/chevron-left-D4U-5A27.js +1 -0
  64. package/dist/ui/dist/assets/chevron-right-CR4Skrf3.js +1 -0
  65. package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +1 -0
  66. package/dist/ui/dist/assets/circle-alert-CyHDwUj8.js +1 -0
  67. package/dist/ui/dist/assets/circle-check-Bb54Ebmu.js +1 -0
  68. package/dist/ui/dist/assets/cpu-Cdgc_B1K.js +1 -0
  69. package/dist/ui/dist/assets/dialog-QnZ0ad8O.js +1 -0
  70. package/dist/ui/dist/assets/download-C3ifGMjJ.js +1 -0
  71. package/dist/ui/dist/assets/dropdown-menu-BK-CO3Od.js +1 -0
  72. package/dist/ui/dist/assets/es-NQNoaWDx.js +1 -0
  73. package/dist/ui/dist/assets/external-link-BvxYeTP1.js +1 -0
  74. package/dist/ui/dist/assets/eye-DqNTU_GD.js +1 -0
  75. package/dist/ui/dist/assets/file-text-BT_9S9SM.js +1 -0
  76. package/dist/ui/dist/assets/folder-open-BhH8y9ac.js +1 -0
  77. package/dist/ui/dist/assets/format-GVHeOyWI.js +1 -0
  78. package/dist/ui/dist/assets/gateway-url-COCbW0IR.js +1 -0
  79. package/dist/ui/dist/assets/gauge-D_TMa4i9.js +1 -0
  80. package/dist/ui/dist/assets/globe-DeCQTCDJ.js +1 -0
  81. package/dist/ui/dist/assets/hexagon-DsGOUl-H.js +1 -0
  82. package/dist/ui/dist/assets/history-BSG-Ypqf.js +1 -0
  83. package/dist/ui/dist/assets/index-B2fCYtTS.css +2 -0
  84. package/dist/ui/dist/assets/index-DMCjjdqf.js +116 -0
  85. package/dist/ui/dist/assets/info-NwLoa2Mj.js +1 -0
  86. package/dist/ui/dist/assets/key-3EP0dhkT.js +1 -0
  87. package/dist/ui/dist/assets/label-D2H1IR_J.js +1 -0
  88. package/dist/ui/dist/assets/loader-circle-CZNax6kS.js +1 -0
  89. package/dist/ui/dist/assets/lock-Ei1_J-Nq.js +1 -0
  90. package/dist/ui/dist/assets/pause-BUqah9Bi.js +1 -0
  91. package/dist/ui/dist/assets/play-NcZ4swwL.js +1 -0
  92. package/dist/ui/dist/assets/plus-CX1xyhp5.js +1 -0
  93. package/dist/ui/dist/assets/progress-BherYzY6.js +1 -0
  94. package/dist/ui/dist/assets/refresh-cw-DaYdjQFk.js +1 -0
  95. package/dist/ui/dist/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
  96. package/dist/ui/dist/assets/save-CUdYyHNy.js +1 -0
  97. package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +1 -0
  98. package/dist/ui/dist/assets/send-B0H5SEIE.js +1 -0
  99. package/dist/ui/dist/assets/settings-Ds4SqD8s.js +1 -0
  100. package/dist/ui/dist/assets/slider-CsiUDxc3.js +14 -0
  101. package/dist/ui/dist/assets/sparkles-yUEb-7oH.js +1 -0
  102. package/dist/ui/dist/assets/square-BD81nFtN.js +1 -0
  103. package/dist/ui/dist/assets/switch-BDwN8RYV.js +1 -0
  104. package/dist/ui/dist/assets/table-CSc8ubon.js +1 -0
  105. package/dist/ui/dist/assets/terminal-DN38Q456.js +1 -0
  106. package/dist/ui/dist/assets/textarea-CXgXWKrT.js +1 -0
  107. package/dist/ui/dist/assets/trash-2-CNjMkoq6.js +1 -0
  108. package/dist/ui/dist/assets/triangle-alert-C9Y8Ub4X.js +1 -0
  109. package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +1 -0
  110. package/dist/ui/dist/assets/utils-3pnRFmFe.js +1 -0
  111. package/dist/ui/dist/assets/vendor-charts-Bu2lyBKP.js +65 -0
  112. package/dist/ui/dist/assets/vendor-query-DsWPbQdG.js +1 -0
  113. package/dist/ui/dist/assets/vendor-radix-cw1bQaVC.js +63 -0
  114. package/dist/ui/dist/assets/vendor-react-D4s9E-zj.js +1 -0
  115. package/dist/ui/dist/assets/vendor-router-C9pIYwbJ.js +3 -0
  116. package/dist/ui/dist/assets/volume-2-CeSXNDv4.js +1 -0
  117. package/dist/ui/dist/assets/zap-hlXjpSeA.js +1 -0
  118. package/dist/ui/dist/favicon.ico +0 -0
  119. package/dist/ui/dist/index.html +40 -0
  120. package/dist/ui/dist/placeholder.svg +1 -0
  121. package/dist/ui/index.html +6 -6
  122. package/package.json +137 -13
  123. package/packages/cli/src/adapters/binary.ts +461 -0
  124. package/packages/cli/src/adapters/bun-global.ts +378 -0
  125. package/packages/cli/src/adapters/config.ts +314 -0
  126. package/packages/cli/src/adapters/docker.ts +308 -0
  127. package/packages/cli/src/adapters/factory.ts +168 -0
  128. package/packages/cli/src/adapters/index.ts +80 -0
  129. package/packages/cli/src/adapters/types.ts +218 -0
  130. package/packages/cli/src/commands/agent-run.ts +168 -0
  131. package/packages/cli/src/commands/agents.ts +398 -0
  132. package/packages/cli/src/commands/chat.ts +142 -0
  133. package/packages/cli/src/commands/config.ts +49 -0
  134. package/packages/cli/src/commands/cron.ts +487 -0
  135. package/packages/cli/src/commands/dev.ts +58 -0
  136. package/packages/cli/src/commands/doctor.ts +320 -0
  137. package/packages/cli/src/commands/gateway.ts +719 -0
  138. package/packages/cli/src/commands/logs.ts +57 -0
  139. package/packages/cli/src/commands/mcp.ts +175 -0
  140. package/packages/cli/src/commands/message.ts +77 -0
  141. package/packages/cli/src/commands/migrate.ts +90 -0
  142. package/packages/cli/src/commands/onboard.ts +1656 -0
  143. package/packages/cli/src/commands/security.ts +144 -0
  144. package/packages/cli/src/commands/service.ts +50 -0
  145. package/packages/cli/src/commands/sessions.ts +116 -0
  146. package/packages/cli/src/commands/skills.ts +215 -0
  147. package/packages/cli/src/commands/update.ts +203 -0
  148. package/packages/cli/src/index.ts +210 -0
  149. package/packages/cli/src/ui-bundle.generated.ts +3 -0
  150. package/packages/cli/src/utils/token.ts +6 -0
  151. package/packages/core/src/agent/agent-loop.ts +691 -0
  152. package/packages/core/src/agent/compaction.ts +240 -0
  153. package/packages/core/src/agent/context-compiler.ts +467 -0
  154. package/packages/core/src/agent/context-guard.ts +91 -0
  155. package/packages/core/src/agent/conversation-store.ts +244 -0
  156. package/packages/core/src/agent/curator.ts +158 -0
  157. package/packages/core/src/agent/hooks.ts +166 -0
  158. package/packages/core/src/agent/llm-client.ts +167 -0
  159. package/packages/core/src/agent/llm-providers/anthropic.ts +212 -0
  160. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  161. package/packages/core/src/agent/llm-providers/gemini.ts +215 -0
  162. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  163. package/packages/core/src/agent/llm-providers/interface.ts +195 -0
  164. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  165. package/packages/core/src/agent/llm-providers/local-llama.ts +37 -0
  166. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  167. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  168. package/packages/core/src/agent/llm-providers/ollama.ts +175 -0
  169. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +379 -0
  170. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  171. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  172. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  173. package/packages/core/src/agent/native-tools.ts +31 -0
  174. package/packages/core/src/agent/playbook-selector.ts +147 -0
  175. package/packages/core/src/agent/prompt-builder.ts +169 -0
  176. package/packages/core/src/agent/providers/index.ts +204 -0
  177. package/packages/core/src/agent/providers.ts +1 -0
  178. package/packages/core/src/agent/reflector.ts +200 -0
  179. package/packages/core/src/agent/service.ts +267 -0
  180. package/packages/core/src/agent/skill-selector.ts +479 -0
  181. package/packages/core/src/agent/stuck-loop.ts +133 -0
  182. package/packages/core/src/agent/tool-selector.ts +569 -0
  183. package/packages/core/src/agent/tracer.ts +100 -0
  184. package/packages/core/src/auth/auth.ts +108 -0
  185. package/packages/core/src/auth/index.ts +1 -0
  186. package/packages/core/src/canvas/a2ui-tools.ts +255 -0
  187. package/packages/core/src/canvas/canvas-manager.ts +390 -0
  188. package/packages/core/src/canvas/canvas-tools.ts +448 -0
  189. package/packages/core/src/canvas/emitter.ts +149 -0
  190. package/packages/core/src/canvas/index.ts +3 -0
  191. package/packages/core/src/channels/base.ts +154 -0
  192. package/packages/core/src/channels/discord.ts +273 -0
  193. package/packages/core/src/channels/index.ts +7 -0
  194. package/packages/core/src/channels/manager.ts +450 -0
  195. package/packages/core/src/channels/slack.ts +323 -0
  196. package/packages/core/src/channels/telegram.ts +612 -0
  197. package/packages/core/src/channels/webchat.ts +139 -0
  198. package/packages/core/src/channels/whatsapp.ts +548 -0
  199. package/packages/core/src/config/index.ts +12 -0
  200. package/packages/core/src/config/loader.ts +569 -0
  201. package/packages/core/src/events/agent-bus.ts +460 -0
  202. package/packages/core/src/events/event-bus.ts +169 -0
  203. package/packages/core/src/gateway/channel-notify.ts +64 -0
  204. package/packages/core/src/gateway/helpers/cors.ts +32 -0
  205. package/packages/core/src/gateway/helpers/index.ts +4 -0
  206. package/packages/core/src/gateway/helpers/narration.ts +57 -0
  207. package/packages/core/src/gateway/helpers/path.ts +13 -0
  208. package/packages/core/src/gateway/helpers/redact.ts +61 -0
  209. package/packages/core/src/gateway/index.ts +5 -0
  210. package/packages/core/src/gateway/initializer.ts +363 -0
  211. package/packages/core/src/gateway/lane-queue.ts +169 -0
  212. package/packages/core/src/gateway/llm-local/client.ts +94 -0
  213. package/packages/core/src/gateway/llm-local/detector.ts +321 -0
  214. package/packages/core/src/gateway/llm-local/downloader.ts +216 -0
  215. package/packages/core/src/gateway/llm-local/index.ts +34 -0
  216. package/packages/core/src/gateway/llm-local/manager.ts +186 -0
  217. package/packages/core/src/gateway/llm-local/models.ts +149 -0
  218. package/packages/core/src/gateway/llm-local/server.ts +179 -0
  219. package/packages/core/src/gateway/resolver.ts +108 -0
  220. package/packages/core/src/gateway/router.ts +124 -0
  221. package/packages/core/src/gateway/routes/agents.ts +210 -0
  222. package/packages/core/src/gateway/routes/auth.ts +244 -0
  223. package/packages/core/src/gateway/routes/channels.ts +484 -0
  224. package/packages/core/src/gateway/routes/chat.ts +241 -0
  225. package/packages/core/src/gateway/routes/config.ts +12 -0
  226. package/packages/core/src/gateway/routes/cron-api.ts +544 -0
  227. package/packages/core/src/gateway/routes/ethics.ts +46 -0
  228. package/packages/core/src/gateway/routes/llm-local.ts +271 -0
  229. package/packages/core/src/gateway/routes/mcp.ts +319 -0
  230. package/packages/core/src/gateway/routes/meeting.ts +232 -0
  231. package/packages/core/src/gateway/routes/models.ts +163 -0
  232. package/packages/core/src/gateway/routes/multimodal.ts +93 -0
  233. package/packages/core/src/gateway/routes/providers.ts +220 -0
  234. package/packages/core/src/gateway/routes/setup.ts +441 -0
  235. package/packages/core/src/gateway/routes/skills.ts +115 -0
  236. package/packages/core/src/gateway/routes/system.ts +469 -0
  237. package/packages/core/src/gateway/routes/tasks.ts +44 -0
  238. package/packages/core/src/gateway/routes/tools.ts +59 -0
  239. package/packages/core/src/gateway/routes/tts-local.ts +388 -0
  240. package/packages/core/src/gateway/routes/users.ts +122 -0
  241. package/packages/core/src/gateway/routes/voice.ts +189 -0
  242. package/packages/core/src/gateway/routes/workspace.ts +281 -0
  243. package/packages/core/src/gateway/server.ts +2744 -0
  244. package/packages/core/src/gateway/session.ts +95 -0
  245. package/packages/core/src/gateway/slash-commands.ts +207 -0
  246. package/packages/core/src/gateway/tts/README.md +94 -0
  247. package/packages/core/src/gateway/tts/package.json +25 -0
  248. package/packages/core/src/gateway/tts/src/client.ts +59 -0
  249. package/packages/core/src/gateway/tts/src/detect.ts +42 -0
  250. package/packages/core/src/gateway/tts/src/index.ts +15 -0
  251. package/packages/core/src/gateway/tts/src/install.ts +129 -0
  252. package/packages/core/src/gateway/tts/src/models.ts +50 -0
  253. package/packages/core/src/gateway/tts/src/server.ts +252 -0
  254. package/packages/core/src/gateway/tts/voices/.gitkeep +0 -0
  255. package/packages/core/src/heartbeat/index.ts +157 -0
  256. package/packages/core/src/index.ts +56 -0
  257. package/packages/core/src/mcp/hot-reload.ts +148 -0
  258. package/packages/core/src/mcp/singleton.ts +21 -0
  259. package/packages/core/src/mcp/tool-sync.ts +176 -0
  260. package/packages/core/src/multimodal/index.ts +2 -0
  261. package/packages/core/src/multimodal/types.ts +28 -0
  262. package/packages/core/src/multimodal/vision-service.ts +283 -0
  263. package/packages/core/src/plugins/api.ts +128 -0
  264. package/packages/core/src/plugins/index.ts +2 -0
  265. package/packages/core/src/plugins/loader.ts +365 -0
  266. package/packages/core/src/resilience/circuit-breaker.ts +225 -0
  267. package/packages/core/src/scheduler/CronScheduler.ts +699 -0
  268. package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
  269. package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
  270. package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
  271. package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
  272. package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
  273. package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
  274. package/packages/core/src/scheduler/dag/errors.ts +37 -0
  275. package/packages/core/src/scheduler/dag/index.ts +26 -0
  276. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
  277. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
  278. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
  279. package/packages/core/src/scheduler/index.ts +22 -0
  280. package/packages/core/src/scheduler/integration.ts +237 -0
  281. package/packages/core/src/scheduler/types.ts +164 -0
  282. package/packages/core/src/security/google-chat.ts +269 -0
  283. package/packages/core/src/security/index.ts +192 -0
  284. package/packages/core/src/security/pairing.ts +250 -0
  285. package/packages/core/src/security/rate-limit.ts +270 -0
  286. package/packages/core/src/security/signal.ts +321 -0
  287. package/packages/core/src/state/store.ts +312 -0
  288. package/packages/core/src/storage/crypto.ts +197 -0
  289. package/packages/core/src/storage/migrate.ts +147 -0
  290. package/packages/core/src/storage/onboarding.ts +1506 -0
  291. package/packages/core/src/storage/schema.ts +666 -0
  292. package/packages/core/src/storage/seed.ts +628 -0
  293. package/packages/core/src/storage/sqlite.ts +407 -0
  294. package/packages/core/src/storage/usage.ts +374 -0
  295. package/packages/core/src/tool-runtime/index.ts +476 -0
  296. package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
  297. package/packages/core/src/tools/agents/get-available-models.ts +118 -0
  298. package/packages/core/src/tools/agents/index.ts +610 -0
  299. package/packages/core/src/tools/canvas/index.ts +420 -0
  300. package/packages/core/src/tools/cli/index.ts +142 -0
  301. package/packages/core/src/tools/core/index.ts +478 -0
  302. package/packages/core/src/tools/cron/index.ts +635 -0
  303. package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
  304. package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
  305. package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
  306. package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
  307. package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
  308. package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
  309. package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
  310. package/packages/core/src/tools/filesystem/index.ts +34 -0
  311. package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
  312. package/packages/core/src/tools/index.ts +197 -0
  313. package/packages/core/src/tools/meeting/index.ts +363 -0
  314. package/packages/core/src/tools/office/index.ts +47 -0
  315. package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
  316. package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
  317. package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
  318. package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
  319. package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
  320. package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
  321. package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
  322. package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
  323. package/packages/core/src/tools/types.ts +39 -0
  324. package/packages/core/src/tools/voice/index.ts +104 -0
  325. package/packages/core/src/tools/web/browser-click.ts +78 -0
  326. package/packages/core/src/tools/web/browser-extract.ts +139 -0
  327. package/packages/core/src/tools/web/browser-navigate.ts +106 -0
  328. package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
  329. package/packages/core/src/tools/web/browser-script.ts +88 -0
  330. package/packages/core/src/tools/web/browser-service.ts +554 -0
  331. package/packages/core/src/tools/web/browser-type.ts +101 -0
  332. package/packages/core/src/tools/web/browser-wait.ts +136 -0
  333. package/packages/core/src/tools/web/index.ts +41 -0
  334. package/packages/core/src/tools/web/web-fetch.ts +78 -0
  335. package/packages/core/src/tools/web/web-search.ts +123 -0
  336. package/packages/core/src/utils/benchmark.ts +80 -0
  337. package/packages/core/src/utils/crypto.ts +73 -0
  338. package/packages/core/src/utils/date.ts +42 -0
  339. package/packages/core/src/utils/index.ts +5 -0
  340. package/packages/core/src/utils/logger.ts +389 -0
  341. package/packages/core/src/utils/retry.ts +70 -0
  342. package/packages/core/src/utils/toon.ts +253 -0
  343. package/packages/core/src/voice/index.ts +643 -0
  344. package/packages/mcp/src/config.ts +13 -0
  345. package/packages/mcp/src/index.ts +1 -0
  346. package/packages/mcp/src/logger.ts +47 -0
  347. package/packages/mcp/src/manager.ts +439 -0
  348. package/packages/mcp/src/transports/index.ts +67 -0
  349. package/packages/mcp/src/transports/sse.ts +238 -0
  350. package/packages/mcp/src/transports/websocket.ts +159 -0
  351. package/packages/skills/src/bundled/agents/agent_spawner/SKILL.md +167 -0
  352. package/packages/skills/src/bundled/agents/code_delegator/SKILL.md +156 -0
  353. package/packages/skills/src/bundled/agents/memory_manager/SKILL.md +143 -0
  354. package/packages/skills/src/bundled/agents/research_and_remember/SKILL.md +139 -0
  355. package/packages/skills/src/bundled/agents/task_orchestrator/SKILL.md +198 -0
  356. package/packages/skills/src/bundled/canvas/a2ui_dashboard/SKILL.md +176 -0
  357. package/packages/skills/src/bundled/canvas/a2ui_form/SKILL.md +202 -0
  358. package/packages/skills/src/bundled/canvas/a2ui_interactive/SKILL.md +206 -0
  359. package/packages/skills/src/bundled/canvas/canvas_dashboard/SKILL.md +146 -0
  360. package/packages/skills/src/bundled/canvas/canvas_interact/SKILL.md +148 -0
  361. package/packages/skills/src/bundled/canvas/canvas_report/SKILL.md +146 -0
  362. package/packages/skills/src/bundled/cli/cli_pipeline/SKILL.md +136 -0
  363. package/packages/skills/src/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  364. package/packages/skills/src/bundled/cron_manager/SKILL.md +188 -0
  365. package/packages/skills/src/bundled/cron_reminder/SKILL.md +112 -0
  366. package/packages/skills/src/bundled/filesystem/file_manager/SKILL.md +118 -0
  367. package/packages/skills/src/bundled/filesystem/file_read_and_summarize/SKILL.md +108 -0
  368. package/packages/skills/src/bundled/filesystem/file_writer/SKILL.md +135 -0
  369. package/packages/skills/src/bundled/meeting/meeting_transcription/SKILL.md +213 -0
  370. package/packages/skills/src/bundled/office/office_document_manager/SKILL.md +262 -0
  371. package/packages/skills/src/bundled/search_knowledge/busqueda_fts5/SKILL.md +74 -0
  372. package/packages/skills/src/bundled/voice/voice_assistant/SKILL.md +174 -0
  373. package/packages/skills/src/bundled/voice/voice_input/SKILL.md +146 -0
  374. package/packages/skills/src/bundled/voice/voice_output/SKILL.md +151 -0
  375. package/packages/skills/src/bundled/web/browser_automate/SKILL.md +120 -0
  376. package/packages/skills/src/bundled/web/browser_scrape/SKILL.md +109 -0
  377. package/packages/skills/src/bundled/web/web_monitor/SKILL.md +127 -0
  378. package/packages/skills/src/bundled/web/web_research/SKILL.md +119 -0
  379. package/packages/skills/src/bundled-data.generated.ts +1964 -0
  380. package/packages/skills/src/index.ts +1 -0
  381. package/packages/skills/src/loader.ts +388 -0
  382. package/dist/ui/assets/AgentNewPage-GB-tVN50.js +0 -1
  383. package/dist/ui/assets/BridgePage-DDcDILKu.js +0 -1
  384. package/dist/ui/assets/CanvasPage-oOk2sGOD.js +0 -33
  385. package/dist/ui/assets/DashboardPage-DV_2qWYJ.js +0 -6
  386. package/dist/ui/assets/LogsPage-DayYjh01.js +0 -1
  387. package/dist/ui/assets/MeetingPage-C01uPuqj.js +0 -1
  388. package/dist/ui/assets/ProjectsPage-B8_am_Ib.js +0 -1
  389. package/dist/ui/assets/ProvidersPage-DBzi66e4.js +0 -1
  390. package/dist/ui/assets/SettingsPage-CFA_Tknl.js +0 -9
  391. package/dist/ui/assets/SetupPage-BrUWbhvT.js +0 -1
  392. package/dist/ui/assets/accordion-DdAEfIXR.js +0 -1
  393. package/dist/ui/assets/chevron-down-DIosfU_U.js +0 -1
  394. package/dist/ui/assets/chevron-up-CI-W21Fy.js +0 -1
  395. package/dist/ui/assets/circle-S0-ouLz-.js +0 -1
  396. package/dist/ui/assets/circle-minus-CE0iJrl8.js +0 -1
  397. package/dist/ui/assets/circle-x-jUJ5zZvQ.js +0 -1
  398. package/dist/ui/assets/dropdown-menu-C2CXM1VE.js +0 -1
  399. package/dist/ui/assets/index-BN0875JH.css +0 -2
  400. package/dist/ui/assets/index-CH6sBa3Q.js +0 -116
  401. package/dist/ui/assets/pencil-5VdSj-h5.js +0 -1
  402. package/dist/ui/assets/progress-JN30I5fF.js +0 -1
  403. package/dist/ui/assets/scroll-area-BQQPitM8.js +0 -1
  404. package/dist/ui/assets/search-ChPgnVKj.js +0 -1
  405. package/dist/ui/assets/switch-C7W2-KEx.js +0 -1
  406. package/dist/ui/assets/terminal-C-R5Fckz.js +0 -1
  407. package/dist/ui/assets/useProviders-TBnWn-Hq.js +0 -1
  408. /package/dist/ui/assets/{card-DFKnZ6ky.js → card-CNf6BS2e.js} +0 -0
  409. /package/dist/ui/assets/{circle-alert-KuAm2FWh.js → circle-alert-CyHDwUj8.js} +0 -0
  410. /package/dist/ui/assets/{circle-check-6Ard1-2z.js → circle-check-Bb54Ebmu.js} +0 -0
  411. /package/dist/ui/assets/{cpu-KDy6-FAI.js → cpu-Cdgc_B1K.js} +0 -0
  412. /package/dist/ui/assets/{download-Cjbk4Rek.js → download-C3ifGMjJ.js} +0 -0
  413. /package/dist/ui/assets/{external-link-HtrFM63g.js → external-link-BvxYeTP1.js} +0 -0
  414. /package/dist/ui/assets/{eye-D1dB40_o.js → eye-DqNTU_GD.js} +0 -0
  415. /package/dist/ui/assets/{file-text-CE58EfH0.js → file-text-BT_9S9SM.js} +0 -0
  416. /package/dist/ui/assets/{folder-open-DIPKeiI_.js → folder-open-BhH8y9ac.js} +0 -0
  417. /package/dist/ui/assets/{format-BwdV8bB5.js → format-GVHeOyWI.js} +0 -0
  418. /package/dist/ui/assets/{gateway-url-D5uj6Nxg.js → gateway-url-COCbW0IR.js} +0 -0
  419. /package/dist/ui/assets/{gauge-DmQmJHEg.js → gauge-D_TMa4i9.js} +0 -0
  420. /package/dist/ui/assets/{globe-_hUGxQF4.js → globe-DeCQTCDJ.js} +0 -0
  421. /package/dist/ui/assets/{hexagon-BaNGQlQj.js → hexagon-DsGOUl-H.js} +0 -0
  422. /package/dist/ui/assets/{history-BfZVGlZa.js → history-BSG-Ypqf.js} +0 -0
  423. /package/dist/ui/assets/{info-CBZ5-AlC.js → info-NwLoa2Mj.js} +0 -0
  424. /package/dist/ui/assets/{key-Bv5DdTPh.js → key-3EP0dhkT.js} +0 -0
  425. /package/dist/ui/assets/{loader-circle-C4hhXLgp.js → loader-circle-CZNax6kS.js} +0 -0
  426. /package/dist/ui/assets/{lock-CkZYexqw.js → lock-Ei1_J-Nq.js} +0 -0
  427. /package/dist/ui/assets/{pause-Bpy1_s7y.js → pause-BUqah9Bi.js} +0 -0
  428. /package/dist/ui/assets/{play-Cj4osqJZ.js → play-NcZ4swwL.js} +0 -0
  429. /package/dist/ui/assets/{plus-BQhgZN3A.js → plus-CX1xyhp5.js} +0 -0
  430. /package/dist/ui/assets/{refresh-cw-BfREHVQM.js → refresh-cw-DaYdjQFk.js} +0 -0
  431. /package/dist/ui/assets/{save-FFTD4dMp.js → save-CUdYyHNy.js} +0 -0
  432. /package/dist/ui/assets/{settings-BdHKUL92.js → settings-Ds4SqD8s.js} +0 -0
  433. /package/dist/ui/assets/{sparkles-r4uJbJAl.js → sparkles-yUEb-7oH.js} +0 -0
  434. /package/dist/ui/assets/{square-G7Hyufqm.js → square-BD81nFtN.js} +0 -0
  435. /package/dist/ui/assets/{textarea-5kyuD04X.js → textarea-CXgXWKrT.js} +0 -0
  436. /package/dist/ui/assets/{trash-2-DXVBRWfh.js → trash-2-CNjMkoq6.js} +0 -0
  437. /package/dist/ui/assets/{triangle-alert-Bu5seg9O.js → triangle-alert-C9Y8Ub4X.js} +0 -0
  438. /package/dist/ui/assets/{vendor-router-CCECILJ0.js → vendor-router-C9pIYwbJ.js} +0 -0
  439. /package/dist/ui/assets/{volume-2-s9DuS696.js → volume-2-CeSXNDv4.js} +0 -0
  440. /package/dist/ui/assets/{zap-BPHZzXKV.js → zap-hlXjpSeA.js} +0 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * LLM client — direct official SDKs, no abstraction layers.
3
+ *
4
+ * gemini / google → native Gemini REST API (v1beta, ?key=)
5
+ * anthropic → @anthropic-ai/sdk
6
+ * ollama → ollama npm package
7
+ * openai → openai npm package
8
+ * groq / mistral / openrouter / deepseek / kimi / local-llama / nvidia / qwen
9
+ * → openai npm package (OpenAI-compatible endpoint, per-provider adapter)
10
+ *
11
+ * Public interface (LLMMessage, callLLM, resolveProviderConfig) is stable.
12
+ */
13
+
14
+ import { logger } from "../utils/logger"
15
+ import { GeminiProvider } from "./llm-providers/gemini"
16
+ import { AnthropicProvider } from "./llm-providers/anthropic"
17
+ import { OllamaProvider } from "./llm-providers/ollama"
18
+ import { OpenAIProvider } from "./llm-providers/openai"
19
+ import { GroqProvider } from "./llm-providers/groq"
20
+ import { MistralProvider } from "./llm-providers/mistral"
21
+ import { OpenRouterProvider } from "./llm-providers/openrouter"
22
+ import { DeepSeekProvider } from "./llm-providers/deepseek"
23
+ import { KimiProvider } from "./llm-providers/kimi"
24
+ import { LocalLlamaProvider } from "./llm-providers/local-llama"
25
+ import { NvidiaProvider } from "./llm-providers/nvidia"
26
+ import { QwenProvider } from "./llm-providers/qwen"
27
+ import type { LLMProvider } from "./llm-providers/interface"
28
+
29
+ const log = logger.child("llm-client")
30
+
31
+ // ─── Canonical types ───────────────────────────────────────────────────────────
32
+
33
+ export interface LLMToolCall {
34
+ id: string
35
+ type: "function"
36
+ function: { name: string; arguments: string }
37
+ /** Gemini 3.x thought signature — must be round-tripped for tool-calling. */
38
+ thought_signature?: string
39
+ }
40
+
41
+ export type ContentPart =
42
+ | { type: "text"; text: string }
43
+ | { type: "image_url"; image_url: { url: string } }
44
+ | { type: "image_base64"; base64: string; mimeType: string }
45
+ | { type: "document"; base64: string; mimeType: string; fileName?: string }
46
+
47
+ export interface LLMMessage {
48
+ role: "system" | "user" | "assistant" | "tool"
49
+ content: string | ContentPart[]
50
+ tool_calls?: LLMToolCall[]
51
+ tool_call_id?: string
52
+ name?: string
53
+ /** Kimi K2 thinking mode — must be round-tripped when tool calls are present. */
54
+ reasoning_content?: string
55
+ }
56
+
57
+ export interface LLMToolDef {
58
+ type: "function"
59
+ function: {
60
+ name: string
61
+ description: string
62
+ parameters: Record<string, unknown>
63
+ }
64
+ }
65
+
66
+ export interface LLMCallOptions {
67
+ provider: string
68
+ model: string
69
+ apiKey: string
70
+ baseUrl?: string
71
+ numCtx?: number
72
+ contextWindow?: number
73
+ messages: LLMMessage[]
74
+ tools?: LLMToolDef[]
75
+ temperature?: number
76
+ maxTokens?: number
77
+ numGpu?: number
78
+ onToken?: (token: string) => void
79
+ signal?: AbortSignal
80
+ /** Enable extended thinking for supported models (Anthropic Claude 3.7+). */
81
+ thinking?: { enabled: boolean; budget_tokens?: number }
82
+ }
83
+
84
+ export interface LLMResponse {
85
+ content: string
86
+ tool_calls?: LLMToolCall[]
87
+ stop_reason: "stop" | "tool_calls" | "max_tokens" | "error"
88
+ usage?: { input_tokens: number; output_tokens: number; thinking_tokens?: number }
89
+ /** Kimi K2 / DeepSeek thinking mode — must be round-tripped in assistant messages. */
90
+ reasoning_content?: string
91
+ /** Anthropic extended thinking content (not sent to LLM, for display only). */
92
+ thinking_content?: string
93
+ }
94
+
95
+ // ─── Provider factory ─────────────────────────────────────────────────────────
96
+
97
+ function getProvider(provider: string): LLMProvider {
98
+ switch (provider) {
99
+ case "gemini":
100
+ case "google": return new GeminiProvider()
101
+ case "anthropic": return new AnthropicProvider()
102
+ case "ollama": return new OllamaProvider()
103
+ case "openai": return new OpenAIProvider()
104
+ case "groq": return new GroqProvider()
105
+ case "mistral": return new MistralProvider()
106
+ case "openrouter": return new OpenRouterProvider()
107
+ case "deepseek": return new DeepSeekProvider()
108
+ case "kimi": return new KimiProvider()
109
+ case "local-llama": return new LocalLlamaProvider()
110
+ case "nvidia": return new NvidiaProvider()
111
+ case "qwen": return new QwenProvider()
112
+ default:
113
+ log.warn(`[llm-client] Unknown provider "${provider}" — falling back to OpenAI-compatible endpoint`)
114
+ return new OpenAIProvider()
115
+ }
116
+ }
117
+
118
+ // ─── Public API ────────────────────────────────────────────────────────────────
119
+
120
+ /**
121
+ * Call any LLM provider. Returns a canonical LLMResponse regardless of provider.
122
+ */
123
+ export async function callLLM(options: LLMCallOptions): Promise<LLMResponse> {
124
+ try {
125
+ return await getProvider(options.provider).call(options)
126
+ } catch (err) {
127
+ const msg = (err as Error).message
128
+ const cleanModel = options.model.replace(new RegExp(`^${options.provider}\\/`), "")
129
+ log.error(`[llm-client] Error calling ${options.provider}/${cleanModel}: ${msg}`, err)
130
+ return { content: `[LLM Error] ${msg}`, stop_reason: "error" }
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Resolve provider config from DB (decrypts API key).
136
+ */
137
+ export async function resolveProviderConfig(
138
+ providerId: string,
139
+ modelId: string
140
+ ): Promise<Pick<LLMCallOptions, "provider" | "model" | "apiKey" | "baseUrl" | "numCtx" | "numGpu" | "contextWindow">> {
141
+ const { getDb } = await import("../storage/sqlite")
142
+ const { loadProviderApiKey } = await import("../storage/crypto")
143
+ const db = getDb()
144
+ const providerRow = db
145
+ .query<any, [string]>("SELECT * FROM providers WHERE id = ? AND enabled = 1")
146
+ .get(providerId)
147
+
148
+ // Load model's context window for token budget management
149
+ const modelRow = db
150
+ .query<any, [string]>("SELECT context_window FROM models WHERE id = ?")
151
+ .get(modelId)
152
+
153
+ let apiKey = await loadProviderApiKey(providerId)
154
+ if (!apiKey) {
155
+ apiKey = process.env[`${providerId.toUpperCase()}_API_KEY`] || ""
156
+ }
157
+
158
+ return {
159
+ provider: providerId,
160
+ model: modelId,
161
+ apiKey,
162
+ baseUrl: providerRow?.base_url || undefined,
163
+ numCtx: providerRow?.num_ctx ?? undefined,
164
+ numGpu: providerRow?.num_gpu ?? undefined,
165
+ contextWindow: modelRow?.context_window ?? undefined,
166
+ }
167
+ }
@@ -0,0 +1,212 @@
1
+ import { logger } from "../../utils/logger"
2
+ import type { LLMCallOptions, LLMProvider, LLMResponse, LLMToolCall } from "./interface"
3
+ import type { ContentPart, LLMMessage } from "../llm-client"
4
+
5
+ const log = logger.child("llm-client")
6
+
7
+ // Models that support extended thinking (claude-3-7+ and claude-4.x).
8
+ const THINKING_CAPABLE_MODELS = new Set([
9
+ "claude-3-7-sonnet-20250219",
10
+ "claude-sonnet-4-5",
11
+ "claude-sonnet-4-6",
12
+ "claude-opus-4-5",
13
+ "claude-opus-4-6",
14
+ "claude-opus-4-7",
15
+ "claude-haiku-4-5",
16
+ "claude-haiku-4-5-20251001",
17
+ ])
18
+
19
+ function supportsThinking(model: string): boolean {
20
+ if (THINKING_CAPABLE_MODELS.has(model)) return true
21
+ // Also match any claude-4.x or claude-3-7+ by prefix
22
+ return /^claude-(4|3-7)/.test(model)
23
+ }
24
+
25
+ export class AnthropicProvider implements LLMProvider {
26
+ private _convertContentPart(part: ContentPart): any {
27
+ switch (part.type) {
28
+ case "text":
29
+ return { type: "text", text: part.text }
30
+ case "image_url": {
31
+ const url = part.image_url.url
32
+ if (url.startsWith("data:")) {
33
+ const match = url.match(/^data:([^;]+);base64,(.+)$/)
34
+ if (match) return { type: "image", source: { type: "base64", media_type: match[1], data: match[2] } }
35
+ }
36
+ return { type: "image", source: { type: "url", url } }
37
+ }
38
+ case "image_base64":
39
+ return { type: "image", source: { type: "base64", media_type: part.mimeType, data: part.base64 } }
40
+ case "document":
41
+ return { type: "document", source: { type: "base64", media_type: part.mimeType, data: part.base64 } }
42
+ default:
43
+ return { type: "text", text: JSON.stringify(part) }
44
+ }
45
+ }
46
+
47
+ private _convertUserContent(msg: LLMMessage): any[] {
48
+ if (Array.isArray(msg.content)) {
49
+ return msg.content.map(p => this._convertContentPart(p))
50
+ }
51
+ return [{ type: "text", text: msg.content }]
52
+ }
53
+
54
+ async call(options: LLMCallOptions): Promise<LLMResponse> {
55
+ const Anthropic = await import("@anthropic-ai/sdk")
56
+ const client = new Anthropic.default({ apiKey: options.apiKey })
57
+
58
+ const systemText = options.messages
59
+ .filter((m) => m.role === "system")
60
+ .map((m) => m.content)
61
+ .join("\n\n")
62
+
63
+ const anthropicMessages: any[] = []
64
+
65
+ for (const msg of options.messages) {
66
+ if (msg.role === "system") continue
67
+
68
+ if (msg.role === "tool") {
69
+ const block = { type: "tool_result", tool_use_id: msg.tool_call_id, content: msg.content }
70
+ const last = anthropicMessages[anthropicMessages.length - 1]
71
+ if (last?.role === "user" && Array.isArray(last.content)) {
72
+ last.content.push(block)
73
+ } else {
74
+ anthropicMessages.push({ role: "user", content: [block] })
75
+ }
76
+ continue
77
+ }
78
+
79
+ if (msg.role === "assistant" && msg.tool_calls?.length) {
80
+ const content: any[] = []
81
+ if (msg.content) content.push({ type: "text", text: msg.content })
82
+ for (const tc of msg.tool_calls) {
83
+ let input: Record<string, unknown>
84
+ try { input = JSON.parse(tc.function.arguments || "{}") } catch { input = {} }
85
+ content.push({ type: "tool_use", id: tc.id, name: tc.function.name, input })
86
+ }
87
+ anthropicMessages.push({ role: "assistant", content })
88
+ continue
89
+ }
90
+
91
+ anthropicMessages.push({ role: msg.role, content: Array.isArray(msg.content) ? this._convertUserContent(msg) : msg.content })
92
+ }
93
+
94
+ const tools: any[] = (options.tools ?? []).map((t) => ({
95
+ name: t.function.name,
96
+ description: t.function.description,
97
+ input_schema: t.function.parameters,
98
+ }))
99
+
100
+ const body: any = {
101
+ model: options.model,
102
+ max_tokens: options.maxTokens ?? 16384,
103
+ messages: anthropicMessages,
104
+ }
105
+ if (systemText) body.system = systemText
106
+ if (tools.length) body.tools = tools
107
+
108
+ // Extended thinking — only for supported models
109
+ const thinkingEnabled = options.thinking?.enabled && supportsThinking(options.model)
110
+ if (thinkingEnabled) {
111
+ body.thinking = { type: "enabled", budget_tokens: options.thinking?.budget_tokens ?? 10000 }
112
+ }
113
+
114
+ log.info(
115
+ `[llm-client] anthropic/${options.model} — ${anthropicMessages.length} msgs, ${tools.length} tools` +
116
+ (thinkingEnabled ? ` thinking=${body.thinking.budget_tokens}tok` : "")
117
+ )
118
+
119
+ let content = ""
120
+ let thinking_content = ""
121
+ const tool_calls: LLMToolCall[] = []
122
+
123
+ // Streaming via messages.stream()
124
+ const useStream = true // Always stream for better UX
125
+ if (useStream) {
126
+ const stream = client.messages.stream({ ...body, ...(options.signal ? {} : {}) })
127
+
128
+ // Track partial tool inputs by index
129
+ const partialInputs: Record<number, string> = {}
130
+ const toolMeta: Record<number, { id: string; name: string }> = {}
131
+
132
+ for await (const event of stream) {
133
+ if (event.type === "content_block_start") {
134
+ if (event.content_block.type === "tool_use") {
135
+ toolMeta[event.index] = { id: event.content_block.id, name: event.content_block.name }
136
+ partialInputs[event.index] = ""
137
+ }
138
+ } else if (event.type === "content_block_delta") {
139
+ if (event.delta.type === "text_delta") {
140
+ content += event.delta.text
141
+ if (options.onToken) options.onToken(event.delta.text)
142
+ } else if (event.delta.type === "thinking_delta") {
143
+ thinking_content += event.delta.thinking
144
+ } else if (event.delta.type === "input_json_delta") {
145
+ if (partialInputs[event.index] !== undefined) {
146
+ partialInputs[event.index] += event.delta.partial_json
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ const finalMsg = await stream.finalMessage()
153
+
154
+ // Build tool_calls from accumulated partial inputs
155
+ for (const [idx, meta] of Object.entries(toolMeta)) {
156
+ const args = partialInputs[Number(idx)] ?? "{}"
157
+ tool_calls.push({
158
+ id: meta.id,
159
+ type: "function",
160
+ function: { name: meta.name, arguments: args },
161
+ })
162
+ }
163
+
164
+ const usage = finalMsg.usage
165
+ return {
166
+ content,
167
+ thinking_content: thinking_content || undefined,
168
+ tool_calls: tool_calls.length ? tool_calls : undefined,
169
+ stop_reason:
170
+ finalMsg.stop_reason === "tool_use" ? "tool_calls"
171
+ : finalMsg.stop_reason === "max_tokens" ? "max_tokens"
172
+ : "stop",
173
+ usage: {
174
+ input_tokens: usage.input_tokens,
175
+ output_tokens: usage.output_tokens,
176
+ thinking_tokens: (usage as any).thinking_tokens ?? 0,
177
+ },
178
+ }
179
+ }
180
+
181
+ // Non-streaming fallback (kept for reference, unreachable with useStream=true)
182
+ const response = await client.messages.create(body)
183
+
184
+ for (const block of response.content) {
185
+ if (block.type === "text") content = block.text
186
+ if (block.type === "thinking") thinking_content = (block as any).thinking ?? ""
187
+ if (block.type === "tool_use") {
188
+ let args: string
189
+ try { args = JSON.stringify(block.input) } catch { args = "{}" }
190
+ tool_calls.push({
191
+ id: block.id,
192
+ type: "function",
193
+ function: { name: block.name, arguments: args },
194
+ })
195
+ }
196
+ }
197
+
198
+ return {
199
+ content,
200
+ thinking_content: thinking_content || undefined,
201
+ tool_calls: tool_calls.length ? tool_calls : undefined,
202
+ stop_reason:
203
+ response.stop_reason === "tool_use" ? "tool_calls"
204
+ : response.stop_reason === "max_tokens" ? "max_tokens"
205
+ : "stop",
206
+ usage: {
207
+ input_tokens: response.usage.input_tokens,
208
+ output_tokens: response.usage.output_tokens,
209
+ },
210
+ }
211
+ }
212
+ }
@@ -0,0 +1,8 @@
1
+ import { OpenAICompatBase } from "./openai-compat-base"
2
+
3
+ export class DeepSeekProvider extends OpenAICompatBase {
4
+ constructor() { super("deepseek") }
5
+
6
+ /** DeepSeek reasoner models return reasoning_content that must be round-tripped. */
7
+ protected needsReasoningRoundtrip(): boolean { return true }
8
+ }
@@ -0,0 +1,215 @@
1
+ import { logger } from "../../utils/logger"
2
+ import { sanitizeMessages } from "./interface"
3
+ import type { LLMCallOptions, LLMProvider, LLMResponse, LLMToolCall } from "./interface"
4
+ import type { ContentPart, LLMMessage } from "../llm-client"
5
+
6
+ const log = logger.child("llm-client")
7
+
8
+ export class GeminiProvider implements LLMProvider {
9
+ private _convertContentPart(part: ContentPart): any {
10
+ switch (part.type) {
11
+ case "text":
12
+ return { text: part.text }
13
+ case "image_url": {
14
+ const url = part.image_url.url
15
+ if (url.startsWith("data:")) {
16
+ const match = url.match(/^data:([^;]+);base64,(.+)$/)
17
+ if (match) return { inlineData: { mimeType: match[1], data: match[2] } }
18
+ }
19
+ return { text: `[Image URL: ${url}]` }
20
+ }
21
+ case "image_base64":
22
+ return { inlineData: { mimeType: part.mimeType, data: part.base64 } }
23
+ case "document":
24
+ return { inlineData: { mimeType: part.mimeType, data: part.base64 } }
25
+ default:
26
+ return { text: JSON.stringify(part) }
27
+ }
28
+ }
29
+
30
+ private _convertUserParts(msg: LLMMessage): any[] {
31
+ if (Array.isArray(msg.content)) {
32
+ return msg.content.map(p => this._convertContentPart(p))
33
+ }
34
+ return [{ text: msg.content }]
35
+ }
36
+
37
+ async call(options: LLMCallOptions): Promise<LLMResponse> {
38
+ const { GoogleGenAI } = await import("@google/genai")
39
+
40
+ const clientOpts: any = { apiKey: options.apiKey }
41
+ if (options.baseUrl?.trim()) clientOpts.httpOptions = { baseUrl: options.baseUrl.trim() }
42
+
43
+ const ai = new GoogleGenAI(clientOpts)
44
+
45
+ const cleanMessages = sanitizeMessages(options.messages)
46
+
47
+ // Build toolCallId → name map for converting tool results
48
+ const toolNameMap = new Map<string, string>()
49
+ for (const msg of cleanMessages) {
50
+ if (msg.role === "assistant" && msg.tool_calls) {
51
+ for (const tc of msg.tool_calls) toolNameMap.set(tc.id, tc.function.name)
52
+ }
53
+ }
54
+
55
+ // Convert canonical messages → Gemini Content[]
56
+ let systemText = ""
57
+ const rawContents: any[] = []
58
+
59
+ for (const msg of cleanMessages) {
60
+ if (msg.role === "system") {
61
+ systemText += (systemText ? "\n\n" : "") + msg.content
62
+ continue
63
+ }
64
+ if (msg.role === "user") {
65
+ rawContents.push({ role: "user", parts: this._convertUserParts(msg) })
66
+ continue
67
+ }
68
+ if (msg.role === "assistant") {
69
+ const parts: any[] = []
70
+ if (msg.content) parts.push({ text: msg.content })
71
+ for (const tc of msg.tool_calls ?? []) {
72
+ const fcPart: any = { functionCall: { name: tc.function.name, args: JSON.parse(tc.function.arguments || "{}") } }
73
+ if (tc.thought_signature) fcPart.thoughtSignature = tc.thought_signature
74
+ parts.push(fcPart)
75
+ }
76
+ if (parts.length) rawContents.push({ role: "model", parts })
77
+ continue
78
+ }
79
+ if (msg.role === "tool") {
80
+ const fnName = toolNameMap.get(msg.tool_call_id || "") || msg.name || "tool"
81
+ const frPart = { functionResponse: { name: fnName, response: { output: msg.content } } }
82
+ const last = rawContents[rawContents.length - 1]
83
+ if (last?.role === "user" && Array.isArray(last.parts)) {
84
+ last.parts.push(frPart)
85
+ } else {
86
+ rawContents.push({ role: "user", parts: [frPart] })
87
+ }
88
+ }
89
+ }
90
+
91
+ // Gemini constraint enforcement
92
+ const contents: any[] = rawContents
93
+
94
+ while (contents.length > 0 && contents[0].role === "model") {
95
+ log.warn(`[llm-client] Gemini: removed leading model turn (no preceding user turn)`)
96
+ contents.shift()
97
+ }
98
+
99
+ let changed = true
100
+ let safetyLimit = 10
101
+ while (changed && safetyLimit-- > 0) {
102
+ changed = false
103
+
104
+ for (let i = 0; i < contents.length; i++) {
105
+ const turn = contents[i]
106
+ const prev = i > 0 ? contents[i - 1] : null
107
+
108
+ // INV-3: merge consecutive model turns
109
+ if (turn.role === "model" && prev?.role === "model") {
110
+ prev.parts.push(...(turn.parts ?? []))
111
+ contents.splice(i, 1)
112
+ i--
113
+ changed = true
114
+ continue
115
+ }
116
+
117
+ // INV-1: model(fc) must come after user
118
+ if (turn.role === "model") {
119
+ const hasFc = turn.parts?.some((p: any) => p.functionCall)
120
+ if (hasFc && prev?.role !== "user") {
121
+ turn.parts = (turn.parts ?? []).filter((p: any) => !p.functionCall)
122
+ log.warn(`[llm-client] Gemini: stripped functionCall not after user turn (i=${i})`)
123
+ if (turn.parts.length === 0) { contents.splice(i, 1); i-- }
124
+ changed = true
125
+ continue
126
+ }
127
+ }
128
+
129
+ // INV-2: user(fr) must come after model(fc)
130
+ if (turn.role === "user") {
131
+ const hasFr = turn.parts?.some((p: any) => p.functionResponse)
132
+ const prevHasFc = prev?.role === "model" && prev?.parts?.some((p: any) => p.functionCall)
133
+ if (hasFr && !prevHasFc) {
134
+ turn.parts = (turn.parts ?? []).filter((p: any) => !p.functionResponse)
135
+ log.warn(`[llm-client] Gemini: stripped orphaned functionResponse (i=${i})`)
136
+ if (turn.parts.length === 0) { contents.splice(i, 1); i-- }
137
+ changed = true
138
+ continue
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ if (safetyLimit <= 0) {
145
+ log.error(`[llm-client] Gemini: constraint enforcement loop exhausted — message history may still violate Gemini constraints`)
146
+ }
147
+
148
+ const config: any = {}
149
+ if (systemText) config.systemInstruction = systemText
150
+ if (options.maxTokens) config.maxOutputTokens = options.maxTokens
151
+ if (options.temperature !== undefined) config.temperature = options.temperature
152
+ if (options.tools?.length) {
153
+ config.tools = [{
154
+ functionDeclarations: options.tools.map((t) => ({
155
+ name: t.function.name,
156
+ description: t.function.description,
157
+ parameters: t.function.parameters,
158
+ })),
159
+ }]
160
+ }
161
+
162
+ log.info(`[llm-client] gemini/${options.model} — ${contents.length} turns, ${options.tools?.length ?? 0} tools`)
163
+
164
+ const response = await ai.models.generateContent({ model: options.model, contents, config })
165
+
166
+ const candidate = response.candidates?.[0]
167
+
168
+ // Handle safety blocks explicitly
169
+ if (candidate?.finishReason === "SAFETY") {
170
+ log.warn(`[llm-client] Gemini: response blocked by safety filters (model=${options.model})`)
171
+ return {
172
+ content: "[Response blocked by Gemini safety filters]",
173
+ stop_reason: "stop",
174
+ usage: response.usageMetadata ? {
175
+ input_tokens: response.usageMetadata.promptTokenCount ?? 0,
176
+ output_tokens: 0,
177
+ } : undefined,
178
+ }
179
+ }
180
+
181
+ const parts: any[] = candidate?.content?.parts ?? []
182
+
183
+ let content = ""
184
+ const tool_calls: LLMToolCall[] = []
185
+
186
+ for (const part of parts) {
187
+ if (part.text) content += part.text
188
+ if (part.functionCall) {
189
+ tool_calls.push({
190
+ id: crypto.randomUUID(),
191
+ type: "function",
192
+ function: { name: part.functionCall.name, arguments: JSON.stringify(part.functionCall.args ?? {}) },
193
+ thought_signature: part.thoughtSignature ?? undefined,
194
+ })
195
+ }
196
+ }
197
+
198
+ const stop_reason: LLMResponse["stop_reason"] =
199
+ tool_calls.length > 0 ? "tool_calls"
200
+ : candidate?.finishReason === "MAX_TOKENS" ? "max_tokens"
201
+ : "stop"
202
+
203
+ const usageMeta = response.usageMetadata
204
+ return {
205
+ content,
206
+ tool_calls: tool_calls.length ? tool_calls : undefined,
207
+ stop_reason,
208
+ usage: usageMeta ? {
209
+ input_tokens: usageMeta.promptTokenCount ?? 0,
210
+ output_tokens: usageMeta.candidatesTokenCount ?? 0,
211
+ thinking_tokens: (usageMeta as any).thoughtsTokenCount ?? 0,
212
+ } : undefined,
213
+ }
214
+ }
215
+ }
@@ -0,0 +1,5 @@
1
+ import { OpenAICompatBase } from "./openai-compat-base"
2
+
3
+ export class GroqProvider extends OpenAICompatBase {
4
+ constructor() { super("groq") }
5
+ }