fix(discord): replyToMode first behaviour

This commit is contained in:
CHISEN Kaoru
2026-02-07 08:10:58 +00:00
committed by Shadow
parent 4b3c9c9c5a
commit e25ae55879
4 changed files with 46 additions and 9 deletions

View File

@@ -200,14 +200,35 @@ describe("createReplyReferencePlanner", () => {
expect(planner.use()).toBe("parent"); expect(planner.use()).toBe("parent");
}); });
it("prefers existing thread id regardless of mode", () => { it("respects replyToMode off even with existingId", () => {
const planner = createReplyReferencePlanner({ const planner = createReplyReferencePlanner({
replyToMode: "off", replyToMode: "off",
existingId: "thread-1", existingId: "thread-1",
startId: "parent", startId: "parent",
}); });
expect(planner.use()).toBeUndefined();
expect(planner.hasReplied()).toBe(false);
});
it("uses existingId once when mode is first", () => {
const planner = createReplyReferencePlanner({
replyToMode: "first",
existingId: "thread-1",
startId: "parent",
});
expect(planner.use()).toBe("thread-1"); expect(planner.use()).toBe("thread-1");
expect(planner.hasReplied()).toBe(true); expect(planner.hasReplied()).toBe(true);
expect(planner.use()).toBeUndefined();
});
it("uses existingId on every call when mode is all", () => {
const planner = createReplyReferencePlanner({
replyToMode: "all",
existingId: "thread-1",
startId: "parent",
});
expect(planner.use()).toBe("thread-1");
expect(planner.use()).toBe("thread-1");
}); });
it("honors allowReference=false", () => { it("honors allowReference=false", () => {

View File

@@ -32,20 +32,18 @@ export function createReplyReferencePlanner(options: {
if (options.replyToMode === "off") { if (options.replyToMode === "off") {
return undefined; return undefined;
} }
if (existingId) { const id = existingId ?? startId;
hasReplied = true; if (!id) {
return existingId;
}
if (!startId) {
return undefined; return undefined;
} }
if (options.replyToMode === "all") { if (options.replyToMode === "all") {
hasReplied = true; hasReplied = true;
return startId; return id;
} }
// "first": only the first reply gets a reference.
if (!hasReplied) { if (!hasReplied) {
hasReplied = true; hasReplied = true;
return startId; return id;
} }
return undefined; return undefined;
}; };

View File

@@ -93,7 +93,22 @@ describe("resolveDiscordReplyDeliveryPlan", () => {
threadChannel: { id: "thread" }, threadChannel: { id: "thread" },
createdThreadId: null, createdThreadId: null,
}); });
// "all" returns the reference on every call.
expect(plan.replyReference.use()).toBe("m1"); expect(plan.replyReference.use()).toBe("m1");
expect(plan.replyReference.use()).toBe("m1");
});
it("uses existingId only on first call with replyToMode first inside a thread", () => {
const plan = resolveDiscordReplyDeliveryPlan({
replyTarget: "channel:thread",
replyToMode: "first",
messageId: "m1",
threadChannel: { id: "thread" },
createdThreadId: null,
});
// "first" returns the reference only once.
expect(plan.replyReference.use()).toBe("m1");
expect(plan.replyReference.use()).toBeUndefined();
}); });
}); });

View File

@@ -89,8 +89,11 @@ function createSlackReplyReferencePlanner(params: {
messageTs: string | undefined; messageTs: string | undefined;
hasReplied?: boolean; hasReplied?: boolean;
}) { }) {
// When already inside a Slack thread, always stay in it regardless of
// replyToMode — thread_ts is required to keep messages in the thread.
const effectiveMode = params.incomingThreadTs ? "all" : params.replyToMode;
return createReplyReferencePlanner({ return createReplyReferencePlanner({
replyToMode: params.replyToMode, replyToMode: effectiveMode,
existingId: params.incomingThreadTs, existingId: params.incomingThreadTs,
startId: params.messageTs, startId: params.messageTs,
hasReplied: params.hasReplied, hasReplied: params.hasReplied,