RA.Aid/ra_aid/tools/ripgrep.py

117 lines
3.2 KiB
Python

from typing import Dict, Union, Optional, List
from langchain_core.tools import tool
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
from ra_aid.proc.interactive import run_interactive_command
from ra_aid.text.processing import truncate_output
console = Console()
DEFAULT_EXCLUDE_DIRS = [
'.git',
'node_modules',
'vendor',
'.venv',
'__pycache__',
'.cache',
'dist',
'build',
'env',
'.env',
'venv',
'.idea',
'.vscode'
]
@tool
def ripgrep_search(
pattern: str,
*,
file_type: str = None,
case_sensitive: bool = True,
include_hidden: bool = False,
follow_links: bool = False,
exclude_dirs: List[str] = None
) -> Dict[str, Union[str, int, bool]]:
"""Execute a ripgrep (rg) search with formatting and common options.
Args:
pattern: Search pattern to find
file_type: Optional file type to filter results (e.g. 'py' for Python files)
case_sensitive: Whether to do case-sensitive search (default: True)
include_hidden: Whether to search hidden files and directories (default: False)
follow_links: Whether to follow symbolic links (default: False)
exclude_dirs: Additional directories to exclude (combines with defaults)
Returns:
Dict containing:
- output: The formatted search results
- return_code: Process return code (0 means success)
- success: Boolean indicating if search succeeded
"""
# Build rg command with options
cmd = ['rg', '--color', 'always']
if not case_sensitive:
cmd.append('-i')
if include_hidden:
cmd.append('--hidden')
if follow_links:
cmd.append('--follow')
if file_type:
cmd.extend(['-t', file_type])
# Add exclusions
exclusions = DEFAULT_EXCLUDE_DIRS + (exclude_dirs or [])
for dir in exclusions:
cmd.extend(['--glob', f'!{dir}'])
# Add the search pattern
cmd.append(pattern)
# Build info sections for display
info_sections = []
# Search parameters section
params = [
"## Search Parameters",
f"**Pattern**: `{pattern}`",
f"**Case Sensitive**: {case_sensitive}",
f"**File Type**: {file_type or 'all'}"
]
if include_hidden:
params.append("**Including Hidden Files**: yes")
if follow_links:
params.append("**Following Symlinks**: yes")
if exclude_dirs:
params.append("\n**Additional Exclusions**:")
for dir in exclude_dirs:
params.append(f"- `{dir}`")
info_sections.append("\n".join(params))
# Execute command
try:
print()
output, return_code = run_interactive_command(cmd)
print()
decoded_output = output.decode() if output else ""
return {
"output": truncate_output(decoded_output),
"return_code": return_code,
"success": return_code == 0
}
except Exception as e:
error_msg = str(e)
console.print(Panel(error_msg, title="❌ Error", border_style="red"))
return {
"output": error_msg,
"return_code": 1,
"success": False
}