Skip to content

Conversation

@hannesrudolph
Copy link
Collaborator

@hannesrudolph hannesrudolph commented Jan 26, 2026

Summary

closes #10239

This PR introduces a smarter way for Roo to read your code files. Instead of just grabbing arbitrary line ranges, Roo can now intelligently extract complete functions, classes, and code blocks based on their structure.

What's New

Indentation Mode for Smart Code Extraction

When Roo needs to read code around a specific line (like when investigating an error or following a search result), it can now use indentation mode to automatically extract the complete containing function or class—not just a fixed number of lines that might cut off mid-block.

Example: If Roo finds an error on line 42 inside a function, indentation mode will return the entire function definition with proper context, instead of an arbitrary range like "lines 40-60" that might miss important context or include unrelated code.

Simplified File Reading

The read_file tool now has two clear modes:

  • Slice mode (default): Read a specific portion of a file using offset and limit
  • Indentation mode: Extract semantically meaningful code blocks

Breaking Changes

Settings Removed

The following settings have been removed from the UI:

  • Max Read File Lines - No longer needed; agents now control read limits per-request
  • Max Concurrent File Reads - Batch file reading has been replaced with single-file reads

If you previously relied on maxReadFileLine to limit file reads, this behavior is now handled automatically by the agent's per-request parameters.

API Changes (for Custom Modes/Prompts)

The line_ranges parameter has been replaced with a simpler offset/limit approach:

Before:

{ "files": [{ "path": "app.ts", "line_ranges": [[1, 50]] }] }

After:

{ "path": "app.ts", "mode": "slice", "offset": 1, "limit": 50 }

For semantic code extraction, use the new indentation mode:

{ "path": "app.ts", "mode": "indentation", "indentation": { "anchor_line": 42 } }

Backward Compatibility

Legacy Format Support

To ensure smooth mid-chat updates, the parser maintains full backward compatibility with the old read_file format. If a model uses the legacy format (based on chat history from before the update), it will still work correctly.

Supported legacy formats:

  • { files: [{ path: "...", line_ranges: [[start, end]] }] } - Array format
  • { files: "[{...}]" } - Double-stringified JSON (model quirk)
  • line_ranges as tuples, objects, or strings

How it works:

  1. NativeToolCallParser detects the presence of a files parameter
  2. If found, it converts the legacy format to the new internal format
  3. ReadFileTool.executeLegacy() handles multi-file batch processing
  4. A telemetry event (READ_FILE_LEGACY_FORMAT_USED) is captured for monitoring adoption

Testing indicator: A console.warn("[read_file] Legacy format detected") message appears when the fallback path is used (temporary, for validation).

Benefits

  • Better code context: Roo now understands code structure and can extract complete functions/classes
  • Simpler configuration: Fewer settings to worry about
  • Cleaner agent prompts: The simplified API reduces confusion and improves reliability
  • Works across languages: Indentation-based extraction works for Python, TypeScript, JavaScript, and other indentation-structured code
  • Seamless updates: Users can update Roo mid-chat without breaking ongoing conversations

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jan 26, 2026
@roomote
Copy link
Contributor

roomote bot commented Jan 26, 2026

Oroocle Clock   See task on Roo Cloud

Re-review for 1a9bbc8 complete. One remaining item still applies.

  • src/integrations/misc/extract-text.ts: remove unused imports (IndentationReadResult, MAX_LINE_LENGTH)
  • src/core/mentions/index.ts: folder mention .rooignore validation passes an absolute path to validateAccess (expects path relative to workspace); can leak ignored entries
  • src/core/tools/ReadFileTool.ts: indentation mode approval UI does not reflect defaulted anchor_line (can look like a slice read)
  • src/core/tools/ReadFileTool.ts: clamp offset/anchor_line to >= 1 to avoid “line 0” approval UI and indentation out-of-range errors
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

@hannesrudolph hannesrudolph changed the title refactor(read_file): Codex-inspired indentation mode with simplified API refactor(read_file): Codex-inspired read_file refactor Jan 27, 2026
@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 5c7a773 to 5785b36 Compare January 27, 2026 18:05
@hannesrudolph hannesrudolph changed the title refactor(read_file): Codex-inspired read_file refactor refactor(read_file): Codex-inspired read_file refactor EXT-617 Jan 27, 2026
@daniel-lxs
Copy link
Member

This requires us to enable parallel tool calling by default, moving it out of experimental

@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 68ef238 to 9c670b4 Compare January 28, 2026 05:21
@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch 2 times, most recently from 123aacc to 1c3ef7d Compare January 28, 2026 20:37
@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 3ae0e4d to ff54851 Compare January 29, 2026 00:32
Copy link
Collaborator

@mrubens mrubens left a comment

Choose a reason for hiding this comment

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

Sorry to keep nagging on this, but are we confident that this won't break existing conversations for people? If there's a chance it will I think we need to discuss the rollout plan more.

@hannesrudolph
Copy link
Collaborator Author

Sorry to keep nagging on this, but are we confident that this won't break existing conversations for people? If there's a chance it will I think we need to discuss the rollout plan more.

My tests worked without a problem

@hannesrudolph
Copy link
Collaborator Author

Sorry to keep nagging on this, but are we confident that this won't break existing conversations for people? If there's a chance it will I think we need to discuss the rollout plan more.

Added fallback for legacy format so if the model gets confused and sends the old format Roo will not break!

@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 3cea212 to 1704ec7 Compare January 29, 2026 17:00
@hannesrudolph
Copy link
Collaborator Author

@roomote Your review comment about the rooignore validation passing an absolute path in mentions/index.ts (line 401) appears to be a false positive.

Looking at the validateAccess() implementation in RooIgnoreController.ts:

validateAccess(filePath: string): boolean {
    // ...
    const absolutePath = path.resolve(this.cwd, filePath)
    // Follow symlinks...
    const relativePath = path.relative(this.cwd, realPath).toPosix()
    return !this.ignoreInstance.ignores(relativePath)
}

The method correctly handles both absolute and relative paths by:

  1. First resolving the input to absolute via path.resolve(this.cwd, filePath) - if filePath is already absolute, this returns it unchanged
  2. Then converting to relative via path.relative(this.cwd, realPath) before checking against ignore patterns

This is also confirmed by the existing test suite in RooIgnoreController.security.spec.ts (lines 178-187) which explicitly tests that absolute paths work correctly.

All other issues from your review (max_lines coercion, unused imports, anchor_line fallback) have been fixed.

Please approve the PR.

@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 1704ec7 to 6029495 Compare January 29, 2026 19:53
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Jan 29, 2026
- Replace multi-file read_file with single-file-per-call design
- Add two reading modes: slice (default) and indentation
- Implement bidirectional expansion algorithm for indentation mode
- Add line truncation (500 chars) and limit (2000 lines default)
- Remove legacy token-budget-based reading approach
- Remove maxReadFileLine setting (replaced by limit parameter)
- Add new IndentationParams and ReadFileParams types
- Clean up stale FileEntry/LineRange types and helpers

Known limitations:
- Lines >500 chars are truncated (content lost)
- No server-side max limit enforcement
This setting was never used after removing the batch file reading
system. Removes dead code from UI, state management, and types.
- Fix formatPathTooltip to add space before additionalContent (fixes display bug where 'index.ts' + 'up to 50 lines' showed as 'index.tsup to 50 lines')
- Add startLine field to ClineSayTool type for read_file operations
- Update ReadFileTool to include startLine in the message
- Update ChatRow to pass startLine to openFile for navigation to the correct line
…ines

- Add explicit 'when to use' guidance for slice and indentation modes
- Add indentation mode example alongside existing slice example
- Fix confusing 'indentation.anchor_line' text in mode description
- Add 'when NOT to use' guidance in anchor_line description
- Enhance descriptions to help non-OpenAI models choose appropriate mode

This follows Anthropic's documented best practices for tool descriptions:
- Explain what the tool does
- Specify when to use and when NOT to use
- Describe parameter impact
- Aim for 3-4+ sentences
- Remove terminalCompressProgressBar from SettingsView.tsx destructuring
- Remove terminalCompressProgressBar from test mock objects
- Property was never defined in GlobalSettings or ExtensionState types
When mode='indentation' but anchor_line is not provided, now defaults to
the offset parameter (or 1 if neither is provided), rather than silently
falling back to slice mode. This aligns with the documented behavior in
packages/types/src/tool-params.ts.
- Add truncation support to extractTextFromFile via readWithSlice (2000 line limit)
- Update parseMentions to return file content as separate MentionContentBlock objects
- Update processUserContentMentions to handle new contentBlocks structure
- Add Gemini-style truncation warnings with IMPORTANT header
- Sync truncation message format between read_file tool and @ mentions
- Put truncation warning at TOP (before content) in both implementations
- Update test mocks and expectations for new behavior
- Changed getLineSnippet() to always return 'up to X lines' even for default limit
- Previously only showed line count when limit < DEFAULT_LINE_LIMIT
- Now users always see how many lines will be read (e.g., 'up to 2000 lines')
When the model makes multiple parallel read_file tool calls, the UI now
consolidates consecutive read_file ask messages into a single batch view
showing 'Roo wants to read these files' instead of showing repeated
'Roo wants to read this file' messages for each file.

The groupedMessages useMemo in ChatView now detects consecutive read_file
asks and creates a synthetic batch message with batchFiles, which triggers
the existing BatchFilePermission component to render the files as a group.

This improves the UX by reducing visual noise when reading multiple files.
Remove IndentationReadResult and MAX_LINE_LENGTH imports that were
not being used, as flagged by the review bot.
…pproval flow

Adds comprehensive tests for ReadFileTool covering:
- Input validation (missing path parameter)
- RooIgnore blocking
- Directory read error handling
- Image handling (memory limits, format detection, model support)
- Binary file handling (PDF, DOCX, unsupported formats)
- Text file processing (slice and indentation modes)
- Approval flow (approve, deny, feedback)
- Output structure formatting
- Error handling (file read errors, stat errors)

29 new tests covering the orchestration layer that was previously
untested after the Codex-inspired refactor.
- Restore convertFileEntries() function in NativeToolCallParser
- Detect and handle both old { files: [...] } and new { path, mode, ... } formats
- Handle double-stringified JSON from models (files as string vs array)
- Add executeLegacy() method in ReadFileTool for multi-file batch processing
- Add READ_FILE_LEGACY_FORMAT_USED telemetry event
- Add console.warn indicator when legacy format is detected (for testing)
- Add 7 new tests for backward compatibility scenarios
- Add legacy param names (files, line_ranges) to toolParamNames
…itted

- getLineSnippet() now always displays 'indentation mode at line X' when mode is indentation
- getStartLine() now always returns the effective anchor line for indentation mode
- Both methods use fallback chain: anchor_line ?? offset ?? 1

Addresses review feedback about approval UI not reflecting defaulted anchor_line
- Clarify when to use each mode with balanced positive framing
- Slice: ideal for exploration, understanding structure, config files
- Indentation: PREFERRED when you have a line number for complete blocks
- Add warning about anchor_line requirement for indentation mode
- Add concrete example from condensed file summaries format
- Strengthen guidance in mode, anchor_line, and indentation field descriptions
- Increase MAX_LINE_LENGTH from 500 to 2000 characters
@hannesrudolph hannesrudolph force-pushed the read-file-refactor-codex branch from 061496b to 3e25f9c Compare January 29, 2026 21:46
if (params.indentation?.anchor_line !== undefined && params.indentation.anchor_line < 1) {
const errorMsg = `anchor_line must be a 1-indexed line number (got ${params.indentation.anchor_line}). Line numbers start at 1.`
pushToolResult(`Error: ${errorMsg}`)
return
Copy link
Contributor

Choose a reason for hiding this comment

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

The current behavior rejects offset/anchor_line <= 0 with an error, but earlier reviews asked to clamp to the documented defaults (>= 1) so invalid model output degrades gracefully (and avoids “line 0” approval UI). If clamping is the intended UX, these early returns should normalize to 1 instead of failing.

Fix it with Roo Code or mention @roomote and request a fix.

@hannesrudolph hannesrudolph merged commit cc86049 into main Jan 29, 2026
10 checks passed
@hannesrudolph hannesrudolph deleted the read-file-refactor-codex branch January 29, 2026 22:16
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Jan 29, 2026
@github-project-automation github-project-automation bot moved this from Triage to Done in Roo Code Roadmap Jan 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[BUG] Incremental file reading is broken across multiple providers

4 participants