feat(plugins): merge Skill management into plugins

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

No files matched your search

+27 -13
View File
@@ -62,7 +62,7 @@ async function fixtureRoot(): Promise<{
}
describe('Pi managed resource loader', () => {
it('materializes only managed prompt and explicitly selected bundled skills', async () => {
it('materializes only managed prompt and explicitly paired package Skills', async () => {
const fixture = await fixtureRoot();
const prompt = 'PRIVATE PARTNER PROMPT CONTENT';
const effectiveSnapshot: EffectivePluginSnapshot = {
@@ -70,7 +70,9 @@ describe('Pi managed resource loader', () => {
projectId: 'project-1',
pluginReleaseIds: ['release-a'],
effectiveSkillIds: ['grilling'],
skillEntries: [{ id: 'grilling', entryPath: 'grilling/SKILL.md' }],
skillEntries: [{
id: 'grilling', entryPath: 'grilling/SKILL.md', packageRoot: fixture.skillsDir,
}],
toolDefinitions: [],
runtimePolicies: [],
unavailableReasons: [],
@@ -81,8 +83,8 @@ describe('Pi managed resource loader', () => {
agentId: 'agent-1',
prompt,
skillEntries: [
{ id: 'grilling', entryPath: 'grilling/SKILL.md' },
{ id: 'grilling', entryPath: 'grilling/SKILL.md' },
{ id: 'grilling', entryPath: 'grilling/SKILL.md', packageRoot: fixture.skillsDir },
{ id: 'grilling', entryPath: 'grilling/SKILL.md', packageRoot: fixture.skillsDir },
],
catalogRevision: 11,
bundledSkillsDir: fixture.skillsDir,
@@ -96,7 +98,7 @@ describe('Pi managed resource loader', () => {
expect(MAKELORE_DEFAULT_LANGUAGE_PROMPT).toContain('可见的思考过程');
expect(resources.skillIds).toEqual(['grilling']);
expect(resources.skillEntries).toEqual([
{ id: 'grilling', entryPath: 'grilling/SKILL.md' },
{ id: 'grilling', entryPath: 'grilling/SKILL.md', packageRoot: fixture.skillsDir },
]);
expect(resources.catalogRevision).toBe(11);
expect(resources.skillPaths).toEqual([path.join(fixture.skillsDir, 'grilling', 'SKILL.md')]);
@@ -109,7 +111,9 @@ describe('Pi managed resource loader', () => {
promptFile: 'agent-1.md',
languagePromptFile: 'agent-1.language.md',
skillIds: ['grilling'],
skillEntries: [{ id: 'grilling', entryPath: 'grilling/SKILL.md' }],
skillEntries: [{
id: 'grilling', entryPath: 'grilling/SKILL.md', packageRoot: fixture.skillsDir,
}],
catalogRevision: 11,
effectivePluginSnapshot: effectiveSnapshot,
revision: { provider: 3, resources: 7 },
@@ -129,7 +133,9 @@ describe('Pi managed resource loader', () => {
projectId: 'project-1',
agentId: 'agent-1',
prompt,
skillEntries: [{ id: 'agent-browser', entryPath: 'agent-browser/SKILL.md' }],
skillEntries: [{
id: 'agent-browser', entryPath: 'agent-browser/SKILL.md', packageRoot: fixture.skillsDir,
}],
catalogRevision: 12,
bundledSkillsDir: fixture.skillsDir,
revision: { provider: 1, resources: 1 },
@@ -183,6 +189,14 @@ describe('Pi managed resource loader', () => {
expect(resources.catalogRevision).toBe(13);
});
it('never resolves a Skill from the retired standalone resource root', async () => {
const fixture = await fixtureRoot();
await expect(resolveExplicitCodingSkillPaths(fixture.skillsDir, [
{ id: 'grilling', entryPath: 'grilling/SKILL.md' },
])).rejects.toThrow('Plugin Skill entry is not a file');
});
it('keeps each effective Skill paired with its verified package root when relative paths collide', async () => {
const fixture = await fixtureRoot();
const firstRoot = path.join(fixture.root, 'packages', 'first');
@@ -210,7 +224,7 @@ describe('Pi managed resource loader', () => {
await expect(readFile(resolved.skillPaths[1]!, 'utf8')).resolves.toBe('second package');
});
it('filters a known disabled plugin Skill for the next worker and restores it after re-enable', async () => {
it('ignores a legacy standalone assignment and restores a disabled plugin Skill after re-enable', async () => {
const fixture = await fixtureRoot();
const assignedSkillIds = ['grilling', 'data-service'];
let enabled = true;
@@ -260,13 +274,13 @@ describe('Pi managed resource loader', () => {
});
const first = await resolve();
expect(first.effectiveSkillIds).toEqual(assignedSkillIds);
expect(first.effectiveSkillIds).toEqual(['data-service']);
expect(first.tools).toHaveLength(10);
enabled = false;
const disabled = await resolve();
expect(assignedSkillIds).toEqual(['grilling', 'data-service']);
expect(disabled.effectiveSkillIds).toEqual(['grilling']);
expect(disabled.effectiveSkillIds).toEqual([]);
expect(disabled.tools).toEqual([]);
await expect(materializePiAgentResources({
userDataDir: fixture.userDataDir,
@@ -277,11 +291,11 @@ describe('Pi managed resource loader', () => {
catalogRevision: disabled.catalogRevision,
bundledSkillsDir: fixture.skillsDir,
revision: { provider: 1, resources: 2 },
})).resolves.toMatchObject({ skillIds: ['grilling'], catalogRevision: 17 });
})).resolves.toMatchObject({ skillIds: [], catalogRevision: 17 });
enabled = true;
const restored = await resolve();
expect(restored.effectiveSkillIds).toEqual(assignedSkillIds);
expect(restored.effectiveSkillIds).toEqual(['data-service']);
expect(restored.tools).toHaveLength(10);
});
@@ -307,7 +321,7 @@ describe('Pi managed resource loader', () => {
const fixture = await fixtureRoot();
await expect(resolveExplicitCodingSkillPaths(fixture.skillsDir, [
{ id: 'not-bundled', entryPath: 'not-bundled/SKILL.md' },
])).rejects.toThrow('Bundled coding Skill entry is not a file');
])).rejects.toThrow('Plugin Skill entry is not a file');
await expect(materializePiAgentResources({
userDataDir: fixture.userDataDir,
projectId: '../outside',