UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

156 lines (155 loc) • 7.26 kB
import { c as normalizeOptionalLowercaseString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-1VuiLaaR.mjs"; import { a as asOptionalRecord, c as isRecord } from "./record-coerce-TIsquoVR.mjs"; import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs"; import { n as buildAgentMainSessionKey } from "./session-key-CmZ4o9-l.mjs"; import { M as parseAgentSessionKey, O as parseThreadSessionSuffix, h as scopedHeartbeatWakeOptions, u as resolveEventSessionKey } from "./session-key-C09ow4h0.mjs"; import { t as deriveSessionChatTypeFromKey } from "./session-chat-type-shared-BzwKnB1m.mjs"; import { r as resolveChannelAccountEntry } from "./account-lookup-D_rRUHd5.mjs"; import { i as resolvePinnedMainDmOwnerFromAllowlist } from "./dm-policy-shared-BRGB1_No.mjs"; import { o as resolveAgentRoute } from "./resolve-route-DYoHvZlS.mjs"; //#region src/infra/event-session-routing.ts function readAllowFrom(value) { const allowFrom = asOptionalRecord(value)?.allowFrom; return Array.isArray(allowFrom) ? allowFrom : void 0; } function readDmAllowFrom(value) { return readAllowFrom(asOptionalRecord(value)?.dm); } /** Parse an agent direct-session key into channel/account/peer routing parts. */ function parseDirectAgentSessionTarget(sessionKey) { const { baseSessionKey } = parseThreadSessionSuffix(sessionKey); const directSessionKey = baseSessionKey ?? sessionKey; const parsed = parseAgentSessionKey(directSessionKey); if (!parsed || deriveSessionChatTypeFromKey(directSessionKey) !== "direct") return null; const parts = parsed.rest.split(":"); const directIndex = parts.findIndex((part) => part === "direct" || part === "dm"); if (directIndex < 0 || directIndex > 2 || directIndex >= parts.length - 1) return null; const peerId = normalizeLowercaseStringOrEmpty(parts.slice(directIndex + 1).join(":")); if (!peerId) return null; return { agentId: parsed.agentId, ...directIndex >= 1 ? { channel: normalizeLowercaseStringOrEmpty(parts[0]) } : {}, ...directIndex >= 2 ? { accountId: normalizeLowercaseStringOrEmpty(parts[1]) } : {}, peerId }; } /** Resolve the configured DM allowlist that applies to an event session. */ function resolveEventSessionAllowFrom(params) { const cfg = params.cfg; if (!cfg?.channels) return; const channelKey = normalizeLowercaseStringOrEmpty(params.channel ?? params.target?.channel); if (!channelKey) return; const channelConfig = isRecord(cfg.channels) ? cfg.channels[channelKey] : void 0; if (!isRecord(channelConfig)) return; const accountId = normalizeLowercaseStringOrEmpty(params.accountId ?? params.target?.accountId); const accountConfig = accountId && isRecord(channelConfig.accounts) ? resolveChannelAccountEntry(channelConfig.accounts, accountId, channelKey, (id) => id) : void 0; const accountNestedConfig = asOptionalRecord(asOptionalRecord(accountConfig)?.config); return readDmAllowFrom(accountConfig) ?? readDmAllowFrom(accountNestedConfig) ?? readAllowFrom(accountConfig) ?? readAllowFrom(accountNestedConfig) ?? readDmAllowFrom(channelConfig) ?? readAllowFrom(channelConfig); } function shouldPreserveDirectSessionKeyFromRoute(params) { if (!params.cfg || !params.target?.channel) return false; try { const route = resolveAgentRoute({ cfg: params.cfg, channel: params.target.channel, accountId: params.target.accountId, peer: { kind: "direct", id: params.target.peerId } }); const { baseSessionKey } = parseThreadSessionSuffix(params.sessionKey); const normalizedRouteSessionKey = normalizeLowercaseStringOrEmpty(route.sessionKey); return route.lastRoutePolicy === "session" && (normalizedRouteSessionKey === normalizeLowercaseStringOrEmpty(params.sessionKey) || baseSessionKey !== void 0 && normalizedRouteSessionKey === normalizeLowercaseStringOrEmpty(baseSessionKey)); } catch { return false; } } /** Build the routing policy used by event wakeups and scoped heartbeat options. */ function resolveEventSessionRoutingPolicy(params) { const target = parseDirectAgentSessionTarget(params.sessionKey); const channel = normalizeOptionalLowercaseString(params.channel ?? target?.channel); const accountId = normalizeOptionalLowercaseString(params.accountId ?? target?.accountId); const allowFrom = params.allowFrom ?? resolveEventSessionAllowFrom({ cfg: params.cfg, target, channel, accountId }); return { mainKey: params.cfg?.session?.mainKey, sessionScope: params.cfg?.session?.scope, dmScope: params.dmScope ?? params.cfg?.session?.dmScope, allowFrom, channel, accountId, preserveSessionKey: params.sessionKey ? shouldPreserveDirectSessionKeyFromRoute({ cfg: params.cfg, sessionKey: params.sessionKey, target }) : false }; } /** Resolve a direct DM event session to the configured main session when allowed. */ function resolveMainScopedEventSessionKey(params) { const sessionKey = params.sessionKey.trim(); if (!sessionKey || params.policy?.preserveSessionKey === true) return null; const target = parseDirectAgentSessionTarget(sessionKey); if (!target) return null; const resolvedAgentId = normalizeAgentId(params.agentId ?? target.agentId); if (normalizeAgentId(target.agentId) !== resolvedAgentId) return null; const policy = params.policy ?? resolveEventSessionRoutingPolicy({ cfg: params.cfg, sessionKey }); const allowFrom = Array.from(policy.allowFrom ?? []); const pinnedOwner = resolvePinnedMainDmOwnerFromAllowlist({ dmScope: policy.dmScope ?? params.cfg?.session?.dmScope, allowFrom, normalizeEntry: normalizeOptionalLowercaseString }); if (!pinnedOwner || normalizeOptionalLowercaseString(target.peerId) !== pinnedOwner) return null; if (shouldPreserveDirectSessionKeyFromRoute({ cfg: params.cfg, sessionKey, target })) return null; if (policy.sessionScope === "global") return "global"; return buildAgentMainSessionKey({ agentId: resolvedAgentId, mainKey: policy.mainKey ?? params.cfg?.session?.mainKey }); } /** Apply event routing policy to a raw session key. */ function resolveEventSessionKeyForPolicy(sessionKey, policy) { const cronScoped = resolveEventSessionKey(sessionKey, policy?.mainKey, policy?.sessionScope); if (cronScoped !== sessionKey) return cronScoped; return resolveMainScopedEventSessionKey({ sessionKey, policy }) ?? sessionKey; } /** Apply event routing policy while preserving wake option typing. */ function scopedHeartbeatWakeOptionsForPolicy(sessionKey, wakeOptions, policy) { if (resolveEventSessionKey(sessionKey, policy?.mainKey, policy?.sessionScope) !== sessionKey) return scopedHeartbeatWakeOptions(sessionKey, wakeOptions, policy?.mainKey, policy?.sessionScope); const mainScoped = resolveMainScopedEventSessionKey({ sessionKey, policy }); if (mainScoped) { if (mainScoped === "global") { const agentId = parseAgentSessionKey(sessionKey)?.agentId; return agentId ? { ...wakeOptions, agentId } : wakeOptions; } return { ...wakeOptions, sessionKey: mainScoped }; } return scopedHeartbeatWakeOptions(sessionKey, wakeOptions, policy?.mainKey, policy?.sessionScope); } //#endregion export { scopedHeartbeatWakeOptionsForPolicy as i, resolveEventSessionRoutingPolicy as n, resolveMainScopedEventSessionKey as r, resolveEventSessionKeyForPolicy as t };