@johpaz/hive-sdk 0.1.4 → 0.1.5
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/CHANGELOG.md +97 -0
- package/README.md +78 -23
- package/bunfig.toml +4 -2
- package/docs/API-AGENTS.md +78 -27
- package/docs/API-CONTEXT-COMPILER.md +31 -34
- package/docs/API-TOOLS-SKILLS-CHANNELS.md +58 -22
- package/docs/HIVE-HARNESS.md +1 -1
- package/docs/INDEX.md +4 -4
- package/docs/TEMPLATE-HIVE-APP.md +10 -10
- package/package.json +9 -4
- package/packages/cli/package.json +2 -2
- package/packages/cli/src/commands/create-app.test.ts +36 -7
- package/packages/cli/src/commands/init.ts +3 -3
- package/packages/cli/src/commands/run.ts +1 -1
- package/packages/cli/src/commands/test.ts +37 -25
- package/packages/cli/src/commands/trace.ts +30 -28
- package/packages/cli/templates/hive-app/.env.example +10 -2
- package/packages/cli/templates/hive-app/README.md +103 -0
- package/packages/cli/templates/hive-app/hive.config.ts +9 -3
- package/packages/cli/templates/hive-app/src/agents/coordinator.ts +8 -1
- package/packages/cli/templates/hive-app/src/main.ts +12 -19
- package/packages/core/package.json +5 -4
- package/packages/core/src/agent/acceptance-checks.ts +166 -0
- package/packages/core/src/agent/agent-catalog.ts +348 -0
- package/packages/core/src/agent/agent-loop.ts +1373 -0
- package/packages/core/src/agent/capability-search.ts +186 -0
- package/packages/core/src/agent/catalog-selector.ts +103 -0
- package/packages/core/src/agent/{Compaction.ts → compaction.ts} +86 -63
- package/packages/core/src/agent/context-compiler.ts +689 -0
- package/packages/core/src/agent/conversation-store.ts +381 -0
- package/packages/core/src/agent/curator.ts +276 -0
- package/packages/core/src/agent/delegation-runtime.ts +241 -0
- package/packages/core/src/agent/goal-runner.ts +323 -0
- package/packages/core/src/agent/index.ts +17 -12
- package/packages/core/src/agent/llm-client.ts +266 -0
- package/packages/core/src/agent/llm-providers/anthropic.ts +264 -0
- package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
- package/packages/core/src/agent/{providers → llm-providers}/gemini.ts +98 -60
- package/packages/core/src/agent/llm-providers/groq.ts +5 -0
- package/packages/core/src/agent/llm-providers/hiveagents.ts +253 -0
- package/packages/core/src/agent/{providers → llm-providers}/interface.ts +73 -13
- package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
- package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
- package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
- package/packages/core/src/agent/llm-providers/modelscope.ts +5 -0
- package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
- package/packages/core/src/agent/{providers → llm-providers}/ollama.ts +31 -5
- package/packages/core/src/agent/llm-providers/openai-compat-base.ts +418 -0
- package/packages/core/src/agent/llm-providers/openai.ts +5 -0
- package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -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/llm-providers/z-ai.ts +5 -0
- package/packages/core/src/agent/minimal-loadout.ts +47 -0
- package/packages/core/src/agent/playbook-selector.ts +119 -0
- package/packages/core/src/agent/{PromptBuilder.ts → prompt-builder.ts} +21 -22
- package/packages/core/src/{harness → agent}/proof-packet.ts +16 -21
- package/packages/core/src/agent/providers/index.ts +35 -16
- package/packages/core/src/agent/reflector.ts +320 -0
- package/packages/core/src/agent/routing-intent.ts +22 -0
- package/packages/core/src/{harness → agent}/run-epoch.ts +4 -3
- package/packages/core/src/{harness → agent}/run-store.ts +142 -81
- package/packages/core/src/agent/{Service.ts → service.ts} +37 -26
- package/packages/core/src/agent/skill-selector.ts +374 -0
- package/packages/core/src/agent/stuck-loop.ts +209 -0
- package/packages/core/src/agent/{selectors/ToolSelector.ts → tool-selector.ts} +188 -178
- package/packages/core/src/{ace/Tracer.ts → agent/tracer.ts} +37 -27
- package/packages/core/src/api/createAgent.test.ts +139 -27
- package/packages/core/src/api/createAgent.ts +232 -44
- package/packages/core/src/artifacts/store.ts +162 -0
- package/packages/core/src/canvas/canvas-manager.ts +161 -0
- package/packages/core/src/canvas/canvas.test.ts +8 -4
- package/packages/core/src/canvas/emitter.ts +131 -80
- package/packages/core/src/canvas/index.ts +1 -3
- package/packages/core/src/channels/base.ts +9 -1
- package/packages/core/src/channels/discord.ts +5 -4
- package/packages/core/src/channels/manager.ts +122 -30
- package/packages/core/src/channels/slack.ts +5 -4
- package/packages/core/src/channels/telegram.ts +36 -6
- package/packages/core/src/channels/webchat.ts +11 -10
- package/packages/core/src/channels/whatsapp.ts +23 -7
- package/packages/core/src/config/index.ts +13 -2
- package/packages/core/src/config/loader.ts +71 -29
- package/packages/core/src/ethics/EthicsGuard.test.ts +90 -36
- package/packages/core/src/ethics/EthicsGuard.ts +51 -47
- package/packages/core/src/events/agent-bus.ts +44 -68
- package/packages/core/src/events/channel-narration.ts +150 -0
- package/packages/core/src/events/narration.ts +82 -0
- package/packages/core/src/events/tool-narration.ts +62 -0
- package/packages/core/src/gateway/delegation-groups.ts +258 -0
- package/packages/core/src/{harness → gateway}/durable-queue.ts +102 -42
- package/packages/core/src/{harness → gateway}/job-store.ts +85 -48
- package/packages/core/src/gateway/lane-queue.ts +173 -0
- package/packages/core/src/gateway/notification-inbox.ts +57 -0
- package/packages/core/src/gateway/server.ts +1 -1
- package/packages/core/src/harness/index.ts +46 -27
- package/packages/core/src/index.ts +33 -27
- package/packages/core/src/mcp/hot-reload.ts +32 -23
- package/packages/core/src/mcp/index.ts +6 -3
- package/packages/core/src/mcp/singleton.ts +1 -4
- package/packages/core/src/mcp/tool-sync.ts +138 -0
- package/packages/core/src/memory/Scratchpad.test.ts +39 -20
- package/packages/core/src/memory/Scratchpad.ts +27 -34
- package/packages/core/src/multimodal/vision-service.ts +44 -38
- package/packages/core/src/resilience/retry.ts +95 -0
- package/packages/core/src/scheduler/CronScheduler.ts +334 -287
- package/packages/core/src/scheduler/index.ts +9 -7
- package/packages/core/src/scheduler/integration.ts +46 -26
- package/packages/core/src/scheduler/scheduler.test.ts +9 -13
- package/packages/core/src/scheduler/types.ts +7 -2
- package/packages/core/src/security/Pairing.ts +1 -1
- package/packages/core/src/skills/bundled/a2ui/a2ui_dashboard/SKILL.md +176 -0
- package/packages/core/src/skills/bundled/a2ui/a2ui_form/SKILL.md +202 -0
- package/packages/core/src/skills/bundled/a2ui/a2ui_interactive/SKILL.md +206 -0
- package/packages/core/src/skills/bundled/agents/agent_spawner/SKILL.md +173 -0
- package/packages/core/src/skills/bundled/agents/memory_manager/SKILL.md +143 -0
- package/packages/core/src/skills/bundled/agents/research_and_remember/SKILL.md +139 -0
- package/packages/core/src/skills/bundled/agents/task_orchestrator/SKILL.md +98 -0
- package/packages/core/src/skills/bundled/api/api_client/SKILL.md +132 -0
- package/packages/core/src/skills/bundled/cli/cli_pipeline/SKILL.md +135 -0
- package/packages/core/src/skills/bundled/cli/cli_safe_exec/SKILL.md +125 -0
- package/packages/core/src/skills/bundled/cli/software_engineering/SKILL.md +23 -0
- package/packages/core/src/skills/bundled/cron_manager/SKILL.md +188 -0
- package/packages/core/src/skills/bundled/cron_reminder/SKILL.md +112 -0
- package/packages/core/src/skills/bundled/filesystem/file_manager/SKILL.md +118 -0
- package/packages/core/src/skills/bundled/filesystem/file_read_and_summarize/SKILL.md +109 -0
- package/packages/core/src/skills/bundled/filesystem/file_writer/SKILL.md +129 -0
- package/packages/core/src/skills/bundled/filesystem/workspace_file_operator/SKILL.md +22 -0
- package/packages/core/src/skills/bundled/office/office_document_manager/SKILL.md +262 -0
- package/packages/core/src/skills/bundled/search_knowledge/capability_discovery/SKILL.md +75 -0
- package/packages/core/src/skills/bundled/web/browser_automate/SKILL.md +120 -0
- package/packages/core/src/skills/bundled/web/browser_scrape/SKILL.md +109 -0
- package/packages/core/src/skills/bundled/web/web_monitor/SKILL.md +127 -0
- package/packages/core/src/skills/bundled/web/web_research/SKILL.md +119 -0
- package/packages/core/src/skills/bundled-data.generated.ts +731 -2678
- package/packages/core/src/skills/skills.test.ts +52 -11
- package/packages/core/src/{harness → storage}/boot-id.ts +5 -2
- package/packages/core/src/storage/bootstrap.ts +151 -0
- package/packages/core/src/storage/causal-events.ts +84 -0
- package/packages/core/src/storage/collections.ts +680 -0
- package/packages/core/src/storage/crypto.ts +205 -74
- package/packages/core/src/{harness/db-helpers.ts → storage/hive.ts} +63 -7
- package/packages/core/src/storage/hivedb.ts +61 -0
- package/packages/core/src/storage/index.ts +111 -18
- package/packages/core/src/storage/model-id.ts +53 -0
- package/packages/core/src/storage/onboarding.ts +540 -972
- package/packages/core/src/storage/reconcile.ts +238 -0
- package/packages/core/src/storage/seed.ts +572 -406
- package/packages/core/src/storage/usage.ts +285 -225
- package/packages/core/src/storage/user-email.ts +11 -0
- package/packages/core/src/swarm/AgentExecutor.ts +1 -1
- package/packages/core/src/swarm/EventBridge.ts +1 -1
- package/packages/core/src/swarm/index.ts +12 -9
- package/packages/core/src/tool-runtime/index.ts +146 -23
- package/packages/core/src/tool-runtime/tool-worker.ts +2 -2
- package/packages/core/src/tool-runtime/worker-tools.ts +27 -0
- package/packages/core/src/{canvas/a2ui-tools.ts → tools/a2ui/index.ts} +17 -8
- package/packages/core/src/tools/agents/get-available-models.ts +36 -54
- package/packages/core/src/tools/agents/index.ts +784 -292
- package/packages/core/src/tools/api/api-request.test.ts +164 -0
- 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/cli/index.ts +4 -0
- package/packages/core/src/tools/core/index.ts +281 -112
- package/packages/core/src/tools/cron/index.ts +121 -124
- package/packages/core/src/tools/index.ts +63 -78
- package/packages/core/src/tools/office/office-escribir-xlsx.ts +3 -1
- package/packages/core/src/tools/types.ts +3 -1
- package/packages/core/src/tools/web/artifact-inspect.ts +23 -0
- package/packages/core/src/tools/web/browser-screenshot.ts +26 -5
- package/packages/core/src/tools/web/browser-service.ts +5 -0
- package/packages/core/src/tools/web/browser-type.ts +3 -8
- package/packages/core/src/tools/web/index.ts +4 -4
- package/packages/core/src/voice/index.ts +89 -63
- package/packages/core/src/workers/agent.worker.ts +2 -2
- package/packages/core/src/workers/workers.test.ts +3 -10
- package/scripts/bump-version.ts +248 -0
- package/scripts/generate-skill-bundle.ts +108 -0
- package/test/agent-loop-terminal-synthesis.test.ts +32 -0
- package/test/catalog-agents-stay-enabled.test.ts +117 -0
- package/test/causal-events.test.ts +117 -0
- package/test/compaction.test.ts +105 -0
- package/test/context-compiler.test.ts +269 -0
- package/test/curator.test.ts +130 -0
- package/test/durable-queue.test.ts +114 -0
- package/test/harness-barrel.test.ts +64 -0
- package/test/hive-helpers.test.ts +130 -0
- package/test/hivedb-search.test.ts +189 -0
- package/test/internal-turns.test.ts +166 -0
- package/test/job-idempotency.test.ts +68 -0
- package/test/job-retry-backoff.test.ts +184 -0
- package/test/job-store.test.ts +381 -0
- package/test/llm-retry.test.ts +97 -0
- package/test/memory-perf.test.ts +774 -0
- package/test/minimal-loadout.test.ts +78 -0
- package/test/model-catalog.test.ts +105 -0
- package/test/preload.ts +12 -0
- package/test/reflector.test.ts +320 -0
- package/test/retention-cap.test.ts +91 -0
- package/test/retired-capabilities-pruned.test.ts +192 -0
- package/test/run-store.test.ts +355 -0
- package/test/scratchpad.test.ts +74 -0
- package/test/secrets-durability.test.ts +119 -0
- package/test/seed-model-reseed.test.ts +155 -0
- package/test/setup-agent-seed.test.ts +264 -0
- package/test/tool-inventory.test.ts +65 -0
- package/test/tool-runtime.test.ts +258 -0
- package/test/toon.test.ts +429 -0
- package/tsconfig.json +2 -0
- package/packages/core/src/ace/Curator.ts +0 -158
- package/packages/core/src/ace/Reflector.ts +0 -200
- package/packages/core/src/ace/index.ts +0 -4
- package/packages/core/src/agent/AgentRunner.ts +0 -711
- package/packages/core/src/agent/ContextCompiler.ts +0 -567
- package/packages/core/src/agent/ContextGuard.ts +0 -91
- package/packages/core/src/agent/ConversationStore.ts +0 -254
- package/packages/core/src/agent/Hooks.ts +0 -166
- package/packages/core/src/agent/StuckLoop.ts +0 -133
- package/packages/core/src/agent/providers/LLMClient.ts +0 -149
- package/packages/core/src/agent/providers/anthropic.ts +0 -212
- package/packages/core/src/agent/providers/openai-compat.ts +0 -231
- package/packages/core/src/agent/selectors/PlaybookSelector.ts +0 -121
- package/packages/core/src/agent/selectors/SkillSelector.ts +0 -322
- package/packages/core/src/agent/selectors/index.ts +0 -6
- package/packages/core/src/auth/auth.ts +0 -121
- package/packages/core/src/auth/index.ts +0 -1
- package/packages/core/src/canvas/CanvasManager.ts +0 -390
- package/packages/core/src/canvas/canvas-tools.ts +0 -448
- package/packages/core/src/harness/collections.ts +0 -98
- package/packages/core/src/harness/goal-verifier.ts +0 -141
- package/packages/core/src/harness/harness.test.ts +0 -236
- package/packages/core/src/harness/reconcile.ts +0 -149
- package/packages/core/src/mcp/MCPToolAdapter.ts +0 -176
- package/packages/core/src/multimodal/VisionService.ts +0 -293
- package/packages/core/src/scheduler/dag/AgentExecutor.ts +0 -53
- package/packages/core/src/scheduler/dag/DAGScheduler.ts +0 -250
- package/packages/core/src/scheduler/dag/EventBridge.ts +0 -122
- package/packages/core/src/scheduler/dag/TaskGraph.ts +0 -192
- package/packages/core/src/scheduler/dag/TaskNode.ts +0 -97
- package/packages/core/src/scheduler/dag/TaskResult.ts +0 -22
- package/packages/core/src/scheduler/dag/errors.ts +0 -37
- package/packages/core/src/scheduler/dag/index.ts +0 -26
- package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +0 -97
- package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +0 -21
- package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +0 -46
- package/packages/core/src/storage/HiveDBStorage.ts +0 -64
- package/packages/core/src/storage/SQLiteStorage.ts +0 -414
- package/packages/core/src/storage/hiveSeed.ts +0 -308
- package/packages/core/src/storage/hiveStorage.test.ts +0 -38
- package/packages/core/src/storage/schema.ts +0 -689
- package/packages/core/src/storage/storage.test.ts +0 -37
- package/packages/core/src/swarm/AgentBus.ts +0 -460
- package/packages/core/src/swarm/EventBus.ts +0 -169
- package/packages/core/src/swarm/WorkerPool.ts +0 -236
- package/packages/core/src/tools/bridge-events.ts +0 -26
- package/packages/core/src/tools/canvas/index.ts +0 -375
- package/packages/core/src/tools/codebridge/index.ts +0 -342
- package/packages/core/src/tools/meeting/index.ts +0 -353
- package/packages/core/src/tools/projects/index.ts +0 -37
- package/packages/core/src/tools/projects/project-create.ts +0 -94
- package/packages/core/src/tools/projects/project-done.ts +0 -66
- package/packages/core/src/tools/projects/project-fail.ts +0 -66
- package/packages/core/src/tools/projects/project-list.ts +0 -96
- package/packages/core/src/tools/projects/project-update.ts +0 -72
- package/packages/core/src/tools/projects/task-create.ts +0 -68
- package/packages/core/src/tools/projects/task-evaluate.ts +0 -93
- package/packages/core/src/tools/projects/task-update.ts +0 -93
- package/packages/core/src/tools/voice/index.ts +0 -104
- package/packages/core/src/tools/web/api-request.test.ts +0 -170
- package/packages/core/src/tools/web/api-request.ts +0 -239
- package/test/setup-db.ts +0 -216
- /package/packages/core/src/agent/{NativeTools.ts → native-tools.ts} +0 -0
|
@@ -1,48 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* HiveDB-based Dynamic Tool Selector Module
|
|
3
|
+
*
|
|
4
4
|
* Context Compiler Level 3 - Intelligent Tool Selection
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* This module intercepts each message BEFORE calling the LLM and uses
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* HiveDB BM25 scoring (Spanish stemming + accent folding, per-field boosts)
|
|
8
|
+
* to select the most relevant tools.
|
|
9
|
+
*
|
|
9
10
|
* DESIGN DECISIONS:
|
|
10
|
-
*
|
|
11
|
+
*
|
|
11
12
|
* 1. Stateless: No memory between turns - each message is evaluated independently.
|
|
12
13
|
* Rationale: Prevents cascade effects where a bad selection in one turn affects
|
|
13
14
|
* future turns. Forces fresh evaluation each time.
|
|
14
|
-
*
|
|
15
|
-
* 2. Maximum
|
|
15
|
+
*
|
|
16
|
+
* 2. Maximum tools per turn: Keeps token count low and prevents overwhelming
|
|
16
17
|
* the LLM with irrelevant tools. Forces prioritization.
|
|
17
|
-
*
|
|
18
|
-
* 3.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
*
|
|
19
|
+
* 3. Relative relevance cutoff: BM25 scores are positive (higher = better) but
|
|
20
|
+
* their magnitude depends on corpus and document length, so hits are kept
|
|
21
|
+
* only if they score at least RELEVANCE_RATIO of the top hit. Conversational
|
|
22
|
+
* messages are short-circuited by pattern matching before any search.
|
|
23
|
+
*
|
|
23
24
|
* 4. Atomic over orchestration: When ambiguous, prefer individual tools over
|
|
24
25
|
* compound/manager tools. Rationale: Atomic tools are more predictable and
|
|
25
26
|
* the LLM can combine them as needed.
|
|
26
|
-
*
|
|
27
|
-
* 5. Performance: Must complete in under 50ms.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
*
|
|
28
|
+
* 5. Performance: Must complete in under 50ms. HiveDB (tantivy) queries are
|
|
29
|
+
* sub-millisecond for small tool catalogs (<100 tools).
|
|
30
|
+
*
|
|
30
31
|
* 6. Tool categorization: Tools are categorized by semantic domain:
|
|
31
32
|
* - scheduling (cron tools)
|
|
32
|
-
* - projects (project/task management)
|
|
33
33
|
* - filesystem (file operations)
|
|
34
34
|
* - web (search/fetch)
|
|
35
35
|
* - browser (browser automation)
|
|
36
36
|
* - memory (notes, memory operations)
|
|
37
37
|
* - code (exec, terminal)
|
|
38
|
-
* -
|
|
38
|
+
* - a2ui (interactive panel rendering)
|
|
39
39
|
* - agents (agent creation/management)
|
|
40
40
|
* - core (notify, report_progress, save_note)
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import
|
|
43
|
+
import { col } from "../storage/hive"
|
|
44
|
+
import type { ToolDoc } from "../storage/collections"
|
|
45
|
+
import { logger } from "../utils/logger"
|
|
46
|
+
import {
|
|
47
|
+
searchCapabilities,
|
|
48
|
+
applyRelativeCutoff,
|
|
49
|
+
replaceCapabilityDocs,
|
|
50
|
+
type CapabilityDoc,
|
|
51
|
+
} from "./capability-search"
|
|
52
|
+
import { isCalendarOperation } from "./routing-intent"
|
|
46
53
|
|
|
47
54
|
const log = logger.child("tool-selector")
|
|
48
55
|
|
|
@@ -75,18 +82,13 @@ export interface ToolSelectorResult {
|
|
|
75
82
|
const MAX_TOOLS_PER_TURN = 12
|
|
76
83
|
|
|
77
84
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* - Score of -5 is MORE relevant than -20
|
|
82
|
-
* - We use -30 as threshold to filter noise while allowing valid matches
|
|
83
|
-
*
|
|
84
|
-
* Previous values: -25 (too strict), -100 (too permissive)
|
|
85
|
-
* New value: -30 (balanced filtering, FTS5 MATCH handles the heavy lifting)
|
|
85
|
+
* Relative relevance cutoff: keep a hit only if it scores at least this
|
|
86
|
+
* fraction of the top hit. HiveDB BM25 scores are positive (higher = better)
|
|
87
|
+
* but corpus-dependent, so absolute thresholds don't transfer — a ratio does.
|
|
86
88
|
*/
|
|
87
|
-
|
|
89
|
+
const RELEVANCE_RATIO = 0.3
|
|
88
90
|
|
|
89
|
-
/** Stopwords to filter out before
|
|
91
|
+
/** Stopwords to filter out before BM25 query construction */
|
|
90
92
|
const STOPWORDS = new Set([
|
|
91
93
|
"que", "con", "para", "por", "una", "uno", "los", "las", "del",
|
|
92
94
|
"como", "esta", "esto", "ese", "eso", "the", "and", "for",
|
|
@@ -113,15 +115,15 @@ const CONVERSATIONAL_PATTERNS = [
|
|
|
113
115
|
//
|
|
114
116
|
// These 47 tools are the core toolset. Each has:
|
|
115
117
|
// - name: unique identifier
|
|
116
|
-
// - description: what the tool does (used for
|
|
118
|
+
// - description: what the tool does (used for BM25 matching)
|
|
117
119
|
// - category: semantic domain for grouping
|
|
118
120
|
// - abstractionLevel: atomic (single operation) vs orchestration (manages multiple)
|
|
119
121
|
//
|
|
120
|
-
// The descriptions are enriched with Spanish/English keywords for better
|
|
122
|
+
// The descriptions are enriched with Spanish/English keywords for better BM25 matching.
|
|
121
123
|
|
|
122
124
|
export const CORE_TOOL_CATALOG: ToolDescriptor[] = [
|
|
123
125
|
// Cron tools (cron.*)
|
|
124
|
-
{ name: "cron.create", description: "Create
|
|
126
|
+
{ name: "cron.create", description: "Create a Hive scheduled automation: recurring (cron expression) or one-shot (fire_at). Requires a task instruction. Spanish keywords: programar tarea, crear automatización, ejecutar después, tarea recurrente, recordatorio automático, una vez", category: "scheduling", abstractionLevel: "atomic" },
|
|
125
127
|
{ name: "cron.list", description: "List all cron jobs with next execution times and status. Spanish keywords: ver tareas programadas, listar cronograma, próximas ejecuciones, tareas activas, recordatorios pendientes", category: "scheduling", abstractionLevel: "atomic" },
|
|
126
128
|
{ name: "cron.update", description: "Update an existing cron job: change expression, task instruction, channel, time window, etc. Use cron.list first to get task_id. Spanish keywords: actualizar tarea, modificar cron, editar recordatorio, cambiar horario, actualizar programación", category: "scheduling", abstractionLevel: "atomic" },
|
|
127
129
|
{ name: "cron.pause", description: "Pause a cron job temporarily without deleting it. Spanish keywords: pausar tarea programada, detener temporalmente, suspender recordatorio", category: "scheduling", abstractionLevel: "atomic" },
|
|
@@ -130,25 +132,12 @@ export const CORE_TOOL_CATALOG: ToolDescriptor[] = [
|
|
|
130
132
|
{ name: "cron.trigger", description: "Manually trigger immediate execution of a cron job now. Spanish keywords: ejecutar tarea ahora, forzar ejecución, disparar manualmente", category: "scheduling", abstractionLevel: "atomic" },
|
|
131
133
|
{ name: "cron.history", description: "Get execution history and run logs for a cron job. Spanish keywords: historial ejecuciones, logs tarea, cuándo corrió, registro de ejecuciones", category: "scheduling", abstractionLevel: "atomic" },
|
|
132
134
|
|
|
133
|
-
// Project management tools (high-level orchestration)
|
|
134
|
-
{ name: "project_create", description: "Create project with tasks, start new project for complex multi-step work. Spanish keywords: crear proyecto, nuevo proyecto, iniciar trabajo, proyecto nuevo, comenzar proyecto", category: "projects", abstractionLevel: "orchestration" },
|
|
135
|
-
{ name: "project_list", description: "List all projects with their status. Spanish keywords: listar proyectos, ver proyectos, historial proyectos, todos los proyectos", category: "projects", abstractionLevel: "atomic" },
|
|
136
|
-
{ name: "project_update", description: "Update project progress, mark progress percentage and status changes. Spanish keywords: actualizar progreso, marcar avance, estado del proyecto, porcentaje completado", category: "projects", abstractionLevel: "atomic" },
|
|
137
|
-
{ name: "project_done", description: "Mark project complete, close finished projects and archive results. Spanish keywords: proyecto terminado, cerrar proyecto, finalizar, proyecto completado, marcar como hecho", category: "projects", abstractionLevel: "atomic" },
|
|
138
|
-
{ name: "project_fail", description: "Mark project failed, record failure reason and lessons learned. Spanish keywords: proyecto fallido, error, marcar como fallido, proyecto fracasado, fracaso", category: "projects", abstractionLevel: "atomic" },
|
|
139
|
-
|
|
140
|
-
// Task management (atomic)
|
|
141
|
-
{ name: "task_create", description: "Add task to project, create subtasks and action items within projects. Spanish keywords: crear tarea, nueva tarea, agregar pendiente, agregar tarea, crear subtarea", category: "projects", abstractionLevel: "atomic" },
|
|
142
|
-
{ name: "task_update", description: "Update task status, mark tasks as complete or in progress. Spanish keywords: actualizar tarea, cambiar estado, marcar completa, tarea completada, tarea en progreso", category: "projects", abstractionLevel: "atomic" },
|
|
143
|
-
{ name: "task_evaluate", description: "Evaluate task result against acceptance criteria. Spanish keywords: evaluar tarea, validar resultado, criterios aceptación, verificar calidad", category: "projects", abstractionLevel: "atomic" },
|
|
144
|
-
|
|
145
135
|
// Code execution
|
|
146
136
|
{ name: "cli_exec", description: "Execute shell commands, run bash scripts and system commands. Spanish keywords: ejecutar comando, terminal, línea de comandos, bash, script, comando del sistema", category: "cli", abstractionLevel: "atomic" },
|
|
147
137
|
|
|
148
138
|
// Web tools
|
|
149
139
|
{ name: "web_search", description: "Search web for current information, find up-to-date news facts and research. Spanish keywords: buscar en internet, buscar web, información, noticias, investigación, buscar", category: "web", abstractionLevel: "atomic" },
|
|
150
140
|
{ name: "web_fetch", description: "Fetch content from URL, download and extract content from web pages. Spanish keywords: obtener página, descargar web, extraer contenido, obtener contenido, página web", category: "web", abstractionLevel: "atomic" },
|
|
151
|
-
{ name: "api_request", description: "Connect to REST APIs, make HTTP requests with authentication and custom headers. Spanish keywords: conectar api, peticion http, llamada api, rest api, endpoint, bearer token, api key, basic auth", category: "web", abstractionLevel: "atomic" },
|
|
152
141
|
|
|
153
142
|
// Memory tools
|
|
154
143
|
{ name: "memory_write", description: "Store in long-term memory, save information to persistent memory for later retrieval. Spanish keywords: guardar memoria, guardar información, recordar, guardar dato, memoria", category: "memory", abstractionLevel: "atomic" },
|
|
@@ -158,8 +147,8 @@ export const CORE_TOOL_CATALOG: ToolDescriptor[] = [
|
|
|
158
147
|
{ name: "memory_delete", description: "Delete memory entry, remove saved memory from long-term storage. Spanish keywords: borrar memoria, eliminar información guardada, borrar dato, eliminar memoria", category: "memory", abstractionLevel: "atomic" },
|
|
159
148
|
|
|
160
149
|
// Agent/worker management
|
|
161
|
-
{ name: "agent_create", description: "Create specialized worker
|
|
162
|
-
{ name: "agent_find", description: "
|
|
150
|
+
{ name: "agent_create", description: "Create a specialized worker, including one persistent MCP server after user confirmation. Spanish keywords: crear agente, nuevo agente, trabajador, crear worker, especialista MCP", category: "agents", abstractionLevel: "orchestration" },
|
|
151
|
+
{ name: "agent_find", description: "Discover available system catalog agents and user-owned workers. Not an execution monitor. Spanish keywords: buscar agente, encontrar trabajador, localizar, buscar worker, encontrar agente", category: "agents", abstractionLevel: "atomic" },
|
|
163
152
|
{ name: "agent_archive", description: "Archive unnecessary worker, terminate and archive idle or completed agents. Spanish keywords: archivar agente, terminar agente, borrar trabajador, desactivar agente", category: "agents", abstractionLevel: "atomic" },
|
|
164
153
|
|
|
165
154
|
// Notes/persistence
|
|
@@ -178,29 +167,11 @@ export const CORE_TOOL_CATALOG: ToolDescriptor[] = [
|
|
|
178
167
|
{ name: "browser_script", description: "Execute arbitrary JavaScript in the browser page context and get the result. Spanish keywords: ejecutar javascript, script, código, función, evaluar, js en página", category: "browser", abstractionLevel: "atomic" },
|
|
179
168
|
{ name: "browser_wait", description: "Wait for an element to appear or condition to be met on the page. Spanish keywords: esperar, wait, condición, elemento, selector, aguardar carga", category: "browser", abstractionLevel: "atomic" },
|
|
180
169
|
|
|
181
|
-
// Canvas/UI rendering tools
|
|
182
|
-
{ name: "canvas_render", description: "Render component on canvas, display UI components and data visualizations. Spanish keywords: renderizar, mostrar en canvas, visualizar, mostrar componente, dibujar", category: "canvas", abstractionLevel: "atomic" },
|
|
183
|
-
{ name: "canvas_ask", description: "Display form and wait for response, show interactive form and collect user input. Spanish keywords: mostrar formulario, pedir datos, solicitar información, formulario interactivo", category: "canvas", abstractionLevel: "atomic" },
|
|
184
|
-
{ name: "canvas_clear", description: "Clear canvas for session, reset canvas display and start fresh. Spanish keywords: limpiar canvas, borrar pantalla, reiniciar, limpiar, borrar", category: "canvas", abstractionLevel: "atomic" },
|
|
185
|
-
{ name: "canvas_show_card", description: "Display card with labeled items, show structured data in card format. Spanish keywords: mostrar tarjeta, visualizar datos, tarjeta de información, mostrar datos", category: "canvas", abstractionLevel: "atomic" },
|
|
186
|
-
{ name: "canvas_show_progress", description: "Display progress bars, show progress indicators and completion status. Spanish keywords: mostrar progreso, barra de progreso, indicador de progreso, avance", category: "canvas", abstractionLevel: "atomic" },
|
|
187
|
-
{ name: "canvas_show_list", description: "Display key-value list, show information in structured list format. Spanish keywords: mostrar lista, listar elementos, lista de valores, mostrar elementos", category: "canvas", abstractionLevel: "atomic" },
|
|
188
|
-
{ name: "canvas_confirm", description: "Show confirmation dialog, request user confirmation for actions. Spanish keywords: confirmar, diálogo de confirmación, confirmar acción, validación", category: "canvas", abstractionLevel: "atomic" },
|
|
189
|
-
|
|
190
170
|
// A2UI v0.9 rich interactive surfaces
|
|
191
171
|
{ name: "a2ui_create_surface", description: "Create A2UI v0.9 surface for rich interactive UIs with forms, dashboards, and workflows. Spanish keywords: crear superficie A2UI, iniciar UI interactiva, crear formulario rico, interfaz A2UI, crear surface", category: "a2ui", abstractionLevel: "orchestration" },
|
|
192
172
|
{ name: "a2ui_update_components", description: "Send A2UI v0.9 components to an existing surface (Text, Button, TextField, Row, Column, Card, etc.). Spanish keywords: enviar componentes A2UI, actualizar UI, renderizar componentes, A2UI componentes, update components", category: "a2ui", abstractionLevel: "atomic" },
|
|
193
173
|
{ name: "a2ui_update_data_model", description: "Update A2UI v0.9 surface data model with JSON Pointer for dynamic data binding. Spanish keywords: actualizar datos A2UI, poblar formulario, cambiar valores, data model A2UI, actualizar modelo de datos", category: "a2ui", abstractionLevel: "atomic" },
|
|
194
|
-
{ name: "a2ui_delete_surface", description: "Delete A2UI v0.9 surface
|
|
195
|
-
|
|
196
|
-
// CodeBridge (subagent process management)
|
|
197
|
-
{ name: "codebridge_launch", description: "Launch subagent process, spawn new code bridge agent process. Spanish keywords: lanzar proceso, iniciar subagente, ejecutar código, nuevo proceso", category: "code", abstractionLevel: "orchestration" },
|
|
198
|
-
{ name: "codebridge_status", description: "Get status of running subagents, check code bridge agent status. Spanish keywords: estado del proceso, verificar subagente, estado del worker, estado", category: "code", abstractionLevel: "atomic" },
|
|
199
|
-
{ name: "codebridge_cancel", description: "Cancel running subagent, terminate code bridge agent process. Spanish keywords: cancelar proceso, terminar subagente, detener proceso, parar", category: "code", abstractionLevel: "atomic" },
|
|
200
|
-
|
|
201
|
-
// Voice tools
|
|
202
|
-
{ name: "voice_transcribe", description: "Transcribe audio to text, convert speech to written text from audio files. Spanish keywords: transcribir audio, voz a texto, convertir audio, transcripción", category: "voice", abstractionLevel: "atomic" },
|
|
203
|
-
{ name: "voice_speak", description: "Convert text to audio and play, synthesize speech from text. Spanish keywords: hablar, sintetizar voz, texto a voz, reproducir audio, voz", category: "voice", abstractionLevel: "atomic" },
|
|
174
|
+
{ name: "a2ui_delete_surface", description: "Delete A2UI v0.9 surface from the user's interactive panel. Spanish keywords: eliminar superficie A2UI, borrar UI, limpiar superficie A2UI, cerrar formulario, delete surface", category: "a2ui", abstractionLevel: "atomic" },
|
|
204
175
|
|
|
205
176
|
// Filesystem tools
|
|
206
177
|
{ name: "fs_read", description: "Read file content from workspace. Spanish keywords: leer archivo, ver contenido, abrir archivo, leer fichero, mostrar archivo", category: "filesystem", abstractionLevel: "atomic" },
|
|
@@ -213,11 +184,35 @@ export const CORE_TOOL_CATALOG: ToolDescriptor[] = [
|
|
|
213
184
|
|
|
214
185
|
// Agent delegation and communication
|
|
215
186
|
{ name: "task_delegate", description: "Delegate general task to worker agent. Spanish keywords: delegar tarea, asignar worker, ejecutar por agente, encomendar tarea", category: "agents", abstractionLevel: "orchestration" },
|
|
216
|
-
{ name: "
|
|
187
|
+
{ name: "task_revise", description: "Send a delegated task back to its worker with feedback when it does not meet its acceptance criteria. Spanish keywords: corregir tarea, devolver al worker, pedir correccion, reencolar tarea", category: "agents", abstractionLevel: "orchestration" },
|
|
188
|
+
{ name: "task_list", description: "List real delegated task executions for the current user from persisted tasks and jobs. Spanish keywords: listar tareas activas, subagentes trabajando, ejecuciones reales", category: "agents", abstractionLevel: "atomic" },
|
|
217
189
|
{ name: "task_status", description: "Get execution status of delegated tasks. Spanish keywords: estado tarea delegada, verificar progreso, consultar tarea, progreso delegado", category: "agents", abstractionLevel: "atomic" },
|
|
218
190
|
{ name: "bus_publish", description: "Publish message to Agent Bus for worker-to-worker communication. Spanish keywords: publicar mensaje, comunicar workers, enviar bus, mensaje bus", category: "agents", abstractionLevel: "atomic" },
|
|
219
191
|
{ name: "bus_read", description: "Read unread messages from Agent Bus. Spanish keywords: leer mensajes bus, recibir mensajes, verificar bus, mensajes workers", category: "agents", abstractionLevel: "atomic" },
|
|
220
|
-
|
|
192
|
+
|
|
193
|
+
// Model discovery
|
|
194
|
+
{ name: "get_available_models", description: "List configured providers and models with their capabilities and context windows. Spanish keywords: modelos disponibles, proveedores activos, qué modelos hay, listar modelos", category: "agents", abstractionLevel: "atomic" },
|
|
195
|
+
|
|
196
|
+
// Capability discovery
|
|
197
|
+
{ name: "search_knowledge", description: "Search everything Hive knows: native tools, MCP tools, skills, catalog agents and playbook rules. Spanish keywords: buscar herramienta, descubrir capacidades, qué puedo hacer, buscar skill, buscar conocimiento", category: "core", abstractionLevel: "atomic" },
|
|
198
|
+
|
|
199
|
+
// HTTP / REST
|
|
200
|
+
{ name: "api_request", description: "Perform an authorized HTTP request against a REST endpoint and validate the response. Spanish keywords: llamar api, request rest, consumir endpoint, petición http, hacer get, hacer post", category: "api", abstractionLevel: "atomic" },
|
|
201
|
+
|
|
202
|
+
// Artifacts
|
|
203
|
+
{ name: "artifact_inspect", description: "Inspect a managed artifact's integrity and metadata without modifying it. Spanish keywords: inspeccionar artefacto, verificar archivo generado, metadatos artefacto, comprobar entrega", category: "web", abstractionLevel: "atomic" },
|
|
204
|
+
|
|
205
|
+
// Office documents — read
|
|
206
|
+
{ name: "office_leer_pdf", description: "Read and extract text from a PDF document. Spanish keywords: leer pdf, extraer texto pdf, abrir pdf, contenido pdf", category: "office", abstractionLevel: "atomic" },
|
|
207
|
+
{ name: "office_leer_docx", description: "Read and extract text from a Word document. Spanish keywords: leer word, leer docx, abrir documento word, contenido word", category: "office", abstractionLevel: "atomic" },
|
|
208
|
+
{ name: "office_leer_xlsx", description: "Read rows and sheets from an Excel spreadsheet. Spanish keywords: leer excel, leer xlsx, abrir hoja de cálculo, contenido excel, leer planilla", category: "office", abstractionLevel: "atomic" },
|
|
209
|
+
{ name: "office_leer_pptx", description: "Read slides and text from a PowerPoint presentation. Spanish keywords: leer powerpoint, leer pptx, abrir presentación, contenido diapositivas", category: "office", abstractionLevel: "atomic" },
|
|
210
|
+
|
|
211
|
+
// Office documents — write
|
|
212
|
+
{ name: "office_escribir_pdf", description: "Generate a PDF document. Spanish keywords: crear pdf, generar pdf, escribir pdf, exportar a pdf", category: "office", abstractionLevel: "atomic" },
|
|
213
|
+
{ name: "office_escribir_docx", description: "Generate a Word document. Spanish keywords: crear word, generar docx, escribir documento word, exportar a word", category: "office", abstractionLevel: "atomic" },
|
|
214
|
+
{ name: "office_escribir_xlsx", description: "Generate an Excel spreadsheet. Spanish keywords: crear excel, generar xlsx, escribir hoja de cálculo, exportar a excel, armar planilla", category: "office", abstractionLevel: "atomic" },
|
|
215
|
+
{ name: "office_escribir_pptx", description: "Generate a PowerPoint presentation. Spanish keywords: crear powerpoint, generar pptx, escribir presentación, armar diapositivas", category: "office", abstractionLevel: "atomic" },
|
|
221
216
|
]
|
|
222
217
|
|
|
223
218
|
// ─── Helper Functions ───────────────────────────────────────────────────────-
|
|
@@ -254,27 +249,6 @@ function isConversational(message: string): boolean {
|
|
|
254
249
|
return false
|
|
255
250
|
}
|
|
256
251
|
|
|
257
|
-
/**
|
|
258
|
-
* Build FTS5 query from user message
|
|
259
|
-
*
|
|
260
|
-
* Strips stopwords, special characters, and limits to 8 keywords.
|
|
261
|
-
* Uses OR operator for flexible matching.
|
|
262
|
-
*/
|
|
263
|
-
function buildFTSQuery(message: string): string {
|
|
264
|
-
log.info(`[tool-selector] Building FTS query from message: "${message}"`)
|
|
265
|
-
const words = message
|
|
266
|
-
.toLowerCase()
|
|
267
|
-
.replace(/[^\p{L}\p{N}\s]/gu, " ")
|
|
268
|
-
.split(/\s+/)
|
|
269
|
-
.filter((w) => w.length > 2 && !STOPWORDS.has(w))
|
|
270
|
-
.slice(0, 8)
|
|
271
|
-
|
|
272
|
-
if (words.length === 0) return ""
|
|
273
|
-
|
|
274
|
-
// Use prefix matching for better recall (e.g., "gener*" matches "generar", "generando", "generación")
|
|
275
|
-
return words.map(w => `${w}*`).join(" OR ")
|
|
276
|
-
}
|
|
277
|
-
|
|
278
252
|
/**
|
|
279
253
|
* Determine abstraction level preference
|
|
280
254
|
*
|
|
@@ -289,19 +263,19 @@ function getAbstractionPreference(): "atomic" | "orchestration" {
|
|
|
289
263
|
// ─── Main Selection Function ─────────────────────────────────────────────────
|
|
290
264
|
|
|
291
265
|
/**
|
|
292
|
-
* Select tools for a given user message using
|
|
293
|
-
*
|
|
266
|
+
* Select tools for a given user message using HiveDB BM25 scoring
|
|
267
|
+
*
|
|
294
268
|
* @param userMessage - The raw user message
|
|
295
269
|
* @param fullToolList - Full list of available tools (for validation/filtering)
|
|
296
|
-
* @returns Array of
|
|
297
|
-
*
|
|
270
|
+
* @returns Array of selected tools
|
|
271
|
+
*
|
|
298
272
|
* ALGORITHM:
|
|
299
273
|
* 1. If conversational → return []
|
|
300
|
-
* 2.
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
274
|
+
* 2. Query the HiveDB capability index with the raw message (the engine
|
|
275
|
+
* handles Spanish stemming, accent folding and malformed input)
|
|
276
|
+
* 3. Keep hits scoring at least RELEVANCE_RATIO of the top hit
|
|
277
|
+
* 4. If ambiguous → prefer atomic over orchestration
|
|
278
|
+
* 5. Return top maxTools results (default: MAX_TOOLS_PER_TURN)
|
|
305
279
|
*/
|
|
306
280
|
export async function selectTools(
|
|
307
281
|
userMessage: string,
|
|
@@ -319,41 +293,64 @@ export async function selectTools(
|
|
|
319
293
|
return []
|
|
320
294
|
}
|
|
321
295
|
|
|
322
|
-
// Step 2:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
296
|
+
// Step 2: Query the capability index with the raw message.
|
|
297
|
+
// Get more initially (maxTools * 2) for filtering, then limit to maxTools.
|
|
298
|
+
let hits
|
|
299
|
+
try {
|
|
300
|
+
hits = await searchCapabilities(userMessage, {
|
|
301
|
+
types: ["tool"],
|
|
302
|
+
k: maxTools * 2,
|
|
303
|
+
})
|
|
304
|
+
} catch (err) {
|
|
305
|
+
log.error(`[tool-selector] Capability search failed:`, err)
|
|
326
306
|
return []
|
|
327
307
|
}
|
|
328
308
|
|
|
329
|
-
log.debug(`[tool-selector] Search query: "${searchQuery}"`)
|
|
330
|
-
|
|
331
|
-
// Step 3: Execute hybrid search over the HiveDB semantic index
|
|
332
|
-
const db = await getHiveDB()
|
|
333
|
-
|
|
334
|
-
// HiveDB text-only BM25 returns positive scores where higher is better.
|
|
335
|
-
const hits = await db.queryHybrid({
|
|
336
|
-
text: searchQuery,
|
|
337
|
-
k: maxTools * 2,
|
|
338
|
-
boosts: { name: 5.0, body: 3.0, tags: 1.0 },
|
|
339
|
-
})
|
|
340
|
-
|
|
341
309
|
if (hits.length === 0) {
|
|
342
|
-
log.debug(`[tool-selector] No
|
|
310
|
+
log.debug(`[tool-selector] No matches, returning empty array`)
|
|
343
311
|
return []
|
|
344
312
|
}
|
|
345
313
|
|
|
346
314
|
// Log raw scores for debugging
|
|
347
|
-
log.info(`[tool-selector] Raw scores: ${hits.slice(0, 10).map(
|
|
315
|
+
log.info(`[tool-selector] Raw scores: ${hits.slice(0, 10).map(h => `${h.rawId}=${h.score.toFixed(2)}`).join(", ")}`)
|
|
316
|
+
|
|
317
|
+
// Step 3: Keep only hits close enough to the best match
|
|
318
|
+
const relevantHits = applyRelativeCutoff(hits, RELEVANCE_RATIO)
|
|
319
|
+
if (relevantHits.length === 0) {
|
|
320
|
+
log.debug(`[tool-selector] All results below ratio cutoff, returning empty`)
|
|
321
|
+
return []
|
|
322
|
+
}
|
|
348
323
|
|
|
349
|
-
// Step 4: Map to tool descriptors with additional metadata
|
|
324
|
+
// Step 4: Map to tool descriptors with additional metadata.
|
|
325
|
+
//
|
|
326
|
+
// El mapa tiene que cubrir lo mismo que se indexó, o el hit se descarta en
|
|
327
|
+
// silencio. `syncToolCatalogToIndex` indexa CORE_TOOL_CATALOG **más** las
|
|
328
|
+
// filas de la colección `tools`; resolver sólo contra `fullToolList` (que
|
|
329
|
+
// por defecto es CORE_TOOL_CATALOG) hacía que una tool registrada en runtime
|
|
330
|
+
// —las que la app declara con `defineTool`— puntuara primero en BM25 y aun
|
|
331
|
+
// así nunca se le ofreciera al modelo.
|
|
350
332
|
const toolMap = new Map(fullToolList.map(t => [t.name, t]))
|
|
333
|
+
const unresolved = relevantHits.filter(h => !toolMap.has(h.rawId))
|
|
334
|
+
if (unresolved.length > 0) {
|
|
335
|
+
const toolsCol = await col<ToolDoc>("tools")
|
|
336
|
+
for (const hit of unresolved) {
|
|
337
|
+
const entry = await toolsCol.get(hit.rawId)
|
|
338
|
+
if (!entry?.doc.enabled || !entry.doc.active) continue
|
|
339
|
+
toolMap.set(entry.doc.name, {
|
|
340
|
+
name: entry.doc.name,
|
|
341
|
+
description: entry.doc.description ?? entry.doc.name,
|
|
342
|
+
category: (entry.doc.category ?? "core") as any,
|
|
343
|
+
abstractionLevel: "atomic",
|
|
344
|
+
})
|
|
345
|
+
}
|
|
346
|
+
}
|
|
351
347
|
|
|
352
|
-
const
|
|
348
|
+
const calendarOperation = isCalendarOperation(userMessage)
|
|
353
349
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
350
|
+
const scoredTools: SelectedTool[] = []
|
|
351
|
+
for (const hit of relevantHits) {
|
|
352
|
+
const tool = toolMap.get(hit.rawId)
|
|
353
|
+
if (tool && !(calendarOperation && tool.category === "scheduling")) {
|
|
357
354
|
scoredTools.push({
|
|
358
355
|
name: tool.name,
|
|
359
356
|
score: hit.score,
|
|
@@ -366,11 +363,12 @@ export async function selectTools(
|
|
|
366
363
|
const abstractionPref = getAbstractionPreference()
|
|
367
364
|
|
|
368
365
|
if (scoredTools.length > MAX_TOOLS_PER_TURN) {
|
|
369
|
-
// Sort by score descending (higher HiveDB score = more relevant)
|
|
370
366
|
scoredTools.sort((a, b) => {
|
|
367
|
+
// First by score (descending: HiveDB scores are positive, higher = better)
|
|
371
368
|
if (Math.abs(a.score - b.score) > 0.1) {
|
|
372
369
|
return b.score - a.score
|
|
373
370
|
}
|
|
371
|
+
// Then by abstraction preference (preferred type first)
|
|
374
372
|
const aTool = toolMap.get(a.name)
|
|
375
373
|
const bTool = toolMap.get(b.name)
|
|
376
374
|
const aLevel = aTool?.abstractionLevel ?? "atomic"
|
|
@@ -392,6 +390,7 @@ export async function selectTools(
|
|
|
392
390
|
|
|
393
391
|
const timing = performance.now() - startTime
|
|
394
392
|
|
|
393
|
+
// Log final selected tools with info level (important for tracking tool selection process)
|
|
395
394
|
if (result.length > 0) {
|
|
396
395
|
log.info(`[tool-selector] Selected ${result.length} tools in ${timing.toFixed(2)}ms:`,
|
|
397
396
|
result.map(t => ({ name: t.name, category: t.category })))
|
|
@@ -402,41 +401,52 @@ export async function selectTools(
|
|
|
402
401
|
return result
|
|
403
402
|
}
|
|
404
403
|
|
|
405
|
-
// ─── Sync Tools to
|
|
404
|
+
// ─── Sync Tools to HiveDB ────────────────────────────────────────────────────
|
|
406
405
|
|
|
407
406
|
/**
|
|
408
|
-
* Sync tool catalog to
|
|
407
|
+
* Sync tool catalog to the HiveDB capability index.
|
|
409
408
|
*
|
|
410
|
-
* Called on initialization from gateway/initializer.ts to populate the
|
|
411
|
-
*
|
|
412
|
-
* Descriptions are enriched with bilingual keywords
|
|
409
|
+
* Called on initialization from gateway/initializer.ts to populate the index.
|
|
410
|
+
* Replaces all `type=tool` documents atomically (delete-by-filter + one
|
|
411
|
+
* batch commit). Descriptions are enriched with bilingual keywords.
|
|
413
412
|
*
|
|
414
413
|
* @param tools - Optional array of tools to sync. If not provided, fetches from DB.
|
|
415
414
|
*/
|
|
416
|
-
export async function
|
|
417
|
-
const db = await getHiveDB()
|
|
418
|
-
|
|
415
|
+
export async function syncToolCatalogToIndex(tools?: ToolDescriptor[]): Promise<void> {
|
|
419
416
|
try {
|
|
420
|
-
// Step 1: Build full catalog = CORE_TOOL_CATALOG + any
|
|
417
|
+
// Step 1: Build full catalog = CORE_TOOL_CATALOG + any tools in DB not already covered
|
|
418
|
+
// CORE_TOOL_CATALOG has bilingual keywords; DB tools may be dynamically registered
|
|
421
419
|
const catalogByName = new Map<string, ToolDescriptor>(
|
|
422
420
|
CORE_TOOL_CATALOG.map(t => [t.name, t])
|
|
423
421
|
)
|
|
424
422
|
|
|
425
|
-
// Merge in any tools
|
|
426
|
-
const toolsCol =
|
|
427
|
-
const dbTools = await toolsCol.scan()
|
|
428
|
-
for (const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
423
|
+
// Merge in any tools from the DB that are missing from the static catalog
|
|
424
|
+
const toolsCol = await col<ToolDoc>("tools")
|
|
425
|
+
const dbTools = (await toolsCol.scan({})).map(e => e.doc)
|
|
426
|
+
for (const row of dbTools) {
|
|
427
|
+
if (catalogByName.has(row.name)) continue
|
|
428
|
+
|
|
429
|
+
// Check if this is a legacy name with different separator
|
|
430
|
+
// (e.g. "cron_create" vs "cron.create" — seed was wrong, tools use dots)
|
|
431
|
+
const altName = row.name.includes("_")
|
|
432
|
+
? row.name.replace(/_/g, ".")
|
|
433
|
+
: row.name.includes(".")
|
|
434
|
+
? row.name.replace(/\./g, "_")
|
|
435
|
+
: ""
|
|
436
|
+
if (altName && catalogByName.has(altName)) {
|
|
437
|
+
log.info(`[tool-selector] Skipping legacy tool name "${row.name}" — canonical "${altName}" already in catalog`)
|
|
438
|
+
continue
|
|
437
439
|
}
|
|
440
|
+
|
|
441
|
+
catalogByName.set(row.name, {
|
|
442
|
+
name: row.name,
|
|
443
|
+
description: row.description ?? row.name,
|
|
444
|
+
category: (row.category ?? "core") as any,
|
|
445
|
+
abstractionLevel: "atomic",
|
|
446
|
+
})
|
|
438
447
|
}
|
|
439
448
|
|
|
449
|
+
// Also merge any explicitly passed tools (e.g. from initializer)
|
|
440
450
|
for (const t of (tools || [])) {
|
|
441
451
|
if (!catalogByName.has(t.name)) {
|
|
442
452
|
catalogByName.set(t.name, t)
|
|
@@ -445,44 +455,41 @@ export async function syncToolCatalogToFTS(tools?: ToolDescriptor[]): Promise<vo
|
|
|
445
455
|
|
|
446
456
|
const toolCatalog = Array.from(catalogByName.values())
|
|
447
457
|
|
|
448
|
-
// Step 2:
|
|
449
|
-
const docs:
|
|
450
|
-
|
|
458
|
+
// Step 2: Replace all tool documents in the HiveDB capability index
|
|
459
|
+
const docs: CapabilityDoc[] = toolCatalog.map(tool => ({
|
|
460
|
+
type: "tool" as const,
|
|
461
|
+
rawId: tool.name,
|
|
451
462
|
name: tool.name,
|
|
452
463
|
body: enrichToolDescription(tool),
|
|
453
464
|
tags: tool.category,
|
|
454
|
-
filters: [{ field: "type", value: "tool" }],
|
|
455
465
|
}))
|
|
456
466
|
|
|
457
|
-
await
|
|
458
|
-
await db.upsertBatch(docs)
|
|
467
|
+
await replaceCapabilityDocs("tool", docs)
|
|
459
468
|
|
|
460
|
-
log.info(`[tool-selector]
|
|
469
|
+
log.info(`[tool-selector] Sync complete: ${toolCatalog.length} tools indexed in HiveDB`)
|
|
461
470
|
|
|
462
471
|
} catch (err) {
|
|
463
|
-
log.error(`[tool-selector]
|
|
464
|
-
throw err
|
|
472
|
+
log.error(`[tool-selector] Tool index sync failed:`, err)
|
|
473
|
+
throw err // Re-throw to inform initializer
|
|
465
474
|
}
|
|
466
475
|
}
|
|
467
476
|
|
|
468
477
|
/**
|
|
469
478
|
* Enrich tool description with category-specific keywords
|
|
470
479
|
*
|
|
471
|
-
* This improves
|
|
480
|
+
* This improves BM25 matching for both English and Spanish queries.
|
|
472
481
|
*/
|
|
473
|
-
|
|
482
|
+
function enrichToolDescription(tool: ToolDescriptor): string {
|
|
474
483
|
const keywordsByCategory: Record<string, string> = {
|
|
475
484
|
scheduling: "programar recordatorio alarma cron schedule reminder task future tiempo",
|
|
476
|
-
projects: "proyecto tarea plan organizer milestone backlog sprint work",
|
|
477
485
|
filesystem: "archivo file leer escribir editar documento content source code",
|
|
478
486
|
web: "buscar internet google web search find information news research",
|
|
479
487
|
browser: "navegador browser click screenshot form automation web page UI",
|
|
480
488
|
memory: "recordar nota guardar memory store remember persist knowledge",
|
|
481
489
|
code: "code ejecutar run script bash shell terminal command devops",
|
|
482
|
-
|
|
483
|
-
agents: "agente worker
|
|
490
|
+
a2ui: "A2UI interactive panel interface form dashboard visualization",
|
|
491
|
+
agents: "agente worker catalog create delegate hire team manager",
|
|
484
492
|
core: "notificar message alert notify communicate progress status",
|
|
485
|
-
voice: "voz audio transcribir speech speak sintetizar audio voice transcription",
|
|
486
493
|
}
|
|
487
494
|
|
|
488
495
|
const extra = keywordsByCategory[tool.category] ?? ""
|
|
@@ -497,25 +504,28 @@ export function enrichToolDescription(tool: ToolDescriptor): string {
|
|
|
497
504
|
* Gemini (and OpenAI) require: start with letter/underscore, only [a-zA-Z0-9_.-:], max 64 chars.
|
|
498
505
|
* Server names from the UI can contain spaces and special chars (e.g. "X antes twiter").
|
|
499
506
|
*
|
|
500
|
-
* Canonical format: `{safeServer}__{safeTool}` (double underscore as separator)
|
|
507
|
+
* Canonical format: `{safeServer}__{safeTool}` (double underscore as separator).
|
|
508
|
+
* The server prefix exists only to disambiguate tools with the same name
|
|
509
|
+
* across servers — when the 64-char budget is exceeded, the SERVER part is
|
|
510
|
+
* shortened first so the distinctive tool name survives intact (long server
|
|
511
|
+
* names must never truncate the tool name).
|
|
501
512
|
*/
|
|
502
513
|
export function mcpToolFullName(serverName: string, toolName: string): string {
|
|
503
|
-
const
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
const trimmed = full.length > 64 ? full.substring(0, 64) : full
|
|
507
|
-
return /^[a-zA-Z_]/.test(trimmed) ? trimmed : `_${trimmed}`.substring(0, 64)
|
|
508
|
-
}
|
|
514
|
+
const MAX = 64
|
|
515
|
+
const MIN_SERVER = 8
|
|
516
|
+
const safe = (s: string) => s.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_\-]/g, '_')
|
|
509
517
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
518
|
+
let server = safe(serverName)
|
|
519
|
+
const tool = safe(toolName)
|
|
520
|
+
|
|
521
|
+
const room = MAX - 2 - tool.length
|
|
522
|
+
if (server.length > room) {
|
|
523
|
+
server = server.substring(0, Math.max(room, MIN_SERVER))
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
let full = `${server}__${tool}`
|
|
527
|
+
if (full.length > MAX) full = full.substring(0, MAX)
|
|
528
|
+
return /^[a-zA-Z_]/.test(full) ? full : `_${full}`.substring(0, MAX)
|
|
519
529
|
}
|
|
520
530
|
|
|
521
531
|
// ─── Debug/Test Helpers ─────────────────────────────────────────────────────
|