Files
openclaw/extensions/discord/src/reply-reference.ts
Peter Steinberger bfb89d3ea6 fix(discord): limit implicit reply fanout (#100784)
* fix(discord): limit implicit reply fanout

Co-authored-by: qingminlong <qing.minlong@xydigit.com>

* fix(discord): preserve oversized fallback fanout

* refactor(discord): make reply metadata per-message

* fix(discord): keep reply receipts serializable

* docs(changelog): defer Discord entry to release

* refactor(discord): model native reply fanout

---------

Co-authored-by: qingminlong <qing.minlong@xydigit.com>
2026-07-06 17:55:23 +01:00

39 lines
1.3 KiB
TypeScript

import type { ReplyToResolution } from "openclaw/plugin-sdk/channel-outbound";
import type { ReplyToMode } from "openclaw/plugin-sdk/config-contracts";
import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
// Keep the native reference and its physical-send scope together so text, media,
// component, and voice paths cannot desynchronize parallel reply options.
export type DiscordReplyReference = Readonly<{
messageId: string;
scope: "all" | "first";
}>;
export function resolveDiscordReplyReference(params: {
replyToId?: string | null;
replyToIdSource?: ReplyToResolution["source"];
replyToMode?: ReplyToMode;
}): DiscordReplyReference | undefined {
if (!params.replyToId) {
return undefined;
}
const singleUse =
params.replyToIdSource !== "explicit" &&
params.replyToMode !== undefined &&
isSingleUseReplyToMode(params.replyToMode);
return { messageId: params.replyToId, scope: singleUse ? "first" : "all" };
}
export function createReusableDiscordReplyReference(
messageId?: string | null,
): DiscordReplyReference | undefined {
return messageId ? { messageId, scope: "all" } : undefined;
}
export function resolveDiscordReplyMessageId(
reply: DiscordReplyReference | undefined,
isFirst: boolean,
): string | undefined {
return reply && (isFirst || reply.scope === "all") ? reply.messageId : undefined;
}