@timmeck/brain-core 2.36.79 → 2.36.81
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/dist/browser/browser-agent.d.ts +188 -0
- package/dist/browser/browser-agent.js +787 -0
- package/dist/browser/browser-agent.js.map +1 -0
- package/dist/chat/brain-bot.d.ts +75 -0
- package/dist/chat/brain-bot.js +246 -0
- package/dist/chat/brain-bot.js.map +1 -0
- package/dist/chat/chat-engine.d.ts +3 -0
- package/dist/chat/chat-engine.js +17 -0
- package/dist/chat/chat-engine.js.map +1 -1
- package/dist/chat/index.d.ts +2 -0
- package/dist/chat/index.js +1 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/debate/debate-engine.js +18 -2
- package/dist/debate/debate-engine.js.map +1 -1
- package/dist/hypothesis/engine.d.ts +34 -0
- package/dist/hypothesis/engine.js +82 -0
- package/dist/hypothesis/engine.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/memory/conversation-memory.d.ts +141 -0
- package/dist/memory/conversation-memory.js +470 -0
- package/dist/memory/conversation-memory.js.map +1 -0
- package/dist/research/autonomous-research-loop.d.ts +104 -0
- package/dist/research/autonomous-research-loop.js +246 -0
- package/dist/research/autonomous-research-loop.js.map +1 -0
- package/dist/research/research-orchestrator.d.ts +3 -0
- package/dist/research/research-orchestrator.js +28 -0
- package/dist/research/research-orchestrator.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { MemoryCategory, MemorySource } from './types.js';
|
|
3
|
+
export interface ConversationMemoryConfig {
|
|
4
|
+
/** Max memories to keep. Default: 50_000 */
|
|
5
|
+
maxMemories?: number;
|
|
6
|
+
/** Days after which unused low-importance memories decay. Default: 90 */
|
|
7
|
+
decayDays?: number;
|
|
8
|
+
/** Default importance for new memories. Default: 5 */
|
|
9
|
+
defaultImportance?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Memory {
|
|
12
|
+
id: number;
|
|
13
|
+
sessionId: string | null;
|
|
14
|
+
category: MemoryCategory;
|
|
15
|
+
content: string;
|
|
16
|
+
key: string | null;
|
|
17
|
+
importance: number;
|
|
18
|
+
source: MemorySource;
|
|
19
|
+
tags: string[];
|
|
20
|
+
accessCount: number;
|
|
21
|
+
lastAccessedAt: string | null;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface RememberOptions {
|
|
27
|
+
category?: MemoryCategory;
|
|
28
|
+
key?: string;
|
|
29
|
+
importance?: number;
|
|
30
|
+
source?: MemorySource;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
sessionId?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface RecallOptions {
|
|
35
|
+
category?: MemoryCategory;
|
|
36
|
+
limit?: number;
|
|
37
|
+
minImportance?: number;
|
|
38
|
+
activeOnly?: boolean;
|
|
39
|
+
tags?: string[];
|
|
40
|
+
}
|
|
41
|
+
export interface SessionSummary {
|
|
42
|
+
sessionId: string;
|
|
43
|
+
startedAt: string;
|
|
44
|
+
endedAt: string | null;
|
|
45
|
+
summary: string | null;
|
|
46
|
+
goals: string[];
|
|
47
|
+
memoriesCreated: number;
|
|
48
|
+
}
|
|
49
|
+
export interface MemorySearchResult {
|
|
50
|
+
memory: Memory;
|
|
51
|
+
relevance: number;
|
|
52
|
+
}
|
|
53
|
+
export interface ConversationMemoryStatus {
|
|
54
|
+
totalMemories: number;
|
|
55
|
+
activeMemories: number;
|
|
56
|
+
totalSessions: number;
|
|
57
|
+
byCategory: Record<string, number>;
|
|
58
|
+
recentMemories: Memory[];
|
|
59
|
+
}
|
|
60
|
+
export interface MemoryRAGAdapter {
|
|
61
|
+
index(collection: string, sourceId: number, text: string, metadata?: Record<string, unknown>): Promise<boolean>;
|
|
62
|
+
search(query: string, options?: {
|
|
63
|
+
collections?: string[];
|
|
64
|
+
limit?: number;
|
|
65
|
+
threshold?: number;
|
|
66
|
+
}): Promise<Array<{
|
|
67
|
+
sourceId: number;
|
|
68
|
+
similarity: number;
|
|
69
|
+
}>>;
|
|
70
|
+
remove(collection: string, sourceId: number): void;
|
|
71
|
+
}
|
|
72
|
+
export interface MemoryJournalAdapter {
|
|
73
|
+
recordDiscovery(title: string, description: string, data: Record<string, unknown>, significance: string): unknown;
|
|
74
|
+
}
|
|
75
|
+
export interface MemoryKnowledgeGraphAdapter {
|
|
76
|
+
addFact(subject: string, predicate: string, object: string, context?: string, confidence?: number, sourceType?: string): unknown;
|
|
77
|
+
}
|
|
78
|
+
export declare function runConversationMemoryMigration(db: Database.Database): void;
|
|
79
|
+
export declare class ConversationMemory {
|
|
80
|
+
private readonly db;
|
|
81
|
+
private readonly config;
|
|
82
|
+
private readonly log;
|
|
83
|
+
private rag;
|
|
84
|
+
private journal;
|
|
85
|
+
private kg;
|
|
86
|
+
private readonly stmtInsert;
|
|
87
|
+
private readonly stmtGetById;
|
|
88
|
+
private readonly stmtSearch;
|
|
89
|
+
private readonly stmtFindByKey;
|
|
90
|
+
private readonly stmtFindByCategory;
|
|
91
|
+
private readonly stmtFindActive;
|
|
92
|
+
private readonly stmtFindRecent;
|
|
93
|
+
private readonly stmtUpdate;
|
|
94
|
+
private readonly stmtDeactivate;
|
|
95
|
+
private readonly stmtRecordAccess;
|
|
96
|
+
private readonly stmtCountByCategory;
|
|
97
|
+
private readonly stmtCountActive;
|
|
98
|
+
private readonly stmtCountTotal;
|
|
99
|
+
private readonly stmtCountSessions;
|
|
100
|
+
private readonly stmtSessionInsert;
|
|
101
|
+
private readonly stmtSessionEnd;
|
|
102
|
+
private readonly stmtSessionGet;
|
|
103
|
+
private readonly stmtSessionCountMemories;
|
|
104
|
+
constructor(db: Database.Database, config?: ConversationMemoryConfig);
|
|
105
|
+
setRAG(rag: MemoryRAGAdapter): void;
|
|
106
|
+
setJournal(journal: MemoryJournalAdapter): void;
|
|
107
|
+
setKnowledgeGraph(kg: MemoryKnowledgeGraphAdapter): void;
|
|
108
|
+
/** Store a memory. Returns memory ID. */
|
|
109
|
+
remember(content: string, options?: RememberOptions): number;
|
|
110
|
+
/** Semantic search for memories. Uses RAG if available, falls back to FTS5. */
|
|
111
|
+
recall(query: string, options?: RecallOptions): Promise<MemorySearchResult[]>;
|
|
112
|
+
/** Full-text search (FTS5). Always available, no embeddings needed. */
|
|
113
|
+
searchText(query: string, options?: RecallOptions): MemorySearchResult[];
|
|
114
|
+
/** Get recent memories for session context. Perfect for session start. */
|
|
115
|
+
getRecentContext(limit?: number): Memory[];
|
|
116
|
+
/** Get all memories for a category. */
|
|
117
|
+
getByCategory(category: MemoryCategory, limit?: number): Memory[];
|
|
118
|
+
/** Get a specific memory by key. */
|
|
119
|
+
getByKey(key: string): Memory | null;
|
|
120
|
+
/** Get the most important memories. */
|
|
121
|
+
getImportant(limit?: number, minImportance?: number): Memory[];
|
|
122
|
+
/** Build a context summary for the LLM (for session start). */
|
|
123
|
+
buildContext(limit?: number): string;
|
|
124
|
+
/** Start a new conversation session. */
|
|
125
|
+
startSession(sessionId: string, goals?: string[], metadata?: Record<string, unknown>): void;
|
|
126
|
+
/** End a conversation session with a summary. */
|
|
127
|
+
endSession(sessionId: string, summary: string): void;
|
|
128
|
+
/** Get session info. */
|
|
129
|
+
getSession(sessionId: string): SessionSummary | null;
|
|
130
|
+
/** Deactivate a memory (soft delete). */
|
|
131
|
+
forget(id: number): void;
|
|
132
|
+
/** Update an existing memory's content. */
|
|
133
|
+
update(id: number, content: string, importance?: number): void;
|
|
134
|
+
/** Cleanup: decay old unused memories, prune excess. */
|
|
135
|
+
maintenance(): {
|
|
136
|
+
decayed: number;
|
|
137
|
+
pruned: number;
|
|
138
|
+
};
|
|
139
|
+
getStatus(): ConversationMemoryStatus;
|
|
140
|
+
private toMemory;
|
|
141
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
// ── Conversation Memory ─────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Langzeitgedächtnis für Claude Code Sessions.
|
|
4
|
+
// Alles was besprochen, entschieden, gebaut wird → persistent gespeichert.
|
|
5
|
+
// Jederzeit abrufbar per semantischer Suche oder Keyword-Suche.
|
|
6
|
+
//
|
|
7
|
+
// Speichert:
|
|
8
|
+
// - Entscheidungen (Architektur, Toolwahl, Patterns)
|
|
9
|
+
// - Präferenzen (Workflow, Coding-Style, Konventionen)
|
|
10
|
+
// - Kontext (Was wurde gebaut, warum, wie)
|
|
11
|
+
// - Fakten (API Keys, Ports, Pfade, Versionen)
|
|
12
|
+
// - Ziele (Was soll erreicht werden)
|
|
13
|
+
// - Lektionen (Was hat funktioniert, was nicht)
|
|
14
|
+
//
|
|
15
|
+
// Integration:
|
|
16
|
+
// - RAG Engine für semantische Suche (Embeddings)
|
|
17
|
+
// - Journal für chronologische Erfassung
|
|
18
|
+
// - KnowledgeGraph für Entitäten-Verknüpfungen
|
|
19
|
+
import { getLogger } from '../utils/logger.js';
|
|
20
|
+
// ── Migration ─────────────────────────────────────────────
|
|
21
|
+
export function runConversationMemoryMigration(db) {
|
|
22
|
+
db.exec(`
|
|
23
|
+
CREATE TABLE IF NOT EXISTS conversation_memories (
|
|
24
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
25
|
+
session_id TEXT,
|
|
26
|
+
category TEXT NOT NULL DEFAULT 'context',
|
|
27
|
+
key TEXT,
|
|
28
|
+
content TEXT NOT NULL,
|
|
29
|
+
importance INTEGER NOT NULL DEFAULT 5,
|
|
30
|
+
source TEXT NOT NULL DEFAULT 'explicit',
|
|
31
|
+
tags TEXT DEFAULT '[]',
|
|
32
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
33
|
+
last_accessed_at TEXT,
|
|
34
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
35
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
36
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
37
|
+
);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_conv_mem_category ON conversation_memories(category);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_conv_mem_session ON conversation_memories(session_id);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_conv_mem_key ON conversation_memories(key);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_conv_mem_active ON conversation_memories(active);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_conv_mem_importance ON conversation_memories(importance DESC);
|
|
43
|
+
`);
|
|
44
|
+
// FTS5 for full-text search
|
|
45
|
+
db.exec(`
|
|
46
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS conversation_memories_fts USING fts5(
|
|
47
|
+
content, tags, key,
|
|
48
|
+
content='conversation_memories',
|
|
49
|
+
content_rowid='id'
|
|
50
|
+
);
|
|
51
|
+
`);
|
|
52
|
+
// Triggers for FTS sync
|
|
53
|
+
try {
|
|
54
|
+
db.exec(`
|
|
55
|
+
CREATE TRIGGER IF NOT EXISTS conv_mem_ai AFTER INSERT ON conversation_memories BEGIN
|
|
56
|
+
INSERT INTO conversation_memories_fts(rowid, content, tags, key) VALUES (new.id, new.content, new.tags, new.key);
|
|
57
|
+
END;
|
|
58
|
+
CREATE TRIGGER IF NOT EXISTS conv_mem_ad AFTER DELETE ON conversation_memories BEGIN
|
|
59
|
+
INSERT INTO conversation_memories_fts(conversation_memories_fts, rowid, content, tags, key) VALUES('delete', old.id, old.content, old.tags, old.key);
|
|
60
|
+
END;
|
|
61
|
+
CREATE TRIGGER IF NOT EXISTS conv_mem_au AFTER UPDATE ON conversation_memories BEGIN
|
|
62
|
+
INSERT INTO conversation_memories_fts(conversation_memories_fts, rowid, content, tags, key) VALUES('delete', old.id, old.content, old.tags, old.key);
|
|
63
|
+
INSERT INTO conversation_memories_fts(rowid, content, tags, key) VALUES (new.id, new.content, new.tags, new.key);
|
|
64
|
+
END;
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Triggers already exist
|
|
69
|
+
}
|
|
70
|
+
// Sessions table
|
|
71
|
+
db.exec(`
|
|
72
|
+
CREATE TABLE IF NOT EXISTS conversation_sessions (
|
|
73
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
74
|
+
session_id TEXT NOT NULL UNIQUE,
|
|
75
|
+
started_at TEXT DEFAULT (datetime('now')),
|
|
76
|
+
ended_at TEXT,
|
|
77
|
+
summary TEXT,
|
|
78
|
+
goals TEXT DEFAULT '[]',
|
|
79
|
+
metadata TEXT DEFAULT '{}'
|
|
80
|
+
);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_conv_sess_id ON conversation_sessions(session_id);
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
// ── Engine ────────────────────────────────────────────────
|
|
85
|
+
const RAG_COLLECTION = 'conversation_memory';
|
|
86
|
+
export class ConversationMemory {
|
|
87
|
+
db;
|
|
88
|
+
config;
|
|
89
|
+
log = getLogger();
|
|
90
|
+
rag = null;
|
|
91
|
+
journal = null;
|
|
92
|
+
kg = null;
|
|
93
|
+
// Prepared statements
|
|
94
|
+
stmtInsert;
|
|
95
|
+
stmtGetById;
|
|
96
|
+
stmtSearch;
|
|
97
|
+
stmtFindByKey;
|
|
98
|
+
stmtFindByCategory;
|
|
99
|
+
stmtFindActive;
|
|
100
|
+
stmtFindRecent;
|
|
101
|
+
stmtUpdate;
|
|
102
|
+
stmtDeactivate;
|
|
103
|
+
stmtRecordAccess;
|
|
104
|
+
stmtCountByCategory;
|
|
105
|
+
stmtCountActive;
|
|
106
|
+
stmtCountTotal;
|
|
107
|
+
stmtCountSessions;
|
|
108
|
+
stmtSessionInsert;
|
|
109
|
+
stmtSessionEnd;
|
|
110
|
+
stmtSessionGet;
|
|
111
|
+
stmtSessionCountMemories;
|
|
112
|
+
constructor(db, config = {}) {
|
|
113
|
+
this.db = db;
|
|
114
|
+
this.config = {
|
|
115
|
+
maxMemories: config.maxMemories ?? 50_000,
|
|
116
|
+
decayDays: config.decayDays ?? 90,
|
|
117
|
+
defaultImportance: config.defaultImportance ?? 5,
|
|
118
|
+
};
|
|
119
|
+
runConversationMemoryMigration(db);
|
|
120
|
+
this.stmtInsert = db.prepare(`
|
|
121
|
+
INSERT INTO conversation_memories (session_id, category, key, content, importance, source, tags)
|
|
122
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
123
|
+
`);
|
|
124
|
+
this.stmtGetById = db.prepare('SELECT * FROM conversation_memories WHERE id = ?');
|
|
125
|
+
this.stmtSearch = db.prepare(`
|
|
126
|
+
SELECT m.* FROM conversation_memories m
|
|
127
|
+
JOIN conversation_memories_fts f ON m.id = f.rowid
|
|
128
|
+
WHERE conversation_memories_fts MATCH ? AND m.active = 1
|
|
129
|
+
ORDER BY rank
|
|
130
|
+
LIMIT ?
|
|
131
|
+
`);
|
|
132
|
+
this.stmtFindByKey = db.prepare('SELECT * FROM conversation_memories WHERE key = ? AND active = 1 ORDER BY updated_at DESC LIMIT 1');
|
|
133
|
+
this.stmtFindByCategory = db.prepare('SELECT * FROM conversation_memories WHERE category = ? AND active = 1 ORDER BY importance DESC, updated_at DESC LIMIT ?');
|
|
134
|
+
this.stmtFindActive = db.prepare('SELECT * FROM conversation_memories WHERE active = 1 ORDER BY importance DESC, updated_at DESC LIMIT ?');
|
|
135
|
+
this.stmtFindRecent = db.prepare('SELECT * FROM conversation_memories WHERE active = 1 ORDER BY created_at DESC LIMIT ?');
|
|
136
|
+
this.stmtUpdate = db.prepare(`
|
|
137
|
+
UPDATE conversation_memories SET content = ?, importance = ?, tags = ?, updated_at = datetime('now')
|
|
138
|
+
WHERE id = ?
|
|
139
|
+
`);
|
|
140
|
+
this.stmtDeactivate = db.prepare("UPDATE conversation_memories SET active = 0, updated_at = datetime('now') WHERE id = ?");
|
|
141
|
+
this.stmtRecordAccess = db.prepare(`
|
|
142
|
+
UPDATE conversation_memories SET access_count = access_count + 1, last_accessed_at = datetime('now')
|
|
143
|
+
WHERE id = ?
|
|
144
|
+
`);
|
|
145
|
+
this.stmtCountByCategory = db.prepare('SELECT category, COUNT(*) as count FROM conversation_memories WHERE active = 1 GROUP BY category');
|
|
146
|
+
this.stmtCountActive = db.prepare('SELECT COUNT(*) as count FROM conversation_memories WHERE active = 1');
|
|
147
|
+
this.stmtCountTotal = db.prepare('SELECT COUNT(*) as count FROM conversation_memories');
|
|
148
|
+
this.stmtCountSessions = db.prepare('SELECT COUNT(*) as count FROM conversation_sessions');
|
|
149
|
+
this.stmtSessionInsert = db.prepare("INSERT INTO conversation_sessions (session_id, goals, metadata) VALUES (?, ?, ?)");
|
|
150
|
+
this.stmtSessionEnd = db.prepare("UPDATE conversation_sessions SET ended_at = datetime('now'), summary = ? WHERE session_id = ?");
|
|
151
|
+
this.stmtSessionGet = db.prepare('SELECT * FROM conversation_sessions WHERE session_id = ?');
|
|
152
|
+
this.stmtSessionCountMemories = db.prepare('SELECT COUNT(*) as count FROM conversation_memories WHERE session_id = ?');
|
|
153
|
+
}
|
|
154
|
+
// ── Setters ────────────────────────────────────────────
|
|
155
|
+
setRAG(rag) { this.rag = rag; }
|
|
156
|
+
setJournal(journal) { this.journal = journal; }
|
|
157
|
+
setKnowledgeGraph(kg) { this.kg = kg; }
|
|
158
|
+
// ── Remember ──────────────────────────────────────────
|
|
159
|
+
/** Store a memory. Returns memory ID. */
|
|
160
|
+
remember(content, options = {}) {
|
|
161
|
+
const category = options.category ?? 'context';
|
|
162
|
+
const key = options.key ?? null;
|
|
163
|
+
const importance = options.importance ?? this.config.defaultImportance;
|
|
164
|
+
const source = options.source ?? 'explicit';
|
|
165
|
+
const tags = JSON.stringify(options.tags ?? []);
|
|
166
|
+
const sessionId = options.sessionId ?? null;
|
|
167
|
+
// If key exists, update instead of insert
|
|
168
|
+
if (key) {
|
|
169
|
+
const existing = this.stmtFindByKey.get(key);
|
|
170
|
+
if (existing) {
|
|
171
|
+
const newImportance = Math.max(existing.importance, importance);
|
|
172
|
+
this.stmtUpdate.run(content, newImportance, tags, existing.id);
|
|
173
|
+
this.log.debug(`[conversation-memory] Updated memory #${existing.id} (key: ${key})`);
|
|
174
|
+
// Update RAG index
|
|
175
|
+
if (this.rag) {
|
|
176
|
+
this.rag.index(RAG_COLLECTION, existing.id, content, { category, key }).catch(() => { });
|
|
177
|
+
}
|
|
178
|
+
return existing.id;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const result = this.stmtInsert.run(sessionId, category, key, content, importance, source, tags);
|
|
182
|
+
const id = result.lastInsertRowid;
|
|
183
|
+
// Index in RAG for semantic search
|
|
184
|
+
if (this.rag) {
|
|
185
|
+
this.rag.index(RAG_COLLECTION, id, content, { category, key, tags: options.tags }).catch(() => { });
|
|
186
|
+
}
|
|
187
|
+
// Record in journal for chronological tracking
|
|
188
|
+
if (this.journal && importance >= 7) {
|
|
189
|
+
try {
|
|
190
|
+
this.journal.recordDiscovery(`Memory: ${key ?? content.slice(0, 50)}`, content.slice(0, 500), { memory_id: id, category, source }, importance >= 9 ? 'notable' : 'routine');
|
|
191
|
+
}
|
|
192
|
+
catch { /* best effort */ }
|
|
193
|
+
}
|
|
194
|
+
// Add to knowledge graph for relationships
|
|
195
|
+
if (this.kg && key) {
|
|
196
|
+
try {
|
|
197
|
+
this.kg.addFact('brain', `remembers_${category}`, key, content.slice(0, 200), importance / 10, 'conversation');
|
|
198
|
+
}
|
|
199
|
+
catch { /* best effort */ }
|
|
200
|
+
}
|
|
201
|
+
this.log.debug(`[conversation-memory] Stored memory #${id} (${category}: ${key ?? content.slice(0, 40)})`);
|
|
202
|
+
return id;
|
|
203
|
+
}
|
|
204
|
+
// ── Recall ────────────────────────────────────────────
|
|
205
|
+
/** Semantic search for memories. Uses RAG if available, falls back to FTS5. */
|
|
206
|
+
async recall(query, options = {}) {
|
|
207
|
+
const limit = options.limit ?? 10;
|
|
208
|
+
// Try RAG semantic search first
|
|
209
|
+
if (this.rag) {
|
|
210
|
+
try {
|
|
211
|
+
const ragResults = await this.rag.search(query, {
|
|
212
|
+
collections: [RAG_COLLECTION],
|
|
213
|
+
limit: limit * 2, // Get extra for filtering
|
|
214
|
+
threshold: 0.3,
|
|
215
|
+
});
|
|
216
|
+
const memories = [];
|
|
217
|
+
for (const r of ragResults) {
|
|
218
|
+
const row = this.stmtGetById.get(r.sourceId);
|
|
219
|
+
if (!row || !row.active)
|
|
220
|
+
continue;
|
|
221
|
+
const mem = this.toMemory(row);
|
|
222
|
+
if (options.category && mem.category !== options.category)
|
|
223
|
+
continue;
|
|
224
|
+
if (options.minImportance && mem.importance < options.minImportance)
|
|
225
|
+
continue;
|
|
226
|
+
if (options.tags?.length && !options.tags.some(t => mem.tags.includes(t)))
|
|
227
|
+
continue;
|
|
228
|
+
// Record access
|
|
229
|
+
this.stmtRecordAccess.run(mem.id);
|
|
230
|
+
memories.push({ memory: mem, relevance: r.similarity });
|
|
231
|
+
if (memories.length >= limit)
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
return memories;
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
this.log.debug(`[conversation-memory] RAG recall failed, falling back to FTS: ${err.message}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Fallback: FTS5 text search
|
|
241
|
+
return this.searchText(query, options);
|
|
242
|
+
}
|
|
243
|
+
/** Full-text search (FTS5). Always available, no embeddings needed. */
|
|
244
|
+
searchText(query, options = {}) {
|
|
245
|
+
const limit = options.limit ?? 10;
|
|
246
|
+
// Sanitize query for FTS5
|
|
247
|
+
const ftsQuery = query.replace(/[^\w\s]/g, ' ').trim().split(/\s+/).filter(w => w.length > 1).join(' OR ');
|
|
248
|
+
if (!ftsQuery)
|
|
249
|
+
return [];
|
|
250
|
+
try {
|
|
251
|
+
const rows = this.stmtSearch.all(ftsQuery, limit * 2);
|
|
252
|
+
const results = [];
|
|
253
|
+
for (const row of rows) {
|
|
254
|
+
const mem = this.toMemory(row);
|
|
255
|
+
if (options.category && mem.category !== options.category)
|
|
256
|
+
continue;
|
|
257
|
+
if (options.minImportance && mem.importance < options.minImportance)
|
|
258
|
+
continue;
|
|
259
|
+
if (options.activeOnly !== false && !mem.active)
|
|
260
|
+
continue;
|
|
261
|
+
this.stmtRecordAccess.run(mem.id);
|
|
262
|
+
results.push({ memory: mem, relevance: 0.5 }); // FTS doesn't give similarity score
|
|
263
|
+
if (results.length >= limit)
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
return results;
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// FTS query might fail on edge cases — fallback to LIKE
|
|
270
|
+
const likeRows = this.db.prepare('SELECT * FROM conversation_memories WHERE active = 1 AND content LIKE ? ORDER BY importance DESC LIMIT ?').all(`%${query}%`, limit);
|
|
271
|
+
return likeRows.map(row => ({
|
|
272
|
+
memory: this.toMemory(row),
|
|
273
|
+
relevance: 0.3,
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// ── Context Retrieval ─────────────────────────────────
|
|
278
|
+
/** Get recent memories for session context. Perfect for session start. */
|
|
279
|
+
getRecentContext(limit = 20) {
|
|
280
|
+
const rows = this.stmtFindRecent.all(limit);
|
|
281
|
+
return rows.map(r => this.toMemory(r));
|
|
282
|
+
}
|
|
283
|
+
/** Get all memories for a category. */
|
|
284
|
+
getByCategory(category, limit = 20) {
|
|
285
|
+
const rows = this.stmtFindByCategory.all(category, limit);
|
|
286
|
+
return rows.map(r => this.toMemory(r));
|
|
287
|
+
}
|
|
288
|
+
/** Get a specific memory by key. */
|
|
289
|
+
getByKey(key) {
|
|
290
|
+
const row = this.stmtFindByKey.get(key);
|
|
291
|
+
if (!row)
|
|
292
|
+
return null;
|
|
293
|
+
this.stmtRecordAccess.run(row.id);
|
|
294
|
+
return this.toMemory(row);
|
|
295
|
+
}
|
|
296
|
+
/** Get the most important memories. */
|
|
297
|
+
getImportant(limit = 10, minImportance = 7) {
|
|
298
|
+
const rows = this.db.prepare('SELECT * FROM conversation_memories WHERE active = 1 AND importance >= ? ORDER BY importance DESC, access_count DESC LIMIT ?').all(minImportance, limit);
|
|
299
|
+
return rows.map(r => this.toMemory(r));
|
|
300
|
+
}
|
|
301
|
+
/** Build a context summary for the LLM (for session start). */
|
|
302
|
+
buildContext(limit = 30) {
|
|
303
|
+
const parts = [];
|
|
304
|
+
parts.push('# Brain Memory Context\n');
|
|
305
|
+
// Decisions
|
|
306
|
+
const decisions = this.getByCategory('decision', 5);
|
|
307
|
+
if (decisions.length > 0) {
|
|
308
|
+
parts.push('## Key Decisions');
|
|
309
|
+
for (const m of decisions)
|
|
310
|
+
parts.push(`- ${m.key ?? m.content.slice(0, 100)}`);
|
|
311
|
+
parts.push('');
|
|
312
|
+
}
|
|
313
|
+
// Preferences
|
|
314
|
+
const prefs = this.getByCategory('preference', 5);
|
|
315
|
+
if (prefs.length > 0) {
|
|
316
|
+
parts.push('## Preferences');
|
|
317
|
+
for (const m of prefs)
|
|
318
|
+
parts.push(`- ${m.key ?? m.content.slice(0, 100)}`);
|
|
319
|
+
parts.push('');
|
|
320
|
+
}
|
|
321
|
+
// Recent context
|
|
322
|
+
const recent = this.getRecentContext(Math.max(5, limit - decisions.length - prefs.length));
|
|
323
|
+
if (recent.length > 0) {
|
|
324
|
+
parts.push('## Recent Context');
|
|
325
|
+
for (const m of recent) {
|
|
326
|
+
const tag = m.tags.length > 0 ? ` [${m.tags.join(', ')}]` : '';
|
|
327
|
+
parts.push(`- [${m.category}] ${m.content.slice(0, 150)}${tag}`);
|
|
328
|
+
}
|
|
329
|
+
parts.push('');
|
|
330
|
+
}
|
|
331
|
+
// Goals
|
|
332
|
+
const goals = this.getByCategory('goal', 3);
|
|
333
|
+
if (goals.length > 0) {
|
|
334
|
+
parts.push('## Active Goals');
|
|
335
|
+
for (const m of goals)
|
|
336
|
+
parts.push(`- ${m.content.slice(0, 100)}`);
|
|
337
|
+
parts.push('');
|
|
338
|
+
}
|
|
339
|
+
// Lessons
|
|
340
|
+
const lessons = this.getByCategory('lesson', 5);
|
|
341
|
+
if (lessons.length > 0) {
|
|
342
|
+
parts.push('## Lessons Learned');
|
|
343
|
+
for (const m of lessons)
|
|
344
|
+
parts.push(`- ${m.content.slice(0, 100)}`);
|
|
345
|
+
}
|
|
346
|
+
return parts.join('\n');
|
|
347
|
+
}
|
|
348
|
+
// ── Sessions ──────────────────────────────────────────
|
|
349
|
+
/** Start a new conversation session. */
|
|
350
|
+
startSession(sessionId, goals = [], metadata = {}) {
|
|
351
|
+
this.stmtSessionInsert.run(sessionId, JSON.stringify(goals), JSON.stringify(metadata));
|
|
352
|
+
this.log.info(`[conversation-memory] Session started: ${sessionId}`);
|
|
353
|
+
}
|
|
354
|
+
/** End a conversation session with a summary. */
|
|
355
|
+
endSession(sessionId, summary) {
|
|
356
|
+
this.stmtSessionEnd.run(summary, sessionId);
|
|
357
|
+
// Store summary as a high-importance memory
|
|
358
|
+
this.remember(`Session ${sessionId}: ${summary}`, {
|
|
359
|
+
category: 'context',
|
|
360
|
+
key: `session_summary:${sessionId}`,
|
|
361
|
+
importance: 7,
|
|
362
|
+
source: 'inferred',
|
|
363
|
+
tags: ['session', 'summary'],
|
|
364
|
+
sessionId,
|
|
365
|
+
});
|
|
366
|
+
this.log.info(`[conversation-memory] Session ended: ${sessionId}`);
|
|
367
|
+
}
|
|
368
|
+
/** Get session info. */
|
|
369
|
+
getSession(sessionId) {
|
|
370
|
+
const row = this.stmtSessionGet.get(sessionId);
|
|
371
|
+
if (!row)
|
|
372
|
+
return null;
|
|
373
|
+
const memCount = this.stmtSessionCountMemories.get(sessionId).count;
|
|
374
|
+
return {
|
|
375
|
+
sessionId: row.session_id,
|
|
376
|
+
startedAt: row.started_at,
|
|
377
|
+
endedAt: row.ended_at,
|
|
378
|
+
summary: row.summary,
|
|
379
|
+
goals: JSON.parse(row.goals || '[]'),
|
|
380
|
+
memoriesCreated: memCount,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
// ── Memory Management ─────────────────────────────────
|
|
384
|
+
/** Deactivate a memory (soft delete). */
|
|
385
|
+
forget(id) {
|
|
386
|
+
this.stmtDeactivate.run(id);
|
|
387
|
+
if (this.rag) {
|
|
388
|
+
this.rag.remove(RAG_COLLECTION, id);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/** Update an existing memory's content. */
|
|
392
|
+
update(id, content, importance) {
|
|
393
|
+
const existing = this.stmtGetById.get(id);
|
|
394
|
+
if (!existing)
|
|
395
|
+
return;
|
|
396
|
+
this.stmtUpdate.run(content, importance ?? existing.importance, existing.tags, id);
|
|
397
|
+
if (this.rag) {
|
|
398
|
+
this.rag.index(RAG_COLLECTION, id, content, {
|
|
399
|
+
category: existing.category,
|
|
400
|
+
key: existing.key,
|
|
401
|
+
}).catch(() => { });
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/** Cleanup: decay old unused memories, prune excess. */
|
|
405
|
+
maintenance() {
|
|
406
|
+
let decayed = 0;
|
|
407
|
+
let pruned = 0;
|
|
408
|
+
// Decay: reduce importance of memories not accessed in X days
|
|
409
|
+
if (this.config.decayDays > 0) {
|
|
410
|
+
const result = this.db.prepare(`
|
|
411
|
+
UPDATE conversation_memories
|
|
412
|
+
SET importance = MAX(1, importance - 1), updated_at = datetime('now')
|
|
413
|
+
WHERE active = 1
|
|
414
|
+
AND importance > 1
|
|
415
|
+
AND access_count = 0
|
|
416
|
+
AND created_at < datetime('now', '-' || ? || ' days')
|
|
417
|
+
`).run(this.config.decayDays);
|
|
418
|
+
decayed = result.changes;
|
|
419
|
+
}
|
|
420
|
+
// Prune: remove excess low-importance memories
|
|
421
|
+
const total = this.stmtCountTotal.get().count;
|
|
422
|
+
if (total > this.config.maxMemories) {
|
|
423
|
+
const excess = total - this.config.maxMemories;
|
|
424
|
+
this.db.prepare(`
|
|
425
|
+
DELETE FROM conversation_memories WHERE id IN (
|
|
426
|
+
SELECT id FROM conversation_memories
|
|
427
|
+
WHERE active = 0 OR importance <= 2
|
|
428
|
+
ORDER BY importance ASC, access_count ASC, created_at ASC
|
|
429
|
+
LIMIT ?
|
|
430
|
+
)
|
|
431
|
+
`).run(excess);
|
|
432
|
+
pruned = excess;
|
|
433
|
+
}
|
|
434
|
+
if (decayed > 0 || pruned > 0) {
|
|
435
|
+
this.log.info(`[conversation-memory] Maintenance: ${decayed} decayed, ${pruned} pruned`);
|
|
436
|
+
}
|
|
437
|
+
return { decayed, pruned };
|
|
438
|
+
}
|
|
439
|
+
// ── Status ────────────────────────────────────────────
|
|
440
|
+
getStatus() {
|
|
441
|
+
const total = this.stmtCountTotal.get().count;
|
|
442
|
+
const active = this.stmtCountActive.get().count;
|
|
443
|
+
const sessions = this.stmtCountSessions.get().count;
|
|
444
|
+
const catRows = this.stmtCountByCategory.all();
|
|
445
|
+
const byCategory = {};
|
|
446
|
+
for (const row of catRows)
|
|
447
|
+
byCategory[row.category] = row.count;
|
|
448
|
+
const recent = this.getRecentContext(5);
|
|
449
|
+
return { totalMemories: total, activeMemories: active, totalSessions: sessions, byCategory, recentMemories: recent };
|
|
450
|
+
}
|
|
451
|
+
// ── Helpers ───────────────────────────────────────────
|
|
452
|
+
toMemory(row) {
|
|
453
|
+
return {
|
|
454
|
+
id: row.id,
|
|
455
|
+
sessionId: row.session_id,
|
|
456
|
+
category: row.category,
|
|
457
|
+
content: row.content,
|
|
458
|
+
key: row.key,
|
|
459
|
+
importance: row.importance,
|
|
460
|
+
source: row.source,
|
|
461
|
+
tags: JSON.parse(row.tags || '[]'),
|
|
462
|
+
accessCount: row.access_count,
|
|
463
|
+
lastAccessedAt: row.last_accessed_at,
|
|
464
|
+
createdAt: row.created_at,
|
|
465
|
+
updatedAt: row.updated_at,
|
|
466
|
+
active: row.active === 1,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=conversation-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-memory.js","sourceRoot":"","sources":["../../src/memory/conversation-memory.ts"],"names":[],"mappings":"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"}
|