Skip to content

Commit b21bbdd

Browse files
fsdwenclaude
andcommitted
fix(session-memory): reset dedup state on user messages to preserve cross-turn replies (#92563)
- Reset lastAssistantText when a visible user message is included in the memory summary, so an assistant reply from a different turn that happens to repeat the same text is preserved. - Only dedupe consecutive assistant rows within the same turn. Co-Authored-By: Claude <[email protected]>
1 parent 8df64a8 commit b21bbdd

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

src/hooks/bundled/session-memory/handler.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,4 +924,21 @@ describe("session-memory hook", () => {
924924
const assistantLines = (memoryContent?.match(/^assistant:/gm) ?? []).length;
925925
expect(assistantLines).toBe(2);
926926
});
927+
928+
it("keeps repeated assistant reply after an intervening visible user message (#92563)", async () => {
929+
// Same assistant text across different turns should NOT be deduped.
930+
const sessionContent = createMockSessionContent([
931+
{ role: "user", content: "Question A" },
932+
{ role: "assistant", content: "OK" },
933+
{ role: "user", content: "Question B" },
934+
{ role: "assistant", content: "OK" },
935+
]);
936+
const memoryContent = await readSessionTranscript({ sessionContent });
937+
938+
expect(memoryContent).toContain("user: Question A");
939+
expect(memoryContent).toContain("assistant: OK");
940+
expect(memoryContent).toContain("user: Question B");
941+
const okCount = (memoryContent?.match(/assistant: OK/g) ?? []).length;
942+
expect(okCount).toBe(2);
943+
});
927944
});

src/hooks/bundled/session-memory/transcript.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,18 @@ export async function getRecentSessionContent(
4747
continue;
4848
}
4949
const text = extractTextMessageContent(msg.content);
50+
// Only dedupe consecutive assistant rows so a reply from a different
51+
// turn that happens to repeat the same text is still included.
5052
if (text && !text.startsWith("/")) {
51-
// Dedupe consecutive assistant messages with identical text.
52-
// Thinking-enabled models produce raw (thinking + text) and
53-
// cleaned (text-only) copies in the same turn; delivery mirrors
54-
// can also repeat the visible text of the preceding assistant.
55-
if (role === "assistant" && text === lastAssistantText) {
56-
continue;
57-
}
58-
allMessages.push(`${role}: ${text}`);
5953
if (role === "assistant") {
54+
if (text === lastAssistantText) {
55+
continue;
56+
}
57+
allMessages.push(`assistant: ${text}`);
6058
lastAssistantText = text;
59+
} else {
60+
allMessages.push(`${role}: ${text}`);
61+
lastAssistantText = undefined;
6162
}
6263
}
6364
}

0 commit comments

Comments
 (0)