UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

211 lines (210 loc) 12.2 kB
import { t as sanitizeForLog } from "./ansi-DrXAcdMD.js"; import { c as normalizeOptionalLowercaseString } from "./string-coerce-CIXf7egm.js"; import { l as normalizePluginsConfig } from "./config-state-BkU1frVq.js"; import { t as isPluginEnabledByDefaultForPlatform } from "./default-enablement-CEIbpabL.js"; import { a as resolveManifestOwnerBasePolicyBlock, n as isActivatedManifestOwner, t as hasExplicitManifestOwnerTrust } from "./manifest-owner-policy-D98oU3cV.js"; import { n as loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry-contributions-BwuDvm89.js"; import "./plugin-registry-DD_0nL_t.js"; import { a as isSafeChannelEnvVarTriggerName } from "./package-state-probes-B2iR-0SK.js"; import { n as listExplicitlyDisabledChannelIdsForConfig } from "./config-presence-Cd62ZvYR.js"; import { n as hasExplicitChannelConfig, s as listExplicitConfiguredChannelIdsForConfig, u as resolveConfiguredChannelPresencePolicy } from "./channel-presence-policy-_eDSlojg.js"; import "./channel-plugin-ids-DIyH-LxI.js"; //#region src/commands/doctor/shared/channel-plugin-blockers.ts const CHANNEL_PLUGIN_BLOCKERS_CHECK_ID = "core/doctor/channel-plugin-blockers"; /** Find configured channel ids whose backing plugins cannot activate. */ function scanConfiguredChannelPluginBlockers(cfg, env = process.env, activationSourceConfig = cfg, options = {}) { const explicitChannelIds = listExplicitConfiguredChannelIdsForConfig(cfg).map((channelId) => normalizeOptionalLowercaseString(channelId)).filter((channelId) => Boolean(channelId)); const sourcePluginsConfig = normalizePluginsConfig(activationSourceConfig.plugins); const effectivePluginsConfig = normalizePluginsConfig(cfg.plugins); const manifestRecords = options.manifestRecords ?? loadPluginManifestRegistryForPluginRegistry({ config: cfg, env, includeDisabled: true }).plugins; const packageEnvTriggers = options.ambientEnvTriggers === "suppress" ? /* @__PURE__ */ new Map() : listPackageEnvConfiguredChannelTriggers(manifestRecords, env); const policyChannelIds = resolveConfiguredChannelPresencePolicy({ config: cfg, activationSourceConfig, env, includePersistedAuthState: false, ambientEnvTriggers: options.ambientEnvTriggers, manifestRecords }).filter((entry) => !packageEnvTriggers.has(entry.channelId) || entry.sources.some((source) => source !== "env" && source !== "manifest-env")).map((entry) => entry.channelId); const genericChannelIds = /* @__PURE__ */ new Set([...explicitChannelIds, ...explicitChannelIds.length === 0 ? policyChannelIds : []]); for (const channelId of listExplicitlyDisabledChannelIdsForConfig(cfg)) { const normalizedChannelId = normalizeOptionalLowercaseString(channelId) ?? channelId; genericChannelIds.delete(normalizedChannelId); packageEnvTriggers.delete(normalizedChannelId); } if (genericChannelIds.size === 0 && packageEnvTriggers.size === 0) return []; const hits = []; const hitKeys = /* @__PURE__ */ new Set(); const globalDisableChannelIds = /* @__PURE__ */ new Set(); const addHits = (channelId, ownerStates, channelAvailable = false) => { for (const state of ownerStates) { if (!state.reason) continue; if (state.reason === "plugins disabled") { if (globalDisableChannelIds.has(channelId)) continue; globalDisableChannelIds.add(channelId); } const key = `${channelId}\0${state.pluginId}\0${state.reason}`; if (hitKeys.has(key)) continue; hitKeys.add(key); const hit = { channelId, pluginId: state.pluginId, reason: state.reason }; if (channelAvailable) hit.channelAvailable = true; hits.push(hit); } }; for (const channelId of genericChannelIds) { const ownerStates = manifestRecords.filter((plugin) => plugin.channels.some((rawChannelId) => normalizeOptionalLowercaseString(rawChannelId) === channelId)).map((plugin) => resolveConfiguredChannelOwnerState({ plugin, channelId, sourceConfig: activationSourceConfig, sourcePluginsConfig, effectiveConfig: cfg, effectivePluginsConfig })); if (ownerStates.some((state) => state.available)) continue; addHits(channelId, ownerStates); } for (const [channelId, triggers] of packageEnvTriggers) { const channelOwnerStates = manifestRecords.filter((plugin) => plugin.channels.some((rawChannelId) => normalizeOptionalLowercaseString(rawChannelId) === channelId)).map((plugin) => resolveConfiguredChannelOwnerState({ plugin, channelId, sourceConfig: activationSourceConfig, sourcePluginsConfig, effectiveConfig: cfg, effectivePluginsConfig })); const channelAvailable = channelOwnerStates.some((state) => state.available); for (const pluginIds of triggers.values()) { const ownerStates = channelOwnerStates.filter((state) => pluginIds.has(state.pluginId)); if (ownerStates.some((state) => state.available)) continue; addHits(channelId, ownerStates, channelAvailable); } } return hits; } function listPackageEnvConfiguredChannelTriggers(plugins, env) { const triggersByChannelId = /* @__PURE__ */ new Map(); for (const plugin of plugins) { const ownedChannelIds = new Set(plugin.channels.map((channelId) => normalizeOptionalLowercaseString(channelId)).filter((channelId) => Boolean(channelId))); const channelId = normalizeOptionalLowercaseString(plugin.packageChannel?.id); if (!channelId || !ownedChannelIds.has(channelId)) continue; const channelEnv = plugin.packageChannel?.configuredState?.env; const allOf = channelEnv?.allOf ?? []; const anyOf = channelEnv?.anyOf ?? []; if (allOf.length === 0 && anyOf.length === 0) continue; let triggers = triggersByChannelId.get(channelId); if (!triggers) { triggers = /* @__PURE__ */ new Map(); triggersByChannelId.set(channelId, triggers); } const hasEnvValue = (envVar) => { if (!isSafeChannelEnvVarTriggerName(envVar)) return false; const value = env[envVar] ?? env[envVar.toUpperCase()]; return typeof value === "string" && value.trim().length > 0; }; if (!allOf.every(hasEnvValue) || anyOf.length > 0 && !anyOf.some(hasEnvValue)) continue; for (const envVar of [...allOf, ...anyOf].filter(hasEnvValue)) { const trigger = envVar.trim().toUpperCase(); let ownerIds = triggers.get(trigger); if (!ownerIds) { ownerIds = /* @__PURE__ */ new Set(); triggers.set(trigger, ownerIds); } ownerIds.add(plugin.id); } } return triggersByChannelId; } function resolveConfiguredChannelOwnerState(params) { const bundledChannelConfigured = params.plugin.origin === "bundled" && hasExplicitChannelConfig({ config: params.sourceConfig, channelId: params.channelId }); const sourceAllowlistBypass = bundledChannelConfigured || params.plugin.origin === "workspace" && params.sourcePluginsConfig.slots.contextEngine === params.plugin.id; const sourceBaseBlock = resolveManifestOwnerBasePolicyBlock({ plugin: params.plugin, normalizedConfig: params.sourcePluginsConfig, allowRestrictiveAllowlistBypass: sourceAllowlistBypass }); const sourceExternalTrusted = params.plugin.origin === "bundled" || hasExplicitManifestOwnerTrust({ plugin: params.plugin, normalizedConfig: params.sourcePluginsConfig }) || params.plugin.origin === "workspace" && params.sourcePluginsConfig.slots.contextEngine === params.plugin.id; const sourceBundledActivated = params.plugin.origin === "bundled" && (bundledChannelConfigured || isActivatedManifestOwner({ plugin: params.plugin, normalizedConfig: params.sourcePluginsConfig, rootConfig: params.sourceConfig })); const sourceBundledNeedsExplicitEnablement = params.plugin.origin === "bundled" && !isPluginEnabledByDefaultForPlatform(params.plugin) && params.sourcePluginsConfig.entries[params.plugin.id]?.enabled !== true; const effectiveBundledChannelConfigured = params.plugin.origin === "bundled" && hasExplicitChannelConfig({ config: params.effectiveConfig, channelId: params.channelId }); const effectiveAllowlistBypass = effectiveBundledChannelConfigured || params.plugin.origin === "workspace" && params.effectivePluginsConfig.slots.contextEngine === params.plugin.id; const available = resolveManifestOwnerBasePolicyBlock({ plugin: params.plugin, normalizedConfig: params.effectivePluginsConfig, allowRestrictiveAllowlistBypass: effectiveAllowlistBypass }) === null && sourceExternalTrusted && (effectiveBundledChannelConfigured || isActivatedManifestOwner({ plugin: params.plugin, normalizedConfig: params.effectivePluginsConfig, rootConfig: params.effectiveConfig })); return { pluginId: params.plugin.id, available, reason: available ? void 0 : params.plugin.origin === "bundled" && sourceBaseBlock === "not-in-allowlist" && sourceBundledNeedsExplicitEnablement ? "not enabled and not in allowlist" : mapManifestOwnerBlockerReason(sourceBaseBlock) ?? (!sourceExternalTrusted && sourceBaseBlock === null ? "missing explicit enablement" : params.plugin.origin === "bundled" && sourceBaseBlock === null && !sourceBundledActivated ? "not enabled" : void 0) }; } function mapManifestOwnerBlockerReason(reason) { if (reason === "plugins-disabled") return "plugins disabled"; if (reason === "plugin-disabled") return "disabled in config"; if (reason === "blocked-by-denylist") return "blocked by denylist"; if (reason === "not-in-allowlist") return "not in allowlist"; } function formatReason(hit) { if (hit.reason === "disabled in config") return `plugin "${sanitizeForLog(hit.pluginId)}" is disabled by plugins.entries.${sanitizeForLog(hit.pluginId)}.enabled=false.`; if (hit.reason === "blocked by denylist") return `plugin "${sanitizeForLog(hit.pluginId)}" is blocked by plugins.deny. Remove "${sanitizeForLog(hit.pluginId)}" from plugins.deny.`; if (hit.reason === "plugins disabled") return `plugins.enabled=false blocks channel plugins globally.`; if (hit.reason === "missing explicit enablement") return `external plugin "${sanitizeForLog(hit.pluginId)}" is installed without explicit trust. Add plugins.entries.${sanitizeForLog(hit.pluginId)}.enabled=true.`; if (hit.reason === "not enabled") return `plugin "${sanitizeForLog(hit.pluginId)}" is installed but not enabled. Add plugins.entries.${sanitizeForLog(hit.pluginId)}.enabled=true.`; if (hit.reason === "not enabled and not in allowlist") return `plugin "${sanitizeForLog(hit.pluginId)}" is not enabled and is omitted from plugins.allow. Add plugins.entries.${sanitizeForLog(hit.pluginId)}.enabled=true and include "${sanitizeForLog(hit.pluginId)}" in plugins.allow.`; if (hit.reason === "not in allowlist") return `plugin "${sanitizeForLog(hit.pluginId)}" is installed but omitted from plugins.allow. Include "${sanitizeForLog(hit.pluginId)}" in plugins.allow.`; return `plugin "${sanitizeForLog(hit.pluginId)}" is not loadable (${sanitizeForLog(hit.reason)}).`; } /** Format doctor warnings for configured channels blocked by plugin activation state. */ function collectConfiguredChannelPluginBlockerWarnings(hits) { return hits.map((hit) => `- channels.${sanitizeForLog(hit.channelId)}: channel is configured, but ${formatReason(hit)} Fix plugin enablement before relying on setup guidance for this channel.`); } function stripListMarker(message) { return message.startsWith("- ") ? message.slice(2) : message; } /** Convert a configured channel plugin blocker into a structured Doctor finding. */ function channelPluginBlockerHitToHealthFinding(hit) { return { checkId: CHANNEL_PLUGIN_BLOCKERS_CHECK_ID, severity: "warning", message: stripListMarker(collectConfiguredChannelPluginBlockerWarnings([hit])[0] ?? ""), path: `channels.${hit.channelId}`, target: hit.pluginId, requirement: hit.reason, fixHint: "Fix plugin enablement before relying on setup guidance for this channel." }; } /** Return true when a setup warning targets a channel already explained by plugin blockers. */ function isWarningBlockedByChannelPlugin(warning, hits) { return hits.some((hit) => { if (hit.channelAvailable) return false; const prefix = `channels.${sanitizeForLog(hit.channelId)}`; return warning.includes(`${prefix}:`) || warning.includes(`${prefix}.`); }); } //#endregion export { channelPluginBlockerHitToHealthFinding, collectConfiguredChannelPluginBlockerWarnings, isWarningBlockedByChannelPlugin, scanConfiguredChannelPluginBlockers };