Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions mini_coding_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ def remember(bucket, item, limit):
def build_tools(self):
tools = {
"list_files": {
"schema": {"path": "str='.'"},
"schema": {"path": "str='.'", "start": "int=1", "end": "int=200"},
"risky": False,
"description": "List files in the workspace.",
"description": "List files in the workspace, up to 200 entries per page.",
"run": self.tool_list_files,
},
"read_file": {
Expand Down Expand Up @@ -540,6 +540,10 @@ def validate_tool(self, name, args):
path = self.path(args.get("path", "."))
if not path.is_dir():
raise ValueError("path is not a directory")
start = int(args.get("start", 1))
end = int(args.get("end", 200))
if start < 1 or end < start:
raise ValueError("invalid entry range")
return

if name == "read_file":
Expand Down Expand Up @@ -743,14 +747,23 @@ def tool_list_files(self, args):
path = self.path(args.get("path", "."))
if not path.is_dir():
raise ValueError("path is not a directory")
start = int(args.get("start", 1))
end = int(args.get("end", 200))
entries = [
item for item in sorted(path.iterdir(), key=lambda item: (item.is_file(), item.name.lower()))
if item.name not in IGNORED_PATH_NAMES
]
page_end = min(end, start + 199)
lines = []
for entry in entries[:200]:
for entry in entries[start - 1 : page_end]:
kind = "[D]" if entry.is_dir() else "[F]"
lines.append(f"{kind} {entry.relative_to(self.root)}")
if page_end < len(entries):
display_path = str(path.relative_to(self.root))
lines.append(
f"... {page_end - start + 1} entries shown; {len(entries) - page_end} additional entries omitted. "
f"Call list_files with path='{display_path}', start={page_end + 1}, end={page_end + 200} to continue."
)
return "\n".join(lines) or "(empty)"

def tool_read_file(self, args):
Expand Down
17 changes: 17 additions & 0 deletions tests/test_mini_coding_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,23 @@ def test_list_files_hides_internal_agent_state(tmp_path):
assert "[F] hello.txt" in result


def test_list_files_reports_truncation_and_supports_pagination(tmp_path):
agent = build_agent(tmp_path, [])
for index in range(203):
(tmp_path / f"item-{index:03}.txt").write_text("item\n", encoding="utf-8")

first_page = agent.run_tool("list_files", {})
assert "200 entries shown; 4 additional entries omitted" in first_page

wide_page = agent.run_tool("list_files", {"end": 400})
assert "[F] item-198.txt" in wide_page
assert "[F] item-200.txt" not in wide_page

next_page = agent.run_tool("list_files", {"start": 201, "end": 400})
assert "[F] item-202.txt" in next_page
assert "[F] item-000.txt" not in next_page


def test_path_rejects_parent_escape(tmp_path):
agent = build_agent(tmp_path, [])

Expand Down