UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

136 lines (135 loc) 5.31 kB
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 };