@@ -20,33 +20,55 @@ class SearchFilesByNameResultObservation(Observation):
20
20
files : list [str ] = Field (
21
21
description = "List of matching file paths" ,
22
22
)
23
+ page : int = Field (
24
+ description = "Current page number (1-based)" ,
25
+ )
26
+ total_pages : int = Field (
27
+ description = "Total number of pages available" ,
28
+ )
29
+ total_files : int = Field (
30
+ description = "Total number of files with matches" ,
31
+ )
32
+ files_per_page : int = Field (
33
+ description = "Number of files shown per page" ,
34
+ )
23
35
24
- str_template : ClassVar [str ] = "Found {total } files matching pattern: {pattern}"
36
+ str_template : ClassVar [str ] = "Found {total_files } files matching pattern: {pattern} (page {page}/{total_pages}) "
25
37
26
38
@property
27
39
def total (self ) -> int :
28
- return len ( self .files )
40
+ return self .total_files
29
41
30
42
31
43
def search_files_by_name (
32
44
codebase : Codebase ,
33
45
pattern : str ,
46
+ page : int = 1 ,
47
+ files_per_page : int = 10 ,
34
48
) -> SearchFilesByNameResultObservation :
35
49
"""Search for files by name pattern in the codebase.
36
50
37
51
Args:
38
52
codebase: The codebase to search in
39
53
pattern: Glob pattern to search for (e.g. "*.py", "test_*.py")
54
+ page: Page number to return (1-based, default: 1)
55
+ files_per_page: Number of files to return per page (default: 10)
40
56
"""
41
57
try :
58
+ # Validate pagination parameters
59
+ if page < 1 :
60
+ page = 1
61
+ if files_per_page < 1 :
62
+ files_per_page = 10
63
+
42
64
if shutil .which ("fd" ) is None :
43
65
logger .warning ("fd is not installed, falling back to find" )
44
66
results = subprocess .check_output (
45
67
["find" , "-name" , pattern ],
46
68
cwd = codebase .repo_path ,
47
69
timeout = 30 ,
48
70
)
49
- files = [path .removeprefix ("./" ) for path in results .decode ("utf-8" ).strip ().split ("\n " )] if results .strip () else []
71
+ all_files = [path .removeprefix ("./" ) for path in results .decode ("utf-8" ).strip ().split ("\n " )] if results .strip () else []
50
72
51
73
else :
52
74
logger .info (f"Searching for files with pattern: { pattern } " )
@@ -55,12 +77,31 @@ def search_files_by_name(
55
77
cwd = codebase .repo_path ,
56
78
timeout = 30 ,
57
79
)
58
- files = results .decode ("utf-8" ).strip ().split ("\n " ) if results .strip () else []
80
+ all_files = results .decode ("utf-8" ).strip ().split ("\n " ) if results .strip () else []
81
+
82
+ # Sort files for consistent pagination
83
+ all_files .sort ()
84
+
85
+ # Calculate pagination
86
+ total_files = len (all_files )
87
+ total_pages = (total_files + files_per_page - 1 ) // files_per_page if total_files > 0 else 1
88
+
89
+ # Ensure page is within valid range
90
+ page = min (page , total_pages )
91
+
92
+ # Get paginated results
93
+ start_idx = (page - 1 ) * files_per_page
94
+ end_idx = start_idx + files_per_page
95
+ paginated_files = all_files [start_idx :end_idx ]
59
96
60
97
return SearchFilesByNameResultObservation (
61
98
status = "success" ,
62
99
pattern = pattern ,
63
- files = files ,
100
+ files = paginated_files ,
101
+ page = page ,
102
+ total_pages = total_pages ,
103
+ total_files = total_files ,
104
+ files_per_page = files_per_page ,
64
105
)
65
106
66
107
except Exception as e :
@@ -69,4 +110,8 @@ def search_files_by_name(
69
110
error = f"Error searching files: { e !s} " ,
70
111
pattern = pattern ,
71
112
files = [],
113
+ page = page ,
114
+ total_pages = 0 ,
115
+ total_files = 0 ,
116
+ files_per_page = files_per_page ,
72
117
)
0 commit comments