@johpaz/hive-agents 0.0.38 → 0.0.39
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 +18 -18
- package/dist/hive.js +3428 -2603
- package/dist/tool-worker.js +2085 -1820
- package/dist/ui/assets/AgentCreateForm-BTCzFbca.js +1 -0
- package/dist/ui/assets/AgentDetailPage-o27TRSVw.js +1 -0
- package/dist/ui/assets/AgentNewPage-400cCpYt.js +1 -0
- package/dist/ui/{dist/assets/AgentsPage-DGNLDXjR.js → assets/AgentsPage-C-GSRk-N.js} +5 -5
- package/dist/ui/assets/ApiClientPage-BOTpz6oP.js +3 -0
- package/dist/ui/assets/{CanvasPage-CnMO1FN8.js → CanvasPage-Cvs5ctza.js} +7 -7
- package/dist/ui/assets/ChannelsPage-C5m_L7P9.js +8 -0
- package/dist/ui/{dist/assets/DashboardPage-VyXXp3U1.js → assets/DashboardPage-CztbRQdm.js} +2 -2
- package/dist/ui/assets/{LoginPage-DPj2s2Qq.js → LoginPage-OMsrx5oj.js} +1 -1
- package/dist/ui/assets/LogsPage-CcYYwjgF.js +1 -0
- package/dist/ui/{dist/assets/MeetingPage-2ky_hKiG.js → assets/MeetingPage-CrKVAfe6.js} +1 -1
- package/dist/ui/assets/{NotFound-BMeQSGcG.js → NotFound-GbAJDgoD.js} +1 -1
- package/dist/ui/assets/ProvidersPage-uqPcZUSV.js +1 -0
- package/dist/ui/{dist/assets/RecoverPage-B-hDZUM2.js → assets/RecoverPage-CwB2ByCU.js} +1 -1
- package/dist/ui/assets/SettingsPage-DKLlye0z.js +9 -0
- package/dist/ui/assets/SetupPage-DOVh1ldK.js +1 -0
- package/dist/ui/{dist/assets/WebChatPage-BuGT2AL0.js → assets/WebChatPage-c-7S9jnT.js} +2 -2
- package/dist/ui/assets/accordion-DAbcVQCn.js +1 -0
- package/dist/ui/{dist/assets/alert-Bq6awLlW.js → assets/alert-D_2Y3qjL.js} +1 -1
- package/dist/ui/{dist/assets/alert-dialog-DQvltYmf.js → assets/alert-dialog-CpMxaNcu.js} +1 -1
- package/dist/ui/assets/{badge-DXUDdTed.js → badge-CxTPR6_t.js} +1 -1
- package/dist/ui/assets/bell-8BqRYmzf.js +1 -0
- package/dist/ui/assets/circle-x-Bv6WrUJo.js +1 -0
- package/dist/ui/assets/copy-dU94ZGsi.js +1 -0
- package/dist/ui/{dist/assets/dialog-bI9jImCS.js → assets/dialog-DfS3idb3.js} +1 -1
- package/dist/ui/{dist/assets/dropdown-menu-BK-CO3Od.js → assets/dropdown-menu-BdCbAW1z.js} +1 -1
- package/dist/ui/assets/{es-Cg8zdT52.js → es-Cz5h9_84.js} +1 -1
- package/dist/ui/assets/index-CmGm_r89.js +116 -0
- package/dist/ui/assets/index-T7HgphSn.css +2 -0
- package/dist/ui/{dist/assets/label-CrH0Jj3v.js → assets/label-byJkqOYq.js} +1 -1
- package/dist/ui/assets/progress-Dtz-Mzys.js +1 -0
- package/dist/ui/assets/scroll-area-BXtLsE9E.js +1 -0
- package/dist/ui/assets/search-BGmPJ-6L.js +1 -0
- package/dist/ui/assets/select-Cl16QYa_.js +1 -0
- package/dist/ui/assets/send-BuQcUO-R.js +1 -0
- package/dist/ui/assets/shield-C-05qB-2.js +1 -0
- package/dist/ui/assets/{slider-CsiUDxc3.js → slider-D2I0qven.js} +1 -1
- package/dist/ui/assets/switch-h2SfQX4B.js +1 -0
- package/dist/ui/assets/table-CVkIRJKK.js +1 -0
- package/dist/ui/assets/tabs-C619jxbO.js +1 -0
- package/dist/ui/assets/textarea-wvA-FDjO.js +1 -0
- package/dist/ui/assets/useProviders-eEri6BAc.js +1 -0
- package/dist/ui/{dist/assets/vendor-radix-cw1bQaVC.js → assets/vendor-radix-D6rA7xKY.js} +4 -4
- package/dist/ui/assets/{vendor-react-D4s9E-zj.js → vendor-react-BU5iQU4f.js} +1 -1
- package/dist/ui/dist/assets/AgentCreateForm-BTCzFbca.js +1 -0
- package/dist/ui/dist/assets/AgentDetailPage-o27TRSVw.js +1 -0
- package/dist/ui/dist/assets/AgentNewPage-400cCpYt.js +1 -0
- package/dist/ui/{assets/AgentsPage-DGNLDXjR.js → dist/assets/AgentsPage-C-GSRk-N.js} +5 -5
- package/dist/ui/dist/assets/ApiClientPage-BOTpz6oP.js +3 -0
- package/dist/ui/dist/assets/{CanvasPage-CnMO1FN8.js → CanvasPage-Cvs5ctza.js} +7 -7
- package/dist/ui/dist/assets/ChannelsPage-C5m_L7P9.js +8 -0
- package/dist/ui/{assets/DashboardPage-VyXXp3U1.js → dist/assets/DashboardPage-CztbRQdm.js} +2 -2
- package/dist/ui/dist/assets/{LoginPage-DPj2s2Qq.js → LoginPage-OMsrx5oj.js} +1 -1
- package/dist/ui/dist/assets/LogsPage-CcYYwjgF.js +1 -0
- package/dist/ui/{assets/MeetingPage-2ky_hKiG.js → dist/assets/MeetingPage-CrKVAfe6.js} +1 -1
- package/dist/ui/dist/assets/{NotFound-BMeQSGcG.js → NotFound-GbAJDgoD.js} +1 -1
- package/dist/ui/dist/assets/ProvidersPage-uqPcZUSV.js +1 -0
- package/dist/ui/{assets/RecoverPage-B-hDZUM2.js → dist/assets/RecoverPage-CwB2ByCU.js} +1 -1
- package/dist/ui/dist/assets/SettingsPage-DKLlye0z.js +9 -0
- package/dist/ui/dist/assets/SetupPage-DOVh1ldK.js +1 -0
- package/dist/ui/{assets/WebChatPage-BuGT2AL0.js → dist/assets/WebChatPage-c-7S9jnT.js} +2 -2
- package/dist/ui/dist/assets/accordion-DAbcVQCn.js +1 -0
- package/dist/ui/{assets/alert-Bq6awLlW.js → dist/assets/alert-D_2Y3qjL.js} +1 -1
- package/dist/ui/{assets/alert-dialog-DQvltYmf.js → dist/assets/alert-dialog-CpMxaNcu.js} +1 -1
- package/dist/ui/dist/assets/{badge-DXUDdTed.js → badge-CxTPR6_t.js} +1 -1
- package/dist/ui/dist/assets/bell-8BqRYmzf.js +1 -0
- package/dist/ui/dist/assets/circle-x-Bv6WrUJo.js +1 -0
- package/dist/ui/dist/assets/copy-dU94ZGsi.js +1 -0
- package/dist/ui/{assets/dialog-bI9jImCS.js → dist/assets/dialog-DfS3idb3.js} +1 -1
- package/dist/ui/{assets/dropdown-menu-BK-CO3Od.js → dist/assets/dropdown-menu-BdCbAW1z.js} +1 -1
- package/dist/ui/dist/assets/{es-Cg8zdT52.js → es-Cz5h9_84.js} +1 -1
- package/dist/ui/dist/assets/index-CmGm_r89.js +116 -0
- package/dist/ui/dist/assets/index-T7HgphSn.css +2 -0
- package/dist/ui/{assets/label-CrH0Jj3v.js → dist/assets/label-byJkqOYq.js} +1 -1
- package/dist/ui/dist/assets/progress-Dtz-Mzys.js +1 -0
- package/dist/ui/dist/assets/scroll-area-BXtLsE9E.js +1 -0
- package/dist/ui/dist/assets/search-BGmPJ-6L.js +1 -0
- package/dist/ui/dist/assets/select-Cl16QYa_.js +1 -0
- package/dist/ui/dist/assets/send-BuQcUO-R.js +1 -0
- package/dist/ui/dist/assets/shield-C-05qB-2.js +1 -0
- package/dist/ui/dist/assets/{slider-CsiUDxc3.js → slider-D2I0qven.js} +1 -1
- package/dist/ui/dist/assets/switch-h2SfQX4B.js +1 -0
- package/dist/ui/dist/assets/table-CVkIRJKK.js +1 -0
- package/dist/ui/dist/assets/tabs-C619jxbO.js +1 -0
- package/dist/ui/dist/assets/textarea-wvA-FDjO.js +1 -0
- package/dist/ui/dist/assets/useProviders-eEri6BAc.js +1 -0
- package/dist/ui/{assets/vendor-radix-cw1bQaVC.js → dist/assets/vendor-radix-D6rA7xKY.js} +4 -4
- package/dist/ui/dist/assets/{vendor-react-D4s9E-zj.js → vendor-react-BU5iQU4f.js} +1 -1
- package/dist/ui/dist/index.html +6 -6
- package/dist/ui/index.html +6 -6
- package/package.json +1 -1
- package/packages/cli/src/adapters/binary.ts +8 -4
- package/packages/cli/src/adapters/bun-global.ts +5 -1
- package/packages/cli/src/adapters/config.ts +4 -3
- package/packages/cli/src/adapters/docker.ts +2 -1
- package/packages/cli/src/commands/gateway.ts +123 -9
- package/packages/cli/src/commands/logs.ts +2 -1
- package/packages/cli/src/commands/onboard.ts +1 -1
- package/packages/cli/src/commands/sessions.ts +2 -1
- package/packages/cli/src/commands/skills.ts +2 -1
- package/packages/core/src/agent/llm-client.ts +4 -0
- package/packages/core/src/agent/llm-providers/anthropic.ts +23 -8
- package/packages/core/src/agent/llm-providers/interface.ts +5 -1
- package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
- package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -0
- package/packages/core/src/channels/whatsapp.ts +13 -1
- package/packages/core/src/config/loader.ts +7 -7
- package/packages/core/src/gateway/helpers/path.ts +2 -1
- package/packages/core/src/gateway/initializer.ts +4 -4
- package/packages/core/src/gateway/llm-local/downloader.ts +130 -11
- package/packages/core/src/gateway/llm-local/index.ts +2 -0
- package/packages/core/src/gateway/llm-local/models.ts +4 -3
- package/packages/core/src/gateway/router.ts +7 -5
- package/packages/core/src/gateway/routes/http-client.ts +16 -0
- package/packages/core/src/gateway/routes/llm-local.ts +51 -5
- package/packages/core/src/gateway/routes/providers.ts +43 -2
- package/packages/core/src/gateway/server.ts +11 -2
- package/packages/core/src/gateway/tts/src/install.ts +17 -9
- package/packages/core/src/storage/crypto.ts +152 -20
- package/packages/core/src/storage/migrate.ts +51 -18
- package/packages/core/src/storage/seed.ts +38 -2
- package/packages/core/src/tool-runtime/index.ts +22 -1
- package/packages/core/src/tools/api/api-request.ts +174 -0
- package/packages/core/src/tools/api/index.ts +16 -0
- package/packages/core/src/tools/index.ts +12 -0
- package/packages/core/src/tools/web/browser-click.ts +2 -2
- package/packages/core/src/tools/web/browser-extract.ts +22 -6
- package/packages/core/src/tools/web/browser-navigate.ts +34 -18
- package/packages/core/src/tools/web/browser-screenshot.ts +40 -8
- package/packages/core/src/tools/web/browser-script.ts +2 -2
- package/packages/core/src/tools/web/browser-service.ts +295 -341
- package/packages/core/src/tools/web/browser-type.ts +5 -10
- package/packages/core/src/tools/web/browser-wait.ts +2 -2
- package/packages/core/src/tools/web/index.ts +1 -1
- package/packages/core/src/utils/logger.ts +2 -1
- package/packages/mcp/src/manager.ts +2 -1
- package/packages/skills/src/bundled/api/api_client/SKILL.md +132 -0
- package/packages/skills/src/bundled-data.generated.ts +1274 -1217
- package/packages/skills/src/loader.ts +2 -1
- package/dist/ui/assets/AgentCreateForm-0oFbN3gj.js +0 -1
- package/dist/ui/assets/AgentDetailPage-BJ4L2fNJ.js +0 -1
- package/dist/ui/assets/AgentNewPage-B3n0LUck.js +0 -1
- package/dist/ui/assets/ChannelsPage-fbF8K4MR.js +0 -8
- package/dist/ui/assets/LogsPage-B2lY9maY.js +0 -1
- package/dist/ui/assets/ProvidersPage-CEyUM2tD.js +0 -1
- package/dist/ui/assets/SettingsPage-eO0i3g8p.js +0 -9
- package/dist/ui/assets/SetupPage-ByYqTELb.js +0 -1
- package/dist/ui/assets/accordion-C5d5Rm5z.js +0 -1
- package/dist/ui/assets/globe-DeCQTCDJ.js +0 -1
- package/dist/ui/assets/index-B2fCYtTS.css +0 -2
- package/dist/ui/assets/index-CQ7fn00w.js +0 -116
- package/dist/ui/assets/progress-BherYzY6.js +0 -1
- package/dist/ui/assets/scroll-area-DkeyX32e.js +0 -1
- package/dist/ui/assets/send-B0H5SEIE.js +0 -1
- package/dist/ui/assets/switch-BDwN8RYV.js +0 -1
- package/dist/ui/assets/table-CSc8ubon.js +0 -1
- package/dist/ui/assets/textarea-CXgXWKrT.js +0 -1
- package/dist/ui/assets/useProviders-CnlC_qCS.js +0 -1
- package/dist/ui/dist/assets/AgentCreateForm-0oFbN3gj.js +0 -1
- package/dist/ui/dist/assets/AgentDetailPage-BJ4L2fNJ.js +0 -1
- package/dist/ui/dist/assets/AgentNewPage-B3n0LUck.js +0 -1
- package/dist/ui/dist/assets/ChannelsPage-fbF8K4MR.js +0 -8
- package/dist/ui/dist/assets/LogsPage-B2lY9maY.js +0 -1
- package/dist/ui/dist/assets/ProvidersPage-CEyUM2tD.js +0 -1
- package/dist/ui/dist/assets/SettingsPage-eO0i3g8p.js +0 -9
- package/dist/ui/dist/assets/SetupPage-ByYqTELb.js +0 -1
- package/dist/ui/dist/assets/accordion-C5d5Rm5z.js +0 -1
- package/dist/ui/dist/assets/globe-DeCQTCDJ.js +0 -1
- package/dist/ui/dist/assets/index-B2fCYtTS.css +0 -2
- package/dist/ui/dist/assets/index-CQ7fn00w.js +0 -116
- package/dist/ui/dist/assets/progress-BherYzY6.js +0 -1
- package/dist/ui/dist/assets/scroll-area-DkeyX32e.js +0 -1
- package/dist/ui/dist/assets/send-B0H5SEIE.js +0 -1
- package/dist/ui/dist/assets/switch-BDwN8RYV.js +0 -1
- package/dist/ui/dist/assets/table-CSc8ubon.js +0 -1
- package/dist/ui/dist/assets/textarea-CXgXWKrT.js +0 -1
- package/dist/ui/dist/assets/useProviders-CnlC_qCS.js +0 -1
- /package/dist/ui/assets/{card-CNf6BS2e.js → card-CXAm46at.js} +0 -0
- /package/dist/ui/assets/{cpu-Cdgc_B1K.js → cpu-DSpPVLAz.js} +0 -0
- /package/dist/ui/assets/{download-C3ifGMjJ.js → download-D9ZyUZZR.js} +0 -0
- /package/dist/ui/assets/{external-link-BvxYeTP1.js → external-link-CHPbUorN.js} +0 -0
- /package/dist/ui/assets/{eye-DqNTU_GD.js → eye-epHJZ_nQ.js} +0 -0
- /package/dist/ui/assets/{file-text-BT_9S9SM.js → file-text-BEjEmgby.js} +0 -0
- /package/dist/ui/assets/{folder-open-BhH8y9ac.js → folder-open-iQMHVEqS.js} +0 -0
- /package/dist/ui/assets/{format-GVHeOyWI.js → format-oFACFaca.js} +0 -0
- /package/dist/ui/assets/{gateway-url-COCbW0IR.js → gateway-url-iG-C6Agn.js} +0 -0
- /package/dist/ui/assets/{gauge-D_TMa4i9.js → gauge-D0_GMEcq.js} +0 -0
- /package/dist/ui/assets/{settings-Ds4SqD8s.js → settings-CcMGI1iU.js} +0 -0
- /package/dist/ui/assets/{sparkles-yUEb-7oH.js → sparkles-D6fx8JC5.js} +0 -0
- /package/dist/ui/assets/{trash-2-CNjMkoq6.js → trash-2-BHRa5ft9.js} +0 -0
- /package/dist/ui/assets/{triangle-alert-C9Y8Ub4X.js → triangle-alert-D4nwAVbc.js} +0 -0
- /package/dist/ui/assets/{vendor-router-C9pIYwbJ.js → vendor-router-pCP7sjma.js} +0 -0
- /package/dist/ui/assets/{volume-2-CeSXNDv4.js → volume-2-B6tkRy2u.js} +0 -0
- /package/dist/ui/assets/{zap-hlXjpSeA.js → zap-QO7iWMRg.js} +0 -0
- /package/dist/ui/dist/assets/{card-CNf6BS2e.js → card-CXAm46at.js} +0 -0
- /package/dist/ui/dist/assets/{cpu-Cdgc_B1K.js → cpu-DSpPVLAz.js} +0 -0
- /package/dist/ui/dist/assets/{download-C3ifGMjJ.js → download-D9ZyUZZR.js} +0 -0
- /package/dist/ui/dist/assets/{external-link-BvxYeTP1.js → external-link-CHPbUorN.js} +0 -0
- /package/dist/ui/dist/assets/{eye-DqNTU_GD.js → eye-epHJZ_nQ.js} +0 -0
- /package/dist/ui/dist/assets/{file-text-BT_9S9SM.js → file-text-BEjEmgby.js} +0 -0
- /package/dist/ui/dist/assets/{folder-open-BhH8y9ac.js → folder-open-iQMHVEqS.js} +0 -0
- /package/dist/ui/dist/assets/{format-GVHeOyWI.js → format-oFACFaca.js} +0 -0
- /package/dist/ui/dist/assets/{gateway-url-COCbW0IR.js → gateway-url-iG-C6Agn.js} +0 -0
- /package/dist/ui/dist/assets/{gauge-D_TMa4i9.js → gauge-D0_GMEcq.js} +0 -0
- /package/dist/ui/dist/assets/{settings-Ds4SqD8s.js → settings-CcMGI1iU.js} +0 -0
- /package/dist/ui/dist/assets/{sparkles-yUEb-7oH.js → sparkles-D6fx8JC5.js} +0 -0
- /package/dist/ui/dist/assets/{trash-2-CNjMkoq6.js → trash-2-BHRa5ft9.js} +0 -0
- /package/dist/ui/dist/assets/{triangle-alert-C9Y8Ub4X.js → triangle-alert-D4nwAVbc.js} +0 -0
- /package/dist/ui/dist/assets/{vendor-router-C9pIYwbJ.js → vendor-router-pCP7sjma.js} +0 -0
- /package/dist/ui/dist/assets/{volume-2-CeSXNDv4.js → volume-2-B6tkRy2u.js} +0 -0
- /package/dist/ui/dist/assets/{zap-hlXjpSeA.js → zap-QO7iWMRg.js} +0 -0
|
@@ -250,11 +250,11 @@ export async function initializeGateway(
|
|
|
250
250
|
const agent = createAgentService();
|
|
251
251
|
await agent.initialize();
|
|
252
252
|
|
|
253
|
-
// 5b. Initialize Browser Service (
|
|
253
|
+
// 5b. Initialize Browser Service (agent-browser CLI)
|
|
254
254
|
let browserAvailable = false;
|
|
255
255
|
|
|
256
256
|
try {
|
|
257
|
-
log.info("
|
|
257
|
+
log.info("Initializing browser automation (agent-browser)...");
|
|
258
258
|
|
|
259
259
|
const browserService = initializeBrowserService(config);
|
|
260
260
|
browserAvailable = await browserService.start();
|
|
@@ -262,8 +262,8 @@ export async function initializeGateway(
|
|
|
262
262
|
if (browserAvailable) {
|
|
263
263
|
activateBrowserTools();
|
|
264
264
|
} else {
|
|
265
|
-
log.warn("⚠️
|
|
266
|
-
log.warn("
|
|
265
|
+
log.warn("⚠️ agent-browser no disponible - browser tools desactivadas");
|
|
266
|
+
log.warn(" Se instalará automáticamente en primer uso o manual: bun add -g agent-browser");
|
|
267
267
|
}
|
|
268
268
|
} catch (error) {
|
|
269
269
|
log.warn(`Browser Service initialization skipped: ${(error as Error).message}`);
|
|
@@ -18,22 +18,116 @@ export const MODELS_DIR = join(LLM_ROOT, "models")
|
|
|
18
18
|
if (!existsSync(BIN_DIR)) mkdirSync(BIN_DIR, { recursive: true })
|
|
19
19
|
if (!existsSync(MODELS_DIR)) mkdirSync(MODELS_DIR, { recursive: true })
|
|
20
20
|
|
|
21
|
-
/** URLs de modelos en HuggingFace (Gemma 4 según
|
|
21
|
+
/** URLs de modelos en HuggingFace (Gemma 4 y Qwen 3.5 según Unsloth) */
|
|
22
22
|
export const HF_MODEL_URLS = {
|
|
23
|
+
// mmproj legacy (E4B)
|
|
23
24
|
mmproj: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/mmproj-BF16.gguf",
|
|
25
|
+
// mmproj Gemma 4
|
|
26
|
+
mmproj_gemma4_12b: "https://huggingface.co/unsloth/gemma-4-12b-it-GGUF/resolve/main/mmproj-BF16.gguf",
|
|
27
|
+
mmproj_gemma4_26b: "https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/mmproj-BF16.gguf",
|
|
28
|
+
mmproj_gemma4_31b: "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/mmproj-BF16.gguf",
|
|
29
|
+
// mmproj Qwen 3.5
|
|
30
|
+
mmproj_qwen3_5_2b: "https://huggingface.co/unsloth/Qwen3.5-2B-GGUF/resolve/main/mmproj-F16.gguf",
|
|
31
|
+
mmproj_qwen3_5_4b: "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/mmproj-F16.gguf",
|
|
32
|
+
mmproj_qwen3_5_9b: "https://huggingface.co/unsloth/Qwen3.5-9B-GGUF/resolve/main/mmproj-F16.gguf",
|
|
33
|
+
mmproj_qwen3_5_27b: "https://huggingface.co/unsloth/Qwen3.5-27B-GGUF/resolve/main/mmproj-F16.gguf",
|
|
34
|
+
mmproj_qwen3_5_35b: "https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/mmproj-F16.gguf",
|
|
35
|
+
// modelos Gemma 4
|
|
24
36
|
e2b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-UD-Q4_K_XL.gguf",
|
|
25
|
-
e4b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-UD-Q4_K_XL.gguf"
|
|
37
|
+
e4b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-UD-Q4_K_XL.gguf",
|
|
38
|
+
gemma4_12b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-12b-it-GGUF/resolve/main/gemma-4-12b-it-UD-Q4_K_XL.gguf",
|
|
39
|
+
gemma4_26b_Q4_K_M: "https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf",
|
|
40
|
+
gemma4_31b_Q4_K_XL: "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-UD-Q4_K_XL.gguf",
|
|
41
|
+
// modelos Qwen 3.5
|
|
42
|
+
qwen3_5_2b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-2B-GGUF/resolve/main/Qwen3.5-2B-UD-Q4_K_XL.gguf",
|
|
43
|
+
qwen3_5_4b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-UD-Q4_K_XL.gguf",
|
|
44
|
+
qwen3_5_9b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-9B-GGUF/resolve/main/Qwen3.5-9B-UD-Q4_K_XL.gguf",
|
|
45
|
+
qwen3_5_27b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-27B-GGUF/resolve/main/Qwen3.5-27B-UD-Q4_K_XL.gguf",
|
|
46
|
+
qwen3_5_35b_Q4_K_XL: "https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/Qwen3.5-35B-A3B-UD-Q4_K_XL.gguf",
|
|
26
47
|
}
|
|
27
48
|
|
|
28
|
-
export type ModelId =
|
|
49
|
+
export type ModelId =
|
|
50
|
+
| "mmproj"
|
|
51
|
+
| "mmproj_gemma4_12b"
|
|
52
|
+
| "mmproj_gemma4_26b"
|
|
53
|
+
| "mmproj_gemma4_31b"
|
|
54
|
+
| "mmproj_qwen3_5_2b"
|
|
55
|
+
| "mmproj_qwen3_5_4b"
|
|
56
|
+
| "mmproj_qwen3_5_9b"
|
|
57
|
+
| "mmproj_qwen3_5_27b"
|
|
58
|
+
| "mmproj_qwen3_5_35b"
|
|
59
|
+
| "e2b_Q4_K_XL"
|
|
60
|
+
| "e4b_Q4_K_XL"
|
|
61
|
+
| "gemma4_12b_Q4_K_XL"
|
|
62
|
+
| "gemma4_26b_Q4_K_M"
|
|
63
|
+
| "gemma4_31b_Q4_K_XL"
|
|
64
|
+
| "qwen3_5_2b_Q4_K_XL"
|
|
65
|
+
| "qwen3_5_4b_Q4_K_XL"
|
|
66
|
+
| "qwen3_5_9b_Q4_K_XL"
|
|
67
|
+
| "qwen3_5_27b_Q4_K_XL"
|
|
68
|
+
| "qwen3_5_35b_Q4_K_XL"
|
|
29
69
|
|
|
30
70
|
/** Modelos que requieren proyector de visión (mmproj) */
|
|
31
|
-
export const VISION_MODELS: ModelId[] = [
|
|
71
|
+
export const VISION_MODELS: ModelId[] = [
|
|
72
|
+
"e4b_Q4_K_XL",
|
|
73
|
+
"gemma4_12b_Q4_K_XL",
|
|
74
|
+
"gemma4_26b_Q4_K_M",
|
|
75
|
+
"gemma4_31b_Q4_K_XL",
|
|
76
|
+
"qwen3_5_2b_Q4_K_XL",
|
|
77
|
+
"qwen3_5_4b_Q4_K_XL",
|
|
78
|
+
"qwen3_5_9b_Q4_K_XL",
|
|
79
|
+
"qwen3_5_27b_Q4_K_XL",
|
|
80
|
+
"qwen3_5_35b_Q4_K_XL",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
/** Mapeo de cada modelo a su mmproj correspondiente */
|
|
84
|
+
export const MODEL_MMPROJ_MAP: Record<ModelId, ModelId | undefined> = {
|
|
85
|
+
mmproj: undefined,
|
|
86
|
+
mmproj_gemma4_12b: undefined,
|
|
87
|
+
mmproj_gemma4_26b: undefined,
|
|
88
|
+
mmproj_gemma4_31b: undefined,
|
|
89
|
+
mmproj_qwen3_5_2b: undefined,
|
|
90
|
+
mmproj_qwen3_5_4b: undefined,
|
|
91
|
+
mmproj_qwen3_5_9b: undefined,
|
|
92
|
+
mmproj_qwen3_5_27b: undefined,
|
|
93
|
+
mmproj_qwen3_5_35b: undefined,
|
|
94
|
+
e2b_Q4_K_XL: undefined,
|
|
95
|
+
e4b_Q4_K_XL: "mmproj",
|
|
96
|
+
gemma4_12b_Q4_K_XL: "mmproj_gemma4_12b",
|
|
97
|
+
gemma4_26b_Q4_K_M: "mmproj_gemma4_26b",
|
|
98
|
+
gemma4_31b_Q4_K_XL: "mmproj_gemma4_31b",
|
|
99
|
+
qwen3_5_2b_Q4_K_XL: "mmproj_qwen3_5_2b",
|
|
100
|
+
qwen3_5_4b_Q4_K_XL: "mmproj_qwen3_5_4b",
|
|
101
|
+
qwen3_5_9b_Q4_K_XL: "mmproj_qwen3_5_9b",
|
|
102
|
+
qwen3_5_27b_Q4_K_XL: "mmproj_qwen3_5_27b",
|
|
103
|
+
qwen3_5_35b_Q4_K_XL: "mmproj_qwen3_5_35b",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Devuelve el ID del mmproj asociado a un modelo, o undefined si no requiere visión */
|
|
107
|
+
export function getModelMMProjId(modelId: ModelId): ModelId | undefined {
|
|
108
|
+
return MODEL_MMPROJ_MAP[modelId]
|
|
109
|
+
}
|
|
32
110
|
|
|
33
111
|
export const MODEL_FILES: Record<ModelId, string> = {
|
|
34
112
|
mmproj: "mmproj-BF16.gguf",
|
|
113
|
+
mmproj_gemma4_12b: "mmproj-gemma4-12b-BF16.gguf",
|
|
114
|
+
mmproj_gemma4_26b: "mmproj-gemma4-26b-BF16.gguf",
|
|
115
|
+
mmproj_gemma4_31b: "mmproj-gemma4-31b-BF16.gguf",
|
|
116
|
+
mmproj_qwen3_5_2b: "mmproj-qwen3.5-2b-F16.gguf",
|
|
117
|
+
mmproj_qwen3_5_4b: "mmproj-qwen3.5-4b-F16.gguf",
|
|
118
|
+
mmproj_qwen3_5_9b: "mmproj-qwen3.5-9b-F16.gguf",
|
|
119
|
+
mmproj_qwen3_5_27b: "mmproj-qwen3.5-27b-F16.gguf",
|
|
120
|
+
mmproj_qwen3_5_35b: "mmproj-qwen3.5-35b-F16.gguf",
|
|
35
121
|
e2b_Q4_K_XL: "gemma-4-E2B-it-UD-Q4_K_XL.gguf",
|
|
36
122
|
e4b_Q4_K_XL: "gemma-4-E4B-it-UD-Q4_K_XL.gguf",
|
|
123
|
+
gemma4_12b_Q4_K_XL: "gemma-4-12b-it-UD-Q4_K_XL.gguf",
|
|
124
|
+
gemma4_26b_Q4_K_M: "gemma-4-26B-A4B-it-UD-Q4_K_M.gguf",
|
|
125
|
+
gemma4_31b_Q4_K_XL: "gemma-4-31B-it-UD-Q4_K_XL.gguf",
|
|
126
|
+
qwen3_5_2b_Q4_K_XL: "Qwen3.5-2B-UD-Q4_K_XL.gguf",
|
|
127
|
+
qwen3_5_4b_Q4_K_XL: "Qwen3.5-4B-UD-Q4_K_XL.gguf",
|
|
128
|
+
qwen3_5_9b_Q4_K_XL: "Qwen3.5-9B-UD-Q4_K_XL.gguf",
|
|
129
|
+
qwen3_5_27b_Q4_K_XL: "Qwen3.5-27B-UD-Q4_K_XL.gguf",
|
|
130
|
+
qwen3_5_35b_Q4_K_XL: "Qwen3.5-35B-A3B-UD-Q4_K_XL.gguf",
|
|
37
131
|
}
|
|
38
132
|
|
|
39
133
|
export function getModelPath(modelId: ModelId): string {
|
|
@@ -65,13 +159,14 @@ export async function downloadFile(
|
|
|
65
159
|
const { done, value } = await reader.read()
|
|
66
160
|
if (done) break
|
|
67
161
|
|
|
68
|
-
writer.write(value)
|
|
162
|
+
await writer.write(value)
|
|
69
163
|
downloaded += value.byteLength
|
|
70
164
|
if (onProgress) onProgress(downloaded, total)
|
|
71
165
|
}
|
|
166
|
+
await writer.flush()
|
|
72
167
|
await writer.end()
|
|
73
168
|
} catch (err) {
|
|
74
|
-
await writer.end()
|
|
169
|
+
try { await writer.end() } catch { /* ignore */ }
|
|
75
170
|
throw err
|
|
76
171
|
}
|
|
77
172
|
}
|
|
@@ -191,9 +286,10 @@ export async function downloadModel(
|
|
|
191
286
|
await downloadFile(url, dest, onProgress)
|
|
192
287
|
console.log(`[hive-local] ✓ Modelo ${modelId} descargado`)
|
|
193
288
|
|
|
194
|
-
// Advertir si el modelo requiere visión y no tenemos mmproj (NO descargar automáticamente)
|
|
195
|
-
|
|
196
|
-
|
|
289
|
+
// Advertir si el modelo requiere visión y no tenemos su mmproj (NO descargar automáticamente)
|
|
290
|
+
const mmprojId = getModelMMProjId(modelId)
|
|
291
|
+
if (mmprojId && !isModelDownloaded(mmprojId)) {
|
|
292
|
+
console.warn(`[hive-local] ⚠️ El modelo ${modelId} requiere el proyector de visión (${mmprojId}). Descárgalo manualmente desde la UI.`)
|
|
197
293
|
}
|
|
198
294
|
|
|
199
295
|
return dest
|
|
@@ -206,11 +302,34 @@ export async function installMMProj(): Promise<string> {
|
|
|
206
302
|
|
|
207
303
|
/** Lista modelos disponibles localmente (solo modelos de texto/visión finales) */
|
|
208
304
|
export function listLocalModels(): { id: ModelId; name: string; size: string; downloaded: boolean }[] {
|
|
209
|
-
const models: ModelId[] = [
|
|
305
|
+
const models: ModelId[] = [
|
|
306
|
+
"e2b_Q4_K_XL",
|
|
307
|
+
"e4b_Q4_K_XL",
|
|
308
|
+
"gemma4_12b_Q4_K_XL",
|
|
309
|
+
"gemma4_26b_Q4_K_M",
|
|
310
|
+
"gemma4_31b_Q4_K_XL",
|
|
311
|
+
"qwen3_5_2b_Q4_K_XL",
|
|
312
|
+
"qwen3_5_4b_Q4_K_XL",
|
|
313
|
+
"qwen3_5_9b_Q4_K_XL",
|
|
314
|
+
"qwen3_5_27b_Q4_K_XL",
|
|
315
|
+
"qwen3_5_35b_Q4_K_XL",
|
|
316
|
+
]
|
|
317
|
+
const sizeMap: Record<string, string> = {
|
|
318
|
+
e2b_Q4_K_XL: "~3 GB",
|
|
319
|
+
e4b_Q4_K_XL: "~5 GB",
|
|
320
|
+
gemma4_12b_Q4_K_XL: "~7 GB",
|
|
321
|
+
gemma4_26b_Q4_K_M: "~10 GB",
|
|
322
|
+
gemma4_31b_Q4_K_XL: "~14 GB",
|
|
323
|
+
qwen3_5_2b_Q4_K_XL: "~1.2 GB",
|
|
324
|
+
qwen3_5_4b_Q4_K_XL: "~2.5 GB",
|
|
325
|
+
qwen3_5_9b_Q4_K_XL: "~5.4 GB",
|
|
326
|
+
qwen3_5_27b_Q4_K_XL: "~16 GB",
|
|
327
|
+
qwen3_5_35b_Q4_K_XL: "~21 GB",
|
|
328
|
+
}
|
|
210
329
|
return models.map((id) => ({
|
|
211
330
|
id,
|
|
212
331
|
name: MODEL_FILES[id],
|
|
213
|
-
size: id
|
|
332
|
+
size: sizeMap[id] || "~?",
|
|
214
333
|
downloaded: isModelDownloaded(id),
|
|
215
334
|
}))
|
|
216
335
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import { existsSync } from "fs"
|
|
8
|
-
import { MODELS_DIR, getModelPath, type ModelId } from "./downloader"
|
|
8
|
+
import { MODELS_DIR, getModelPath, getModelMMProjId, type ModelId } from "./downloader"
|
|
9
9
|
|
|
10
10
|
export interface ModelConfig {
|
|
11
11
|
modelPath: string
|
|
@@ -43,8 +43,9 @@ export function getModelConfig(modelId: ModelId, port: number = 8081): ModelConf
|
|
|
43
43
|
throw new Error(`Modelo no descargado: ${modelId}. Ejecuta downloadModel("${modelId}") primero.`)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const
|
|
47
|
-
const
|
|
46
|
+
const mmprojId = getModelMMProjId(modelId)
|
|
47
|
+
const mmprojPath = mmprojId ? getModelPath(mmprojId) : undefined
|
|
48
|
+
const hasMMProj = mmprojPath ? existsSync(mmprojPath) : false
|
|
48
49
|
|
|
49
50
|
return {
|
|
50
51
|
modelPath,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Config, Binding } from "../config/loader.ts";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
2
4
|
|
|
3
5
|
export interface RoutingContext {
|
|
4
6
|
channel: string;
|
|
@@ -113,12 +115,12 @@ export class Router {
|
|
|
113
115
|
const agent = agents.find((a) => a.id === agentId);
|
|
114
116
|
|
|
115
117
|
if (agent?.workspace) {
|
|
116
|
-
return agent.workspace.replace(/^~/,
|
|
118
|
+
return agent.workspace.replace(/^~/, homedir());
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
const baseDir = this.config.agent?.baseDir?.replace(/^~/,
|
|
120
|
-
??
|
|
121
|
-
|
|
122
|
-
return
|
|
121
|
+
const baseDir = this.config.agent?.baseDir?.replace(/^~/, homedir())
|
|
122
|
+
?? path.join(homedir(), ".hive", "agents");
|
|
123
|
+
|
|
124
|
+
return path.join(baseDir, agentId, "workspace");
|
|
123
125
|
}
|
|
124
126
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { apiRequestTool } from "../../tools/api/api-request.ts";
|
|
2
|
+
|
|
3
|
+
export async function handleHttpRequest(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
|
|
4
|
+
try {
|
|
5
|
+
const body = await req.json().catch(() => ({}));
|
|
6
|
+
|
|
7
|
+
const result = await apiRequestTool.execute(body, { configurable: {} });
|
|
8
|
+
|
|
9
|
+
return addCorsHeaders(Response.json(result), req);
|
|
10
|
+
} catch (error) {
|
|
11
|
+
return addCorsHeaders(Response.json({
|
|
12
|
+
ok: false,
|
|
13
|
+
error: `Request failed: ${(error as Error).message}`,
|
|
14
|
+
}), req);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -19,6 +19,15 @@ let installing = false
|
|
|
19
19
|
let installLogs: string[] = []
|
|
20
20
|
let downloadingModelId: string | null = null
|
|
21
21
|
|
|
22
|
+
interface DownloadProgress {
|
|
23
|
+
modelId: string
|
|
24
|
+
downloaded: number
|
|
25
|
+
total: number
|
|
26
|
+
percent: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let currentDownloadProgress: DownloadProgress | null = null
|
|
30
|
+
|
|
22
31
|
async function getInstalledStatus() {
|
|
23
32
|
const { LLAMA_CPP_DEFAULT_VER } = await import("../llm-local/detector")
|
|
24
33
|
const gpu = await detectGPU()
|
|
@@ -183,7 +192,12 @@ export async function handleDownloadLLMModel(
|
|
|
183
192
|
;(async () => {
|
|
184
193
|
try {
|
|
185
194
|
await downloadModel(modelId, (d, t) => {
|
|
186
|
-
|
|
195
|
+
currentDownloadProgress = {
|
|
196
|
+
modelId,
|
|
197
|
+
downloaded: d,
|
|
198
|
+
total: t,
|
|
199
|
+
percent: t > 0 ? Math.round((d / t) * 100) : 0,
|
|
200
|
+
}
|
|
187
201
|
})
|
|
188
202
|
installLogs.push(`✓ Modelo ${modelId} descargado exitosamente`)
|
|
189
203
|
} catch (err) {
|
|
@@ -191,6 +205,7 @@ export async function handleDownloadLLMModel(
|
|
|
191
205
|
installLogs.push(`[error] Error descargando ${modelId}: ${msg}`)
|
|
192
206
|
} finally {
|
|
193
207
|
downloadingModelId = null
|
|
208
|
+
currentDownloadProgress = null
|
|
194
209
|
}
|
|
195
210
|
})()
|
|
196
211
|
|
|
@@ -207,7 +222,15 @@ export async function handleStartLocalLLM(
|
|
|
207
222
|
} catch { /* ignore if no body */ }
|
|
208
223
|
|
|
209
224
|
const mode = body.mode || "TEXT"
|
|
210
|
-
|
|
225
|
+
// If no modelId specified, prefer the recommended model; fall back to the
|
|
226
|
+
// first downloaded model so the user doesn't get an error when they only
|
|
227
|
+
// downloaded a non-default model.
|
|
228
|
+
const recommended = getRecommendedModel(mode.toLowerCase() as any)
|
|
229
|
+
const allModels = listLocalModels()
|
|
230
|
+
const downloadedModels = allModels.filter(m => m.downloaded)
|
|
231
|
+
const resolvedModelId: string =
|
|
232
|
+
body.modelId ||
|
|
233
|
+
(downloadedModels.find(m => m.id === recommended) ? recommended : (downloadedModels[0]?.id ?? recommended))
|
|
211
234
|
|
|
212
235
|
const status = await getInstalledStatus()
|
|
213
236
|
if (!status.installed && !status.binaryExists) {
|
|
@@ -217,11 +240,18 @@ export async function handleStartLocalLLM(
|
|
|
217
240
|
)
|
|
218
241
|
}
|
|
219
242
|
|
|
243
|
+
if (downloadedModels.length === 0) {
|
|
244
|
+
return addCors(
|
|
245
|
+
Response.json({ started: false, reason: "No hay modelos descargados. Descarga un modelo primero desde la sección de modelos." }, { status: 400 }),
|
|
246
|
+
req
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
|
|
220
250
|
try {
|
|
221
|
-
installLogs.push(`[llm-server] Iniciando servidor en modo ${mode} con modelo ${
|
|
222
|
-
await llamaManager.start(mode,
|
|
251
|
+
installLogs.push(`[llm-server] Iniciando servidor en modo ${mode} con modelo ${resolvedModelId}...`)
|
|
252
|
+
await llamaManager.start(mode, resolvedModelId as any)
|
|
223
253
|
installLogs.push(`[llm-server] Servidor ${mode} iniciado correctamente.`)
|
|
224
|
-
return addCors(Response.json({ started: true, mode }), req)
|
|
254
|
+
return addCors(Response.json({ started: true, mode, modelId: resolvedModelId }), req)
|
|
225
255
|
} catch (err) {
|
|
226
256
|
const msg = err instanceof Error ? err.message : String(err)
|
|
227
257
|
installLogs.push(`[error] Servidor LLM falló al iniciar: ${msg}`)
|
|
@@ -251,6 +281,22 @@ export async function handleStopLocalLLM(
|
|
|
251
281
|
* Verifica el estado del LLM local al iniciar el gateway.
|
|
252
282
|
* NO auto-inicia el servidor ni descarga nada — el usuario debe hacerlo manualmente.
|
|
253
283
|
*/
|
|
284
|
+
export async function handleGetDownloadProgress(
|
|
285
|
+
req: Request,
|
|
286
|
+
addCors: (r: Response, req: Request) => Response
|
|
287
|
+
): Promise<Response> {
|
|
288
|
+
if (!currentDownloadProgress) {
|
|
289
|
+
return addCors(Response.json({ active: false }), req)
|
|
290
|
+
}
|
|
291
|
+
return addCors(
|
|
292
|
+
Response.json({
|
|
293
|
+
active: true,
|
|
294
|
+
...currentDownloadProgress,
|
|
295
|
+
}),
|
|
296
|
+
req
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
|
|
254
300
|
export async function initializeLocalLLM() {
|
|
255
301
|
try {
|
|
256
302
|
const status = await getInstalledStatus()
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
loadProviderApiKey, storeProviderApiKey,
|
|
5
5
|
loadProviderHeaders, storeProviderHeaders,
|
|
6
6
|
} from "../../storage/crypto"
|
|
7
|
+
import { listLocalModels } from "../llm-local/downloader"
|
|
7
8
|
|
|
8
9
|
export async function handleGetProviders(req: Request, addCorsHeaders: (r: Response, req: Request) => Response): Promise<Response> {
|
|
9
10
|
const rawProviders = getDb().query(`
|
|
@@ -24,20 +25,60 @@ export async function handleGetProviders(req: Request, addCorsHeaders: (r: Respo
|
|
|
24
25
|
})
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
// Inyectar modelos locales descargados dinámicamente para local-llama
|
|
29
|
+
try {
|
|
30
|
+
const localModels = listLocalModels()
|
|
31
|
+
const downloadedLocalModels = localModels.filter(m => m.downloaded)
|
|
32
|
+
if (downloadedLocalModels.length > 0) {
|
|
33
|
+
const existingLocalModels = modelsByProvider["local-llama"] || []
|
|
34
|
+
for (const localModel of downloadedLocalModels) {
|
|
35
|
+
const existingIdx = existingLocalModels.findIndex((m: any) => m.id === localModel.id)
|
|
36
|
+
if (existingIdx === -1) {
|
|
37
|
+
existingLocalModels.push({
|
|
38
|
+
id: localModel.id,
|
|
39
|
+
name: localModel.name,
|
|
40
|
+
provider_id: "local-llama",
|
|
41
|
+
model_type: "llm",
|
|
42
|
+
context_window: 16000,
|
|
43
|
+
capabilities: JSON.stringify(["chat", "local"]),
|
|
44
|
+
enabled: true,
|
|
45
|
+
active: true,
|
|
46
|
+
})
|
|
47
|
+
} else {
|
|
48
|
+
// Modelo del seed ya existe pero está descargado: forzar activo
|
|
49
|
+
existingLocalModels[existingIdx] = {
|
|
50
|
+
...existingLocalModels[existingIdx],
|
|
51
|
+
enabled: true,
|
|
52
|
+
active: true,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
modelsByProvider["local-llama"] = existingLocalModels
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// Ignorar si no se pueden obtener modelos locales
|
|
60
|
+
}
|
|
61
|
+
|
|
27
62
|
const providers = await Promise.all(rawProviders.map(async (p) => {
|
|
28
63
|
const apiKey = await loadProviderApiKey(p.id as string)
|
|
29
64
|
const headers = await loadProviderHeaders(p.id as string)
|
|
65
|
+
const providerModels = modelsByProvider[p.id as string] || []
|
|
66
|
+
// Auto-activar local-llama si tiene modelos descargados dinámicamente
|
|
67
|
+
let active = p.active
|
|
68
|
+
if (p.id === "local-llama" && providerModels.some((m: any) => m.active || m.enabled)) {
|
|
69
|
+
active = true
|
|
70
|
+
}
|
|
30
71
|
return {
|
|
31
72
|
id: p.id,
|
|
32
73
|
name: p.name,
|
|
33
74
|
base_url: p.base_url,
|
|
34
75
|
enabled: p.enabled,
|
|
35
|
-
active
|
|
76
|
+
active,
|
|
36
77
|
num_ctx: p.num_ctx ?? null,
|
|
37
78
|
has_api_key: apiKey ? 1 : 0,
|
|
38
79
|
has_headers: Object.keys(headers).length > 0 ? 1 : 0,
|
|
39
80
|
masked_api_key: apiKey ? maskApiKey(apiKey) : null,
|
|
40
|
-
models:
|
|
81
|
+
models: providerModels,
|
|
41
82
|
}
|
|
42
83
|
}))
|
|
43
84
|
|
|
@@ -73,12 +73,13 @@ import { handleGetModels, handleCreateModel, handleToggleModel, handleGetModelsC
|
|
|
73
73
|
import { handleGetVoiceProviders, handleGetConfiguredVoiceProviders, handleSaveVoiceProviderKey, handleTestVoice, handleGetChannelVoice, handleUpdateChannelVoice, handleGetVoiceProviderVoices } from "./routes/voice";
|
|
74
74
|
import { handleGetVisionProviders, handleGetChannelVision, handleUpdateChannelVision, handleOcrImage } from "./routes/multimodal";
|
|
75
75
|
import { handleGetLocalTTSStatus, handleGetLocalTTSLogs, handleInstallLocalTTS, handleStartLocalTTS, handleStopLocalTTS, handleSpeakLocalTTS, handleGetAvailableModels, handleGetInstalledVoices, handleDownloadModel, handleGetDownloadLogs, initializeLocalTTS } from "./routes/tts-local";
|
|
76
|
-
import { handleGetLocalLLMStatus, handleGetLocalLLMLogs, handleInstallLocalLLM, handleStartLocalLLM, handleStopLocalLLM, handleDownloadLLMModel, initializeLocalLLM } from "./routes/llm-local";
|
|
76
|
+
import { handleGetLocalLLMStatus, handleGetLocalLLMLogs, handleInstallLocalLLM, handleStartLocalLLM, handleStopLocalLLM, handleDownloadLLMModel, handleGetDownloadProgress, initializeLocalLLM } from "./routes/llm-local";
|
|
77
77
|
import { handleCreateMeeting, handleListMeetings, handleGetMeeting, handleAddMeetingSegment, handleStopMeeting } from "./routes/meeting";
|
|
78
78
|
import { handleGetActivityStats, handleGetSystemStats, handleGetUsageStats, handleSystemReload, handleApiReload, handleGetVersion, handleTriggerUpdate } from "./routes/system";
|
|
79
79
|
import { handleGetChatHistory, handleGetCanvas, handleGetNotes, handleUpdateNote } from "./routes/chat";
|
|
80
80
|
import { handleChat as handlePostChat } from "./routes/chat";
|
|
81
81
|
import { handleGetConfig } from "./routes/config";
|
|
82
|
+
import { handleHttpRequest } from "./routes/http-client";
|
|
82
83
|
import { handleGetWorkspace, handleUpdateWorkspace, handleValidateWorkspace, handleCreateWorkspace, handleOpenWorkspace } from "./routes/workspace";
|
|
83
84
|
import { getNarration, expandPath, addCorsHeaders, CORS_ORIGINS } from "./helpers";
|
|
84
85
|
import { redactConfig } from "./helpers";
|
|
@@ -961,6 +962,11 @@ export async function startGateway(config: Config): Promise<void> {
|
|
|
961
962
|
}
|
|
962
963
|
}
|
|
963
964
|
|
|
965
|
+
// ── HTTP Client API ────────────────────────────────────────────────
|
|
966
|
+
if ((url.pathname === "/api/http-request" || url.pathname === "/api/http-request/") && req.method === "POST") {
|
|
967
|
+
return await handleHttpRequest(req, addCorsHeaders)
|
|
968
|
+
}
|
|
969
|
+
|
|
964
970
|
// ── Tasks API ─────────────────────────────────────────────────────
|
|
965
971
|
if ((url.pathname === "/api/tasks" || url.pathname === "/api/tasks/") && req.method === "GET") {
|
|
966
972
|
return await handleGetTasks(req, addCorsHeaders)
|
|
@@ -1626,6 +1632,9 @@ export async function startGateway(config: Config): Promise<void> {
|
|
|
1626
1632
|
if (url.pathname === "/api/llm-local/download-model" && req.method === "POST") {
|
|
1627
1633
|
return await handleDownloadLLMModel(req, addCorsHeaders)
|
|
1628
1634
|
}
|
|
1635
|
+
if (url.pathname === "/api/llm-local/download-progress" && req.method === "GET") {
|
|
1636
|
+
return await handleGetDownloadProgress(req, addCorsHeaders)
|
|
1637
|
+
}
|
|
1629
1638
|
|
|
1630
1639
|
// ── Meeting Transcription API ────────────────────────────────────────
|
|
1631
1640
|
if (url.pathname === "/api/meetings" && req.method === "POST") {
|
|
@@ -2729,7 +2738,7 @@ export async function startGateway(config: Config): Promise<void> {
|
|
|
2729
2738
|
process.exit(0);
|
|
2730
2739
|
});
|
|
2731
2740
|
|
|
2732
|
-
process.on("SIGHUP", async () => {
|
|
2741
|
+
if (process.platform !== "win32") process.on("SIGHUP", async () => {
|
|
2733
2742
|
log.info("Received SIGHUP, reloading configuration...");
|
|
2734
2743
|
try {
|
|
2735
2744
|
const newConfig = await loadConfig();
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Los datos se guardan en $HIVE_HOME/tts/ (por defecto ~/.hive/tts/).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { existsSync, mkdirSync, readdirSync, renameSync } from "fs"
|
|
7
|
+
import { existsSync, mkdirSync, readdirSync, renameSync, unlinkSync, rmSync } from "fs"
|
|
8
8
|
import { join } from "path"
|
|
9
9
|
import { homedir } from "os"
|
|
10
10
|
import {
|
|
@@ -37,16 +37,24 @@ async function extractTarGz(archivePath: string, destDir: string): Promise<void>
|
|
|
37
37
|
stderr: "inherit",
|
|
38
38
|
}).exited
|
|
39
39
|
if (code !== 0) throw new Error(`tar falló con código ${code}`)
|
|
40
|
-
|
|
40
|
+
unlinkSync(archivePath)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async function extractZip(archivePath: string, destDir: string): Promise<void> {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
let code: number
|
|
45
|
+
if (process.platform === "win32") {
|
|
46
|
+
code = await Bun.spawn(
|
|
47
|
+
["powershell", "-Command", `Expand-Archive -Path "${archivePath}" -DestinationPath "${destDir}" -Force`],
|
|
48
|
+
{ stdout: "inherit", stderr: "inherit" }
|
|
49
|
+
).exited
|
|
50
|
+
} else {
|
|
51
|
+
code = await Bun.spawn(["unzip", "-q", archivePath, "-d", destDir], {
|
|
52
|
+
stdout: "inherit",
|
|
53
|
+
stderr: "inherit",
|
|
54
|
+
}).exited
|
|
55
|
+
}
|
|
56
|
+
if (code !== 0) throw new Error(`Extracción ZIP falló con código ${code}`)
|
|
57
|
+
unlinkSync(archivePath)
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
/**
|
|
@@ -86,7 +94,7 @@ export async function runInstall(ttsRoot: string): Promise<void> {
|
|
|
86
94
|
for (const entry of readdirSync(tempDir)) {
|
|
87
95
|
renameSync(join(tempDir, entry), join(BIN_DIR, entry))
|
|
88
96
|
}
|
|
89
|
-
|
|
97
|
+
rmSync(tempDir, { recursive: true, force: true })
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
if (!existsSync(binaryPath)) {
|