Skip to content
Open
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
2 changes: 1 addition & 1 deletion src/fastcontext/agent/tool/grep.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ A powerful search tool built on ripgrep
Usage:
- Prefer using Grep for search tasks when you know the exact symbols or strings to search for. Whenever possible, use this tool instead of invoking grep or rg as a terminal command.
- Supports full regex syntax (e.g., "log.*Error", "function\s+\w+")
- Filter files with glob parameter (e.g., ".js", "**/.tsx") or type parameter (e.g., "js", "py", "rust")
- Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")
- Output modes: "content" shows matching lines (default), "files_with_matches" shows only file paths, "count" shows match counts
- Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use interface\{\} to find interface{} in Go code)
- Multiline matching: By default patterns match within single lines only. For cross-line patterns like struct \{[\s\S]*?field, use multiline: true
Expand Down
30 changes: 30 additions & 0 deletions tests/test_grep_glob_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import asyncio
import json
import tempfile
from pathlib import Path

from fastcontext.agent.tool.glob import GlobTool
from fastcontext.agent.tool.grep import GrepTool


def test_grep_doc_glob_examples_are_valid():
"""The glob examples in the Grep description must be extension globs, not
the malformed dotfile patterns '.js' / '**/.tsx'."""
desc = GrepTool().description
assert '"*.js"' in desc and '"**/*.tsx"' in desc
# The old malformed examples must be gone.
assert '(e.g., ".js"' not in desc
assert '"**/.tsx"' not in desc


def test_documented_extension_glob_actually_matches():
"""Sanity-check that the documented '*.js' pattern matches by extension
(the malformed '.js' would only match a literal dotfile)."""
glob = GlobTool()
with tempfile.TemporaryDirectory() as cwd:
(Path(cwd) / "app.js").write_text("x", encoding="utf-8")
(Path(cwd) / "readme.md").write_text("x", encoding="utf-8")

out = asyncio.run(glob.call(json.dumps({"directory": cwd, "pattern": "*.js"}), cwd=cwd))
names = {Path(line).name for line in out.splitlines()}
assert names == {"app.js"}