From b16fe2b229cc6b80a13d3d5b6f1ff78af112341e Mon Sep 17 00:00:00 2001 From: Shakker Date: Tue, 28 Apr 2026 02:55:42 +0100 Subject: [PATCH] feat: add plugin startup activation metadata --- src/plugins/manifest.json5-tolerance.test.ts | 2 ++ src/plugins/manifest.ts | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/plugins/manifest.json5-tolerance.test.ts b/src/plugins/manifest.json5-tolerance.test.ts index 2c218937d4b..2809f7c4577 100644 --- a/src/plugins/manifest.json5-tolerance.test.ts +++ b/src/plugins/manifest.json5-tolerance.test.ts @@ -127,6 +127,7 @@ describe("loadPluginManifest JSON5 tolerance", () => { const json5Content = `{ id: "openai", activation: { + onStartup: false, onProviders: ["openai", "", "openai-codex"], onCommands: ["models", ""], onChannels: ["web", ""], @@ -150,6 +151,7 @@ describe("loadPluginManifest JSON5 tolerance", () => { expect(result.ok).toBe(true); if (result.ok) { expect(result.manifest.activation).toEqual({ + onStartup: false, onProviders: ["openai", "openai-codex"], onCommands: ["models"], onChannels: ["web"], diff --git a/src/plugins/manifest.ts b/src/plugins/manifest.ts index cb92bf457e2..f132302d817 100644 --- a/src/plugins/manifest.ts +++ b/src/plugins/manifest.ts @@ -140,6 +140,14 @@ export type PluginManifestProviderRequest = { export type PluginManifestActivationCapability = "provider" | "channel" | "tool" | "hook"; export type PluginManifestActivation = { + /** + * Explicit Gateway startup activation. Every plugin should set this as + * OpenClaw moves away from implicit startup sidecar loading. Set true when + * the plugin must be imported during Gateway startup; set false to opt out + * of the deprecated implicit startup sidecar fallback when no other + * activation trigger matches. + */ + onStartup?: boolean; /** * Provider ids that should include this plugin in activation/load plans. * This is planner metadata only; runtime behavior still comes from register(). @@ -920,6 +928,7 @@ function normalizeManifestActivation(value: unknown): PluginManifestActivation | const onChannels = normalizeTrimmedStringList(value.onChannels); const onRoutes = normalizeTrimmedStringList(value.onRoutes); const onConfigPaths = normalizeTrimmedStringList(value.onConfigPaths); + const onStartup = typeof value.onStartup === "boolean" ? value.onStartup : undefined; const onCapabilities = normalizeTrimmedStringList(value.onCapabilities).filter( (capability): capability is PluginManifestActivationCapability => capability === "provider" || @@ -929,6 +938,7 @@ function normalizeManifestActivation(value: unknown): PluginManifestActivation | ); const activation = { + ...(onStartup !== undefined ? { onStartup } : {}), ...(onProviders.length > 0 ? { onProviders } : {}), ...(onAgentHarnesses.length > 0 ? { onAgentHarnesses } : {}), ...(onCommands.length > 0 ? { onCommands } : {}),