Skip to content
Closed
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
145 changes: 85 additions & 60 deletions src/core/sliding-window/__tests__/sliding-window.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ describe("Sliding Window", () => {
})
})

it("should truncate if tokens are above max tokens threshold", async () => {
it("should not truncate if tokens are above max tokens threshold when autoCondenseContext is false", async () => {
const modelInfo = createModelInfo(100000, 30000)
const totalTokens = 70001 // Above threshold

Expand All @@ -294,30 +294,23 @@ describe("Sliding Window", () => {
{ ...messages[messages.length - 1], content: "" },
]

// When truncating, always uses 0.5 fraction
// With 4 messages after the first, 0.5 fraction means remove 2 messages
const expectedMessages = [
messagesWithSmallContent[0],
messagesWithSmallContent[3],
messagesWithSmallContent[4],
]

const result = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens,
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - should not truncate
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})

// When autoCondenseContext is false, should NOT truncate
expect(result).toEqual({
messages: expectedMessages,
messages: messagesWithSmallContent, // Original messages preserved
summary: "",
cost: 0,
prevContextTokens: totalTokens,
Expand All @@ -343,7 +336,7 @@ describe("Sliding Window", () => {
contextWindow: modelInfo1.contextWindow,
maxTokens: modelInfo1.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
Expand All @@ -357,7 +350,7 @@ describe("Sliding Window", () => {
contextWindow: modelInfo2.contextWindow,
maxTokens: modelInfo2.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
Expand All @@ -370,15 +363,15 @@ describe("Sliding Window", () => {
expect(result1.cost).toEqual(result2.cost)
expect(result1.prevContextTokens).toEqual(result2.prevContextTokens)

// Test above threshold
// Test above threshold - with autoCondenseContext false, should not truncate
const aboveThreshold = 70001
const result3 = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens: aboveThreshold,
contextWindow: modelInfo1.contextWindow,
maxTokens: modelInfo1.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
Expand All @@ -392,14 +385,17 @@ describe("Sliding Window", () => {
contextWindow: modelInfo2.contextWindow,
maxTokens: modelInfo2.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})

// Both should preserve original messages when autoCondenseContext is false
expect(result3.messages).toEqual(messagesWithSmallContent)
expect(result4.messages).toEqual(messagesWithSmallContent)
expect(result3.messages).toEqual(result4.messages)
expect(result3.summary).toEqual(result4.summary)
expect(result3.cost).toEqual(result4.cost)
Expand Down Expand Up @@ -463,14 +459,15 @@ describe("Sliding Window", () => {
contextWindow: modelInfo.contextWindow,
maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(resultWithLarge.messages).not.toEqual(messagesWithLargeContent) // Should truncate
// When autoCondenseContext is false, should NOT truncate
expect(resultWithLarge.messages).toEqual(messagesWithLargeContent) // Should NOT truncate
expect(resultWithLarge.summary).toBe("")
expect(resultWithLarge.cost).toBe(0)
expect(resultWithLarge.prevContextTokens).toBe(baseTokensForLarge + largeContentTokens)
Expand All @@ -491,20 +488,21 @@ describe("Sliding Window", () => {
contextWindow: modelInfo.contextWindow,
maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(resultWithVeryLarge.messages).not.toEqual(messagesWithVeryLargeContent) // Should truncate
// When autoCondenseContext is false, should NOT truncate
expect(resultWithVeryLarge.messages).toEqual(messagesWithVeryLargeContent) // Should NOT truncate
expect(resultWithVeryLarge.summary).toBe("")
expect(resultWithVeryLarge.cost).toBe(0)
expect(resultWithVeryLarge.prevContextTokens).toBe(baseTokensForVeryLarge + veryLargeContentTokens)
})

it("should truncate if tokens are within TOKEN_BUFFER_PERCENTAGE of the threshold", async () => {
it("should not truncate if tokens are within TOKEN_BUFFER_PERCENTAGE when autoCondenseContext is false", async () => {
const modelInfo = createModelInfo(100000, 30000)
const dynamicBuffer = modelInfo.contextWindow * TOKEN_BUFFER_PERCENTAGE // 10% of 100000 = 10000
const totalTokens = 70000 - dynamicBuffer + 1 // Just within the dynamic buffer of threshold (70000)
Expand All @@ -515,29 +513,22 @@ describe("Sliding Window", () => {
{ ...messages[messages.length - 1], content: "" },
]

// When truncating, always uses 0.5 fraction
// With 4 messages after the first, 0.5 fraction means remove 2 messages
const expectedResult = [
messagesWithSmallContent[0],
messagesWithSmallContent[3],
messagesWithSmallContent[4],
]

const result = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens,
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
// When autoCondenseContext is false, should NOT truncate
expect(result).toEqual({
messages: expectedResult,
messages: messagesWithSmallContent, // Original messages preserved
summary: "",
cost: 0,
prevContextTokens: totalTokens,
Expand Down Expand Up @@ -577,7 +568,7 @@ describe("Sliding Window", () => {
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: true,
autoCondenseContextPercent: 100,
autoCondenseContextPercent: 50, // Use a threshold less than 100%
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
Expand Down Expand Up @@ -644,7 +635,7 @@ describe("Sliding Window", () => {
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: true,
autoCondenseContextPercent: 100,
autoCondenseContextPercent: 50, // Use a threshold less than 100%
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
Expand Down Expand Up @@ -676,21 +667,13 @@ describe("Sliding Window", () => {
{ ...messages[messages.length - 1], content: "" },
]

// When truncating, always uses 0.5 fraction
// With 4 messages after the first, 0.5 fraction means remove 2 messages
const expectedMessages = [
messagesWithSmallContent[0],
messagesWithSmallContent[3],
messagesWithSmallContent[4],
]

const result = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens,
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - should not truncate
autoCondenseContextPercent: 50, // This shouldn't matter since autoCondenseContext is false
systemPrompt: "System prompt",
taskId,
Expand All @@ -701,9 +684,9 @@ describe("Sliding Window", () => {
// Verify summarizeConversation was not called
expect(summarizeSpy).not.toHaveBeenCalled()

// Verify it used truncation
// When autoCondenseContext is false, should NOT truncate even if above threshold
expect(result).toEqual({
messages: expectedMessages,
messages: messagesWithSmallContent, // Original messages preserved
summary: "",
cost: 0,
prevContextTokens: totalTokens,
Expand Down Expand Up @@ -821,6 +804,48 @@ describe("Sliding Window", () => {
// Clean up
summarizeSpy.mockRestore()
})

it("should not truncate when autoCondenseContext is false even if tokens exceed allowedTokens", async () => {
const modelInfo = createModelInfo(100000, 30000)
const totalTokens = 75000 // This exceeds allowedTokens (60000) but should not truncate when disabled

const messagesWithSmallContent = [
...messages.slice(0, -1),
{ ...messages[messages.length - 1], content: "" },
]

// Spy on summarizeConversation to ensure it's not called
const summarizeSpy = vi.spyOn(condenseModule, "summarizeConversation")

const result = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens,
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false, // Disabled - should not truncate
autoCondenseContextPercent: 50, // This shouldn't matter since autoCondenseContext is false
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})

// Verify summarizeConversation was NOT called
expect(summarizeSpy).not.toHaveBeenCalled()

// Should NOT truncate even though tokens exceed allowedTokens when autoCondenseContext is false
expect(result).toEqual({
messages: messagesWithSmallContent,
summary: "",
cost: 0,
prevContextTokens: totalTokens,
error: undefined,
})

// Clean up
summarizeSpy.mockRestore()
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great test coverage for the main scenario! Would it be worth adding an edge case test for threshold values slightly above 100 (e.g., 101%) to ensure the >= 100 condition in the implementation handles these cases correctly? Even though such values shouldn't occur in practice, defensive testing could catch potential issues.

})

/**
Expand Down Expand Up @@ -1081,22 +1106,22 @@ describe("Sliding Window", () => {
prevContextTokens: 39999,
})

// Above max tokens - truncate
// Above max tokens - but with autoCondenseContext false, should not truncate
const result2 = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens: 50001, // Above threshold
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(result2.messages).not.toEqual(messagesWithSmallContent)
expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction
// When autoCondenseContext is false, should NOT truncate
expect(result2.messages).toEqual(messagesWithSmallContent)
expect(result2.summary).toBe("")
expect(result2.cost).toBe(0)
expect(result2.prevContextTokens).toBe(50001)
Expand Down Expand Up @@ -1134,22 +1159,22 @@ describe("Sliding Window", () => {
prevContextTokens: 81807,
})

// Above max tokens - truncate
// Above max tokens - but with autoCondenseContext false, should not truncate
const result2 = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens: 81809, // Above threshold (81808)
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(result2.messages).not.toEqual(messagesWithSmallContent)
expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction
// When autoCondenseContext is false, should NOT truncate
expect(result2.messages).toEqual(messagesWithSmallContent)
expect(result2.summary).toBe("")
expect(result2.cost).toBe(0)
expect(result2.prevContextTokens).toBe(81809)
Expand Down Expand Up @@ -1181,22 +1206,22 @@ describe("Sliding Window", () => {
})
expect(result1.messages).toEqual(messagesWithSmallContent)

// Above max tokens - truncate
// Above max tokens - but with autoCondenseContext false, should not truncate
const result2 = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens: 40001, // Above threshold
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(result2).not.toEqual(messagesWithSmallContent)
expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction
// When autoCondenseContext is false, should NOT truncate
expect(result2.messages).toEqual(messagesWithSmallContent)
})

it("should handle large context windows appropriately", async () => {
Expand Down Expand Up @@ -1226,22 +1251,22 @@ describe("Sliding Window", () => {
})
expect(result1.messages).toEqual(messagesWithSmallContent)

// Above max tokens - truncate
// Above max tokens - but with autoCondenseContext false, should not truncate
const result2 = await truncateConversationIfNeeded({
messages: messagesWithSmallContent,
totalTokens: 170001, // Above threshold
contextWindow: modelInfo.contextWindow,
maxTokens: modelInfo.maxTokens,
apiHandler: mockApiHandler,
autoCondenseContext: false,
autoCondenseContext: false, // Disabled - no truncation
autoCondenseContextPercent: 100,
systemPrompt: "System prompt",
taskId,
profileThresholds: {},
currentProfileId: "default",
})
expect(result2).not.toEqual(messagesWithSmallContent)
expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction
// When autoCondenseContext is false, should NOT truncate
expect(result2.messages).toEqual(messagesWithSmallContent)
})
})
})
Loading
Loading