@johpaz/hive-agents 0.0.35 → 0.0.37
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 +3231 -3189
- package/dist/tool-worker.js +218406 -0
- package/dist/ui/assets/{AgentCreateForm-B4eK7efF.js → AgentCreateForm-tJZv9FZC.js} +1 -1
- package/dist/ui/assets/{AgentDetailPage-BD2uoJWk.js → AgentDetailPage-Du-mRcAX.js} +1 -1
- package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +1 -0
- package/dist/ui/assets/{AgentsPage-4JUZXvkA.js → AgentsPage-YvSgWRiw.js} +6 -6
- package/dist/ui/assets/CanvasPage-DtMwGvxf.js +33 -0
- package/dist/ui/assets/{ChannelsPage-BUn7-nhV.js → ChannelsPage-BdBXWHjj.js} +1 -1
- package/dist/ui/assets/DashboardPage-ghl1ZguH.js +6 -0
- package/dist/ui/assets/{LoginPage-C8j_urUD.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-Drh-sJPN.js → NotFound-BMeQSGcG.js} +1 -1
- package/dist/ui/assets/ProvidersPage-Ct6HsAi1.js +1 -0
- package/dist/ui/assets/{RecoverPage-DNb1Pr8h.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-R-YOwA4F.js → WebChatPage-CVRcKept.js} +2 -2
- package/dist/ui/assets/accordion-C5d5Rm5z.js +1 -0
- package/dist/ui/assets/{alert-U8FsgWi7.js → alert-C-NE-P3s.js} +1 -1
- package/dist/ui/assets/{alert-dialog-CRdMkkmk.js → alert-dialog-C5mzbHdP.js} +1 -1
- package/dist/ui/assets/{badge-Cli1jnH5.js → badge-ChpACfWO.js} +1 -1
- package/dist/ui/assets/chevron-up-BYhk0K2J.js +1 -0
- package/dist/ui/assets/{dialog-DQ3s-LuO.js → dialog-QnZ0ad8O.js} +1 -1
- package/dist/ui/assets/dropdown-menu-BK-CO3Od.js +1 -0
- package/dist/ui/assets/{es-DcMjrpbA.js → es-NQNoaWDx.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/{label-0BvGVXvZ.js → label-D2H1IR_J.js} +1 -1
- package/dist/ui/assets/progress-BherYzY6.js +1 -0
- package/dist/ui/assets/scroll-area-DkeyX32e.js +1 -0
- package/dist/ui/assets/{slider-D47dOrRa.js → slider-CsiUDxc3.js} +1 -1
- package/dist/ui/assets/switch-BDwN8RYV.js +1 -0
- package/dist/ui/assets/{table-DhowbNxQ.js → table-CSc8ubon.js} +1 -1
- package/dist/ui/assets/terminal-DN38Q456.js +1 -0
- 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/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 +6 -6
- package/package.json +138 -13
- 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 +502 -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/AgentNewPage-GB-tVN50.js +0 -1
- package/dist/ui/assets/BridgePage-DDcDILKu.js +0 -1
- package/dist/ui/assets/CanvasPage-oOk2sGOD.js +0 -33
- package/dist/ui/assets/DashboardPage-DV_2qWYJ.js +0 -6
- package/dist/ui/assets/LogsPage-DayYjh01.js +0 -1
- package/dist/ui/assets/MeetingPage-C01uPuqj.js +0 -1
- package/dist/ui/assets/ProjectsPage-B8_am_Ib.js +0 -1
- package/dist/ui/assets/ProvidersPage-DBzi66e4.js +0 -1
- package/dist/ui/assets/SettingsPage-CFA_Tknl.js +0 -9
- package/dist/ui/assets/SetupPage-BrUWbhvT.js +0 -1
- package/dist/ui/assets/accordion-DdAEfIXR.js +0 -1
- package/dist/ui/assets/chevron-down-DIosfU_U.js +0 -1
- package/dist/ui/assets/chevron-up-CI-W21Fy.js +0 -1
- package/dist/ui/assets/circle-S0-ouLz-.js +0 -1
- package/dist/ui/assets/circle-minus-CE0iJrl8.js +0 -1
- package/dist/ui/assets/circle-x-jUJ5zZvQ.js +0 -1
- package/dist/ui/assets/dropdown-menu-C2CXM1VE.js +0 -1
- package/dist/ui/assets/index-BN0875JH.css +0 -2
- package/dist/ui/assets/index-CH6sBa3Q.js +0 -116
- package/dist/ui/assets/pencil-5VdSj-h5.js +0 -1
- package/dist/ui/assets/progress-JN30I5fF.js +0 -1
- package/dist/ui/assets/scroll-area-BQQPitM8.js +0 -1
- package/dist/ui/assets/search-ChPgnVKj.js +0 -1
- package/dist/ui/assets/switch-C7W2-KEx.js +0 -1
- package/dist/ui/assets/terminal-C-R5Fckz.js +0 -1
- package/dist/ui/assets/useProviders-TBnWn-Hq.js +0 -1
- /package/dist/ui/assets/{card-DFKnZ6ky.js → card-CNf6BS2e.js} +0 -0
- /package/dist/ui/assets/{circle-alert-KuAm2FWh.js → circle-alert-CyHDwUj8.js} +0 -0
- /package/dist/ui/assets/{circle-check-6Ard1-2z.js → circle-check-Bb54Ebmu.js} +0 -0
- /package/dist/ui/assets/{cpu-KDy6-FAI.js → cpu-Cdgc_B1K.js} +0 -0
- /package/dist/ui/assets/{download-Cjbk4Rek.js → download-C3ifGMjJ.js} +0 -0
- /package/dist/ui/assets/{external-link-HtrFM63g.js → external-link-BvxYeTP1.js} +0 -0
- /package/dist/ui/assets/{eye-D1dB40_o.js → eye-DqNTU_GD.js} +0 -0
- /package/dist/ui/assets/{file-text-CE58EfH0.js → file-text-BT_9S9SM.js} +0 -0
- /package/dist/ui/assets/{folder-open-DIPKeiI_.js → folder-open-BhH8y9ac.js} +0 -0
- /package/dist/ui/assets/{format-BwdV8bB5.js → format-GVHeOyWI.js} +0 -0
- /package/dist/ui/assets/{gateway-url-D5uj6Nxg.js → gateway-url-COCbW0IR.js} +0 -0
- /package/dist/ui/assets/{gauge-DmQmJHEg.js → gauge-D_TMa4i9.js} +0 -0
- /package/dist/ui/assets/{globe-_hUGxQF4.js → globe-DeCQTCDJ.js} +0 -0
- /package/dist/ui/assets/{hexagon-BaNGQlQj.js → hexagon-DsGOUl-H.js} +0 -0
- /package/dist/ui/assets/{history-BfZVGlZa.js → history-BSG-Ypqf.js} +0 -0
- /package/dist/ui/assets/{info-CBZ5-AlC.js → info-NwLoa2Mj.js} +0 -0
- /package/dist/ui/assets/{key-Bv5DdTPh.js → key-3EP0dhkT.js} +0 -0
- /package/dist/ui/assets/{loader-circle-C4hhXLgp.js → loader-circle-CZNax6kS.js} +0 -0
- /package/dist/ui/assets/{lock-CkZYexqw.js → lock-Ei1_J-Nq.js} +0 -0
- /package/dist/ui/assets/{pause-Bpy1_s7y.js → pause-BUqah9Bi.js} +0 -0
- /package/dist/ui/assets/{play-Cj4osqJZ.js → play-NcZ4swwL.js} +0 -0
- /package/dist/ui/assets/{plus-BQhgZN3A.js → plus-CX1xyhp5.js} +0 -0
- /package/dist/ui/assets/{refresh-cw-BfREHVQM.js → refresh-cw-DaYdjQFk.js} +0 -0
- /package/dist/ui/assets/{save-FFTD4dMp.js → save-CUdYyHNy.js} +0 -0
- /package/dist/ui/assets/{settings-BdHKUL92.js → settings-Ds4SqD8s.js} +0 -0
- /package/dist/ui/assets/{sparkles-r4uJbJAl.js → sparkles-yUEb-7oH.js} +0 -0
- /package/dist/ui/assets/{square-G7Hyufqm.js → square-BD81nFtN.js} +0 -0
- /package/dist/ui/assets/{textarea-5kyuD04X.js → textarea-CXgXWKrT.js} +0 -0
- /package/dist/ui/assets/{trash-2-DXVBRWfh.js → trash-2-CNjMkoq6.js} +0 -0
- /package/dist/ui/assets/{triangle-alert-Bu5seg9O.js → triangle-alert-C9Y8Ub4X.js} +0 -0
- /package/dist/ui/assets/{vendor-router-CCECILJ0.js → vendor-router-C9pIYwbJ.js} +0 -0
- /package/dist/ui/assets/{volume-2-s9DuS696.js → volume-2-CeSXNDv4.js} +0 -0
- /package/dist/ui/assets/{zap-BPHZzXKV.js → zap-hlXjpSeA.js} +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Local LLM — Cliente interno
|
|
3
|
+
* Usado por los agentes y skills para generar texto vía WebSocket
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface GenerateOptions {
|
|
7
|
+
prompt: string
|
|
8
|
+
model?: "e2b_iq3" | "e4b_iq3" | "e2b_q8" | "e4b_q8"
|
|
9
|
+
imagePath?: string
|
|
10
|
+
audioPath?: string
|
|
11
|
+
nPredict?: number
|
|
12
|
+
timeout?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getBaseURL(): string {
|
|
16
|
+
if (typeof globalThis !== "undefined" && "window" in globalThis) {
|
|
17
|
+
const win = (globalThis as any).window
|
|
18
|
+
const protocol = win.location.protocol === "https:" ? "wss:" : "ws:"
|
|
19
|
+
return `${protocol}//${win.location.host}`
|
|
20
|
+
}
|
|
21
|
+
return process.env.HIVE_LOCAL_WS_URL ?? "ws://localhost:3000"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const BASE_URL = getBaseURL()
|
|
25
|
+
const WS_URL = `${BASE_URL}/ws/llm`
|
|
26
|
+
|
|
27
|
+
/** Verifica si el servidor local está disponible */
|
|
28
|
+
export async function isLocalLLMAvailable(): Promise<boolean> {
|
|
29
|
+
try {
|
|
30
|
+
const httpUrl = BASE_URL.replace(/^ws/, "http")
|
|
31
|
+
const res = await fetch(`${httpUrl}/api/llm/status`, {
|
|
32
|
+
signal: AbortSignal.timeout(1000),
|
|
33
|
+
})
|
|
34
|
+
return res.ok
|
|
35
|
+
} catch {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Genera texto vía WebSocket con streaming */
|
|
41
|
+
export async function* generateLocal(options: GenerateOptions): AsyncGenerator<string> {
|
|
42
|
+
const ws = new WebSocket(WS_URL)
|
|
43
|
+
|
|
44
|
+
await new Promise<void>((resolve, reject) => {
|
|
45
|
+
ws.onopen = () => resolve()
|
|
46
|
+
ws.onerror = () => reject(new Error("No se pudo conectar a hive-local"))
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
ws.send(JSON.stringify({
|
|
50
|
+
type: "generate",
|
|
51
|
+
prompt: options.prompt,
|
|
52
|
+
model: options.model ?? "e2b_iq3",
|
|
53
|
+
imagePath: options.imagePath,
|
|
54
|
+
audioPath: options.audioPath,
|
|
55
|
+
nPredict: options.nPredict ?? 512,
|
|
56
|
+
}))
|
|
57
|
+
|
|
58
|
+
const timeout = options.timeout ?? 60_000
|
|
59
|
+
const timeoutId = setTimeout(() => ws.close(1000, "timeout"), timeout)
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
while (true) {
|
|
63
|
+
const message = await new Promise<string>((resolve, reject) => {
|
|
64
|
+
ws.onmessage = (event) => resolve(event.data as string)
|
|
65
|
+
ws.onerror = () => reject(new Error("WebSocket error"))
|
|
66
|
+
ws.onclose = () => reject(new Error("WebSocket cerrado"))
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const data = JSON.parse(message)
|
|
70
|
+
|
|
71
|
+
if (data.type === "token") {
|
|
72
|
+
yield data.text
|
|
73
|
+
} else if (data.type === "done") {
|
|
74
|
+
break
|
|
75
|
+
} else if (data.type === "error") {
|
|
76
|
+
throw new Error(data.message)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} finally {
|
|
80
|
+
clearTimeout(timeoutId)
|
|
81
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
82
|
+
ws.close()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Genera texto completo (no streaming, retorna string) */
|
|
88
|
+
export async function generateLocalComplete(options: GenerateOptions): Promise<string> {
|
|
89
|
+
const tokens: string[] = []
|
|
90
|
+
for await (const token of generateLocal(options)) {
|
|
91
|
+
tokens.push(token)
|
|
92
|
+
}
|
|
93
|
+
return tokens.join(" ")
|
|
94
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Local LLM — Detector de GPU
|
|
3
|
+
* Detecta Vulkan, CUDA, Metal o fallback a CPU
|
|
4
|
+
*
|
|
5
|
+
* Estrategias para Vulkan (en orden):
|
|
6
|
+
* 1) vulkaninfo --summary (si está instalado)
|
|
7
|
+
* 2) ICD JSON files + /sys/class/drm (sin herramientas extra)
|
|
8
|
+
* 3) lspci (último recurso)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export type GPUBackend = "cuda" | "vulkan" | "metal" | "rocm" | "none"
|
|
12
|
+
export type PlatformArch = "linux-x64" | "linux-arm64" | "windows-x64" | "macos-x64" | "macos-arm64"
|
|
13
|
+
export type GPUType = "iGPU" | "dGPU"
|
|
14
|
+
|
|
15
|
+
export interface GPUInfo {
|
|
16
|
+
backend: GPUBackend
|
|
17
|
+
deviceName?: string
|
|
18
|
+
vramMB?: number
|
|
19
|
+
gpuType?: GPUType
|
|
20
|
+
platform: PlatformArch
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function detectPlatform(): PlatformArch {
|
|
24
|
+
const os = process.platform
|
|
25
|
+
const arch = process.arch
|
|
26
|
+
|
|
27
|
+
if (os === "linux" && arch === "x64") return "linux-x64"
|
|
28
|
+
if (os === "linux" && arch === "arm64") return "linux-arm64"
|
|
29
|
+
if (os === "win32" && arch === "x64") return "windows-x64"
|
|
30
|
+
if (os === "darwin" && arch === "x64") return "macos-x64"
|
|
31
|
+
if (os === "darwin" && arch === "arm64") return "macos-arm64"
|
|
32
|
+
|
|
33
|
+
throw new Error(`Plataforma no soportada: ${os}/${arch}`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Intenta detectar CUDA via nvidia-smi */
|
|
37
|
+
async function detectCUDA(): Promise<{ deviceName: string; vramMB: number } | null> {
|
|
38
|
+
try {
|
|
39
|
+
const proc = Bun.spawn(["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv,noheader"], {
|
|
40
|
+
stdout: "pipe",
|
|
41
|
+
stderr: "pipe",
|
|
42
|
+
})
|
|
43
|
+
const output = await new Response(proc.stdout).text()
|
|
44
|
+
const exitCode = await proc.exited
|
|
45
|
+
if (exitCode !== 0) return null
|
|
46
|
+
|
|
47
|
+
const line = output.trim().split("\n")[0]
|
|
48
|
+
if (!line) return null
|
|
49
|
+
const match = line.match(/^(.+?),\s*(\d+)\s*MiB/)
|
|
50
|
+
if (!match) return null
|
|
51
|
+
|
|
52
|
+
return { deviceName: match[1].trim(), vramMB: parseInt(match[2], 10) }
|
|
53
|
+
} catch {
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Lee un archivo del sistema de forma segura */
|
|
59
|
+
async function readSysFile(path: string): Promise<string | null> {
|
|
60
|
+
try {
|
|
61
|
+
const file = Bun.file(path)
|
|
62
|
+
if (!(await file.exists())) return null
|
|
63
|
+
return (await file.text()).trim()
|
|
64
|
+
} catch {
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Mapea vendor ID hex a nombre legible */
|
|
70
|
+
function vendorName(vendorId: string): string {
|
|
71
|
+
const map: Record<string, string> = {
|
|
72
|
+
"0x1002": "AMD",
|
|
73
|
+
"0x8086": "Intel",
|
|
74
|
+
"0x10de": "NVIDIA",
|
|
75
|
+
"0x1af4": "VirtIO",
|
|
76
|
+
}
|
|
77
|
+
return map[vendorId.toLowerCase()] ?? vendorId
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Nombres amigables para cada ICD conocido */
|
|
81
|
+
const KNOWN_ICDS: Record<string, string> = {
|
|
82
|
+
intel_icd: "Intel Graphics",
|
|
83
|
+
radeon_icd: "AMD Radeon",
|
|
84
|
+
amd_icd: "AMD Radeon",
|
|
85
|
+
nvidia_icd: "NVIDIA GPU",
|
|
86
|
+
nouveau_icd: "NVIDIA (nouveau)",
|
|
87
|
+
lvp_icd: "llvmpipe (Software)",
|
|
88
|
+
dzn_icd: "Microsoft DirectX (dzn)",
|
|
89
|
+
virtio_icd: "VirtIO GPU",
|
|
90
|
+
asahi_icd: "Apple Silicon GPU",
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const SOFTWARE_ICDS = ["lvp_icd", "dzn_icd"]
|
|
94
|
+
|
|
95
|
+
/** Detecta Vulkan con 3 estrategias en cascada */
|
|
96
|
+
async function detectVulkan(): Promise<{
|
|
97
|
+
deviceName: string
|
|
98
|
+
vramMB?: number
|
|
99
|
+
gpuType?: GPUType
|
|
100
|
+
} | null> {
|
|
101
|
+
// ── Estrategia 1: vulkaninfo (más preciso, si está instalado) ────────────────
|
|
102
|
+
try {
|
|
103
|
+
const proc = Bun.spawn(["vulkaninfo", "--summary"], { stdout: "pipe", stderr: "pipe" })
|
|
104
|
+
const output = await new Response(proc.stdout).text()
|
|
105
|
+
const exitCode = await proc.exited
|
|
106
|
+
if (exitCode === 0) {
|
|
107
|
+
const deviceMatch = output.match(/deviceName\s*=\s*(.+)/)
|
|
108
|
+
if (deviceMatch) return { deviceName: deviceMatch[1].trim() }
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
// vulkaninfo no instalado → siguiente estrategia
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── Estrategia 2: ICD JSON files + /sys/class/drm ───────────────────────────
|
|
115
|
+
if (process.platform === "linux") {
|
|
116
|
+
const icdDirs = ["/usr/share/vulkan/icd.d", "/etc/vulkan/icd.d"]
|
|
117
|
+
|
|
118
|
+
for (const dir of icdDirs) {
|
|
119
|
+
let files: string[] = []
|
|
120
|
+
try {
|
|
121
|
+
const glob = new Bun.Glob("*.json")
|
|
122
|
+
files = await Array.fromAsync(glob.scan({ cwd: dir, absolute: true }))
|
|
123
|
+
} catch {
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (files.length === 0) continue
|
|
128
|
+
|
|
129
|
+
// Ordenar: hardware primero, software al final
|
|
130
|
+
files.sort((a, b) => {
|
|
131
|
+
const swA = SOFTWARE_ICDS.some(k => a.includes(k)) ? 1 : 0
|
|
132
|
+
const swB = SOFTWARE_ICDS.some(k => b.includes(k)) ? 1 : 0
|
|
133
|
+
return swA - swB
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Recopilar tarjetas DRM disponibles una sola vez
|
|
137
|
+
let drmCards: string[] = []
|
|
138
|
+
try {
|
|
139
|
+
const drmGlob = new Bun.Glob("card*")
|
|
140
|
+
const all = await Array.fromAsync(drmGlob.scan({ cwd: "/sys/class/drm", absolute: true }))
|
|
141
|
+
drmCards = all.filter(c => /\/card\d+$/.test(c))
|
|
142
|
+
} catch {
|
|
143
|
+
// sin acceso a sysfs
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Procesar cada ICD
|
|
147
|
+
const hwResults: Array<{ deviceName: string; vramMB?: number; gpuType?: GPUType }> = []
|
|
148
|
+
const swResults: Array<{ deviceName: string }> = []
|
|
149
|
+
|
|
150
|
+
for (const filePath of files) {
|
|
151
|
+
const text = await readSysFile(filePath)
|
|
152
|
+
if (!text) continue
|
|
153
|
+
|
|
154
|
+
let icd: { ICD?: { library_path?: string } } = {}
|
|
155
|
+
try { icd = JSON.parse(text) } catch { continue }
|
|
156
|
+
|
|
157
|
+
const libPath = icd?.ICD?.library_path
|
|
158
|
+
if (!libPath) continue
|
|
159
|
+
|
|
160
|
+
// Verificar que la librería existe en el sistema
|
|
161
|
+
if (!(await Bun.file(libPath).exists())) continue
|
|
162
|
+
|
|
163
|
+
const baseName = filePath.split("/").pop()?.replace(/\.x86_64\.json$|\.arm64\.json$|\.json$/, "") ?? ""
|
|
164
|
+
const isSoftware = SOFTWARE_ICDS.some(k => baseName.includes(k))
|
|
165
|
+
const matchedKey = Object.keys(KNOWN_ICDS).find(k => baseName.includes(k))
|
|
166
|
+
let deviceName = matchedKey ? KNOWN_ICDS[matchedKey] : baseName
|
|
167
|
+
|
|
168
|
+
if (isSoftware) {
|
|
169
|
+
swResults.push({ deviceName })
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Enriquecer con DRM sysfs
|
|
174
|
+
let vramMB: number | undefined
|
|
175
|
+
let gpuType: GPUType | undefined
|
|
176
|
+
let foundMatch = false
|
|
177
|
+
|
|
178
|
+
for (const cardPath of drmCards) {
|
|
179
|
+
const vendor = await readSysFile(`${cardPath}/device/vendor`)
|
|
180
|
+
if (!vendor) continue
|
|
181
|
+
|
|
182
|
+
const vName = vendorName(vendor)
|
|
183
|
+
|
|
184
|
+
// ¿Coincide este card con el ICD actual?
|
|
185
|
+
const matches =
|
|
186
|
+
(baseName.includes("intel") && vName === "Intel") ||
|
|
187
|
+
(baseName.includes("radeon") && vName === "AMD") ||
|
|
188
|
+
(baseName.includes("amd") && vName === "AMD") ||
|
|
189
|
+
(baseName.includes("nvidia") && vName === "NVIDIA") ||
|
|
190
|
+
(baseName.includes("nouveau") && vName === "NVIDIA") ||
|
|
191
|
+
(baseName.includes("virtio") && vName === "VirtIO")
|
|
192
|
+
|
|
193
|
+
if (!matches) continue
|
|
194
|
+
foundMatch = true
|
|
195
|
+
|
|
196
|
+
// VRAM desde sysfs (AMD expone mem_info_vram_total en bytes)
|
|
197
|
+
const vramRaw = await readSysFile(`${cardPath}/device/mem_info_vram_total`)
|
|
198
|
+
if (vramRaw) {
|
|
199
|
+
const bytes = parseInt(vramRaw, 10)
|
|
200
|
+
vramMB = Math.round(bytes / (1024 * 1024))
|
|
201
|
+
gpuType = bytes >= 512 * 1024 * 1024 ? "dGPU" : "iGPU"
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Enriquecer nombre con tipo de GPU
|
|
205
|
+
if (gpuType === "iGPU") {
|
|
206
|
+
deviceName = `${vName} iGPU (integrada)`
|
|
207
|
+
} else if (gpuType === "dGPU") {
|
|
208
|
+
deviceName = `${vName} GPU (dedicada)`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
break
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (foundMatch) hwResults.push({ deviceName, vramMB, gpuType })
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Retornar el primer resultado de hardware real encontrado
|
|
218
|
+
if (hwResults.length > 0) return hwResults[0]
|
|
219
|
+
// Si no hay hardware, reportar software renderer
|
|
220
|
+
if (swResults.length > 0) return swResults[0]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ── Estrategia 3: lspci (último recurso) ────────────────────────────────────
|
|
225
|
+
try {
|
|
226
|
+
const proc = Bun.spawn(["lspci"], { stdout: "pipe", stderr: "pipe" })
|
|
227
|
+
const output = await new Response(proc.stdout).text()
|
|
228
|
+
const exitCode = await proc.exited
|
|
229
|
+
if (exitCode === 0) {
|
|
230
|
+
const match = output.match(/(?:VGA|3D|Display)[^:]*:\s*(.+)/i)
|
|
231
|
+
if (match) return { deviceName: match[1].trim() }
|
|
232
|
+
}
|
|
233
|
+
} catch {
|
|
234
|
+
// lspci no disponible
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return null
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Detecta Metal en macOS */
|
|
241
|
+
async function detectMetal(): Promise<{ deviceName: string } | null> {
|
|
242
|
+
if (process.platform !== "darwin") return null
|
|
243
|
+
return { deviceName: "Apple Metal" }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Detección completa de GPU y plataforma */
|
|
247
|
+
export async function detectGPU(): Promise<GPUInfo> {
|
|
248
|
+
const platform = detectPlatform()
|
|
249
|
+
|
|
250
|
+
const cuda = await detectCUDA()
|
|
251
|
+
if (cuda) return { backend: "cuda", ...cuda, platform }
|
|
252
|
+
|
|
253
|
+
const vulkan = await detectVulkan()
|
|
254
|
+
if (vulkan) return { backend: "vulkan", ...vulkan, platform }
|
|
255
|
+
|
|
256
|
+
const metal = await detectMetal()
|
|
257
|
+
if (metal) return { backend: "metal", ...metal, platform }
|
|
258
|
+
|
|
259
|
+
return { backend: "none", platform }
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Devuelve el nombre del binario según GPU y plataforma (legacy hive-cli) */
|
|
263
|
+
export function getHiveCLIBinaryName(gpu: GPUInfo): string {
|
|
264
|
+
const { backend } = gpu
|
|
265
|
+
const backendPart = backend === "none" ? "cpu" : backend
|
|
266
|
+
const os = process.platform === "win32" ? "windows" : (process.platform === "darwin" ? "darwin" : "linux")
|
|
267
|
+
const arch = process.arch === "x64" ? "amd64" : (process.arch === "arm64" ? "arm64" : process.arch)
|
|
268
|
+
const ext = os === "windows" ? ".exe" : ""
|
|
269
|
+
return `hive-cli-${os}-${arch}-${backendPart}${ext}`
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export const HIVE_CLI_RELEASE_BASE = "https://github.com/johpaz/hive-cli/releases/download"
|
|
273
|
+
export const HIVE_CLI_VERSION = "v0.0.1"
|
|
274
|
+
|
|
275
|
+
export function getHiveCLIDownloadURL(binaryName: string): string {
|
|
276
|
+
return `${HIVE_CLI_RELEASE_BASE}/${HIVE_CLI_VERSION}/${binaryName}`
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Devuelve el sufijo del binario oficial de llama.cpp según GPU y plataforma
|
|
281
|
+
* Basado en GUIA-SERVIDOR.md
|
|
282
|
+
*/
|
|
283
|
+
export function getLlamaServerSuffix(gpu: GPUInfo): string {
|
|
284
|
+
const { backend, platform } = gpu
|
|
285
|
+
|
|
286
|
+
switch (platform) {
|
|
287
|
+
case "linux-x64":
|
|
288
|
+
if (backend === "vulkan") return "bin-ubuntu-vulkan-x64"
|
|
289
|
+
if (backend === "cuda") return "bin-ubuntu-cuda-x64" // Nota: el oficial suele ser vulkan/cpu/rocm/sycl en ubuntu
|
|
290
|
+
if (backend === "rocm") return "bin-ubuntu-rocm-7.2-x64"
|
|
291
|
+
return "bin-ubuntu-x64"
|
|
292
|
+
|
|
293
|
+
case "linux-arm64":
|
|
294
|
+
if (backend === "vulkan") return "bin-ubuntu-vulkan-arm64"
|
|
295
|
+
return "bin-ubuntu-arm64"
|
|
296
|
+
|
|
297
|
+
case "windows-x64":
|
|
298
|
+
if (backend === "cuda") return "bin-win-cuda-12.4-x64"
|
|
299
|
+
if (backend === "vulkan") return "bin-win-vulkan-x64"
|
|
300
|
+
return "bin-win-cpu-x64"
|
|
301
|
+
|
|
302
|
+
case "macos-arm64":
|
|
303
|
+
return "bin-macos-arm64"
|
|
304
|
+
|
|
305
|
+
case "macos-x64":
|
|
306
|
+
return "bin-macos-x64"
|
|
307
|
+
|
|
308
|
+
default:
|
|
309
|
+
return "bin-ubuntu-x64"
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export const LLAMA_CPP_RELEASE_BASE = "https://github.com/ggml-org/llama.cpp/releases/download"
|
|
314
|
+
export const LLAMA_CPP_DEFAULT_VER = "b9025"
|
|
315
|
+
|
|
316
|
+
export function getLlamaServerDownloadURL(suffix: string, version: string = LLAMA_CPP_DEFAULT_VER): string {
|
|
317
|
+
const isWin = suffix.includes("win")
|
|
318
|
+
const ext = isWin ? "zip" : "tar.gz"
|
|
319
|
+
const filename = `llama-${version}-${suffix}.${ext}`
|
|
320
|
+
return `${LLAMA_CPP_RELEASE_BASE}/${version}/${filename}`
|
|
321
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Local LLM — Downloader
|
|
3
|
+
* Descarga binarios desde GitHub releases y modelos desde HuggingFace
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, mkdirSync } from "fs"
|
|
7
|
+
import { join, dirname } from "path"
|
|
8
|
+
import { homedir } from "os"
|
|
9
|
+
import { detectGPU, getHiveCLIBinaryName, getHiveCLIDownloadURL, getLlamaServerSuffix, getLlamaServerDownloadURL, LLAMA_CPP_DEFAULT_VER } from "./detector"
|
|
10
|
+
|
|
11
|
+
const LLM_ROOT =
|
|
12
|
+
process.env.HIVE_LLM_ROOT ??
|
|
13
|
+
join(process.env.HIVE_HOME ?? join(homedir(), ".hive"), "llm-local")
|
|
14
|
+
|
|
15
|
+
export const BIN_DIR = join(LLM_ROOT, "bin")
|
|
16
|
+
export const MODELS_DIR = join(LLM_ROOT, "models")
|
|
17
|
+
|
|
18
|
+
if (!existsSync(BIN_DIR)) mkdirSync(BIN_DIR, { recursive: true })
|
|
19
|
+
if (!existsSync(MODELS_DIR)) mkdirSync(MODELS_DIR, { recursive: true })
|
|
20
|
+
|
|
21
|
+
/** URLs de modelos en HuggingFace (Gemma 4 según GUIA-SERVIDOR.md) */
|
|
22
|
+
export const HF_MODEL_URLS = {
|
|
23
|
+
mmproj: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/mmproj-BF16.gguf",
|
|
24
|
+
e2b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-UD-Q4_K_XL.gguf",
|
|
25
|
+
e4b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-UD-Q4_K_XL.gguf"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ModelId = "mmproj" | "e2b_Q4_K_XL" | "e4b_Q4_K_XL"
|
|
29
|
+
|
|
30
|
+
/** Modelos que requieren proyector de visión (mmproj) */
|
|
31
|
+
export const VISION_MODELS: ModelId[] = ["e4b_Q4_K_XL"]
|
|
32
|
+
|
|
33
|
+
export const MODEL_FILES: Record<ModelId, string> = {
|
|
34
|
+
mmproj: "mmproj-BF16.gguf",
|
|
35
|
+
e2b_Q4_K_XL: "gemma-4-E2B-it-UD-Q4_K_XL.gguf",
|
|
36
|
+
e4b_Q4_K_XL: "gemma-4-E4B-it-UD-Q4_K_XL.gguf",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getModelPath(modelId: ModelId): string {
|
|
40
|
+
return join(MODELS_DIR, MODEL_FILES[modelId])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isModelDownloaded(modelId: ModelId): boolean {
|
|
44
|
+
return existsSync(getModelPath(modelId))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Descarga un archivo con progreso (streaming a disco para evitar OOM) */
|
|
48
|
+
export async function downloadFile(
|
|
49
|
+
url: string,
|
|
50
|
+
dest: string,
|
|
51
|
+
onProgress?: (downloaded: number, total: number) => void
|
|
52
|
+
): Promise<void> {
|
|
53
|
+
const res = await fetch(url)
|
|
54
|
+
if (!res.ok) throw new Error(`HTTP ${res.status} al descargar ${url}`)
|
|
55
|
+
|
|
56
|
+
const total = Number(res.headers.get("content-length") ?? 0)
|
|
57
|
+
const reader = res.body?.getReader()
|
|
58
|
+
if (!reader) throw new Error("No body en respuesta")
|
|
59
|
+
|
|
60
|
+
const writer = Bun.file(dest).writer()
|
|
61
|
+
let downloaded = 0
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
while (true) {
|
|
65
|
+
const { done, value } = await reader.read()
|
|
66
|
+
if (done) break
|
|
67
|
+
|
|
68
|
+
writer.write(value)
|
|
69
|
+
downloaded += value.byteLength
|
|
70
|
+
if (onProgress) onProgress(downloaded, total)
|
|
71
|
+
}
|
|
72
|
+
await writer.end()
|
|
73
|
+
} catch (err) {
|
|
74
|
+
await writer.end()
|
|
75
|
+
throw err
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Descarga el binario hive-cli si no existe */
|
|
80
|
+
export async function installHiveCLI(): Promise<string> {
|
|
81
|
+
const gpu = await detectGPU()
|
|
82
|
+
const binaryName = getHiveCLIBinaryName(gpu)
|
|
83
|
+
const binaryPath = join(BIN_DIR, binaryName)
|
|
84
|
+
|
|
85
|
+
if (existsSync(binaryPath)) {
|
|
86
|
+
return binaryPath
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`[hive-local] Instalando hive-cli para ${gpu.platform} + ${gpu.backend}...`)
|
|
90
|
+
const url = getHiveCLIDownloadURL(binaryName)
|
|
91
|
+
|
|
92
|
+
await downloadFile(url, binaryPath, (d, t) => {
|
|
93
|
+
const pct = t > 0 ? ((d / t) * 100).toFixed(1) : "?"
|
|
94
|
+
process.stdout.write(`\r Descargando... ${pct}%`)
|
|
95
|
+
})
|
|
96
|
+
console.log("")
|
|
97
|
+
|
|
98
|
+
if (process.platform !== "win32") {
|
|
99
|
+
await Bun.spawn(["chmod", "+x", binaryPath]).exited
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(`[hive-local] ✓ hive-cli instalado en ${binaryPath}`)
|
|
103
|
+
return binaryPath
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Busca el binario llama-server sin descargarlo.
|
|
108
|
+
* Retorna la ruta si existe, o null si no está instalado.
|
|
109
|
+
*/
|
|
110
|
+
export async function findLlamaServerBinary(): Promise<string | null> {
|
|
111
|
+
const ext = process.platform === "win32" ? ".exe" : ""
|
|
112
|
+
const versionDir = join(BIN_DIR, `llama-${LLAMA_CPP_DEFAULT_VER}`)
|
|
113
|
+
const binaryPath = join(versionDir, `llama-server${ext}`)
|
|
114
|
+
return existsSync(binaryPath) ? binaryPath : null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Instala llama-server oficial si no existe
|
|
119
|
+
* Retorna la ruta al binario llama-server.
|
|
120
|
+
* ⚠️ Esta función DESCARGA el binario — solo llamar por acción explícita del usuario.
|
|
121
|
+
*/
|
|
122
|
+
export async function installLlamaServer(): Promise<string> {
|
|
123
|
+
const gpu = await detectGPU()
|
|
124
|
+
const suffix = getLlamaServerSuffix(gpu)
|
|
125
|
+
const version = LLAMA_CPP_DEFAULT_VER
|
|
126
|
+
|
|
127
|
+
// Directorio específico de la versión para evitar conflictos
|
|
128
|
+
const versionDir = join(BIN_DIR, `llama-${version}`)
|
|
129
|
+
const ext = process.platform === "win32" ? ".exe" : ""
|
|
130
|
+
const binaryPath = join(versionDir, `llama-server${ext}`)
|
|
131
|
+
|
|
132
|
+
if (existsSync(binaryPath)) {
|
|
133
|
+
return binaryPath
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!existsSync(versionDir)) mkdirSync(versionDir, { recursive: true })
|
|
137
|
+
|
|
138
|
+
console.log(`[hive-local] Instalando llama-server ${version} para ${gpu.platform} + ${gpu.backend}...`)
|
|
139
|
+
const url = getLlamaServerDownloadURL(suffix, version)
|
|
140
|
+
const isZip = url.endsWith(".zip")
|
|
141
|
+
const archivePath = join(BIN_DIR, `llama-${version}-${suffix}.${isZip ? "zip" : "tar.gz"}`)
|
|
142
|
+
|
|
143
|
+
await downloadFile(url, archivePath, (d, t) => {
|
|
144
|
+
const pct = t > 0 ? ((d / t) * 100).toFixed(1) : "?"
|
|
145
|
+
process.stdout.write(`\r Descargando binarios... ${pct}%`)
|
|
146
|
+
})
|
|
147
|
+
console.log("")
|
|
148
|
+
|
|
149
|
+
// Extraer
|
|
150
|
+
console.log(`[hive-local] Extrayendo binarios...`)
|
|
151
|
+
if (isZip) {
|
|
152
|
+
if (process.platform === "win32") {
|
|
153
|
+
await Bun.spawn(["powershell", "-Command", `Expand-Archive -Path "${archivePath}" -DestinationPath "${versionDir}" -Force`]).exited
|
|
154
|
+
} else {
|
|
155
|
+
await Bun.spawn(["unzip", "-o", archivePath, "-d", versionDir]).exited
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// El tar.gz oficial contiene una carpeta llama-bXXXXX/
|
|
159
|
+
await Bun.spawn(["tar", "-xzf", archivePath, "-C", BIN_DIR]).exited
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Limpiar archivo descargado
|
|
163
|
+
try {
|
|
164
|
+
const { unlinkSync } = await import("fs")
|
|
165
|
+
unlinkSync(archivePath)
|
|
166
|
+
} catch { /* ignore */ }
|
|
167
|
+
|
|
168
|
+
if (process.platform !== "win32") {
|
|
169
|
+
// Dar permisos a todos los binarios extraídos
|
|
170
|
+
await Bun.spawn(["chmod", "-R", "+x", versionDir]).exited
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log(`[hive-local] ✓ llama-server instalado en ${binaryPath}`)
|
|
174
|
+
return binaryPath
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Descarga un modelo si no existe */
|
|
178
|
+
export async function downloadModel(
|
|
179
|
+
modelId: ModelId,
|
|
180
|
+
onProgress?: (downloaded: number, total: number) => void
|
|
181
|
+
): Promise<string> {
|
|
182
|
+
const dest = getModelPath(modelId)
|
|
183
|
+
|
|
184
|
+
if (existsSync(dest)) {
|
|
185
|
+
return dest
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const url = HF_MODEL_URLS[modelId]
|
|
189
|
+
console.log(`[hive-local] Descargando modelo ${modelId}...`)
|
|
190
|
+
|
|
191
|
+
await downloadFile(url, dest, onProgress)
|
|
192
|
+
console.log(`[hive-local] ✓ Modelo ${modelId} descargado`)
|
|
193
|
+
|
|
194
|
+
// Advertir si el modelo requiere visión y no tenemos mmproj (NO descargar automáticamente)
|
|
195
|
+
if (VISION_MODELS.includes(modelId) && !isModelDownloaded("mmproj")) {
|
|
196
|
+
console.warn(`[hive-local] ⚠️ El modelo ${modelId} requiere el proyector de visión (mmproj). Descárgalo manualmente desde la UI.`)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return dest
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Descarga mmproj en postinstall (ligero) */
|
|
203
|
+
export async function installMMProj(): Promise<string> {
|
|
204
|
+
return downloadModel("mmproj")
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Lista modelos disponibles localmente (solo modelos de texto/visión finales) */
|
|
208
|
+
export function listLocalModels(): { id: ModelId; name: string; size: string; downloaded: boolean }[] {
|
|
209
|
+
const models: ModelId[] = ["e2b_Q4_K_XL", "e4b_Q4_K_XL"]
|
|
210
|
+
return models.map((id) => ({
|
|
211
|
+
id,
|
|
212
|
+
name: MODEL_FILES[id],
|
|
213
|
+
size: id.includes("Q4_K_XL") ? "~5-8 GB" : "~2-3 GB",
|
|
214
|
+
downloaded: isModelDownloaded(id),
|
|
215
|
+
}))
|
|
216
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Local LLM — Index
|
|
3
|
+
* Exporta todo el módulo
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { detectGPU, getHiveCLIBinaryName, getHiveCLIDownloadURL, getLlamaServerSuffix, getLlamaServerDownloadURL } from "./detector"
|
|
7
|
+
export type { GPUBackend, GPUInfo, PlatformArch } from "./detector"
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
installHiveCLI,
|
|
11
|
+
installLlamaServer,
|
|
12
|
+
findLlamaServerBinary,
|
|
13
|
+
downloadModel,
|
|
14
|
+
installMMProj,
|
|
15
|
+
listLocalModels,
|
|
16
|
+
isModelDownloaded,
|
|
17
|
+
getModelPath,
|
|
18
|
+
BIN_DIR,
|
|
19
|
+
MODELS_DIR,
|
|
20
|
+
HF_MODEL_URLS,
|
|
21
|
+
} from "./downloader"
|
|
22
|
+
export type { ModelId } from "./downloader"
|
|
23
|
+
|
|
24
|
+
export { getModelConfig, buildLlamaServerArgs, buildHiveCLIArgs, getRecommendedModel } from "./models"
|
|
25
|
+
export type { ModelConfig } from "./models"
|
|
26
|
+
|
|
27
|
+
export { llamaManager } from "./manager"
|
|
28
|
+
export type { ServerMode } from "./manager"
|
|
29
|
+
|
|
30
|
+
export { handleLLMWebSocket, handleLLMStatus } from "./server"
|
|
31
|
+
export type { LLMMessage } from "./server"
|
|
32
|
+
|
|
33
|
+
export { isLocalLLMAvailable, generateLocal, generateLocalComplete } from "./client"
|
|
34
|
+
export type { GenerateOptions } from "./client"
|