UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

80 lines (79 loc) 3.2 kB
import { c as normalizeOptionalString, s as normalizeOptionalLowercaseString } from "./string-coerce-mnp54Vah.js"; import { n as resolveGlobalSingleton } from "./global-singleton-PwlQSEal.js"; import { c as parseAgentSessionKey } from "./session-key-utils-Bx3apsJ3.js"; import "./globals-GTrXU4s9.js"; import { n as resolveGlobalDedupeCache } from "./dedupe-DnzL4okR.js"; import { n as channelRouteDedupeKey } from "./channel-route-D7X5briz.js"; import { c as resolveCommandTurnTargetSessionKey } from "./command-turn-context-YXLLZVCi.js"; //#region src/auto-reply/reply/inbound-dedupe.ts const DEFAULT_INBOUND_DEDUPE_TTL_MS = 20 * 6e4; const DEFAULT_INBOUND_DEDUPE_MAX = 5e3; /** * Keep inbound dedupe shared across bundled chunks so the same provider * message cannot bypass dedupe by entering through a different chunk copy. */ const INBOUND_DEDUPE_CACHE_KEY = Symbol.for("openclaw.inboundDedupeCache"); const INBOUND_DEDUPE_INFLIGHT_KEY = Symbol.for("openclaw.inboundDedupeInflight"); const inboundDedupeCache = resolveGlobalDedupeCache(INBOUND_DEDUPE_CACHE_KEY, { ttlMs: DEFAULT_INBOUND_DEDUPE_TTL_MS, maxSize: DEFAULT_INBOUND_DEDUPE_MAX }); const inboundDedupeInFlight = resolveGlobalSingleton(INBOUND_DEDUPE_INFLIGHT_KEY, () => /* @__PURE__ */ new Set()); const resolveInboundPeerId = (ctx) => ctx.OriginatingTo ?? ctx.To ?? ctx.From ?? ctx.SessionKey; function resolveInboundDedupeSessionScope(ctx) { const sessionKey = resolveCommandTurnTargetSessionKey(ctx) || normalizeOptionalString(ctx.SessionKey) || ""; if (!sessionKey) return ""; const parsed = parseAgentSessionKey(sessionKey); if (!parsed) return sessionKey; return `agent:${parsed.agentId}`; } function buildInboundDedupeKey(ctx) { const provider = normalizeOptionalLowercaseString(ctx.OriginatingChannel ?? ctx.Provider ?? ctx.Surface) || ""; const messageId = normalizeOptionalString(ctx.MessageSid); if (!provider || !messageId) return null; const peerId = resolveInboundPeerId(ctx); if (!peerId) return null; const sessionScope = resolveInboundDedupeSessionScope(ctx); const routeKey = channelRouteDedupeKey({ channel: provider, to: peerId, accountId: normalizeOptionalString(ctx.AccountId) ?? "", threadId: ctx.MessageThreadId }); return JSON.stringify([ sessionScope, routeKey, messageId ]); } function claimInboundDedupe(ctx, opts) { const key = buildInboundDedupeKey(ctx); if (!key) return { status: "invalid" }; if ((opts?.cache ?? inboundDedupeCache).peek(key, opts?.now)) return { status: "duplicate", key }; const inFlight = opts?.inFlight ?? inboundDedupeInFlight; if (inFlight.has(key)) return { status: "inflight", key }; inFlight.add(key); return { status: "claimed", key }; } function commitInboundDedupe(key, opts) { (opts?.cache ?? inboundDedupeCache).check(key, opts?.now); (opts?.inFlight ?? inboundDedupeInFlight).delete(key); } function releaseInboundDedupe(key, opts) { (opts?.inFlight ?? inboundDedupeInFlight).delete(key); } function resetInboundDedupe() { inboundDedupeCache.clear(); inboundDedupeInFlight.clear(); } //#endregion export { resetInboundDedupe as i, commitInboundDedupe as n, releaseInboundDedupe as r, claimInboundDedupe as t };