From a216f2dabe77185f197d8e2f71f07705bcf024b8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 24 Feb 2026 03:52:27 +0000 Subject: [PATCH] fix: extend discord thread parent fallback coverage (#24897) (thanks @z-x-yang) --- CHANGELOG.md | 1 + .../monitor/threading.parent-info.test.ts | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe7ba34ff..d7851591e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Discord/Threading: recover missing thread parent IDs by refetching thread metadata before resolving parent channel context. (#24897) Thanks @z-x-yang. - Web UI/i18n: load and hydrate saved locale translations during startup so non-English sessions apply immediately without manual toggling. (#24795) Thanks @chilu18. - Plugins/Config schema: support legacy plugin schemas without `toJSONSchema()` by falling back to permissive object schema generation. (#24933) Thanks @pandego. - Cron/Isolated sessions: use full prompt mode for isolated cron runs so skills/extensions are available during cron execution. (#24944) diff --git a/src/discord/monitor/threading.parent-info.test.ts b/src/discord/monitor/threading.parent-info.test.ts index 8ad36c11f..1954dd4fe 100644 --- a/src/discord/monitor/threading.parent-info.test.ts +++ b/src/discord/monitor/threading.parent-info.test.ts @@ -44,4 +44,63 @@ describe("resolveDiscordThreadParentInfo", () => { type: ChannelType.GuildText, }); }); + + it("does not fetch thread info when parentId is already present", async () => { + const fetchChannel = vi.fn(async (channelId: string) => { + if (channelId === "parent-1") { + return { + id: "parent-1", + type: ChannelType.GuildText, + name: "parent-name", + }; + } + return null; + }); + + const client = { fetchChannel } as unknown as import("@buape/carbon").Client; + const result = await resolveDiscordThreadParentInfo({ + client, + threadChannel: { + id: "thread-1", + parentId: "parent-1", + }, + channelInfo: null, + }); + + expect(fetchChannel).toHaveBeenCalledTimes(1); + expect(fetchChannel).toHaveBeenCalledWith("parent-1"); + expect(result).toEqual({ + id: "parent-1", + name: "parent-name", + type: ChannelType.GuildText, + }); + }); + + it("returns empty parent info when fallback thread lookup has no parentId", async () => { + const fetchChannel = vi.fn(async (channelId: string) => { + if (channelId === "thread-1") { + return { + id: "thread-1", + type: ChannelType.PublicThread, + name: "thread-name", + parentId: undefined, + }; + } + return null; + }); + + const client = { fetchChannel } as unknown as import("@buape/carbon").Client; + const result = await resolveDiscordThreadParentInfo({ + client, + threadChannel: { + id: "thread-1", + parentId: undefined, + }, + channelInfo: null, + }); + + expect(fetchChannel).toHaveBeenCalledTimes(1); + expect(fetchChannel).toHaveBeenCalledWith("thread-1"); + expect(result).toEqual({}); + }); });