UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

55 lines (54 loc) 2.85 kB
import { c as normalizeOptionalLowercaseString, l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { n as normalizeAccountId } from "./account-id-CETVCrTz.js"; import { a as isInternalMessageChannel } from "./message-channel-BQrhwUEA.js"; import { createHash } from "node:crypto"; //#region src/auto-reply/reply/source-turn-id.ts const CHANNEL_SOURCE_TURN_ID_PREFIX = "channel-user:v1:"; const CHANNEL_SOURCE_TURN_ID = Symbol("openclaw.channelSourceTurnId"); const CHANNEL_SOURCE_TURN_SAME_THREAD_REQUIRED = Symbol("openclaw.channelSourceTurnSameThreadRequired"); /** * Internal-origin turns (gateway chat.send stamps the internal channel as the * ingress provider) carry run ids, not provider message ids. Minting a channel * source-turn id from them breaks the run-keyed user-turn admission guard; * gateway turns own restart via fingerprint admission and client retries. */ function shouldMintChannelSourceTurnId(ingressProvider) { return !isInternalMessageChannel(ingressProvider); } /** * Identifies one inbound channel turn across shared sessions. * Provider message ids are not globally unique, so route scope is mandatory. */ function buildChannelSourceTurnId(params) { const provider = normalizeOptionalLowercaseString(params.provider); const conversationId = normalizeOptionalString(params.conversationId); const messageId = normalizeOptionalString(typeof params.messageId === "number" ? String(params.messageId) : params.messageId); if (!provider || !conversationId || !messageId) return; const digest = createHash("sha256").update(JSON.stringify([ provider, normalizeAccountId(params.accountId), conversationId, messageId ])).digest("hex"); return `${CHANNEL_SOURCE_TURN_ID_PREFIX}${digest}`; } /** Carries host-only source identity through internal context clones without public type drift. */ function setChannelSourceTurnId(context, sourceTurnId) { const scoped = context; if (sourceTurnId) scoped[CHANNEL_SOURCE_TURN_ID] = sourceTurnId; else delete scoped[CHANNEL_SOURCE_TURN_ID]; } function readChannelSourceTurnId(context) { return context[CHANNEL_SOURCE_TURN_ID]; } /** Carries the original channel adapter's narrowed message-action scope privately. */ function setChannelSourceTurnSameThreadRequired(context, sameThreadRequired) { const scoped = context; if (sameThreadRequired === true) scoped[CHANNEL_SOURCE_TURN_SAME_THREAD_REQUIRED] = true; else delete scoped[CHANNEL_SOURCE_TURN_SAME_THREAD_REQUIRED]; } function readChannelSourceTurnSameThreadRequired(context) { return context[CHANNEL_SOURCE_TURN_SAME_THREAD_REQUIRED] === true; } //#endregion export { setChannelSourceTurnSameThreadRequired as a, setChannelSourceTurnId as i, readChannelSourceTurnId as n, shouldMintChannelSourceTurnId as o, readChannelSourceTurnSameThreadRequired as r, buildChannelSourceTurnId as t };