feat(plugins): merge Skill management into plugins

This commit is contained in:
inman
2026-09-07 18:36:33 +08:00
parent bb8a19eecf
commit ab9f889233
49 changed files with 461 additions and 1218 deletions

View File

@@ -87,7 +87,9 @@ const CODE_OWNED_PLUGIN_SIGNING_KEYS_SOURCE_MARKER = 'makelore.plugin-trust.code
const PI_AI_PROVIDER_PREFIX = 'pi-runtime/node_modules/@earendil-works/pi-ai/dist/providers/';
const PI_AI_PROVIDER_ASAR_PREFIX = 'app.asar/node_modules/@earendil-works/pi-ai/dist/providers/';
export const BUNDLED_CODING_PLUGIN_RESOURCE_ROOT = 'resources/coding-plugins';
export const CORE_CODING_SKILL_RESOURCE_ROOT = 'resources/coding-skills';
// Historical path retained only as an artifact-deny rule. Standalone Skills
// must not exist in either source or packaged resources.
const LEGACY_CODING_SKILL_RESOURCE_ROOT = 'resources/coding-skills';
const SDK_ASSET_PATH_PATTERN = /^skills\/[^/]+\/assets\/.+\.(?:js|ts)$/u;
async function pathExists(path) {
@@ -548,27 +550,6 @@ async function inspectProductRuntime(executable, resourcesDirectory) {
return JSON.parse(stdout.trim());
}
async function packagedSkillIds(resourcesDirectory) {
const root = join(resourcesDirectory, 'resources', 'coding-skills');
if (!await pathExists(root)) throw new Error(`Packaged coding skills are missing: ${root}`);
const entries = await readdir(root, { withFileTypes: true });
const ids = [];
for (const entry of entries) {
if (!entry.isDirectory()) continue;
if (!await pathExists(join(root, entry.name, 'SKILL.md'))) {
throw new Error(`Packaged coding skill has no SKILL.md: ${entry.name}`);
}
ids.push(entry.name);
}
return ids.sort();
}
async function sourceSkillIds(projectRoot) {
const root = join(projectRoot, 'resources', 'coding-skills');
const entries = await readdir(root, { withFileTypes: true });
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
}
export async function verifyBundledCodingPluginResources({
projectRoot,
resourcesDirectory,
@@ -698,13 +679,10 @@ export async function verifyBundledCodingPluginResources({
);
}
const sourceCoreRoot = join(root, CORE_CODING_SKILL_RESOURCE_ROOT);
const packagedCoreRoot = join(resourcesDirectory, CORE_CODING_SKILL_RESOURCE_ROOT);
const coreFiles = await assertMirroredResourceTree(sourceCoreRoot, packagedCoreRoot, 'core coding resources');
const expectedSkills = await sourceSkillIds(root);
const actualSkills = await packagedSkillIds(resourcesDirectory);
if (JSON.stringify(actualSkills) !== JSON.stringify(expectedSkills)) {
throw new Error(`Packaged coding skills differ: expected ${expectedSkills}, got ${actualSkills}`);
const sourceLegacySkillRoot = join(root, LEGACY_CODING_SKILL_RESOURCE_ROOT);
const packagedLegacySkillRoot = join(resourcesDirectory, LEGACY_CODING_SKILL_RESOURCE_ROOT);
if (await pathExists(sourceLegacySkillRoot) || await pathExists(packagedLegacySkillRoot)) {
throw new Error('Standalone coding Skill resources must not be bundled; distribute them through Plugins');
}
return {
root: BUNDLED_CODING_PLUGIN_RESOURCE_ROOT,
@@ -715,9 +693,9 @@ export async function verifyBundledCodingPluginResources({
packagedInAsar: true,
},
coreResources: {
root: CORE_CODING_SKILL_RESOURCE_ROOT,
files: coreFiles,
skills: actualSkills,
root: null,
files: [],
skills: [],
},
result: 'pass',
};