refactor: unify reply dispatch across providers

This commit is contained in:
Peter Steinberger
2026-01-05 19:43:54 +01:00
parent bfe7f5f126
commit c75b2a7067
17 changed files with 953 additions and 476 deletions

View File

@@ -18,6 +18,7 @@ import {
import { chunkText, resolveTextChunkLimit } from "../auto-reply/chunk.js";
import { hasControlCommand } from "../auto-reply/command-detection.js";
import { formatAgentEnvelope } from "../auto-reply/envelope.js";
import { createReplyDispatcher } from "../auto-reply/reply/reply-dispatcher.js";
import { getReplyFromConfig } from "../auto-reply/reply.js";
import type { ReplyPayload } from "../auto-reply/types.js";
import type {
@@ -532,39 +533,36 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
}
let didSendReply = false;
let blockSendChain: Promise<void> = Promise.resolve();
const sendBlockReply = (payload: ReplyPayload) => {
if (
!payload?.text &&
!payload?.mediaUrl &&
!(payload?.mediaUrls?.length ?? 0)
) {
return;
}
blockSendChain = blockSendChain
.then(async () => {
await deliverReplies({
replies: [payload],
target: replyTarget,
token,
runtime,
replyToMode,
textLimit,
});
didSendReply = true;
})
.catch((err) => {
runtime.error?.(
danger(`discord block reply failed: ${String(err)}`),
);
const dispatcher = createReplyDispatcher({
responsePrefix: cfg.messages?.responsePrefix,
deliver: async (payload) => {
await deliverReplies({
replies: [payload],
target: replyTarget,
token,
runtime,
replyToMode,
textLimit,
});
};
didSendReply = true;
},
onError: (err, info) => {
runtime.error?.(
danger(`discord ${info.kind} reply failed: ${String(err)}`),
);
},
});
const replyResult = await getReplyFromConfig(
ctxPayload,
{
onReplyStart: () => sendTyping(message),
onBlockReply: sendBlockReply,
onToolResult: (payload) => {
dispatcher.sendToolResult(payload);
},
onBlockReply: (payload) => {
dispatcher.sendBlockReply(payload);
},
},
cfg,
);
@@ -573,8 +571,12 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
? replyResult
: [replyResult]
: [];
await blockSendChain;
if (replies.length === 0) {
let queuedFinal = false;
for (const reply of replies) {
queuedFinal = dispatcher.sendFinalReply(reply) || queuedFinal;
}
await dispatcher.waitForIdle();
if (!queuedFinal) {
if (
isGuildMessage &&
shouldClearHistory &&
@@ -585,19 +587,11 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
}
return;
}
await deliverReplies({
replies,
target: replyTarget,
token,
runtime,
replyToMode,
textLimit,
});
didSendReply = true;
if (shouldLogVerbose()) {
const finalCount = dispatcher.getQueuedCounts().final;
logVerbose(
`discord: delivered ${replies.length} reply${replies.length === 1 ? "" : "ies"} to ${replyTarget}`,
`discord: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${replyTarget}`,
);
}
if (