openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
103 lines (102 loc) • 5.52 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { l as resolveAgentIdFromSessionKey, s as isUnscopedSessionKeySentinel, x as isCronRunSessionKey } from "./session-key-C09ow4h0.mjs";
import { t as isPluginOwnedBindingMetadata } from "./conversation-binding-metadata-CFOhDjMh.mjs";
//#region src/channels/conversation-binding-route-facts.ts
/** The same normalization governs initial projection and later ownership comparison. */
function resolveConversationBindingSelection(binding) {
const sessionKey = binding?.targetSessionKey?.trim();
if (!binding || !sessionKey) return { kind: "none" };
if (isCronRunSessionKey(sessionKey)) return {
kind: "none",
ignoredCronSessionKey: sessionKey
};
const metadata = binding.metadata;
if (isPluginOwnedBindingMetadata(metadata)) {
const pluginId = metadata.pluginId.trim();
if (pluginId) return {
kind: "plugin",
binding,
pluginId,
pluginRoot: metadata.pluginRoot
};
}
return {
kind: "agent",
binding,
sessionKey
};
}
function resolveConversationBindingAgentId(binding, fallbackAgentId) {
const sessionKey = binding.targetSessionKey.trim();
return resolveAgentIdFromSessionKey(sessionKey, isUnscopedSessionKeySentinel(sessionKey) ? normalizeOptionalString(binding.metadata?.agentId) ?? fallbackAgentId : void 0);
}
const BINDING_ROUTE_FACTS = Symbol.for("openclaw.conversationBindingRouteFacts");
function withConversationBindingRouteFacts(route, selection, fallbackAgentId, conversation) {
const previous = readConversationBindingRouteFacts(route);
const sameConversation = previous && previous.conversation.channel === conversation.channel && previous.conversation.accountId === conversation.accountId && previous.conversation.conversationId === conversation.conversationId && previous.conversation.parentConversationId === conversation.parentConversationId;
const scope = {
agentId: route.agentId,
observedAgentId: selection.kind === "agent" ? resolveConversationBindingAgentId(selection.binding, fallbackAgentId) : route.agentId,
previous: sameConversation ? previous.previous : previous,
fallbackAgentId,
conversation: Object.freeze({ ...conversation })
};
let facts;
if (selection.kind === "none" || selection.kind === "unavailable") facts = Object.freeze({
...scope,
kind: selection.kind
});
else {
const { binding } = selection;
const identity = {
...scope,
bindingId: binding.bindingId,
boundAt: binding.boundAt,
targetSessionKey: binding.targetSessionKey,
targetKind: binding.targetKind,
bindingConversation: Object.freeze({ ...binding.conversation })
};
facts = selection.kind === "plugin" ? Object.freeze({
...identity,
kind: "plugin",
pluginId: selection.pluginId,
pluginRoot: selection.pluginRoot
}) : Object.freeze({
...identity,
kind: "agent"
});
}
return Object.assign(route, { [BINDING_ROUTE_FACTS]: facts });
}
function readConversationBindingRouteFacts(value) {
return value[BINDING_ROUTE_FACTS];
}
function copyConversationBindingRouteFacts(route, context) {
const facts = readConversationBindingRouteFacts(route);
const selectedSessionKey = route.dispatchSessionKey ?? route.sessionKey;
if (facts && selectedSessionKey === context.SessionKey && facts.agentId === context.AgentId) Object.assign(context, { [BINDING_ROUTE_FACTS]: facts });
}
function matchesConversationBindingRouteFacts(expected, current) {
if (expected.kind === "unavailable") return false;
const selection = resolveConversationBindingSelection(current);
if (selection.kind === "none") return expected.kind === "none";
if (expected.kind === "none" || expected.kind !== selection.kind) return false;
const binding = selection.binding;
if (binding.bindingId !== expected.bindingId || binding.boundAt !== expected.boundAt || binding.targetSessionKey !== expected.targetSessionKey || binding.targetKind !== expected.targetKind || binding.conversation.channel !== expected.bindingConversation.channel || binding.conversation.accountId !== expected.bindingConversation.accountId || binding.conversation.conversationId !== expected.bindingConversation.conversationId || binding.conversation.parentConversationId !== expected.bindingConversation.parentConversationId) return false;
return expected.kind === "plugin" ? selection.kind === "plugin" && selection.pluginId === expected.pluginId && selection.pluginRoot === expected.pluginRoot : selection.kind === "agent" && resolveConversationBindingAgentId(selection.binding, expected.fallbackAgentId) === expected.observedAgentId;
}
/** Configured routing changes the dispatch owner without changing the inspected selection. */
function projectConfiguredConversationBindingRouteFacts(route) {
const facts = readConversationBindingRouteFacts(route);
return facts ? Object.assign({ ...route }, { [BINDING_ROUTE_FACTS]: Object.freeze({
...facts,
agentId: route.agentId
}) }) : route;
}
function readConversationBindingRouteObservations(value) {
const observations = [];
for (let current = readConversationBindingRouteFacts(value); current; current = current.previous) observations.unshift(current);
return observations;
}
//#endregion
export { readConversationBindingRouteObservations as a, withConversationBindingRouteFacts as c, readConversationBindingRouteFacts as i, matchesConversationBindingRouteFacts as n, resolveConversationBindingAgentId as o, projectConfiguredConversationBindingRouteFacts as r, resolveConversationBindingSelection as s, copyConversationBindingRouteFacts as t };