Ctrl K
ComunidadGuías…

lib/clay-skill-storage.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var fs = require('fs');
var path = require('path');
var crypto = require('crypto');

function isClaySkill(name) { return /^clay-[a-z0-9_-]+$/i.test(name); }
function privateRoot(base) { return path.join(base, '.clay', 'skills'); }
function stat(file) { try { return fs.lstatSync(file); } catch (e) { if (e.code === 'ENOENT') return null; throw e; } }
function directory(dir) {
  var parent = path.dirname(dir);
  if (parent !== dir && (!stat(parent) || path.basename(parent) === ".clay")) directory(parent);
  var info = stat(dir);
  if (info && (!info.isDirectory() || info.isSymbolicLink())) throw new Error('Clay skill directory must not be a symlink: ' + dir);
  if (!info) fs.mkdirSync(dir, { mode: 0o700 });
}
// Snapshot links before moving targets so aliases can be removed without losing their contents.
function migrate(roots) {
  var entries = [];
  roots.forEach(function (root) {
    var names;
    try { names = fs.readdirSync(root.path); } catch (e) { if (e.code === 'ENOENT') return; throw e; }
    names.filter(isClaySkill).forEach(function (name) {
      var source = path.join(root.path, name);
      var info = stat(source);
      if (!info || (!info.isDirectory() && !info.isSymbolicLink())) return;
      var resolved;
      try { resolved = fs.realpathSync(source); } catch (e) { return; }
      if (!fs.existsSync(path.join(resolved, 'SKILL.md'))) return;
      entries.push({ source: source, resolved: resolved, name: name, base: root.base, link: info.isSymbolicLink() });
    });
  });
  entries.reverse();
  // Copy everything successfully before removing any publicly discoverable entry.
  entries.forEach(function (entry) {
    var dest = path.join(privateRoot(entry.base), entry.name);
    directory(privateRoot(entry.base));
    if (stat(dest)) {
      var backup = path.join(entry.base, '.clay', 'skill-backups'); directory(backup);
      dest = path.join(backup, entry.name + '-' + crypto.randomBytes(8).toString('hex'));
    }
    fs.cpSync(entry.resolved, dest, { recursive: true, dereference: true, errorOnExist: true, force: false });
  });
  entries.forEach(function (entry) {
    if (entry.link) fs.unlinkSync(entry.source);
    else fs.rmSync(entry.source, { recursive: true });
  });
  return entries.length;
}
module.exports = { isClaySkill: isClaySkill, privateRoot: privateRoot, migrate: migrate, directory: directory };
if (require.main === module) migrate(JSON.parse(process.argv[2]));