Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/core/condense/__tests__/condense.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Line 2
{ role: "user", content: "Ninth message" },
]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

// Verify we have a summary message with role "user" (fresh start model)
const summaryMessage = result.messages.find((msg) => msg.isSummary)
Expand Down Expand Up @@ -164,7 +164,7 @@ Line 2
{ role: "user", content: "Fifth message" },
]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

// All original messages should be tagged with condenseParent
const taggedMessages = result.messages.filter((msg) => !msg.isSummary)
Expand Down Expand Up @@ -193,7 +193,7 @@ Line 2
{ role: "user", content: "Ninth message" },
]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

const summaryMessage = result.messages.find((msg) => msg.isSummary)
expect(summaryMessage).toBeTruthy()
Expand Down Expand Up @@ -227,7 +227,7 @@ Line 2
{ role: "user", content: "Perfect!" },
]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

// Effective history should contain only the summary (fresh start)
const effectiveHistory = getEffectiveApiHistory(result.messages)
Expand All @@ -239,7 +239,7 @@ Line 2
it("should return error when not enough messages to summarize", async () => {
const messages: ApiMessage[] = [{ role: "user", content: "Only one message" }]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

// Should return an error since we have only 1 message
expect(result.error).toBeDefined()
Expand All @@ -253,7 +253,7 @@ Line 2
{ role: "assistant", content: "Previous summary", isSummary: true },
]

const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)

// Should return an error due to recent summary with no substantial messages after
expect(result.error).toBeDefined()
Expand Down Expand Up @@ -286,7 +286,7 @@ Line 2
{ role: "user", content: "Seventh" },
]

const result = await summarizeConversation(messages, emptyHandler, "System prompt", taskId, 5000, false)
const result = await summarizeConversation(messages, emptyHandler, "System prompt", taskId, false)

expect(result.error).toBeDefined()
expect(result.messages).toEqual(messages)
Expand Down
159 changes: 23 additions & 136 deletions src/core/condense/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ vi.mock("@roo-code/telemetry", () => ({
}))

const taskId = "test-task-id"
const DEFAULT_PREV_CONTEXT_TOKENS = 1000

describe("extractCommandBlocks", () => {
it("should extract command blocks from string content", () => {
Expand Down Expand Up @@ -713,13 +712,7 @@ describe("summarizeConversation", () => {
it("should not summarize when there are not enough messages", async () => {
const messages: ApiMessage[] = [{ role: "user", content: "Hello", ts: 1 }]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
expect(result.messages).toEqual(messages)
expect(result.cost).toBe(0)
expect(result.summary).toBe("")
Expand All @@ -739,13 +732,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "Tell me more", ts: 7 },
]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

// Check that the API was called correctly
expect(mockApiHandler.createMessage).toHaveBeenCalled()
Expand Down Expand Up @@ -781,7 +768,8 @@ describe("summarizeConversation", () => {
// Check the cost and token counts
expect(result.cost).toBe(0.05)
expect(result.summary).toBe("This is a summary")
expect(result.newContextTokens).toBe(250) // outputTokens(150) + countTokens(100)
// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content, not outputTokens
expect(result.newContextTokens).toBe(100) // countTokens mock returns 100
expect(result.error).toBeUndefined()
})

Expand All @@ -798,13 +786,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "What's new?", ts: 5 },
]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

const summaryMessage = result.messages.find((m) => m.isSummary)
expect(summaryMessage).toBeDefined()
Expand All @@ -827,13 +809,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "What's new?", ts: 5 },
]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

const summaryMessage = result.messages.find((m) => m.isSummary)
expect(summaryMessage).toBeDefined()
Expand Down Expand Up @@ -870,13 +846,7 @@ describe("summarizeConversation", () => {
return messages.map(({ role, content }: { role: string; content: any }) => ({ role, content }))
})

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

// Should return original messages when summary is empty
expect(result.messages).toEqual(messages)
Expand All @@ -897,7 +867,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "Tell me more", ts: 7 },
]

await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId, DEFAULT_PREV_CONTEXT_TOKENS)
await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

// Verify that createMessage was called with the SUMMARY_PROMPT (which contains CRITICAL instructions), messages array, and optional metadata
expect(mockApiHandler.createMessage).toHaveBeenCalledWith(
Expand Down Expand Up @@ -929,7 +899,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "Newest", ts: 7 },
]

await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId, DEFAULT_PREV_CONTEXT_TOKENS)
await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

const mockCallArgs = (maybeRemoveImageBlocks as Mock).mock.calls[0][0] as any[]

Expand Down Expand Up @@ -967,65 +937,19 @@ describe("summarizeConversation", () => {
// Override the mock for this test
mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithUsage) as any

const result = await summarizeConversation(
messages,
mockApiHandler,
systemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, systemPrompt, taskId)

// Verify that countTokens was called with system prompt
// Verify that countTokens was called with system prompt + summary message
expect(mockApiHandler.countTokens).toHaveBeenCalled()

// newContextTokens includes the summary output tokens plus countTokens(systemPrompt)
expect(result.newContextTokens).toBe(300) // outputTokens(200) + countTokens(100)
// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content
expect(result.newContextTokens).toBe(100) // countTokens mock returns 100
expect(result.cost).toBe(0.06)
expect(result.summary).toBe("This is a summary with system prompt")
expect(result.error).toBeUndefined()
})

it("should return error when new context tokens >= previous context tokens", async () => {
const messages: ApiMessage[] = [
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "Hi there", ts: 2 },
{ role: "user", content: "How are you?", ts: 3 },
{ role: "assistant", content: "I'm good", ts: 4 },
{ role: "user", content: "What's new?", ts: 5 },
{ role: "assistant", content: "Not much", ts: 6 },
{ role: "user", content: "Tell me more", ts: 7 },
]

// Create a stream that produces a summary
const streamWithLargeTokens = (async function* () {
yield { type: "text" as const, text: "This is a very long summary that uses many tokens" }
yield { type: "usage" as const, totalCost: 0.08, outputTokens: 500 }
})()

// Override the mock for this test
mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithLargeTokens) as any

// Mock countTokens to return a value >= prevContextTokens
mockApiHandler.countTokens = vi.fn().mockImplementation(() => Promise.resolve(600)) as any

const prevContextTokens = 600
const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
prevContextTokens,
)

// Should return original messages when context would not shrink
expect(result.messages).toEqual(messages)
expect(result.cost).toBe(0.08)
expect(result.summary).toBe("")
expect(result.error).toBeTruthy() // Error should be set
expect(result.newContextTokens).toBeUndefined()
})

it("should successfully summarize when new context tokens < previous context tokens", async () => {
it("should successfully summarize conversation", async () => {
const messages: ApiMessage[] = [
{ role: "user", content: "Hello", ts: 1 },
{ role: "assistant", content: "Hi there", ts: 2 },
Expand All @@ -1045,17 +969,10 @@ describe("summarizeConversation", () => {
// Override the mock for this test
mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithSmallTokens) as any

// Mock countTokens to return a small value so total is < prevContextTokens
// Mock countTokens to return a small value
mockApiHandler.countTokens = vi.fn().mockImplementation(() => Promise.resolve(30)) as any

const prevContextTokens = 200
const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
prevContextTokens,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

// Result contains all messages plus summary
expect(result.messages.length).toBe(messages.length + 1)
Expand All @@ -1068,8 +985,8 @@ describe("summarizeConversation", () => {
expect(result.cost).toBe(0.03)
expect(result.summary).toBe("Concise summary")
expect(result.error).toBeUndefined()
expect(result.newContextTokens).toBe(80) // outputTokens(50) + countTokens(30)
expect(result.newContextTokens).toBeLessThan(prevContextTokens)
// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content
expect(result.newContextTokens).toBe(30) // countTokens mock returns 30
})

it("should return error when API handler is invalid", async () => {
Expand All @@ -1095,13 +1012,7 @@ describe("summarizeConversation", () => {
const mockError = vi.fn()
console.error = mockError

const result = await summarizeConversation(
messages,
invalidHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, invalidHandler, defaultSystemPrompt, taskId)

// Should return original messages when handler is invalid
expect(result.messages).toEqual(messages)
Expand All @@ -1126,13 +1037,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "Thanks", ts: 5 },
]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

const summaryMessage = result.messages.find((m) => m.isSummary)
expect(summaryMessage).toBeDefined()
Expand All @@ -1153,13 +1058,7 @@ describe("summarizeConversation", () => {
{ role: "user", content: "Thanks", ts: 5 },
]

const result = await summarizeConversation(
messages,
mockApiHandler,
defaultSystemPrompt,
taskId,
DEFAULT_PREV_CONTEXT_TOKENS,
)
const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)

// Summary should be the last message
const lastMessage = result.messages[result.messages.length - 1]
Expand Down Expand Up @@ -1228,7 +1127,6 @@ describe("summarizeConversation with custom settings", () => {
mockMainApiHandler,
defaultSystemPrompt,
localTaskId,
DEFAULT_PREV_CONTEXT_TOKENS,
false,
customPrompt,
)
Expand All @@ -1248,15 +1146,7 @@ describe("summarizeConversation with custom settings", () => {
*/
it("should use default systemPrompt when custom prompt is empty or not provided", async () => {
// Test with empty string
await summarizeConversation(
sampleMessages,
mockMainApiHandler,
defaultSystemPrompt,
localTaskId,
DEFAULT_PREV_CONTEXT_TOKENS,
false,
" ", // Empty custom prompt
)
await summarizeConversation(sampleMessages, mockMainApiHandler, defaultSystemPrompt, localTaskId, false, " ")

// Verify the default SUMMARY_PROMPT was used (contains CRITICAL instructions)
let createMessageCalls = (mockMainApiHandler.createMessage as Mock).mock.calls
Expand All @@ -1273,9 +1163,8 @@ describe("summarizeConversation with custom settings", () => {
mockMainApiHandler,
defaultSystemPrompt,
localTaskId,
DEFAULT_PREV_CONTEXT_TOKENS,
false,
undefined, // No custom prompt
undefined,
)

// Verify the default SUMMARY_PROMPT was used again (contains CRITICAL instructions)
Expand All @@ -1296,7 +1185,6 @@ describe("summarizeConversation with custom settings", () => {
mockMainApiHandler,
defaultSystemPrompt,
localTaskId,
DEFAULT_PREV_CONTEXT_TOKENS,
false,
"Custom prompt",
)
Expand All @@ -1318,7 +1206,6 @@ describe("summarizeConversation with custom settings", () => {
mockMainApiHandler,
defaultSystemPrompt,
localTaskId,
DEFAULT_PREV_CONTEXT_TOKENS,
true, // isAutomaticTrigger
"Custom prompt",
)
Expand Down
Loading
Loading