diff --git a/src/fastcontext/agent/tool/grep.py b/src/fastcontext/agent/tool/grep.py index 4ee161f..96fd78a 100644 --- a/src/fastcontext/agent/tool/grep.py +++ b/src/fastcontext/agent/tool/grep.py @@ -26,7 +26,7 @@ class GrepTool(Tool): "output_mode": { "type": "string", "enum": ["content", "files_with_matches", "count"], - "description": 'Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches".', + "description": 'Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "content".', }, "-B": { "type": "number", @@ -72,7 +72,7 @@ async def call(self, parameters: str, **kwargs) -> str: pattern = params.get("pattern") path = params.get("path", cwd) glob = params.get("glob") - output_mode = params.get("output_mode") + output_mode = params.get("output_mode", "content") before_context = params.get("-B") after_context = params.get("-A") context = params.get("-C", 3) diff --git a/tests/test_grep_default_mode.py b/tests/test_grep_default_mode.py new file mode 100644 index 0000000..6ecbf8c --- /dev/null +++ b/tests/test_grep_default_mode.py @@ -0,0 +1,31 @@ +import asyncio +import json +import re +import tempfile +from pathlib import Path + +from fastcontext.agent.tool.grep import GrepTool + + +def test_grep_defaults_to_content(): + """With output_mode omitted, Grep must behave as 'content' (matching lines + with line numbers), not as files_with_matches and not as a flag-less rg + call that drops -n.""" + grep = GrepTool() + with tempfile.TemporaryDirectory() as cwd: + (Path(cwd) / "haystack.txt").write_text("alpha\nMATCH here\nbeta\n", encoding="utf-8") + + out = asyncio.run(grep.call(json.dumps({"pattern": "MATCH"}), cwd=cwd)) + lines = out.splitlines() + + # Content mode with -n emits ":" rows for matches. + assert any(re.match(r"\d+:.*MATCH", ln) for ln in lines), f"expected line-numbered match, got: {out!r}" + # files_with_matches would emit only the bare path with no match text. + assert "MATCH here" in out + + +def test_grep_schema_documents_content_default(): + schema = GrepTool().schema() + desc = schema["function"]["parameters"]["properties"]["output_mode"]["description"] + assert 'Defaults to "content"' in desc + assert "files_with_matches" not in desc.split("Defaults to")[1]