Skip to content

Commit 7e1899a

Browse files
feat: search_in_files now accepts a file path as first argument
When a file path is passed instead of a folder, the function searches only that single file and silently ignores the file_extensions filter. Backward compatible — all existing folder-based calls are unaffected. Error message updated to say 'not a valid directory or file'. Model: claude-sonnet-4-6 Co-Authored-By: bpsa2 <241537330+bpsa2@users.noreply.github.com>
1 parent 02b15de commit 7e1899a

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

src/smolagents/bp_tools.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,12 +1735,13 @@ def inject_tree(folder: str) -> str:
17351735
def search_in_files(folder_path: str, search_pattern: str, file_extensions: tuple = None,
17361736
case_sensitive: bool = False, max_results: int = 50) -> str:
17371737
"""
1738-
Searches for a pattern in files within a folder and its subfolders.
1738+
Searches for a pattern in files within a folder (and its subfolders) or a single file.
17391739
Returns matching lines with file paths and line numbers. This is much more efficient
17401740
than loading all files when you need to find specific code patterns.
17411741
17421742
Args:
1743-
folder_path: str The root folder to search in
1743+
folder_path: str The root folder to search in, or a direct path to a single file.
1744+
When a file path is given, file_extensions is ignored.
17441745
search_pattern: str The text pattern to search for
17451746
file_extensions: tuple Optional tuple of file extensions to search (e.g., ('.py', '.js'))
17461747
If None, searches all text files
@@ -1750,8 +1751,29 @@ def search_in_files(folder_path: str, search_pattern: str, file_extensions: tupl
17501751
Returns:
17511752
str: Search results formatted as "filepath:line_number: line_content"
17521753
"""
1754+
if os.path.isfile(folder_path):
1755+
# Single-file mode: search only this file, ignore file_extensions
1756+
results = []
1757+
count = 0
1758+
pattern = search_pattern if case_sensitive else search_pattern.lower()
1759+
try:
1760+
with open(folder_path, 'r', encoding='utf-8') as f:
1761+
for line_num, line in enumerate(f, 1):
1762+
search_line = line if case_sensitive else line.lower()
1763+
if pattern in search_line:
1764+
results.append(f"{folder_path}:{line_num}: {line.rstrip()}")
1765+
count += 1
1766+
if count >= max_results:
1767+
results.append(f"\n... (stopped at {max_results} results)")
1768+
return "\n".join(results)
1769+
except (UnicodeDecodeError, PermissionError, IOError):
1770+
return f"Error: could not read file '{folder_path}'"
1771+
if not results:
1772+
return f"No matches found for '{search_pattern}' in '{folder_path}'"
1773+
return "\n".join(results)
1774+
17531775
if not os.path.isdir(folder_path):
1754-
return f"Error: '{folder_path}' is not a valid directory"
1776+
return f"Error: '{folder_path}' is not a valid directory or file"
17551777

17561778
results = []
17571779
count = 0

0 commit comments

Comments
 (0)