Files
openclaw/src/agents/runtime-plugins.ts
brokemac79 de4b8d8ebf feat(plugins): allow installed trusted policy contracts
Allow explicitly enabled installed plugins to register declared trusted tool policies and agent tool result middleware, with trusted policy ids scoped by plugin owner.\n\nVerification covered targeted plugin/agent tests, typecheck, build, lint, local autoreview, and a Blacksmith Testbox runtime proof (tbx_01ktr1nq0rhq47fjkwrepm7fd3).
2026-06-10 16:18:23 +10:00

68 lines
2.5 KiB
TypeScript

/**
* Ensures runtime plugin registries are loaded for agent execution. Startup
* plugin IDs from metadata scope the load when available.
*/
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { normalizePluginsConfig } from "../plugins/config-state.js";
import { getCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
import { getActivePluginRuntimeSubagentMode } from "../plugins/runtime.js";
import { ensureStandaloneRuntimePluginRegistryLoaded } from "../plugins/runtime/standalone-runtime-registry-loader.js";
import { resolveUserPath } from "../utils.js";
type StartupScopedPluginSnapshot = NonNullable<
ReturnType<typeof getCurrentPluginMetadataSnapshot>
> & {
startup?: {
pluginIds?: readonly unknown[];
};
};
function resolveStartupPluginIdsFromCurrentSnapshot(params: {
config?: OpenClawConfig;
workspaceDir?: string;
}): string[] | undefined {
const snapshot = getCurrentPluginMetadataSnapshot({
config: params.config,
workspaceDir: params.workspaceDir,
}) as StartupScopedPluginSnapshot | undefined;
const pluginIds = snapshot?.startup?.pluginIds;
if (!Array.isArray(pluginIds)) {
return undefined;
}
return pluginIds.filter((pluginId): pluginId is string => typeof pluginId === "string");
}
/** Ensure standalone runtime plugins are loaded for the current agent context. */
export function ensureRuntimePluginsLoaded(params: {
config?: OpenClawConfig;
workspaceDir?: string | null;
allowGatewaySubagentBinding?: boolean;
}): void {
if (params.config && !normalizePluginsConfig(params.config.plugins).enabled) {
return;
}
const workspaceDir =
typeof params.workspaceDir === "string" && params.workspaceDir.trim()
? resolveUserPath(params.workspaceDir)
: undefined;
const startupPluginIds = resolveStartupPluginIdsFromCurrentSnapshot({
config: params.config,
workspaceDir,
});
const allowGatewaySubagentBinding =
params.allowGatewaySubagentBinding === true ||
getActivePluginRuntimeSubagentMode() === "gateway-bindable";
ensureStandaloneRuntimePluginRegistryLoaded({
requiredPluginIds: startupPluginIds,
loadOptions: {
config: params.config,
workspaceDir,
...(startupPluginIds === undefined ? {} : { onlyPluginIds: startupPluginIds }),
...(startupPluginIds === undefined ? {} : { forceFullRuntimeForChannelPlugins: true }),
runtimeOptions: allowGatewaySubagentBinding
? { allowGatewaySubagentBinding: true }
: undefined,
},
});
}