openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
262 lines (261 loc) • 11.8 kB
JavaScript
import { t as isPromiseLike } from "./promise-like-D7-l5Fsp.mjs";
import { t as createHostChannelInboundEventContextBuilder } from "./host-context-builder-D5DUAH9V.mjs";
import { r as shouldIncludeSupplementalContext } from "./context-visibility-C5CaKMWO.mjs";
import { n as createCommandTurnContext, t as commandTurnKindToSource } from "./command-turn-context-B-DtktkV.mjs";
import { i as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-jAt0CAb-.mjs";
import { t as copyConversationBindingRouteFacts } from "./conversation-binding-route-facts-DCKt7P60.mjs";
import { t as buildChannelInboundMediaPayload } from "./media-WfthCSQx.mjs";
//#region src/channels/inbound-event/context.ts
/**
* Channel inbound event context builder.
*
* Converts route, sender, command, media, and supplemental facts into finalized message context.
*/
function filterSupplementalContext(params) {
if (!params.mode || params.mode === "all") return params.context;
if (params.context?.senderAllowed === void 0) return;
return shouldIncludeSupplementalContext({
mode: params.mode,
kind: params.kind,
senderAllowed: params.context.senderAllowed
}) ? params.context : void 0;
}
function filterChannelInboundSupplementalContext(params) {
const supplemental = params.supplemental;
if (!supplemental) return;
return {
...supplemental,
quote: filterSupplementalContext({
mode: params.contextVisibility,
kind: "quote",
context: supplemental.quote
}),
forwarded: filterSupplementalContext({
mode: params.contextVisibility,
kind: "forwarded",
context: supplemental.forwarded
}),
thread: filterSupplementalContext({
mode: params.contextVisibility,
kind: "thread",
context: supplemental.thread
})
};
}
/** Resolves whether a supplemental-context sender passes the active group policy. */
function resolveInboundSupplementalSenderAllowed(params) {
if (!params.isGroup || params.groupPolicy !== "allowlist") return true;
return params.isSenderAllowed(params.allowFrom);
}
function filterChannelInboundQuoteContext(contextVisibility, quote) {
return filterSupplementalContext({
mode: contextVisibility,
kind: "quote",
context: quote
});
}
function definedFields(fields) {
return Object.fromEntries(Object.entries(fields).filter((entry) => entry[1] !== void 0));
}
function resolveChannelInboundSupplementalForFinalizer(params) {
const rawSupplemental = params.supplemental;
const filtered = filterChannelInboundSupplementalContext({
supplemental: rawSupplemental,
contextVisibility: params.contextVisibility
});
const media = [...params.media ?? []];
if (!rawSupplemental?.quote || !filtered?.quote) return {
rawSupplemental,
supplemental: filtered,
media
};
const quote = filtered.quote;
const selfQuote = quote.isSelf === true;
const suppressSelfQuoteBody = params.suppressSelfQuoteBody ?? false;
const suppressSelfQuoteMedia = params.suppressSelfQuoteMedia ?? true;
const finalizeQuote = (quoteMedia) => {
if (!(selfQuote && suppressSelfQuoteMedia)) media.push(...quoteMedia ?? []);
const { media: _media, isSelf: _isSelf, ...stripped } = quote;
const visibleQuote = selfQuote && suppressSelfQuoteBody ? (({ body: _body, ...withoutBody }) => withoutBody)(stripped) : stripped;
return {
rawSupplemental,
supplemental: {
...filtered,
quote: visibleQuote
},
media
};
};
if (selfQuote && suppressSelfQuoteMedia) return finalizeQuote(void 0);
if (!params.resolveSupplementalMedia) return finalizeQuote(Array.isArray(quote.media) ? quote.media : void 0);
if (typeof quote.media !== "function") return finalizeQuote(quote.media);
const resolved = quote.media();
return isPromiseLike(resolved) ? resolved.then(finalizeQuote) : finalizeQuote(resolved);
}
function finalizePreparedChannelInboundContext(params) {
const mediaPayload = params.media ? definedFields(buildChannelInboundMediaPayload(params.media)) : {};
const baseContext = {
...params.originalContext,
SupplementalContext: params.supplemental,
...params.media ? { media: [...params.media] } : {},
...mediaPayload
};
const channelStructuredContext = resolveChannelStructuredContext({
supplemental: params.supplemental,
extra: baseContext
});
return {
context: (params.finalize ?? finalizeInboundContext)({
...baseContext,
...channelStructuredContext !== void 0 ? { ChannelStructuredContext: channelStructuredContext } : {}
}, params.finalizeOptions),
supplemental: params.supplemental,
quoteHidden: Boolean(params.rawSupplemental?.quote && !params.supplemental?.quote),
forwardedHidden: Boolean(params.rawSupplemental?.forwarded && !params.supplemental?.forwarded),
threadHidden: Boolean(params.rawSupplemental?.thread && !params.supplemental?.thread)
};
}
function finalizeChannelInboundContext(params) {
const contextSupplemental = params.context.SupplementalContext;
const prepared = resolveChannelInboundSupplementalForFinalizer({
supplemental: params.supplemental ?? contextSupplemental,
contextVisibility: params.contextVisibility,
media: params.media,
resolveSupplementalMedia: params.resolveSupplementalMedia,
suppressSelfQuoteBody: params.suppressSelfQuoteBody,
suppressSelfQuoteMedia: params.suppressSelfQuoteMedia
});
const finish = (result) => finalizePreparedChannelInboundContext({
originalContext: params.context,
finalize: params.finalize,
finalizeOptions: params.finalizeOptions,
...result
});
if (params.resolveSupplementalMedia) return Promise.resolve(prepared).then(finish);
return isPromiseLike(prepared) ? prepared.then(finish) : finish(prepared);
}
function normalizeUntrustedGroupPrompt(value) {
if (typeof value !== "string") return;
const normalized = normalizeInboundTextNewlines(value);
return normalized.trim().length > 0 ? normalized : void 0;
}
function resolveChannelStructuredContext(params) {
const entries = [];
const extraEntries = params.extra?.ChannelStructuredContext ?? params.extra?.UntrustedStructuredContext;
if (Array.isArray(extraEntries)) entries.push(...extraEntries);
const supplementalEntries = params.supplemental?.channelStructuredContext ?? params.supplemental?.untrustedContext;
if (supplementalEntries !== void 0) entries.push(...supplementalEntries);
const groupPrompt = normalizeUntrustedGroupPrompt(params.supplemental?.untrustedGroupSystemPrompt);
if (groupPrompt) entries.push({
label: "Group prompt context",
type: "group_prompt_context",
payload: { text: groupPrompt }
});
return extraEntries !== void 0 || supplementalEntries !== void 0 || groupPrompt !== void 0 ? entries : void 0;
}
function resolveChannelCommandContext(params) {
if (params.commandTurn) return params.commandTurn;
const command = params.command;
if (!command) return;
const body = command.body ?? params.message.commandBody ?? params.message.rawBody;
return createCommandTurnContext(commandTurnKindToSource(command.kind), {
authorized: command.kind === "normal" ? false : command.authorized ?? params.access?.commands?.authorized === true,
commandName: command.name,
body
});
}
function buildChannelInboundEventContext(params) {
return buildChannelInboundEventContextValue(params);
}
const buildHostChannelInboundEventContextValue = createHostChannelInboundEventContextBuilder(buildChannelInboundEventContextValue);
function buildHostChannelInboundEventContext(params) {
return buildHostChannelInboundEventContextValue(params);
}
function buildChannelInboundEventContextValue(params) {
const body = params.message.body ?? params.message.rawBody;
const commandTurn = resolveChannelCommandContext({
command: params.command,
commandTurn: params.commandTurn,
message: params.message,
access: params.access
});
const context = {
Body: body,
InboundEventKind: params.message.inboundEventKind ?? "user_request",
BodyForAgent: params.message.bodyForAgent ?? params.message.rawBody,
InboundHistory: params.message.inboundHistory,
SessionTranscriptContext: params.sessionTranscript && params.sessionTranscript.historyLimit > 0 ? params.sessionTranscript : void 0,
SourceModality: params.message.sourceModality,
RawBody: params.message.rawBody,
CommandBody: params.message.commandBody ?? params.message.rawBody,
BodyForCommands: params.message.commandBody ?? params.message.rawBody,
From: params.from,
To: params.reply.to,
SessionKey: params.route.dispatchSessionKey ?? params.route.routeSessionKey,
AgentId: params.route.agentId,
DmScope: params.route.dmScope,
AccountId: params.route.accountId ?? params.accountId,
ParentSessionKey: params.route.parentSessionKey,
ModelParentSessionKey: params.route.modelParentSessionKey,
MessageSid: params.messageId,
MessageSidFull: params.messageIdFull,
ReplyToId: params.reply.replyToId,
ReplyToIdFull: params.reply.replyToIdFull,
ChatType: params.conversation.kind,
ChatId: params.conversation.id,
ConversationRoutePeerId: params.conversation.routePeer?.id,
ConversationLabel: params.conversation.label,
GroupSubject: params.conversation.kind !== "direct" ? params.conversation.label : void 0,
GroupSpace: params.conversation.spaceId,
SenderName: params.sender.name ?? params.sender.displayLabel,
SenderId: params.sender.id,
SenderUsername: params.sender.username,
SenderTag: params.sender.tag,
SenderIsBot: params.sender.isBot,
SenderIsSelf: params.sender.isSelf === true ? true : void 0,
MemberRoleIds: params.sender.roles,
Timestamp: params.timestamp,
Provider: params.provider ?? params.channel,
Surface: params.surface ?? params.provider ?? params.channel,
WasMentioned: params.access?.mentions?.wasMentioned,
GroupRequireMention: params.access?.mentions?.requireMention,
ExplicitlyMentionedBot: params.access?.mentions?.explicitlyMentionedBot,
MentionedUserIds: params.access?.mentions?.mentionedUserIds,
MentionedSubteamIds: params.access?.mentions?.mentionedSubteamIds,
ImplicitMentionKinds: params.access?.mentions?.implicitMentionKinds,
MentionSource: params.access?.mentions?.mentionSource,
CommandAuthorized: params.access?.commands?.authorized === true,
ConversationToolPolicy: params.access?.toolPolicy,
CommandTurn: commandTurn,
MessageThreadId: params.reply.messageThreadId ?? params.conversation.threadId,
NativeChannelId: params.reply.nativeChannelId ?? params.conversation.nativeChannelId,
ConversationAvatar: params.conversation.avatar,
ConversationLink: params.conversation.link,
ChannelContext: params.channelContext,
OriginatingChannel: params.channel,
OriginatingTo: params.reply.originatingTo ?? params.reply.to,
ThreadParentId: params.reply.threadParentId ?? params.conversation.parentId,
InboundAccessAuthorized: true,
ConversationRouteContextObserved: params.conversation.routePeer ? true : void 0,
...params.extra
};
copyConversationBindingRouteFacts(params.route, context);
const finalizeParams = {
finalize: params.finalize,
finalizeOptions: params.finalizeOptions,
supplemental: params.supplemental,
contextVisibility: params.contextVisibility,
media: params.media,
context
};
const result = params.resolveSupplementalMedia ? finalizeChannelInboundContext({
...finalizeParams,
resolveSupplementalMedia: true,
suppressSelfQuoteBody: params.suppressSelfQuoteBody,
suppressSelfQuoteMedia: params.suppressSelfQuoteMedia
}) : finalizeChannelInboundContext(finalizeParams);
const unwrap = (finalized) => finalized.context;
return isPromiseLike(result) ? result.then(unwrap) : unwrap(result);
}
//#endregion
export { finalizeChannelInboundContext as a, filterChannelInboundSupplementalContext as i, buildHostChannelInboundEventContext as n, resolveInboundSupplementalSenderAllowed as o, filterChannelInboundQuoteContext as r, buildChannelInboundEventContext as t };