fix: defer bundled plugin runtime deps until enabled

This commit is contained in:
Peter Steinberger
2026-04-23 03:16:44 +01:00
parent 4479d4d437
commit 90696bffff
7 changed files with 309 additions and 61 deletions

View File

@@ -549,7 +549,7 @@ describe("bundled channel entry shape guards", () => {
}
});
it("loads bundled setup entries from external staged runtime deps", async () => {
it("does not load bundled setup entries through external staged runtime deps during discovery", async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-bundled-setup-runtime-deps-"));
const stageRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-bundled-stage-"));
const previousBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
@@ -620,8 +620,8 @@ describe("bundled channel entry shape guards", () => {
"./bundled.js?scope=bundled-setup-runtime-deps",
);
expect(bundled.getBundledChannelSetupPlugin("alpha")?.meta.label).toBe("staged-alpha");
expect(testGlobal.__bundledSetupRuntimeDepMarker).toBe("staged-alpha");
expect(bundled.getBundledChannelSetupPlugin("alpha")).toBeUndefined();
expect(testGlobal.__bundledSetupRuntimeDepMarker).toBeUndefined();
} finally {
restoreBundledPluginsDir(previousBundledPluginsDir);
if (previousPluginStageDir === undefined) {

View File

@@ -4,6 +4,7 @@ import { createSubsystemLogger } from "../../logging/subsystem.js";
import type {
BundledChannelLegacySessionSurface,
BundledChannelLegacyStateMigrationDetector,
BundledEntryModuleLoadOptions,
} from "../../plugin-sdk/channel-entry-contract.js";
import {
listBundledChannelPluginMetadata,
@@ -39,8 +40,10 @@ type BundledChannelEntryRuntimeContract = {
type BundledChannelSetupEntryRuntimeContract = {
kind: "bundled-channel-setup-entry";
loadSetupPlugin: () => ChannelPlugin;
loadSetupSecrets?: () => ChannelPlugin["secrets"] | undefined;
loadSetupPlugin: (options?: BundledEntryModuleLoadOptions) => ChannelPlugin;
loadSetupSecrets?: (
options?: BundledEntryModuleLoadOptions,
) => ChannelPlugin["secrets"] | undefined;
loadLegacyStateMigrationDetector?: () => BundledChannelLegacyStateMigrationDetector;
loadLegacySessionSurface?: () => BundledChannelLegacySessionSurface;
features?: {
@@ -179,6 +182,7 @@ function loadGeneratedBundledChannelModule(params: {
rootScope: BundledChannelRootScope;
metadata: BundledChannelPluginMetadata;
entry: BundledChannelPluginMetadata["source"] | BundledChannelPluginMetadata["setupSource"];
installRuntimeDeps?: boolean;
}): unknown {
let modulePath = resolveGeneratedBundledChannelModulePath(params);
if (!modulePath) {
@@ -191,7 +195,7 @@ function loadGeneratedBundledChannelModule(params: {
metadata: params.metadata,
modulePath,
});
if (isBuiltBundledPluginRuntimeRoot(boundaryRoot)) {
if (params.installRuntimeDeps !== false && isBuiltBundledPluginRuntimeRoot(boundaryRoot)) {
const prepared = prepareBundledPluginRuntimeRoot({
pluginId: params.metadata.manifest.id,
pluginRoot: boundaryRoot,
@@ -225,6 +229,7 @@ function loadGeneratedBundledChannelEntry(params: {
rootScope: params.rootScope,
metadata: params.metadata,
entry: params.metadata.source,
installRuntimeDeps: true,
}),
);
if (!entry) {
@@ -257,6 +262,7 @@ function loadGeneratedBundledChannelSetupEntry(params: {
rootScope: params.rootScope,
metadata: params.metadata,
entry: params.metadata.setupSource,
installRuntimeDeps: false,
}),
);
if (!setupEntry) {
@@ -563,7 +569,7 @@ function getBundledChannelSetupPluginForRoot(
}
cacheContext.setupPluginLoadInProgressIds.add(id);
try {
const plugin = entry.loadSetupPlugin();
const plugin = entry.loadSetupPlugin({ installRuntimeDeps: false });
cacheContext.lazySetupPluginsById.set(id, plugin);
return plugin;
} catch (error) {