openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
631 lines (630 loc) • 24.5 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.mjs";
import { c as resolveSessionStorePathCore } from "./paths-Bonddxfk.mjs";
import { r as resolveAgentConfig } from "./agent-scope-config-BEk6-ThS.mjs";
import { i as toDatabaseOptions } from "./session-accessor.sqlite-scope-helpers-CfDTAEsL.mjs";
import "./agent-scope-bJOokm5r.mjs";
import { r as supportsOpenClawAgentDatabaseExecution } from "./openclaw-agent-execution-C2B2fucX.mjs";
import { d as withOwnedSessionTranscriptWriterFence } from "./transcript-write-context-DwwjCPCE.mjs";
import "./group-thread-context-DLcO7Z-w.mjs";
import { n as readChannelIngressStoreAllowFromForDmPolicy } from "./store-allow-from-VtdIouAp.mjs";
import { d as resolveSqliteTranscriptScope, n as captureLifecycleDatabaseScope } from "./session-accessor.sqlite-scope-BkgwxatT.mjs";
import { r as captureIncognitoSessionOperation } from "./session-incognito-binding-Dp6RTei2.mjs";
import { i as startSessionTranscriptIndexReconcile } from "./session-transcript-reconcile-BwrFIOby.mjs";
import { n as runSessionEntryWorkerOperation } from "./session-entry-patch-fXJDvWHG.mjs";
import { n as assertNonMessageTranscriptEvent } from "./session-accessor.sqlite-transcript-write-guard-B9tPlUJx.mjs";
import { t as appendTranscriptEvent } from "./session-accessor.sqlite-transcript-write-ClP59_lJ.mjs";
import { u as readSessionUpdatedAtCore } from "./session-accessor.sqlite-entry-DLa7_9ui.mjs";
import { t as expandAllowFromWithAccessGroups } from "./access-groups-b3YFEUNd.mjs";
import { n as resolveDmGroupAccessWithLists, t as DM_GROUP_ACCESS_REASON } from "./dm-policy-shared-BAoCKf0l.mjs";
import "./session-accessor-C3ljJ974.mjs";
import { l as withSessionEntryReadOnlyInWorker, o as readSessionUpdatedAtInWorker } from "./session-entry-read-runtime-BdnQjoL6.mjs";
import { t as executeSessionMessageRewriteOperation } from "./session-message-rewrite-domain-Ll8GY8i_.mjs";
import { o as resolveSessionTranscriptRuntimeTarget } from "./session-accessor.transcript-target-DdAdqCJ1.mjs";
import { n as resolveInboundDebounceMs, t as createInboundDebouncer } from "./inbound-debounce-D_uzsHO6.mjs";
import "./location-CxESZbHi.mjs";
import { c as normalizeOutboundReplyPayload } from "./reply-payload-eiK8mKuN.mjs";
import "./sessions-CRUJeu5H.mjs";
import { o as resolveAgentRoute } from "./resolve-route-DeZAxBYa.mjs";
import "./mentions-DhMxVyTi.mjs";
import "./dispatch-24DdbDip.mjs";
import "./live-BtWpKyHV.mjs";
import { r as isControlCommandMessage } from "./command-detection-DD2oRRYt.mjs";
import { a as resolveEnvelopeFormatOptions } from "./envelope-UOtEX9A5.mjs";
import "./media-B-17jCYF.mjs";
import { i as filterChannelInboundSupplementalContext, n as buildHostChannelInboundEventContext, t as buildChannelInboundEventContext } from "./context-CNczOQBo.mjs";
import { n as publicChannelTurnParams, t as publicChannelTurn } from "./reply-options-vskFqRCa.mjs";
import { t as runPreparedChannelTurn } from "./execution-Dbc2Hj0P.mjs";
import { t as createChannelReplyPipeline } from "./reply-pipeline-Tm9TGN8z.mjs";
import { n as dispatchAssembledChannelTurn, r as dispatchRoutedChannelTurn } from "./lifecycle-HFxbsXpo.mjs";
import { n as runChannelTurn } from "./run-channel-turn-D73TvDkz.mjs";
import { n as createChannelInboundEnvelopeBuilderAsync, o as resolveInboundRouteEnvelopeBuilderWithRuntime } from "./envelope-z7JVcwnO.mjs";
import "./channel-access-compat-BJ4baF0D.mjs";
import "./direct-dm-guard-policy-DBugFbho.mjs";
import "./logging-C9LTVJNE.mjs";
import { isMainThread } from "node:worker_threads";
//#region src/channels/direct-dm-access.ts
function toLegacyDmReasonCode(reasonCode) {
switch (reasonCode) {
case DM_GROUP_ACCESS_REASON.DM_POLICY_OPEN:
case DM_GROUP_ACCESS_REASON.DM_POLICY_DISABLED:
case DM_GROUP_ACCESS_REASON.DM_POLICY_ALLOWLISTED:
case DM_GROUP_ACCESS_REASON.DM_POLICY_PAIRING_REQUIRED:
case DM_GROUP_ACCESS_REASON.DM_POLICY_NOT_ALLOWLISTED: return reasonCode;
default: return DM_GROUP_ACCESS_REASON.DM_POLICY_NOT_ALLOWLISTED;
}
}
/**
* Resolves legacy direct-DM access lists, pairing-store entries, and command authorization.
* @deprecated Use `resolveChannelMessageIngress` from `openclaw/plugin-sdk/channel-ingress-runtime`.
*/
async function resolveInboundDirectDmAccessWithRuntime(params) {
const dmPolicy = params.dmPolicy ?? "pairing";
const shouldComputeAuth = params.runtime.shouldComputeCommandAuthorized(params.rawBody, params.cfg);
const storeAllowFrom = dmPolicy === "pairing" ? await readChannelIngressStoreAllowFromForDmPolicy({
provider: params.channel,
accountId: params.accountId,
dmPolicy,
readStore: params.readStoreAllowFrom
}) : [];
const [allowFrom, effectiveStoreAllowFrom] = await Promise.all([params.allowFrom, storeAllowFrom].map((entries) => expandAllowFromWithAccessGroups({
cfg: params.cfg,
allowFrom: entries,
channel: params.channel,
accountId: params.accountId,
senderId: params.senderId,
isSenderAllowed: params.isSenderAllowed,
resolveMembership: params.resolveAccessGroupMembership
})));
const access = resolveDmGroupAccessWithLists({
isGroup: false,
dmPolicy,
allowFrom,
storeAllowFrom: effectiveStoreAllowFrom,
groupAllowFromFallbackToAllowFrom: false,
isSenderAllowed: (allowEntries) => params.isSenderAllowed(params.senderId, allowEntries)
});
const reasonCode = toLegacyDmReasonCode(access.reasonCode);
const senderAllowedForCommands = params.isSenderAllowed(params.senderId, access.effectiveAllowFrom);
const commandAuthorized = shouldComputeAuth ? params.runtime.resolveCommandAuthorizedFromAuthorizers?.({
useAccessGroups: true,
authorizers: [{
configured: access.effectiveAllowFrom.length > 0,
allowed: senderAllowedForCommands
}],
modeWhenAccessGroupsOff: params.modeWhenAccessGroupsOff
}) ?? senderAllowedForCommands : void 0;
return {
access: {
decision: access.decision,
reasonCode,
reason: access.reason,
effectiveAllowFrom: access.effectiveAllowFrom
},
shouldComputeAuth,
senderAllowedForCommands,
commandAuthorized
};
}
/**
* Creates a pre-crypto authorizer that can issue pairing challenges before payload decryption.
* @deprecated Use `resolveChannelMessageIngress` from `openclaw/plugin-sdk/channel-ingress-runtime`.
*/
function createPreCryptoDirectDmAuthorizer(params) {
return async (input) => {
const resolved = await params.resolveAccess(input.senderId);
const access = "access" in resolved ? resolved.access : resolved;
if (access.decision === "allow") return "allow";
if (access.decision === "pairing") {
await params.issuePairingChallenge?.({
senderId: input.senderId,
reply: input.reply
});
return "pairing";
}
params.onBlocked?.({
senderId: input.senderId,
reason: access.reason,
reasonCode: access.reasonCode
});
return "block";
};
}
//#endregion
//#region src/channels/direct-dm.ts
async function buildDirectDmContext(params, route, body) {
const accountId = route.accountId ?? params.accountId;
const injectedBuilder = params.channelRuntime?.inbound?.buildContext;
return (typeof injectedBuilder === "function" ? injectedBuilder : buildChannelInboundEventContext)({
channel: params.channel,
accountId,
provider: params.provider,
surface: params.surface,
messageId: params.messageId,
messageIdFull: params.messageId,
timestamp: params.timestamp,
from: params.senderAddress,
sender: {
id: params.senderId,
name: params.conversationLabel
},
conversation: {
kind: "direct",
id: params.peer.id,
routePeer: params.peer,
label: params.conversationLabel
},
route: {
agentId: route.agentId,
accountId: route.accountId,
routeSessionKey: route.sessionKey,
dispatchSessionKey: route.sessionKey
},
reply: {
to: params.recipientAddress,
originatingTo: params.originatingTo ?? params.senderAddress
},
message: {
body,
bodyForAgent: params.bodyForAgent ?? params.rawBody,
rawBody: params.rawBody,
commandBody: params.commandBody ?? params.rawBody
},
access: { commands: { authorized: params.commandAuthorized === true } },
channelIngress: params.channelIngress,
extra: {
NativeDirectUserId: params.peer.id,
OriginatingChannel: params.originatingChannel ?? params.channel,
...params.extraContext
}
});
}
async function dispatchInboundDirectDm(params) {
const route = resolveAgentRoute({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
peer: params.peer
});
const channelIngress = params.resolveChannelIngress ? await params.resolveChannelIngress({
agentId: route.agentId,
sessionKey: route.sessionKey,
messageId: params.messageId,
inboundEventKind: "user_request"
}) : params.channelIngress;
const boundParams = channelIngress === params.channelIngress ? params : {
...params,
channelIngress
};
const ctxPayload = await buildDirectDmContext(boundParams, route, (await createChannelInboundEnvelopeBuilderAsync({
cfg: params.cfg,
route
}))({
channel: params.channelLabel,
from: params.conversationLabel,
body: params.rawBody,
timestamp: params.timestamp
}));
await dispatchRoutedChannelTurn(buildDirectDmTurnPlan(boundParams, route, ctxPayload));
return {
route,
ctxPayload
};
}
function buildDirectDmTurnPlan(params, route, ctxPayload) {
const { onModelSelected, ...replyPipeline } = createChannelReplyPipeline({
cfg: params.cfg,
agentId: route.agentId,
channel: params.channel,
accountId: route.accountId ?? params.accountId
});
return {
cfg: params.cfg,
channel: params.channel,
accountId: route.accountId ?? params.accountId,
route: {
agentId: route.agentId,
sessionKey: route.sessionKey
},
ctxPayload,
record: { onRecordError: params.onRecordError },
delivery: {
deliver: async (payload) => await params.deliver(normalizeOutboundReplyPayload(payload)),
onError: params.onDispatchError
},
replyPipeline,
replyOptions: {
onModelSelected,
...params.turnAdoptionLifecycle ? { turnAdoptionLifecycle: params.turnAdoptionLifecycle } : {}
}
};
}
/** @deprecated Use dispatchInboundDirectDm. Retained for released SDK runtime callbacks until the next major. */
async function dispatchInboundDirectDmWithRuntime(params) {
const { route, buildEnvelope } = resolveInboundRouteEnvelopeBuilderWithRuntime({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
peer: params.peer,
runtime: params.runtime.channel,
sessionStore: params.cfg.session?.store
});
const { storePath, body } = buildEnvelope({
channel: params.channelLabel,
from: params.conversationLabel,
body: params.rawBody,
timestamp: params.timestamp
});
const ctxPayload = params.runtime.channel.reply.finalizeInboundContext({
Body: body,
BodyForAgent: params.bodyForAgent ?? params.rawBody,
RawBody: params.rawBody,
CommandBody: params.commandBody ?? params.rawBody,
From: params.senderAddress,
To: params.recipientAddress,
SessionKey: route.sessionKey,
AccountId: route.accountId ?? params.accountId,
ChatType: "direct",
ConversationLabel: params.conversationLabel,
SenderId: params.senderId,
Provider: params.provider ?? params.channel,
Surface: params.surface ?? params.channel,
MessageSid: params.messageId,
MessageSidFull: params.messageId,
Timestamp: params.timestamp,
CommandAuthorized: params.commandAuthorized,
...params.inboundAccessAuthorized === true ? {
InboundAccessAuthorized: true,
ConversationRouteContextObserved: true
} : {},
ConversationRoutePeerId: params.peer.id,
OriginatingChannel: params.originatingChannel ?? params.channel,
OriginatingTo: params.originatingTo ?? params.senderAddress,
NativeDirectUserId: params.peer.id,
...params.extraContext
});
const plan = buildDirectDmTurnPlan(params, route, ctxPayload);
await params.runtime.channel.inbound.run({
channel: params.channel,
accountId: route.accountId ?? params.accountId,
raw: ctxPayload,
adapter: {
ingest: () => ({
id: params.messageId,
timestamp: params.timestamp,
rawText: params.rawBody,
textForAgent: params.bodyForAgent,
textForCommands: params.commandBody,
raw: ctxPayload
}),
resolveTurn: () => plan
}
});
return {
route,
storePath,
ctxPayload
};
}
//#endregion
//#region src/channels/inbound-debounce-policy.ts
function shouldDebounceTextInbound(params) {
if (params.allowDebounce === false) return false;
if (params.hasMedia) return false;
const text = normalizeOptionalString(params.text) ?? "";
if (!text) return false;
return !isControlCommandMessage(text, params.cfg, params.commandOptions);
}
/** Snapshot timing by default; resolveDebounceMs opts into per-entry timing. */
function createChannelInboundDebouncer(params) {
const debounceMs = resolveInboundDebounceMs({
cfg: params.cfg,
channel: params.channel,
overrideMs: params.debounceMsOverride
});
const { cfg: _cfg, channel: _channel, debounceMsOverride: _override, ...rest } = params;
return {
debounceMs,
debouncer: createInboundDebouncer({
debounceMs,
...rest
})
};
}
//#endregion
//#region src/channels/session-envelope.ts
/** @deprecated Use resolveInboundSessionEnvelopeContextAsync. Retained until the next Plugin SDK major. */
function resolveInboundSessionEnvelopeContext(params) {
const storePath = resolveSessionStorePathCore(params.cfg.session?.store, { agentId: params.agentId });
return {
storePath,
envelopeOptions: resolveEnvelopeFormatOptions(params.cfg),
previousTimestamp: readSessionUpdatedAtCore({
storePath,
sessionKey: params.sessionKey
})
};
}
/** Prepares descriptive session facts before building an inbound envelope. */
async function resolveInboundSessionEnvelopeContextAsync(params) {
const storePath = resolveSessionStorePathCore(params.cfg.session?.store, { agentId: params.agentId });
return {
storePath,
envelopeOptions: resolveEnvelopeFormatOptions(params.cfg),
previousTimestamp: await readSessionUpdatedAtInWorker({
storePath,
sessionKey: params.sessionKey
})
};
}
//#endregion
//#region src/channels/inbound-event/classification.ts
function classifyChannelInboundEvent(params) {
if (params.unmentionedGroupPolicy !== "room_event") return "user_request";
if (params.conversation.kind !== "group" && params.conversation.kind !== "channel") return "user_request";
if (params.wasMentioned === true || params.hasControlCommand === true || params.hasAbortRequest === true || params.commandSource === "native") return "user_request";
return "room_event";
}
function resolveUnmentionedGroupInboundPolicy(params) {
const agentGroupChat = params.agentId ? resolveAgentConfig(params.cfg, params.agentId)?.groupChat : void 0;
if (agentGroupChat && Object.hasOwn(agentGroupChat, "unmentionedInbound")) return agentGroupChat.unmentionedInbound ?? "user_request";
return params.cfg.messages?.groupChat?.unmentionedInbound ?? "user_request";
}
//#endregion
//#region src/config/sessions/session-transcript-event.ts
/** Retain the selected reader through the canonical writer's acknowledged event append. */
async function appendPreparedTranscriptEvent(requested, event, assertCurrent) {
assertNonMessageTranscriptEvent(event);
const fenced = withOwnedSessionTranscriptWriterFence(requested);
const scope = captureLifecycleDatabaseScope(resolveSqliteTranscriptScope(fenced));
const database = {
...toDatabaseOptions(scope),
path: scope.path
};
const eventJson = JSON.stringify(event);
assertCurrent();
const incognito = captureIncognitoSessionOperation(fenced);
if (incognito) {
await incognito.actor.sessions.transcript({ assertCurrent() {
incognito.authority.assertCurrent();
assertCurrent();
} }, {
type: "session.event.append",
input: {
sessionKey: scope.sessionKey,
sessionId: scope.sessionId,
fence: {
expectedLifecycleRevision: fenced.expectedLifecycleRevision,
expectedWriterRunId: fenced.expectedWriterRunId,
expectedOwner: fenced.expectedOwner
},
eventJson
}
}, void 0, void 0, ({ projectionNeedsReconcile }) => {
if (projectionNeedsReconcile) startSessionTranscriptIndexReconcile({
...database,
preferredSessionId: scope.sessionId
});
});
return;
}
if (!isMainThread || !supportsOpenClawAgentDatabaseExecution(database)) return appendTranscriptEvent(requested, JSON.parse(eventJson), { beforeCommitInTransaction: assertCurrent });
await runSessionEntryWorkerOperation({
database,
agentId: scope.agentId,
assertCurrent,
candidateKind: "session-transcript-event",
prepareWorker: () => ({
async prepare() {
const { restoreSessionColdTranscript } = await import("./session-cold-storage-L7zFwmx1.mjs");
await restoreSessionColdTranscript({
...requested,
env: scope.env
}, assertCurrent);
},
beforeWrite: assertCurrent,
async release() {}
}),
run: (worker, commit) => commit(() => executeSessionMessageRewriteOperation(worker, database.agentId, {
type: "session.transcript.event.append",
input: {
scope,
eventJson
}
})),
onCommitted: ({ projectionNeedsReconcile }) => {
if (projectionNeedsReconcile) startSessionTranscriptIndexReconcile({
...database,
preferredSessionId: scope.sessionId
});
return true;
}
});
}
//#endregion
//#region src/channels/feedback-reflection.ts
const DEFAULT_CHANNEL_FEEDBACK_REFLECTION_COOLDOWN_MS = 3e5;
const MAX_RESPONSE_CHARS = 500;
const MAX_COOLDOWN_ENTRIES = 500;
const lastReflectionBySession = /* @__PURE__ */ new Map();
async function recordChannelFeedbackEvent(params) {
const storePath = resolveSessionStorePathCore(params.cfg.session?.store, { agentId: params.agentId });
return withSessionEntryReadOnlyInWorker({
agentId: params.agentId,
sessionKey: params.sessionKey,
storePath
}, () => {}, async (read, owner) => {
if (!read.ok) throw read.error;
if (!read.value?.sessionId) return false;
const target = await resolveSessionTranscriptRuntimeTarget({
...owner.scope,
agentId: params.agentId,
sessionId: read.value.sessionId,
sessionKey: params.sessionKey,
storePath: owner.scope?.storePath ?? storePath
});
owner.assertCurrent();
await appendPreparedTranscriptEvent({
...target,
env: owner.scope?.env
}, params.event, owner.assertCurrent);
return true;
});
}
function buildReflectionPrompt(params) {
const response = params.thumbedDownResponse;
const truncated = response && response.length > MAX_RESPONSE_CHARS ? `${truncateUtf16Safe(response, MAX_RESPONSE_CHARS)}...` : response;
return [
"A user indicated your previous response wasn't helpful.",
truncated ? `\nYour response was:\n> ${truncated}` : void 0,
params.userComment ? `\nUser's comment: "${params.userComment}"` : void 0,
"\nBriefly reflect: what could you improve? Consider tone, length, accuracy, relevance, and specificity. Reply with one JSON object only: {\"learning\":\"...\",\"followUp\":false,\"userMessage\":\"\"}. Keep learning to 1-2 sentences. Set followUp only when the user needs a direct reply."
].filter(Boolean).join("\n");
}
function parseReflectionResponse(text) {
const trimmed = text.trim();
const candidates = [trimmed, ...trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i)?.slice(1, 2) ?? []];
for (const candidate of candidates) try {
const value = JSON.parse(candidate.trim());
const learning = typeof value.learning === "string" ? value.learning.trim() : "";
if (!learning) continue;
return {
learning,
followUp: value.followUp === true || typeof value.followUp === "string" && ["true", "yes"].includes(value.followUp.trim().toLowerCase()),
userMessage: (typeof value.userMessage === "string" ? value.userMessage.trim() : "") || void 0
};
} catch {}
return trimmed ? {
learning: trimmed,
followUp: false
} : null;
}
async function runChannelFeedbackReflection(params) {
const cooldownMs = params.cooldownMs ?? 3e5;
if (Date.now() - (lastReflectionBySession.get(params.sessionKey) ?? Number.NEGATIVE_INFINITY) < cooldownMs) return { status: "cooldown" };
const prompt = buildReflectionPrompt(params);
const timestamp = Date.now();
const body = (await createChannelInboundEnvelopeBuilderAsync({
cfg: params.cfg,
route: {
agentId: params.agentId,
sessionKey: params.sessionKey
}
}))({
channel: params.channelLabel,
from: "system",
body: prompt,
timestamp
});
const target = `conversation:${params.conversationId}`;
const ctxPayload = buildHostChannelInboundEventContext({
channelIngress: "unsupported",
channel: params.channel,
accountId: params.accountId,
messageId: `feedback-reflection:${timestamp}`,
timestamp,
from: `${params.channel}:system:${params.conversationId}`,
sender: {
id: "system",
name: "system"
},
conversation: {
kind: params.conversationKind,
id: params.conversationId
},
route: {
agentId: params.agentId,
accountId: params.accountId,
routeSessionKey: params.sessionKey,
dispatchSessionKey: params.sessionKey
},
reply: {
to: target,
originatingTo: target
},
message: {
body,
bodyForAgent: prompt,
rawBody: prompt,
commandBody: prompt
},
access: { commands: { authorized: false } },
extra: { ConversationRouteContextObserved: false }
});
const responses = [];
await dispatchRoutedChannelTurn({
cfg: params.cfg,
channel: params.channel,
accountId: params.accountId,
route: {
agentId: params.agentId,
sessionKey: params.sessionKey
},
ctxPayload,
record: { onRecordError: params.onRecordError },
delivery: {
deliver: async (payload) => {
if (payload.text) responses.push(payload.text);
return { visibleReplySent: false };
},
onError: (error) => params.onDispatchError?.(error)
},
replyPipeline: {}
});
const response = responses.join("\n");
const parsed = parseReflectionResponse(response);
if (!parsed) return { status: "empty" };
lastReflectionBySession.set(params.sessionKey, Date.now());
if (lastReflectionBySession.size > MAX_COOLDOWN_ENTRIES) {
for (const [key, time] of lastReflectionBySession) if (Date.now() - time >= cooldownMs) lastReflectionBySession.delete(key);
}
return {
status: "complete",
learning: parsed.learning,
storePath: resolveSessionStorePathCore(params.cfg.session?.store, { agentId: params.agentId }),
followUp: parsed.followUp,
userMessage: parsed.userMessage,
responseLength: response.trim().length
};
}
//#endregion
//#region src/plugin-sdk/channel-inbound.ts
/**
* Builds inbound-event context for callers still passing `inboundTurnKind`.
*
* @deprecated Use `buildChannelInboundEventContext`.
*/
function buildChannelTurnContext(params) {
const inboundEventKind = params.message.inboundEventKind ?? params.message.inboundTurnKind;
const ctx = buildChannelInboundEventContext({
...params,
message: {
...params.message,
...inboundEventKind ? { inboundEventKind } : {}
}
});
return {
...ctx,
InboundTurnKind: ctx.InboundEventKind
};
}
/**
* Deprecated supplemental-context filter alias retained for channel SDK compatibility.
*
* @deprecated Use `filterChannelInboundSupplementalContext`.
*/
const filterChannelTurnSupplementalContext = filterChannelInboundSupplementalContext;
async function runPreparedInboundReply(params) {
return await runPreparedChannelTurn(params);
}
async function runChannelInboundEvent(params) {
return await runChannelTurn(publicChannelTurnParams(params));
}
async function dispatchChannelInboundReply(params) {
return await dispatchAssembledChannelTurn(publicChannelTurn(params));
}
async function dispatchChannelInboundTurn(params) {
return await dispatchRoutedChannelTurn(publicChannelTurn(params));
}
//#endregion
export { dispatchInboundDirectDmWithRuntime as _, runChannelInboundEvent as a, recordChannelFeedbackEvent as c, resolveUnmentionedGroupInboundPolicy as d, resolveInboundSessionEnvelopeContext as f, dispatchInboundDirectDm as g, shouldDebounceTextInbound as h, filterChannelTurnSupplementalContext as i, runChannelFeedbackReflection as l, createChannelInboundDebouncer as m, dispatchChannelInboundReply as n, runPreparedInboundReply as o, resolveInboundSessionEnvelopeContextAsync as p, dispatchChannelInboundTurn as r, DEFAULT_CHANNEL_FEEDBACK_REFLECTION_COOLDOWN_MS as s, buildChannelTurnContext as t, classifyChannelInboundEvent as u, createPreCryptoDirectDmAuthorizer as v, resolveInboundDirectDmAccessWithRuntime as y };