@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,322 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HiveDB-based Dynamic Skill Selector Module
|
|
3
|
-
*
|
|
4
|
-
* Context Compiler Level 4 - Intelligent Skill Selection
|
|
5
|
-
*
|
|
6
|
-
* Uses HiveDB hybrid search (BM25 + optional vector) over the skills index.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { getHiveDB } from "../../storage/HiveDBStorage.ts"
|
|
10
|
-
import { logger } from "../../utils/logger.ts"
|
|
11
|
-
import type { HiveSkillDoc } from "../../storage/hiveSeed.ts"
|
|
12
|
-
import type { IndexDoc } from "@johpaz/hive-db"
|
|
13
|
-
|
|
14
|
-
const log = logger.child("skill-selector")
|
|
15
|
-
|
|
16
|
-
// ─── Minimal Skill Set ─────────────────────────────────────────────────────────
|
|
17
|
-
|
|
18
|
-
export const MINIMAL_SKILL_NAMES = new Set([
|
|
19
|
-
"memory_manager",
|
|
20
|
-
"canvas_report",
|
|
21
|
-
"task_orchestrator",
|
|
22
|
-
])
|
|
23
|
-
|
|
24
|
-
// ─── Types ───────────────────────────────────────────────────────────────────────
|
|
25
|
-
|
|
26
|
-
export interface SkillDescriptor {
|
|
27
|
-
id: string
|
|
28
|
-
name: string
|
|
29
|
-
description: string
|
|
30
|
-
category: string
|
|
31
|
-
tools: string
|
|
32
|
-
triggers: string
|
|
33
|
-
preferred_agents: string
|
|
34
|
-
body: string
|
|
35
|
-
version: string
|
|
36
|
-
version_num: number
|
|
37
|
-
active: number
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface SelectedSkill {
|
|
41
|
-
id: string
|
|
42
|
-
name: string
|
|
43
|
-
score: number
|
|
44
|
-
category: string
|
|
45
|
-
description: string
|
|
46
|
-
body: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface SkillSelectorResult {
|
|
50
|
-
skills: SkillDescriptor[]
|
|
51
|
-
selected: SelectedSkill[]
|
|
52
|
-
reasoning: string
|
|
53
|
-
timingMs: number
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ─── Configuration ─────────────────────────────────────────────────────────
|
|
57
|
-
|
|
58
|
-
const MAX_SKILLS_PER_TURN = 4
|
|
59
|
-
|
|
60
|
-
const MIN_RELEVANCE_THRESHOLD = 0.5
|
|
61
|
-
|
|
62
|
-
const STOPWORDS = new Set([
|
|
63
|
-
"que", "con", "para", "por", "una", "uno", "los", "las", "del",
|
|
64
|
-
"como", "esta", "esto", "ese", "eso", "the", "and", "for",
|
|
65
|
-
"with", "this", "that", "have", "will", "also", "de", "en",
|
|
66
|
-
"el", "la", "se", "su", "sus", "al", "es", "son", "pero",
|
|
67
|
-
"más", "mas", "ya", "yo", "tu", "te", "ti", "mi", "me",
|
|
68
|
-
"hola", "hi", "hello", "hey", "gracias", "thank", "please",
|
|
69
|
-
"ok", "okay", "yes", "si", "no", "bien", "good", "great",
|
|
70
|
-
"puedes", "necesito", "quiero", "podés", "necesitás", "querés",
|
|
71
|
-
])
|
|
72
|
-
|
|
73
|
-
const CONVERSATIONAL_PATTERNS = [
|
|
74
|
-
/^(hola|hi|hello|hey|buenos? días?|buenas? noches?|qué tal|howdy)/i,
|
|
75
|
-
/^(gracias|thank you|thanks|muchas gracias|muchas thanks)/i,
|
|
76
|
-
/^(cómo estás?|how are you?|qué流水|you doing|qué cuentas)/i,
|
|
77
|
-
/^(sí|yes|ok|okay|de acuerdo|perfecto|claro|por supuesto)/i,
|
|
78
|
-
/^(adiós|bye|nos vemos|see you|later|chau)/i,
|
|
79
|
-
/^(entiendo|understand|i see|ya veo|got it)/i,
|
|
80
|
-
/^(bien|good|great|excelente|awesome|perfect)/i,
|
|
81
|
-
/^(?:\?|¿)$/,
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
// ─── Helper Functions ───────────────────────────────────────────────────────
|
|
85
|
-
|
|
86
|
-
function isConversational(message: string): boolean {
|
|
87
|
-
const trimmed = message.trim()
|
|
88
|
-
if (trimmed.length < 2) return true
|
|
89
|
-
for (const pattern of CONVERSATIONAL_PATTERNS) {
|
|
90
|
-
if (pattern.test(trimmed)) {
|
|
91
|
-
log.debug(`[skill-selector] Message matched conversational pattern: ${pattern}`)
|
|
92
|
-
return true
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
const words = trimmed.toLowerCase().split(/\s+/)
|
|
96
|
-
const meaningfulWords = words.filter(w => w.length > 2 && !STOPWORDS.has(w))
|
|
97
|
-
if (meaningfulWords.length === 0) {
|
|
98
|
-
log.debug(`[skill-selector] All words are stopwords - conversational`)
|
|
99
|
-
return true
|
|
100
|
-
}
|
|
101
|
-
return false
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function buildFTSQuery(message: string): string {
|
|
105
|
-
const words = message
|
|
106
|
-
.toLowerCase()
|
|
107
|
-
.replace(/[^\p{L}\p{N}\s]/gu, " ")
|
|
108
|
-
.split(/\s+/)
|
|
109
|
-
.filter((w) => w.length > 2 && !STOPWORDS.has(w))
|
|
110
|
-
.slice(0, 8)
|
|
111
|
-
|
|
112
|
-
if (words.length === 0) return ""
|
|
113
|
-
return words.join(" ")
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function matchTriggers(message: string, triggers: string[]): boolean {
|
|
117
|
-
if (!triggers || triggers.length === 0) return false
|
|
118
|
-
const lowerMessage = message.toLowerCase()
|
|
119
|
-
return triggers.some(trigger =>
|
|
120
|
-
lowerMessage.includes(trigger.toLowerCase())
|
|
121
|
-
)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function toSkillDescriptor(doc: HiveSkillDoc): SkillDescriptor {
|
|
125
|
-
return {
|
|
126
|
-
id: doc.id,
|
|
127
|
-
name: doc.name,
|
|
128
|
-
description: doc.description,
|
|
129
|
-
category: doc.category,
|
|
130
|
-
tools: Array.isArray(doc.tools) ? doc.tools.join(",") : String(doc.tools ?? ""),
|
|
131
|
-
triggers: Array.isArray(doc.triggers) ? doc.triggers.join(",") : String(doc.triggers ?? ""),
|
|
132
|
-
preferred_agents: Array.isArray(doc.preferredAgents) ? doc.preferredAgents.join(",") : String(doc.preferredAgents ?? ""),
|
|
133
|
-
body: doc.body,
|
|
134
|
-
version: doc.version,
|
|
135
|
-
version_num: doc.versionNum,
|
|
136
|
-
active: doc.active ? 1 : 0,
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// ─── Main Selection Function ─────────────────────────────────────────────────
|
|
141
|
-
|
|
142
|
-
export async function selectSkills(userMessage: string): Promise<SkillDescriptor[]> {
|
|
143
|
-
const startTime = performance.now()
|
|
144
|
-
|
|
145
|
-
log.debug(`[skill-selector] Processing user message: "${userMessage.substring(0, 100)}"`)
|
|
146
|
-
|
|
147
|
-
if (isConversational(userMessage)) {
|
|
148
|
-
log.debug(`[skill-selector] Conversational message, returning empty array`)
|
|
149
|
-
return []
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const db = await getHiveDB()
|
|
153
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
154
|
-
const entries = await skillsCol.scan()
|
|
155
|
-
const allSkills = entries.map(e => e.doc).filter(s => s.active)
|
|
156
|
-
|
|
157
|
-
for (const skill of allSkills) {
|
|
158
|
-
if (matchTriggers(userMessage, skill.triggers)) {
|
|
159
|
-
log.info(`[skill-selector] Trigger match found: ${skill.name}`)
|
|
160
|
-
return [toSkillDescriptor(skill)]
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const ftsQuery = buildFTSQuery(userMessage)
|
|
165
|
-
if (!ftsQuery) {
|
|
166
|
-
log.debug(`[skill-selector] No valid query terms, returning empty array`)
|
|
167
|
-
return []
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
log.debug(`[skill-selector] Search query: "${ftsQuery}"`)
|
|
171
|
-
|
|
172
|
-
const hits = await db.queryHybrid({
|
|
173
|
-
text: ftsQuery,
|
|
174
|
-
k: 20,
|
|
175
|
-
boosts: { name: 4.0, body: 5.0, tags: 3.0 },
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
if (hits.length === 0) {
|
|
179
|
-
log.debug(`[skill-selector] No index matches, returning empty array`)
|
|
180
|
-
return []
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
log.info(`[skill-selector] Raw scores: ${hits.slice(0, 10).map(r => `id=${r.id}, score=${r.score.toFixed(2)}`).join(", ")}`)
|
|
184
|
-
|
|
185
|
-
const relevantResults = hits.filter(r => r.score >= MIN_RELEVANCE_THRESHOLD)
|
|
186
|
-
if (relevantResults.length === 0) {
|
|
187
|
-
log.debug(`[skill-selector] All results below threshold ${MIN_RELEVANCE_THRESHOLD}, returning empty`)
|
|
188
|
-
return []
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const skillMap = new Map(allSkills.map(s => [s.id, s]))
|
|
192
|
-
const scoredSkills: SelectedSkill[] = []
|
|
193
|
-
|
|
194
|
-
for (const hit of relevantResults) {
|
|
195
|
-
const skill = skillMap.get(hit.id)
|
|
196
|
-
if (skill) {
|
|
197
|
-
scoredSkills.push({
|
|
198
|
-
id: skill.id,
|
|
199
|
-
name: skill.name,
|
|
200
|
-
score: hit.score,
|
|
201
|
-
category: skill.category,
|
|
202
|
-
description: skill.description || "",
|
|
203
|
-
body: skill.body,
|
|
204
|
-
})
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const topSkills = scoredSkills.slice(0, MAX_SKILLS_PER_TURN)
|
|
209
|
-
const result = topSkills.map(t => toSkillDescriptor(skillMap.get(t.id)!)).filter(Boolean)
|
|
210
|
-
|
|
211
|
-
const timing = performance.now() - startTime
|
|
212
|
-
|
|
213
|
-
if (result.length > 0) {
|
|
214
|
-
log.info(`[skill-selector] Selected ${result.length} skills in ${timing.toFixed(2)}ms:`,
|
|
215
|
-
result.map(s => ({ name: s.name, category: s.category })))
|
|
216
|
-
} else {
|
|
217
|
-
log.debug(`[skill-selector] No skills selected, returning empty array in ${timing.toFixed(2)}ms`)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return result
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ─── Minimal Skills Loader ───────────────────────────────────────────────────
|
|
224
|
-
|
|
225
|
-
export async function getMinimalSkills(): Promise<SkillDescriptor[]> {
|
|
226
|
-
try {
|
|
227
|
-
const db = await getHiveDB()
|
|
228
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
229
|
-
const entries = await skillsCol.scan()
|
|
230
|
-
const skills = entries
|
|
231
|
-
.map(e => e.doc)
|
|
232
|
-
.filter(s => s.active && MINIMAL_SKILL_NAMES.has(s.name))
|
|
233
|
-
.map(toSkillDescriptor)
|
|
234
|
-
|
|
235
|
-
log.info(`[skill-selector] Loaded ${skills.length} minimal skills: ${skills.map(s => s.name).join(", ")}`)
|
|
236
|
-
return skills
|
|
237
|
-
} catch (err) {
|
|
238
|
-
log.error(`[skill-selector] Failed to load minimal skills:`, err)
|
|
239
|
-
return []
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ─── Sync Skills to Index ───────────────────────────────────────────────────
|
|
244
|
-
|
|
245
|
-
export async function syncSkillsToFTS(): Promise<void> {
|
|
246
|
-
const db = await getHiveDB()
|
|
247
|
-
|
|
248
|
-
try {
|
|
249
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
250
|
-
const entries = await skillsCol.scan()
|
|
251
|
-
const dbSkills = entries.map(e => e.doc).filter(s => s.active)
|
|
252
|
-
|
|
253
|
-
if (dbSkills.length === 0) {
|
|
254
|
-
log.debug(`[skill-selector] No skills found in DB to sync`)
|
|
255
|
-
return
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const docs: IndexDoc[] = dbSkills.map(skill => ({
|
|
259
|
-
id: skill.id,
|
|
260
|
-
name: skill.name,
|
|
261
|
-
body: `${skill.description || ""} ${skill.body || ""}`,
|
|
262
|
-
tags: [skill.category, ...skill.tools, ...skill.triggers].join(" "),
|
|
263
|
-
filters: [{ field: "type", value: "skill" }],
|
|
264
|
-
}))
|
|
265
|
-
|
|
266
|
-
await db.upsertBatch(docs)
|
|
267
|
-
|
|
268
|
-
log.info(`[skill-selector] Atomic sync complete: ${dbSkills.length} skills indexed in HiveDB`)
|
|
269
|
-
|
|
270
|
-
} catch (err) {
|
|
271
|
-
log.error(`[skill-selector] Transactional sync failed:`, err)
|
|
272
|
-
throw err
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ─── Initialization ───────────────────────────────────────────────────────
|
|
277
|
-
|
|
278
|
-
export function initializeSkillSelector(): void {
|
|
279
|
-
log.info(`[skill-selector] Initializing skill selector (deprecated - sync is done in seed)`)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// ─── Debug/Test Helpers ─────────────────────────────────────────────────────
|
|
283
|
-
|
|
284
|
-
export async function getAllSkillsFromDB(): Promise<SkillDescriptor[]> {
|
|
285
|
-
try {
|
|
286
|
-
const db = await getHiveDB()
|
|
287
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
288
|
-
const entries = await skillsCol.scan()
|
|
289
|
-
return entries.map(e => toSkillDescriptor(e.doc)).filter(s => s.active)
|
|
290
|
-
} catch (err) {
|
|
291
|
-
log.error(`[skill-selector] Failed to fetch skills:`, err)
|
|
292
|
-
return []
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
export async function getSkillByName(name: string): Promise<SkillDescriptor | undefined> {
|
|
297
|
-
try {
|
|
298
|
-
const db = await getHiveDB()
|
|
299
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
300
|
-
const entries = await skillsCol.scan()
|
|
301
|
-
const skill = entries.map(e => e.doc).find(s => s.name === name && s.active)
|
|
302
|
-
return skill ? toSkillDescriptor(skill) : undefined
|
|
303
|
-
} catch (err) {
|
|
304
|
-
log.error(`[skill-selector] Failed to fetch skill by name:`, err)
|
|
305
|
-
return undefined
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export async function getSkillsByCategory(category: string): Promise<SkillDescriptor[]> {
|
|
310
|
-
try {
|
|
311
|
-
const db = await getHiveDB()
|
|
312
|
-
const skillsCol = db.collection<HiveSkillDoc>("skills")
|
|
313
|
-
const entries = await skillsCol.scan()
|
|
314
|
-
return entries
|
|
315
|
-
.map(e => e.doc)
|
|
316
|
-
.filter(s => s.active && s.category === category)
|
|
317
|
-
.map(toSkillDescriptor)
|
|
318
|
-
} catch (err) {
|
|
319
|
-
log.error(`[skill-selector] Failed to fetch skills by category:`, err)
|
|
320
|
-
return []
|
|
321
|
-
}
|
|
322
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export type { ToolDescriptor, SelectedTool, ToolSelectorResult } from "./ToolSelector.ts";
|
|
2
|
-
export { MIN_RELEVANCE_THRESHOLD, CORE_TOOL_CATALOG, selectTools, syncToolCatalogToFTS, mcpToolFullName, initializeToolSelector, getAllTools, getToolByName, getToolsByCategory } from "./ToolSelector.ts";
|
|
3
|
-
export type { SkillDescriptor, SelectedSkill, SkillSelectorResult } from "./SkillSelector.ts";
|
|
4
|
-
export { MINIMAL_SKILL_NAMES, selectSkills, getMinimalSkills, syncSkillsToFTS, initializeSkillSelector, getAllSkillsFromDB, getSkillByName, getSkillsByCategory } from "./SkillSelector.ts";
|
|
5
|
-
export type { PlaybookRule } from "./PlaybookSelector.ts";
|
|
6
|
-
export { selectPlaybookRules, syncPlaybookToFTS } from "./PlaybookSelector.ts";
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import jwt from "jsonwebtoken";
|
|
2
|
-
import { hashString } from "../utils/crypto.ts";
|
|
3
|
-
import { getHiveDB } from "../storage/HiveDBStorage.ts";
|
|
4
|
-
|
|
5
|
-
const JWT_SECRET = process.env.JWT_SECRET || "hive-default-jwt-secret-change-in-production";
|
|
6
|
-
const ACCESS_TOKEN_EXPIRY = "15m";
|
|
7
|
-
const REFRESH_TOKEN_EXPIRY = "7d";
|
|
8
|
-
const REFRESH_TOKEN_EXPIRY_SECONDS = 7 * 24 * 60 * 60;
|
|
9
|
-
|
|
10
|
-
interface AuthTokens {
|
|
11
|
-
accessToken: string;
|
|
12
|
-
refreshToken: string;
|
|
13
|
-
expiresIn: number;
|
|
14
|
-
tokenType: "Bearer";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface JwtPayload {
|
|
18
|
-
userId: string;
|
|
19
|
-
type: "access" | "refresh";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface RefreshTokenDoc {
|
|
23
|
-
userId: string;
|
|
24
|
-
tokenHash: string;
|
|
25
|
-
expiresAt: number;
|
|
26
|
-
revoked: boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function tokensCollection() {
|
|
30
|
-
return getHiveDB().then(db => db.collection<RefreshTokenDoc>("refresh_tokens"));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function generateTokens(userId: string): Promise<AuthTokens> {
|
|
34
|
-
const accessToken = jwt.sign({ userId, type: "access" } satisfies JwtPayload, JWT_SECRET, {
|
|
35
|
-
expiresIn: ACCESS_TOKEN_EXPIRY,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const refreshToken = jwt.sign({ userId, type: "refresh" } satisfies JwtPayload, JWT_SECRET, {
|
|
39
|
-
expiresIn: REFRESH_TOKEN_EXPIRY,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const refreshTokenHash = hashString(refreshToken);
|
|
43
|
-
const expiresAt = Math.floor(Date.now() / 1000) + REFRESH_TOKEN_EXPIRY_SECONDS;
|
|
44
|
-
|
|
45
|
-
const col = await tokensCollection();
|
|
46
|
-
await col.put(refreshTokenHash, { userId, tokenHash: refreshTokenHash, expiresAt, revoked: false });
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
accessToken,
|
|
50
|
-
refreshToken,
|
|
51
|
-
expiresIn: 15 * 60,
|
|
52
|
-
tokenType: "Bearer",
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export async function refreshAccessToken(refreshToken: string): Promise<AuthTokens> {
|
|
57
|
-
let payload: JwtPayload;
|
|
58
|
-
try {
|
|
59
|
-
payload = jwt.verify(refreshToken, JWT_SECRET) as JwtPayload;
|
|
60
|
-
} catch {
|
|
61
|
-
throw new Error("Invalid or expired refresh token");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (payload.type !== "refresh") {
|
|
65
|
-
throw new Error("Invalid token type");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const refreshTokenHash = hashString(refreshToken);
|
|
69
|
-
const col = await tokensCollection();
|
|
70
|
-
const entry = await col.get(refreshTokenHash);
|
|
71
|
-
|
|
72
|
-
if (!entry) {
|
|
73
|
-
throw new Error("Refresh token not found");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const tokenRow = entry.doc;
|
|
77
|
-
|
|
78
|
-
if (tokenRow.revoked) {
|
|
79
|
-
throw new Error("Refresh token has been revoked");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (tokenRow.expiresAt < Math.floor(Date.now() / 1000)) {
|
|
83
|
-
await col.delete(refreshTokenHash);
|
|
84
|
-
throw new Error("Refresh token has expired");
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
await col.delete(refreshTokenHash);
|
|
88
|
-
|
|
89
|
-
return generateTokens(payload.userId);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export async function validateAccessToken(token: string): Promise<{ userId: string } | null> {
|
|
93
|
-
try {
|
|
94
|
-
const payload = jwt.verify(token, JWT_SECRET) as JwtPayload;
|
|
95
|
-
if (payload.type !== "access") {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
return { userId: payload.userId };
|
|
99
|
-
} catch {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function revokeRefreshToken(refreshToken: string): Promise<void> {
|
|
105
|
-
const refreshTokenHash = hashString(refreshToken);
|
|
106
|
-
const col = await tokensCollection();
|
|
107
|
-
const entry = await col.get(refreshTokenHash);
|
|
108
|
-
if (entry) {
|
|
109
|
-
await col.put(refreshTokenHash, { ...entry.doc, revoked: true });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export async function revokeAllUserTokens(userId: string): Promise<void> {
|
|
114
|
-
const col = await tokensCollection();
|
|
115
|
-
const entries = await col.scan();
|
|
116
|
-
for (const e of entries) {
|
|
117
|
-
if (e.doc.userId === userId && !e.doc.revoked) {
|
|
118
|
-
await col.put(e.id, { ...e.doc, revoked: true });
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./auth.ts";
|