@trlc/super-memory 1.3.6 ā 1.3.7
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/index.js +78 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import { homedir } from 'os';
|
|
|
22
22
|
import { join } from 'path';
|
|
23
23
|
import readline from 'readline';
|
|
24
24
|
const CONVEX_URL = 'https://clear-lemming-473.convex.cloud';
|
|
25
|
-
const VERSION = '1.3.
|
|
25
|
+
const VERSION = '1.3.7';
|
|
26
26
|
// Paths
|
|
27
27
|
const getBaseDir = () => join(homedir(), '.openclaw', 'workspace');
|
|
28
28
|
const getMemoryDir = () => join(getBaseDir(), 'memory');
|
|
@@ -493,7 +493,50 @@ async function cmdSync(args) {
|
|
|
493
493
|
}
|
|
494
494
|
console.log('š Syncing with cloud...\n');
|
|
495
495
|
try {
|
|
496
|
-
//
|
|
496
|
+
// STEP 1: Push local memories to cloud
|
|
497
|
+
console.log('š¤ Checking for local memories to upload...');
|
|
498
|
+
const localMemories = getLocalMemoriesForSync();
|
|
499
|
+
let uploadedCount = 0;
|
|
500
|
+
for (const mem of localMemories) {
|
|
501
|
+
try {
|
|
502
|
+
// Generate salt for this memory
|
|
503
|
+
const salt = generateSalt();
|
|
504
|
+
// Encrypt content
|
|
505
|
+
const key = deriveKey(config.licenseKey, salt);
|
|
506
|
+
const encrypted = encrypt(mem.content, key);
|
|
507
|
+
if (!encrypted) {
|
|
508
|
+
console.warn(`ā ļø Failed to encrypt memory: ${mem.content.substring(0, 50)}...`);
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
// Push to cloud
|
|
512
|
+
const pushResponse = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
513
|
+
method: 'POST',
|
|
514
|
+
headers: { 'Content-Type': 'application/json' },
|
|
515
|
+
body: JSON.stringify({
|
|
516
|
+
path: 'memories:push',
|
|
517
|
+
args: {
|
|
518
|
+
licenseKey: config.licenseKey,
|
|
519
|
+
encryptedContent: encrypted.encrypted,
|
|
520
|
+
iv: encrypted.iv,
|
|
521
|
+
salt: salt,
|
|
522
|
+
category: mem.category,
|
|
523
|
+
timestamp: mem.timestamp,
|
|
524
|
+
},
|
|
525
|
+
}),
|
|
526
|
+
});
|
|
527
|
+
const pushResult = await pushResponse.json();
|
|
528
|
+
if (pushResult.status === 'success') {
|
|
529
|
+
uploadedCount++;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
console.warn(`ā ļø Error uploading memory: ${err}`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (uploadedCount > 0) {
|
|
537
|
+
console.log(`ā
Uploaded ${uploadedCount} memories to cloud\n`);
|
|
538
|
+
}
|
|
539
|
+
// STEP 2: Pull from cloud
|
|
497
540
|
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
498
541
|
method: 'POST',
|
|
499
542
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -552,6 +595,7 @@ async function cmdSync(args) {
|
|
|
552
595
|
config.lastSyncAt = Date.now();
|
|
553
596
|
saveConfig(config);
|
|
554
597
|
console.log(`\nā
Sync complete!`);
|
|
598
|
+
console.log(` Uploaded: ${uploadedCount} memories`);
|
|
555
599
|
console.log(` Downloaded: ${syncedCount} memories`);
|
|
556
600
|
console.log(` Last sync: ${new Date().toLocaleString()}\n`);
|
|
557
601
|
}
|
|
@@ -656,6 +700,38 @@ function getLocalStats() {
|
|
|
656
700
|
}
|
|
657
701
|
return stats;
|
|
658
702
|
}
|
|
703
|
+
// Helper: Get local memories for sync (push to cloud)
|
|
704
|
+
function getLocalMemoriesForSync() {
|
|
705
|
+
const memories = [];
|
|
706
|
+
const memoryDir = getMemoryDir();
|
|
707
|
+
if (!existsSync(memoryDir))
|
|
708
|
+
return memories;
|
|
709
|
+
const files = readdirSync(memoryDir).filter(f => f.endsWith('.md') && !f.includes('INDEX'));
|
|
710
|
+
for (const file of files) {
|
|
711
|
+
const filePath = join(memoryDir, file);
|
|
712
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
713
|
+
const lines = content.split('\n');
|
|
714
|
+
for (const line of lines) {
|
|
715
|
+
const emojiMatch = line.match(/^(š“|š”|š¤|š£)\s*\[?(GOTCHA|PROBLEM|DECISION|DISCOVERY)\]?\s*(.+)$/i);
|
|
716
|
+
if (emojiMatch) {
|
|
717
|
+
const emoji = emojiMatch[1];
|
|
718
|
+
const categoryMap = {
|
|
719
|
+
'š“': 'gotcha',
|
|
720
|
+
'š”': 'problem',
|
|
721
|
+
'š¤': 'decision',
|
|
722
|
+
'š£': 'discovery',
|
|
723
|
+
};
|
|
724
|
+
const category = categoryMap[emoji] || 'discovery';
|
|
725
|
+
const content = emojiMatch[3].trim();
|
|
726
|
+
// Extract timestamp from filename (YYYY-MM-DD.md)
|
|
727
|
+
const dateStr = file.replace('.md', '');
|
|
728
|
+
const timestamp = new Date(dateStr).getTime() || Date.now();
|
|
729
|
+
memories.push({ content, category, timestamp });
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return memories;
|
|
734
|
+
}
|
|
659
735
|
// COMMAND: help
|
|
660
736
|
function cmdHelp() {
|
|
661
737
|
console.log(`
|