fix: preserve original first message context during conversation condensing (#7939)

This commit is contained in:
Daniel 2025-09-12 11:52:02 -05:00 committed by GitHub
parent 08d7f80e22
commit c4c478023d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 26 additions and 13 deletions

View file

@ -229,9 +229,9 @@ describe("Condense", () => {
const result = getMessagesSinceLastSummary(messages)
// Should include a user message prefix for Bedrock compatibility, the summary, and messages after
// Should include the original first user message for context preservation, the summary, and messages after
expect(result[0].role).toBe("user")
expect(result[0].content).toBe("Please continue from the following summary:")
expect(result[0].content).toBe("First message") // Preserves original first message
expect(result[1]).toEqual(messages[2]) // The summary
expect(result[2]).toEqual(messages[3])
expect(result[3]).toEqual(messages[4])
@ -249,9 +249,9 @@ describe("Condense", () => {
const result = getMessagesSinceLastSummary(messages)
// Should only include from the last summary
// Should only include from the last summary with original first message preserved
expect(result[0].role).toBe("user")
expect(result[0].content).toBe("Please continue from the following summary:")
expect(result[0].content).toBe("First message") // Preserves original first message
expect(result[1]).toEqual(messages[3]) // Second summary
expect(result[2]).toEqual(messages[4])
expect(result[3]).toEqual(messages[5])

View file

@ -36,7 +36,7 @@ describe("getMessagesSinceLastSummary", () => {
expect(result).toEqual(messages)
})
it("should return messages since the last summary with prepended user message", () => {
it("should return messages since the last summary with original first user message", () => {
const messages: ApiMessage[] = [
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "Hi there", ts: 2 },
@ -47,14 +47,14 @@ describe("getMessagesSinceLastSummary", () => {
const result = getMessagesSinceLastSummary(messages)
expect(result).toEqual([
{ role: "user", content: "Please continue from the following summary:", ts: 0 },
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "Summary of conversation", ts: 3, isSummary: true },
{ role: "user", content: "How are you?", ts: 4 },
{ role: "assistant", content: "I'm good", ts: 5 },
])
})
it("should handle multiple summary messages and return since the last one with prepended user message", () => {
it("should handle multiple summary messages and return since the last one with original first user message", () => {
const messages: ApiMessage[] = [
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "First summary", ts: 2, isSummary: true },
@ -65,7 +65,7 @@ describe("getMessagesSinceLastSummary", () => {
const result = getMessagesSinceLastSummary(messages)
expect(result).toEqual([
{ role: "user", content: "Please continue from the following summary:", ts: 0 },
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "Second summary", ts: 4, isSummary: true },
{ role: "user", content: "What's new?", ts: 5 },
])

View file

@ -223,11 +223,24 @@ export function getMessagesSinceLastSummary(messages: ApiMessage[]): ApiMessage[
const messagesSinceSummary = messages.slice(lastSummaryIndex)
// Bedrock requires the first message to be a user message.
// We preserve the original first message to maintain context.
// See https://github.com/RooCodeInc/Roo-Code/issues/4147
const userMessage: ApiMessage = {
role: "user",
content: "Please continue from the following summary:",
ts: messages[0]?.ts ? messages[0].ts - 1 : Date.now(),
if (messagesSinceSummary.length > 0 && messagesSinceSummary[0].role !== "user") {
// Get the original first message (should always be a user message with the task)
const originalFirstMessage = messages[0]
if (originalFirstMessage && originalFirstMessage.role === "user") {
// Use the original first message unchanged to maintain full context
return [originalFirstMessage, ...messagesSinceSummary]
} else {
// Fallback to generic message if no original first message exists (shouldn't happen)
const userMessage: ApiMessage = {
role: "user",
content: "Please continue from the following summary:",
ts: messages[0]?.ts ? messages[0].ts - 1 : Date.now(),
}
return [userMessage, ...messagesSinceSummary]
}
}
return [userMessage, ...messagesSinceSummary]
return messagesSinceSummary
}