openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
136 lines (135 loc) • 5.31 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { C as isCronRunSessionKey, f as resolveAgentIdFromSessionKey, l as isUnscopedSessionKeySentinel } from "./session-key-BnWWjqNc.js";
import { r as logVerbose } from "./globals-CTaGxEqj.js";
import { n as inspectSessionBindingByConversation, t as getSessionBindingService } from "./session-binding-service-DTXs8JDw.js";
import { t as isPluginOwnedBindingMetadata } from "./conversation-binding-metadata-CFOhDjMh.js";
import { n as deriveLastRoutePolicy } from "./resolve-route-BRXfbiKP.js";
import { n as resolveConfiguredBinding } from "./configured-binding-registry-Cuw2WGgE.js";
import { t as ensureConfiguredBindingTargetReady } from "./binding-targets-C2dEPPXN.js";
//#region src/channels/plugins/binding-routing.ts
/**
* Channel binding route resolver.
*
* Applies configured and runtime conversation bindings to agent route resolution.
*/
const CONFIGURED_BINDING_ROUTE_READY_TIMEOUT_MS = 3e4;
function resolveConfiguredBindingConversationRef(params) {
if ("conversation" in params) return params.conversation;
return {
channel: params.channel,
accountId: params.accountId,
conversationId: params.conversationId,
parentConversationId: params.parentConversationId
};
}
/**
* Rewrites an agent route when the current conversation matches a configured binding.
*/
function resolveConfiguredBindingRoute(params) {
const bindingResolution = resolveConfiguredBinding({
cfg: params.cfg,
conversation: resolveConfiguredBindingConversationRef(params)
}) ?? null;
if (!bindingResolution) return {
bindingResolution: null,
route: params.route
};
const boundSessionKey = bindingResolution.statefulTarget.sessionKey.trim();
if (!boundSessionKey) return {
bindingResolution,
route: params.route
};
const boundAgentId = resolveAgentIdFromSessionKey(boundSessionKey, bindingResolution.statefulTarget.agentId);
return {
bindingResolution,
boundSessionKey,
boundAgentId,
route: {
...params.route,
sessionKey: boundSessionKey,
agentId: boundAgentId,
lastRoutePolicy: deriveLastRoutePolicy({
sessionKey: boundSessionKey,
mainSessionKey: params.route.mainSessionKey
}),
matchedBy: "binding.channel"
}
};
}
/**
* Rewrites an agent route using a persisted runtime conversation binding, when applicable.
*/
function resolveRuntimeConversationBindingRoute(params) {
const inspection = inspectSessionBindingByConversation(resolveConfiguredBindingConversationRef(params));
if (inspection.status === "unavailable") return {
bindingOwnerAvailable: false,
bindingRecord: null,
route: params.route
};
const bindingRecord = inspection.binding;
const boundSessionKey = bindingRecord?.targetSessionKey?.trim();
if (!bindingRecord || !boundSessionKey) return {
bindingOwnerAvailable: true,
bindingRecord: null,
route: params.route
};
if (isCronRunSessionKey(boundSessionKey)) {
logVerbose(`ignored runtime conversation binding ${bindingRecord.bindingId} to isolated cron run session ${boundSessionKey}`);
return {
bindingOwnerAvailable: true,
bindingRecord: null,
route: params.route
};
}
if (params.touchBinding !== false) getSessionBindingService().touch(bindingRecord.bindingId, void 0, bindingRecord.conversation);
const pluginId = isPluginOwnedBindingMetadata(bindingRecord.metadata) ? bindingRecord.metadata.pluginId.trim() : void 0;
if (pluginId) return {
bindingOwnerAvailable: true,
bindingRecord,
pluginId,
route: params.route
};
const boundAgentId = resolveAgentIdFromSessionKey(boundSessionKey, isUnscopedSessionKeySentinel(boundSessionKey) ? normalizeOptionalString(bindingRecord.metadata?.agentId) ?? params.route.agentId : void 0);
return {
bindingOwnerAvailable: true,
bindingRecord,
boundSessionKey,
boundAgentId,
route: {
...params.route,
sessionKey: boundSessionKey,
agentId: boundAgentId,
lastRoutePolicy: deriveLastRoutePolicy({
sessionKey: boundSessionKey,
mainSessionKey: params.route.mainSessionKey
}),
matchedBy: "binding.channel"
}
};
}
/**
* Ensures a configured binding target is ready without blocking route resolution indefinitely.
*/
async function ensureConfiguredBindingRouteReady(params) {
const readyPromise = ensureConfiguredBindingTargetReady(params);
let timer;
const timeoutToken = Symbol("configured-binding-route-ready-timeout");
const timeoutPromise = new Promise((resolve) => {
timer = setTimeout(() => resolve(timeoutToken), CONFIGURED_BINDING_ROUTE_READY_TIMEOUT_MS);
timer.unref?.();
});
try {
const result = await Promise.race([readyPromise, timeoutPromise]);
if (result !== timeoutToken) return result;
logVerbose(`configured binding route ready check timed out after ${CONFIGURED_BINDING_ROUTE_READY_TIMEOUT_MS / 1e3}s`);
readyPromise.then((lateResult) => logVerbose(`configured binding route ready check settled after timeout (ok=${lateResult.ok})`), (err) => logVerbose(`configured binding route ready check rejected after timeout: ${String(err)}`));
return {
ok: false,
error: "Configured binding route ready check timed out"
};
} finally {
clearTimeout(timer);
}
}
//#endregion
export { resolveConfiguredBindingRoute as n, resolveRuntimeConversationBindingRoute as r, ensureConfiguredBindingRouteReady as t };