aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-system.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-05-27 06:00:43 +0200
committerAgando <roduccomm@gmail.com>2026-05-27 06:00:43 +0200
commit212708b464c2bdbdd9670c00804623dca0729d2c (patch)
treeee190cbb0d1524350baea641df65aa19817744b5 /modules/core/module-system.js
parentf4d934d341056142da1212c845eeeb170fd452c2 (diff)
auto: 2026-05-27_06:00 changes
Diffstat (limited to 'modules/core/module-system.js')
-rw-r--r--modules/core/module-system.js95
1 files changed, 93 insertions, 2 deletions
diff --git a/modules/core/module-system.js b/modules/core/module-system.js
index f21946a..b561ef2 100644
--- a/modules/core/module-system.js
+++ b/modules/core/module-system.js
@@ -14,6 +14,9 @@
'factory-reset': 'factory-reset [--confirm] — Wipe all webx11_ data (VFS, config, AI profile, mindmaps, themes, all localStorage)',
'reset-vfs': 'reset-vfs [--confirm] — Clear only the virtual filesystem (keeps settings, modules, AI profile)',
'logs': 'logs [n] [LEVEL] — Show last n log entries (optionally filtered by level: INFO/WARN/ERROR)',
+ 'logrotate': 'logrotate — Rotate current.log to a dated archive (auto-cleans old)',
+ 'health-check': 'health-check — Audit VFS size, modules, logs, trash, skills, tool failures',
+ 'memory-map-export': 'memory-map-export — Generate memory map markdown from memory/index.json',
'font-size': 'font-size <8-32> — Set terminal font size (persists across sessions)',
'setfont': 'setfont <8-32> — Alias for font-size',
'smart-prompt': 'smart-prompt [on|off] — Toggle context-aware prompt (shows name, skills, sessions, memory, edits)',
@@ -92,6 +95,93 @@
this.terminal.print('--- Logs (last ' + tail.length + ') ---', 'info');
tail.forEach(l => this.terminal.print(l, l.includes('[ERROR]') ? 'error' : 'info'));
};
+ // Auto-rotate logs on startup (silently)
+ this._autoRotateLogs();
+ this.commands['logrotate'] = () => {
+ const rotated = this._autoRotateLogs(true);
+ if (rotated) {
+ this.terminal.print('Log rotated: ' + rotated, 'success');
+ } else {
+ this.terminal.print('Log rotation not needed (<50KB, <500 lines)', 'info');
+ }
+ };
+ this.commands['health-check'] = () => this._healthCheck();
+ this.commands['memory-map-export'] = () => this._memoryMapExport();
+ }
+ _autoRotateLogs(force = false) {
+ try {
+ const content = this.terminal.fs.readFile('/logs/current.log') || '';
+ const lines = content.split('\n').filter(l => l);
+ const size = content.length;
+ if (!force && size < 51200 && lines.length < 500) return null;
+ const now = new Date();
+ const stamp = now.getFullYear() + '-' +
+ String(now.getMonth()+1).padStart(2,'0') + '-' +
+ String(now.getDate()).padStart(2,'0') + '_' +
+ String(now.getHours()).padStart(2,'0') + '00';
+ this.terminal.fs.writeFile('/logs/' + stamp + '.log', content);
+ this.terminal.fs.writeFile('/logs/current.log', '');
+ // Clean oldest rotated logs (>10)
+ const logsDir = this.terminal.fs.readDir('/logs');
+ if (logsDir && logsDir.content) {
+ const rotated = Object.keys(logsDir.content)
+ .filter(k => k.endsWith('.log') && k !== 'current.log')
+ .sort();
+ while (rotated.length > 10) {
+ const oldest = rotated.shift();
+ this.terminal.fs.deleteFile('/logs/' + oldest);
+ }
+ }
+ return stamp + '.log';
+ } catch (e) { return null; }
+ }
+ _healthCheck() {
+ const fs = this.terminal.fs;
+ let warnings = 0;
+ this.terminal.print('╔══════════════════════════════════════╗', 'info');
+ this.terminal.print('║ 🔍 SYSTEM HEALTH CHECK ║', 'info');
+ this.terminal.print('╚══════════════════════════════════════╝', 'info');
+ // VFS size
+ const dump = JSON.stringify(fs.root).length;
+ const vfsOk = dump < 524288;
+ this.terminal.print(`VFS size: ${(dump/1024).toFixed(1)}KB ${vfsOk ? '✅' : '⚠️ > 512KB'}`, vfsOk ? 'info' : 'warning');
+ if (!vfsOk) warnings++;
+ // Modules
+ const modTotal = Object.keys(this.terminal.moduleManager.modules || {}).length;
+ this.terminal.print(`Modules loaded: ${modTotal} ✅`, 'info');
+ // Logs
+ const logContent = fs.readFile('/logs/current.log') || '';
+ const logLines = logContent.split('\n').filter(l => l).length;
+ this.terminal.print(`Current log: ${logLines} lines`, logLines > 500 ? 'warning' : 'info');
+ if (logLines > 500) warnings++;
+ // Trash
+ const trashList = fs.listTrash ? fs.listTrash() : [];
+ this.terminal.print(`Trash items: ${trashList.length}`, 'info');
+ // Skills
+ const skillIdx = fs.fsReadJSON ? (fs.fsReadJSON('/skills/index.json') || {}) : {};
+ const skillCount = Object.keys(skillIdx).length;
+ this.terminal.print(`Skills: ${skillCount}`, skillCount > 0 ? 'info' : 'warning');
+ if (skillCount === 0) warnings++;
+ // Summary
+ this.terminal.print('─'.repeat(40), 'text-muted');
+ if (warnings === 0) {
+ this.terminal.print('All checks passed ✅', 'success');
+ } else {
+ this.terminal.print(`${warnings} warning(s) found`, 'warning');
+ }
+ }
+ _memoryMapExport() {
+ const fs = this.terminal.fs;
+ const idx = fs.fsReadJSON ? (fs.fsReadJSON('/memory/index.json') || {}) : null;
+ if (!idx) {
+ this.terminal.print('No memory index found at /memory/index.json', 'error');
+ return;
+ }
+ this.terminal.print('---\nname: adaptive-memory-map\ndescription: Auto-generated from memory/index.json\ntags: [memory, context, tracking, adaptation]\ncategory: system\n---\n', 'info');
+ for (const [k,v] of Object.entries(idx)) {
+ this.terminal.print(`## ${k}\n- Tasks: ${v.tasks || 0}\n- Updated: ${v.updated || 'unknown'}\n- Summary: ${(v.summary || '').substring(0,100)}...`, 'info');
+ }
+ this.terminal.print('(Not saved — render to file with memory-map-export > /memory/reference.md if desired)', 'text-muted');
}
handleHelp(args) {
const helpMap = this.terminal.moduleManager.getAllHelp();
@@ -116,8 +206,9 @@
files: ['ls','ll','cat','put','rm','mv','cp','mkdir','rmdir','cd','pwd','find','grep','head','tail','sort','wc','touch','tree','du','upload','download','vfs-export','vfs-import','edit','diff'],
ai: ['ai','ask','ai-clear','ai-system','ai-context','ai-allow','ai-deny','ai-stop','ai-model'],
search: ['search','s','ddg','duck','fetch','web','extract'],
- tools: ['calc','cron-every','cron-list','cron-stop','cron-clear','wpm','mindmap','theme','voice','alias','unalias'],
- system: ['help','clear','cls','echo','mem','status','font-size','setfont','smart-prompt','logs','preview','factory-reset','reset-vfs'],
+ tools: ['calc','cron-every','cron-list','cron-stop','cron-clear','wpm','mindmap','theme','voice','alias','unalias',
+ 'which','env','date','cal','yes','seq','base64','printf','cut','uniq','hostname','whoami','basename','dirname','sleep','expand'],
+ system: ['help','clear','cls','echo','mem','status','font-size','setfont','smart-prompt','logs','preview','factory-reset','reset-vfs','export','unset','script','set','test'],
net: ['server','servers','server-check','server-remove','monitor'],
mods: ['modules','listmods','loadmod','removemod','load-local','loadlocal','startup-modules'],
ollama: ['ollama','ollamaconnect','ollamadisconnect','ollamamodels','ollamasetmodel','ollamasetproxy','models','model-info','model-pull','model-delete','model-run'],