From 4b69d3666a8d842d07df2689200a364b8fdd662e Mon Sep 17 00:00:00 2001 From: Agando Date: Fri, 23 Oct 2026 20:59:29 +0200 Subject: fix(newos4): outboxResult scoped, markdown mime, old reply path retired (v4.6.81) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit delegateTask declared `const outboxResult` inside the AI branch and returned it outside, so a delegation with the AI module missing threw 'outboxResult is not defined'. The catch turned that into _handleAgentFailure: the worker stayed idle with no result while spawn_agent reported ok — the reported symptom exactly. Now function-scoped, and the no-module path returns 'queued — AI module not loaded, nothing executed' rather than claiming 'completed'. Also: nginx served _docs/*.md as application/octet-stream (no .md type) — now text/markdown + nosniff; agent-replies.php returns 410 for GET as well as POST, so there is one reply path. Verified: with the AI module deleted at runtime, delegateTask returns the queued string and throws nothing. --- modules/core/core-bundle.js | 9 +++++++-- modules/core/module-loader.js | 2 +- modules/core/module-orchestrator.js | 9 +++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'modules/core') diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index 73f5ab3..b565365 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -16721,6 +16721,10 @@ class OrchestratorModule { // Single sub-task — fall through to normal path } + // Declared in function scope: the AI branch assigns it, but the return at the end of + // this method runs even when that branch never did. + let outboxResult = null; + // Find an idle agent and immediately stamp it busy (atomic claim) let agent = Object.values(this._agents).find(a => a.status === 'idle'); if (agent) { @@ -16809,7 +16813,7 @@ class OrchestratorModule { this.terminal.print(`✅ ${agent.id} completed task`, 'success'); // Return result for callers that await delegateTask - const outboxResult = typeof result === 'string' ? result : (result?.content || 'completed'); + outboxResult = typeof result === 'string' ? result : (result?.content || 'completed'); // Check restart policy — if always, set back to idle for next task if (agent.restartPolicy === 'always') { @@ -16820,6 +16824,7 @@ class OrchestratorModule { } } else { this.terminal.print(`ℹ️ AI module not available — task queued for ${agent.id}`, 'info'); + outboxResult = 'queued — AI module not loaded, nothing executed'; } } catch (e) { this._handleAgentFailure(agent.id, e.message); @@ -16835,7 +16840,7 @@ class OrchestratorModule { agent.status = 'idle'; agent.lastHeartbeat = Date.now(); } - return outboxResult || 'completed'; + return outboxResult || 'no result recorded'; } // ─── Recurring Scheduling ─── diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js index acff509..74e3a86 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.80'; + const LATEST_VER = 'v4.6.81'; const CACHE = '?v=' + LATEST_VER; const stored = localStorage.getItem('webx11_cache_ver'); if (stored !== LATEST_VER) { diff --git a/modules/core/module-orchestrator.js b/modules/core/module-orchestrator.js index b3b76cd..5e03b0b 100644 --- a/modules/core/module-orchestrator.js +++ b/modules/core/module-orchestrator.js @@ -1153,6 +1153,10 @@ class OrchestratorModule { // Single sub-task — fall through to normal path } + // Declared in function scope: the AI branch assigns it, but the return at the end of + // this method runs even when that branch never did. + let outboxResult = null; + // Find an idle agent and immediately stamp it busy (atomic claim) let agent = Object.values(this._agents).find(a => a.status === 'idle'); if (agent) { @@ -1241,7 +1245,7 @@ class OrchestratorModule { this.terminal.print(`✅ ${agent.id} completed task`, 'success'); // Return result for callers that await delegateTask - const outboxResult = typeof result === 'string' ? result : (result?.content || 'completed'); + outboxResult = typeof result === 'string' ? result : (result?.content || 'completed'); // Check restart policy — if always, set back to idle for next task if (agent.restartPolicy === 'always') { @@ -1252,6 +1256,7 @@ class OrchestratorModule { } } else { this.terminal.print(`ℹ️ AI module not available — task queued for ${agent.id}`, 'info'); + outboxResult = 'queued — AI module not loaded, nothing executed'; } } catch (e) { this._handleAgentFailure(agent.id, e.message); @@ -1267,7 +1272,7 @@ class OrchestratorModule { agent.status = 'idle'; agent.lastHeartbeat = Date.now(); } - return outboxResult || 'completed'; + return outboxResult || 'no result recorded'; } // ─── Recurring Scheduling ─── -- cgit v1.2.3