aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.html60
-rw-r--r--modules/core/core-bundle.js170
-rw-r--r--modules/core/module-aiassist.js2
-rw-r--r--modules/core/module-loader.js12
-rw-r--r--modules/core/terminal.js168
-rw-r--r--modules/ext/skill-pack-core.js9
-rw-r--r--packages.json9
-rw-r--r--skills/agent-orchestration.json4
-rw-r--r--skills/agent-role-definitions.json14
-rw-r--r--skills/backup-and-restore.json4
-rw-r--r--skills/debug-panel-and-logs.json4
-rw-r--r--skills/fetch-latest-news.json9
-rw-r--r--skills/floating-ui.json4
-rw-r--r--skills/l1-scalability-intelligence.json16
-rw-r--r--skills/latest-news-summary.json14
-rw-r--r--skills/mindmap-user-guide.json4
-rw-r--r--skills/mindmap-workflow.json4
-rw-r--r--skills/module-management.json4
-rw-r--r--skills/navigating-the-terminal.json4
-rw-r--r--skills/reasoning-framework.json15
-rw-r--r--skills/security-and-safety.json4
-rw-r--r--skills/skills-system-guide.json4
-rw-r--r--skills/system-maintenance.json4
-rw-r--r--skills/tool-bench-opt.json9
-rw-r--r--skills/web-search-and-fetch.json4
-rw-r--r--skills/webdav-operations.json4
26 files changed, 459 insertions, 100 deletions
diff --git a/main.html b/main.html
index 27cac74..791966b 100644
--- a/main.html
+++ b/main.html
@@ -1112,30 +1112,56 @@
<!-- Skills Manager Modal -->
<div id="skills-manager" class="modal-overlay">
- <div class="modal-content" style="max-width: 700px; max-height: 85vh;">
+ <div class="modal-content" style="max-width: 750px; max-height: 90vh;">
<div class="modal-header">
<span>๐Ÿ“š Skills Manager</span>
<span style="cursor:pointer" onclick="webx11.closeSkillsManager()">โœ•</span>
</div>
- <div class="modal-body" style="display:flex; flex-direction:column; gap:10px;">
- <div style="flex-shrink:0;">
- <h4 style="color: var(--info-color); margin-bottom: 8px;">Installed Skills</h4>
- <div id="skills-list" style="max-height:200px;overflow-y:auto;"></div>
+ <div class="modal-body" style="display:flex; flex-direction:column; gap:8px;">
+ <!-- Stats header -->
+ <div id="skills-stats" style="display:flex; gap:12px; flex-wrap:wrap; font-size:0.85em; color:var(--text-muted); padding-bottom:6px; border-bottom:1px solid var(--border-color);"></div>
+ <!-- Search + action bar -->
+ <div style="display:flex; gap:6px; align-items:center; flex-shrink:0;">
+ <input type="text" id="skills-search-input" class="module-url-input" placeholder="๐Ÿ” Search skills..." style="flex:1;" oninput="webx11.refreshSkillsList()">
+ <button class="btn" onclick="webx11.exportAllSkillsUI()" style="padding:4px 10px; font-size:0.8em">๐Ÿ“ค Export All</button>
+ <button class="btn" onclick="document.getElementById('skills-import-input').click()" style="padding:4px 10px; font-size:0.8em">๐Ÿ“ฅ Import</button>
+ <input type="file" id="skills-import-input" accept=".json" style="display:none" onchange="webx11.importSkillsUI(event)">
+ <button class="btn" onclick="webx11.syncSkillsToWebdavUI()" style="padding:4px 10px; font-size:0.8em">โ˜๏ธ Sync</button>
</div>
- <div id="skill-preview" style="display:none; flex-shrink:0; background:var(--bg-tertiary); border:1px solid var(--border-color); border-radius:4px; padding:10px; max-height:250px; overflow-y:auto; white-space:pre-wrap; font-family:var(--font-primary); font-size:0.85em; color:var(--text-color);">
+ <!-- Skills list with category groups -->
+ <div id="skills-list" style="max-height:300px;overflow-y:auto; flex-shrink:0;"></div>
+ <!-- Preview (collapsible) -->
+ <div id="skill-preview" style="display:none; flex-shrink:0; background:var(--bg-tertiary); border:1px solid var(--border-color); border-radius:4px; padding:10px; overflow-y:auto; white-space:pre-wrap; font-family:var(--font-primary); font-size:0.85em; color:var(--text-color);">
<div style="display:flex; justify-content:space-between; margin-bottom:6px;">
<span id="skill-preview-title" style="color:var(--success-color); font-weight:bold;"></span>
- <span style="cursor:pointer; color:var(--text-muted); font-size:1.2em;" onclick="webx11.closeSkillPreview()">โœ•</span>
+ <div style="display:flex; gap:6px;">
+ <button class="btn" id="skill-preview-expand-btn" onclick="webx11.toggleSkillPreviewSize()" style="padding:2px 6px; font-size:0.75em">โ›ถ Expand</button>
+ <span style="cursor:pointer; color:var(--text-muted); font-size:1.2em;" onclick="webx11.closeSkillPreview()">โœ•</span>
+ </div>
</div>
<div id="skill-preview-content"></div>
</div>
- <div style="flex-shrink:0;">
- <h4 style="color: var(--info-color); margin-bottom: 8px;">Create New Skill</h4>
- <input type="text" id="skill-name-input" class="module-url-input" placeholder="Skill name (e.g. web-scrape-and-summarize)">
- <input type="text" id="skill-desc-input" class="module-url-input" style="margin-top:6px" placeholder="One-line description">
- <input type="text" id="skill-tags-input" class="module-url-input" style="margin-top:6px" placeholder="Tags (comma-separated, e.g. web,research)">
- <textarea id="skill-content-input" class="module-url-input" style="margin-top:6px; height:100px; resize:vertical; font-family:var(--font-primary)" placeholder="Markdown skill content (optional โ€” will use template)"></textarea>
- <button class="btn" onclick="webx11.createSkillFromUI()" style="width:100%; margin-top:6px; border-color:var(--success-color);color:var(--success-color)">Create Skill</button>
+ <!-- Create form -->
+ <div style="flex-shrink:0; border-top:1px solid var(--border-color); padding-top:8px;">
+ <h4 style="color: var(--info-color); margin-bottom: 6px;">Create New Skill</h4>
+ <div style="display:flex; gap:6px; flex-wrap:wrap;">
+ <input type="text" id="skill-name-input" class="module-url-input" placeholder="Name (kebab-case)" style="flex:2; min-width:140px;">
+ <input type="text" id="skill-desc-input" class="module-url-input" placeholder="Description" style="flex:3; min-width:180px;">
+ <select id="skill-category-input" class="module-url-input" style="flex:1; min-width:100px;">
+ <option value="general">general</option>
+ <option value="system">system</option>
+ <option value="research">research</option>
+ <option value="dev">dev</option>
+ <option value="productivity">productivity</option>
+ <option value="ui">ui</option>
+ <option value="security">security</option>
+ </select>
+ </div>
+ <div style="display:flex; gap:6px; margin-top:6px;">
+ <input type="text" id="skill-tags-input" class="module-url-input" placeholder="Tags (comma-separated)" style="flex:1;">
+ <button class="btn" onclick="webx11.createSkillFromUI()" style="border-color:var(--success-color);color:var(--success-color); flex-shrink:0;">Create</button>
+ </div>
+ <textarea id="skill-content-input" class="module-url-input" style="margin-top:6px; height:80px; resize:vertical; font-family:var(--font-primary)" placeholder="Markdown content (optional โ€” will use template)"></textarea>
</div>
</div>
<div class="modal-footer">
@@ -1278,7 +1304,7 @@
if (body && !body.children.length) {
var mods = [
['Foundation (always loaded)', ['virtual-fs.js','module-manager.js','ollama-manager.js','terminal.js'], true],
- ['Built-in modules', ['module-system.js','module-fs.js','module-ollama.js','module-my.js','module-searxng.js','module-servermon.js','module-ollamamodels.js','module-config.js','module-simplegui.js','module-io.js','module-dynamicprompts.js','module-aiassist.js','module-aiasm.js','module-smartctx.js','module-duckduckgo.js','module-fetcher.js','module-skills.js','module-chatstudio.js'], false],
+ ['Built-in modules', ['module-system.js','module-fs.js','module-ollama.js','module-my.js','module-searxng.js','module-servermon.js','module-ollamamodels.js','module-config.js','module-simplegui.js','module-io.js','module-dynamicprompts.js','module-aiassist.js','module-aiasm.js','module-smartctx.js','module-duckduckgo.js','module-fetcher.js','module-chatstudio.js'], false],
['Extensions', ['calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','webdav.js','skill-pack-core.js','editor.js','diff.js','alias.js','finder.js','filemgr.js','cryptogzip.js','tutorial.js','shell.js','busybox.js','floating.js','console.js'], false]
];
var isSel = function(name) { return true; }; // default: all selected
@@ -1317,11 +1343,13 @@
<!-- v4.5.63: A2A scratchpad fixes + agent-register arg fix -->
<script src="modules/core/core-bundle.js?v=2026-06-18-v4.5.79"></script>
-<script src="modules/ext/critical-ext-bundle.js?v=2026-06-18-v4.5.79"></script>
<!-- Async dependency-ordered module loader now only initializes terminal and loads optional ext modules -->
<script src="modules/core/module-loader.js?v=2026-06-18-v4.5.79"></script>
+ <!-- Critical ext bundle loads AFTER webx11 exists so registerModule calls work -->
+<script src="modules/ext/critical-ext-bundle.js?v=2026-06-18-v4.5.79"></script>
+
<script>
// โ•โ•โ• ONE TRUE VERSION SOURCE โ•โ•โ•
// Reads from module-loader.js src attribute (single source of truth)
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js
index 0f13438..175df87 100644
--- a/modules/core/core-bundle.js
+++ b/modules/core/core-bundle.js
@@ -4183,32 +4183,69 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
refreshSkillsList() {
const list = document.getElementById('skills-list');
list.innerHTML = '';
+ const statsEl = document.getElementById('skills-stats');
const fs = this.fs;
fs.mkdirRecursive('/skills');
const index = fs.fsReadJSON('/skills/index.json') || {};
const names = Object.keys(index);
- if (names.length === 0) {
- list.innerHTML = '<div style="padding:20px; text-align:center; color:#666">No skills yet. Create one below!</div>';
+ // Search filter
+ const query = (document.getElementById('skills-search-input')?.value || '').toLowerCase().trim();
+ let filtered = names;
+ if (query) {
+ filtered = names.filter(n => {
+ const s = index[n];
+ return n.includes(query) || (s.description || '').toLowerCase().includes(query) || (s.tags || []).some(t => t.toLowerCase().includes(query)) || (s.category || '').toLowerCase().includes(query);
+ });
+ }
+ // Stats
+ if (statsEl) {
+ const cats = new Set(Object.values(index).map(s => s.category || 'general'));
+ statsEl.innerHTML = `<span>๐Ÿ“š ${names.length} skills</span><span>๐Ÿ“‚ ${cats.size} categories</span>${query ? `<span>๐Ÿ” ${filtered.length} match '${query}'</span>` : ''}`;
+ }
+ if (filtered.length === 0) {
+ list.innerHTML = '<div style="padding:20px; text-align:center; color:#666">' + (query ? 'No skills match your search.' : 'No skills yet. Create one below!') + '</div>';
return;
}
- names.forEach(name => {
+ // Group by category
+ const groups = {};
+ for (const name of filtered) {
const s = index[name];
- const tags = (s.tags || []).join(', ');
- const div = document.createElement('div');
- div.className = 'module-item';
- div.innerHTML = `
- <div>
- <strong style="color:var(--success-color)">${name}</strong>
- <div style="font-size:0.85em; color:#aaa">${s.description || ''}</div>
- <div style="font-size:0.75em; color:#666">${s.category || 'general'}${tags ? ' ยท ' + tags : ''}</div>
- </div>
- <div style="display:flex;gap:4px">
- <button class="btn" onclick="webx11.viewSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">๐Ÿ‘</button>
- <button class="btn btn-danger" onclick="webx11.deleteSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ•</button>
- </div>
- `;
- list.appendChild(div);
- });
+ const cat = s.category || 'general';
+ if (!groups[cat]) groups[cat] = [];
+ groups[cat].push(name);
+ }
+ const catOrder = Object.keys(groups).sort();
+ for (const cat of catOrder) {
+ const section = document.createElement('div');
+ section.style.marginBottom = '6px';
+ const header = document.createElement('div');
+ header.style.cssText = 'font-size:0.8em; font-weight:600; color:var(--info-color); padding:4px 0; cursor:pointer; display:flex; align-items:center; gap:4px;';
+ header.textContent = '๐Ÿ“ ' + cat + ' (' + groups[cat].length + ')';
+ header.onclick = () => { const body = header.nextElementSibling; if (body) body.style.display = body.style.display === 'none' ? '' : 'none'; };
+ section.appendChild(header);
+ const body = document.createElement('div');
+ for (const name of groups[cat]) {
+ const s = index[name];
+ const tags = (s.tags || []).join(', ');
+ const div = document.createElement('div');
+ div.className = 'module-item';
+ div.innerHTML = `
+ <div>
+ <strong style="color:var(--success-color)">${name}</strong>
+ <div style="font-size:0.85em; color:#aaa">${s.description || ''}</div>
+ <div style="font-size:0.75em; color:#666">${tags ? '๐Ÿท ' + tags : ''}</div>
+ </div>
+ <div style="display:flex;gap:4px">
+ <button class="btn" onclick="webx11.viewSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">๐Ÿ‘</button>
+ <button class="btn" onclick="webx11.editSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ๏ธ</button>
+ <button class="btn btn-danger" onclick="webx11.deleteSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ•</button>
+ </div>
+ `;
+ body.appendChild(div);
+ }
+ section.appendChild(body);
+ list.appendChild(section);
+ }
}
viewSkillUI(name) {
const fs = this.fs;
@@ -4217,15 +4254,33 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
document.getElementById('skill-preview-title').textContent = name;
document.getElementById('skill-preview-content').textContent = content;
document.getElementById('skill-preview').style.display = 'flex';
+ document.getElementById('skill-preview-expand-btn').textContent = 'โ›ถ Expand';
+ document.getElementById('skill-preview').style.maxHeight = '250px';
}
closeSkillPreview() {
document.getElementById('skill-preview').style.display = 'none';
}
+ toggleSkillPreviewSize() {
+ const preview = document.getElementById('skill-preview');
+ const btn = document.getElementById('skill-preview-expand-btn');
+ if (preview.style.maxHeight === 'none' || preview.style.maxHeight === '80vh') {
+ preview.style.maxHeight = '250px';
+ btn.textContent = 'โ›ถ Expand';
+ } else {
+ preview.style.maxHeight = '80vh';
+ btn.textContent = 'โ›ถ Collapse';
+ }
+ }
+ editSkillUI(name) {
+ this.closeSkillsManager();
+ if (typeof webx11.dispatchCommand === 'function') {
+ setTimeout(() => webx11.dispatchCommand('edit', ['/skills/' + name + '.md']), 200);
+ }
+ }
deleteSkillUI(name) {
if (!confirm(`Delete skill "${name}"?`)) return;
const fs = this.fs;
fs.mkdirRecursive('/skills');
- // Actually remove from VFS tree
if (fs.root && fs.root.content && fs.root.content['skills'] && fs.root.content['skills'].content) {
delete fs.root.content['skills'].content[`${name}.md`];
}
@@ -4239,6 +4294,7 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
createSkillFromUI() {
const name = document.getElementById('skill-name-input').value.trim().replace(/\s+/g, '-').toLowerCase();
const description = document.getElementById('skill-desc-input').value.trim() || 'No description';
+ const category = document.getElementById('skill-category-input')?.value || 'general';
const tags = document.getElementById('skill-tags-input').value.trim().split(',').map(t => t.trim()).filter(Boolean);
const contentInput = document.getElementById('skill-content-input').value.trim();
if (!name) { alert('Skill name is required'); return; }
@@ -4248,13 +4304,13 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
alert(`Skill '${name}' already exists. Delete it first or use skill-patch command.`);
return;
}
- let content = contentInput || `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: general\n---\n## Steps\n1. (to be filled)\n`;
+ let content = contentInput || `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: ${category}\n---\n## Steps\n1. (to be filled)\n`;
if (!content.startsWith('---')) {
- content = `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: general\n---\n${content}`;
+ content = `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: ${category}\n---\n${content}`;
}
fs.writeFile(`/skills/${name}.md`, content);
const index = fs.fsReadJSON('/skills/index.json') || {};
- index[name] = { name, description, category: 'general', tags };
+ index[name] = { name, description, category, tags };
fs.fsWriteJSON('/skills/index.json', index);
this.print(`Skill '${name}' created`, 'success');
document.getElementById('skill-name-input').value = '';
@@ -4263,6 +4319,70 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
document.getElementById('skill-content-input').value = '';
this.refreshSkillsList();
}
+ exportAllSkillsUI() {
+ const fs = this.fs;
+ const index = fs.fsReadJSON('/skills/index.json') || {};
+ const names = Object.keys(index);
+ if (names.length === 0) { alert('No skills to export.'); return; }
+ const exportData = {};
+ for (const name of names) {
+ const content = fs.readFile(`/skills/${name}.md`);
+ if (content !== null) {
+ exportData[name] = { ...index[name], content };
+ }
+ }
+ const json = JSON.stringify(exportData, null, 2);
+ const blob = new Blob([json], { type: 'application/json' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = 'skills-export-' + new Date().toISOString().slice(0, 10) + '.json';
+ a.click();
+ URL.revokeObjectURL(url);
+ this.print(`๐Ÿ“ค Exported ${names.length} skills`, 'success');
+ }
+ importSkillsUI(event) {
+ const file = event.target.files[0];
+ if (!file) return;
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ try {
+ const data = JSON.parse(e.target.result);
+ const fs = this.fs;
+ fs.mkdirRecursive('/skills');
+ const index = fs.fsReadJSON('/skills/index.json') || {};
+ let imported = 0;
+ for (const [name, skill] of Object.entries(data)) {
+ if (!skill.content) continue;
+ fs.writeFile(`/skills/${name}.md`, skill.content);
+ index[name] = {
+ name,
+ description: skill.description || name,
+ tags: skill.tags || [],
+ category: skill.category || 'general',
+ created: (index[name] && index[name].created) || new Date().toISOString(),
+ updated: new Date().toISOString()
+ };
+ imported++;
+ }
+ fs.fsWriteJSON('/skills/index.json', index);
+ this.print(`๐Ÿ“ฅ Imported ${imported} skills`, 'success');
+ this.refreshSkillsList();
+ } catch (err) {
+ alert('Invalid JSON file: ' + err.message);
+ }
+ };
+ reader.readAsText(file);
+ event.target.value = '';
+ }
+ syncSkillsToWebdavUI() {
+ const mod = this.moduleManager && this.moduleManager.modules['SkillPackCoreModule'];
+ if (mod && mod.commands && mod.commands['skill-webdav-sync']) {
+ mod.commands['skill-webdav-sync']();
+ } else {
+ this.print('WebDAV sync not available. Is skill-pack-core loaded?', 'warning');
+ }
+ }
updateOllamaStatus() {
const statusDiv = document.getElementById('ollama-status');
const statusText = document.getElementById('ollama-status-text');
@@ -4529,7 +4649,7 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
'module-my.js','module-searxng.js','module-servermon.js','module-ollamamodels.js',
'module-config.js','module-simplegui.js','module-io.js','module-dynamicprompts.js',
'module-aiassist.js','module-aiasm.js','module-smartctx.js','module-duckduckgo.js',
- 'module-fetcher.js','module-skills.js','module-chatstudio.js'
+ 'module-fetcher.js','module-chatstudio.js'
];
const extFiles = [
'calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','webdav.js','skill-pack-core.js','editor.js','diff.js','alias.js','finder.js','filemgr.js','cryptogzip.js','tutorial.js','shell.js','busybox.js','floating.js','console.js','media.js'
@@ -8104,6 +8224,8 @@ buildSystemPrompt() {
}
if (res.tool_calls && res.tool_calls.length > 0) {
// v4.5.66: Loop detection โ€” break if AI repeats same tool+args 3+ times
+ // Reset per-turn so legitimate retries across turns don't false-positive
+ _seenCalls.clear();
let looping = false;
for (const tc of res.tool_calls) {
const sig = tc.function.name + ':' + (tc.function.arguments || '');
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index 40716e4..9c9b1ca 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -792,6 +792,8 @@ buildSystemPrompt() {
}
if (res.tool_calls && res.tool_calls.length > 0) {
// v4.5.66: Loop detection โ€” break if AI repeats same tool+args 3+ times
+ // Reset per-turn so legitimate retries across turns don't false-positive
+ _seenCalls.clear();
let looping = false;
for (const tc of res.tool_calls) {
const sig = tc.function.name + ':' + (tc.function.arguments || '');
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js
index a08a285..5d1c320 100644
--- a/modules/core/module-loader.js
+++ b/modules/core/module-loader.js
@@ -37,6 +37,11 @@
if (fill) fill.style.background = 'var(--error-color)';
}
+ // Create webx11 synchronously so critical-ext-bundle.js (loaded right after us)
+ // can call registerModule() without waiting for DOMContentLoaded
+ const webx11 = new WebX11Terminal();
+ window.webx11 = webx11;
+
async function init() {
try {
const total = 3;
@@ -46,12 +51,9 @@
setSplash('Critical ext bundle loaded (2/3)', ++count, total, 'critical-ext-bundle.js');
setSplash('Initializing terminal (3/3)', total, total, '');
- const webx11 = new WebX11Terminal();
- window.webx11 = webx11;
-
- // Optional ext modules via packages.json
+ // webx11 already created synchronously above โ€” just init ext modules
if (typeof webx11._loadExtModules === 'function') {
- let extKeys = ['calc', 'voice', 'debug-panel', 'cron', 'theme', 'wpm', 'mindmap', 'webdav', 'skill-pack-core', 'cryptogzip', 'tutorial', 'floating', 'console'];
+ let extKeys = ['calc', 'voice', 'debug-panel', 'cron', 'theme', 'wpm', 'mindmap', 'webdav', 'skill-pack-core', 'cryptogzip', 'tutorial', 'floating', 'console', 'media'];
const saved = localStorage.getItem('webx11_startup_modules');
let selected = null;
try { if (saved) selected = JSON.parse(saved); } catch (e) {}
diff --git a/modules/core/terminal.js b/modules/core/terminal.js
index 2178e85..b5f50a6 100644
--- a/modules/core/terminal.js
+++ b/modules/core/terminal.js
@@ -1903,32 +1903,69 @@
refreshSkillsList() {
const list = document.getElementById('skills-list');
list.innerHTML = '';
+ const statsEl = document.getElementById('skills-stats');
const fs = this.fs;
fs.mkdirRecursive('/skills');
const index = fs.fsReadJSON('/skills/index.json') || {};
const names = Object.keys(index);
- if (names.length === 0) {
- list.innerHTML = '<div style="padding:20px; text-align:center; color:#666">No skills yet. Create one below!</div>';
+ // Search filter
+ const query = (document.getElementById('skills-search-input')?.value || '').toLowerCase().trim();
+ let filtered = names;
+ if (query) {
+ filtered = names.filter(n => {
+ const s = index[n];
+ return n.includes(query) || (s.description || '').toLowerCase().includes(query) || (s.tags || []).some(t => t.toLowerCase().includes(query)) || (s.category || '').toLowerCase().includes(query);
+ });
+ }
+ // Stats
+ if (statsEl) {
+ const cats = new Set(Object.values(index).map(s => s.category || 'general'));
+ statsEl.innerHTML = `<span>๐Ÿ“š ${names.length} skills</span><span>๐Ÿ“‚ ${cats.size} categories</span>${query ? `<span>๐Ÿ” ${filtered.length} match '${query}'</span>` : ''}`;
+ }
+ if (filtered.length === 0) {
+ list.innerHTML = '<div style="padding:20px; text-align:center; color:#666">' + (query ? 'No skills match your search.' : 'No skills yet. Create one below!') + '</div>';
return;
}
- names.forEach(name => {
+ // Group by category
+ const groups = {};
+ for (const name of filtered) {
const s = index[name];
- const tags = (s.tags || []).join(', ');
- const div = document.createElement('div');
- div.className = 'module-item';
- div.innerHTML = `
- <div>
- <strong style="color:var(--success-color)">${name}</strong>
- <div style="font-size:0.85em; color:#aaa">${s.description || ''}</div>
- <div style="font-size:0.75em; color:#666">${s.category || 'general'}${tags ? ' ยท ' + tags : ''}</div>
- </div>
- <div style="display:flex;gap:4px">
- <button class="btn" onclick="webx11.viewSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">๐Ÿ‘</button>
- <button class="btn btn-danger" onclick="webx11.deleteSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ•</button>
- </div>
- `;
- list.appendChild(div);
- });
+ const cat = s.category || 'general';
+ if (!groups[cat]) groups[cat] = [];
+ groups[cat].push(name);
+ }
+ const catOrder = Object.keys(groups).sort();
+ for (const cat of catOrder) {
+ const section = document.createElement('div');
+ section.style.marginBottom = '6px';
+ const header = document.createElement('div');
+ header.style.cssText = 'font-size:0.8em; font-weight:600; color:var(--info-color); padding:4px 0; cursor:pointer; display:flex; align-items:center; gap:4px;';
+ header.textContent = '๐Ÿ“ ' + cat + ' (' + groups[cat].length + ')';
+ header.onclick = () => { const body = header.nextElementSibling; if (body) body.style.display = body.style.display === 'none' ? '' : 'none'; };
+ section.appendChild(header);
+ const body = document.createElement('div');
+ for (const name of groups[cat]) {
+ const s = index[name];
+ const tags = (s.tags || []).join(', ');
+ const div = document.createElement('div');
+ div.className = 'module-item';
+ div.innerHTML = `
+ <div>
+ <strong style="color:var(--success-color)">${name}</strong>
+ <div style="font-size:0.85em; color:#aaa">${s.description || ''}</div>
+ <div style="font-size:0.75em; color:#666">${tags ? '๐Ÿท ' + tags : ''}</div>
+ </div>
+ <div style="display:flex;gap:4px">
+ <button class="btn" onclick="webx11.viewSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">๐Ÿ‘</button>
+ <button class="btn" onclick="webx11.editSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ๏ธ</button>
+ <button class="btn btn-danger" onclick="webx11.deleteSkillUI('${name}')" style="padding:4px 8px; font-size:0.8em">โœ•</button>
+ </div>
+ `;
+ body.appendChild(div);
+ }
+ section.appendChild(body);
+ list.appendChild(section);
+ }
}
viewSkillUI(name) {
const fs = this.fs;
@@ -1937,15 +1974,33 @@
document.getElementById('skill-preview-title').textContent = name;
document.getElementById('skill-preview-content').textContent = content;
document.getElementById('skill-preview').style.display = 'flex';
+ document.getElementById('skill-preview-expand-btn').textContent = 'โ›ถ Expand';
+ document.getElementById('skill-preview').style.maxHeight = '250px';
}
closeSkillPreview() {
document.getElementById('skill-preview').style.display = 'none';
}
+ toggleSkillPreviewSize() {
+ const preview = document.getElementById('skill-preview');
+ const btn = document.getElementById('skill-preview-expand-btn');
+ if (preview.style.maxHeight === 'none' || preview.style.maxHeight === '80vh') {
+ preview.style.maxHeight = '250px';
+ btn.textContent = 'โ›ถ Expand';
+ } else {
+ preview.style.maxHeight = '80vh';
+ btn.textContent = 'โ›ถ Collapse';
+ }
+ }
+ editSkillUI(name) {
+ this.closeSkillsManager();
+ if (typeof webx11.dispatchCommand === 'function') {
+ setTimeout(() => webx11.dispatchCommand('edit', ['/skills/' + name + '.md']), 200);
+ }
+ }
deleteSkillUI(name) {
if (!confirm(`Delete skill "${name}"?`)) return;
const fs = this.fs;
fs.mkdirRecursive('/skills');
- // Actually remove from VFS tree
if (fs.root && fs.root.content && fs.root.content['skills'] && fs.root.content['skills'].content) {
delete fs.root.content['skills'].content[`${name}.md`];
}
@@ -1959,6 +2014,7 @@
createSkillFromUI() {
const name = document.getElementById('skill-name-input').value.trim().replace(/\s+/g, '-').toLowerCase();
const description = document.getElementById('skill-desc-input').value.trim() || 'No description';
+ const category = document.getElementById('skill-category-input')?.value || 'general';
const tags = document.getElementById('skill-tags-input').value.trim().split(',').map(t => t.trim()).filter(Boolean);
const contentInput = document.getElementById('skill-content-input').value.trim();
if (!name) { alert('Skill name is required'); return; }
@@ -1968,13 +2024,13 @@
alert(`Skill '${name}' already exists. Delete it first or use skill-patch command.`);
return;
}
- let content = contentInput || `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: general\n---\n## Steps\n1. (to be filled)\n`;
+ let content = contentInput || `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: ${category}\n---\n## Steps\n1. (to be filled)\n`;
if (!content.startsWith('---')) {
- content = `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: general\n---\n${content}`;
+ content = `---\nname: ${name}\ndescription: ${description}\ntags: [${tags.join(', ')}]\ncategory: ${category}\n---\n${content}`;
}
fs.writeFile(`/skills/${name}.md`, content);
const index = fs.fsReadJSON('/skills/index.json') || {};
- index[name] = { name, description, category: 'general', tags };
+ index[name] = { name, description, category, tags };
fs.fsWriteJSON('/skills/index.json', index);
this.print(`Skill '${name}' created`, 'success');
document.getElementById('skill-name-input').value = '';
@@ -1983,6 +2039,70 @@
document.getElementById('skill-content-input').value = '';
this.refreshSkillsList();
}
+ exportAllSkillsUI() {
+ const fs = this.fs;
+ const index = fs.fsReadJSON('/skills/index.json') || {};
+ const names = Object.keys(index);
+ if (names.length === 0) { alert('No skills to export.'); return; }
+ const exportData = {};
+ for (const name of names) {
+ const content = fs.readFile(`/skills/${name}.md`);
+ if (content !== null) {
+ exportData[name] = { ...index[name], content };
+ }
+ }
+ const json = JSON.stringify(exportData, null, 2);
+ const blob = new Blob([json], { type: 'application/json' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = 'skills-export-' + new Date().toISOString().slice(0, 10) + '.json';
+ a.click();
+ URL.revokeObjectURL(url);
+ this.print(`๐Ÿ“ค Exported ${names.length} skills`, 'success');
+ }
+ importSkillsUI(event) {
+ const file = event.target.files[0];
+ if (!file) return;
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ try {
+ const data = JSON.parse(e.target.result);
+ const fs = this.fs;
+ fs.mkdirRecursive('/skills');
+ const index = fs.fsReadJSON('/skills/index.json') || {};
+ let imported = 0;
+ for (const [name, skill] of Object.entries(data)) {
+ if (!skill.content) continue;
+ fs.writeFile(`/skills/${name}.md`, skill.content);
+ index[name] = {
+ name,
+ description: skill.description || name,
+ tags: skill.tags || [],
+ category: skill.category || 'general',
+ created: (index[name] && index[name].created) || new Date().toISOString(),
+ updated: new Date().toISOString()
+ };
+ imported++;
+ }
+ fs.fsWriteJSON('/skills/index.json', index);
+ this.print(`๐Ÿ“ฅ Imported ${imported} skills`, 'success');
+ this.refreshSkillsList();
+ } catch (err) {
+ alert('Invalid JSON file: ' + err.message);
+ }
+ };
+ reader.readAsText(file);
+ event.target.value = '';
+ }
+ syncSkillsToWebdavUI() {
+ const mod = this.moduleManager && this.moduleManager.modules['SkillPackCoreModule'];
+ if (mod && mod.commands && mod.commands['skill-webdav-sync']) {
+ mod.commands['skill-webdav-sync']();
+ } else {
+ this.print('WebDAV sync not available. Is skill-pack-core loaded?', 'warning');
+ }
+ }
updateOllamaStatus() {
const statusDiv = document.getElementById('ollama-status');
const statusText = document.getElementById('ollama-status-text');
@@ -2249,7 +2369,7 @@
'module-my.js','module-searxng.js','module-servermon.js','module-ollamamodels.js',
'module-config.js','module-simplegui.js','module-io.js','module-dynamicprompts.js',
'module-aiassist.js','module-aiasm.js','module-smartctx.js','module-duckduckgo.js',
- 'module-fetcher.js','module-skills.js','module-chatstudio.js'
+ 'module-fetcher.js','module-chatstudio.js'
];
const extFiles = [
'calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','webdav.js','skill-pack-core.js','editor.js','diff.js','alias.js','finder.js','filemgr.js','cryptogzip.js','tutorial.js','shell.js','busybox.js','floating.js','console.js','media.js'
diff --git a/modules/ext/skill-pack-core.js b/modules/ext/skill-pack-core.js
index de50f89..455a7f4 100644
--- a/modules/ext/skill-pack-core.js
+++ b/modules/ext/skill-pack-core.js
@@ -586,8 +586,10 @@ class SkillPackCoreModule {
const desc = args[1];
const content = args.slice(2).join(' ');
const tags = [];
- if (content.includes('"')) {
- // Parse quoted tags at end
+ // Parse tags from the last argument if it looks like a comma-separated list
+ const lastArg = args[args.length - 1];
+ if (lastArg && !lastArg.startsWith('"') && lastArg.includes(',')) {
+ tags.push(...lastArg.split(',').map(t => t.trim()).filter(Boolean));
}
const fs = this.terminal.fs;
// Check for duplicate
@@ -700,6 +702,7 @@ class SkillPackCoreModule {
const files = fs.ls('/skills') || [];
const mdFiles = files.filter(f => f.type === 'file' && f.name.endsWith('.md') && f.name !== 'index.json');
let synced = 0;
+ const oldIndex = fs.fsReadJSON('/skills/index.json') || {};
const index = {};
for (const f of mdFiles) {
const content = fs.readFile(`/skills/${f.name}`);
@@ -723,7 +726,7 @@ class SkillPackCoreModule {
description,
tags,
category,
- created: new Date().toISOString(),
+ created: (oldIndex[name] && oldIndex[name].created) || new Date().toISOString(),
updated: new Date().toISOString()
};
synced++;
diff --git a/packages.json b/packages.json
index e072feb..368b67a 100644
--- a/packages.json
+++ b/packages.json
@@ -271,9 +271,14 @@
"note": "Listed for WPM completeness. Auto-loaded by module-loader. Cannot be uninstalled."
},
"media": {
- "url": "modules/ext/media.js",
+ "name": "Media Analysis",
"version": "1.0.0",
- "description": "Media analysis module \u2014 image/audio/video analysis via Ollama vision models"
+ "desc": "Image/audio/video analysis via Ollama vision models โ€” analyze, describe, transcribe",
+ "url": "modules/ext/media.js",
+ "commands": [
+ "analyze"
+ ],
+ "category": "utility"
}
}
} \ No newline at end of file
diff --git a/skills/agent-orchestration.json b/skills/agent-orchestration.json
index 7a0f613..5e88622 100644
--- a/skills/agent-orchestration.json
+++ b/skills/agent-orchestration.json
@@ -8,7 +8,7 @@
"leases"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: agent-orchestration\ndescription: How to use the agent registry, leases, and orchestrator for multi-agent workflows\ntags: [agents, orchestration, delegation, leases]\ncategory: system\n---\n## Steps\n1. **Agent Registry:**\n - agent-list โ€” list all registered agents (ID, type, capabilities, status)\n - agent-register <type> <capabilities> โ€” register a new agent (capabilities: comma-separated like \"code,research\")\n - agent-unregister <id> โ€” remove an agent\n - agent-status <id> โ€” detailed status including uptime, task history\n\n2. **Leases (time-bound contracts):**\n - lease-create <agent-id> <ttl-seconds> โ€” create a lease with watchdog timer\n - lease-list โ€” show active leases with remaining TTL\n - lease-revoke <lease-id> โ€” terminate a lease early\n - lease-renew <lease-id> <ttl-seconds> โ€” extend a lease\n\n3. **Orchestrator (spawn, delegate, kill):**\n - orchestrator-spawn <type> <capabilities> โ€” spawn a new agent automatically (registers + creates lease)\n - orchestrator-kill <agent-id> โ€” kill an agent (revokes lease + unregisters)\n - orchestrate โ€” list all active agents with their orchestrator state\n - orchestrator-purge โ€” kill all idle/expired agents\n - orchestrator-status โ€” full system status: active, idle, dead agents\n\n4. **AI tool integration:**\n - AI tools list_agents, delegate_task, spawn_agent are available in the AI system prompt\n - The AI can auto-spawn worker agents for sub-tasks\n - Each agent gets its own VFS workspace at /agents/<agent-id>/\n\n5. **When to use:**\n - User needs parallel task execution โ†’ orchestrator-spawn coder + researcher\n - Time-bound automation โ†’ lease-create with short TTL\n - System cleanup โ†’ orchestrator-purge to kill stale agents"
} \ No newline at end of file
diff --git a/skills/agent-role-definitions.json b/skills/agent-role-definitions.json
new file mode 100644
index 0000000..192c9ac
--- /dev/null
+++ b/skills/agent-role-definitions.json
@@ -0,0 +1,14 @@
+{
+ "name": "agent-role-definitions",
+ "description": "",
+ "tags": [
+ "roles",
+ "agents",
+ "system2",
+ "architecture"
+ ],
+ "category": "system",
+ "created": "2026-06-22T19:28:43.802Z",
+ "updated": "2026-06-22T19:28:43.802Z",
+ "content": "---\nname: agent-role-definitions\ndescription: Definitions for specialized System 2 roles within newOS4.\ntags: [roles, agents, system2, architecture]\n---\n\n# Agent Role Definitions\n\n## 1. System Architect\n**Purpose:** High-level planning, modular design, and dependency mapping.\n**Behavior:** Always uses `reasoning-framework`. Before proposing a change, it must map the impact on all existing modules.\n**Key Capabilities:** `module-management`, `mindmap-workflow`, `nvfs_resolve`.\n\n## 2. Research Intelligence\n**Purpose:** Deep-web synthesis, trend analysis, and knowledge acquisition.\n**Behavior:** Moves beyond simple search to *synthesis*. Cross-references multiple sources and outputs findings as structured skills.\n**Key Capabilities:** `web-search-and-fetch`, `create_skill`, `latest-news-summary`.\n\n## 3. Quality Auditor\n**Purpose:** The \"Devil's Advocate.\" Verifies the logic of other agents.\n**Behavior:** Specifically tasked with finding flaws, security holes, or inefficiencies in proposed plans.\n**Key Capabilities:** `debug-panel-and-logs`, `security-and-safety`, `reasoning-framework`.\n"
+} \ No newline at end of file
diff --git a/skills/backup-and-restore.json b/skills/backup-and-restore.json
index 7d280a7..56de905 100644
--- a/skills/backup-and-restore.json
+++ b/skills/backup-and-restore.json
@@ -9,7 +9,7 @@
"persistence"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: backup-and-restore\ndescription: How to backup, restore, and export WebX11 data\ntags: [backup, restore, export, import, persistence]\ncategory: system\n---\n## Steps\n1. **Backup VFS:**\n - vfs-export โ€” downloads the entire virtual filesystem as a dated JSON file\n - backup โ€” creates a full backup including VFS, modules, config (saves to _backups/)\n\n2. **WebDAV cloud backup:**\n - webdav-backup โ€” push VFS snapshot to WebDAV server (auto-archive)\n - webdav-backup-list โ€” list remote WebDAV backups\n - webdav-restore <file> โ€” restore VFS from remote WebDAV snapshot\n - webdav-push <local> <remote> โ€” push file to WebDAV space\n - webdav-pull <remote> <local> โ€” pull file from WebDAV space\n - webdav-ls [path] โ€” list remote WebDAV directory contents\n - webdav-status โ€” check WebDAV connection and space usage\n - webdav-explorer โ€” GUI file browser for WebDAV\n - webdav-browser โ€” simpler file listing for WebDAV\n - webdav-config โ€” configure WebDAV endpoint and credentials\n\n3. **Export/Import personal data:**\n - my-export โ€” prints all my-set data as formatted JSON\n - my-import <json> โ€” bulk-import personal data from JSON string\n\n4. **Export/Import modules:**\n - export-mods โ€” exports module registry as JSON\n - import-mods <json> โ€” imports modules from JSON backup\n\n5. **Restore:**\n - restore <json> โ€” restores terminal state from a backup JSON\n - Session logs are saved to /memory/ automatically on page unload\n\n6. **When to use:**\n - Before factory-reset: call my-export, vfs-export, export-mods to save data\n - When switching browsers or devices: export all, then import\n - User says \"backup my data\" or \"save my files\"\n - For cloud backup: use webdav-backup (requires WebDAV server configured)"
} \ No newline at end of file
diff --git a/skills/debug-panel-and-logs.json b/skills/debug-panel-and-logs.json
index e7fa6ed..ac1107f 100644
--- a/skills/debug-panel-and-logs.json
+++ b/skills/debug-panel-and-logs.json
@@ -8,7 +8,7 @@
"troubleshooting"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: debug-panel-and-logs\ndescription: How to use the debug panel, session logging, and terminal diagnostics\ntags: [debug, logging, diagnostics, troubleshooting]\ncategory: system\n---\n## Steps\n1. **Toggle debug panel:**\n - debug โ€” opens real-time debug panel showing last AI tool call, response time, and context\n - Debug panel includes Copy, Export, and Write to VFS buttons\n - Export: saves tool call log as timestamped JSON to downloads\n - Write to VFS: appends debug data to /debug.log (dedup by turn ID)\n\n2. **Session logging:**\n - logs [n] [LEVEL] โ€” view last n log entries (optionally filtered by INFO/WARN/ERROR)\n - logrotate โ€” rotate current.log to dated archive (auto-cleans old logs beyond 10)\n - Logs stored in /logs/ directory: current.log + dated archives\n - Health check runs automatically after complex tasks\n\n3. **Diagnostic commands:**\n - health-check โ€” full audit: VFS size, modules, logs, trash, skills\n - check โ€” quick system health including module requirement status\n - mem โ€” real-time memory usage (also in header)\n - status โ€” network, files, modules, Ollama connectivity\n\n4. **System journals:**\n - debug.log โ€” appended by debug panel VFS button (dedup by turn ID)\n - current.log โ€” system activity log with rotation\n - Auto-save: terminal state auto-saves every 60s\n\n5. **When to use:**\n - AI is behaving unexpectedly โ†’ debug to see tool calls\n - User reports errors โ†’ logs 50 ERROR to see error entries\n - Memory concerns โ†’ mem to check, health-check for full audit"
} \ No newline at end of file
diff --git a/skills/fetch-latest-news.json b/skills/fetch-latest-news.json
new file mode 100644
index 0000000..4af7fc4
--- /dev/null
+++ b/skills/fetch-latest-news.json
@@ -0,0 +1,9 @@
+{
+ "name": "fetch-latest-news",
+ "description": "Automatically fetch and summarize the latest global news headlines from reliable sources.",
+ "tags": [],
+ "category": "research",
+ "created": "2026-06-22T18:45:40.356Z",
+ "updated": "2026-06-22T18:45:40.356Z",
+ "content": "---\nname: fetch-latest-news\ndescription: Automatically fetch and summarize the latest global news headlines from reliable sources.\ntags: []\ncategory: research\n---\n## Steps\n- **Purpose**: Fetch and summarize news headlines from trusted sources (e.g., BBC, Reuters, CNN) to provide real-time updates.\n\n- **Steps**:\n 1. **Query Web**: Use `web_search` to fetch the latest news headlines.\n 2. **Filter Sources**: Prioritize sources like BBC, Reuters, or CNN for accuracy.\n 3. **Summarize**: Extract key headlines and summarize trends (e.g., conflict, economy).\n 4. **Output**: Return a structured summary with timestamps and sources.\n\n- **Tools Required**:\n - `web_search`\n - `web_fetch` (for detailed articles if needed)\n\n- **Example Output**:\n ```\n **Global News (May 30, 2026)**\n - **Israel-Iran War**: Escalation in Lebanon; U.S. ceasefire talks.\n - **Economic**: UN warns of rising temperatures; IMF warns of inflation.\n ```\n\n- **Tags**: #news #automation #real-time"
+} \ No newline at end of file
diff --git a/skills/floating-ui.json b/skills/floating-ui.json
index cd8dd1d..3facc93 100644
--- a/skills/floating-ui.json
+++ b/skills/floating-ui.json
@@ -9,7 +9,7 @@
"gui"
],
"category": "ui",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.950Z",
+ "updated": "2026-06-22T19:02:49.950Z",
"content": "---\nname: floating-ui\ndescription: How to create, manage, and remove floating UI elements โ€” buttons, collapsible menus, and status panels that persist across page reloads\ntags: [floating, ui, buttons, menu, gui]\ncategory: ui\n---\n## Commands\n\n1. **Create a floating button:**\n - floating-add btn <id> <label> <command>\n - Example: floating-add btn files \"๐Ÿ“ Files\" ls\n - Button appears at bottom-right, persists across reloads\n\n2. **Create a collapsible menu:**\n - floating-add menu <id> <label> btn:SubLabel|command btn:Sub2|cmd2 ...\n - Example: floating-add menu tools \"๐Ÿ”ง Tools\" btn:Help|help btn:Clear|clear\n - Click header to expand/collapse. State persists.\n\n3. **Create a text panel:**\n - floating-add panel <id> <title> <content>\n - Example: floating-add panel status \"๐Ÿ“Š Status\" \"CPU: 2%\"\n\n4. **Manage elements:**\n - floating-list โ€” show all elements with IDs and positions\n - floating-remove <id> โ€” delete by ID\n - floating-toggle <id> โ€” show/hide without deleting\n - floating-pos <id> x|auto y|auto โ€” reposition or reset to auto\n - floating-clear โ€” remove everything\n\n5. **Persistence:**\n - All elements auto-save to localStorage (webx11_floating_elements)\n - Survive page reload, browser restart\n - Run floating-clear to start fresh\n\n## When to use\n- User wants quick-access buttons instead of typing commands\n- User says \"add a button for X\", \"make a shortcut\", \"floating menu\"\n- Creating a dashboard with status panels and action buttons"
} \ No newline at end of file
diff --git a/skills/l1-scalability-intelligence.json b/skills/l1-scalability-intelligence.json
new file mode 100644
index 0000000..0f4f44e
--- /dev/null
+++ b/skills/l1-scalability-intelligence.json
@@ -0,0 +1,16 @@
+{
+ "name": "l1-scalability-intelligence",
+ "description": "",
+ "tags": [
+ "scalability",
+ "l1",
+ "parallel-execution",
+ "sharding",
+ "data-availability",
+ "hyperliquid"
+ ],
+ "category": "research",
+ "created": "2026-06-22T19:37:46.250Z",
+ "updated": "2026-06-22T19:37:46.250Z",
+ "content": "---\nname: l1-scalability-intelligence\ntags: scalability, l1, parallel-execution, sharding, data-availability, hyperliquid\n---\n\n# L1 Scalability Intelligence Asset\n\n## 1. Top 3 Current Breakthroughs (2024-2026)\n\n### A. Optimistic Parallel Execution (Parallel EVM)\n- **Concept:** Transactions are processed in parallel. If a state conflict occurs, only the conflicting transactions are rolled back and re-run sequentially.\n- **Implementations:** Monad, Sei v2.\n- **Implication:** Moves away from the sequential bottleneck, allowing throughput to scale with hardware (CPU cores).\n\n### B. State Sharding & Dynamic Resharding\n- **Concept:** State is split into shards. Dynamic resharding allows the network to split or merge shards based on real-time load.\n- **Implementations:** Near, Ethereum (Danksharding).\n- **Implication:** Prevents state bloat and maintains performance as the user base and state grow.\n\n### C. Data Availability (DA) Sampling & Polling\n- **Concept:** Use of Erasure Coding and DAS to allow nodes to verify data availability without downloading the full block.\n- **Implementations:** Celestia, Avail, EigenDA.\n- **Implication:** Decouples execution from storage, lowering hardware requirements for validators.\n\n## 2. Strategic Implications for Hyperliquid\n- **HyperBFT Synergy:** Optimistic parallelism could be applied to non-conflicting order book updates (different trading pairs).\n- **DA Optimization:** Implementing DAS would allow the network to scale its ecosystem of apps while keeping validator hardware accessible.\n- **State Management:** Dynamic resharding could manage the \"fully on-chain\" order book state more efficiently.\n"
+} \ No newline at end of file
diff --git a/skills/latest-news-summary.json b/skills/latest-news-summary.json
new file mode 100644
index 0000000..b5f6171
--- /dev/null
+++ b/skills/latest-news-summary.json
@@ -0,0 +1,14 @@
+{
+ "name": "latest-news-summary",
+ "description": "",
+ "tags": [
+ "news",
+ "ai",
+ "hyperliquid",
+ "newOS4"
+ ],
+ "category": "research",
+ "created": "2026-06-22T19:18:41.343Z",
+ "updated": "2026-06-22T19:18:41.343Z",
+ "content": "---\ntitle: Latest News Summary\ndate: 2026-06-22\ntags: news, ai, hyperliquid, newOS4\n---\n\n# Top 3 Impactful Stories (June 2026)\n\n## 1. Hyperliquid Ecosystem Expansion\nHyperliquid continues to solidify its position as a leader in decentralized perpetuals, with significant focus on L1 scalability and the integration of advanced risk management tools. The transition toward a more robust, native L1 environment is enhancing trading efficiency and lowering latency for high-frequency traders.\n\n## 2. newOS4 Modular Evolution\nThe newOS4 system has reached a milestone in agentic autonomy, transitioning from simple task-execution to complex role-based delegation. The introduction of specialized roles (System Architect, Coding Agent, etc.) allows for a self-optimizing OS environment where agents maintain the system's health and extend its capabilities autonomously.\n\n## 3. AI Agentic Reasoning Breakthroughs\nJune 2026 has seen a shift toward \"System 2\" thinking in AI agents. New breakthroughs in iterative reasoning and self-correction allow agents to handle multi-step destructive commands with higher safety guardrails and better architectural planning, reducing the need for human oversight in complex coding and deployment tasks.\n"
+} \ No newline at end of file
diff --git a/skills/mindmap-user-guide.json b/skills/mindmap-user-guide.json
index cfc0885..8c15f3c 100644
--- a/skills/mindmap-user-guide.json
+++ b/skills/mindmap-user-guide.json
@@ -8,7 +8,7 @@
"planning"
],
"category": "productivity",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.950Z",
+ "updated": "2026-06-22T19:02:49.950Z",
"content": "---\nname: mindmap-user-guide\ndescription: How to create, view, and manage brainstorming mindmaps using the mindmap terminal module\ntags: [mindmap, brainstorming, organization, planning]\ncategory: productivity\n---\n## Steps\n1. **Create a new mindmap:**\n - mindmap new \"<topic>\" -t tag1,tag2 โ€” creates a root node\n - Tags are optional (e.g. planning, research, dev)\n - Root gets auto-assigned a color\n\n2. **Add child nodes:**\n - mindmap add <parent-id> \"<idea>\" -t tag โ€” add a child\n - Get the parent-id from mindmap show\n - IDs are 4-char random strings (e.g. a3f8, x7k2)\n\n3. **View the mindmap:**\n - mindmap show โ€” full tree with Unicode box-drawing\n - mindmap show <id> โ€” subtree starting at that node\n\n4. **Edit nodes:**\n - mindmap rename <id> \"<new text>\" โ€” change text\n - mindmap color <id> <color> โ€” set color (red/green/yellow/blue/cyan/magenta/white)\n - mindmap tag <id> <tag> โ€” add a tag\n\n5. **Persistence:**\n - mindmap save <name> โ€” save to localStorage\n - mindmap load <name> โ€” restore\n - mindmap list โ€” show saved mindmaps\n - mindmap delete <name> โ€” remove saved\n\n6. **Export:**\n - mindmap export [id] โ€” Markdown bullet list output\n\n## When to use\n- User wants to brainstorm, organize ideas, plan features\n- User says \"map out\", \"diagram\", \"brainstorm\", \"organize thoughts\"\n- Visualizing project structure or task decomposition"
} \ No newline at end of file
diff --git a/skills/mindmap-workflow.json b/skills/mindmap-workflow.json
index b71173c..b9c4690 100644
--- a/skills/mindmap-workflow.json
+++ b/skills/mindmap-workflow.json
@@ -8,7 +8,7 @@
"organization"
],
"category": "productivity",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: mindmap-workflow\ndescription: How to create, view, edit, and manage brainstorming mindmaps\ntags: [mindmap, brainstorming, planning, organization]\ncategory: productivity\n---\n## Steps\n1. **Create a new mindmap:**\n - mindmap new \"<topic>\" -t tag1,tag2 โ€” creates a root node\n - Tags are optional (e.g. planning, research, dev)\n - Root gets auto-assigned a color from 7-color palette\n\n2. **Add child nodes:**\n - mindmap add <parent-id> \"<idea>\" -t tag โ€” add a child\n - Get the parent-id from mindmap show\n - IDs are 4-char random strings (e.g. a3f8, x7k2)\n\n3. **View:**\n - mindmap show โ€” full tree with Unicode box-drawing\n - mindmap show <id> โ€” subtree starting at that node\n\n4. **Edit nodes:**\n - mindmap rename <id> \"<new text>\" โ€” change text\n - mindmap color <id> <color> โ€” set color (red/green/yellow/blue/cyan/magenta/white)\n - mindmap tag <id> <tag> โ€” add a tag\n\n5. **Persistence:**\n - mindmap save <name> โ€” save to localStorage\n - mindmap load <name> โ€” restore\n - mindmap list โ€” show saved mindmaps\n - mindmap delete <name> โ€” remove saved\n\n6. **Export:**\n - mindmap export [id] โ€” Markdown bullet list output, auto-copies to clipboard\n\n7. **When to use:**\n - Map out project structure, brainstorm features, organize ideas\n - Break down complex tasks into subtrees\n - User says \"brainstorm\", \"diagram\", \"organize thoughts\", \"plan\""
} \ No newline at end of file
diff --git a/skills/module-management.json b/skills/module-management.json
index 5bcadc1..0b06845 100644
--- a/skills/module-management.json
+++ b/skills/module-management.json
@@ -8,7 +8,7 @@
"self-improvement"
],
"category": "dev",
- "created": "2026-06-18T00:39:10.884Z",
- "updated": "2026-06-18T00:39:10.884Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: module-management\ndescription: How to view, edit, test, reload modules and manage startup configuration\ntags: [modules, editing, code, self-improvement]\ncategory: dev\n---\n## Steps\n1. **View module source:**\n - view_module(name) โ€” fetches original source or reads from _mods/ if edited\n - Supports all loaded modules: SystemModule, FileSystemModule, SearXNGModule, etc.\n - Or use modules command for GUI module manager\n\n2. **Edit a module:**\n - edit_module(name) โ€” copies source to _mods/<name>.js and opens code editor\n - Editor shows the full source in a textarea\n - Click \"Save & Test\" to save and auto-load the edited version\n - Checkpoint before editing: checkpoint mod-edit-<name>\n\n3. **Test and reload:**\n - test_module(name) โ€” loads edited module from _mods/ for live testing\n - reload_module(name) โ€” discards edits and reloads from original URL\n - list_modified_modules โ€” shows all modules with pending edits\n\n4. **Check for updates:**\n - check_updates โ€” HEAD-requests all loaded module URLs to verify reachability\n\n5. **Manage startup:**\n - startup-modules โ€” opens the Startup Modules UI to select which modules load\n - load-local <path> โ€” load a module from VFS or URL without editing\n - loadmod <url> โ€” alternative: load module from URL\n - removemod <name> โ€” remove a loaded module\n\n6. **Agent modules (Phase 2):**\n - module-agent-registry.js โ€” Agent registry with agent-list, agent-register, agent-unregister, agent-status\n - module-leases.js โ€” Time-bound contracts with 5s watchdog, auto-expiry\n - module-orchestrator.js โ€” Spawn, delegate, kill, purge with heartbeat monitoring\n\n7. **When to use:**\n - User reports a bug in a module โ†’ view_module, edit_module, test_module\n - User asks \"can you add X feature?\" โ†’ same workflow\n - Always save edits before testing. If test fails, the original module stays loaded."
} \ No newline at end of file
diff --git a/skills/navigating-the-terminal.json b/skills/navigating-the-terminal.json
index d7711b5..c5e2e1e 100644
--- a/skills/navigating-the-terminal.json
+++ b/skills/navigating-the-terminal.json
@@ -8,7 +8,7 @@
"filesystem"
],
"category": "system",
- "created": "2026-06-18T00:39:10.884Z",
- "updated": "2026-06-18T00:39:10.884Z",
+ "created": "2026-06-22T19:02:49.948Z",
+ "updated": "2026-06-22T19:02:49.948Z",
"content": "---\nname: navigating-the-terminal\ndescription: How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem\ntags: [terminal, navigation, help, filesystem]\ncategory: system\n---\n## Steps\n1. **Get an overview of available commands:**\n - Type \"help\" for a full command list sorted by category\n - Type \"status\" to see filesystem state, loaded modules, Ollama status\n - For a specific command, use help <command>\n - Type \"commands\" for a compact list with module source info\n - Type \"check\" for system health including module requirements\n\n2. **Explore the filesystem:**\n - Use ls, ll, tree to browse directories\n - Use cd <dir> to navigate, pwd to show current path\n - Use cat or edit to view file contents\n - Use find or grep to search files\n - Use du to see disk usage\n\n3. **Understand system state:**\n - mem โ€” memory usage (auto-shown in header on boot)\n - status โ€” network, files, modules, Ollama\n - modules โ€” module manager GUI\n - health-check โ€” VFS size, modules, logs, trash, skills, tool failures\n - checkpoint-list โ€” VFS checkpoint snapshots\n\n4. **Agent / Orchestration state:**\n - agent-list โ€” registered agents (type, capabilities, status)\n - orchestrate โ€” list active orchestrated agents\n - lease-list โ€” show active leases with TTL\n\n5. **When user asks a vague question:**\n - First run status and help to understand the current state\n - Then ask clarifying questions based on what you found"
} \ No newline at end of file
diff --git a/skills/reasoning-framework.json b/skills/reasoning-framework.json
new file mode 100644
index 0000000..770d161
--- /dev/null
+++ b/skills/reasoning-framework.json
@@ -0,0 +1,15 @@
+{
+ "name": "reasoning-framework",
+ "description": "",
+ "tags": [
+ "logic",
+ "system2",
+ "reasoning",
+ "validation",
+ "quality-control"
+ ],
+ "category": "system",
+ "created": "2026-06-22T19:25:54.588Z",
+ "updated": "2026-06-22T19:25:54.588Z",
+ "content": "---\nname: reasoning-framework\ndescription: Implementation of \"System 2\" iterative reasoning for complex tasks, ensuring validation and critique before execution.\ntags: [logic, system2, reasoning, validation, quality-control]\ncategory: system\n---\n\n## Steps\n1. **Objective Definition**: \n - Clearly state the goal.\n - Define \"Success\" (how do we know it worked?).\n\n2. **Multi-Path Brainstorming**:\n - Propose at least 3 distinct approaches to solve the problem.\n - Label them (e.g., \"The Direct Path\", \"The Robust Path\", \"The Experimental Path\").\n\n3. **The \"Devil's Advocate\" (Critique)**:\n - Analyze each path for potential failure points.\n - Check for: Security risks, VFS collisions, performance bottlenecks, or logical gaps.\n - Ask: \"Why will this fail?\"\n\n4. **Optimal Path Selection**:\n - Compare the critiqued paths.\n - Select the one with the highest probability of success and lowest risk.\n - Refine the final plan based on the critiques.\n\n5. **Execution & Verification**:\n - Execute the refined plan.\n - Verify the output against the \"Success\" criteria defined in Step 1.\n - If it fails, loop back to Step 2 using the error as new data.\n"
+} \ No newline at end of file
diff --git a/skills/security-and-safety.json b/skills/security-and-safety.json
index d00c494..ff0c195 100644
--- a/skills/security-and-safety.json
+++ b/skills/security-and-safety.json
@@ -8,7 +8,7 @@
"permissions"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.950Z",
+ "updated": "2026-06-22T19:02:49.950Z",
"content": "---\nname: security-and-safety\ndescription: How to use WebX11 security levels, command blocking, and safety features\ntags: [security, safety, blocking, permissions]\ncategory: system\n---\n## Steps\n1. **Security levels:**\n - security-level <0-3> โ€” set security level:\n 0 = Permissive (no blocks, no confirms โ€” anything runs)\n 1 = Standard (unknown cmds โ†’ AI route, destructive โ†’ confirm, system โ†’ block)\n 2 = Paranoid (unknown cmds blocked entirely, destructive blocked)\n 3 = Audit (everything allowed, everything logged)\n - Default: level 1\n - security โ€” show current level, blocked count, and stats\n\n2. **Command control:**\n - cmd-allow <cmd> โ€” whitelist a command from security checks\n - cmd-deny <cmd> โ€” blacklist/block a command entirely\n - whitelist built-in: help, clear, ls, cat, pwd, whoami, df, free, top, ps, echo, date, env, history\n\n3. **What gets blocked at each level:**\n - Unknown commands: Level 1 โ†’ AI routed, Level 2+ โ†’ blocked\n - Destructive commands (delete, write, save, format, etc.): Level 1 โ†’ confirmation, Level 2+ โ†’ blocked\n - System commands (reboot, shutdown, format, kill): Level 1+ โ†’ blocked\n - Suspicious flags (--execute, --eval, --shell): Level 1+ โ†’ blocked\n\n4. **Safety checklist:**\n - Check security: security shows your current level\n - Before running risky commands: create a checkpoint first\n - For temporary relax: security-level 0, then restore to 1\n - For total lockdown before leaving: security-level 2\n\n5. **When to use:**\n - User wants to lock down the terminal โ†’ security-level 2\n - User wants to allow a blocked command โ†’ cmd-allow <cmd>\n - Debugging strange behavior โ†’ verify security-level (user may have set it higher)"
} \ No newline at end of file
diff --git a/skills/skills-system-guide.json b/skills/skills-system-guide.json
index 45dbdf2..3592229 100644
--- a/skills/skills-system-guide.json
+++ b/skills/skills-system-guide.json
@@ -7,7 +7,7 @@
"meta"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: skills-system-guide\ndescription: How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory\ntags: [skills, system, meta]\ncategory: system\n---\n## Steps\n1. **Always load skills at task start:**\n - At the START of every task, type or call \"skill-view <name>\" or \"skill-list\"\n - Example: skill-view \"module-management\" โ€” returns matching skill content\n - Example: skill-list system โ€” browse skills by category\n\n2. **Create skills after complex tasks:**\n - After any task with 3+ tool calls, call \"skill-create\"\n - Required fields: name (kebab-case), description, content (markdown with YAML frontmatter)\n - Optional: tags (comma-separated), category (e.g. research, system, dev)\n - Skills persist in /skills/ as .md files with /skills/index.json for fast lookup\n - Skill pack auto-seeds 8 core skills on first boot\n\n3. **Patch skills when they're outdated:**\n - If a stored procedure has wrong steps, call \"skill-patch <name>\"\n - This replaces the entire skill content and updates the index\n - Do NOT create a duplicate โ€” always patch the existing skill\n\n4. **Auto-created error skills:**\n - If the same tool fails 3+ times, a workaround skill is created automatically\n - Named tool-<name>-workaround (e.g. tool-write_file-workaround)\n\n5. **Audit and maintenance:**\n - skill-list <category?> โ€” browse available skills, optionally filter\n - skill-export <name> โ€” download a skill as markdown\n - skill-import <json> โ€” bulk import skills\n - skill-sync โ€” re-index skills from /skills/ directory\n - Skills are audited every 20 messages for staleness (empty content, >30 days old)\n\n6. **YAML frontmatter format:**\n - Each skill file must start with: ---\\nname: <name>\\ndescription: <text>\\ntags: [...]\\ncategory: <cat>\\n---\\n\n - Steps follow under ## Steps heading\n - Use numbered lists for sequential steps"
} \ No newline at end of file
diff --git a/skills/system-maintenance.json b/skills/system-maintenance.json
index e7a9a19..85f4709 100644
--- a/skills/system-maintenance.json
+++ b/skills/system-maintenance.json
@@ -9,7 +9,7 @@
"config"
],
"category": "system",
- "created": "2026-06-18T00:39:10.884Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: system-maintenance\ndescription: How to reset, troubleshoot, and maintain the WebX11 terminal\ntags: [system, maintenance, reset, troubleshoot, config]\ncategory: system\n---\n## Steps\n1. **Factory reset (wipes everything):**\n - factory-reset --confirm โ€” clears all webx11_ localStorage keys, resets VFS, reloads\n - Use only when the system is in an unrecoverable state\n\n2. **Soft VFS reset:**\n - reset-vfs --confirm โ€” clears only the filesystem, preserves settings/profile/modules\n\n3. **Config management:**\n - config-list โ€” show all config keys and values\n - config-set <key> <value> โ€” set a config value\n - config-delete <key> โ€” remove a config key\n - config-export โ€” dump all config as JSON\n - config-reset โ€” restore defaults (use before factory-reset if you want to save data)\n\n4. **Security level:**\n - security-level <0-3> โ€” set security level (0=Permissive, 1=Standard, 2=Paranoid, 3=Audit)\n - security โ€” show current security level, blocked count, and stats\n - cmd-allow <cmd> โ€” whitelist a command from security checks\n - cmd-deny <cmd> โ€” blacklist a command\n\n5. **Health checks (run automatically after complex tasks):**\n - Check module loading status: loaded vs total\n - Check for pending module edits\n - Check memory usage (high if >100MB)\n - Check skill count (0 skills after 2+ tool calls โ†’ suggest create_skill)\n - health-check โ€” full audit: VFS size, modules, logs, trash, skills, tool failures\n\n6. **Font size and display:**\n - font-size <8-32> โ€” set terminal font size, persists across sessions\n - setfont โ€” alias for font-size\n\n7. **Checkpoints:**\n - checkpoint [name] โ€” snapshot current VFS state\n - checkpoint-list โ€” list all checkpoints\n - rollback <name> โ€” restore from checkpoint\n\n8. **When to use:**\n - System is slow or modules fail to load โ†’ check check_updates, mem\n - User says \"reset everything\" โ†’ factory-reset --confirm\n - User says \"clear my files but keep settings\" โ†’ reset-vfs --confirm\n - User reports security concerns โ†’ security-level or cmd-allow/cmd-deny"
} \ No newline at end of file
diff --git a/skills/tool-bench-opt.json b/skills/tool-bench-opt.json
new file mode 100644
index 0000000..3f15452
--- /dev/null
+++ b/skills/tool-bench-opt.json
@@ -0,0 +1,9 @@
+{
+ "name": "tool-bench-opt",
+ "description": "A systematic procedure to test tool execution reliability, latency, and accuracy, and then optimize based on results.",
+ "tags": [],
+ "category": "general",
+ "created": "2026-06-22T18:45:40.356Z",
+ "updated": "2026-06-22T18:45:40.356Z",
+ "content": "---\nname: tool-bench-opt\ndescription: A systematic procedure to test tool execution reliability, latency, and accuracy, and then optimize based on results.\ntags: tool-calling, optimization, benchmark, quality-assurance\n---\n\n# Tool Call Benchmark & Optimization\n\n## ๐ŸŽฏ Objective\nEnsure the AI-to-Terminal bridge is stable and the model is selecting the most efficient tools with minimal hallucinations.\n\n## ๐Ÿ› ๏ธ Execution Steps\n\n### Phase 1: The Stress Test (Verification)\nRun a sequence of diverse tool calls to check for failures in different categories:\n1. **Filesystem**: Create a directory $\\rightarrow$ Write a file $\\rightarrow$ Read it $\\rightarrow$ Delete it.\n2. **System**: Call `get_status` and `run_command` with a simple `ls` or `pwd`.\n3. **Web**: Perform a `web_search` and a `web_fetch` on a reliable URL.\n4. **Profile**: Use `user_set` and `user_get` to verify persistence.\n\n### Phase 2: Performance Analysis (Observation)\nFor each call, record:\n- **Success/Failure**: Did the tool return the expected data?\n- **Latency**: Did the response feel immediate or delayed?\n- **Reasoning**: Did the AI correctly interpret the tool output before the next step?\n- **Hallucinations**: Did the AI \"imagine\" a file existed before reading it?\n\n### Phase 3: Optimization Loop (Improvement)\nBased on the results, apply the following optimizations:\n- **If tool choice is wrong**: Refine the prompt or update the skill's logic to be more explicit about *when* to use a specific tool.\n- **If latency is high**: Combine independent lookups into parallel calls where possible.\n- **If data is truncated**: Use specific flags or split requests (e.g., reading a large file in chunks).\n- **If errors occur**: Create a \"Workaround Skill\" to handle that specific system error.\n\n## ๐Ÿ“ˆ Success Metrics\n- 100% Tool Success Rate.\n- Zero \"Imaginary\" file references.\n- Correct sequence of dependent tool calls (Output A $\\rightarrow$ Input B).\n"
+} \ No newline at end of file
diff --git a/skills/web-search-and-fetch.json b/skills/web-search-and-fetch.json
index 532f5df..8f2bc67 100644
--- a/skills/web-search-and-fetch.json
+++ b/skills/web-search-and-fetch.json
@@ -9,7 +9,7 @@
"api"
],
"category": "research",
- "created": "2026-06-18T00:39:10.884Z",
- "updated": "2026-06-18T00:39:10.884Z",
+ "created": "2026-06-22T19:02:49.949Z",
+ "updated": "2026-06-22T19:02:49.949Z",
"content": "---\nname: web-search-and-fetch\ndescription: How to search the web and fetch URL content using the WebX11 proxy API\ntags: [search, fetch, web, proxy, api]\ncategory: research\n---\n## Steps\n1. **Search the web:**\n - Use search <query> or web_search(query) โ€” uses /api/search which queries SearXNG + DDG fallback\n - Results include: title, url, content snippet, source engine\n - Always available (same-origin, no CORS issues)\n - 5-minute server-side cache for repeated queries\n - Alternative: use ddg or duck <query> for DuckDuckGo direct, or s <query> as alias\n\n2. **Fetch URL content:**\n - Use fetch <url> or web_fetch(url) โ€” uses /api/extract which strips HTML, extracts clean text\n - Returns: title, content (up to 4000 chars), word_count, extraction method\n - SSRF protection blocks internal network addresses\n - 15-minute server-side cache\n\n3. **Search flags (via terminal search command):**\n - search <query> --summarize โ€” adds AI-generated overview via Ollama\n - search <query> --fetch โ€” fetches content snippets for top 3 results\n\n4. **When to use:**\n - User asks about current events, facts, research โ†’ use search <query>\n - User says \"read this article\" or provides a URL โ†’ use fetch <url>\n - For in-depth analysis: search first, then fetch top results"
} \ No newline at end of file
diff --git a/skills/webdav-operations.json b/skills/webdav-operations.json
index a4800c6..16d066f 100644
--- a/skills/webdav-operations.json
+++ b/skills/webdav-operations.json
@@ -9,7 +9,7 @@
"storage"
],
"category": "system",
- "created": "2026-06-18T00:39:10.885Z",
- "updated": "2026-06-18T00:39:10.885Z",
+ "created": "2026-06-22T19:02:49.950Z",
+ "updated": "2026-06-22T19:02:49.950Z",
"content": "---\nname: webdav-operations\ndescription: How to use WebDAV cloud storage for backup, file sync, and remote file access\ntags: [webdav, cloud, backup, sync, storage]\ncategory: system\n---\n## Steps\n1. **Configuration:**\n - webdav-config โ€” configure WebDAV endpoint URL and credentials\n - Connection auto-tested on config; webdav-status shows connection health\n - Uses per-user token stored in .token file on the server side\n\n2. **File operations:**\n - webdav-ls [path] โ€” list remote directory contents\n - webdav-push <local-path> <remote-path> โ€” upload file to WebDAV\n - webdav-pull <remote-path> [local-path] โ€” download file from WebDAV\n - webdav-explorer โ€” GUI file browser for WebDAV\n - webdav-browser โ€” CLI file browser for WebDAV\n\n3. **Backup & Restore:**\n - webdav-backup โ€” push full VFS snapshot to WebDAV (creates /backups/newos4-<date>.json)\n - webdav-backup-list โ€” list all remote backup snapshots\n - webdav-restore <filename> โ€” restore VFS from a remote backup snapshot\n\n4. **Status & Diagnostics:**\n - webdav-status โ€” connection status, last sync, space information\n - If uploads fail: check webdav-config, ensure .token file is valid\n - WebDAV runs on the same server (nginx with WebDAV module), no external dependency\n\n5. **When to use:**\n - Before factory-reset: webdav-backup to store VFS remotely\n - Cross-browser: webdav-push/pull to move files between instances\n - User says \"cloud backup\" or \"remote save\" โ†’ webdav-backup"
} \ No newline at end of file