Skip to content

Commit e89143d

Browse files
hannesrudolphroomotedaniel-lxs
authored andcommitted
feat(condense v2.1): add smart code folding (RooCodeInc#10942)
* feat(condense): add smart code folding with tree-sitter signatures At context condensation time, use tree-sitter to generate folded code signatures (function definitions, class declarations) for files read during the conversation. Each file is included as its own <system-reminder> block in the condensed summary, preserving structural awareness without consuming excessive tokens. - Add getFilesReadByRoo() method to FileContextTracker - Create generateFoldedFileContext() using tree-sitter parsing - Update summarizeConversation() to accept array of file sections - Each file gets its own content block in the summary message - Add comprehensive test coverage (12 tests) * fix: skip tree-sitter error strings in folded file context - Add isTreeSitterErrorString helper to detect error messages - Skip files that return error strings instead of embedding them - Add test for error string handling * refactor: move generateFoldedFileContext() inside summarizeConversation() - Update summarizeConversation() to accept filesReadByRoo, cwd, rooIgnoreController instead of pre-generated sections - Move folded file context generation inside summarizeConversation() (lines 319-339) - Update ContextManagementOptions type and manageContext() to pass new parameters - Remove generateFoldedFileContext from Task.ts imports - folding now handled internally - Update all tests to use new parameter signature - Reduces Task.ts complexity by moving folding logic to summarization module * fix: prioritize most recently read files in folded context Files are now sorted by roo_read_date descending before folded context generation, so if the character budget runs out, the most relevant (recently read) files are included and older files are skipped. * refactor: improve code quality in condense module - Convert summarizeConversation to use options object instead of 11 positional params - Extract duplicated getFilesReadByRoo error handling into helper method - Remove unnecessary re-export of generateFoldedFileContext - Update all test files to use new options object pattern * fix: address roomote feedback - batch error logging and early budget exit --------- Co-authored-by: Roo Code <roomote@roocode.com> Co-authored-by: daniel-lxs <ricciodaniel98@gmail.com>
1 parent e3a0888 commit e89143d

9 files changed

Lines changed: 1100 additions & 104 deletions

File tree

src/core/condense/__tests__/condense.spec.ts

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,13 @@ Line 2
136136
{ role: "user", content: "Ninth message" },
137137
]
138138

139-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
139+
const result = await summarizeConversation({
140+
messages,
141+
apiHandler: mockApiHandler,
142+
systemPrompt: "System prompt",
143+
taskId,
144+
isAutomaticTrigger: false,
145+
})
140146

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

167-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
173+
const result = await summarizeConversation({
174+
messages,
175+
apiHandler: mockApiHandler,
176+
systemPrompt: "System prompt",
177+
taskId,
178+
isAutomaticTrigger: false,
179+
})
168180

169181
// All original messages should be tagged with condenseParent
170182
const taggedMessages = result.messages.filter((msg) => !msg.isSummary)
@@ -193,7 +205,13 @@ Line 2
193205
{ role: "user", content: "Ninth message" },
194206
]
195207

196-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
208+
const result = await summarizeConversation({
209+
messages,
210+
apiHandler: mockApiHandler,
211+
systemPrompt: "System prompt",
212+
taskId,
213+
isAutomaticTrigger: false,
214+
})
197215

198216
const summaryMessage = result.messages.find((msg) => msg.isSummary)
199217
expect(summaryMessage).toBeTruthy()
@@ -227,7 +245,13 @@ Line 2
227245
{ role: "user", content: "Perfect!" },
228246
]
229247

230-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
248+
const result = await summarizeConversation({
249+
messages,
250+
apiHandler: mockApiHandler,
251+
systemPrompt: "System prompt",
252+
taskId,
253+
isAutomaticTrigger: false,
254+
})
231255

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

242-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
266+
const result = await summarizeConversation({
267+
messages,
268+
apiHandler: mockApiHandler,
269+
systemPrompt: "System prompt",
270+
taskId,
271+
isAutomaticTrigger: false,
272+
})
243273

244274
// Should return an error since we have only 1 message
245275
expect(result.error).toBeDefined()
@@ -253,7 +283,13 @@ Line 2
253283
{ role: "user", content: "Previous summary", isSummary: true },
254284
]
255285

256-
const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
286+
const result = await summarizeConversation({
287+
messages,
288+
apiHandler: mockApiHandler,
289+
systemPrompt: "System prompt",
290+
taskId,
291+
isAutomaticTrigger: false,
292+
})
257293

258294
// Should return an error due to recent summary with no substantial messages after
259295
expect(result.error).toBeDefined()
@@ -286,7 +322,13 @@ Line 2
286322
{ role: "user", content: "Seventh" },
287323
]
288324

289-
const result = await summarizeConversation(messages, emptyHandler, "System prompt", taskId, false)
325+
const result = await summarizeConversation({
326+
messages,
327+
apiHandler: emptyHandler,
328+
systemPrompt: "System prompt",
329+
taskId,
330+
isAutomaticTrigger: false,
331+
})
290332

291333
expect(result.error).toBeDefined()
292334
expect(result.messages).toEqual(messages)

0 commit comments

Comments
 (0)