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/sandbox-worker.js | |
| parent | b538577cd0a4292e4cd4ca1c9f9829fc7e133caa (diff) | |
auto: 2026-06-06_06:00 changes
Diffstat (limited to 'modules/core/sandbox-worker.js')
| -rw-r--r-- | modules/core/sandbox-worker.js | 119 |
1 files changed, 61 insertions, 58 deletions
diff --git a/modules/core/sandbox-worker.js b/modules/core/sandbox-worker.js index 5841582..696c510 100644 --- a/modules/core/sandbox-worker.js +++ b/modules/core/sandbox-worker.js @@ -5,11 +5,16 @@ let _vfs = null; let _apiProxyOrigin = null; -self.onmessage = async (e) => { - const { taskId, task, capabilities, vfsSnapshot, allowedCommands, apiProxy } = e.data; - _apiProxyOrigin = apiProxy ? new URL(apiProxy).origin : null; +// Signal ready immediately +self.postMessage({ type: 'ready' }); - const startTime = performance.now(); +self.addEventListener('message', async (e) => { + const { taskId, task, capabilities, vfsSnapshot, allowedCommands, apiProxy } = e.data || {}; + + // Must have a taskId to respond to + if (!taskId) return; + + const startTime = self.performance.now(); let toolCalls = 0; let result = ''; let error = null; @@ -17,18 +22,13 @@ self.onmessage = async (e) => { try { // Rebuild VFS from snapshot _vfs = vfsSnapshot ? JSON.parse(vfsSnapshot) : { root: { type: 'dir', content: {} }, currentPath: [] }; - - // Log start - console.log(`[Sandbox ${taskId}] Starting task: "${task.substring(0, 60)}"`); + _apiProxyOrigin = apiProxy ? new URL(apiProxy).origin : null; // Parse the task for tool use - const toolResults = {}; + const parts = (task || '').trim().split(/\s+/); + const cmd = parts.length > 0 ? parts[0].toLowerCase() : ''; const commandWhitelist = allowedCommands || ['ls', 'cat', 'echo', 'find', 'grep', 'help', 'status']; - // Execute basic commands - const parts = task.trim().split(/\s+/); - const cmd = parts[0].toLowerCase(); - if (cmd === 'ls' || cmd === 'list') { result = sandbox_ls(parts[1] || '/'); toolCalls++; @@ -50,117 +50,115 @@ self.onmessage = async (e) => { } else if (cmd === 'status') { result = sandbox_status(); toolCalls++; - } else if (capabilities.includes('run_command') && commandWhitelist.includes(cmd)) { + } else if (capabilities && capabilities.includes('run_command') && commandWhitelist.includes(cmd)) { result = sandbox_run(cmd, parts.slice(1)); toolCalls++; } else { // If the task is descriptive (not a command), run smart handling - if (capabilities.includes('list_files') || capabilities.includes('read_file')) { - // Smart mode: interpret task - const lower = task.toLowerCase(); + if (capabilities && (capabilities.includes('list_files') || capabilities.includes('read_file'))) { + const lower = (task || '').toLowerCase(); if (lower.includes('list') || lower.includes('file')) { const dir = parts.find(p => p.startsWith('/') || p.startsWith('.')) || '/'; result = sandbox_ls(dir); } else if (lower.includes('find') || lower.includes('search')) { - const q = task.replace(/find|search/i, '').trim(); + const q = (task || '').replace(/find|search/i, '').trim(); result = sandbox_find(q || ''); } else if (lower.includes('count') || lower.includes('how many')) { result = sandbox_ls('/'); const count = (result.match(/\[file\]|\[dir\]/g) || []).length; - result = `Found ${count} items in total.\\n${result}`; + result = 'Found ' + count + ' items in total.\n' + result; } else if (lower.includes('status') || lower.includes('health')) { result = sandbox_status(); } else { - result = `Task interpreted: "${task}"\\nCapabilities: ${capabilities.join(', ')}\\nTip: Be more specific (e.g. "list files in /")`; + result = 'Task interpreted: "' + (task || '') + '"\nCapabilities: ' + (capabilities || []).join(', ') + '\nTip: Be more specific (e.g. "list files in /")'; } toolCalls++; } else { - result = `Task: "${task}"\\nNo matching capability for command "${cmd}"`; + result = 'Task: "' + (task || '') + '"\nNo matching capability for command "' + cmd + '"'; } } } catch (e) { - error = e.message; - console.error(`[Sandbox ${taskId}] Error:`, e); + error = e.message || String(e); } - const duration = ((performance.now() - startTime) / 1000).toFixed(2); + const duration = ((self.performance.now() - startTime) / 1000).toFixed(2); self.postMessage({ - taskId, - result, - error, - toolCalls, + taskId: taskId, + result: result, + error: error, + toolCalls: toolCalls, duration: parseFloat(duration), vfsSnapshot: JSON.stringify(_vfs) }); -}; +}); // ─── Sandboxed VFS Operations ─── function sandbox_ls(path) { path = path || '/'; const entries = _vfs_get_entries(path); - if (!entries) return `ls: ${path}: No such directory`; - const lines = entries.map(e => { + if (!entries) return 'ls: ' + path + ': No such directory'; + const lines = entries.map(function(e) { const icon = e.type === 'dir' ? '[dir]' : '[file]'; - const size = e.size !== undefined ? ` (${e.size}B)` : ''; - return `${icon} ${e.name}${size}`; + const size = e.size !== undefined ? ' (' + e.size + 'B)' : ''; + return icon + ' ' + e.name + size; }); - return lines.join('\\n') || '(empty)'; + return lines.join('\n') || '(empty)'; } function sandbox_cat(path) { const content = _vfs_get_content(path); - if (content === null) return `cat: ${path}: No such file`; - if (typeof content === 'object') return `cat: ${path}: Is a directory`; - if (content.length > 8000) return content.substring(0, 8000) + '\\n... (truncated at 8KB)'; + if (content === null) return 'cat: ' + path + ': No such file'; + if (typeof content === 'object') return 'cat: ' + path + ': Is a directory'; + if (content.length > 8000) return content.substring(0, 8000) + '\n... (truncated at 8KB)'; return content; } function sandbox_find(query) { const results = []; const q = query ? query.toLowerCase() : ''; - _vfs_walk('/', (path, node) => { + _vfs_walk('/', function(path, node) { if (node.type === 'file') { if (!q || path.toLowerCase().includes(q)) { results.push(path); } } }); - if (results.length === 0) return `No files found${query ? ` matching "${query}"` : ''}`; - return results.join('\\n'); + if (results.length === 0) return 'No files found' + (query ? ' matching "' + query + '"' : ''); + return results.join('\n'); } function sandbox_grep(query) { if (!query) return 'grep: missing pattern'; const q = query.toLowerCase(); const results = []; - _vfs_walk('/', (path, node) => { + _vfs_walk('/', function(path, node) { if (node.type === 'file' && typeof node.content === 'string') { - const lines = node.content.split('\\n'); + const lines = node.content.split('\n'); for (let i = 0; i < lines.length; i++) { if (lines[i].toLowerCase().includes(q)) { - results.push(`${path}:${i + 1}: ${lines[i].trim().substring(0, 100)}`); + results.push(path + ':' + (i + 1) + ': ' + lines[i].trim().substring(0, 100)); } } } }); - if (results.length === 0) return `grep: no matches for "${query}"`; - return results.slice(0, 50).join('\\n') + (results.length > 50 ? `\\n... (+${results.length - 50} more)` : ''); + if (results.length === 0) return 'grep: no matches for "' + query + '"'; + return results.slice(0, 50).join('\n') + (results.length > 50 ? '\n... (+' + (results.length - 50) + ' more)' : ''); } function sandbox_status() { let fileCount = 0, dirCount = 0; - _vfs_walk('/', (path, node) => { + _vfs_walk('/', function(path, node) { if (node.type === 'file') fileCount++; else dirCount++; }); const vfsSize = JSON.stringify(_vfs).length; - return `Sandbox VFS Status:\\n Files: ${fileCount}\\n Directories: ${dirCount}\\n VFS Size: ${(vfsSize / 1024).toFixed(1)}KB`; + return 'Sandbox VFS Status:\n Files: ' + fileCount + '\n Directories: ' + dirCount + '\n VFS Size: ' + (vfsSize / 1024).toFixed(1) + 'KB'; } function sandbox_run(cmd, args) { - return `[sandbox] ${cmd} ${args.join(' ')}\\n(Command execution limited in sandbox mode)`; + return '[sandbox] ' + cmd + ' ' + args.join(' ') + '\n(Command execution limited in sandbox mode)'; } // ─── VFS Helpers ─── @@ -168,11 +166,15 @@ function sandbox_run(cmd, args) { function _vfs_get_entries(path) { const dir = _vfs_resolve(path); if (!dir || dir.type !== 'dir') return null; - return Object.entries(dir.content || {}).map(([name, node]) => ({ - name, - type: node.type || 'file', - size: typeof node.content === 'string' ? node.content.length : undefined - })).sort((a, b) => a.name.localeCompare(b.name)); + return Object.entries(dir.content || {}).map(function(entry) { + const name = entry[0]; + const node = entry[1]; + return { + name: name, + type: node.type || 'file', + size: typeof node.content === 'string' ? node.content.length : undefined + }; + }).sort(function(a, b) { return a.name.localeCompare(b.name); }); } function _vfs_get_content(path) { @@ -184,11 +186,11 @@ function _vfs_get_content(path) { function _vfs_resolve(path) { if (!_vfs || !_vfs.root) return null; if (path === '/' || path === '') return _vfs.root; - const parts = path.split('/').filter(p => p); + const parts = path.split('/').filter(function(p) { return p; }); let current = _vfs.root; - for (const part of parts) { - if (!current.content || !current.content[part]) return null; - current = current.content[part]; + for (let i = 0; i < parts.length; i++) { + if (!current.content || !current.content[parts[i]]) return null; + current = current.content[parts[i]]; } return current; } @@ -198,8 +200,9 @@ function _vfs_walk(path, cb) { if (!node) return; cb(path, node); if (node.type === 'dir' && node.content) { - for (const [name, child] of Object.entries(node.content)) { - _vfs_walk(path === '/' ? '/' + name : path + '/' + name, cb); + const names = Object.keys(node.content); + for (let i = 0; i < names.length; i++) { + _vfs_walk(path === '/' ? '/' + names[i] : path + '/' + names[i], cb); } } }
\ No newline at end of file |