openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
338 lines (337 loc) • 18.2 kB
JavaScript
import { a as getPluginCache } from "./plugin-cache-DGWspMEc.js";
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { l as normalizeSortedUniqueStringEntries } from "./string-normalization-DsCfAx8q.js";
import { c as resolveUserPath } from "./home-dir-BPhrG-aM.js";
import { S as resolveConfigEnvVars } from "./redact-BtvPPfTi.js";
import "./utils-P__uGsPB.js";
import { a as pluginCacheRealpathSync, c as readPluginCacheFile, n as parsePluginCacheJson, o as pluginCacheStatSync, r as pluginCacheExistsSync } from "./plugin-cache-files-DLPF_Tw2.js";
import { n as resolveOpenClawDevSourceRoot } from "./dev-source-root-DCu97Qvh.js";
import { f as extractPluginInstallRecordsFromInstalledPluginIndex } from "./installed-plugin-index-wrDsjyMD.js";
import { l as normalizePluginsConfig, n as createPluginActivationSource, t as applyTestPluginDefaults } from "./config-state-BkU1frVq.js";
import { i as loadInstalledPluginIndexInstallRecordsSync } from "./installed-plugin-index-record-reader-SXWwf_BU.js";
import { d as serializePluginIdScope, h as resolvePluginDiscoveryContext, n as getCurrentPluginMetadataSnapshot, p as fingerprintPluginDiscoveryContext, u as normalizePluginIdScope } from "./current-plugin-metadata-snapshot-CmSX4G3W.js";
import { o as createConfigRuntimeEnv } from "./config-env-vars-DUfQlcAk.js";
import "./env-vars-CyiONVe6.js";
import { t as resolvePluginActivationSourceConfig } from "./activation-source-config-DnARnJdS.js";
import { _ as getPluginRegistryForContext, d as getActivePluginRegistryKey, p as getActivePluginRegistryWorkspaceDir, u as getActivePluginRegistry } from "./runtime-BL4wZfTq.js";
import "./installed-plugin-index-records-C06Xozeq.js";
import { n as resolvePluginRuntimeArtifactPreference } from "./plugin-runtime-artifact-selection-OSt151GX.js";
import path from "node:path";
import { createHash } from "node:crypto";
//#region src/plugins/loader-load-context.ts
function resolveBundledPackageRootForCache(stockRoot) {
if (!stockRoot) return;
const resolved = path.resolve(stockRoot);
const parent = path.dirname(resolved);
if (path.basename(resolved) === "extensions" && (path.basename(parent) === "dist" || path.basename(parent) === "dist-runtime")) return path.dirname(parent);
const sourcePackageRoot = parent;
return pluginCacheExistsSync(path.join(sourcePackageRoot, "package.json")) ? sourcePackageRoot : void 0;
}
function readPackageVersionForCache(packageJsonPath) {
const file = readPluginCacheFile({
rootDir: path.dirname(packageJsonPath),
relativePath: path.basename(packageJsonPath),
rejectHardlinks: false
});
const parsed = file.ok ? parsePluginCacheJson(file) : void 0;
if (!parsed?.ok || !isRecord(parsed.value)) return "unknown";
const version = parsed.value.version;
return typeof version === "string" && version.trim() ? version.trim() : "unknown";
}
const runtimeBindingCacheIds = /* @__PURE__ */ new WeakMap();
let nextRuntimeBindingCacheId = 1;
function resolveRuntimeBindingCacheId(value) {
if (!value) return;
const existing = runtimeBindingCacheIds.get(value);
if (existing !== void 0) return existing;
const id = nextRuntimeBindingCacheId++;
runtimeBindingCacheIds.set(value, id);
return id;
}
function resolveRuntimeBindingCacheIdentity(runtimeOptions) {
return JSON.stringify({
nodes: resolveRuntimeBindingCacheId(runtimeOptions?.nodes),
subagent: resolveRuntimeBindingCacheId(runtimeOptions?.subagent)
});
}
function resolveBundledPackageCacheIdentity(stockRoot) {
if (!stockRoot) return;
const bundledPackages = getPluginCache().sdk.bundledPackages;
const stockRootKey = path.resolve(stockRoot);
if (bundledPackages.has(stockRootKey)) return bundledPackages.get(stockRootKey);
const packageRoot = resolveBundledPackageRootForCache(stockRoot);
if (!packageRoot) {
bundledPackages.set(stockRootKey, void 0);
return;
}
const packageJsonPath = path.join(packageRoot, "package.json");
const stat = pluginCacheStatSync(packageJsonPath);
const identity = {
packageJson: pluginCacheRealpathSync(packageJsonPath) ?? path.resolve(packageJsonPath),
packageRoot: pluginCacheRealpathSync(packageRoot) ?? path.resolve(packageRoot),
packageVersion: stat ? readPackageVersionForCache(packageJsonPath) : "missing",
size: stat?.size ?? -1,
mtimeMs: stat?.mtimeMs ?? -1
};
bundledPackages.set(stockRootKey, identity);
return identity;
}
function buildActivationMetadataHash(params) {
const sourceChannelEnablement = Object.entries(params.activationSource.rootConfig?.channels ?? {}).flatMap(([channelId, value]) => {
if (!value || typeof value !== "object" || Array.isArray(value)) return [];
const enabled = value.enabled;
return typeof enabled === "boolean" ? [[channelId, enabled]] : [];
}).toSorted(([left], [right]) => left.localeCompare(right));
const pluginEntryInputs = Object.entries(params.activationSource.plugins.entries).map(([pluginId, { enabled, config }]) => [pluginId, {
enabled,
config
}]).toSorted(([left], [right]) => left.localeCompare(right));
const autoEnableReasonEntries = Object.entries(params.autoEnabledReasons).map(([pluginId, reasons]) => [pluginId, [...reasons]]).toSorted(([left], [right]) => left.localeCompare(right));
return createHash("sha256").update(JSON.stringify({
enabled: params.activationSource.plugins.enabled,
allow: params.activationSource.plugins.allow,
deny: params.activationSource.plugins.deny,
memorySlot: params.activationSource.plugins.slots.memory,
entries: pluginEntryInputs,
channelEnablement: sourceChannelEnablement,
autoEnabledReasons: autoEnableReasonEntries
})).digest("hex");
}
function buildCacheKey(params) {
const discoveryContext = resolvePluginDiscoveryContext({
workspaceDir: params.workspaceDir,
loadPaths: params.plugins.loadPaths,
env: params.env
});
const { roots, loadPaths } = discoveryContext;
const bundledPackage = resolveBundledPackageCacheIdentity(roots.stock);
const installs = Object.fromEntries(Object.entries(params.installs ?? {}).map(([pluginId, install]) => [pluginId, {
...install,
installPath: typeof install.installPath === "string" ? resolveUserPath(install.installPath, params.env) : install.installPath,
sourcePath: typeof install.sourcePath === "string" ? resolveUserPath(install.sourcePath, params.env) : install.sourcePath
}]));
const setupOnlyKey = params.includeSetupOnlyChannelPlugins === true ? "setup-only" : "runtime";
const setupOnlyModeKey = params.forceSetupOnlyChannelPlugins === true ? "force-setup" : "normal-setup";
const setupOnlyRequirementKey = params.requireSetupEntryForSetupOnlyChannelPlugins === true ? "require-setup-entry" : "allow-full-fallback";
const rawConfigEnvMode = params.resolveRawConfigEnvVars === true ? "resolve-raw-env" : "runtime-config";
const moduleLoadMode = params.loadModules === false ? "manifest-only" : "load-modules";
const discoveryMode = params.toolDiscovery === true ? "tool-discovery" : "default-discovery";
const activationMode = params.activate === false ? "snapshot" : "active";
const cacheIdentity = `${roots.workspace ?? ""}::${roots.global ?? ""}::${roots.stock ?? ""}::${JSON.stringify({
bundledPackage,
devSourceRoot: params.devSourceRoot ?? "",
discoveryFingerprint: fingerprintPluginDiscoveryContext(discoveryContext),
...params.plugins,
installs,
loadPaths,
activationMetadataKey: params.activationMetadataKey ?? "",
capabilityCatalogIdentity: params.capabilityCatalogIdentity,
allowProcessHomeSessionCatalogs: params.allowProcessHomeSessionCatalogs !== false
})}::${serializePluginIdScope(params.onlyPluginIds)}::${setupOnlyKey}::${setupOnlyModeKey}::${setupOnlyRequirementKey}::${params.channelPluginLoadIntent}::${params.artifactPreference}::${rawConfigEnvMode}::${moduleLoadMode}::${discoveryMode}::${params.runtimeSubagentMode ?? "default"}::${params.runtimeBindingIdentity ?? "{}"}::${params.pluginSdkResolution ?? "auto"}::${JSON.stringify(params.coreGatewayMethodNames ?? [])}::${activationMode}`;
return createHash("sha256").update(cacheIdentity).digest("hex");
}
function resolveRuntimeSubagentMode(runtimeOptions) {
if (runtimeOptions?.allowGatewaySubagentBinding === true) return "gateway-bindable";
return runtimeOptions?.subagent ? "explicit" : "default";
}
function resolveCoreGatewayMethodNames(options) {
const names = new Set(options.coreGatewayMethodNames ?? []);
for (const name of Object.keys(options.coreGatewayHandlers ?? {})) names.add(name);
return Array.from(names).sort();
}
function mergePluginTrustList(runtimeList, sourceList) {
if (runtimeList === sourceList || sourceList.length === 0) return runtimeList;
const merged = [...runtimeList];
const seen = new Set(merged);
for (const entry of sourceList) if (!seen.has(entry)) {
merged.push(entry);
seen.add(entry);
}
return merged.length === runtimeList.length ? runtimeList : merged;
}
function mergeTrustPluginConfigFromActivationSource(params) {
const source = params.activationSource.plugins;
const allow = mergePluginTrustList(params.normalized.allow, source.allow);
const deny = mergePluginTrustList(params.normalized.deny, source.deny);
const loadPaths = mergePluginTrustList(params.normalized.loadPaths, source.loadPaths);
if (allow === params.normalized.allow && deny === params.normalized.deny && loadPaths === params.normalized.loadPaths) return params.normalized;
return {
...params.normalized,
allow,
deny,
loadPaths
};
}
function resolvePluginLoadCacheContext(options = {}) {
const shouldResolveRawConfigEnvVars = options.resolveRawConfigEnvVars === true;
const baseEnv = options.env ?? process.env;
const rawConfig = options.config ?? {};
const rawActivationSourceConfig = resolvePluginActivationSourceConfig({
config: options.config,
activationSourceConfig: options.activationSourceConfig
});
const env = shouldResolveRawConfigEnvVars ? createConfigRuntimeEnv(rawConfig, baseEnv) : baseEnv;
const cfg = applyTestPluginDefaults(shouldResolveRawConfigEnvVars ? resolveConfigEnvVars(rawConfig, env, { onMissing: () => void 0 }) : rawConfig, env);
const activationSourceConfig = shouldResolveRawConfigEnvVars ? resolveConfigEnvVars(rawActivationSourceConfig, env, { onMissing: () => void 0 }) : rawActivationSourceConfig;
const normalized = normalizePluginsConfig(cfg.plugins);
const activationSource = createPluginActivationSource({
config: activationSourceConfig,
plugins: cfg.plugins === activationSourceConfig.plugins ? normalized : void 0
});
const trustNormalized = mergeTrustPluginConfigFromActivationSource({
normalized,
activationSource
});
const onlyPluginIds = normalizePluginIdScope(options.onlyPluginIds);
const includeSetupOnlyChannelPlugins = options.includeSetupOnlyChannelPlugins === true;
const forceSetupOnlyChannelPlugins = options.forceSetupOnlyChannelPlugins === true;
const requireSetupEntryForSetupOnlyChannelPlugins = options.requireSetupEntryForSetupOnlyChannelPlugins === true;
const channelPluginLoadIntent = options.channelPluginLoadIntent ?? "full";
const artifactPreference = resolvePluginRuntimeArtifactPreference(options.preferBuiltPluginArtifacts);
const runtimeSubagentMode = resolveRuntimeSubagentMode(options.runtimeOptions);
const coreGatewayMethodNames = resolveCoreGatewayMethodNames(options);
const currentMetadataSnapshot = options.installRecords === void 0 && trustNormalized.loadPaths === normalized.loadPaths && !shouldResolveRawConfigEnvVars && (options.env === void 0 || options.env === process.env) ? getCurrentPluginMetadataSnapshot({
config: rawConfig,
env,
workspaceDir: options.workspaceDir
}) ?? (onlyPluginIds !== void 0 ? getCurrentPluginMetadataSnapshot({
config: rawConfig,
env,
workspaceDir: options.workspaceDir,
pluginIds: onlyPluginIds
}) : void 0) : void 0;
const preparedInstallRecords = currentMetadataSnapshot && (options.manifestRegistry === void 0 || options.manifestRegistry === currentMetadataSnapshot.manifestRegistry) ? extractPluginInstallRecordsFromInstalledPluginIndex(currentMetadataSnapshot.index) : void 0;
const installRecords = {
...options.installRecords ?? preparedInstallRecords ?? loadInstalledPluginIndexInstallRecordsSync({ env }),
...cfg.plugins?.installs
};
const devSourceRoot = resolveOpenClawDevSourceRoot(env);
const cacheKey = buildCacheKey({
workspaceDir: options.workspaceDir,
plugins: trustNormalized,
activationMetadataKey: buildActivationMetadataHash({
activationSource,
autoEnabledReasons: options.autoEnabledReasons ?? {}
}),
installs: installRecords,
env,
devSourceRoot,
onlyPluginIds,
includeSetupOnlyChannelPlugins,
forceSetupOnlyChannelPlugins,
requireSetupEntryForSetupOnlyChannelPlugins,
channelPluginLoadIntent,
artifactPreference,
resolveRawConfigEnvVars: options.resolveRawConfigEnvVars,
toolDiscovery: options.toolDiscovery,
capabilityCatalogIdentity: options.capabilityCatalog ? JSON.stringify([
options.capabilityCatalog.family,
resolveRuntimeBindingCacheId(options.capabilityCatalog.context),
resolveRuntimeBindingCacheId(getPluginCache()),
resolveRuntimeBindingCacheId(getPluginRegistryForContext() ?? void 0)
]) : void 0,
loadModules: options.loadModules,
runtimeSubagentMode,
runtimeBindingIdentity: resolveRuntimeBindingCacheIdentity(options.runtimeOptions),
pluginSdkResolution: options.pluginSdkResolution,
coreGatewayMethodNames,
allowProcessHomeSessionCatalogs: options.allowProcessHomeSessionCatalogs,
activate: options.activate
});
return {
env,
cfg,
metadataSnapshot: currentMetadataSnapshot,
normalized: trustNormalized,
activationSourceConfig,
activationSource,
autoEnabledReasons: options.autoEnabledReasons ?? {},
onlyPluginIds,
includeSetupOnlyChannelPlugins,
forceSetupOnlyChannelPlugins,
requireSetupEntryForSetupOnlyChannelPlugins,
channelPluginLoadIntent,
artifactPreference,
shouldActivate: options.activate !== false,
shouldLoadModules: options.loadModules !== false,
runtimeSubagentMode,
installRecords,
devSourceRoot,
cacheKey
};
}
//#endregion
//#region src/plugins/active-runtime-registry.ts
function getActiveRuntimePluginRegistry() {
return getActivePluginRegistry();
}
/** Return the exact active registry without triggering a fresh load on cache miss. */
function resolveCompatibleRuntimePluginRegistry(options) {
const activeRegistry = getActivePluginRegistry() ?? void 0;
if (!activeRegistry || options === void 0) return activeRegistry;
const activeCacheKey = getActivePluginRegistryKey();
if (!activeCacheKey) return;
return resolvePluginLoadCacheContext(options).cacheKey === activeCacheKey ? activeRegistry : void 0;
}
function isRuntimePluginRecordLoaded(plugin) {
return plugin.status === "loaded" && (plugin.format === "bundle" || plugin.imported !== false);
}
/** Lists runtime-loaded plugin ids from an immutable/request-scoped registry handle. */
function listRuntimePluginIdsFromRegistry(registry) {
return normalizeSortedUniqueStringEntries(registry.plugins.filter(isRuntimePluginRecordLoaded).map((plugin) => plugin.id));
}
function listLoadedRuntimePluginIds() {
const registry = getActivePluginRegistry();
return registry ? listRuntimePluginIdsFromRegistry(registry) : [];
}
function normalizeRequiredPluginIds(ids) {
if (ids === void 0) return;
return normalizeSortedUniqueStringEntries(ids);
}
function registryContainsRuntimePluginIds(registry, pluginIds) {
if (pluginIds === void 0) return true;
if (pluginIds.length === 0 && registry.plugins.length > 0) return false;
const missing = new Set(pluginIds);
for (const plugin of registry.plugins) if (plugin.status === void 0 || isRuntimePluginRecordLoaded(plugin)) missing.delete(plugin.id);
if (pluginIds.length > 0 && missing.size === 0) return true;
if (registry.plugins.some((plugin) => missing.has(plugin.id))) return false;
for (const [key, value] of Object.entries(registry)) {
if (key === "diagnostics" || key === "channelSetups" || !Array.isArray(value)) continue;
for (const entry of value) if (entry && typeof entry === "object" && "pluginId" in entry) {
const pluginId = entry.pluginId;
if (typeof pluginId === "string" && pluginId.length > 0) {
if (pluginIds.length === 0) return false;
missing.delete(pluginId);
if (missing.size === 0) return true;
}
}
}
return pluginIds.length === 0;
}
function registryMatchesManifestPluginIds(registry, manifestPlugins, pluginIds) {
if (!manifestPlugins) return false;
const records = new Map(registry.plugins.map((plugin) => [plugin.id, plugin]));
const manifests = new Map(manifestPlugins.map((plugin) => [plugin.id, plugin]));
return pluginIds.every((pluginId) => {
const record = records.get(pluginId);
const manifest = manifests.get(pluginId);
return Boolean(record && manifest && record.origin === manifest.origin && (record.origin === "bundled" || record.rootDir === manifest.rootDir && record.source === manifest.source));
});
}
function getLoadedRuntimePluginRegistry(params = {}) {
const requiredPluginIds = normalizeRequiredPluginIds(params.requiredPluginIds ?? params.loadOptions?.onlyPluginIds);
if (params.loadOptions && requiredPluginIds?.length !== 0) {
const compatible = resolveCompatibleRuntimePluginRegistry(params.loadOptions);
if (compatible && registryContainsRuntimePluginIds(compatible, requiredPluginIds)) return compatible;
if (requiredPluginIds === void 0) return;
}
const activeWorkspaceDir = getActivePluginRegistryWorkspaceDir();
const requestedWorkspaceDir = params.workspaceDir ?? params.loadOptions?.workspaceDir;
if (requestedWorkspaceDir !== void 0 && activeWorkspaceDir !== requestedWorkspaceDir) return;
const registry = getActivePluginRegistry();
if (!registry) return;
if (!registryContainsRuntimePluginIds(registry, requiredPluginIds)) return;
return registry;
}
//#endregion
export { registryContainsRuntimePluginIds as a, resolvePluginLoadCacheContext as c, listRuntimePluginIdsFromRegistry as i, resolveRuntimeSubagentMode as l, getLoadedRuntimePluginRegistry as n, registryMatchesManifestPluginIds as o, listLoadedRuntimePluginIds as r, resolveCompatibleRuntimePluginRegistry as s, getActiveRuntimePluginRegistry as t };