UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

252 lines (251 loc) 10.1 kB
import { c as normalizeOptionalString } from "./string-coerce-mnp54Vah.js"; import { t as createSubsystemLogger } from "./subsystem-BzXSmsuh.js"; import { u as resolveStorePath } from "./paths-NEwU8m3X.js"; import { o as readSessionUpdatedAt, s as recordSessionMetaFromInbound, u as updateLastRoute } from "./store-Qsgtu-0y.js"; import "./sessions-D6zZvoxX.js"; import "./logging-CvNAh8ZC.js"; import { u as saveMediaBuffer } from "./store-C9M_0A1p.js"; import { i as shouldComputeCommandAuthorized, r as isControlCommandMessage, t as hasControlCommand } from "./command-detection-iKcBJ8it.js"; import { a as settleReplyDispatcher, i as dispatchReplyFromConfig, o as withReplyDispatcher } from "./dispatch-DO0Fpkbp.js"; import { n as resolveChannelGroupRequireMention, t as resolveChannelGroupPolicy } from "./group-policy-CShy7eWv.js"; import { i as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-xcIS8NFL.js"; import { t as resolveCommandAuthorizedFromAuthorizers } from "./command-gating-65fgTdwb.js"; import { a as saveRemoteMedia, i as readRemoteMediaBuffer, o as saveResponseMedia, r as fetchRemoteMedia } from "./fetch-2npQWHQh.js"; import { i as resolveHumanDelayConfig, r as resolveEffectiveMessagesConfig } from "./identity-Qcvvo6SY.js"; import { a as chunkText, c as resolveTextChunkLimit, i as chunkMarkdownTextWithMode, o as chunkTextWithMode, r as chunkMarkdownText, s as resolveChunkMode, t as chunkByNewline } from "./chunk-Cpb8JO1x.js"; import { t as loadChannelOutboundAdapter } from "./load-BBQWnOQX.js"; import { t as convertMarkdownTables } from "./tables-BgtXxld3.js"; import { n as shouldHandleTextCommands } from "./commands-text-routing-B25gG5ny.js"; import "./commands-registry-wvHlpYBK.js"; import { i as matchesMentionWithExplicit, n as buildMentionRegexes, r as matchesMentionPatterns } from "./mentions-Be0DZkGs.js"; import { r as createReplyDispatcherWithTyping } from "./reply-dispatcher.types-CKL81tAi.js"; import { t as finalizeInboundContext } from "./inbound-context-CZx-NgvC.js"; import { t as dispatchReplyWithBufferedBlockDispatcher } from "./provider-dispatcher-CkTw0sGQ.js"; import { a as resolveEnvelopeFormatOptions, r as formatInboundEnvelope, t as formatAgentEnvelope } from "./envelope-IMcsY0tl.js"; import { n as resolveInboundDebounceMs, t as createInboundDebouncer } from "./inbound-debounce-k9j7XKN1.js"; import { i as shouldAckReaction, n as removeAckReactionAfterReply, r as removeAckReactionHandleAfterReply, t as createAckReactionHandle } from "./ack-reactions-D4-6N7fi.js"; import { l as runPreparedInboundReply, o as runChannelInboundEvent, r as dispatchChannelInboundReply, y as buildChannelInboundEventContext } from "./kernel-BdraY_qZ.js"; import { n as resolveInboundMentionDecision, t as implicitMentionKindWhen } from "./mention-gating-3P8aSD7o.js"; import { n as setChannelConversationBindingMaxAgeBySessionKey, t as setChannelConversationBindingIdleTimeoutBySessionKey } from "./conversation-bindings-CwT1FQjH.js"; import { t as recordInboundSession } from "./session-Do0yFgU8.js"; import { t as resolveMarkdownTableMode } from "./markdown-tables-LfSv7QSx.js"; import { n as recordChannelActivity, t as getChannelActivity } from "./channel-activity-4piA219h.js"; import { t as buildPairingReply } from "./pairing-messages-BJSYThef.js"; import { a as readChannelAllowFromStore, d as upsertChannelPairingRequest } from "./pairing-store-CxANz_ON.js"; //#region src/plugins/runtime/channel-runtime-contexts.ts const log = createSubsystemLogger("plugins/runtime-channel"); function normalizeRuntimeContextString(value) { return normalizeOptionalString(value) ?? ""; } function normalizeRuntimeContextKey(params) { const channelId = normalizeRuntimeContextString(params.channelId); const capability = normalizeRuntimeContextString(params.capability); const accountId = normalizeRuntimeContextString(params.accountId); if (!channelId || !capability) return null; return { mapKey: `${channelId}\u0000${accountId}\u0000${capability}`, normalizedKey: { channelId, capability, ...accountId ? { accountId } : {} } }; } function doesRuntimeContextWatcherMatch(params) { if (params.watcher.channelId && params.watcher.channelId !== params.event.key.channelId) return false; if (params.watcher.accountId !== void 0 && params.watcher.accountId !== (params.event.key.accountId ?? "")) return false; if (params.watcher.capability && params.watcher.capability !== params.event.key.capability) return false; return true; } /** Creates the in-memory channel runtime context registry used by plugin runtime surfaces. */ function createChannelRuntimeContextRegistry() { const runtimeContexts = /* @__PURE__ */ new Map(); const runtimeContextWatchers = /* @__PURE__ */ new Set(); const emitRuntimeContextEvent = (event) => { for (const watcher of runtimeContextWatchers) { if (!doesRuntimeContextWatcherMatch({ watcher: watcher.filter, event })) continue; try { watcher.onEvent(event); } catch (error) { const message = error instanceof Error ? error.message : String(error); log.error(`runtime context watcher failed during ${event.type} channel=${event.key.channelId} capability=${event.key.capability}` + (event.key.accountId ? ` account=${event.key.accountId}` : "") + `: ${message}`); } } }; return { register: (params) => { const normalized = normalizeRuntimeContextKey(params); if (!normalized) return { dispose: () => {} }; if (params.abortSignal?.aborted) return { dispose: () => {} }; const token = Symbol(normalized.mapKey); let disposed = false; const dispose = () => { if (disposed) return; disposed = true; const current = runtimeContexts.get(normalized.mapKey); if (!current || current.token !== token) return; runtimeContexts.delete(normalized.mapKey); emitRuntimeContextEvent({ type: "unregistered", key: normalized.normalizedKey }); }; params.abortSignal?.addEventListener("abort", dispose, { once: true }); if (params.abortSignal?.aborted) { dispose(); return { dispose }; } runtimeContexts.set(normalized.mapKey, { token, context: params.context, normalizedKey: normalized.normalizedKey }); if (disposed) return { dispose }; emitRuntimeContextEvent({ type: "registered", key: normalized.normalizedKey, context: params.context }); return { dispose }; }, get: (params) => { const normalized = normalizeRuntimeContextKey(params); if (!normalized) return; return runtimeContexts.get(normalized.mapKey)?.context; }, watch: (params) => { const watcher = { filter: { ...params.channelId?.trim() ? { channelId: params.channelId.trim() } : {}, ...params.accountId != null ? { accountId: params.accountId.trim() } : {}, ...params.capability?.trim() ? { capability: params.capability.trim() } : {} }, onEvent: params.onEvent }; runtimeContextWatchers.add(watcher); return () => { runtimeContextWatchers.delete(watcher); }; } }; } //#endregion //#region src/plugins/runtime/runtime-channel.ts function createRuntimeChannel() { return { text: { chunkByNewline, chunkMarkdownText, chunkMarkdownTextWithMode, chunkText, chunkTextWithMode, resolveChunkMode, resolveTextChunkLimit, hasControlCommand, resolveMarkdownTableMode, convertMarkdownTables }, reply: { dispatchReplyWithBufferedBlockDispatcher, createReplyDispatcherWithTyping, resolveEffectiveMessagesConfig, resolveHumanDelayConfig, dispatchReplyFromConfig, withReplyDispatcher, settleReplyDispatcher, finalizeInboundContext, formatAgentEnvelope, /** @deprecated Prefer `BodyForAgent` + structured user-context blocks (do not build plaintext envelopes for prompts). */ formatInboundEnvelope, resolveEnvelopeFormatOptions }, routing: { buildAgentSessionKey, resolveAgentRoute }, pairing: { buildPairingReply, readAllowFromStore: ({ channel, accountId, env }) => readChannelAllowFromStore(channel, env, accountId), upsertPairingRequest: ({ channel, id, accountId, meta, env, pairingAdapter }) => upsertChannelPairingRequest({ channel, id, accountId, meta, env, pairingAdapter }) }, media: { readRemoteMediaBuffer, fetchRemoteMedia, saveRemoteMedia, saveResponseMedia, saveMediaBuffer }, activity: { record: recordChannelActivity, get: getChannelActivity }, session: { resolveStorePath, readSessionUpdatedAt, recordSessionMetaFromInbound, recordInboundSession, updateLastRoute }, mentions: { buildMentionRegexes, matchesMentionPatterns, matchesMentionWithExplicit, implicitMentionKindWhen, resolveInboundMentionDecision }, reactions: { createAckReactionHandle, shouldAckReaction, removeAckReactionAfterReply, removeAckReactionHandleAfterReply }, groups: { resolveGroupPolicy: resolveChannelGroupPolicy, resolveRequireMention: resolveChannelGroupRequireMention }, debounce: { createInboundDebouncer, resolveInboundDebounceMs }, commands: { resolveCommandAuthorizedFromAuthorizers, isControlCommandMessage, shouldComputeCommandAuthorized, shouldHandleTextCommands }, outbound: { loadAdapter: loadChannelOutboundAdapter }, inbound: { buildContext: buildChannelInboundEventContext, run: runChannelInboundEvent, runPreparedReply: runPreparedInboundReply, dispatchReply: dispatchChannelInboundReply }, threadBindings: { setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) => setChannelConversationBindingIdleTimeoutBySessionKey({ channelId, targetSessionKey, accountId, idleTimeoutMs }), setMaxAgeBySessionKey: ({ channelId, targetSessionKey, accountId, maxAgeMs }) => setChannelConversationBindingMaxAgeBySessionKey({ channelId, targetSessionKey, accountId, maxAgeMs }) }, runtimeContexts: createChannelRuntimeContextRegistry() }; } //#endregion export { createRuntimeChannel as t };