Compare commits

...

2 Commits

Author SHA1 Message Date
Haoran Xu
41f8960302 fix: astrbot_file_read_tool returns clear error for directory path instead of misleading Permission denied (#9088)
When LLM passes a directory path to astrbot_file_read_tool, the tool previously
returned Error: [Errno 13] Permission denied, misleading the LLM into thinking
it was a permissions issue. The real cause: _probe_local_file() calls open('rb')
on the path, which fails on directories with Errno 13 on Windows. This is caught
by except PermissionError and displayed as-is.

Fix: Add os.path.isdir() check in FileReadTool.call() before any file I/O, at
the earliest safe point after path normalization and permission validation.
Returns a clear message: '<path> is a directory, not a file. Use a file path
instead, or use astrbot_execute_shell to list directory contents.'

Changes:
- astrbot/core/tools/computer_tools/fs.py: add isdir guard
- tests/test_computer_fs_tools.py: add test_file_read_tool_rejects_directory_with_clear_message
2026-06-30 20:39:50 +08:00
Soulter
7831c68660 chore: bump version to 4.26.3 2026-06-30 20:10:58 +08:00
5 changed files with 58 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
import logging
__version__ = "4.26.2"
__version__ = "4.26.3"
logger = logging.getLogger("astrbot")

View File

@@ -304,6 +304,11 @@ class FileReadTool(FunctionTool):
)
if not normalized_path:
raise ValueError("`path` must be a non-empty string.")
if local_env and os.path.isdir(normalized_path):
return (
f"Error: '{normalized_path}' is a directory, not a file. "
"Use a file path instead, or use 'astrbot_execute_shell' to list directory contents."
)
offset, limit = self._validate_read_window(offset, limit)
sb = await get_booter(
context.context.context,

31
changelogs/v4.26.3.md Normal file
View File

@@ -0,0 +1,31 @@
## What's Changed
### Features
- Support installing local plugins (#8448)
### Fixes
- Preserve fallback models for future tasks (#9054)
- Validate plugin install sources (#9061)
- Paginate knowledge base dashboard lists (#9055)
### Styles
- Standardize dashboard dialog styling (#9062)
## 中文翻译
### 功能
- 支持安装本地插件 (#8448)
### 修复
- 保留未来任务可用的 fallback models (#9054)
- 校验插件安装来源 (#9061)
- 为知识库仪表盘列表增加分页 (#9055)
### 样式
- 统一仪表盘对话框样式 (#9062)

View File

@@ -1,6 +1,6 @@
[project]
name = "AstrBot"
version = "4.26.2"
version = "4.26.3"
description = "Easy-to-use multi-platform LLM chatbot and development framework"
readme = "README.md"
license = { text = "AGPL-3.0-or-later" }

View File

@@ -620,3 +620,23 @@ async def test_grep_tool_applies_result_limit(
assert "match-2" in result
assert "match-3" not in result
assert "[Truncated to first 2 result groups.]" in result
@pytest.mark.asyncio
async def test_file_read_tool_rejects_directory_with_clear_message(
monkeypatch: pytest.MonkeyPatch,
tmp_path,
):
"""FileReadTool should return a helpful message when given a directory path."""
workspace = _setup_local_fs_tools(monkeypatch, tmp_path)
subdir = workspace / "my-directory"
subdir.mkdir()
result = await fs_tools.FileReadTool().call(
_make_context(),
path="my-directory",
)
assert "is a directory, not a file" in result
assert "my-directory" in result
assert "'astrbot_execute_shell'" in result