openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
344 lines (343 loc) • 13.2 kB
JavaScript
import { c as normalizeOptionalLowercaseString, l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-1VuiLaaR.mjs";
import { r as resolveGlobalMap } from "./global-singleton-0m-JziJW.mjs";
import { d as resolveAgentWorkspaceDir, r as resolveAgentConfig } from "./agent-scope-config-CDYpzA0r.mjs";
import "./session-key-C09ow4h0.mjs";
import { n as normalizeAccountId } from "./account-id-DbRsdayc.mjs";
import { c as resolveAgentExplicitModelPrimary } from "./agent-scope-CG17uXFn.mjs";
import { r as getPluginRegistryForContext } from "./gateway-request-scope-BSmCVVpP.mjs";
import { r as getLoadedChannelPluginEntryById } from "./registry-loaded-BugfxX6l.mjs";
import { n as parseModelRef } from "./model-selection-normalize-AjjSfI-g.mjs";
import { n as resolveConfiguredThinkingDefaultCore } from "./model-thinking-default-twlQ6xyp.mjs";
import { r as listConfiguredBindings } from "./bindings-Cw_QSeBA.mjs";
import { a as pickFirstExistingAgentId } from "./resolve-route-DYoHvZlS.mjs";
import { i as parseConfiguredAcpSessionKey, n as normalizeBindingConfig, o as toConfiguredAcpBindingRecord, r as normalizeMode, t as buildConfiguredAcpSessionKey } from "./persistent-bindings.types-DfGgDDKL.mjs";
//#region src/channels/plugins/acp-configured-binding-consumer.ts
function resolveAgentRuntimeAcpDefaults(params) {
const ownerAgentId = normalizeLowercaseStringOrEmpty(params.ownerAgentId);
const agent = resolveAgentConfig(params.cfg, ownerAgentId);
if (!agent || agent.runtime?.type !== "acp") return {};
return {
acpAgentId: normalizeOptionalString(agent.runtime.acp?.agent),
mode: normalizeOptionalString(agent.runtime.acp?.mode),
cwd: normalizeOptionalString(agent.runtime.acp?.cwd),
backend: normalizeOptionalString(agent.runtime.acp?.backend)
};
}
function resolveConfiguredBindingWorkspaceCwd(params) {
if (normalizeOptionalString(resolveAgentConfig(params.cfg, params.agentId)?.workspace) || normalizeOptionalString(params.cfg.agents?.defaults?.workspace)) return resolveAgentWorkspaceDir(params.cfg, params.agentId);
}
function buildAcpTargetFactory(params) {
if (params.binding.type !== "acp") return null;
const runtimeDefaults = resolveAgentRuntimeAcpDefaults({
cfg: params.cfg,
ownerAgentId: params.agentId
});
const bindingOverrides = normalizeBindingConfig(params.binding.acp);
const mode = normalizeMode(bindingOverrides.mode ?? runtimeDefaults.mode);
const model = resolveAgentExplicitModelPrimary(params.cfg, params.agentId);
const modelRef = model ? parseModelRef(model, "") : null;
const thinking = resolveAgentConfig(params.cfg, params.agentId)?.thinkingDefault ?? (modelRef ? resolveConfiguredThinkingDefaultCore({
cfg: params.cfg,
...modelRef
}) : params.cfg.agents?.defaults?.thinkingDefault);
const cwd = bindingOverrides.cwd ?? runtimeDefaults.cwd ?? resolveConfiguredBindingWorkspaceCwd({
cfg: params.cfg,
agentId: params.agentId
});
const backend = bindingOverrides.backend ?? runtimeDefaults.backend;
const label = bindingOverrides.label;
return {
driverId: "acp",
materialize: ({ accountId, conversation }) => {
const spec = {
channel: params.channel,
accountId,
conversationId: conversation.conversationId,
parentConversationId: conversation.parentConversationId,
agentId: params.agentId,
acpAgentId: runtimeDefaults.acpAgentId,
mode,
model,
thinking,
cwd,
backend,
label
};
return {
record: toConfiguredAcpBindingRecord(spec),
statefulTarget: {
kind: "stateful",
driverId: "acp",
sessionKey: buildConfiguredAcpSessionKey(spec),
agentId: params.agentId,
...label ? { label } : {}
}
};
}
};
}
/**
* Configured binding consumer that materializes ACP persistent or oneshot targets.
*/
const acpConfiguredBindingConsumer = {
id: "acp",
supports: (binding) => binding.type === "acp",
buildTargetFactory: buildAcpTargetFactory,
parseSessionKey: ({ sessionKey }) => parseConfiguredAcpSessionKey(sessionKey),
matchesSessionKey: ({ sessionKey, materializedTarget }) => materializedTarget.record.targetSessionKey === sessionKey
};
//#endregion
//#region src/channels/plugins/configured-binding-consumers.ts
const registeredConfiguredBindingConsumers = resolveGlobalMap(Symbol.for("openclaw.configuredBindingConsumers"), "plugin-registry");
/**
* Lists registered configured binding consumers in registration order.
*/
function listConfiguredBindingConsumers() {
return [...registeredConfiguredBindingConsumers.values()];
}
/**
* Finds the first configured binding consumer that supports a raw binding rule.
*/
function resolveConfiguredBindingConsumer(binding) {
return listConfiguredBindingConsumers().find((consumer) => consumer.supports(binding)) ?? null;
}
/**
* Registers a configured binding consumer idempotently by trimmed id.
*/
function registerConfiguredBindingConsumer(consumer) {
const id = consumer.id.trim();
if (!id) throw new Error("Configured binding consumer id is required");
if (registeredConfiguredBindingConsumers.get(id)) return;
registeredConfiguredBindingConsumers.set(id, {
...consumer,
id
});
}
//#endregion
//#region src/channels/plugins/configured-binding-builtins.ts
/**
* Registers configured binding consumers bundled with core.
*/
function ensureConfiguredBindingBuiltinsRegistered() {
registerConfiguredBindingConsumer(acpConfiguredBindingConsumer);
}
//#endregion
//#region src/channels/plugins/configured-binding-compiler.ts
function resolveConfiguredBindingAdapter(channel) {
const normalized = normalizeOptionalLowercaseString(channel);
if (!normalized) return null;
const plugin = getLoadedChannelPluginEntryById(normalized, getPluginRegistryForContext() ?? void 0)?.plugin;
const provider = plugin?.bindings;
if (!plugin || !provider || !provider.compileConfiguredBinding || !provider.matchInboundConversation) return null;
return {
channel: plugin.id,
provider
};
}
function resolveCompiledBindingRegistry(cfg) {
const rulesByChannel = /* @__PURE__ */ new Map();
for (const binding of listConfiguredBindings(cfg)) {
const consumer = resolveConfiguredBindingConsumer(binding);
if (!consumer) continue;
const bindingConversationId = normalizeOptionalString(binding.match?.peer?.id);
if (!bindingConversationId) continue;
const resolvedChannel = resolveConfiguredBindingAdapter(binding.match.channel);
if (!resolvedChannel) continue;
const target = resolvedChannel.provider.compileConfiguredBinding({
binding,
conversationId: bindingConversationId
});
if (!target) continue;
const agentId = pickFirstExistingAgentId(cfg, binding.agentId ?? "main");
const targetFactory = consumer.buildTargetFactory({
cfg,
binding,
channel: resolvedChannel.channel,
agentId,
target,
bindingConversationId
});
if (!targetFactory) continue;
const rule = {
channel: resolvedChannel.channel,
accountPattern: normalizeOptionalString(binding.match.accountId),
binding,
bindingConversationId,
target,
agentId,
provider: resolvedChannel.provider,
targetFactory
};
const existing = rulesByChannel.get(rule.channel);
if (existing) existing.push(rule);
else rulesByChannel.set(rule.channel, [rule]);
}
return { rulesByChannel };
}
//#endregion
//#region src/channels/plugins/configured-binding-match.ts
/**
* Ranks account pattern matches for configured binding rules.
*/
function resolveAccountMatchPriority(match, actual) {
const trimmed = (match ?? "").trim();
if (!trimmed) return actual === "default" ? 2 : 0;
if (trimmed === "*") return 1;
return normalizeAccountId(trimmed) === actual ? 2 : 0;
}
/**
* Normalizes a raw channel id into a configured-binding channel id.
*/
function resolveCompiledBindingChannel(raw) {
const normalized = normalizeOptionalLowercaseString(raw);
return normalized ? normalized : null;
}
/**
* Converts an outbound conversation ref into configured-binding match input.
*/
function toConfiguredBindingConversationRef(conversation) {
const channel = resolveCompiledBindingChannel(conversation.channel);
const conversationId = conversation.conversationId.trim();
if (!channel || !conversationId) return null;
return {
channel,
accountId: normalizeAccountId(conversation.accountId),
conversationId,
parentConversationId: normalizeOptionalString(conversation.parentConversationId)
};
}
/**
* Resolves the best configured binding rule for a conversation.
*/
function resolveMatchingConfiguredBinding(params) {
if (!params.conversation) return null;
let bestMatch = null;
let bestAccountPriority = 0;
let bestMatchPriority = 0;
for (const rule of params.rules) {
const accountMatchPriority = resolveAccountMatchPriority(rule.accountPattern, params.conversation.accountId);
if (accountMatchPriority === 0) continue;
const match = rule.provider.matchInboundConversation({
binding: rule.binding,
compiledBinding: rule.target,
conversationId: params.conversation.conversationId,
parentConversationId: params.conversation.parentConversationId
});
if (!match) continue;
const matchPriority = match.matchPriority ?? 0;
if (!bestMatch || accountMatchPriority > bestAccountPriority || accountMatchPriority === bestAccountPriority && matchPriority > bestMatchPriority) {
bestMatch = {
rule,
match
};
bestAccountPriority = accountMatchPriority;
bestMatchPriority = matchPriority;
}
}
return bestMatch;
}
//#endregion
//#region src/channels/plugins/configured-binding-session-lookup.ts
/**
* Resolves a configured binding record from a stateful target session key.
*/
function resolveConfiguredBindingRecordBySessionKeyFromRegistry(params) {
const sessionKey = params.sessionKey.trim();
if (!sessionKey) return null;
for (const consumer of listConfiguredBindingConsumers()) {
const parsed = consumer.parseSessionKey?.({ sessionKey });
if (!parsed) continue;
const channel = resolveCompiledBindingChannel(parsed.channel);
if (!channel) continue;
const rules = params.registry.rulesByChannel.get(channel);
if (!rules || rules.length === 0) continue;
let wildcardMatch = null;
for (const rule of rules) {
if (rule.targetFactory.driverId !== consumer.id) continue;
const accountMatchPriority = resolveAccountMatchPriority(rule.accountPattern, parsed.accountId);
if (accountMatchPriority === 0) continue;
const materializedTarget = rule.targetFactory.materialize({
accountId: normalizeAccountId(parsed.accountId),
conversation: rule.target
});
if (consumer.matchesSessionKey?.({
sessionKey,
compiledBinding: rule,
accountId: parsed.accountId,
materializedTarget
}) ?? materializedTarget.record.targetSessionKey === sessionKey) {
if (accountMatchPriority === 2) return materializedTarget;
wildcardMatch = materializedTarget;
}
}
if (wildcardMatch) return wildcardMatch;
}
return null;
}
//#endregion
//#region src/channels/plugins/configured-binding-registry.ts
function resolveMaterializedConfiguredBinding(params) {
const conversation = toConfiguredBindingConversationRef(params.conversation);
if (!conversation) return null;
const rules = resolveCompiledBindingRegistry(params.cfg).rulesByChannel.get(conversation.channel);
if (!rules || rules.length === 0) return null;
const resolved = resolveMatchingConfiguredBinding({
rules,
conversation
});
if (!resolved) return null;
return {
conversation,
resolved,
materializedTarget: resolved.rule.targetFactory.materialize({
accountId: conversation.accountId,
conversation: resolved.match
})
};
}
/** Compile plugin binding rules before publishing a config or plugin generation. */
function validateConfiguredBindings(cfg) {
ensureConfiguredBindingBuiltinsRegistered();
resolveCompiledBindingRegistry(cfg);
}
/**
* Resolves a configured binding record from explicit channel/account/conversation ids.
*/
function resolveConfiguredBindingRecord(params) {
ensureConfiguredBindingBuiltinsRegistered();
return resolveMaterializedConfiguredBinding({
cfg: params.cfg,
conversation: {
channel: params.channel,
accountId: params.accountId,
conversationId: params.conversationId,
parentConversationId: params.parentConversationId
}
})?.materializedTarget ?? null;
}
/**
* Resolves the full configured binding match, including compiled rule and match diagnostics.
*/
function resolveConfiguredBinding(params) {
ensureConfiguredBindingBuiltinsRegistered();
const resolved = resolveMaterializedConfiguredBinding(params);
if (!resolved) return null;
return {
conversation: resolved.conversation,
compiledBinding: resolved.resolved.rule,
match: resolved.resolved.match,
...resolved.materializedTarget
};
}
/**
* Resolves a configured binding record by the stateful target session key.
*/
function resolveConfiguredBindingRecordBySessionKey(params) {
ensureConfiguredBindingBuiltinsRegistered();
return resolveConfiguredBindingRecordBySessionKeyFromRegistry({
registry: resolveCompiledBindingRegistry(params.cfg),
sessionKey: params.sessionKey
});
}
//#endregion
export { validateConfiguredBindings as i, resolveConfiguredBindingRecord as n, resolveConfiguredBindingRecordBySessionKey as r, resolveConfiguredBinding as t };