techprotrade/LuunaOS / scripts /validate-kit.mjs
techprotrade's picture
download
raw
2.98 kB
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const registryPath = path.join(root, "registry", "skills.index.json");
const schemaPath = path.join(root, "schemas", "universal-skill.schema.json");
const readJson = (filePath) => JSON.parse(fs.readFileSync(filePath, "utf8"));
const errors = [];
const warnings = [];
function exists(relativePath) {
return fs.existsSync(path.join(root, relativePath));
}
function validateRegistry() {
const registry = readJson(registryPath);
if (!Array.isArray(registry.skills)) {
errors.push("registry/skills.index.json: `skills` must be an array");
return;
}
const seen = new Set();
for (const entry of registry.skills) {
if (!entry.id) errors.push("registry entry missing `id`");
if (seen.has(entry.id)) errors.push(`duplicate registry id: ${entry.id}`);
seen.add(entry.id);
if (!entry.path) {
errors.push(`${entry.id}: missing path`);
} else if (!exists(entry.path)) {
errors.push(`${entry.id}: path does not exist: ${entry.path}`);
}
}
}
function validateUcaFile(relativePath, schema) {
const data = readJson(path.join(root, relativePath));
for (const field of schema.required || []) {
if (!(field in data)) {
errors.push(`${relativePath}: missing required field: ${field}`);
}
}
const statusEnum = schema.properties?.status?.enum || [];
if (data.status && !statusEnum.includes(data.status)) {
errors.push(`${relativePath}: invalid status: ${data.status}`);
}
const queueEnum = schema.properties?.queue_state?.enum || [];
if (data.queue_state && !queueEnum.includes(data.queue_state)) {
errors.push(`${relativePath}: invalid queue_state: ${data.queue_state}`);
}
if (data.steps && !Array.isArray(data.steps)) {
errors.push(`${relativePath}: steps must be an array`);
}
}
function validateUcaFiles() {
const schema = readJson(schemaPath);
const candidates = [
"skills/create-skill/skill.json",
"skills/luuna-capability-radar/skill.json",
"examples/luuna-capability-radar.example.json",
];
for (const relativePath of candidates) {
if (!exists(relativePath)) {
warnings.push(`skipped missing UCA file: ${relativePath}`);
continue;
}
validateUcaFile(relativePath, schema);
}
}
function validateLegacyNames() {
for (const legacy of ["arhidecture", "capibility-radar", "files"]) {
if (exists(legacy)) errors.push(`legacy folder still exists: ${legacy}`);
}
}
validateRegistry();
validateUcaFiles();
validateLegacyNames();
if (warnings.length) {
console.log("Warnings:");
for (const warning of warnings) console.log(`- ${warning}`);
}
if (errors.length) {
console.error("Validation failed:");
for (const error of errors) console.error(`- ${error}`);
process.exit(1);
}
console.log("SKILLGENERATOR validation OK");

Xet Storage Details

Size:
2.98 kB
·
Xet hash:
ddb6e63b0689290d78b587def9d0952f8667293452bfb48b16495d815bcfea29

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.