aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-fs.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/core/module-fs.js')
-rw-r--r--modules/core/module-fs.js74
1 files changed, 54 insertions, 20 deletions
diff --git a/modules/core/module-fs.js b/modules/core/module-fs.js
index 309010d..ab8fd99 100644
--- a/modules/core/module-fs.js
+++ b/modules/core/module-fs.js
@@ -403,24 +403,18 @@ class FileSystemModule {
this.commands['session-save'] = (args) => {
if (!args[0]) return this.terminal.print('Usage: session-save <name>', 'warning');
const name = args[0].replace(/[^a-zA-Z0-9_-]/g, '_');
- // Strip system dirs to avoid recursive bloat in snapshots
- const fsRoot = JSON.parse(JSON.stringify(this.terminal.fs.root));
- if (fsRoot && fsRoot.content) {
- delete fsRoot.content['_sessions'];
- delete fsRoot.content['_snapshots'];
- delete fsRoot.content['.trash'];
- }
- const snapshot = {
+ // v2: metadata-only — VFS is persisted independently in localStorage
+ const manifest = {
type: 'session',
+ version: 2,
savedAt: new Date().toISOString(),
- fsRoot: fsRoot,
currentPath: this.terminal.fs.currentPath,
- version: 1
+ terminalLines: this.terminal._historyBuffer ? this.terminal._historyBuffer.slice(-50) : []
};
const filePath = '_sessions/' + name + '.json';
this.terminal.fs.mkdirRecursive('_sessions');
- this.terminal.fs.writeFile(filePath, JSON.stringify(snapshot, null, 2));
- this.terminal.print('Session saved: ' + name, 'success');
+ this.terminal.fs.writeFile(filePath, JSON.stringify(manifest));
+ this.terminal.print('Session saved: ' + name + ' (' + (manifest.terminalLines.length || 0) + ' history lines)', 'success');
};
this.commands['session-load'] = (args) => {
if (!args[0]) return this.terminal.print('Usage: session-load <name>', 'warning');
@@ -429,11 +423,28 @@ class FileSystemModule {
if (content === null) return this.terminal.print('Session not found: ' + args[0], 'error');
try {
const session = JSON.parse(content);
- if (!session || session.type !== 'session' || !session.fsRoot) {
+ if (!session || session.type !== 'session') {
return this.terminal.print('Invalid session file: ' + args[0], 'error');
}
- this.terminal.fs.root = session.fsRoot;
- this.terminal.fs.currentPath = session.currentPath || [];
+ if (session.version === 2) {
+ // v2: metadata-only restore — keep existing VFS, just restore path + terminal history
+ this.terminal.fs.currentPath = session.currentPath || [];
+ if (session.terminalLines && Array.isArray(session.terminalLines) && this.terminal._historyBuffer) {
+ this.terminal._historyBuffer = session.terminalLines.slice(-50);
+ // Re-render last few lines for context
+ this.terminal.outputContainer.innerHTML = '';
+ session.terminalLines.forEach(line => {
+ const text = typeof line === 'string' ? line : (line.l || '');
+ const type = typeof line === 'object' ? (line.t || '') : '';
+ this.terminal.print(text, type);
+ });
+ }
+ } else {
+ // v1: full VFS restore (legacy)
+ if (!session.fsRoot) return this.terminal.print('Invalid session file', 'error');
+ this.terminal.fs.root = session.fsRoot;
+ this.terminal.fs.currentPath = session.currentPath || [];
+ }
this.terminal.fs.saveToStorage();
this.terminal.updatePrompt();
this.terminal.print('Session loaded: ' + args[0] + ' (' + new Date(session.savedAt).toLocaleString() + ')', 'success');
@@ -453,8 +464,13 @@ class FileSystemModule {
const content = JSON.parse(this.terminal.fs.readFile('_sessions/' + f.name));
const label = f.name.replace('.json', '');
const date = content.savedAt ? new Date(content.savedAt).toLocaleString() : 'unknown';
- const fileCount = content.fsRoot ? Object.keys(content.fsRoot.content || {}).length : 0;
- this.terminal.print(' ' + label + ' (' + fileCount + ' items, ' + date + ')');
+ if (content.version === 2) {
+ const lines = content.terminalLines ? content.terminalLines.length : 0;
+ this.terminal.print(' ' + label + ' (' + lines + ' history lines, ' + date + ')');
+ } else {
+ const fileCount = content.fsRoot ? Object.keys(content.fsRoot.content || {}).length : 0;
+ this.terminal.print(' ' + label + ' (' + fileCount + ' items, ' + date + ')');
+ }
} catch (e) {
this.terminal.print(' ' + f.name.replace('.json', '') + ' (corrupt)');
}
@@ -497,12 +513,30 @@ class FileSystemModule {
reader.onload = (evt) => {
try {
const session = JSON.parse(evt.target.result);
- if (!session || session.type !== 'session' || !session.fsRoot) {
+ if (!session || session.type !== 'session') {
this.terminal.print('Invalid session file (not a valid session export)', 'error');
return;
}
- this.terminal.fs.root = session.fsRoot;
- this.terminal.fs.currentPath = session.currentPath || [];
+ if (session.version === 2) {
+ // v2: metadata-only — keep existing VFS, restore path
+ this.terminal.fs.currentPath = session.currentPath || [];
+ if (session.terminalLines && Array.isArray(session.terminalLines) && this.terminal._historyBuffer) {
+ this.terminal._historyBuffer = session.terminalLines.slice(-50);
+ this.terminal.outputContainer.innerHTML = '';
+ session.terminalLines.forEach(line => {
+ const text = typeof line === 'string' ? line : (line.l || '');
+ const type = typeof line === 'object' ? (line.t || '') : '';
+ this.terminal.print(text, type);
+ });
+ }
+ } else {
+ if (!session.fsRoot) {
+ this.terminal.print('Invalid session file (not a valid session export)', 'error');
+ return;
+ }
+ this.terminal.fs.root = session.fsRoot;
+ this.terminal.fs.currentPath = session.currentPath || [];
+ }
this.terminal.fs.saveToStorage();
this.terminal.updatePrompt();
this.terminal.print('Session imported: ' + file.name + ' (' + (session.savedAt ? new Date(session.savedAt).toLocaleString() : 'unknown date') + ')', 'success');