UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

189 lines (188 loc) 8.77 kB
import { s as resolveConfigPath } from "./paths-mvMm5bYV.js"; import { t as parseJsonWithJson5Fallback } from "./parse-json-compat-DvZKmwhP.js"; import { n as resolveBundledPluginsDir } from "./bundled-dir-CG-NYRXR.js"; import { t as loadPluginManifestRegistry } from "./manifest-registry-BywZIeAq.js"; import { l as resolveEffectivePluginActivationState, n as createPluginActivationSource, s as normalizePluginsConfig } from "./config-state-CikNNz7T.js"; import { t as isPluginEnabledByDefaultForPlatform } from "./default-enablement-CEIbpabL.js"; import { r as getCurrentPluginMetadataSnapshot } from "./current-plugin-metadata-snapshot-CfA_n2Nc.js"; import { i as getRuntimeConfigSnapshot, s as getRuntimeConfigSourceSnapshot } from "./runtime-snapshot-D93_HOsR.js"; import { i as configMayNeedPluginAutoEnable, t as applyPluginAutoEnable } from "./plugin-auto-enable-pAtqig-B.js"; import { r as resolveRegistryPluginModuleLocationFromRecords } from "./facade-resolution-shared-CLzcjb4a.js"; import fs from "node:fs"; import JSON5 from "json5"; import path from "node:path"; //#region src/plugin-sdk/facade-activation-check.runtime.ts /** * Runtime boundary checks for bundled plugin public-surface facade imports. */ const ALWAYS_ALLOWED_RUNTIME_DIR_NAMES = new Set([ "image-generation-core", "media-understanding-core", "speech-core" ]); const EMPTY_FACADE_BOUNDARY_CONFIG = {}; function readFacadeBoundaryConfigSafely() { try { const sourceSnapshot = getRuntimeConfigSourceSnapshot(); if (sourceSnapshot) return { rawConfig: sourceSnapshot }; const runtimeSnapshot = getRuntimeConfigSnapshot(); if (runtimeSnapshot) return { rawConfig: runtimeSnapshot }; const configPath = resolveConfigPath(); if (!fs.existsSync(configPath)) return { rawConfig: EMPTY_FACADE_BOUNDARY_CONFIG }; const raw = fs.readFileSync(configPath, "utf8"); const parsed = JSON5.parse(raw); return { rawConfig: parsed && typeof parsed === "object" ? parsed : EMPTY_FACADE_BOUNDARY_CONFIG }; } catch { return { rawConfig: EMPTY_FACADE_BOUNDARY_CONFIG }; } } function getFacadeBoundaryResolvedConfig() { const { rawConfig } = readFacadeBoundaryConfigSafely(); const autoEnabled = configMayNeedPluginAutoEnable(rawConfig, process.env) ? applyPluginAutoEnable({ config: rawConfig, env: process.env }) : { config: rawConfig, autoEnabledReasons: {} }; const config = autoEnabled.config; return { rawConfig, config, normalizedPluginsConfig: normalizePluginsConfig(config?.plugins), activationSource: createPluginActivationSource({ config: rawConfig }), autoEnabledReasons: autoEnabled.autoEnabledReasons }; } function getFacadeManifestRegistry(params) { const envOption = params.env ? { env: params.env } : {}; const resolved = getFacadeBoundaryResolvedConfig(); const current = getCurrentPluginMetadataSnapshot({ config: resolved.config, ...envOption, allowWorkspaceScopedSnapshot: true }); if (current?.manifestRegistry) return current.manifestRegistry.plugins; return loadPluginManifestRegistry({ config: resolved.config, ...envOption }).plugins; } /** Resolves the concrete plugin module location recorded in the manifest registry. */ function resolveRegistryPluginModuleLocation(params) { return resolveRegistryPluginModuleLocationFromRecords({ registry: getFacadeManifestRegistry(params.env ? { env: params.env } : {}), dirName: params.dirName, artifactBasename: params.artifactBasename }); } function readBundledPluginManifestRecordFromDir(params) { const manifestPath = path.join(params.pluginsRoot, params.resolvedDirName, "openclaw.plugin.json"); if (!fs.existsSync(manifestPath)) return null; try { const raw = parseJsonWithJson5Fallback(fs.readFileSync(manifestPath, "utf8")); if (typeof raw.id !== "string" || raw.id.trim().length === 0) return null; return { id: raw.id, origin: "bundled", enabledByDefault: raw.enabledByDefault === true, rootDir: path.join(params.pluginsRoot, params.resolvedDirName), channels: Array.isArray(raw.channels) ? raw.channels.filter((entry) => typeof entry === "string") : [] }; } catch { return null; } } function resolveBundledMetadataManifestRecord(params) { if (!params.location) return null; if (params.location.modulePath.startsWith(`${params.sourceExtensionsRoot}${path.sep}`)) { const resolvedDirName = path.relative(params.sourceExtensionsRoot, params.location.modulePath).split(path.sep)[0]; if (!resolvedDirName) return null; return readBundledPluginManifestRecordFromDir({ pluginsRoot: params.sourceExtensionsRoot, resolvedDirName }); } const bundledPluginsDir = resolveBundledPluginsDir(params.env ?? process.env); if (!bundledPluginsDir) return null; const normalizedBundledPluginsDir = path.resolve(bundledPluginsDir); if (!params.location.modulePath.startsWith(`${normalizedBundledPluginsDir}${path.sep}`)) return null; const resolvedDirName = path.relative(normalizedBundledPluginsDir, params.location.modulePath).split(path.sep)[0]; if (!resolvedDirName) return null; return readBundledPluginManifestRecordFromDir({ pluginsRoot: normalizedBundledPluginsDir, resolvedDirName }); } function resolveBundledPluginManifestRecord(params) { const metadataRecord = resolveBundledMetadataManifestRecord(params); if (metadataRecord) return metadataRecord; const registry = getFacadeManifestRegistry(params.env ? { env: params.env } : {}); return (params.location ? registry.find((plugin) => { const normalizedRootDir = path.resolve(plugin.rootDir); const normalizedModulePath = path.resolve(params.location.modulePath); return normalizedModulePath === normalizedRootDir || normalizedModulePath.startsWith(`${normalizedRootDir}${path.sep}`); }) : null) ?? registry.find((plugin) => plugin.id === params.dirName) ?? registry.find((plugin) => path.basename(plugin.rootDir) === params.dirName) ?? registry.find((plugin) => plugin.channels.includes(params.dirName)) ?? null; } /** Resolves the stable plugin id used for telemetry and error reporting. */ function resolveTrackedFacadePluginId(params) { return resolveBundledPluginManifestRecord(params)?.id ?? params.dirName; } /** Evaluates whether a bundled plugin's api/runtime-api facade is currently enabled. */ function resolveBundledPluginPublicSurfaceAccess(params) { if (params.artifactBasename === "runtime-api.js" && ALWAYS_ALLOWED_RUNTIME_DIR_NAMES.has(params.dirName)) return { allowed: true, pluginId: params.dirName }; const manifestRecord = resolveBundledPluginManifestRecord(params); if (!manifestRecord) return { allowed: false, reason: `no bundled plugin manifest found for ${params.dirName}` }; const { config, normalizedPluginsConfig, activationSource, autoEnabledReasons } = getFacadeBoundaryResolvedConfig(); return evaluateBundledPluginPublicSurfaceAccess({ params, manifestRecord, config, normalizedPluginsConfig, activationSource, autoEnabledReasons }); } /** Applies normalized config and default enablement rules to one bundled manifest. */ function evaluateBundledPluginPublicSurfaceAccess(params) { const activationState = resolveEffectivePluginActivationState({ id: params.manifestRecord.id, origin: params.manifestRecord.origin, config: params.normalizedPluginsConfig, rootConfig: params.config, enabledByDefault: isPluginEnabledByDefaultForPlatform(params.manifestRecord), activationSource: params.activationSource, autoEnabledReason: params.autoEnabledReasons[params.manifestRecord.id]?.[0] }); if (activationState.enabled) return { allowed: true, pluginId: params.manifestRecord.id }; return { allowed: false, pluginId: params.manifestRecord.id, reason: activationState.reason ?? "plugin runtime is not activated" }; } /** Throws the public error used when a disabled bundled plugin facade is imported. */ function throwForBundledPluginPublicSurfaceAccess(params) { const pluginLabel = params.access.pluginId ?? params.request.dirName; throw new Error(`Bundled plugin public surface access blocked for "${pluginLabel}" via ${params.request.dirName}/${params.request.artifactBasename}: ${params.access.reason ?? "plugin runtime is not activated"}`); } /** Resolves bundled facade access and throws unless the facade is allowed to load. */ function resolveActivatedBundledPluginPublicSurfaceAccessOrThrow(params) { const access = resolveBundledPluginPublicSurfaceAccess(params); if (!access.allowed) throwForBundledPluginPublicSurfaceAccess({ access, request: params }); return access; } //#endregion export { evaluateBundledPluginPublicSurfaceAccess, resolveActivatedBundledPluginPublicSurfaceAccessOrThrow, resolveBundledPluginPublicSurfaceAccess, resolveRegistryPluginModuleLocation, resolveTrackedFacadePluginId, throwForBundledPluginPublicSurfaceAccess };