aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-skills.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/core/module-skills.js')
-rw-r--r--modules/core/module-skills.js68
1 files changed, 46 insertions, 22 deletions
diff --git a/modules/core/module-skills.js b/modules/core/module-skills.js
index ed6e14f..9d0adec 100644
--- a/modules/core/module-skills.js
+++ b/modules/core/module-skills.js
@@ -1,6 +1,30 @@
// Extracted from newOS4 index.html — SkillsModule (v4.2 — Self-improving AI)
class SkillsModule {
- constructor() { this.commands = {}; this.terminal = null; }
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this._skillIndexCache = null;
+ this._skillIndexDirty = false;
+ this._skillIndexFlushTimer = null;
+ }
+ _readSkillIndex() {
+ if (this._skillIndexCache !== null) return this._skillIndexCache;
+ const fs = this.terminal.fs;
+ this._skillIndexCache = fs.fsReadJSON('/skills/index.json') || {};
+ return this._skillIndexCache;
+ }
+ _markSkillIndexDirty() {
+ this._skillIndexDirty = true;
+ if (this._skillIndexFlushTimer) clearTimeout(this._skillIndexFlushTimer);
+ this._skillIndexFlushTimer = setTimeout(() => this._flushSkillIndex(), 2000);
+ }
+ _flushSkillIndex() {
+ if (!this._skillIndexDirty || this._skillIndexCache === null) return;
+ const fs = this.terminal.fs;
+ fs.fsWriteJSON('/skills/index.json', this._skillIndexCache);
+ this._skillIndexDirty = false;
+ this._skillIndexFlushTimer = null;
+ }
getHelpInfo() {
return {
'skill-list': 'skill-list — List all installed skills',
@@ -35,7 +59,7 @@
}
listSkills() {
this.ensureSkillsDir();
- const index = this.terminal.fs.fsReadJSON('/skills/index.json') || {};
+ const index = this._readSkillIndex();
const names = Object.keys(index);
if (names.length === 0) {
this.terminal.print('No skills found.', 'info');
@@ -54,7 +78,7 @@
this.terminal.print('Usage: skill-view <name>', 'warning');
return;
}
- const content = this.terminal.fs.fsRead(`/skills/${name}.md`);
+ const content = this.terminal.fs.readFile(`/skills/${name}.md`);
if (!content) {
this.terminal.print(`Skill '${name}' not found`, 'error');
return;
@@ -73,15 +97,15 @@
const category = args[2] || 'general';
const tags = (args[3] || '').split(',').filter(Boolean);
const fs = this.terminal.fs;
- if (fs.fsRead(`/skills/${name}.md`)) {
+ if (fs.readFile(`/skills/${name}.md`)) {
this.terminal.print(`Skill '${name}' already exists. Use skill-patch to modify it.`, 'warning');
return;
}
const content = '---\nname: ' + name + '\ndescription: ' + description + '\ntags: [' + tags.join(', ') + ']\ncategory: ' + category + '\n---\n## Steps\n1. (to be filled)\n';
- fs.fsWrite(`/skills/${name}.md`, content);
- const index = fs.fsReadJSON('/skills/index.json') || {};
+ fs.writeFile(`/skills/${name}.md`, content);
+ const index = this._readSkillIndex();
index[name] = { name, description, category, tags };
- fs.fsWriteJSON('/skills/index.json', index);
+ this._markSkillIndexDirty();
this.terminal.print(`Skill '${name}' created. Edit its content with skill-patch ${name}`, 'success');
}
patchSkill(args) {
@@ -91,7 +115,7 @@
return;
}
const fs = this.terminal.fs;
- const existing = fs.fsRead(`/skills/${name}.md`);
+ const existing = fs.readFile(`/skills/${name}.md`);
if (!existing) {
this.terminal.print(`Skill '${name}' not found. Use skill-create first.`, 'error');
return;
@@ -105,7 +129,7 @@
return;
}
const newContent = args.slice(1).join(' ');
- fs.fsWrite(`/skills/${name}.md`, newContent);
+ fs.writeFile(`/skills/${name}.md`, newContent);
this.terminal.print(`Skill '${name}' patched`, 'success');
}
deleteSkill(args) {
@@ -115,14 +139,14 @@
return;
}
const fs = this.terminal.fs;
- if (!fs.fsRead(`/skills/${name}.md`)) {
+ if (!fs.readFile(`/skills/${name}.md`)) {
this.terminal.print(`Skill '${name}' not found`, 'error');
return;
}
- fs.fsWrite(`/skills/${name}.md`, '');
- const index = fs.fsReadJSON('/skills/index.json') || {};
+ fs.writeFile(`/skills/${name}.md`, '');
+ const index = this._readSkillIndex();
delete index[name];
- fs.fsWriteJSON('/skills/index.json', index);
+ this._markSkillIndexDirty();
this.terminal.print(`Skill '${name}' deleted`, 'success');
}
getWebDAVModule() {
@@ -141,12 +165,12 @@
}
this.ensureSkillsDir();
const fs = this.terminal.fs;
- const content = fs.fsRead(`/skills/${name}.md`);
+ const content = fs.readFile(`/skills/${name}.md`);
if (!content) {
this.terminal.print(`Skill '${name}' not found in VFS`, 'error');
return;
}
- const index = fs.fsReadJSON('/skills/index.json') || {};
+ const index = this._readSkillIndex();
const meta = index[name];
try {
// Ensure remote skills dir
@@ -188,7 +212,7 @@
const content = await resp.text();
this.ensureSkillsDir();
const fs = this.terminal.fs;
- fs.fsWrite(`/skills/${name}.md`, content);
+ fs.writeFile(`/skills/${name}.md`, content);
// Try to pull the index to get metadata; if fails, create minimal entry
let meta = { name, description: 'Imported from WebDAV', category: 'general', tags: [] };
try {
@@ -200,9 +224,9 @@
}
}
} catch (e) { /* use default meta */ }
- const index = fs.fsReadJSON('/skills/index.json') || {};
+ const index = this._readSkillIndex();
index[name] = meta;
- fs.fsWriteJSON('/skills/index.json', index);
+ this._markSkillIndexDirty();
this.terminal.print(`Skill '${name}' imported from WebDAV (${content.length} bytes)`, 'success');
} catch (e) {
this.terminal.print('Import failed: ' + e.message, 'error');
@@ -216,7 +240,7 @@
}
this.ensureSkillsDir();
const fs = this.terminal.fs;
- const localIndex = fs.fsReadJSON('/skills/index.json') || {};
+ const localIndex = this._readSkillIndex();
const localNames = new Set(Object.keys(localIndex));
this.terminal.print('Syncing skills with WebDAV...', 'info');
let imported = 0, exported = 0;
@@ -233,7 +257,7 @@
// Export local-only skills to remote
for (const name of localNames) {
if (!remoteNames.has(name)) {
- const content = fs.fsRead(`/skills/${name}.md`);
+ const content = fs.readFile(`/skills/${name}.md`);
if (content) {
await wd._ensureDir('skills');
await wd._webdavRequest('PUT', 'skills/' + name + '.md', {
@@ -250,14 +274,14 @@
const resp = await wd._webdavRequest('GET', 'skills/' + name + '.md');
if (resp.ok) {
const content = await resp.text();
- fs.fsWrite(`/skills/${name}.md`, content);
+ fs.writeFile(`/skills/${name}.md`, content);
localIndex[name] = remoteIndex[name];
imported++;
}
}
}
// Push updated local index back to remote
- fs.fsWriteJSON('/skills/index.json', localIndex);
+ this._markSkillIndexDirty();
await wd._ensureDir('skills');
await wd._webdavRequest('PUT', 'skills/index.json', {
body: JSON.stringify(localIndex, null, 2),