UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

90 lines (89 loc) 3.24 kB
//#region src/plugins/slots.ts const SLOT_BY_KIND = { memory: "memory", "context-engine": "contextEngine" }; const DEFAULT_SLOT_BY_KEY = { memory: "memory-core", contextEngine: "legacy" }; /** Normalize a kind field to an array for uniform iteration. */ function normalizeKinds(kind) { if (!kind) return []; return Array.isArray(kind) ? kind : [kind]; } /** Check whether a plugin's kind field includes a specific kind. */ function hasKind(kind, target) { if (!kind) return false; return Array.isArray(kind) ? kind.includes(target) : kind === target; } /** Order-insensitive equality check for two kind values (string or array). */ function kindsEqual(a, b) { const aN = normalizeKinds(a).toSorted(); const bN = normalizeKinds(b).toSorted(); return aN.length === bN.length && aN.every((k, i) => k === bN[i]); } /** Return all slot keys that a plugin's kind field maps to. */ function slotKeysForPluginKind(kind) { return normalizeKinds(kind).map((k) => SLOT_BY_KIND[k]).filter((k) => k != null); } /** Returns the implicit plugin id that owns a slot before config overrides it. */ function defaultSlotIdForKey(slotKey) { return DEFAULT_SLOT_BY_KEY[slotKey]; } /** Updates config so the selected plugin owns all slots implied by its kind. */ function applyExclusiveSlotSelection(params) { const slotKeys = slotKeysForPluginKind(params.selectedKind); if (slotKeys.length === 0) return { config: params.config, warnings: [], changed: false }; const warnings = []; const pluginsConfig = params.config.plugins ?? {}; let anyChanged = false; const entries = { ...pluginsConfig.entries }; const slots = { ...pluginsConfig.slots }; for (const slotKey of slotKeys) { const prevSlot = slots[slotKey]; slots[slotKey] = params.selectedId; const inferredPrevSlot = prevSlot ?? defaultSlotIdForKey(slotKey); if (inferredPrevSlot && inferredPrevSlot !== params.selectedId) warnings.push(`Exclusive slot "${slotKey}" switched from "${inferredPrevSlot}" to "${params.selectedId}".`); const disabledIds = []; if (params.registry) for (const plugin of params.registry.plugins) { if (plugin.id === params.selectedId) continue; const kindForSlot = Object.keys(SLOT_BY_KIND).find((k) => SLOT_BY_KIND[k] === slotKey); if (!kindForSlot || !hasKind(plugin.kind, kindForSlot)) continue; if (Object.keys(SLOT_BY_KIND).map((k) => SLOT_BY_KIND[k]).filter((sk) => sk !== slotKey).some((sk) => (slots[sk] ?? defaultSlotIdForKey(sk)) === plugin.id)) continue; const entry = entries[plugin.id]; if (!entry || entry.enabled !== false) { entries[plugin.id] = { ...entry, enabled: false }; disabledIds.push(plugin.id); } } if (disabledIds.length > 0) warnings.push(`Disabled other "${slotKey}" slot plugins: ${disabledIds.toSorted().join(", ")}.`); if (prevSlot !== params.selectedId || disabledIds.length > 0) anyChanged = true; } if (!anyChanged) return { config: params.config, warnings: [], changed: false }; return { config: { ...params.config, plugins: { ...pluginsConfig, slots, entries } }, warnings, changed: true }; } //#endregion export { kindsEqual as i, defaultSlotIdForKey as n, hasKind as r, applyExclusiveSlotSelection as t };