memory-lucia 2.0.1 → 2.0.3

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,213 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Memory V1 to V2 Migration Script
4
+ * Migrates data from old memory format to V2 schema
5
+ */
6
+
7
+ const sqlite3 = require('sqlite3').verbose();
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ class MemoryMigration {
12
+ constructor(sourceDbPath, targetDbPath = './memory-v2.db') {
13
+ this.sourceDbPath = sourceDbPath;
14
+ this.targetDbPath = targetDbPath;
15
+ this.sourceDb = null;
16
+ this.targetDb = null;
17
+ }
18
+
19
+ async init() {
20
+ // Check if source exists
21
+ if (!fs.existsSync(this.sourceDbPath)) {
22
+ throw new Error(`Source database not found: ${this.sourceDbPath}`);
23
+ }
24
+
25
+ // Open source database
26
+ this.sourceDb = new sqlite3.Database(this.sourceDbPath, sqlite3.OPEN_READONLY);
27
+
28
+ // Open/create target database
29
+ this.targetDb = new sqlite3.Database(this.targetDbPath);
30
+
31
+ console.log('✅ Connected to source and target databases');
32
+ }
33
+
34
+ async runSchema() {
35
+ const schemaPath = path.join(__dirname, '..', 'database', 'schema.sql');
36
+
37
+ if (!fs.existsSync(schemaPath)) {
38
+ throw new Error(`Schema file not found: ${schemaPath}`);
39
+ }
40
+
41
+ const schema = fs.readFileSync(schemaPath, 'utf8');
42
+ const statements = schema
43
+ .split(';')
44
+ .map(s => s.trim())
45
+ .filter(s => s.length > 0);
46
+
47
+ for (const statement of statements) {
48
+ await this.runTarget(statement);
49
+ }
50
+
51
+ console.log('✅ Target database schema initialized');
52
+ }
53
+
54
+ async migratePriorities() {
55
+ console.log('🔄 Migrating priorities...');
56
+
57
+ try {
58
+ const rows = await this.allSource(
59
+ "SELECT * FROM memory_priorities WHERE created_at >= datetime('now', '-90 days')"
60
+ );
61
+
62
+ for (const row of rows) {
63
+ await this.runTarget(
64
+ `INSERT INTO memory_priorities
65
+ (msg_id, conv_id, priority_level, reasoning, category, created_at)
66
+ VALUES (?, ?, ?, ?, ?, ?)`,
67
+ [row.msg_id, row.conv_id, row.priority_level, row.reasoning, row.category, row.created_at]
68
+ );
69
+ }
70
+
71
+ console.log(`✅ Migrated ${rows.length} priority records`);
72
+ } catch (err) {
73
+ console.log('ℹ️ No priorities to migrate or table does not exist');
74
+ }
75
+ }
76
+
77
+ async migrateLearning() {
78
+ console.log('🔄 Migrating learning records...');
79
+
80
+ try {
81
+ const rows = await this.allSource(
82
+ "SELECT * FROM memory_learning WHERE status != 'abandoned'"
83
+ );
84
+
85
+ for (const row of rows) {
86
+ await this.runTarget(
87
+ `INSERT INTO memory_learning
88
+ (msg_id, conv_id, topic, description, status, progress, started_at, updated_at, completed_at)
89
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
90
+ [row.msg_id, row.conv_id, row.topic, row.description, row.status,
91
+ row.progress, row.started_at, row.updated_at, row.completed_at]
92
+ );
93
+ }
94
+
95
+ console.log(`✅ Migrated ${rows.length} learning records`);
96
+ } catch (err) {
97
+ console.log('ℹ️ No learning records to migrate or table does not exist');
98
+ }
99
+ }
100
+
101
+ async migrateDecisions() {
102
+ console.log('🔄 Migrating decisions...');
103
+
104
+ try {
105
+ const rows = await this.allSource(
106
+ "SELECT * FROM memory_decisions WHERE status IN ('pending', 'implemented')"
107
+ );
108
+
109
+ for (const row of rows) {
110
+ await this.runTarget(
111
+ `INSERT INTO memory_decisions
112
+ (msg_id, conv_id, summary, context, expected_outcome, actual_outcome,
113
+ status, review_scheduled_at, reviewed_at, created_at)
114
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
115
+ [row.msg_id, row.conv_id, row.summary, row.context, row.expected_outcome,
116
+ row.actual_outcome, row.status, row.review_scheduled_at, row.reviewed_at, row.created_at]
117
+ );
118
+ }
119
+
120
+ console.log(`✅ Migrated ${rows.length} decision records`);
121
+ } catch (err) {
122
+ console.log('ℹ️ No decisions to migrate or table does not exist');
123
+ }
124
+ }
125
+
126
+ async migrateEvolution() {
127
+ console.log('🔄 Migrating skill evolution...');
128
+
129
+ try {
130
+ const rows = await this.allSource(
131
+ "SELECT * FROM memory_evolution WHERE usage_count > 0"
132
+ );
133
+
134
+ for (const row of rows) {
135
+ await this.runTarget(
136
+ `INSERT INTO memory_evolution
137
+ (skill_name, category, usage_count, success_count, last_used_at, first_used_at)
138
+ VALUES (?, ?, ?, ?, ?, ?)`,
139
+ [row.skill_name, row.category, row.usage_count, row.success_count,
140
+ row.last_used_at, row.first_used_at]
141
+ );
142
+ }
143
+
144
+ console.log(`✅ Migrated ${rows.length} skill evolution records`);
145
+ } catch (err) {
146
+ console.log('ℹ️ No evolution records to migrate or table does not exist');
147
+ }
148
+ }
149
+
150
+ async runTarget(sql, params = []) {
151
+ return new Promise((resolve, reject) => {
152
+ this.targetDb.run(sql, params, function(err) {
153
+ if (err) reject(err);
154
+ else resolve({ id: this.lastID, changes: this.changes });
155
+ });
156
+ });
157
+ }
158
+
159
+ async allSource(sql, params = []) {
160
+ return new Promise((resolve, reject) => {
161
+ this.sourceDb.all(sql, params, (err, rows) => {
162
+ if (err) reject(err);
163
+ else resolve(rows);
164
+ });
165
+ });
166
+ }
167
+
168
+ async close() {
169
+ if (this.sourceDb) {
170
+ await new Promise((resolve) => this.sourceDb.close(resolve));
171
+ }
172
+ if (this.targetDb) {
173
+ await new Promise((resolve) => this.targetDb.close(resolve));
174
+ }
175
+ console.log('✅ Database connections closed');
176
+ }
177
+
178
+ async migrate() {
179
+ try {
180
+ await this.init();
181
+ await this.runSchema();
182
+ await this.migratePriorities();
183
+ await this.migrateLearning();
184
+ await this.migrateDecisions();
185
+ await this.migrateEvolution();
186
+
187
+ console.log('\n🎉 Migration completed successfully!');
188
+ console.log(`📁 New database: ${path.resolve(this.targetDbPath)}`);
189
+ } catch (err) {
190
+ console.error('\n❌ Migration failed:', err.message);
191
+ process.exit(1);
192
+ } finally {
193
+ await this.close();
194
+ }
195
+ }
196
+ }
197
+
198
+ // CLI usage
199
+ if (require.main === module) {
200
+ const sourceDb = process.argv[2];
201
+ const targetDb = process.argv[3] || './memory-v2.db';
202
+
203
+ if (!sourceDb) {
204
+ console.log('Usage: node migrations/v1-to-v2.js <source-v1.db> [target-v2.db]');
205
+ console.log('Example: node migrations/v1-to-v2.js ./memory-v1.db ./memory-v2.db');
206
+ process.exit(1);
207
+ }
208
+
209
+ const migration = new MemoryMigration(sourceDb, targetDb);
210
+ migration.migrate();
211
+ }
212
+
213
+ module.exports = MemoryMigration;
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
- {
2
- "name": "memory-lucia",
3
- "version": "2.0.1",
4
- "description": "Advanced memory system for OpenClaw agents with priority analysis, learning tracking, decision recording, and skill evolution",
5
- "main": "api/index.js",
6
- "scripts": {
7
- "start": "node api/index.js",
8
- "init": "node scripts/init-memory.js",
9
- "test": "node tests/test.js",
10
- "backup": "node scripts/backup.js"
11
- },
12
- "keywords": [
13
- "openclaw",
14
- "skill",
15
- "memory",
16
- "learning",
17
- "decision",
18
- "priority",
19
- "evolution",
20
- "sqlite"
21
- ],
22
- "author": "Chief of Staff",
23
- "license": "MIT",
24
- "dependencies": {
25
- "sqlite3": "^5.1.6"
26
- },
27
- "repository": {
28
- "type": "git",
29
- "url": "https://github.com/wen521/memory-lucia-.git"
30
- },
31
- "bugs": {
32
- "url": "https://github.com/wen521/memory-lucia-/issues"
33
- },
34
- "homepage": "https://github.com/wen521/memory-lucia-#readme"
35
- }
1
+ {
2
+ "name": "memory-lucia",
3
+ "version": "2.0.3",
4
+ "description": "Advanced memory system for OpenClaw agents with priority analysis, learning tracking, decision recording, and skill evolution",
5
+ "main": "api/index.js",
6
+ "scripts": {
7
+ "start": "node api/index.js",
8
+ "init": "node scripts/init-memory.js",
9
+ "test": "node tests/test.js",
10
+ "backup": "node scripts/backup.js"
11
+ },
12
+ "keywords": [
13
+ "openclaw",
14
+ "skill",
15
+ "memory",
16
+ "learning",
17
+ "decision",
18
+ "priority",
19
+ "evolution",
20
+ "sqlite"
21
+ ],
22
+ "author": "Chief of Staff",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "sqlite3": "^5.1.6"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/wen521/memory-lucia-.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/wen521/memory-lucia-/issues"
33
+ },
34
+ "homepage": "https://github.com/wen521/memory-lucia-#readme"
35
+ }
@@ -0,0 +1,364 @@
1
+ # Memory V2 API Reference
2
+
3
+ Complete API documentation for the Memory V2 system.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Initialization](#initialization)
8
+ - [Priority Module](#priority-module)
9
+ - [Learning Module](#learning-module)
10
+ - [Decision Module](#decision-module)
11
+ - [Evolution Module](#evolution-module)
12
+ - [Dashboard](#dashboard)
13
+ - [Version Management](#version-management)
14
+
15
+ ---
16
+
17
+ ## Initialization
18
+
19
+ ```javascript
20
+ const MemoryAPI = require('./api');
21
+
22
+ // Create instance
23
+ const api = new MemoryAPI('./memory-v2.db');
24
+
25
+ // Initialize database
26
+ await api.init();
27
+
28
+ // Close when done
29
+ await api.close();
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Priority Module
35
+
36
+ ### analyzePriority(message)
37
+ Analyze a message and return priority assessment.
38
+
39
+ **Parameters:**
40
+ - `message` (string): The message to analyze
41
+
42
+ **Returns:**
43
+ ```javascript
44
+ {
45
+ priority_level: 'critical' | 'high' | 'medium' | 'low',
46
+ reasoning: string,
47
+ category: string
48
+ }
49
+ ```
50
+
51
+ ### storePriority(msgId, convId, analysis)
52
+ Store priority analysis in database.
53
+
54
+ **Parameters:**
55
+ - `msgId` (string): Message ID
56
+ - `convId` (string): Conversation ID
57
+ - `analysis` (object): Result from analyzePriority
58
+
59
+ **Returns:** `Promise<{id: number}>`
60
+
61
+ ### getHighPriority(limit = 10)
62
+ Get recent high/critical priority items.
63
+
64
+ **Parameters:**
65
+ - `limit` (number): Maximum results
66
+
67
+ **Returns:** `Promise<Array>`
68
+
69
+ ### getPriorityStats()
70
+ Get priority distribution statistics.
71
+
72
+ **Returns:**
73
+ ```javascript
74
+ {
75
+ critical: number,
76
+ high: number,
77
+ medium: number,
78
+ low: number,
79
+ total: number
80
+ }
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Learning Module
86
+
87
+ ### startLearning(msgId, convId, message)
88
+ Start tracking a new learning topic.
89
+
90
+ **Parameters:**
91
+ - `msgId` (string): Message ID
92
+ - `convId` (string): Conversation ID
93
+ - `message` (string): Message describing the learning topic
94
+
95
+ **Returns:**
96
+ ```javascript
97
+ {
98
+ id: number,
99
+ topic: string,
100
+ status: 'active',
101
+ progress: 0
102
+ }
103
+ ```
104
+
105
+ ### updateLearningProgress(learningId, updates)
106
+ Update learning progress.
107
+
108
+ **Parameters:**
109
+ - `learningId` (number): Learning record ID
110
+ - `updates` (object):
111
+ - `progress` (number): 0-100
112
+ - `status` (string): 'active' | 'paused' | 'completed' | 'abandoned'
113
+
114
+ ### addMilestone(learningId, milestone)
115
+ Add a milestone to a learning record.
116
+
117
+ **Parameters:**
118
+ - `learningId` (number): Learning record ID
119
+ - `milestone` (object):
120
+ - `title` (string): Milestone title
121
+ - `description` (string): Optional description
122
+
123
+ ### getActiveLearning(limit = 5)
124
+ Get currently active learning topics.
125
+
126
+ **Parameters:**
127
+ - `limit` (number): Maximum results
128
+
129
+ **Returns:** `Promise<Array>`
130
+
131
+ ### getLearningStats()
132
+ Get learning statistics.
133
+
134
+ **Returns:**
135
+ ```javascript
136
+ {
137
+ active: number,
138
+ completed: number,
139
+ total: number,
140
+ avg_progress: number
141
+ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Decision Module
147
+
148
+ ### recordDecision(msgId, convId, decisionData)
149
+ Record a new decision.
150
+
151
+ **Parameters:**
152
+ - `msgId` (string): Message ID
153
+ - `convId` (string): Conversation ID
154
+ - `decisionData` (object):
155
+ - `summary` (string): Decision summary (required)
156
+ - `context` (string): Decision context
157
+ - `expectedOutcome` (string): Expected result
158
+ - `reviewDate` (string): ISO date for review
159
+
160
+ **Returns:** `Promise<{id: number}>`
161
+
162
+ ### updateDecisionOutcome(decisionId, outcome)
163
+ Update the actual outcome of a decision.
164
+
165
+ **Parameters:**
166
+ - `decisionId` (number): Decision ID
167
+ - `outcome` (object):
168
+ - `actualOutcome` (string): What actually happened
169
+ - `status` (string): 'implemented' | 'validated' | 'rejected'
170
+
171
+ ### getPendingDecisions()
172
+ Get decisions pending review or implementation.
173
+
174
+ **Returns:** `Promise<Array>`
175
+
176
+ ### scheduleReview(decisionId, reviewDate)
177
+ Schedule a review for a decision.
178
+
179
+ **Parameters:**
180
+ - `decisionId` (number): Decision ID
181
+ - `reviewDate` (string): ISO date string
182
+
183
+ ---
184
+
185
+ ## Evolution Module
186
+
187
+ ### recordSkillUsage(skillName, category, result)
188
+ Record skill usage.
189
+
190
+ **Parameters:**
191
+ - `skillName` (string): Name of the skill
192
+ - `category` (string): Skill category
193
+ - `result` (string): 'success' | 'failure'
194
+
195
+ ### getTopSkills(limit = 10)
196
+ Get most frequently used skills.
197
+
198
+ **Parameters:**
199
+ - `limit` (number): Maximum results
200
+
201
+ **Returns:** `Promise<Array>`
202
+
203
+ ### getSkillStats(skillName)
204
+ Get statistics for a specific skill.
205
+
206
+ **Parameters:**
207
+ - `skillName` (string): Skill name
208
+
209
+ **Returns:**
210
+ ```javascript
211
+ {
212
+ skill_name: string,
213
+ category: string,
214
+ usage_count: number,
215
+ success_count: number,
216
+ success_rate: number,
217
+ last_used_at: string
218
+ }
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Dashboard
224
+
225
+ ### getDashboard()
226
+ Get unified dashboard of all memory data.
227
+
228
+ **Returns:**
229
+ ```javascript
230
+ {
231
+ summary: {
232
+ total_priorities: number,
233
+ total_learning: number,
234
+ total_decisions: number,
235
+ total_skills: number
236
+ },
237
+ recent: {
238
+ priorities: Array,
239
+ learning: Array,
240
+ decisions: Array
241
+ },
242
+ stats: {
243
+ priorities: Object,
244
+ learning: Object,
245
+ skills: Array
246
+ }
247
+ }
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Version Management
253
+
254
+ ### createBackup(label)
255
+ Create a database backup.
256
+
257
+ **Parameters:**
258
+ - `label` (string): Optional label for the backup
259
+
260
+ **Returns:** `Promise<{backupPath: string}>`
261
+
262
+ ### listBackups()
263
+ List all available backups.
264
+
265
+ **Returns:** `Promise<Array>`
266
+
267
+ ### restoreBackup(backupPath)
268
+ Restore from a backup.
269
+
270
+ **Parameters:**
271
+ - `backupPath` (string): Path to backup file
272
+
273
+ **Returns:** `Promise<boolean>`
274
+
275
+ ### cleanupBackups(keepCount = 10)
276
+ Clean up old backups, keeping only the specified number.
277
+
278
+ **Parameters:**
279
+ - `keepCount` (number): Number of backups to keep
280
+
281
+ ---
282
+
283
+ ## Database Views
284
+
285
+ The following SQL views are available for direct queries:
286
+
287
+ ### v_pending_decisions
288
+ Decisions that need attention (pending, overdue, or due soon).
289
+
290
+ ### v_skill_summary
291
+ Skill usage statistics with success rates.
292
+
293
+ ### v_weekly_learning_report
294
+ Learning activity summary for the past week.
295
+
296
+ ### v_high_priority
297
+ Combined view of high priority items and pending decisions.
298
+
299
+ ---
300
+
301
+ ## Error Handling
302
+
303
+ All API methods return Promises and may throw:
304
+
305
+ ```javascript
306
+ try {
307
+ const result = await api.storePriority(msgId, convId, analysis);
308
+ } catch (err) {
309
+ console.error('API Error:', err.message);
310
+ }
311
+ ```
312
+
313
+ Common errors:
314
+ - Database not initialized
315
+ - Invalid parameters
316
+ - Constraint violations
317
+ - File system errors (backups)
318
+
319
+ ---
320
+
321
+ ## Examples
322
+
323
+ ### Complete Workflow
324
+
325
+ ```javascript
326
+ const MemoryAPI = require('./api');
327
+ const api = new MemoryAPI('./memory-v2.db');
328
+
329
+ async function example() {
330
+ await api.init();
331
+
332
+ // Record a decision
333
+ const decision = await api.recordDecision('msg-123', 'conv-456', {
334
+ summary: 'Use SQLite for local storage',
335
+ context: 'Need embedded database for skill',
336
+ expectedOutcome: 'Simpler deployment'
337
+ });
338
+
339
+ // Start learning
340
+ const learning = await api.startLearning('msg-124', 'conv-456',
341
+ 'Learning SQLite advanced features'
342
+ );
343
+
344
+ // Update progress
345
+ await api.updateLearningProgress(learning.id, { progress: 50 });
346
+
347
+ // Record skill usage
348
+ await api.recordSkillUsage('memory-v2', 'storage', 'success');
349
+
350
+ // Get dashboard
351
+ const dashboard = await api.getDashboard();
352
+ console.log(dashboard);
353
+
354
+ await api.close();
355
+ }
356
+
357
+ example();
358
+ ```
359
+
360
+ ---
361
+
362
+ ## License
363
+
364
+ MIT