Files
maka/scripts/gen-bundled-skill-catalog.mjs
agent-radar 7be535059e
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 19:05:14 +08:00

121 lines
4.2 KiB
JavaScript

#!/usr/bin/env node
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { createHash } from 'node:crypto';
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const repositoryRoot = dirname(dirname(fileURLToPath(import.meta.url)));
const sourcesDir = join(repositoryRoot, 'packages', 'runtime', 'resources', 'bundled-skills');
const outFile = join(
repositoryRoot,
'packages',
'runtime',
'src',
'bundled-skill-catalog.generated.ts',
);
const ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,80}$/;
const LEGACY_CONTENT_SHA256_BY_ID = {
'computer-use': [
'sha256:419088b2f8a0b12061b4811323abc381869ebe8fccbfc8f2bdfc96ff37a1e45b',
'sha256:8e4404349be4e5493fcf13981624ed55198c0670a794fbf88e2bad81ddb79f6c',
],
};
export function readBundledSkillSources(dir = sourcesDir) {
const ids = readdirSync(dir, { withFileTypes: true })
.filter((entry) => entry.isDirectory() && ID_RE.test(entry.name))
.map((entry) => entry.name)
.sort((a, b) => a.localeCompare(b));
const sourceIds = new Set(ids);
const orphanedLegacyIds = Object.keys(LEGACY_CONTENT_SHA256_BY_ID).filter(
(id) => !sourceIds.has(id),
);
if (orphanedLegacyIds.length > 0) {
throw new Error(
`legacy content hashes reference missing bundled skills: ${orphanedLegacyIds.join(', ')}`,
);
}
return ids.map((id) => {
const body = readFileSync(join(dir, id, 'SKILL.md'), 'utf8');
if (!body.startsWith('---')) {
throw new Error(`bundled skill ${id} is missing YAML front-matter`);
}
return {
id,
body,
sourceName: 'maka-bundled',
sourceVersion: '1',
contentSha256: `sha256:${createHash('sha256').update(body).digest('hex')}`,
legacyContentSha256: LEGACY_CONTENT_SHA256_BY_ID[id] ?? [],
};
});
}
export function renderGeneratedModule(skills) {
const entries = skills
.map(
(skill) =>
` { id: ${JSON.stringify(skill.id)}, body: ${JSON.stringify(skill.body)}, sourceName: ${JSON.stringify(skill.sourceName)}, sourceVersion: ${JSON.stringify(skill.sourceVersion)}, contentSha256: ${JSON.stringify(skill.contentSha256)}, legacyContentSha256: ${JSON.stringify(skill.legacyContentSha256)} },`,
)
.join('\n');
return `// @generated by scripts/gen-bundled-skill-catalog.mjs — do not edit by hand.
// Source of truth: packages/runtime/resources/bundled-skills/<id>/SKILL.md
// Regenerate: npm run generate:bundled-skills
export interface BundledSkillSource {
id: string;
body: string;
sourceName: string;
sourceVersion: string;
contentSha256: string;
legacyContentSha256: readonly string[];
}
// biome-ignore format: generated catalog keeps one reviewable source per line.
export const BUNDLED_SKILL_CATALOG: ReadonlyArray<BundledSkillSource> = [
${entries}
];
`;
}
export function expectedBundledSkillCatalog() {
return renderGeneratedModule(readBundledSkillSources());
}
function main() {
const expected = expectedBundledSkillCatalog();
if (process.argv.includes('--check')) {
if (readFileSync(outFile, 'utf8') !== expected) {
throw new Error('Bundled Skill catalog is stale; run npm run generate:bundled-skills');
}
console.log('[gen] bundled Skill catalog is current');
return;
}
writeFileSync(outFile, expected, 'utf8');
console.log(`[gen] wrote ${readBundledSkillSources().length} bundled skills -> ${outFile}`);
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) main();