Use compact MCP input advertisements by default while preserving explicit full, canonical validation, output contracts and complete Evidence. Require an explicit selected catalog for runtime identity and honor both profiles in CLI status. Real ripgrep/Zellij SDK tasks, independent ELF oracle, actual client trials, profile parity workflows and CI are recorded in experiments/analysis-efficiency/mcp-input-catalog.md. SDK token estimates improve; actual Codex token savings and general latency/memory gains are not established. Refs #5861 BREAKING CHANGE: MCP input advertisements default to compact. Set REA_MCP_INPUT_SCHEMA_PROFILE=full for complete advertised guidance and nested constraints.
88 lines
3.2 KiB
JavaScript
88 lines
3.2 KiB
JavaScript
import { mkdir, readFile, readdir, rm } from "node:fs/promises";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
import { ensureGeneratedFile } from "./lib/generated-file.mjs";
|
|
|
|
const arguments_ = new Set(process.argv.slice(2));
|
|
for (const argument of arguments_)
|
|
if (argument !== "--check")
|
|
throw new Error(`Unknown skill metadata option: ${argument}`);
|
|
|
|
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const sourceRoot = join(root, ".agents/skills/reverse-engineer-anything");
|
|
const outputRoot = join(root, "skills/reverse-engineer-anything");
|
|
const check = arguments_.has("--check");
|
|
const current = (
|
|
await readFile(join(sourceRoot, "SKILL.md"), "utf8")
|
|
).replaceAll("\r\n", "\n");
|
|
const cacheBust = String(Date.now());
|
|
const { FULL_CATALOG_IDENTITY } = await import(
|
|
`${pathToFileURL(join(root, "dist/catalogIdentity.js")).href}?${cacheBust}`
|
|
);
|
|
const { PRODUCT_IDENTITY } = await import(
|
|
`${pathToFileURL(join(root, "dist/identity.js")).href}?${cacheBust}`
|
|
);
|
|
if (/^\s{2}(?:tool_count|catalog_digest):/mu.test(current))
|
|
throw new Error(
|
|
"Catalog metadata belongs in the generated skill, not the authored source",
|
|
);
|
|
const versionLine = /^ {2}version: "[^"\r\n]+"$/mu;
|
|
if (!versionLine.test(current))
|
|
throw new Error("Missing authored skill version");
|
|
// A shipped skill must run the version it ships with, not whatever `@latest` resolves to.
|
|
const latestSpecifier = PRODUCT_IDENTITY.packageSpecifier;
|
|
const pinnedSpecifier = PRODUCT_IDENTITY.registrationPackageSpecifier;
|
|
const source = current
|
|
.replace(
|
|
versionLine,
|
|
`$&\n tool_count: ${String(FULL_CATALOG_IDENTITY.counts.mcp_tools)}`,
|
|
)
|
|
.replaceAll(latestSpecifier, pinnedSpecifier);
|
|
const paths = await filePaths(sourceRoot);
|
|
// Rebuild this owned output directory so removed references cannot survive a build.
|
|
if (!check) await rm(outputRoot, { recursive: true, force: true });
|
|
for (const relativePath of paths) {
|
|
const path = join(outputRoot, relativePath);
|
|
if (!check) await mkdir(dirname(path), { recursive: true });
|
|
await ensureGeneratedFile({
|
|
path,
|
|
source:
|
|
relativePath === "SKILL.md"
|
|
? source
|
|
: (await readFile(join(sourceRoot, relativePath), "utf8")).replaceAll(
|
|
"\r\n",
|
|
"\n",
|
|
),
|
|
check,
|
|
generateCommand: "npm run docs:generate",
|
|
});
|
|
}
|
|
if (
|
|
check &&
|
|
JSON.stringify(await filePaths(outputRoot)) !== JSON.stringify(paths)
|
|
)
|
|
throw new Error(
|
|
"Generated skill file inventory drifted; run npm run docs:generate",
|
|
);
|
|
|
|
async function filePaths(directory, prefix = "") {
|
|
const paths = [];
|
|
for (const entry of (await readdir(directory, { withFileTypes: true })).sort(
|
|
(left, right) =>
|
|
left.name < right.name ? -1 : left.name > right.name ? 1 : 0,
|
|
)) {
|
|
const relativePath = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
if (entry.isDirectory())
|
|
paths.push(
|
|
...(await filePaths(join(directory, entry.name), relativePath)),
|
|
);
|
|
else if (entry.isFile()) paths.push(relativePath);
|
|
else
|
|
throw new Error(
|
|
`Skill bundle requires regular files or directories: ${relativePath}`,
|
|
);
|
|
}
|
|
return paths;
|
|
}
|