fix(discord): resolve forum thread activity targets (#108603)

* fix(discord): resolve activity thread targets

* chore: keep changelog release-owned
This commit is contained in:
Peter Steinberger
2026-07-15 21:29:34 -07:00
committed by GitHub
parent 8a141549f2
commit 2ab4f9f370
2 changed files with 55 additions and 2 deletions
@@ -71,6 +71,36 @@ describe("discord_widget", () => {
});
});
it("resolves a provider-prefixed forum thread target", async () => {
const runtime = createActivityTestRuntime();
const send = vi.fn(async (..._args: Parameters<typeof sendMessageDiscord>) => ({
messageId: "message-1",
channelId: "987654321",
receipt: {},
}));
const tool = createDiscordWidgetTool(
discordContext({
nativeChannelId: undefined,
deliveryContext: { channel: "discord", to: "discord:channel:987654321" },
}),
{
runtime,
sendMessage: send as unknown as typeof sendMessageDiscord,
},
);
if (!tool) {
throw new Error("expected Discord widget tool");
}
const result = await tool.execute("forum-widget", {
html: "<p>Forum widget</p>",
title: "Forum widget",
});
expect(result.details).toMatchObject({ channelId: "987654321" });
expect(send).toHaveBeenCalledWith("channel:987654321", "Forum widget", expect.any(Object));
});
it("keeps full documents unchanged and rejects oversized HTML", async () => {
const document = "<!doctype html><html><body>full</body></html>";
const runtime = createActivityTestRuntime();
@@ -139,4 +169,23 @@ describe("discord_widget", () => {
tool.execute("missing-channel", { html: "hello", title: "No channel" }),
).rejects.toThrow("requires a concrete Discord channel");
});
it("rejects direct-message targets without a channel", async () => {
const tool = createDiscordWidgetTool(
discordContext({
nativeChannelId: undefined,
deliveryContext: { channel: "discord", to: "discord:user:987654321" },
}),
{
runtime: createActivityTestRuntime(),
sendMessage: vi.fn() as unknown as typeof sendMessageDiscord,
},
);
if (!tool) {
throw new Error("expected Discord widget tool");
}
await expect(tool.execute("dm-target", { html: "hello", title: "No channel" })).rejects.toThrow(
"requires a concrete Discord channel",
);
});
});
+6 -2
View File
@@ -7,6 +7,7 @@ import { resolveDiscordAccount } from "../accounts.js";
import { buildDiscordActivityCustomId } from "../component-custom-id.js";
import { Button, Row } from "../internal/discord.js";
import { sendMessageDiscord } from "../send.js";
import { resolveDiscordChannelId as resolveDiscordTargetChannelId } from "../target-parsing.js";
import type { DiscordActivitiesRuntime } from "./runtime.js";
const DISCORD_WIDGET_HTML_MAX_BYTES = 48 * 1024;
@@ -47,8 +48,11 @@ function resolveDiscordChannelId(context: OpenClawPluginToolContext): string | u
if (!raw) {
return undefined;
}
const normalized = raw.replace(/^channel:/i, "");
return /^\d+$/.test(normalized) ? normalized : undefined;
try {
return resolveDiscordTargetChannelId(raw);
} catch {
return undefined;
}
}
function buildDiscordWidgetDocument(title: string, html: string): string {