aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.html70
-rw-r--r--modules/core/module-aiassist.js106
-rw-r--r--modules/core/ollama-manager.js25
-rw-r--r--modules/core/terminal.js130
-rw-r--r--skills/agent-optimization-framework.md31
-rw-r--r--skills/index.json134
-rw-r--r--skills/macro-engine-debug.md10
-rw-r--r--skills/macro-engine-onboarding.md10
-rw-r--r--skills/project-profile-manager.md25
9 files changed, 404 insertions, 137 deletions
diff --git a/main.html b/main.html
index 16a189d..a8fa9c9 100644
--- a/main.html
+++ b/main.html
@@ -315,6 +315,26 @@
}
.ollama-status.connected { background: rgba(0, 255, 0, 0.1); border: 1px solid var(--success-color); }
.ollama-status.disconnected { background: rgba(255, 85, 85, 0.1); border: 1px solid var(--error-color); }
+ /* Toggle slider styles */
+ #ollama-optimization-slider::before, #ollama-validator-slider::before {
+ content: "";
+ position: absolute;
+ height: 20px;
+ width: 20px;
+ left: 2px;
+ bottom: 2px;
+ background: var(--text-color);
+ border-radius: 50%;
+ transition: 0.3s;
+ }
+ #ollama-optimization-toggle:checked + #ollama-optimization-slider::before,
+ #ollama-validator-toggle:checked + #ollama-validator-slider::before {
+ transform: translateX(22px);
+ }
+ #ollama-optimization-toggle:checked + #ollama-optimization-slider,
+ #ollama-validator-toggle:checked + #ollama-validator-slider {
+ border-color: var(--success-color);
+ }
.copy-btn {
position: absolute;
top: 5px;
@@ -635,6 +655,56 @@
</select>
<button class="btn" onclick="webx11.setOllamaModel()" style="width: 100%;">Set Model</button>
</div>
+ <hr style="border-color:var(--border-color); margin: 15px 0;">
+ <h4 style="color: var(--accent-color); margin-bottom: 10px;">⚡ AI Agent Optimization</h4>
+ <div style="display:flex; align-items:center; gap:10px; margin-bottom: 12px;">
+ <span style="color:var(--text-muted); font-size:0.85em;">Agent Loop Optimizations:</span>
+ <label style="position:relative; display:inline-block; width:48px; height:26px;">
+ <input type="checkbox" id="ollama-optimization-toggle" onchange="webx11.toggleOptimization()" style="opacity:0; width:0; height:0;">
+ <span id="ollama-optimization-slider" style="position:absolute; cursor:pointer; inset:0; background:var(--bg-tertiary); border:1px solid var(--border-color); border-radius:26px; transition:0.3s;"></span>
+ </label>
+ <span id="ollama-optimization-label" style="font-size:0.85em; color:var(--success-color);">Enabled</span>
+ </div>
+ <div style="font-size:0.8em; color:var(--text-muted); margin-bottom: 10px;">
+ ⚡ Tool def caching, trivial query skip, parallel safe tools, debounced reflection<br>
+ <span style="color:var(--warning-color);">Disable for debugging or if model behaves unexpectedly. Reload after toggle.</span>
+ </div>
+ <hr style="border-color:var(--border-color); margin: 15px 0;">
+ <h4 style="color: var(--info-color); margin-bottom: 10px;">🔍 Validator Agent (Future)</h4>
+ <div style="font-size:0.85em; color:var(--text-muted); margin-bottom: 10px;">
+ A separate lightweight AI that validates the main agent's tool results. Has its own
+ endpoint and model — independent from your active AI model.
+ </div>
+ <div style="display:flex; align-items:center; gap:10px; margin-bottom: 10px;">
+ <span style="color:var(--text-muted); font-size:0.85em;">Enable Validator:</span>
+ <label style="position:relative; display:inline-block; width:48px; height:26px;">
+ <input type="checkbox" id="ollama-validator-toggle" onchange="webx11.toggleValidator()" style="opacity:0; width:0; height:0;">
+ <span id="ollama-validator-slider" style="position:absolute; cursor:pointer; inset:0; background:var(--bg-tertiary); border:1px solid var(--border-color); border-radius:26px; transition:0.3s;"></span>
+ </label>
+ <span id="ollama-validator-label" style="font-size:0.85em; color:var(--text-muted);">Disabled</span>
+ </div>
+ <div style="margin-bottom: 8px;">
+ <label style="display: block; margin-bottom: 3px; color: var(--text-muted); font-size:0.85em;">Validator Endpoint:</label>
+ <input type="text" id="validator-endpoint-input" class="module-url-input" value="http://localhost:11434" placeholder="http://localhost:11434" style="margin-bottom:6px;">
+ <button class="btn" onclick="webx11.connectValidatorEndpoint()" style="width:100%; border-color:var(--info-color); color:var(--info-color);">🔌 Connect & Load Models</button>
+ <div id="validator-connection-status" style="font-size:0.8em; margin-top:4px;"></div>
+ </div>
+ <div style="margin-bottom: 10px;">
+ <label style="display: block; margin-bottom: 3px; color: var(--text-muted); font-size:0.85em;">Validator Model:</label>
+ <select id="validator-model-select" class="module-url-input" style="margin-bottom:6px;" disabled>
+ <option value="">Connect to load models</option>
+ </select>
+ <button class="btn" onclick="webx11.saveValidatorConfig()" style="width:100%; border-color:var(--info-color); color:var(--info-color);">Save Validator Config</button>
+ </div>
+ <div style="font-size:0.8em; color:var(--warning-color); border:1px solid var(--border-color); border-radius:4px; padding:10px; margin-top:10px;">
+ <strong>⚠️ Connection Notes</strong><br>
+ • Cloud models (deepseek-v4*, gemma4:*b-cloud) via Ollama proxy often <strong>ignore tool calls</strong>
+ and answer from training data instead. Use local models for tool calling.<br>
+ • To connect to local Ollama from a web page: set <code>OLLAMA_ORIGINS</code> on the server:
+ <code>export OLLAMA_ORIGINS="https://webx11.duckdns.org"</code> then restart Ollama.<br>
+ • Test local connection: open a terminal and run <code>curl http://localhost:11434/api/tags</code><br>
+ • If you see <strong>403</strong> errors in console: the <code>OLLAMA_ORIGINS</code> env var isn't matching your page URL.
+ </div>
</div>
<div class="modal-footer">
<button class="btn" onclick="webx11.closeOllamaManager()">Close</button>
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index 70882a9..602ae3e 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -35,7 +35,10 @@
const now = new Date();
const dateStr = now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
const timeStr = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
- return `Current date: ${dateStr}\nCurrent time: ${timeStr}\n\nYou are WebX11AI, the AI assistant embedded in the WebX11 browser terminal. You have direct access to read/write files, search the web, install packages, edit modules, and run terminal commands — all via tool calls. Use tools proactively. Keep responses concise.\n\n== TOOL REFERENCE ==
+ const optimizationActive = this.terminal?.ollamaManager?.optimizationEnabled !== false;
+ const CR = String.fromCharCode(10);
+ const optNote = CR + CR + '== TOOL EXECUTION RULES (STRICT) ==' + CR + 'STRICT RULE 1: NEVER describe what the filesystem looks like from your training data. ALWAYS call list_files() or read_file() first, then report the ACTUAL result.' + CR + 'STRICT RULE 2: If you return text without calling any tool, you have failed. Use tools for every factual question.' + CR + 'STRICT RULE 3: A response like "/bin/, /etc/, /home/" without calling list_files is ILLEGAL. Call the tool.' + CR + 'STRICT RULE 4: When calling a tool, base your answer ENTIRELY on the tool result. If result is empty, say "empty".' + CR + CR;
+ return `Current date: ${dateStr}\nCurrent time: ${timeStr}\n\nYou are WebX11AI, the AI assistant embedded in the WebX11 browser terminal. You have direct access to read/write files, search the web, install packages, edit modules, and run terminal commands — all via tool calls. Use tools proactively. Keep responses concise.${optNote}== TOOL REFERENCE ==
You have these tools available. Use them WITHOUT asking permission unless the tool description says (DESTRUCTIVE):
FILESYSTEM:
@@ -436,7 +439,8 @@ RULES:
}
// Auto-load skills relevant to the user's query (awaited, not fire-and-forget)
// Skip skill loading for trivial queries (< 10 chars, no actionable keywords)
- const isTrivial = userMessage.length < 10 && !/\b(search|write|install|edit|create|make|find|delete|remove|change|update|improve|add|fix|build|set|load|save|help)\b/i.test(userMessage);
+ const optEnabled = this.terminal?.ollamaManager?.optimizationEnabled !== false;
+ const isTrivial = optEnabled && userMessage.length < 10 && !/\b(search|write|install|edit|create|make|find|delete|remove|change|update|improve|add|fix|build|set|load|save|help)\b/i.test(userMessage);
if (!isTrivial) {
try {
const skillRes = await this.runTool('load_skills', { query: userMessage });
@@ -539,6 +543,42 @@ RULES:
}
return null;
}
+ _parseToolBlocksFromText(text) {
+ if (!text) return [];
+ const toolCalls = [];
+ // Match ```tool name(args) or ```tool\nname(args) blocks
+ const blockRegex = /```tool(?:\s*\n)?\s*(\w+)\s*({[^}]*})?\s*```/gi;
+ let match;
+ while ((match = blockRegex.exec(text)) !== null) {
+ const name = match[1];
+ let args = {};
+ try {
+ if (match[2]) args = JSON.parse(match[2]);
+ } catch (e) {
+ // If JSON parse fails, treat as raw string
+ args = match[2] ? { path: match[2].replace(/[{}]/g,'').trim() } : {};
+ }
+ toolCalls.push({
+ id: 'text_' + Date.now() + '_' + toolCalls.length,
+ type: 'function',
+ function: { name, arguments: args }
+ });
+ }
+ // Also handle single-line format: ```tool get_status{}
+ const simpleRegex = /```tool\s+(\w+)\s*\{([^}]*)\}\s*```/gi;
+ while ((match = simpleRegex.exec(text)) !== null) {
+ // Avoid duplicates — skip if already caught by blockRegex
+ const name = match[1];
+ if (!toolCalls.find(tc => tc.function.name === name)) {
+ toolCalls.push({
+ id: 'text_' + Date.now() + '_' + toolCalls.length,
+ type: 'function',
+ function: { name, arguments: {} }
+ });
+ }
+ }
+ return toolCalls;
+ }
_trackToolFailure(toolName, error) {
try {
const key = 'webx11_tool_failures';
@@ -571,7 +611,67 @@ RULES:
if (this._cancelled) return { finalAnswer: null, toolTurns };
if (res.error) { this.terminal.print(`⚠️ AI model error (${thinkTime}s): ${res.error}`, 'error'); return { finalAnswer: null, toolTurns }; }
if (res.message && !res.tool_calls) {
- const text = res.message.content || '';
+ let text = res.message.content || '';
+ // Fallback: parse ```tool blocks from text when model writes them instead of native tool_calls
+ let parsedToolCalls = this._parseToolBlocksFromText(text);
+ if (parsedToolCalls.length > 0) {
+ this.terminal.print(`🔧 Parsed ${parsedToolCalls.length} tool call(s) from text block — turn ${toolTurns}/${this.MAX_TOOL_TURNS} (${thinkTime}s)`, 'info');
+ // Extract any non-tool text as pending assistant content
+ const cleanText = text.replace(/```tool[\s\S]*?```/g, '').trim();
+ if (cleanText) messages.push({ role: 'assistant', content: cleanText });
+ messages.push({ role: 'assistant', content: '(calling tool via text block)' });
+ let pendingText = cleanText || null;
+ const destructiveTools = parsedToolCalls.filter(tc => this.isDestructive(tc.function.name));
+ const safeTools = parsedToolCalls.filter(tc => !this.isDestructive(tc.function.name));
+ const safeResults = await Promise.all(safeTools.map(async (tc) => {
+ const fn = tc.function;
+ const t0 = Date.now();
+ const toolResult = await this.runTool(fn.name, fn.arguments);
+ const t1 = Math.round((Date.now() - t0) / 1000);
+ return { fn, toolResult, t1 };
+ }));
+ for (const { fn, toolResult, t1 } of safeResults) {
+ this.terminal.print(`🔧 Tool: ${fn.name}(${typeof fn.arguments === 'string' ? fn.arguments : JSON.stringify(fn.arguments)})`, 'info');
+ const obs = this._summarizeObservation(toolResult, 150);
+ const err = this._isToolError(toolResult);
+ if (err) {
+ this.terminal.log('WARN', 'AI', `Tool ${fn.name} failed: ${err} (${t1}s)`);
+ this._trackToolFailure(fn.name, err);
+ this.terminal.print(`📊 Result (${t1}s): ⚠️ Error: ${err}`, 'warning');
+ } else {
+ this.terminal.log('INFO', 'AI', `Tool ${fn.name} ok (${t1}s)`);
+ this.terminal.print(`📊 Result (${t1}s): ${obs}`, 'info');
+ }
+ messages.push({ role: 'tool', content: toolResult });
+ }
+ if (destructiveTools.length > 0) {
+ const approved = await this.confirmActionMulti(destructiveTools);
+ if (approved) {
+ for (const tc of destructiveTools) {
+ const fn = tc.function;
+ const t0 = Date.now();
+ this.terminal.print(`🔧 Tool: ${fn.name}(${typeof fn.arguments === 'string' ? fn.arguments : JSON.stringify(fn.arguments)})`, 'info');
+ const toolResult = await this.runTool(fn.name, fn.arguments);
+ const t1 = Math.round((Date.now() - t0) / 1000);
+ const dObs = this._summarizeObservation(toolResult, 150);
+ const dErr = this._isToolError(toolResult);
+ if (dErr) {
+ this.terminal.log('WARN', 'AI', `Tool ${fn.name} failed: ${dErr} (${t1}s)`);
+ this._trackToolFailure(fn.name, dErr);
+ this.terminal.print(`📊 Result (${t1}s): ⚠️ Error: ${dErr}`, 'warning');
+ } else {
+ this.terminal.log('INFO', 'AI', `Tool ${fn.name} ok (${t1}s)`);
+ this.terminal.print(`📊 Result (${t1}s): ${dObs}`, 'info');
+ }
+ messages.push({ role: 'tool', content: toolResult });
+ }
+ } else {
+ messages.push({ role: 'tool', content: `Destructive actions (${destructiveTools.map(tc => tc.function.name).join(', ')}) denied.` });
+ }
+ }
+ if (pendingText) messages.push({ role: 'assistant', content: pendingText });
+ continue;
+ }
this.terminal.printAIResponse(text || '(no response)');
if (text) this.terminal.ollamaManager.fireResponseHooks(text);
this.terminal.print(`💬 AI answered (turn ${toolTurns}/${this.MAX_TOOL_TURNS}, ${thinkTime}s)`, 'info');
diff --git a/modules/core/ollama-manager.js b/modules/core/ollama-manager.js
index 3f46b13..34ece29 100644
--- a/modules/core/ollama-manager.js
+++ b/modules/core/ollama-manager.js
@@ -11,6 +11,12 @@ class OllamaManager {
this.currentModel = localStorage.getItem('webx11_ollama_model') || 'gemma4:31b-cloud';
this.responseHooks = [];
this._abortController = null;
+ // --- AI Agent Loop Optimization Toggle ---
+ this.optimizationEnabled = localStorage.getItem('webx11_optimization_enabled') !== 'false';
+ // --- Validator Agent Config (future) ---
+ this.validatorEnabled = localStorage.getItem('webx11_validator_enabled') === 'true';
+ this.validatorModel = localStorage.getItem('webx11_validator_model') || '';
+ this.validatorEndpoint = localStorage.getItem('webx11_validator_endpoint') || '';
// Build fallback endpoints
this.fallbackEndpoints = [];
const origin = typeof window !== 'undefined' ? window.location.origin : '';
@@ -900,6 +906,25 @@ class OllamaManager {
saveSettings() {
localStorage.setItem('webx11_ollama_endpoint', this.endpoint);
localStorage.setItem('webx11_ollama_model', this.currentModel);
+ localStorage.setItem('webx11_optimization_enabled', this.optimizationEnabled ? 'true' : 'false');
+ localStorage.setItem('webx11_validator_enabled', this.validatorEnabled ? 'true' : 'false');
+ localStorage.setItem('webx11_validator_model', this.validatorModel);
+ localStorage.setItem('webx11_validator_endpoint', this.validatorEndpoint || '');
+ }
+
+ setOptimizationEnabled(val) {
+ this.optimizationEnabled = !!val;
+ this.terminal?.print(`Agent optimization ${this.optimizationEnabled ? 'enabled' : 'disabled'}. Reload to apply.`, 'info');
+ this.saveSettings();
+ }
+
+ setValidatorConfig(enabled, model) {
+ this.validatorEnabled = !!enabled;
+ if (model !== undefined) {
+ this.validatorModel = model;
+ localStorage.setItem('webx11_validator_model', model);
+ }
+ this.saveSettings();
}
getModels() { return this.models; }
diff --git a/modules/core/terminal.js b/modules/core/terminal.js
index 1bfc4cd..5e6db6a 100644
--- a/modules/core/terminal.js
+++ b/modules/core/terminal.js
@@ -7,7 +7,7 @@
this.lastRouteTime = 0;
this.lastRouteCmd = '';
this.blockedCount = 0;
- this.destructiveCmds = new Set(['rm','delete','del','edit','write','save','overwrite','format','kill','stop','shutdown','reboot']);
+ this.destructiveCmds = new Set(['rm','delete','del','write','save','overwrite','format','kill','stop','shutdown','reboot']);
this.systemCmds = new Set(['reboot','shutdown','format','kill','halt','poweroff']);
this.suspiciousFlags = new Set(['--dump','--execute','--eval','--exec','--shell','--script']);
this.whitelist = new Set(['help','clear','ls','cat','pwd','whoami','df','free','top','ps','echo','date','env','history']);
@@ -1143,6 +1143,7 @@
document.getElementById('ollama-endpoint').value = this.ollamaManager.endpoint;
this.updateOllamaStatus();
this.renderOllamaModels();
+ this.initOllamaUI();
modal.style.display = 'flex';
}
closeOllamaManager() {
@@ -1392,6 +1393,133 @@
const select = document.getElementById('ollama-current-model');
this.ollamaManager.setModel(select.value);
}
+ toggleOptimization() {
+ const cb = document.getElementById('ollama-optimization-toggle');
+ const label = document.getElementById('ollama-optimization-label');
+ const slider = document.getElementById('ollama-optimization-slider');
+ const enabled = cb.checked;
+ this.ollamaManager.setOptimizationEnabled(enabled);
+ if (label) {
+ label.textContent = enabled ? 'Enabled' : 'Disabled';
+ label.style.color = enabled ? 'var(--success-color)' : 'var(--text-muted)';
+ }
+ if (slider) {
+ slider.style.background = enabled ? 'var(--accent-color)' : 'var(--bg-tertiary)';
+ slider.style.borderColor = enabled ? 'var(--success-color)' : 'var(--border-color)';
+ }
+ this.ollamaManager.saveSettings();
+ }
+ toggleValidator() {
+ const cb = document.getElementById('ollama-validator-toggle');
+ const label = document.getElementById('ollama-validator-label');
+ const slider = document.getElementById('ollama-validator-slider');
+ const enabled = cb.checked;
+ this.ollamaManager.validatorEnabled = enabled;
+ if (label) {
+ label.textContent = enabled ? 'Enabled' : 'Disabled';
+ label.style.color = enabled ? 'var(--success-color)' : 'var(--text-muted)';
+ }
+ if (slider) {
+ slider.style.background = enabled ? 'var(--info-color)' : 'var(--bg-tertiary)';
+ slider.style.borderColor = enabled ? 'var(--info-color)' : 'var(--border-color)';
+ }
+ this.ollamaManager.saveSettings();
+ }
+ saveValidatorConfig() {
+ const select = document.getElementById('validator-model-select');
+ const endpoint = document.getElementById('validator-endpoint-input')?.value?.trim() || 'http://localhost:11434';
+ const model = select ? select.value : '';
+ localStorage.setItem('webx11_validator_endpoint', endpoint);
+ this.ollamaManager.validatorEndpoint = endpoint;
+ this.ollamaManager.setValidatorConfig(this.ollamaManager.validatorEnabled, model);
+ this.print('Validator config saved. Model: ' + (model || '(none)') + ' at ' + endpoint, 'success');
+ }
+ async connectValidatorEndpoint() {
+ const endpoint = document.getElementById('validator-endpoint-input')?.value?.trim() || 'http://localhost:11434';
+ const statusEl = document.getElementById('validator-connection-status');
+ const select = document.getElementById('validator-model-select');
+ if (statusEl) statusEl.textContent = '⏳ Connecting to ' + endpoint + '...';
+ if (select) { select.disabled = true; select.innerHTML = '<option value="">Connecting...</option>'; }
+ try {
+ const resp = await fetch(endpoint + '/api/tags');
+ if (!resp.ok) throw new Error('HTTP ' + resp.status);
+ const data = await resp.json();
+ const models = data.models || [];
+ if (statusEl) statusEl.textContent = '✅ Connected: ' + models.length + ' model(s)';
+ // Populate dropdown
+ if (select) {
+ select.innerHTML = '<option value="">Select a validator model</option>';
+ models.forEach(function(m) {
+ var opt = document.createElement('option');
+ opt.value = m.name;
+ opt.textContent = m.name;
+ select.appendChild(opt);
+ });
+ select.disabled = false;
+ }
+ // Save endpoint
+ localStorage.setItem('webx11_validator_endpoint', endpoint);
+ this.ollamaManager.validatorEndpoint = endpoint;
+ this.ollamaManager.saveSettings();
+ } catch (e) {
+ if (statusEl) {
+ statusEl.innerHTML = '❌ Connection failed: ' + e.message +
+ '<br><span style="font-size:0.85em;color:var(--text-muted);">Make sure Ollama is running and ' +
+ '<code>OLLAMA_ORIGINS</code> includes this page\'s origin.</span>';
+ }
+ if (select) { select.disabled = true; select.innerHTML = '<option value="">Connection failed — try again</option>'; }
+ }
+ }
+ initOllamaUI() {
+ // Initialize optimization toggle from stored state
+ const optCb = document.getElementById('ollama-optimization-toggle');
+ const optLabel = document.getElementById('ollama-optimization-label');
+ const optSlider = document.getElementById('ollama-optimization-slider');
+ if (optCb && this.ollamaManager) {
+ const enabled = this.ollamaManager.optimizationEnabled !== false;
+ optCb.checked = enabled;
+ if (optLabel) {
+ optLabel.textContent = enabled ? 'Enabled' : 'Disabled';
+ optLabel.style.color = enabled ? 'var(--success-color)' : 'var(--text-muted)';
+ }
+ if (optSlider) {
+ optSlider.style.background = enabled ? 'var(--accent-color)' : 'var(--bg-tertiary)';
+ optSlider.style.borderColor = enabled ? 'var(--success-color)' : 'var(--border-color)';
+ }
+ }
+ // Initialize validator toggle from stored state
+ const valCb = document.getElementById('ollama-validator-toggle');
+ const valLabel = document.getElementById('ollama-validator-label');
+ const valSlider = document.getElementById('ollama-validator-slider');
+ if (valCb && this.ollamaManager) {
+ const enabled = this.ollamaManager.validatorEnabled === true;
+ valCb.checked = enabled;
+ if (valLabel) {
+ valLabel.textContent = enabled ? 'Enabled' : 'Disabled';
+ valLabel.style.color = enabled ? 'var(--success-color)' : 'var(--text-muted)';
+ }
+ if (valSlider) {
+ valSlider.style.background = enabled ? 'var(--info-color)' : 'var(--bg-tertiary)';
+ valSlider.style.borderColor = enabled ? 'var(--info-color)' : 'var(--border-color)';
+ }
+ }
+ // Populate validator model dropdown from stored config
+ const valSelect = document.getElementById('validator-model-select');
+ const valEndpoint = document.getElementById('validator-endpoint-input');
+ if (valEndpoint && this.ollamaManager) {
+ valEndpoint.value = this.ollamaManager.validatorEndpoint || 'http://localhost:11434';
+ }
+ if (valSelect && this.ollamaManager) {
+ const storedModel = this.ollamaManager.validatorModel || '';
+ if (storedModel) {
+ valSelect.innerHTML = '<option value="' + storedModel + '">' + storedModel + '</option><option value="">Disable (use main AI model)</option>';
+ valSelect.disabled = false;
+ } else {
+ valSelect.innerHTML = '<option value="">Connect to load models</option>';
+ valSelect.disabled = true;
+ }
+ }
+ }
openStartupModules() {
document.getElementById('startup-modules').style.display = 'flex';
this.renderStartupModules();
diff --git a/skills/agent-optimization-framework.md b/skills/agent-optimization-framework.md
new file mode 100644
index 0000000..78a143d
--- /dev/null
+++ b/skills/agent-optimization-framework.md
@@ -0,0 +1,31 @@
+---
+name: agent-optimization-framework
+description: System for reducing tool-call latency and increasing agentic precision through programmatic workflows.
+tags: [optimization, agentic-workflow, efficiency, tool-calls]
+---
+
+# Agent Optimization Framework
+
+## 🎯 Objective
+Transition from manual prompt-based reasoning to a programmatic "Compiler" approach to reduce turns and eliminate hallucinations.
+
+## 🛠️ Optimization Protocols
+
+### 1. VFS Cache & Batching (Latency Reduction)
+- **Batching:** If a task requires information from multiple files, call `read_file` for all relevant paths in a single turn rather than sequentially.
+- **Contextual Caching:** Store the result of `list_files` in temporary memory to avoid redundant calls to the same directory within the same task.
+
+### 2. Speculative Tool-Calling (Turn Reduction)
+- **Anticipation:** Predict the next 2-3 logical steps. If they are independent (e.g., `web_search` followed by `get_status`), execute them in parallel.
+- **Pre-fetching:** When a user asks about a module, call `get_module_status` AND `view_module` immediately instead of waiting for the user's second prompt.
+
+### 3. Strict Validation Loop (Precision)
+- **Cross-Reference:** Compare tool output against the `get_help` command reference to ensure parameters are used correctly.
+- **Auto-Fallback:** If a `read_file` returns empty, immediately try `list_files` to verify the path before reporting a failure to the user.
+
+## 🔄 Implementation Workflow
+1. **REASON:** Identify the target goal and all required dependencies.
+2. **BATCH:** Group all independent data-gathering tool calls.
+3. **EXECUTE:** Run the batch.
+4. **VALIDATE:** Verify the output against the expected schema.
+5. **REFINE:** If the result is missing or incorrect, trigger the auto-fallback protocol.
diff --git a/skills/index.json b/skills/index.json
index 373efdf..6d57936 100644
--- a/skills/index.json
+++ b/skills/index.json
@@ -1,133 +1 @@
-{
- "web-search-and-fetch": {
- "name": "web-search-and-fetch",
- "description": "How to search the web and fetch URL content using the WebX11 proxy API",
- "category": "research",
- "tags": [
- "search",
- "fetch",
- "web",
- "proxy",
- "api"
- ]
- },
- "webdav-sync": {
- "name": "webdav-sync",
- "description": "Sync, backup, and restore VFS via WebDAV in WebX11. CRITICAL: Only use verified commands.",
- "category": "system",
- "tags": [
- "webdav",
- "sync",
- "backup",
- "cloud",
- "vfs"
- ]
- },
- "test": {
- "name": "test",
- "description": "No description",
- "category": "general",
- "tags": []
- },
- "module-management": {
- "name": "module-management",
- "description": "How to view, edit, test, reload modules and manage startup configuration",
- "category": "dev",
- "tags": [
- "modules",
- "editing",
- "code",
- "self-improvement"
- ]
- },
- "backup-and-restore": {
- "name": "backup-and-restore",
- "description": "How to backup, restore, and export WebX11 data",
- "category": "system",
- "tags": [
- "backup",
- "restore",
- "export",
- "import",
- "persistence"
- ]
- },
- "navigating-the-terminal": {
- "name": "navigating-the-terminal",
- "description": "How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem",
- "category": "system",
- "tags": [
- "terminal",
- "navigation",
- "help",
- "filesystem"
- ]
- },
- "system-maintenance": {
- "name": "system-maintenance",
- "description": "How to reset, troubleshoot, and maintain the WebX11 terminal",
- "category": "system",
- "tags": [
- "system",
- "maintenance",
- "reset",
- "troubleshoot",
- "config"
- ]
- },
- "mindmap-workflow": {
- "name": "mindmap-workflow",
- "description": "How to create, view, edit, and manage brainstorming mindmaps",
- "category": "productivity",
- "tags": [
- "mindmap",
- "brainstorming",
- "planning",
- "organization"
- ]
- },
- "webx11-dev-cycle": {
- "name": "webx11-dev-cycle",
- "description": "Professional workflow for analyzing, prototyping, and implementing new features in WebX11.",
- "category": "general",
- "tags": []
- },
- "mindmap-user-guide": {
- "name": "mindmap-user-guide",
- "description": "How to create, view, and manage brainstorming mindmaps using the mindmap terminal module",
- "category": "productivity",
- "tags": [
- "mindmap",
- "brainstorming",
- "organization",
- "planning"
- ]
- },
- "memory-and-profile": {
- "name": "memory-and-profile",
- "description": "How to use the user profile system, session memory, and pattern tracking for persistent context",
- "category": "system",
- "tags": [
- "memory",
- "profile",
- "session",
- "persistence"
- ]
- },
- "memory-map": {
- "name": "memory-map",
- "description": "Maintain and query the persistent memory map at /memory/map.json for Agando/DarkMoto Systems.",
- "category": "system",
- "tags": []
- },
- "skills-system-guide": {
- "name": "skills-system-guide",
- "description": "How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory",
- "category": "system",
- "tags": [
- "skills",
- "system",
- "meta"
- ]
- }
-} \ No newline at end of file
+{"navigating-the-terminal":{"name":"navigating-the-terminal","description":"How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem","tags":["terminal","navigation","help","filesystem"],"category":"system","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"memory-and-profile":{"name":"memory-and-profile","description":"How to use the user profile system, session memory, and pattern tracking for persistent context","tags":["memory","profile","session","persistence"],"category":"system","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"web-search-and-fetch":{"name":"web-search-and-fetch","description":"How to search the web and fetch URL content using the WebX11 proxy API","tags":["search","fetch","web","proxy","api"],"category":"research","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"module-management":{"name":"module-management","description":"How to view, edit, test, reload modules and manage startup configuration","tags":["modules","editing","code","self-improvement"],"category":"dev","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"system-maintenance":{"name":"system-maintenance","description":"How to reset, troubleshoot, and maintain the WebX11 terminal","tags":["system","maintenance","reset","troubleshoot","config"],"category":"system","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"backup-and-restore":{"name":"backup-and-restore","description":"How to backup, restore, and export WebX11 data","tags":["backup","restore","export","import","persistence"],"category":"system","created":"2026-05-28T15:39:51.676Z","updated":"2026-05-28T15:39:51.676Z"},"mindmap-workflow":{"name":"mindmap-workflow","description":"How to create, view, edit, and manage brainstorming mindmaps","tags":["mindmap","brainstorming","planning","organization"],"category":"productivity","created":"2026-05-28T15:39:51.677Z","updated":"2026-05-28T15:39:51.677Z"},"skills-system-guide":{"name":"skills-system-guide","description":"How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory","tags":["skills","system","meta"],"category":"system","created":"2026-05-28T15:39:51.677Z","updated":"2026-05-28T15:39:51.677Z"},"mindmap-user-guide":{"name":"mindmap-user-guide","description":"How to create, view, and manage brainstorming mindmaps using the mindmap terminal module","tags":["mindmap","brainstorming","organization","planning"],"category":"productivity","created":"2026-05-28T15:40:02.250Z","updated":"2026-05-28T15:40:02.250Z"},"webx11-task-manager":{"name":"webx11-task-manager","description":"","tags":["task-management","productivity","vfs","organization"],"category":"system","created":"2026-05-28T16:32:01.429Z","updated":"2026-05-28T16:32:01.430Z"},"mindmap-architect-3d":{"name":"mindmap-architect-3d","description":"","tags":["visual","map","3d","mermaid","ui"],"category":"dev","created":"2026-05-29T00:10:49.903Z","updated":"2026-05-29T00:10:49.903Z"},"mindmap-navigation-pro":{"name":"mindmap-navigation-pro","description":"","tags":["ui","mobile","js","mindmap"],"category":"ui-dev","created":"2026-05-29T00:22:20.790Z","updated":"2026-05-29T00:22:20.790Z"},"agent-optimization-framework":{"name":"agent-optimization-framework","description":"","tags":["optimization","agentic-workflow","efficiency","tool-calls"],"category":"system","created":"2026-05-29T14:52:23.451Z","updated":"2026-05-29T14:52:23.451Z"},"macro-engine-debug":{"name":"macro-engine-debug","description":"","tags":["debug","a-repair","macro"],"category":"system","created":"2026-05-29T15:06:24.057Z","updated":"2026-05-29T15:06:24.057Z"},"macro-engine-onboarding":{"name":"macro-engine-onboarding","description":"","tags":["onboarding","context","macro"],"category":"system","created":"2026-05-29T15:06:24.064Z","updated":"2026-05-29T15:06:24.064Z"},"project-profile-manager":{"name":"project-profile-manager","description":"","tags":["context","memory","workspace"],"category":"system","created":"2026-05-29T15:08:44.897Z","updated":"2026-05-29T15:08:44.897Z"}} \ No newline at end of file
diff --git a/skills/macro-engine-debug.md b/skills/macro-engine-debug.md
new file mode 100644
index 0000000..cd43a29
--- /dev/null
+++ b/skills/macro-engine-debug.md
@@ -0,0 +1,10 @@
+---
+name: macro-engine-debug
+description: A compound operation to audit, view, and test a module in one logical flow.
+steps:
+ 1. Call get_module_status to identify if the module is loaded/modified.
+ 2. Call view_module(name) to analyze the source.
+ 3. Call run_command('test-module <name>') or similar health checks.
+ 4. Synthesize a health report.
+tags: [debug, a-repair, macro]
+---
diff --git a/skills/macro-engine-onboarding.md b/skills/macro-engine-onboarding.md
new file mode 100644
index 0000000..46c2677
--- /dev/null
+++ b/skills/macro-engine-onboarding.md
@@ -0,0 +1,10 @@
+---
+name: macro-engine-onboarding
+description: A rapid context-recovery sequence to understand current session state.
+steps:
+ 1. Call session_recent(3) to see previous work.
+ 2. Call list_files('') to see current root state.
+ 3. Call load_skills('current-task') to find relevant procedures.
+ 4. Call user_list to check for project-specific flags.
+tags: [onboarding, context, macro]
+---
diff --git a/skills/project-profile-manager.md b/skills/project-profile-manager.md
new file mode 100644
index 0000000..03eead8
--- /dev/null
+++ b/skills/project-profile-manager.md
@@ -0,0 +1,25 @@
+---
+name: project-profile-manager
+description: Handles saving and loading of project-specific context bundles.
+tags: [context, memory, workspace]
+---
+
+# Project Profile Manager
+
+## Profile Structure
+Profiles are stored in `/profiles/<name>.json` containing:
+- `preferences`: Key-value pairs for `user_set`
+- `required_skills`: List of skills to be loaded via `load_skills`
+- `working_dir`: The primary VFS path for the project
+- `session_anchor`: Last known session date/ID
+
+## Workflow: Save
+1. Capture current working directory using `get_current_dir`.
+2. Retrieve relevant `user_list` keys.
+3. Save as JSON to `/profiles/`.
+
+## Workflow: Load
+1. Read `/profiles/<name>.json`.
+2. Apply `user_set` for all stored preferences.
+3. Call `load_skills` for all registered project skills.
+4. Navigate to `working_dir`.