openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
206 lines (205 loc) • 11.4 kB
JavaScript
import { c as normalizeOptionalLowercaseString } from "./string-coerce-1VuiLaaR.mjs";
import { n as sanitizeForLog } from "./ansi-DyIsQZAA.mjs";
import { t as isPluginEnabledByDefaultForPlatform } from "./default-enablement-CEIbpabL.mjs";
import { u as normalizePluginsConfig } from "./config-state-Ba1MVBAI.mjs";
import { a as isSafeChannelEnvVarTriggerName } from "./package-state-probes-DQKrSE4l.mjs";
import { t as listExplicitlyDisabledChannelIdsForConfig } from "./config-presence-CaTtZ_Jm.mjs";
import { a as resolveManifestOwnerBasePolicyBlock, n as isActivatedManifestOwner, t as hasExplicitManifestOwnerTrust } from "./manifest-owner-policy-Cqbh_mxQ.mjs";
import { n as loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry-contributions-vIYsvMGK.mjs";
import { n as hasExplicitChannelConfig, s as listExplicitConfiguredChannelIdsForConfig, u as resolveConfiguredChannelPresencePolicy } from "./channel-presence-policy-CZfPoPKL.mjs";
import "./plugin-registry-qMoFDG9O.mjs";
import "./channel-plugin-ids-Dy16pCvQ.mjs";
//#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);
}
};
const resolveChannelOwnerStates = (channelId) => manifestRecords.filter((plugin) => plugin.channels.some((rawChannelId) => normalizeOptionalLowercaseString(rawChannelId) === channelId)).map((plugin) => resolveConfiguredChannelOwnerState({
plugin,
channelId,
sourceConfig: activationSourceConfig,
sourcePluginsConfig,
effectiveConfig: cfg,
effectivePluginsConfig
}));
for (const channelId of genericChannelIds) {
const ownerStates = resolveChannelOwnerStates(channelId);
if (ownerStates.some((state) => state.available)) continue;
addHits(channelId, ownerStates);
}
for (const [channelId, triggers] of packageEnvTriggers) {
const channelOwnerStates = resolveChannelOwnerStates(channelId);
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 resolveBase = (config, normalizedConfig) => {
const bundledChannelConfigured = params.plugin.origin === "bundled" && hasExplicitChannelConfig({
config,
channelId: params.channelId
});
const workspaceSlot = params.plugin.origin === "workspace" && normalizedConfig.slots.contextEngine === params.plugin.id;
return {
bundledChannelConfigured,
workspaceSlot,
block: resolveManifestOwnerBasePolicyBlock({
plugin: params.plugin,
normalizedConfig,
allowRestrictiveAllowlistBypass: bundledChannelConfigured || workspaceSlot
})
};
};
const source = resolveBase(params.sourceConfig, params.sourcePluginsConfig);
const sourceBaseBlock = source.block;
const sourceExternalTrusted = params.plugin.origin === "bundled" || hasExplicitManifestOwnerTrust({
plugin: params.plugin,
normalizedConfig: params.sourcePluginsConfig
}) || source.workspaceSlot;
const sourceBundledActivated = params.plugin.origin === "bundled" && (source.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 effective = resolveBase(params.effectiveConfig, params.effectivePluginsConfig);
const available = effective.block === null && sourceExternalTrusted && (effective.bundledChannelConfigured || 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) {
return reason === null ? void 0 : {
"plugins-disabled": "plugins disabled",
"plugin-disabled": "disabled in config",
"blocked-by-denylist": "blocked by denylist",
"not-in-allowlist": "not in allowlist"
}[reason];
}
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.`;
return `plugin "${sanitizeForLog(hit.pluginId)}" is installed but omitted from plugins.allow. Include "${sanitizeForLog(hit.pluginId)}" in plugins.allow.`;
}
function formatChannelPluginBlocker(hit) {
return `channels.${sanitizeForLog(hit.channelId)}: channel is configured, but ${formatReason(hit)} Fix plugin enablement before relying on setup guidance for this channel.`;
}
/** Format doctor warnings for configured channels blocked by plugin activation state. */
function collectConfiguredChannelPluginBlockerWarnings(hits) {
return hits.map((hit) => `- ${formatChannelPluginBlocker(hit)}`);
}
/** Convert a configured channel plugin blocker into a structured Doctor finding. */
function channelPluginBlockerHitToHealthFinding(hit) {
return {
checkId: CHANNEL_PLUGIN_BLOCKERS_CHECK_ID,
severity: "warning",
message: formatChannelPluginBlocker(hit),
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 };