diff options
| author | Agando <roduccomm@gmail.com> | 2026-06-04 06:01:04 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-06-04 06:01:04 +0200 |
| commit | a5023e61be61f2f2287342039addab6bb28ad2fd (patch) | |
| tree | 9b1b3c166869cd6fee91bffe1f4134513005b8b1 /modules/core/module-aiassist.js | |
| parent | 301f75ab03302a05b3c35950a3b0ab49f9f69ed6 (diff) | |
auto: 2026-06-04_06:00 changes
Diffstat (limited to 'modules/core/module-aiassist.js')
| -rw-r--r-- | modules/core/module-aiassist.js | 208 |
1 files changed, 195 insertions, 13 deletions
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js index eb41af9..cb1482f 100644 --- a/modules/core/module-aiassist.js +++ b/modules/core/module-aiassist.js @@ -418,6 +418,56 @@ RULES: required: ['role'] } } + }, { + type: 'function', + function: { + name: 'nvfs_resolve', + description: 'Search VFS files by semantic concept using Neural VFS index. Call nvfs-index first to build the index.', + parameters: { + type: 'object', + properties: { + concept: { type: 'string', description: 'Concept to search (e.g. skill, memory, module, webdav, security)' } + }, + required: ['concept'] + } + } + }, { + type: 'function', + function: { + name: 'list_available_modules', + description: 'List all available modules with metadata (core/ext, commands, class name, layer). Filter by type with type=core or type=ext.', + parameters: { + type: 'object', + properties: { + type: { type: 'string', description: 'Optional: filter to "core" or "ext"' } + }, + required: [] + } + } + }, { + type: 'function', + function: { + name: 'smart_context_list', + description: 'List available AI context profiles (e.g. coding, debug, creative, technical). Returns profile names and system prompts.', + parameters: { + type: 'object', + properties: {}, + required: [] + } + } + }, { + type: 'function', + function: { + name: 'smart_context_set', + description: 'Set the active AI context profile. Changes the AI\'s behavior (temperature, style) for subsequent responses.', + parameters: { + type: 'object', + properties: { + name: { type: 'string', description: 'Profile name (e.g. "coding", "debug", "creative", "technical", "chat")' } + }, + required: ['name'] + } + } }]; } getHelpInfo() { @@ -695,6 +745,9 @@ RULES: duration: t1, error: this._isToolError(toolResult) ? true : false }); + // Telemetry + const sm = this.terminal.moduleManager.modules['ServerMonitorModule']; + if (sm && sm.logToolCall) sm.logToolCall(fn.name, (t1 * 1000) || 1, this._isToolError(toolResult)); if (this._debugPanelEnabled) this._updateDebugPanel(); return { fn, toolResult, t1 }; })); @@ -734,6 +787,9 @@ RULES: duration: t1, error: this._isToolError(toolResult) ? true : false }); + // Telemetry + const sm2 = this.terminal.moduleManager.modules['ServerMonitorModule']; + if (sm2 && sm2.logToolCall) sm2.logToolCall(fn.name, (t1 * 1000) || 1, this._isToolError(toolResult)); if (this._debugPanelEnabled) this._updateDebugPanel(); const dObs = this._summarizeObservation(toolResult, 150); const dErr = this._isToolError(toolResult); @@ -1338,6 +1394,76 @@ RULES: .filter(s => !filterCat || (s.category || '').toLowerCase() === filterCat); return JSON.stringify({ skills: list, count: list.length }); } + case 'nvfs_resolve': { + const concept = (a.concept || '').toLowerCase(); + if (!concept) return JSON.stringify({ error: 'Concept is required' }); + const nvfs = this.terminal.moduleManager.modules['NeuralVFSModule']; + if (!nvfs) return JSON.stringify({ error: 'Neural VFS module not loaded — run nvfs-index first' }); + // Build index if empty + if (Object.keys(nvfs.index).length === 0) { + const saved = this.terminal.fs.fsReadJSON('/.semantic_index/map.json'); + if (saved) { nvfs.index = saved; } + else { return JSON.stringify({ error: 'No semantic index found — run nvfs-index first' }); } + } + const exact = nvfs.index[concept]; + const fuzzy = Object.keys(nvfs.index).filter(k => + k.includes(concept) || concept.includes(k) + ).filter(k => k !== concept); + const results = []; + if (exact) results.push(...exact.map(e => ({ concept, path: e.path, summary: e.summary }))); + for (const f of fuzzy.slice(0, 5)) { + results.push(...nvfs.index[f].slice(0, 3).map(e => ({ concept: f, path: e.path, summary: e.summary }))); + } + return JSON.stringify({ concept, exact: !!exact, count: results.length, results: results.slice(0, 20) }); + } + case 'list_available_modules': { + try { + const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || '')); + if (!resp.ok) return JSON.stringify({ error: 'Module index not available' }); + const idx = await resp.json(); + const filterType = (a.type || '').toLowerCase(); + let mods = Object.values(idx.modules); + if (filterType) mods = mods.filter(m => m.type === filterType); + return JSON.stringify({ + total: mods.length, + available: idx.total, + type: filterType || 'all', + modules: mods.map(m => ({ + name: m.name, + type: m.type, + class: m.class, + commands: m.commands.slice(0, 8), + description: (m.description || '').substring(0, 80), + auto_load: m.auto_load + })) + }); + } catch (e) { return JSON.stringify({ error: 'Failed to load module index: ' + e.message }); } + } + case 'smart_context_list': { + const scm = this.terminal.moduleManager.modules['SmartContextModule']; + if (!scm) return JSON.stringify({ error: 'SmartContextModule not loaded', profiles: [] }); + const profiles = scm.contextProfiles || {}; + return JSON.stringify({ + profiles: Object.entries(profiles).map(([key, p]) => ({ + name: key, + displayName: p.name || key, + systemPrompt: (p.systemPrompt || '').substring(0, 80), + temperature: p.temperature || 0.7, + active: scm.activeProfile === key + })) + }); + } + case 'smart_context_set': { + const scm = this.terminal.moduleManager.modules['SmartContextModule']; + if (!scm) return JSON.stringify({ error: 'SmartContextModule not loaded' }); + const name = (a.name || '').toLowerCase(); + if (!scm.contextProfiles[name]) { + return JSON.stringify({ error: `Profile '${name}' not found`, available: Object.keys(scm.contextProfiles) }); + } + scm.activeProfile = name; + const profile = scm.contextProfiles[name]; + return JSON.stringify({ success: true, name, displayName: profile.name, systemPrompt: profile.systemPrompt, temperature: profile.temperature }); + } case 'view_module': case 'edit_module': case 'test_module': @@ -1364,16 +1490,41 @@ RULES: const code = this.terminal.fs.readFile(`_mods/${modName}.js`); if (code) return code; const url = entry ? entry.url : null; - if (!url) return JSON.stringify({ error: `No source URL for ${modName}` }); + // Try registry URL first + if (url) { + try { + const resp = await fetch(url); + if (resp.ok) { + const src = await resp.text(); + this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src); + return src.substring(0, 8000); + } + } catch (e) { /* fall through */ } + } + // Fallback: use modules-index.json to map class name to filename try { - const resp = await fetch(url); - if (resp.ok) { - const src = await resp.text(); - this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src); - return src.substring(0, 8000); + const idxResp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || '')); + if (idxResp.ok) { + const idx = await idxResp.json(); + // modName is the class name (e.g. "WebX11AIAssistantModule") + // or already a filename (e.g. "module-aiassist") + // Try matching by class name first + let match = Object.values(idx.modules).find(m => m.class === modName); + // Then by name + if (!match) match = idx.modules[modName]; + if (match) { + const filePath = match.file; // e.g. "modules/core/module-aiassist.js" + const fetchUrl = `/spaces/newos4/${filePath}`; + const resp = await fetch(fetchUrl); + if (resp.ok) { + const src = await resp.text(); + this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src); + return src.substring(0, 8000); + } + } } - return JSON.stringify({ error: `HTTP ${resp.status}` }); - } catch (e) { return JSON.stringify({ error: e.message }); } + } catch (e) { /* fall through */ } + return JSON.stringify({ error: `Cannot find source for ${modName} — not in registry, not in modules-index.json` }); } case 'edit_module': { const modName = a.name || ''; @@ -1425,11 +1576,42 @@ RULES: const mm = this.terminal.moduleManager; const modsDir = this.terminal.fs.getCurrentDir(); const hasMods = modsDir.content['_mods'] ? !!Object.keys(modsDir.content['_mods'].content).length : false; - const modules = mm.moduleRegistry.map(m => ({ - name: m.name, url: m.url, enabled: m.enabled, - loaded: !!mm.modules[m.name], - modified: !!this.terminal.fs.readFile(`_mods/${m.name}.js`) - })); + // Load module index for file path lookup + let idxMap = {}; + try { + const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || '')); + if (resp.ok) { + const idx = await resp.json(); + for (const [name, meta] of Object.entries(idx.modules)) { + idxMap[meta.class] = '/spaces/newos4/' + meta.file; + } + } + } catch (e) {} + const modules = []; + const seen = new Set(); + for (const [className, instance] of Object.entries(mm.modules)) { + const name = instance.constructor ? instance.constructor.name : className; + if (seen.has(name)) continue; + seen.add(name); + modules.push({ + name: name, + url: idxMap[name] || null, + enabled: true, + loaded: true, + modified: !!this.terminal.fs.readFile(`_mods/${name}.js`), + source: 'loaded' + }); + } + for (const m of mm.moduleRegistry) { + if (seen.has(m.name)) continue; + seen.add(m.name); + modules.push({ + name: m.name, url: m.url || idxMap[m.name] || null, enabled: m.enabled, + loaded: !!mm.modules[m.name], + modified: !!this.terminal.fs.readFile(`_mods/${m.name}.js`), + source: m.url ? 'ext' : 'core' + }); + } return JSON.stringify({ modules, total: modules.length, hasLocalEdits: hasMods }); } default: return JSON.stringify({ error: `Unknown module tool: ${name}` }); |