| |
| import type { OpenClawConfig } from "../../config/types.openclaw.js"; |
| import type { PluginInstallRecord } from "../../config/types.plugins.js"; |
| import { createSubsystemLogger } from "../../logging.js"; |
| import { normalizePluginsConfig } from "../config-state.js"; |
| import { hashStableJson } from "../installed-plugin-index-hash.js"; |
| import { resolvePluginRegistrationConfigKey } from "../loader-registration-config.js"; |
| import type { PluginLoadOptions } from "../loader-types.js"; |
| import type { PluginManifestRegistry } from "../manifest-registry.js"; |
| import { resolvePluginControlPlaneFingerprint } from "../plugin-control-plane-context.js"; |
| import type { PluginMetadataSnapshot } from "../plugin-metadata-snapshot.types.js"; |
| import { buildDeclaredProviderOwnerIndex } from "../provider-owner-index.js"; |
| import type { PluginRegistry } from "../registry-types.js"; |
| import type { PluginLogger } from "../types.js"; |
| import { |
| bindPluginRuntimeLoadContextState, |
| getPluginRuntimeLoadContextState, |
| type PluginRuntimeLoadContextState, |
| } from "./load-context-state.js"; |
|
|
| const log = createSubsystemLogger("plugins"); |
|
|
| |
| export type PluginRuntimeLoadContext = { |
| rawConfig: OpenClawConfig; |
| config: OpenClawConfig; |
| activationSourceConfig: OpenClawConfig; |
| autoEnabledReasons: Readonly<Record<string, string[]>>; |
| workspaceDir: string | undefined; |
| env: NodeJS.ProcessEnv; |
| logger: PluginLogger; |
| manifestRegistry?: PluginManifestRegistry; |
| metadataSnapshot?: PluginMetadataSnapshot; |
| installRecords?: Record<string, PluginInstallRecord>; |
| preferBuiltPluginArtifacts?: boolean; |
| expectedSourceDigests?: PluginLoadOptions["expectedSourceDigests"]; |
| }; |
|
|
| function activationResultFingerprint(context: PluginRuntimeLoadContext): string { |
| return hashStableJson({ |
| config: context.config, |
| activationSourceConfig: context.activationSourceConfig, |
| autoEnabledReasons: context.autoEnabledReasons, |
| env: context.env, |
| }); |
| } |
|
|
| export function setPluginRuntimeLoadContext( |
| registry: PluginRegistry, |
| context: PluginRuntimeLoadContext, |
| registrationConfigKey?: string, |
| loaderCacheIdentity?: PluginRuntimeLoadContextState["loaderCacheIdentity"], |
| ): void { |
| const previous = getPluginRuntimeLoadContextState(registry); |
| const capturedIdentity = previous?.loaderCacheIdentity ?? loaderCacheIdentity; |
| const bound = { |
| ...context, |
| activationInputFingerprint: hashStableJson({ config: context.rawConfig, env: context.env }), |
| activationResultFingerprint: activationResultFingerprint(context), |
| ...(capturedIdentity ? { loaderCacheIdentity: capturedIdentity } : {}), |
| |
| registrationConfigKey: |
| previous?.registrationConfigKey ?? |
| registrationConfigKey ?? |
| resolvePluginRegistrationConfigKey({ |
| runtimeEntries: normalizePluginsConfig(context.config.plugins).entries, |
| sourceEntries: normalizePluginsConfig(context.activationSourceConfig.plugins).entries, |
| }), |
| declaredProviderOwners: |
| context.metadataSnapshot && |
| context.metadataSnapshot.manifestRegistry === context.manifestRegistry |
| ? context.metadataSnapshot.declaredProviderOwners |
| : buildDeclaredProviderOwnerIndex(context.manifestRegistry?.plugins ?? []), |
| |
| controlPlaneFingerprint: resolvePluginControlPlaneFingerprint({ |
| config: context.rawConfig, |
| env: context.env, |
| workspaceDir: context.workspaceDir, |
| }), |
| }; |
| bindPluginRuntimeLoadContextState(registry, bound); |
| } |
|
|
| |
| export const getPluginRuntimeLoadContext = ( |
| registry: object | undefined, |
| ): (PluginRuntimeLoadContext & PluginRuntimeLoadContextState) | undefined => |
| |
| getPluginRuntimeLoadContextState(registry) as |
| | (PluginRuntimeLoadContext & PluginRuntimeLoadContextState) |
| | undefined; |
|
|
| |
| export function getReusablePluginRuntimeActivation( |
| registry: object | undefined, |
| params: { |
| config: OpenClawConfig; |
| env: NodeJS.ProcessEnv; |
| workspaceDir: string | undefined; |
| metadataSnapshot: PluginMetadataSnapshot; |
| }, |
| ): |
| | Pick<PluginRuntimeLoadContext, "config" | "activationSourceConfig" | "autoEnabledReasons"> |
| | undefined { |
| const context = getPluginRuntimeLoadContext(registry); |
| if ( |
| !context || |
| context.metadataSnapshot !== params.metadataSnapshot || |
| context.workspaceDir !== params.workspaceDir || |
| context.activationResultFingerprint !== activationResultFingerprint(context) |
| ) { |
| return undefined; |
| } |
| const inputFingerprint = hashStableJson({ config: params.config, env: params.env }); |
| |
| if ( |
| inputFingerprint !== context.activationInputFingerprint && |
| inputFingerprint !== hashStableJson({ config: context.config, env: context.env }) && |
| inputFingerprint !== |
| hashStableJson({ config: context.activationSourceConfig, env: context.env }) |
| ) { |
| return undefined; |
| } |
| return { |
| config: context.config, |
| activationSourceConfig: context.activationSourceConfig, |
| autoEnabledReasons: context.autoEnabledReasons, |
| }; |
| } |
|
|
| |
| type PluginRuntimeResolvedLoadValues = Pick< |
| PluginLoadOptions, |
| | "config" |
| | "activationSourceConfig" |
| | "autoEnabledReasons" |
| | "workspaceDir" |
| | "env" |
| | "logger" |
| | "manifestRegistry" |
| | "installRecords" |
| | "preferBuiltPluginArtifacts" |
| | "expectedSourceDigests" |
| >; |
|
|
| |
| export function createPluginRuntimeLoaderLogger(): PluginLogger { |
| return { |
| info: (message) => log.info(message), |
| warn: (message) => log.warn(message), |
| error: (message) => log.error(message), |
| debug: (message) => log.debug(message), |
| }; |
| } |
|
|
| |
| export function buildPluginRuntimeLoadOptions( |
| values: PluginRuntimeResolvedLoadValues, |
| overrides?: Partial<PluginLoadOptions>, |
| ): PluginLoadOptions { |
| return { |
| config: values.config, |
| activationSourceConfig: values.activationSourceConfig, |
| autoEnabledReasons: values.autoEnabledReasons, |
| workspaceDir: values.workspaceDir, |
| env: values.env, |
| logger: values.logger, |
| manifestRegistry: values.manifestRegistry, |
| installRecords: values.installRecords, |
| preferBuiltPluginArtifacts: values.preferBuiltPluginArtifacts, |
| expectedSourceDigests: values.expectedSourceDigests, |
| ...overrides, |
| }; |
| } |
|
|