feat(sdk): add plugin activationScope (app/project)

Manifests can now declare activationScope to defer activation until a
project is focused, instead of always activating at app bootstrap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 14:43:23 +02:00
parent 6bca9cc4c0
commit e509e796b4
3 changed files with 25 additions and 0 deletions

View File

@ -1,4 +1,5 @@
export type {
IdeAPluginActivationScope,
IdeAPluginCapability,
IdeAPluginManifest,
IdeAPluginEngineConstraints,

View File

@ -9,6 +9,10 @@ export interface IdeAPluginManifest {
publisher?: string;
engines?: IdeAPluginEngineConstraints;
capabilities?: IdeAPluginCapability[];
/**
* Defaults to "app". Use "project" when activate(ctx) requires a focused project.
*/
activationScope?: IdeAPluginActivationScope;
contributes?: {
menus?: IdeAPluginTopLevelMenuContribution[];
menuItems?: IdeAPluginMenuItemContribution[];
@ -19,6 +23,8 @@ export interface IdeAPluginManifest {
export type IdeAPluginCapability = "ui" | "mcp" | "tooling";
export type IdeAPluginActivationScope = "app" | "project";
export interface IdeAPluginEngineConstraints {
idea?: string;
}
@ -100,6 +106,7 @@ export function validatePluginManifest(input: unknown): PluginManifestValidation
validateEngines(input.engines, errors);
validateCapabilities(input.capabilities, errors);
validateActivationScope(input.activationScope, errors);
validateContributes(input.contributes, errors);
if (errors.length > 0) {
@ -151,6 +158,16 @@ function validateCapabilities(value: unknown, errors: string[]): void {
});
}
function validateActivationScope(value: unknown, errors: string[]): void {
if (value === undefined) {
return;
}
if (value !== "app" && value !== "project") {
errors.push("activationScope must be \"app\" or \"project\" when provided");
}
}
function validateContributes(value: unknown, errors: string[]): void {
if (value === undefined) {
return;