Skip to content

feat: grep tool - #13

Merged
bobrykov merged 2 commits into
masterfrom
feat/grep-tool
Jul 26, 2026
Merged

feat: grep tool#13
bobrykov merged 2 commits into
masterfrom
feat/grep-tool

Conversation

@bobrykov

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e0cef98b-aaa5-4272-91d4-304790e18eb4

📥 Commits

Reviewing files that changed from the base of the PR and between a684bda and 445865c.

📒 Files selected for processing (3)
  • crates/dch-tools/src/grep.rs
  • crates/dch-tools/src/output.rs
  • crates/dch-tools/src/regex_cache.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/dch-tools/src/regex_cache.rs
  • crates/dch-tools/src/output.rs
  • crates/dch-tools/src/grep.rs

📝 Walkthrough

Walkthrough

Adds a built-in GrepTool for regex searches across gitignore-aware directories, with filtering, case handling, match limits, binary skipping, cached compilation, and large-output spilling. The tool is exported and registered alongside supporting workspace dependencies and tests.

Changes

Grep tool

Layer / File(s) Summary
Shared regex and output services
Cargo.toml, crates/dch-tools/Cargo.toml, crates/dch-tools/src/regex_cache.rs, crates/dch-tools/src/output.rs, crates/dch-tools/src/lib.rs
Adds workspace-managed dependencies, an LRU regex cache, UTF-8-safe output truncation and temp-file spilling, public exports, and unit tests for both services.
Grep input and filesystem execution
crates/dch-tools/src/grep.rs
Adds validated JSON input, regex compilation, cwd and path handling, filtered filesystem scanning, ordered matches, per-file and total limits, binary and oversized-file skipping, result formatting, and integration tests.
Builtin registry integration
crates/dch-tools/src/registry.rs, crates/dch-tools/src/grep.rs
Registers GrepTool and validates its identity, read-only status, concurrency safety, and registry presence.

Sequence Diagram(s)

sequenceDiagram
  participant RunnerContext
  participant GrepTool
  participant FilesystemWalker
  participant OutputHelpers
  RunnerContext->>GrepTool: provide runner cwd
  GrepTool->>FilesystemWalker: scan filtered files
  FilesystemWalker-->>GrepTool: return regex matches
  GrepTool->>OutputHelpers: serialize or spill output
Loading

Possibly related PRs

  • dch-labs/dch#10: Extends the same builtin tool registry with MultiEditTool.
  • dch-labs/dch#12: Provides the shared gitignore-aware walking and glob-filtering behavior used by GrepTool.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a grep tool.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 50.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/grep-tool

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
crates/dch-tools/src/output.rs (1)

202-217: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test doesn't exercise the actual boundary-backup path.

Both assertions use content shorter than PREVIEW_BYTES, so floor_char_boundary always hits the i == s.len() short-circuit and never walks back over a continuation byte. The comment's claim that this "asserts the function is boundary-safe at the const limit" doesn't hold — the interesting case (target landing mid-character) is never constructed, and the multi half discards its result entirely.

✅ Suggested addition: directly test the backward-scan branch
+    #[test]
+    fn floor_char_boundary_backs_up_over_continuation_bytes() {
+        let s = "ééééé"; // 5 chars, 2 bytes each = 10 bytes total
+        // Byte 1 is a continuation byte of the first 'é'; must back up to 0.
+        assert_eq!(floor_char_boundary(s, 1), 0);
+        // Byte 3 is a continuation byte of the second 'é'; must back up to 2.
+        assert_eq!(floor_char_boundary(s, 3), 2);
+        // An exact boundary should be returned unchanged.
+        assert_eq!(floor_char_boundary(s, 4), 4);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/dch-tools/src/output.rs` around lines 202 - 217, Update the test
preview_slice_respects_char_boundary to use input longer than PREVIEW_BYTES with
a multibyte character crossing the cutoff, so preview_slice must back up over
continuation bytes. Assert the returned value explicitly equals the input prefix
ending at the preceding valid character boundary, and remove the
discarded-result assertion and inaccurate commentary.
crates/dch-tools/src/grep.rs (1)

238-264: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

No cap on total matches across files or on individual file size read into memory.

The per-file max_matches cap bounds a single file's contribution, but job::run accumulates matches across an unbounded number of files with no overall ceiling, and each file is read fully into memory regardless of size. On a large repo or a huge matched text file this can spike memory/CPU on the blocking thread well before the 50 KiB output-spill kicks in.

♻️ Suggested: bound total matches across the walk
     pub(super) fn run(job: &SearchJob) -> ToolOutput {
         let mut matches = Vec::new();
+        const MAX_TOTAL_MATCHES: usize = 10_000;
         for entry in walk::walk_files(&job.base, &job.include, &job.exclude) {
+            if matches.len() >= MAX_TOTAL_MATCHES {
+                break;
+            }
             let path = entry.path();
             if walk::likely_binary(path) {
                 continue;
             }
             let Ok(content) = std::fs::read_to_string(path) else {
                 continue;
             };
             let file_matches = search_file(&job.regex, &content, path, &job.base, job.max_matches);
             matches.extend(file_matches);
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/dch-tools/src/grep.rs` around lines 238 - 264, Update job::run to
enforce a total match limit across all files, stopping or truncating collection
once the cap is reached while preserving the per-file job.max_matches behavior.
Replace the unbounded read_to_string call with bounded file reading or an
explicit size guard so oversized files are skipped or processed without loading
them fully into memory, and keep the existing output truncation flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/dch-tools/src/grep.rs`:
- Around line 444-458: Update the match-collection loop in the grep result
function to check whether results has reached max_matches before testing or
pushing a matching line, so max_matches = 0 returns no results while positive
limits retain the existing cap behavior.

In `@crates/dch-tools/src/regex_cache.rs`:
- Around line 141-142: Serialize the cache-size-sensitive tests, including
clear_cache_empties_state and the tests around cache_hit_returns_matching_regex
and the additional affected ranges, so they cannot run concurrently with other
REGEX_CACHE-mutating tests. Use the module’s existing test-serialization
mechanism if available, or add a shared synchronization guard around each
affected test while preserving their current assertions and behavior.

---

Nitpick comments:
In `@crates/dch-tools/src/grep.rs`:
- Around line 238-264: Update job::run to enforce a total match limit across all
files, stopping or truncating collection once the cap is reached while
preserving the per-file job.max_matches behavior. Replace the unbounded
read_to_string call with bounded file reading or an explicit size guard so
oversized files are skipped or processed without loading them fully into memory,
and keep the existing output truncation flow.

In `@crates/dch-tools/src/output.rs`:
- Around line 202-217: Update the test preview_slice_respects_char_boundary to
use input longer than PREVIEW_BYTES with a multibyte character crossing the
cutoff, so preview_slice must back up over continuation bytes. Assert the
returned value explicitly equals the input prefix ending at the preceding valid
character boundary, and remove the discarded-result assertion and inaccurate
commentary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d049e366-b473-4248-8461-2af97044dddc

📥 Commits

Reviewing files that changed from the base of the PR and between 6300e7f and a684bda.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • crates/dch-tools/Cargo.toml
  • crates/dch-tools/src/grep.rs
  • crates/dch-tools/src/lib.rs
  • crates/dch-tools/src/output.rs
  • crates/dch-tools/src/regex_cache.rs
  • crates/dch-tools/src/registry.rs

Comment thread crates/dch-tools/src/grep.rs
Comment thread crates/dch-tools/src/regex_cache.rs
@bobrykov
bobrykov merged commit b03b0d0 into master Jul 26, 2026
8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant