undoai 0.1.0-beta.1
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/README.md +243 -0
- package/dist/cli/commands/restore.d.ts +11 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +188 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/status.d.ts +5 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +46 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +5 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +21 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +5 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +138 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +45 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/daemon.d.ts +35 -0
- package/dist/core/daemon.d.ts.map +1 -0
- package/dist/core/daemon.js +94 -0
- package/dist/core/daemon.js.map +1 -0
- package/dist/core/snapshot.d.ts +39 -0
- package/dist/core/snapshot.d.ts.map +1 -0
- package/dist/core/snapshot.js +119 -0
- package/dist/core/snapshot.js.map +1 -0
- package/dist/core/storage.d.ts +92 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +198 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/example.d.ts +2 -0
- package/dist/example.d.ts.map +1 -0
- package/dist/example.js +30 -0
- package/dist/example.js.map +1 -0
- package/dist/utils/logger.d.ts +42 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/watcher.d.ts +55 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +122 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { FileWatcher } from '../../watcher.js';
|
|
2
|
+
import { SnapshotManager } from '../../core/snapshot.js';
|
|
3
|
+
import { Storage, STORAGE_PATHS } from '../../core/storage.js';
|
|
4
|
+
import { DaemonManager } from '../../core/daemon.js';
|
|
5
|
+
import { Logger } from '../../utils/logger.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { minimatch } from 'minimatch';
|
|
8
|
+
/**
|
|
9
|
+
* Important file patterns that should trigger snapshot even if only 1 file changed
|
|
10
|
+
*/
|
|
11
|
+
const IMPORTANT_FILE_PATTERNS = [
|
|
12
|
+
'.env',
|
|
13
|
+
'.env.*',
|
|
14
|
+
'package.json',
|
|
15
|
+
'package-lock.json',
|
|
16
|
+
'pnpm-lock.yaml',
|
|
17
|
+
'yarn.lock',
|
|
18
|
+
'tsconfig.json',
|
|
19
|
+
'jsconfig.json',
|
|
20
|
+
'**/*.prisma',
|
|
21
|
+
'**/schema.prisma',
|
|
22
|
+
'**/migrations/**',
|
|
23
|
+
'Dockerfile',
|
|
24
|
+
'docker-compose.yml',
|
|
25
|
+
'docker-compose.*.yml',
|
|
26
|
+
'.github/workflows/**',
|
|
27
|
+
'.gitlab-ci.yml',
|
|
28
|
+
'Jenkinsfile',
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Check if file is important (should trigger snapshot even if single file)
|
|
32
|
+
*/
|
|
33
|
+
function isImportantFile(filePath, projectRoot) {
|
|
34
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
35
|
+
return IMPORTANT_FILE_PATTERNS.some(pattern => minimatch(relativePath, pattern));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Smart detection: should we create snapshot?
|
|
39
|
+
*/
|
|
40
|
+
function shouldCreateSnapshot(changedFiles, projectRoot, timeDiff) {
|
|
41
|
+
const fileCount = changedFiles.size;
|
|
42
|
+
// Priority 1: Burst detection (≥3 files)
|
|
43
|
+
if (fileCount >= 3) {
|
|
44
|
+
return { should: true, reason: `Burst detected (${fileCount} files)` };
|
|
45
|
+
}
|
|
46
|
+
// Priority 2: Important file changed (even if 1 file)
|
|
47
|
+
const hasImportant = Array.from(changedFiles).some(file => isImportantFile(file, projectRoot));
|
|
48
|
+
if (hasImportant) {
|
|
49
|
+
return { should: true, reason: 'Important file changed' };
|
|
50
|
+
}
|
|
51
|
+
// Priority 3: Velocity-based AI detection
|
|
52
|
+
if (timeDiff && fileCount >= 2 && timeDiff < 1000) {
|
|
53
|
+
// 2+ files in < 1 second = likely AI
|
|
54
|
+
return { should: true, reason: 'High velocity change (likely AI)' };
|
|
55
|
+
}
|
|
56
|
+
return { should: false, reason: 'Below threshold' };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Watch command - start watching for file changes
|
|
60
|
+
*/
|
|
61
|
+
export async function watchCommand() {
|
|
62
|
+
// Check if already running
|
|
63
|
+
if (DaemonManager.isRunning()) {
|
|
64
|
+
Logger.error('undoai is already watching');
|
|
65
|
+
Logger.info('Use "undoai stop" to stop watching');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Initialize storage
|
|
69
|
+
Storage.init();
|
|
70
|
+
// Get current directory as project root
|
|
71
|
+
const projectRoot = process.cwd();
|
|
72
|
+
// Create snapshot manager
|
|
73
|
+
const snapshotManager = new SnapshotManager(projectRoot);
|
|
74
|
+
// Create initial snapshot if needed
|
|
75
|
+
const existingSnapshots = snapshotManager.listSnapshots();
|
|
76
|
+
if (existingSnapshots.length === 0) {
|
|
77
|
+
console.log('');
|
|
78
|
+
Logger.info('📸 Creating initial baseline snapshot...');
|
|
79
|
+
Logger.dim('This captures your current working state');
|
|
80
|
+
// We'll implement full initial snapshot in next iteration
|
|
81
|
+
// For now, just log that baseline will be created on first change
|
|
82
|
+
Logger.info('💡 Baseline will be created on first file change');
|
|
83
|
+
console.log('');
|
|
84
|
+
}
|
|
85
|
+
let lastChangeTime = Date.now();
|
|
86
|
+
// Create file watcher with smart detection
|
|
87
|
+
const watcher = new FileWatcher({
|
|
88
|
+
watchPath: projectRoot,
|
|
89
|
+
onBurstChange: (changedFiles) => {
|
|
90
|
+
const currentTime = Date.now();
|
|
91
|
+
const timeDiff = currentTime - lastChangeTime;
|
|
92
|
+
lastChangeTime = currentTime;
|
|
93
|
+
// Smart detection
|
|
94
|
+
const detection = shouldCreateSnapshot(changedFiles, projectRoot, timeDiff);
|
|
95
|
+
if (detection.should) {
|
|
96
|
+
// Create snapshot
|
|
97
|
+
try {
|
|
98
|
+
const snapshotId = snapshotManager.createSnapshot(changedFiles, 'AI_BURST');
|
|
99
|
+
Logger.snapshot(`Snapshot saved (${changedFiles.size} files changed)`);
|
|
100
|
+
Logger.dim(`Reason: ${detection.reason}`);
|
|
101
|
+
Logger.dim(`Snapshot ID: ${snapshotId}`);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
Logger.error(`Failed to create snapshot: ${error}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Just log, no snapshot
|
|
109
|
+
Logger.dim(`${changedFiles.size} file(s) changed (${detection.reason})`);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
burstThreshold: 3, // Lowered from 5 to 3
|
|
113
|
+
debounceDelay: 2000,
|
|
114
|
+
});
|
|
115
|
+
// Start watching
|
|
116
|
+
watcher.start();
|
|
117
|
+
// Mark daemon as running
|
|
118
|
+
DaemonManager.markAsRunning(process.pid);
|
|
119
|
+
// Display startup message
|
|
120
|
+
console.log('');
|
|
121
|
+
Logger.success('undoai is now watching');
|
|
122
|
+
Logger.dim(`📁 Project: ${projectRoot}`);
|
|
123
|
+
Logger.dim(`💾 Storage: ${STORAGE_PATHS.root}`);
|
|
124
|
+
Logger.dim(`🔒 100% local - your code never leaves this machine`);
|
|
125
|
+
console.log('');
|
|
126
|
+
Logger.info('🎯 Smart detection enabled:');
|
|
127
|
+
Logger.dim(' • ≥3 files changed = snapshot');
|
|
128
|
+
Logger.dim(' • Important files (.env, package.json, etc) = snapshot');
|
|
129
|
+
Logger.dim(' • High velocity changes = snapshot');
|
|
130
|
+
console.log('');
|
|
131
|
+
Logger.info('Watching for file changes... (Press Ctrl+C to stop)');
|
|
132
|
+
console.log('');
|
|
133
|
+
// Setup graceful shutdown
|
|
134
|
+
DaemonManager.setupShutdownHandlers(async () => {
|
|
135
|
+
await watcher.stop();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../../src/cli/commands/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { watchCommand } from './commands/watch.js';
|
|
4
|
+
import { restoreCommand } from './commands/restore.js';
|
|
5
|
+
import { stopCommand } from './commands/stop.js';
|
|
6
|
+
import { statusCommand } from './commands/status.js';
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name('undoai')
|
|
10
|
+
.description('Free, local undo button for AI coding')
|
|
11
|
+
.version('1.0.0');
|
|
12
|
+
// Watch command
|
|
13
|
+
program
|
|
14
|
+
.command('watch')
|
|
15
|
+
.description('Start watching for file changes')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
await watchCommand();
|
|
18
|
+
});
|
|
19
|
+
// Restore command
|
|
20
|
+
program
|
|
21
|
+
.command('restore')
|
|
22
|
+
.description('Restore files from a snapshot')
|
|
23
|
+
.option('-i, --interactive', 'Select specific files to restore')
|
|
24
|
+
.option('-f, --files <patterns>', 'Restore specific files (comma-separated patterns)')
|
|
25
|
+
.option('-p, --pattern <glob>', 'Restore files matching glob pattern')
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
await restoreCommand(options);
|
|
28
|
+
});
|
|
29
|
+
// Stop command
|
|
30
|
+
program
|
|
31
|
+
.command('stop')
|
|
32
|
+
.description('Stop watching daemon')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
await stopCommand();
|
|
35
|
+
});
|
|
36
|
+
// Status command
|
|
37
|
+
program
|
|
38
|
+
.command('status')
|
|
39
|
+
.description('Show undoai status')
|
|
40
|
+
.action(async () => {
|
|
41
|
+
await statusCommand();
|
|
42
|
+
});
|
|
43
|
+
// Parse arguments
|
|
44
|
+
program.parse();
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,gBAAgB;AAChB,OAAO;KACF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,KAAK,IAAI,EAAE;IACf,MAAM,YAAY,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEP,kBAAkB;AAClB,OAAO;KACF,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,mBAAmB,EAAE,kCAAkC,CAAC;KAC/D,MAAM,CAAC,wBAAwB,EAAE,mDAAmD,CAAC;KACrF,MAAM,CAAC,sBAAsB,EAAE,qCAAqC,CAAC;KACrE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACtB,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEP,eAAe;AACf,OAAO;KACF,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,KAAK,IAAI,EAAE;IACf,MAAM,WAAW,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEP,iBAAiB;AACjB,OAAO;KACF,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,KAAK,IAAI,EAAE;IACf,MAAM,aAAa,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEP,kBAAkB;AAClB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon process manager
|
|
3
|
+
*/
|
|
4
|
+
export declare class DaemonManager {
|
|
5
|
+
/**
|
|
6
|
+
* Check if daemon is running
|
|
7
|
+
*/
|
|
8
|
+
static isRunning(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Get daemon PID
|
|
11
|
+
*/
|
|
12
|
+
static getPid(): number | null;
|
|
13
|
+
/**
|
|
14
|
+
* Save daemon PID
|
|
15
|
+
*/
|
|
16
|
+
static savePid(pid: number): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clean up PID file
|
|
19
|
+
*/
|
|
20
|
+
static cleanupPidFile(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Stop daemon process
|
|
23
|
+
*/
|
|
24
|
+
static stop(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Start daemon in background (for watch command)
|
|
27
|
+
* Note: This is called from the watch command itself
|
|
28
|
+
*/
|
|
29
|
+
static markAsRunning(pid: number): void;
|
|
30
|
+
/**
|
|
31
|
+
* Setup graceful shutdown handlers
|
|
32
|
+
*/
|
|
33
|
+
static setupShutdownHandlers(onShutdown: () => Promise<void>): void;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/core/daemon.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,qBAAa,aAAa;IACtB;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,OAAO;IAkB3B;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI;IAY9B;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIjC;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,IAAI;IAM7B;;OAEG;IACH,MAAM,CAAC,IAAI,IAAI,OAAO;IAkBtB;;;OAGG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvC;;OAEG;IACH,MAAM,CAAC,qBAAqB,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;CAWtE"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { STORAGE_PATHS } from './storage.js';
|
|
3
|
+
/**
|
|
4
|
+
* Daemon process manager
|
|
5
|
+
*/
|
|
6
|
+
export class DaemonManager {
|
|
7
|
+
/**
|
|
8
|
+
* Check if daemon is running
|
|
9
|
+
*/
|
|
10
|
+
static isRunning() {
|
|
11
|
+
if (!fs.existsSync(STORAGE_PATHS.daemonPid)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const pid = parseInt(fs.readFileSync(STORAGE_PATHS.daemonPid, 'utf-8'));
|
|
16
|
+
// Check if process exists
|
|
17
|
+
process.kill(pid, 0);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
// Process doesn't exist, clean up stale PID file
|
|
22
|
+
this.cleanupPidFile();
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get daemon PID
|
|
28
|
+
*/
|
|
29
|
+
static getPid() {
|
|
30
|
+
if (!fs.existsSync(STORAGE_PATHS.daemonPid)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return parseInt(fs.readFileSync(STORAGE_PATHS.daemonPid, 'utf-8'));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Save daemon PID
|
|
42
|
+
*/
|
|
43
|
+
static savePid(pid) {
|
|
44
|
+
fs.writeFileSync(STORAGE_PATHS.daemonPid, pid.toString(), 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Clean up PID file
|
|
48
|
+
*/
|
|
49
|
+
static cleanupPidFile() {
|
|
50
|
+
if (fs.existsSync(STORAGE_PATHS.daemonPid)) {
|
|
51
|
+
fs.unlinkSync(STORAGE_PATHS.daemonPid);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Stop daemon process
|
|
56
|
+
*/
|
|
57
|
+
static stop() {
|
|
58
|
+
const pid = this.getPid();
|
|
59
|
+
if (!pid) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
process.kill(pid, 'SIGTERM');
|
|
64
|
+
this.cleanupPidFile();
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// Process doesn't exist
|
|
69
|
+
this.cleanupPidFile();
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Start daemon in background (for watch command)
|
|
75
|
+
* Note: This is called from the watch command itself
|
|
76
|
+
*/
|
|
77
|
+
static markAsRunning(pid) {
|
|
78
|
+
this.savePid(pid);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Setup graceful shutdown handlers
|
|
82
|
+
*/
|
|
83
|
+
static setupShutdownHandlers(onShutdown) {
|
|
84
|
+
const shutdown = async (signal) => {
|
|
85
|
+
console.log(`\n\n👋 Received ${signal}, stopping watcher...`);
|
|
86
|
+
await onShutdown();
|
|
87
|
+
this.cleanupPidFile();
|
|
88
|
+
process.exit(0);
|
|
89
|
+
};
|
|
90
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
91
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/core/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SnapshotMetadata } from './storage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot manager for creating and restoring snapshots
|
|
4
|
+
*/
|
|
5
|
+
export declare class SnapshotManager {
|
|
6
|
+
private projectRoot;
|
|
7
|
+
constructor(projectRoot: string);
|
|
8
|
+
/**
|
|
9
|
+
* Create a snapshot from changed files
|
|
10
|
+
*/
|
|
11
|
+
createSnapshot(changedFiles: Set<string>, label?: 'AI_BURST' | 'AUTO'): string;
|
|
12
|
+
/**
|
|
13
|
+
* Restore files from a snapshot
|
|
14
|
+
*/
|
|
15
|
+
restoreSnapshot(snapshotId: string): number;
|
|
16
|
+
/**
|
|
17
|
+
* List all available snapshots
|
|
18
|
+
*/
|
|
19
|
+
listSnapshots(): Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
metadata: SnapshotMetadata;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Get snapshot details
|
|
25
|
+
*/
|
|
26
|
+
getSnapshot(snapshotId: string): {
|
|
27
|
+
id: string;
|
|
28
|
+
metadata: SnapshotMetadata;
|
|
29
|
+
} | null;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a snapshot
|
|
32
|
+
*/
|
|
33
|
+
deleteSnapshot(snapshotId: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get snapshot count
|
|
36
|
+
*/
|
|
37
|
+
getSnapshotCount(): number;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzD;;GAEG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACH,cAAc,CACV,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,EACzB,KAAK,GAAE,UAAU,GAAG,MAAmB,GACxC,MAAM;IAkDT;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IA6B3C;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,gBAAgB,CAAA;KAAE,CAAC;IAclE;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,gBAAgB,CAAA;KAAE,GAAG,IAAI;IAUlF;;OAEG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIxC;;OAEG;IACH,gBAAgB,IAAI,MAAM;CAG7B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Storage } from './storage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot manager for creating and restoring snapshots
|
|
4
|
+
*/
|
|
5
|
+
export class SnapshotManager {
|
|
6
|
+
constructor(projectRoot) {
|
|
7
|
+
this.projectRoot = projectRoot;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a snapshot from changed files
|
|
11
|
+
*/
|
|
12
|
+
createSnapshot(changedFiles, label = 'AI_BURST') {
|
|
13
|
+
// Generate snapshot ID (timestamp)
|
|
14
|
+
const timestamp = Date.now();
|
|
15
|
+
const snapshotId = timestamp.toString();
|
|
16
|
+
// Create snapshot directory
|
|
17
|
+
Storage.createSnapshotDir(snapshotId);
|
|
18
|
+
// Filter files: only snapshot files that still exist
|
|
19
|
+
// (skip deleted files to avoid ENOENT errors)
|
|
20
|
+
const fileArray = Array.from(changedFiles);
|
|
21
|
+
const existingFiles = [];
|
|
22
|
+
const skippedFiles = [];
|
|
23
|
+
for (const file of fileArray) {
|
|
24
|
+
if (Storage.fileExists(file)) {
|
|
25
|
+
try {
|
|
26
|
+
Storage.copyFileToSnapshot(file, snapshotId, this.projectRoot);
|
|
27
|
+
existingFiles.push(file);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error(`Failed to copy file ${file}:`, error);
|
|
31
|
+
skippedFiles.push(file);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// File was deleted before snapshot - skip it
|
|
36
|
+
skippedFiles.push(file);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Create metadata with only successfully backed up files
|
|
40
|
+
const metadata = {
|
|
41
|
+
timestamp,
|
|
42
|
+
date: new Date(timestamp).toISOString(),
|
|
43
|
+
projectRoot: this.projectRoot,
|
|
44
|
+
changedFiles: existingFiles, // Only files that were actually saved
|
|
45
|
+
fileCount: existingFiles.length,
|
|
46
|
+
label,
|
|
47
|
+
};
|
|
48
|
+
// Save metadata
|
|
49
|
+
Storage.saveMetadata(snapshotId, metadata);
|
|
50
|
+
// Log summary if files were skipped
|
|
51
|
+
if (skippedFiles.length > 0) {
|
|
52
|
+
console.log(`⚠️ Skipped ${skippedFiles.length} deleted file(s)`);
|
|
53
|
+
}
|
|
54
|
+
return snapshotId;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Restore files from a snapshot
|
|
58
|
+
*/
|
|
59
|
+
restoreSnapshot(snapshotId) {
|
|
60
|
+
// Get metadata
|
|
61
|
+
const metadata = Storage.getSnapshotMetadata(snapshotId);
|
|
62
|
+
if (!metadata) {
|
|
63
|
+
throw new Error(`Snapshot ${snapshotId} not found`);
|
|
64
|
+
}
|
|
65
|
+
// Check if project root matches
|
|
66
|
+
if (metadata.projectRoot !== this.projectRoot) {
|
|
67
|
+
throw new Error(`Snapshot was created in different project: ${metadata.projectRoot}`);
|
|
68
|
+
}
|
|
69
|
+
// Restore all files
|
|
70
|
+
let restoredCount = 0;
|
|
71
|
+
for (const file of metadata.changedFiles) {
|
|
72
|
+
try {
|
|
73
|
+
Storage.restoreFileFromSnapshot(file, snapshotId, this.projectRoot);
|
|
74
|
+
restoredCount++;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error(`Failed to restore file ${file}:`, error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return restoredCount;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* List all available snapshots
|
|
84
|
+
*/
|
|
85
|
+
listSnapshots() {
|
|
86
|
+
const snapshotIds = Storage.getSnapshotIds();
|
|
87
|
+
const snapshots = [];
|
|
88
|
+
for (const id of snapshotIds) {
|
|
89
|
+
const metadata = Storage.getSnapshotMetadata(id);
|
|
90
|
+
if (metadata) {
|
|
91
|
+
snapshots.push({ id, metadata });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return snapshots;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get snapshot details
|
|
98
|
+
*/
|
|
99
|
+
getSnapshot(snapshotId) {
|
|
100
|
+
const metadata = Storage.getSnapshotMetadata(snapshotId);
|
|
101
|
+
if (!metadata) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return { id: snapshotId, metadata };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Delete a snapshot
|
|
108
|
+
*/
|
|
109
|
+
deleteSnapshot(snapshotId) {
|
|
110
|
+
Storage.deleteSnapshot(snapshotId);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get snapshot count
|
|
114
|
+
*/
|
|
115
|
+
getSnapshotCount() {
|
|
116
|
+
return Storage.getSnapshotIds().length;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage paths configuration
|
|
3
|
+
*/
|
|
4
|
+
export declare const STORAGE_PATHS: {
|
|
5
|
+
readonly root: string;
|
|
6
|
+
readonly snapshots: string;
|
|
7
|
+
readonly daemonPid: string;
|
|
8
|
+
readonly config: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Metadata for a snapshot
|
|
12
|
+
*/
|
|
13
|
+
export interface SnapshotMetadata {
|
|
14
|
+
timestamp: number;
|
|
15
|
+
date: string;
|
|
16
|
+
projectRoot: string;
|
|
17
|
+
changedFiles: string[];
|
|
18
|
+
fileCount: number;
|
|
19
|
+
label: 'AI_BURST' | 'AUTO';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Storage manager for undoai snapshots
|
|
23
|
+
*/
|
|
24
|
+
export declare class Storage {
|
|
25
|
+
/**
|
|
26
|
+
* Initialize storage directory structure
|
|
27
|
+
*/
|
|
28
|
+
static init(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Check if storage is initialized
|
|
31
|
+
*/
|
|
32
|
+
static isInitialized(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a file exists
|
|
35
|
+
*/
|
|
36
|
+
static fileExists(filePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get all snapshot IDs (sorted by timestamp, newest first)
|
|
39
|
+
*/
|
|
40
|
+
static getSnapshotIds(): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Get snapshot metadata
|
|
43
|
+
*/
|
|
44
|
+
static getSnapshotMetadata(snapshotId: string): SnapshotMetadata | null;
|
|
45
|
+
/**
|
|
46
|
+
* Get snapshot directory path
|
|
47
|
+
*/
|
|
48
|
+
static getSnapshotDir(snapshotId: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Get snapshot files directory path
|
|
51
|
+
*/
|
|
52
|
+
static getSnapshotFilesDir(snapshotId: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Create a new snapshot directory
|
|
55
|
+
*/
|
|
56
|
+
static createSnapshotDir(snapshotId: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Save snapshot metadata
|
|
59
|
+
*/
|
|
60
|
+
static saveMetadata(snapshotId: string, metadata: SnapshotMetadata): void;
|
|
61
|
+
/**
|
|
62
|
+
* Convert file path to safe filename (replace / with __)
|
|
63
|
+
* Example: /home/user/project/src/auth.ts -> src__auth.ts
|
|
64
|
+
*/
|
|
65
|
+
static pathToSafeFilename(filePath: string, projectRoot: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Convert safe filename back to relative path
|
|
68
|
+
* Example: src__auth.ts -> src/auth.ts
|
|
69
|
+
*/
|
|
70
|
+
static safeFilenameToPath(safeFilename: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Copy file to snapshot with compression
|
|
73
|
+
*/
|
|
74
|
+
static copyFileToSnapshot(sourceFile: string, snapshotId: string, projectRoot: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* Restore file from snapshot with decompression
|
|
77
|
+
*/
|
|
78
|
+
static restoreFileFromSnapshot(originalPath: string, snapshotId: string, projectRoot: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Delete a snapshot
|
|
81
|
+
*/
|
|
82
|
+
static deleteSnapshot(snapshotId: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Get total storage size in bytes
|
|
85
|
+
*/
|
|
86
|
+
static getStorageSize(): number;
|
|
87
|
+
/**
|
|
88
|
+
* Format bytes to human readable string
|
|
89
|
+
*/
|
|
90
|
+
static formatBytes(bytes: number): string;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,OAAO;IAChB;;OAEG;IACH,MAAM,CAAC,IAAI,IAAI,IAAI;IAYnB;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,OAAO;IAI/B;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAS5C;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM,EAAE;IAcjC;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAgBvE;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAIjD;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAItD;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAUpD;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAKzE;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;IAKxE;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAIvD;;OAEG;IACH,MAAM,CAAC,kBAAkB,CACrB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GACpB,IAAI;IAUP;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAC1B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GACpB,IAAI;IAoBP;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAQ/C;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM;IA0B/B;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAS5C"}
|