diff options
| author | Agando <roduccomm@gmail.com> | 2026-06-17 06:01:20 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-06-17 06:01:20 +0200 |
| commit | cebacc27a48168e666679018f8e27156d12d4527 (patch) | |
| tree | b306d33b67b9d8c84bd9b9c16b1e91ee217628a6 /modules/core/terminal.js | |
| parent | 6aa24b976952a698c673d350977721b27193183d (diff) | |
auto: 2026-06-17_06:01 changes
Diffstat (limited to 'modules/core/terminal.js')
| -rw-r--r-- | modules/core/terminal.js | 97 |
1 files changed, 58 insertions, 39 deletions
diff --git a/modules/core/terminal.js b/modules/core/terminal.js index 504e08d..05aefef 100644 --- a/modules/core/terminal.js +++ b/modules/core/terminal.js @@ -10,7 +10,7 @@ this.destructiveCmds = new Set(['delete','del','write','save','overwrite','format','kill','stop','shutdown','reboot']); this.systemCmds = new Set(['reboot','shutdown','format','kill','halt','poweroff']); this.suspiciousFlags = new Set(['--dump','--execute','--eval','--exec','--shell','--script']); - this.whitelist = new Set(['help','clear','ls','cat','pwd','whoami','df','free','top','ps','echo','date','env','history','find','grep','tree','head','tail','wc','sort','du','diff','which','hostname','cal','basename','dirname','yes','seq','cut','uniq','expand','printf','base64','sleep','ll','h','mem','status','health-check','system-health','alias','unalias','modules','listmods','modules-list','nvfs-index','nvfs-status','nvfs-resolve','nvfs-tree','nvfs-config','nvfs-alias','nvfs-sync','floating-add','floating-remove','floating-list','floating-pos','floating-clear','floating-toggle','mem-debug','reset-mem']); + this.whitelist = new Set(['help','clear','ls','cat','pwd','whoami','df','free','top','ps','echo','date','env','history','find','grep','tree','head','tail','wc','sort','du','diff','which','hostname','cal','basename','dirname','yes','seq','cut','uniq','expand','printf','base64','sleep','ll','h','mem','status','health-check','system-health','alias','unalias','modules','listmods','modules-list','nvfs-index','nvfs-status','nvfs-resolve','nvfs-tree','nvfs-config','nvfs-alias','nvfs-sync','floating-add','floating-remove','floating-list','floating-pos','floating-clear','floating-toggle','mem-debug','reset-mem','orchestrate','orchestrate-parallel','orchestrate-decompose','orchestrate-result','orchestrator-status','orchestrator-spawn','orchestrator-kill','orchestrator-purge','orchestrator-config','orchestrator-list','orchestrator-sleep','orchestrator-wake','orchestrator-restart-policy','a2a-send','a2a-list','a2a-post','a2a-poll','a2a-ack','a2a-reject','a2a-status','a2a-prune','consensus','consensus-status','consensus-history','pipeline','agent-list','agent-register','agent-status','agent-unregister','contract-list','contract-register']); // Load persisted overrides from localStorage try { const d = localStorage.getItem('webx11_security_destructive'); if(d){JSON.parse(d).forEach(c=>this.destructiveCmds.add(c));} }catch(e){} try { const s = localStorage.getItem('webx11_security_system'); if(s){JSON.parse(s).forEach(c=>this.systemCmds.add(c));} }catch(e){} @@ -19,7 +19,7 @@ this._registerBuiltIn(); } _registerBuiltIn() { - const internals = ['clear','help','ls','cat','df','free','env','history','cd','pwd','touch','mkdir','rm','cp','mv','edit','cat','run','font-size','load-local','loadlocal','mem','security','security-level','security-destructive','security-system','security-whitelist','security-flag','config','ai-config','startup-modules','smart-prompt','cmd-allow','cmd-deny','system-health','server','servers','server-check','monitor','vfs','vfs-clean','vfs-size','empty-trash','expand','sysmsg']; + const internals = ['clear','help','ls','cat','df','free','env','history','cd','pwd','touch','mkdir','rm','cp','mv','edit','cat','run','font-size','load-local','loadlocal','mem','security','security-level','security-destructive','security-system','security-whitelist','security-flag','config','ai-config','startup-modules','smart-prompt','cmd-allow','cmd-deny','system-health','server','servers','server-check','monitor','vfs','vfs-clean','vfs-size','empty-trash','expand','sysmsg','orchestrate','orchestrate-parallel','orchestrate-decompose','orchestrate-result','orchestrator-status','orchestrator-spawn','orchestrator-kill','orchestrator-purge','orchestrator-config','orchestrator-list','orchestrator-sleep','orchestrator-wake','orchestrator-restart-policy','a2a-send','a2a-list','a2a-post','a2a-poll','a2a-ack','a2a-reject','a2a-status','a2a-prune','consensus','consensus-status','consensus-history','pipeline','agent-list','agent-register','agent-status','agent-unregister','contract-list','contract-register']; internals.forEach(c => this.registerCommand(c, { category: 'builtin' })); } setLevel(n) { @@ -854,35 +854,14 @@ _autoSaveSession() { try { this.fs.mkdirRecursive('_sessions'); - var rootClone; - try { - const json = JSON.stringify(this.fs.root); - if (json.length > 52428800) { // 50MB cap - rootClone = { type: 'directory', name: '/', content: {}, _truncated: true }; - this.print('⚠ Auto-save skipped (VFS too large)', 'warning'); - return; - } - rootClone = JSON.parse(json); - } catch (e) { - rootClone = { type: 'directory', name: '/', content: {}, _error: true }; - return; - } - if (rootClone && rootClone.content && rootClone.content['_sessions']) { - delete rootClone.content['_sessions']; - } const snapshot = { type: 'session', + version: 2, savedAt: new Date().toISOString(), - fsRoot: rootClone, currentPath: this.fs.currentPath, - version: 1, terminalLines: this._historyBuffer.slice(-50) }; const snapshotJson = JSON.stringify(snapshot); - if (snapshotJson.length > 52428800) { - this.print('⚠ Auto-save snapshot too large, skipping', 'warning'); - return; - } this.fs.writeFile('_sessions/_auto.json', snapshotJson); try { const ctx = localStorage.getItem('webx11_ai_context'); @@ -907,19 +886,40 @@ this.print('↻ Skipped stale auto-session backup (older than last reset)', 'info'); return; } - if (data && data.fsRoot) { + if (data.version === 2) { + // v2: metadata-only restore (VFS is persisted independently in localStorage) + this.fs.currentPath = data.currentPath || []; + this.fs.saveToStorage(); + this.updatePrompt(); + this.print('↻ Auto-restored session from ' + (data.savedAt ? new Date(data.savedAt).toLocaleTimeString() : 'recent'), 'success'); + // Optionally re-render last few terminal lines + if (data.terminalLines && Array.isArray(data.terminalLines)) { + data.terminalLines.slice(-10).forEach(line => { + const text = typeof line === 'string' ? line : (line.l || ''); + this.print(text, typeof line === 'object' ? (line.t || '') : ''); + }); + } + try { + const aiCtx = this.fs.readFile('_sessions/_auto-context.json'); + if (aiCtx) { + localStorage.setItem('webx11_ai_context', aiCtx); + } + } catch (e) {} + this.fs.deleteFile('_sessions/_auto.json'); + this.fs.deleteFile('_sessions/_auto-context.json'); + } else if (data && data.fsRoot) { + // v1: full VFS restore (legacy) this.fs.root = data.fsRoot; this.fs.currentPath = data.currentPath || []; this.fs.saveToStorage(); + this.updatePrompt(); this.print('↻ Auto-restored session from ' + (data.savedAt ? new Date(data.savedAt).toLocaleTimeString() : 'recent'), 'success'); - // Defer AI context restoration (AI module loads after terminal init) try { const aiCtx = this.fs.readFile('_sessions/_auto-context.json'); if (aiCtx) { localStorage.setItem('webx11_ai_context', aiCtx); } } catch (e) {} - // v4.5.47: delete backup after successful restore so reset-mem doesn't get resurrected this.fs.deleteFile('_sessions/_auto.json'); this.fs.deleteFile('_sessions/_auto-context.json'); } @@ -1566,22 +1566,41 @@ return; } if (cmd === 'history') { - const search = args.join(' ').toLowerCase(); const entries = this.history; if (!entries.length) { this.print('No command history.', 'info'); return; } - if (search) { - const filtered = entries.map((c, i) => ({ i, c })).filter(e => e.c.toLowerCase().includes(search)); - if (!filtered.length) { this.print(`No history entries matching: ${search}`, 'info'); return; } - this.print(`=== History (matching: ${search}) ===`, 'info'); - filtered.forEach(e => this.print(` ${e.i + 1} ${e.c}`)); - } else { - this.print(`=== Command History (${entries.length} entries) ===`, 'info'); - const start = Math.max(0, entries.length - 50); - for (let i = start; i < entries.length; i++) { - this.print(` ${i + 1} ${entries[i]}`); + // Flags + if (args[0] === '--clear' || args[0] === '-c') { + this.history = []; + this.historyIndex = 0; + localStorage.removeItem('webx11_command_history'); + this.print('History cleared.', 'success'); + return; + } + if (args[0] === '--export' || args[0] === '-e') { + try { + this.fs.mkdirRecursive('system'); + this.fs.writeFile('system/history.json', JSON.stringify(entries)); + this.print('History exported to /system/history.json (' + entries.length + ' entries).', 'success'); + } catch (e) { + this.print('Export failed: ' + e.message, 'error'); } - if (entries.length > 50) this.print(`... (${entries.length - 50} older entries hidden, use history <search> to find)`); + return; + } + if (args[0] === '--search' || args[0] === '-s') { + const term = args.slice(1).join(' ').toLowerCase(); + if (!term) { this.print('Usage: history --search <term>', 'warning'); return; } + const filtered = entries.filter(e => e.toLowerCase().includes(term)); + if (!filtered.length) { this.print('No matches for: ' + term, 'info'); return; } + this.print('=== History (matching: ' + term + ') ===', 'info'); + filtered.forEach(e => this.print(' ' + e)); + return; } + let count = 50; + if (args[0] === '-n' && args[1]) count = parseInt(args[1]) || 50; + const slice = entries.slice(-count); + this.print('=== Command History (' + entries.length + ' entries) ===', 'info'); + slice.forEach(c => this.print(' ' + c)); + if (entries.length > count) this.print('... (' + (entries.length - count) + ' older, use history --search <term> to find)'); return; } for (const modName in this.moduleManager.modules) { |