perf: skip explicit startup opt out plugins

This commit is contained in:
Shakker
2026-04-28 02:55:48 +01:00
parent 5d52233c25
commit 7754158292
2 changed files with 99 additions and 13 deletions

View File

@@ -245,6 +245,28 @@ function createManifestRegistryFixture() {
providers: [],
cliBackends: [],
},
{
id: "demo-global-startup-opt-out",
channels: [],
activation: {
onStartup: false,
},
origin: "global",
enabledByDefault: undefined,
providers: [],
cliBackends: [],
},
{
id: "demo-global-explicit-startup",
channels: [],
activation: {
onStartup: true,
},
origin: "global",
enabledByDefault: undefined,
providers: [],
cliBackends: [],
},
].map(withManifestLoadPaths),
diagnostics: [],
};
@@ -297,7 +319,12 @@ function createInstalledPluginRecordFixture(
enabled: true,
...(record.enabledByDefault === true ? { enabledByDefault: true } : {}),
startup: {
sidecar: record.channels.length === 0 && !hasRuntimeContractSurface(record) && !memory,
sidecar:
record.activation?.onStartup === true ||
(record.activation?.onStartup === undefined &&
record.channels.length === 0 &&
!hasRuntimeContractSurface(record) &&
!memory),
memory,
deferConfiguredChannelFullLoadUntilAfterListen:
record.startupDeferConfiguredChannelFullLoadUntilAfterListen === true,
@@ -623,6 +650,42 @@ describe("resolveGatewayStartupPluginIds", () => {
});
});
it("keeps deprecated implicit startup sidecar fallback for legacy plugins", () => {
expectStartupPluginIdsCase({
config: createStartupConfig({
enabledPluginIds: ["demo-global-sidecar"],
allowPluginIds: ["demo-global-sidecar"],
noConfiguredChannels: true,
memorySlot: "none",
}),
expected: ["demo-global-sidecar"],
});
});
it("skips deprecated implicit startup sidecar fallback when activation.onStartup is false", () => {
expectStartupPluginIdsCase({
config: createStartupConfig({
enabledPluginIds: ["demo-global-startup-opt-out"],
allowPluginIds: ["demo-global-startup-opt-out"],
noConfiguredChannels: true,
memorySlot: "none",
}),
expected: [],
});
});
it("loads explicit startup plugins when activation.onStartup is true", () => {
expectStartupPluginIdsCase({
config: createStartupConfig({
enabledPluginIds: ["demo-global-explicit-startup"],
allowPluginIds: ["demo-global-explicit-startup"],
noConfiguredChannels: true,
memorySlot: "none",
}),
expected: ["demo-global-explicit-startup"],
});
});
it("starts bundled sidecars selected by root config activation paths", () => {
const rawConfig = {
browser: {

View File

@@ -65,8 +65,16 @@ function isGatewayStartupMemoryPlugin(plugin: InstalledPluginIndexRecord): boole
return plugin.startup.memory;
}
function isGatewayStartupSidecar(plugin: InstalledPluginIndexRecord): boolean {
return plugin.startup.sidecar;
/**
* @deprecated Compatibility fallback for plugins that do not declare
* `activation.onStartup`. Keep this path visible so we can remove it after
* plugin manifests migrate to explicit startup activation.
*/
function isDeprecatedLegacyImplicitStartupSidecar(params: {
plugin: InstalledPluginIndexRecord;
manifest: PluginManifestRecord | undefined;
}): boolean {
return params.plugin.startup.sidecar && params.manifest?.activation?.onStartup === undefined;
}
function resolveGatewayStartupDreamingPluginIds(config: OpenClawConfig): Set<string> {
@@ -108,12 +116,26 @@ function resolveMemorySlotStartupPluginId(params: {
function shouldConsiderForGatewayStartup(params: {
plugin: InstalledPluginIndexRecord;
manifest: PluginManifestRecord | undefined;
startupDreamingPluginIds: ReadonlySet<string>;
memorySlotStartupPluginId?: string;
}): boolean {
if (isGatewayStartupSidecar(params.plugin)) {
if (params.manifest?.activation?.onStartup === true) {
return true;
}
if (params.plugin.startup.sidecar) {
if (params.manifest?.activation?.onStartup === false) {
return false;
}
// Deprecated compatibility fallback: plugins without explicit startup
// activation metadata may still need startup import to register hooks or
// services. All plugins should declare activation.onStartup explicitly as
// we migrate away from implicit startup sidecar loading.
return isDeprecatedLegacyImplicitStartupSidecar({
plugin: params.plugin,
manifest: params.manifest,
});
}
if (!isGatewayStartupMemoryPlugin(params.plugin)) {
return false;
}
@@ -399,15 +421,6 @@ export function resolveGatewayStartupPluginIdsFromRegistry(params: {
});
return activationState.enabled;
}
if (
!shouldConsiderForGatewayStartup({
plugin,
startupDreamingPluginIds,
memorySlotStartupPluginId,
})
) {
return false;
}
if (
canStartConfiguredRootPlugin({
plugin,
@@ -419,6 +432,16 @@ export function resolveGatewayStartupPluginIdsFromRegistry(params: {
) {
return true;
}
if (
!shouldConsiderForGatewayStartup({
plugin,
manifest,
startupDreamingPluginIds,
memorySlotStartupPluginId,
})
) {
return false;
}
const activationState = resolveEffectivePluginActivationState({
id: plugin.pluginId,
origin: plugin.origin,