UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

180 lines (179 loc) 8.86 kB
import { r as normalizeOptionalAccountId } from "./account-id-CETVCrTz.js"; import { r as isInternalNonDeliveryChannel } from "./message-channel-constants-2zSoJXQC.js"; import { n as normalizeMessageChannel, t as isNormalizedMessageChannel } from "./message-channel-core-AaEWic-A.js"; import { l as normalizeChannelRouteRef, o as channelRouteThreadId, r as channelRouteTarget, t as channelRouteCompactKey, u as normalizeChannelRouteTarget } from "./channel-route--2in3Ckg.js"; //#region src/utils/delivery-context.shared.ts /** * Delivery-context normalization and projection helpers. * * Persisted sessions expose one closed delivery state. Compatibility * projections are derived from that state at public boundaries. */ /** Normalizes a delivery context into canonical channel route fields, dropping invalid routes. */ function normalizeDeliveryContext(context) { if (!context) return; const route = normalizeChannelRouteTarget({ channel: typeof context.channel === "string" ? normalizeMessageChannel(context.channel) ?? context.channel.trim() : void 0, to: context.to, accountId: context.accountId, threadId: context.threadId }); if (!route) return; const normalized = { channel: route.channel, to: channelRouteTarget(route), accountId: normalizeOptionalAccountId(route.accountId) }; const threadId = channelRouteThreadId(route); if (threadId != null) normalized.threadId = threadId; return normalized; } /** Checks raw channel/to presence only; does not normalize or validate deliverability. */ function hasDeliveryTargetFields(context) { return Boolean(context?.channel && context?.to); } /** Normalizes an unknown channel route payload from persisted session/plugin metadata. */ function normalizeDeliveryChannelRoute(route) { if (!route || typeof route !== "object" || Array.isArray(route)) return; const candidate = route; return normalizeChannelRouteRef({ channel: candidate.channel, to: candidate.target?.to, rawTo: candidate.target?.rawTo, chatType: candidate.target?.chatType, accountId: candidate.accountId, threadId: candidate.thread?.id, threadKind: candidate.thread?.kind, threadSource: candidate.thread?.source }); } /** Converts a normalized channel route reference into a delivery context. */ function deliveryContextFromChannelRoute(route) { const normalized = normalizeDeliveryChannelRoute(route); return normalizeDeliveryContext({ channel: normalized?.channel, to: channelRouteTarget(normalized), accountId: normalized?.accountId, threadId: channelRouteThreadId(normalized) }); } /** Converts delivery context fields into the SDK channel route reference shape. */ function channelRouteFromDeliveryContext(context) { return normalizeChannelRouteTarget(normalizeDeliveryContext(context)); } function mergeRouteMetadataWithDeliveryContext(route, context) { if (!route) return channelRouteFromDeliveryContext(context); return normalizeChannelRouteRef({ channel: route.channel ?? context.channel, to: route.target?.to ?? context.to, rawTo: route.target?.rawTo, chatType: route.target?.chatType, accountId: route.accountId ?? context.accountId, threadId: route.thread?.id ?? context.threadId, threadKind: route.thread?.kind, threadSource: route.thread?.source }); } function isInternalRouteContext(context) { const channel = context?.channel; return Boolean(channel && (channel === "webchat" || isInternalNonDeliveryChannel(channel))); } function hasExternalDeliveryTarget(context) { const channel = context?.channel; return Boolean(channel && isNormalizedMessageChannel(channel) && !isInternalNonDeliveryChannel(channel) && context?.to); } function mergeExternalDeliveryContextOverInternalRoute(deliveryContext, internalContext) { return normalizeDeliveryContext({ channel: deliveryContext?.channel, to: deliveryContext?.to, accountId: deliveryContext?.accountId ?? internalContext?.accountId, threadId: deliveryContext?.threadId ?? internalContext?.threadId }); } function isCanonicalSessionDeliveryState(value) { if (!value || typeof value !== "object" || Array.isArray(value)) return false; const candidate = value; if (candidate.kind === "none" || candidate.kind === "internal") return true; return candidate.kind === "external" && Boolean(candidate.route && typeof candidate.route === "object") && Boolean(candidate.context && typeof candidate.context === "object") && Boolean(candidate.origin && typeof candidate.origin === "object"); } /** Builds one canonical delivery state from current turn routing facts. */ function normalizeSessionDeliveryState(params) { if (!params) return { kind: "none" }; const normalizedRoute = normalizeDeliveryChannelRoute(params.route); const routeContext = deliveryContextFromChannelRoute(normalizedRoute); const originContext = normalizeDeliveryContext({ channel: params.origin?.provider, to: params.origin?.to, accountId: params.origin?.accountId, threadId: params.origin?.threadId }); const context = normalizeDeliveryContext(params.context); const fallbackContext = mergeDeliveryContext(context, originContext); const routeIsInternalFallback = isInternalRouteContext(routeContext) && hasExternalDeliveryTarget(context); const merged = routeIsInternalFallback ? mergeExternalDeliveryContextOverInternalRoute(context, mergeDeliveryContext(routeContext, originContext)) : mergeDeliveryContext(routeContext, fallbackContext); if (!merged) return { kind: "none" }; if (isInternalRouteContext(merged)) return { kind: "internal" }; const route = mergeRouteMetadataWithDeliveryContext(routeIsInternalFallback ? void 0 : normalizedRoute, merged); if (!route) return { kind: "none" }; const origin = { ...params.origin }; origin.provider ??= merged.channel; origin.to ??= merged.to; origin.accountId ??= merged.accountId; origin.threadId ??= merged.threadId; origin.chatType ??= route.target?.chatType; return { kind: "external", route, context: merged, origin }; } /** Projects compatibility fields without persisting duplicate delivery state. */ function projectSessionDeliveryFields(delivery) { if (delivery?.kind !== "external") return {}; return { route: delivery.route, deliveryContext: delivery.context, origin: delivery.origin, channel: delivery.context.channel ?? delivery.origin.provider, lastChannel: delivery.context.channel, lastTo: delivery.context.to, lastAccountId: delivery.context.accountId, lastThreadId: delivery.context.threadId }; } /** Reads only the canonical persisted delivery record. */ function deliveryContextFromSession(entry) { return entry?.delivery?.kind === "external" ? entry.delivery.context : void 0; } function sessionDeliveryRoute(entry) { return entry?.delivery?.kind === "external" ? entry.delivery.route : void 0; } function sessionDeliveryOrigin(entry) { return entry?.delivery?.kind === "external" ? entry.delivery.origin : void 0; } function sessionDeliveryChannel(entry) { const delivery = entry?.delivery; return delivery?.kind === "external" ? delivery.context.channel ?? delivery.origin.provider : void 0; } /** Merges delivery contexts without mixing target/account/thread fields across route owners. */ function mergeDeliveryContext(primary, fallback) { const normalizedPrimary = normalizeDeliveryContext(primary); const normalizedFallback = normalizeDeliveryContext(fallback); if (!normalizedPrimary && !normalizedFallback) return; const channelsConflict = normalizedPrimary?.channel && normalizedFallback?.channel && normalizedPrimary.channel !== normalizedFallback.channel; const accountsConflict = normalizedPrimary?.accountId && normalizedFallback?.accountId && normalizedPrimary.accountId !== normalizedFallback.accountId; const routesConflict = channelsConflict || accountsConflict; return normalizeDeliveryContext({ channel: accountsConflict ? normalizedPrimary?.channel : normalizedPrimary?.channel ?? normalizedFallback?.channel, to: routesConflict ? normalizedPrimary?.to : normalizedPrimary?.to ?? normalizedFallback?.to, accountId: routesConflict ? normalizedPrimary?.accountId : normalizedPrimary?.accountId ?? normalizedFallback?.accountId, threadId: routesConflict ? normalizedPrimary?.threadId : normalizedPrimary?.threadId ?? normalizedFallback?.threadId }); } /** Builds a compact stable key for a routable delivery context. */ function deliveryContextKey(context) { return channelRouteCompactKey(normalizeDeliveryContext(context)); } //#endregion export { isCanonicalSessionDeliveryState as a, normalizeDeliveryContext as c, sessionDeliveryChannel as d, sessionDeliveryOrigin as f, hasDeliveryTargetFields as i, normalizeSessionDeliveryState as l, deliveryContextFromSession as n, mergeDeliveryContext as o, sessionDeliveryRoute as p, deliveryContextKey as r, normalizeDeliveryChannelRoute as s, deliveryContextFromChannelRoute as t, projectSessionDeliveryFields as u };