feat(cli): dispatch du callback plugin slash-command vers le runtime registry — #166 (QA verte)
Boucle le gap end-to-end de #165 : à l'exécution d'une commande slash plugin depuis le composer custom, l'UI traite l'effet pluginCallback et le dispatche au PluginRuntimeRegistry pour que la callback du plugin s'exécute réellement. - runtime/registry: runCommandStrict (échec explicite si handler absent) + propagation de la valeur de retour ; élargit les types de retour (unknown). - runtime/loader: chargement de contributes.slashCommands au registre + propagation du retour du handler. - features/plugins/usePluginMenus: runCommand retourne unknown. - features/agents/CustomAgentChatView: handler de l'effet pluginCallback -> pluginRuntime.registry.runCommandStrict, avec retour utilisateur en cas d'échec (commande indisponible / callback absente). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -98,7 +98,7 @@ describe("loadPlugins", () => {
|
||||
);
|
||||
expect(failures).toEqual([]);
|
||||
expect((globalThis as Record<string, unknown>).__registerError).toMatch(
|
||||
/not declared by any menu item/,
|
||||
/not declared by any command contribution/,
|
||||
);
|
||||
});
|
||||
|
||||
@ -591,6 +591,13 @@ describe("loadPlugins", () => {
|
||||
command: "hello-plugin",
|
||||
},
|
||||
],
|
||||
slashCommands: [
|
||||
{
|
||||
name: "/hello",
|
||||
shortDescription: "Run the hello-plugin callback",
|
||||
command: "hello-plugin",
|
||||
},
|
||||
],
|
||||
layouts: [
|
||||
{
|
||||
type: "hello-plugin.hello-world",
|
||||
@ -613,6 +620,13 @@ describe("loadPlugins", () => {
|
||||
},
|
||||
]);
|
||||
expect(registry.get("com.example.hello-plugin")?.contributes.mcpServers).toEqual([]);
|
||||
expect(registry.get("com.example.hello-plugin")?.contributes.slashCommands).toEqual([
|
||||
{
|
||||
name: "/hello",
|
||||
shortDescription: "Run the hello-plugin callback",
|
||||
command: "hello-plugin",
|
||||
},
|
||||
]);
|
||||
await registry.runCommand("com.example.hello-plugin", "hello-plugin");
|
||||
expect((globalThis as Record<string, unknown>).__helloArchiveCommandRan).toBe(true);
|
||||
const Layout = registry.layoutComponent(
|
||||
@ -623,6 +637,39 @@ describe("loadPlugins", () => {
|
||||
expect((Layout as unknown as () => string)()).toBe("hello-world");
|
||||
});
|
||||
|
||||
it("allows command callbacks declared only by slashCommands", async () => {
|
||||
const bundle = dataUrl(`
|
||||
export function activate(ctx) {
|
||||
ctx.commands.registerCommand("dev.acme.explain", () => {
|
||||
globalThis.__slashOnlyCommandRan = true;
|
||||
});
|
||||
}
|
||||
`);
|
||||
const { registry, failures } = await loadPlugins(
|
||||
[
|
||||
entry({
|
||||
id: "dev.acme.slash",
|
||||
displayName: "Slash",
|
||||
bundleUrl: bundle,
|
||||
contributes: {
|
||||
slashCommands: [
|
||||
{
|
||||
name: "/explain",
|
||||
shortDescription: "Explain selection",
|
||||
command: "dev.acme.explain",
|
||||
},
|
||||
],
|
||||
} as unknown as PluginContributionDto,
|
||||
}),
|
||||
],
|
||||
gateways,
|
||||
);
|
||||
|
||||
expect(failures).toEqual([]);
|
||||
await registry.runCommand("dev.acme.slash", "dev.acme.explain");
|
||||
expect((globalThis as Record<string, unknown>).__slashOnlyCommandRan).toBe(true);
|
||||
});
|
||||
|
||||
it("confines a malformed runtime catalog entry and still loads healthy plugins", async () => {
|
||||
const bundle = dataUrl(`
|
||||
export function activate(ctx) {
|
||||
|
||||
Reference in New Issue
Block a user