@aigentic/claude-flow 3.7.0-alpha.69
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/.claude/agents/MIGRATION_SUMMARY.md +222 -0
- package/.claude/agents/analysis/analyze-code-quality.md +58 -0
- package/.claude/agents/analysis/code-analyzer.md +189 -0
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +58 -0
- package/.claude/agents/architecture/arch-system-design.md +157 -0
- package/.claude/agents/architecture/system-design/arch-system-design.md +36 -0
- package/.claude/agents/base-template-generator.md +41 -0
- package/.claude/agents/browser/browser-agent.yaml +182 -0
- package/.claude/agents/consensus/byzantine-coordinator.md +43 -0
- package/.claude/agents/consensus/crdt-synchronizer.md +977 -0
- package/.claude/agents/consensus/gossip-coordinator.md +43 -0
- package/.claude/agents/consensus/performance-benchmarker.md +831 -0
- package/.claude/agents/consensus/quorum-manager.md +803 -0
- package/.claude/agents/consensus/raft-manager.md +43 -0
- package/.claude/agents/consensus/security-manager.md +602 -0
- package/.claude/agents/core/coder.md +255 -0
- package/.claude/agents/core/planner.md +152 -0
- package/.claude/agents/core/researcher.md +174 -0
- package/.claude/agents/core/reviewer.md +309 -0
- package/.claude/agents/core/tester.md +300 -0
- package/.claude/agents/custom/test-long-runner.md +43 -0
- package/.claude/agents/data/data-ml-model.md +445 -0
- package/.claude/agents/data/ml/data-ml-model.md +76 -0
- package/.claude/agents/database-specialist.md +9 -0
- package/.claude/agents/development/backend/dev-backend-api.md +29 -0
- package/.claude/agents/development/dev-backend-api.md +178 -0
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +52 -0
- package/.claude/agents/devops/ops-cicd-github.md +165 -0
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +63 -0
- package/.claude/agents/documentation/docs-api-openapi.md +355 -0
- package/.claude/agents/dual-mode/codex-coordinator.md +206 -0
- package/.claude/agents/dual-mode/codex-worker.md +190 -0
- package/.claude/agents/dual-mode/dual-orchestrator.md +253 -0
- package/.claude/agents/flow-nexus/app-store.md +88 -0
- package/.claude/agents/flow-nexus/authentication.md +69 -0
- package/.claude/agents/flow-nexus/challenges.md +81 -0
- package/.claude/agents/flow-nexus/neural-network.md +88 -0
- package/.claude/agents/flow-nexus/payments.md +83 -0
- package/.claude/agents/flow-nexus/sandbox.md +76 -0
- package/.claude/agents/flow-nexus/swarm.md +76 -0
- package/.claude/agents/flow-nexus/user-tools.md +96 -0
- package/.claude/agents/flow-nexus/workflow.md +84 -0
- package/.claude/agents/github/code-review-swarm.md +521 -0
- package/.claude/agents/github/github-modes.md +154 -0
- package/.claude/agents/github/issue-tracker.md +299 -0
- package/.claude/agents/github/multi-repo-swarm.md +525 -0
- package/.claude/agents/github/pr-manager.md +163 -0
- package/.claude/agents/github/project-board-sync.md +478 -0
- package/.claude/agents/github/release-manager.md +336 -0
- package/.claude/agents/github/release-swarm.md +551 -0
- package/.claude/agents/github/repo-architect.md +365 -0
- package/.claude/agents/github/swarm-issue.md +548 -0
- package/.claude/agents/github/swarm-pr.md +399 -0
- package/.claude/agents/github/sync-coordinator.md +423 -0
- package/.claude/agents/github/workflow-automation.md +605 -0
- package/.claude/agents/goal/agent.md +817 -0
- package/.claude/agents/goal/code-goal-planner.md +445 -0
- package/.claude/agents/goal/goal-planner.md +168 -0
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -0
- package/.claude/agents/hive-mind/queen-coordinator.md +202 -0
- package/.claude/agents/hive-mind/scout-explorer.md +241 -0
- package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -0
- package/.claude/agents/hive-mind/worker-specialist.md +216 -0
- package/.claude/agents/neural/safla-neural.md +74 -0
- package/.claude/agents/optimization/benchmark-suite.md +663 -0
- package/.claude/agents/optimization/load-balancer.md +429 -0
- package/.claude/agents/optimization/performance-monitor.md +670 -0
- package/.claude/agents/optimization/resource-allocator.md +672 -0
- package/.claude/agents/optimization/topology-optimizer.md +806 -0
- package/.claude/agents/payments/agentic-payments.md +126 -0
- package/.claude/agents/project-coordinator.md +8 -0
- package/.claude/agents/python-specialist.md +9 -0
- package/.claude/agents/reasoning/agent.md +817 -0
- package/.claude/agents/reasoning/goal-planner.md +73 -0
- package/.claude/agents/security-auditor.md +9 -0
- package/.claude/agents/sona/sona-learning-optimizer.md +65 -0
- package/.claude/agents/sparc/architecture.md +453 -0
- package/.claude/agents/sparc/pseudocode.md +299 -0
- package/.claude/agents/sparc/refinement.md +504 -0
- package/.claude/agents/sparc/specification.md +258 -0
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +88 -0
- package/.claude/agents/specialized/spec-mobile-react-native.md +227 -0
- package/.claude/agents/sublinear/consensus-coordinator.md +338 -0
- package/.claude/agents/sublinear/matrix-optimizer.md +185 -0
- package/.claude/agents/sublinear/pagerank-analyzer.md +299 -0
- package/.claude/agents/sublinear/performance-optimizer.md +368 -0
- package/.claude/agents/sublinear/trading-predictor.md +246 -0
- package/.claude/agents/swarm/adaptive-coordinator.md +364 -0
- package/.claude/agents/swarm/hierarchical-coordinator.md +300 -0
- package/.claude/agents/swarm/mesh-coordinator.md +363 -0
- package/.claude/agents/templates/automation-smart-agent.md +185 -0
- package/.claude/agents/templates/base-template-generator.md +289 -0
- package/.claude/agents/templates/coordinator-swarm-init.md +83 -0
- package/.claude/agents/templates/github-pr-manager.md +155 -0
- package/.claude/agents/templates/implementer-sparc-coder.md +243 -0
- package/.claude/agents/templates/memory-coordinator.md +163 -0
- package/.claude/agents/templates/migration-plan.md +724 -0
- package/.claude/agents/templates/orchestrator-task.md +120 -0
- package/.claude/agents/templates/performance-analyzer.md +179 -0
- package/.claude/agents/templates/sparc-coordinator.md +163 -0
- package/.claude/agents/testing/production-validator.md +373 -0
- package/.claude/agents/testing/tdd-london-swarm.md +222 -0
- package/.claude/agents/testing/unit/tdd-london-swarm.md +222 -0
- package/.claude/agents/testing/validation/production-validator.md +373 -0
- package/.claude/agents/typescript-specialist.md +9 -0
- package/.claude/agents/v3/adr-architect.md +184 -0
- package/.claude/agents/v3/aidefence-guardian.md +282 -0
- package/.claude/agents/v3/claims-authorizer.md +208 -0
- package/.claude/agents/v3/collective-intelligence-coordinator.md +993 -0
- package/.claude/agents/v3/database-specialist.md +9 -0
- package/.claude/agents/v3/ddd-domain-expert.md +220 -0
- package/.claude/agents/v3/injection-analyst.md +236 -0
- package/.claude/agents/v3/memory-specialist.md +995 -0
- package/.claude/agents/v3/performance-engineer.md +1233 -0
- package/.claude/agents/v3/pii-detector.md +151 -0
- package/.claude/agents/v3/project-coordinator.md +8 -0
- package/.claude/agents/v3/python-specialist.md +9 -0
- package/.claude/agents/v3/reasoningbank-learner.md +213 -0
- package/.claude/agents/v3/security-architect-aidefence.md +410 -0
- package/.claude/agents/v3/security-architect.md +867 -0
- package/.claude/agents/v3/security-auditor.md +771 -0
- package/.claude/agents/v3/sparc-orchestrator.md +182 -0
- package/.claude/agents/v3/swarm-memory-manager.md +157 -0
- package/.claude/agents/v3/test-architect.md +9 -0
- package/.claude/agents/v3/typescript-specialist.md +9 -0
- package/.claude/agents/v3/v3-integration-architect.md +312 -0
- package/.claude/agents/v3/v3-memory-specialist.md +281 -0
- package/.claude/agents/v3/v3-performance-engineer.md +363 -0
- package/.claude/agents/v3/v3-queen-coordinator.md +63 -0
- package/.claude/agents/v3/v3-security-architect.md +140 -0
- package/.claude/checkpoints/1767754460.json +8 -0
- package/.claude/commands/agents/README.md +10 -0
- package/.claude/commands/agents/agent-capabilities.md +21 -0
- package/.claude/commands/agents/agent-coordination.md +28 -0
- package/.claude/commands/agents/agent-spawning.md +28 -0
- package/.claude/commands/agents/agent-types.md +26 -0
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
- package/.claude/commands/analysis/README.md +9 -0
- package/.claude/commands/analysis/bottleneck-detect.md +162 -0
- package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
- package/.claude/commands/analysis/performance-report.md +25 -0
- package/.claude/commands/analysis/token-efficiency.md +45 -0
- package/.claude/commands/analysis/token-usage.md +25 -0
- package/.claude/commands/automation/README.md +9 -0
- package/.claude/commands/automation/auto-agent.md +122 -0
- package/.claude/commands/automation/self-healing.md +106 -0
- package/.claude/commands/automation/session-memory.md +90 -0
- package/.claude/commands/automation/smart-agents.md +73 -0
- package/.claude/commands/automation/smart-spawn.md +25 -0
- package/.claude/commands/automation/workflow-select.md +25 -0
- package/.claude/commands/claude-flow-help.md +103 -0
- package/.claude/commands/claude-flow-memory.md +107 -0
- package/.claude/commands/claude-flow-swarm.md +205 -0
- package/.claude/commands/coordination/README.md +9 -0
- package/.claude/commands/coordination/agent-spawn.md +25 -0
- package/.claude/commands/coordination/init.md +44 -0
- package/.claude/commands/coordination/orchestrate.md +43 -0
- package/.claude/commands/coordination/spawn.md +45 -0
- package/.claude/commands/coordination/swarm-init.md +85 -0
- package/.claude/commands/coordination/task-orchestrate.md +25 -0
- package/.claude/commands/flow-nexus/app-store.md +124 -0
- package/.claude/commands/flow-nexus/challenges.md +120 -0
- package/.claude/commands/flow-nexus/login-registration.md +65 -0
- package/.claude/commands/flow-nexus/neural-network.md +134 -0
- package/.claude/commands/flow-nexus/payments.md +116 -0
- package/.claude/commands/flow-nexus/sandbox.md +83 -0
- package/.claude/commands/flow-nexus/swarm.md +87 -0
- package/.claude/commands/flow-nexus/user-tools.md +152 -0
- package/.claude/commands/flow-nexus/workflow.md +115 -0
- package/.claude/commands/github/README.md +11 -0
- package/.claude/commands/github/code-review-swarm.md +514 -0
- package/.claude/commands/github/code-review.md +25 -0
- package/.claude/commands/github/github-modes.md +147 -0
- package/.claude/commands/github/github-swarm.md +121 -0
- package/.claude/commands/github/issue-tracker.md +292 -0
- package/.claude/commands/github/issue-triage.md +25 -0
- package/.claude/commands/github/multi-repo-swarm.md +519 -0
- package/.claude/commands/github/pr-enhance.md +26 -0
- package/.claude/commands/github/pr-manager.md +170 -0
- package/.claude/commands/github/project-board-sync.md +471 -0
- package/.claude/commands/github/release-manager.md +338 -0
- package/.claude/commands/github/release-swarm.md +544 -0
- package/.claude/commands/github/repo-analyze.md +25 -0
- package/.claude/commands/github/repo-architect.md +367 -0
- package/.claude/commands/github/swarm-issue.md +482 -0
- package/.claude/commands/github/swarm-pr.md +285 -0
- package/.claude/commands/github/sync-coordinator.md +301 -0
- package/.claude/commands/github/workflow-automation.md +442 -0
- package/.claude/commands/hive-mind/README.md +17 -0
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
- package/.claude/commands/hive-mind/hive-mind.md +27 -0
- package/.claude/commands/hooks/README.md +11 -0
- package/.claude/commands/hooks/overview.md +58 -0
- package/.claude/commands/hooks/post-edit.md +117 -0
- package/.claude/commands/hooks/post-task.md +112 -0
- package/.claude/commands/hooks/pre-edit.md +113 -0
- package/.claude/commands/hooks/pre-task.md +111 -0
- package/.claude/commands/hooks/session-end.md +118 -0
- package/.claude/commands/hooks/setup.md +103 -0
- package/.claude/commands/memory/README.md +9 -0
- package/.claude/commands/memory/memory-persist.md +25 -0
- package/.claude/commands/memory/memory-search.md +25 -0
- package/.claude/commands/memory/memory-usage.md +25 -0
- package/.claude/commands/memory/neural.md +47 -0
- package/.claude/commands/monitoring/README.md +9 -0
- package/.claude/commands/monitoring/agent-metrics.md +25 -0
- package/.claude/commands/monitoring/agents.md +44 -0
- package/.claude/commands/monitoring/real-time-view.md +25 -0
- package/.claude/commands/monitoring/status.md +46 -0
- package/.claude/commands/monitoring/swarm-monitor.md +25 -0
- package/.claude/commands/optimization/README.md +9 -0
- package/.claude/commands/optimization/auto-topology.md +62 -0
- package/.claude/commands/optimization/cache-manage.md +25 -0
- package/.claude/commands/optimization/parallel-execute.md +25 -0
- package/.claude/commands/optimization/parallel-execution.md +50 -0
- package/.claude/commands/optimization/topology-optimize.md +25 -0
- package/.claude/commands/pair/README.md +261 -0
- package/.claude/commands/pair/commands.md +546 -0
- package/.claude/commands/pair/config.md +510 -0
- package/.claude/commands/pair/examples.md +512 -0
- package/.claude/commands/pair/modes.md +348 -0
- package/.claude/commands/pair/session.md +407 -0
- package/.claude/commands/pair/start.md +209 -0
- package/.claude/commands/sparc/analyzer.md +52 -0
- package/.claude/commands/sparc/architect.md +53 -0
- package/.claude/commands/sparc/ask.md +97 -0
- package/.claude/commands/sparc/batch-executor.md +54 -0
- package/.claude/commands/sparc/code.md +89 -0
- package/.claude/commands/sparc/coder.md +54 -0
- package/.claude/commands/sparc/debug.md +83 -0
- package/.claude/commands/sparc/debugger.md +54 -0
- package/.claude/commands/sparc/designer.md +53 -0
- package/.claude/commands/sparc/devops.md +109 -0
- package/.claude/commands/sparc/docs-writer.md +80 -0
- package/.claude/commands/sparc/documenter.md +54 -0
- package/.claude/commands/sparc/innovator.md +54 -0
- package/.claude/commands/sparc/integration.md +83 -0
- package/.claude/commands/sparc/mcp.md +117 -0
- package/.claude/commands/sparc/memory-manager.md +54 -0
- package/.claude/commands/sparc/optimizer.md +54 -0
- package/.claude/commands/sparc/orchestrator.md +132 -0
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
- package/.claude/commands/sparc/researcher.md +54 -0
- package/.claude/commands/sparc/reviewer.md +54 -0
- package/.claude/commands/sparc/security-review.md +80 -0
- package/.claude/commands/sparc/sparc-modes.md +174 -0
- package/.claude/commands/sparc/sparc.md +111 -0
- package/.claude/commands/sparc/spec-pseudocode.md +80 -0
- package/.claude/commands/sparc/supabase-admin.md +348 -0
- package/.claude/commands/sparc/swarm-coordinator.md +54 -0
- package/.claude/commands/sparc/tdd.md +54 -0
- package/.claude/commands/sparc/tester.md +54 -0
- package/.claude/commands/sparc/tutorial.md +79 -0
- package/.claude/commands/sparc/workflow-manager.md +54 -0
- package/.claude/commands/sparc.md +166 -0
- package/.claude/commands/stream-chain/pipeline.md +121 -0
- package/.claude/commands/stream-chain/run.md +70 -0
- package/.claude/commands/swarm/README.md +15 -0
- package/.claude/commands/swarm/analysis.md +95 -0
- package/.claude/commands/swarm/development.md +96 -0
- package/.claude/commands/swarm/examples.md +168 -0
- package/.claude/commands/swarm/maintenance.md +102 -0
- package/.claude/commands/swarm/optimization.md +117 -0
- package/.claude/commands/swarm/research.md +136 -0
- package/.claude/commands/swarm/swarm-analysis.md +8 -0
- package/.claude/commands/swarm/swarm-background.md +8 -0
- package/.claude/commands/swarm/swarm-init.md +19 -0
- package/.claude/commands/swarm/swarm-modes.md +8 -0
- package/.claude/commands/swarm/swarm-monitor.md +8 -0
- package/.claude/commands/swarm/swarm-spawn.md +19 -0
- package/.claude/commands/swarm/swarm-status.md +8 -0
- package/.claude/commands/swarm/swarm-strategies.md +8 -0
- package/.claude/commands/swarm/swarm.md +27 -0
- package/.claude/commands/swarm/testing.md +131 -0
- package/.claude/commands/training/README.md +9 -0
- package/.claude/commands/training/model-update.md +25 -0
- package/.claude/commands/training/neural-patterns.md +74 -0
- package/.claude/commands/training/neural-train.md +25 -0
- package/.claude/commands/training/pattern-learn.md +25 -0
- package/.claude/commands/training/specialization.md +63 -0
- package/.claude/commands/truth/start.md +143 -0
- package/.claude/commands/verify/check.md +50 -0
- package/.claude/commands/verify/start.md +128 -0
- package/.claude/commands/workflows/README.md +9 -0
- package/.claude/commands/workflows/development.md +78 -0
- package/.claude/commands/workflows/research.md +63 -0
- package/.claude/commands/workflows/workflow-create.md +25 -0
- package/.claude/commands/workflows/workflow-execute.md +25 -0
- package/.claude/commands/workflows/workflow-export.md +25 -0
- package/.claude/config/v3-dependency-optimization.json +266 -0
- package/.claude/config/v3-performance-targets.json +251 -0
- package/.claude/helpers/README.md +97 -0
- package/.claude/helpers/adr-compliance.sh +186 -0
- package/.claude/helpers/aggressive-microcompact.mjs +36 -0
- package/.claude/helpers/auto-commit.sh +178 -0
- package/.claude/helpers/auto-memory-hook.mjs +564 -0
- package/.claude/helpers/checkpoint-manager.sh +251 -0
- package/.claude/helpers/context-persistence-hook.mjs +1979 -0
- package/.claude/helpers/daemon-manager.sh +252 -0
- package/.claude/helpers/ddd-tracker.sh +144 -0
- package/.claude/helpers/github-safe.js +106 -0
- package/.claude/helpers/github-setup.sh +28 -0
- package/.claude/helpers/guidance-hook.sh +13 -0
- package/.claude/helpers/guidance-hooks.sh +102 -0
- package/.claude/helpers/health-monitor.sh +108 -0
- package/.claude/helpers/hook-handler.cjs +269 -0
- package/.claude/helpers/intelligence.cjs +230 -0
- package/.claude/helpers/learning-hooks.sh +329 -0
- package/.claude/helpers/learning-optimizer.sh +127 -0
- package/.claude/helpers/learning-service.mjs +1144 -0
- package/.claude/helpers/memory.cjs +84 -0
- package/.claude/helpers/memory.js +83 -0
- package/.claude/helpers/metrics-db.mjs +488 -0
- package/.claude/helpers/patch-aggressive-prune.mjs +184 -0
- package/.claude/helpers/pattern-consolidator.sh +86 -0
- package/.claude/helpers/perf-worker.sh +160 -0
- package/.claude/helpers/post-commit +16 -0
- package/.claude/helpers/pre-commit +26 -0
- package/.claude/helpers/quick-start.sh +19 -0
- package/.claude/helpers/router.cjs +62 -0
- package/.claude/helpers/router.js +66 -0
- package/.claude/helpers/security-scanner.sh +127 -0
- package/.claude/helpers/session.cjs +125 -0
- package/.claude/helpers/session.js +135 -0
- package/.claude/helpers/setup-mcp.sh +18 -0
- package/.claude/helpers/standard-checkpoint-hooks.sh +189 -0
- package/.claude/helpers/statusline-hook.sh +21 -0
- package/.claude/helpers/statusline.cjs +878 -0
- package/.claude/helpers/statusline.js +352 -0
- package/.claude/helpers/swarm-comms.sh +353 -0
- package/.claude/helpers/swarm-hooks.sh +761 -0
- package/.claude/helpers/swarm-monitor.sh +211 -0
- package/.claude/helpers/sync-v3-metrics.sh +245 -0
- package/.claude/helpers/update-v3-progress.sh +166 -0
- package/.claude/helpers/v3-quick-status.sh +58 -0
- package/.claude/helpers/v3.sh +111 -0
- package/.claude/helpers/validate-v3-config.sh +216 -0
- package/.claude/helpers/worker-manager.sh +170 -0
- package/.claude/mcp.json +13 -0
- package/.claude/scheduled_tasks.lock +1 -0
- package/.claude/settings.json +285 -0
- package/.claude/settings.json.bak +526 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
- package/.claude/skills/agentdb-learning/SKILL.md +545 -0
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
- package/.claude/skills/browser/SKILL.md +204 -0
- package/.claude/skills/dual-mode/README.md +71 -0
- package/.claude/skills/dual-mode/dual-collect.md +103 -0
- package/.claude/skills/dual-mode/dual-coordinate.md +85 -0
- package/.claude/skills/dual-mode/dual-spawn.md +81 -0
- package/.claude/skills/flow-nexus-neural/SKILL.md +727 -0
- package/.claude/skills/flow-nexus-platform/SKILL.md +1154 -0
- package/.claude/skills/flow-nexus-swarm/SKILL.md +604 -0
- package/.claude/skills/github-code-review/SKILL.md +1125 -0
- package/.claude/skills/github-multi-repo/SKILL.md +862 -0
- package/.claude/skills/github-project-management/SKILL.md +1263 -0
- package/.claude/skills/github-release-management/SKILL.md +1064 -0
- package/.claude/skills/github-workflow-automation/SKILL.md +1047 -0
- package/.claude/skills/hive-mind-advanced/SKILL.md +709 -0
- package/.claude/skills/hooks-automation/SKILL.md +1201 -0
- package/.claude/skills/pair-programming/SKILL.md +1202 -0
- package/.claude/skills/performance-analysis/SKILL.md +560 -0
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/.claude/skills/sparc-methodology/SKILL.md +1106 -0
- package/.claude/skills/stream-chain/SKILL.md +560 -0
- package/.claude/skills/swarm-advanced/SKILL.md +970 -0
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
- package/.claude/skills/v3-cli-modernization/SKILL.md +872 -0
- package/.claude/skills/v3-core-implementation/SKILL.md +797 -0
- package/.claude/skills/v3-ddd-architecture/SKILL.md +442 -0
- package/.claude/skills/v3-integration-deep/SKILL.md +241 -0
- package/.claude/skills/v3-mcp-optimization/SKILL.md +777 -0
- package/.claude/skills/v3-memory-unification/SKILL.md +174 -0
- package/.claude/skills/v3-performance-optimization/SKILL.md +390 -0
- package/.claude/skills/v3-security-overhaul/SKILL.md +82 -0
- package/.claude/skills/v3-swarm-coordination/SKILL.md +340 -0
- package/.claude/skills/verification-quality/SKILL.md +691 -0
- package/.claude/skills/worker-benchmarks/SKILL.md +129 -0
- package/.claude/skills/worker-integration/SKILL.md +147 -0
- package/.claude/statusline-command.sh +176 -0
- package/.claude/statusline.mjs +109 -0
- package/.claude/statusline.sh +431 -0
- package/.claude-plugin/README.md +720 -0
- package/.claude-plugin/docs/INSTALLATION.md +261 -0
- package/.claude-plugin/docs/PLUGIN_SUMMARY.md +361 -0
- package/.claude-plugin/docs/QUICKSTART.md +361 -0
- package/.claude-plugin/docs/STRUCTURE.md +128 -0
- package/.claude-plugin/hooks/hooks.json +75 -0
- package/.claude-plugin/marketplace.json +170 -0
- package/.claude-plugin/plugin.json +71 -0
- package/.claude-plugin/scripts/install.sh +234 -0
- package/.claude-plugin/scripts/ruflo-hook.sh +33 -0
- package/.claude-plugin/scripts/uninstall.sh +36 -0
- package/.claude-plugin/scripts/verify.sh +108 -0
- package/LICENSE +21 -0
- package/README.md +410 -0
- package/bin/cli.js +11 -0
- package/bin/npx-repair.js +7 -0
- package/bin/npx-safe-launch.js +9 -0
- package/package.json +159 -0
- package/v3/@claude-flow/cli/README.md +410 -0
- package/v3/@claude-flow/cli/bin/cli.js +233 -0
- package/v3/@claude-flow/cli/bin/mcp-server.js +224 -0
- package/v3/@claude-flow/cli/bin/preinstall.cjs +2 -0
- package/v3/@claude-flow/cli/dist/src/appliance/gguf-engine.d.ts +91 -0
- package/v3/@claude-flow/cli/dist/src/appliance/gguf-engine.js +425 -0
- package/v3/@claude-flow/cli/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
- package/v3/@claude-flow/cli/dist/src/appliance/ruvllm-bridge.js +292 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-builder.d.ts +44 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-builder.js +329 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-distribution.d.ts +97 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-distribution.js +370 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-format.d.ts +111 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-format.js +393 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-runner.d.ts +69 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-runner.js +237 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-signing.d.ts +123 -0
- package/v3/@claude-flow/cli/dist/src/appliance/rvfa-signing.js +347 -0
- package/v3/@claude-flow/cli/dist/src/autopilot-state.d.ts +77 -0
- package/v3/@claude-flow/cli/dist/src/autopilot-state.js +271 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/pretrain/index.d.ts +58 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/pretrain/index.js +404 -0
- package/v3/@claude-flow/cli/dist/src/commands/agent-wasm.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/commands/agent-wasm.js +333 -0
- package/v3/@claude-flow/cli/dist/src/commands/agent.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/agent.js +927 -0
- package/v3/@claude-flow/cli/dist/src/commands/analyze.d.ts +19 -0
- package/v3/@claude-flow/cli/dist/src/commands/analyze.js +2048 -0
- package/v3/@claude-flow/cli/dist/src/commands/appliance-advanced.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/commands/appliance-advanced.js +215 -0
- package/v3/@claude-flow/cli/dist/src/commands/appliance.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/appliance.js +404 -0
- package/v3/@claude-flow/cli/dist/src/commands/autopilot.d.ts +15 -0
- package/v3/@claude-flow/cli/dist/src/commands/autopilot.js +362 -0
- package/v3/@claude-flow/cli/dist/src/commands/benchmark.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/benchmark.js +460 -0
- package/v3/@claude-flow/cli/dist/src/commands/claims.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/claims.js +620 -0
- package/v3/@claude-flow/cli/dist/src/commands/cleanup.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/commands/cleanup.js +250 -0
- package/v3/@claude-flow/cli/dist/src/commands/completions.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/completions.js +539 -0
- package/v3/@claude-flow/cli/dist/src/commands/config.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/config.js +430 -0
- package/v3/@claude-flow/cli/dist/src/commands/daemon.d.ts +28 -0
- package/v3/@claude-flow/cli/dist/src/commands/daemon.js +1093 -0
- package/v3/@claude-flow/cli/dist/src/commands/deployment.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/deployment.js +672 -0
- package/v3/@claude-flow/cli/dist/src/commands/doctor.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +885 -0
- package/v3/@claude-flow/cli/dist/src/commands/embeddings.d.ts +18 -0
- package/v3/@claude-flow/cli/dist/src/commands/embeddings.js +1623 -0
- package/v3/@claude-flow/cli/dist/src/commands/guidance.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/guidance.js +556 -0
- package/v3/@claude-flow/cli/dist/src/commands/hive-mind.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/hive-mind.js +1297 -0
- package/v3/@claude-flow/cli/dist/src/commands/hooks.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/hooks.js +4499 -0
- package/v3/@claude-flow/cli/dist/src/commands/index.d.ts +118 -0
- package/v3/@claude-flow/cli/dist/src/commands/index.js +344 -0
- package/v3/@claude-flow/cli/dist/src/commands/init.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/init.js +997 -0
- package/v3/@claude-flow/cli/dist/src/commands/issues.d.ts +21 -0
- package/v3/@claude-flow/cli/dist/src/commands/issues.js +567 -0
- package/v3/@claude-flow/cli/dist/src/commands/mcp.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/mcp.js +718 -0
- package/v3/@claude-flow/cli/dist/src/commands/memory.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/memory.js +1456 -0
- package/v3/@claude-flow/cli/dist/src/commands/migrate.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/migrate.js +742 -0
- package/v3/@claude-flow/cli/dist/src/commands/neural.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/neural.js +1531 -0
- package/v3/@claude-flow/cli/dist/src/commands/performance.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/performance.js +583 -0
- package/v3/@claude-flow/cli/dist/src/commands/plugins.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/plugins.js +826 -0
- package/v3/@claude-flow/cli/dist/src/commands/process.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/process.js +694 -0
- package/v3/@claude-flow/cli/dist/src/commands/progress.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/progress.js +259 -0
- package/v3/@claude-flow/cli/dist/src/commands/providers.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/providers.js +502 -0
- package/v3/@claude-flow/cli/dist/src/commands/route.d.ts +16 -0
- package/v3/@claude-flow/cli/dist/src/commands/route.js +813 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/backup.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/backup.js +747 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/benchmark.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/benchmark.js +490 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/import.d.ts +18 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/import.js +373 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/index.d.ts +29 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/index.js +129 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/init.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/init.js +467 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/migrate.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/migrate.js +498 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/optimize.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/optimize.js +505 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/pg-utils.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/pg-utils.js +41 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/setup.d.ts +18 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/setup.js +765 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/status.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/status.js +479 -0
- package/v3/@claude-flow/cli/dist/src/commands/security.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/commands/security.js +920 -0
- package/v3/@claude-flow/cli/dist/src/commands/session.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/session.js +757 -0
- package/v3/@claude-flow/cli/dist/src/commands/start.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/start.js +418 -0
- package/v3/@claude-flow/cli/dist/src/commands/status.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/status.js +591 -0
- package/v3/@claude-flow/cli/dist/src/commands/swarm.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/swarm.js +887 -0
- package/v3/@claude-flow/cli/dist/src/commands/task.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/task.js +675 -0
- package/v3/@claude-flow/cli/dist/src/commands/transfer-store.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/commands/transfer-store.js +428 -0
- package/v3/@claude-flow/cli/dist/src/commands/update.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/update.js +276 -0
- package/v3/@claude-flow/cli/dist/src/commands/verify.d.ts +19 -0
- package/v3/@claude-flow/cli/dist/src/commands/verify.js +261 -0
- package/v3/@claude-flow/cli/dist/src/commands/workflow.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/commands/workflow.js +617 -0
- package/v3/@claude-flow/cli/dist/src/config-adapter.d.ts +15 -0
- package/v3/@claude-flow/cli/dist/src/config-adapter.js +186 -0
- package/v3/@claude-flow/cli/dist/src/encryption/vault.d.ts +94 -0
- package/v3/@claude-flow/cli/dist/src/encryption/vault.js +172 -0
- package/v3/@claude-flow/cli/dist/src/fs-secure.d.ts +67 -0
- package/v3/@claude-flow/cli/dist/src/fs-secure.js +74 -0
- package/v3/@claude-flow/cli/dist/src/index.d.ts +81 -0
- package/v3/@claude-flow/cli/dist/src/index.js +538 -0
- package/v3/@claude-flow/cli/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
- package/v3/@claude-flow/cli/dist/src/infrastructure/in-memory-repositories.js +264 -0
- package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.d.ts +16 -0
- package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.js +363 -0
- package/v3/@claude-flow/cli/dist/src/init/executor.d.ts +41 -0
- package/v3/@claude-flow/cli/dist/src/init/executor.js +1904 -0
- package/v3/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +60 -0
- package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +1185 -0
- package/v3/@claude-flow/cli/dist/src/init/index.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/init/index.js +15 -0
- package/v3/@claude-flow/cli/dist/src/init/mcp-generator.d.ts +26 -0
- package/v3/@claude-flow/cli/dist/src/init/mcp-generator.js +116 -0
- package/v3/@claude-flow/cli/dist/src/init/settings-generator.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/init/settings-generator.js +456 -0
- package/v3/@claude-flow/cli/dist/src/init/statusline-generator.d.ts +28 -0
- package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +937 -0
- package/v3/@claude-flow/cli/dist/src/init/types.d.ts +308 -0
- package/v3/@claude-flow/cli/dist/src/init/types.js +263 -0
- package/v3/@claude-flow/cli/dist/src/log-filters.d.ts +22 -0
- package/v3/@claude-flow/cli/dist/src/log-filters.js +36 -0
- package/v3/@claude-flow/cli/dist/src/mcp-client.d.ts +92 -0
- package/v3/@claude-flow/cli/dist/src/mcp-client.js +287 -0
- package/v3/@claude-flow/cli/dist/src/mcp-server.d.ts +163 -0
- package/v3/@claude-flow/cli/dist/src/mcp-server.js +732 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-execute-core.d.ts +92 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-execute-core.js +328 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-tools.js +716 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.d.ts +33 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +867 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/analyze-tools.js +346 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/auto-install.d.ts +83 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/auto-install.js +131 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/autopilot-tools.d.ts +12 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/autopilot-tools.js +231 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-session-tools.d.ts +23 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-session-tools.js +324 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +757 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/claims-tools.d.ts +12 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/claims-tools.js +863 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/config-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/config-tools.js +411 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js +729 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/daa-tools.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/daa-tools.js +534 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/embeddings-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/embeddings-tools.js +904 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/github-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/github-tools.js +659 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/guidance-tools.d.ts +15 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/guidance-tools.js +639 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.js +953 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.d.ts +46 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +3939 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/index.d.ts +27 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/index.js +26 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-agent-tools.d.ts +22 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-agent-tools.js +357 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +1240 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.d.ts +16 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +793 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.d.ts +16 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +675 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/progress-tools.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/progress-tools.js +348 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/request-tracker.d.ts +17 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/request-tracker.js +27 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/ruvllm-tools.js +339 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/security-tools.d.ts +18 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/security-tools.js +556 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/session-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/session-tools.js +517 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/swarm-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/swarm-tools.js +388 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +674 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.js +487 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/terminal-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/terminal-tools.js +306 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/transfer-tools.js +447 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/types.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/types.js +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/validate-input.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/validate-input.js +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/wasm-agent-tools.js +291 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.js +884 -0
- package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.d.ts +295 -0
- package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.js +601 -0
- package/v3/@claude-flow/cli/dist/src/memory/intelligence.d.ts +357 -0
- package/v3/@claude-flow/cli/dist/src/memory/intelligence.js +1200 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.d.ts +492 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +2101 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +420 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +2376 -0
- package/v3/@claude-flow/cli/dist/src/memory/neural-package-bridge.d.ts +48 -0
- package/v3/@claude-flow/cli/dist/src/memory/neural-package-bridge.js +87 -0
- package/v3/@claude-flow/cli/dist/src/memory/rabitq-index.d.ts +60 -0
- package/v3/@claude-flow/cli/dist/src/memory/rabitq-index.js +242 -0
- package/v3/@claude-flow/cli/dist/src/memory/sona-optimizer.d.ts +267 -0
- package/v3/@claude-flow/cli/dist/src/memory/sona-optimizer.js +779 -0
- package/v3/@claude-flow/cli/dist/src/output.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/output.js +9 -0
- package/v3/@claude-flow/cli/dist/src/parser.d.ts +69 -0
- package/v3/@claude-flow/cli/dist/src/parser.js +473 -0
- package/v3/@claude-flow/cli/dist/src/plugins/manager.d.ts +133 -0
- package/v3/@claude-flow/cli/dist/src/plugins/manager.js +402 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/discovery.d.ts +91 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/discovery.js +1202 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/index.d.ts +76 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/index.js +141 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/search.d.ts +46 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/search.js +230 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/types.d.ts +274 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/types.js +7 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/demo-plugin-store.js +126 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/standalone-test.d.ts +12 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/standalone-test.js +188 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
- package/v3/@claude-flow/cli/dist/src/plugins/tests/test-plugin-store.js +206 -0
- package/v3/@claude-flow/cli/dist/src/production/circuit-breaker.d.ts +101 -0
- package/v3/@claude-flow/cli/dist/src/production/circuit-breaker.js +241 -0
- package/v3/@claude-flow/cli/dist/src/production/error-handler.d.ts +92 -0
- package/v3/@claude-flow/cli/dist/src/production/error-handler.js +299 -0
- package/v3/@claude-flow/cli/dist/src/production/index.d.ts +23 -0
- package/v3/@claude-flow/cli/dist/src/production/index.js +18 -0
- package/v3/@claude-flow/cli/dist/src/production/monitoring.d.ts +161 -0
- package/v3/@claude-flow/cli/dist/src/production/monitoring.js +356 -0
- package/v3/@claude-flow/cli/dist/src/production/rate-limiter.d.ts +80 -0
- package/v3/@claude-flow/cli/dist/src/production/rate-limiter.js +201 -0
- package/v3/@claude-flow/cli/dist/src/production/retry.d.ts +48 -0
- package/v3/@claude-flow/cli/dist/src/production/retry.js +179 -0
- package/v3/@claude-flow/cli/dist/src/prompt.d.ts +44 -0
- package/v3/@claude-flow/cli/dist/src/prompt.js +501 -0
- package/v3/@claude-flow/cli/dist/src/runtime/headless.d.ts +60 -0
- package/v3/@claude-flow/cli/dist/src/runtime/headless.js +284 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/agent-wasm.d.ts +193 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/agent-wasm.js +354 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/ast-analyzer.d.ts +67 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/ast-analyzer.js +277 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/coverage-router.d.ts +160 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/coverage-router.js +531 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/coverage-tools.d.ts +33 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/coverage-tools.js +157 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/diff-classifier.d.ts +175 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/diff-classifier.js +699 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.d.ts +78 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.js +310 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/enhanced-model-router.d.ts +146 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/enhanced-model-router.js +529 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/graph-analyzer.d.ts +187 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/graph-analyzer.js +929 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/graph-backend.d.ts +79 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/graph-backend.js +220 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/index.d.ts +38 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/index.js +82 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/lora-adapter.d.ts +240 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/lora-adapter.js +550 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/model-router.d.ts +241 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/model-router.js +608 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/q-learning-router.d.ts +211 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/q-learning-router.js +681 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/ruvllm-wasm.js +367 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/semantic-router.d.ts +77 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/semantic-router.js +178 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/vector-db.d.ts +73 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/vector-db.js +264 -0
- package/v3/@claude-flow/cli/dist/src/services/agentic-flow-bridge.d.ts +50 -0
- package/v3/@claude-flow/cli/dist/src/services/agentic-flow-bridge.js +95 -0
- package/v3/@claude-flow/cli/dist/src/services/claim-service.d.ts +204 -0
- package/v3/@claude-flow/cli/dist/src/services/claim-service.js +818 -0
- package/v3/@claude-flow/cli/dist/src/services/config-file-manager.d.ts +37 -0
- package/v3/@claude-flow/cli/dist/src/services/config-file-manager.js +233 -0
- package/v3/@claude-flow/cli/dist/src/services/container-worker-pool.d.ts +197 -0
- package/v3/@claude-flow/cli/dist/src/services/container-worker-pool.js +583 -0
- package/v3/@claude-flow/cli/dist/src/services/headless-worker-executor.d.ts +310 -0
- package/v3/@claude-flow/cli/dist/src/services/headless-worker-executor.js +1058 -0
- package/v3/@claude-flow/cli/dist/src/services/index.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/services/index.js +11 -0
- package/v3/@claude-flow/cli/dist/src/services/registry-api.d.ts +58 -0
- package/v3/@claude-flow/cli/dist/src/services/registry-api.js +146 -0
- package/v3/@claude-flow/cli/dist/src/services/ruvector-training.d.ts +222 -0
- package/v3/@claude-flow/cli/dist/src/services/ruvector-training.js +688 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +323 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +1323 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-queue.d.ts +194 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-queue.js +513 -0
- package/v3/@claude-flow/cli/dist/src/suggest.d.ts +53 -0
- package/v3/@claude-flow/cli/dist/src/suggest.js +200 -0
- package/v3/@claude-flow/cli/dist/src/transfer/anonymization/index.d.ts +25 -0
- package/v3/@claude-flow/cli/dist/src/transfer/anonymization/index.js +175 -0
- package/v3/@claude-flow/cli/dist/src/transfer/deploy-seraphine.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/transfer/deploy-seraphine.js +205 -0
- package/v3/@claude-flow/cli/dist/src/transfer/export.d.ts +25 -0
- package/v3/@claude-flow/cli/dist/src/transfer/export.js +113 -0
- package/v3/@claude-flow/cli/dist/src/transfer/index.d.ts +12 -0
- package/v3/@claude-flow/cli/dist/src/transfer/index.js +31 -0
- package/v3/@claude-flow/cli/dist/src/transfer/ipfs/client.d.ts +109 -0
- package/v3/@claude-flow/cli/dist/src/transfer/ipfs/client.js +307 -0
- package/v3/@claude-flow/cli/dist/src/transfer/ipfs/upload.d.ts +95 -0
- package/v3/@claude-flow/cli/dist/src/transfer/ipfs/upload.js +413 -0
- package/v3/@claude-flow/cli/dist/src/transfer/models/seraphine.d.ts +72 -0
- package/v3/@claude-flow/cli/dist/src/transfer/models/seraphine.js +373 -0
- package/v3/@claude-flow/cli/dist/src/transfer/serialization/cfp.d.ts +49 -0
- package/v3/@claude-flow/cli/dist/src/transfer/serialization/cfp.js +183 -0
- package/v3/@claude-flow/cli/dist/src/transfer/storage/gcs.d.ts +82 -0
- package/v3/@claude-flow/cli/dist/src/transfer/storage/gcs.js +272 -0
- package/v3/@claude-flow/cli/dist/src/transfer/storage/index.d.ts +6 -0
- package/v3/@claude-flow/cli/dist/src/transfer/storage/index.js +6 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/discovery.d.ts +84 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/discovery.js +382 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/download.d.ts +70 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/download.js +334 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/index.d.ts +84 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/index.js +153 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/publish.d.ts +76 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/publish.js +294 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/registry.d.ts +58 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/registry.js +285 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/search.d.ts +54 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/search.js +232 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/tests/standalone-test.js +190 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/types.d.ts +193 -0
- package/v3/@claude-flow/cli/dist/src/transfer/store/types.js +6 -0
- package/v3/@claude-flow/cli/dist/src/transfer/test-seraphine.d.ts +6 -0
- package/v3/@claude-flow/cli/dist/src/transfer/test-seraphine.js +105 -0
- package/v3/@claude-flow/cli/dist/src/transfer/tests/test-store.d.ts +7 -0
- package/v3/@claude-flow/cli/dist/src/transfer/tests/test-store.js +214 -0
- package/v3/@claude-flow/cli/dist/src/transfer/types.d.ts +245 -0
- package/v3/@claude-flow/cli/dist/src/transfer/types.js +6 -0
- package/v3/@claude-flow/cli/dist/src/types.d.ts +13 -0
- package/v3/@claude-flow/cli/dist/src/types.js +13 -0
- package/v3/@claude-flow/cli/dist/src/update/checker.d.ts +34 -0
- package/v3/@claude-flow/cli/dist/src/update/checker.js +191 -0
- package/v3/@claude-flow/cli/dist/src/update/executor.d.ts +33 -0
- package/v3/@claude-flow/cli/dist/src/update/executor.js +217 -0
- package/v3/@claude-flow/cli/dist/src/update/index.d.ts +33 -0
- package/v3/@claude-flow/cli/dist/src/update/index.js +64 -0
- package/v3/@claude-flow/cli/dist/src/update/rate-limiter.d.ts +20 -0
- package/v3/@claude-flow/cli/dist/src/update/rate-limiter.js +96 -0
- package/v3/@claude-flow/cli/dist/src/update/validator.d.ts +17 -0
- package/v3/@claude-flow/cli/dist/src/update/validator.js +123 -0
- package/v3/@claude-flow/cli/package.json +133 -0
- package/v3/@claude-flow/guidance/README.md +1195 -0
- package/v3/@claude-flow/guidance/package.json +198 -0
- package/v3/@claude-flow/shared/README.md +323 -0
- package/v3/@claude-flow/shared/package.json +43 -0
- package/v3/README.md +493 -0
|
@@ -0,0 +1,2101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Bridge — Routes CLI memory operations through ControllerRegistry + AgentDB v3
|
|
3
|
+
*
|
|
4
|
+
* Per ADR-053 Phases 1-6: Full controller activation pipeline.
|
|
5
|
+
* CLI → ControllerRegistry → AgentDB v3 controllers.
|
|
6
|
+
*
|
|
7
|
+
* Phase 1: Core CRUD + embeddings + HNSW + controller access (complete)
|
|
8
|
+
* Phase 2: BM25 hybrid search, TieredCache read/write, MutationGuard validation
|
|
9
|
+
* Phase 3: ReasoningBank pattern store, recordFeedback, CausalMemoryGraph edges
|
|
10
|
+
* Phase 4: SkillLibrary promotion, ExplainableRecall provenance, AttestationLog
|
|
11
|
+
* Phase 5: ReflexionMemory session lifecycle, WitnessChain attestation
|
|
12
|
+
* Phase 6: AgentDB MCP tools (separate file), COW branching
|
|
13
|
+
*
|
|
14
|
+
* Uses better-sqlite3 API (synchronous .all()/.get()/.run()) since that's
|
|
15
|
+
* what AgentDB v3 uses internally.
|
|
16
|
+
*
|
|
17
|
+
* @module v3/cli/memory-bridge
|
|
18
|
+
*/
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
import * as crypto from 'crypto';
|
|
21
|
+
import { createRequire } from 'node:module';
|
|
22
|
+
// ===== Lazy singleton =====
|
|
23
|
+
let registryPromise = null;
|
|
24
|
+
let registryInstance = null;
|
|
25
|
+
let bridgeAvailable = null;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve database path with path traversal protection.
|
|
28
|
+
* Only allows paths within or below the project's working directory,
|
|
29
|
+
* or the special ':memory:' path.
|
|
30
|
+
*
|
|
31
|
+
* #1945: the previous hard-coded `<cwd>/.swarm/memory.db` default ignored
|
|
32
|
+
* `CLAUDE_FLOW_MEMORY_PATH` / `claude-flow.config.json#memory.persistPath`
|
|
33
|
+
* — so users with non-default memory paths had `memory init` write to e.g.
|
|
34
|
+
* `data/memory/memory.db` while `bridgeStoreEntry()` wrote to
|
|
35
|
+
* `.swarm/memory.db`. CLI store reported success against the wrong file and
|
|
36
|
+
* a fresh process reading the configured path saw nothing.
|
|
37
|
+
*
|
|
38
|
+
* Use `getMemoryRoot()` (from memory-initializer) so the bridge and the
|
|
39
|
+
* initializer agree on the same file. Imported via require() to avoid a
|
|
40
|
+
* circular ESM dep between memory-initializer.ts and memory-bridge.ts.
|
|
41
|
+
*/
|
|
42
|
+
function getDbPath(customPath) {
|
|
43
|
+
let defaultDir = path.resolve(process.cwd(), '.swarm');
|
|
44
|
+
try {
|
|
45
|
+
// `getMemoryRoot()` honors $CLAUDE_FLOW_MEMORY_PATH, then the
|
|
46
|
+
// claude-flow.config.json `memory.persistPath`, then defaults to `.swarm`.
|
|
47
|
+
const cjsRequire = createRequire(import.meta.url);
|
|
48
|
+
const mod = cjsRequire('./memory-initializer.js');
|
|
49
|
+
if (typeof mod.getMemoryRoot === 'function') {
|
|
50
|
+
defaultDir = mod.getMemoryRoot();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* memory-initializer not resolvable in this build — keep `.swarm/` default */
|
|
55
|
+
}
|
|
56
|
+
if (!customPath)
|
|
57
|
+
return path.join(defaultDir, 'memory.db');
|
|
58
|
+
if (customPath === ':memory:')
|
|
59
|
+
return ':memory:';
|
|
60
|
+
const resolved = path.resolve(customPath);
|
|
61
|
+
// Ensure the path doesn't escape the working directory.
|
|
62
|
+
const cwd = process.cwd();
|
|
63
|
+
if (!resolved.startsWith(cwd)) {
|
|
64
|
+
return path.join(defaultDir, 'memory.db'); // fallback to safe default
|
|
65
|
+
}
|
|
66
|
+
return resolved;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Generate a secure random ID for memory entries.
|
|
70
|
+
*/
|
|
71
|
+
function generateId(prefix) {
|
|
72
|
+
return `${prefix}_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Lazily initialize the ControllerRegistry singleton.
|
|
76
|
+
* Returns null if @claude-flow/memory is not available.
|
|
77
|
+
*/
|
|
78
|
+
async function getRegistry(dbPath) {
|
|
79
|
+
if (bridgeAvailable === false)
|
|
80
|
+
return null;
|
|
81
|
+
if (registryInstance)
|
|
82
|
+
return registryInstance;
|
|
83
|
+
if (!registryPromise) {
|
|
84
|
+
registryPromise = (async () => {
|
|
85
|
+
try {
|
|
86
|
+
const { ControllerRegistry } = await import('@claude-flow/memory');
|
|
87
|
+
const registry = new ControllerRegistry();
|
|
88
|
+
// Suppress noisy console.log during init
|
|
89
|
+
const origLog = console.log;
|
|
90
|
+
console.log = (...args) => {
|
|
91
|
+
const msg = String(args[0] ?? '');
|
|
92
|
+
if (msg.includes('Transformers.js') ||
|
|
93
|
+
msg.includes('better-sqlite3') ||
|
|
94
|
+
msg.includes('[AgentDB]') ||
|
|
95
|
+
msg.includes('[HNSWLibBackend]') ||
|
|
96
|
+
msg.includes('RuVector graph'))
|
|
97
|
+
return;
|
|
98
|
+
origLog.apply(console, args);
|
|
99
|
+
};
|
|
100
|
+
try {
|
|
101
|
+
await registry.initialize({
|
|
102
|
+
dbPath: dbPath || getDbPath(),
|
|
103
|
+
embeddingModel: 'Xenova/all-MiniLM-L6-v2',
|
|
104
|
+
dimension: 384,
|
|
105
|
+
vectorBackend: 'auto',
|
|
106
|
+
controllers: {
|
|
107
|
+
reasoningBank: true,
|
|
108
|
+
learningBridge: false,
|
|
109
|
+
tieredCache: true,
|
|
110
|
+
hierarchicalMemory: true,
|
|
111
|
+
memoryConsolidation: true,
|
|
112
|
+
memoryGraph: true,
|
|
113
|
+
vectorBackend: true,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
console.log = origLog;
|
|
119
|
+
}
|
|
120
|
+
// Wire intelligence module as the learning backend.
|
|
121
|
+
// AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db
|
|
122
|
+
// handle which ControllerRegistry doesn't expose. Instead, use the
|
|
123
|
+
// local intelligence module (SONA + LocalReasoningBank + file
|
|
124
|
+
// persistence) for learning.
|
|
125
|
+
//
|
|
126
|
+
// PERF: parallelize the two independent post-init paths
|
|
127
|
+
// (intelligence module load + agentdb import). Previously these
|
|
128
|
+
// ran serially, adding ~50-150ms to cold start. Both can resolve
|
|
129
|
+
// concurrently because they touch disjoint controller slots.
|
|
130
|
+
try {
|
|
131
|
+
const reg = registry;
|
|
132
|
+
const intelligencePromise = (async () => {
|
|
133
|
+
try {
|
|
134
|
+
const intelligence = await import('./intelligence.js');
|
|
135
|
+
const initResult = await intelligence.initializeIntelligence();
|
|
136
|
+
if (initResult.reasoningBankEnabled) {
|
|
137
|
+
const rb = intelligence.getReasoningBank();
|
|
138
|
+
if (rb && !reg.get('reasoningBank')) {
|
|
139
|
+
if (typeof reg.set === 'function')
|
|
140
|
+
reg.set('reasoningBank', rb);
|
|
141
|
+
else
|
|
142
|
+
reg._controllers = { ...(reg._controllers || {}), reasoningBank: rb };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (initResult.sonaEnabled) {
|
|
146
|
+
const sona = intelligence.getSonaCoordinator();
|
|
147
|
+
if (sona && !reg.get('learningSystem')) {
|
|
148
|
+
if (typeof reg.set === 'function')
|
|
149
|
+
reg.set('learningSystem', sona);
|
|
150
|
+
else
|
|
151
|
+
reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch { /* intelligence module not available — learning stays unwired */ }
|
|
156
|
+
})();
|
|
157
|
+
const agentdbPromise = (async () => {
|
|
158
|
+
// Single import shared across SkillLibrary + SemanticRouter probe.
|
|
159
|
+
let agentdb = null;
|
|
160
|
+
try {
|
|
161
|
+
agentdb = (await import('agentdb'));
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return; /* AgentDB not available */
|
|
165
|
+
}
|
|
166
|
+
// SkillLibrary (no db required)
|
|
167
|
+
try {
|
|
168
|
+
const SkillCtor = agentdb.SkillLibrary;
|
|
169
|
+
if (SkillCtor && !reg.get('skills')) {
|
|
170
|
+
const sk = new SkillCtor();
|
|
171
|
+
if (typeof reg.set === 'function')
|
|
172
|
+
reg.set('skills', sk);
|
|
173
|
+
else
|
|
174
|
+
reg._controllers = { ...(reg._controllers || {}), skills: sk };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch { /* SkillLibrary optional */ }
|
|
178
|
+
// ADR-093 F9: probe multiple router class names across agentdb
|
|
179
|
+
// alpha versions (alpha.10 had SemanticRouter; alpha.11+ removed
|
|
180
|
+
// it in favor of @ruvector/router; future versions may
|
|
181
|
+
// reintroduce). Wire only if .route() is callable.
|
|
182
|
+
try {
|
|
183
|
+
const candidates = ['SemanticRouter', 'IntentRouter', 'TaskRouter'];
|
|
184
|
+
let routerInstance = null;
|
|
185
|
+
for (const name of candidates) {
|
|
186
|
+
const Ctor = agentdb[name];
|
|
187
|
+
if (typeof Ctor === 'function') {
|
|
188
|
+
try {
|
|
189
|
+
const inst = (() => {
|
|
190
|
+
try {
|
|
191
|
+
return new Ctor({ dimension: 384 });
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return new Ctor();
|
|
195
|
+
}
|
|
196
|
+
})();
|
|
197
|
+
if (inst && typeof inst.route === 'function') {
|
|
198
|
+
routerInstance = inst;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch { /* try next candidate */ }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (routerInstance && !reg.get('semanticRouter')) {
|
|
206
|
+
if (typeof reg.set === 'function')
|
|
207
|
+
reg.set('semanticRouter', routerInstance);
|
|
208
|
+
else
|
|
209
|
+
reg._controllers = { ...(reg._controllers || {}), semanticRouter: routerInstance };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch { /* router optional */ }
|
|
213
|
+
// ADR-095 G7: load disabled-by-default controllers via direct
|
|
214
|
+
// file:// URLs from the bundled agentdb. agentdb's exports
|
|
215
|
+
// field doesn't expose these subpaths and we can't reliably
|
|
216
|
+
// patch it across pnpm-hoisted multi-version trees, so we
|
|
217
|
+
// sidestep the exports field entirely and import the file
|
|
218
|
+
// by absolute URL. Only loads controllers whose constructor
|
|
219
|
+
// is safe with no special prerequisites — others remain off
|
|
220
|
+
// pending per-controller activation ADRs.
|
|
221
|
+
try {
|
|
222
|
+
const { createRequire } = await import('node:module');
|
|
223
|
+
const { pathToFileURL } = await import('node:url');
|
|
224
|
+
const path = await import('node:path');
|
|
225
|
+
const fs = await import('node:fs');
|
|
226
|
+
const cjsRequire = createRequire(import.meta.url);
|
|
227
|
+
let adbPkgJsonPath = null;
|
|
228
|
+
try {
|
|
229
|
+
adbPkgJsonPath = cjsRequire.resolve('agentdb/package.json');
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
adbPkgJsonPath = null;
|
|
233
|
+
}
|
|
234
|
+
if (adbPkgJsonPath) {
|
|
235
|
+
const adbDir = path.dirname(adbPkgJsonPath);
|
|
236
|
+
const candidates = [
|
|
237
|
+
// GNNService and RVFOptimizer can construct with no args
|
|
238
|
+
// in current agentdb — safe to activate as-is.
|
|
239
|
+
{ name: 'gnnService', relPath: 'dist/src/services/GNNService.js', configurable: false },
|
|
240
|
+
{ name: 'rvfOptimizer', relPath: 'dist/src/optimizations/RVFOptimizer.js', configurable: false },
|
|
241
|
+
// ADR-095 G7 follow-up: MutationGuard constructs cleanly
|
|
242
|
+
// with no args and exposes WASM-backed proof generation.
|
|
243
|
+
// No external deps; safe-default activation.
|
|
244
|
+
{ name: 'mutationGuard', relPath: 'dist/src/security/MutationGuard.js', configurable: false },
|
|
245
|
+
// AttestationLog needs a sqlite db handle — wired below
|
|
246
|
+
// separately because we have to construct a db too.
|
|
247
|
+
// GuardedVectorBackend needs key material — leave for
|
|
248
|
+
// follow-up ADR.
|
|
249
|
+
];
|
|
250
|
+
for (const cand of candidates) {
|
|
251
|
+
if (reg.get(cand.name))
|
|
252
|
+
continue;
|
|
253
|
+
const abs = path.join(adbDir, cand.relPath);
|
|
254
|
+
if (!fs.existsSync(abs))
|
|
255
|
+
continue;
|
|
256
|
+
try {
|
|
257
|
+
const url = pathToFileURL(abs).href;
|
|
258
|
+
const mod = await import(url);
|
|
259
|
+
// Look for a default export, named export matching the
|
|
260
|
+
// file basename, or any class-typed export.
|
|
261
|
+
const baseName = path.basename(cand.relPath, '.js');
|
|
262
|
+
const Ctor = (mod[baseName] || mod.default ||
|
|
263
|
+
Object.values(mod).find(v => typeof v === 'function'));
|
|
264
|
+
if (typeof Ctor !== 'function')
|
|
265
|
+
continue;
|
|
266
|
+
const inst = new Ctor();
|
|
267
|
+
if (typeof reg.set === 'function')
|
|
268
|
+
reg.set(cand.name, inst);
|
|
269
|
+
else
|
|
270
|
+
reg._controllers = { ...(reg._controllers || {}), [cand.name]: inst };
|
|
271
|
+
}
|
|
272
|
+
catch { /* skip controllers that fail to construct */ }
|
|
273
|
+
}
|
|
274
|
+
// AttestationLog activation — needs a better-sqlite3
|
|
275
|
+
// database. We open a dedicated file at .swarm/attestation.db
|
|
276
|
+
// (separate from the main memory.db so the audit trail
|
|
277
|
+
// is isolated). Best-effort: if better-sqlite3 isn't
|
|
278
|
+
// resolvable in this env, skip cleanly.
|
|
279
|
+
let attestationInst = null;
|
|
280
|
+
if (!reg.get('attestationLog')) {
|
|
281
|
+
try {
|
|
282
|
+
const attestationFile = path.join(adbDir, 'dist/src/security/AttestationLog.js');
|
|
283
|
+
if (fs.existsSync(attestationFile)) {
|
|
284
|
+
const Database = cjsRequire('better-sqlite3');
|
|
285
|
+
const swarmDir = path.resolve(process.cwd(), '.swarm');
|
|
286
|
+
if (!fs.existsSync(swarmDir))
|
|
287
|
+
fs.mkdirSync(swarmDir, { recursive: true });
|
|
288
|
+
const dbPath = path.join(swarmDir, 'attestation.db');
|
|
289
|
+
const db = new Database(dbPath);
|
|
290
|
+
const url = pathToFileURL(attestationFile).href;
|
|
291
|
+
const mod = await import(url);
|
|
292
|
+
const Ctor = mod.AttestationLog;
|
|
293
|
+
if (typeof Ctor === 'function') {
|
|
294
|
+
const inst = new Ctor({ db });
|
|
295
|
+
attestationInst = inst;
|
|
296
|
+
if (typeof reg.set === 'function')
|
|
297
|
+
reg.set('attestationLog', inst);
|
|
298
|
+
else
|
|
299
|
+
reg._controllers = { ...(reg._controllers || {}), attestationLog: inst };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch { /* better-sqlite3 missing or schema init failed — skip silently */ }
|
|
304
|
+
}
|
|
305
|
+
// ADR-095 G7 follow-up: GuardedVectorBackend wraps the
|
|
306
|
+
// existing vectorBackend with mutationGuard + attestationLog
|
|
307
|
+
// for proof-gated state mutations (ADR-060). All three
|
|
308
|
+
// dependencies are reachable here — vectorBackend is in
|
|
309
|
+
// the baseline init, mutationGuard was just activated, and
|
|
310
|
+
// attestationLog is constructed above. Skip if any piece
|
|
311
|
+
// is missing rather than constructing with undefined.
|
|
312
|
+
if (!reg.get('guardedVectorBackend')) {
|
|
313
|
+
try {
|
|
314
|
+
const gvbFile = path.join(adbDir, 'dist/src/backends/ruvector/GuardedVectorBackend.js');
|
|
315
|
+
if (fs.existsSync(gvbFile)) {
|
|
316
|
+
const inner = reg.get('vectorBackend');
|
|
317
|
+
const guard = reg.get('mutationGuard');
|
|
318
|
+
const log = attestationInst ?? reg.get('attestationLog');
|
|
319
|
+
if (inner && guard) {
|
|
320
|
+
const url = pathToFileURL(gvbFile).href;
|
|
321
|
+
const mod = await import(url);
|
|
322
|
+
const Ctor = mod.GuardedVectorBackend;
|
|
323
|
+
if (typeof Ctor === 'function') {
|
|
324
|
+
const inst = new Ctor(inner, guard, log);
|
|
325
|
+
if (typeof reg.set === 'function')
|
|
326
|
+
reg.set('guardedVectorBackend', inst);
|
|
327
|
+
else
|
|
328
|
+
reg._controllers = { ...(reg._controllers || {}), guardedVectorBackend: inst };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch { /* GuardedVectorBackend optional */ }
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch { /* G7 wiring optional */ }
|
|
338
|
+
})();
|
|
339
|
+
// Run both in parallel; settle either way so a single failing
|
|
340
|
+
// path doesn't tear down the rest of the post-init wiring.
|
|
341
|
+
await Promise.allSettled([intelligencePromise, agentdbPromise]);
|
|
342
|
+
// Remaining disabled controllers tracked in ADR-095 G7 for
|
|
343
|
+
// per-controller activation ADRs:
|
|
344
|
+
// - graphAdapter (graph DB adapter — needs graph DB connection)
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// Top-level catch — registry stays usable even if post-init wiring fails wholesale.
|
|
348
|
+
}
|
|
349
|
+
registryInstance = registry;
|
|
350
|
+
bridgeAvailable = true;
|
|
351
|
+
return registry;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
bridgeAvailable = false;
|
|
355
|
+
registryPromise = null;
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
})();
|
|
359
|
+
}
|
|
360
|
+
return registryPromise;
|
|
361
|
+
}
|
|
362
|
+
// ===== Phase 2: BM25 hybrid scoring =====
|
|
363
|
+
/**
|
|
364
|
+
* BM25 scoring for keyword-based search.
|
|
365
|
+
* Replaces naive String.includes() with proper information retrieval scoring.
|
|
366
|
+
* Parameters tuned for short memory entries (k1=1.2, b=0.75).
|
|
367
|
+
*/
|
|
368
|
+
function bm25Score(queryTerms, docContent, avgDocLength, docCount, termDocFreqs) {
|
|
369
|
+
const k1 = 1.2;
|
|
370
|
+
const b = 0.75;
|
|
371
|
+
const docWords = docContent.toLowerCase().split(/\s+/);
|
|
372
|
+
const docLength = docWords.length;
|
|
373
|
+
let score = 0;
|
|
374
|
+
for (const term of queryTerms) {
|
|
375
|
+
const tf = docWords.filter(w => w === term || w.includes(term)).length;
|
|
376
|
+
if (tf === 0)
|
|
377
|
+
continue;
|
|
378
|
+
const df = termDocFreqs.get(term) || 1;
|
|
379
|
+
const idf = Math.log((docCount - df + 0.5) / (df + 0.5) + 1);
|
|
380
|
+
const tfNorm = (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * (docLength / Math.max(1, avgDocLength))));
|
|
381
|
+
score += idf * tfNorm;
|
|
382
|
+
}
|
|
383
|
+
return score;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Compute BM25 term document frequencies for a set of rows.
|
|
387
|
+
*/
|
|
388
|
+
function computeTermDocFreqs(queryTerms, rows) {
|
|
389
|
+
const termDocFreqs = new Map();
|
|
390
|
+
let totalLength = 0;
|
|
391
|
+
for (const row of rows) {
|
|
392
|
+
const content = (row.content || '').toLowerCase();
|
|
393
|
+
const words = content.split(/\s+/);
|
|
394
|
+
totalLength += words.length;
|
|
395
|
+
for (const term of queryTerms) {
|
|
396
|
+
if (content.includes(term)) {
|
|
397
|
+
termDocFreqs.set(term, (termDocFreqs.get(term) || 0) + 1);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return { termDocFreqs, avgDocLength: rows.length > 0 ? totalLength / rows.length : 1 };
|
|
402
|
+
}
|
|
403
|
+
// ===== Phase 2: TieredCache helpers =====
|
|
404
|
+
/**
|
|
405
|
+
* Try to read from TieredCache before hitting DB.
|
|
406
|
+
* Returns cached value or null if cache miss.
|
|
407
|
+
*/
|
|
408
|
+
async function cacheGet(registry, cacheKey) {
|
|
409
|
+
try {
|
|
410
|
+
const cache = registry.get('tieredCache');
|
|
411
|
+
if (!cache || typeof cache.get !== 'function')
|
|
412
|
+
return null;
|
|
413
|
+
return cache.get(cacheKey) ?? null;
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Write to TieredCache after DB write.
|
|
421
|
+
*/
|
|
422
|
+
async function cacheSet(registry, cacheKey, value) {
|
|
423
|
+
try {
|
|
424
|
+
const cache = registry.get('tieredCache');
|
|
425
|
+
if (cache && typeof cache.set === 'function') {
|
|
426
|
+
cache.set(cacheKey, value);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
// Non-fatal
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Invalidate a cache key after mutation.
|
|
435
|
+
*/
|
|
436
|
+
async function cacheInvalidate(registry, cacheKey) {
|
|
437
|
+
try {
|
|
438
|
+
const cache = registry.get('tieredCache');
|
|
439
|
+
if (cache && typeof cache.delete === 'function') {
|
|
440
|
+
cache.delete(cacheKey);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
// Non-fatal
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// ===== Phase 2: MutationGuard helpers =====
|
|
448
|
+
/**
|
|
449
|
+
* Validate a mutation through MutationGuard before executing.
|
|
450
|
+
* Returns true if the mutation is allowed, false if rejected.
|
|
451
|
+
* When guard is unavailable (not installed), mutations are allowed.
|
|
452
|
+
* When guard is present but throws, mutations are DENIED (fail-closed).
|
|
453
|
+
*/
|
|
454
|
+
async function guardValidate(registry, operation, params) {
|
|
455
|
+
try {
|
|
456
|
+
const guard = registry.get('mutationGuard');
|
|
457
|
+
if (!guard || typeof guard.validate !== 'function') {
|
|
458
|
+
return { allowed: true }; // No guard installed = allow (degraded mode)
|
|
459
|
+
}
|
|
460
|
+
const result = guard.validate({ operation, params, timestamp: Date.now() });
|
|
461
|
+
return { allowed: result?.allowed === true, reason: result?.reason };
|
|
462
|
+
}
|
|
463
|
+
catch {
|
|
464
|
+
return { allowed: false, reason: 'MutationGuard validation error' }; // Fail-closed
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
// ===== Phase 3: AttestationLog helpers =====
|
|
468
|
+
/**
|
|
469
|
+
* Log a write operation to AttestationLog/WitnessChain.
|
|
470
|
+
*/
|
|
471
|
+
async function logAttestation(registry, operation, entryId, metadata) {
|
|
472
|
+
try {
|
|
473
|
+
const attestation = registry.get('attestationLog');
|
|
474
|
+
if (!attestation)
|
|
475
|
+
return;
|
|
476
|
+
if (typeof attestation.record === 'function') {
|
|
477
|
+
attestation.record({ operation, entryId, timestamp: Date.now(), ...metadata });
|
|
478
|
+
}
|
|
479
|
+
else if (typeof attestation.log === 'function') {
|
|
480
|
+
attestation.log(operation, entryId, metadata);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
// Non-fatal — attestation is observability, not correctness
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Get the AgentDB database handle and ensure memory_entries table exists.
|
|
489
|
+
* Returns null if not available.
|
|
490
|
+
*/
|
|
491
|
+
function getDb(registry) {
|
|
492
|
+
const agentdb = registry.getAgentDB();
|
|
493
|
+
if (!agentdb?.database)
|
|
494
|
+
return null;
|
|
495
|
+
const db = agentdb.database;
|
|
496
|
+
// Ensure memory_entries table exists (idempotent)
|
|
497
|
+
try {
|
|
498
|
+
db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
|
|
499
|
+
id TEXT PRIMARY KEY,
|
|
500
|
+
key TEXT NOT NULL,
|
|
501
|
+
namespace TEXT DEFAULT 'default',
|
|
502
|
+
content TEXT NOT NULL,
|
|
503
|
+
type TEXT DEFAULT 'semantic',
|
|
504
|
+
embedding TEXT,
|
|
505
|
+
embedding_model TEXT DEFAULT 'local',
|
|
506
|
+
embedding_dimensions INTEGER,
|
|
507
|
+
tags TEXT,
|
|
508
|
+
metadata TEXT,
|
|
509
|
+
owner_id TEXT,
|
|
510
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
|
|
511
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
|
|
512
|
+
expires_at INTEGER,
|
|
513
|
+
last_accessed_at INTEGER,
|
|
514
|
+
access_count INTEGER DEFAULT 0,
|
|
515
|
+
status TEXT DEFAULT 'active',
|
|
516
|
+
UNIQUE(namespace, key)
|
|
517
|
+
)`);
|
|
518
|
+
// Ensure indexes
|
|
519
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_ns ON memory_entries(namespace)`);
|
|
520
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_key ON memory_entries(key)`);
|
|
521
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_status ON memory_entries(status)`);
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
// Table already exists or db is read-only — that's fine
|
|
525
|
+
}
|
|
526
|
+
return { db, agentdb };
|
|
527
|
+
}
|
|
528
|
+
// ===== Bridge functions — match memory-initializer.ts signatures =====
|
|
529
|
+
/**
|
|
530
|
+
* Store an entry via AgentDB v3.
|
|
531
|
+
* Phase 2-5: Routes through MutationGuard → TieredCache → DB → AttestationLog.
|
|
532
|
+
* Returns null to signal fallback to sql.js.
|
|
533
|
+
*/
|
|
534
|
+
export async function bridgeStoreEntry(options) {
|
|
535
|
+
const registry = await getRegistry(options.dbPath);
|
|
536
|
+
if (!registry)
|
|
537
|
+
return null;
|
|
538
|
+
const ctx = getDb(registry);
|
|
539
|
+
if (!ctx)
|
|
540
|
+
return null;
|
|
541
|
+
try {
|
|
542
|
+
const { key, value, namespace = 'default', tags = [], ttl } = options;
|
|
543
|
+
const id = generateId('entry');
|
|
544
|
+
const now = Date.now();
|
|
545
|
+
// Phase 5: MutationGuard validation before write
|
|
546
|
+
const guardResult = await guardValidate(registry, 'store', { key, namespace, size: value.length });
|
|
547
|
+
if (!guardResult.allowed) {
|
|
548
|
+
return { success: false, id, error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
549
|
+
}
|
|
550
|
+
// Generate embedding via AgentDB's embedder
|
|
551
|
+
let embeddingJson = null;
|
|
552
|
+
let dimensions = 0;
|
|
553
|
+
let model = 'local';
|
|
554
|
+
if (options.generateEmbeddingFlag !== false && value.length > 0) {
|
|
555
|
+
try {
|
|
556
|
+
const embedder = ctx.agentdb.embedder;
|
|
557
|
+
if (embedder) {
|
|
558
|
+
const emb = await embedder.embed(value);
|
|
559
|
+
if (emb) {
|
|
560
|
+
embeddingJson = JSON.stringify(Array.from(emb));
|
|
561
|
+
dimensions = emb.length;
|
|
562
|
+
model = 'Xenova/all-MiniLM-L6-v2';
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
// Embedding failed — store without
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
// better-sqlite3 uses synchronous .run() with positional params
|
|
571
|
+
const insertSql = options.upsert
|
|
572
|
+
? `INSERT OR REPLACE INTO memory_entries (
|
|
573
|
+
id, key, namespace, content, type,
|
|
574
|
+
embedding, embedding_dimensions, embedding_model,
|
|
575
|
+
tags, metadata, created_at, updated_at, expires_at, status
|
|
576
|
+
) VALUES (?, ?, ?, ?, 'semantic', ?, ?, ?, ?, ?, ?, ?, ?, 'active')`
|
|
577
|
+
: `INSERT INTO memory_entries (
|
|
578
|
+
id, key, namespace, content, type,
|
|
579
|
+
embedding, embedding_dimensions, embedding_model,
|
|
580
|
+
tags, metadata, created_at, updated_at, expires_at, status
|
|
581
|
+
) VALUES (?, ?, ?, ?, 'semantic', ?, ?, ?, ?, ?, ?, ?, ?, 'active')`;
|
|
582
|
+
// #1941: provision a `vector_indexes` row for this namespace before the
|
|
583
|
+
// entry insert. AgentDB's HNSW/router keys lookups by namespace via this
|
|
584
|
+
// table — if it has no row for e.g. `claude-memories`, `memory_search`
|
|
585
|
+
// returns 0 results even when memory_entries holds hundreds of rows for
|
|
586
|
+
// that namespace. INSERT OR IGNORE so existing index rows are preserved.
|
|
587
|
+
try {
|
|
588
|
+
ctx.db
|
|
589
|
+
.prepare(`INSERT OR IGNORE INTO vector_indexes (id, name, dimensions) VALUES (?, ?, ?)`)
|
|
590
|
+
.run(namespace, namespace, dimensions || 384);
|
|
591
|
+
}
|
|
592
|
+
catch { /* vector_indexes may not exist on legacy DBs — fall through */ }
|
|
593
|
+
const stmt = ctx.db.prepare(insertSql);
|
|
594
|
+
stmt.run(id, key, namespace, value, embeddingJson, dimensions || null, model, tags.length > 0 ? JSON.stringify(tags) : null, '{}', now, now, ttl ? now + (ttl * 1000) : null);
|
|
595
|
+
// Phase 2: Write-through to TieredCache
|
|
596
|
+
const safeNs = String(namespace).replace(/:/g, '_');
|
|
597
|
+
const safeKey = String(key).replace(/:/g, '_');
|
|
598
|
+
const cacheKey = `entry:${safeNs}:${safeKey}`;
|
|
599
|
+
await cacheSet(registry, cacheKey, { id, key, namespace, content: value, embedding: embeddingJson });
|
|
600
|
+
// Phase 4: AttestationLog write audit
|
|
601
|
+
await logAttestation(registry, 'store', id, { key, namespace, hasEmbedding: !!embeddingJson });
|
|
602
|
+
return {
|
|
603
|
+
success: true,
|
|
604
|
+
id,
|
|
605
|
+
embedding: embeddingJson ? { dimensions, model } : undefined,
|
|
606
|
+
rawEmbedding: embeddingJson ? JSON.parse(embeddingJson) : undefined,
|
|
607
|
+
guarded: true,
|
|
608
|
+
cached: true,
|
|
609
|
+
attested: true,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
catch {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Search entries via AgentDB v3.
|
|
618
|
+
* Phase 2: BM25 hybrid scoring replaces naive String.includes() keyword fallback.
|
|
619
|
+
* Combines cosine similarity (semantic) with BM25 (lexical) via reciprocal rank fusion.
|
|
620
|
+
*/
|
|
621
|
+
export async function bridgeSearchEntries(options) {
|
|
622
|
+
const registry = await getRegistry(options.dbPath);
|
|
623
|
+
if (!registry)
|
|
624
|
+
return null;
|
|
625
|
+
const ctx = getDb(registry);
|
|
626
|
+
if (!ctx)
|
|
627
|
+
return null;
|
|
628
|
+
try {
|
|
629
|
+
const { query: queryStr, namespace, limit = 10, threshold = 0.3 } = options;
|
|
630
|
+
const effectiveNamespace = namespace || 'all';
|
|
631
|
+
const startTime = Date.now();
|
|
632
|
+
// Generate query embedding
|
|
633
|
+
let queryEmbedding = null;
|
|
634
|
+
try {
|
|
635
|
+
const embedder = ctx.agentdb.embedder;
|
|
636
|
+
if (embedder) {
|
|
637
|
+
const emb = await embedder.embed(queryStr);
|
|
638
|
+
queryEmbedding = Array.from(emb);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
catch {
|
|
642
|
+
// Fall back to keyword search
|
|
643
|
+
}
|
|
644
|
+
// better-sqlite3: .prepare().all() returns array of objects
|
|
645
|
+
const nsFilter = effectiveNamespace !== 'all'
|
|
646
|
+
? `AND namespace = ?`
|
|
647
|
+
: '';
|
|
648
|
+
let rows;
|
|
649
|
+
try {
|
|
650
|
+
const stmt = ctx.db.prepare(`
|
|
651
|
+
SELECT id, key, namespace, content, embedding
|
|
652
|
+
FROM memory_entries
|
|
653
|
+
WHERE status = 'active' ${nsFilter}
|
|
654
|
+
LIMIT 1000
|
|
655
|
+
`);
|
|
656
|
+
rows = effectiveNamespace !== 'all' ? stmt.all(effectiveNamespace) : stmt.all();
|
|
657
|
+
}
|
|
658
|
+
catch {
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
// Phase 2: Compute BM25 term stats for the corpus
|
|
662
|
+
const queryTerms = queryStr.toLowerCase().split(/\s+/).filter(t => t.length > 1);
|
|
663
|
+
const { termDocFreqs, avgDocLength } = computeTermDocFreqs(queryTerms, rows);
|
|
664
|
+
const docCount = rows.length;
|
|
665
|
+
const results = [];
|
|
666
|
+
for (const row of rows) {
|
|
667
|
+
let semanticScore = 0;
|
|
668
|
+
let bm25ScoreVal = 0;
|
|
669
|
+
// Semantic scoring via cosine similarity
|
|
670
|
+
if (queryEmbedding && row.embedding) {
|
|
671
|
+
try {
|
|
672
|
+
const embedding = JSON.parse(row.embedding);
|
|
673
|
+
semanticScore = cosineSim(queryEmbedding, embedding);
|
|
674
|
+
}
|
|
675
|
+
catch {
|
|
676
|
+
// Invalid embedding
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
// Phase 2: BM25 keyword scoring (replaces String.includes fallback)
|
|
680
|
+
if (queryTerms.length > 0 && row.content) {
|
|
681
|
+
bm25ScoreVal = bm25Score(queryTerms, row.content, avgDocLength, docCount, termDocFreqs);
|
|
682
|
+
// Normalize BM25 to 0-1 range (cap at 10 for normalization)
|
|
683
|
+
bm25ScoreVal = Math.min(bm25ScoreVal / 10, 1.0);
|
|
684
|
+
}
|
|
685
|
+
// Reciprocal rank fusion: combine semantic and BM25
|
|
686
|
+
// Weight: 0.7 semantic + 0.3 BM25 when both embeddings present
|
|
687
|
+
// Fall back to BM25-only when either query or row lacks an embedding
|
|
688
|
+
const score = semanticScore > 0
|
|
689
|
+
? (0.7 * semanticScore + 0.3 * bm25ScoreVal)
|
|
690
|
+
: bm25ScoreVal;
|
|
691
|
+
if (score >= threshold) {
|
|
692
|
+
// Phase 4: ExplainableRecall provenance
|
|
693
|
+
const provenance = queryEmbedding
|
|
694
|
+
? `semantic:${semanticScore.toFixed(3)}+bm25:${bm25ScoreVal.toFixed(3)}`
|
|
695
|
+
: `bm25:${bm25ScoreVal.toFixed(3)}`;
|
|
696
|
+
results.push({
|
|
697
|
+
id: String(row.id).substring(0, 12),
|
|
698
|
+
key: row.key || String(row.id).substring(0, 15),
|
|
699
|
+
content: (row.content || '').substring(0, 60) + ((row.content || '').length > 60 ? '...' : ''),
|
|
700
|
+
score,
|
|
701
|
+
namespace: row.namespace || 'default',
|
|
702
|
+
provenance,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
results.sort((a, b) => b.score - a.score);
|
|
707
|
+
return {
|
|
708
|
+
success: true,
|
|
709
|
+
results: results.slice(0, limit),
|
|
710
|
+
searchTime: Date.now() - startTime,
|
|
711
|
+
searchMethod: queryEmbedding ? 'hybrid-bm25-semantic' : 'bm25-only',
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
catch {
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* List entries via AgentDB v3.
|
|
720
|
+
*/
|
|
721
|
+
export async function bridgeListEntries(options) {
|
|
722
|
+
const registry = await getRegistry(options.dbPath);
|
|
723
|
+
if (!registry)
|
|
724
|
+
return null;
|
|
725
|
+
const ctx = getDb(registry);
|
|
726
|
+
if (!ctx)
|
|
727
|
+
return null;
|
|
728
|
+
try {
|
|
729
|
+
const { namespace, limit = 20, offset = 0 } = options;
|
|
730
|
+
const nsFilter = namespace ? `AND namespace = ?` : '';
|
|
731
|
+
const nsParams = namespace ? [namespace] : [];
|
|
732
|
+
// Count
|
|
733
|
+
let total = 0;
|
|
734
|
+
try {
|
|
735
|
+
const countStmt = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' ${nsFilter}`);
|
|
736
|
+
const countRow = countStmt.get(...nsParams);
|
|
737
|
+
total = countRow?.cnt ?? 0;
|
|
738
|
+
}
|
|
739
|
+
catch {
|
|
740
|
+
return null;
|
|
741
|
+
}
|
|
742
|
+
// List
|
|
743
|
+
const entries = [];
|
|
744
|
+
try {
|
|
745
|
+
const stmt = ctx.db.prepare(`
|
|
746
|
+
SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at
|
|
747
|
+
FROM memory_entries
|
|
748
|
+
WHERE status = 'active' ${nsFilter}
|
|
749
|
+
ORDER BY updated_at DESC
|
|
750
|
+
LIMIT ? OFFSET ?
|
|
751
|
+
`);
|
|
752
|
+
const rows = stmt.all(...nsParams, limit, offset);
|
|
753
|
+
for (const row of rows) {
|
|
754
|
+
entries.push({
|
|
755
|
+
id: String(row.id).substring(0, 20),
|
|
756
|
+
key: row.key || String(row.id).substring(0, 15),
|
|
757
|
+
namespace: row.namespace || 'default',
|
|
758
|
+
size: (row.content || '').length,
|
|
759
|
+
accessCount: row.access_count ?? 0,
|
|
760
|
+
createdAt: row.created_at || new Date().toISOString(),
|
|
761
|
+
updatedAt: row.updated_at || new Date().toISOString(),
|
|
762
|
+
hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
catch {
|
|
767
|
+
return null;
|
|
768
|
+
}
|
|
769
|
+
return { success: true, entries, total };
|
|
770
|
+
}
|
|
771
|
+
catch {
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Get a specific entry via AgentDB v3.
|
|
777
|
+
* Phase 2: TieredCache consulted before DB hit.
|
|
778
|
+
*/
|
|
779
|
+
export async function bridgeGetEntry(options) {
|
|
780
|
+
const registry = await getRegistry(options.dbPath);
|
|
781
|
+
if (!registry)
|
|
782
|
+
return null;
|
|
783
|
+
const ctx = getDb(registry);
|
|
784
|
+
if (!ctx)
|
|
785
|
+
return null;
|
|
786
|
+
try {
|
|
787
|
+
const { key, namespace = 'default' } = options;
|
|
788
|
+
// Phase 2: Check TieredCache first
|
|
789
|
+
const safeNs = String(namespace).replace(/:/g, '_');
|
|
790
|
+
const safeKey = String(key).replace(/:/g, '_');
|
|
791
|
+
const cacheKey = `entry:${safeNs}:${safeKey}`;
|
|
792
|
+
const cached = await cacheGet(registry, cacheKey);
|
|
793
|
+
if (cached && cached.content) {
|
|
794
|
+
return {
|
|
795
|
+
success: true,
|
|
796
|
+
found: true,
|
|
797
|
+
cacheHit: true,
|
|
798
|
+
entry: {
|
|
799
|
+
id: String(cached.id || ''),
|
|
800
|
+
key: cached.key || key,
|
|
801
|
+
namespace: cached.namespace || namespace,
|
|
802
|
+
content: cached.content || '',
|
|
803
|
+
accessCount: cached.accessCount ?? 0,
|
|
804
|
+
createdAt: cached.createdAt || new Date().toISOString(),
|
|
805
|
+
updatedAt: cached.updatedAt || new Date().toISOString(),
|
|
806
|
+
hasEmbedding: !!cached.embedding,
|
|
807
|
+
tags: cached.tags || [],
|
|
808
|
+
},
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
let row;
|
|
812
|
+
try {
|
|
813
|
+
const stmt = ctx.db.prepare(`
|
|
814
|
+
SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
|
|
815
|
+
FROM memory_entries
|
|
816
|
+
WHERE status = 'active' AND key = ? AND namespace = ?
|
|
817
|
+
LIMIT 1
|
|
818
|
+
`);
|
|
819
|
+
row = stmt.get(key, namespace);
|
|
820
|
+
}
|
|
821
|
+
catch {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
if (!row) {
|
|
825
|
+
return { success: true, found: false };
|
|
826
|
+
}
|
|
827
|
+
// Update access count
|
|
828
|
+
try {
|
|
829
|
+
ctx.db.prepare(`UPDATE memory_entries SET access_count = access_count + 1, last_accessed_at = ? WHERE id = ?`).run(Date.now(), row.id);
|
|
830
|
+
}
|
|
831
|
+
catch {
|
|
832
|
+
// Non-fatal
|
|
833
|
+
}
|
|
834
|
+
let tags = [];
|
|
835
|
+
if (row.tags) {
|
|
836
|
+
try {
|
|
837
|
+
tags = JSON.parse(row.tags);
|
|
838
|
+
}
|
|
839
|
+
catch { /* invalid */ }
|
|
840
|
+
}
|
|
841
|
+
const entry = {
|
|
842
|
+
id: String(row.id),
|
|
843
|
+
key: row.key || String(row.id),
|
|
844
|
+
namespace: row.namespace || 'default',
|
|
845
|
+
content: row.content || '',
|
|
846
|
+
accessCount: (row.access_count ?? 0) + 1,
|
|
847
|
+
createdAt: row.created_at || new Date().toISOString(),
|
|
848
|
+
updatedAt: row.updated_at || new Date().toISOString(),
|
|
849
|
+
hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
|
|
850
|
+
tags,
|
|
851
|
+
};
|
|
852
|
+
// Phase 2: Populate cache for next read
|
|
853
|
+
await cacheSet(registry, cacheKey, entry);
|
|
854
|
+
return { success: true, found: true, cacheHit: false, entry };
|
|
855
|
+
}
|
|
856
|
+
catch {
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Delete an entry via AgentDB v3.
|
|
862
|
+
* Phase 5: MutationGuard validation, cache invalidation, attestation logging.
|
|
863
|
+
*/
|
|
864
|
+
export async function bridgeDeleteEntry(options) {
|
|
865
|
+
const registry = await getRegistry(options.dbPath);
|
|
866
|
+
if (!registry)
|
|
867
|
+
return null;
|
|
868
|
+
const ctx = getDb(registry);
|
|
869
|
+
if (!ctx)
|
|
870
|
+
return null;
|
|
871
|
+
try {
|
|
872
|
+
const { key, namespace = 'default' } = options;
|
|
873
|
+
// Phase 5: MutationGuard validation before delete
|
|
874
|
+
const guardResult = await guardValidate(registry, 'delete', { key, namespace });
|
|
875
|
+
if (!guardResult.allowed) {
|
|
876
|
+
return { success: false, deleted: false, key, namespace, remainingEntries: 0, error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
877
|
+
}
|
|
878
|
+
// Soft delete using parameterized query
|
|
879
|
+
let changes = 0;
|
|
880
|
+
try {
|
|
881
|
+
const result = ctx.db.prepare(`
|
|
882
|
+
UPDATE memory_entries
|
|
883
|
+
SET status = 'deleted', updated_at = ?
|
|
884
|
+
WHERE key = ? AND namespace = ? AND status = 'active'
|
|
885
|
+
`).run(Date.now(), key, namespace);
|
|
886
|
+
changes = result?.changes ?? 0;
|
|
887
|
+
}
|
|
888
|
+
catch {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
// Phase 2: Invalidate cache
|
|
892
|
+
const safeNs = String(namespace).replace(/:/g, '_');
|
|
893
|
+
const safeKey = String(key).replace(/:/g, '_');
|
|
894
|
+
await cacheInvalidate(registry, `entry:${safeNs}:${safeKey}`);
|
|
895
|
+
// Phase 4: AttestationLog delete audit
|
|
896
|
+
if (changes > 0) {
|
|
897
|
+
await logAttestation(registry, 'delete', key, { namespace });
|
|
898
|
+
}
|
|
899
|
+
let remaining = 0;
|
|
900
|
+
try {
|
|
901
|
+
const row = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`).get();
|
|
902
|
+
remaining = row?.cnt ?? 0;
|
|
903
|
+
}
|
|
904
|
+
catch {
|
|
905
|
+
// Non-fatal
|
|
906
|
+
}
|
|
907
|
+
return {
|
|
908
|
+
success: true,
|
|
909
|
+
deleted: changes > 0,
|
|
910
|
+
key,
|
|
911
|
+
namespace,
|
|
912
|
+
remainingEntries: remaining,
|
|
913
|
+
guarded: true,
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
catch {
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
// ===== Phase 2: Embedding bridge =====
|
|
921
|
+
/**
|
|
922
|
+
* Generate embedding via AgentDB v3's embedder.
|
|
923
|
+
* Returns null if bridge unavailable — caller falls back to own ONNX/hash.
|
|
924
|
+
*/
|
|
925
|
+
export async function bridgeGenerateEmbedding(text, dbPath) {
|
|
926
|
+
const registry = await getRegistry(dbPath);
|
|
927
|
+
if (!registry)
|
|
928
|
+
return null;
|
|
929
|
+
try {
|
|
930
|
+
const agentdb = registry.getAgentDB();
|
|
931
|
+
const embedder = agentdb?.embedder;
|
|
932
|
+
if (!embedder)
|
|
933
|
+
return null;
|
|
934
|
+
const emb = await embedder.embed(text);
|
|
935
|
+
if (!emb)
|
|
936
|
+
return null;
|
|
937
|
+
return {
|
|
938
|
+
embedding: Array.from(emb),
|
|
939
|
+
dimensions: emb.length,
|
|
940
|
+
model: 'Xenova/all-MiniLM-L6-v2',
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
catch {
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Load embedding model via AgentDB v3 (it loads on init).
|
|
949
|
+
* Returns null if unavailable.
|
|
950
|
+
*/
|
|
951
|
+
export async function bridgeLoadEmbeddingModel(dbPath) {
|
|
952
|
+
const startTime = Date.now();
|
|
953
|
+
const registry = await getRegistry(dbPath);
|
|
954
|
+
if (!registry)
|
|
955
|
+
return null;
|
|
956
|
+
try {
|
|
957
|
+
const agentdb = registry.getAgentDB();
|
|
958
|
+
const embedder = agentdb?.embedder;
|
|
959
|
+
if (!embedder)
|
|
960
|
+
return null;
|
|
961
|
+
// Verify embedder works by generating a test embedding
|
|
962
|
+
const test = await embedder.embed('test');
|
|
963
|
+
if (!test)
|
|
964
|
+
return null;
|
|
965
|
+
return {
|
|
966
|
+
success: true,
|
|
967
|
+
dimensions: test.length,
|
|
968
|
+
modelName: 'Xenova/all-MiniLM-L6-v2',
|
|
969
|
+
loadTime: Date.now() - startTime,
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
catch {
|
|
973
|
+
return null;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
// ===== Phase 3: HNSW bridge =====
|
|
977
|
+
/**
|
|
978
|
+
* Get HNSW status from AgentDB v3's vector backend or HNSW index.
|
|
979
|
+
* Returns null if unavailable.
|
|
980
|
+
*/
|
|
981
|
+
export async function bridgeGetHNSWStatus(dbPath) {
|
|
982
|
+
const registry = await getRegistry(dbPath);
|
|
983
|
+
if (!registry)
|
|
984
|
+
return null;
|
|
985
|
+
try {
|
|
986
|
+
const ctx = getDb(registry);
|
|
987
|
+
if (!ctx)
|
|
988
|
+
return null;
|
|
989
|
+
// Count entries with embeddings
|
|
990
|
+
let entryCount = 0;
|
|
991
|
+
try {
|
|
992
|
+
const row = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND embedding IS NOT NULL`).get();
|
|
993
|
+
entryCount = row?.cnt ?? 0;
|
|
994
|
+
}
|
|
995
|
+
catch {
|
|
996
|
+
// Table might not exist
|
|
997
|
+
}
|
|
998
|
+
return {
|
|
999
|
+
available: true,
|
|
1000
|
+
initialized: true,
|
|
1001
|
+
entryCount,
|
|
1002
|
+
dimensions: 384,
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
catch {
|
|
1006
|
+
return null;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Search using AgentDB v3's embedder + SQLite entries.
|
|
1011
|
+
* This is the HNSW-equivalent search through the bridge.
|
|
1012
|
+
* Returns null if unavailable.
|
|
1013
|
+
*/
|
|
1014
|
+
export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
|
|
1015
|
+
const registry = await getRegistry(dbPath);
|
|
1016
|
+
if (!registry)
|
|
1017
|
+
return null;
|
|
1018
|
+
const ctx = getDb(registry);
|
|
1019
|
+
if (!ctx)
|
|
1020
|
+
return null;
|
|
1021
|
+
try {
|
|
1022
|
+
const k = options?.k ?? 10;
|
|
1023
|
+
const threshold = options?.threshold ?? 0.3;
|
|
1024
|
+
const nsFilter = options?.namespace && options.namespace !== 'all'
|
|
1025
|
+
? `AND namespace = ?`
|
|
1026
|
+
: '';
|
|
1027
|
+
let rows;
|
|
1028
|
+
try {
|
|
1029
|
+
const stmt = ctx.db.prepare(`
|
|
1030
|
+
SELECT id, key, namespace, content, embedding
|
|
1031
|
+
FROM memory_entries
|
|
1032
|
+
WHERE status = 'active' AND embedding IS NOT NULL ${nsFilter}
|
|
1033
|
+
LIMIT 10000
|
|
1034
|
+
`);
|
|
1035
|
+
rows = nsFilter
|
|
1036
|
+
? stmt.all(options.namespace)
|
|
1037
|
+
: stmt.all();
|
|
1038
|
+
}
|
|
1039
|
+
catch {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
const results = [];
|
|
1043
|
+
for (const row of rows) {
|
|
1044
|
+
if (!row.embedding)
|
|
1045
|
+
continue;
|
|
1046
|
+
try {
|
|
1047
|
+
const emb = JSON.parse(row.embedding);
|
|
1048
|
+
const score = cosineSim(queryEmbedding, emb);
|
|
1049
|
+
if (score >= threshold) {
|
|
1050
|
+
results.push({
|
|
1051
|
+
id: String(row.id).substring(0, 12),
|
|
1052
|
+
key: row.key || String(row.id).substring(0, 15),
|
|
1053
|
+
content: (row.content || '').substring(0, 60) +
|
|
1054
|
+
((row.content || '').length > 60 ? '...' : ''),
|
|
1055
|
+
score,
|
|
1056
|
+
namespace: row.namespace || 'default',
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
catch {
|
|
1061
|
+
// Skip invalid embeddings
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
results.sort((a, b) => b.score - a.score);
|
|
1065
|
+
return results.slice(0, k);
|
|
1066
|
+
}
|
|
1067
|
+
catch {
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Add entry to the bridge's database with embedding.
|
|
1073
|
+
* Returns null if unavailable.
|
|
1074
|
+
*/
|
|
1075
|
+
export async function bridgeAddToHNSW(id, embedding, entry, dbPath) {
|
|
1076
|
+
const registry = await getRegistry(dbPath);
|
|
1077
|
+
if (!registry)
|
|
1078
|
+
return null;
|
|
1079
|
+
const ctx = getDb(registry);
|
|
1080
|
+
if (!ctx)
|
|
1081
|
+
return null;
|
|
1082
|
+
try {
|
|
1083
|
+
const now = Date.now();
|
|
1084
|
+
const embeddingJson = JSON.stringify(embedding);
|
|
1085
|
+
ctx.db.prepare(`
|
|
1086
|
+
INSERT OR REPLACE INTO memory_entries (
|
|
1087
|
+
id, key, namespace, content, type,
|
|
1088
|
+
embedding, embedding_dimensions, embedding_model,
|
|
1089
|
+
created_at, updated_at, status
|
|
1090
|
+
) VALUES (?, ?, ?, ?, 'semantic', ?, ?, 'Xenova/all-MiniLM-L6-v2', ?, ?, 'active')
|
|
1091
|
+
`).run(id, entry.key, entry.namespace, entry.content, embeddingJson, embedding.length, now, now);
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1094
|
+
catch {
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
// ===== Phase 4: Controller access =====
|
|
1099
|
+
/**
|
|
1100
|
+
* Get a named controller from AgentDB v3 via ControllerRegistry.
|
|
1101
|
+
* Returns null if unavailable.
|
|
1102
|
+
*/
|
|
1103
|
+
export async function bridgeGetController(name, dbPath) {
|
|
1104
|
+
const registry = await getRegistry(dbPath);
|
|
1105
|
+
if (!registry)
|
|
1106
|
+
return null;
|
|
1107
|
+
try {
|
|
1108
|
+
return registry.get(name) ?? null;
|
|
1109
|
+
}
|
|
1110
|
+
catch {
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Check if a controller is available.
|
|
1116
|
+
*/
|
|
1117
|
+
export async function bridgeHasController(name, dbPath) {
|
|
1118
|
+
const registry = await getRegistry(dbPath);
|
|
1119
|
+
if (!registry)
|
|
1120
|
+
return false;
|
|
1121
|
+
try {
|
|
1122
|
+
const controller = registry.get(name);
|
|
1123
|
+
return controller !== null && controller !== undefined;
|
|
1124
|
+
}
|
|
1125
|
+
catch {
|
|
1126
|
+
return false;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* List all controllers and their status.
|
|
1131
|
+
*/
|
|
1132
|
+
export async function bridgeListControllers(dbPath) {
|
|
1133
|
+
const registry = await getRegistry(dbPath);
|
|
1134
|
+
if (!registry)
|
|
1135
|
+
return null;
|
|
1136
|
+
try {
|
|
1137
|
+
return registry.listControllers();
|
|
1138
|
+
}
|
|
1139
|
+
catch {
|
|
1140
|
+
return null;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Check if the AgentDB v3 bridge is available.
|
|
1145
|
+
*/
|
|
1146
|
+
export async function isBridgeAvailable(dbPath) {
|
|
1147
|
+
if (bridgeAvailable !== null)
|
|
1148
|
+
return bridgeAvailable;
|
|
1149
|
+
const registry = await getRegistry(dbPath);
|
|
1150
|
+
return registry !== null;
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Get the ControllerRegistry instance (for advanced consumers).
|
|
1154
|
+
*/
|
|
1155
|
+
export async function getControllerRegistry(dbPath) {
|
|
1156
|
+
return getRegistry(dbPath);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Shutdown the bridge and release resources.
|
|
1160
|
+
*/
|
|
1161
|
+
export async function shutdownBridge() {
|
|
1162
|
+
if (registryInstance) {
|
|
1163
|
+
try {
|
|
1164
|
+
await registryInstance.shutdown();
|
|
1165
|
+
}
|
|
1166
|
+
catch {
|
|
1167
|
+
// Best-effort
|
|
1168
|
+
}
|
|
1169
|
+
registryInstance = null;
|
|
1170
|
+
registryPromise = null;
|
|
1171
|
+
bridgeAvailable = null;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
// ===== Phase 3: ReasoningBank pattern operations =====
|
|
1175
|
+
/**
|
|
1176
|
+
* Store a pattern via ReasoningBank controller.
|
|
1177
|
+
* Falls back to raw SQL if ReasoningBank unavailable.
|
|
1178
|
+
*/
|
|
1179
|
+
export async function bridgeStorePattern(options) {
|
|
1180
|
+
const registry = await getRegistry(options.dbPath);
|
|
1181
|
+
if (!registry)
|
|
1182
|
+
return null;
|
|
1183
|
+
try {
|
|
1184
|
+
const reasoningBank = registry.get('reasoningBank');
|
|
1185
|
+
const patternId = generateId('pattern');
|
|
1186
|
+
if (reasoningBank && typeof reasoningBank.store === 'function') {
|
|
1187
|
+
await reasoningBank.store({
|
|
1188
|
+
id: patternId,
|
|
1189
|
+
content: options.pattern,
|
|
1190
|
+
type: options.type,
|
|
1191
|
+
confidence: options.confidence,
|
|
1192
|
+
metadata: options.metadata,
|
|
1193
|
+
timestamp: Date.now(),
|
|
1194
|
+
});
|
|
1195
|
+
return { success: true, patternId, controller: 'reasoningBank' };
|
|
1196
|
+
}
|
|
1197
|
+
// Fallback: store via bridge SQL
|
|
1198
|
+
const patternValue = JSON.stringify({ pattern: options.pattern, type: options.type, confidence: options.confidence, metadata: options.metadata });
|
|
1199
|
+
const result = await bridgeStoreEntry({
|
|
1200
|
+
key: patternId,
|
|
1201
|
+
value: patternValue,
|
|
1202
|
+
namespace: 'pattern',
|
|
1203
|
+
generateEmbeddingFlag: true,
|
|
1204
|
+
tags: [options.type, 'reasoning-pattern'],
|
|
1205
|
+
dbPath: options.dbPath,
|
|
1206
|
+
});
|
|
1207
|
+
if (!result)
|
|
1208
|
+
return null;
|
|
1209
|
+
// Add to HNSW index for fast semantic search (bridgeStoreEntry stores SQL only)
|
|
1210
|
+
if (result.rawEmbedding) {
|
|
1211
|
+
try {
|
|
1212
|
+
const { addToHNSWIndex } = await import('./memory-initializer.js');
|
|
1213
|
+
await addToHNSWIndex(result.id, result.rawEmbedding, {
|
|
1214
|
+
id: result.id,
|
|
1215
|
+
key: patternId,
|
|
1216
|
+
namespace: 'pattern',
|
|
1217
|
+
content: patternValue,
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
catch { /* HNSW is best-effort */ }
|
|
1221
|
+
}
|
|
1222
|
+
return { success: true, patternId: result.id, controller: 'bridge-fallback' };
|
|
1223
|
+
}
|
|
1224
|
+
catch {
|
|
1225
|
+
return null;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Search patterns via ReasoningBank controller.
|
|
1230
|
+
*/
|
|
1231
|
+
export async function bridgeSearchPatterns(options) {
|
|
1232
|
+
const registry = await getRegistry(options.dbPath);
|
|
1233
|
+
if (!registry)
|
|
1234
|
+
return null;
|
|
1235
|
+
try {
|
|
1236
|
+
const reasoningBank = registry.get('reasoningBank');
|
|
1237
|
+
// ReasoningBank may expose .searchPatterns() (agentdb) or .search() (legacy) (#1492 Bug 2)
|
|
1238
|
+
if (reasoningBank && typeof (reasoningBank.searchPatterns ?? reasoningBank.search) === 'function') {
|
|
1239
|
+
let results;
|
|
1240
|
+
if (typeof reasoningBank.searchPatterns === 'function') {
|
|
1241
|
+
results = await reasoningBank.searchPatterns({ task: options.query, k: options.topK || 5, threshold: options.minConfidence || 0.3 });
|
|
1242
|
+
}
|
|
1243
|
+
else {
|
|
1244
|
+
results = await reasoningBank.search(options.query, { topK: options.topK || 5, minScore: options.minConfidence || 0.3 });
|
|
1245
|
+
}
|
|
1246
|
+
return {
|
|
1247
|
+
results: Array.isArray(results) ? results.map((r) => ({
|
|
1248
|
+
id: r.id || r.patternId || '',
|
|
1249
|
+
content: r.content || r.pattern || '',
|
|
1250
|
+
score: r.score ?? r.confidence ?? 0,
|
|
1251
|
+
})) : [],
|
|
1252
|
+
controller: 'reasoningBank',
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
// Fallback: search via bridge
|
|
1256
|
+
const result = await bridgeSearchEntries({
|
|
1257
|
+
query: options.query,
|
|
1258
|
+
namespace: 'pattern',
|
|
1259
|
+
limit: options.topK || 5,
|
|
1260
|
+
threshold: options.minConfidence || 0.3,
|
|
1261
|
+
dbPath: options.dbPath,
|
|
1262
|
+
});
|
|
1263
|
+
return result ? {
|
|
1264
|
+
results: result.results.map(r => ({ id: r.id, content: r.content, score: r.score })),
|
|
1265
|
+
controller: 'bridge-fallback',
|
|
1266
|
+
} : null;
|
|
1267
|
+
}
|
|
1268
|
+
catch {
|
|
1269
|
+
return null;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
// ===== Phase 3: Feedback recording =====
|
|
1273
|
+
/**
|
|
1274
|
+
* Record task feedback for learning via ReasoningBank or LearningSystem.
|
|
1275
|
+
* Wired into hooks_post-task handler.
|
|
1276
|
+
*/
|
|
1277
|
+
export async function bridgeRecordFeedback(options) {
|
|
1278
|
+
const registry = await getRegistry(options.dbPath);
|
|
1279
|
+
if (!registry)
|
|
1280
|
+
return null;
|
|
1281
|
+
try {
|
|
1282
|
+
let controller = 'none';
|
|
1283
|
+
let updated = 0;
|
|
1284
|
+
// Try LearningSystem first (Phase 4)
|
|
1285
|
+
const learningSystem = registry.get('learningSystem');
|
|
1286
|
+
if (learningSystem) {
|
|
1287
|
+
try {
|
|
1288
|
+
if (typeof learningSystem.recordFeedback === 'function') {
|
|
1289
|
+
await learningSystem.recordFeedback({
|
|
1290
|
+
taskId: options.taskId, success: options.success, quality: options.quality,
|
|
1291
|
+
agent: options.agent, duration: options.duration, timestamp: Date.now(),
|
|
1292
|
+
});
|
|
1293
|
+
controller = 'learningSystem';
|
|
1294
|
+
updated++;
|
|
1295
|
+
}
|
|
1296
|
+
else if (typeof learningSystem.record === 'function') {
|
|
1297
|
+
await learningSystem.record(options.taskId, options.quality, options.success ? 'success' : 'failure');
|
|
1298
|
+
controller = 'learningSystem';
|
|
1299
|
+
updated++;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
catch { /* API mismatch — skip */ }
|
|
1303
|
+
}
|
|
1304
|
+
// Also record in ReasoningBank for pattern reinforcement
|
|
1305
|
+
const reasoningBank = registry.get('reasoningBank');
|
|
1306
|
+
if (reasoningBank) {
|
|
1307
|
+
try {
|
|
1308
|
+
if (typeof reasoningBank.recordOutcome === 'function') {
|
|
1309
|
+
await reasoningBank.recordOutcome({
|
|
1310
|
+
taskId: options.taskId, verdict: options.success ? 'success' : 'failure',
|
|
1311
|
+
score: options.quality, timestamp: Date.now(),
|
|
1312
|
+
});
|
|
1313
|
+
controller = controller === 'none' ? 'reasoningBank' : `${controller}+reasoningBank`;
|
|
1314
|
+
updated++;
|
|
1315
|
+
}
|
|
1316
|
+
else if (typeof reasoningBank.record === 'function') {
|
|
1317
|
+
await reasoningBank.record(options.taskId, options.quality);
|
|
1318
|
+
controller = controller === 'none' ? 'reasoningBank' : `${controller}+reasoningBank`;
|
|
1319
|
+
updated++;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
catch { /* API mismatch — skip */ }
|
|
1323
|
+
}
|
|
1324
|
+
// Phase 4: SkillLibrary promotion for high-quality patterns
|
|
1325
|
+
if (options.success && options.quality >= 0.9 && options.patterns?.length) {
|
|
1326
|
+
const skills = registry.get('skills');
|
|
1327
|
+
if (skills && typeof skills.promote === 'function') {
|
|
1328
|
+
for (const pattern of options.patterns) {
|
|
1329
|
+
try {
|
|
1330
|
+
await skills.promote(pattern, options.quality);
|
|
1331
|
+
updated++;
|
|
1332
|
+
}
|
|
1333
|
+
catch { /* skip */ }
|
|
1334
|
+
}
|
|
1335
|
+
controller += '+skills';
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
// Always store feedback as a memory entry for retrieval (ensures it persists)
|
|
1339
|
+
const storeResult = await bridgeStoreEntry({
|
|
1340
|
+
key: `feedback-${options.taskId}`,
|
|
1341
|
+
value: JSON.stringify(options),
|
|
1342
|
+
namespace: 'feedback',
|
|
1343
|
+
tags: [options.success ? 'success' : 'failure', options.agent || 'unknown'],
|
|
1344
|
+
dbPath: options.dbPath,
|
|
1345
|
+
});
|
|
1346
|
+
if (storeResult?.success) {
|
|
1347
|
+
controller = controller === 'none' ? 'bridge-store' : `${controller}+bridge-store`;
|
|
1348
|
+
updated++;
|
|
1349
|
+
}
|
|
1350
|
+
return { success: true, controller, updated };
|
|
1351
|
+
}
|
|
1352
|
+
catch {
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
// ===== Phase 3: CausalMemoryGraph =====
|
|
1357
|
+
/**
|
|
1358
|
+
* Record a causal edge between two entries (e.g., task → result).
|
|
1359
|
+
*/
|
|
1360
|
+
export async function bridgeRecordCausalEdge(options) {
|
|
1361
|
+
const registry = await getRegistry(options.dbPath);
|
|
1362
|
+
if (!registry)
|
|
1363
|
+
return null;
|
|
1364
|
+
try {
|
|
1365
|
+
const causalGraph = registry.get('causalGraph');
|
|
1366
|
+
if (causalGraph && typeof causalGraph.addEdge === 'function') {
|
|
1367
|
+
causalGraph.addEdge(options.sourceId, options.targetId, {
|
|
1368
|
+
relation: options.relation,
|
|
1369
|
+
weight: options.weight ?? 1.0,
|
|
1370
|
+
timestamp: Date.now(),
|
|
1371
|
+
});
|
|
1372
|
+
return { success: true, controller: 'causalGraph' };
|
|
1373
|
+
}
|
|
1374
|
+
// Fallback: store edge as metadata
|
|
1375
|
+
const ctx = getDb(registry);
|
|
1376
|
+
if (ctx) {
|
|
1377
|
+
try {
|
|
1378
|
+
ctx.db.prepare(`
|
|
1379
|
+
INSERT OR REPLACE INTO memory_entries (id, key, namespace, content, type, created_at, updated_at, status)
|
|
1380
|
+
VALUES (?, ?, 'causal-edges', ?, 'procedural', ?, ?, 'active')
|
|
1381
|
+
`).run(generateId('edge'), `${options.sourceId}→${options.targetId}`, JSON.stringify(options), Date.now(), Date.now());
|
|
1382
|
+
return { success: true, controller: 'bridge-fallback' };
|
|
1383
|
+
}
|
|
1384
|
+
catch { /* skip */ }
|
|
1385
|
+
}
|
|
1386
|
+
return null;
|
|
1387
|
+
}
|
|
1388
|
+
catch {
|
|
1389
|
+
return null;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
// ===== #1784: Delete tools for hierarchical + causal-graph =====
|
|
1393
|
+
/**
|
|
1394
|
+
* Delete a hierarchical-memory entry by key (#1784).
|
|
1395
|
+
*
|
|
1396
|
+
* Reality check: agentdb's HierarchicalMemory class doesn't expose a public
|
|
1397
|
+
* delete API today, so the real-backend path falls back to direct SQL on
|
|
1398
|
+
* the underlying SQLite tables (status flip to 'deleted' + AttestationLog
|
|
1399
|
+
* audit). The bridge-fallback path that bridgeHierarchicalStore uses when
|
|
1400
|
+
* HierarchicalMemory isn't loaded writes plain memory_entries rows that
|
|
1401
|
+
* `bridgeDeleteEntry` already handles.
|
|
1402
|
+
*
|
|
1403
|
+
* Returns { controller: 'native-unsupported' } when the real HM is loaded
|
|
1404
|
+
* and the SQL fallback can't reach its private tables — surfacing the
|
|
1405
|
+
* limitation honestly instead of silently returning success.
|
|
1406
|
+
*/
|
|
1407
|
+
export async function bridgeDeleteHierarchical(options) {
|
|
1408
|
+
const registry = await getRegistry(options.dbPath);
|
|
1409
|
+
if (!registry)
|
|
1410
|
+
return null;
|
|
1411
|
+
try {
|
|
1412
|
+
const { key, tier } = options;
|
|
1413
|
+
// MutationGuard validation
|
|
1414
|
+
const guardResult = await guardValidate(registry, 'delete', { key, namespace: 'hierarchical' });
|
|
1415
|
+
if (!guardResult.allowed) {
|
|
1416
|
+
return { success: false, deleted: false, key, tier, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
1417
|
+
}
|
|
1418
|
+
const hm = registry.get('hierarchicalMemory');
|
|
1419
|
+
// 1. agentdb@3.0.0-alpha.13+: ReflexionMemory.deleteEpisode propagates through
|
|
1420
|
+
// graph adapter / generic graph backend / vector backend AND purges SQL
|
|
1421
|
+
// episodes + episode_embeddings rows. Single call, durably consistent.
|
|
1422
|
+
// See agentic-flow#150/#151 (closes ruvnet/RuVector#427 the cli-visible way).
|
|
1423
|
+
const reflexion = registry.get('reflexionMemory');
|
|
1424
|
+
if (reflexion && typeof reflexion.deleteEpisode === 'function') {
|
|
1425
|
+
try {
|
|
1426
|
+
const removed = await reflexion.deleteEpisode(key);
|
|
1427
|
+
if (removed) {
|
|
1428
|
+
await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
|
|
1429
|
+
return { success: true, deleted: true, key, tier, controller: 'reflexionMemory', guarded: true };
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
catch { /* fall through */ }
|
|
1433
|
+
}
|
|
1434
|
+
// 2. Try HierarchicalMemory's own delete API if it ever ships one.
|
|
1435
|
+
if (hm && typeof hm.delete === 'function') {
|
|
1436
|
+
try {
|
|
1437
|
+
await hm.delete(key);
|
|
1438
|
+
await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
|
|
1439
|
+
return { success: true, deleted: true, key, tier, controller: 'hierarchicalMemory', guarded: true };
|
|
1440
|
+
}
|
|
1441
|
+
catch (err) {
|
|
1442
|
+
// Fall through to SQL fallback
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
// 3. Stub HierarchicalMemory may expose `remove` or `forget`
|
|
1446
|
+
if (hm && typeof hm.remove === 'function') {
|
|
1447
|
+
try {
|
|
1448
|
+
await hm.remove(key);
|
|
1449
|
+
await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
|
|
1450
|
+
return { success: true, deleted: true, key, tier, controller: 'hierarchicalMemory-stub', guarded: true };
|
|
1451
|
+
}
|
|
1452
|
+
catch { /* fall through */ }
|
|
1453
|
+
}
|
|
1454
|
+
// 3. Bridge-fallback: HM stored to memory_entries with namespace prefix
|
|
1455
|
+
// (used when the real controller isn't loaded). Soft-delete via SQL.
|
|
1456
|
+
const ctx = getDb(registry);
|
|
1457
|
+
if (ctx) {
|
|
1458
|
+
try {
|
|
1459
|
+
const result = ctx.db.prepare(`
|
|
1460
|
+
UPDATE memory_entries
|
|
1461
|
+
SET status = 'deleted', updated_at = ?
|
|
1462
|
+
WHERE key = ? AND namespace LIKE 'hierarchical%' AND status = 'active'
|
|
1463
|
+
`).run(Date.now(), key);
|
|
1464
|
+
const changes = result?.changes ?? 0;
|
|
1465
|
+
if (changes > 0) {
|
|
1466
|
+
await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
|
|
1467
|
+
return { success: true, deleted: true, key, tier, controller: 'bridge-fallback', guarded: true };
|
|
1468
|
+
}
|
|
1469
|
+
// Nothing to delete in SQL fallback — and no real-HM delete API.
|
|
1470
|
+
// Surface the situation honestly.
|
|
1471
|
+
return {
|
|
1472
|
+
success: false, deleted: false, key, tier,
|
|
1473
|
+
controller: hm ? 'native-unsupported' : 'not-found',
|
|
1474
|
+
error: hm
|
|
1475
|
+
? 'HierarchicalMemory has no public delete API; entry remains in native storage'
|
|
1476
|
+
: 'No hierarchical entry found with this key',
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
catch (err) {
|
|
1480
|
+
return { success: false, deleted: false, key, tier, controller: 'sql-error', error: err.message };
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
return null;
|
|
1484
|
+
}
|
|
1485
|
+
catch {
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Delete a causal edge between two memory entries (#1784).
|
|
1491
|
+
*
|
|
1492
|
+
* The bridge stores fallback edges in namespace='causal-edges' with key
|
|
1493
|
+
* '{sourceId}→{targetId}'. Those CAN be soft-deleted. The native graph-node
|
|
1494
|
+
* backend has no delete API (createNode/createEdge/createHyperedge only),
|
|
1495
|
+
* so an edge that landed in graph-node native storage stays there. We
|
|
1496
|
+
* surface that explicitly via controller: 'native-unsupported'.
|
|
1497
|
+
*/
|
|
1498
|
+
export async function bridgeDeleteCausalEdge(options) {
|
|
1499
|
+
const registry = await getRegistry(options.dbPath);
|
|
1500
|
+
if (!registry)
|
|
1501
|
+
return null;
|
|
1502
|
+
try {
|
|
1503
|
+
const { sourceId, targetId, relation } = options;
|
|
1504
|
+
const edgeKey = `${sourceId}→${targetId}`;
|
|
1505
|
+
const guardResult = await guardValidate(registry, 'delete', { key: edgeKey, namespace: 'causal-edges' });
|
|
1506
|
+
if (!guardResult.allowed) {
|
|
1507
|
+
return { success: false, deleted: false, sourceId, targetId, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
1508
|
+
}
|
|
1509
|
+
const causalGraph = registry.get('causalGraph');
|
|
1510
|
+
// 1. agentdb@3.0.0-alpha.13+: GraphDatabaseAdapter.deleteEdgesByEndpoints
|
|
1511
|
+
// handles the (sourceId, targetId, relation?) tuple case directly via
|
|
1512
|
+
// Cypher MATCH … DETACH DELETE. Cypher-injection-safe (label validated
|
|
1513
|
+
// against /^[A-Za-z_][A-Za-z0-9_]*$/ upstream).
|
|
1514
|
+
if (causalGraph && typeof causalGraph.deleteEdgesByEndpoints === 'function') {
|
|
1515
|
+
try {
|
|
1516
|
+
const r = await causalGraph.deleteEdgesByEndpoints(sourceId, targetId, relation);
|
|
1517
|
+
const deletedCount = typeof r === 'object' && r ? (r.deleted ?? 0) : (r ? 1 : 0);
|
|
1518
|
+
if (deletedCount > 0) {
|
|
1519
|
+
await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation, count: deletedCount });
|
|
1520
|
+
return { success: true, deleted: true, sourceId, targetId, controller: 'causalGraph-cypher', guarded: true };
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
catch { /* fall through */ }
|
|
1524
|
+
}
|
|
1525
|
+
// 2. Pre-alpha.13 / different controller: try removeEdge() if exposed.
|
|
1526
|
+
if (causalGraph && typeof causalGraph.removeEdge === 'function') {
|
|
1527
|
+
try {
|
|
1528
|
+
await causalGraph.removeEdge(sourceId, targetId, relation);
|
|
1529
|
+
await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation });
|
|
1530
|
+
return { success: true, deleted: true, sourceId, targetId, controller: 'causalGraph', guarded: true };
|
|
1531
|
+
}
|
|
1532
|
+
catch { /* fall through */ }
|
|
1533
|
+
}
|
|
1534
|
+
// 2. Bridge-fallback: soft-delete the memory_entries row.
|
|
1535
|
+
const ctx = getDb(registry);
|
|
1536
|
+
if (ctx) {
|
|
1537
|
+
try {
|
|
1538
|
+
const result = ctx.db.prepare(`
|
|
1539
|
+
UPDATE memory_entries
|
|
1540
|
+
SET status = 'deleted', updated_at = ?
|
|
1541
|
+
WHERE key = ? AND namespace = 'causal-edges' AND status = 'active'
|
|
1542
|
+
`).run(Date.now(), edgeKey);
|
|
1543
|
+
const changes = result?.changes ?? 0;
|
|
1544
|
+
if (changes > 0) {
|
|
1545
|
+
await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation });
|
|
1546
|
+
return { success: true, deleted: true, sourceId, targetId, controller: 'bridge-fallback', guarded: true };
|
|
1547
|
+
}
|
|
1548
|
+
return {
|
|
1549
|
+
success: false, deleted: false, sourceId, targetId,
|
|
1550
|
+
controller: 'native-unsupported',
|
|
1551
|
+
error: 'graph-node native backend has no delete API; edge cannot be removed from native storage. SQL fallback found no matching row.',
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
catch (err) {
|
|
1555
|
+
return { success: false, deleted: false, sourceId, targetId, controller: 'sql-error', error: err.message };
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
return null;
|
|
1559
|
+
}
|
|
1560
|
+
catch {
|
|
1561
|
+
return null;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Cascade-delete a causal node and all its incident edges (#1784).
|
|
1566
|
+
*
|
|
1567
|
+
* Same constraint as bridgeDeleteCausalEdge — native graph-node lacks a
|
|
1568
|
+
* delete API. SQL fallback path soft-deletes the node (if stored as a
|
|
1569
|
+
* memory_entries row) and every edge whose key contains the nodeId.
|
|
1570
|
+
*/
|
|
1571
|
+
export async function bridgeDeleteCausalNode(options) {
|
|
1572
|
+
const registry = await getRegistry(options.dbPath);
|
|
1573
|
+
if (!registry)
|
|
1574
|
+
return null;
|
|
1575
|
+
try {
|
|
1576
|
+
const { nodeId } = options;
|
|
1577
|
+
const guardResult = await guardValidate(registry, 'delete', { key: nodeId, namespace: 'causal-nodes' });
|
|
1578
|
+
if (!guardResult.allowed) {
|
|
1579
|
+
return { success: false, deletedNode: false, deletedEdges: 0, nodeId, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
1580
|
+
}
|
|
1581
|
+
// 1. agentdb@3.0.0-alpha.13+: GraphDatabaseAdapter.deleteNode(id, {cascade})
|
|
1582
|
+
// counts incident edges before delete so we get accurate audit numbers
|
|
1583
|
+
// regardless of binding stats. Cypher MATCH (n {id}) DETACH DELETE n.
|
|
1584
|
+
const causalGraph = registry.get('causalGraph');
|
|
1585
|
+
if (causalGraph && typeof causalGraph.deleteNode === 'function') {
|
|
1586
|
+
try {
|
|
1587
|
+
const r = await causalGraph.deleteNode(nodeId, { cascade: true });
|
|
1588
|
+
if (r && typeof r === 'object') {
|
|
1589
|
+
const deletedNodeNative = !!r.deletedNode;
|
|
1590
|
+
const deletedEdgesNative = typeof r.deletedEdges === 'number' ? r.deletedEdges : 0;
|
|
1591
|
+
await logAttestation(registry, 'delete', nodeId, { namespace: 'causal-nodes', deletedEdges: deletedEdgesNative });
|
|
1592
|
+
return {
|
|
1593
|
+
success: true,
|
|
1594
|
+
deletedNode: deletedNodeNative,
|
|
1595
|
+
deletedEdges: deletedEdgesNative,
|
|
1596
|
+
nodeId,
|
|
1597
|
+
controller: 'causalGraph-cypher',
|
|
1598
|
+
guarded: true,
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
catch { /* fall through to SQL */ }
|
|
1603
|
+
}
|
|
1604
|
+
// 2. SQL fallback: soft-delete the node row + every causal-edges row whose
|
|
1605
|
+
// key contains nodeId on either side. Used when agentdb pre-alpha.13 OR
|
|
1606
|
+
// when the entry was stored via the bridge's SQL fallback path.
|
|
1607
|
+
const ctx = getDb(registry);
|
|
1608
|
+
if (!ctx)
|
|
1609
|
+
return null;
|
|
1610
|
+
let deletedEdges = 0;
|
|
1611
|
+
let deletedNode = false;
|
|
1612
|
+
try {
|
|
1613
|
+
const edgeResult = ctx.db.prepare(`
|
|
1614
|
+
UPDATE memory_entries
|
|
1615
|
+
SET status = 'deleted', updated_at = ?
|
|
1616
|
+
WHERE namespace = 'causal-edges'
|
|
1617
|
+
AND status = 'active'
|
|
1618
|
+
AND (key LIKE ? OR key LIKE ?)
|
|
1619
|
+
`).run(Date.now(), `${nodeId}→%`, `%→${nodeId}`);
|
|
1620
|
+
deletedEdges = edgeResult?.changes ?? 0;
|
|
1621
|
+
const nodeResult = ctx.db.prepare(`
|
|
1622
|
+
UPDATE memory_entries
|
|
1623
|
+
SET status = 'deleted', updated_at = ?
|
|
1624
|
+
WHERE key = ? AND status = 'active'
|
|
1625
|
+
`).run(Date.now(), nodeId);
|
|
1626
|
+
deletedNode = (nodeResult?.changes ?? 0) > 0;
|
|
1627
|
+
await logAttestation(registry, 'delete', nodeId, { namespace: 'causal-nodes', deletedEdges });
|
|
1628
|
+
}
|
|
1629
|
+
catch (err) {
|
|
1630
|
+
return { success: false, deletedNode: false, deletedEdges: 0, nodeId, controller: 'sql-error', error: err.message };
|
|
1631
|
+
}
|
|
1632
|
+
return {
|
|
1633
|
+
success: true,
|
|
1634
|
+
deletedNode,
|
|
1635
|
+
deletedEdges,
|
|
1636
|
+
nodeId,
|
|
1637
|
+
controller: 'bridge-fallback',
|
|
1638
|
+
guarded: true,
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1641
|
+
catch {
|
|
1642
|
+
return null;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
// ===== Phase 5: ReflexionMemory session lifecycle =====
|
|
1646
|
+
/**
|
|
1647
|
+
* Start a session with ReflexionMemory episodic replay.
|
|
1648
|
+
* Loads relevant past session patterns for the new session.
|
|
1649
|
+
*/
|
|
1650
|
+
export async function bridgeSessionStart(options) {
|
|
1651
|
+
const registry = await getRegistry(options.dbPath);
|
|
1652
|
+
if (!registry)
|
|
1653
|
+
return null;
|
|
1654
|
+
try {
|
|
1655
|
+
let restoredPatterns = 0;
|
|
1656
|
+
let controller = 'none';
|
|
1657
|
+
// Try ReflexionMemory for episodic session replay
|
|
1658
|
+
const reflexion = registry.get('reflexion');
|
|
1659
|
+
if (reflexion && typeof reflexion.startEpisode === 'function') {
|
|
1660
|
+
await reflexion.startEpisode(options.sessionId, { context: options.context });
|
|
1661
|
+
controller = 'reflexion';
|
|
1662
|
+
}
|
|
1663
|
+
// Load recent patterns from past sessions
|
|
1664
|
+
const searchResult = await bridgeSearchEntries({
|
|
1665
|
+
query: options.context || 'session patterns',
|
|
1666
|
+
namespace: 'session',
|
|
1667
|
+
limit: 10,
|
|
1668
|
+
threshold: 0.2,
|
|
1669
|
+
dbPath: options.dbPath,
|
|
1670
|
+
});
|
|
1671
|
+
if (searchResult?.results) {
|
|
1672
|
+
restoredPatterns = searchResult.results.length;
|
|
1673
|
+
}
|
|
1674
|
+
return {
|
|
1675
|
+
success: true,
|
|
1676
|
+
controller: controller === 'none' ? 'bridge-search' : controller,
|
|
1677
|
+
restoredPatterns,
|
|
1678
|
+
sessionId: options.sessionId,
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
catch {
|
|
1682
|
+
return null;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* End a session and persist episodic summary to ReflexionMemory.
|
|
1687
|
+
*/
|
|
1688
|
+
export async function bridgeSessionEnd(options) {
|
|
1689
|
+
const registry = await getRegistry(options.dbPath);
|
|
1690
|
+
if (!registry)
|
|
1691
|
+
return null;
|
|
1692
|
+
try {
|
|
1693
|
+
let controller = 'none';
|
|
1694
|
+
let persisted = false;
|
|
1695
|
+
// End episode in ReflexionMemory
|
|
1696
|
+
const reflexion = registry.get('reflexion');
|
|
1697
|
+
if (reflexion && typeof reflexion.endEpisode === 'function') {
|
|
1698
|
+
await reflexion.endEpisode(options.sessionId, {
|
|
1699
|
+
summary: options.summary,
|
|
1700
|
+
tasksCompleted: options.tasksCompleted,
|
|
1701
|
+
patternsLearned: options.patternsLearned,
|
|
1702
|
+
});
|
|
1703
|
+
controller = 'reflexion';
|
|
1704
|
+
persisted = true;
|
|
1705
|
+
}
|
|
1706
|
+
// Persist session summary as memory entry
|
|
1707
|
+
await bridgeStoreEntry({
|
|
1708
|
+
key: `session-${options.sessionId}`,
|
|
1709
|
+
value: JSON.stringify({
|
|
1710
|
+
sessionId: options.sessionId,
|
|
1711
|
+
summary: options.summary || 'Session ended',
|
|
1712
|
+
tasksCompleted: options.tasksCompleted ?? 0,
|
|
1713
|
+
patternsLearned: options.patternsLearned ?? 0,
|
|
1714
|
+
endedAt: new Date().toISOString(),
|
|
1715
|
+
}),
|
|
1716
|
+
namespace: 'session',
|
|
1717
|
+
tags: ['session-end'],
|
|
1718
|
+
upsert: true,
|
|
1719
|
+
dbPath: options.dbPath,
|
|
1720
|
+
});
|
|
1721
|
+
if (controller === 'none')
|
|
1722
|
+
controller = 'bridge-store';
|
|
1723
|
+
persisted = true;
|
|
1724
|
+
// Phase 3: Trigger NightlyLearner consolidation if available
|
|
1725
|
+
const nightlyLearner = registry.get('nightlyLearner');
|
|
1726
|
+
if (nightlyLearner && typeof nightlyLearner.consolidate === 'function') {
|
|
1727
|
+
try {
|
|
1728
|
+
await nightlyLearner.consolidate({ sessionId: options.sessionId });
|
|
1729
|
+
controller += '+nightlyLearner';
|
|
1730
|
+
}
|
|
1731
|
+
catch { /* non-fatal */ }
|
|
1732
|
+
}
|
|
1733
|
+
return { success: true, controller, persisted };
|
|
1734
|
+
}
|
|
1735
|
+
catch {
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
// ===== Phase 5: SemanticRouter bridge =====
|
|
1740
|
+
/**
|
|
1741
|
+
* Route a task via AgentDB's SemanticRouter.
|
|
1742
|
+
* Returns null to fall back to local ruvector router.
|
|
1743
|
+
*/
|
|
1744
|
+
export async function bridgeRouteTask(options) {
|
|
1745
|
+
const registry = await getRegistry(options.dbPath);
|
|
1746
|
+
if (!registry)
|
|
1747
|
+
return null;
|
|
1748
|
+
try {
|
|
1749
|
+
// Try AgentDB's SemanticRouter
|
|
1750
|
+
const semanticRouter = registry.get('semanticRouter');
|
|
1751
|
+
if (semanticRouter && typeof semanticRouter.route === 'function') {
|
|
1752
|
+
const result = await semanticRouter.route(options.task, { context: options.context });
|
|
1753
|
+
if (result) {
|
|
1754
|
+
return {
|
|
1755
|
+
route: result.route || result.category || 'general',
|
|
1756
|
+
confidence: result.confidence ?? result.score ?? 0.5,
|
|
1757
|
+
agents: result.agents || result.suggestedAgents || [],
|
|
1758
|
+
controller: 'semanticRouter',
|
|
1759
|
+
};
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
// Try LearningSystem recommendAlgorithm (Phase 4)
|
|
1763
|
+
const learningSystem = registry.get('learningSystem');
|
|
1764
|
+
if (learningSystem && typeof learningSystem.recommendAlgorithm === 'function') {
|
|
1765
|
+
const rec = await learningSystem.recommendAlgorithm(options.task);
|
|
1766
|
+
if (rec) {
|
|
1767
|
+
return {
|
|
1768
|
+
route: rec.algorithm || rec.route || 'general',
|
|
1769
|
+
confidence: rec.confidence ?? 0.5,
|
|
1770
|
+
agents: rec.agents || [],
|
|
1771
|
+
controller: 'learningSystem',
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
return null; // Fall back to local router
|
|
1776
|
+
}
|
|
1777
|
+
catch {
|
|
1778
|
+
return null;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
// ===== Phase 4: Health check with attestation =====
|
|
1782
|
+
/**
|
|
1783
|
+
* Get comprehensive bridge health including all controller statuses.
|
|
1784
|
+
*/
|
|
1785
|
+
export async function bridgeHealthCheck(dbPath) {
|
|
1786
|
+
const registry = await getRegistry(dbPath);
|
|
1787
|
+
if (!registry)
|
|
1788
|
+
return null;
|
|
1789
|
+
try {
|
|
1790
|
+
const controllers = registry.listControllers();
|
|
1791
|
+
// Phase 4: AttestationLog stats
|
|
1792
|
+
let attestationCount = 0;
|
|
1793
|
+
const attestation = registry.get('attestationLog');
|
|
1794
|
+
if (attestation && typeof attestation.count === 'function') {
|
|
1795
|
+
attestationCount = attestation.count();
|
|
1796
|
+
}
|
|
1797
|
+
// Phase 2: TieredCache stats
|
|
1798
|
+
let cacheStats = { size: 0, hits: 0, misses: 0 };
|
|
1799
|
+
const cache = registry.get('tieredCache');
|
|
1800
|
+
if (cache && typeof cache.stats === 'function') {
|
|
1801
|
+
const s = cache.stats();
|
|
1802
|
+
cacheStats = { size: s.size ?? 0, hits: s.hits ?? 0, misses: s.misses ?? 0 };
|
|
1803
|
+
}
|
|
1804
|
+
return { available: true, controllers, attestationCount, cacheStats };
|
|
1805
|
+
}
|
|
1806
|
+
catch {
|
|
1807
|
+
return null;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
// ===== Phase 7: Hierarchical memory, consolidation, batch, context, semantic route =====
|
|
1811
|
+
/**
|
|
1812
|
+
* Store to hierarchical memory with tier.
|
|
1813
|
+
* Valid tiers: working, episodic, semantic
|
|
1814
|
+
*
|
|
1815
|
+
* Real HierarchicalMemory API (agentdb alpha.10+):
|
|
1816
|
+
* store(content, importance?, tier?, options?) → Promise<string>
|
|
1817
|
+
* Stub API (fallback):
|
|
1818
|
+
* store(key, value, tier) — synchronous
|
|
1819
|
+
*/
|
|
1820
|
+
export async function bridgeHierarchicalStore(params) {
|
|
1821
|
+
const registry = await getRegistry();
|
|
1822
|
+
if (!registry)
|
|
1823
|
+
return null;
|
|
1824
|
+
try {
|
|
1825
|
+
const hm = registry.get('hierarchicalMemory');
|
|
1826
|
+
if (!hm)
|
|
1827
|
+
return { success: false, error: 'HierarchicalMemory not available' };
|
|
1828
|
+
const tier = params.tier || 'working';
|
|
1829
|
+
// Detect real HierarchicalMemory (has async store returning id) vs stub
|
|
1830
|
+
if (typeof hm.getStats === 'function' && typeof hm.promote === 'function') {
|
|
1831
|
+
// Real agentdb HierarchicalMemory
|
|
1832
|
+
const id = await hm.store(params.value, params.importance || 0.5, tier, {
|
|
1833
|
+
metadata: { key: params.key },
|
|
1834
|
+
tags: [params.key],
|
|
1835
|
+
});
|
|
1836
|
+
return { success: true, id, key: params.key, tier };
|
|
1837
|
+
}
|
|
1838
|
+
// Stub fallback
|
|
1839
|
+
hm.store(params.key, params.value, tier);
|
|
1840
|
+
return { success: true, key: params.key, tier };
|
|
1841
|
+
}
|
|
1842
|
+
catch (e) {
|
|
1843
|
+
return { success: false, error: e.message };
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
/**
|
|
1847
|
+
* Recall from hierarchical memory.
|
|
1848
|
+
*
|
|
1849
|
+
* Real HierarchicalMemory API (agentdb alpha.10+):
|
|
1850
|
+
* recall(query: MemoryQuery) → Promise<MemoryItem[]>
|
|
1851
|
+
* where MemoryQuery = { query, tier?, k?, threshold?, context?, includeDecayed? }
|
|
1852
|
+
* Stub API (fallback):
|
|
1853
|
+
* recall(query: string, topK: number) → synchronous array
|
|
1854
|
+
*/
|
|
1855
|
+
export async function bridgeHierarchicalRecall(params) {
|
|
1856
|
+
const registry = await getRegistry();
|
|
1857
|
+
if (!registry)
|
|
1858
|
+
return null;
|
|
1859
|
+
try {
|
|
1860
|
+
const hm = registry.get('hierarchicalMemory');
|
|
1861
|
+
if (!hm)
|
|
1862
|
+
return { results: [], error: 'HierarchicalMemory not available' };
|
|
1863
|
+
// Detect real HierarchicalMemory vs stub
|
|
1864
|
+
if (typeof hm.getStats === 'function' && typeof hm.promote === 'function') {
|
|
1865
|
+
// Real agentdb HierarchicalMemory — recall takes MemoryQuery object
|
|
1866
|
+
const memoryQuery = {
|
|
1867
|
+
query: params.query,
|
|
1868
|
+
k: params.topK || 5,
|
|
1869
|
+
};
|
|
1870
|
+
if (params.tier) {
|
|
1871
|
+
memoryQuery.tier = params.tier;
|
|
1872
|
+
}
|
|
1873
|
+
const results = await hm.recall(memoryQuery);
|
|
1874
|
+
return { results: results || [], controller: 'hierarchicalMemory' };
|
|
1875
|
+
}
|
|
1876
|
+
// Stub fallback — recall(string, number)
|
|
1877
|
+
const results = hm.recall(params.query, params.topK || 5);
|
|
1878
|
+
const filtered = params.tier
|
|
1879
|
+
? results.filter((r) => r.tier === params.tier)
|
|
1880
|
+
: results;
|
|
1881
|
+
return { results: filtered, controller: 'hierarchicalMemory' };
|
|
1882
|
+
}
|
|
1883
|
+
catch (e) {
|
|
1884
|
+
return { results: [], error: e.message };
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Run memory consolidation.
|
|
1889
|
+
*
|
|
1890
|
+
* Real MemoryConsolidation API (agentdb alpha.10+):
|
|
1891
|
+
* consolidate() → Promise<ConsolidationReport>
|
|
1892
|
+
* ConsolidationReport = { episodicProcessed, semanticCreated, memoriesForgotten, ... }
|
|
1893
|
+
* Stub API (fallback):
|
|
1894
|
+
* consolidate() → { promoted, pruned, timestamp }
|
|
1895
|
+
*/
|
|
1896
|
+
export async function bridgeConsolidate(params) {
|
|
1897
|
+
const registry = await getRegistry();
|
|
1898
|
+
if (!registry)
|
|
1899
|
+
return null;
|
|
1900
|
+
try {
|
|
1901
|
+
const mc = registry.get('memoryConsolidation');
|
|
1902
|
+
if (!mc)
|
|
1903
|
+
return { success: false, error: 'MemoryConsolidation not available' };
|
|
1904
|
+
const result = await mc.consolidate();
|
|
1905
|
+
return { success: true, consolidated: result };
|
|
1906
|
+
}
|
|
1907
|
+
catch (e) {
|
|
1908
|
+
return { success: false, error: e.message };
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Batch operations (insert, update, delete).
|
|
1913
|
+
* - insert: calls insertEpisodes(entries) where entries are {content, metadata?}
|
|
1914
|
+
* - delete: calls bulkDelete(table, conditions) on episodes table
|
|
1915
|
+
* - update: calls bulkUpdate(table, updates, conditions) on episodes table
|
|
1916
|
+
*/
|
|
1917
|
+
export async function bridgeBatchOperation(params) {
|
|
1918
|
+
const registry = await getRegistry();
|
|
1919
|
+
if (!registry)
|
|
1920
|
+
return null;
|
|
1921
|
+
try {
|
|
1922
|
+
const batch = registry.get('batchOperations');
|
|
1923
|
+
if (!batch)
|
|
1924
|
+
return { success: false, error: 'BatchOperations not available' };
|
|
1925
|
+
let result;
|
|
1926
|
+
switch (params.operation) {
|
|
1927
|
+
case 'insert': {
|
|
1928
|
+
if (typeof batch.insertEpisodes !== 'function') {
|
|
1929
|
+
return { success: false, error: 'BatchOperations.insertEpisodes not available — embedder may not be initialized. Use memory_store instead.' };
|
|
1930
|
+
}
|
|
1931
|
+
const episodes = params.entries.map((e) => ({
|
|
1932
|
+
content: e.value || e.content || JSON.stringify(e),
|
|
1933
|
+
metadata: e.metadata || { key: e.key },
|
|
1934
|
+
}));
|
|
1935
|
+
try {
|
|
1936
|
+
result = await batch.insertEpisodes(episodes);
|
|
1937
|
+
}
|
|
1938
|
+
catch (insertErr) {
|
|
1939
|
+
if (insertErr?.message?.includes('null') || insertErr?.message?.includes('embedBatch')) {
|
|
1940
|
+
return { success: false, error: 'Embedder not initialized for batch insert. Use memory_store for individual entries or run embeddings_init first.' };
|
|
1941
|
+
}
|
|
1942
|
+
throw insertErr;
|
|
1943
|
+
}
|
|
1944
|
+
break;
|
|
1945
|
+
}
|
|
1946
|
+
case 'delete': {
|
|
1947
|
+
// bulkDelete(table, conditions) — conditions is a WHERE clause object
|
|
1948
|
+
const keys = params.entries.map((e) => e.key).filter(Boolean);
|
|
1949
|
+
for (const key of keys) {
|
|
1950
|
+
await batch.bulkDelete('episodes', { key });
|
|
1951
|
+
}
|
|
1952
|
+
result = { deleted: keys.length };
|
|
1953
|
+
break;
|
|
1954
|
+
}
|
|
1955
|
+
case 'update': {
|
|
1956
|
+
// bulkUpdate(table, updates, conditions)
|
|
1957
|
+
for (const entry of params.entries) {
|
|
1958
|
+
await batch.bulkUpdate('episodes', { content: entry.value || entry.content }, { key: entry.key });
|
|
1959
|
+
}
|
|
1960
|
+
result = { updated: params.entries.length };
|
|
1961
|
+
break;
|
|
1962
|
+
}
|
|
1963
|
+
default: return { success: false, error: `Unknown operation: ${params.operation}` };
|
|
1964
|
+
}
|
|
1965
|
+
return { success: true, operation: params.operation, count: params.entries.length, result };
|
|
1966
|
+
}
|
|
1967
|
+
catch (e) {
|
|
1968
|
+
return { success: false, error: e.message };
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
/**
|
|
1972
|
+
* Synthesize context from memories.
|
|
1973
|
+
* ContextSynthesizer.synthesize is a static method that takes MemoryPattern[] (not a string).
|
|
1974
|
+
*/
|
|
1975
|
+
export async function bridgeContextSynthesize(params) {
|
|
1976
|
+
const registry = await getRegistry();
|
|
1977
|
+
if (!registry)
|
|
1978
|
+
return null;
|
|
1979
|
+
try {
|
|
1980
|
+
const CS = registry.get('contextSynthesizer');
|
|
1981
|
+
if (!CS || typeof CS.synthesize !== 'function') {
|
|
1982
|
+
return { success: false, error: 'ContextSynthesizer not available' };
|
|
1983
|
+
}
|
|
1984
|
+
// Gather memory patterns from hierarchical memory as input
|
|
1985
|
+
const hm = registry.get('hierarchicalMemory');
|
|
1986
|
+
let memories = [];
|
|
1987
|
+
if (hm && typeof hm.recall === 'function') {
|
|
1988
|
+
// Detect real HierarchicalMemory (MemoryQuery object) vs stub (string, number)
|
|
1989
|
+
let recalled;
|
|
1990
|
+
if (typeof hm.promote === 'function') {
|
|
1991
|
+
// Real agentdb HierarchicalMemory
|
|
1992
|
+
recalled = await hm.recall({ query: params.query, k: params.maxEntries || 10 });
|
|
1993
|
+
}
|
|
1994
|
+
else {
|
|
1995
|
+
// Stub
|
|
1996
|
+
recalled = hm.recall(params.query, params.maxEntries || 10);
|
|
1997
|
+
}
|
|
1998
|
+
memories = (recalled || []).map((r) => ({
|
|
1999
|
+
content: r.value || r.content || '',
|
|
2000
|
+
key: r.key || r.id || '',
|
|
2001
|
+
reward: 1,
|
|
2002
|
+
verdict: 'success',
|
|
2003
|
+
}));
|
|
2004
|
+
}
|
|
2005
|
+
const result = CS.synthesize(memories, { includeRecommendations: true });
|
|
2006
|
+
return { success: true, synthesis: result };
|
|
2007
|
+
}
|
|
2008
|
+
catch (e) {
|
|
2009
|
+
return { success: false, error: e.message };
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
/**
|
|
2013
|
+
* Route via SemanticRouter.
|
|
2014
|
+
* Available since agentdb 3.0.0-alpha.10 — uses @ruvector/router for
|
|
2015
|
+
* semantic matching with keyword fallback.
|
|
2016
|
+
*/
|
|
2017
|
+
export async function bridgeSemanticRoute(params) {
|
|
2018
|
+
const registry = await getRegistry();
|
|
2019
|
+
if (!registry)
|
|
2020
|
+
return null;
|
|
2021
|
+
try {
|
|
2022
|
+
const router = registry.get('semanticRouter');
|
|
2023
|
+
if (!router) {
|
|
2024
|
+
// ADR-093 F9: surface an actionable error pointing callers at the
|
|
2025
|
+
// alternative routing surfaces that DO work, instead of just
|
|
2026
|
+
// saying "not available".
|
|
2027
|
+
return {
|
|
2028
|
+
route: null,
|
|
2029
|
+
error: 'SemanticRouter not available in current agentdb build',
|
|
2030
|
+
recommendation: 'Use bridgeRouteTask (registers as `agentdb_route` MCP tool) for keyword+pattern routing, or hooks_model-route for ADR-026 model selection.',
|
|
2031
|
+
controller: 'none',
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
const result = await router.route(params.input);
|
|
2035
|
+
return { route: result, controller: 'semanticRouter' };
|
|
2036
|
+
}
|
|
2037
|
+
catch (e) {
|
|
2038
|
+
return { route: null, error: e.message, controller: 'error' };
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
// ===== RaBitQ data export =====
|
|
2042
|
+
/**
|
|
2043
|
+
* Export all embeddings from the bridge's better-sqlite3 connection.
|
|
2044
|
+
* Used by RaBitQ to build its index from the same data that memory_store writes.
|
|
2045
|
+
* Returns null if bridge is unavailable (caller falls back to sql.js).
|
|
2046
|
+
*/
|
|
2047
|
+
export async function bridgeGetAllEmbeddings(options) {
|
|
2048
|
+
const registry = await getRegistry(options?.dbPath);
|
|
2049
|
+
if (!registry)
|
|
2050
|
+
return null;
|
|
2051
|
+
const ctx = getDb(registry);
|
|
2052
|
+
if (!ctx)
|
|
2053
|
+
return null;
|
|
2054
|
+
try {
|
|
2055
|
+
const dims = options?.dimensions ?? 384;
|
|
2056
|
+
const maxRows = options?.limit ?? 50000;
|
|
2057
|
+
const rows = ctx.db.prepare(`
|
|
2058
|
+
SELECT id, key, namespace, embedding
|
|
2059
|
+
FROM memory_entries
|
|
2060
|
+
WHERE status = 'active' AND embedding IS NOT NULL
|
|
2061
|
+
LIMIT ?
|
|
2062
|
+
`).all(maxRows);
|
|
2063
|
+
const results = [];
|
|
2064
|
+
for (const row of rows) {
|
|
2065
|
+
if (!row.embedding)
|
|
2066
|
+
continue;
|
|
2067
|
+
try {
|
|
2068
|
+
const emb = JSON.parse(row.embedding);
|
|
2069
|
+
if (emb.length !== dims)
|
|
2070
|
+
continue;
|
|
2071
|
+
results.push({
|
|
2072
|
+
id: String(row.id),
|
|
2073
|
+
key: row.key || String(row.id),
|
|
2074
|
+
namespace: row.namespace || 'default',
|
|
2075
|
+
embedding: emb,
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
catch { /* skip invalid */ }
|
|
2079
|
+
}
|
|
2080
|
+
return results;
|
|
2081
|
+
}
|
|
2082
|
+
catch {
|
|
2083
|
+
return null;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
// ===== Utility =====
|
|
2087
|
+
function cosineSim(a, b) {
|
|
2088
|
+
if (!a || !b || a.length === 0 || b.length === 0)
|
|
2089
|
+
return 0;
|
|
2090
|
+
const len = Math.min(a.length, b.length);
|
|
2091
|
+
let dot = 0, normA = 0, normB = 0;
|
|
2092
|
+
for (let i = 0; i < len; i++) {
|
|
2093
|
+
const ai = a[i], bi = b[i];
|
|
2094
|
+
dot += ai * bi;
|
|
2095
|
+
normA += ai * ai;
|
|
2096
|
+
normB += bi * bi;
|
|
2097
|
+
}
|
|
2098
|
+
const mag = Math.sqrt(normA * normB);
|
|
2099
|
+
return mag === 0 ? 0 : dot / mag;
|
|
2100
|
+
}
|
|
2101
|
+
//# sourceMappingURL=memory-bridge.js.map
|