Skip to content

Commit 854a867

Browse files
authored
Merge pull request aden-hive#293 from yumosx/graph
feat(file_system_toolkits): add encoding and max_size params to view_file
2 parents 35ef467 + 89dbc63 commit 854a867

2 files changed

Lines changed: 70 additions & 5 deletions

File tree

tools/src/aden_tools/tools/file_system_toolkits/view_file/view_file.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import os
2+
23
from mcp.server.fastmcp import FastMCP
4+
35
from ..security import get_secure_path
46

7+
58
def register_tools(mcp: FastMCP) -> None:
69
"""Register file view tools with the MCP server."""
710

811
@mcp.tool()
9-
def view_file(path: str, workspace_id: str, agent_id: str, session_id: str) -> dict:
12+
def view_file(
13+
path: str,
14+
workspace_id: str,
15+
agent_id: str,
16+
session_id: str,
17+
encoding: str = "utf-8",
18+
max_size: int = 10 * 1024 * 1024,
19+
) -> dict:
1020
"""
1121
Purpose
1222
Read the content of a file within the session sandbox.
@@ -23,27 +33,39 @@ def view_file(path: str, workspace_id: str, agent_id: str, session_id: str) -> d
2333
2434
Args:
2535
path: The path to the file (relative to session root)
26-
workspace_id: The ID of the workspace
27-
agent_id: The ID of the agent
36+
workspace_id: The ID of workspace
37+
agent_id: The ID of agent
2838
session_id: The ID of the current session
39+
encoding: The encoding to use for reading the file (default: "utf-8")
40+
max_size: The maximum size of file content to return in bytes (default: 10MB)
2941
3042
Returns:
3143
Dict with file content and metadata, or error dict
3244
"""
3345
try:
46+
if max_size < 0:
47+
return {"error": f"max_size must be non-negative, got {max_size}"}
48+
3449
secure_path = get_secure_path(path, workspace_id, agent_id, session_id)
3550
if not os.path.exists(secure_path):
3651
return {"error": f"File not found at {path}"}
3752

38-
with open(secure_path, "r", encoding="utf-8") as f:
53+
if not os.path.isfile(secure_path):
54+
return {"error": f"Path is not a file: {path}"}
55+
56+
with open(secure_path, "r", encoding=encoding) as f:
3957
content = f.read()
4058

59+
if len(content.encode(encoding)) > max_size:
60+
content = content[:max_size]
61+
content += "\n\n[... Content truncated due to size limit ...]"
62+
4163
return {
4264
"success": True,
4365
"path": path,
4466
"content": content,
4567
"size_bytes": len(content.encode("utf-8")),
46-
"lines": len(content.splitlines())
68+
"lines": len(content.splitlines()),
4769
}
4870
except Exception as e:
4971
return {"error": f"Failed to read file: {str(e)}"}

tools/tests/tools/test_file_system_toolkits.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,49 @@ def test_view_nested_file(self, view_file_fn, mock_workspace, mock_secure_path,
117117
assert result["success"] is True
118118
assert result["content"] == "nested content"
119119

120+
def test_view_file_with_max_size_truncation(self, view_file_fn, mock_workspace, mock_secure_path, tmp_path):
121+
"""Viewing a file with max_size truncates content when exceeding limit."""
122+
test_file = tmp_path / "large.txt"
123+
content = "x" * 1000
124+
test_file.write_text(content)
125+
126+
result = view_file_fn(path="large.txt", max_size=100, **mock_workspace)
127+
128+
assert result["success"] is True
129+
assert len(result["content"]) <= 100 + len("\n\n[... Content truncated due to size limit ...]")
130+
assert "[... Content truncated due to size limit ...]" in result["content"]
131+
132+
def test_view_file_with_negative_max_size(self, view_file_fn, mock_workspace, mock_secure_path, tmp_path):
133+
"""Viewing a file with negative max_size returns error."""
134+
test_file = tmp_path / "test.txt"
135+
test_file.write_text("content")
136+
137+
result = view_file_fn(path="test.txt", max_size=-1, **mock_workspace)
138+
139+
assert "error" in result
140+
assert "max_size must be non-negative" in result["error"]
141+
142+
def test_view_file_with_custom_encoding(self, view_file_fn, mock_workspace, mock_secure_path, tmp_path):
143+
"""Viewing a file with custom encoding works correctly."""
144+
test_file = tmp_path / "encoded.txt"
145+
content = "Hello 世界"
146+
test_file.write_text(content, encoding="utf-8")
147+
148+
result = view_file_fn(path="encoded.txt", encoding="utf-8", **mock_workspace)
149+
150+
assert result["success"] is True
151+
assert result["content"] == content
152+
153+
def test_view_file_with_invalid_encoding(self, view_file_fn, mock_workspace, mock_secure_path, tmp_path):
154+
"""Viewing a file with invalid encoding returns error."""
155+
test_file = tmp_path / "test.txt"
156+
test_file.write_text("content")
157+
158+
result = view_file_fn(path="test.txt", encoding="invalid-encoding", **mock_workspace)
159+
160+
assert "error" in result
161+
assert "Failed to read file" in result["error"]
162+
120163

121164
class TestWriteToFileTool:
122165
"""Tests for write_to_file tool."""

0 commit comments

Comments
 (0)