diff --git a/CHANGELOG.md b/CHANGELOG.md index ed9e17b43..7d4adc782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ - Discord: include recent guild context when replying to mentions and add `discord.historyLimit` to tune how many messages are captured. - Discord: include author tag + id in group context `[from:]` lines for ping-ready replies (thanks @thewilloftheshadow). - Discord: include replied-to message context when a Discord message references another message (thanks @thewilloftheshadow). +- Discord: preserve newlines when stripping reply tags from agent output. - Gateway: fix TypeScript build by aligning hook mapping `channel` types and removing a dead Group DM branch in Discord monitor. - Skills: switch imsg installer to brew tap formula. - Skills: gate macOS-only skills by OS and surface block reasons in the Skills UI. diff --git a/src/auto-reply/reply.directive.test.ts b/src/auto-reply/reply.directive.test.ts index 709a2fa8c..aac22e6b2 100644 --- a/src/auto-reply/reply.directive.test.ts +++ b/src/auto-reply/reply.directive.test.ts @@ -109,6 +109,15 @@ describe("directive parsing", () => { expect(res.cleaned).toBe("see now"); }); + it("preserves newlines when stripping reply tags", () => { + const res = extractReplyToTag( + "line 1\nline 2 [[reply_to_current]]\n\nline 3", + "msg-2", + ); + expect(res.replyToId).toBe("msg-2"); + expect(res.cleaned).toBe("line 1\nline 2\n\nline 3"); + }); + it("strips reply tags and maps reply_to_current to MessageSid", async () => { await withTempHome(async (home) => { vi.mocked(runEmbeddedPiAgent).mockResolvedValue({ diff --git a/src/auto-reply/reply.ts b/src/auto-reply/reply.ts index 87f5d6c69..20dd24d9a 100644 --- a/src/auto-reply/reply.ts +++ b/src/auto-reply/reply.ts @@ -193,7 +193,10 @@ export function extractReplyToTag( hasTag = true; } - cleaned = cleaned.replace(/\s+/g, " ").trim(); + cleaned = cleaned + .replace(/[ \t]+/g, " ") + .replace(/[ \t]*\n[ \t]*/g, "\n") + .trim(); return { cleaned, replyToId, hasTag }; }