Spaces:
Paused
Paused
| import type { Client } from "@buape/carbon"; | |
| import { describe, expect, it } from "vitest"; | |
| import { buildAgentSessionKey } from "../../routing/resolve-route.js"; | |
| import { | |
| resolveDiscordAutoThreadContext, | |
| resolveDiscordAutoThreadReplyPlan, | |
| resolveDiscordReplyDeliveryPlan, | |
| } from "./threading.js"; | |
| describe("resolveDiscordAutoThreadContext", () => { | |
| it("returns null when no createdThreadId", () => { | |
| expect( | |
| resolveDiscordAutoThreadContext({ | |
| agentId: "agent", | |
| channel: "discord", | |
| messageChannelId: "parent", | |
| createdThreadId: undefined, | |
| }), | |
| ).toBeNull(); | |
| }); | |
| it("re-keys session context to the created thread", () => { | |
| const context = resolveDiscordAutoThreadContext({ | |
| agentId: "agent", | |
| channel: "discord", | |
| messageChannelId: "parent", | |
| createdThreadId: "thread", | |
| }); | |
| expect(context).not.toBeNull(); | |
| expect(context?.To).toBe("channel:thread"); | |
| expect(context?.From).toBe("discord:channel:thread"); | |
| expect(context?.OriginatingTo).toBe("channel:thread"); | |
| expect(context?.SessionKey).toBe( | |
| buildAgentSessionKey({ | |
| agentId: "agent", | |
| channel: "discord", | |
| peer: { kind: "channel", id: "thread" }, | |
| }), | |
| ); | |
| expect(context?.ParentSessionKey).toBe( | |
| buildAgentSessionKey({ | |
| agentId: "agent", | |
| channel: "discord", | |
| peer: { kind: "channel", id: "parent" }, | |
| }), | |
| ); | |
| }); | |
| }); | |
| describe("resolveDiscordReplyDeliveryPlan", () => { | |
| it("uses reply references when posting to the original target", () => { | |
| const plan = resolveDiscordReplyDeliveryPlan({ | |
| replyTarget: "channel:parent", | |
| replyToMode: "all", | |
| messageId: "m1", | |
| threadChannel: null, | |
| createdThreadId: null, | |
| }); | |
| expect(plan.deliverTarget).toBe("channel:parent"); | |
| expect(plan.replyTarget).toBe("channel:parent"); | |
| expect(plan.replyReference.use()).toBe("m1"); | |
| }); | |
| it("disables reply references when autoThread creates a new thread", () => { | |
| const plan = resolveDiscordReplyDeliveryPlan({ | |
| replyTarget: "channel:parent", | |
| replyToMode: "all", | |
| messageId: "m1", | |
| threadChannel: null, | |
| createdThreadId: "thread", | |
| }); | |
| expect(plan.deliverTarget).toBe("channel:thread"); | |
| expect(plan.replyTarget).toBe("channel:thread"); | |
| expect(plan.replyReference.use()).toBeUndefined(); | |
| }); | |
| it("always uses existingId when inside a thread", () => { | |
| const plan = resolveDiscordReplyDeliveryPlan({ | |
| replyTarget: "channel:thread", | |
| replyToMode: "off", | |
| messageId: "m1", | |
| threadChannel: { id: "thread" }, | |
| createdThreadId: null, | |
| }); | |
| expect(plan.replyReference.use()).toBe("m1"); | |
| }); | |
| }); | |
| describe("resolveDiscordAutoThreadReplyPlan", () => { | |
| it("switches delivery + session context to the created thread", async () => { | |
| const client = { | |
| rest: { post: async () => ({ id: "thread" }) }, | |
| } as unknown as Client; | |
| const plan = await resolveDiscordAutoThreadReplyPlan({ | |
| client, | |
| message: { | |
| id: "m1", | |
| channelId: "parent", | |
| } as unknown as import("./listeners.js").DiscordMessageEvent["message"], | |
| isGuildMessage: true, | |
| channelConfig: { | |
| autoThread: true, | |
| } as unknown as import("./allow-list.js").DiscordChannelConfigResolved, | |
| threadChannel: null, | |
| baseText: "hello", | |
| combinedBody: "hello", | |
| replyToMode: "all", | |
| agentId: "agent", | |
| channel: "discord", | |
| }); | |
| expect(plan.deliverTarget).toBe("channel:thread"); | |
| expect(plan.replyReference.use()).toBeUndefined(); | |
| expect(plan.autoThreadContext?.SessionKey).toBe( | |
| buildAgentSessionKey({ | |
| agentId: "agent", | |
| channel: "discord", | |
| peer: { kind: "channel", id: "thread" }, | |
| }), | |
| ); | |
| }); | |
| it("does nothing when autoThread is disabled", async () => { | |
| const client = { rest: { post: async () => ({ id: "thread" }) } } as unknown as Client; | |
| const plan = await resolveDiscordAutoThreadReplyPlan({ | |
| client, | |
| message: { | |
| id: "m1", | |
| channelId: "parent", | |
| } as unknown as import("./listeners.js").DiscordMessageEvent["message"], | |
| isGuildMessage: true, | |
| channelConfig: { | |
| autoThread: false, | |
| } as unknown as import("./allow-list.js").DiscordChannelConfigResolved, | |
| threadChannel: null, | |
| baseText: "hello", | |
| combinedBody: "hello", | |
| replyToMode: "all", | |
| agentId: "agent", | |
| channel: "discord", | |
| }); | |
| expect(plan.deliverTarget).toBe("channel:parent"); | |
| expect(plan.autoThreadContext).toBeNull(); | |
| }); | |
| }); | |