@trlc/super-memory 1.3.6 → 1.3.8

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.
Files changed (2) hide show
  1. package/dist/index.js +108 -2
  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.6';
25
+ const VERSION = '1.3.8';
26
26
  // Paths
27
27
  const getBaseDir = () => join(homedir(), '.openclaw', 'workspace');
28
28
  const getMemoryDir = () => join(getBaseDir(), 'memory');
@@ -493,7 +493,65 @@ async function cmdSync(args) {
493
493
  }
494
494
  console.log('šŸ”„ Syncing with cloud...\n');
495
495
  try {
496
- // Pull from cloud
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
+ // Log audit
531
+ await fetch(`${CONVEX_URL}/api/mutation`, {
532
+ method: 'POST',
533
+ headers: { 'Content-Type': 'application/json' },
534
+ body: JSON.stringify({
535
+ path: 'audit:logCli',
536
+ args: {
537
+ licenseKey: config.licenseKey,
538
+ action: 'memory_save',
539
+ details: `Saved ${mem.category}: ${mem.content.substring(0, 50)}...`,
540
+ ipAddress: 'cli',
541
+ deviceInfo: config.deviceId,
542
+ },
543
+ }),
544
+ });
545
+ }
546
+ }
547
+ catch (err) {
548
+ console.warn(`āš ļø Error uploading memory: ${err}`);
549
+ }
550
+ }
551
+ if (uploadedCount > 0) {
552
+ console.log(`āœ… Uploaded ${uploadedCount} memories to cloud\n`);
553
+ }
554
+ // STEP 2: Pull from cloud
497
555
  const response = await fetch(`${CONVEX_URL}/api/query`, {
498
556
  method: 'POST',
499
557
  headers: { 'Content-Type': 'application/json' },
@@ -552,8 +610,24 @@ async function cmdSync(args) {
552
610
  config.lastSyncAt = Date.now();
553
611
  saveConfig(config);
554
612
  console.log(`\nāœ… Sync complete!`);
613
+ console.log(` Uploaded: ${uploadedCount} memories`);
555
614
  console.log(` Downloaded: ${syncedCount} memories`);
556
615
  console.log(` Last sync: ${new Date().toLocaleString()}\n`);
616
+ // Log sync audit
617
+ await fetch(`${CONVEX_URL}/api/mutation`, {
618
+ method: 'POST',
619
+ headers: { 'Content-Type': 'application/json' },
620
+ body: JSON.stringify({
621
+ path: 'audit:logCli',
622
+ args: {
623
+ licenseKey: config.licenseKey,
624
+ action: 'sync_push',
625
+ details: `Sync: ${uploadedCount} up, ${syncedCount} down`,
626
+ ipAddress: 'cli',
627
+ deviceInfo: config.deviceId,
628
+ },
629
+ }),
630
+ });
557
631
  }
558
632
  catch (error) {
559
633
  console.error(`āŒ Sync failed: ${error.message}\n`);
@@ -656,6 +730,38 @@ function getLocalStats() {
656
730
  }
657
731
  return stats;
658
732
  }
733
+ // Helper: Get local memories for sync (push to cloud)
734
+ function getLocalMemoriesForSync() {
735
+ const memories = [];
736
+ const memoryDir = getMemoryDir();
737
+ if (!existsSync(memoryDir))
738
+ return memories;
739
+ const files = readdirSync(memoryDir).filter(f => f.endsWith('.md') && !f.includes('INDEX'));
740
+ for (const file of files) {
741
+ const filePath = join(memoryDir, file);
742
+ const content = readFileSync(filePath, 'utf-8');
743
+ const lines = content.split('\n');
744
+ for (const line of lines) {
745
+ const emojiMatch = line.match(/^(šŸ”“|🟔|🟤|🟣)\s*\[?(GOTCHA|PROBLEM|DECISION|DISCOVERY)\]?\s*(.+)$/i);
746
+ if (emojiMatch) {
747
+ const emoji = emojiMatch[1];
748
+ const categoryMap = {
749
+ 'šŸ”“': 'gotcha',
750
+ '🟔': 'problem',
751
+ '🟤': 'decision',
752
+ '🟣': 'discovery',
753
+ };
754
+ const category = categoryMap[emoji] || 'discovery';
755
+ const content = emojiMatch[3].trim();
756
+ // Extract timestamp from filename (YYYY-MM-DD.md)
757
+ const dateStr = file.replace('.md', '');
758
+ const timestamp = new Date(dateStr).getTime() || Date.now();
759
+ memories.push({ content, category, timestamp });
760
+ }
761
+ }
762
+ }
763
+ return memories;
764
+ }
659
765
  // COMMAND: help
660
766
  function cmdHelp() {
661
767
  console.log(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trlc/super-memory",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "Super Memory CLI - AI-powered persistent memory by The Red Lobster Cartel",
5
5
  "main": "dist/index.js",
6
6
  "bin": {