diff --git a/astrbot/core/computer/file_read_utils.py b/astrbot/core/computer/file_read_utils.py index 5b5fd9fc8e..3e0432bcf5 100644 --- a/astrbot/core/computer/file_read_utils.py +++ b/astrbot/core/computer/file_read_utils.py @@ -652,6 +652,12 @@ async def read_file_tool_result( workspace_dir: str | None = None, ) -> ToolExecResult: if local_mode: + if Path(path).is_dir(): + return ( + f"Error: `{path}` is a directory, not a file. " + "Provide a file path instead, or use `astrbot_execute_shell` " + "to list directory contents." + ) probe_payload = await _probe_local_file(path) else: probe_payload = await _exec_python_json( diff --git a/tests/test_computer_fs_tools.py b/tests/test_computer_fs_tools.py index 11571665a5..61586aee93 100644 --- a/tests/test_computer_fs_tools.py +++ b/tests/test_computer_fs_tools.py @@ -450,6 +450,25 @@ async def test_file_read_tool_allows_partial_read_for_large_text_file( assert result == "".join(lines[1000:1003]) +@pytest.mark.asyncio +async def test_file_read_tool_reports_directory_clearly( + monkeypatch: pytest.MonkeyPatch, + tmp_path, +): + workspace = _setup_local_fs_tools(monkeypatch, tmp_path) + (workspace / "some_dir").mkdir() + + result = await fs_tools.FileReadTool().call( + _make_context(), + path="some_dir", + ) + + assert isinstance(result, str) + assert "is a directory" in result + assert "astrbot_execute_shell" in result + assert "Permission denied" not in result + + @pytest.mark.asyncio async def test_file_read_tool_returns_image_call_tool_result_for_images( monkeypatch: pytest.MonkeyPatch,