genesis-ai-cli 7.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- package/package.json +60 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis 6.0 - Memory Consolidation Service
|
|
4
|
+
*
|
|
5
|
+
* Implements sleep-based memory consolidation:
|
|
6
|
+
* - Episodic → Semantic (pattern extraction)
|
|
7
|
+
* - Episodic → Procedural (skill learning)
|
|
8
|
+
* - Forgetting weak memories
|
|
9
|
+
* - Merging similar memories
|
|
10
|
+
*
|
|
11
|
+
* Inspired by:
|
|
12
|
+
* - Memory consolidation during sleep (Walker & Stickgold, 2006)
|
|
13
|
+
* - Systems consolidation theory (McClelland et al., 1995)
|
|
14
|
+
* - Schema theory (Bartlett, 1932)
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.ConsolidationService = void 0;
|
|
18
|
+
exports.createConsolidationService = createConsolidationService;
|
|
19
|
+
const forgetting_js_1 = require("./forgetting.js");
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Default Configuration
|
|
22
|
+
// ============================================================================
|
|
23
|
+
const DEFAULT_CONFIG = {
|
|
24
|
+
retentionThreshold: forgetting_js_1.FORGETTING_THRESHOLDS.FORGET,
|
|
25
|
+
consolidationThreshold: 0.7,
|
|
26
|
+
mergeThreshold: 0.85,
|
|
27
|
+
backgroundIntervalMs: 10 * 60 * 1000, // 10 minutes
|
|
28
|
+
sleepDurationMs: 5 * 60 * 1000, // 5 minutes (simulated)
|
|
29
|
+
maxEpisodicAge: 30, // 30 days
|
|
30
|
+
maxSemanticSize: 50000,
|
|
31
|
+
};
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Consolidation Service
|
|
34
|
+
// ============================================================================
|
|
35
|
+
class ConsolidationService {
|
|
36
|
+
episodicStore;
|
|
37
|
+
semanticStore;
|
|
38
|
+
proceduralStore;
|
|
39
|
+
config;
|
|
40
|
+
backgroundTimer = null;
|
|
41
|
+
isConsolidating = false;
|
|
42
|
+
lastConsolidation = null;
|
|
43
|
+
consolidationHistory = [];
|
|
44
|
+
eventLog = [];
|
|
45
|
+
constructor(episodicStore, semanticStore, proceduralStore, config = {}) {
|
|
46
|
+
this.episodicStore = episodicStore;
|
|
47
|
+
this.semanticStore = semanticStore;
|
|
48
|
+
this.proceduralStore = proceduralStore;
|
|
49
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
50
|
+
}
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Main Consolidation Methods
|
|
53
|
+
// ============================================================================
|
|
54
|
+
/**
|
|
55
|
+
* Run full consolidation cycle (sleep mode)
|
|
56
|
+
*/
|
|
57
|
+
async sleep() {
|
|
58
|
+
return this.consolidate('sleep');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Run quick consolidation (background)
|
|
62
|
+
*/
|
|
63
|
+
async backgroundConsolidate() {
|
|
64
|
+
return this.consolidate('background');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Run immediate consolidation for specific memories
|
|
68
|
+
*/
|
|
69
|
+
async immediateConsolidate(episodeIds) {
|
|
70
|
+
const episodes = episodeIds
|
|
71
|
+
.map((id) => this.episodicStore.peek(id))
|
|
72
|
+
.filter((e) => e !== undefined);
|
|
73
|
+
return this.processEpisodes(episodes, 'immediate');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Core consolidation logic
|
|
77
|
+
*/
|
|
78
|
+
async consolidate(mode) {
|
|
79
|
+
if (this.isConsolidating) {
|
|
80
|
+
throw new Error('Consolidation already in progress');
|
|
81
|
+
}
|
|
82
|
+
this.isConsolidating = true;
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
try {
|
|
85
|
+
// Get episodes ready for consolidation
|
|
86
|
+
const episodes = mode === 'background'
|
|
87
|
+
? this.episodicStore.getReadyForConsolidation(this.config.consolidationThreshold)
|
|
88
|
+
: this.episodicStore.getAll().filter((e) => !e.consolidated);
|
|
89
|
+
// Process episodes
|
|
90
|
+
const result = await this.processEpisodes(episodes, mode);
|
|
91
|
+
// Run forgetting
|
|
92
|
+
const forgottenEpisodic = this.episodicStore.runForgetting();
|
|
93
|
+
const forgottenSemantic = this.semanticStore.runForgetting();
|
|
94
|
+
const forgottenProcedural = this.proceduralStore.runForgetting();
|
|
95
|
+
result.forgotten = forgottenEpisodic.forgotten +
|
|
96
|
+
forgottenSemantic.forgotten +
|
|
97
|
+
forgottenProcedural.forgotten;
|
|
98
|
+
result.duration = Date.now() - startTime;
|
|
99
|
+
result.timestamp = new Date();
|
|
100
|
+
// Record history
|
|
101
|
+
this.consolidationHistory.push(result);
|
|
102
|
+
if (this.consolidationHistory.length > 100) {
|
|
103
|
+
this.consolidationHistory.shift();
|
|
104
|
+
}
|
|
105
|
+
this.lastConsolidation = new Date();
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
this.isConsolidating = false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Process a batch of episodes
|
|
114
|
+
*/
|
|
115
|
+
async processEpisodes(episodes, mode) {
|
|
116
|
+
const result = {
|
|
117
|
+
mode,
|
|
118
|
+
timestamp: new Date(),
|
|
119
|
+
duration: 0,
|
|
120
|
+
episodicProcessed: 0,
|
|
121
|
+
semanticCreated: 0,
|
|
122
|
+
proceduralUpdated: 0,
|
|
123
|
+
forgotten: 0,
|
|
124
|
+
merged: 0,
|
|
125
|
+
newFacts: [],
|
|
126
|
+
updatedSkills: [],
|
|
127
|
+
};
|
|
128
|
+
// Group episodes by similarity for pattern extraction
|
|
129
|
+
const groups = this.groupSimilarEpisodes(episodes);
|
|
130
|
+
for (const group of groups) {
|
|
131
|
+
result.episodicProcessed += group.length;
|
|
132
|
+
// Extract patterns from group
|
|
133
|
+
if (group.length >= 2) {
|
|
134
|
+
// Multiple similar episodes -> extract semantic fact
|
|
135
|
+
const fact = this.extractFact(group);
|
|
136
|
+
if (fact) {
|
|
137
|
+
const created = this.semanticStore.createFact(fact);
|
|
138
|
+
result.semanticCreated++;
|
|
139
|
+
result.newFacts.push(created.id);
|
|
140
|
+
this.logEvent('CONSOLIDATE', created.id, 'semantic');
|
|
141
|
+
}
|
|
142
|
+
// Check for procedural patterns
|
|
143
|
+
const procedure = this.extractProcedure(group);
|
|
144
|
+
if (procedure) {
|
|
145
|
+
const skill = this.proceduralStore.createSkill(procedure);
|
|
146
|
+
result.proceduralUpdated++;
|
|
147
|
+
result.updatedSkills.push(skill.id);
|
|
148
|
+
this.logEvent('CONSOLIDATE', skill.id, 'procedural');
|
|
149
|
+
}
|
|
150
|
+
// Merge similar episodes
|
|
151
|
+
if (group.length > 3) {
|
|
152
|
+
const merged = this.mergeEpisodes(group);
|
|
153
|
+
result.merged += group.length - 1;
|
|
154
|
+
for (const e of group.slice(1)) {
|
|
155
|
+
this.episodicStore.delete(e.id);
|
|
156
|
+
this.logEvent('MERGE', e.id, 'episodic');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Mark as consolidated
|
|
161
|
+
for (const episode of group) {
|
|
162
|
+
this.episodicStore.update(episode.id, { consolidated: true });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Pattern Extraction
|
|
169
|
+
// ============================================================================
|
|
170
|
+
/**
|
|
171
|
+
* Group similar episodes together
|
|
172
|
+
*/
|
|
173
|
+
groupSimilarEpisodes(episodes) {
|
|
174
|
+
const groups = [];
|
|
175
|
+
const used = new Set();
|
|
176
|
+
for (const episode of episodes) {
|
|
177
|
+
if (used.has(episode.id))
|
|
178
|
+
continue;
|
|
179
|
+
const group = [episode];
|
|
180
|
+
used.add(episode.id);
|
|
181
|
+
// Find similar episodes
|
|
182
|
+
for (const other of episodes) {
|
|
183
|
+
if (used.has(other.id))
|
|
184
|
+
continue;
|
|
185
|
+
if (this.episodeSimilarity(episode, other) >= this.config.mergeThreshold) {
|
|
186
|
+
group.push(other);
|
|
187
|
+
used.add(other.id);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
groups.push(group);
|
|
191
|
+
}
|
|
192
|
+
return groups;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Calculate similarity between two episodes
|
|
196
|
+
*/
|
|
197
|
+
episodeSimilarity(a, b) {
|
|
198
|
+
let score = 0;
|
|
199
|
+
let factors = 0;
|
|
200
|
+
// Content similarity (simplified - would use embeddings in production)
|
|
201
|
+
const contentA = JSON.stringify(a.content).toLowerCase();
|
|
202
|
+
const contentB = JSON.stringify(b.content).toLowerCase();
|
|
203
|
+
const wordsA = new Set(contentA.split(/\s+/));
|
|
204
|
+
const wordsB = new Set(contentB.split(/\s+/));
|
|
205
|
+
const intersection = new Set([...wordsA].filter((w) => wordsB.has(w)));
|
|
206
|
+
const union = new Set([...wordsA, ...wordsB]);
|
|
207
|
+
if (union.size > 0) {
|
|
208
|
+
score += intersection.size / union.size;
|
|
209
|
+
factors++;
|
|
210
|
+
}
|
|
211
|
+
// Tag similarity
|
|
212
|
+
if (a.tags.length > 0 || b.tags.length > 0) {
|
|
213
|
+
const tagsA = new Set(a.tags);
|
|
214
|
+
const tagsB = new Set(b.tags);
|
|
215
|
+
const tagIntersection = new Set([...tagsA].filter((t) => tagsB.has(t)));
|
|
216
|
+
const tagUnion = new Set([...tagsA, ...tagsB]);
|
|
217
|
+
if (tagUnion.size > 0) {
|
|
218
|
+
score += tagIntersection.size / tagUnion.size;
|
|
219
|
+
factors++;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Location similarity
|
|
223
|
+
if (a.where && b.where) {
|
|
224
|
+
if (a.where.location === b.where.location) {
|
|
225
|
+
score += 1;
|
|
226
|
+
}
|
|
227
|
+
factors++;
|
|
228
|
+
}
|
|
229
|
+
// Agent similarity
|
|
230
|
+
if (a.who && b.who) {
|
|
231
|
+
const agentsA = new Set(a.who.agents);
|
|
232
|
+
const agentsB = new Set(b.who.agents);
|
|
233
|
+
const agentIntersection = new Set([...agentsA].filter((ag) => agentsB.has(ag)));
|
|
234
|
+
const agentUnion = new Set([...agentsA, ...agentsB]);
|
|
235
|
+
if (agentUnion.size > 0) {
|
|
236
|
+
score += agentIntersection.size / agentUnion.size;
|
|
237
|
+
factors++;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return factors > 0 ? score / factors : 0;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Extract a semantic fact from a group of similar episodes
|
|
244
|
+
*/
|
|
245
|
+
extractFact(episodes) {
|
|
246
|
+
if (episodes.length < 2)
|
|
247
|
+
return null;
|
|
248
|
+
// Find common elements
|
|
249
|
+
const allTags = new Map();
|
|
250
|
+
const allContent = [];
|
|
251
|
+
let totalImportance = 0;
|
|
252
|
+
for (const e of episodes) {
|
|
253
|
+
for (const tag of e.tags) {
|
|
254
|
+
allTags.set(tag, (allTags.get(tag) || 0) + 1);
|
|
255
|
+
}
|
|
256
|
+
allContent.push(e.content.what);
|
|
257
|
+
totalImportance += e.importance;
|
|
258
|
+
}
|
|
259
|
+
// Most common tags become the concept
|
|
260
|
+
const sortedTags = [...allTags.entries()]
|
|
261
|
+
.sort((a, b) => b[1] - a[1]);
|
|
262
|
+
if (sortedTags.length === 0) {
|
|
263
|
+
// Use content analysis
|
|
264
|
+
const words = allContent.join(' ').toLowerCase().split(/\s+/);
|
|
265
|
+
const wordFreq = new Map();
|
|
266
|
+
for (const word of words) {
|
|
267
|
+
if (word.length > 3) { // Skip short words
|
|
268
|
+
wordFreq.set(word, (wordFreq.get(word) || 0) + 1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const topWord = [...wordFreq.entries()]
|
|
272
|
+
.sort((a, b) => b[1] - a[1])[0];
|
|
273
|
+
if (!topWord)
|
|
274
|
+
return null;
|
|
275
|
+
sortedTags.push([topWord[0], topWord[1]]);
|
|
276
|
+
}
|
|
277
|
+
const mainConcept = sortedTags[0][0];
|
|
278
|
+
return {
|
|
279
|
+
concept: mainConcept,
|
|
280
|
+
definition: `Observed pattern from ${episodes.length} episodes`,
|
|
281
|
+
properties: {
|
|
282
|
+
occurrences: episodes.length,
|
|
283
|
+
timeSpan: {
|
|
284
|
+
first: episodes[0].when.timestamp,
|
|
285
|
+
last: episodes[episodes.length - 1].when.timestamp,
|
|
286
|
+
},
|
|
287
|
+
sources: episodes.map((e) => e.id),
|
|
288
|
+
},
|
|
289
|
+
category: 'extracted',
|
|
290
|
+
sources: episodes.map((e) => e.id),
|
|
291
|
+
importance: totalImportance / episodes.length,
|
|
292
|
+
tags: sortedTags.slice(0, 5).map(([tag]) => tag),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Extract a procedural skill from a group of similar episodes
|
|
297
|
+
*/
|
|
298
|
+
extractProcedure(episodes) {
|
|
299
|
+
if (episodes.length < 3)
|
|
300
|
+
return null;
|
|
301
|
+
// Look for sequential patterns
|
|
302
|
+
const sortedEpisodes = [...episodes].sort((a, b) => a.when.timestamp.getTime() - b.when.timestamp.getTime());
|
|
303
|
+
// Check if episodes form a sequence (within a session)
|
|
304
|
+
const timeDiffs = [];
|
|
305
|
+
for (let i = 1; i < sortedEpisodes.length; i++) {
|
|
306
|
+
const diff = sortedEpisodes[i].when.timestamp.getTime() -
|
|
307
|
+
sortedEpisodes[i - 1].when.timestamp.getTime();
|
|
308
|
+
timeDiffs.push(diff);
|
|
309
|
+
}
|
|
310
|
+
// If episodes are too spread out, not a procedure
|
|
311
|
+
const avgTimeDiff = timeDiffs.reduce((a, b) => a + b, 0) / timeDiffs.length;
|
|
312
|
+
if (avgTimeDiff > 60 * 60 * 1000) { // More than 1 hour apart on average
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
// Extract steps from episode sequence
|
|
316
|
+
const steps = sortedEpisodes.map((e) => ({
|
|
317
|
+
action: e.content.what,
|
|
318
|
+
}));
|
|
319
|
+
// Common tags become the skill name
|
|
320
|
+
const allTags = new Set();
|
|
321
|
+
for (const e of sortedEpisodes) {
|
|
322
|
+
for (const t of e.tags)
|
|
323
|
+
allTags.add(t);
|
|
324
|
+
}
|
|
325
|
+
const name = [...allTags][0] || 'extracted-procedure';
|
|
326
|
+
return {
|
|
327
|
+
name: `${name}-workflow`,
|
|
328
|
+
description: `Workflow extracted from ${episodes.length} sequential episodes`,
|
|
329
|
+
steps,
|
|
330
|
+
importance: sortedEpisodes.reduce((sum, e) => sum + e.importance, 0) / sortedEpisodes.length,
|
|
331
|
+
tags: [...allTags],
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Merge multiple similar episodes into one
|
|
336
|
+
*/
|
|
337
|
+
mergeEpisodes(episodes) {
|
|
338
|
+
const first = episodes[0];
|
|
339
|
+
// Combine content
|
|
340
|
+
const mergedContent = {
|
|
341
|
+
what: `Merged: ${first.content.what} (${episodes.length} occurrences)`,
|
|
342
|
+
details: {
|
|
343
|
+
originalCount: episodes.length,
|
|
344
|
+
mergedFrom: episodes.map((e) => e.id),
|
|
345
|
+
timeRange: {
|
|
346
|
+
first: episodes[0].when.timestamp,
|
|
347
|
+
last: episodes[episodes.length - 1].when.timestamp,
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
// Update first episode with merged content
|
|
352
|
+
this.episodicStore.update(first.id, {
|
|
353
|
+
content: mergedContent,
|
|
354
|
+
importance: Math.max(...episodes.map((e) => e.importance)),
|
|
355
|
+
S: Math.max(...episodes.map((e) => e.S)), // Keep strongest stability
|
|
356
|
+
});
|
|
357
|
+
return first;
|
|
358
|
+
}
|
|
359
|
+
// ============================================================================
|
|
360
|
+
// Background Consolidation
|
|
361
|
+
// ============================================================================
|
|
362
|
+
/**
|
|
363
|
+
* Start background consolidation timer
|
|
364
|
+
*/
|
|
365
|
+
startBackground() {
|
|
366
|
+
if (this.backgroundTimer)
|
|
367
|
+
return;
|
|
368
|
+
this.backgroundTimer = setInterval(async () => {
|
|
369
|
+
try {
|
|
370
|
+
await this.backgroundConsolidate();
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
console.error('[Consolidation] Background error:', error);
|
|
374
|
+
}
|
|
375
|
+
}, this.config.backgroundIntervalMs);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Stop background consolidation
|
|
379
|
+
*/
|
|
380
|
+
stopBackground() {
|
|
381
|
+
if (this.backgroundTimer) {
|
|
382
|
+
clearInterval(this.backgroundTimer);
|
|
383
|
+
this.backgroundTimer = null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Check if background consolidation is running
|
|
388
|
+
*/
|
|
389
|
+
isBackgroundRunning() {
|
|
390
|
+
return this.backgroundTimer !== null;
|
|
391
|
+
}
|
|
392
|
+
// ============================================================================
|
|
393
|
+
// Event Logging
|
|
394
|
+
// ============================================================================
|
|
395
|
+
logEvent(type, memoryId, memoryType) {
|
|
396
|
+
this.eventLog.push({
|
|
397
|
+
type,
|
|
398
|
+
memoryId,
|
|
399
|
+
memoryType,
|
|
400
|
+
timestamp: new Date(),
|
|
401
|
+
});
|
|
402
|
+
// Keep log bounded
|
|
403
|
+
if (this.eventLog.length > 1000) {
|
|
404
|
+
this.eventLog.shift();
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// ============================================================================
|
|
408
|
+
// Stats and History
|
|
409
|
+
// ============================================================================
|
|
410
|
+
getStats() {
|
|
411
|
+
return {
|
|
412
|
+
lastConsolidation: this.lastConsolidation,
|
|
413
|
+
isConsolidating: this.isConsolidating,
|
|
414
|
+
backgroundRunning: this.isBackgroundRunning(),
|
|
415
|
+
totalConsolidations: this.consolidationHistory.length,
|
|
416
|
+
recentResults: this.consolidationHistory.slice(-10),
|
|
417
|
+
memoryStats: {
|
|
418
|
+
episodic: (0, forgetting_js_1.calculateForgettingStats)(this.episodicStore.getAll()),
|
|
419
|
+
semantic: (0, forgetting_js_1.calculateForgettingStats)(this.semanticStore.getAll()),
|
|
420
|
+
procedural: (0, forgetting_js_1.calculateForgettingStats)(this.proceduralStore.getAll()),
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
getHistory(limit) {
|
|
425
|
+
if (limit) {
|
|
426
|
+
return this.consolidationHistory.slice(-limit);
|
|
427
|
+
}
|
|
428
|
+
return [...this.consolidationHistory];
|
|
429
|
+
}
|
|
430
|
+
getEventLog(limit) {
|
|
431
|
+
if (limit) {
|
|
432
|
+
return this.eventLog.slice(-limit);
|
|
433
|
+
}
|
|
434
|
+
return [...this.eventLog];
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
exports.ConsolidationService = ConsolidationService;
|
|
438
|
+
// ============================================================================
|
|
439
|
+
// Factory
|
|
440
|
+
// ============================================================================
|
|
441
|
+
function createConsolidationService(episodicStore, semanticStore, proceduralStore, config) {
|
|
442
|
+
return new ConsolidationService(episodicStore, semanticStore, proceduralStore, config);
|
|
443
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis 6.0 - Episodic Memory Store
|
|
3
|
+
*
|
|
4
|
+
* Stores autobiographical memories - events with context.
|
|
5
|
+
* "What happened, when, where, who was involved"
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Temporal ordering and sequencing
|
|
9
|
+
* - Context binding (where, who)
|
|
10
|
+
* - Emotional coloring
|
|
11
|
+
* - Forgetting curve integration
|
|
12
|
+
*
|
|
13
|
+
* Reference: Tulving, E. (1972). Episodic and semantic memory.
|
|
14
|
+
*/
|
|
15
|
+
import { EpisodicMemory, IMemoryStore, MemoryFilter, StoreStats } from './types.js';
|
|
16
|
+
export interface EpisodicStoreConfig {
|
|
17
|
+
maxSize: number;
|
|
18
|
+
autoForget: boolean;
|
|
19
|
+
forgetThreshold: number;
|
|
20
|
+
defaultStability: number;
|
|
21
|
+
}
|
|
22
|
+
export interface CreateEpisodicOptions {
|
|
23
|
+
what: string;
|
|
24
|
+
details?: any;
|
|
25
|
+
when?: Date;
|
|
26
|
+
duration?: number;
|
|
27
|
+
where?: {
|
|
28
|
+
location: string;
|
|
29
|
+
context: string;
|
|
30
|
+
};
|
|
31
|
+
who?: {
|
|
32
|
+
agents: string[];
|
|
33
|
+
roles?: Record<string, string>;
|
|
34
|
+
};
|
|
35
|
+
feeling?: {
|
|
36
|
+
valence: number;
|
|
37
|
+
arousal: number;
|
|
38
|
+
label?: string;
|
|
39
|
+
};
|
|
40
|
+
importance?: number;
|
|
41
|
+
tags?: string[];
|
|
42
|
+
associations?: string[];
|
|
43
|
+
source?: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class EpisodicStore implements IMemoryStore<EpisodicMemory> {
|
|
46
|
+
private memories;
|
|
47
|
+
private config;
|
|
48
|
+
private byTime;
|
|
49
|
+
private byLocation;
|
|
50
|
+
private byAgent;
|
|
51
|
+
private byTag;
|
|
52
|
+
constructor(config?: Partial<EpisodicStoreConfig>);
|
|
53
|
+
store(input: Omit<EpisodicMemory, 'id' | 'created' | 'lastAccessed' | 'accessCount'>): EpisodicMemory;
|
|
54
|
+
/**
|
|
55
|
+
* Convenience method to create an episodic memory from options
|
|
56
|
+
*/
|
|
57
|
+
createEpisode(options: CreateEpisodicOptions): EpisodicMemory;
|
|
58
|
+
get(id: string): EpisodicMemory | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Get without updating access (for internal use)
|
|
61
|
+
*/
|
|
62
|
+
peek(id: string): EpisodicMemory | undefined;
|
|
63
|
+
update(id: string, updates: Partial<EpisodicMemory>): EpisodicMemory | undefined;
|
|
64
|
+
delete(id: string): boolean;
|
|
65
|
+
query(filter: MemoryFilter<EpisodicMemory>): EpisodicMemory[];
|
|
66
|
+
/**
|
|
67
|
+
* Search by keyword in content
|
|
68
|
+
*/
|
|
69
|
+
search(queryStr: string, limit?: number): EpisodicMemory[];
|
|
70
|
+
/**
|
|
71
|
+
* Get episodes in a time range
|
|
72
|
+
*/
|
|
73
|
+
getByTimeRange(start: Date, end: Date): EpisodicMemory[];
|
|
74
|
+
/**
|
|
75
|
+
* Get recent episodes
|
|
76
|
+
*/
|
|
77
|
+
getRecent(limit?: number): EpisodicMemory[];
|
|
78
|
+
/**
|
|
79
|
+
* Get episodes from today
|
|
80
|
+
*/
|
|
81
|
+
getToday(): EpisodicMemory[];
|
|
82
|
+
/**
|
|
83
|
+
* Get episodes involving a specific agent
|
|
84
|
+
*/
|
|
85
|
+
getByAgent(agentId: string): EpisodicMemory[];
|
|
86
|
+
/**
|
|
87
|
+
* Get episodes at a location
|
|
88
|
+
*/
|
|
89
|
+
getByLocation(location: string): EpisodicMemory[];
|
|
90
|
+
getAll(): EpisodicMemory[];
|
|
91
|
+
clear(): void;
|
|
92
|
+
count(): number;
|
|
93
|
+
stats(): StoreStats;
|
|
94
|
+
/**
|
|
95
|
+
* Get episodes that should be forgotten
|
|
96
|
+
*/
|
|
97
|
+
getForgotten(): EpisodicMemory[];
|
|
98
|
+
/**
|
|
99
|
+
* Get episodes ready for consolidation (strong retention, not yet consolidated)
|
|
100
|
+
*/
|
|
101
|
+
getReadyForConsolidation(threshold?: number): EpisodicMemory[];
|
|
102
|
+
/**
|
|
103
|
+
* Run forgetting cycle - remove memories below threshold
|
|
104
|
+
*/
|
|
105
|
+
runForgetting(): {
|
|
106
|
+
forgotten: number;
|
|
107
|
+
ids: string[];
|
|
108
|
+
};
|
|
109
|
+
private accessMemory;
|
|
110
|
+
private updateIndexes;
|
|
111
|
+
private removeFromIndexes;
|
|
112
|
+
private maintainSize;
|
|
113
|
+
}
|
|
114
|
+
export declare function createEpisodicStore(config?: Partial<EpisodicStoreConfig>): EpisodicStore;
|