aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-skills.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-06-06 06:00:27 +0200
committerAgando <roduccomm@gmail.com>2026-06-06 06:00:27 +0200
commitccc7d9956559d2195e20345e7a794662b52cd403 (patch)
tree757354fbfec5c75b4577b2cb620d5ab1582e19b1 /modules/core/module-skills.js
parentb538577cd0a4292e4cd4ca1c9f9829fc7e133caa (diff)
auto: 2026-06-06_06:00 changes
Diffstat (limited to 'modules/core/module-skills.js')
-rw-r--r--modules/core/module-skills.js295
1 files changed, 0 insertions, 295 deletions
diff --git a/modules/core/module-skills.js b/modules/core/module-skills.js
deleted file mode 100644
index 9d0adec..0000000
--- a/modules/core/module-skills.js
+++ /dev/null
@@ -1,295 +0,0 @@
-// Extracted from newOS4 index.html — SkillsModule (v4.2 — Self-improving AI)
- class SkillsModule {
- 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',
- 'skill-view': 'skill-view <name> — View the content of a skill',
- 'skill-create': 'skill-create <name> [desc] [category] [tags] — Create a new skill',
- 'skill-patch': 'skill-patch <name> [content...] — Update skill content (no args to view current)',
- 'skill-delete': 'skill-delete <name> — Delete a skill',
- 'skill-export': 'skill-export <name> — Export a skill to WebDAV',
- 'skill-import': 'skill-import <name> — Import a skill from WebDAV',
- 'skill-sync': 'skill-sync — Bidirectional sync all skills with WebDAV',
- };
- }
- ensureSkillsDir() {
- if (this.terminal && this.terminal.fs) {
- const fs = this.terminal.fs;
- // Ensure /skills/ directory exists
- if (!fs.root.content['skills']) {
- fs.root.content['skills'] = { type: 'dir', content: {} };
- fs.saveToStorage();
- }
- }
- }
- registerCommands() {
- this.commands['skill-list'] = () => this.listSkills();
- this.commands['skill-view'] = (args) => this.viewSkill(args);
- this.commands['skill-create'] = (args) => this.createSkill(args);
- this.commands['skill-patch'] = (args) => this.patchSkill(args);
- this.commands['skill-delete'] = (args) => this.deleteSkill(args);
- this.commands['skill-export'] = (args) => this.exportSkill(args);
- this.commands['skill-import'] = (args) => this.importSkill(args);
- this.commands['skill-sync'] = () => this.syncSkills();
- }
- listSkills() {
- this.ensureSkillsDir();
- const index = this._readSkillIndex();
- const names = Object.keys(index);
- if (names.length === 0) {
- this.terminal.print('No skills found.', 'info');
- return;
- }
- this.terminal.print(`=== Skills (${names.length}) ===`, 'info');
- names.forEach(name => {
- const s = index[name];
- const tags = (s.tags || []).join(', ');
- this.terminal.print(`📘 ${name} — ${s.description} [${s.category}] ${tags ? '(' + tags + ')' : ''}`);
- });
- }
- viewSkill(args) {
- const name = (args[0] || '').replace(/\.md$/, '');
- if (!name) {
- this.terminal.print('Usage: skill-view <name>', 'warning');
- return;
- }
- const content = this.terminal.fs.readFile(`/skills/${name}.md`);
- if (!content) {
- this.terminal.print(`Skill '${name}' not found`, 'error');
- return;
- }
- this.terminal.print(`=== ${name} ===`, 'info');
- this.terminal.print(content, 'info');
- }
- createSkill(args) {
- this.ensureSkillsDir();
- const name = args[0];
- if (!name) {
- this.terminal.print('Usage: skill-create <name> [description] [category] [tag1,tag2,...]', 'warning');
- return;
- }
- const description = args[1] || 'No description';
- const category = args[2] || 'general';
- const tags = (args[3] || '').split(',').filter(Boolean);
- const fs = this.terminal.fs;
- 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.writeFile(`/skills/${name}.md`, content);
- const index = this._readSkillIndex();
- index[name] = { name, description, category, tags };
- this._markSkillIndexDirty();
- this.terminal.print(`Skill '${name}' created. Edit its content with skill-patch ${name}`, 'success');
- }
- patchSkill(args) {
- const name = args[0];
- if (!name) {
- this.terminal.print('Usage: skill-patch <name> [content...]', 'warning');
- return;
- }
- const fs = this.terminal.fs;
- const existing = fs.readFile(`/skills/${name}.md`);
- if (!existing) {
- this.terminal.print(`Skill '${name}' not found. Use skill-create first.`, 'error');
- return;
- }
- if (args.length < 2) {
- // No new content — show the skill so user can copy-paste
- this.terminal.print(`=== ${name} (current content) ===`, 'info');
- this.terminal.print(existing, 'info');
- this.terminal.print('---', 'info');
- this.terminal.print('Pass new content as additional arguments: skill-patch <name> <full content>', 'warning');
- return;
- }
- const newContent = args.slice(1).join(' ');
- fs.writeFile(`/skills/${name}.md`, newContent);
- this.terminal.print(`Skill '${name}' patched`, 'success');
- }
- deleteSkill(args) {
- const name = (args[0] || '').replace(/\.md$/, '');
- if (!name) {
- this.terminal.print('Usage: skill-delete <name>', 'warning');
- return;
- }
- const fs = this.terminal.fs;
- if (!fs.readFile(`/skills/${name}.md`)) {
- this.terminal.print(`Skill '${name}' not found`, 'error');
- return;
- }
- fs.writeFile(`/skills/${name}.md`, '');
- const index = this._readSkillIndex();
- delete index[name];
- this._markSkillIndexDirty();
- this.terminal.print(`Skill '${name}' deleted`, 'success');
- }
- getWebDAVModule() {
- return this.terminal && this.terminal.moduleManager.modules['WebDAVModule'];
- }
- async exportSkill(args) {
- const name = (args[0] || '').replace(/\.md$/, '');
- if (!name) {
- this.terminal.print('Usage: skill-export <name>', 'warning');
- return;
- }
- const wd = this.getWebDAVModule();
- if (!wd || !wd.config || !wd.config.url) {
- this.terminal.print('WebDAV not configured. Use webdav-config first.', 'warning');
- return;
- }
- this.ensureSkillsDir();
- const fs = this.terminal.fs;
- const content = fs.readFile(`/skills/${name}.md`);
- if (!content) {
- this.terminal.print(`Skill '${name}' not found in VFS`, 'error');
- return;
- }
- const index = this._readSkillIndex();
- const meta = index[name];
- try {
- // Ensure remote skills dir
- if (typeof wd._ensureDir === 'function') await wd._ensureDir('skills');
- // Push the skill file
- const resp1 = await wd._webdavRequest('PUT', 'skills/' + name + '.md', {
- body: content,
- headers: { 'Content-Type': 'text/markdown' }
- });
- if (!resp1.ok && resp1.status !== 201 && resp1.status !== 204) {
- throw new Error('Upload failed: HTTP ' + resp1.status);
- }
- // Push updated index
- const indexResp = await wd._webdavRequest('PUT', 'skills/index.json', {
- body: JSON.stringify(index, null, 2),
- headers: { 'Content-Type': 'application/json' }
- });
- if (indexResp.ok || indexResp.status === 201 || indexResp.status === 204) {
- this.terminal.print(`Skill '${name}' exported to WebDAV skills/`, 'success');
- }
- } catch (e) {
- this.terminal.print('Export failed: ' + e.message, 'error');
- }
- }
- async importSkill(args) {
- const name = (args[0] || '').replace(/\.md$/, '');
- if (!name) {
- this.terminal.print('Usage: skill-import <name>', 'warning');
- return;
- }
- const wd = this.getWebDAVModule();
- if (!wd || !wd.config || !wd.config.url) {
- this.terminal.print('WebDAV not configured. Use webdav-config first.', 'warning');
- return;
- }
- try {
- const resp = await wd._webdavRequest('GET', 'skills/' + name + '.md');
- if (!resp.ok) throw new Error('HTTP ' + resp.status);
- const content = await resp.text();
- this.ensureSkillsDir();
- const fs = this.terminal.fs;
- 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 {
- const indexResp = await wd._webdavRequest('GET', 'skills/index.json');
- if (indexResp.ok) {
- const remoteIndex = JSON.parse(await indexResp.text());
- if (remoteIndex && remoteIndex[name]) {
- meta = remoteIndex[name];
- }
- }
- } catch (e) { /* use default meta */ }
- const index = this._readSkillIndex();
- index[name] = meta;
- this._markSkillIndexDirty();
- this.terminal.print(`Skill '${name}' imported from WebDAV (${content.length} bytes)`, 'success');
- } catch (e) {
- this.terminal.print('Import failed: ' + e.message, 'error');
- }
- }
- async syncSkills() {
- const wd = this.getWebDAVModule();
- if (!wd || !wd.config || !wd.config.url) {
- this.terminal.print('WebDAV not configured. Use webdav-config first.', 'warning');
- return;
- }
- this.ensureSkillsDir();
- const fs = this.terminal.fs;
- const localIndex = this._readSkillIndex();
- const localNames = new Set(Object.keys(localIndex));
- this.terminal.print('Syncing skills with WebDAV...', 'info');
- let imported = 0, exported = 0;
- try {
- // Try to get remote index
- let remoteIndex = {};
- try {
- const resp = await wd._webdavRequest('GET', 'skills/index.json');
- if (resp.ok) {
- remoteIndex = JSON.parse(await resp.text()) || {};
- }
- } catch (e) { /* no remote index yet */ }
- const remoteNames = new Set(Object.keys(remoteIndex));
- // Export local-only skills to remote
- for (const name of localNames) {
- if (!remoteNames.has(name)) {
- const content = fs.readFile(`/skills/${name}.md`);
- if (content) {
- await wd._ensureDir('skills');
- await wd._webdavRequest('PUT', 'skills/' + name + '.md', {
- body: content,
- headers: { 'Content-Type': 'text/markdown' }
- });
- exported++;
- }
- }
- }
- // Import remote-only skills to local
- for (const name of remoteNames) {
- if (!localNames.has(name)) {
- const resp = await wd._webdavRequest('GET', 'skills/' + name + '.md');
- if (resp.ok) {
- const content = await resp.text();
- fs.writeFile(`/skills/${name}.md`, content);
- localIndex[name] = remoteIndex[name];
- imported++;
- }
- }
- }
- // Push updated local index back to remote
- this._markSkillIndexDirty();
- await wd._ensureDir('skills');
- await wd._webdavRequest('PUT', 'skills/index.json', {
- body: JSON.stringify(localIndex, null, 2),
- headers: { 'Content-Type': 'application/json' }
- });
- this.terminal.print(`Sync complete: ${exported} exported, ${imported} imported`, 'success');
- } catch (e) {
- this.terminal.print('Sync failed: ' + e.message, 'error');
- }
- }
- }