feat(DIS-102): sanitizeForDiscord strips paths and tokens before Discord send #46

Merged
dev merged 4 commits from phase-1/sanitize-for-discord into main 2026-04-10 08:05:44 +00:00
2 changed files with 38 additions and 5 deletions
Showing only changes of commit 714e0c01e5 - Show all commits

View file

@ -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);

View file

@ -64,4 +64,24 @@ describe("sanitizeForDiscord", () => {
});
expect(result).toBe("<disclaw>/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 <disclaw>\\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 <disclaw>/src/main.ts");
});
});