diff --git a/src/router.ts b/src/router.ts index 4a0be8f..cd5057a 100644 --- a/src/router.ts +++ b/src/router.ts @@ -107,30 +107,43 @@ export async function routeMessage( message.author.username ); + // Sanitize the full response once, then use the sanitized version + // for both Discord output and conversation history storage. + // This prevents a feedback loop where raw paths in stored history + // get fed back to the agent as context, causing it to reproduce them. + const sanitizeOpts = { + repoRoot: workspace.workspace_path, + home: os.homedir(), + }; + const sanitizedResponse = sanitizeForDiscord(response, sanitizeOpts); + // Split and send response - const chunks = splitMessage(response); + const chunks = splitMessage(sanitizedResponse); let firstMsgId: string | null = null; for (const chunk of chunks) { - const sent = await channel.send(sanitizeForDiscord(chunk, { home: os.homedir() })); + const sent = await channel.send(chunk); if (!firstMsgId) { firstMsgId = sent.id; } } - // Store assistant response (use first message id for dedup) + // Store sanitized assistant response (use first message id for dedup) if (firstMsgId) { db.addConversation( workspace.id, firstMsgId, "assistant", - response, + sanitizedResponse, null ); } } catch (error) { const msg = error instanceof Error ? error.message : "Unbekannter Fehler"; - const safeMsg = sanitizeForDiscord(`Fehler bei der Verarbeitung: ${msg}`, { home: os.homedir() }); + const safeMsg = sanitizeForDiscord(`Fehler bei der Verarbeitung: ${msg}`, { + repoRoot: workspace.workspace_path, + home: os.homedir(), + }); await channel.send(safeMsg).catch(() => {}); } finally { clearInterval(typingInterval); diff --git a/tests/unit/sanitize-for-discord.test.ts b/tests/unit/sanitize-for-discord.test.ts index 1d704d3..5a75e42 100644 --- a/tests/unit/sanitize-for-discord.test.ts +++ b/tests/unit/sanitize-for-discord.test.ts @@ -64,4 +64,24 @@ describe("sanitizeForDiscord", () => { }); expect(result).toBe("/src/index.ts and ~/other.ts"); }); + + // Windows-style backslash paths are sanitized + it("replaces Windows backslash paths", () => { + const text = "File at C:\\Users\\dev\\.disclaw\\workspaces\\agent-x\\src\\main.ts"; + const result = sanitizeForDiscord(text, { + repoRoot: "C:\\Users\\dev\\.disclaw\\workspaces\\agent-x", + home: "C:\\Users\\dev", + }); + expect(result).toBe("File at \\src\\main.ts"); + }); + + // Mixed slash styles (common on Windows when tools output forward slashes) + it("replaces forward-slash variants of Windows paths", () => { + const text = "File at C:/Users/dev/.disclaw/workspaces/agent-x/src/main.ts"; + const result = sanitizeForDiscord(text, { + repoRoot: "C:\\Users\\dev\\.disclaw\\workspaces\\agent-x", + home: "C:\\Users\\dev", + }); + expect(result).toBe("File at /src/main.ts"); + }); });