SPARKNET / src /tools /file_tools.py
MHamdan's picture
Initial commit: SPARKNET framework
a9dc537
raw
history blame
8.01 kB
"""
File Tools for SPARKNET
Tools for file system operations
"""
from pathlib import Path
from typing import Optional
from loguru import logger
from .base_tool import BaseTool, ToolResult
import json
class FileReaderTool(BaseTool):
"""Tool for reading files."""
def __init__(self):
super().__init__(
name="file_reader",
description="Read contents of a file from the file system",
)
self.add_parameter("file_path", "str", "Path to the file to read", required=True)
self.add_parameter("encoding", "str", "File encoding", required=False, default="utf-8")
async def execute(self, file_path: str, encoding: str = "utf-8", **kwargs) -> ToolResult:
"""
Read file contents.
Args:
file_path: Path to file
encoding: File encoding
Returns:
ToolResult with file contents
"""
try:
path = Path(file_path)
if not path.exists():
return ToolResult(
success=False,
output=None,
error=f"File not found: {file_path}",
)
if not path.is_file():
return ToolResult(
success=False,
output=None,
error=f"Path is not a file: {file_path}",
)
with open(path, "r", encoding=encoding) as f:
contents = f.read()
return ToolResult(
success=True,
output=contents,
metadata={
"file_path": str(path.absolute()),
"size_bytes": len(contents),
"encoding": encoding,
},
)
except Exception as e:
return ToolResult(
success=False,
output=None,
error=f"Error reading file: {str(e)}",
)
class FileWriterTool(BaseTool):
"""Tool for writing files."""
def __init__(self):
super().__init__(
name="file_writer",
description="Write contents to a file",
)
self.add_parameter("file_path", "str", "Path to the file to write", required=True)
self.add_parameter("content", "str", "Content to write to file", required=True)
self.add_parameter("encoding", "str", "File encoding", required=False, default="utf-8")
self.add_parameter("append", "bool", "Append to file instead of overwriting", required=False, default=False)
async def execute(
self,
file_path: str,
content: str,
encoding: str = "utf-8",
append: bool = False,
**kwargs,
) -> ToolResult:
"""
Write content to file.
Args:
file_path: Path to file
content: Content to write
encoding: File encoding
append: Whether to append
Returns:
ToolResult
"""
try:
path = Path(file_path)
# Create parent directories if needed
path.parent.mkdir(parents=True, exist_ok=True)
mode = "a" if append else "w"
with open(path, mode, encoding=encoding) as f:
f.write(content)
return ToolResult(
success=True,
output=f"Successfully wrote to {file_path}",
metadata={
"file_path": str(path.absolute()),
"bytes_written": len(content.encode(encoding)),
"mode": "append" if append else "write",
},
)
except Exception as e:
return ToolResult(
success=False,
output=None,
error=f"Error writing file: {str(e)}",
)
class FileSearchTool(BaseTool):
"""Tool for searching files."""
def __init__(self):
super().__init__(
name="file_search",
description="Search for files matching a pattern",
)
self.add_parameter("directory", "str", "Directory to search in", required=True)
self.add_parameter("pattern", "str", "File pattern to match (e.g., '*.txt')", required=True)
self.add_parameter("recursive", "bool", "Search recursively", required=False, default=True)
async def execute(
self,
directory: str,
pattern: str,
recursive: bool = True,
**kwargs,
) -> ToolResult:
"""
Search for files.
Args:
directory: Directory to search
pattern: File pattern
recursive: Search recursively
Returns:
ToolResult with list of matching files
"""
try:
path = Path(directory)
if not path.exists():
return ToolResult(
success=False,
output=None,
error=f"Directory not found: {directory}",
)
if recursive:
files = list(path.rglob(pattern))
else:
files = list(path.glob(pattern))
file_paths = [str(f.absolute()) for f in files if f.is_file()]
return ToolResult(
success=True,
output=file_paths,
metadata={
"directory": str(path.absolute()),
"pattern": pattern,
"count": len(file_paths),
"recursive": recursive,
},
)
except Exception as e:
return ToolResult(
success=False,
output=None,
error=f"Error searching files: {str(e)}",
)
class DirectoryListTool(BaseTool):
"""Tool for listing directory contents."""
def __init__(self):
super().__init__(
name="directory_list",
description="List contents of a directory",
)
self.add_parameter("directory", "str", "Directory to list", required=True)
self.add_parameter("include_hidden", "bool", "Include hidden files", required=False, default=False)
async def execute(
self,
directory: str,
include_hidden: bool = False,
**kwargs,
) -> ToolResult:
"""
List directory contents.
Args:
directory: Directory to list
include_hidden: Include hidden files
Returns:
ToolResult with directory contents
"""
try:
path = Path(directory)
if not path.exists():
return ToolResult(
success=False,
output=None,
error=f"Directory not found: {directory}",
)
if not path.is_dir():
return ToolResult(
success=False,
output=None,
error=f"Path is not a directory: {directory}",
)
items = []
for item in path.iterdir():
if not include_hidden and item.name.startswith("."):
continue
items.append({
"name": item.name,
"path": str(item.absolute()),
"type": "directory" if item.is_dir() else "file",
"size": item.stat().st_size if item.is_file() else None,
})
return ToolResult(
success=True,
output=items,
metadata={
"directory": str(path.absolute()),
"count": len(items),
},
)
except Exception as e:
return ToolResult(
success=False,
output=None,
error=f"Error listing directory: {str(e)}",
)