diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/core/module-loader.js | 2 | ||||
| -rw-r--r-- | modules/core/module-manager.js | 4 | ||||
| -rw-r--r-- | modules/core/module-predictor.js | 3 | ||||
| -rw-r--r-- | modules/core/terminal.js | 8 | ||||
| -rw-r--r-- | modules/ext/skill-pack-core.js | 42 |
5 files changed, 54 insertions, 5 deletions
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js index c5237ad..f4bd20b 100644 --- a/modules/core/module-loader.js +++ b/modules/core/module-loader.js @@ -105,7 +105,7 @@ window.__moduleLoaderReload = reloadWithSelection; -const LATEST_VER = '2026-06-06-v4.5.6'; +const LATEST_VER = '2026-06-06-v4.5.9'; const CACHE = '?v=' + LATEST_VER; const stored = localStorage.getItem('webx11_cache_ver'); if (stored !== LATEST_VER) { diff --git a/modules/core/module-manager.js b/modules/core/module-manager.js index c508778..4f004ee 100644 --- a/modules/core/module-manager.js +++ b/modules/core/module-manager.js @@ -30,7 +30,7 @@ const instance = new ModuleClass(); this.registerModule(instance, url); if (instance.init) { - await instance.init(); + await instance.init(this.terminal); } this.terminal.print(`Module loaded successfully from ${url}`, 'success'); return true; @@ -88,7 +88,7 @@ const instance = new ModuleClass(); this.registerModule(instance, url); if (instance.init) { - instance.init(); + instance.init(this.terminal); } this.terminal.print(`Module loaded from editor: ${instance.constructor.name}`, 'success'); return true; diff --git a/modules/core/module-predictor.js b/modules/core/module-predictor.js index 312325b..3d868ae 100644 --- a/modules/core/module-predictor.js +++ b/modules/core/module-predictor.js @@ -106,6 +106,7 @@ class PredictorModule { hasWeb: /\b(fetch|url|http|web)\b/.test(lower), hasOrchestrate: /\b(orchestrat|delegate|agent)\b/.test(lower), hasModule: /\b(module|edit_module|view_module)\b/.test(lower), + hasSync: /\b(sync|recall|remember|previous session|state sync)\b/.test(lower), complexity: Math.min(task.length / 50, 10), // 0-10 scale keywords: [...new Set(lower.split(/\s+/).filter(w => w.length > 3))].slice(0, 10) }; @@ -128,6 +129,7 @@ class PredictorModule { features.hasWeb === f.hasWeb, features.hasOrchestrate === f.hasOrchestrate, features.hasModule === f.hasModule, + features.hasSync === f.hasSync, ]; score = matches.filter(Boolean).length / matches.length; // Keyword overlap bonus @@ -146,6 +148,7 @@ class PredictorModule { if (features.hasSearch || features.hasWeb) { baseDuration = 25; baseTurns = 5; } if (features.hasWrite) { baseDuration = 20; baseTurns = 4; } if (features.hasOrchestrate) { baseDuration = 40; baseTurns = 8; } + if (features.hasSync) { baseDuration = 30; baseTurns = 6; } if (features.complexity > 5) baseDuration *= 1.5; return { duration: baseDuration, diff --git a/modules/core/terminal.js b/modules/core/terminal.js index be57c05..8f1ad19 100644 --- a/modules/core/terminal.js +++ b/modules/core/terminal.js @@ -2167,8 +2167,12 @@ modifiedAt: new Date().toISOString(), editCount: 1 })); try { - await this.moduleManager.loadModuleFromCode(code, 'blob://_mods/' + mod.name + '.js'); - this.print('✅ Module loaded live from _mods/' + mod.name + '.js', 'success'); + const ok = await this.moduleManager.loadModuleFromCode(code, 'blob://_mods/' + mod.name + '.js'); + if (ok) { + this.print('✅ Module loaded live from _mods/' + mod.name + '.js', 'success'); + } else { + this.print('⚠️ Auto-test failed — edits saved but module not loaded', 'warning'); + } } catch (e) { this.print('⚠️ Auto-test failed: ' + e.message + ' — edits saved but module not loaded', 'error'); } diff --git a/modules/ext/skill-pack-core.js b/modules/ext/skill-pack-core.js index 41844bd..6f7ad4c 100644 --- a/modules/ext/skill-pack-core.js +++ b/modules/ext/skill-pack-core.js @@ -29,6 +29,7 @@ class SkillPackCoreModule { 'skill-export': 'skill-export <name> — Export a skill as JSON', 'skill-import': 'skill-import <json> — Import a skill from JSON string', 'skill-sync': 'skill-sync — Rebuild skills index from /skills/ directory', + 'skill-webdav-sync': 'skill-webdav-sync — Push all skills to WebDAV as JSON files', }; } @@ -487,6 +488,7 @@ class SkillPackCoreModule { this.commands['skill-export'] = (args) => this._cmdSkillExport(args); this.commands['skill-import'] = (args) => this._cmdSkillImport(args); this.commands['skill-sync'] = () => this._cmdSkillSync(); + this.commands['skill-webdav-sync'] = () => this._cmdSkillWebdavSync(); } // ── Skill Commands ── @@ -690,6 +692,46 @@ class SkillPackCoreModule { this.terminal.print(`📚 Skill index rebuilt: ${synced} skills synced`, 'success'); } + async _cmdSkillWebdavSync() { + const fs = this.terminal.fs; + const index = fs.fsReadJSON('/skills/index.json') || {}; + const names = Object.keys(index); + if (names.length === 0) { + this.terminal.print('No skills to sync', 'info'); + return; + } + // Find the webdav module + const webdavMod = this.terminal.moduleManager.modules['WebDAVModule']; + if (!webdavMod || !webdavMod._webdavRequest) { + this.terminal.print('WebDAV module not loaded. Configure webdav first with webdav-config', 'warning'); + return; + } + this.terminal.print(`📤 Syncing ${names.length} skills to WebDAV...`, 'info'); + let ok = 0, fail = 0; + await webdavMod._ensureDir('skills'); + for (const name of names) { + const content = fs.readFile(`/skills/${name}.md`); + if (content === null) { fail++; continue; } + const meta = index[name]; + const exportObj = { ...meta, content }; + const json = JSON.stringify(exportObj, null, 2); + try { + const resp = await webdavMod._webdavRequest('PUT', 'skills/' + name + '.json', { + body: json, + headers: { 'Content-Type': 'application/json' } + }); + if (resp.ok || resp.status === 201 || resp.status === 204) { + ok++; + } else { + fail++; + } + } catch (e) { + fail++; + } + } + this.terminal.print(`📤 Skill WebDAV sync complete: ${ok} pushed, ${fail} failed`, fail > 0 ? 'warning' : 'success'); + } + init() { this.seed(); } |