memory-lucia 2.0.1 → 2.0.2
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/CLAWHUB-FIXES.md +127 -0
- package/README.md +1 -1
- package/SKILL.md +1 -1
- package/database/schema.sql +152 -0
- package/migrations/v1-to-v2.js +213 -0
- package/package.json +1 -1
- package/references/API.md +364 -0
- package/GITHUB-SETUP.md +0 -81
- package/NPM-PUBLISH-GUIDE.md +0 -169
- package/PUBLISH-STEPS.md +0 -102
- package/publish-with-otp.bat +0 -13
- package/publish.bat +0 -17
- package/publish.sh +0 -20
- package/push-final.bat +0 -28
- package/push-gh-cli.bat +0 -21
- package/push-manual.bat +0 -24
- package/push-to-github.bat +0 -19
- package/push-with-gh.bat +0 -26
package/CLAWHUB-FIXES.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# ClawHub Audit Fixes
|
|
2
|
+
|
|
3
|
+
This document summarizes the fixes applied to address ClawHub security audit feedback.
|
|
4
|
+
|
|
5
|
+
## Issues Fixed
|
|
6
|
+
|
|
7
|
+
### ✅ 1. Missing Files
|
|
8
|
+
|
|
9
|
+
| File | Status | Description |
|
|
10
|
+
|------|--------|-------------|
|
|
11
|
+
| `database/schema.sql` | ✅ Created | Complete database schema with tables, indexes, and views |
|
|
12
|
+
| `migrations/v1-to-v2.js` | ✅ Created | Migration script from V1 to V2 database |
|
|
13
|
+
| `references/API.md` | ✅ Created | Complete API documentation |
|
|
14
|
+
|
|
15
|
+
### ✅ 2. Version Consistency
|
|
16
|
+
|
|
17
|
+
| Location | Before | After |
|
|
18
|
+
|----------|--------|-------|
|
|
19
|
+
| SKILL.md | 2.0.0 | 2.0.1 |
|
|
20
|
+
| README.md | 2.0.0 | 2.0.1 |
|
|
21
|
+
| package.json | 2.0.1 | 2.0.1 (already correct) |
|
|
22
|
+
|
|
23
|
+
### ✅ 3. Removed Development Files
|
|
24
|
+
|
|
25
|
+
Removed from repository:
|
|
26
|
+
- `publish.bat`
|
|
27
|
+
- `publish-with-otp.bat`
|
|
28
|
+
- `push-final.bat`
|
|
29
|
+
- `push-gh-cli.bat`
|
|
30
|
+
- `push-manual.bat`
|
|
31
|
+
- `push-to-github.bat`
|
|
32
|
+
- `push-with-gh.bat`
|
|
33
|
+
|
|
34
|
+
Updated `.gitignore` to exclude:
|
|
35
|
+
- `*.bat` files
|
|
36
|
+
- Publish documentation files
|
|
37
|
+
- GitHub workflows (if not ready)
|
|
38
|
+
|
|
39
|
+
### ✅ 4. Source Verification
|
|
40
|
+
|
|
41
|
+
All source URLs are valid:
|
|
42
|
+
- **npm**: https://www.npmjs.com/package/memory-lucia
|
|
43
|
+
- **GitHub**: https://github.com/wen521/memory-lucia-
|
|
44
|
+
- **Issues**: https://github.com/wen521/memory-lucia-/issues
|
|
45
|
+
|
|
46
|
+
## Security Considerations Addressed
|
|
47
|
+
|
|
48
|
+
### Database Safety
|
|
49
|
+
- ✅ Schema file (`schema.sql`) now included with proper table definitions
|
|
50
|
+
- ✅ All views (`v_pending_decisions`, `v_skill_summary`, `v_weekly_learning_report`, `v_high_priority`) defined in schema
|
|
51
|
+
- ✅ Database initialization script (`database/init.js`) properly references schema.sql
|
|
52
|
+
- ✅ Migration script (`migrations/v1-to-v2.js`) included for data portability
|
|
53
|
+
|
|
54
|
+
### File System Operations
|
|
55
|
+
- ✅ Database path is configurable (default: `./memory-v2.db`)
|
|
56
|
+
- ✅ Backup directory created relative to working directory
|
|
57
|
+
- ✅ No system files or critical directories accessed
|
|
58
|
+
|
|
59
|
+
### Backup Management
|
|
60
|
+
- ✅ Backup retention configurable via `keepCount` parameter
|
|
61
|
+
- ✅ Automatic cleanup only removes old backups, never active database
|
|
62
|
+
- ✅ Rollback requires explicit backup path selection
|
|
63
|
+
|
|
64
|
+
## File Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
memory-v2-skill/
|
|
68
|
+
├── SKILL.md # Skill description (version 2.0.1)
|
|
69
|
+
├── README.md # Documentation (version 2.0.1)
|
|
70
|
+
├── package.json # Package metadata
|
|
71
|
+
├── LICENSE # MIT License
|
|
72
|
+
├── .gitignore # Excludes dev files
|
|
73
|
+
├── api/
|
|
74
|
+
│ └── index.js # Main API module
|
|
75
|
+
├── database/
|
|
76
|
+
│ ├── init.js # Database initialization
|
|
77
|
+
│ └── schema.sql # ✅ Database schema (NEW)
|
|
78
|
+
├── modules/
|
|
79
|
+
│ ├── priority.js # Priority analysis
|
|
80
|
+
│ ├── learning.js # Learning tracking
|
|
81
|
+
│ ├── decision.js # Decision recording
|
|
82
|
+
│ ├── evolution.js # Skill evolution
|
|
83
|
+
│ └── version.js # Version management
|
|
84
|
+
├── migrations/
|
|
85
|
+
│ └── v1-to-v2.js # ✅ Migration script (NEW)
|
|
86
|
+
├── references/
|
|
87
|
+
│ └── API.md # ✅ API documentation (NEW)
|
|
88
|
+
└── scripts/
|
|
89
|
+
└── init-memory.js # Setup script
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Pre-Publish Checklist
|
|
93
|
+
|
|
94
|
+
Before publishing to ClawHub/npm:
|
|
95
|
+
|
|
96
|
+
- [ ] Verify all files listed above are present
|
|
97
|
+
- [ ] Run `npm test` to ensure tests pass
|
|
98
|
+
- [ ] Run `node scripts/init-memory.js` to verify database initialization
|
|
99
|
+
- [ ] Verify no `.bat` files in the package
|
|
100
|
+
- [ ] Verify version is consistent across all files (2.0.1)
|
|
101
|
+
- [ ] Verify GitHub repository is public and accessible
|
|
102
|
+
- [ ] Verify npm package is published and accessible
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Install dependencies
|
|
108
|
+
npm install
|
|
109
|
+
|
|
110
|
+
# Initialize database
|
|
111
|
+
node scripts/init-memory.js
|
|
112
|
+
|
|
113
|
+
# Run tests
|
|
114
|
+
npm test
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Notes for Reviewers
|
|
118
|
+
|
|
119
|
+
1. **Database Views**: All SQL views referenced in the code are defined in `database/schema.sql`
|
|
120
|
+
2. **Migration**: The `migrations/v1-to-v2.js` script handles data migration from V1 format
|
|
121
|
+
3. **API Documentation**: Complete API reference available in `references/API.md`
|
|
122
|
+
4. **No Executables**: All `.bat` files have been removed; only Node.js scripts remain
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
Last updated: 2026-03-25
|
|
127
|
+
Version: 2.0.1
|
package/README.md
CHANGED
package/SKILL.md
CHANGED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
-- Memory V2.0 Database Schema
|
|
2
|
+
-- SQLite database schema for OpenClaw Memory System
|
|
3
|
+
|
|
4
|
+
-- Priority Analysis Table
|
|
5
|
+
CREATE TABLE IF NOT EXISTS memory_priorities (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
msg_id TEXT NOT NULL,
|
|
8
|
+
conv_id TEXT,
|
|
9
|
+
priority_level TEXT CHECK(priority_level IN ('critical', 'high', 'medium', 'low')),
|
|
10
|
+
reasoning TEXT,
|
|
11
|
+
category TEXT,
|
|
12
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Learning Tracking Table
|
|
16
|
+
CREATE TABLE IF NOT EXISTS memory_learning (
|
|
17
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
|
+
msg_id TEXT NOT NULL,
|
|
19
|
+
conv_id TEXT,
|
|
20
|
+
topic TEXT,
|
|
21
|
+
description TEXT,
|
|
22
|
+
status TEXT CHECK(status IN ('active', 'paused', 'completed', 'abandoned')) DEFAULT 'active',
|
|
23
|
+
progress INTEGER DEFAULT 0 CHECK(progress >= 0 AND progress <= 100),
|
|
24
|
+
started_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
25
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
completed_at DATETIME
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- Learning Milestones Table
|
|
30
|
+
CREATE TABLE IF NOT EXISTS memory_learning_milestones (
|
|
31
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
32
|
+
learning_id INTEGER NOT NULL,
|
|
33
|
+
title TEXT NOT NULL,
|
|
34
|
+
description TEXT,
|
|
35
|
+
achieved_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
36
|
+
FOREIGN KEY (learning_id) REFERENCES memory_learning(id) ON DELETE CASCADE
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Decision Records Table
|
|
40
|
+
CREATE TABLE IF NOT EXISTS memory_decisions (
|
|
41
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
42
|
+
msg_id TEXT NOT NULL,
|
|
43
|
+
conv_id TEXT,
|
|
44
|
+
summary TEXT NOT NULL,
|
|
45
|
+
context TEXT,
|
|
46
|
+
expected_outcome TEXT,
|
|
47
|
+
actual_outcome TEXT,
|
|
48
|
+
status TEXT CHECK(status IN ('pending', 'implemented', 'validated', 'rejected')) DEFAULT 'pending',
|
|
49
|
+
review_scheduled_at DATETIME,
|
|
50
|
+
reviewed_at DATETIME,
|
|
51
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
-- Skill Evolution Table
|
|
55
|
+
CREATE TABLE IF NOT EXISTS memory_evolution (
|
|
56
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
57
|
+
skill_name TEXT NOT NULL,
|
|
58
|
+
category TEXT,
|
|
59
|
+
usage_count INTEGER DEFAULT 0,
|
|
60
|
+
success_count INTEGER DEFAULT 0,
|
|
61
|
+
last_used_at DATETIME,
|
|
62
|
+
first_used_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
-- Database Version Tracking
|
|
66
|
+
CREATE TABLE IF NOT EXISTS memory_schema_version (
|
|
67
|
+
version TEXT PRIMARY KEY,
|
|
68
|
+
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
-- Insert initial version
|
|
72
|
+
INSERT OR IGNORE INTO memory_schema_version (version) VALUES ('2.0.0');
|
|
73
|
+
|
|
74
|
+
-- Create indexes for performance
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_priorities_level ON memory_priorities(priority_level);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_priorities_created ON memory_priorities(created_at);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_learning_status ON memory_learning(status);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_learning_topic ON memory_learning(topic);
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_decisions_status ON memory_decisions(status);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_decisions_review ON memory_decisions(review_scheduled_at);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_evolution_skill ON memory_evolution(skill_name);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_evolution_category ON memory_evolution(category);
|
|
83
|
+
|
|
84
|
+
-- Views for common queries
|
|
85
|
+
|
|
86
|
+
-- View: Pending Decisions
|
|
87
|
+
CREATE VIEW IF NOT EXISTS v_pending_decisions AS
|
|
88
|
+
SELECT
|
|
89
|
+
d.*,
|
|
90
|
+
CASE
|
|
91
|
+
WHEN review_scheduled_at < CURRENT_TIMESTAMP THEN 'overdue'
|
|
92
|
+
WHEN review_scheduled_at <= datetime('now', '+7 days') THEN 'due_soon'
|
|
93
|
+
ELSE 'scheduled'
|
|
94
|
+
END as review_status
|
|
95
|
+
FROM memory_decisions d
|
|
96
|
+
WHERE status IN ('pending', 'implemented')
|
|
97
|
+
AND (review_scheduled_at IS NULL OR review_scheduled_at <= datetime('now', '+7 days'))
|
|
98
|
+
ORDER BY review_scheduled_at ASC;
|
|
99
|
+
|
|
100
|
+
-- View: Skill Summary
|
|
101
|
+
CREATE VIEW IF NOT EXISTS v_skill_summary AS
|
|
102
|
+
SELECT
|
|
103
|
+
skill_name,
|
|
104
|
+
category,
|
|
105
|
+
usage_count,
|
|
106
|
+
success_count,
|
|
107
|
+
CASE
|
|
108
|
+
WHEN usage_count > 0 THEN ROUND(100.0 * success_count / usage_count, 2)
|
|
109
|
+
ELSE 0
|
|
110
|
+
END as success_rate,
|
|
111
|
+
last_used_at,
|
|
112
|
+
first_used_at
|
|
113
|
+
FROM memory_evolution
|
|
114
|
+
ORDER BY usage_count DESC;
|
|
115
|
+
|
|
116
|
+
-- View: Weekly Learning Report
|
|
117
|
+
CREATE VIEW IF NOT EXISTS v_weekly_learning_report AS
|
|
118
|
+
SELECT
|
|
119
|
+
topic,
|
|
120
|
+
COUNT(*) as session_count,
|
|
121
|
+
AVG(progress) as avg_progress,
|
|
122
|
+
MAX(updated_at) as last_activity,
|
|
123
|
+
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count
|
|
124
|
+
FROM memory_learning
|
|
125
|
+
WHERE updated_at >= datetime('now', '-7 days')
|
|
126
|
+
GROUP BY topic
|
|
127
|
+
ORDER BY last_activity DESC;
|
|
128
|
+
|
|
129
|
+
-- View: High Priority Items
|
|
130
|
+
CREATE VIEW IF NOT EXISTS v_high_priority AS
|
|
131
|
+
SELECT
|
|
132
|
+
'priority' as type,
|
|
133
|
+
id,
|
|
134
|
+
msg_id,
|
|
135
|
+
priority_level as level,
|
|
136
|
+
category,
|
|
137
|
+
reasoning as details,
|
|
138
|
+
created_at
|
|
139
|
+
FROM memory_priorities
|
|
140
|
+
WHERE priority_level IN ('critical', 'high')
|
|
141
|
+
UNION ALL
|
|
142
|
+
SELECT
|
|
143
|
+
'decision' as type,
|
|
144
|
+
id,
|
|
145
|
+
msg_id,
|
|
146
|
+
status as level,
|
|
147
|
+
'decision' as category,
|
|
148
|
+
summary as details,
|
|
149
|
+
created_at
|
|
150
|
+
FROM memory_decisions
|
|
151
|
+
WHERE status = 'pending' AND review_scheduled_at <= CURRENT_TIMESTAMP
|
|
152
|
+
ORDER BY created_at DESC;
|
|
@@ -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