@johpaz/hive-agents 0.0.34 → 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.
- package/README.md +64 -39
- package/dist/hive.js +4539 -4586
- package/dist/ui/assets/AgentCreateForm-tJZv9FZC.js +1 -0
- package/dist/ui/assets/AgentDetailPage-Du-mRcAX.js +1 -0
- package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
- package/dist/ui/assets/{AgentsPage-DhCjvDNa.js → AgentsPage-YvSgWRiw.js} +7 -7
- package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
- package/dist/ui/assets/ChannelsPage-BdBXWHjj.js +8 -0
- package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
- package/dist/ui/assets/{LoginPage-B30OrEBy.js → LoginPage-CAmSI9Vy.js} +1 -1
- package/dist/ui/assets/LogsPage-DAPBHkwK.js +1 -0
- package/dist/ui/assets/MeetingPage-WjjGOqqU.js +1 -0
- package/dist/ui/assets/{NotFound-HD1Yp9yK.js → NotFound-BMeQSGcG.js} +1 -1
- package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
- package/dist/ui/assets/{RecoverPage-CLF6buGP.js → RecoverPage-DpW3l-yv.js} +1 -1
- package/dist/ui/assets/SettingsPage-DBJ7_E6C.js +9 -0
- package/dist/ui/assets/SetupPage-DKmLVUaj.js +1 -0
- package/dist/ui/assets/{WebChatPage-Um3VANzn.js → WebChatPage-CVRcKept.js} +2 -2
- package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
- package/dist/ui/assets/{activity-SfJ6UDF2.js → activity-c3pNngT_.js} +1 -1
- package/dist/ui/assets/alert-C-NE-P3s.js +1 -0
- package/dist/ui/assets/{alert-dialog-M893TdvF.js → alert-dialog-C5mzbHdP.js} +1 -1
- package/dist/ui/assets/arrow-left-CBcbX5EZ.js +1 -0
- package/dist/ui/assets/badge-ChpACfWO.js +1 -0
- package/dist/ui/assets/{calendar-CMMeWsP-.js → calendar-B-KZ9RQO.js} +1 -1
- package/dist/ui/assets/{card-C7P3W6_y.js → card-CNf6BS2e.js} +1 -1
- package/dist/ui/assets/chevron-left-D4U-5A27.js +1 -0
- package/dist/ui/assets/chevron-right-CR4Skrf3.js +1 -0
- package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
- package/dist/ui/assets/{circle-alert-7koABcbO.js → circle-alert-CyHDwUj8.js} +1 -1
- package/dist/ui/assets/circle-check-Bb54Ebmu.js +1 -0
- package/dist/ui/assets/{cpu-mBJgRJzM.js → cpu-Cdgc_B1K.js} +1 -1
- package/dist/ui/assets/dialog-QnZ0ad8O.js +1 -0
- package/dist/ui/assets/{download-oaofq4K1.js → download-C3ifGMjJ.js} +1 -1
- package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
- package/dist/ui/assets/{es-eUrU2hyB.js → es-NQNoaWDx.js} +1 -1
- package/dist/ui/assets/{external-link-SkkF2Z7B.js → external-link-BvxYeTP1.js} +1 -1
- package/dist/ui/assets/{eye-B8lq7sWG.js → eye-DqNTU_GD.js} +1 -1
- package/dist/ui/assets/{file-text-0oYol8Bb.js → file-text-BT_9S9SM.js} +1 -1
- package/dist/ui/assets/{folder-open-DVYu2lgk.js → folder-open-BhH8y9ac.js} +1 -1
- package/dist/ui/assets/gauge-D_TMa4i9.js +1 -0
- package/dist/ui/assets/{globe-BVPd5DRa.js → globe-DeCQTCDJ.js} +1 -1
- package/dist/ui/assets/{hexagon-BIAFUAlQ.js → hexagon-DsGOUl-H.js} +1 -1
- package/dist/ui/assets/{history-BUAnaMQo.js → history-BSG-Ypqf.js} +1 -1
- package/dist/ui/assets/index-B2fCYtTS.css +2 -0
- package/dist/ui/assets/index-DMCjjdqf.js +116 -0
- package/dist/ui/assets/{info-DWioleen.js → info-NwLoa2Mj.js} +1 -1
- package/dist/ui/assets/{key-BCGwSKKc.js → key-3EP0dhkT.js} +1 -1
- package/dist/ui/assets/label-D2H1IR_J.js +1 -0
- package/dist/ui/assets/loader-circle-CZNax6kS.js +1 -0
- package/dist/ui/assets/{lock-D7PCO7GC.js → lock-Ei1_J-Nq.js} +1 -1
- package/dist/ui/assets/{pause-CI1JFH6r.js → pause-BUqah9Bi.js} +1 -1
- package/dist/ui/assets/play-NcZ4swwL.js +1 -0
- package/dist/ui/assets/plus-CX1xyhp5.js +1 -0
- package/dist/ui/assets/progress-BherYzY6.js +1 -0
- package/dist/ui/assets/{refresh-cw-BLmKlO4J.js → refresh-cw-DaYdjQFk.js} +1 -1
- package/dist/ui/assets/{save-M1nv6H3P.js → save-CUdYyHNy.js} +1 -1
- package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
- package/dist/ui/assets/{send-ijRfR0gp.js → send-B0H5SEIE.js} +1 -1
- package/dist/ui/assets/{settings-BvXhlJCF.js → settings-Ds4SqD8s.js} +1 -1
- package/dist/ui/assets/{slider-DrDFLwXh.js → slider-CsiUDxc3.js} +1 -1
- package/dist/ui/assets/{sparkles-C4MACMbE.js → sparkles-yUEb-7oH.js} +1 -1
- package/dist/ui/assets/{square-D_-gRT1l.js → square-BD81nFtN.js} +1 -1
- package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
- package/dist/ui/assets/{table-DWEJJiuF.js → table-CSc8ubon.js} +1 -1
- package/dist/ui/assets/terminal-DN38Q456.js +1 -0
- package/dist/ui/assets/{textarea-CwPvQVAG.js → textarea-CXgXWKrT.js} +1 -1
- package/dist/ui/assets/{trash-2-Blkv31Dz.js → trash-2-CNjMkoq6.js} +1 -1
- package/dist/ui/assets/{triangle-alert-BKgbd30k.js → triangle-alert-C9Y8Ub4X.js} +1 -1
- package/dist/ui/assets/useProviders-C6_QHsEi.js +1 -0
- package/dist/ui/assets/{vendor-radix-JY4ncZrD.js → vendor-radix-cw1bQaVC.js} +4 -4
- package/dist/ui/assets/{vendor-react-CscwQerf.js → vendor-react-D4s9E-zj.js} +1 -1
- package/dist/ui/assets/{volume-2-BiUgObeI.js → volume-2-CeSXNDv4.js} +1 -1
- package/dist/ui/assets/{zap-CpyuQJEC.js → zap-hlXjpSeA.js} +1 -1
- package/dist/ui/dist/assets/AgentCreateForm-tJZv9FZC.js +1 -0
- package/dist/ui/dist/assets/AgentDetailPage-Du-mRcAX.js +1 -0
- package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +1 -0
- package/dist/ui/dist/assets/AgentsPage-YvSgWRiw.js +10 -0
- package/dist/ui/dist/assets/CanvasPage-DtMwGvxf.js +33 -0
- package/dist/ui/dist/assets/ChannelsPage-BdBXWHjj.js +8 -0
- package/dist/ui/dist/assets/DashboardPage-ghl1ZguH.js +6 -0
- package/dist/ui/dist/assets/LoginPage-CAmSI9Vy.js +1 -0
- package/dist/ui/dist/assets/LogsPage-DAPBHkwK.js +1 -0
- package/dist/ui/dist/assets/MeetingPage-WjjGOqqU.js +1 -0
- package/dist/ui/dist/assets/NotFound-BMeQSGcG.js +1 -0
- package/dist/ui/dist/assets/ProvidersPage-Ct6HsAi1.js +1 -0
- package/dist/ui/dist/assets/RecoverPage-DpW3l-yv.js +1 -0
- package/dist/ui/dist/assets/SettingsPage-DBJ7_E6C.js +9 -0
- package/dist/ui/dist/assets/SetupPage-DKmLVUaj.js +1 -0
- package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +16 -0
- package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +1 -0
- package/dist/ui/dist/assets/activity-c3pNngT_.js +1 -0
- package/dist/ui/dist/assets/alert-C-NE-P3s.js +1 -0
- package/dist/ui/dist/assets/alert-dialog-C5mzbHdP.js +1 -0
- package/dist/ui/dist/assets/arrow-left-CBcbX5EZ.js +1 -0
- package/dist/ui/dist/assets/badge-ChpACfWO.js +1 -0
- package/dist/ui/dist/assets/calendar-B-KZ9RQO.js +1 -0
- package/dist/ui/dist/assets/card-CNf6BS2e.js +1 -0
- package/dist/ui/dist/assets/chevron-left-D4U-5A27.js +1 -0
- package/dist/ui/dist/assets/chevron-right-CR4Skrf3.js +1 -0
- package/dist/ui/dist/assets/chevron-up-BYhk0K2J.js +1 -0
- package/dist/ui/dist/assets/circle-alert-CyHDwUj8.js +1 -0
- package/dist/ui/dist/assets/circle-check-Bb54Ebmu.js +1 -0
- package/dist/ui/dist/assets/cpu-Cdgc_B1K.js +1 -0
- package/dist/ui/dist/assets/dialog-QnZ0ad8O.js +1 -0
- package/dist/ui/dist/assets/download-C3ifGMjJ.js +1 -0
- package/dist/ui/dist/assets/dropdown-menu-BK-CO3Od.js +1 -0
- package/dist/ui/dist/assets/es-NQNoaWDx.js +1 -0
- package/dist/ui/dist/assets/external-link-BvxYeTP1.js +1 -0
- package/dist/ui/dist/assets/eye-DqNTU_GD.js +1 -0
- package/dist/ui/dist/assets/file-text-BT_9S9SM.js +1 -0
- package/dist/ui/dist/assets/folder-open-BhH8y9ac.js +1 -0
- package/dist/ui/dist/assets/format-GVHeOyWI.js +1 -0
- package/dist/ui/dist/assets/gateway-url-COCbW0IR.js +1 -0
- package/dist/ui/dist/assets/gauge-D_TMa4i9.js +1 -0
- package/dist/ui/dist/assets/globe-DeCQTCDJ.js +1 -0
- package/dist/ui/dist/assets/hexagon-DsGOUl-H.js +1 -0
- package/dist/ui/dist/assets/history-BSG-Ypqf.js +1 -0
- package/dist/ui/dist/assets/index-B2fCYtTS.css +2 -0
- package/dist/ui/dist/assets/index-DMCjjdqf.js +116 -0
- package/dist/ui/dist/assets/info-NwLoa2Mj.js +1 -0
- package/dist/ui/dist/assets/key-3EP0dhkT.js +1 -0
- package/dist/ui/dist/assets/label-D2H1IR_J.js +1 -0
- package/dist/ui/dist/assets/loader-circle-CZNax6kS.js +1 -0
- package/dist/ui/dist/assets/lock-Ei1_J-Nq.js +1 -0
- package/dist/ui/dist/assets/pause-BUqah9Bi.js +1 -0
- package/dist/ui/dist/assets/play-NcZ4swwL.js +1 -0
- package/dist/ui/dist/assets/plus-CX1xyhp5.js +1 -0
- package/dist/ui/dist/assets/progress-BherYzY6.js +1 -0
- package/dist/ui/dist/assets/refresh-cw-DaYdjQFk.js +1 -0
- package/dist/ui/dist/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
- package/dist/ui/dist/assets/save-CUdYyHNy.js +1 -0
- package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +1 -0
- package/dist/ui/dist/assets/send-B0H5SEIE.js +1 -0
- package/dist/ui/dist/assets/settings-Ds4SqD8s.js +1 -0
- package/dist/ui/dist/assets/slider-CsiUDxc3.js +14 -0
- package/dist/ui/dist/assets/sparkles-yUEb-7oH.js +1 -0
- package/dist/ui/dist/assets/square-BD81nFtN.js +1 -0
- package/dist/ui/dist/assets/switch-BDwN8RYV.js +1 -0
- package/dist/ui/dist/assets/table-CSc8ubon.js +1 -0
- package/dist/ui/dist/assets/terminal-DN38Q456.js +1 -0
- package/dist/ui/dist/assets/textarea-CXgXWKrT.js +1 -0
- package/dist/ui/dist/assets/trash-2-CNjMkoq6.js +1 -0
- package/dist/ui/dist/assets/triangle-alert-C9Y8Ub4X.js +1 -0
- package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +1 -0
- package/dist/ui/dist/assets/utils-3pnRFmFe.js +1 -0
- package/dist/ui/dist/assets/vendor-charts-Bu2lyBKP.js +65 -0
- package/dist/ui/dist/assets/vendor-query-DsWPbQdG.js +1 -0
- package/dist/ui/dist/assets/vendor-radix-cw1bQaVC.js +63 -0
- package/dist/ui/dist/assets/vendor-react-D4s9E-zj.js +1 -0
- package/dist/ui/dist/assets/vendor-router-C9pIYwbJ.js +3 -0
- package/dist/ui/dist/assets/volume-2-CeSXNDv4.js +1 -0
- package/dist/ui/dist/assets/zap-hlXjpSeA.js +1 -0
- package/dist/ui/dist/favicon.ico +0 -0
- package/dist/ui/dist/index.html +40 -0
- package/dist/ui/dist/placeholder.svg +1 -0
- package/dist/ui/index.html +7 -11
- package/package.json +137 -15
- package/packages/cli/src/adapters/binary.ts +461 -0
- package/packages/cli/src/adapters/bun-global.ts +378 -0
- package/packages/cli/src/adapters/config.ts +314 -0
- package/packages/cli/src/adapters/docker.ts +308 -0
- package/packages/cli/src/adapters/factory.ts +168 -0
- package/packages/cli/src/adapters/index.ts +80 -0
- package/packages/cli/src/adapters/types.ts +218 -0
- package/packages/cli/src/commands/agent-run.ts +168 -0
- package/packages/cli/src/commands/agents.ts +398 -0
- package/packages/cli/src/commands/chat.ts +142 -0
- package/packages/cli/src/commands/config.ts +49 -0
- package/packages/cli/src/commands/cron.ts +487 -0
- package/packages/cli/src/commands/dev.ts +58 -0
- package/packages/cli/src/commands/doctor.ts +320 -0
- package/packages/cli/src/commands/gateway.ts +719 -0
- package/packages/cli/src/commands/logs.ts +57 -0
- package/packages/cli/src/commands/mcp.ts +175 -0
- package/packages/cli/src/commands/message.ts +77 -0
- package/packages/cli/src/commands/migrate.ts +90 -0
- package/packages/cli/src/commands/onboard.ts +1656 -0
- package/packages/cli/src/commands/security.ts +144 -0
- package/packages/cli/src/commands/service.ts +50 -0
- package/packages/cli/src/commands/sessions.ts +116 -0
- package/packages/cli/src/commands/skills.ts +215 -0
- package/packages/cli/src/commands/update.ts +203 -0
- package/packages/cli/src/index.ts +210 -0
- package/packages/cli/src/ui-bundle.generated.ts +3 -0
- package/packages/cli/src/utils/token.ts +6 -0
- package/packages/core/src/agent/agent-loop.ts +691 -0
- package/packages/core/src/agent/compaction.ts +240 -0
- package/packages/core/src/agent/context-compiler.ts +467 -0
- package/packages/core/src/agent/context-guard.ts +91 -0
- package/packages/core/src/agent/conversation-store.ts +244 -0
- package/packages/core/src/agent/curator.ts +158 -0
- package/packages/core/src/agent/hooks.ts +166 -0
- package/packages/core/src/agent/llm-client.ts +167 -0
- package/packages/core/src/agent/llm-providers/anthropic.ts +212 -0
- package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
- package/packages/core/src/agent/llm-providers/gemini.ts +215 -0
- package/packages/core/src/agent/llm-providers/groq.ts +5 -0
- package/packages/core/src/agent/llm-providers/interface.ts +195 -0
- package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
- package/packages/core/src/agent/llm-providers/local-llama.ts +37 -0
- package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
- package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
- package/packages/core/src/agent/llm-providers/ollama.ts +175 -0
- package/packages/core/src/agent/llm-providers/openai-compat-base.ts +379 -0
- package/packages/core/src/agent/llm-providers/openai.ts +5 -0
- package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
- package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
- package/packages/core/src/agent/native-tools.ts +31 -0
- package/packages/core/src/agent/playbook-selector.ts +147 -0
- package/packages/core/src/agent/prompt-builder.ts +169 -0
- package/packages/core/src/agent/providers/index.ts +204 -0
- package/packages/core/src/agent/providers.ts +1 -0
- package/packages/core/src/agent/reflector.ts +200 -0
- package/packages/core/src/agent/service.ts +267 -0
- package/packages/core/src/agent/skill-selector.ts +479 -0
- package/packages/core/src/agent/stuck-loop.ts +133 -0
- package/packages/core/src/agent/tool-selector.ts +569 -0
- package/packages/core/src/agent/tracer.ts +100 -0
- package/packages/core/src/auth/auth.ts +108 -0
- package/packages/core/src/auth/index.ts +1 -0
- package/packages/core/src/canvas/a2ui-tools.ts +255 -0
- package/packages/core/src/canvas/canvas-manager.ts +390 -0
- package/packages/core/src/canvas/canvas-tools.ts +448 -0
- package/packages/core/src/canvas/emitter.ts +149 -0
- package/packages/core/src/canvas/index.ts +3 -0
- package/packages/core/src/channels/base.ts +154 -0
- package/packages/core/src/channels/discord.ts +273 -0
- package/packages/core/src/channels/index.ts +7 -0
- package/packages/core/src/channels/manager.ts +450 -0
- package/packages/core/src/channels/slack.ts +323 -0
- package/packages/core/src/channels/telegram.ts +612 -0
- package/packages/core/src/channels/webchat.ts +139 -0
- package/packages/core/src/channels/whatsapp.ts +548 -0
- package/packages/core/src/config/index.ts +12 -0
- package/packages/core/src/config/loader.ts +569 -0
- package/packages/core/src/events/agent-bus.ts +460 -0
- package/packages/core/src/events/event-bus.ts +169 -0
- package/packages/core/src/gateway/channel-notify.ts +64 -0
- package/packages/core/src/gateway/helpers/cors.ts +32 -0
- package/packages/core/src/gateway/helpers/index.ts +4 -0
- package/packages/core/src/gateway/helpers/narration.ts +57 -0
- package/packages/core/src/gateway/helpers/path.ts +13 -0
- package/packages/core/src/gateway/helpers/redact.ts +61 -0
- package/packages/core/src/gateway/index.ts +5 -0
- package/packages/core/src/gateway/initializer.ts +363 -0
- package/packages/core/src/gateway/lane-queue.ts +169 -0
- package/packages/core/src/gateway/llm-local/client.ts +94 -0
- package/packages/core/src/gateway/llm-local/detector.ts +321 -0
- package/packages/core/src/gateway/llm-local/downloader.ts +216 -0
- package/packages/core/src/gateway/llm-local/index.ts +34 -0
- package/packages/core/src/gateway/llm-local/manager.ts +186 -0
- package/packages/core/src/gateway/llm-local/models.ts +149 -0
- package/packages/core/src/gateway/llm-local/server.ts +179 -0
- package/packages/core/src/gateway/resolver.ts +108 -0
- package/packages/core/src/gateway/router.ts +124 -0
- package/packages/core/src/gateway/routes/agents.ts +210 -0
- package/packages/core/src/gateway/routes/auth.ts +244 -0
- package/packages/core/src/gateway/routes/channels.ts +484 -0
- package/packages/core/src/gateway/routes/chat.ts +241 -0
- package/packages/core/src/gateway/routes/config.ts +12 -0
- package/packages/core/src/gateway/routes/cron-api.ts +544 -0
- package/packages/core/src/gateway/routes/ethics.ts +46 -0
- package/packages/core/src/gateway/routes/llm-local.ts +271 -0
- package/packages/core/src/gateway/routes/mcp.ts +319 -0
- package/packages/core/src/gateway/routes/meeting.ts +232 -0
- package/packages/core/src/gateway/routes/models.ts +163 -0
- package/packages/core/src/gateway/routes/multimodal.ts +93 -0
- package/packages/core/src/gateway/routes/providers.ts +220 -0
- package/packages/core/src/gateway/routes/setup.ts +441 -0
- package/packages/core/src/gateway/routes/skills.ts +115 -0
- package/packages/core/src/gateway/routes/system.ts +469 -0
- package/packages/core/src/gateway/routes/tasks.ts +44 -0
- package/packages/core/src/gateway/routes/tools.ts +59 -0
- package/packages/core/src/gateway/routes/tts-local.ts +388 -0
- package/packages/core/src/gateway/routes/users.ts +122 -0
- package/packages/core/src/gateway/routes/voice.ts +189 -0
- package/packages/core/src/gateway/routes/workspace.ts +281 -0
- package/packages/core/src/gateway/server.ts +2744 -0
- package/packages/core/src/gateway/session.ts +95 -0
- package/packages/core/src/gateway/slash-commands.ts +207 -0
- package/packages/core/src/gateway/tts/README.md +94 -0
- package/packages/core/src/gateway/tts/package.json +25 -0
- package/packages/core/src/gateway/tts/src/client.ts +59 -0
- package/packages/core/src/gateway/tts/src/detect.ts +42 -0
- package/packages/core/src/gateway/tts/src/index.ts +15 -0
- package/packages/core/src/gateway/tts/src/install.ts +129 -0
- package/packages/core/src/gateway/tts/src/models.ts +50 -0
- package/packages/core/src/gateway/tts/src/server.ts +252 -0
- package/packages/core/src/gateway/tts/voices/.gitkeep +0 -0
- package/packages/core/src/heartbeat/index.ts +157 -0
- package/packages/core/src/index.ts +56 -0
- package/packages/core/src/mcp/hot-reload.ts +148 -0
- package/packages/core/src/mcp/singleton.ts +21 -0
- package/packages/core/src/mcp/tool-sync.ts +176 -0
- package/packages/core/src/multimodal/index.ts +2 -0
- package/packages/core/src/multimodal/types.ts +28 -0
- package/packages/core/src/multimodal/vision-service.ts +283 -0
- package/packages/core/src/plugins/api.ts +128 -0
- package/packages/core/src/plugins/index.ts +2 -0
- package/packages/core/src/plugins/loader.ts +365 -0
- package/packages/core/src/resilience/circuit-breaker.ts +225 -0
- package/packages/core/src/scheduler/CronScheduler.ts +699 -0
- package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
- package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
- package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
- package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
- package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
- package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
- package/packages/core/src/scheduler/dag/errors.ts +37 -0
- package/packages/core/src/scheduler/dag/index.ts +26 -0
- package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
- package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
- package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
- package/packages/core/src/scheduler/index.ts +22 -0
- package/packages/core/src/scheduler/integration.ts +237 -0
- package/packages/core/src/scheduler/types.ts +164 -0
- package/packages/core/src/security/google-chat.ts +269 -0
- package/packages/core/src/security/index.ts +192 -0
- package/packages/core/src/security/pairing.ts +250 -0
- package/packages/core/src/security/rate-limit.ts +270 -0
- package/packages/core/src/security/signal.ts +321 -0
- package/packages/core/src/state/store.ts +312 -0
- package/packages/core/src/storage/crypto.ts +197 -0
- package/packages/core/src/storage/migrate.ts +147 -0
- package/packages/core/src/storage/onboarding.ts +1506 -0
- package/packages/core/src/storage/schema.ts +666 -0
- package/packages/core/src/storage/seed.ts +628 -0
- package/packages/core/src/storage/sqlite.ts +407 -0
- package/packages/core/src/storage/usage.ts +374 -0
- package/packages/core/src/tool-runtime/index.ts +476 -0
- package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
- package/packages/core/src/tools/agents/get-available-models.ts +118 -0
- package/packages/core/src/tools/agents/index.ts +610 -0
- package/packages/core/src/tools/canvas/index.ts +420 -0
- package/packages/core/src/tools/cli/index.ts +142 -0
- package/packages/core/src/tools/core/index.ts +478 -0
- package/packages/core/src/tools/cron/index.ts +635 -0
- package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
- package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
- package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
- package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
- package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
- package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
- package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
- package/packages/core/src/tools/filesystem/index.ts +34 -0
- package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
- package/packages/core/src/tools/index.ts +197 -0
- package/packages/core/src/tools/meeting/index.ts +363 -0
- package/packages/core/src/tools/office/index.ts +47 -0
- package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
- package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
- package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
- package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
- package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
- package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
- package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
- package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
- package/packages/core/src/tools/types.ts +39 -0
- package/packages/core/src/tools/voice/index.ts +104 -0
- package/packages/core/src/tools/web/browser-click.ts +78 -0
- package/packages/core/src/tools/web/browser-extract.ts +139 -0
- package/packages/core/src/tools/web/browser-navigate.ts +106 -0
- package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
- package/packages/core/src/tools/web/browser-script.ts +88 -0
- package/packages/core/src/tools/web/browser-service.ts +554 -0
- package/packages/core/src/tools/web/browser-type.ts +101 -0
- package/packages/core/src/tools/web/browser-wait.ts +136 -0
- package/packages/core/src/tools/web/index.ts +41 -0
- package/packages/core/src/tools/web/web-fetch.ts +78 -0
- package/packages/core/src/tools/web/web-search.ts +123 -0
- package/packages/core/src/utils/benchmark.ts +80 -0
- package/packages/core/src/utils/crypto.ts +73 -0
- package/packages/core/src/utils/date.ts +42 -0
- package/packages/core/src/utils/index.ts +5 -0
- package/packages/core/src/utils/logger.ts +389 -0
- package/packages/core/src/utils/retry.ts +70 -0
- package/packages/core/src/utils/toon.ts +253 -0
- package/packages/core/src/voice/index.ts +643 -0
- package/packages/mcp/src/config.ts +13 -0
- package/packages/mcp/src/index.ts +1 -0
- package/packages/mcp/src/logger.ts +47 -0
- package/packages/mcp/src/manager.ts +439 -0
- package/packages/mcp/src/transports/index.ts +67 -0
- package/packages/mcp/src/transports/sse.ts +238 -0
- package/packages/mcp/src/transports/websocket.ts +159 -0
- package/packages/skills/src/bundled/agents/agent_spawner/SKILL.md +167 -0
- package/packages/skills/src/bundled/agents/code_delegator/SKILL.md +156 -0
- package/packages/skills/src/bundled/agents/memory_manager/SKILL.md +143 -0
- package/packages/skills/src/bundled/agents/research_and_remember/SKILL.md +139 -0
- package/packages/skills/src/bundled/agents/task_orchestrator/SKILL.md +198 -0
- package/packages/skills/src/bundled/canvas/a2ui_dashboard/SKILL.md +176 -0
- package/packages/skills/src/bundled/canvas/a2ui_form/SKILL.md +202 -0
- package/packages/skills/src/bundled/canvas/a2ui_interactive/SKILL.md +206 -0
- package/packages/skills/src/bundled/canvas/canvas_dashboard/SKILL.md +146 -0
- package/packages/skills/src/bundled/canvas/canvas_interact/SKILL.md +148 -0
- package/packages/skills/src/bundled/canvas/canvas_report/SKILL.md +146 -0
- package/packages/skills/src/bundled/cli/cli_pipeline/SKILL.md +136 -0
- package/packages/skills/src/bundled/cli/cli_safe_exec/SKILL.md +125 -0
- package/packages/skills/src/bundled/cron_manager/SKILL.md +188 -0
- package/packages/skills/src/bundled/cron_reminder/SKILL.md +112 -0
- package/packages/skills/src/bundled/filesystem/file_manager/SKILL.md +118 -0
- package/packages/skills/src/bundled/filesystem/file_read_and_summarize/SKILL.md +108 -0
- package/packages/skills/src/bundled/filesystem/file_writer/SKILL.md +135 -0
- package/packages/skills/src/bundled/meeting/meeting_transcription/SKILL.md +213 -0
- package/packages/skills/src/bundled/office/office_document_manager/SKILL.md +262 -0
- package/packages/skills/src/bundled/search_knowledge/busqueda_fts5/SKILL.md +74 -0
- package/packages/skills/src/bundled/voice/voice_assistant/SKILL.md +174 -0
- package/packages/skills/src/bundled/voice/voice_input/SKILL.md +146 -0
- package/packages/skills/src/bundled/voice/voice_output/SKILL.md +151 -0
- package/packages/skills/src/bundled/web/browser_automate/SKILL.md +120 -0
- package/packages/skills/src/bundled/web/browser_scrape/SKILL.md +109 -0
- package/packages/skills/src/bundled/web/web_monitor/SKILL.md +127 -0
- package/packages/skills/src/bundled/web/web_research/SKILL.md +119 -0
- package/packages/skills/src/bundled-data.generated.ts +1964 -0
- package/packages/skills/src/index.ts +1 -0
- package/packages/skills/src/loader.ts +388 -0
- package/dist/ui/assets/AgentCreateForm-DS6yXjGV.js +0 -1
- package/dist/ui/assets/AgentDetailPage-Ud552U7_.js +0 -1
- package/dist/ui/assets/AgentNewPage-DWWs1P7s.js +0 -1
- package/dist/ui/assets/BridgePage-BD93aBKM.js +0 -1
- package/dist/ui/assets/CanvasPage-CM35yj0Q.js +0 -33
- package/dist/ui/assets/ChannelsPage-CtsWtJdc.js +0 -8
- package/dist/ui/assets/DashboardPage-BpiwR5Jg.js +0 -6
- package/dist/ui/assets/LogsPage-DqUsG3MW.js +0 -1
- package/dist/ui/assets/MeetingPage-C5B8-IzE.js +0 -1
- package/dist/ui/assets/ProjectsPage-zic2sjUf.js +0 -1
- package/dist/ui/assets/ProvidersPage-BxyIGKzh.js +0 -1
- package/dist/ui/assets/SettingsPage-CNFm3nun.js +0 -9
- package/dist/ui/assets/SetupPage-RBcjQtv7.js +0 -1
- package/dist/ui/assets/accordion-BEVqJf2A.js +0 -1
- package/dist/ui/assets/alert-BeGcM0nb.js +0 -1
- package/dist/ui/assets/api-q5Ax-vD2.js +0 -63
- package/dist/ui/assets/arrow-left-B_jlw8X_.js +0 -1
- package/dist/ui/assets/badge-pNhtItyt.js +0 -1
- package/dist/ui/assets/chevron-down-B16UVNlu.js +0 -1
- package/dist/ui/assets/chevron-left-_8ly7Fz0.js +0 -1
- package/dist/ui/assets/chevron-right-yzZLjezG.js +0 -1
- package/dist/ui/assets/chevron-up-CxKDQEE5.js +0 -1
- package/dist/ui/assets/circle-CFKiO9Ds.js +0 -1
- package/dist/ui/assets/circle-check-E2u7ZS2r.js +0 -1
- package/dist/ui/assets/circle-minus-1-TZF2pu.js +0 -1
- package/dist/ui/assets/circle-x-Cm3Sr-xb.js +0 -1
- package/dist/ui/assets/dialog-BaJbZsQF.js +0 -1
- package/dist/ui/assets/dist-DB-fE0Co.js +0 -1
- package/dist/ui/assets/dropdown-menu-DJoOchfz.js +0 -1
- package/dist/ui/assets/gauge-BTpFKuAj.js +0 -1
- package/dist/ui/assets/index-BN0875JH.css +0 -2
- package/dist/ui/assets/index-D4pdc0Uw.js +0 -54
- package/dist/ui/assets/label-C6tqnnKd.js +0 -1
- package/dist/ui/assets/loader-circle-CK3qRV3f.js +0 -1
- package/dist/ui/assets/pencil-BF2_XX-i.js +0 -1
- package/dist/ui/assets/play-DidATMfT.js +0 -1
- package/dist/ui/assets/plus-DXm1XDhQ.js +0 -1
- package/dist/ui/assets/progress-B1HC9cB_.js +0 -1
- package/dist/ui/assets/scroll-area-DKNpYkRA.js +0 -1
- package/dist/ui/assets/search-Co6mulZS.js +0 -1
- package/dist/ui/assets/switch-7AuR7x2g.js +0 -1
- package/dist/ui/assets/terminal-CjZu0OZ0.js +0 -1
- package/dist/ui/assets/useProviders-Bxsnav4y.js +0 -1
- package/dist/ui/assets/useWebSocketStore-ZCW_Nt1w.js +0 -1
- package/dist/ui/assets/x-5cXW_1ZS.js +0 -1
- /package/dist/ui/assets/{format-C0EOLKvf.js → format-GVHeOyWI.js} +0 -0
- /package/dist/ui/assets/{gateway-url-OqLaEDK-.js → gateway-url-COCbW0IR.js} +0 -0
- /package/dist/ui/assets/{utils-_qMjiZaF.js → utils-3pnRFmFe.js} +0 -0
- /package/dist/ui/assets/{vendor-router-DhLEd920.js → vendor-router-C9pIYwbJ.js} +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Sync — Persist MCP tool definitions to DB and FTS5
|
|
3
|
+
*
|
|
4
|
+
* When an MCP server connects, its tool definitions are persisted to
|
|
5
|
+
* the mcp_tools table and indexed in mcp_tools_fts for search_knowledge.
|
|
6
|
+
* When the server disconnects, all its tools are deleted from both.
|
|
7
|
+
*
|
|
8
|
+
* This enables:
|
|
9
|
+
* 1. search_knowledge to find MCP tools via FTS5
|
|
10
|
+
* 2. Tool definitions to survive across context compiler invocations
|
|
11
|
+
* 3. Offline visibility of what MCP tools were available
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { getDb } from "../storage/sqlite"
|
|
15
|
+
import { logger } from "../utils/logger"
|
|
16
|
+
|
|
17
|
+
const log = logger.child("mcp:tool-sync")
|
|
18
|
+
|
|
19
|
+
export interface MCPToolDefinition {
|
|
20
|
+
name: string
|
|
21
|
+
description: string
|
|
22
|
+
inputSchema?: Record<string, unknown>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Generate a stable ID for an MCP tool based on server + tool name.
|
|
27
|
+
* Uses the same sanitization as mcpToolFullName for consistency.
|
|
28
|
+
*/
|
|
29
|
+
export function mcpToolId(serverName: string, toolName: string): string {
|
|
30
|
+
const safe = (s: string) => s.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_\-]/g, '_')
|
|
31
|
+
const full = `${safe(serverName)}__${safe(toolName)}`
|
|
32
|
+
const trimmed = full.length > 64 ? full.substring(0, 64) : full
|
|
33
|
+
return /^[a-zA-Z_]/.test(trimmed) ? trimmed : `_${trimmed}`.substring(0, 64)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Persist MCP tool definitions to the mcp_tools table.
|
|
38
|
+
* Called when a server connects or reconnects.
|
|
39
|
+
* Deletes existing tools for the server first, then inserts fresh data.
|
|
40
|
+
*/
|
|
41
|
+
export function syncMCPToolsToDB(
|
|
42
|
+
serverId: string,
|
|
43
|
+
serverName: string,
|
|
44
|
+
tools: MCPToolDefinition[]
|
|
45
|
+
): void {
|
|
46
|
+
const db = getDb()
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const deleteExisting = db.prepare("DELETE FROM mcp_tools WHERE server_id = ?")
|
|
50
|
+
deleteExisting.run(serverId)
|
|
51
|
+
|
|
52
|
+
if (tools.length === 0) {
|
|
53
|
+
log.debug(`[mcp:tool-sync] No tools to persist for server ${serverName}`)
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const insertTool = db.prepare(`
|
|
58
|
+
INSERT INTO mcp_tools(id, server_id, server_name, tool_name, description, category, active, created_at, updated_at)
|
|
59
|
+
VALUES (?, ?, ?, ?, ?, 'mcp', 1, (unixepoch()), (unixepoch()))
|
|
60
|
+
`)
|
|
61
|
+
|
|
62
|
+
let count = 0
|
|
63
|
+
for (const tool of tools) {
|
|
64
|
+
const id = mcpToolId(serverName, tool.name)
|
|
65
|
+
insertTool.run(id, serverId, serverName, tool.name, tool.description || "")
|
|
66
|
+
count++
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log.info(`[mcp:tool-sync] Persisted ${count} MCP tools for server ${serverName} to mcp_tools`)
|
|
70
|
+
} catch (err) {
|
|
71
|
+
log.error(`[mcp:tool-sync] Failed to persist MCP tools for server ${serverName}:`, err)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Sync all active MCP tools from mcp_tools table to mcp_tools_fts.
|
|
77
|
+
* Called after syncMCPToolsToDB or after startup to ensure FTS5 is in sync.
|
|
78
|
+
*
|
|
79
|
+
* This does a full clear + re-insert to avoid schema drift.
|
|
80
|
+
*/
|
|
81
|
+
export async function syncMCPToolsToFTS(): Promise<void> {
|
|
82
|
+
const db = getDb()
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const syncTransaction = db.transaction(() => {
|
|
86
|
+
// Verify table exists
|
|
87
|
+
const tableCheck = db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='mcp_tools_fts'").get()
|
|
88
|
+
if (!tableCheck) {
|
|
89
|
+
throw new Error("mcp_tools_fts table does not exist!")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Clear existing FTS data
|
|
93
|
+
db.run("DELETE FROM mcp_tools_fts")
|
|
94
|
+
|
|
95
|
+
// Re-populate from mcp_tools where active
|
|
96
|
+
const mcpTools = db.query(`
|
|
97
|
+
SELECT id, server_name, tool_name, description, category
|
|
98
|
+
FROM mcp_tools
|
|
99
|
+
WHERE active = 1
|
|
100
|
+
`).all() as Array<{ id: string; server_name: string; tool_name: string; description: string; category: string }>
|
|
101
|
+
|
|
102
|
+
if (mcpTools.length === 0) {
|
|
103
|
+
log.debug(`[mcp:tool-sync] No MCP tools to sync to FTS5`)
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const insert = db.prepare(`
|
|
108
|
+
INSERT INTO mcp_tools_fts(id, server_name, tool_name, description, category)
|
|
109
|
+
VALUES (?, ?, ?, ?, ?)
|
|
110
|
+
`)
|
|
111
|
+
|
|
112
|
+
for (const tool of mcpTools) {
|
|
113
|
+
insert.run(tool.id, tool.server_name, tool.tool_name, tool.description, tool.category)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
log.info(`[mcp:tool-sync] Synced ${mcpTools.length} MCP tools to mcp_tools_fts`)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
syncTransaction()
|
|
120
|
+
} catch (err) {
|
|
121
|
+
log.error(`[mcp:tool-sync] Failed to sync MCP tools to FTS5:`, err)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Delete all MCP tool definitions for a server from both mcp_tools and mcp_tools_fts.
|
|
127
|
+
* Called when a server disconnects or is removed.
|
|
128
|
+
*/
|
|
129
|
+
export function clearMCPToolsFromDB(serverId: string): void {
|
|
130
|
+
const db = getDb()
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
// Delete from mcp_tools (CASCADE will handle FTS5 via trigger or manual sync)
|
|
134
|
+
const result = db.query("DELETE FROM mcp_tools WHERE server_id = ?").run(serverId)
|
|
135
|
+
|
|
136
|
+
log.info(`[mcp:tool-sync] Cleared MCP tools for server_id=${serverId}`)
|
|
137
|
+
|
|
138
|
+
// Re-sync FTS5 to remove stale entries
|
|
139
|
+
syncMCPToolsToFTSSync()
|
|
140
|
+
} catch (err) {
|
|
141
|
+
log.error(`[mcp:tool-sync] Failed to clear MCP tools for server_id=${serverId}:`, err)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Synchronous version of syncMCPToolsToFTS for use in clearMCPToolsFromDB.
|
|
147
|
+
* Avoids async/await in transaction that was already started.
|
|
148
|
+
*/
|
|
149
|
+
function syncMCPToolsToFTSSync(): void {
|
|
150
|
+
const db = getDb()
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
db.run("DELETE FROM mcp_tools_fts")
|
|
154
|
+
|
|
155
|
+
const mcpTools = db.query(`
|
|
156
|
+
SELECT id, server_name, tool_name, description, category
|
|
157
|
+
FROM mcp_tools
|
|
158
|
+
WHERE active = 1
|
|
159
|
+
`).all() as Array<{ id: string; server_name: string; tool_name: string; description: string; category: string }>
|
|
160
|
+
|
|
161
|
+
if (mcpTools.length === 0) return
|
|
162
|
+
|
|
163
|
+
const insert = db.prepare(`
|
|
164
|
+
INSERT INTO mcp_tools_fts(id, server_name, tool_name, description, category)
|
|
165
|
+
VALUES (?, ?, ?, ?, ?)
|
|
166
|
+
`)
|
|
167
|
+
|
|
168
|
+
for (const tool of mcpTools) {
|
|
169
|
+
insert.run(tool.id, tool.server_name, tool.tool_name, tool.description, tool.category)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
log.debug(`[mcp:tool-sync] Re-synced ${mcpTools.length} MCP tools to FTS5 after deletion`)
|
|
173
|
+
} catch (err) {
|
|
174
|
+
log.error(`[mcp:tool-sync] Failed to re-sync MCP tools to FTS5:`, err)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ContentPart =
|
|
2
|
+
| { type: "text"; text: string }
|
|
3
|
+
| { type: "image_url"; image_url: { url: string } }
|
|
4
|
+
| { type: "image_base64"; base64: string; mimeType: string }
|
|
5
|
+
| { type: "document"; base64: string; mimeType: string; fileName?: string }
|
|
6
|
+
|
|
7
|
+
export interface ImageInput {
|
|
8
|
+
type: "url" | "base64" | "buffer"
|
|
9
|
+
data: string | Buffer
|
|
10
|
+
mimeType?: string
|
|
11
|
+
caption?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DocumentInput {
|
|
15
|
+
type: "url" | "base64" | "buffer"
|
|
16
|
+
data: string | Buffer
|
|
17
|
+
mimeType: string
|
|
18
|
+
fileName?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface VisionConfig {
|
|
22
|
+
visionEnabled: boolean
|
|
23
|
+
ocrProvider: string | null
|
|
24
|
+
visionProvider: string | null
|
|
25
|
+
visionModelId: string | null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type MultimodalMessageType = "text" | "image" | "document" | "audio"
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { getDb } from "../storage/sqlite"
|
|
2
|
+
import { loadProviderApiKey } from "../storage/crypto"
|
|
3
|
+
import { logger } from "../utils/logger"
|
|
4
|
+
import type { ImageInput, DocumentInput, VisionConfig } from "./types"
|
|
5
|
+
import type { ContentPart } from "./types"
|
|
6
|
+
|
|
7
|
+
const log = logger.child("multimodal")
|
|
8
|
+
|
|
9
|
+
class MultimodalService {
|
|
10
|
+
private static instance: MultimodalService
|
|
11
|
+
|
|
12
|
+
private constructor() {}
|
|
13
|
+
|
|
14
|
+
static getInstance(): MultimodalService {
|
|
15
|
+
if (!MultimodalService.instance) {
|
|
16
|
+
MultimodalService.instance = new MultimodalService()
|
|
17
|
+
}
|
|
18
|
+
return MultimodalService.instance
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getChannelVisionConfig(channelId: string): VisionConfig {
|
|
22
|
+
const db = getDb()
|
|
23
|
+
const result = db.query(`
|
|
24
|
+
SELECT vision_enabled, ocr_provider, vision_provider, vision_model_id
|
|
25
|
+
FROM channels WHERE id = ?
|
|
26
|
+
`).get(channelId) as {
|
|
27
|
+
vision_enabled: number
|
|
28
|
+
ocr_provider: string | null
|
|
29
|
+
vision_provider: string | null
|
|
30
|
+
vision_model_id: string | null
|
|
31
|
+
} | undefined
|
|
32
|
+
|
|
33
|
+
if (!result) {
|
|
34
|
+
return { visionEnabled: false, ocrProvider: null, visionProvider: null, visionModelId: null }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
visionEnabled: result.vision_enabled === 1,
|
|
39
|
+
ocrProvider: result.ocr_provider,
|
|
40
|
+
visionProvider: result.vision_provider,
|
|
41
|
+
visionModelId: result.vision_model_id,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async processImage(image: ImageInput, visionModelId?: string): Promise<ContentPart[]> {
|
|
46
|
+
const parts: ContentPart[] = []
|
|
47
|
+
|
|
48
|
+
if (image.caption) {
|
|
49
|
+
parts.push({ type: "text", text: image.caption })
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (image.type === "url") {
|
|
53
|
+
parts.push({ type: "image_url", image_url: { url: image.data as string } })
|
|
54
|
+
} else if (image.type === "base64") {
|
|
55
|
+
parts.push({
|
|
56
|
+
type: "image_base64",
|
|
57
|
+
base64: image.data as string,
|
|
58
|
+
mimeType: image.mimeType || "image/jpeg",
|
|
59
|
+
})
|
|
60
|
+
} else if (image.type === "buffer") {
|
|
61
|
+
const base64 = Buffer.from(image.data as Buffer).toString("base64")
|
|
62
|
+
parts.push({
|
|
63
|
+
type: "image_base64",
|
|
64
|
+
base64,
|
|
65
|
+
mimeType: image.mimeType || "image/jpeg",
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return parts
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async ocrImage(image: ImageInput, providerId?: string): Promise<string> {
|
|
73
|
+
const resolved = providerId || "openai"
|
|
74
|
+
|
|
75
|
+
if (resolved === "openai") {
|
|
76
|
+
return this.ocrWithOpenAI(image)
|
|
77
|
+
} else if (resolved === "gemini") {
|
|
78
|
+
return this.ocrWithGemini(image)
|
|
79
|
+
} else if (resolved === "anthropic") {
|
|
80
|
+
return this.ocrWithAnthropic(image)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
log.warn(`Unknown OCR provider ${resolved}, defaulting to OpenAI`)
|
|
84
|
+
return this.ocrWithOpenAI(image)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
normalizeImageFromChannel(channelType: string, imageData: unknown): ImageInput {
|
|
88
|
+
const data = imageData as { url?: string; base64?: string; buffer?: Buffer; mimeType?: string; caption?: string }
|
|
89
|
+
|
|
90
|
+
if (data.url) {
|
|
91
|
+
return { type: "url", data: data.url, mimeType: data.mimeType, caption: data.caption }
|
|
92
|
+
}
|
|
93
|
+
if (data.base64) {
|
|
94
|
+
return { type: "base64", data: data.base64, mimeType: data.mimeType || "image/jpeg", caption: data.caption }
|
|
95
|
+
}
|
|
96
|
+
if (data.buffer) {
|
|
97
|
+
return { type: "buffer", data: data.buffer, mimeType: data.mimeType || "image/jpeg", caption: data.caption }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error(`${channelType} image missing url, base64, or buffer`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
normalizeDocumentFromChannel(channelType: string, docData: unknown): DocumentInput {
|
|
104
|
+
const data = docData as { url?: string; base64?: string; buffer?: Buffer; mimeType?: string; fileName?: string }
|
|
105
|
+
|
|
106
|
+
if (data.url) {
|
|
107
|
+
return { type: "url", data: data.url, mimeType: data.mimeType || "application/pdf", fileName: data.fileName }
|
|
108
|
+
}
|
|
109
|
+
if (data.base64) {
|
|
110
|
+
return { type: "base64", data: data.base64, mimeType: data.mimeType || "application/pdf", fileName: data.fileName }
|
|
111
|
+
}
|
|
112
|
+
if (data.buffer) {
|
|
113
|
+
return { type: "buffer", data: data.buffer, mimeType: data.mimeType || "application/pdf", fileName: data.fileName }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
throw new Error(`${channelType} document missing url, base64, or buffer`)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async resolveImageUrl(image: ImageInput): Promise<string> {
|
|
120
|
+
if (image.type === "url") return image.data as string
|
|
121
|
+
if (image.type === "base64") {
|
|
122
|
+
const mime = image.mimeType || "image/jpeg"
|
|
123
|
+
return `data:${mime};base64,${image.data as string}`
|
|
124
|
+
}
|
|
125
|
+
if (image.type === "buffer") {
|
|
126
|
+
const base64 = Buffer.from(image.data as Buffer).toString("base64")
|
|
127
|
+
const mime = image.mimeType || "image/jpeg"
|
|
128
|
+
return `data:${mime};base64,${base64}`
|
|
129
|
+
}
|
|
130
|
+
throw new Error("Cannot resolve image URL")
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private async getProviderApiKey(providerId: string): Promise<string | null> {
|
|
134
|
+
const db = getDb()
|
|
135
|
+
const apiKey = await loadProviderApiKey(providerId)
|
|
136
|
+
return apiKey || null
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private async ocrWithOpenAI(image: ImageInput): Promise<string> {
|
|
140
|
+
const key = await this.getProviderApiKey("openai") || process.env.OPENAI_API_KEY
|
|
141
|
+
if (!key) throw new Error("OPENAI_API_KEY not configured for OCR")
|
|
142
|
+
|
|
143
|
+
const imageUrl = await this.resolveImageUrl(image)
|
|
144
|
+
|
|
145
|
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${key}` },
|
|
148
|
+
body: JSON.stringify({
|
|
149
|
+
model: "gpt-4o-mini",
|
|
150
|
+
messages: [{
|
|
151
|
+
role: "user",
|
|
152
|
+
content: [
|
|
153
|
+
{ type: "text", text: "Describe el contenido de esta imagen en detalle. Si hay texto, transcríbelo exactamente." },
|
|
154
|
+
{ type: "image_url", image_url: { url: imageUrl } },
|
|
155
|
+
],
|
|
156
|
+
}],
|
|
157
|
+
max_tokens: 1000,
|
|
158
|
+
}),
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
if (!response.ok) {
|
|
162
|
+
const error = await response.text()
|
|
163
|
+
throw new Error(`OpenAI OCR failed: ${error}`)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const data = await response.json() as { choices: Array<{ message: { content: string } }> }
|
|
167
|
+
return data.choices[0]?.message?.content || ""
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private async ocrWithGemini(image: ImageInput): Promise<string> {
|
|
171
|
+
const key = await this.getProviderApiKey("gemini") || process.env.GEMINI_API_KEY
|
|
172
|
+
if (!key) throw new Error("GEMINI_API_KEY not configured for OCR")
|
|
173
|
+
|
|
174
|
+
let imagePart: any
|
|
175
|
+
if (image.type === "url") {
|
|
176
|
+
const imgResponse = await fetch(image.data as string)
|
|
177
|
+
const buffer = Buffer.from(await imgResponse.arrayBuffer())
|
|
178
|
+
imagePart = { inlineData: { data: buffer.toString("base64"), mimeType: image.mimeType || "image/jpeg" } }
|
|
179
|
+
} else if (image.type === "base64") {
|
|
180
|
+
imagePart = { inlineData: { data: image.data as string, mimeType: image.mimeType || "image/jpeg" } }
|
|
181
|
+
} else {
|
|
182
|
+
imagePart = { inlineData: { data: Buffer.from(image.data as Buffer).toString("base64"), mimeType: image.mimeType || "image/jpeg" } }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const response = await fetch(
|
|
186
|
+
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key}`,
|
|
187
|
+
{
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers: { "Content-Type": "application/json" },
|
|
190
|
+
body: JSON.stringify({
|
|
191
|
+
contents: [{ parts: [{ text: "Describe el contenido de esta imagen en detalle. Si hay texto, transcríbelo exactamente." }, imagePart] }],
|
|
192
|
+
}),
|
|
193
|
+
},
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
if (!response.ok) {
|
|
197
|
+
const error = await response.text()
|
|
198
|
+
throw new Error(`Gemini OCR failed: ${error}`)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const data = await response.json() as { candidates: Array<{ content: { parts: Array<{ text?: string }> } }> }
|
|
202
|
+
return data.candidates?.[0]?.content?.parts?.[0]?.text || ""
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private async ocrWithAnthropic(image: ImageInput): Promise<string> {
|
|
206
|
+
const key = await this.getProviderApiKey("anthropic") || process.env.ANTHROPIC_API_KEY
|
|
207
|
+
if (!key) throw new Error("ANTHROPIC_API_KEY not configured for OCR")
|
|
208
|
+
|
|
209
|
+
const imageUrl = await this.resolveImageUrl(image)
|
|
210
|
+
|
|
211
|
+
let source: any
|
|
212
|
+
if (imageUrl.startsWith("data:")) {
|
|
213
|
+
const match = imageUrl.match(/^data:([^;]+);base64,(.+)$/)
|
|
214
|
+
if (match) {
|
|
215
|
+
source = { type: "base64", media_type: match[1], data: match[2] }
|
|
216
|
+
} else {
|
|
217
|
+
throw new Error("Invalid base64 data URL")
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
source = { type: "url", url: imageUrl }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
224
|
+
method: "POST",
|
|
225
|
+
headers: {
|
|
226
|
+
"Content-Type": "application/json",
|
|
227
|
+
"x-api-key": key,
|
|
228
|
+
"anthropic-version": "2023-06-01",
|
|
229
|
+
"anthropic-dangerous-direct-browser-access": "true",
|
|
230
|
+
},
|
|
231
|
+
body: JSON.stringify({
|
|
232
|
+
model: "claude-haiku-4-5-20251001",
|
|
233
|
+
max_tokens: 1000,
|
|
234
|
+
messages: [{
|
|
235
|
+
role: "user",
|
|
236
|
+
content: [
|
|
237
|
+
{ type: "image", source },
|
|
238
|
+
{ type: "text", text: "Describe el contenido de esta imagen en detalle. Si hay texto, transcríbelo exactamente." },
|
|
239
|
+
],
|
|
240
|
+
}],
|
|
241
|
+
}),
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
if (!response.ok) {
|
|
245
|
+
const error = await response.text()
|
|
246
|
+
throw new Error(`Anthropic OCR failed: ${error}`)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const data = await response.json() as { content: Array<{ type: string; text?: string }> }
|
|
250
|
+
const textBlock = data.content?.find(b => b.type === "text" && b.text)
|
|
251
|
+
return textBlock?.text || ""
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
getConfiguredVisionProviders(): Record<string, boolean> {
|
|
255
|
+
const db = getDb()
|
|
256
|
+
const hasDbKey = (providerId: string): boolean => {
|
|
257
|
+
const row = db.query(
|
|
258
|
+
`SELECT api_key_encrypted FROM providers WHERE id = ? AND api_key_encrypted IS NOT NULL AND api_key_encrypted != ''`
|
|
259
|
+
).get(providerId) as { api_key_encrypted: string } | undefined
|
|
260
|
+
return !!row
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
openai: hasDbKey("openai") || !!(process.env.OPENAI_API_KEY),
|
|
265
|
+
gemini: hasDbKey("gemini") || !!(process.env.GEMINI_API_KEY),
|
|
266
|
+
anthropic: hasDbKey("anthropic") || !!(process.env.ANTHROPIC_API_KEY),
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
modelSupportsVision(providerId: string, modelId: string): boolean {
|
|
271
|
+
const db = getDb()
|
|
272
|
+
const model = db.query(`SELECT capabilities FROM models WHERE id = ? AND provider_id = ?`).get(modelId, providerId) as { capabilities: string } | undefined
|
|
273
|
+
if (!model?.capabilities) return false
|
|
274
|
+
try {
|
|
275
|
+
const caps = JSON.parse(model.capabilities) as string[]
|
|
276
|
+
return caps.includes("vision")
|
|
277
|
+
} catch {
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export const multimodalService = MultimodalService.getInstance()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Logger, ChildLogger } from "../utils/logger.ts";
|
|
2
|
+
import type { eventBus, EventMap, EventKey } from "../events/event-bus.ts";
|
|
3
|
+
import type { StateStore } from "../state/store.ts";
|
|
4
|
+
|
|
5
|
+
export interface PluginManifest {
|
|
6
|
+
name: string;
|
|
7
|
+
version: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
author?: string;
|
|
10
|
+
dependencies?: string[];
|
|
11
|
+
hiveVersion?: string;
|
|
12
|
+
main?: string;
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ToolDefinition {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
parameters: Record<string, ParameterDefinition>;
|
|
20
|
+
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ParameterDefinition {
|
|
24
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
25
|
+
description?: string;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
default?: unknown;
|
|
28
|
+
enum?: string[];
|
|
29
|
+
items?: ParameterDefinition;
|
|
30
|
+
properties?: Record<string, ParameterDefinition>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ChannelDefinition {
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
config: Record<string, unknown>;
|
|
37
|
+
start: () => Promise<void>;
|
|
38
|
+
stop: () => Promise<void>;
|
|
39
|
+
send: (sessionId: string, message: unknown) => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CLICommand {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
handler: (args: string[], options: Record<string, unknown>) => Promise<void>;
|
|
46
|
+
options?: Record<string, CommandOption>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface CommandOption {
|
|
50
|
+
alias?: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
type?: "string" | "boolean" | "number";
|
|
53
|
+
default?: unknown;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface PluginContext {
|
|
57
|
+
pluginName: string;
|
|
58
|
+
logger: ChildLogger;
|
|
59
|
+
config: Record<string, unknown>;
|
|
60
|
+
registerTool: (tool: ToolDefinition) => void;
|
|
61
|
+
unregisterTool: (name: string) => void;
|
|
62
|
+
registerChannel: (channel: ChannelDefinition) => void;
|
|
63
|
+
unregisterChannel: (name: string) => void;
|
|
64
|
+
registerCommand: (command: CLICommand) => void;
|
|
65
|
+
unregisterCommand: (name: string) => void;
|
|
66
|
+
events: {
|
|
67
|
+
emit: <K extends EventKey>(event: K, data: EventMap[K]) => void;
|
|
68
|
+
on: <K extends EventKey>(event: K, handler: (data: EventMap[K]) => void | Promise<void>) => () => void;
|
|
69
|
+
once: <K extends EventKey>(event: K, handler: (data: EventMap[K]) => void | Promise<void>) => void;
|
|
70
|
+
};
|
|
71
|
+
state: {
|
|
72
|
+
get: () => ReturnType<StateStore["getState"]>;
|
|
73
|
+
subscribe: (listener: (state: ReturnType<StateStore["getState"]>) => void) => () => void;
|
|
74
|
+
};
|
|
75
|
+
getTool: (name: string) => ToolDefinition | undefined;
|
|
76
|
+
getTools: () => ToolDefinition[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface InboundMessage {
|
|
80
|
+
sessionId: string;
|
|
81
|
+
channel: string;
|
|
82
|
+
userId: string;
|
|
83
|
+
content: string;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface AgentResponse {
|
|
88
|
+
sessionId: string;
|
|
89
|
+
content: string;
|
|
90
|
+
toolsUsed: string[];
|
|
91
|
+
duration: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface PluginToolCall {
|
|
95
|
+
name: string;
|
|
96
|
+
args: Record<string, unknown>;
|
|
97
|
+
sessionId: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type MiddlewareNext = () => Promise<void>;
|
|
101
|
+
export type MiddlewareResult = Promise<void>;
|
|
102
|
+
|
|
103
|
+
export interface HivePlugin {
|
|
104
|
+
name: string;
|
|
105
|
+
version: string;
|
|
106
|
+
dependencies?: string[];
|
|
107
|
+
manifest?: PluginManifest;
|
|
108
|
+
|
|
109
|
+
activate(context: PluginContext): Promise<void>;
|
|
110
|
+
deactivate(): Promise<void>;
|
|
111
|
+
|
|
112
|
+
onMessage?: (message: InboundMessage, next: MiddlewareNext) => MiddlewareResult;
|
|
113
|
+
onAgentResponse?: (response: AgentResponse, next: MiddlewareNext) => MiddlewareResult;
|
|
114
|
+
onToolCall?: (call: PluginToolCall, next: () => Promise<unknown>) => Promise<unknown>;
|
|
115
|
+
onError?: (error: Error, context: Record<string, unknown>) => Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface PluginState {
|
|
119
|
+
name: string;
|
|
120
|
+
status: "inactive" | "activating" | "active" | "deactivating" | "error";
|
|
121
|
+
version: string;
|
|
122
|
+
enabled: boolean;
|
|
123
|
+
error?: string;
|
|
124
|
+
loadedAt?: number;
|
|
125
|
+
activatedAt?: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type PluginConstructor = new () => HivePlugin;
|