From 69f1dcdba7c843a21ba845f6d6d1cc21c183293b Mon Sep 17 00:00:00 2001 From: 19emtuck Date: Sun, 22 Mar 2026 19:08:45 +0100 Subject: [PATCH 1/3] proposal to adopt mypy some e.g. interfaces problems --- nanobot/agent/tools/filesystem.py | 24 ++++++++++++++++++++---- pyproject.toml | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/nanobot/agent/tools/filesystem.py b/nanobot/agent/tools/filesystem.py index 4f83642..8ccffb2 100644 --- a/nanobot/agent/tools/filesystem.py +++ b/nanobot/agent/tools/filesystem.py @@ -93,8 +93,10 @@ class ReadFileTool(_FsTool): "required": ["path"], } - async def execute(self, path: str, offset: int = 1, limit: int | None = None, **kwargs: Any) -> Any: + async def execute(self, path: str | None = None, offset: int = 1, limit: int | None = None, **kwargs: Any) -> Any: try: + if not path: + return f"Error: File not found: {path}" fp = self._resolve(path) if not fp.exists(): return f"Error: File not found: {path}" @@ -174,8 +176,12 @@ class WriteFileTool(_FsTool): "required": ["path", "content"], } - async def execute(self, path: str, content: str, **kwargs: Any) -> str: + async def execute(self, path: str | None = None, content: str | None = None, **kwargs: Any) -> str: try: + if not path: + raise ValueError(f"Unknown path") + if content is None: + raise ValueError("Unknown content") fp = self._resolve(path) fp.parent.mkdir(parents=True, exist_ok=True) fp.write_text(content, encoding="utf-8") @@ -248,10 +254,18 @@ class EditFileTool(_FsTool): } async def execute( - self, path: str, old_text: str, new_text: str, + self, path: str | None = None, old_text: str | None = None, + new_text: str | None = None, replace_all: bool = False, **kwargs: Any, ) -> str: try: + if not path: + raise ValueError(f"Unknown path") + if old_text is None: + raise ValueError(f"Unknown old_text") + if new_text is None: + raise ValueError(f"Unknown next_text") + fp = self._resolve(path) if not fp.exists(): return f"Error: File not found: {path}" @@ -350,10 +364,12 @@ class ListDirTool(_FsTool): } async def execute( - self, path: str, recursive: bool = False, + self, path: str | None = None, recursive: bool = False, max_entries: int | None = None, **kwargs: Any, ) -> str: try: + if path is None: + raise ValueError(f"Unknown path") dp = self._resolve(path) if not dp.exists(): return f"Error: Directory not found: {path}" diff --git a/pyproject.toml b/pyproject.toml index b765720..a941ab1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,7 @@ dev = [ "matrix-nio[e2e]>=0.25.2", "mistune>=3.0.0,<4.0.0", "nh3>=0.2.17,<1.0.0", + "mypy>=1.19.1", ] [project.scripts] From d4a7194c88fc47b57ed254f5ad587ac309719b8b Mon Sep 17 00:00:00 2001 From: 19emtuck Date: Mon, 23 Mar 2026 12:26:06 +0100 Subject: [PATCH 2/3] remove some none used f string --- nanobot/agent/tools/filesystem.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nanobot/agent/tools/filesystem.py b/nanobot/agent/tools/filesystem.py index 8ccffb2..a967073 100644 --- a/nanobot/agent/tools/filesystem.py +++ b/nanobot/agent/tools/filesystem.py @@ -179,7 +179,7 @@ class WriteFileTool(_FsTool): async def execute(self, path: str | None = None, content: str | None = None, **kwargs: Any) -> str: try: if not path: - raise ValueError(f"Unknown path") + raise ValueError("Unknown path") if content is None: raise ValueError("Unknown content") fp = self._resolve(path) @@ -260,11 +260,11 @@ class EditFileTool(_FsTool): ) -> str: try: if not path: - raise ValueError(f"Unknown path") + raise ValueError("Unknown path") if old_text is None: - raise ValueError(f"Unknown old_text") + raise ValueError("Unknown old_text") if new_text is None: - raise ValueError(f"Unknown next_text") + raise ValueError("Unknown next_text") fp = self._resolve(path) if not fp.exists(): @@ -369,7 +369,7 @@ class ListDirTool(_FsTool): ) -> str: try: if path is None: - raise ValueError(f"Unknown path") + raise ValueError("Unknown path") dp = self._resolve(path) if not dp.exists(): return f"Error: Directory not found: {path}" From d25985be0b7631e54acb1c6dfb9f500b3eb094d3 Mon Sep 17 00:00:00 2001 From: Xubin Ren Date: Tue, 24 Mar 2026 03:45:16 +0000 Subject: [PATCH 3/3] fix(filesystem): clarify optional tool argument handling Keep the mypy-friendly optional execute signatures while returning clearer errors for missing arguments and locking that behavior with regression tests. Made-with: Cursor --- nanobot/agent/tools/filesystem.py | 4 ++-- tests/test_filesystem_tools.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/nanobot/agent/tools/filesystem.py b/nanobot/agent/tools/filesystem.py index a967073..da7778d 100644 --- a/nanobot/agent/tools/filesystem.py +++ b/nanobot/agent/tools/filesystem.py @@ -96,7 +96,7 @@ class ReadFileTool(_FsTool): async def execute(self, path: str | None = None, offset: int = 1, limit: int | None = None, **kwargs: Any) -> Any: try: if not path: - return f"Error: File not found: {path}" + return "Error reading file: Unknown path" fp = self._resolve(path) if not fp.exists(): return f"Error: File not found: {path}" @@ -264,7 +264,7 @@ class EditFileTool(_FsTool): if old_text is None: raise ValueError("Unknown old_text") if new_text is None: - raise ValueError("Unknown next_text") + raise ValueError("Unknown new_text") fp = self._resolve(path) if not fp.exists(): diff --git a/tests/test_filesystem_tools.py b/tests/test_filesystem_tools.py index 76d0a51..ca6629e 100644 --- a/tests/test_filesystem_tools.py +++ b/tests/test_filesystem_tools.py @@ -77,6 +77,11 @@ class TestReadFileTool: assert "Error" in result assert "not found" in result + @pytest.mark.asyncio + async def test_missing_path_returns_clear_error(self, tool): + result = await tool.execute() + assert result == "Error reading file: Unknown path" + @pytest.mark.asyncio async def test_char_budget_trims(self, tool, tmp_path): """When the selected slice exceeds _MAX_CHARS the output is trimmed.""" @@ -200,6 +205,13 @@ class TestEditFileTool: assert "Error" in result assert "not found" in result + @pytest.mark.asyncio + async def test_missing_new_text_returns_clear_error(self, tool, tmp_path): + f = tmp_path / "a.py" + f.write_text("hello", encoding="utf-8") + result = await tool.execute(path=str(f), old_text="hello") + assert result == "Error editing file: Unknown new_text" + # --------------------------------------------------------------------------- # ListDirTool @@ -265,6 +277,11 @@ class TestListDirTool: assert "Error" in result assert "not found" in result + @pytest.mark.asyncio + async def test_missing_path_returns_clear_error(self, tool): + result = await tool.execute() + assert result == "Error listing directory: Unknown path" + # --------------------------------------------------------------------------- # Workspace restriction + extra_allowed_dirs