Files
openclaw/src/plugin-sdk/direct-dm.ts
2026-05-01 23:55:26 +01:00

152 lines
4.9 KiB
TypeScript

import type { DispatchReplyWithBufferedBlockDispatcher } from "../auto-reply/reply/provider-dispatcher.types.js";
import type { FinalizedMsgContext } from "../auto-reply/templating.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { resolveInboundRouteEnvelopeBuilderWithRuntime } from "./inbound-envelope.js";
import { recordInboundSessionAndDispatchReply } from "./inbound-reply-dispatch.js";
import type { OutboundReplyPayload } from "./reply-payload.js";
export {
createPreCryptoDirectDmAuthorizer,
resolveInboundDirectDmAccessWithRuntime,
type AccessGroupMembershipResolver,
type DirectDmCommandAuthorizationRuntime,
type ResolvedInboundDirectDmAccess,
} from "./direct-dm-access.js";
export {
createDirectDmPreCryptoGuardPolicy,
type DirectDmPreCryptoGuardPolicy,
type DirectDmPreCryptoGuardPolicyOverrides,
} from "./direct-dm-guard-policy.js";
type DirectDmRoutePeer = {
kind: "direct";
id: string;
};
type DirectDmRoute = {
agentId: string;
sessionKey: string;
accountId?: string;
};
type DirectDmRuntime = {
channel: {
routing: {
resolveAgentRoute: (params: {
cfg: OpenClawConfig;
channel: string;
accountId: string;
peer: DirectDmRoutePeer;
}) => DirectDmRoute;
};
session: {
resolveStorePath: typeof import("../config/sessions.js").resolveStorePath;
readSessionUpdatedAt: (params: {
storePath: string;
sessionKey: string;
}) => number | undefined;
recordInboundSession: typeof import("../channels/session.js").recordInboundSession;
};
reply: {
resolveEnvelopeFormatOptions: (
cfg: OpenClawConfig,
) => ReturnType<typeof import("../auto-reply/envelope.js").resolveEnvelopeFormatOptions>;
formatAgentEnvelope: typeof import("../auto-reply/envelope.js").formatAgentEnvelope;
finalizeInboundContext: typeof import("../auto-reply/reply/inbound-context.js").finalizeInboundContext;
dispatchReplyWithBufferedBlockDispatcher: DispatchReplyWithBufferedBlockDispatcher;
};
};
};
/** Route, envelope, record, and dispatch one direct-DM turn through the standard pipeline. */
export async function dispatchInboundDirectDmWithRuntime(params: {
cfg: OpenClawConfig;
runtime: DirectDmRuntime;
channel: string;
channelLabel: string;
accountId: string;
peer: DirectDmRoutePeer;
senderId: string;
senderAddress: string;
recipientAddress: string;
conversationLabel: string;
rawBody: string;
messageId: string;
timestamp?: number;
commandAuthorized?: boolean;
bodyForAgent?: string;
commandBody?: string;
provider?: string;
surface?: string;
originatingChannel?: string;
originatingTo?: string;
extraContext?: Record<string, unknown>;
deliver: (payload: OutboundReplyPayload) => Promise<void>;
onRecordError: (err: unknown) => void;
onDispatchError: (err: unknown, info: { kind: string }) => void;
}): Promise<{
route: DirectDmRoute;
storePath: string;
ctxPayload: FinalizedMsgContext;
}> {
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,
OriginatingChannel: params.originatingChannel ?? params.channel,
OriginatingTo: params.originatingTo ?? params.recipientAddress,
...params.extraContext,
});
await recordInboundSessionAndDispatchReply({
cfg: params.cfg,
channel: params.channel,
accountId: route.accountId ?? params.accountId,
agentId: route.agentId,
routeSessionKey: route.sessionKey,
storePath,
ctxPayload,
recordInboundSession: params.runtime.channel.session.recordInboundSession,
dispatchReplyWithBufferedBlockDispatcher:
params.runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher,
deliver: params.deliver,
onRecordError: params.onRecordError,
onDispatchError: params.onDispatchError,
});
return {
route,
storePath,
ctxPayload,
};
}