agentdb 1.0.0
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/LICENSE +38 -0
- package/LICENSE-APACHE +190 -0
- package/LICENSE-MIT +21 -0
- package/README.md +953 -0
- package/bin/agentdb.js +485 -0
- package/bin/plugin-cli-wrapper.mjs +21 -0
- package/dist/cache/query-cache.d.ts +105 -0
- package/dist/cache/query-cache.d.ts.map +1 -0
- package/dist/cache/query-cache.js +224 -0
- package/dist/cache/query-cache.js.map +1 -0
- package/dist/cache/query-cache.mjs +219 -0
- package/dist/cli/cache/query-cache.d.ts +104 -0
- package/dist/cli/cache/query-cache.js +244 -0
- package/dist/cli/cli/db-commands.d.ts +48 -0
- package/dist/cli/cli/db-commands.js +613 -0
- package/dist/cli/commands.d.ts +7 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +113 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/commands.mjs +104 -0
- package/dist/cli/core/backend-interface.d.ts +70 -0
- package/dist/cli/core/backend-interface.js +15 -0
- package/dist/cli/core/native-backend.d.ts +140 -0
- package/dist/cli/core/native-backend.js +432 -0
- package/dist/cli/core/vector-db.d.ts +126 -0
- package/dist/cli/core/vector-db.js +338 -0
- package/dist/cli/core/wasm-backend.d.ts +95 -0
- package/dist/cli/core/wasm-backend.js +418 -0
- package/dist/cli/db-commands.d.ts +49 -0
- package/dist/cli/db-commands.d.ts.map +1 -0
- package/dist/cli/db-commands.js +533 -0
- package/dist/cli/db-commands.js.map +1 -0
- package/dist/cli/db-commands.mjs +522 -0
- package/dist/cli/generator.d.ts +11 -0
- package/dist/cli/generator.d.ts.map +1 -0
- package/dist/cli/generator.js +567 -0
- package/dist/cli/generator.js.map +1 -0
- package/dist/cli/generator.mjs +527 -0
- package/dist/cli/help.d.ts +18 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +676 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/help.mjs +667 -0
- package/dist/cli/index/hnsw.d.ts +164 -0
- package/dist/cli/index/hnsw.js +558 -0
- package/dist/cli/plugin-cli.d.ts +7 -0
- package/dist/cli/plugin-cli.d.ts.map +1 -0
- package/dist/cli/plugin-cli.js +295 -0
- package/dist/cli/plugin-cli.js.map +1 -0
- package/dist/cli/plugin-cli.mjs +289 -0
- package/dist/cli/quantization/product-quantization.d.ts +108 -0
- package/dist/cli/quantization/product-quantization.js +350 -0
- package/dist/cli/query/query-builder.d.ts +322 -0
- package/dist/cli/query/query-builder.js +600 -0
- package/dist/cli/templates.d.ts +14 -0
- package/dist/cli/templates.d.ts.map +1 -0
- package/dist/cli/templates.js +182 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/cli/templates.mjs +176 -0
- package/dist/cli/types/index.d.ts +116 -0
- package/dist/cli/types/index.js +5 -0
- package/dist/cli/types.d.ts +91 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +6 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/types.mjs +4 -0
- package/dist/cli/wizard/index.d.ts +6 -0
- package/dist/cli/wizard/index.d.ts.map +1 -0
- package/dist/cli/wizard/index.js +138 -0
- package/dist/cli/wizard/index.js.map +1 -0
- package/dist/cli/wizard/index.mjs +131 -0
- package/dist/cli/wizard/prompts.d.ts +11 -0
- package/dist/cli/wizard/prompts.d.ts.map +1 -0
- package/dist/cli/wizard/prompts.js +482 -0
- package/dist/cli/wizard/prompts.js.map +1 -0
- package/dist/cli/wizard/prompts.mjs +470 -0
- package/dist/cli/wizard/validator.d.ts +13 -0
- package/dist/cli/wizard/validator.d.ts.map +1 -0
- package/dist/cli/wizard/validator.js +234 -0
- package/dist/cli/wizard/validator.js.map +1 -0
- package/dist/cli/wizard/validator.mjs +224 -0
- package/dist/core/backend-interface.d.ts +71 -0
- package/dist/core/backend-interface.d.ts.map +1 -0
- package/dist/core/backend-interface.js +16 -0
- package/dist/core/backend-interface.js.map +1 -0
- package/dist/core/backend-interface.mjs +12 -0
- package/dist/core/native-backend.d.ts +141 -0
- package/dist/core/native-backend.d.ts.map +1 -0
- package/dist/core/native-backend.js +457 -0
- package/dist/core/native-backend.js.map +1 -0
- package/dist/core/native-backend.mjs +449 -0
- package/dist/core/vector-db.d.ts +127 -0
- package/dist/core/vector-db.d.ts.map +1 -0
- package/dist/core/vector-db.js +266 -0
- package/dist/core/vector-db.js.map +1 -0
- package/dist/core/vector-db.mjs +261 -0
- package/dist/core/wasm-backend.d.ts +96 -0
- package/dist/core/wasm-backend.d.ts.map +1 -0
- package/dist/core/wasm-backend.js +393 -0
- package/dist/core/wasm-backend.js.map +1 -0
- package/dist/core/wasm-backend.mjs +385 -0
- package/dist/index/hnsw-optimized.d.ts +75 -0
- package/dist/index/hnsw-optimized.d.ts.map +1 -0
- package/dist/index/hnsw-optimized.js +412 -0
- package/dist/index/hnsw-optimized.js.map +1 -0
- package/dist/index/hnsw-optimized.mjs +407 -0
- package/dist/index/hnsw.d.ts +165 -0
- package/dist/index/hnsw.d.ts.map +1 -0
- package/dist/index/hnsw.js +521 -0
- package/dist/index/hnsw.js.map +1 -0
- package/dist/index/hnsw.mjs +516 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +63 -0
- package/dist/mcp-server.d.ts +27 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +789 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp-server.mjs +784 -0
- package/dist/plugins/base-plugin.d.ts +114 -0
- package/dist/plugins/base-plugin.d.ts.map +1 -0
- package/dist/plugins/base-plugin.js +313 -0
- package/dist/plugins/base-plugin.js.map +1 -0
- package/dist/plugins/base-plugin.mjs +275 -0
- package/dist/plugins/implementations/active-learning.d.ts +135 -0
- package/dist/plugins/implementations/active-learning.d.ts.map +1 -0
- package/dist/plugins/implementations/active-learning.js +372 -0
- package/dist/plugins/implementations/active-learning.js.map +1 -0
- package/dist/plugins/implementations/active-learning.mjs +367 -0
- package/dist/plugins/implementations/actor-critic.d.ts +64 -0
- package/dist/plugins/implementations/actor-critic.d.ts.map +1 -0
- package/dist/plugins/implementations/actor-critic.js +363 -0
- package/dist/plugins/implementations/actor-critic.js.map +1 -0
- package/dist/plugins/implementations/actor-critic.mjs +358 -0
- package/dist/plugins/implementations/adversarial-training.d.ts +133 -0
- package/dist/plugins/implementations/adversarial-training.d.ts.map +1 -0
- package/dist/plugins/implementations/adversarial-training.js +409 -0
- package/dist/plugins/implementations/adversarial-training.js.map +1 -0
- package/dist/plugins/implementations/adversarial-training.mjs +404 -0
- package/dist/plugins/implementations/curriculum-learning.d.ts +132 -0
- package/dist/plugins/implementations/curriculum-learning.d.ts.map +1 -0
- package/dist/plugins/implementations/curriculum-learning.js +354 -0
- package/dist/plugins/implementations/curriculum-learning.js.map +1 -0
- package/dist/plugins/implementations/curriculum-learning.mjs +349 -0
- package/dist/plugins/implementations/decision-transformer.d.ts +77 -0
- package/dist/plugins/implementations/decision-transformer.d.ts.map +1 -0
- package/dist/plugins/implementations/decision-transformer.js +422 -0
- package/dist/plugins/implementations/decision-transformer.js.map +1 -0
- package/dist/plugins/implementations/decision-transformer.mjs +417 -0
- package/dist/plugins/implementations/federated-learning.d.ts +126 -0
- package/dist/plugins/implementations/federated-learning.d.ts.map +1 -0
- package/dist/plugins/implementations/federated-learning.js +436 -0
- package/dist/plugins/implementations/federated-learning.js.map +1 -0
- package/dist/plugins/implementations/federated-learning.mjs +431 -0
- package/dist/plugins/implementations/index.d.ts +30 -0
- package/dist/plugins/implementations/index.d.ts.map +1 -0
- package/dist/plugins/implementations/index.js +45 -0
- package/dist/plugins/implementations/index.js.map +1 -0
- package/dist/plugins/implementations/index.mjs +31 -0
- package/dist/plugins/implementations/multi-task-learning.d.ts +115 -0
- package/dist/plugins/implementations/multi-task-learning.d.ts.map +1 -0
- package/dist/plugins/implementations/multi-task-learning.js +369 -0
- package/dist/plugins/implementations/multi-task-learning.js.map +1 -0
- package/dist/plugins/implementations/multi-task-learning.mjs +364 -0
- package/dist/plugins/implementations/neural-architecture-search.d.ts +148 -0
- package/dist/plugins/implementations/neural-architecture-search.d.ts.map +1 -0
- package/dist/plugins/implementations/neural-architecture-search.js +379 -0
- package/dist/plugins/implementations/neural-architecture-search.js.map +1 -0
- package/dist/plugins/implementations/neural-architecture-search.mjs +374 -0
- package/dist/plugins/implementations/q-learning.d.ts +98 -0
- package/dist/plugins/implementations/q-learning.d.ts.map +1 -0
- package/dist/plugins/implementations/q-learning.js +435 -0
- package/dist/plugins/implementations/q-learning.js.map +1 -0
- package/dist/plugins/implementations/q-learning.mjs +430 -0
- package/dist/plugins/implementations/sarsa.d.ts +103 -0
- package/dist/plugins/implementations/sarsa.d.ts.map +1 -0
- package/dist/plugins/implementations/sarsa.js +347 -0
- package/dist/plugins/implementations/sarsa.js.map +1 -0
- package/dist/plugins/implementations/sarsa.mjs +342 -0
- package/dist/plugins/index.d.ts +107 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +179 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/index.mjs +168 -0
- package/dist/plugins/interface.d.ts +439 -0
- package/dist/plugins/interface.d.ts.map +1 -0
- package/dist/plugins/interface.js +12 -0
- package/dist/plugins/interface.js.map +1 -0
- package/dist/plugins/interface.mjs +10 -0
- package/dist/plugins/learning-plugin.interface.d.ts +257 -0
- package/dist/plugins/learning-plugin.interface.d.ts.map +1 -0
- package/dist/plugins/learning-plugin.interface.js +7 -0
- package/dist/plugins/learning-plugin.interface.js.map +1 -0
- package/dist/plugins/learning-plugin.interface.mjs +5 -0
- package/dist/plugins/plugin-exports.d.ts +71 -0
- package/dist/plugins/plugin-exports.d.ts.map +1 -0
- package/dist/plugins/plugin-exports.js +78 -0
- package/dist/plugins/plugin-exports.js.map +1 -0
- package/dist/plugins/plugin-exports.mjs +69 -0
- package/dist/plugins/registry.d.ts +206 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +365 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/registry.mjs +356 -0
- package/dist/plugins/validator.d.ts +63 -0
- package/dist/plugins/validator.d.ts.map +1 -0
- package/dist/plugins/validator.js +464 -0
- package/dist/plugins/validator.js.map +1 -0
- package/dist/plugins/validator.mjs +458 -0
- package/dist/quantization/binary-quantization.d.ts +104 -0
- package/dist/quantization/binary-quantization.d.ts.map +1 -0
- package/dist/quantization/binary-quantization.js +246 -0
- package/dist/quantization/binary-quantization.js.map +1 -0
- package/dist/quantization/binary-quantization.mjs +240 -0
- package/dist/quantization/optimized-pq.d.ts +138 -0
- package/dist/quantization/optimized-pq.d.ts.map +1 -0
- package/dist/quantization/optimized-pq.js +320 -0
- package/dist/quantization/optimized-pq.js.map +1 -0
- package/dist/quantization/optimized-pq.mjs +313 -0
- package/dist/quantization/product-quantization.d.ts +109 -0
- package/dist/quantization/product-quantization.d.ts.map +1 -0
- package/dist/quantization/product-quantization.js +287 -0
- package/dist/quantization/product-quantization.js.map +1 -0
- package/dist/quantization/product-quantization.mjs +282 -0
- package/dist/quantization/scalar-quantization.d.ts +100 -0
- package/dist/quantization/scalar-quantization.d.ts.map +1 -0
- package/dist/quantization/scalar-quantization.js +324 -0
- package/dist/quantization/scalar-quantization.js.map +1 -0
- package/dist/quantization/scalar-quantization.mjs +319 -0
- package/dist/query/index.d.ts +6 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +9 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/index.mjs +4 -0
- package/dist/query/query-builder.d.ts +323 -0
- package/dist/query/query-builder.d.ts.map +1 -0
- package/dist/query/query-builder.js +524 -0
- package/dist/query/query-builder.js.map +1 -0
- package/dist/query/query-builder.mjs +519 -0
- package/dist/reasoning/context-synthesizer.d.ts +57 -0
- package/dist/reasoning/context-synthesizer.d.ts.map +1 -0
- package/dist/reasoning/context-synthesizer.js +224 -0
- package/dist/reasoning/context-synthesizer.js.map +1 -0
- package/dist/reasoning/context-synthesizer.mjs +219 -0
- package/dist/reasoning/experience-curator.d.ts +66 -0
- package/dist/reasoning/experience-curator.d.ts.map +1 -0
- package/dist/reasoning/experience-curator.js +288 -0
- package/dist/reasoning/experience-curator.js.map +1 -0
- package/dist/reasoning/experience-curator.mjs +283 -0
- package/dist/reasoning/memory-optimizer.d.ts +69 -0
- package/dist/reasoning/memory-optimizer.d.ts.map +1 -0
- package/dist/reasoning/memory-optimizer.js +331 -0
- package/dist/reasoning/memory-optimizer.js.map +1 -0
- package/dist/reasoning/memory-optimizer.mjs +326 -0
- package/dist/reasoning/pattern-matcher.d.ts +59 -0
- package/dist/reasoning/pattern-matcher.d.ts.map +1 -0
- package/dist/reasoning/pattern-matcher.js +229 -0
- package/dist/reasoning/pattern-matcher.js.map +1 -0
- package/dist/reasoning/pattern-matcher.mjs +224 -0
- package/dist/reasoningbank/adapter/agentdb-adapter.d.ts +118 -0
- package/dist/reasoningbank/adapter/agentdb-adapter.d.ts.map +1 -0
- package/dist/reasoningbank/adapter/agentdb-adapter.js +477 -0
- package/dist/reasoningbank/adapter/agentdb-adapter.js.map +1 -0
- package/dist/reasoningbank/adapter/types.d.ts +113 -0
- package/dist/reasoningbank/adapter/types.d.ts.map +1 -0
- package/dist/reasoningbank/adapter/types.js +9 -0
- package/dist/reasoningbank/adapter/types.js.map +1 -0
- package/dist/reasoningbank/cli/commands.d.ts +16 -0
- package/dist/reasoningbank/cli/commands.d.ts.map +1 -0
- package/dist/reasoningbank/cli/commands.js +272 -0
- package/dist/reasoningbank/cli/commands.js.map +1 -0
- package/dist/reasoningbank/mcp/agentdb-tools.d.ts +319 -0
- package/dist/reasoningbank/mcp/agentdb-tools.d.ts.map +1 -0
- package/dist/reasoningbank/mcp/agentdb-tools.js +301 -0
- package/dist/reasoningbank/mcp/agentdb-tools.js.map +1 -0
- package/dist/reasoningbank/migration/migrate.d.ts +25 -0
- package/dist/reasoningbank/migration/migrate.d.ts.map +1 -0
- package/dist/reasoningbank/migration/migrate.js +178 -0
- package/dist/reasoningbank/migration/migrate.js.map +1 -0
- package/dist/reasoningbank/reasoning/context-synthesizer.d.ts +37 -0
- package/dist/reasoningbank/reasoning/context-synthesizer.d.ts.map +1 -0
- package/dist/reasoningbank/reasoning/context-synthesizer.js +114 -0
- package/dist/reasoningbank/reasoning/context-synthesizer.js.map +1 -0
- package/dist/reasoningbank/reasoning/experience-curator.d.ts +39 -0
- package/dist/reasoningbank/reasoning/experience-curator.d.ts.map +1 -0
- package/dist/reasoningbank/reasoning/experience-curator.js +98 -0
- package/dist/reasoningbank/reasoning/experience-curator.js.map +1 -0
- package/dist/reasoningbank/reasoning/memory-optimizer.d.ts +44 -0
- package/dist/reasoningbank/reasoning/memory-optimizer.d.ts.map +1 -0
- package/dist/reasoningbank/reasoning/memory-optimizer.js +184 -0
- package/dist/reasoningbank/reasoning/memory-optimizer.js.map +1 -0
- package/dist/reasoningbank/reasoning/pattern-matcher.d.ts +40 -0
- package/dist/reasoningbank/reasoning/pattern-matcher.d.ts.map +1 -0
- package/dist/reasoningbank/reasoning/pattern-matcher.js +87 -0
- package/dist/reasoningbank/reasoning/pattern-matcher.js.map +1 -0
- package/dist/reasoningbank/sync/quic-sync.d.ts +77 -0
- package/dist/reasoningbank/sync/quic-sync.d.ts.map +1 -0
- package/dist/reasoningbank/sync/quic-sync.js +165 -0
- package/dist/reasoningbank/sync/quic-sync.js.map +1 -0
- package/dist/sync/conflict.d.ts +78 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +202 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/conflict.mjs +196 -0
- package/dist/sync/coordinator.d.ts +111 -0
- package/dist/sync/coordinator.d.ts.map +1 -0
- package/dist/sync/coordinator.js +256 -0
- package/dist/sync/coordinator.js.map +1 -0
- package/dist/sync/coordinator.mjs +250 -0
- package/dist/sync/delta.d.ts +81 -0
- package/dist/sync/delta.d.ts.map +1 -0
- package/dist/sync/delta.js +245 -0
- package/dist/sync/delta.js.map +1 -0
- package/dist/sync/delta.mjs +238 -0
- package/dist/sync/index.d.ts +11 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +22 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/index.mjs +9 -0
- package/dist/sync/quic-sync.d.ts +81 -0
- package/dist/sync/quic-sync.d.ts.map +1 -0
- package/dist/sync/quic-sync.js +329 -0
- package/dist/sync/quic-sync.js.map +1 -0
- package/dist/sync/quic-sync.mjs +323 -0
- package/dist/sync/types.d.ts +168 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +8 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/types.mjs +6 -0
- package/dist/types/index.d.ts +117 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +4 -0
- package/dist/wasm-loader.d.ts +32 -0
- package/dist/wasm-loader.d.ts.map +1 -0
- package/dist/wasm-loader.js +75 -0
- package/dist/wasm-loader.js.map +1 -0
- package/dist/wasm-loader.mjs +64 -0
- package/examples/adaptive-learning.ts +284 -0
- package/examples/browser/README.md +732 -0
- package/examples/browser/adaptive-recommendations/index.html +427 -0
- package/examples/browser/collaborative-filtering/index.html +310 -0
- package/examples/browser/continual-learning/index.html +736 -0
- package/examples/browser/experience-replay/index.html +616 -0
- package/examples/browser/index.html +369 -0
- package/examples/browser/meta-learning/index.html +789 -0
- package/examples/browser/neuro-symbolic/index.html +692 -0
- package/examples/browser/pattern-learning/index.html +620 -0
- package/examples/browser/quantum-inspired/index.html +728 -0
- package/examples/browser/rag/index.html +624 -0
- package/examples/browser/swarm-intelligence/index.html +811 -0
- package/examples/browser-basic.html +170 -0
- package/examples/hnsw-example.ts +148 -0
- package/examples/node-basic.js +70 -0
- package/examples/quic-sync-example.ts +310 -0
- package/examples/quick-start.js +68 -0
- package/examples/wasm-example.ts +222 -0
- package/package.json +118 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MemoryOptimizer - Collapse and compress old memories for efficiency
|
|
4
|
+
*
|
|
5
|
+
* Implements memory consolidation strategies:
|
|
6
|
+
* - Graph-based summarization (similar memories clustered)
|
|
7
|
+
* - Hierarchical compression (temporal aggregation)
|
|
8
|
+
* - Quality-based pruning (remove low-value memories)
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.MemoryOptimizer = void 0;
|
|
12
|
+
class MemoryOptimizer {
|
|
13
|
+
constructor(db) {
|
|
14
|
+
this.memoryNodesTable = 'memory_nodes';
|
|
15
|
+
this.db = db;
|
|
16
|
+
this.initializeMemoryNodes();
|
|
17
|
+
}
|
|
18
|
+
initializeMemoryNodes() {
|
|
19
|
+
const rawDb = this.db.getDatabase();
|
|
20
|
+
rawDb.exec(`
|
|
21
|
+
CREATE TABLE IF NOT EXISTS ${this.memoryNodesTable} (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
original_ids TEXT NOT NULL,
|
|
24
|
+
count INTEGER NOT NULL,
|
|
25
|
+
quality REAL NOT NULL,
|
|
26
|
+
domains TEXT NOT NULL,
|
|
27
|
+
time_range_start INTEGER NOT NULL,
|
|
28
|
+
time_range_end INTEGER NOT NULL,
|
|
29
|
+
metadata TEXT,
|
|
30
|
+
timestamp INTEGER NOT NULL
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_quality ON ${this.memoryNodesTable}(quality);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_time ON ${this.memoryNodesTable}(time_range_end);
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Collapse old memories into compressed summary nodes
|
|
39
|
+
*
|
|
40
|
+
* @param maxAge - Maximum age in milliseconds for memories to collapse
|
|
41
|
+
* @param strategy - Collapse strategy to use
|
|
42
|
+
* @returns Number of memories collapsed
|
|
43
|
+
*/
|
|
44
|
+
async collapseMemories(maxAge = 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
45
|
+
strategy = {
|
|
46
|
+
type: 'graph',
|
|
47
|
+
threshold: 0.9,
|
|
48
|
+
maxNodes: 100
|
|
49
|
+
}) {
|
|
50
|
+
const startTime = Date.now();
|
|
51
|
+
const cutoffTime = Date.now() - maxAge;
|
|
52
|
+
// Get old vectors to collapse
|
|
53
|
+
const oldVectors = this.getOldVectors(cutoffTime, strategy.preserveRecent);
|
|
54
|
+
if (oldVectors.length === 0) {
|
|
55
|
+
console.log('[MemoryOptimizer] No memories to collapse');
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
let collapsed = 0;
|
|
59
|
+
switch (strategy.type) {
|
|
60
|
+
case 'graph':
|
|
61
|
+
collapsed = await this.graphBasedCollapse(oldVectors, strategy);
|
|
62
|
+
break;
|
|
63
|
+
case 'hierarchical':
|
|
64
|
+
collapsed = await this.hierarchicalCollapse(oldVectors, strategy);
|
|
65
|
+
break;
|
|
66
|
+
case 'temporal':
|
|
67
|
+
collapsed = await this.temporalCollapse(oldVectors, strategy);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
const duration = Date.now() - startTime;
|
|
71
|
+
console.log(`[MemoryOptimizer] Collapsed ${collapsed} memories in ${duration}ms using ${strategy.type} strategy`);
|
|
72
|
+
return collapsed;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Graph-based collapse: cluster similar memories
|
|
76
|
+
*/
|
|
77
|
+
async graphBasedCollapse(vectors, strategy) {
|
|
78
|
+
const clusters = this.clusterVectors(vectors, strategy.threshold);
|
|
79
|
+
let collapsed = 0;
|
|
80
|
+
for (const cluster of clusters) {
|
|
81
|
+
if (cluster.length < 2)
|
|
82
|
+
continue;
|
|
83
|
+
const node = this.createMemoryNode(cluster);
|
|
84
|
+
this.storeMemoryNode(node);
|
|
85
|
+
// Remove original vectors
|
|
86
|
+
for (const vector of cluster) {
|
|
87
|
+
this.db.delete(vector.id);
|
|
88
|
+
}
|
|
89
|
+
collapsed += cluster.length;
|
|
90
|
+
}
|
|
91
|
+
return collapsed;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Hierarchical collapse: aggregate by time periods
|
|
95
|
+
*/
|
|
96
|
+
async hierarchicalCollapse(vectors, strategy) {
|
|
97
|
+
// Group by time periods (e.g., daily buckets)
|
|
98
|
+
const periodSize = 24 * 60 * 60 * 1000; // 1 day
|
|
99
|
+
const periods = new Map();
|
|
100
|
+
for (const vector of vectors) {
|
|
101
|
+
const period = Math.floor(vector.timestamp / periodSize);
|
|
102
|
+
if (!periods.has(period)) {
|
|
103
|
+
periods.set(period, []);
|
|
104
|
+
}
|
|
105
|
+
periods.get(period).push(vector);
|
|
106
|
+
}
|
|
107
|
+
let collapsed = 0;
|
|
108
|
+
// Collapse each period
|
|
109
|
+
for (const [period, periodVectors] of periods) {
|
|
110
|
+
if (periodVectors.length < 2)
|
|
111
|
+
continue;
|
|
112
|
+
const node = this.createMemoryNode(periodVectors);
|
|
113
|
+
this.storeMemoryNode(node);
|
|
114
|
+
// Remove original vectors
|
|
115
|
+
for (const vector of periodVectors) {
|
|
116
|
+
this.db.delete(vector.id);
|
|
117
|
+
}
|
|
118
|
+
collapsed += periodVectors.length;
|
|
119
|
+
}
|
|
120
|
+
return collapsed;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Temporal collapse: merge sequential memories
|
|
124
|
+
*/
|
|
125
|
+
async temporalCollapse(vectors, strategy) {
|
|
126
|
+
// Sort by timestamp
|
|
127
|
+
vectors.sort((a, b) => a.timestamp - b.timestamp);
|
|
128
|
+
const sequences = [];
|
|
129
|
+
let currentSequence = [vectors[0]];
|
|
130
|
+
for (let i = 1; i < vectors.length; i++) {
|
|
131
|
+
const timeDiff = vectors[i].timestamp - vectors[i - 1].timestamp;
|
|
132
|
+
// If within 1 hour, add to sequence
|
|
133
|
+
if (timeDiff < 60 * 60 * 1000) {
|
|
134
|
+
currentSequence.push(vectors[i]);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
if (currentSequence.length >= 2) {
|
|
138
|
+
sequences.push(currentSequence);
|
|
139
|
+
}
|
|
140
|
+
currentSequence = [vectors[i]];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (currentSequence.length >= 2) {
|
|
144
|
+
sequences.push(currentSequence);
|
|
145
|
+
}
|
|
146
|
+
let collapsed = 0;
|
|
147
|
+
for (const sequence of sequences) {
|
|
148
|
+
const node = this.createMemoryNode(sequence);
|
|
149
|
+
this.storeMemoryNode(node);
|
|
150
|
+
for (const vector of sequence) {
|
|
151
|
+
this.db.delete(vector.id);
|
|
152
|
+
}
|
|
153
|
+
collapsed += sequence.length;
|
|
154
|
+
}
|
|
155
|
+
return collapsed;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Cluster vectors based on similarity threshold
|
|
159
|
+
*/
|
|
160
|
+
clusterVectors(vectors, threshold) {
|
|
161
|
+
const clusters = [];
|
|
162
|
+
const assigned = new Set();
|
|
163
|
+
for (const vector of vectors) {
|
|
164
|
+
if (assigned.has(vector.id))
|
|
165
|
+
continue;
|
|
166
|
+
const cluster = [vector];
|
|
167
|
+
assigned.add(vector.id);
|
|
168
|
+
// Find similar vectors
|
|
169
|
+
const results = this.db.search(vector.embedding, vectors.length, 'cosine', threshold);
|
|
170
|
+
for (const result of results) {
|
|
171
|
+
if (result.id !== vector.id && !assigned.has(result.id)) {
|
|
172
|
+
const match = vectors.find(v => v.id === result.id);
|
|
173
|
+
if (match) {
|
|
174
|
+
cluster.push(match);
|
|
175
|
+
assigned.add(result.id);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (cluster.length >= 2) {
|
|
180
|
+
clusters.push(cluster);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return clusters;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create a memory node from a cluster of vectors
|
|
187
|
+
*/
|
|
188
|
+
createMemoryNode(vectors) {
|
|
189
|
+
// Calculate centroid (average embedding)
|
|
190
|
+
const embeddingLength = vectors[0].embedding.length;
|
|
191
|
+
const centroid = new Array(embeddingLength).fill(0);
|
|
192
|
+
for (const vector of vectors) {
|
|
193
|
+
for (let i = 0; i < embeddingLength; i++) {
|
|
194
|
+
centroid[i] += vector.embedding[i];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (let i = 0; i < embeddingLength; i++) {
|
|
198
|
+
centroid[i] /= vectors.length;
|
|
199
|
+
}
|
|
200
|
+
// Extract metadata
|
|
201
|
+
const originalIds = vectors.map(v => v.id);
|
|
202
|
+
const domains = [...new Set(vectors.map(v => v.metadata?.domain).filter(Boolean))];
|
|
203
|
+
const timestamps = vectors.map(v => v.timestamp).sort((a, b) => a - b);
|
|
204
|
+
// Calculate quality (average of vector qualities)
|
|
205
|
+
const quality = vectors.reduce((sum, v) => {
|
|
206
|
+
const q = v.metadata?.quality || 0.5;
|
|
207
|
+
return sum + q;
|
|
208
|
+
}, 0) / vectors.length;
|
|
209
|
+
return {
|
|
210
|
+
id: this.generateNodeId(),
|
|
211
|
+
embeddings: vectors.map(v => v.embedding),
|
|
212
|
+
count: vectors.length,
|
|
213
|
+
centroid,
|
|
214
|
+
quality,
|
|
215
|
+
metadata: {
|
|
216
|
+
originalIds,
|
|
217
|
+
domains,
|
|
218
|
+
timeRange: [timestamps[0], timestamps[timestamps.length - 1]]
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Store memory node
|
|
224
|
+
*/
|
|
225
|
+
storeMemoryNode(node) {
|
|
226
|
+
// Store centroid as searchable vector
|
|
227
|
+
this.db.insert({
|
|
228
|
+
id: `node_${node.id}`,
|
|
229
|
+
embedding: node.centroid,
|
|
230
|
+
metadata: {
|
|
231
|
+
type: 'memory_node',
|
|
232
|
+
nodeId: node.id,
|
|
233
|
+
count: node.count,
|
|
234
|
+
quality: node.quality
|
|
235
|
+
},
|
|
236
|
+
timestamp: Date.now()
|
|
237
|
+
});
|
|
238
|
+
// Store node metadata
|
|
239
|
+
const rawDb = this.db.getDatabase();
|
|
240
|
+
const stmt = rawDb.prepare(`
|
|
241
|
+
INSERT INTO ${this.memoryNodesTable}
|
|
242
|
+
(id, original_ids, count, quality, domains, time_range_start, time_range_end, metadata, timestamp)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
244
|
+
`);
|
|
245
|
+
stmt.run(node.id, JSON.stringify(node.metadata.originalIds), node.count, node.quality, JSON.stringify(node.metadata.domains), node.metadata.timeRange[0], node.metadata.timeRange[1], JSON.stringify({ embeddings: node.embeddings }), Date.now());
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Query collapsed memory nodes
|
|
249
|
+
*/
|
|
250
|
+
async queryNodes(queryEmbedding, k = 5) {
|
|
251
|
+
const results = this.db.search(queryEmbedding, k, 'cosine', 0.7);
|
|
252
|
+
const nodeResults = results.filter(r => r.metadata?.type === 'memory_node');
|
|
253
|
+
const nodes = [];
|
|
254
|
+
const rawDb = this.db.getDatabase();
|
|
255
|
+
for (const result of nodeResults) {
|
|
256
|
+
const metadata = result.metadata || {};
|
|
257
|
+
const nodeId = metadata.nodeId;
|
|
258
|
+
const stmt = rawDb.prepare(`SELECT * FROM ${this.memoryNodesTable} WHERE id = ?`);
|
|
259
|
+
const row = stmt.get(nodeId);
|
|
260
|
+
if (row) {
|
|
261
|
+
const metadata = JSON.parse(row.metadata);
|
|
262
|
+
nodes.push({
|
|
263
|
+
id: row.id,
|
|
264
|
+
embeddings: metadata.embeddings,
|
|
265
|
+
count: row.count,
|
|
266
|
+
centroid: result.embedding,
|
|
267
|
+
quality: row.quality,
|
|
268
|
+
metadata: {
|
|
269
|
+
originalIds: JSON.parse(row.original_ids),
|
|
270
|
+
domains: JSON.parse(row.domains),
|
|
271
|
+
timeRange: [row.time_range_start, row.time_range_end]
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return nodes;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get vectors older than cutoff time
|
|
280
|
+
*/
|
|
281
|
+
getOldVectors(cutoffTime, preserveRecent) {
|
|
282
|
+
const rawDb = this.db.getDatabase();
|
|
283
|
+
let sql = 'SELECT * FROM vectors WHERE timestamp < ?';
|
|
284
|
+
if (preserveRecent) {
|
|
285
|
+
// Keep recent 100 vectors regardless of age
|
|
286
|
+
sql += ` AND id NOT IN (
|
|
287
|
+
SELECT id FROM vectors
|
|
288
|
+
ORDER BY timestamp DESC
|
|
289
|
+
LIMIT 100
|
|
290
|
+
)`;
|
|
291
|
+
}
|
|
292
|
+
const stmt = rawDb.prepare(sql);
|
|
293
|
+
const rows = stmt.all(cutoffTime);
|
|
294
|
+
return rows.map(row => ({
|
|
295
|
+
id: row.id,
|
|
296
|
+
embedding: this.deserializeEmbedding(row.embedding),
|
|
297
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : {},
|
|
298
|
+
timestamp: row.timestamp
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
deserializeEmbedding(buffer) {
|
|
302
|
+
const view = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4);
|
|
303
|
+
return Array.from(view);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Get memory optimization statistics
|
|
307
|
+
*/
|
|
308
|
+
getStats() {
|
|
309
|
+
const rawDb = this.db.getDatabase();
|
|
310
|
+
const countStmt = rawDb.prepare(`SELECT COUNT(*) as count FROM ${this.memoryNodesTable}`);
|
|
311
|
+
const totalNodes = countStmt.get().count;
|
|
312
|
+
const sumStmt = rawDb.prepare(`SELECT SUM(count) as sum FROM ${this.memoryNodesTable}`);
|
|
313
|
+
const totalCollapsed = sumStmt.get().sum || 0;
|
|
314
|
+
const qualityStmt = rawDb.prepare(`SELECT AVG(quality) as avg FROM ${this.memoryNodesTable}`);
|
|
315
|
+
const avgQuality = qualityStmt.get().avg || 0;
|
|
316
|
+
const memoryReduction = totalCollapsed > 0
|
|
317
|
+
? ((totalCollapsed - totalNodes) / totalCollapsed) * 100
|
|
318
|
+
: 0;
|
|
319
|
+
return {
|
|
320
|
+
totalNodes,
|
|
321
|
+
totalCollapsed,
|
|
322
|
+
avgQuality,
|
|
323
|
+
memoryReduction
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
generateNodeId() {
|
|
327
|
+
return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
exports.MemoryOptimizer = MemoryOptimizer;
|
|
331
|
+
//# sourceMappingURL=memory-optimizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-optimizer.js","sourceRoot":"","sources":["../../src/reasoning/memory-optimizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryOptimizer - Collapse and compress old memories for efficiency
|
|
3
|
+
*
|
|
4
|
+
* Implements memory consolidation strategies:
|
|
5
|
+
* - Graph-based summarization (similar memories clustered)
|
|
6
|
+
* - Hierarchical compression (temporal aggregation)
|
|
7
|
+
* - Quality-based pruning (remove low-value memories)
|
|
8
|
+
*/
|
|
9
|
+
export class MemoryOptimizer {
|
|
10
|
+
constructor(db) {
|
|
11
|
+
this.memoryNodesTable = 'memory_nodes';
|
|
12
|
+
this.db = db;
|
|
13
|
+
this.initializeMemoryNodes();
|
|
14
|
+
}
|
|
15
|
+
initializeMemoryNodes() {
|
|
16
|
+
const rawDb = this.db.getDatabase();
|
|
17
|
+
rawDb.exec(`
|
|
18
|
+
CREATE TABLE IF NOT EXISTS ${this.memoryNodesTable} (
|
|
19
|
+
id TEXT PRIMARY KEY,
|
|
20
|
+
original_ids TEXT NOT NULL,
|
|
21
|
+
count INTEGER NOT NULL,
|
|
22
|
+
quality REAL NOT NULL,
|
|
23
|
+
domains TEXT NOT NULL,
|
|
24
|
+
time_range_start INTEGER NOT NULL,
|
|
25
|
+
time_range_end INTEGER NOT NULL,
|
|
26
|
+
metadata TEXT,
|
|
27
|
+
timestamp INTEGER NOT NULL
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_quality ON ${this.memoryNodesTable}(quality);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_time ON ${this.memoryNodesTable}(time_range_end);
|
|
32
|
+
`);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Collapse old memories into compressed summary nodes
|
|
36
|
+
*
|
|
37
|
+
* @param maxAge - Maximum age in milliseconds for memories to collapse
|
|
38
|
+
* @param strategy - Collapse strategy to use
|
|
39
|
+
* @returns Number of memories collapsed
|
|
40
|
+
*/
|
|
41
|
+
async collapseMemories(maxAge = 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
42
|
+
strategy = {
|
|
43
|
+
type: 'graph',
|
|
44
|
+
threshold: 0.9,
|
|
45
|
+
maxNodes: 100
|
|
46
|
+
}) {
|
|
47
|
+
const startTime = Date.now();
|
|
48
|
+
const cutoffTime = Date.now() - maxAge;
|
|
49
|
+
// Get old vectors to collapse
|
|
50
|
+
const oldVectors = this.getOldVectors(cutoffTime, strategy.preserveRecent);
|
|
51
|
+
if (oldVectors.length === 0) {
|
|
52
|
+
console.log('[MemoryOptimizer] No memories to collapse');
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
let collapsed = 0;
|
|
56
|
+
switch (strategy.type) {
|
|
57
|
+
case 'graph':
|
|
58
|
+
collapsed = await this.graphBasedCollapse(oldVectors, strategy);
|
|
59
|
+
break;
|
|
60
|
+
case 'hierarchical':
|
|
61
|
+
collapsed = await this.hierarchicalCollapse(oldVectors, strategy);
|
|
62
|
+
break;
|
|
63
|
+
case 'temporal':
|
|
64
|
+
collapsed = await this.temporalCollapse(oldVectors, strategy);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
const duration = Date.now() - startTime;
|
|
68
|
+
console.log(`[MemoryOptimizer] Collapsed ${collapsed} memories in ${duration}ms using ${strategy.type} strategy`);
|
|
69
|
+
return collapsed;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Graph-based collapse: cluster similar memories
|
|
73
|
+
*/
|
|
74
|
+
async graphBasedCollapse(vectors, strategy) {
|
|
75
|
+
const clusters = this.clusterVectors(vectors, strategy.threshold);
|
|
76
|
+
let collapsed = 0;
|
|
77
|
+
for (const cluster of clusters) {
|
|
78
|
+
if (cluster.length < 2)
|
|
79
|
+
continue;
|
|
80
|
+
const node = this.createMemoryNode(cluster);
|
|
81
|
+
this.storeMemoryNode(node);
|
|
82
|
+
// Remove original vectors
|
|
83
|
+
for (const vector of cluster) {
|
|
84
|
+
this.db.delete(vector.id);
|
|
85
|
+
}
|
|
86
|
+
collapsed += cluster.length;
|
|
87
|
+
}
|
|
88
|
+
return collapsed;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Hierarchical collapse: aggregate by time periods
|
|
92
|
+
*/
|
|
93
|
+
async hierarchicalCollapse(vectors, strategy) {
|
|
94
|
+
// Group by time periods (e.g., daily buckets)
|
|
95
|
+
const periodSize = 24 * 60 * 60 * 1000; // 1 day
|
|
96
|
+
const periods = new Map();
|
|
97
|
+
for (const vector of vectors) {
|
|
98
|
+
const period = Math.floor(vector.timestamp / periodSize);
|
|
99
|
+
if (!periods.has(period)) {
|
|
100
|
+
periods.set(period, []);
|
|
101
|
+
}
|
|
102
|
+
periods.get(period).push(vector);
|
|
103
|
+
}
|
|
104
|
+
let collapsed = 0;
|
|
105
|
+
// Collapse each period
|
|
106
|
+
for (const [period, periodVectors] of periods) {
|
|
107
|
+
if (periodVectors.length < 2)
|
|
108
|
+
continue;
|
|
109
|
+
const node = this.createMemoryNode(periodVectors);
|
|
110
|
+
this.storeMemoryNode(node);
|
|
111
|
+
// Remove original vectors
|
|
112
|
+
for (const vector of periodVectors) {
|
|
113
|
+
this.db.delete(vector.id);
|
|
114
|
+
}
|
|
115
|
+
collapsed += periodVectors.length;
|
|
116
|
+
}
|
|
117
|
+
return collapsed;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Temporal collapse: merge sequential memories
|
|
121
|
+
*/
|
|
122
|
+
async temporalCollapse(vectors, strategy) {
|
|
123
|
+
// Sort by timestamp
|
|
124
|
+
vectors.sort((a, b) => a.timestamp - b.timestamp);
|
|
125
|
+
const sequences = [];
|
|
126
|
+
let currentSequence = [vectors[0]];
|
|
127
|
+
for (let i = 1; i < vectors.length; i++) {
|
|
128
|
+
const timeDiff = vectors[i].timestamp - vectors[i - 1].timestamp;
|
|
129
|
+
// If within 1 hour, add to sequence
|
|
130
|
+
if (timeDiff < 60 * 60 * 1000) {
|
|
131
|
+
currentSequence.push(vectors[i]);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
if (currentSequence.length >= 2) {
|
|
135
|
+
sequences.push(currentSequence);
|
|
136
|
+
}
|
|
137
|
+
currentSequence = [vectors[i]];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (currentSequence.length >= 2) {
|
|
141
|
+
sequences.push(currentSequence);
|
|
142
|
+
}
|
|
143
|
+
let collapsed = 0;
|
|
144
|
+
for (const sequence of sequences) {
|
|
145
|
+
const node = this.createMemoryNode(sequence);
|
|
146
|
+
this.storeMemoryNode(node);
|
|
147
|
+
for (const vector of sequence) {
|
|
148
|
+
this.db.delete(vector.id);
|
|
149
|
+
}
|
|
150
|
+
collapsed += sequence.length;
|
|
151
|
+
}
|
|
152
|
+
return collapsed;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Cluster vectors based on similarity threshold
|
|
156
|
+
*/
|
|
157
|
+
clusterVectors(vectors, threshold) {
|
|
158
|
+
const clusters = [];
|
|
159
|
+
const assigned = new Set();
|
|
160
|
+
for (const vector of vectors) {
|
|
161
|
+
if (assigned.has(vector.id))
|
|
162
|
+
continue;
|
|
163
|
+
const cluster = [vector];
|
|
164
|
+
assigned.add(vector.id);
|
|
165
|
+
// Find similar vectors
|
|
166
|
+
const results = this.db.search(vector.embedding, vectors.length, 'cosine', threshold);
|
|
167
|
+
for (const result of results) {
|
|
168
|
+
if (result.id !== vector.id && !assigned.has(result.id)) {
|
|
169
|
+
const match = vectors.find(v => v.id === result.id);
|
|
170
|
+
if (match) {
|
|
171
|
+
cluster.push(match);
|
|
172
|
+
assigned.add(result.id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (cluster.length >= 2) {
|
|
177
|
+
clusters.push(cluster);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return clusters;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a memory node from a cluster of vectors
|
|
184
|
+
*/
|
|
185
|
+
createMemoryNode(vectors) {
|
|
186
|
+
// Calculate centroid (average embedding)
|
|
187
|
+
const embeddingLength = vectors[0].embedding.length;
|
|
188
|
+
const centroid = new Array(embeddingLength).fill(0);
|
|
189
|
+
for (const vector of vectors) {
|
|
190
|
+
for (let i = 0; i < embeddingLength; i++) {
|
|
191
|
+
centroid[i] += vector.embedding[i];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
for (let i = 0; i < embeddingLength; i++) {
|
|
195
|
+
centroid[i] /= vectors.length;
|
|
196
|
+
}
|
|
197
|
+
// Extract metadata
|
|
198
|
+
const originalIds = vectors.map(v => v.id);
|
|
199
|
+
const domains = [...new Set(vectors.map(v => v.metadata?.domain).filter(Boolean))];
|
|
200
|
+
const timestamps = vectors.map(v => v.timestamp).sort((a, b) => a - b);
|
|
201
|
+
// Calculate quality (average of vector qualities)
|
|
202
|
+
const quality = vectors.reduce((sum, v) => {
|
|
203
|
+
const q = v.metadata?.quality || 0.5;
|
|
204
|
+
return sum + q;
|
|
205
|
+
}, 0) / vectors.length;
|
|
206
|
+
return {
|
|
207
|
+
id: this.generateNodeId(),
|
|
208
|
+
embeddings: vectors.map(v => v.embedding),
|
|
209
|
+
count: vectors.length,
|
|
210
|
+
centroid,
|
|
211
|
+
quality,
|
|
212
|
+
metadata: {
|
|
213
|
+
originalIds,
|
|
214
|
+
domains,
|
|
215
|
+
timeRange: [timestamps[0], timestamps[timestamps.length - 1]]
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Store memory node
|
|
221
|
+
*/
|
|
222
|
+
storeMemoryNode(node) {
|
|
223
|
+
// Store centroid as searchable vector
|
|
224
|
+
this.db.insert({
|
|
225
|
+
id: `node_${node.id}`,
|
|
226
|
+
embedding: node.centroid,
|
|
227
|
+
metadata: {
|
|
228
|
+
type: 'memory_node',
|
|
229
|
+
nodeId: node.id,
|
|
230
|
+
count: node.count,
|
|
231
|
+
quality: node.quality
|
|
232
|
+
},
|
|
233
|
+
timestamp: Date.now()
|
|
234
|
+
});
|
|
235
|
+
// Store node metadata
|
|
236
|
+
const rawDb = this.db.getDatabase();
|
|
237
|
+
const stmt = rawDb.prepare(`
|
|
238
|
+
INSERT INTO ${this.memoryNodesTable}
|
|
239
|
+
(id, original_ids, count, quality, domains, time_range_start, time_range_end, metadata, timestamp)
|
|
240
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
241
|
+
`);
|
|
242
|
+
stmt.run(node.id, JSON.stringify(node.metadata.originalIds), node.count, node.quality, JSON.stringify(node.metadata.domains), node.metadata.timeRange[0], node.metadata.timeRange[1], JSON.stringify({ embeddings: node.embeddings }), Date.now());
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Query collapsed memory nodes
|
|
246
|
+
*/
|
|
247
|
+
async queryNodes(queryEmbedding, k = 5) {
|
|
248
|
+
const results = this.db.search(queryEmbedding, k, 'cosine', 0.7);
|
|
249
|
+
const nodeResults = results.filter(r => r.metadata?.type === 'memory_node');
|
|
250
|
+
const nodes = [];
|
|
251
|
+
const rawDb = this.db.getDatabase();
|
|
252
|
+
for (const result of nodeResults) {
|
|
253
|
+
const metadata = result.metadata || {};
|
|
254
|
+
const nodeId = metadata.nodeId;
|
|
255
|
+
const stmt = rawDb.prepare(`SELECT * FROM ${this.memoryNodesTable} WHERE id = ?`);
|
|
256
|
+
const row = stmt.get(nodeId);
|
|
257
|
+
if (row) {
|
|
258
|
+
const metadata = JSON.parse(row.metadata);
|
|
259
|
+
nodes.push({
|
|
260
|
+
id: row.id,
|
|
261
|
+
embeddings: metadata.embeddings,
|
|
262
|
+
count: row.count,
|
|
263
|
+
centroid: result.embedding,
|
|
264
|
+
quality: row.quality,
|
|
265
|
+
metadata: {
|
|
266
|
+
originalIds: JSON.parse(row.original_ids),
|
|
267
|
+
domains: JSON.parse(row.domains),
|
|
268
|
+
timeRange: [row.time_range_start, row.time_range_end]
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return nodes;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Get vectors older than cutoff time
|
|
277
|
+
*/
|
|
278
|
+
getOldVectors(cutoffTime, preserveRecent) {
|
|
279
|
+
const rawDb = this.db.getDatabase();
|
|
280
|
+
let sql = 'SELECT * FROM vectors WHERE timestamp < ?';
|
|
281
|
+
if (preserveRecent) {
|
|
282
|
+
// Keep recent 100 vectors regardless of age
|
|
283
|
+
sql += ` AND id NOT IN (
|
|
284
|
+
SELECT id FROM vectors
|
|
285
|
+
ORDER BY timestamp DESC
|
|
286
|
+
LIMIT 100
|
|
287
|
+
)`;
|
|
288
|
+
}
|
|
289
|
+
const stmt = rawDb.prepare(sql);
|
|
290
|
+
const rows = stmt.all(cutoffTime);
|
|
291
|
+
return rows.map(row => ({
|
|
292
|
+
id: row.id,
|
|
293
|
+
embedding: this.deserializeEmbedding(row.embedding),
|
|
294
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : {},
|
|
295
|
+
timestamp: row.timestamp
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
deserializeEmbedding(buffer) {
|
|
299
|
+
const view = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4);
|
|
300
|
+
return Array.from(view);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Get memory optimization statistics
|
|
304
|
+
*/
|
|
305
|
+
getStats() {
|
|
306
|
+
const rawDb = this.db.getDatabase();
|
|
307
|
+
const countStmt = rawDb.prepare(`SELECT COUNT(*) as count FROM ${this.memoryNodesTable}`);
|
|
308
|
+
const totalNodes = countStmt.get().count;
|
|
309
|
+
const sumStmt = rawDb.prepare(`SELECT SUM(count) as sum FROM ${this.memoryNodesTable}`);
|
|
310
|
+
const totalCollapsed = sumStmt.get().sum || 0;
|
|
311
|
+
const qualityStmt = rawDb.prepare(`SELECT AVG(quality) as avg FROM ${this.memoryNodesTable}`);
|
|
312
|
+
const avgQuality = qualityStmt.get().avg || 0;
|
|
313
|
+
const memoryReduction = totalCollapsed > 0
|
|
314
|
+
? ((totalCollapsed - totalNodes) / totalCollapsed) * 100
|
|
315
|
+
: 0;
|
|
316
|
+
return {
|
|
317
|
+
totalNodes,
|
|
318
|
+
totalCollapsed,
|
|
319
|
+
avgQuality,
|
|
320
|
+
memoryReduction
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
generateNodeId() {
|
|
324
|
+
return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
325
|
+
}
|
|
326
|
+
}
|