UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

142 lines (141 loc) • 7.4 kB
import { l as normalizeOptionalString } from "./string-coerce-6kR-86XC.mjs"; import { A as parseAgentSessionKey } from "./session-key-BC4m_Ly5.mjs"; import { t as ADMIN_SCOPE } from "./operator-scopes-D-CL26h0.mjs"; import { i as GATEWAY_CLIENT_NAMES, r as GATEWAY_CLIENT_MODES } from "./client-info-S_xwnr2o.mjs"; import { t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-constants-Dq-VU_KZ.mjs"; import { n as normalizeMessageChannel } from "./message-channel-core-JDeu-bNU.mjs"; import { i as isGatewayCliClient, l as isWebchatClient } from "./message-channel-BCUrZuO3.mjs"; import { r as sessionDeliveryOrigin, t as deliveryContextFromSession } from "./delivery-context.read-CR06zOJ4.mjs"; import "./method-scopes-C-MKLkWf.mjs"; import { n as isPluginOwnedSessionBindingRecord } from "./conversation-binding-metadata-CFOhDjMh.mjs"; import { t as getSessionBindingService } from "./session-binding-service-BxjdmbUW.mjs"; import { t as sanitizeChatSendMessageInput } from "./chat-input-sanitize-BUL6M46s.mjs"; //#region src/gateway/server-methods/chat-origin-routing.ts const CHANNEL_AGNOSTIC_SESSION_SCOPES = /* @__PURE__ */ new Set([ "main", "direct", "dm", "group", "channel", "cron", "run", "subagent", "acp", "thread", "topic" ]); const CHANNEL_SCOPED_SESSION_SHAPES = /* @__PURE__ */ new Set([ "direct", "dm", "group", "channel" ]); function normalizeExplicitChatSendOrigin(params) { const originatingChannel = normalizeOptionalString(params.originatingChannel); const originatingTo = normalizeOptionalString(params.originatingTo); const accountId = normalizeOptionalString(params.accountId); const messageThreadId = normalizeOptionalString(params.messageThreadId); if (!Boolean(originatingChannel || originatingTo || accountId || messageThreadId)) return { ok: true }; const normalizedChannel = normalizeMessageChannel(originatingChannel); if (!normalizedChannel) return { ok: false, error: "originatingChannel is required when using originating route fields" }; if (!originatingTo) return { ok: false, error: "originatingTo is required when using originating route fields" }; return { ok: true, value: { originatingChannel: normalizedChannel, originatingTo, ...accountId ? { accountId } : {}, ...messageThreadId ? { messageThreadId } : {} } }; } function resolveChatSendOriginatingRoute(params) { if (params.explicitOrigin?.originatingChannel && params.explicitOrigin.originatingTo) return { originatingChannel: params.explicitOrigin.originatingChannel, originatingTo: params.explicitOrigin.originatingTo, ...params.explicitOrigin.accountId ? { accountId: params.explicitOrigin.accountId } : {}, ...params.explicitOrigin.messageThreadId ? { messageThreadId: params.explicitOrigin.messageThreadId } : {}, explicitDeliverRoute: params.deliver === true }; const internalRoute = { originatingChannel: INTERNAL_MESSAGE_CHANNEL, originatingTo: params.sessionKey, explicitDeliverRoute: false }; if (params.deliver !== true) return internalRoute; const sessionDeliveryContext = deliveryContextFromSession(params.entry); const sessionOrigin = sessionDeliveryOrigin(params.entry); const routeChannelCandidate = normalizeMessageChannel(sessionDeliveryContext?.channel ?? sessionOrigin?.provider); const routeToCandidate = sessionDeliveryContext?.to; const routeAccountIdCandidate = sessionDeliveryContext?.accountId ?? sessionOrigin?.accountId; const routeThreadIdCandidate = sessionDeliveryContext?.threadId ?? sessionOrigin?.threadId; if (params.sessionKey.length > 512) return internalRoute; const sessionScopeParts = (parseAgentSessionKey(params.sessionKey)?.rest ?? params.sessionKey).split(":", 3).filter(Boolean); const sessionScopeHead = sessionScopeParts[0]; const sessionChannelHint = normalizeMessageChannel(sessionScopeHead); const normalizedSessionScopeHead = (sessionScopeHead ?? "").trim().toLowerCase(); const sessionPeerShapeCandidates = [sessionScopeParts[1], sessionScopeParts[2]].map((part) => (part ?? "").trim().toLowerCase()).filter(Boolean); const isChannelAgnosticSessionScope = CHANNEL_AGNOSTIC_SESSION_SCOPES.has(normalizedSessionScopeHead); const isChannelScopedSession = sessionPeerShapeCandidates.some((part) => CHANNEL_SCOPED_SESSION_SHAPES.has(part)); const hasLegacyChannelPeerShape = !isChannelScopedSession && typeof sessionScopeParts[1] === "string" && sessionChannelHint === routeChannelCandidate; const isFromWebchatClient = isWebchatClient(params.client); const isFromGatewayCliClient = isGatewayCliClient(params.client); const hasClientMetadata = typeof params.client?.mode === "string" && params.client.mode.trim().length > 0 || typeof params.client?.id === "string" && params.client.id.trim().length > 0; const configuredMainKey = (params.mainKey ?? "main").trim().toLowerCase(); const canInheritConfiguredMainRoute = normalizedSessionScopeHead.length > 0 && normalizedSessionScopeHead === configuredMainKey && params.hasConnectedClient && (isFromGatewayCliClient || !hasClientMetadata); if (!(Boolean(!isFromWebchatClient && sessionChannelHint && sessionChannelHint !== "webchat" && (!isChannelAgnosticSessionScope && (isChannelScopedSession || hasLegacyChannelPeerShape) || canInheritConfiguredMainRoute)) && routeChannelCandidate && routeChannelCandidate !== "webchat" && typeof routeToCandidate === "string" && routeToCandidate.trim().length > 0)) return internalRoute; return { originatingChannel: routeChannelCandidate, originatingTo: routeToCandidate, accountId: routeAccountIdCandidate, messageThreadId: routeThreadIdCandidate, explicitDeliverRoute: true }; } function isAcpSessionKey(sessionKey) { return Boolean(sessionKey?.split(":").includes("acp")); } function resolveExplicitOriginBinding(origin) { if (!origin?.originatingChannel || !origin.originatingTo || !origin.accountId) return; const channel = normalizeMessageChannel(origin.originatingChannel); if (!channel || channel === "webchat") return; return getSessionBindingService().resolveByConversation({ channel, accountId: origin.accountId, conversationId: origin.originatingTo }); } function explicitOriginTargetsAcpSession(origin) { return isAcpSessionKey(resolveExplicitOriginBinding(origin)?.targetSessionKey); } function explicitOriginTargetsPluginBinding(origin) { return isPluginOwnedSessionBindingRecord(resolveExplicitOriginBinding(origin)); } function normalizeOptionalChatSystemReceipt(value) { if (value == null) return { ok: true }; if (typeof value !== "string") return { ok: false, error: "systemProvenanceReceipt must be a string" }; const sanitized = sanitizeChatSendMessageInput(value); if (!sanitized.ok) return sanitized; return { ok: true, receipt: sanitized.message.trim() || void 0 }; } function isAcpBridgeClient(client) { const info = client?.connect?.client; return info?.id === GATEWAY_CLIENT_NAMES.CLI && info?.mode === GATEWAY_CLIENT_MODES.CLI && info?.displayName === "ACP" && info?.version === "acp"; } function hasGatewayAdminScope(client) { return (Array.isArray(client?.connect?.scopes) ? client.connect.scopes : []).includes(ADMIN_SCOPE); } //#endregion export { normalizeExplicitChatSendOrigin as a, isAcpBridgeClient as i, explicitOriginTargetsPluginBinding as n, normalizeOptionalChatSystemReceipt as o, hasGatewayAdminScope as r, resolveChatSendOriginatingRoute as s, explicitOriginTargetsAcpSession as t };