diff options
| author | Agando <roduccomm@gmail.com> | 2026-06-06 06:00:27 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-06-06 06:00:27 +0200 |
| commit | ccc7d9956559d2195e20345e7a794662b52cd403 (patch) | |
| tree | 757354fbfec5c75b4577b2cb620d5ab1582e19b1 /modules/core/module-sandbox.js | |
| parent | b538577cd0a4292e4cd4ca1c9f9829fc7e133caa (diff) | |
auto: 2026-06-06_06:00 changes
Diffstat (limited to 'modules/core/module-sandbox.js')
| -rw-r--r-- | modules/core/module-sandbox.js | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/modules/core/module-sandbox.js b/modules/core/module-sandbox.js index dc8dc76..67b8357 100644 --- a/modules/core/module-sandbox.js +++ b/modules/core/module-sandbox.js @@ -33,7 +33,7 @@ class SandboxModule { init(terminal) { this.terminal = terminal; - this.workerUrl = '/spaces/newos4/modules/core/sandbox-worker.js'; + this.workerUrl = '/spaces/newos4/modules/core/sandbox-worker.js?v=2026-06-05-v4.4.0'; // Detect Worker availability if (typeof Worker === 'undefined') { @@ -41,6 +41,19 @@ class SandboxModule { this.terminal.print('⚠️ WebWorkers not available — sandbox using inline fallback', 'warning'); } else { this._initPool(); + // Deferred check: workers may fail asynchronously (headless browsers) + // If no worker proves alive within 1.5s, switch to inline fallback + this._workerCheckTimer = setTimeout(() => { + if (!this._fallbackMode && this.workers.length > 0) { + const alive = this.workers.some(w => !w._failed && this._workerReady[w._sandboxId]); + if (!alive) { + this._fallbackMode = true; + this.workers.forEach(w => w.terminate()); + this.workers = []; + this.terminal.print('⚠️ WebWorkers unavailable — switching to inline fallback', 'warning'); + } + } + }, 1500); } this.terminal.print('🧪 Sandbox module loaded', 'info'); @@ -49,44 +62,65 @@ class SandboxModule { _initPool() { // Start with MIN_WORKERS, grow on demand up to MAX_WORKERS for (let i = 0; i < this.MIN_WORKERS; i++) { - this._spawnWorker(); + const w = this._spawnWorker(); + if (!w) break; // first failure kills the pool } } _spawnWorker() { if (this.workers.length >= this.MAX_WORKERS) return null; + if (this._fallbackMode) return null; try { const worker = new Worker(this.workerUrl); const id = `w${this.workers.length + 1}`; worker._sandboxId = id; worker._busy = false; + worker._failed = false; - worker.onmessage = (e) => this._handleResult(e.data, id); + // Detect immediate worker failure (headless browsers, restricted contexts) + const failTimer = setTimeout(() => { + if (!worker._failed) { + // Worker survived 2 seconds - likely functional + } + }, 2000); + + worker.onmessage = (e) => { + clearTimeout(failTimer); + if (e.data && e.data.type === 'ready') { + this._workerReady[id] = true; + } else { + this._handleResult(e.data, id); + } + }; worker.onerror = (e) => { - console.error(`[Sandbox] Worker ${id} error:`, e.message); - this._totalErrors++; - this._replaceWorker(id); + clearTimeout(failTimer); + worker._failed = true; + worker.terminate(); + console.warn(`[Sandbox] Worker ${id} failed (headless env) — switching to inline`); + this._fallbackMode = true; + this.workers.forEach(w => w.terminate()); + this.workers = []; + this.terminal.print('⚠️ WebWorkers unavailable in this environment — using inline fallback', 'warning'); }; this.workers.push(worker); - this._workerReady[id] = true; return worker; } catch (e) { - console.error('[Sandbox] Failed to spawn worker:', e); + console.warn('[Sandbox] Failed to spawn worker:', e); this._fallbackMode = true; return null; } } _replaceWorker(id) { + // In headless environments, workers don't work — don't retry + if (this._fallbackMode) return; const idx = this.workers.findIndex(w => w._sandboxId === id); if (idx !== -1) { this.workers[idx].terminate(); this.workers.splice(idx, 1); delete this._workerReady[id]; } - // Re-spawn after a delay - setTimeout(() => this._spawnWorker(), 1000); } _getIdleWorker() { @@ -104,7 +138,13 @@ class SandboxModule { async runInSandbox(task, capabilities) { if (!task) return this.terminal.print('Usage: sandbox-run <task>', 'error'); - if (this._fallbackMode) { + // Check if any worker is actually alive and ready + const hasAliveWorker = this.workers.some(w => + !w._failed && this._workerReady[w._sandboxId] + ); + const useInline = this._fallbackMode || this.workers.length === 0 || !hasAliveWorker; + + if (useInline) { return this._runInline(task, capabilities); } |