UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

258 lines (257 loc) • 11.5 kB
import { f as asSafeIntegerInRange } from "./number-coercion-Dq1l5muL.mjs"; import { c as isRecord } from "./record-coerce-TIsquoVR.mjs"; import { r as normalizeArrayBackedTrimmedStringList } from "./string-normalization-YMwDjufr.mjs"; import { t as normalizePluginPolicyId } from "./plugin-policy-id-BaT4nwBS.mjs"; import { i as normalizeChatChannelId } from "./ids-Cua-jgDU.mjs"; import { a as normalizeSlotValue, s as resolveSlotSelection } from "./slots-CSgIxf6O.mjs"; //#region src/plugins/config-activation-shared.ts const PLUGIN_ACTIVATION_REASON_BY_CAUSE = { "enabled-in-config": "enabled in config", "bundled-channel-enabled-in-config": "channel enabled in config", "selected-memory-slot": "selected memory slot", "selected-context-engine-slot": "selected context engine slot", "selected-in-allowlist": "selected in allowlist", "plugins-disabled": "plugins disabled", "blocked-by-denylist": "blocked by denylist", "disabled-in-config": "disabled in config", "channel-disabled-in-config": "channel disabled in config", "workspace-disabled-by-default": "workspace plugin (disabled by default)", "not-in-allowlist": "not in allowlist", "enabled-by-effective-config": "enabled by effective config", "bundled-channel-configured": "channel configured", "bundled-default-enablement": "bundled default enablement", "bundled-disabled-by-default": "bundled (disabled by default)" }; function toPluginActivationState(decision) { return { enabled: decision.enabled, activated: decision.activated, explicitlyEnabled: decision.explicitlyEnabled, source: decision.source, reason: decision.reason || (decision.cause ? PLUGIN_ACTIVATION_REASON_BY_CAUSE[decision.cause] : void 0) }; } function resolveExplicitPluginSelectionShared(params) { const policyId = normalizePluginPolicyId(params.id); if (params.config.entries[policyId]?.enabled === true) return { explicitlyEnabled: true, cause: "enabled-in-config" }; if (params.origin === "bundled" && params.resolveChannelConfigEnablement(params.rootConfig, params.id, params.channelIds) === true) return { explicitlyEnabled: true, cause: "bundled-channel-enabled-in-config" }; if (params.config.slots.memory === params.id) return { explicitlyEnabled: true, cause: "selected-memory-slot" }; if (params.config.slots.contextEngine === params.id) return { explicitlyEnabled: true, cause: "selected-context-engine-slot" }; if (params.origin !== "bundled" && params.config.allow.includes(policyId)) return { explicitlyEnabled: true, cause: "selected-in-allowlist" }; return { explicitlyEnabled: false }; } function resolvePluginActivationDecisionShared(params) { const activationSource = params.activationSource ?? { plugins: params.config, rootConfig: params.rootConfig }; const explicitSelection = resolveExplicitPluginSelectionShared({ id: params.id, origin: params.origin, config: activationSource.plugins, rootConfig: activationSource.rootConfig, channelIds: params.channelIds, resolveChannelConfigEnablement: params.resolveChannelConfigEnablement }); const decision = (source, details = {}) => ({ enabled: source !== "disabled", activated: source !== "disabled", explicitlyEnabled: explicitSelection.explicitlyEnabled, source, ...details }); if (!params.config.enabled) return decision("disabled", { cause: "plugins-disabled" }); const policyId = normalizePluginPolicyId(params.id); if (params.config.deny.includes(policyId)) return decision("disabled", { cause: "blocked-by-denylist" }); const entry = params.config.entries[policyId]; if (entry?.enabled === false) return decision("disabled", { cause: "disabled-in-config" }); if (params.resolveChannelConfigEnablement(activationSource.rootConfig ?? params.rootConfig, params.id, params.channelIds) === false) return decision("disabled", { cause: "channel-disabled-in-config" }); const explicitlyAllowed = params.config.allow.includes(policyId); if (params.origin === "workspace" && !explicitlyAllowed && entry?.enabled !== true && explicitSelection.cause !== "selected-context-engine-slot") return decision("disabled", { cause: "workspace-disabled-by-default" }); if (params.config.slots.memory === params.id) return decision("explicit", { explicitlyEnabled: true, cause: "selected-memory-slot" }); if (params.config.slots.contextEngine === params.id) return decision("explicit", { explicitlyEnabled: true, cause: "selected-context-engine-slot" }); if (params.allowBundledChannelExplicitBypassesAllowlist === true && explicitSelection.cause === "bundled-channel-enabled-in-config") return decision("explicit", { explicitlyEnabled: true, cause: explicitSelection.cause }); if (params.config.allow.length > 0 && !explicitlyAllowed) return decision("disabled", { cause: "not-in-allowlist" }); if (explicitSelection.explicitlyEnabled) return decision("explicit", { explicitlyEnabled: true, cause: explicitSelection.cause }); if (params.autoEnabledReason) return decision("auto", { explicitlyEnabled: false, reason: params.autoEnabledReason }); if (entry?.enabled === true) return decision("auto", { explicitlyEnabled: false, cause: "enabled-by-effective-config" }); if (params.origin === "bundled" && params.resolveChannelConfigEnablement(params.rootConfig, params.id, params.channelIds) === true) return decision("auto", { explicitlyEnabled: false, cause: "bundled-channel-configured" }); if (params.origin === "bundled" && params.enabledByDefault === true) return decision("default", { explicitlyEnabled: false, cause: "bundled-default-enablement" }); if (params.origin === "bundled") return decision("disabled", { explicitlyEnabled: false, cause: "bundled-disabled-by-default" }); return decision("default"); } function hasKind(kind, target) { if (!kind) return false; return Array.isArray(kind) ? kind.includes(target) : kind === target; } function resolveMemorySlotDecisionShared(params) { if (!hasKind(params.kind, "memory")) return { enabled: true }; const isMultiKind = Array.isArray(params.kind) && params.kind.length > 1; if (params.slot === null) return isMultiKind ? { enabled: true } : { enabled: false, reason: "memory slot disabled" }; if (typeof params.slot === "string") { if (params.slot === params.id) return { enabled: true, selected: true }; return isMultiKind ? { enabled: true } : { enabled: false, reason: `memory slot set to "${params.slot}"` }; } if (params.selectedId && params.selectedId !== params.id) return isMultiKind ? { enabled: true } : { enabled: false, reason: `memory slot already filled by "${params.selectedId}"` }; return { enabled: true, selected: true }; } //#endregion //#region src/plugins/config-normalization-shared.ts /** Default plugin id normalizer for already-canonical ids. */ const identityNormalizePluginId = (id) => id.trim(); function normalizePluginConfigList(value, normalizePluginId) { if (!Array.isArray(value)) return []; return value.map((entry) => typeof entry === "string" ? normalizePluginId(entry) : "").filter(Boolean); } function normalizeHookTimeoutMs(value) { return asSafeIntegerInRange(value, { min: 1, max: 6e5 }); } function normalizeHookTimeouts(value) { if (!isRecord(value)) return; const normalized = {}; for (const [hookName, timeoutMs] of Object.entries(value)) { const normalizedTimeoutMs = normalizeHookTimeoutMs(timeoutMs); if (normalizedTimeoutMs !== void 0) normalized[hookName] = normalizedTimeoutMs; } return Object.keys(normalized).length > 0 ? normalized : void 0; } function normalizePluginHooks(value) { if (!isRecord(value)) return; const hooks = {}; for (const key of ["allowPromptInjection", "allowConversationAccess"]) if (typeof value[key] === "boolean") hooks[key] = value[key]; const timeoutMs = normalizeHookTimeoutMs(value.timeoutMs); const timeouts = normalizeHookTimeouts(value.timeouts); if (timeoutMs !== void 0) hooks.timeoutMs = timeoutMs; if (timeouts !== void 0) hooks.timeouts = timeouts; return Object.keys(hooks).length > 0 ? hooks : void 0; } function normalizePluginModelConfig(value, kind) { if (!isRecord(value)) return; const config = {}; if (typeof value.allowModelOverride === "boolean") config.allowModelOverride = value.allowModelOverride; for (const [key, configuredKey] of [["allowedModels", "hasAllowedModelsConfig"], ["allowedCompletionModels", "hasAllowedCompletionModelsConfig"]]) { if (key === "allowedCompletionModels" && kind !== "llm") continue; const models = normalizeArrayBackedTrimmedStringList(value[key]); if (models) { config[configuredKey] = true; if (models.length > 0) config[key] = models; } } if (kind === "llm") { for (const key of ["allowAuthProfileOverride", "allowAgentIdOverride"]) if (typeof value[key] === "boolean") config[key] = value[key]; } return Object.keys(config).length > 0 ? config : void 0; } function normalizePluginEntries(entries, normalizePluginId) { if (!isRecord(entries)) return {}; const normalized = {}; for (const [key, value] of Object.entries(entries)) { const normalizedKey = normalizePluginId(key); if (!normalizedKey) continue; if (!isRecord(value)) { normalized[normalizedKey] = {}; continue; } const entry = value; normalized[normalizedKey] = { ...normalized[normalizedKey], enabled: typeof entry.enabled === "boolean" ? entry.enabled : normalized[normalizedKey]?.enabled, hooks: normalizePluginHooks(entry.hooks) ?? normalized[normalizedKey]?.hooks, subagent: normalizePluginModelConfig(entry.subagent, "subagent") ?? normalized[normalizedKey]?.subagent, llm: normalizePluginModelConfig(entry.llm, "llm") ?? normalized[normalizedKey]?.llm, config: "config" in entry ? entry.config : normalized[normalizedKey]?.config }; } return normalized; } /** Normalizes plugin config while allowing callers to resolve aliases first. */ function normalizePluginsConfigWithResolverCore(config, normalizePluginId = identityNormalizePluginId) { const memorySlot = resolveSlotSelection("memory", config?.slots?.memory); return { enabled: config?.enabled ?? true, allow: normalizePluginConfigList(config?.allow, normalizePluginId), deny: normalizePluginConfigList(config?.deny, normalizePluginId), loadPaths: normalizePluginConfigList(config?.load?.paths, identityNormalizePluginId), slots: { memory: memorySlot.kind === "off" ? null : memorySlot.pluginId, contextEngine: normalizeSlotValue(config?.slots?.contextEngine) }, entries: normalizePluginEntries(config?.entries, normalizePluginId) }; } /** * Enables an owner for any enabled channel; disables it only when all channels are off. * Unspecified channels leave the plugin's own activation policy in control. */ function resolveChannelConfigEnablement(cfg, pluginId, channelIds = []) { const channels = cfg?.channels; if (!channels) return; const enablement = (channelIds.length ? channelIds.map((channelId) => normalizeChatChannelId(channelId) ?? channelId) : [normalizeChatChannelId(pluginId)]).map((channelId) => { const entry = channelId ? channels[channelId] : void 0; return isRecord(entry) ? entry.enabled : void 0; }); if (enablement.includes(true)) return true; return enablement.every((enabled) => enabled === false) ? false : void 0; } //#endregion export { resolvePluginActivationDecisionShared as a, resolveMemorySlotDecisionShared as i, normalizePluginsConfigWithResolverCore as n, toPluginActivationState as o, resolveChannelConfigEnablement as r, normalizePluginConfigList as t };