openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
85 lines (84 loc) • 4.14 kB
JavaScript
import { c as isRecord, r as asNullableRecord } from "./record-coerce-DItp3I4t.js";
import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js";
import { o as listAgentIds, t as AgentSelectionRequiredError } from "./agent-scope-config-DcbEhP0R.js";
import "./session-key-BnWWjqNc.js";
import { n as normalizeAccountId } from "./account-id-CETVCrTz.js";
import { n as resolveNormalizedAccountEntry } from "./account-lookup-CvFhSs3G.js";
import { r as listChannelAccountRouteBindings, s as resolveAgentRoute } from "./resolve-route-BRXfbiKP.js";
import { n as resolveReadOnlyChannelPluginsForConfig } from "./read-only-0zbnWxaR.js";
//#region src/commands/doctor/shared/legacy-config-binding-repair.ts
function pruneBindingsForMissingAgents(cfg, changes) {
const agents = cfg.agents?.list;
const bindings = cfg.bindings;
if (!Array.isArray(agents) || agents.length === 0 || !Array.isArray(bindings)) return cfg;
const validAgents = agents.filter((agent) => {
return agent !== null && typeof agent === "object" && typeof agent.id === "string";
});
if (validAgents.length !== agents.length) return cfg;
const agentIds = new Set(validAgents.map((agent) => normalizeAgentId(agent.id)));
const nextBindings = bindings.filter((binding) => {
const agentId = binding && typeof binding === "object" ? binding.agentId : void 0;
return typeof agentId !== "string" || agentId === "main" || agentIds.has(normalizeAgentId(agentId));
});
const removed = bindings.length - nextBindings.length;
if (removed === 0) return cfg;
changes.push(`Removed ${removed} binding${removed === 1 ? "" : "s"} that referenced missing agents.list ids.`);
return {
...cfg,
...nextBindings.length > 0 ? { bindings: nextBindings } : { bindings: void 0 }
};
}
/** Materialize only channel-account owners already established by narrower route bindings. */
function repairUnownedChannelAccountBindings(cfg) {
const agentIds = new Set(listAgentIds(cfg));
const additions = [];
if (agentIds.size < 2 || cfg.plugins?.enabled === false || !Array.isArray(cfg.bindings) || cfg.bindings.length === 0 || !cfg.bindings.every((binding) => isRecord(binding) && isRecord(binding.match) && typeof binding.agentId === "string" && binding.agentId.trim().length > 0 && typeof binding.match.channel === "string" && (binding.match.accountId === void 0 || typeof binding.match.accountId === "string"))) return {
config: cfg,
changes: []
};
const inventory = resolveReadOnlyChannelPluginsForConfig(cfg, {
includePersistedAuthState: false,
includeSetupFallbackPlugins: true
});
const plugins = new Map(inventory.plugins.map((plugin) => [plugin.id, plugin]));
for (const channelId of [...inventory.configuredChannelIds].toSorted()) {
const plugin = plugins.get(channelId);
const channel = asNullableRecord(cfg.channels?.[channelId]);
if (!plugin || channel?.enabled === false) continue;
const accounts = asNullableRecord(channel?.accounts) ?? void 0;
const accountIds = [...new Set(plugin.config.listAccountIds(cfg).map(normalizeAccountId))].toSorted();
for (const accountId of accountIds) {
const account = resolveNormalizedAccountEntry(accounts, accountId, normalizeAccountId);
if (asNullableRecord(account)?.enabled === false) continue;
const routeInput = {
cfg,
channel: channelId,
accountId
};
try {
resolveAgentRoute(routeInput);
continue;
} catch (error) {
if (!(error instanceof AgentSelectionRequiredError)) throw error;
}
const owners = new Set(listChannelAccountRouteBindings(routeInput).map((binding) => normalizeAgentId(binding.agentId)));
const [agentId] = owners;
if (owners.size === 1 && agentId && agentIds.has(agentId)) additions.push({
agentId,
match: {
channel: channelId,
accountId
}
});
}
}
return {
config: additions.length ? {
...cfg,
bindings: [...cfg.bindings, ...additions]
} : cfg,
changes: additions.map(({ agentId, match }) => `Bound ${match.channel}:${match.accountId} to its sole configured route owner "${agentId}".`)
};
}
//#endregion
export { repairUnownedChannelAccountBindings as n, pruneBindingsForMissingAgents as t };