






















@@ -4,6 +4,7 @@ import {
44resolveEnvelopeFormatOptions,
55} from "openclaw/plugin-sdk/channel-inbound";
66import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
7+import { runPreparedInboundReplyTurn } from "openclaw/plugin-sdk/inbound-reply-dispatch";
78import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
89import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
910import { createNonExitingRuntime, logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -238,35 +239,6 @@ export async function dispatchDiscordComponentEvent(params: {
238239resolveDiscordComponentOriginatingTo(interactionCtx) ?? `channel:${interactionCtx.channelId}`,
239240});
240241241-await recordInboundSession({
242- storePath,
243-sessionKey: ctxPayload.SessionKey ?? sessionKey,
244-ctx: ctxPayload,
245-updateLastRoute: interactionCtx.isDirectMessage
246- ? {
247-sessionKey: route.mainSessionKey,
248-channel: "discord",
249-to:
250-resolveDiscordComponentOriginatingTo(interactionCtx) ?? `user:${interactionCtx.userId}`,
251- accountId,
252-mainDmOwnerPin: pinnedMainDmOwner
253- ? {
254-ownerRecipient: pinnedMainDmOwner,
255-senderRecipient: interactionCtx.userId,
256-onSkip: ({ ownerRecipient, senderRecipient }) => {
257-logVerbose(
258-`discord: skip main-session last route for ${senderRecipient} (pinned owner ${ownerRecipient})`,
259-);
260-},
261-}
262- : undefined,
263-}
264- : undefined,
265-onRecordError: (err) => {
266-logVerbose(`discord: failed updating component session meta: ${String(err)}`);
267-},
268-});
269-270242const deliverTarget = `channel:${interactionCtx.channelId}`;
271243const typingChannelId = interactionCtx.channelId;
272244const { createChannelReplyPipeline } = await loadReplyPipelineRuntime();
@@ -298,48 +270,83 @@ export async function dispatchDiscordComponentEvent(params: {
298270startId: params.replyToId,
299271});
300272301-await dispatchReplyWithBufferedBlockDispatcher({
302-ctx: ctxPayload,
303-cfg: ctx.cfg,
304-replyOptions: { onModelSelected },
305-dispatcherOptions: {
306- ...replyPipeline,
307-humanDelay: resolveHumanDelayConfig(ctx.cfg, agentId),
308-deliver: async (payload) => {
309-const replyToId = replyReference.use();
310-await deliverDiscordReply({
311-cfg: ctx.cfg,
312-replies: [payload],
313-target: deliverTarget,
314- token,
315- accountId,
316-rest: interaction.client.rest,
317- runtime,
318- replyToId,
319- replyToMode,
320- textLimit,
321-maxLinesPerMessage: resolveDiscordMaxLinesPerMessage({
322-cfg: ctx.cfg,
323-discordConfig: ctx.discordConfig,
273+await runPreparedInboundReplyTurn({
274+channel: "discord",
275+ accountId,
276+routeSessionKey: sessionKey,
277+ storePath,
278+ ctxPayload,
279+ recordInboundSession,
280+record: {
281+updateLastRoute: interactionCtx.isDirectMessage
282+ ? {
283+sessionKey: route.mainSessionKey,
284+channel: "discord",
285+to:
286+resolveDiscordComponentOriginatingTo(interactionCtx) ??
287+`user:${interactionCtx.userId}`,
324288 accountId,
325-}),
326- tableMode,
327-chunkMode: resolveChunkMode(ctx.cfg, "discord", accountId),
328- mediaLocalRoots,
329-});
330-replyReference.markSent();
331-},
332-onReplyStart: async () => {
333-try {
334-const { sendTyping } = await loadTypingRuntime();
335-await sendTyping({ rest: feedbackRest, channelId: typingChannelId });
336-} catch (err) {
337-logVerbose(`discord: typing failed for component reply: ${String(err)}`);
338-}
339-},
340-onError: (err) => {
341-logError(`discord component dispatch failed: ${String(err)}`);
289+mainDmOwnerPin: pinnedMainDmOwner
290+ ? {
291+ownerRecipient: pinnedMainDmOwner,
292+senderRecipient: interactionCtx.userId,
293+onSkip: ({ ownerRecipient, senderRecipient }) => {
294+logVerbose(
295+`discord: skip main-session last route for ${senderRecipient} (pinned owner ${ownerRecipient})`,
296+);
297+},
298+}
299+ : undefined,
300+}
301+ : undefined,
302+onRecordError: (err) => {
303+logVerbose(`discord: failed updating component session meta: ${String(err)}`);
342304},
343305},
306+runDispatch: () =>
307+dispatchReplyWithBufferedBlockDispatcher({
308+ctx: ctxPayload,
309+cfg: ctx.cfg,
310+replyOptions: { onModelSelected },
311+dispatcherOptions: {
312+ ...replyPipeline,
313+humanDelay: resolveHumanDelayConfig(ctx.cfg, agentId),
314+deliver: async (payload) => {
315+const replyToId = replyReference.use();
316+await deliverDiscordReply({
317+cfg: ctx.cfg,
318+replies: [payload],
319+target: deliverTarget,
320+ token,
321+ accountId,
322+rest: interaction.client.rest,
323+ runtime,
324+ replyToId,
325+ replyToMode,
326+ textLimit,
327+maxLinesPerMessage: resolveDiscordMaxLinesPerMessage({
328+cfg: ctx.cfg,
329+discordConfig: ctx.discordConfig,
330+ accountId,
331+}),
332+ tableMode,
333+chunkMode: resolveChunkMode(ctx.cfg, "discord", accountId),
334+ mediaLocalRoots,
335+});
336+replyReference.markSent();
337+},
338+onReplyStart: async () => {
339+try {
340+const { sendTyping } = await loadTypingRuntime();
341+await sendTyping({ rest: feedbackRest, channelId: typingChannelId });
342+} catch (err) {
343+logVerbose(`discord: typing failed for component reply: ${String(err)}`);
344+}
345+},
346+onError: (err) => {
347+logError(`discord component dispatch failed: ${String(err)}`);
348+},
349+},
350+}),
344351});
345352}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。