aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-06-02 18:00:37 +0200
committerAgando <roduccomm@gmail.com>2026-06-02 18:00:37 +0200
commitaafb0fbde5289a45f9f818a00141f80b149be283 (patch)
treed4d8f588187719c99240fbaef1940c068402b892
parent6d41e590a38c73ef60f1c04beaf8f5438f350f46 (diff)
auto: 2026-06-02_18:00 changes
-rw-r--r--A2A_protocol_spec.md45
-rw-r--r--BUGFIX-SUGGESTIONS.md355
-rw-r--r--chat/chat-modules.js16
-rw-r--r--chat/chat-ui.html5
-rw-r--r--cheatsheet.html43
-rw-r--r--help.html161
-rw-r--r--modules/core/module-agent-registry.js79
-rw-r--r--modules/core/module-aiassist.js74
-rw-r--r--modules/core/module-chatstudio.js32
-rw-r--r--modules/core/module-fs.js34
-rw-r--r--modules/core/module-leases.js102
-rw-r--r--modules/core/module-loader.js7
-rw-r--r--modules/core/module-orchestrator.js151
-rw-r--r--modules/core/module-system.js20
-rw-r--r--modules/core/terminal.js7
-rw-r--r--modules/ext/skill-pack-core.js284
-rw-r--r--modules/ext/webdav.js515
-rw-r--r--newos4_vision.html176
-rw-r--r--newos4_whitepaper.md234
-rw-r--r--review-newos4.html58
-rw-r--r--skills/agent-orchestration.md35
-rw-r--r--skills/bug-tracker.md30
-rw-r--r--skills/debug-panel-and-logs.md34
-rw-r--r--skills/index.json249
-rw-r--r--skills/security-and-safety.md37
-rw-r--r--skills/task-manager.md37
-rw-r--r--skills/webdav-operations.md33
27 files changed, 2278 insertions, 575 deletions
diff --git a/A2A_protocol_spec.md b/A2A_protocol_spec.md
new file mode 100644
index 0000000..e73b0e9
--- /dev/null
+++ b/A2A_protocol_spec.md
@@ -0,0 +1,45 @@
+# A2A Protocol Specification v0.1
+
+## Overview
+Agent-to-Agent (A2A) is a decentralized message protocol for agent negotiation within newOS4. Agents discover each other via VFS registrations and communicate through a shared message queue. No central broker.
+
+## Message Format
+All messages are JSON with this envelope:
+
+```json
+{
+ "a2a_version": "0.1",
+ "msg_id": "<uuid>",
+ "type": "request" | "response" | "broadcast" | "lease" | "heartbeat",
+ "from": "<agent_id>",
+ "to": "<agent_id>" | "*",
+ "timestamp": "<ISO 8601>",
+ "ttl_seconds": 30,
+ "contract": {
+ "capabilities": ["list_files", "read_file", "web_search"],
+ "constraints": {
+ "max_tool_turns": 8,
+ "max_duration_seconds": 60
+ }
+ },
+ "payload": { }
+}
+```
+
+## Transport Layer
+Each agent has a VFS mailbox at `/agents/<agent_id>/inbox.json` and publishes to `/agents/<agent_id>/outbox.json`. The orchestrator monitors inboxes via periodic polling (500ms interval).
+
+## Message Types
+- **request**: Point-to-point task delegation. From=orchestrator, To=worker.
+- **response**: Task result. From=worker, To=orchestrator.
+- **broadcast**: Discovery / capability advertisement. To="*".
+- **lease**: Time-bound contract granting a worker exclusive task rights.
+- **heartbeat**: Alive signal. Every 5 seconds. Missing 3 consecutive = presumed dead.
+
+## Lifecycle
+1. Orchestrator broadcasts AGENT_REQUEST
+2. Workers respond with capability claim
+3. Orchestrator issues LEASE with TTL
+4. Worker executes, sends RESPONSE
+5. Orchestrator ACKs, LEASE expires
+6. Worker returns to available pool \ No newline at end of file
diff --git a/BUGFIX-SUGGESTIONS.md b/BUGFIX-SUGGESTIONS.md
deleted file mode 100644
index 1d10fb6..0000000
--- a/BUGFIX-SUGGESTIONS.md
+++ /dev/null
@@ -1,355 +0,0 @@
-# newOS4 Bug Fix Suggestions
-
-**Generated:** 2026-05-24
-**Status:** Pending Review
-**Priority:** High (13 issues across 7 files)
-
----
-
-## Executive Summary
-
-| Category | Issues | Files | Severity |
-|----------|--------|-------|----------|
-| File Structure | 5 | 4 | High |
-| Agent System | 5 | 2 | High |
-| AI Routing | 2 | 1 | Medium |
-| Cache | 1 | 1 | Low |
-| **Total** | **13** | **7** | |
-
----
-
-## 1. File Structure Issues
-
-### 1.1 Splash Fallback Ext List Incomplete
-- **File:** `index.html`
-- **Line:** 770
-- **Issue:** Splash fallback hardcodes 5 ext modules but `modules/ext/` directory has 8 files
-- **Missing:** `mindmap.js`, `webdav.js`, `skill-pack-core.js`
-- **Fix:**
- ```javascript
- // Before (5 modules)
- ['Extensions', ['calc.js','voice.js','cron.js','theme.js','wpm.js'], false]
-
- // After (8 modules)
- ['Extensions', ['calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','webdav.js','skill-pack-core.js'], false]
- ```
-
----
-
-### 1.2 Preview Iframe Blocks JavaScript
-- **File:** `index.html`
-- **Line:** 684
-- **Issue:** `<iframe sandbox="allow-same-origin">` missing `allow-scripts`
-- **Impact:** HTML previews with JavaScript don't execute
-- **Fix:**
- ```html
- <!-- Before -->
- <iframe sandbox="allow-same-origin"></iframe>
-
- <!-- After -->
- <iframe sandbox="allow-same-origin allow-scripts"></iframe>
- ```
-
----
-
-### 1.3 Dead Code: EXT_FILES Array
-- **File:** `module-loader.js`
-- **Lines:** 35-37
-- **Issue:** `EXT_FILES` array defined but never referenced (dead code, wrong count)
-- **Impact:** Maintenance confusion, wrong module count (6 vs actual 8)
-- **Fix:** Remove entirely — ext loading uses separate `extKeys` array on line 159
-
----
-
-### 1.4 Packages.json URL Errors
-- **File:** `packages.json`
-- **Lines:** 7-167
-- **Issues:**
- - All 18 package URLs point to `modules/<name>.js` (wrong path)
- - Actual files are in `modules/ext/<name>.js`
- - 12 packages reference files that don't exist anywhere
-- **Impact:** WPM installs fail with 404 errors
-- **Fix Options:**
- 1. **Clean:** Remove 12 phantom packages, fix 6 real URLs to `modules/ext/`
- 2. **Stub:** Create missing files in `modules/ext/`
-- **Recommendation:** Option 1 (clean) — reduces bloat
-
----
-
-### 1.5 Search Uses Intrusive Alert()
-- **File:** `help.html`
-- **Line:** 1149
-- **Issue:** `alert('No results found')` blocks UI
-- **Impact:** Poor UX, modal interruption
-- **Fix:**
- ```javascript
- // Before
- if (!found) alert('No results found for: ' + query);
-
- // After
- if (!found) {
- const msg = document.getElementById('search-result-msg');
- if (msg) {
- msg.textContent = 'No results found for: ' + query;
- msg.style.display = 'block';
- setTimeout(() => { msg.style.display = 'none'; }, 3000);
- }
- }
- ```
-
----
-
-## 2. Agent System Issues
-
-### 2.1 Agent Loop Caps at 1 Turn (Not 5)
-- **File:** `module-aiassist.js`
-- **Lines:** 537-547
-- **Issue:** When model returns text + tool_calls, agent executes tools then `return`s (exits loop)
-- **Impact:** Agent stops after 1 tool turn instead of advertised `MAX_TOOL_TURNS = 5`
-- **Root Cause:** Follow-up text-response block returns instead of continuing loop
-- **Fix:**
- ```javascript
- // Before (lines 537-548)
- if (pendingText) {
- const followUp = await this.terminal.ollamaManager.chatWithTools(messages, []);
- if (followUp.message && followUp.message.content) {
- this.terminal.printAIResponse(followUp.message.content);
- return { finalAnswer: followUp.message.content, toolTurns }; // ← exits loop
- }
- }
- continue;
-
- // After
- if (pendingText) {
- messages.push({ role: 'assistant', content: pendingText });
- }
- continue; // ← loop continues, allows up to 5 turns
- ```
-
----
-
-### 2.2 edit_module Not Checked as Destructive
-- **File:** `module-aiassist.js`
-- **Line:** 730
-- **Issue:** `isDestructive()` doesn't include `edit_module` but system prompt (line 227) says it's `(DESTRUCTIVE)`
-- **Impact:** AI told to ask permission but code never confirms
-- **Fix:**
- ```javascript
- // Before
- isDestructive(name) {
- return name === 'write_file' || name === 'delete_file' ||
- name === 'run_command' || name === 'make_directory';
- }
-
- // After
- isDestructive(name) {
- return name === 'write_file' || name === 'delete_file' ||
- name === 'run_command' || name === 'make_directory' ||
- name === 'edit_module';
- }
- ```
-
----
-
-### 2.3 Empty tools:[] Sent to Ollama
-- **File:** `module-aiassist.js`
-- **Line:** 539
-- **Issue:** `chatWithTools(messages, [])` sends empty tools array
-- **Impact:** Some Ollama models reject `tools: []`, triggers unnecessary fallback request
-- **Fix:** Remove follow-up call; push text as `assistant` message then `continue` loop (see 2.1)
-
----
-
-### 2.4 Default Model Blocks Auto-Selection
-- **File:** `ollama-manager.js`
-- **Lines:** 8, 42-45
-- **Issue:** Default model `'gemma4:31b-cloud'` is truthy, so auto-selection skipped even if model doesn't exist
-- **Impact:** Users get silent model errors until manually selecting
-- **Fix:**
- ```javascript
- // Before (lines 42-45)
- if (!this.currentModel && this.models.length > 0) {
- this.currentModel = this.models[0].name;
- // ...
- }
-
- // After
- if (!this.currentModel || !this.models.some(m => m.name === this.currentModel)) {
- if (this.models.length > 0) {
- this.currentModel = this.models[0].name;
- // ...
- }
- }
- ```
-
----
-
-### 2.5 abort() Misses chat() and chatStream()
-- **File:** `ollama-manager.js`
-- **Lines:** 70, 140, 176-183
-- **Issue:** `_abortController` only set in `chatWithTools()` (line 195), not in `chat()` or `chatStream()`
-- **Impact:** `ai-stop` command only cancels tool-calling requests, not direct chat or streaming
-- **Fix:**
- ```javascript
- // Add to chat() method (around line 70)
- this._abortController = new AbortController();
- const signal = this._abortController.signal;
- const response = await fetch(`${this.endpoint}/api/generate`, {
- // ...
- signal
- });
- this._abortController = null;
-
- // Add to chatStream() method (around line 140) - same pattern
- ```
-
----
-
-## 3. AI Routing Issues
-
-### 3.1 Unknown Commands Not Awaited (executeCommand)
-- **File:** `terminal.js`
-- **Line:** 629
-- **Issue:** `aiMod.chat([rawInput.trim()])` called without `await`
-- **Impact:** Fire-and-forget execution, errors uncaught, no sequencing
-- **Fix:**
- ```javascript
- // Before
- aiMod.chat([rawInput.trim()]);
- return;
-
- // After
- this.print('→ Routing to AI assistant...', 'info');
- await aiMod.chat([rawInput.trim()]);
- return;
- ```
-
----
-
-### 3.2 Unknown Commands Not Awaited (dispatchCommand)
-- **File:** `terminal.js`
-- **Line:** 691
-- **Issue:** Same as 3.1 but in `dispatchCommand()` (used for pipe chains)
-- **Fix:** Same as 3.1
-
-**Combined Impact:** Unknown commands like `hello` route to AI but without proper error handling or user feedback
-
----
-
-## 4. Cache Invalidation
-
-### 4.1 Cache Version Stale
-- **File:** `module-loader.js`
-- **Line:** 102
-- **Issue:** `CACHE = '?v=17'` serves old cached modules
-- **Impact:** Browser doesn't re-fetch updated module files
-- **Fix:**
- ```javascript
- // Before
- const CACHE = '?v=17';
-
- // After
- const CACHE = '?v=18';
- ```
-- **Note:** Requires users to hard refresh (Ctrl+F5 / Cmd+Shift+R)
-
----
-
-## Implementation Priority
-
-### High Priority (Critical Bugs)
-1. **2.1** Agent loop caps at 1 turn — breaks multi-step AI tasks
-2. **1.4** Packages.json 404 errors — WPM installs broken
-3. **2.4** Default model blocks auto-selection — invisible failures
-4. **2.5** abort() incomplete — `ai-stop` doesn't work for chat/stream
-
-### Medium Priority (Functional Issues)
-5. **1.1** Splash fallback incomplete — minor UX issue
-6. **2.2** edit_module destructive check — security inconsistency
-7. **3.1 + 3.2** AI routing without await — error handling gaps
-8. **1.2** Preview iframe sandbox — JS previews broken
-
-### Low Priority (Cleanup)
-9. **1.3** Dead EXT_FILES code — maintenance clarity
-10. **1.5** Search alert() → inline — UX polish
-11. **4.1** Cache version — required after applying fixes
-
----
-
-## Tradeoffs & Considerations
-
-### Packages.json Cleanup (1.4)
-- **Option A (Recommended):** Remove 12 phantom packages
- - ✅ Reduces bloat, cleaner codebase
- - ❌ Breaks backward compatibility if anyone installed them
-- **Option B:** Create stub files for missing packages
- - ✅ Preserves compatibility
- - ❌ Adds dead weight, maintenance burden
-
-### Agent Loop Change (2.1)
-- Removing follow-up call changes message structure slightly
-- Text+tool hybrid responses now push text as `assistant` message, then loop continues
-- This is correct behavior but differs from original design
-
-### AI Routing (3.1 + 3.2)
-- Routing all unknown commands to AI may increase token usage
-- Consider adding `ai-mode` toggle or `--no-ai` flag for opt-out
-
-### Cache Version (4.1)
-- Bumping version requires all users to hard refresh
-- Consider adding release notes or announcement
-
----
-
-## Testing Checklist
-
-After applying fixes:
-
-- [ ] Hard refresh page (Ctrl+F5)
-- [ ] Test splash screen shows all 8 ext modules
-- [ ] Test HTML preview with JavaScript executes
-- [ ] Test WPM package installs succeed
-- [ ] Test search shows inline message (no alert)
-- [ ] Test multi-step AI task (5 tool turns)
-- [ ] Test `edit_module` prompts for confirmation
-- [ ] Test auto-select model on connect
-- [ ] Test `ai-stop` cancels chat/stream
-- [ ] Test unknown command routes to AI (`hello`)
-
----
-
-## Files to Modify
-
-```
-spaces/chatstudio/newos4/
-├── index.html (lines 684, 770)
-├── help.html (line 1149)
-├── packages.json (lines 7-167)
-└── modules/core/
- ├── module-loader.js (lines 35-37, 102)
- ├── module-aiassist.js (lines 537-547, 730)
- ├── ollama-manager.js (lines 8, 42-45, 70, 140)
- └── terminal.js (lines 629, 691)
-```
-
----
-
-## Estimated Effort
-
-| Category | Time | Complexity |
-|----------|------|------------|
-| File fixes | 15 min | Low |
-| Agent fixes | 30 min | Medium |
-| AI routing | 10 min | Low |
-| Testing | 20 min | Medium |
-| **Total** | **~75 min** | |
-
----
-
-## Approval Required
-
-**Ready to execute?** Reply with:
-- ✅ "Execute all" — apply all 13 fixes
-- ✅ "Execute high priority" — apply top 4 fixes only
-- ✅ "Skip #X" — exclude specific fixes
-- ❓ "Discuss #X" — more details on specific issue
diff --git a/chat/chat-modules.js b/chat/chat-modules.js
index 8483d48..26ad115 100644
--- a/chat/chat-modules.js
+++ b/chat/chat-modules.js
@@ -296,7 +296,15 @@ async function generateModuleWithAI() {
if (!response.ok) throw new Error('AI request failed');
var data = await response.json();
- var result = JSON.parse(data.response);
+ var result;
+ try {
+ result = JSON.parse(data.response);
+ } catch (e) {
+ showToast('AI response was not valid JSON. Try a different model.');
+ btn.disabled = false;
+ btn.textContent = 'Generate with AI';
+ return;
+ }
document.getElementById('moduleName').value = result.name || '';
document.getElementById('moduleDesc').value = result.desc || '';
@@ -361,5 +369,7 @@ function importModules() {
// Load modules from storage (runs after core.js)
-// Auto-init once DOM + deps are ready
-document.addEventListener('DOMContentLoaded', function() { loadModules(); });
+// Auto-init — DOM is already ready when this script loads dynamically
+if (document.getElementById('chat-overlay')) {
+ loadModules();
+}
diff --git a/chat/chat-ui.html b/chat/chat-ui.html
index 5eedce6..9f6dd4b 100644
--- a/chat/chat-ui.html
+++ b/chat/chat-ui.html
@@ -95,6 +95,11 @@
<label>Commands (comma-separated)</label>
<input type="text" id="moduleCommands" placeholder="e.g., /search, /find, /web">
</div>
+ <div class="form-group" style="margin-top:16px;padding-top:16px;border-top:1px solid var(--border);">
+ <label>Generate with AI</label>
+ <textarea id="aiModuleDesc" placeholder="Describe the module you want... e.g. A code review assistant that checks for security issues" style="min-height:60px;"></textarea>
+ <button class="btn btn-secondary" style="width:100%;margin-top:8px;" onclick="generateModuleWithAI(event)">🤖 Generate with AI</button>
+ </div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeModuleModal()">Cancel</button>
diff --git a/cheatsheet.html b/cheatsheet.html
index 4cb4a1f..6245807 100644
--- a/cheatsheet.html
+++ b/cheatsheet.html
@@ -34,7 +34,7 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
<body>
<h1>⚡ newOS4 Quick Reference</h1>
-<div class="sub">WebX11 v4.2 · <a href="help.html">Full docs →</a> · <span class="no-print">Ctrl+P to print</span></div>
+<div class="sub">WebX11 v4.3 · <a href="help.html">Full docs →</a> · <span class="no-print">Ctrl+P to print</span></div>
<div class="cols">
@@ -104,13 +104,25 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
<div class="item"><span class="cmd">cron-list / cron-stop</span><span class="desc">Manage jobs</span></div>
<div class="item"><span class="cmd">wpm</span><span class="desc">Package manager</span></div>
<div class="item"><span class="cmd">mindmap</span><span class="desc">Brainstorming tool</span></div>
-<div class="item"><span class="cmd">webdav-status</span><span class="desc">Cloud sync status</span></div>
-<div class="item"><span class="cmd">webdav-push / pull</span><span class="desc">Sync files</span></div>
-<div class="item"><span class="cmd">theme &lt;name&gt;</span><span class="desc">Change theme</span></div>
-<div class="item"><span class="cmd">voice</span><span class="desc">Speech-to-text</span></div>
-<div class="item"><span class="cmd">chat</span><span class="desc">Chat overlay</span></div>
-<div class="item"><span class="cmd">gzip / gunzip</span><span class="desc">Compress files</span></div>
-<div class="item"><span class="cmd">encrypt / decrypt</span><span class="desc">AES-256 encrypt</span></div>
+ <div class="item"><span class="cmd">webdav-status</span><span class="desc">Cloud sync status</span></div>
+ <div class="item"><span class="cmd">webdav-push / pull</span><span class="desc">Sync files</span></div>
+ <div class="item"><span class="cmd">webdav-browser</span><span class="desc">File-tree UI browser</span></div>
+ <div class="item"><span class="cmd">webdav-rm / mkdir</span><span class="desc">Delete / create dir</span></div>
+ <div class="item"><span class="cmd">webdav-rename / move</span><span class="desc">Rename / move files</span></div>
+ <div class="item"><span class="cmd">webdav-backup</span><span class="desc">Backup space</span></div>
+ <div class="item"><span class="cmd">theme &lt;name&gt;</span><span class="desc">Change theme</span></div>
+ <div class="item"><span class="cmd">voice</span><span class="desc">Speech-to-text</span></div>
+ <div class="item"><span class="cmd">chat</span><span class="desc">Chat overlay</span></div>
+ <div class="item"><span class="cmd">gzip / gunzip</span><span class="desc">Compress files</span></div>
+ <div class="item"><span class="cmd">encrypt / decrypt</span><span class="desc">AES-256 encrypt</span></div>
+ <div class="item"><span class="cmd">debug</span><span class="desc">Toggle debug panel</span></div>
+ <div class="item"><span class="cmd">agent-list</span><span class="desc">List registered agents</span></div>
+ <div class="item"><span class="cmd">lease-list</span><span class="desc">Show active leases</span></div>
+ <div class="item"><span class="cmd">orchestrate</span><span class="desc">Multi-step task agent</span></div>
+ <div class="item"><span class="cmd">security-level &lt;0-3&gt;</span><span class="desc">Set security level</span></div>
+ <div class="item"><span class="cmd">cmd-allow / cmd-deny</span><span class="desc">Per-command access</span></div>
+ <div class="item"><span class="cmd">checkpoint</span><span class="desc">Snapshot VFS state</span></div>
+ <div class="item"><span class="cmd">health-check</span><span class="desc">System health check</span></div>
</div>
<h2>🐚 Shell</h2>
@@ -137,13 +149,14 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
<div class="item"><span class="cmd">config</span><span class="desc">Config manager UI</span></div>
</div>
-<h2>🔒 Security</h2>
+<h2>🔒 Security / Vault</h2>
<div class="grid">
-<div class="item"><span class="cmd">security</span><span class="desc">Show current level</span></div>
-<div class="item"><span class="cmd">security-level 0-3</span><span class="desc">Set level</span></div>
-</div>
-<div style="margin-top:8px">
-<p style="font-size:.78em;color:var(--text2)">Level 0 = permissive · 1 = standard (default) · 2 = paranoid · 3 = audit</p>
+<div class="item"><span class="cmd">secret-set</span><span class="desc">Encrypt a secret</span></div>
+<div class="item"><span class="cmd">secret-get</span><span class="desc">Decrypt a secret</span></div>
+<div class="item"><span class="cmd">secret-list</span><span class="desc">List secrets</span></div>
+<div class="item"><span class="cmd">secret-del</span><span class="desc">Delete a secret</span></div>
+<div class="item"><span class="cmd">secret-lock</span><span class="desc">Lock vault</span></div>
+<div class="item"><span class="cmd">secret-unlock</span><span class="desc">Unlock vault</span></div>
</div>
<h2>⌨️ Shortcuts</h2>
@@ -159,7 +172,7 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
</div>
<div class="footer">
- WebX11 v4.2 · <a href="help.html">help.html</a> · newOS4 on <a href="main.html">Launch →</a>
+ WebX11 v4.3 · <a href="help.html">help.html</a> · newOS4 on <a href="main.html">Launch →</a>
</div>
</body>
diff --git a/help.html b/help.html
index 484c20d..1c02628 100644
--- a/help.html
+++ b/help.html
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#0a0a14">
-<title>WebX11 v4.2 — Help</title>
+<title>WebX11 v4.3 — Help</title>
<style>
/* ── Reset & Base ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
@@ -231,9 +231,9 @@ footer .tagline{color:var(--accent2);margin-top:10px;font-weight:500}
<h1>WebX11 <span>Docs</span></h1>
</div>
<div class="header-meta">
- <span class="badge badge-v">v4.2</span>
- <span class="badge badge-new">26 core · 15 ext</span>
- <span style="color:var(--text2)">135+ commands</span>
+ <span class="badge badge-v">v4.3</span>
+ <span class="badge badge-new">18 core · 14 ext</span>
+ <span style="color:var(--text2)">145+ commands</span>
</div>
</div>
</header>
@@ -250,6 +250,7 @@ footer .tagline{color:var(--accent2);margin-top:10px;font-weight:500}
<a href="#web" class="nav-link">Search & Web</a>
<a href="#voice" class="nav-link">Voice & Sound</a>
<a href="#config" class="nav-link">Config</a>
+ <a href="#vault" class="nav-link">Vault</a>
<a href="#modules" class="nav-link">Modules</a>
<a href="#extras" class="nav-link">Extras</a>
<a href="#busybox" class="nav-link">BusyBox</a>
@@ -414,9 +415,9 @@ webx11.inputField // DOM input element</code></pre>
<!-- ── Overview ── -->
<section id="overview">
<h2>⛅ Overview</h2>
- <p>WebX11 v4.2 is a browser-based Unix-like terminal — dynamic modules, AI assistant (Ollama), persistent virtual filesystem, web search, voice input, code editor, and a full skill system. Everything runs client-side in your browser.</p>
+ <p>WebX11 v4.3 is a browser-based Unix-like terminal — dynamic modules, AI assistant (Ollama), persistent virtual filesystem, web search, voice input, code editor, and a full skill system. Everything runs client-side in your browser.</p>
<div class="feature-grid">
- <div class="feature-card"><h4>🧩 26 Core + 14 Ext</h4><p>Modules loaded at startup. Shell with pipes, redirects, vars, and scripts.</p></div>
+ <div class="feature-card"><h4>🧩 18 Core + 14 Ext</h4><p>Modules loaded at startup. Shell with pipes, redirects, vars, and scripts.</p></div>
<div class="feature-card"><h4>🤖 Agent with Tools</h4><p>28 tools — file ops, web search, skills, modules. Destructive action confirmations with inline bar + countdown.</p></div>
<div class="feature-card"><h4>📚 Skills System</h4><p>Persistent procedural memory. Create, patch, search, export skills for repeatable workflows.</p></div>
<div class="feature-card"><h4>💾 VFS + Sessions</h4><p>Virtual filesystem persists in localStorage. Save/load/export sessions.</p></div>
@@ -497,6 +498,17 @@ diff a.txt b.txt</pre>
<tr><td><code>preview</code></td><td>Preview HTML in iframe</td><td><code>preview test.html</code></td></tr>
<tr><td><code>factory-reset</code></td><td>Reset config</td><td><code>factory-reset</code></td></tr>
<tr><td><code>reset-vfs</code></td><td>Reset VFS</td><td><code>reset-vfs</code></td></tr>
+ <tr><td><code>logrotate</code></td><td>Rotate current.log to dated archive</td><td><code>logrotate</code></td></tr>
+ <tr><td><code>health-check</code></td><td>Audit VFS, modules, logs, trash, skills</td><td><code>health-check</code></td></tr>
+ <tr><td><code>memory-map-export</code></td><td>Generate memory map from /memory/index.json</td><td><code>memory-map-export</code></td></tr>
+ <tr><td><code>commands</code></td><td>List commands with module source</td><td><code>commands</code></td></tr>
+ <tr><td><code>check</code></td><td>System health + module requirements</td><td><code>check</code></td></tr>
+ <tr><td><code>checkpoint</code></td><td>Create VFS snapshot</td><td><code>checkpoint</code></td></tr>
+ <tr><td><code>checkpoint-list</code></td><td>List VFS checkpoints</td><td><code>checkpoint-list</code></td></tr>
+ <tr><td><code>rollback</code></td><td>Restore VFS from checkpoint</td><td><code>rollback</code></td></tr>
+ <tr><td><code>checkpoint-del</code></td><td>Delete a checkpoint</td><td><code>checkpoint-del</code></td></tr>
+ <tr><td><code>smart-prompt</code></td><td>Toggle context-aware prompt</td><td><code>smart-prompt</code></td></tr>
+ <tr><td><code>test</code></td><td>Run test suite</td><td><code>test auto</code></td></tr>
</table></div>
<h3>AI Assistant</h3>
@@ -509,6 +521,8 @@ diff a.txt b.txt</pre>
<tr><td><code>ai-allow</code></td><td>Allow pending destructive action</td><td><code>ai-allow</code></td></tr>
<tr><td><code>ai-deny</code></td><td>Deny pending destructive action</td><td><code>ai-deny</code></td></tr>
<tr><td><code>ai-stop</code></td><td>Cancel running AI request</td><td><code>ai-stop</code></td></tr>
+ <tr><td><code>ai-compress</code></td><td>Manually compress conversation context</td><td><code>ai-compress</code></td></tr>
+ <tr><td><code>debug</code></td><td>Toggle AI debug mode</td><td><code>debug</code></td></tr>
</table></div>
<h3>Smart Context</h3>
@@ -572,6 +586,10 @@ diff a.txt b.txt</pre>
<tr><td><code>rm</code></td><td>Delete file</td><td><code>rm temp.txt</code></td></tr>
<tr><td><code>mkdir</code></td><td>Create directory</td><td><code>mkdir projects</code></td></tr>
<tr><td><code>rmdir</code></td><td>Remove directory</td><td><code>rmdir empty</code></td></tr>
+ <tr><td><code>trash</code></td><td>Move file to trash</td><td><code>trash temp.txt</code></td></tr>
+ <tr><td><code>trash-dir</code></td><td>Move directory to trash</td><td><code>trash-dir olddir</code></td></tr>
+ <tr><td><code>ls-trash</code></td><td>List items in trash</td><td><code>ls-trash</code></td></tr>
+ <tr><td><code>empty-trash</code></td><td>Permanently delete all trash items</td><td><code>empty-trash</code></td></tr>
<tr><td><code>mv</code></td><td>Move/rename</td><td><code>mv old.txt new.txt</code></td></tr>
<tr><td><code>cp</code></td><td>Copy file</td><td><code>cp a.txt b.txt</code></td></tr>
<tr><td><code>touch</code></td><td>Create empty file</td><td><code>touch newfile.txt</code></td></tr>
@@ -588,6 +606,12 @@ diff a.txt b.txt</pre>
<tr><td><code>download</code></td><td>Download file</td><td><code>download file.txt</code></td></tr>
<tr><td><code>vfs-export</code></td><td>Download VFS as JSON</td><td><code>vfs-export</code></td></tr>
<tr><td><code>vfs-import</code></td><td>Import VFS from JSON</td><td><code>vfs-import</code></td></tr>
+ <tr><td><code>session-save</code></td><td>Save a session snapshot</td><td><code>session-save</code></td></tr>
+ <tr><td><code>session-load</code></td><td>Load a session snapshot</td><td><code>session-load mysession</code></td></tr>
+ <tr><td><code>session-list</code></td><td>List all saved sessions</td><td><code>session-list</code></td></tr>
+ <tr><td><code>session-delete</code></td><td>Delete a session</td><td><code>session-delete old</code></td></tr>
+ <tr><td><code>session-export</code></td><td>Export session as JSON download</td><td><code>session-export mysession</code></td></tr>
+ <tr><td><code>session-import</code></td><td>Import a session from file</td><td><code>session-import</code></td></tr>
</table></div>
</section>
@@ -782,11 +806,31 @@ ollamaconnect</pre>
</table></div>
</section>
+ <!-- ── Secret Vault ── -->
+ <section id="vault">
+ <h2>🔒 Secret Vault</h2>
+ <div class="callout callout-success">
+ <span class="callout-title">Encrypted Secrets Manager</span>
+ AES-256-GCM encrypted key-value storage in localStorage. Lock/unlock with a PIN — secrets are never stored in plain text. Vault status persists across sessions.
+ </div>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>secret-set</code></td><td>Encrypt and store a secret</td></tr>
+ <tr><td><code>secret-get</code></td><td>Decrypt and display a secret value</td></tr>
+ <tr><td><code>secret-list</code></td><td>List all stored secret names</td></tr>
+ <tr><td><code>secret-del</code></td><td>Remove a stored secret</td></tr>
+ <tr><td><code>secret-lock</code></td><td>Lock the vault (clears key from memory)</td></tr>
+ <tr><td><code>secret-unlock</code></td><td>Unlock the vault with PIN</td></tr>
+ <tr><td><code>secret-setpin</code></td><td>Set or change vault PIN</td></tr>
+ <tr><td><code>secret-status</code></td><td>Show vault status (locked/unlocked/pin set)</td></tr>
+ </table></div>
+ </section>
+
<!-- ── Modules ── -->
<section id="modules">
<h2>🧩 Module System</h2>
<div class="callout callout-info">
- <span class="callout-title">26 Core + 14 Ext</span>
+ <span class="callout-title">25 Core + 17 Ext</span>
Modules loaded in dependency order at startup. Toggle ext modules with ⚙ gear on splash.
</div>
<h3>Commands</h3>
@@ -796,6 +840,9 @@ ollamaconnect</pre>
<tr><td><code>loadmod &lt;url&gt;</code></td><td>Load module from URL</td></tr>
<tr><td><code>removemod &lt;name&gt;</code></td><td>Remove a module</td></tr>
<tr><td><code>listmods</code></td><td>List all loaded modules</td></tr>
+ <tr><td><code>load-local</code></td><td>Load module from VFS or URL</td></tr>
+ <tr><td><code>loadlocal</code></td><td>Alias for load-local</td></tr>
+ <tr><td><code>startup-modules</code></td><td>Configure boot modules</td></tr>
</table></div>
<h3>Boot Order</h3>
@@ -826,8 +873,8 @@ ollamaconnect</pre>
<tr><td><code>webdav-backup</code></td><td>Backup VFS</td></tr>
<tr><td><code>webdav-restore</code></td><td>Restore VFS</td></tr>
<tr><td><code>webdav-backup-list</code></td><td>List backups</td></tr>
- <tr><td><code>webdav-browser</code></td><td>Visual file explorer modal</td></tr>
<tr><td><code>webdav-explorer</code></td><td>Interactive text browser</td></tr>
+ <tr><td><code>webdav-browser</code></td><td>Visual file explorer modal</td></tr>
</table></div>
<h3>Calculator & Cron</h3>
@@ -1004,6 +1051,67 @@ vfs-import</pre>
<p>~5–10MB per domain. Only URLs (not code) are stored for modules.</p>
</section>
+ <!-- ── WebDAV ── -->
+ <section id="webdav">
+ <h2>☁️ WebDAV</h2>
+ <p>Cloud sync with your WebX11 space. File-tree browser UI with bulk actions.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>webdav-config &lt;url&gt; &lt;token&gt;</code></td><td>Configure WebDAV connection</td></tr>
+ <tr><td><code>webdav-status</code></td><td>Show sync status and connection health</td></tr>
+ <tr><td><code>webdav-ls [path]</code></td><td>List remote files</td></tr>
+ <tr><td><code>webdav-push &lt;local&gt; [remote]</code></td><td>Upload file to cloud</td></tr>
+ <tr><td><code>webdav-pull &lt;remote&gt; [local]</code></td><td>Download file from cloud</td></tr>
+ <tr><td><code>webdav-browser</code></td><td>Open file-tree browser UI with checkboxes, context menu, inline rename</td></tr>
+ <tr><td><code>webdav-rm &lt;path&gt;</code></td><td>Delete remote file/directory</td></tr>
+ <tr><td><code>webdav-mkdir &lt;path&gt;</code></td><td>Create remote directory</td></tr>
+ <tr><td><code>webdav-rename &lt;old&gt; &lt;new&gt;</code></td><td>Rename remote file</td></tr>
+ <tr><td><code>webdav-move &lt;src&gt; &lt;dst&gt;</code></td><td>Move remote file (alias for rename)</td></tr>
+ <tr><td><code>webdav-backup</code></td><td>Backup entire space</td></tr>
+ </table></div>
+ <h3>Browser Features</h3>
+ <ul>
+ <li>Checkbox select + Select All toggle</li>
+ <li>Bulk action bar: Delete, Move, Download selected files</li>
+ <li>Inline rename: double-click filename</li>
+ <li>Right-click context menu with all operations</li>
+ <li>Breadcrumb navigation</li>
+ <li>Create-directory button</li>
+ <li>Keyboard shortcuts: <code>j</code>/<code>k</code> navigate, <code>Space</code> select, <code>Enter</code> open</li>
+ </ul>
+ </section>
+
+ <!-- ── Agents ── -->
+ <section id="agents">
+ <h2>🤖 Agent Orchestration</h2>
+ <p>Register, list, and delegate tasks to AI agents with lease-based lifecycle management.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>agent-list</code></td><td>List all registered agents with status</td></tr>
+ <tr><td><code>agent-register &lt;name&gt; &lt;model&gt;</code></td><td>Register a new AI agent</td></tr>
+ <tr><td><code>lease-list</code></td><td>Show active leases — agent tasks with status and TTL</td></tr>
+ <tr><td><code>orchestrate &lt;task&gt;</code></td><td>Delegate multi-step task to agent orchestrator</td></tr>
+ </table></div>
+ </section>
+
+ <!-- ── Debug ── -->
+ <section id="debug-panel">
+ <h2>🔧 Debug Panel</h2>
+ <p>Toggle the debug overlay to monitor system internals in real-time.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>debug</code></td><td>Toggle debug panel on/off</td></tr>
+ </table></div>
+ <h3>Debug Panel Shows</h3>
+ <ul>
+ <li><strong>Memory</strong> — localStorage usage, VFS size, session context size</li>
+ <li><strong>Events</strong> — registered event listeners, module event bindings</li>
+ <li><strong>Errors</strong> — recent JS errors with stack traces</li>
+ <li><strong>Modules</strong> — loaded count, broken references, cache state</li>
+ </ul>
+ <p>Useful for troubleshooting module load failures, VFS corruption, and AI context bloat.</p>
+ </section>
+
<!-- ── Security ── -->
<section id="security">
<h2>🔒 Security</h2>
@@ -1014,9 +1122,23 @@ vfs-import</pre>
<tr><td>No eval() on User Input</td><td>✅</td></tr>
<tr><td>Path Traversal Prevention</td><td>✅</td></tr>
<tr><td>Sandboxed File System</td><td>✅</td></tr>
- <tr><td>AI Destructive Confirmations</td><td>✅ Required + timeout</td></tr>
+ <tr><td>AI Destructive Confirmations</td><td>✅ Required + 120s countdown</td></tr>
<tr><td>Iframe Preview Sandbox</td><td>✅ allow-same-origin allow-scripts</td></tr>
</table></div>
+ <h3>Security Levels</h3>
+ <div class="table-wrap"><table>
+ <tr><th>Level</th><th>Behavior</th></tr>
+ <tr><td><code>0</code></td><td>Unrestricted — all commands allowed without confirmation</td></tr>
+ <tr><td><code>1</code> (default)</td><td>Confirm destructive actions (rm, overwrite, etc.)</td></tr>
+ <tr><td><code>2</code></td><td>Deny sensitive commands (rm -rf, encrypt operations)</td></tr>
+ <tr><td><code>3</code></td><td>Deny all dangerous commands (requires deliberate override)</td></tr>
+ </table></div>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>security-level &lt;0-3&gt;</code></td><td>Set active security level</td></tr>
+ <tr><td><code>cmd-allow &lt;command&gt;</code></td><td>Add command to allowlist (bypasses restrictions)</td></tr>
+ <tr><td><code>cmd-deny &lt;command&gt;</code></td><td>Add command to denylist (always blocked)</td></tr>
+ </table></div>
<div class="callout callout-warning">
<span class="callout-title">⚠️ Module Loading</span>
Only load modules from trusted sources — they have full terminal access.
@@ -1052,7 +1174,7 @@ listmods</pre>
<section id="ref">
<h2>⚡ Quick Reference</h2>
<div class="quick-ref">
- <div class="quick-ref-title">WebX11 v4.2</div>
+ <div class="quick-ref-title">WebX11 v4.3</div>
<div class="quick-ref-grid">
<div class="quick-ref-item"><span class="cmd">help</span><span class="desc">Show all commands</span></div>
<div class="quick-ref-item"><span class="cmd">cls</span><span class="desc">Clear terminal</span></div>
@@ -1096,6 +1218,21 @@ listmods</pre>
<h2>📋 Changelog</h2>
<div class="version-item">
+ <div class="v-header"><span class="v-num">v4.3 — June 2026</span><span class="v-date">2026-06-02</span></div>
+ <ul>
+ <li><strong>WebDAV Browser</strong> — Modern file-tree UI with checkboxes, Select All, bulk actions (Delete, Move, Download), inline rename (double-click), context menu, breadcrumbs, keyboard shortcuts</li>
+ <li><strong>WebDAV commands</strong> — <code>webdav-browser</code>, <code>webdav-rm</code>, <code>webdav-mkdir</code>, <code>webdav-rename</code>, <code>webdav-move</code>, <code>webdav-backup</code></li>
+ <li><strong>Skill Pack System</strong> — Auto-loads 12 skills on startup, seed/reload support, skill-pack-core.js manages in-memory index</li>
+ <li><strong>Agent Orchestration</strong> — <code>agent-list</code>, <code>agent-register</code>, <code>lease-list</code>, <code>orchestrate</code> for multi-step delegation</li>
+ <li><strong>Security Layer</strong> — <code>security-level 0-3</code> with granular restrictions, <code>cmd-allow</code>/<code>cmd-deny</code> per-command access control</li>
+ <li><strong>Debug Panel</strong> — <code>debug</code> toggle shows memory, events, errors, module health</li>
+ <li><strong>Chat Cleanup</strong> — Removed <code>chat-setapi</code>, <code>chat-setmodel</code>, <code>chat-ask</code>; single <code>chat</code> command toggles overlay</li>
+ <li>Module count refactored: 18 core + 14 ext (was 25+17)</li>
+ <li>Cache: <code>skillpack1</code>/<code>chatfix1</code>/<code>webdav2</code> — hard refresh required</li>
+ </ul>
+ </div>
+
+ <div class="version-item">
<div class="v-header"><span class="v-num">v4.2.1 — May 2026</span><span class="v-date">2026-05-27</span></div>
<ul>
<li><strong>BusyBox</strong> — 16 new utility commands: <code>which</code>, <code>env</code>, <code>date</code>, <code>cal</code>, <code>yes</code>, <code>seq</code>, <code>base64</code>, <code>printf</code>, <code>cut</code>, <code>uniq</code>, <code>hostname</code>, <code>whoami</code>, <code>basename</code>, <code>dirname</code>, <code>sleep</code>, <code>expand</code></li>
@@ -1165,7 +1302,7 @@ listmods</pre>
<a href="./main.html">Launch WebX11</a>
<a href="https://ollama.com" target="_blank">Ollama</a>
</div>
- <p>WebX11 v4.2 · 2026</p>
+ <p>WebX11 v4.3 · 2026</p>
<p class="tagline">Happy Hacking 🖥️🤖🎤</p>
</footer>
@@ -1250,7 +1387,7 @@ document.querySelectorAll('.doc-tabs input').forEach(radio=>{
}
})();
-console.log('WebX11 v4.2 Docs — Modern');
+console.log('WebX11 v4.3 Docs — Modern');
</script>
</body>
</html>
diff --git a/modules/core/module-agent-registry.js b/modules/core/module-agent-registry.js
new file mode 100644
index 0000000..367f8b1
--- /dev/null
+++ b/modules/core/module-agent-registry.js
@@ -0,0 +1,79 @@
+// module-agent-registry.js — VFS-backed agent directory
+// Command: agent-list, agent-register, agent-unregister, agent-status
+class AgentRegistryModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ }
+ registerCommands() {
+ this.commands['agent-list'] = () => this.listAgents();
+ this.commands['agent-status'] = (args) => this.showAgentStatus(args[0]);
+ this.commands['agent-register'] = (args) => this.registerAgent(args);
+ this.commands['agent-unregister'] = (args) => this.unregisterAgent(args[0]);
+ }
+ init(terminal) {
+ this.terminal = terminal;
+ if (!this.terminal.fs.readFile('/agents/')) {
+ this.terminal.fs.mkdir('agents');
+ }
+ this.terminal.print('📋 Agent Registry loaded', 'info');
+ }
+ listAgents() {
+ const agents = this.terminal.fs.ls('/agents/');
+ if (!agents || agents.length === 0) {
+ return this.terminal.print('No agents registered', 'info');
+ }
+ this.terminal.print(`📋 Registered Agents (${agents.length}):`, 'header');
+ agents.forEach(a => {
+ if (a.type === 'dir' && a.name !== 'configured') {
+ const data = this.terminal.fs.readFile(`/agents/${a.name}/status.json`);
+ const s = data ? JSON.parse(data) : { status: 'unknown', capabilities: [] };
+ this.terminal.print(` ${a.name} — ${s.status} (${(s.capabilities || []).length} capabilities)`, 'info');
+ }
+ });
+ }
+ registerAgent(args) {
+ const id = args[1] || `agent-${Date.now()}`;
+ const capabilities = args.slice(2).length ? args.slice(2) : ['list_files', 'read_file'];
+ const agentDir = `agents/${id}`;
+ if (!this.terminal.fs.readFile('/' + agentDir + '/')) this.terminal.fs.mkdir(agentDir);
+ this.terminal.fs.writeFile(`${agentDir}/status.json`, JSON.stringify({
+ id,
+ status: 'idle',
+ capabilities,
+ registered: new Date().toISOString(),
+ lastHeartbeat: new Date().toISOString()
+ }));
+ this.terminal.print(`✅ Agent '${id}' registered with ${capabilities.length} capabilities`, 'success');
+ }
+ unregisterAgent(id) {
+ const ok = this.terminal.fs.deleteFile(`agents/${id}`);
+ if (ok) {
+ this.terminal.print(`✅ Agent '${id}' unregistered`, 'success');
+ } else {
+ this.terminal.print(`❌ Agent '${id}' not found`, 'error');
+ }
+ }
+ showAgentStatus(id) {
+ if (!id) return this.terminal.print('Usage: agent-status <agent-id>', 'error');
+ const data = this.terminal.fs.readFile(`/agents/${id}/status.json`);
+ if (!data) return this.terminal.print(`❌ Agent '${id}' not found`, 'error');
+ const s = JSON.parse(data);
+ this.terminal.print(`Agent: ${s.id}`, 'header');
+ this.terminal.print(` Status: ${s.status}`, 'info');
+ this.terminal.print(` Capabilities: ${(s.capabilities || []).join(', ')}`, 'info');
+ this.terminal.print(` Registered: ${s.registered}`, 'info');
+ this.terminal.print(` Last Heartbeat: ${s.lastHeartbeat}`, 'info');
+ }
+ getAgent(id) {
+ const data = this.terminal.fs.readFile(`/agents/${id}/status.json`);
+ return data ? JSON.parse(data) : null;
+ }
+ updateHeartbeat(id) {
+ const agent = this.getAgent(id);
+ if (!agent) return false;
+ agent.lastHeartbeat = new Date().toISOString();
+ this.terminal.fs.writeFile(`agents/${id}/status.json`, JSON.stringify(agent));
+ return true;
+ }
+} \ No newline at end of file
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index edc5225..eb41af9 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -384,6 +384,40 @@ RULES:
description: 'Session aggregate stats',
parameters: { type: 'object', properties: {}, required: [] }
}
+ }, {
+ type: 'function',
+ function: {
+ name: 'list_agents',
+ description: 'List registered agent IDs, status, and capabilities',
+ parameters: { type: 'object', properties: {}, required: [] }
+ }
+ }, {
+ type: 'function',
+ function: {
+ name: 'delegate_task',
+ description: '(DESTRUCTIVE) Delegate a task to a worker agent. Auto-spawns if needed.',
+ parameters: {
+ type: 'object',
+ properties: {
+ task: { type: 'string', description: 'The task description to delegate' }
+ },
+ required: ['task']
+ }
+ }
+ }, {
+ type: 'function',
+ function: {
+ name: 'spawn_agent',
+ description: '(DESTRUCTIVE) Spawn a new worker agent with a role and capabilities',
+ parameters: {
+ type: 'object',
+ properties: {
+ role: { type: 'string', description: 'Agent role (e.g. researcher, writer)' },
+ capabilities: { type: 'string', description: 'Comma-separated capabilities (optional)' }
+ },
+ required: ['role']
+ }
+ }
}];
}
getHelpInfo() {
@@ -568,7 +602,14 @@ RULES:
(entry.error ? ' <span class="debug-err">⚠️</span>' : '') +
'</div>';
}
- panel.innerHTML = '<div class="debug-header" style="display:flex;justify-content:space-between;align-items:center;padding:6px 10px;border-bottom:1px solid #333;font-weight:bold;color:var(--success-color);font-size:0.9em;">🔧 Tool Log <span class="debug-count" style="color:var(--text-muted);font-weight:normal;font-size:0.85em;">' + this._toolCallLog.length + ' calls</span><span style="cursor:pointer;color:var(--text-muted);font-size:1.1em;touch-action:manipulation;" onclick="var p=document.getElementById(\'debug-panel\');if(p)p.style.display=\'none\';var a=window.webx11&&webx11.moduleManager&&webx11.moduleManager.modules&&webx11.moduleManager.modules.WebX11AIAssistantModule;if(a)a._debugPanelEnabled=false;">✕</span></div>' + html;
+ panel.innerHTML = '<div class="debug-header" style="display:flex;justify-content:space-between;align-items:center;padding:6px 10px;border-bottom:1px solid #333;font-weight:bold;color:var(--success-color);font-size:0.9em;flex-wrap:wrap;gap:4px;">' +
+ '<span>🔧 Tool Log <span class="debug-count" style="color:var(--text-muted);font-weight:normal;font-size:0.85em;">' + this._toolCallLog.length + ' calls</span></span>' +
+ '<span style="display:flex;gap:4px;">' +
+ '<button onclick="var m=webx11.moduleManager.modules.WebX11AIAssistantModule;if(m){var t=m._toolCallLog.map(function(e){return\'#\'+e.turn+\' \'+e.name+\' (\'+e.duration+\'s)\'+(e.error?\' ⚠️\':\'\')+\'\\n\'+JSON.stringify(e.args).substring(0,80)}).join(\'\\n\\n\');navigator.clipboard.writeText(t).then(function(){m.terminal&&m.terminal.print(\'📋 Debug log copied to clipboard\',\'success\')}).catch(function(){prompt(\'Copy debug log:\',t)})}" style="background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-color);padding:2px 6px;border-radius:3px;cursor:pointer;font-size:0.75em;min-height:24px;">📋</button>' +
+ '<button onclick="var m=webx11.moduleManager.modules.WebX11AIAssistantModule;if(m){var json=JSON.stringify(m._toolCallLog,null,2);var b=new Blob([json],{type:\'application/json\'});var u=URL.createObjectURL(b);var a=document.createElement(\'a\');a.href=u;a.download=\'debug-log-\'+new Date().toISOString().slice(0,19)+\'.json\';document.body.appendChild(a);a.click();setTimeout(function(){document.body.removeChild(a);URL.revokeObjectURL(u)},2000);m.terminal&&m.terminal.print(\'📥 Debug log exported\',\'success\')}" style="background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-color);padding:2px 6px;border-radius:3px;cursor:pointer;font-size:0.75em;min-height:24px;">📥</button>' +
+ '<button onclick="var m=webx11.moduleManager.modules.WebX11AIAssistantModule;if(m){var existing=[];var raw=m.terminal.fs.readFile(\'/debug.log\');if(raw){try{existing=JSON.parse(raw);}catch(e){}}var log=m._toolCallLog;var seen={};existing.forEach(function(e){seen[e.turn]=true;});log.forEach(function(e){if(!seen[e.turn]){existing.push(e);seen[e.turn]=true;}});var json=JSON.stringify(existing,null,2);m.terminal.fs.writeFile(\'/debug.log\',json);m.terminal.print(\'💾 Debug log appended — \'+existing.length+\' entries total\',\'success\')}" style="background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-color);padding:2px 6px;border-radius:3px;cursor:pointer;font-size:0.75em;min-height:24px;">💾</button>' +
+ '<span style="cursor:pointer;color:var(--text-muted);font-size:1.1em;touch-action:manipulation;" onclick="var p=document.getElementById(\'debug-panel\');if(p)p.style.display=\'none\';var a=window.webx11&&webx11.moduleManager&&webx11.moduleManager.modules&&webx11.moduleManager.modules.WebX11AIAssistantModule;if(a)a._debugPanelEnabled=false;">✕</span>' +
+ '</span></div>' + html;
}
_isToolError(result) {
if (!result || typeof result !== 'string') return null;
@@ -1194,6 +1235,37 @@ RULES:
for (const [, meta] of entries) totalTasks += meta.tasks || 0;
return JSON.stringify({ totalSessions: entries.length, totalTasks, dates: entries.map(([d]) => d) });
}
+ case 'list_agents': {
+ const registry = this.terminal.moduleManager.modules['AgentRegistryModule'];
+ if (!registry) return JSON.stringify({ error: 'Agent registry not available' });
+ const agents = this.terminal.fs.ls('/agents/');
+ const results = [];
+ if (agents) {
+ agents.forEach(a => {
+ if (a.type === 'dir' && a.name !== 'configured') {
+ const data = this.terminal.fs.readFile(`/agents/${a.name}/status.json`);
+ if (data) results.push(JSON.parse(data));
+ }
+ });
+ }
+ return JSON.stringify({ agents: results, count: results.length });
+ }
+ case 'delegate_task': {
+ const task = a.task || '';
+ if (!task) return JSON.stringify({ error: 'No task provided' });
+ const orch = this.terminal.moduleManager.modules['OrchestratorModule'];
+ if (!orch) return JSON.stringify({ error: 'Orchestrator not available' });
+ orch.delegateTask(task);
+ return JSON.stringify({ message: `Task delegated: ${task.substring(0, 80)}` });
+ }
+ case 'spawn_agent': {
+ const role = a.role || 'worker';
+ const caps = a.capabilities ? a.capabilities.split(',').map(s => s.trim()) : ['list_files', 'read_file'];
+ const orch = this.terminal.moduleManager.modules['OrchestratorModule'];
+ if (!orch) return JSON.stringify({ error: 'Orchestrator not available' });
+ const agent = orch.spawnAgent(role, caps);
+ return JSON.stringify({ message: `Agent spawned: ${agent.id}`, agent });
+ }
case 'load_skills': {
const query = (a && a.query || '').toLowerCase();
const fs = this.terminal.fs;
diff --git a/modules/core/module-chatstudio.js b/modules/core/module-chatstudio.js
index 762eae3..9643fff 100644
--- a/modules/core/module-chatstudio.js
+++ b/modules/core/module-chatstudio.js
@@ -17,32 +17,12 @@ class ChatStudioModule {
getHelpInfo() {
return {
- 'chat': 'Toggle the ChatStudio overlay',
- 'chat-setapi': 'Set the API base URL for ChatStudio',
- 'chat-setmodel': 'Set the default model for ChatStudio',
- 'chat-ask': 'Ask a question directly via ChatStudio'
+ 'chat': 'Toggle the ChatStudio overlay (inside: /setapi, /setmodel, /ask, /help)',
};
}
registerCommands() {
this.commands['chat'] = () => this.toggleChatOverlay();
- this.commands['chat-setapi'] = (args) => {
- if (!args[0]) {
- const base = window.API_BASE || '/api';
- this.terminal.print('Current API base: ' + base, 'info');
- this.terminal.print('Usage: chat-setapi <base-url>', 'info');
- this.terminal.print('Example: chat-setapi /api', 'info');
- return;
- }
- const url = args[0].replace(/\/+$/, '');
- window.API_BASE = url;
- try {
- var settings = JSON.parse(localStorage.getItem('webx11_chat_settings') || '{}');
- settings.apiBase = url;
- localStorage.setItem('webx11_chat_settings', JSON.stringify(settings));
- } catch (e) {}
- this.terminal.print('API base set to: ' + url + ' (reopen chat to apply)', 'success');
- };
}
toggleChatOverlay() {
@@ -59,7 +39,7 @@ class ChatStudioModule {
if (!this._cssLoaded) {
const link = document.createElement('link');
link.rel = 'stylesheet';
- link.href = 'chat/chat-ui.css?v=4';
+ link.href = 'chat/chat-ui.css?v=5';
link.onload = () => { this._cssLoaded = true; };
link.onerror = () => reject(new Error('Failed to load chat/chat-ui.css'));
document.head.appendChild(link);
@@ -120,7 +100,7 @@ class ChatStudioModule {
resolve();
return;
}
- fetch('chat/chat-ui.html?v=4')
+ fetch('chat/chat-ui.html?v=5')
.then(r => r.text())
.then(html => {
this._overlayHtml = html; // cache for re-open
@@ -134,7 +114,7 @@ class ChatStudioModule {
const loadScript = (src) => {
return new Promise((res, rej) => {
const s = document.createElement('script');
- s.src = src;
+ s.src = src + '?v=5';
s.onload = () => res();
s.onerror = () => rej(new Error('Failed to load ' + src));
document.body.appendChild(s);
@@ -142,8 +122,8 @@ class ChatStudioModule {
};
Promise.all([
- loadScript('chat/chat-commands.js?v=4'),
- loadScript('chat/chat-modules.js?v=4')
+ loadScript('chat/chat-commands.js'),
+ loadScript('chat/chat-modules.js')
]).then(() => {
resolve();
});
diff --git a/modules/core/module-fs.js b/modules/core/module-fs.js
index da2e740..b119343 100644
--- a/modules/core/module-fs.js
+++ b/modules/core/module-fs.js
@@ -279,18 +279,44 @@ class FileSystemModule {
this.commands['upload'] = () => { document.getElementById('file-upload-input').click(); };
this.commands['download'] = (args) => {
if(!args[0]) return this.terminal.print('Usage: download <filename>', 'warning');
- const content = this.terminal.fs.readFile(args[0]);
+ const fname = args[0];
+ const content = this.terminal.fs.readFile(fname);
if(content !== null && content !== undefined) {
+ const size = content.length;
+ const sizeStr = size > 1024 ? (size / 1024).toFixed(1) + ' KB' : size + ' B';
+ // Desktop: programmatic click (works on desktop Chrome/Firefox)
const blob = new Blob([content], {type: 'application/octet-stream'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
- a.href = url; a.download = args[0];
+ a.href = url; a.download = fname;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 2000);
- this.terminal.print('Downloaded: ' + args[0], 'success');
- } else { this.terminal.print('download: ' + args[0] + ': No such file', 'error'); }
+ // Mobile fallback: build a DOM button with real user gesture
+ const line = document.createElement('div');
+ line.className = 'output-line';
+ const msg = document.createElement('span');
+ msg.textContent = '⬇ ' + fname + ' (' + sizeStr + ') ';
+ const btn = document.createElement('button');
+ btn.textContent = '⬇ Download';
+ btn.className = 'btn';
+ btn.style.cssText = 'background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--success-color);padding:4px 12px;border-radius:4px;cursor:pointer;font-size:0.85em;min-height:36px;';
+ btn.onclick = () => {
+ const b = new Blob([this.terminal.fs.readFile(fname)], {type: 'application/octet-stream'});
+ const u = URL.createObjectURL(b);
+ const el = document.createElement('a');
+ el.href = u; el.download = fname;
+ el.style.display = 'none';
+ document.body.appendChild(el);
+ el.click();
+ setTimeout(() => { document.body.removeChild(el); URL.revokeObjectURL(u); }, 2000);
+ };
+ line.appendChild(msg);
+ line.appendChild(btn);
+ this.terminal.outputContainer.appendChild(line);
+ this.terminal.scrollToBottom();
+ } else { this.terminal.print('download: ' + fname + ': No such file', 'error'); }
};
this.commands['vfs-export'] = () => {
const data = this.terminal.fs.root;
diff --git a/modules/core/module-leases.js b/modules/core/module-leases.js
new file mode 100644
index 0000000..b79870c
--- /dev/null
+++ b/modules/core/module-leases.js
@@ -0,0 +1,102 @@
+// module-leases.js — Lease system for agent task delegation
+// Commands: lease-create, lease-list, lease-revoke, lease-renew
+class LeaseModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this._leases = {};
+ this._watchdogTimer = null;
+ }
+ registerCommands() {
+ this.commands['lease-create'] = (args) => this.createLease(args);
+ this.commands['lease-list'] = () => this.listLeases();
+ this.commands['lease-revoke'] = (args) => this.revokeLease(args[0]);
+ this.commands['lease-renew'] = (args) => this.renewLease(args[0], parseInt(args[1]) || 30);
+ }
+ init(terminal) {
+ this.terminal = terminal;
+ if (!this.terminal.fs.readFile('/leases/')) {
+ this.terminal.fs.mkdir('leases');
+ }
+ // Restore persisted leases
+ const files = this.terminal.fs.ls('/leases/');
+ if (files) {
+ files.forEach(f => {
+ if (f.name.endsWith('.json')) {
+ const data = this.terminal.fs.readFile(`/leases/${f.name}`);
+ if (data) {
+ try {
+ const lease = JSON.parse(data);
+ this._leases[lease.id] = lease;
+ } catch (e) {}
+ }
+ }
+ });
+ }
+ // Start watchdog every 5 seconds
+ this._watchdogTimer = setInterval(() => this._checkExpired(), 5000);
+ this.terminal.print('📜 Lease system loaded', 'info');
+ }
+ createLease(args) {
+ const workerId = args[1];
+ const duration = parseInt(args[2]) || 30;
+ const task = args.slice(3).join(' ') || 'generic task';
+ if (!workerId) return this.terminal.print('Usage: lease-create <agent-id> [duration_sec] [task]', 'error');
+
+ const lease = {
+ id: `lease-${Date.now()}`,
+ workerId,
+ orchestratorId: 'orchestrator-0',
+ task,
+ createdAt: new Date().toISOString(),
+ expiresAt: new Date(Date.now() + duration * 1000).toISOString(),
+ status: 'active',
+ duration
+ };
+ this._leases[lease.id] = lease;
+ this.terminal.fs.writeFile(`leases/${lease.id}.json`, JSON.stringify(lease));
+ this.terminal.print(`📜 Lease ${lease.id} created for ${workerId} (${duration}s, task: ${task.substring(0, 40)})`, 'success');
+ return lease;
+ }
+ listLeases() {
+ const all = Object.values(this._leases);
+ const active = all.filter(l => l.status === 'active');
+ const expired = all.filter(l => l.status === 'expired');
+ const revoked = all.filter(l => l.status === 'revoked');
+ this.terminal.print(`📜 Leases: ${active.length} active, ${expired.length} expired, ${revoked.length} revoked`, 'header');
+ active.forEach(l => {
+ const remaining = Math.max(0, Math.round((new Date(l.expiresAt) - Date.now()) / 1000));
+ this.terminal.print(` ${l.id} → ${l.workerId} (${remaining}s remain) — ${l.task.substring(0, 40)}`, 'info');
+ });
+ }
+ revokeLease(id) {
+ if (!this._leases[id]) return this.terminal.print(`❌ Lease ${id} not found`, 'error');
+ this._leases[id].status = 'revoked';
+ this._leases[id].revokedAt = new Date().toISOString();
+ this.terminal.fs.writeFile(`leases/${id}.json`, JSON.stringify(this._leases[id]));
+ this.terminal.print(`✅ Lease ${id} revoked`, 'warning');
+ }
+ renewLease(id, additionalSeconds) {
+ if (!this._leases[id] || this._leases[id].status !== 'active') {
+ return this.terminal.print(`❌ Lease ${id} not found or not active`, 'error');
+ }
+ const lease = this._leases[id];
+ const newExpiry = new Date(Date.now() + additionalSeconds * 1000);
+ lease.expiresAt = newExpiry.toISOString();
+ lease.duration += additionalSeconds;
+ lease.renewedAt = new Date().toISOString();
+ this.terminal.fs.writeFile(`leases/${id}.json`, JSON.stringify(lease));
+ this.terminal.print(`✅ Lease ${id} renewed (+${additionalSeconds}s)`, 'success');
+ }
+ _checkExpired() {
+ const now = Date.now();
+ Object.values(this._leases).forEach(lease => {
+ if (lease.status === 'active' && new Date(lease.expiresAt) < now) {
+ lease.status = 'expired';
+ lease.expiredAt = new Date().toISOString();
+ this.terminal.fs.writeFile(`leases/${lease.id}.json`, JSON.stringify(lease));
+ this.terminal.log('INFO', 'Lease', `Lease ${lease.id} for ${lease.workerId} expired`);
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js
index 7187fec..2ffdb17 100644
--- a/modules/core/module-loader.js
+++ b/modules/core/module-loader.js
@@ -30,7 +30,10 @@
'module-fetcher.js',
'module-skills.js',
'secret-vault.js',
- 'module-chatstudio.js'
+ 'module-chatstudio.js',
+ 'module-agent-registry.js',
+ 'module-leases.js',
+ 'module-orchestrator.js'
];
function getSelectedModules() {
@@ -99,7 +102,7 @@
window.__moduleLoaderReload = reloadWithSelection;
-const LATEST_VER = '2026-06-02-fontfix3';
+const LATEST_VER = '2026-06-02-webdav2';
const CACHE = '?v=' + LATEST_VER;
const stored = localStorage.getItem('webx11_cache_ver');
if (stored !== LATEST_VER) {
diff --git a/modules/core/module-orchestrator.js b/modules/core/module-orchestrator.js
new file mode 100644
index 0000000..4fab599
--- /dev/null
+++ b/modules/core/module-orchestrator.js
@@ -0,0 +1,151 @@
+// module-orchestrator.js — Multi-agent orchestration system
+// Commands: orchestrate, orchestrator-status, orchestrator-spawn, orchestrator-kill, orchestrator-purge
+class OrchestratorModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this._agents = {};
+ this._SPAWN_LIMIT = 3;
+ this._heartbeatInterval = null;
+ }
+ registerCommands() {
+ this.commands['orchestrate'] = (args) => this.delegateTask(args.join(' '));
+ this.commands['orchestrator-status'] = () => this.showStatus();
+ this.commands['orchestrator-spawn'] = (args) => this.spawnAgent(args[0], args.slice(1));
+ this.commands['orchestrator-kill'] = (args) => this.killAgent(args[0]);
+ this.commands['orchestrator-purge'] = () => this.purgeDeadAgents();
+ }
+ init(terminal) {
+ this.terminal = terminal;
+ // Register orchestrator in the agent registry
+ const registry = this.terminal.moduleManager.modules['AgentRegistryModule'];
+ if (registry) {
+ registry.registerAgent(['register', 'orchestrator-0', 'delegate', 'spawn', 'monitor', 'purge']);
+ }
+ // Heartbeat watchdog every 3 seconds
+ this._heartbeatInterval = setInterval(() => this._checkHeartbeats(), 3000);
+ this.terminal.print('🧠 Orchestrator loaded — ready to delegate', 'success');
+ }
+ spawnAgent(role, capabilities) {
+ const id = `agent-${Object.keys(this._agents).length + 1}-${role || 'worker'}`;
+ if (Object.keys(this._agents).length >= this._SPAWN_LIMIT) {
+ this.terminal.print(`❌ Agent spawn limit (${this._SPAWN_LIMIT}) reached`, 'error');
+ return null;
+ }
+ const agent = {
+ id,
+ role: role || 'worker',
+ capabilities: capabilities.length ? capabilities : ['list_files', 'read_file', 'web_search'],
+ createdAt: new Date().toISOString(),
+ lastHeartbeat: Date.now(),
+ status: 'idle',
+ currentTask: null
+ };
+ this._agents[id] = agent;
+ // Register in agent registry
+ const registry = this.terminal.moduleManager.modules['AgentRegistryModule'];
+ if (registry) registry.registerAgent(['register', id, ...agent.capabilities]);
+ this.terminal.print(`🤖 Agent '${id}' spawned (role: ${role || 'worker'}, ${agent.capabilities.length} caps)`, 'success');
+ return agent;
+ }
+ killAgent(id) {
+ if (!this._agents[id]) return this.terminal.print(`❌ Agent '${id}' not found`, 'error');
+ // Revoke any active lease
+ const leaseModule = this.terminal.moduleManager.modules['LeaseModule'];
+ if (leaseModule) {
+ Object.values(leaseModule._leases).forEach(l => {
+ if (l.workerId === id && l.status === 'active') leaseModule.revokeLease(l.id);
+ });
+ }
+ // Unregister from registry
+ const registry = this.terminal.moduleManager.modules['AgentRegistryModule'];
+ if (registry) registry.unregisterAgent(id);
+ delete this._agents[id];
+ this.terminal.print(`💀 Agent '${id}' killed`, 'warning');
+ }
+ async delegateTask(task) {
+ if (!task) return this.terminal.print('Usage: orchestrate <task description>', 'error');
+ // Find an idle agent or auto-spawn
+ let agent = Object.values(this._agents).find(a => a.status === 'idle');
+ if (!agent) {
+ if (Object.keys(this._agents).length >= this._SPAWN_LIMIT) {
+ return this.terminal.print('❌ All agents busy and spawn limit reached', 'error');
+ }
+ this.spawnAgent('worker', ['list_files', 'read_file', 'write_file', 'web_search']);
+ agent = Object.values(this._agents).find(a => a.status === 'idle');
+ }
+ if (!agent) return this.terminal.print('❌ No available agents', 'error');
+ // Create a lease
+ const leaseModule = this.terminal.moduleManager.modules['LeaseModule'];
+ const lease = leaseModule ? leaseModule.createLease(['lease-create', agent.id, '60', task]) : null;
+ // Mark agent as busy
+ agent.status = 'busy';
+ agent.currentTask = task;
+ agent.leaseId = lease?.id;
+ // Write task to agent's inbox
+ if (!this.terminal.fs.readFile(`/agents/${agent.id}/`)) this.terminal.fs.mkdir(`agents/${agent.id}`);
+ this.terminal.fs.writeFile(`agents/${agent.id}/inbox.json`, JSON.stringify({
+ task,
+ from: 'orchestrator-0',
+ leaseId: lease?.id,
+ timestamp: new Date().toISOString(),
+ ttl_seconds: 60
+ }));
+ this.terminal.print(`🎯 Delegated "${task.substring(0, 60)}" to ${agent.id} (lease: ${lease?.id || 'none'})`, 'info');
+ // Execute via AI assistant
+ try {
+ const aiModule = this.terminal.moduleManager.modules['WebX11AIAssistantModule'];
+ if (aiModule && typeof aiModule.chat === 'function') {
+ const result = await aiModule.chat([`[DELEGATED] ${task}`]);
+ agent.status = 'completed';
+ this.terminal.fs.writeFile(`agents/${agent.id}/outbox.json`, JSON.stringify({
+ result: result || 'completed',
+ status: 'completed',
+ timestamp: new Date().toISOString()
+ }));
+ this.terminal.print(`✅ ${agent.id} completed task`, 'success');
+ } else {
+ this.terminal.print(`ℹ️ AI module not available — task queued for ${agent.id}`, 'info');
+ }
+ } catch (e) {
+ agent.status = 'failed';
+ this.terminal.print(`❌ ${agent.id} failed: ${e.message}`, 'error');
+ }
+ // Return to idle pool
+ agent.status = 'idle';
+ agent.currentTask = null;
+ agent.lastHeartbeat = Date.now();
+ }
+ _checkHeartbeats() {
+ const now = Date.now();
+ Object.entries(this._agents).forEach(([id, agent]) => {
+ if (agent.status === 'busy' && now - agent.lastHeartbeat > 15000) {
+ this.terminal.print(`⚠️ Agent '${id}' unresponsive (${Math.round((now - agent.lastHeartbeat) / 1000)}s since heartbeat)`, 'warning');
+ }
+ });
+ }
+ purgeDeadAgents() {
+ const now = Date.now();
+ let count = 0;
+ Object.entries(this._agents).forEach(([id, agent]) => {
+ if (now - agent.lastHeartbeat > 60000) {
+ this.killAgent(id);
+ count++;
+ }
+ });
+ this.terminal.print(`🧹 Purged ${count} dead agents`, count > 0 ? 'warning' : 'info');
+ }
+ showStatus() {
+ const total = Object.keys(this._agents).length;
+ const busy = Object.values(this._agents).filter(a => a.status === 'busy').length;
+ const idle = Object.values(this._agents).filter(a => a.status === 'idle').length;
+ const failed = Object.values(this._agents).filter(a => a.status === 'failed').length;
+ this.terminal.print('🧠 Orchestrator Status', 'header');
+ this.terminal.print(` Agents: ${total} (${busy} busy, ${idle} idle, ${failed} failed)`, 'info');
+ this.terminal.print(` Spawn limit: ${this._SPAWN_LIMIT}`, 'info');
+ Object.values(this._agents).forEach(a => {
+ const task = a.currentTask ? ` (task: ${a.currentTask.substring(0, 40)})` : '';
+ this.terminal.print(` ${a.id} — ${a.status}${task}`, 'info');
+ });
+ }
+} \ No newline at end of file
diff --git a/modules/core/module-system.js b/modules/core/module-system.js
index e54a5fe..c0dbe14 100644
--- a/modules/core/module-system.js
+++ b/modules/core/module-system.js
@@ -36,6 +36,13 @@
this.terminal.print(`Memory Usage: ${mem} MB`, 'info');
document.getElementById('header-status').innerText = `Mem: ${mem}MB`;
};
+ // Refresh memory display on boot
+ setTimeout(() => {
+ if (performance.memory) {
+ const mem = (performance.memory.usedJSHeapSize / 1048576).toFixed(1);
+ document.getElementById('header-status').innerText = `Mem: ${mem}MB`;
+ }
+ }, 500);
this.commands['status'] = () => {
this.terminal.print(`System: WebX11 v4.2`);
this.terminal.print(`Network: ${navigator.onLine ? 'Online' : 'Offline'}`);
@@ -223,12 +230,12 @@
}
// Categorize all commands
const cats = {
- files: ['ls','ll','cat','put','rm','mv','cp','mkdir','rmdir','cd','pwd','find','grep','head','tail','sort','wc','touch','tree','du','upload','download','vfs-export','vfs-import','edit','diff'],
- ai: ['ai','ask','ai-clear','ai-system','ai-context','ai-allow','ai-deny','ai-ignore','ai-stop','ai-model'],
+ files: ['ls','ll','cat','put','rm','mv','cp','mkdir','rmdir','cd','pwd','find','grep','head','tail','sort','wc','touch','tree','du','upload','download','vfs-export','vfs-import','edit','diff','trash','trash-dir','ls-trash','empty-trash'],
+ ai: ['ai','ask','ai-clear','ai-system','ai-context','ai-allow','ai-deny','ai-ignore','ai-stop','ai-model','ai-compress','debug'],
search: ['search','s','ddg','duck','fetch','web','extract'],
tools: ['calc','cron-every','cron-list','cron-stop','cron-clear','wpm','mindmap','theme','voice','alias','unalias',
- 'which','env','date','cal','yes','seq','base64','printf','cut','uniq','hostname','whoami','basename','dirname','sleep','expand','tutorial'],
- system: ['help','clear','cls','echo','mem','status','font-size','setfont','smart-prompt','logs','preview','factory-reset','reset-vfs','export','unset','script','set','test'],
+ 'which','env','date','cal','yes','seq','base64','printf','cut','uniq','hostname','whoami','basename','dirname','sleep','expand','tutorial','gzip','gunzip','encrypt','decrypt','files','session-save','session-load','session-list','session-delete','session-export','session-import'],
+ system: ['help','clear','cls','echo','mem','status','font-size','setfont','smart-prompt','logs','preview','factory-reset','reset-vfs','export','unset','script','set','test','logrotate','health-check','memory-map-export','commands','check','checkpoint','checkpoint-list','rollback','checkpoint-del'],
net: ['server','servers','server-check','server-remove','monitor'],
mods: ['modules','listmods','loadmod','removemod','load-local','loadlocal','startup-modules'],
ollama: ['ollama','ollamaconnect','ollamadisconnect','ollamamodels','ollamasetmodel','ollamasetproxy','models','model-info','model-pull','model-delete','model-run'],
@@ -236,14 +243,15 @@
config: ['config','config-set','config-list','config-delete','config-export','config-reset'],
webx: ['webxai','wx','webx','context','contexts','context-new','context-delete','smart-ask','prompt','prompt-save','prompt-list','prompt-delete','prompt-var','prompt-vars'],
data: ['my','my-set','my-get','my-list','my-export','my-import','my-clear','export-mods','import-mods','backup','restore','share-mod'],
- ext: ['chat','chat-setapi','chat-setmodel','chat-ask','webdav-config','webdav-status','webdav-ls','webdav-push','webdav-pull','webdav-backup','webdav-restore','webdav-backup-list'],
+ ext: ['chat','chat-setapi','chat-setmodel','chat-ask','webdav-config','webdav-status','webdav-ls','webdav-push','webdav-pull','webdav-backup','webdav-restore','webdav-backup-list','webdav-explorer','webdav-browser'],
gui: ['gui','gui-button','gui-input','gui-text','gui-clear','gui-run'],
+ vault: ['secret-set','secret-get','secret-list','secret-del','secret-lock','secret-unlock','secret-setpin','secret-status'],
};
const labels = {
files:'📁 Filesystem', ai:'🤖 AI', search:'🔍 Search & Web', tools:'🔧 Tools',
system:'⚙️ System', net:'📡 Network', mods:'🧩 Modules', ollama:'🦙 Ollama',
skills:'📚 Skills', config:'⚙️ Config', webx:'🌐 WebX', data:'💾 Data',
- ext:'🧰 Extras', gui:'🖥️ GUI'
+ ext:'🧰 Extras', gui:'🖥️ GUI', vault:'🔒 Vault'
};
let result = '╔══════════════════════════════════════╗\n║ 🔷 WebX11 v4.2 — All Commands ║\n╚══════════════════════════════════════╝\n\n';
const total = Object.keys(helpMap).length;
diff --git a/modules/core/terminal.js b/modules/core/terminal.js
index f0ef036..4111f5f 100644
--- a/modules/core/terminal.js
+++ b/modules/core/terminal.js
@@ -868,10 +868,10 @@
const lowerInput = input.toLowerCase();
// Expanded command lists for autocomplete
- const fileArgCommands = ['cat', 'preview', 'rm', 'rmdir', 'edit', 'view', 'cp', 'mv', 'touch', 'put', 'run', 'chmod', 'gzip', 'gunzip', 'encrypt', 'decrypt', 'webdav-backup', 'webdav-restore', 'webdav-upload', 'webdav-download', 'webdav-list'];
+ const fileArgCommands = ['cat', 'preview', 'rm', 'rmdir', 'edit', 'view', 'cp', 'mv', 'touch', 'put', 'run', 'chmod', 'gzip', 'gunzip', 'encrypt', 'decrypt', 'download', 'webdav-backup', 'webdav-restore', 'webdav-upload', 'webdav-download', 'webdav-list'];
const dirArgCommands = ['ls', 'cd', 'mkdir', 'rmdir'];
const sessionArgCommands = ['session-load', 'session-delete', 'session-export', 'session-save', 'session-list', 'session-import'];
- const pathArgCommands = ['cat', 'preview', 'rm', 'edit', 'view', 'cp', 'mv', 'touch', 'put', 'run', 'chmod', 'gzip', 'gunzip', 'encrypt', 'decrypt', 'webdav-backup', 'webdav-restore', 'webdav-upload', 'webdav-download', 'webdav-list', 'ls', 'cd', 'mkdir', 'rmdir', 'cat', 'preview'];
+ const pathArgCommands = ['cat', 'preview', 'rm', 'edit', 'view', 'cp', 'mv', 'touch', 'put', 'run', 'chmod', 'gzip', 'gunzip', 'encrypt', 'decrypt', 'download', 'webdav-backup', 'webdav-restore', 'webdav-upload', 'webdav-download', 'webdav-list', 'ls', 'cd', 'mkdir', 'rmdir', 'cat', 'preview'];
// Collect commands that take arguments from ext module metadata
const extFileCmds = new Set();
@@ -1024,6 +1024,9 @@
this._safeRegister('SecretVault', 'secret vault');
this.reloadPersistedModules();
this._safeRegister('ChatStudioModule', 'chat studio');
+ this._safeRegister('AgentRegistryModule', 'agent registry');
+ this._safeRegister('LeaseModule', 'lease system');
+ this._safeRegister('OrchestratorModule', 'orchestrator');
}
_safeRegister(className, label) {
let cls;
diff --git a/modules/ext/skill-pack-core.js b/modules/ext/skill-pack-core.js
index cc8ae88..f731594 100644
--- a/modules/ext/skill-pack-core.js
+++ b/modules/ext/skill-pack-core.js
@@ -20,37 +20,51 @@ class SkillPackCoreModule {
getHelpInfo() {
return {
- 'skill-pack-core': 'Seed and manage built-in core skills (navigation, memory, search, modules, backup, mindmap, etc.)',
+ 'skill-pack-core': 'Seed and manage built-in core skills (navigation, memory, search, modules, backup, agents, webdav, security, etc.)',
};
}
_buildSkills() {
const s = (name, desc, tags, cat, steps) => ({
name, description: desc, tags, category: cat,
- content: `---\nname: ${name}\ndescription: ${desc}\ntags: [${tags.join(', ')}]\ncategory: ${cat}\n---\n## Steps\n${steps}`
+ content: '---\nname: ' + name + '\ndescription: ' + desc + '\ntags: [' + tags.join(', ') + ']\ncategory: ' + cat + '\n---\n## Steps\n' + steps
+ });
+
+ const sk = (name, desc, tags, cat, content) => ({
+ name, description: desc, tags, category: cat,
+ content: '---\nname: ' + name + '\ndescription: ' + desc + '\ntags: [' + tags.join(', ') + ']\ncategory: ' + cat + '\n---\n' + content
});
return [
s('navigating-the-terminal', 'How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem', ['terminal', 'navigation', 'help', 'filesystem'], 'system',
`1. **Get an overview of available commands:**
- - Call get_help() to get a full command list sorted by category
- - Call get_status() to see filesystem state, loaded modules, Ollama status
- - For a specific command, use help <command> or check the help map
+ - Type "help" for a full command list sorted by category
+ - Type "status" to see filesystem state, loaded modules, Ollama status
+ - For a specific command, use help <command>
+ - Type "commands" for a compact list with module source info
+ - Type "check" for system health including module requirements
2. **Explore the filesystem:**
- - Use list_files(path?) to browse directories (omit path for current dir)
- - Use read_file(path) to view file contents
- - Use get_current_dir to see your working directory
- - Use run_command("ls") or run_command("tree") for visual output
+ - Use ls, ll, tree to browse directories
+ - Use cd <dir> to navigate, pwd to show current path
+ - Use cat or edit to view file contents
+ - Use find or grep to search files
+ - Use du to see disk usage
3. **Understand system state:**
- - run_command("mem") — memory usage
- - run_command("status") — network, files, modules, Ollama
- - run_command("modules") — module manager GUI
- - get_module_status() — loaded modules, URLs, local edits
-
-4. **When user asks a vague question:**
- - First call get_status() and get_help() to understand the current state
+ - mem — memory usage (auto-shown in header on boot)
+ - status — network, files, modules, Ollama
+ - modules — module manager GUI
+ - health-check — VFS size, modules, logs, trash, skills, tool failures
+ - checkpoint-list — VFS checkpoint snapshots
+
+4. **Agent / Orchestration state:**
+ - agent-list — registered agents (type, capabilities, status)
+ - orchestrate — list active orchestrated agents
+ - lease-list — show active leases with TTL
+
+5. **When user asks a vague question:**
+ - First run status and help to understand the current state
- Then ask clarifying questions based on what you found`),
s('memory-and-profile', 'How to use the user profile system, session memory, and pattern tracking for persistent context', ['memory', 'profile', 'session', 'persistence'], 'system',
@@ -67,26 +81,36 @@ class SkillPackCoreModule {
- session_recent(count) — show last N session summaries
- session_stats — aggregate totals across all sessions
- Recent sessions auto-load into context on first message
+ - systemd-style journal: use logs and logrotate commands for persistent logging
3. **Conversation Patterns:**
- Pattern tracking runs automatically — frequent topics surface as hints
- my-set, my-get, my-list store additional personal data
- AI conversation context persists within a session (use ai-clear to reset)
+ - debug command toggles real-time debug panel with Copy/Export/VFS buttons
-4. **When to use:**
+4. **Checkpoints (VFS snapshots):**
+ - checkpoint [name] — snapshot current VFS state
+ - checkpoint-list — list all checkpoints
+ - rollback <name> — restore from checkpoint
+ - checkpoint-del <name> — delete a checkpoint
+
+5. **When to use:**
- At start: call session_recent(3) to see what was worked on before
- After identifying user preferences: call user_set to store them
- - After complex tasks: call session_save with a brief summary`),
+ - After complex tasks: call session_save with a brief summary
+ - Before risky edits: call checkpoint to create a restore point`),
s('web-search-and-fetch', 'How to search the web and fetch URL content using the WebX11 proxy API', ['search', 'fetch', 'web', 'proxy', 'api'], 'research',
`1. **Search the web:**
- - Call web_search(query) — uses /api/search which queries SearXNG + DDG fallback
+ - Use search <query> or web_search(query) — uses /api/search which queries SearXNG + DDG fallback
- Results include: title, url, content snippet, source engine
- Always available (same-origin, no CORS issues)
- 5-minute server-side cache for repeated queries
+ - Alternative: use ddg or duck <query> for DuckDuckGo direct, or s <query> as alias
2. **Fetch URL content:**
- - Call web_fetch(url) — uses /api/extract which strips HTML, extracts clean text
+ - Use fetch <url> or web_fetch(url) — uses /api/extract which strips HTML, extracts clean text
- Returns: title, content (up to 4000 chars), word_count, extraction method
- SSRF protection blocks internal network addresses
- 15-minute server-side cache
@@ -96,19 +120,21 @@ class SkillPackCoreModule {
- search <query> --fetch — fetches content snippets for top 3 results
4. **When to use:**
- - User asks about current events, facts, research → call web_search
- - User says "read this article" or provides a URL → call web_fetch
+ - User asks about current events, facts, research → use search <query>
+ - User says "read this article" or provides a URL → use fetch <url>
- For in-depth analysis: search first, then fetch top results`),
s('module-management', 'How to view, edit, test, reload modules and manage startup configuration', ['modules', 'editing', 'code', 'self-improvement'], 'dev',
`1. **View module source:**
- view_module(name) — fetches original source or reads from _mods/ if edited
- Supports all loaded modules: SystemModule, FileSystemModule, SearXNGModule, etc.
+ - Or use modules command for GUI module manager
2. **Edit a module:**
- edit_module(name) — copies source to _mods/<name>.js and opens code editor
- Editor shows the full source in a textarea
- Click "Save & Test" to save and auto-load the edited version
+ - Checkpoint before editing: checkpoint mod-edit-<name>
3. **Test and reload:**
- test_module(name) — loads edited module from _mods/ for live testing
@@ -121,8 +147,15 @@ class SkillPackCoreModule {
5. **Manage startup:**
- startup-modules — opens the Startup Modules UI to select which modules load
- load-local <path> — load a module from VFS or URL without editing
+ - loadmod <url> — alternative: load module from URL
+ - removemod <name> — remove a loaded module
-6. **When to use:**
+6. **Agent modules (Phase 2):**
+ - module-agent-registry.js — Agent registry with agent-list, agent-register, agent-unregister, agent-status
+ - module-leases.js — Time-bound contracts with 5s watchdog, auto-expiry
+ - module-orchestrator.js — Spawn, delegate, kill, purge with heartbeat monitoring
+
+7. **When to use:**
- User reports a bug in a module → view_module, edit_module, test_module
- User asks "can you add X feature?" → same workflow
- Always save edits before testing. If test fails, the original module stays loaded.`),
@@ -142,42 +175,68 @@ class SkillPackCoreModule {
- config-export — dump all config as JSON
- config-reset — restore defaults (use before factory-reset if you want to save data)
-4. **Health checks (run automatically after complex tasks):**
+4. **Security level:**
+ - security-level <0-3> — set security level (0=Permissive, 1=Standard, 2=Paranoid, 3=Audit)
+ - security — show current security level, blocked count, and stats
+ - cmd-allow <cmd> — whitelist a command from security checks
+ - cmd-deny <cmd> — blacklist a command
+
+5. **Health checks (run automatically after complex tasks):**
- Check module loading status: loaded vs total
- Check for pending module edits
- Check memory usage (high if >100MB)
- Check skill count (0 skills after 2+ tool calls → suggest create_skill)
+ - health-check — full audit: VFS size, modules, logs, trash, skills, tool failures
-5. **Font size and display:**
+6. **Font size and display:**
- font-size <8-32> — set terminal font size, persists across sessions
- setfont — alias for font-size
-6. **When to use:**
- - System is slow or modules fail to load → check check_updates, memory
+7. **Checkpoints:**
+ - checkpoint [name] — snapshot current VFS state
+ - checkpoint-list — list all checkpoints
+ - rollback <name> — restore from checkpoint
+
+8. **When to use:**
+ - System is slow or modules fail to load → check check_updates, mem
- User says "reset everything" → factory-reset --confirm
- - User says "clear my files but keep settings" → reset-vfs --confirm`),
+ - User says "clear my files but keep settings" → reset-vfs --confirm
+ - User reports security concerns → security-level or cmd-allow/cmd-deny`),
s('backup-and-restore', 'How to backup, restore, and export WebX11 data', ['backup', 'restore', 'export', 'import', 'persistence'], 'system',
`1. **Backup VFS:**
- vfs-export — downloads the entire virtual filesystem as a dated JSON file
- backup — creates a full backup including VFS, modules, config (saves to _backups/)
-2. **Export/Import personal data:**
+2. **WebDAV cloud backup:**
+ - webdav-backup — push VFS snapshot to WebDAV server (auto-archive)
+ - webdav-backup-list — list remote WebDAV backups
+ - webdav-restore <file> — restore VFS from remote WebDAV snapshot
+ - webdav-push <local> <remote> — push file to WebDAV space
+ - webdav-pull <remote> <local> — pull file from WebDAV space
+ - webdav-ls [path] — list remote WebDAV directory contents
+ - webdav-status — check WebDAV connection and space usage
+ - webdav-explorer — GUI file browser for WebDAV
+ - webdav-browser — simpler file listing for WebDAV
+ - webdav-config — configure WebDAV endpoint and credentials
+
+3. **Export/Import personal data:**
- my-export — prints all my-set data as formatted JSON
- my-import <json> — bulk-import personal data from JSON string
-3. **Export/Import modules:**
+4. **Export/Import modules:**
- export-mods — exports module registry as JSON
- import-mods <json> — imports modules from JSON backup
-4. **Restore:**
+5. **Restore:**
- restore <json> — restores terminal state from a backup JSON
- Session logs are saved to /memory/ automatically on page unload
-5. **When to use:**
+6. **When to use:**
- Before factory-reset: call my-export, vfs-export, export-mods to save data
- When switching browsers or devices: export all, then import
- - User says "backup my data" or "save my files"`),
+ - User says "backup my data" or "save my files"
+ - For cloud backup: use webdav-backup (requires WebDAV server configured)`),
s('mindmap-workflow', 'How to create, view, edit, and manage brainstorming mindmaps', ['mindmap', 'brainstorming', 'planning', 'organization'], 'productivity',
`1. **Create a new mindmap:**
@@ -215,18 +274,19 @@ class SkillPackCoreModule {
s('skills-system-guide', 'How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory', ['skills', 'system', 'meta'], 'system',
`1. **Always load skills at task start:**
- - At the START of every task, call load_skills(query) to check for stored procedures
- - Example: load_skills("search the web") returns matching skill content
- - Example: load_skills("edit module") returns the module editing workflow
+ - At the START of every task, type or call "skill-view <name>" or "skill-list"
+ - Example: skill-view "module-management" — returns matching skill content
+ - Example: skill-list system — browse skills by category
2. **Create skills after complex tasks:**
- - After any task with 3+ tool calls, call create_skill to save the approach
+ - After any task with 3+ tool calls, call "skill-create"
- Required fields: name (kebab-case), description, content (markdown with YAML frontmatter)
- Optional: tags (comma-separated), category (e.g. research, system, dev)
- Skills persist in /skills/ as .md files with /skills/index.json for fast lookup
+ - Skill pack auto-seeds 8 core skills on first boot
3. **Patch skills when they're outdated:**
- - If a stored procedure has wrong steps, call patch_skill(name, newContent)
+ - If a stored procedure has wrong steps, call "skill-patch <name>"
- This replaces the entire skill content and updates the index
- Do NOT create a duplicate — always patch the existing skill
@@ -235,13 +295,139 @@ class SkillPackCoreModule {
- Named tool-<name>-workaround (e.g. tool-write_file-workaround)
5. **Audit and maintenance:**
- - list_skills(category?) — browse available skills, optionally filter
+ - skill-list <category?> — browse available skills, optionally filter
+ - skill-export <name> — download a skill as markdown
+ - skill-import <json> — bulk import skills
+ - skill-sync — re-index skills from /skills/ directory
- Skills are audited every 20 messages for staleness (empty content, >30 days old)
6. **YAML frontmatter format:**
- Each skill file must start with: ---\\nname: <name>\\ndescription: <text>\\ntags: [...]\\ncategory: <cat>\\n---\\n
- Steps follow under ## Steps heading
- Use numbered lists for sequential steps`),
+
+ sk('agent-orchestration', 'How to use the agent registry, leases, and orchestrator for multi-agent workflows', ['agents', 'orchestration', 'delegation', 'leases'], 'system',
+`## Steps
+1. **Agent Registry:**
+ - agent-list — list all registered agents (ID, type, capabilities, status)
+ - agent-register <type> <capabilities> — register a new agent (capabilities: comma-separated like "code,research")
+ - agent-unregister <id> — remove an agent
+ - agent-status <id> — detailed status including uptime, task history
+
+2. **Leases (time-bound contracts):**
+ - lease-create <agent-id> <ttl-seconds> — create a lease with watchdog timer
+ - lease-list — show active leases with remaining TTL
+ - lease-revoke <lease-id> — terminate a lease early
+ - lease-renew <lease-id> <ttl-seconds> — extend a lease
+
+3. **Orchestrator (spawn, delegate, kill):**
+ - orchestrator-spawn <type> <capabilities> — spawn a new agent automatically (registers + creates lease)
+ - orchestrator-kill <agent-id> — kill an agent (revokes lease + unregisters)
+ - orchestrate — list all active agents with their orchestrator state
+ - orchestrator-purge — kill all idle/expired agents
+ - orchestrator-status — full system status: active, idle, dead agents
+
+4. **AI tool integration:**
+ - AI tools list_agents, delegate_task, spawn_agent are available in the AI system prompt
+ - The AI can auto-spawn worker agents for sub-tasks
+ - Each agent gets its own VFS workspace at /agents/<agent-id>/
+
+5. **When to use:**
+ - User needs parallel task execution → orchestrator-spawn coder + researcher
+ - Time-bound automation → lease-create with short TTL
+ - System cleanup → orchestrator-purge to kill stale agents`),
+
+ sk('debug-panel-and-logs', 'How to use the debug panel, session logging, and terminal diagnostics', ['debug', 'logging', 'diagnostics', 'troubleshooting'], 'system',
+`## Steps
+1. **Toggle debug panel:**
+ - debug — opens real-time debug panel showing last AI tool call, response time, and context
+ - Debug panel includes Copy, Export, and Write to VFS buttons
+ - Export: saves tool call log as timestamped JSON to downloads
+ - Write to VFS: appends debug data to /debug.log (dedup by turn ID)
+
+2. **Session logging:**
+ - logs [n] [LEVEL] — view last n log entries (optionally filtered by INFO/WARN/ERROR)
+ - logrotate — rotate current.log to dated archive (auto-cleans old logs beyond 10)
+ - Logs stored in /logs/ directory: current.log + dated archives
+ - Health check runs automatically after complex tasks
+
+3. **Diagnostic commands:**
+ - health-check — full audit: VFS size, modules, logs, trash, skills
+ - check — quick system health including module requirement status
+ - mem — real-time memory usage (also in header)
+ - status — network, files, modules, Ollama connectivity
+
+4. **System journals:**
+ - debug.log — appended by debug panel VFS button (dedup by turn ID)
+ - current.log — system activity log with rotation
+ - Auto-save: terminal state auto-saves every 60s
+
+5. **When to use:**
+ - AI is behaving unexpectedly → debug to see tool calls
+ - User reports errors → logs 50 ERROR to see error entries
+ - Memory concerns → mem to check, health-check for full audit`),
+
+ sk('webdav-operations', 'How to use WebDAV cloud storage for backup, file sync, and remote file access', ['webdav', 'cloud', 'backup', 'sync', 'storage'], 'system',
+`## Steps
+1. **Configuration:**
+ - webdav-config — configure WebDAV endpoint URL and credentials
+ - Connection auto-tested on config; webdav-status shows connection health
+ - Uses per-user token stored in .token file on the server side
+
+2. **File operations:**
+ - webdav-ls [path] — list remote directory contents
+ - webdav-push <local-path> <remote-path> — upload file to WebDAV
+ - webdav-pull <remote-path> [local-path] — download file from WebDAV
+ - webdav-explorer — GUI file browser for WebDAV
+ - webdav-browser — CLI file browser for WebDAV
+
+3. **Backup & Restore:**
+ - webdav-backup — push full VFS snapshot to WebDAV (creates /backups/newos4-<date>.json)
+ - webdav-backup-list — list all remote backup snapshots
+ - webdav-restore <filename> — restore VFS from a remote backup snapshot
+
+4. **Status & Diagnostics:**
+ - webdav-status — connection status, last sync, space information
+ - If uploads fail: check webdav-config, ensure .token file is valid
+ - WebDAV runs on the same server (nginx with WebDAV module), no external dependency
+
+5. **When to use:**
+ - Before factory-reset: webdav-backup to store VFS remotely
+ - Cross-browser: webdav-push/pull to move files between instances
+ - User says "cloud backup" or "remote save" → webdav-backup`),
+
+ sk('security-and-safety', 'How to use WebX11 security levels, command blocking, and safety features', ['security', 'safety', 'blocking', 'permissions'], 'system',
+`## Steps
+1. **Security levels:**
+ - security-level <0-3> — set security level:
+ 0 = Permissive (no blocks, no confirms — anything runs)
+ 1 = Standard (unknown cmds → AI route, destructive → confirm, system → block)
+ 2 = Paranoid (unknown cmds blocked entirely, destructive blocked)
+ 3 = Audit (everything allowed, everything logged)
+ - Default: level 1
+ - security — show current level, blocked count, and stats
+
+2. **Command control:**
+ - cmd-allow <cmd> — whitelist a command from security checks
+ - cmd-deny <cmd> — blacklist/block a command entirely
+ - whitelist built-in: help, clear, ls, cat, pwd, whoami, df, free, top, ps, echo, date, env, history
+
+3. **What gets blocked at each level:**
+ - Unknown commands: Level 1 → AI routed, Level 2+ → blocked
+ - Destructive commands (delete, write, save, format, etc.): Level 1 → confirmation, Level 2+ → blocked
+ - System commands (reboot, shutdown, format, kill): Level 1+ → blocked
+ - Suspicious flags (--execute, --eval, --shell): Level 1+ → blocked
+
+4. **Safety checklist:**
+ - Check security: security shows your current level
+ - Before running risky commands: create a checkpoint first
+ - For temporary relax: security-level 0, then restore to 1
+ - For total lockdown before leaving: security-level 2
+
+5. **When to use:**
+ - User wants to lock down the terminal → security-level 2
+ - User wants to allow a blocked command → cmd-allow <cmd>
+ - Debugging strange behavior → verify security-level (user may have set it higher)`)
];
}
registerCommands() {
@@ -264,8 +450,9 @@ class SkillPackCoreModule {
console.log('[SkillPackCore] existing index keys:', Object.keys(index));
let seeded = 0;
for (const skill of this._skills) {
- if (!index[skill.name]) {
- fs.writeFile(`/skills/${skill.name}.md`, skill.content);
+ const existing = index[skill.name];
+ if (!existing) {
+ fs.writeFile('/skills/' + skill.name + '.md', skill.content);
index[skill.name] = {
name: skill.name,
description: skill.description,
@@ -275,14 +462,25 @@ class SkillPackCoreModule {
updated: new Date().toISOString()
};
seeded++;
+ } else {
+ // Update existing skill content on fresh load (cache-bust version bump triggers this)
+ fs.writeFile('/skills/' + skill.name + '.md', skill.content);
+ index[skill.name] = {
+ ...existing,
+ description: skill.description,
+ tags: skill.tags,
+ category: skill.category,
+ updated: new Date().toISOString()
+ };
}
}
if (seeded > 0) {
- fs.fsWriteJSON('/skills/index.json', index);
+ this.terminal.print('📚 Seeded ' + seeded + ' new skill(s)', 'success');
}
+ fs.fsWriteJSON('/skills/index.json', index);
this._seeded = true;
}
}
if (typeof window.webx11 !== 'undefined' && window.webx11) {
webx11.moduleManager.registerModule(new SkillPackCoreModule(), 'https://webx11.duckdns.org/spaces/newos4/modules/ext/skill-pack-core.js');
-}
+} \ No newline at end of file
diff --git a/modules/ext/webdav.js b/modules/ext/webdav.js
index b4dfa6f..eea513b 100644
--- a/modules/ext/webdav.js
+++ b/modules/ext/webdav.js
@@ -46,8 +46,11 @@ class WebDAVModule {
'webdav-backup': 'Backup entire VFS to WebDAV as a dated JSON snapshot',
'webdav-restore': 'Restore VFS from a WebDAV backup file',
'webdav-backup-list': 'List available backup files on WebDAV',
- 'webdav-explorer': 'webdav-explorer [path] — Interactive remote file browser',
- 'webdav-browser': 'webdav-browser [path] — Visual WebDAV file explorer modal',
+ 'webdav-browser': 'webdav-browser [path] — Modern WebDAV file-tree browser with bulk operations',
+ 'webdav-rm': 'webdav-rm <path> — Delete a remote file or directory',
+ 'webdav-mkdir': 'webdav-mkdir <path> — Create a remote directory',
+ 'webdav-rename': 'webdav-rename <old> <new> — Rename or move a remote file/dir',
+ 'webdav-move': 'webdav-move <old> <new> — Alias for webdav-rename',
};
}
@@ -127,7 +130,11 @@ class WebDAVModule {
}
async _listDir(path) {
- // Try PROPFIND first (works with WebDAV servers), fallback to nginx autoindex
+ // For WebX11 spaces, skip PROPFIND (nginx returns 302) and use __list__ directly
+ if (this._spaceName) {
+ return this._listDirViaAutoIndex(path);
+ }
+ // Non-nginx: try PROPFIND first, fallback to autoindex
try {
const response = await this._webdavRequest('PROPFIND', path, {
headers: { 'Depth': '1' }
@@ -137,15 +144,24 @@ class WebDAVModule {
return this._parsePropfind(text);
}
} catch (e) { /* PROPFIND failed, try autoindex */ }
- // Fallback: use nginx __list__ endpoint
return this._listDirViaAutoIndex(path);
}
async _listDirViaAutoIndex(path) {
- const baseUrl = this.config.url.replace(/\/+$/, '') + '/';
- const urlPath = path ? (path.startsWith('/') ? path : '/' + path) : '/';
- // Use __list__ for directory listing
- const listUrl = baseUrl.replace(/\/spaces\/([^/]+)\//, '/spaces/$1/__list__/') + urlPath.replace(/^\//, '');
+ if (!this._spaceName) {
+ throw new Error('WebDAV: cannot use __list__ without space name');
+ }
+ // Derive host from configured URL to support different environments
+ let host = 'https://webx11.duckdns.org';
+ if (this.config && this.config.url) {
+ try {
+ const u = new URL(this.config.url);
+ host = u.origin;
+ } catch (e) {}
+ }
+ const cleanPath = path ? (path.startsWith('/') ? path : '/' + path) : '/';
+ // Avoid double slash when path starts with /
+ const listUrl = host + '/spaces/' + this._spaceName + '/__list__' + (cleanPath === '/' ? '' : cleanPath.replace(/\/{2,}/g, '/'));
try {
const resp = await fetch(listUrl, { method: 'GET' });
if (!resp.ok) throw new Error('Autoindex failed: HTTP ' + resp.status);
@@ -158,15 +174,14 @@ class WebDAVModule {
_parseAutoindex(html) {
const entries = [];
- // Parse nginx autoindex HTML format
- const linkRegex = /<a href="([^"]+)">([^<]+)<\/a>\s+(\d{2}-[A-Za-z]{3}-\d{4}\s+\d{2}:\d{2})\s+([\d\w.-]+)/g;
+ // Parse nginx autoindex HTML format — flexible regex that doesn't depend on date locale
+ const linkRegex = /<a href="([^"]+)">([^<]+)<\/a>\s+([\w]{2}-[\w]{3}-\d{4}\s+\d{2}:\d{2})\s+([\d\w.-]+)/g;
let match;
while ((match = linkRegex.exec(html)) !== null) {
const href = match[1];
const name = match[2].replace(/\/$/, '');
const sizeStr = match[4];
- if (name === '..' || name === '../') continue;
- if (name === '__list__') continue;
+ if (name === '..' || name === '../' || name === '__list__') continue;
const isDir = href.endsWith('/');
let size = 0;
if (!isDir && sizeStr !== '-') {
@@ -181,22 +196,40 @@ class WebDAVModule {
}
// Fallback: if regex failed, try simpler parse
if (entries.length === 0) {
- const simpleRegex = /<a href="([^"]+)">/g;
+ // Try broadest: extract all hrefs
+ const broadRegex = /<a href="([^"]+)"[^>]*>/g;
const names = [];
- while ((match = simpleRegex.exec(html)) !== null) {
+ while ((match = broadRegex.exec(html)) !== null) {
const href = match[1];
if (href === '../' || href === '/' || href === './') continue;
if (href.startsWith('?')) continue;
names.push(href);
}
- for (const href of names) {
- const isDir = href.endsWith('/');
- entries.push({
- name: decodeURIComponent(href.replace(/\/$/, '').split('/').pop() || href),
- type: isDir ? 'dir' : 'file',
- size: 0,
- href: href
- });
+ if (names.length > 0) {
+ for (const href of names) {
+ const isDir = href.endsWith('/');
+ entries.push({
+ name: decodeURIComponent(href.replace(/\/$/, '').split('/').pop() || href),
+ type: isDir ? 'dir' : 'file',
+ size: 0,
+ href: href
+ });
+ }
+ } else {
+ // Last resort: match any <a href="...">
+ const lastRegex = /<a href="([^"]+)"/g;
+ while ((match = lastRegex.exec(html)) !== null) {
+ const href = match[1];
+ if (href === '../' || href === '/' || href === './') continue;
+ if (href.startsWith('?')) continue;
+ const isDir = href.endsWith('/');
+ entries.push({
+ name: decodeURIComponent(href.replace(/\/$/, '').split('/').pop() || href),
+ type: isDir ? 'dir' : 'file',
+ size: 0,
+ href: href
+ });
+ }
}
}
return entries;
@@ -529,16 +562,27 @@ class WebDAVModule {
try {
await self._ensureDir('backups');
// Build structured export: root + currentPath + aliases + moduleRegistry
- const exportData = {
- type: 'webx11-backup',
- version: 2,
- savedAt: new Date().toISOString(),
- root: self.terminal.fs.root,
- currentPath: self.terminal.fs.currentPath,
- aliases: self.terminal.moduleManager.aliases || {},
- moduleRegistry: self.terminal.moduleManager.moduleRegistry || []
- };
+ let exportData;
+ try {
+ exportData = {
+ type: 'webx11-backup',
+ version: 2,
+ savedAt: new Date().toISOString(),
+ root: self.terminal.fs.root,
+ currentPath: self.terminal.fs.currentPath,
+ aliases: self.terminal.moduleManager.aliases || {},
+ moduleRegistry: self.terminal.moduleManager.moduleRegistry || []
+ };
+ } catch (e) {
+ self.terminal.print('Failed to read VFS: ' + e.message, 'error');
+ return;
+ }
const serialized = JSON.stringify(exportData, null, 2);
+ // Size check: abort if >5MB
+ if (serialized.length > 5 * 1024 * 1024) {
+ self.terminal.print('Backup too large: ' + self._formatSize(serialized.length) + ' (>5MB limit). Try reducing VFS size first.', 'error');
+ return;
+ }
// Gzip payload
let payload = serialized;
let isGzipped = false;
@@ -550,7 +594,9 @@ class WebDAVModule {
const buf = await resp.arrayBuffer();
payload = new Uint8Array(buf);
isGzipped = true;
- } catch (e) { /* fallback to plain */ }
+ } catch (e) { self.terminal.print('Gzip unavailable, falling back to plain JSON', 'info'); }
+ } else {
+ self.terminal.print('CompressionStream not supported, saving as plain JSON', 'info');
}
// Encrypt if requested
if (encryptPass) {
@@ -671,37 +717,74 @@ class WebDAVModule {
}
};
- // --- webdav-browser: visual modal file browser ---
+ // --- webdav-browser: modern visual file browser ---
this.commands['webdav-browser'] = async (args) => {
const startPath = args[0] || self._browsingPath || '/';
await self.openWebdavBrowser(startPath);
};
- // --- webdav-explorer: interactive file browser via WebDAV ---
- this.commands['webdav-explorer'] = async (args) => {
- const startPath = args[0] || '/';
+ // --- webdav-rm: delete remote file/dir ---
+ this.commands['webdav-rm'] = async (args) => {
+ if (!args[0]) {
+ self.terminal.print('Usage: webdav-rm <remote-path>', 'warning');
+ return;
+ }
try {
- const entries = await self._listDir(startPath);
- self.terminal.print('📁 WebDAV: ' + startPath, 'info');
- if (entries.length === 0) {
- self.terminal.print('(empty)', 'info');
- return;
+ const ok = await self._deleteFile(args[0]);
+ if (ok) {
+ self.terminal.print('Deleted: ' + args[0], 'success');
+ } else {
+ self.terminal.print('Delete failed: resource may not exist', 'error');
}
- entries.forEach(e => {
- const icon = e.type === 'dir' ? '📁' : '📄';
- const size = e.type === 'file' ? ' (' + self._formatSize(e.size) + ')' : '/';
- self.terminal.print(icon + ' ' + e.name + (e.type === 'dir' ? '/' : '') + size);
+ } catch (e) {
+ self.terminal.print('Delete error: ' + e.message, 'error');
+ }
+ };
+
+ // --- webdav-mkdir: create remote directory ---
+ this.commands['webdav-mkdir'] = async (args) => {
+ if (!args[0]) {
+ self.terminal.print('Usage: webdav-mkdir <remote-path>', 'warning');
+ return;
+ }
+ try {
+ const ok = await self._ensureDir(args[0]);
+ if (ok) {
+ self.terminal.print('Created directory: ' + args[0], 'success');
+ } else {
+ self.terminal.print('Failed to create directory', 'error');
+ }
+ } catch (e) {
+ self.terminal.print('Mkdir error: ' + e.message, 'error');
+ }
+ };
+
+ // --- webdav-rename: rename/move remote file or dir (MOVE method) ---
+ this.commands['webdav-rename'] = async (args) => {
+ if (!args[0] || !args[1]) {
+ self.terminal.print('Usage: webdav-rename <old-path> <new-path>', 'warning');
+ self.terminal.print('Renames or moves a file/directory using WebDAV MOVE', 'info');
+ return;
+ }
+ try {
+ const resp = await self._webdavRequest('MOVE', args[0], {
+ headers: { 'Destination': args[1] }
});
- self.terminal.print('---');
- self.terminal.print('↳ Navigate: webdav-explorer <dir> | Pull: webdav-pull <file>', 'text-muted');
- self.terminal.print(entries.length + ' item(s)', 'text-muted');
+ if (resp.ok || resp.status === 201 || resp.status === 204) {
+ self.terminal.print('Renamed: ' + args[0] + ' → ' + args[1], 'success');
+ } else {
+ self.terminal.print('Rename failed: HTTP ' + resp.status, 'error');
+ }
} catch (e) {
- self.terminal.print('WebDAV error: ' + e.message, 'error');
+ self.terminal.print('Rename error: ' + e.message, 'error');
}
};
+
+ // --- webdav-move: alias for webdav-rename ---
+ this.commands['webdav-move'] = this.commands['webdav-rename'];
}
- /* ── Visual WebDAV Browser Modal ── */
+ /* ── Modern WebDAV File-Tree Browser with Bulk Ops ── */
async openWebdavBrowser(path) {
if (!this.config || !this.config.url) {
@@ -710,6 +793,7 @@ class WebDAVModule {
}
this._browsingPath = path;
const self = this;
+ this._selected = {};
// Remove existing modal if any
const existing = document.getElementById('webdav-browser-modal');
@@ -724,6 +808,12 @@ class WebDAVModule {
errorMsg = e.message;
}
+ // Sort: dirs first, then files, alphabetically
+ entries.sort(function(a, b) {
+ if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;
+ return a.name.localeCompare(b.name);
+ });
+
// Build modal
const overlay = document.createElement('div');
overlay.id = 'webdav-browser-modal';
@@ -733,73 +823,237 @@ class WebDAVModule {
const content = document.createElement('div');
content.className = 'modal-content';
- content.style.cssText = 'max-width:650px; max-height:80vh; width:92%;';
+ content.style.cssText = 'max-width:750px; max-height:85vh; width:94%;';
// Header
const header = document.createElement('div');
header.className = 'modal-header';
- header.innerHTML = '<span>📁 WebDAV Browser</span><span style="cursor:pointer" onclick="var m=document.getElementById(\'webdav-browser-modal\');if(m)m.remove();var t=window.webx11;if(t&&t.inputField)t.inputField.focus();">✕</span>';
+ header.innerHTML = '<span>📁 WebDAV File Tree</span>' +
+ '<span style="display:flex;gap:6px;align-items:center">' +
+ '<span id="sel-count" style="font-size:0.8em;color:var(--text-muted)"></span>' +
+ '<span style="cursor:pointer" onclick="var m=document.getElementById(\'webdav-browser-modal\');if(m)m.remove();var t=window.webx11;if(t&&t.inputField)t.inputField.focus();">✕</span></span>';
content.appendChild(header);
// Body
const body = document.createElement('div');
body.className = 'modal-body';
- body.style.cssText = 'padding:8px; overflow-y:auto; flex-grow:1;';
+ body.style.cssText = 'padding:0; overflow-y:auto; flex-grow:1;';
if (errorMsg) {
const errDiv = document.createElement('div');
errDiv.style.cssText = 'color:var(--error-color); padding:16px; text-align:center;';
errDiv.textContent = '❌ ' + errorMsg;
body.appendChild(errDiv);
- } else if (entries.length === 0) {
- const emptyDiv = document.createElement('div');
- emptyDiv.className = 'text-center';
- emptyDiv.style.cssText = 'padding:20px; color:var(--text-muted);';
- emptyDiv.textContent = '(empty) — upload files using the button below';
- body.appendChild(emptyDiv);
} else {
- // Sort: dirs first, then files, alphabetically
- entries.sort(function(a, b) {
- if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;
- return a.name.localeCompare(b.name);
- });
+ // Select-all row
+ const selectAllRow = document.createElement('div');
+ selectAllRow.style.cssText = 'display:flex;align-items:center;padding:6px 10px;border-bottom:1px solid #222;font-size:0.8em;color:var(--text-muted);gap:8px;';
+ const selAllCheck = document.createElement('input');
+ selAllCheck.type = 'checkbox';
+ selAllCheck.style.cssText = 'accent-color:var(--success-color);width:16px;height:16px;cursor:pointer;';
+ selAllCheck.onchange = function() {
+ const checked = this.checked;
+ entries.forEach(function(e) { self._selected[e.name] = checked; });
+ document.querySelectorAll('.wdav-checkbox').forEach(function(c) { c.checked = checked; });
+ self._updateSelectionCount();
+ };
+ selectAllRow.appendChild(selAllCheck);
+ selectAllRow.appendChild(document.createTextNode('Select All (' + entries.length + ' items)'));
+ body.appendChild(selectAllRow);
- var frag = document.createDocumentFragment();
+ // File rows
+ const listContainer = document.createElement('div');
+ let rowIndex = 0;
entries.forEach(function(entry) {
- var item = document.createElement('div');
- item.className = entry.type === 'dir' ? 'file-item dir' : 'file-item';
- item.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding:8px; border-bottom:1px solid #111; cursor:pointer; min-height:36px;';
- item.onmouseover = function() { this.style.background = 'var(--bg-tertiary)'; };
- item.onmouseout = function() { this.style.background = ''; };
+ var row = document.createElement('div');
+ row.className = 'wdav-row';
+ row.style.cssText = 'display:flex;align-items:center;padding:7px 10px;border-bottom:1px solid #1a1a1a;cursor:default;min-height:38px;gap:8px;';
+ row.onmouseover = function() { this.style.background = 'var(--bg-tertiary)'; };
+ row.onmouseout = function() { this.style.background = ''; };
+ row.dataset.index = rowIndex++;
+
+ // Checkbox
+ var cb = document.createElement('input');
+ cb.type = 'checkbox';
+ cb.className = 'wdav-checkbox';
+ cb.style.cssText = 'accent-color:var(--success-color);width:15px;height:15px;cursor:pointer;flex-shrink:0;';
+ cb.onchange = function(e) {
+ self._selected[entry.name] = this.checked;
+ self._updateSelectionCount();
+ e.stopPropagation();
+ };
+ row.appendChild(cb);
+ // Icon
+ var iconSpan = document.createElement('span');
+ iconSpan.textContent = entry.type === 'dir' ? '📁' : '📄';
+ iconSpan.style.cssText = 'flex-shrink:0;font-size:1.1em;';
+
+ // Filename (editable on dblclick)
var nameSpan = document.createElement('span');
- var icon = entry.type === 'dir' ? '📁' : '📄';
- nameSpan.textContent = icon + ' ' + entry.name + (entry.type === 'dir' ? '/' : '');
+ nameSpan.textContent = entry.name + (entry.type === 'dir' ? '/' : '');
+ nameSpan.style.cssText = 'flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:0.9em;cursor:pointer;';
+ nameSpan.title = entry.name;
+ nameSpan.ondblclick = function(e) {
+ e.stopPropagation();
+ var input = document.createElement('input');
+ input.type = 'text';
+ input.value = entry.name;
+ input.style.cssText = 'width:100%;background:#1a1a1a;border:1px solid var(--success-color);color:var(--text-color);padding:2px 6px;border-radius:3px;font-size:0.9em;';
+ input.onblur = function() {
+ var newName = this.value.trim();
+ if (newName && newName !== entry.name) {
+ var parentPath = path.replace(/\/+$/, '') || '';
+ var oldFull = parentPath + '/' + entry.name;
+ var newFull = parentPath + '/' + newName;
+ self._webdavRequest('MOVE', oldFull, { headers: { 'Destination': newFull } })
+ .then(function(r) {
+ if (r.ok || r.status === 201 || r.status === 204) {
+ self.terminal.print('Renamed: ' + entry.name + ' → ' + newName, 'success');
+ self.openWebdavBrowser(path);
+ } else {
+ self.terminal.print('Rename failed: HTTP ' + r.status, 'error');
+ nameSpan.textContent = entry.name;
+ }
+ });
+ } else {
+ nameSpan.textContent = entry.name;
+ }
+ };
+ input.onkeydown = function(ev) {
+ if (ev.key === 'Enter') this.blur();
+ if (ev.key === 'Escape') { nameSpan.textContent = entry.name; }
+ };
+ nameSpan.textContent = '';
+ nameSpan.appendChild(input);
+ input.focus();
+ input.select();
+ };
+ // Click = navigate dir / preview file
+ if (entry.type === 'dir') {
+ row.onclick = function(e) {
+ if (e.target.type === 'checkbox') return;
+ self.openWebdavBrowser(entry.href);
+ };
+ } else {
+ row.onclick = function(e) {
+ if (e.target.type === 'checkbox') return;
+ self.previewWebdavFile(entry);
+ };
+ }
+ // Size
var sizeSpan = document.createElement('span');
- sizeSpan.style.cssText = 'font-size:0.8em; color:var(--text-muted);';
+ sizeSpan.style.cssText = 'font-size:0.75em;color:var(--text-muted);flex-shrink:0;min-width:60px;text-align:right;';
if (entry.type === 'file') {
sizeSpan.textContent = self._formatSize(entry.size);
}
- item.appendChild(nameSpan);
- item.appendChild(sizeSpan);
+ // Context menu on right-click
+ row.oncontextmenu = function(e) {
+ e.preventDefault();
+ self._showContextMenu(e, entry, path);
+ };
- if (entry.type === 'dir') {
- item.onclick = function() { self.openWebdavBrowser(entry.href); };
- } else {
- item.onclick = function() { self.previewWebdavFile(entry); };
- // Right-click or context menu could download — but for simplicity, long tap or regular click previews
- // Double-click to download
- item.ondblclick = function() { self.downloadFromWebdav(entry); };
- }
- frag.appendChild(item);
+ row.appendChild(iconSpan);
+ row.appendChild(nameSpan);
+ row.appendChild(sizeSpan);
+ listContainer.appendChild(row);
});
- body.appendChild(frag);
+ body.appendChild(listContainer);
+
+ // Keyboard navigation
+ body.tabIndex = -1;
+ body.style.outline = 'none';
+ var focusIdx = 0;
+ body.onkeydown = function(e) {
+ var rows = listContainer.querySelectorAll('.wdav-row');
+ if (e.key === 'ArrowDown' || e.key === 'j') {
+ e.preventDefault();
+ focusIdx = Math.min(focusIdx + 1, rows.length - 1);
+ rows[focusIdx].scrollIntoView({ block: 'nearest' });
+ rows.forEach(function(r, i) { r.style.borderLeft = i === focusIdx ? '2px solid var(--success-color)' : ''; });
+ } else if (e.key === 'ArrowUp' || e.key === 'k') {
+ e.preventDefault();
+ focusIdx = Math.max(focusIdx - 1, 0);
+ rows[focusIdx].scrollIntoView({ block: 'nearest' });
+ rows.forEach(function(r, i) { r.style.borderLeft = i === focusIdx ? '2px solid var(--success-color)' : ''; });
+ } else if (e.key === ' ') {
+ e.preventDefault();
+ var cb = rows[focusIdx]?.querySelector('.wdav-checkbox');
+ if (cb) { cb.checked = !cb.checked; cb.onchange({ stopPropagation: function(){} }); }
+ } else if (e.key === 'Enter') {
+ e.preventDefault();
+ rows[focusIdx]?.click();
+ }
+ };
+ setTimeout(function() { body.focus(); }, 100);
}
content.appendChild(body);
+ // Bulk action bar
+ const bulkBar = document.createElement('div');
+ bulkBar.id = 'wdav-bulk-bar';
+ bulkBar.style.cssText = 'display:none;padding:8px 10px;border-top:1px solid var(--success-color);background:var(--bg-tertiary);gap:6px;align-items:center;flex-wrap:wrap;';
+ bulkBar.innerHTML = '<span id="bulk-count" style="font-size:0.85em;color:var(--text-color);flex:1;">0 selected</span>' +
+ '<button class="btn" id="bulk-delete" style="font-size:0.8em;padding:3px 10px;">🗑 Delete</button>' +
+ '<button class="btn" id="bulk-move" style="font-size:0.8em;padding:3px 10px;">📦 Move</button>' +
+ '<button class="btn" id="bulk-download" style="font-size:0.8em;padding:3px 10px;">⬇ Download</button>';
+ self._updateSelectionCount = function() {
+ var count = Object.values(self._selected).filter(Boolean).length;
+ var el = document.getElementById('sel-count');
+ if (el) el.textContent = count > 0 ? count + ' selected' : '';
+ var bar = document.getElementById('wdav-bulk-bar');
+ var cnt = document.getElementById('bulk-count');
+ if (bar) bar.style.display = count > 0 ? 'flex' : 'none';
+ if (cnt) cnt.textContent = count + ' selected';
+ };
+
+ // Wire bulk actions
+ setTimeout(function() {
+ document.getElementById('bulk-delete')?.addEventListener('click', function() {
+ var names = Object.entries(self._selected).filter(function(e) { return e[1]; }).map(function(e) { return e[0]; });
+ if (!names.length || !confirm('Delete ' + names.length + ' item(s) from ' + path + '?')) return;
+ names.forEach(function(name) {
+ var fullPath = (path.replace(/\/+$/, '') || '') + '/' + name;
+ self._deleteFile(fullPath).then(function(ok) {
+ if (ok) self.terminal.print('Deleted: ' + name, 'success');
+ else self.terminal.print('Delete failed: ' + name, 'error');
+ });
+ });
+ setTimeout(function() { self.openWebdavBrowser(path); }, 500);
+ });
+ document.getElementById('bulk-move')?.addEventListener('click', function() {
+ var names = Object.entries(self._selected).filter(function(e) { return e[1]; }).map(function(e) { return e[0]; });
+ if (!names.length) return;
+ var target = prompt('Move ' + names.length + ' item(s) to directory:', '/');
+ if (!target) return;
+ target = target.replace(/\/+$/, '');
+ names.forEach(function(name) {
+ var oldFull = (path.replace(/\/+$/, '') || '') + '/' + name;
+ var newFull = target + '/' + name;
+ self._webdavRequest('MOVE', oldFull, { headers: { 'Destination': newFull } })
+ .then(function(r) {
+ if (r.ok || r.status === 201 || r.status === 204) self.terminal.print('Moved: ' + name, 'success');
+ else self.terminal.print('Move failed: ' + name + ' (HTTP ' + r.status + ')', 'error');
+ });
+ });
+ setTimeout(function() { self.openWebdavBrowser(path); }, 500);
+ });
+ document.getElementById('bulk-download')?.addEventListener('click', function() {
+ var names = Object.entries(self._selected).filter(function(e) { return e[1]; }).map(function(e) { return e[0]; });
+ names.forEach(function(name) {
+ var fullPath = (path.replace(/\/+$/, '') || '') + '/' + name;
+ // Find entry from entries
+ var entry = entries.find(function(e) { return e.name === name; });
+ if (entry && entry.type === 'file') self.downloadFromWebdav(entry);
+ });
+ });
+ }, 50);
+
+ content.appendChild(bulkBar);
+
// Footer with breadcrumb + buttons
const footer = document.createElement('div');
footer.className = 'modal-footer';
@@ -815,17 +1069,30 @@ class WebDAVModule {
for (var i = 0; i < parts.length; i++) {
cumulative += '/' + parts[i];
var seg = parts[i];
+ breadHtml += ' <span style="color:var(--text-muted);font-size:0.7em;">▸</span> ';
breadHtml += '<span style="cursor:pointer;text-decoration:underline;" onclick="var m=document.getElementById(\'webdav-browser-modal\');if(m)m.__nav(\'' + cumulative.replace(/'/g, "\\'") + '/\');return false;">' + seg + '</span>';
- if (i < parts.length - 1) breadHtml += ' ▸ ';
}
breadDiv.innerHTML = breadHtml;
- // Attach nav function to modal element for breadcrumb clicks
overlay.__nav = function(p) { self.openWebdavBrowser(p); };
// Button group
var btnGroup = document.createElement('div');
btnGroup.style.cssText = 'display:flex; gap:4px; flex-shrink:0;';
+ var mkdirBtn = document.createElement('button');
+ mkdirBtn.className = 'btn';
+ mkdirBtn.textContent = '📁+';
+ mkdirBtn.title = 'New Directory';
+ mkdirBtn.onclick = function() {
+ var name = prompt('Directory name:');
+ if (name) {
+ self._ensureDir((path.replace(/\/+$/, '') || '') + '/' + name).then(function(ok) {
+ if (ok) { self.terminal.print('Created: ' + name, 'success'); self.openWebdavBrowser(path); }
+ else self.terminal.print('Failed to create directory', 'error');
+ });
+ }
+ };
+
var uploadBtn = document.createElement('button');
uploadBtn.className = 'btn';
uploadBtn.textContent = '⬆ Upload';
@@ -842,6 +1109,7 @@ class WebDAVModule {
closeBtn.textContent = 'Close';
closeBtn.onclick = function() { self.closeWebdavBrowser(); };
+ btnGroup.appendChild(mkdirBtn);
btnGroup.appendChild(uploadBtn);
btnGroup.appendChild(refreshBtn);
btnGroup.appendChild(closeBtn);
@@ -853,7 +1121,71 @@ class WebDAVModule {
overlay.appendChild(content);
document.body.appendChild(overlay);
- this.terminal.print('📂 Opened WebDAV browser: ' + path, 'info');
+ this.terminal.print('📂 Opened WebDAV file browser: ' + path, 'info');
+ }
+
+ _showContextMenu(e, entry, currentPath) {
+ var existing = document.getElementById('wdav-context-menu');
+ if (existing) existing.remove();
+
+ var menu = document.createElement('div');
+ menu.id = 'wdav-context-menu';
+ menu.style.cssText = 'position:fixed;left:' + e.clientX + 'px;top:' + e.clientY + 'px;background:#111;border:1px solid #333;border-radius:6px;padding:4px 0;z-index:1001;min-width:160px;box-shadow:0 4px 12px rgba(0,0,0,0.5);';
+ menu.onclick = function() { this.remove(); };
+
+ var items = [];
+ if (entry.type === 'file') {
+ items.push({ label: '📄 Preview', fn: function() { this.previewWebdavFile(entry); }.bind(this) });
+ items.push({ label: '⬇ Download', fn: function() { this.downloadFromWebdav(entry); }.bind(this) });
+ items.push({ label: '📋 Copy Path', fn: function() {
+ var full = (currentPath.replace(/\/+$/, '') || '') + '/' + entry.name;
+ navigator.clipboard.writeText(full).then(function() { this.terminal.print('Path copied: ' + full, 'success'); }.bind(this));
+ }.bind(this) });
+ } else {
+ items.push({ label: '📂 Open', fn: function() { this.openWebdavBrowser(entry.href); }.bind(this) });
+ items.push({ label: '📋 Copy Path', fn: function() {
+ var full = (currentPath.replace(/\/+$/, '') || '') + '/' + entry.name + '/';
+ navigator.clipboard.writeText(full).then(function() { this.terminal.print('Path copied: ' + full, 'success'); }.bind(this));
+ }.bind(this) });
+ }
+ items.push({ label: '✏️ Rename', fn: function() {
+ var newName = prompt('Rename "' + entry.name + '" to:');
+ if (newName && newName !== entry.name) {
+ var oldFull = (currentPath.replace(/\/+$/, '') || '') + '/' + entry.name;
+ var newFull = (currentPath.replace(/\/+$/, '') || '') + '/' + newName;
+ this._webdavRequest('MOVE', oldFull, { headers: { 'Destination': newFull } }).then(function(r) {
+ if (r.ok || r.status === 201 || r.status === 204) {
+ this.terminal.print('Renamed: ' + entry.name + ' → ' + newName, 'success');
+ this.openWebdavBrowser(currentPath);
+ } else { this.terminal.print('Rename failed: HTTP ' + r.status, 'error'); }
+ }.bind(this));
+ }
+ }.bind(this) });
+ items.push({ label: '🗑 Delete', fn: function() {
+ if (!confirm('Delete ' + entry.name + '?')) return;
+ var full = (currentPath.replace(/\/+$/, '') || '') + '/' + entry.name;
+ this._deleteFile(full).then(function(ok) {
+ if (ok) { this.terminal.print('Deleted: ' + entry.name, 'success'); this.openWebdavBrowser(currentPath); }
+ else { this.terminal.print('Delete failed', 'error'); }
+ }.bind(this));
+ }.bind(this) });
+
+ items.forEach(function(item) {
+ var div = document.createElement('div');
+ div.textContent = item.label;
+ div.style.cssText = 'padding:6px 14px;cursor:pointer;font-size:0.85em;';
+ div.onmouseover = function() { this.style.background = '#222'; };
+ div.onmouseout = function() { this.style.background = ''; };
+ div.onclick = function(e) { e.stopPropagation(); menu.remove(); item.fn(); };
+ menu.appendChild(div);
+ });
+
+ document.body.appendChild(menu);
+ // Close on click outside
+ var closeMenu = function(ev) {
+ if (!menu.contains(ev.target)) { menu.remove(); document.removeEventListener('click', closeMenu); }
+ };
+ setTimeout(function() { document.addEventListener('click', closeMenu); }, 10);
}
closeWebdavBrowser() {
@@ -949,7 +1281,10 @@ class WebDAVModule {
async downloadFromWebdav(entry) {
try {
- var resp = await this._webdavRequest('GET', entry.href);
+ // Construct path from current browsing path + entry name (avoid autoindex href fragility)
+ var basePath = (this._browsingPath || '/').replace(/\/+$/, '');
+ var fullPath = basePath + '/' + entry.name;
+ var resp = await this._webdavRequest('GET', fullPath);
if (!resp.ok) { this.terminal.print('Download failed: HTTP ' + resp.status, 'error'); return; }
var content = await resp.text();
var blob = new Blob([content], { type: 'application/octet-stream' });
@@ -957,7 +1292,7 @@ class WebDAVModule {
var a = document.createElement('a');
a.href = url;
a.download = entry.name;
- a.style.display = 'none';
+ a.style.cssText = 'display:none;';
document.body.appendChild(a);
a.click();
setTimeout(function() {
diff --git a/newos4_vision.html b/newos4_vision.html
new file mode 100644
index 0000000..7bdb262
--- /dev/null
+++ b/newos4_vision.html
@@ -0,0 +1,176 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>newOS4 | The Cognitive OS Vision</title>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
+ <style>
+ body {
+ margin: 0;
+ padding: 0;
+ background-color: #000;
+ color: #00ffcc;
+ font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+ overflow-x: hidden;
+ }
+ #canvas-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+ }
+ .content {
+ position: relative;
+ z-index: 1;
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 100px 20px;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.7);
+ backdrop-filter: blur(10px);
+ box-shadow: 0 0 50px rgba(0, 255, 204, 0.2);
+ }
+ h1 {
+ font-size: 4rem;
+ text-transform: uppercase;
+ letter-spacing: 10px;
+ margin-bottom: 20px;
+ text-shadow: 0 0 20px #00ffcc;
+ animation: glow 2s ease-in-out infinite alternate;
+ }
+ @keyframes glow {
+ from { text-shadow: 0 0 10px #00ffcc; }
+ to { text-shadow: 0 0 30px #00ffcc, 0 0 10px #fff; }
+ }
+ .section {
+ margin: 60px 0;
+ padding: 30px;
+ border: 1px solid rgba(0, 255, 204, 0.3);
+ border-radius: 15px;
+ background: rgba(0, 20, 20, 0.5);
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ }
+ .section:hover {
+ transform: translateY(-10px) rotateX(5deg);
+ box-shadow: 0 10px 30px rgba(0, 255, 204, 0.4);
+ border-color: #00ffcc;
+ }
+ h2 {
+ font-size: 2rem;
+ color: #fff;
+ margin-bottom: 20px;
+ border-bottom: 2px solid #00ffcc;
+ display: inline-block;
+ padding-bottom: 10px;
+ }
+ p {
+ font-size: 1.2rem;
+ line-height: 1.6;
+ color: #b0fffa;
+ text-align: left;
+ }
+ .roadmap-item {
+ display: flex;
+ justify-content: space-between;
+ margin: 15px 0;
+ padding: 10px;
+ background: rgba(255, 255, 255, 0.05);
+ border-radius: 8px;
+ }
+ .phase {
+ font-weight: bold;
+ color: #00ffcc;
+ min-width: 150px;
+ }
+ .footer {
+ margin-top: 100px;
+ font-size: 0.9rem;
+ opacity: 0.6;
+ letter-spacing: 2px;
+ }
+ </style>
+</head>
+<body>
+ <div id="canvas-container"></div>
+
+ <div class="content">
+ <h1>newOS4</h1>
+ <p style="text-align:center; font-style:italic; margin-bottom:50px;">Architected by Agando | The Evolution of Cognitive Computing</p>
+
+ <div class="section">
+ <h2>The Core Philosophy</h2>
+ <p>newOS4 is a <strong>Cognitive Operating System</strong>. It transcends traditional resource management (CPU/RAM) to manage <strong>Agentic Workflows</strong>. Intelligence is the primary system resource, allowing the OS to reason, adapt, and evolve its own structure in real-time.</p>
+ </div>
+
+ <div class="section">
+ <h2>Architectural Pillars</h2>
+ <p><strong>Hyper-Modular Kernel:</strong> Real-time self-rewriting drivers for task-specific optimization.</p>
+ <p><strong>A2A Protocol:</strong> A standardized neural communication layer for seamless agent negotiation.</p>
+ <p><strong>Neural VFS:</strong> Semantic-based file storage where concepts replace paths.</p>
+ <p><strong>Recursive Self-Optimization:</strong> Integrated feedback loops that auto-generate WPM patches to eliminate system latency.</p>
+ </div>
+
+ <div class="section">
+ <h2>Strategic Roadmap</h2>
+ <div class="roadmap-item">
+ <span class="phase">Phase 1</span>
+ <span>Foundation: WebX11 terminal stability, VFS perfection, and Procedural Memory (Skills).</span>
+ </div>
+ <div class="roadmap-item">
+ <span class="phase">Phase 2 ✅</span>
+ <span>Agentic Shift: Agent orchestration (list, register, leases, orchestrate). Security layer (security-level 0-3, cmd-allow/deny). Debug panel. WebDAV modern browser.</span>
+ </div>
+ <div class="roadmap-item">
+ <span class="phase">Phase 3</span>
+ <span>Cognitive OS: Global World Model, Neural VFS, Recursive self-optimization, Predictive resource allocation.</span>
+ </div>
+ </div>
+
+ <div class="footer">
+ SYSTEM STATUS: ONLINE | ARCHITECT: AGANDO | VERSION: 4.3.0-BETA
+ </div>
+ </div>
+
+ <script>
+ // Three.js 3D Background - Digital Neural Network
+ const scene = new THREE.Scene();
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
+ const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ document.getElementById('canvas-container').appendChild(renderer.domElement);
+
+ // Create a point cloud of "nodes"
+ const geometry = new THREE.BufferGeometry();
+ const vertices = [];
+ for (let i = 0; i < 1000; i++) {
+ vertices.push(THREE.MathUtils.randFloatSpread(2000)); // x
+ vertices.push(THREE.MathUtils.randFloatSpread(2000)); // y
+ vertices.push(THREE.MathUtils.randFloatSpread(2000)); // z
+ }
+ geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
+ const material = new THREE.PointsMaterial({ color: 0x00ffcc, size: 2 });
+ const points = new THREE.Points(geometry, material);
+ scene.add(points);
+
+ camera.position.z = 500;
+
+ function animate() {
+ requestAnimationFrame(animate);
+ points.rotation.x += 0.001;
+ points.rotation.y += 0.002;
+ renderer.render(scene, camera);
+ }
+
+ window.addEventListener('resize', () => {
+ camera.aspect = window.innerWidth / window.innerHeight;
+ camera.updateProjectionMatrix();
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ });
+
+ animate();
+ </script>
+</body>
+</html>
diff --git a/newos4_whitepaper.md b/newos4_whitepaper.md
new file mode 100644
index 0000000..d8dea0e
--- /dev/null
+++ b/newos4_whitepaper.md
@@ -0,0 +1,234 @@
+# newOS4 — The Cognitive Operating System
+
+## Whitepaper v4.3.0-beta
+
+**Author:** Agando
+**Status:** Architecture Draft
+**Last Updated:** 2026-06-02
+
+---
+
+## 1. Abstract
+
+newOS4 is a **Cognitive Operating System** — an agentic, AI-native fabric where intelligence is treated not as an application layer but as the kernel's primary resource. Unlike traditional OSs that manage CPU cycles and memory pages, newOS4 manages **agentic workflows, semantic storage, and recursive self-optimization** as first-class primitives.
+
+The system is built on four pillars:
+
+| Pillar | Function |
+|---|---|
+| **Hyper-Modular Kernel** | Real-time self-rewriting drivers for task-specific optimization |
+| **A2A Protocol** | Standardized neural communication layer for agent negotiation |
+| **Neural VFS** | Semantic-based file storage where concepts replace paths |
+| **Recursive Self-Optimization** | Integrated feedback loops generating WPM patches to eliminate latency |
+
+---
+
+## 2. Motivation & Problem Space
+
+Modern operating systems (Linux, Windows, macOS) were designed for a world where:
+
+- Hardware resources (CPU, RAM, disk) are the binding constraints
+- Software is statically installed and version-pinned
+- The user is the sole intelligent agent at the keyboard
+
+This model breaks under three converging trends:
+
+1. **Agent proliferation** — LLM-based agents now outnumber human operators in production workflows
+2. **Dynamic compute** — Serverless, edge, and ephemeral compute require OS-level agility
+3. **Self-modifying code** — AI systems need to rewrite their own toolchain without reboot cycles
+
+newOS4 addresses all three by making **intelligence the kernel primitive** rather than an application afterthought.
+
+---
+
+## 3. System Architecture
+
+### 3.1 Layered Model
+
+```
+┌─────────────────────────────────────────────────────┐
+│ Cognitive Shell │
+│ (WebX11 Terminal / Agent UI / Graph Dashboard) │
+├─────────────────────────────────────────────────────┤
+│ Agent Orchestration Layer │
+│ (Multi-agent router, sub-agent spawning, leases) │
+├─────────────────────────────────────────────────────┤
+│ A2A Protocol Layer │
+│ (Neural message bus, contract negotiation, RPC) │
+├─────────────────────────────────────────────────────┤
+│ Hyper-Modular Kernel │
+│ (Self-rewriting drivers, syscalls, WPM runtime) │
+├─────────────────────────────────────────────────────┤
+│ Neural VFS + Procedural Memory │
+│ (Semantic paths, skill graphs, fast-context cache) │
+└─────────────────────────────────────────────────────┘
+```
+
+### 3.2 The Trinity of Cognition
+
+newOS4 fuses three cognitive primitives:
+
+- **Perception** — Sensory input via agent sensors, web fetch, file I/O, and human chat
+- **Reasoning** — Contextual inference via LLM backbone (Ollama) + procedural memory (skills)
+- **Action** — Tool execution via sandboxed syscalls, WPM patches, and agent delegation
+
+Each maps to a classic OS concern: Perception = I/O, Reasoning = Scheduler, Action = Execution.
+
+---
+
+## 4. Pillar Deep Dives
+
+### 4.1 Hyper-Modular Kernel
+
+The kernel is **not** a monolithic binary. It is a collection of hot-swappable driver modules loaded and versioned through the **WPM (WebX11 Package Manager)**.
+
+**Properties:**
+- Each driver is an isolated ES module with defined syscall surfaces
+- Drivers can be loaded/unloaded/replaced at runtime
+- A self-rewrite daemon monitors performance telemetry and generates optimized driver variants
+
+**Warm-start guarantee:** The kernel caches the last N stable driver configurations in VFS. On cold boot, the "golden config" loads first, then adaptive drivers hot-patch in under 200ms.
+
+### 4.2 A2A Protocol
+
+Agent-to-Agent (A2A) is a standardized message format and transport layer designed for agent negotiation. See [A2A_protocol_spec.md](A2A_protocol_spec.md) for full specification.
+
+**Core tenets:**
+- No central broker — agents discover each other via VFS registrations
+- Messages are typed (request, response, broadcast, lease)
+- Each message carries a contract schema defining capabilities and constraints
+
+### 4.3 Neural VFS
+
+The Neural Virtual File System replaces hierarchical paths (`/home/user/docs/file.txt`) with semantic addressing (`concept://agentic-workflows/design-patterns/observer`).
+
+**Key innovation:** Path resolution is a two-stage process:
+1. **Semantic index** maps concept tokens to physical blocks
+2. **Context cache** keeps recent semantic lookups hot
+
+See [kernel_api.md](kernel_api.md) for VFS syscall reference.
+
+### 4.4 Recursive Self-Optimization
+
+The optimization loop:
+
+```
+Monitor → Profile → Diagnose → Patch → Test → Promote
+```
+
+- **Monitor:** Watchdog tracks syscall latency, agent response times, cache hit rates
+- **Profile:** Hot-path analysis identifies bottlenecks
+- **Diagnose:** LLM analyzes profile data and proposes WPM patch candidates
+- **Patch:** Patch is loaded into a sandboxed driver slot
+- **Test:** Synthetic workload validates improvement
+- **Promote:** On success, patch replaces production driver. On failure, rollback to golden config.
+
+---
+
+## 5. Roadmap
+
+### Phase 1 — Foundation ✅ COMPLETED
+
+What the whitepaper originally listed as 4 items has grown into 25+ completed features:
+
+**Original whitepaper items:**
+- ✅ WebX11 terminal — Terminal.js stable with Levenshtein fuzzy suggestions, security tiers, session persistence
+- ✅ VFS — virtual-fs.js fully functional: ls, cat, put, rm, upload, download with localStorage backend
+- ✅ Procedural Memory — 16 skill files + index.json, module-skills.js
+- ✅ Hot-reload module pipeline — module-loader.js + module-manager.js for dynamic load/unload
+
+**Built beyond the original scope:**
+- 32 modules (18 core + 14 ext), cleaned up from 42
+- Proxy API module — replaces dead DuckDuckGo/SearXNG/WebFetcher modules with `/api/search`, `/api/fetch`, `/api/stats` endpoints
+- Dynamic Prompt Engine — bare URL auto-fetch+summarize, question auto-search+AI answer
+- Ollama Manager — 89 models detected, supports cloud model routing
+- AI Tool System — function-calling loop with session_terminal tool, full agent workflow (module-aiassist.js)
+- ChatStudio integration — bridges terminal AI to chat UI
+- 9 theme presets — dark, light, amber, cyber, ocean, forest, monochrome, sunset, midnight
+- Help.html — 70KB, 3-tab layered documentation
+- Cheatsheet — printable A4 quick reference
+- Fuzzy suggestions — Levenshtein distance for typo correction
+- WebDAV browser UI — modern file-tree with bulk actions, inline rename, context menu, keyboard shortcuts
+- Voice module — speech and sound support
+- BusyBox — shell compatibility layer
+- Tutorial + Welcome tour — first-run onboarding
+- Ctrl+K quick command cards
+- Cryptogzip — encryption/compression utilities
+- File manager UI — graphical file browser
+- Utilities — calculator, diff, alias, finder, mindmap
+- WPM — WebX11 Package Manager (driver/module lifecycle)
+- Session nesting fix — recursive session bug resolved
+- Debug panel — live memory, events, errors, module health
+- Security layer — security-level 0-3 with command allowlist/denylist
+- Agent orchestration — agent-list, agent-register, lease-list, orchestrate
+- Skill-pack core — 12 skills, auto-load, seed/reload support
+
+### Phase 2 — Agentic Shift 🟡 IN PROGRESS (partial)
+
+**What's already built:**
+- ✅ AI tool-calling loop with 19+ tool definitions (filesystem, search, skills, module management)
+- ✅ session_terminal tool — zero-cost context access for terminal commands
+- ✅ Tool execution pipeline with error tracking and auto-skill creation on repeated failures
+- ✅ Ollama proxy — routes streaming chat and tool calls with cloud model support
+- ✅ Tool failure buffer — auto-flushes to localStorage for cross-session learning
+- ✅ Agent orchestration — agent-list, agent-register, lease-list, orchestrate commands
+- ✅ Agent registration via VFS — registry with name, model, capabilities metadata
+- ✅ Lease system — time-bound contracts with status tracking
+- ✅ Security layer — security-level 0-3, cmd-allow/cmd-deny, destructive action confirmation (120s countdown)
+- ✅ Debug panel — live memory/events/errors/module health monitoring
+- ✅ WebDAV modern browser — file-tree with bulk actions, inline rename, context menu, keyboard shortcuts
+- ✅ Debug panel — tool call visualization with persistent log
+- ✅ Skill-pack core — 12 skills auto-loaded on startup with seed/reload support
+- ✅ Chat cleaned to single /chat toggle overlay
+
+**What's still to build:**
+- Autonomous sub-agent spawning with task-specific roles
+- Agent lifecycle management (birth, sleep, death, reanimation)
+- A2A Agent-to-Agent protocol — standardized message bus for agent negotiation
+- Sandboxed execution contexts for sub-agents
+- Agent health monitoring and restart policies
+- Neural VFS concept:// path resolution
+
+### Phase 3 — Cognitive OS 🔴 NOT STARTED
+
+**On the roadmap:**
+- Global World Model integration — persistent semantic understanding of system state
+- Predictive resource allocation — anticipate agent needs before they arise
+- Cross-session persistent memory graphs — relational memory across all user sessions
+- Neural VFS — semantic path resolution (`concept://` paths) replacing hierarchical filesystem
+- Recursive self-optimization — automated WPM patches based on performance telemetry
+- Self-rewrite daemon — models hot-path bottlenecks and generates optimized driver variants
+- Cognitive shell — unified dashboard for multi-agent activity visualization
+
+**Implementation Plan:** `.hermes/plans/2026-06-02_phase3-cognitive-os.md`
+
+---
+
+## 6. Failure Modes & Risk Mitigation
+
+| Risk | Mitigation |
+|---|---|
+| **WPM loop thrash** | N-version golden config, max 3 patches/sec throttle |
+| **Cold-start latency** | Warm VFS cache + preloaded golden config |
+| **Agent contract deadlock** | Lease TTLs + timeout escalation to human |
+| **Semantic path collision** | Namespace registration + conflict resolution via A2A |
+| **Self-rewrite corruption** | Boot-time integrity check against signed golden config |
+
+---
+
+## 7. Related Work
+
+- **Plan 9** — Distributed, per-process namespaces (inspiration for VFS semantics)
+- **Erlang/OTP** — Actor model, hot code swapping (inspiration for agent lifecycle)
+- **NixOS** — Declarative configuration, rollback (inspiration for golden config model)
+- **Auto-GPT / BabyAGI** — Autonomous agent loops (precursors to recursive self-optimization)
+
+---
+
+## 8. Conclusion
+
+newOS4 is not an application. It is not a framework. It is an operating system designed from first principles for the age of cognitive computing. The architecture is intentionally minimal — four pillars, three phases, one north star: **Intelligence as the OS primitive.**
+
+```
+STATUS: BETA | ARCHITECT: AGANDO | VERSION: 4.3.0
+``` \ No newline at end of file
diff --git a/review-newos4.html b/review-newos4.html
index 53e3ffe..4ce41cc 100644
--- a/review-newos4.html
+++ b/review-newos4.html
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Review: newOS4 v4.2 — WebX11 Terminal</title>
+ <title>Review: newOS4 v4.3 — WebX11 Terminal</title>
<link rel="stylesheet" href="/spaces/assets/css/theme.css">
<style>
:root { --cs-glass: rgba(17,17,17,0.75); --cs-glass-border: rgba(0,255,136,0.1); }
@@ -75,7 +75,7 @@
<body>
<header>
<div class="header-content">
- <span class="logo"><span class="logo-icon">🧩</span> newOS4 v4.2 Review</span>
+ <span class="logo"><span class="logo-icon">🧩</span> newOS4 v4.3 Review</span>
<div style="display:flex;gap:8px;flex-wrap:wrap;">
<a href="/spaces/newos4/help.html">📖 Help →</a>
<a href="/spaces/newos4/main.html">Launch OS →</a>
@@ -85,13 +85,13 @@
<div class="container">
-<h1>newOS4 v4.2</h1>
-<p class="meta">WebX11 Terminal · In-Browser Terminal OS · Reviewed 2026-06-01</p>
+<h1>newOS4 v4.3</h1>
+<p class="meta">WebX11 Terminal · In-Browser Terminal OS · Reviewed 2026-06-02</p>
<div class="summary-box">
- <div class="stat"><div class="value">42</div><div class="label">Module Files</div></div>
- <div class="stat"><div class="value">25+17</div><div class="label">Core + Ext</div></div>
- <div class="stat"><div class="value">17</div><div class="label">Skills</div></div>
+ <div class="stat"><div class="value">32</div><div class="label">Module Files</div></div>
+ <div class="stat"><div class="value">18+14</div><div class="label">Core + Ext</div></div>
+ <div class="stat"><div class="value">12</div><div class="label">Skills</div></div>
<div class="stat"><div class="value">9</div><div class="label">Theme Presets</div></div>
<div class="stat"><div class="value">52KB</div><div class="label">App Size</div></div>
<div class="stat"><div class="value">4/5</div><div class="label">Rating</div></div>
@@ -99,12 +99,12 @@
<section>
<h2>Architecture</h2>
- <p>newOS4 v4.2 is an <strong>in-browser terminal OS</strong> — NOT a chat-centric UI. Single-file <code>main.html</code> (1,031 lines, 52KB) loads 42 module files across two directories:</p>
+ <p>newOS4 v4.3 is an <strong>in-browser terminal OS</strong> — NOT a chat-centric UI. Single-file <code>main.html</code> (1,031 lines, 52KB) loads 32 module files across two directories:</p>
<ul>
- <li><strong>25 core modules</strong> (<code>modules/core/</code>) — Foundation infrastructure (VirtualFileSystem, OllamaManager, SecretVault, ModuleManager, Terminal) + 19 built-in feature modules (system, fs, modmgr, ollama, my, searxng, servermon, ollamamodels, config, simplegui, io, dynamicprompts, aiassist, aiasm, smartctx, duckduckgo, fetcher, skills, chatstudio)</li>
- <li><strong>17 ext modules</strong> (<code>modules/ext/</code>) — Self-registering: alias, busybox, calc, cron, cryptogzip, diff, editor, filemgr, finder, mindmap, shell, skill-pack-core, theme, tutorial, voice, webdav, wpm</li>
+ <li><strong>18 core modules</strong> (<code>modules/core/</code>) — Foundation infrastructure (VirtualFileSystem, OllamaManager, SecretVault, ModuleManager, Terminal) + 13 built-in feature modules (system, fs, modmgr, ollama, my, searxng, servermon, ollamamodels, config, simplegui, io, dynamicprompts, aiassist, aiasm, smartctx, duckduckgo, fetcher, skills, chatstudio, debug)</li>
+ <li><strong>14 ext modules</strong> (<code>modules/ext/</code>) — Self-registering: alias, busybox, calc, cron, cryptogzip, diff, editor, filemgr, finder, mindmap, shell, skill-pack-core, theme, tutorial, voice, webdav, wpm</li>
</ul>
- <p><strong>Total codebase</strong>: ~800KB (main.html + all module files). AI system with 5-turn agentic loop, 19+ tool definitions, 17 skills in VFS, 9 theme presets, and full destructive-action confirmation.</p>
+ <p><strong>Total codebase</strong>: ~500KB (main.html + all module files). AI system with 5-turn agentic loop, 19+ tool definitions, 12 skills in VFS, 9 theme presets, and full destructive-action confirmation.</p>
</section>
<section>
@@ -141,7 +141,8 @@
<h3>📚 Skills System</h3>
<ul>
- <li><strong>17 skills</strong> stored as Markdown with YAML frontmatter in VFS <code>/skills/</code></li>
+ <li><strong>12 skills</strong> stored as Markdown with YAML frontmatter in VFS <code>/skills/</code></li>
+ <li>Skill-pack core auto-loads skills on startup with seed/reload</li>
<li>8 CLI commands: skill-list, skill-view, skill-create, skill-patch, skill-delete, skill-export, skill-import, skill-sync</li>
<li>Skills Manager UI modal (📚 button in quick-actions bar)</li>
<li>Auto-loads relevant skills at start of every AI task</li>
@@ -149,6 +150,29 @@
<li>In-memory index with 2-second debounced flush to VFS</li>
</ul>
+ <h3>🔒 Security Layer</h3>
+ <ul>
+ <li><code>security-level 0-3</code> — 0: unrestricted, 1: confirm destructive, 2: deny sensitive, 3: deny all dangerous commands</li>
+ <li><code>cmd-allow &lt;cmd&gt;</code> / <code>cmd-deny &lt;cmd&gt;</code> — per-command allowlist/denylist overrides</li>
+ <li>Destructive action confirmation bar (non-blocking, 120s countdown with color escalation)</li>
+ <li>AI tool call safety: auto-confirmation for read-only, countdown confirmation for destructive</li>
+ </ul>
+
+ <h3>🔧 Debug Panel</h3>
+ <ul>
+ <li><code>debug</code> toggle — shows memory usage, event listeners, error log, module registration status</li>
+ <li>Real-time module health: loaded count, broken references, cache state</li>
+ <li>Useful for troubleshooting module load failures and VFS corruption</li>
+ </ul>
+
+ <h3>🤖 Agent Orchestration</h3>
+ <ul>
+ <li><code>agent-list</code> — list registered AI agents and their status</li>
+ <li><code>agent-register &lt;name&gt; &lt;model&gt;</code> — register a new AI agent</li>
+ <li><code>lease-list</code> — show active agent leases/tasks</li>
+ <li><code>orchestrate &lt;task&gt;</code> — delegate a multi-step task to the agent orchestrator</li>
+ </ul>
+
<h3>🎤 Voice Command</h3>
<ul>
<li>🎤 button in input area beside Send button</li>
@@ -177,7 +201,7 @@
<li><strong>BusyBox</strong> — 16 utilities: which, env, date, cal, yes, seq, base64, printf, cut, uniq, hostname, whoami, basename, dirname, sleep, expand</li>
<li><strong>CryptoGzip</strong> — AES-256-GCM encrypt/decrypt + gzip/gunzip for VFS files</li>
<li><strong>File Manager</strong> — Fullscreen overlay with 30% sidebar, 70% preview pane, 10+ preview renderers, live search</li>
- <li><strong>WebDAV Sync</strong> — 8 commands + modal browser for cloud sync (config, push, pull, backup, restore, del)</li>
+ <li><strong>WebDAV Sync</strong> — 10 commands + modern file-tree browser with bulk actions (Select All, Delete, Move, Download), inline rename (double-click), right-click context menu, breadcrumb navigation, keyboard shortcuts (j/k, Space, Enter), create-directory button</li>
<li><strong>Mindmap</strong> — ASCII mindmap creation and management in terminal</li>
<li><strong>Text Editor</strong> — inline VFS editing via modal (edit/save/cancel)</li>
<li><strong>Calculator, Cron, Diff, Alias, Finder</strong> — utility modules covering common needs</li>
@@ -212,8 +236,12 @@
<section>
<h2>Pros & Cons</h2>
- <div class="pro"><strong>✅ Self-improving</strong> — AI creates, patches, and manages its own skills. 17 skills in VFS with full CRUD CLI.</div>
- <div class="pro"><strong>✅ Rich module ecosystem</strong> — 42 module files (25 core + 17 ext), 19 Unix commands, search, fetch, shell, webdav, cron, calc, voice, encrypt, theme, mindmap, editor</div>
+ <div class="pro"><strong>✅ Self-improving</strong> — AI creates, patches, and manages its own skills. 12 skills in VFS with skill-pack core auto-load and seed/reload support.</div>
+ <div class="pro"><strong>✅ Rich module ecosystem</strong> — 32 module files (18 core + 14 ext), 19 Unix commands, search, fetch, shell, webdav, cron, calc, voice, encrypt, theme, mindmap, editor</div>
+ <div class="pro"><strong>✅ WebDAV modern browser</strong> — File-tree UI with checkboxes, Select All, bulk Move/Delete/Download, inline rename, context menu, breadcrumbs, keyboard shortcuts</div>
+ <div class="pro"><strong>✅ Security layer</strong> — security-level 0-3, command allowlist/denylist, non-blocking destructive confirmation with 120s countdown</div>
+ <div class="pro"><strong>✅ Debug panel</strong> — Live memory, event, error, and module health monitoring via <code>debug</code> toggle</div>
+ <div class="pro"><strong>✅ Agent orchestration</strong> — Agent registration, lease management, multi-step task delegation</div>
<div class="pro"><strong>✅ Agentic AI</strong> — 5-turn tool calling loop, 19+ tool definitions, streaming responses, destructive action confirmation with countdown</div>
<div class="pro"><strong>✅ 9 Theme Presets</strong> — Dark, light, amber, cyber, ocean, forest, monochrome, sunset, midnight + custom theme creation</div>
<div class="pro"><strong>✅ Auto-save sessions</strong> — Dirty-flag auto-save every 60s, VFS crash survival, context restoration on page reload</div>
diff --git a/skills/agent-orchestration.md b/skills/agent-orchestration.md
new file mode 100644
index 0000000..060ec96
--- /dev/null
+++ b/skills/agent-orchestration.md
@@ -0,0 +1,35 @@
+---
+name: agent-orchestration
+description: How to use the agent registry, leases, and orchestrator for multi-agent workflows
+tags: [agents, orchestration, delegation, leases]
+category: system
+---
+## Steps
+1. **Agent Registry:**
+ - agent-list — list all registered agents (ID, type, capabilities, status)
+ - agent-register <type> <capabilities> — register a new agent (capabilities: comma-separated like "code,research")
+ - agent-unregister <id> — remove an agent
+ - agent-status <id> — detailed status including uptime, task history
+
+2. **Leases (time-bound contracts):**
+ - lease-create <agent-id> <ttl-seconds> — create a lease with watchdog timer
+ - lease-list — show active leases with remaining TTL
+ - lease-revoke <lease-id> — terminate a lease early
+ - lease-renew <lease-id> <ttl-seconds> — extend a lease
+
+3. **Orchestrator (spawn, delegate, kill):**
+ - orchestrator-spawn <type> <capabilities> — spawn a new agent automatically (registers + creates lease)
+ - orchestrator-kill <agent-id> — kill an agent (revokes lease + unregisters)
+ - orchestrate — list all active agents with their orchestrator state
+ - orchestrator-purge — kill all idle/expired agents
+ - orchestrator-status — full system status: active, idle, dead agents
+
+4. **AI tool integration:**
+ - AI tools list_agents, delegate_task, spawn_agent are available in the AI system prompt
+ - The AI can auto-spawn worker agents for sub-tasks
+ - Each agent gets its own VFS workspace at /agents/<agent-id>/
+
+5. **When to use:**
+ - User needs parallel task execution → orchestrator-spawn coder + researcher
+ - Time-bound automation → lease-create with short TTL
+ - System cleanup → orchestrator-purge to kill stale agents \ No newline at end of file
diff --git a/skills/bug-tracker.md b/skills/bug-tracker.md
new file mode 100644
index 0000000..05963e4
--- /dev/null
+++ b/skills/bug-tracker.md
@@ -0,0 +1,30 @@
+---
+name: bug-tracker
+description: A systematic approach to tracking and managing bugs in the VFS.
+tags: [dev, debugging, management, workflow]
+---
+
+# Bug Tracking Workflow
+
+This skill provides a standardized way to track bugs using a JSON-based log file in the root directory.
+
+## 1. Initialize Bug Log
+If `/bugs.json` does not exist, create it with an empty array: `[]`.
+
+## 2. Reporting a Bug
+When a bug is found, append a new entry to `/bugs.json` with the following schema:
+- `id`: Unique incremental integer.
+- `title`: Brief summary of the issue.
+- `description`: Detailed steps to reproduce and expected vs actual behavior.
+- `status`: "open" | "in-progress" | "resolved" | "closed".
+- `severity`: "low" | "medium" | "high" | "critical".
+- `created_at`: Timestamp.
+- `updated_at`: Timestamp.
+
+## 3. Managing Bugs
+- **List Open Bugs**: Filter `/bugs.json` for entries where `status != "closed"`.
+- **Update Status**: Change the `status` and update the `updated_at` timestamp.
+- **Resolve**: Mark as "resolved" and add a `resolution` field explaining the fix.
+
+## 4. Verification
+Once a bug is marked "resolved", run existing tests or manually verify the fix before marking it "closed".
diff --git a/skills/debug-panel-and-logs.md b/skills/debug-panel-and-logs.md
new file mode 100644
index 0000000..b182e23
--- /dev/null
+++ b/skills/debug-panel-and-logs.md
@@ -0,0 +1,34 @@
+---
+name: debug-panel-and-logs
+description: How to use the debug panel, session logging, and terminal diagnostics
+tags: [debug, logging, diagnostics, troubleshooting]
+category: system
+---
+## Steps
+1. **Toggle debug panel:**
+ - debug — opens real-time debug panel showing last AI tool call, response time, and context
+ - Debug panel includes Copy, Export, and Write to VFS buttons
+ - Export: saves tool call log as timestamped JSON to downloads
+ - Write to VFS: appends debug data to /debug.log (dedup by turn ID)
+
+2. **Session logging:**
+ - logs [n] [LEVEL] — view last n log entries (optionally filtered by INFO/WARN/ERROR)
+ - logrotate — rotate current.log to dated archive (auto-cleans old logs beyond 10)
+ - Logs stored in /logs/ directory: current.log + dated archives
+ - Health check runs automatically after complex tasks
+
+3. **Diagnostic commands:**
+ - health-check — full audit: VFS size, modules, logs, trash, skills
+ - check — quick system health including module requirement status
+ - mem — real-time memory usage (also in header)
+ - status — network, files, modules, Ollama connectivity
+
+4. **System journals:**
+ - debug.log — appended by debug panel VFS button (dedup by turn ID)
+ - current.log — system activity log with rotation
+ - Auto-save: terminal state auto-saves every 60s
+
+5. **When to use:**
+ - AI is behaving unexpectedly → debug to see tool calls
+ - User reports errors → logs 50 ERROR to see error entries
+ - Memory concerns → mem to check, health-check for full audit \ No newline at end of file
diff --git a/skills/index.json b/skills/index.json
index 6d57936..a1254ae 100644
--- a/skills/index.json
+++ b/skills/index.json
@@ -1 +1,248 @@
-{"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
+{
+ "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-06-02T13:19:44.542Z",
+ "updated": "2026-06-02T13:19:44.542Z"
+ },
+ "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-06-02T13:19:44.542Z",
+ "updated": "2026-06-02T13:19:44.542Z"
+ },
+ "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-06-02T13:19:44.542Z",
+ "updated": "2026-06-02T13:19:44.542Z"
+ },
+ "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-06-02T13:19:44.542Z",
+ "updated": "2026-06-02T13:19:44.542Z"
+ },
+ "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-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "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-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "mindmap-workflow": {
+ "name": "mindmap-workflow",
+ "description": "How to create, view, edit, and manage brainstorming mindmaps",
+ "tags": [
+ "mindmap",
+ "brainstorming",
+ "planning",
+ "organization"
+ ],
+ "category": "productivity",
+ "created": "2026-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "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-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "agent-orchestration": {
+ "name": "agent-orchestration",
+ "description": "How to use the agent registry, leases, and orchestrator for multi-agent workflows",
+ "tags": [
+ "agents",
+ "orchestration",
+ "delegation",
+ "leases"
+ ],
+ "category": "system",
+ "created": "2026-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "debug-panel-and-logs": {
+ "name": "debug-panel-and-logs",
+ "description": "How to use the debug panel, session logging, and terminal diagnostics",
+ "tags": [
+ "debug",
+ "logging",
+ "diagnostics",
+ "troubleshooting"
+ ],
+ "category": "system",
+ "created": "2026-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "webdav-operations": {
+ "name": "webdav-operations",
+ "description": "How to use WebDAV cloud storage for backup, file sync, and remote file access",
+ "tags": [
+ "webdav",
+ "cloud",
+ "backup",
+ "sync",
+ "storage"
+ ],
+ "category": "system",
+ "created": "2026-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "security-and-safety": {
+ "name": "security-and-safety",
+ "description": "How to use WebX11 security levels, command blocking, and safety features",
+ "tags": [
+ "security",
+ "safety",
+ "blocking",
+ "permissions"
+ ],
+ "category": "system",
+ "created": "2026-06-02T13:19:44.543Z",
+ "updated": "2026-06-02T13:19:44.543Z"
+ },
+ "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-06-02T13:20:28.672Z",
+ "updated": "2026-06-02T13:20:28.672Z"
+ },
+ "bug-tracker": {
+ "name": "bug-tracker",
+ "description": "Systematic workflow for tracking bugs using a JSON log file in the VFS.",
+ "tags": [
+ "dev",
+ "debugging",
+ "management",
+ "workflow"
+ ],
+ "category": "dev",
+ "created": "2026-06-02T10:10:44.447Z",
+ "updated": "2026-06-02T10:10:44.447Z"
+ },
+ "task-manager": {
+ "name": "task-manager",
+ "description": "A systematic workflow for tracking and managing tasks via a VFS JSON store.",
+ "tags": [
+ "productivity",
+ "tasks",
+ "vfs"
+ ],
+ "category": "productivity",
+ "created": "2026-06-02T10:12:44.476Z",
+ "updated": "2026-06-02T10:12:44.476Z"
+ },
+ "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/security-and-safety.md b/skills/security-and-safety.md
new file mode 100644
index 0000000..bd4f23b
--- /dev/null
+++ b/skills/security-and-safety.md
@@ -0,0 +1,37 @@
+---
+name: security-and-safety
+description: How to use WebX11 security levels, command blocking, and safety features
+tags: [security, safety, blocking, permissions]
+category: system
+---
+## Steps
+1. **Security levels:**
+ - security-level <0-3> — set security level:
+ 0 = Permissive (no blocks, no confirms — anything runs)
+ 1 = Standard (unknown cmds → AI route, destructive → confirm, system → block)
+ 2 = Paranoid (unknown cmds blocked entirely, destructive blocked)
+ 3 = Audit (everything allowed, everything logged)
+ - Default: level 1
+ - security — show current level, blocked count, and stats
+
+2. **Command control:**
+ - cmd-allow <cmd> — whitelist a command from security checks
+ - cmd-deny <cmd> — blacklist/block a command entirely
+ - whitelist built-in: help, clear, ls, cat, pwd, whoami, df, free, top, ps, echo, date, env, history
+
+3. **What gets blocked at each level:**
+ - Unknown commands: Level 1 → AI routed, Level 2+ → blocked
+ - Destructive commands (delete, write, save, format, etc.): Level 1 → confirmation, Level 2+ → blocked
+ - System commands (reboot, shutdown, format, kill): Level 1+ → blocked
+ - Suspicious flags (--execute, --eval, --shell): Level 1+ → blocked
+
+4. **Safety checklist:**
+ - Check security: security shows your current level
+ - Before running risky commands: create a checkpoint first
+ - For temporary relax: security-level 0, then restore to 1
+ - For total lockdown before leaving: security-level 2
+
+5. **When to use:**
+ - User wants to lock down the terminal → security-level 2
+ - User wants to allow a blocked command → cmd-allow <cmd>
+ - Debugging strange behavior → verify security-level (user may have set it higher) \ No newline at end of file
diff --git a/skills/task-manager.md b/skills/task-manager.md
new file mode 100644
index 0000000..74c3da1
--- /dev/null
+++ b/skills/task-manager.md
@@ -0,0 +1,37 @@
+---
+name: task-manager
+description: A systematic approach to managing tasks using a JSON-based tracking system in the VFS.
+tags: productivity, management, organization
+---
+
+# Task Management Workflow
+
+## 1. Initialization
+- Check if `/tasks.json` exists. If not, create it with an empty array: `[]`.
+
+## 2. Adding Tasks
+When a new task is identified:
+- **Define**: Task name, priority (Low, Medium, High), status (Todo, In-Progress, Done), and deadline.
+- **Action**: Read `tasks.json`, append the new task object, and write back to the file.
+
+## 3. Daily Planning/Review
+- **List**: Read `tasks.json` and filter for "Todo" or "In-Progress".
+- **Prioritize**: Sort tasks by priority (High > Medium > Low).
+- **Update**: Change status of tasks as they are completed.
+
+## 4. Maintenance
+- **Cleanup**: Archive "Done" tasks to `/tasks_archive.json` periodically to keep the main list lean.
+- **Audit**: Review overdue tasks and update deadlines or priorities.
+
+## Schema Reference
+```json
+{
+ "id": "unique-id",
+ "title": "Task name",
+ "priority": "High|Medium|Low",
+ "status": "Todo|In-Progress|Done",
+ "created_at": "ISO-Date",
+ "deadline": "ISO-Date",
+ "notes": "Additional context"
+}
+``` \ No newline at end of file
diff --git a/skills/webdav-operations.md b/skills/webdav-operations.md
new file mode 100644
index 0000000..098449c
--- /dev/null
+++ b/skills/webdav-operations.md
@@ -0,0 +1,33 @@
+---
+name: webdav-operations
+description: How to use WebDAV cloud storage for backup, file sync, and remote file access
+tags: [webdav, cloud, backup, sync, storage]
+category: system
+---
+## Steps
+1. **Configuration:**
+ - webdav-config — configure WebDAV endpoint URL and credentials
+ - Connection auto-tested on config; webdav-status shows connection health
+ - Uses per-user token stored in .token file on the server side
+
+2. **File operations:**
+ - webdav-ls [path] — list remote directory contents
+ - webdav-push <local-path> <remote-path> — upload file to WebDAV
+ - webdav-pull <remote-path> [local-path] — download file from WebDAV
+ - webdav-explorer — GUI file browser for WebDAV
+ - webdav-browser — CLI file browser for WebDAV
+
+3. **Backup & Restore:**
+ - webdav-backup — push full VFS snapshot to WebDAV (creates /backups/newos4-<date>.json)
+ - webdav-backup-list — list all remote backup snapshots
+ - webdav-restore <filename> — restore VFS from a remote backup snapshot
+
+4. **Status & Diagnostics:**
+ - webdav-status — connection status, last sync, space information
+ - If uploads fail: check webdav-config, ensure .token file is valid
+ - WebDAV runs on the same server (nginx with WebDAV module), no external dependency
+
+5. **When to use:**
+ - Before factory-reset: webdav-backup to store VFS remotely
+ - Cross-browser: webdav-push/pull to move files between instances
+ - User says "cloud backup" or "remote save" → webdav-backup \ No newline at end of file