claude-flow-novice 1.3.0 → 1.3.2
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-flow-novice/preferences/generation.json +147 -0
- package/.claude-flow-novice/preferences/language-configs/javascript.json +51 -0
- package/.claude-flow-novice/preferences/language-configs/python.json +50 -0
- package/.claude-flow-novice/preferences/language-configs/rust.json +237 -0
- package/.claude-flow-novice/preferences/language-configs/typescript.json +54 -0
- package/.claude-flow-novice/preferences/project-local.json +91 -0
- package/.claude-flow-novice/preferences/resource-delegation.json +120 -0
- package/.claude-flow-novice/preferences/team-shared.json +195 -0
- package/.claude-flow-novice/preferences/user-global.json +247 -0
- package/.claude-flow-novice/templates/claude-md-templates/CLAUDE-JAVASCRIPT.md +769 -0
- package/.claude-flow-novice/templates/claude-md-templates/CLAUDE-PYTHON.md +1214 -0
- package/.claude-flow-novice/templates/claude-md-templates/CLAUDE-RUST.md +475 -0
- package/.claude-flow-novice/templates/claude-md-templates/CLAUDE-TYPESCRIPT.md +851 -0
- package/.claude-flow-novice/templates/claude-md-templates/README.md +263 -0
- package/CLAUDE.md +81 -0
- package/README-NPM.md +0 -0
- package/package.json +11 -7
- package/scripts/build/README.md +167 -0
- package/scripts/build/build-config.js +27 -0
- package/scripts/build/build-prompt-copier.sh +30 -0
- package/scripts/build/performance-monitor.js +869 -0
- package/scripts/build/prepare-publish.js +150 -0
- package/scripts/build/typescript-fixer.js +621 -0
- package/scripts/build/unified-builder.sh +428 -0
- package/scripts/build/update-bin-version.js +32 -0
- package/scripts/dev/README.md +264 -0
- package/scripts/dev/claude-flow-wrapper.sh +35 -0
- package/scripts/dev/claude-monitor.py +419 -0
- package/scripts/dev/claude-sparc.sh +562 -0
- package/scripts/dev/claude-wrapper.sh +17 -0
- package/scripts/dev/demo-phase3-compliance.js +172 -0
- package/scripts/dev/demo-task-system.ts +224 -0
- package/scripts/dev/deployment-validator.js +315 -0
- package/scripts/dev/spawn-claude-terminal.sh +32 -0
- package/scripts/dev/start-portal.sh +506 -0
- package/scripts/dev/start-web-ui.js +15 -0
- package/scripts/dev/stop-portal.sh +311 -0
- package/scripts/dev/validate-examples.ts +288 -0
- package/scripts/dev/validate-phase2.cjs +451 -0
- package/scripts/dev/validate-phase2.js +785 -0
- package/scripts/dev/validate-phase3.cjs +208 -0
- package/scripts/dev/validate-security-remediation.js +1 -0
- package/scripts/legacy/README.md +272 -0
- package/scripts/legacy/batch-fix-ts.sh +54 -0
- package/scripts/legacy/build-migration.sh +105 -0
- package/scripts/legacy/build-monitor.js +209 -0
- package/scripts/legacy/build-with-filter.sh +84 -0
- package/scripts/legacy/build-workaround.sh +71 -0
- package/scripts/legacy/fix-ts-advanced.js +358 -0
- package/scripts/legacy/fix-ts-final.sh +50 -0
- package/scripts/legacy/fix-ts-targeted.sh +49 -0
- package/scripts/legacy/fix-typescript-errors.js +305 -0
- package/scripts/legacy/force-build.sh +63 -0
- package/scripts/legacy/optimize-performance.js +400 -0
- package/scripts/legacy/performance-monitor.js +263 -0
- package/scripts/legacy/performance-monitoring.js +532 -0
- package/scripts/legacy/performance-test-runner.js +645 -0
- package/scripts/legacy/quick-fix-ts.js +281 -0
- package/scripts/legacy/safe-build.sh +63 -0
- package/scripts/migration/README.md +434 -0
- package/scripts/migration/install-arm64.js +78 -0
- package/scripts/migration/install.js +83 -0
- package/scripts/migration/migrate-hooks.js +173 -0
- package/scripts/migration/migration-examples.ts +318 -0
- package/scripts/optimization/build-optimizer.js +438 -0
- package/scripts/optimization/config-validator.js +761 -0
- package/scripts/optimization/test-optimization.js +432 -0
- package/scripts/optimization/unified-activation.js +839 -0
- package/scripts/performance/ACTIVATION_COMMANDS.md +292 -0
- package/scripts/performance/sqlite-enhanced-activation.sh +583 -0
- package/scripts/performance/test-enhanced-backend.sh +504 -0
- package/scripts/performance-test-runner.js +698 -0
- package/scripts/security/README.md +339 -0
- package/scripts/security/install-git-hooks.sh +132 -0
- package/scripts/security/ruv-swarm-safe.js +74 -0
- package/scripts/test/README.md +236 -0
- package/scripts/test/check-links.ts +274 -0
- package/scripts/test/check-performance-regression.ts +168 -0
- package/scripts/test/coverage-report.ts +692 -0
- package/scripts/test/generate-swarm-tests.js +633 -0
- package/scripts/test/integration-test-validation.cjs +253 -0
- package/scripts/test/load-test-swarm.js +576 -0
- package/scripts/test/run-phase3-compliance-tests.js +427 -0
- package/scripts/test/test-batch-tasks.ts +29 -0
- package/scripts/test/test-byzantine-resolution.js +246 -0
- package/scripts/test/test-claude-spawn-options.sh +63 -0
- package/scripts/test/test-cli-wizard.js +331 -0
- package/scripts/test/test-comprehensive.js +401 -0
- package/scripts/test/test-coordination-features.ts +238 -0
- package/scripts/test/test-fallback-systems.js +276 -0
- package/scripts/test/test-init-command.ts +302 -0
- package/scripts/test/test-mcp.ts +251 -0
- package/scripts/test/test-runner.ts +568 -0
- package/scripts/test/test-swarm-integration.sh +92 -0
- package/scripts/test/test-swarm.ts +142 -0
- package/scripts/test/validation-summary.ts +408 -0
- package/scripts/utils/README.md +261 -0
- package/scripts/utils/clean-build-artifacts.sh +94 -0
- package/scripts/utils/cleanup-root.sh +69 -0
- package/scripts/utils/fix-cliffy-imports.js +307 -0
- package/scripts/utils/fix-duplicate-imports.js +114 -0
- package/scripts/utils/fix-error-handling.cjs +70 -0
- package/scripts/utils/fix-import-paths.js +104 -0
- package/scripts/utils/fix-imports.js +116 -0
- package/scripts/utils/fix-shebang.js +78 -0
- package/scripts/utils/fix-test-modules.js +27 -0
- package/scripts/utils/fix-timezone-issue-246.js +200 -0
- package/scripts/utils/fix-ts-comprehensive.py +182 -0
- package/scripts/utils/fix-ts-targeted-batch.js +250 -0
- package/scripts/utils/remove-benchmark-conflicts.sh +140 -0
- package/scripts/utils/simple-test-fixer.js +190 -0
- package/scripts/utils/validate-metrics-structure.cjs +144 -0
- package/scripts/verify-mcp-server.js +86 -0
- package/src/cli/simple-commands/__tests__/agent.test.js +291 -0
- package/src/cli/simple-commands/__tests__/memory.test.js +8 -0
- package/src/cli/simple-commands/__tests__/swarm.test.js +371 -0
- package/src/cli/simple-commands/__tests__/task.test.js +8 -0
- package/src/cli/simple-commands/agent.js +216 -0
- package/src/cli/simple-commands/analysis.js +570 -0
- package/src/cli/simple-commands/automation-executor.js +1603 -0
- package/src/cli/simple-commands/automation.js +627 -0
- package/src/cli/simple-commands/batch-manager.js +338 -0
- package/src/cli/simple-commands/claude-telemetry.js +311 -0
- package/src/cli/simple-commands/claude-track.js +102 -0
- package/src/cli/simple-commands/concurrent-display.js +348 -0
- package/src/cli/simple-commands/config.js +319 -0
- package/src/cli/simple-commands/coordination.js +307 -0
- package/src/cli/simple-commands/enhanced-ui-views.js +654 -0
- package/src/cli/simple-commands/enhanced-webui-complete.js +1038 -0
- package/src/cli/simple-commands/fix-hook-variables.js +363 -0
- package/src/cli/simple-commands/github/gh-coordinator.js +605 -0
- package/src/cli/simple-commands/github/github-api.js +624 -0
- package/src/cli/simple-commands/github/init.js +543 -0
- package/src/cli/simple-commands/github.js +377 -0
- package/src/cli/simple-commands/goal.js +145 -0
- package/src/cli/simple-commands/hive-mind/auto-save-middleware.js +311 -0
- package/src/cli/simple-commands/hive-mind/communication.js +740 -0
- package/src/cli/simple-commands/hive-mind/core.js +1031 -0
- package/src/cli/simple-commands/hive-mind/db-optimizer.js +872 -0
- package/src/cli/simple-commands/hive-mind/mcp-wrapper.js +1364 -0
- package/src/cli/simple-commands/hive-mind/memory.js +1292 -0
- package/src/cli/simple-commands/hive-mind/performance-optimizer.js +618 -0
- package/src/cli/simple-commands/hive-mind/performance-test.js +373 -0
- package/src/cli/simple-commands/hive-mind/queen.js +809 -0
- package/src/cli/simple-commands/hive-mind/session-manager.js +1223 -0
- package/src/cli/simple-commands/hive-mind-optimize.js +361 -0
- package/src/cli/simple-commands/hive-mind-wizard.js +281 -0
- package/src/cli/simple-commands/hive-mind.js +3112 -0
- package/src/cli/simple-commands/hive.js +140 -0
- package/src/cli/simple-commands/hook-safety.js +671 -0
- package/src/cli/simple-commands/hooks.js +1268 -0
- package/src/cli/simple-commands/init/.claude/checkpoints/1756224542.json +7 -0
- package/src/cli/simple-commands/init/.claude/checkpoints/1756224544.json +8 -0
- package/src/cli/simple-commands/init/README.md +106 -0
- package/src/cli/simple-commands/init/VALIDATION_ROLLBACK.md +488 -0
- package/src/cli/simple-commands/init/agent-copier.js +347 -0
- package/src/cli/simple-commands/init/batch-init.js +663 -0
- package/src/cli/simple-commands/init/claude-commands/claude-flow-commands.js +438 -0
- package/src/cli/simple-commands/init/claude-commands/optimized-claude-flow-commands.js +876 -0
- package/src/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +356 -0
- package/src/cli/simple-commands/init/claude-commands/optimized-sparc-commands.js +501 -0
- package/src/cli/simple-commands/init/claude-commands/slash-commands.js +57 -0
- package/src/cli/simple-commands/init/claude-commands/sparc-commands.js +296 -0
- package/src/cli/simple-commands/init/copy-revised-templates.js +175 -0
- package/src/cli/simple-commands/init/executable-wrapper.js +122 -0
- package/src/cli/simple-commands/init/gitignore-updater.js +137 -0
- package/src/cli/simple-commands/init/help.js +110 -0
- package/src/cli/simple-commands/init/hive-mind-init.js +749 -0
- package/src/cli/simple-commands/init/index.js +1953 -0
- package/src/cli/simple-commands/init/performance-monitor.js +344 -0
- package/src/cli/simple-commands/init/rollback/backup-manager.js +542 -0
- package/src/cli/simple-commands/init/rollback/index.js +399 -0
- package/src/cli/simple-commands/init/rollback/recovery-manager.js +778 -0
- package/src/cli/simple-commands/init/rollback/rollback-executor.js +521 -0
- package/src/cli/simple-commands/init/rollback/state-tracker.js +486 -0
- package/src/cli/simple-commands/init/sparc/roo-readme.js +61 -0
- package/src/cli/simple-commands/init/sparc/roomodes-config.js +102 -0
- package/src/cli/simple-commands/init/sparc/workflows.js +40 -0
- package/src/cli/simple-commands/init/sparc-structure.js +68 -0
- package/src/cli/simple-commands/init/template-copier.js +640 -0
- package/src/cli/simple-commands/init/templates/CLAUDE.md +1185 -0
- package/src/cli/simple-commands/init/templates/CLAUDE.md.optimized +265 -0
- package/src/cli/simple-commands/init/templates/claude-flow-universal +81 -0
- package/src/cli/simple-commands/init/templates/claude-flow.bat +18 -0
- package/src/cli/simple-commands/init/templates/claude-flow.ps1 +24 -0
- package/src/cli/simple-commands/init/templates/claude-md.js +1101 -0
- package/src/cli/simple-commands/init/templates/commands/analysis/bottleneck-detect.md +162 -0
- package/src/cli/simple-commands/init/templates/commands/automation/auto-agent.md +122 -0
- package/src/cli/simple-commands/init/templates/commands/coordination/swarm-init.md +85 -0
- package/src/cli/simple-commands/init/templates/commands/github/github-swarm.md +121 -0
- package/src/cli/simple-commands/init/templates/commands/helpers/standard-checkpoint-hooks.sh +179 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/notification.md +113 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/post-command.md +116 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/post-edit.md +117 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/post-task.md +112 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/pre-command.md +113 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/pre-edit.md +113 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/pre-search.md +112 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/pre-task.md +111 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/session-end.md +118 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/session-restore.md +118 -0
- package/src/cli/simple-commands/init/templates/commands/hooks/session-start.md +117 -0
- package/src/cli/simple-commands/init/templates/coordination-md.js +340 -0
- package/src/cli/simple-commands/init/templates/coordination.md +16 -0
- package/src/cli/simple-commands/init/templates/enhanced-templates.js +2347 -0
- package/src/cli/simple-commands/init/templates/github-safe-enhanced.js +331 -0
- package/src/cli/simple-commands/init/templates/github-safe.js +106 -0
- package/src/cli/simple-commands/init/templates/memory-bank-md.js +259 -0
- package/src/cli/simple-commands/init/templates/memory-bank.md +16 -0
- package/src/cli/simple-commands/init/templates/readme-files.js +72 -0
- package/src/cli/simple-commands/init/templates/safe-hook-patterns.js +430 -0
- package/src/cli/simple-commands/init/templates/settings.json +109 -0
- package/src/cli/simple-commands/init/templates/settings.json.enhanced +35 -0
- package/src/cli/simple-commands/init/templates/sparc-modes.js +1401 -0
- package/src/cli/simple-commands/init/templates/verification-claude-md.js +432 -0
- package/src/cli/simple-commands/init/validation/config-validator.js +354 -0
- package/src/cli/simple-commands/init/validation/health-checker.js +599 -0
- package/src/cli/simple-commands/init/validation/index.js +388 -0
- package/src/cli/simple-commands/init/validation/mode-validator.js +387 -0
- package/src/cli/simple-commands/init/validation/post-init-validator.js +390 -0
- package/src/cli/simple-commands/init/validation/pre-init-validator.js +290 -0
- package/src/cli/simple-commands/init/validation/test-runner.js +488 -0
- package/src/cli/simple-commands/init.js +4 -0
- package/src/cli/simple-commands/mcp-health.js +163 -0
- package/src/cli/simple-commands/mcp-integration-layer.js +689 -0
- package/src/cli/simple-commands/mcp.js +420 -0
- package/src/cli/simple-commands/memory-consolidation.js +631 -0
- package/src/cli/simple-commands/memory.js +345 -0
- package/src/cli/simple-commands/migrate-hooks.js +63 -0
- package/src/cli/simple-commands/monitor.js +417 -0
- package/src/cli/simple-commands/neural.js +148 -0
- package/src/cli/simple-commands/pair-autofix-only.js +755 -0
- package/src/cli/simple-commands/pair-basic.js +751 -0
- package/src/cli/simple-commands/pair-old.js +623 -0
- package/src/cli/simple-commands/pair-working.js +849 -0
- package/src/cli/simple-commands/pair.js +849 -0
- package/src/cli/simple-commands/performance-hooks.js +149 -0
- package/src/cli/simple-commands/performance-metrics.js +601 -0
- package/src/cli/simple-commands/process-ui-enhanced.js +821 -0
- package/src/cli/simple-commands/process-ui.js +274 -0
- package/src/cli/simple-commands/realtime-update-system.js +659 -0
- package/src/cli/simple-commands/sparc/architecture.js +1750 -0
- package/src/cli/simple-commands/sparc/commands.js +575 -0
- package/src/cli/simple-commands/sparc/completion.js +1831 -0
- package/src/cli/simple-commands/sparc/coordinator.js +1045 -0
- package/src/cli/simple-commands/sparc/index.js +321 -0
- package/src/cli/simple-commands/sparc/phase-base.js +430 -0
- package/src/cli/simple-commands/sparc/pseudocode.js +984 -0
- package/src/cli/simple-commands/sparc/refinement.js +1856 -0
- package/src/cli/simple-commands/sparc/specification.js +736 -0
- package/src/cli/simple-commands/sparc-modes/architect.js +125 -0
- package/src/cli/simple-commands/sparc-modes/ask.js +126 -0
- package/src/cli/simple-commands/sparc-modes/code.js +148 -0
- package/src/cli/simple-commands/sparc-modes/debug.js +112 -0
- package/src/cli/simple-commands/sparc-modes/devops.js +137 -0
- package/src/cli/simple-commands/sparc-modes/docs-writer.js +38 -0
- package/src/cli/simple-commands/sparc-modes/generic.js +34 -0
- package/src/cli/simple-commands/sparc-modes/index.js +201 -0
- package/src/cli/simple-commands/sparc-modes/integration.js +55 -0
- package/src/cli/simple-commands/sparc-modes/mcp.js +38 -0
- package/src/cli/simple-commands/sparc-modes/monitoring.js +38 -0
- package/src/cli/simple-commands/sparc-modes/optimization.js +38 -0
- package/src/cli/simple-commands/sparc-modes/security-review.js +130 -0
- package/src/cli/simple-commands/sparc-modes/sparc-orchestrator.js +167 -0
- package/src/cli/simple-commands/sparc-modes/spec-pseudocode.js +38 -0
- package/src/cli/simple-commands/sparc-modes/supabase-admin.js +149 -0
- package/src/cli/simple-commands/sparc-modes/swarm.js +436 -0
- package/src/cli/simple-commands/sparc-modes/tdd.js +112 -0
- package/src/cli/simple-commands/sparc-modes/tutorial.js +277 -0
- package/src/cli/simple-commands/sparc.js +530 -0
- package/src/cli/simple-commands/start-ui.js +147 -0
- package/src/cli/simple-commands/start-wrapper.js +285 -0
- package/src/cli/simple-commands/start.js +2 -0
- package/src/cli/simple-commands/status.js +303 -0
- package/src/cli/simple-commands/stream-chain-clean.js +221 -0
- package/src/cli/simple-commands/stream-chain-fixed.js +89 -0
- package/src/cli/simple-commands/stream-chain-real.js +408 -0
- package/src/cli/simple-commands/stream-chain-working.js +323 -0
- package/src/cli/simple-commands/stream-chain.js +491 -0
- package/src/cli/simple-commands/stream-processor.js +340 -0
- package/src/cli/simple-commands/swarm-executor.js +253 -0
- package/src/cli/simple-commands/swarm-metrics-integration.js +371 -0
- package/src/cli/simple-commands/swarm-ui.js +741 -0
- package/src/cli/simple-commands/swarm-webui-integration.js +311 -0
- package/src/cli/simple-commands/swarm.js +2277 -0
- package/src/cli/simple-commands/task.js +228 -0
- package/src/cli/simple-commands/templates/mle-star-workflow.json +294 -0
- package/src/cli/simple-commands/timestamp-fix.js +104 -0
- package/src/cli/simple-commands/token-tracker.js +372 -0
- package/src/cli/simple-commands/tool-execution-framework.js +555 -0
- package/src/cli/simple-commands/train-and-stream.js +354 -0
- package/src/cli/simple-commands/training-pipeline.js +874 -0
- package/src/cli/simple-commands/training.js +288 -0
- package/src/cli/simple-commands/verification-hooks.js +336 -0
- package/src/cli/simple-commands/verification-integration.js +464 -0
- package/src/cli/simple-commands/verification-training-integration.js +646 -0
- package/src/cli/simple-commands/verification.js +551 -0
- package/src/cli/simple-commands/web-server.js +929 -0
- package/src/cli/simple-commands/webui-validator.js +136 -0
- package/src/language/README.md +503 -0
- package/src/language/claude-md-generator.js +618 -0
- package/src/language/cli.js +422 -0
- package/src/language/example.js +347 -0
- package/src/language/integration-system.js +619 -0
- package/src/language/language-detector.js +581 -0
|
@@ -0,0 +1,1292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collective Memory System for Hive Mind
|
|
3
|
+
* Shared knowledge base and learning system
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import EventEmitter from 'events';
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { performance } from 'perf_hooks';
|
|
10
|
+
import { Worker } from 'worker_threads';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Memory types and their characteristics
|
|
14
|
+
*/
|
|
15
|
+
const MEMORY_TYPES = {
|
|
16
|
+
knowledge: { priority: 1, ttl: null, compress: false },
|
|
17
|
+
context: { priority: 2, ttl: 3600000, compress: false }, // 1 hour
|
|
18
|
+
task: { priority: 3, ttl: 1800000, compress: true }, // 30 minutes
|
|
19
|
+
result: { priority: 2, ttl: null, compress: true },
|
|
20
|
+
error: { priority: 1, ttl: 86400000, compress: false }, // 24 hours
|
|
21
|
+
metric: { priority: 3, ttl: 3600000, compress: true }, // 1 hour
|
|
22
|
+
consensus: { priority: 1, ttl: null, compress: false },
|
|
23
|
+
system: { priority: 1, ttl: null, compress: false },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Memory Pool for object reuse
|
|
28
|
+
*/
|
|
29
|
+
class MemoryPool {
|
|
30
|
+
constructor(createFn, resetFn, maxSize = 1000) {
|
|
31
|
+
this.createFn = createFn;
|
|
32
|
+
this.resetFn = resetFn;
|
|
33
|
+
this.maxSize = maxSize;
|
|
34
|
+
this.pool = [];
|
|
35
|
+
this.allocated = 0;
|
|
36
|
+
this.reused = 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
acquire() {
|
|
40
|
+
if (this.pool.length > 0) {
|
|
41
|
+
this.reused++;
|
|
42
|
+
return this.pool.pop();
|
|
43
|
+
}
|
|
44
|
+
this.allocated++;
|
|
45
|
+
return this.createFn();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
release(obj) {
|
|
49
|
+
if (this.pool.length < this.maxSize) {
|
|
50
|
+
this.resetFn(obj);
|
|
51
|
+
this.pool.push(obj);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getStats() {
|
|
56
|
+
return {
|
|
57
|
+
poolSize: this.pool.length,
|
|
58
|
+
allocated: this.allocated,
|
|
59
|
+
reused: this.reused,
|
|
60
|
+
reuseRate: (this.reused / (this.allocated + this.reused)) * 100,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Optimized LRU Cache with memory pressure handling
|
|
67
|
+
*/
|
|
68
|
+
class OptimizedLRUCache {
|
|
69
|
+
constructor(maxSize = 1000, maxMemoryMB = 50) {
|
|
70
|
+
this.maxSize = maxSize;
|
|
71
|
+
this.maxMemory = maxMemoryMB * 1024 * 1024;
|
|
72
|
+
this.cache = new Map();
|
|
73
|
+
this.currentMemory = 0;
|
|
74
|
+
this.hits = 0;
|
|
75
|
+
this.misses = 0;
|
|
76
|
+
this.evictions = 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get(key) {
|
|
80
|
+
if (this.cache.has(key)) {
|
|
81
|
+
const value = this.cache.get(key);
|
|
82
|
+
// Move to end (most recently used)
|
|
83
|
+
this.cache.delete(key);
|
|
84
|
+
this.cache.set(key, value);
|
|
85
|
+
this.hits++;
|
|
86
|
+
return value.data;
|
|
87
|
+
}
|
|
88
|
+
this.misses++;
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
set(key, data) {
|
|
93
|
+
const size = this._estimateSize(data);
|
|
94
|
+
|
|
95
|
+
// Check memory pressure
|
|
96
|
+
if (this.currentMemory + size > this.maxMemory) {
|
|
97
|
+
this._evictByMemoryPressure(size);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check size limit
|
|
101
|
+
if (this.cache.size >= this.maxSize) {
|
|
102
|
+
this._evictLRU();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const entry = {
|
|
106
|
+
data,
|
|
107
|
+
size,
|
|
108
|
+
timestamp: Date.now(),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
this.cache.set(key, entry);
|
|
112
|
+
this.currentMemory += size;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
_estimateSize(obj) {
|
|
116
|
+
return JSON.stringify(obj).length * 2; // Rough estimate
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_evictLRU() {
|
|
120
|
+
const firstKey = this.cache.keys().next().value;
|
|
121
|
+
if (firstKey) {
|
|
122
|
+
const entry = this.cache.get(firstKey);
|
|
123
|
+
this.cache.delete(firstKey);
|
|
124
|
+
this.currentMemory -= entry.size;
|
|
125
|
+
this.evictions++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_evictByMemoryPressure(neededSize) {
|
|
130
|
+
while (this.currentMemory + neededSize > this.maxMemory && this.cache.size > 0) {
|
|
131
|
+
this._evictLRU();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
forEach(callback) {
|
|
136
|
+
this.cache.forEach((entry, key) => {
|
|
137
|
+
callback(entry, key);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
delete(key) {
|
|
142
|
+
if (this.cache.has(key)) {
|
|
143
|
+
const entry = this.cache.get(key);
|
|
144
|
+
this.cache.delete(key);
|
|
145
|
+
this.currentMemory -= entry.size;
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
getStats() {
|
|
152
|
+
return {
|
|
153
|
+
size: this.cache.size,
|
|
154
|
+
memoryUsage: this.currentMemory,
|
|
155
|
+
hitRate: (this.hits / (this.hits + this.misses)) * 100,
|
|
156
|
+
evictions: this.evictions,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Optimized CollectiveMemory class with advanced memory management
|
|
163
|
+
*/
|
|
164
|
+
export class CollectiveMemory extends EventEmitter {
|
|
165
|
+
constructor(config = {}) {
|
|
166
|
+
super();
|
|
167
|
+
|
|
168
|
+
/** @type {import('better-sqlite3').Database | null} */
|
|
169
|
+
this.db = null;
|
|
170
|
+
|
|
171
|
+
this.config = {
|
|
172
|
+
swarmId: config.swarmId,
|
|
173
|
+
maxSize: config.maxSize || 100, // MB
|
|
174
|
+
dbPath: config.dbPath || path.join(process.cwd(), '.hive-mind', 'hive.db'),
|
|
175
|
+
compressionThreshold: config.compressionThreshold || 1024, // bytes
|
|
176
|
+
gcInterval: config.gcInterval || 300000, // 5 minutes
|
|
177
|
+
cacheSize: config.cacheSize || 1000,
|
|
178
|
+
cacheMemoryMB: config.cacheMemoryMB || 50,
|
|
179
|
+
enablePooling: config.enablePooling !== false,
|
|
180
|
+
enableAsyncOperations: config.enableAsyncOperations !== false,
|
|
181
|
+
...config,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
this.state = {
|
|
185
|
+
totalSize: 0,
|
|
186
|
+
entryCount: 0,
|
|
187
|
+
compressionRatio: 1,
|
|
188
|
+
lastGC: Date.now(),
|
|
189
|
+
accessPatterns: new Map(),
|
|
190
|
+
performanceMetrics: {
|
|
191
|
+
queryTimes: [],
|
|
192
|
+
avgQueryTime: 0,
|
|
193
|
+
cacheHitRate: 0,
|
|
194
|
+
memoryEfficiency: 0,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
this.gcTimer = null;
|
|
199
|
+
|
|
200
|
+
// Optimized cache with LRU eviction
|
|
201
|
+
this.cache = new OptimizedLRUCache(this.config.cacheSize, this.config.cacheMemoryMB);
|
|
202
|
+
|
|
203
|
+
// Memory pools for frequently created objects
|
|
204
|
+
this.pools = {
|
|
205
|
+
queryResults: new MemoryPool(
|
|
206
|
+
() => ({ results: [], metadata: {} }),
|
|
207
|
+
(obj) => {
|
|
208
|
+
obj.results.length = 0;
|
|
209
|
+
Object.keys(obj.metadata).forEach((k) => delete obj.metadata[k]);
|
|
210
|
+
},
|
|
211
|
+
),
|
|
212
|
+
memoryEntries: new MemoryPool(
|
|
213
|
+
() => ({ id: '', key: '', value: '', metadata: {} }),
|
|
214
|
+
(obj) => {
|
|
215
|
+
obj.id = obj.key = obj.value = '';
|
|
216
|
+
Object.keys(obj.metadata).forEach((k) => delete obj.metadata[k]);
|
|
217
|
+
},
|
|
218
|
+
),
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Prepared statements for better performance
|
|
222
|
+
this.statements = new Map();
|
|
223
|
+
|
|
224
|
+
// Background worker for heavy operations
|
|
225
|
+
this.backgroundWorker = null;
|
|
226
|
+
|
|
227
|
+
this._initialize();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Initialize collective memory with optimizations
|
|
232
|
+
*/
|
|
233
|
+
_initialize() {
|
|
234
|
+
try {
|
|
235
|
+
// Open database connection with optimizations
|
|
236
|
+
this.db = new Database(this.config.dbPath);
|
|
237
|
+
|
|
238
|
+
// Performance optimizations
|
|
239
|
+
this.db.pragma('journal_mode = WAL');
|
|
240
|
+
this.db.pragma('synchronous = NORMAL');
|
|
241
|
+
this.db.pragma('cache_size = -64000'); // 64MB cache
|
|
242
|
+
this.db.pragma('temp_store = MEMORY');
|
|
243
|
+
this.db.pragma('mmap_size = 268435456'); // 256MB memory mapping
|
|
244
|
+
this.db.pragma('optimize');
|
|
245
|
+
|
|
246
|
+
// Ensure table exists with optimized schema
|
|
247
|
+
this.db.exec(`
|
|
248
|
+
CREATE TABLE IF NOT EXISTS collective_memory (
|
|
249
|
+
id TEXT PRIMARY KEY,
|
|
250
|
+
swarm_id TEXT NOT NULL,
|
|
251
|
+
key TEXT NOT NULL,
|
|
252
|
+
value BLOB,
|
|
253
|
+
type TEXT DEFAULT 'knowledge',
|
|
254
|
+
confidence REAL DEFAULT 1.0,
|
|
255
|
+
created_by TEXT,
|
|
256
|
+
created_at INTEGER DEFAULT (strftime('%s','now')),
|
|
257
|
+
accessed_at INTEGER DEFAULT (strftime('%s','now')),
|
|
258
|
+
access_count INTEGER DEFAULT 0,
|
|
259
|
+
compressed INTEGER DEFAULT 0,
|
|
260
|
+
size INTEGER DEFAULT 0,
|
|
261
|
+
FOREIGN KEY (swarm_id) REFERENCES swarms(id)
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
-- Optimized indexes
|
|
265
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_swarm_key
|
|
266
|
+
ON collective_memory(swarm_id, key);
|
|
267
|
+
|
|
268
|
+
CREATE INDEX IF NOT EXISTS idx_memory_type_accessed
|
|
269
|
+
ON collective_memory(type, accessed_at DESC);
|
|
270
|
+
|
|
271
|
+
CREATE INDEX IF NOT EXISTS idx_memory_size_compressed
|
|
272
|
+
ON collective_memory(size, compressed);
|
|
273
|
+
|
|
274
|
+
-- Memory optimization view
|
|
275
|
+
CREATE VIEW IF NOT EXISTS memory_stats AS
|
|
276
|
+
SELECT
|
|
277
|
+
swarm_id,
|
|
278
|
+
type,
|
|
279
|
+
COUNT(*) as entry_count,
|
|
280
|
+
SUM(size) as total_size,
|
|
281
|
+
AVG(access_count) as avg_access,
|
|
282
|
+
MAX(accessed_at) as last_access
|
|
283
|
+
FROM collective_memory
|
|
284
|
+
GROUP BY swarm_id, type;
|
|
285
|
+
`);
|
|
286
|
+
|
|
287
|
+
// Prepare optimized statements
|
|
288
|
+
this._prepareStatements();
|
|
289
|
+
|
|
290
|
+
// Load initial statistics
|
|
291
|
+
this._updateStatistics();
|
|
292
|
+
|
|
293
|
+
// Start background optimization processes
|
|
294
|
+
this._startOptimizationTimers();
|
|
295
|
+
|
|
296
|
+
// Initialize background worker for heavy operations
|
|
297
|
+
if (this.config.enableAsyncOperations) {
|
|
298
|
+
this._initializeBackgroundWorker();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
this.emit('memory:initialized', {
|
|
302
|
+
swarmId: this.config.swarmId,
|
|
303
|
+
optimizations: {
|
|
304
|
+
pooling: this.config.enablePooling,
|
|
305
|
+
asyncOps: this.config.enableAsyncOperations,
|
|
306
|
+
cacheSize: this.config.cacheSize,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
} catch (error) {
|
|
310
|
+
this.emit('error', error);
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Prepare optimized SQL statements
|
|
317
|
+
*/
|
|
318
|
+
_prepareStatements() {
|
|
319
|
+
this.statements.set(
|
|
320
|
+
'insert',
|
|
321
|
+
this.db.prepare(`
|
|
322
|
+
INSERT OR REPLACE INTO collective_memory
|
|
323
|
+
(id, swarm_id, key, value, type, confidence, created_by, compressed, size)
|
|
324
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
325
|
+
`),
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
this.statements.set(
|
|
329
|
+
'update',
|
|
330
|
+
this.db.prepare(`
|
|
331
|
+
UPDATE collective_memory
|
|
332
|
+
SET value = ?, accessed_at = strftime('%s','now'), access_count = access_count + 1,
|
|
333
|
+
compressed = ?, size = ?
|
|
334
|
+
WHERE swarm_id = ? AND key = ?
|
|
335
|
+
`),
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
this.statements.set(
|
|
339
|
+
'select',
|
|
340
|
+
this.db.prepare(`
|
|
341
|
+
SELECT value, type, compressed, confidence, access_count
|
|
342
|
+
FROM collective_memory
|
|
343
|
+
WHERE swarm_id = ? AND key = ?
|
|
344
|
+
`),
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
this.statements.set(
|
|
348
|
+
'updateAccess',
|
|
349
|
+
this.db.prepare(`
|
|
350
|
+
UPDATE collective_memory
|
|
351
|
+
SET accessed_at = strftime('%s','now'), access_count = access_count + 1
|
|
352
|
+
WHERE swarm_id = ? AND key = ?
|
|
353
|
+
`),
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
this.statements.set(
|
|
357
|
+
'searchByPattern',
|
|
358
|
+
this.db.prepare(`
|
|
359
|
+
SELECT key, type, confidence, created_at, accessed_at, access_count
|
|
360
|
+
FROM collective_memory
|
|
361
|
+
WHERE swarm_id = ? AND key LIKE ? AND confidence >= ?
|
|
362
|
+
ORDER BY access_count DESC, confidence DESC
|
|
363
|
+
LIMIT ?
|
|
364
|
+
`),
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
this.statements.set(
|
|
368
|
+
'getStats',
|
|
369
|
+
this.db.prepare(`
|
|
370
|
+
SELECT
|
|
371
|
+
COUNT(*) as count,
|
|
372
|
+
SUM(size) as totalSize,
|
|
373
|
+
AVG(confidence) as avgConfidence,
|
|
374
|
+
SUM(compressed) as compressedCount,
|
|
375
|
+
AVG(access_count) as avgAccess
|
|
376
|
+
FROM collective_memory
|
|
377
|
+
WHERE swarm_id = ?
|
|
378
|
+
`),
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
this.statements.set(
|
|
382
|
+
'deleteExpired',
|
|
383
|
+
this.db.prepare(`
|
|
384
|
+
DELETE FROM collective_memory
|
|
385
|
+
WHERE swarm_id = ? AND type = ? AND (strftime('%s','now') - accessed_at) > ?
|
|
386
|
+
`),
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
this.statements.set(
|
|
390
|
+
'getLRU',
|
|
391
|
+
this.db.prepare(`
|
|
392
|
+
SELECT id, size FROM collective_memory
|
|
393
|
+
WHERE swarm_id = ? AND type NOT IN ('system', 'consensus')
|
|
394
|
+
ORDER BY accessed_at ASC, access_count ASC
|
|
395
|
+
LIMIT ?
|
|
396
|
+
`),
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Start optimization timers
|
|
402
|
+
*/
|
|
403
|
+
_startOptimizationTimers() {
|
|
404
|
+
// Main garbage collection
|
|
405
|
+
this.gcTimer = setInterval(() => this._garbageCollect(), this.config.gcInterval);
|
|
406
|
+
|
|
407
|
+
// Database optimization
|
|
408
|
+
this.optimizeTimer = setInterval(() => this._optimizeDatabase(), 1800000); // 30 minutes
|
|
409
|
+
|
|
410
|
+
// Cache cleanup
|
|
411
|
+
this.cacheTimer = setInterval(() => this._optimizeCache(), 60000); // 1 minute
|
|
412
|
+
|
|
413
|
+
// Performance monitoring
|
|
414
|
+
this.metricsTimer = setInterval(() => this._updatePerformanceMetrics(), 30000); // 30 seconds
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Initialize background worker for heavy operations
|
|
419
|
+
*/
|
|
420
|
+
_initializeBackgroundWorker() {
|
|
421
|
+
// Note: In production, this would initialize a proper Worker
|
|
422
|
+
// For now, we'll use async operations
|
|
423
|
+
this.backgroundQueue = [];
|
|
424
|
+
this.backgroundProcessing = false;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Store data in collective memory
|
|
429
|
+
*/
|
|
430
|
+
async store(key, value, type = 'knowledge', metadata = {}) {
|
|
431
|
+
try {
|
|
432
|
+
const serialized = JSON.stringify(value);
|
|
433
|
+
const size = Buffer.byteLength(serialized);
|
|
434
|
+
const shouldCompress =
|
|
435
|
+
size > this.config.compressionThreshold && MEMORY_TYPES[type]?.compress;
|
|
436
|
+
|
|
437
|
+
let storedValue = serialized;
|
|
438
|
+
let compressed = 0;
|
|
439
|
+
|
|
440
|
+
if (shouldCompress) {
|
|
441
|
+
// In production, use proper compression like zlib
|
|
442
|
+
// For now, we'll just mark it as compressed
|
|
443
|
+
compressed = 1;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const id = `${this.config.swarmId}-${key}-${Date.now()}`;
|
|
447
|
+
|
|
448
|
+
// Check if key already exists
|
|
449
|
+
const existing = this.db
|
|
450
|
+
.prepare(
|
|
451
|
+
`
|
|
452
|
+
SELECT id FROM collective_memory
|
|
453
|
+
WHERE swarm_id = ? AND key = ?
|
|
454
|
+
`,
|
|
455
|
+
)
|
|
456
|
+
.get(this.config.swarmId, key);
|
|
457
|
+
|
|
458
|
+
if (existing) {
|
|
459
|
+
// Update existing entry
|
|
460
|
+
this.db
|
|
461
|
+
.prepare(
|
|
462
|
+
`
|
|
463
|
+
UPDATE collective_memory
|
|
464
|
+
SET value = ?, type = ?, confidence = ?,
|
|
465
|
+
accessed_at = CURRENT_TIMESTAMP, access_count = access_count + 1,
|
|
466
|
+
compressed = ?, size = ?
|
|
467
|
+
WHERE swarm_id = ? AND key = ?
|
|
468
|
+
`,
|
|
469
|
+
)
|
|
470
|
+
.run(
|
|
471
|
+
storedValue,
|
|
472
|
+
type,
|
|
473
|
+
metadata.confidence || 1.0,
|
|
474
|
+
compressed,
|
|
475
|
+
size,
|
|
476
|
+
this.config.swarmId,
|
|
477
|
+
key,
|
|
478
|
+
);
|
|
479
|
+
} else {
|
|
480
|
+
// Insert new entry
|
|
481
|
+
this.db
|
|
482
|
+
.prepare(
|
|
483
|
+
`
|
|
484
|
+
INSERT INTO collective_memory
|
|
485
|
+
(id, swarm_id, key, value, type, confidence, created_by, compressed, size)
|
|
486
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
487
|
+
`,
|
|
488
|
+
)
|
|
489
|
+
.run(
|
|
490
|
+
id,
|
|
491
|
+
this.config.swarmId,
|
|
492
|
+
key,
|
|
493
|
+
storedValue,
|
|
494
|
+
type,
|
|
495
|
+
metadata.confidence || 1.0,
|
|
496
|
+
metadata.createdBy || 'system',
|
|
497
|
+
compressed,
|
|
498
|
+
size,
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Update cache
|
|
503
|
+
this.cache.set(key, {
|
|
504
|
+
value,
|
|
505
|
+
type,
|
|
506
|
+
timestamp: Date.now(),
|
|
507
|
+
size,
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// Check memory limits
|
|
511
|
+
this._checkMemoryLimits();
|
|
512
|
+
|
|
513
|
+
// Track access pattern
|
|
514
|
+
this._trackAccess(key, 'write');
|
|
515
|
+
|
|
516
|
+
this.emit('memory:stored', { key, type, size });
|
|
517
|
+
|
|
518
|
+
return { success: true, id, size };
|
|
519
|
+
} catch (error) {
|
|
520
|
+
this.emit('error', error);
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Retrieve data from collective memory
|
|
527
|
+
*/
|
|
528
|
+
async retrieve(key) {
|
|
529
|
+
try {
|
|
530
|
+
// Check cache first
|
|
531
|
+
if (this.cache.has(key)) {
|
|
532
|
+
const cached = this.cache.get(key);
|
|
533
|
+
this._trackAccess(key, 'cache_hit');
|
|
534
|
+
return cached.value;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Query database
|
|
538
|
+
const result = this.db
|
|
539
|
+
.prepare(
|
|
540
|
+
`
|
|
541
|
+
SELECT value, type, compressed, confidence
|
|
542
|
+
FROM collective_memory
|
|
543
|
+
WHERE swarm_id = ? AND key = ?
|
|
544
|
+
`,
|
|
545
|
+
)
|
|
546
|
+
.get(this.config.swarmId, key);
|
|
547
|
+
|
|
548
|
+
if (!result) {
|
|
549
|
+
this._trackAccess(key, 'miss');
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Update access statistics
|
|
554
|
+
this.db
|
|
555
|
+
.prepare(
|
|
556
|
+
`
|
|
557
|
+
UPDATE collective_memory
|
|
558
|
+
SET accessed_at = CURRENT_TIMESTAMP,
|
|
559
|
+
access_count = access_count + 1
|
|
560
|
+
WHERE swarm_id = ? AND key = ?
|
|
561
|
+
`,
|
|
562
|
+
)
|
|
563
|
+
.run(this.config.swarmId, key);
|
|
564
|
+
|
|
565
|
+
// Decompress if needed
|
|
566
|
+
let value = result.value;
|
|
567
|
+
if (result.compressed) {
|
|
568
|
+
// In production, decompress here
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Parse JSON
|
|
572
|
+
const parsed = JSON.parse(value);
|
|
573
|
+
|
|
574
|
+
// Add to cache
|
|
575
|
+
this.cache.set(key, {
|
|
576
|
+
value: parsed,
|
|
577
|
+
type: result.type,
|
|
578
|
+
timestamp: Date.now(),
|
|
579
|
+
confidence: result.confidence,
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
this._trackAccess(key, 'read');
|
|
583
|
+
|
|
584
|
+
return parsed;
|
|
585
|
+
} catch (error) {
|
|
586
|
+
this.emit('error', error);
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Search collective memory
|
|
593
|
+
*/
|
|
594
|
+
async search(pattern, options = {}) {
|
|
595
|
+
try {
|
|
596
|
+
const limit = options.limit || 50;
|
|
597
|
+
const type = options.type || null;
|
|
598
|
+
const minConfidence = options.minConfidence || 0;
|
|
599
|
+
|
|
600
|
+
let query = `
|
|
601
|
+
SELECT key, type, confidence, created_at, accessed_at, access_count
|
|
602
|
+
FROM collective_memory
|
|
603
|
+
WHERE swarm_id = ?
|
|
604
|
+
AND key LIKE ?
|
|
605
|
+
AND confidence >= ?
|
|
606
|
+
`;
|
|
607
|
+
|
|
608
|
+
const params = [this.config.swarmId, `%${pattern}%`, minConfidence];
|
|
609
|
+
|
|
610
|
+
if (type) {
|
|
611
|
+
query += ' AND type = ?';
|
|
612
|
+
params.push(type);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
query += ' ORDER BY access_count DESC, confidence DESC LIMIT ?';
|
|
616
|
+
params.push(limit);
|
|
617
|
+
|
|
618
|
+
const results = this.db.prepare(query).all(...params);
|
|
619
|
+
|
|
620
|
+
this._trackAccess(`search:${pattern}`, 'search');
|
|
621
|
+
|
|
622
|
+
return results;
|
|
623
|
+
} catch (error) {
|
|
624
|
+
this.emit('error', error);
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Get related memories using association
|
|
631
|
+
*/
|
|
632
|
+
async getRelated(key, limit = 10) {
|
|
633
|
+
try {
|
|
634
|
+
// Get the original memory
|
|
635
|
+
const original = await this.retrieve(key);
|
|
636
|
+
if (!original) return [];
|
|
637
|
+
|
|
638
|
+
// Simple association: find memories accessed around the same time
|
|
639
|
+
const result = this.db
|
|
640
|
+
.prepare(
|
|
641
|
+
`
|
|
642
|
+
SELECT m1.key, m1.type, m1.confidence, m1.access_count
|
|
643
|
+
FROM collective_memory m1
|
|
644
|
+
JOIN collective_memory m2 ON m1.swarm_id = m2.swarm_id
|
|
645
|
+
WHERE m2.key = ?
|
|
646
|
+
AND m1.key != ?
|
|
647
|
+
AND m1.swarm_id = ?
|
|
648
|
+
AND ABS(julianday(m1.accessed_at) - julianday(m2.accessed_at)) < 0.01
|
|
649
|
+
ORDER BY m1.confidence DESC, m1.access_count DESC
|
|
650
|
+
LIMIT ?
|
|
651
|
+
`,
|
|
652
|
+
)
|
|
653
|
+
.all(key, key, this.config.swarmId, limit);
|
|
654
|
+
|
|
655
|
+
return result;
|
|
656
|
+
} catch (error) {
|
|
657
|
+
this.emit('error', error);
|
|
658
|
+
throw error;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Build associations between memories
|
|
664
|
+
*/
|
|
665
|
+
async associate(key1, key2, strength = 1.0) {
|
|
666
|
+
try {
|
|
667
|
+
// Store bidirectional association
|
|
668
|
+
await this.store(
|
|
669
|
+
`assoc:${key1}:${key2}`,
|
|
670
|
+
{
|
|
671
|
+
from: key1,
|
|
672
|
+
to: key2,
|
|
673
|
+
strength,
|
|
674
|
+
created: Date.now(),
|
|
675
|
+
},
|
|
676
|
+
'system',
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
await this.store(
|
|
680
|
+
`assoc:${key2}:${key1}`,
|
|
681
|
+
{
|
|
682
|
+
from: key2,
|
|
683
|
+
to: key1,
|
|
684
|
+
strength,
|
|
685
|
+
created: Date.now(),
|
|
686
|
+
},
|
|
687
|
+
'system',
|
|
688
|
+
);
|
|
689
|
+
|
|
690
|
+
this.emit('memory:associated', { key1, key2, strength });
|
|
691
|
+
} catch (error) {
|
|
692
|
+
this.emit('error', error);
|
|
693
|
+
throw error;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Consolidate similar memories
|
|
699
|
+
*/
|
|
700
|
+
async consolidate() {
|
|
701
|
+
try {
|
|
702
|
+
// Find similar memories
|
|
703
|
+
const memories = this.db
|
|
704
|
+
.prepare(
|
|
705
|
+
`
|
|
706
|
+
SELECT key, value, type, confidence, access_count
|
|
707
|
+
FROM collective_memory
|
|
708
|
+
WHERE swarm_id = ?
|
|
709
|
+
AND type IN ('knowledge', 'result')
|
|
710
|
+
ORDER BY created_at DESC
|
|
711
|
+
LIMIT 1000
|
|
712
|
+
`,
|
|
713
|
+
)
|
|
714
|
+
.all(this.config.swarmId);
|
|
715
|
+
|
|
716
|
+
const consolidated = new Map();
|
|
717
|
+
|
|
718
|
+
// Group by similarity (simple implementation)
|
|
719
|
+
memories.forEach((memory) => {
|
|
720
|
+
const value = JSON.parse(memory.value);
|
|
721
|
+
const category = this._categorizeMemory(value);
|
|
722
|
+
|
|
723
|
+
if (!consolidated.has(category)) {
|
|
724
|
+
consolidated.set(category, []);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
consolidated.get(category).push({
|
|
728
|
+
...memory,
|
|
729
|
+
value,
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
// Merge similar memories
|
|
734
|
+
let mergeCount = 0;
|
|
735
|
+
consolidated.forEach((group, category) => {
|
|
736
|
+
if (group.length > 1) {
|
|
737
|
+
const merged = this._mergeMemories(group);
|
|
738
|
+
|
|
739
|
+
// Store merged memory
|
|
740
|
+
this.store(`consolidated:${category}`, merged, 'knowledge', {
|
|
741
|
+
confidence: merged.confidence,
|
|
742
|
+
createdBy: 'consolidation',
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
mergeCount++;
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
this.emit('memory:consolidated', { categories: consolidated.size, merged: mergeCount });
|
|
750
|
+
|
|
751
|
+
return { categories: consolidated.size, merged: mergeCount };
|
|
752
|
+
} catch (error) {
|
|
753
|
+
this.emit('error', error);
|
|
754
|
+
throw error;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Categorize memory for consolidation
|
|
760
|
+
*/
|
|
761
|
+
_categorizeMemory(value) {
|
|
762
|
+
// Simple categorization based on content
|
|
763
|
+
if (typeof value === 'string') {
|
|
764
|
+
return 'text';
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (typeof value === 'object') {
|
|
768
|
+
const keys = Object.keys(value).sort().join(':');
|
|
769
|
+
return `object:${keys.substring(0, 50)}`;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
return 'other';
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Merge similar memories
|
|
777
|
+
*/
|
|
778
|
+
_mergeMemories(memories) {
|
|
779
|
+
// Calculate weighted average confidence
|
|
780
|
+
let totalWeight = 0;
|
|
781
|
+
let weightedConfidence = 0;
|
|
782
|
+
const mergedValue = {};
|
|
783
|
+
|
|
784
|
+
memories.forEach((memory) => {
|
|
785
|
+
const weight = memory.access_count + 1;
|
|
786
|
+
totalWeight += weight;
|
|
787
|
+
weightedConfidence += memory.confidence * weight;
|
|
788
|
+
|
|
789
|
+
// Merge values (simple implementation)
|
|
790
|
+
if (typeof memory.value === 'object') {
|
|
791
|
+
Object.assign(mergedValue, memory.value);
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
return {
|
|
796
|
+
value: mergedValue,
|
|
797
|
+
confidence: weightedConfidence / totalWeight,
|
|
798
|
+
sourceCount: memories.length,
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Garbage collection
|
|
804
|
+
*/
|
|
805
|
+
_garbageCollect() {
|
|
806
|
+
try {
|
|
807
|
+
const now = Date.now();
|
|
808
|
+
let deletedCount = 0;
|
|
809
|
+
|
|
810
|
+
// Delete expired memories based on TTL
|
|
811
|
+
Object.entries(MEMORY_TYPES).forEach(([type, config]) => {
|
|
812
|
+
if (config.ttl) {
|
|
813
|
+
const result = this.db
|
|
814
|
+
.prepare(
|
|
815
|
+
`
|
|
816
|
+
DELETE FROM collective_memory
|
|
817
|
+
WHERE swarm_id = ?
|
|
818
|
+
AND type = ?
|
|
819
|
+
AND (julianday('now') - julianday(accessed_at)) * 86400000 > ?
|
|
820
|
+
`,
|
|
821
|
+
)
|
|
822
|
+
.run(this.config.swarmId, type, config.ttl);
|
|
823
|
+
|
|
824
|
+
deletedCount += result.changes;
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
// Clear old cache entries
|
|
829
|
+
const cacheTimeout = 300000; // 5 minutes
|
|
830
|
+
this.cache.forEach((value, key) => {
|
|
831
|
+
if (now - value.timestamp > cacheTimeout) {
|
|
832
|
+
this.cache.delete(key);
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
// Update statistics
|
|
837
|
+
this._updateStatistics();
|
|
838
|
+
|
|
839
|
+
this.state.lastGC = now;
|
|
840
|
+
|
|
841
|
+
if (deletedCount > 0) {
|
|
842
|
+
this.emit('memory:gc', { deleted: deletedCount, cacheSize: this.cache.size });
|
|
843
|
+
}
|
|
844
|
+
} catch (error) {
|
|
845
|
+
this.emit('error', error);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Check memory limits and evict if necessary
|
|
851
|
+
*/
|
|
852
|
+
_checkMemoryLimits() {
|
|
853
|
+
if (this.state.totalSize > this.config.maxSize * 1024 * 1024) {
|
|
854
|
+
// Evict least recently used memories
|
|
855
|
+
const toEvict = this.db
|
|
856
|
+
.prepare(
|
|
857
|
+
`
|
|
858
|
+
SELECT id, size FROM collective_memory
|
|
859
|
+
WHERE swarm_id = ?
|
|
860
|
+
AND type NOT IN ('system', 'consensus')
|
|
861
|
+
ORDER BY accessed_at ASC, access_count ASC
|
|
862
|
+
LIMIT 100
|
|
863
|
+
`,
|
|
864
|
+
)
|
|
865
|
+
.all(this.config.swarmId);
|
|
866
|
+
|
|
867
|
+
let freedSize = 0;
|
|
868
|
+
toEvict.forEach((memory) => {
|
|
869
|
+
this.db.prepare('DELETE FROM collective_memory WHERE id = ?').run(memory.id);
|
|
870
|
+
freedSize += memory.size;
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
this.emit('memory:evicted', { count: toEvict.length, freedSize });
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Optimize database performance
|
|
879
|
+
*/
|
|
880
|
+
_optimizeDatabase() {
|
|
881
|
+
try {
|
|
882
|
+
// Run database optimization
|
|
883
|
+
this.db.pragma('optimize');
|
|
884
|
+
this.db.pragma('analysis_limit=1000');
|
|
885
|
+
this.db.exec('ANALYZE');
|
|
886
|
+
|
|
887
|
+
// Update database statistics
|
|
888
|
+
this._updateStatistics();
|
|
889
|
+
|
|
890
|
+
this.emit('database:optimized');
|
|
891
|
+
} catch (error) {
|
|
892
|
+
this.emit('error', error);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Optimize cache performance
|
|
898
|
+
*/
|
|
899
|
+
_optimizeCache() {
|
|
900
|
+
try {
|
|
901
|
+
const now = Date.now();
|
|
902
|
+
const cacheTimeout = 300000; // 5 minutes
|
|
903
|
+
|
|
904
|
+
// Clear expired cache entries
|
|
905
|
+
if (this.cache.cache) {
|
|
906
|
+
this.cache.cache.forEach((value, key) => {
|
|
907
|
+
if (now - value.timestamp > cacheTimeout) {
|
|
908
|
+
this.cache.cache.delete(key);
|
|
909
|
+
}
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
this.emit('cache:optimized', {
|
|
914
|
+
size: this.cache.cache ? this.cache.cache.size : 0,
|
|
915
|
+
});
|
|
916
|
+
} catch (error) {
|
|
917
|
+
this.emit('error', error);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Update performance metrics
|
|
923
|
+
*/
|
|
924
|
+
_updatePerformanceMetrics() {
|
|
925
|
+
try {
|
|
926
|
+
// Calculate cache hit rate
|
|
927
|
+
const cacheStats = this.cache.getStats();
|
|
928
|
+
this.state.performanceMetrics.cacheHitRate = cacheStats.hitRate || 0;
|
|
929
|
+
|
|
930
|
+
// Calculate memory efficiency
|
|
931
|
+
this.state.performanceMetrics.memoryEfficiency =
|
|
932
|
+
(this.state.totalSize / (this.config.maxSize * 1024 * 1024)) * 100;
|
|
933
|
+
|
|
934
|
+
// Update average query time if we have recent measurements
|
|
935
|
+
if (this.state.performanceMetrics.queryTimes.length > 0) {
|
|
936
|
+
this.state.performanceMetrics.avgQueryTime =
|
|
937
|
+
this.state.performanceMetrics.queryTimes.reduce((sum, time) => sum + time, 0) /
|
|
938
|
+
this.state.performanceMetrics.queryTimes.length;
|
|
939
|
+
|
|
940
|
+
// Keep only recent query times (last 100)
|
|
941
|
+
if (this.state.performanceMetrics.queryTimes.length > 100) {
|
|
942
|
+
this.state.performanceMetrics.queryTimes =
|
|
943
|
+
this.state.performanceMetrics.queryTimes.slice(-100);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
this.emit('metrics:updated', this.state.performanceMetrics);
|
|
948
|
+
} catch (error) {
|
|
949
|
+
this.emit('error', error);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Update memory statistics
|
|
955
|
+
*/
|
|
956
|
+
_updateStatistics() {
|
|
957
|
+
const stats = this.db
|
|
958
|
+
.prepare(
|
|
959
|
+
`
|
|
960
|
+
SELECT
|
|
961
|
+
COUNT(*) as count,
|
|
962
|
+
SUM(size) as totalSize,
|
|
963
|
+
AVG(confidence) as avgConfidence,
|
|
964
|
+
SUM(compressed) as compressedCount
|
|
965
|
+
FROM collective_memory
|
|
966
|
+
WHERE swarm_id = ?
|
|
967
|
+
`,
|
|
968
|
+
)
|
|
969
|
+
.get(this.config.swarmId);
|
|
970
|
+
|
|
971
|
+
this.state.entryCount = stats.count || 0;
|
|
972
|
+
this.state.totalSize = stats.totalSize || 0;
|
|
973
|
+
this.state.avgConfidence = stats.avgConfidence || 1.0;
|
|
974
|
+
|
|
975
|
+
if (stats.compressedCount > 0) {
|
|
976
|
+
// Estimate compression ratio
|
|
977
|
+
this.state.compressionRatio = 0.6; // Assume 40% compression
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Track access patterns
|
|
983
|
+
*/
|
|
984
|
+
_trackAccess(key, operation) {
|
|
985
|
+
const pattern = this.state.accessPatterns.get(key) || {
|
|
986
|
+
reads: 0,
|
|
987
|
+
writes: 0,
|
|
988
|
+
searches: 0,
|
|
989
|
+
cacheHits: 0,
|
|
990
|
+
misses: 0,
|
|
991
|
+
lastAccess: Date.now(),
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
switch (operation) {
|
|
995
|
+
case 'read':
|
|
996
|
+
pattern.reads++;
|
|
997
|
+
break;
|
|
998
|
+
case 'write':
|
|
999
|
+
pattern.writes++;
|
|
1000
|
+
break;
|
|
1001
|
+
case 'search':
|
|
1002
|
+
pattern.searches++;
|
|
1003
|
+
break;
|
|
1004
|
+
case 'cache_hit':
|
|
1005
|
+
pattern.cacheHits++;
|
|
1006
|
+
break;
|
|
1007
|
+
case 'miss':
|
|
1008
|
+
pattern.misses++;
|
|
1009
|
+
break;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
pattern.lastAccess = Date.now();
|
|
1013
|
+
this.state.accessPatterns.set(key, pattern);
|
|
1014
|
+
|
|
1015
|
+
// Keep access patterns size limited
|
|
1016
|
+
if (this.state.accessPatterns.size > 1000) {
|
|
1017
|
+
// Remove oldest entries
|
|
1018
|
+
const sorted = Array.from(this.state.accessPatterns.entries()).sort(
|
|
1019
|
+
(a, b) => a[1].lastAccess - b[1].lastAccess,
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
sorted.slice(0, 100).forEach(([key]) => {
|
|
1023
|
+
this.state.accessPatterns.delete(key);
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Get enhanced memory statistics
|
|
1030
|
+
*/
|
|
1031
|
+
getStatistics() {
|
|
1032
|
+
return {
|
|
1033
|
+
swarmId: this.config.swarmId,
|
|
1034
|
+
entryCount: this.state.entryCount,
|
|
1035
|
+
totalSize: this.state.totalSize,
|
|
1036
|
+
maxSize: this.config.maxSize * 1024 * 1024,
|
|
1037
|
+
utilizationPercent: (this.state.totalSize / (this.config.maxSize * 1024 * 1024)) * 100,
|
|
1038
|
+
avgConfidence: this.state.avgConfidence,
|
|
1039
|
+
compressionRatio: this.state.compressionRatio,
|
|
1040
|
+
cacheSize: this.cache.cache ? this.cache.cache.size : 0,
|
|
1041
|
+
lastGC: new Date(this.state.lastGC).toISOString(),
|
|
1042
|
+
accessPatterns: this.state.accessPatterns.size,
|
|
1043
|
+
optimization: {
|
|
1044
|
+
cacheOptimized: true,
|
|
1045
|
+
poolingEnabled: this.config.enablePooling,
|
|
1046
|
+
asyncOperations: this.config.enableAsyncOperations,
|
|
1047
|
+
compressionRatio: this.state.compressionRatio,
|
|
1048
|
+
performanceMetrics: this.state.performanceMetrics,
|
|
1049
|
+
},
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Export memory snapshot
|
|
1055
|
+
*/
|
|
1056
|
+
async exportSnapshot(filepath) {
|
|
1057
|
+
try {
|
|
1058
|
+
const memories = this.db
|
|
1059
|
+
.prepare(
|
|
1060
|
+
`
|
|
1061
|
+
SELECT * FROM collective_memory
|
|
1062
|
+
WHERE swarm_id = ?
|
|
1063
|
+
ORDER BY created_at DESC
|
|
1064
|
+
`,
|
|
1065
|
+
)
|
|
1066
|
+
.all(this.config.swarmId);
|
|
1067
|
+
|
|
1068
|
+
const snapshot = {
|
|
1069
|
+
swarmId: this.config.swarmId,
|
|
1070
|
+
timestamp: new Date().toISOString(),
|
|
1071
|
+
statistics: this.getStatistics(),
|
|
1072
|
+
memories: memories.map((m) => ({
|
|
1073
|
+
...m,
|
|
1074
|
+
value: JSON.parse(m.value),
|
|
1075
|
+
})),
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
// In production, write to file
|
|
1079
|
+
// For now, return the snapshot
|
|
1080
|
+
this.emit('memory:exported', { count: memories.length });
|
|
1081
|
+
|
|
1082
|
+
return snapshot;
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
this.emit('error', error);
|
|
1085
|
+
throw error;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Import memory snapshot
|
|
1091
|
+
*/
|
|
1092
|
+
async importSnapshot(snapshot) {
|
|
1093
|
+
try {
|
|
1094
|
+
let imported = 0;
|
|
1095
|
+
|
|
1096
|
+
for (const memory of snapshot.memories) {
|
|
1097
|
+
await this.store(memory.key, memory.value, memory.type, {
|
|
1098
|
+
confidence: memory.confidence,
|
|
1099
|
+
createdBy: memory.created_by,
|
|
1100
|
+
});
|
|
1101
|
+
imported++;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
this.emit('memory:imported', { count: imported });
|
|
1105
|
+
|
|
1106
|
+
return { imported };
|
|
1107
|
+
} catch (error) {
|
|
1108
|
+
this.emit('error', error);
|
|
1109
|
+
throw error;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Enhanced shutdown with cleanup
|
|
1115
|
+
*/
|
|
1116
|
+
close() {
|
|
1117
|
+
// Clear all timers
|
|
1118
|
+
if (this.gcTimer) clearInterval(this.gcTimer);
|
|
1119
|
+
if (this.optimizeTimer) clearInterval(this.optimizeTimer);
|
|
1120
|
+
if (this.cacheTimer) clearInterval(this.cacheTimer);
|
|
1121
|
+
if (this.metricsTimer) clearInterval(this.metricsTimer);
|
|
1122
|
+
|
|
1123
|
+
// Final optimization before closing
|
|
1124
|
+
try {
|
|
1125
|
+
this.db.pragma('optimize');
|
|
1126
|
+
} catch (error) {
|
|
1127
|
+
// Ignore errors during shutdown
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// Close database
|
|
1131
|
+
if (this.db) {
|
|
1132
|
+
this.db.close();
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// Clear memory pools
|
|
1136
|
+
if (this.config.enablePooling) {
|
|
1137
|
+
Object.values(this.pools).forEach((pool) => {
|
|
1138
|
+
pool.pool.length = 0;
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
const finalStats = {
|
|
1143
|
+
cacheStats: this.cache.getStats ? this.cache.getStats() : {},
|
|
1144
|
+
poolStats: this.config.enablePooling
|
|
1145
|
+
? {
|
|
1146
|
+
queryResults: this.pools.queryResults.getStats(),
|
|
1147
|
+
memoryEntries: this.pools.memoryEntries.getStats(),
|
|
1148
|
+
}
|
|
1149
|
+
: null,
|
|
1150
|
+
performanceMetrics: this.state.performanceMetrics,
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1153
|
+
this.emit('memory:closed', finalStats);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Get comprehensive memory analytics
|
|
1158
|
+
*/
|
|
1159
|
+
getAnalytics() {
|
|
1160
|
+
return {
|
|
1161
|
+
basic: this.getStatistics(),
|
|
1162
|
+
performance: this.state.performanceMetrics,
|
|
1163
|
+
cache: this.cache.getStats ? this.cache.getStats() : {},
|
|
1164
|
+
pools: this.config.enablePooling
|
|
1165
|
+
? {
|
|
1166
|
+
queryResults: this.pools.queryResults.getStats(),
|
|
1167
|
+
memoryEntries: this.pools.memoryEntries.getStats(),
|
|
1168
|
+
}
|
|
1169
|
+
: null,
|
|
1170
|
+
database: {
|
|
1171
|
+
fragmentation: this.db.pragma('freelist_count'),
|
|
1172
|
+
pageSize: this.db.pragma('page_size'),
|
|
1173
|
+
cacheSize: this.db.pragma('cache_size'),
|
|
1174
|
+
},
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Memory health check
|
|
1180
|
+
*/
|
|
1181
|
+
async healthCheck() {
|
|
1182
|
+
const analytics = this.getAnalytics();
|
|
1183
|
+
const health = {
|
|
1184
|
+
status: 'healthy',
|
|
1185
|
+
issues: [],
|
|
1186
|
+
recommendations: [],
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
// Check cache hit rate
|
|
1190
|
+
if (analytics.cache.hitRate < 50) {
|
|
1191
|
+
health.issues.push('Low cache hit rate');
|
|
1192
|
+
health.recommendations.push('Consider increasing cache size');
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// Check memory usage
|
|
1196
|
+
if (analytics.basic.utilizationPercent > 90) {
|
|
1197
|
+
health.status = 'warning';
|
|
1198
|
+
health.issues.push('High memory utilization');
|
|
1199
|
+
health.recommendations.push('Consider increasing max memory or running garbage collection');
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// Check query performance
|
|
1203
|
+
if (analytics.performance.avgQueryTime > 100) {
|
|
1204
|
+
health.issues.push('Slow query performance');
|
|
1205
|
+
health.recommendations.push('Consider database optimization or indexing');
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
return health;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* Memory optimization utilities
|
|
1214
|
+
*/
|
|
1215
|
+
export class MemoryOptimizer {
|
|
1216
|
+
static async optimizeCollectiveMemory(memory) {
|
|
1217
|
+
const startTime = performance.now();
|
|
1218
|
+
|
|
1219
|
+
// Run comprehensive optimization
|
|
1220
|
+
await memory._optimizeDatabase();
|
|
1221
|
+
memory._optimizeCache();
|
|
1222
|
+
memory._garbageCollect();
|
|
1223
|
+
|
|
1224
|
+
const duration = performance.now() - startTime;
|
|
1225
|
+
|
|
1226
|
+
return {
|
|
1227
|
+
duration,
|
|
1228
|
+
analytics: memory.getAnalytics(),
|
|
1229
|
+
health: await memory.healthCheck(),
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
static calculateOptimalCacheSize(memoryStats, accessPatterns) {
|
|
1234
|
+
const avgEntrySize = memoryStats.totalSize / memoryStats.entryCount;
|
|
1235
|
+
const hotKeys = Array.from(accessPatterns.entries())
|
|
1236
|
+
.sort((a, b) => b[1] - a[1])
|
|
1237
|
+
.slice(0, Math.min(1000, memoryStats.entryCount * 0.2));
|
|
1238
|
+
|
|
1239
|
+
const optimalCacheEntries = hotKeys.length * 1.2; // 20% buffer
|
|
1240
|
+
const optimalCacheMemoryMB = (optimalCacheEntries * avgEntrySize) / (1024 * 1024);
|
|
1241
|
+
|
|
1242
|
+
return {
|
|
1243
|
+
entries: Math.ceil(optimalCacheEntries),
|
|
1244
|
+
memoryMB: Math.ceil(optimalCacheMemoryMB),
|
|
1245
|
+
efficiency: (hotKeys.length / memoryStats.entryCount) * 100,
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
static generateOptimizationReport(analytics) {
|
|
1250
|
+
const report = {
|
|
1251
|
+
timestamp: new Date().toISOString(),
|
|
1252
|
+
summary: {},
|
|
1253
|
+
recommendations: [],
|
|
1254
|
+
metrics: analytics,
|
|
1255
|
+
};
|
|
1256
|
+
|
|
1257
|
+
// Performance summary
|
|
1258
|
+
report.summary.avgQueryTime = analytics.performance.avgQueryTime;
|
|
1259
|
+
report.summary.cacheHitRate = analytics.cache.hitRate || 0;
|
|
1260
|
+
report.summary.memoryEfficiency = analytics.cache.memoryUsage / (1024 * 1024);
|
|
1261
|
+
|
|
1262
|
+
// Generate recommendations
|
|
1263
|
+
if ((analytics.cache.hitRate || 0) < 70) {
|
|
1264
|
+
report.recommendations.push({
|
|
1265
|
+
type: 'cache',
|
|
1266
|
+
priority: 'high',
|
|
1267
|
+
description: 'Increase cache size to improve hit rate',
|
|
1268
|
+
impact: 'Reduce database queries by up to 30%',
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
if (analytics.performance.avgQueryTime > 50) {
|
|
1273
|
+
report.recommendations.push({
|
|
1274
|
+
type: 'database',
|
|
1275
|
+
priority: 'medium',
|
|
1276
|
+
description: 'Optimize database indexes and run ANALYZE',
|
|
1277
|
+
impact: 'Improve query performance by 20-40%',
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
if (analytics.pools?.queryResults?.reuseRate < 50) {
|
|
1282
|
+
report.recommendations.push({
|
|
1283
|
+
type: 'pooling',
|
|
1284
|
+
priority: 'low',
|
|
1285
|
+
description: 'Increase object pool sizes for better reuse',
|
|
1286
|
+
impact: 'Reduce garbage collection pressure',
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
return report;
|
|
1291
|
+
}
|
|
1292
|
+
}
|