diff options
| author | Agando <roduccomm@gmail.com> | 2026-10-22 01:23:47 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-10-22 01:23:47 +0200 |
| commit | 8dd236e7a03b3cfe3cfb4a0d77b62ce112e4d418 (patch) | |
| tree | 807a8736b0c711b8d7d9a3b667df67d78165ca5d /modules/core | |
| parent | 70b9a2f8cc2b249362ca4893fdbb6703c0ea7b8a (diff) | |
fix(newos4): dashboard shows the real world model and stops dying after 10 s (v4.6.51)
Two defects, both verified live before/after:
1. The World Model panel always said "Not synthesized yet". The page had a
renderer for data.worldModel and _collectDashboardData() never set it -- the
model was right there in WorldModelModule._model. Now collected and mapped to
the renderer's exact keys (model has modules.loaded/skills.count/memory.nodes,
the page reads modules/skills/memoryNodes), plus changesSinceLastSnapshot and
the recent-error sample, with an honest "not synthesized" fallback.
2. The page discarded any payload older than 10 s and its own 5 s auto-refresh
then showed "Cannot connect to newOS4". Stale payloads are now rendered with
their age ("Data as of 1:20:14 AM - 3m ago"), labelled amber past 5 min.
Also: the Refresh button wrote a localStorage key nobody read -> the terminal now
listens for it and re-collects (page says "No terminal tab answered" when no
terminal tab is open); storage events repaint instantly; the dead /api/dashboard
fetch (404 on all three paths, 5 s stall) is gone; `dashboard --watch` / `--stop`
re-collects every 5 s; header says the data is this browser's instance.
Verified v4.6.51: panel rows "Synthesized 34s ago / v4.6.51 / 46-22 / 136-3 /
1 nodes 0 edges / OK / none recorded"; 130 s-old payload still renders with
"- 3m ago" and no banner (previously "Cannot connect"); storage event moves the
footer 13s -> 0s; watch timer advances the payload, --stop clears it; mobile
360/390 px all OK; 0 console errors.
Diffstat (limited to 'modules/core')
| -rw-r--r-- | modules/core/core-bundle.js | 73 | ||||
| -rw-r--r-- | modules/core/module-aiassist.js | 31 | ||||
| -rw-r--r-- | modules/core/module-loader.js | 2 | ||||
| -rw-r--r-- | modules/core/terminal.js | 42 |
4 files changed, 125 insertions, 23 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index 2264ef0..245f2bd 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -2918,6 +2918,16 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm this.hideAutocomplete(); } }); + // 2026-10-22: dashboard.html wrote this key on β³ Refresh and nothing listened. + window.addEventListener('storage', function (ev) { + if (ev.key !== 'webx11_dashboard_data_request') return; + const aiMod = this.moduleManager && this.moduleManager.modules + ? this.moduleManager.modules.WebX11AIAssistantModule : null; + if (aiMod && typeof aiMod._collectDashboardData === 'function') { + aiMod._collectDashboardData(); + } + }.bind(this)); + window.addEventListener('online', () => this.updateNetworkStatus()); window.addEventListener('offline', () => this.updateNetworkStatus()); document.getElementById('file-upload-input').addEventListener('change', (e) => { @@ -4014,18 +4024,28 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm if (cmd === 'smart-prompt') { const val = args[0] && args[0] === 'off' ? 'off' : 'on'; localStorage.setItem('webx11_smart_prompt', val); this.print('Smart prompt ' + val, 'success'); this.updatePrompt(); return; } if (cmd === 'mem') { this.printMemoryStats(); return; } if (cmd === 'dashboard') { - // Collect dashboard data and open the dashboard page - const aiMod = this.moduleManager?.modules?.WebX11AIAssistantModule; - if (aiMod && typeof aiMod._collectDashboardData === 'function') { - aiMod._collectDashboardData().then(function() { - this.print('π Dashboard data collected β opening dashboard...', 'success'); - window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); - }.bind(this)); - } else { - // Fallback: just open the page (it will try localStorage) - this.print('π Opening dashboard...', 'info'); - window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); + const aiMod = this.moduleManager && this.moduleManager.modules + ? this.moduleManager.modules.WebX11AIAssistantModule : null; + const collect = function () { + if (aiMod && typeof aiMod._collectDashboardData === 'function') return aiMod._collectDashboardData(); + return Promise.resolve(null); + }; + if (args.indexOf('--stop') !== -1) { + if (this._dashTimer) { clearInterval(this._dashTimer); this._dashTimer = null; this.print('π Dashboard watch stopped', 'info'); } + else this.print('π Dashboard watch is not running', 'warning'); + return; + } + if (args.indexOf('--watch') !== -1) { + if (this._dashTimer) clearInterval(this._dashTimer); + collect(); + this._dashTimer = setInterval(collect, 5000); + this.print('π Dashboard watch on (5s) β open the dashboard tab; `dashboard --stop` to stop', 'success'); + return; } + collect().then(function () { + this.print('π Dashboard data collected β opening dashboard...', 'success'); + window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); + }.bind(this)); return; } if (cmd === 'config') { @@ -12794,6 +12814,37 @@ buildSystemPrompt() { predictorAccuracy: predictorAcc }; + // 2026-10-22: the panel had a renderer and no collector, so it always said + // "Not synthesized yet" while WorldModelModule._model was right there. + // Map the model shape (modules.loaded, skills.count, files.total, memory.nodesβ¦) + // onto the keys the page reads (modules, skills, files, memoryNodesβ¦). + try { + var wm = mm ? mm.modules['WorldModelModule'] : null; + var wmModel = wm && wm._model; + if (wmModel) { + data.worldModel = { + synthesized: wmModel.synthesized || null, + version: wmModel.version || '?', + modules: wmModel.modules ? wmModel.modules.loaded : null, + skills: wmModel.skills ? wmModel.skills.count : null, + files: wmModel.files ? wmModel.files.total : null, + agents: wmModel.agents ? wmModel.agents.agents : null, + memoryNodes: wmModel.memory ? wmModel.memory.nodes : null, + memoryEdges: wmModel.memory ? wmModel.memory.edges : null, + health: wmModel.system ? wmModel.system.health : null, + activeProjects: ((wmModel.projects && wmModel.projects.activeProjects) || []) + .map(function (p) { return p.name + ' (' + p.accesses + 'x)'; }), + recent: (wmModel.recent || []).slice(0, 5), + changes: (typeof wm._diffSincePrev === 'function') ? wm._diffSincePrev() : [], + errors: (typeof wm._errorSample === 'function') ? wm._errorSample() : [] + }; + } else { + data.worldModel = { missing: true }; + } + } catch (e) { + data.worldModel = { missing: true, error: e.message }; + } + data.timestamp = Date.now(); // Write to localStorage for the dashboard HTML page to read diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js index a8c0ae1..abbe9ce 100644 --- a/modules/core/module-aiassist.js +++ b/modules/core/module-aiassist.js @@ -4632,6 +4632,37 @@ buildSystemPrompt() { predictorAccuracy: predictorAcc }; + // 2026-10-22: the panel had a renderer and no collector, so it always said + // "Not synthesized yet" while WorldModelModule._model was right there. + // Map the model shape (modules.loaded, skills.count, files.total, memory.nodesβ¦) + // onto the keys the page reads (modules, skills, files, memoryNodesβ¦). + try { + var wm = mm ? mm.modules['WorldModelModule'] : null; + var wmModel = wm && wm._model; + if (wmModel) { + data.worldModel = { + synthesized: wmModel.synthesized || null, + version: wmModel.version || '?', + modules: wmModel.modules ? wmModel.modules.loaded : null, + skills: wmModel.skills ? wmModel.skills.count : null, + files: wmModel.files ? wmModel.files.total : null, + agents: wmModel.agents ? wmModel.agents.agents : null, + memoryNodes: wmModel.memory ? wmModel.memory.nodes : null, + memoryEdges: wmModel.memory ? wmModel.memory.edges : null, + health: wmModel.system ? wmModel.system.health : null, + activeProjects: ((wmModel.projects && wmModel.projects.activeProjects) || []) + .map(function (p) { return p.name + ' (' + p.accesses + 'x)'; }), + recent: (wmModel.recent || []).slice(0, 5), + changes: (typeof wm._diffSincePrev === 'function') ? wm._diffSincePrev() : [], + errors: (typeof wm._errorSample === 'function') ? wm._errorSample() : [] + }; + } else { + data.worldModel = { missing: true }; + } + } catch (e) { + data.worldModel = { missing: true, error: e.message }; + } + data.timestamp = Date.now(); // Write to localStorage for the dashboard HTML page to read diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js index 64ece7c..46aad17 100644 --- a/modules/core/module-loader.js +++ b/modules/core/module-loader.js @@ -4,7 +4,7 @@ // Core module bundle loaded synchronously in main.html. // This loader only handles version cache-busting, splash, terminal init, and optional ext modules. - const LATEST_VER = 'v4.6.50'; + const LATEST_VER = 'v4.6.51'; const CACHE = '?v=' + LATEST_VER; const stored = localStorage.getItem('webx11_cache_ver'); if (stored !== LATEST_VER) { diff --git a/modules/core/terminal.js b/modules/core/terminal.js index 425c5d6..c586538 100644 --- a/modules/core/terminal.js +++ b/modules/core/terminal.js @@ -479,6 +479,16 @@ this.hideAutocomplete(); } }); + // 2026-10-22: dashboard.html wrote this key on β³ Refresh and nothing listened. + window.addEventListener('storage', function (ev) { + if (ev.key !== 'webx11_dashboard_data_request') return; + const aiMod = this.moduleManager && this.moduleManager.modules + ? this.moduleManager.modules.WebX11AIAssistantModule : null; + if (aiMod && typeof aiMod._collectDashboardData === 'function') { + aiMod._collectDashboardData(); + } + }.bind(this)); + window.addEventListener('online', () => this.updateNetworkStatus()); window.addEventListener('offline', () => this.updateNetworkStatus()); document.getElementById('file-upload-input').addEventListener('change', (e) => { @@ -1575,18 +1585,28 @@ if (cmd === 'smart-prompt') { const val = args[0] && args[0] === 'off' ? 'off' : 'on'; localStorage.setItem('webx11_smart_prompt', val); this.print('Smart prompt ' + val, 'success'); this.updatePrompt(); return; } if (cmd === 'mem') { this.printMemoryStats(); return; } if (cmd === 'dashboard') { - // Collect dashboard data and open the dashboard page - const aiMod = this.moduleManager?.modules?.WebX11AIAssistantModule; - if (aiMod && typeof aiMod._collectDashboardData === 'function') { - aiMod._collectDashboardData().then(function() { - this.print('π Dashboard data collected β opening dashboard...', 'success'); - window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); - }.bind(this)); - } else { - // Fallback: just open the page (it will try localStorage) - this.print('π Opening dashboard...', 'info'); - window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); + const aiMod = this.moduleManager && this.moduleManager.modules + ? this.moduleManager.modules.WebX11AIAssistantModule : null; + const collect = function () { + if (aiMod && typeof aiMod._collectDashboardData === 'function') return aiMod._collectDashboardData(); + return Promise.resolve(null); + }; + if (args.indexOf('--stop') !== -1) { + if (this._dashTimer) { clearInterval(this._dashTimer); this._dashTimer = null; this.print('π Dashboard watch stopped', 'info'); } + else this.print('π Dashboard watch is not running', 'warning'); + return; } + if (args.indexOf('--watch') !== -1) { + if (this._dashTimer) clearInterval(this._dashTimer); + collect(); + this._dashTimer = setInterval(collect, 5000); + this.print('π Dashboard watch on (5s) β open the dashboard tab; `dashboard --stop` to stop', 'success'); + return; + } + collect().then(function () { + this.print('π Dashboard data collected β opening dashboard...', 'success'); + window.open('/spaces/newos4/downloads/dashboard.html', 'newOS4 Dashboard', 'width=1200,height=800'); + }.bind(this)); return; } if (cmd === 'config') { |