UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

338 lines (337 loc) 18.2 kB
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 };