@timmeck/brain-core 2.36.80 → 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.
@@ -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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"}
@@ -0,0 +1,104 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { ThoughtStream } from '../consciousness/thought-stream.js';
3
+ import type { ResearchJournal } from './journal.js';
4
+ export interface AutonomousResearchConfig {
5
+ /** Max autonomous missions per day. Default: 5 */
6
+ maxMissionsPerDay?: number;
7
+ /** Cooldown between research cycles in ms. Default: 30min */
8
+ cycleCooldownMs?: number;
9
+ /** Minimum gap score to trigger research. Default: 0.5 */
10
+ minGapScore?: number;
11
+ /** Minimum desire priority to trigger research. Default: 5 */
12
+ minDesirePriority?: number;
13
+ /** Mission depth for autonomous missions. Default: 'standard' */
14
+ missionDepth?: 'quick' | 'standard' | 'deep';
15
+ /** Enable/disable the loop. Default: false (opt-in) */
16
+ enabled?: boolean;
17
+ }
18
+ export interface AutonomousResearchStatus {
19
+ enabled: boolean;
20
+ running: boolean;
21
+ cyclesCompleted: number;
22
+ missionsLaunchedToday: number;
23
+ maxMissionsPerDay: number;
24
+ lastCycleAt: number | null;
25
+ nextCycleAt: number | null;
26
+ lastTopic: string | null;
27
+ recentTopics: string[];
28
+ }
29
+ export interface AutonomousResearchResult {
30
+ action: 'mission_launched' | 'skipped_no_target' | 'skipped_budget' | 'skipped_cooldown' | 'skipped_disabled';
31
+ topic?: string;
32
+ missionId?: number;
33
+ reason?: string;
34
+ }
35
+ export interface AutonomousResearchSources {
36
+ getCuriosityGaps?: (limit: number) => Array<{
37
+ topic: string;
38
+ gapScore: number;
39
+ gapType: string;
40
+ questions: string[];
41
+ }>;
42
+ getDesires?: () => Array<{
43
+ key: string;
44
+ suggestion: string;
45
+ priority: number;
46
+ }>;
47
+ createMission?: (topic: string, depth: 'quick' | 'standard' | 'deep') => {
48
+ id?: number;
49
+ topic: string;
50
+ status: string;
51
+ };
52
+ getMissionStatus?: () => {
53
+ activeMissions: number;
54
+ completedMissions: number;
55
+ totalMissions: number;
56
+ };
57
+ observeHypothesis?: (obs: {
58
+ source: string;
59
+ type: string;
60
+ value: number;
61
+ timestamp: number;
62
+ }) => void;
63
+ checkBudget?: (engineId: string) => {
64
+ allowed: boolean;
65
+ reason?: string;
66
+ };
67
+ }
68
+ export declare function runAutonomousResearchMigration(db: Database.Database): void;
69
+ export declare class AutonomousResearchLoop {
70
+ private readonly db;
71
+ private readonly config;
72
+ private readonly log;
73
+ private ts;
74
+ private journal;
75
+ private sources;
76
+ private timer;
77
+ private cyclesCompleted;
78
+ private lastCycleAt;
79
+ private lastTopic;
80
+ private recentTopics;
81
+ private readonly stmtLogAction;
82
+ private readonly stmtCountToday;
83
+ private readonly stmtRecentTopics;
84
+ constructor(db: Database.Database, config?: AutonomousResearchConfig);
85
+ setThoughtStream(stream: ThoughtStream): void;
86
+ setJournal(journal: ResearchJournal): void;
87
+ setSources(sources: AutonomousResearchSources): void;
88
+ /** Update config at runtime. */
89
+ updateConfig(partial: Partial<AutonomousResearchConfig>): void;
90
+ /** Start the autonomous research timer. */
91
+ start(): void;
92
+ /** Stop the timer. */
93
+ stop(): void;
94
+ /** Run one autonomous research cycle. Can be called manually or by timer. */
95
+ cycle(): Promise<AutonomousResearchResult>;
96
+ /** Select the best research target from curiosity gaps and desires. */
97
+ private selectTarget;
98
+ /** Extract a researchable topic from a desire suggestion string. */
99
+ private extractTopicFromDesire;
100
+ /** Simple topic overlap check (Jaccard on words). */
101
+ private topicOverlap;
102
+ getStatus(): AutonomousResearchStatus;
103
+ getConfig(): Readonly<Required<AutonomousResearchConfig>>;
104
+ }