mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-30 14:52:36 +00:00
Merge branch 'lorenze/feat/grep-tool' of github.com:crewAIInc/crewAI into lorenze/feat/file-discovery-tools
This commit is contained in:
@@ -77,6 +77,7 @@ from crewai_tools.tools.generate_crewai_automation_tool.generate_crewai_automati
|
||||
GenerateCrewaiAutomationTool,
|
||||
)
|
||||
from crewai_tools.tools.github_search_tool.github_search_tool import GithubSearchTool
|
||||
from crewai_tools.tools.grep_tool.grep_tool import GrepTool
|
||||
from crewai_tools.tools.hyperbrowser_load_tool.hyperbrowser_load_tool import (
|
||||
HyperbrowserLoadTool,
|
||||
)
|
||||
@@ -230,6 +231,7 @@ __all__ = [
|
||||
"FirecrawlSearchTool",
|
||||
"GenerateCrewaiAutomationTool",
|
||||
"GithubSearchTool",
|
||||
"GrepTool",
|
||||
"HyperbrowserLoadTool",
|
||||
"InvokeCrewAIAutomationTool",
|
||||
"JSONSearchTool",
|
||||
|
||||
@@ -66,6 +66,7 @@ from crewai_tools.tools.generate_crewai_automation_tool.generate_crewai_automati
|
||||
GenerateCrewaiAutomationTool,
|
||||
)
|
||||
from crewai_tools.tools.github_search_tool.github_search_tool import GithubSearchTool
|
||||
from crewai_tools.tools.grep_tool.grep_tool import GrepTool
|
||||
from crewai_tools.tools.hyperbrowser_load_tool.hyperbrowser_load_tool import (
|
||||
HyperbrowserLoadTool,
|
||||
)
|
||||
@@ -214,6 +215,7 @@ __all__ = [
|
||||
"FirecrawlSearchTool",
|
||||
"GenerateCrewaiAutomationTool",
|
||||
"GithubSearchTool",
|
||||
"GrepTool",
|
||||
"HyperbrowserLoadTool",
|
||||
"InvokeCrewAIAutomationTool",
|
||||
"JSONSearchTool",
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from crewai_tools.tools.grep_tool.grep_tool import GrepTool
|
||||
|
||||
__all__ = ["GrepTool"]
|
||||
@@ -2,33 +2,33 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
from crewai.tools import BaseTool
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
|
||||
|
||||
MAX_OUTPUT_CHARS = 50_000
|
||||
MAX_FILES = 10_000
|
||||
MAX_MATCHES_PER_FILE = 200
|
||||
MAX_LINE_LENGTH = 500
|
||||
BINARY_CHECK_SIZE = 8192
|
||||
|
||||
SKIP_DIRS = frozenset({
|
||||
".git",
|
||||
"__pycache__",
|
||||
"node_modules",
|
||||
".venv",
|
||||
"venv",
|
||||
".tox",
|
||||
".mypy_cache",
|
||||
".pytest_cache",
|
||||
})
|
||||
SKIP_DIRS = frozenset(
|
||||
{
|
||||
".git",
|
||||
"__pycache__",
|
||||
"node_modules",
|
||||
".venv",
|
||||
"venv",
|
||||
".tox",
|
||||
".mypy_cache",
|
||||
".pytest_cache",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -52,7 +52,9 @@ class FileSearchResult:
|
||||
class GrepToolSchema(BaseModel):
|
||||
"""Schema for grep tool arguments."""
|
||||
|
||||
pattern: str = Field(..., description="Regex pattern to search for in file contents")
|
||||
pattern: str = Field(
|
||||
..., description="Regex pattern to search for in file contents"
|
||||
)
|
||||
path: str | None = Field(
|
||||
default=None,
|
||||
description="File or directory to search in. Defaults to current working directory.",
|
||||
@@ -84,13 +86,23 @@ class GrepTool(BaseTool):
|
||||
|
||||
Recursively searches files in a directory for lines matching a regex pattern.
|
||||
Supports glob filtering, context lines, and multiple output modes.
|
||||
|
||||
Example:
|
||||
>>> tool = GrepTool()
|
||||
>>> result = tool.run(pattern="def.*main", path="/path/to/project")
|
||||
>>> result = tool.run(
|
||||
... pattern="TODO",
|
||||
... path="/path/to/project",
|
||||
... glob_pattern="*.py",
|
||||
... context_lines=2,
|
||||
... )
|
||||
"""
|
||||
|
||||
name: str = "grep"
|
||||
name: str = "Search file contents"
|
||||
description: str = (
|
||||
"Search file contents on disk using regex patterns. "
|
||||
"A tool that searches file contents on disk using regex patterns. "
|
||||
"Recursively searches files in a directory for matching lines. "
|
||||
"Returns matching content, file paths, or match counts."
|
||||
"Returns matching content with line numbers, file paths only, or match counts."
|
||||
)
|
||||
args_schema: type[BaseModel] = GrepToolSchema
|
||||
|
||||
@@ -154,7 +166,10 @@ class GrepTool(BaseTool):
|
||||
|
||||
# Truncate if needed
|
||||
if len(output) > MAX_OUTPUT_CHARS:
|
||||
output = output[:MAX_OUTPUT_CHARS] + "\n\n... Output truncated. Try a narrower search pattern or glob filter."
|
||||
output = (
|
||||
output[:MAX_OUTPUT_CHARS]
|
||||
+ "\n\n... Output truncated. Try a narrower search pattern or glob filter."
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
@@ -255,11 +270,13 @@ class GrepTool(BaseTool):
|
||||
text = lines[i].rstrip("\n\r")
|
||||
if len(text) > MAX_LINE_LENGTH:
|
||||
text = text[:MAX_LINE_LENGTH] + "..."
|
||||
current_group.append(MatchLine(
|
||||
line_number=i + 1, # 1-indexed
|
||||
text=text,
|
||||
is_match=(i in match_line_nums),
|
||||
))
|
||||
current_group.append(
|
||||
MatchLine(
|
||||
line_number=i + 1, # 1-indexed
|
||||
text=text,
|
||||
is_match=(i in match_line_nums),
|
||||
)
|
||||
)
|
||||
|
||||
prev_end = end
|
||||
|
||||
@@ -4,7 +4,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai.tools.agent_tools.grep_tool import GrepTool
|
||||
from crewai_tools import GrepTool
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -69,7 +69,7 @@ class TestGrepTool:
|
||||
|
||||
def test_tool_metadata(self) -> None:
|
||||
"""Test tool has correct name and description."""
|
||||
assert self.tool.name == "grep"
|
||||
assert self.tool.name == "Search file contents"
|
||||
assert "search" in self.tool.description.lower() or "Search" in self.tool.description
|
||||
|
||||
def test_args_schema(self) -> None:
|
||||
@@ -8360,6 +8360,126 @@
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A tool that searches file contents on disk using regex patterns. Recursively searches files in a directory for matching lines. Returns matching content with line numbers, file paths only, or match counts.",
|
||||
"env_vars": [],
|
||||
"humanized_name": "Search file contents",
|
||||
"init_params_schema": {
|
||||
"$defs": {
|
||||
"EnvVar": {
|
||||
"properties": {
|
||||
"default": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"title": "Default"
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"default": true,
|
||||
"title": "Required",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"title": "EnvVar",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"description": "Tool for searching file contents on disk using regex patterns.\n\nRecursively searches files in a directory for lines matching a regex pattern.\nSupports glob filtering, context lines, and multiple output modes.\n\nExample:\n >>> tool = GrepTool()\n >>> result = tool.run(pattern=\"def.*main\", path=\"/path/to/project\")\n >>> result = tool.run(\n ... pattern=\"TODO\",\n ... path=\"/path/to/project\",\n ... glob_pattern=\"*.py\",\n ... context_lines=2,\n ... )",
|
||||
"properties": {},
|
||||
"title": "GrepTool",
|
||||
"type": "object"
|
||||
},
|
||||
"name": "GrepTool",
|
||||
"package_dependencies": [],
|
||||
"run_params_schema": {
|
||||
"description": "Schema for grep tool arguments.",
|
||||
"properties": {
|
||||
"case_insensitive": {
|
||||
"default": false,
|
||||
"description": "Whether to perform case-insensitive matching",
|
||||
"title": "Case Insensitive",
|
||||
"type": "boolean"
|
||||
},
|
||||
"context_lines": {
|
||||
"default": 0,
|
||||
"description": "Number of lines to show before and after each match",
|
||||
"title": "Context Lines",
|
||||
"type": "integer"
|
||||
},
|
||||
"glob_pattern": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Glob pattern to filter files (e.g. '*.py', '*.{ts,tsx}')",
|
||||
"title": "Glob Pattern"
|
||||
},
|
||||
"include_line_numbers": {
|
||||
"default": true,
|
||||
"description": "Whether to prefix matching lines with line numbers",
|
||||
"title": "Include Line Numbers",
|
||||
"type": "boolean"
|
||||
},
|
||||
"output_mode": {
|
||||
"default": "content",
|
||||
"description": "Output mode: 'content' shows matching lines, 'files_with_matches' shows only file paths, 'count' shows match counts per file",
|
||||
"enum": [
|
||||
"content",
|
||||
"files_with_matches",
|
||||
"count"
|
||||
],
|
||||
"title": "Output Mode",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "File or directory to search in. Defaults to current working directory.",
|
||||
"title": "Path"
|
||||
},
|
||||
"pattern": {
|
||||
"description": "Regex pattern to search for in file contents",
|
||||
"title": "Pattern",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pattern"
|
||||
],
|
||||
"title": "GrepToolSchema",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Scrape or crawl a website using Hyperbrowser and return the contents in properly formatted markdown or html",
|
||||
"env_vars": [
|
||||
|
||||
Reference in New Issue
Block a user