selfevolveagent / evoagentx /tools /storage_file.py
iLOVE2D's picture
Upload 2846 files
5374a2d verified
from .tool import Tool, Toolkit
from .storage_handler import FileStorageHandler, LocalStorageHandler
from typing import Dict, Any, List, Optional
from ..core.logging import logger
class SaveTool(Tool):
name: str = "save"
description: str = "Save content to a file with automatic format detection and support for various file types including documents, data files, images, videos, and sound files"
inputs: Dict[str, Dict[str, str]] = {
"file_path": {
"type": "string",
"description": "Path to the file to save"
},
"content": {
"type": "string",
"description": "Content to save to the file (string for text, JSON string for structured data, or Python object for JSON files)"
},
"encoding": {
"type": "string",
"description": "Text encoding for text files (default: utf-8)"
},
"indent": {
"type": "integer",
"description": "Indentation for JSON files (default: 2)"
},
"sheet_name": {
"type": "string",
"description": "Sheet name for Excel files (default: Sheet1)"
},
"root_tag": {
"type": "string",
"description": "Root tag for XML files (default: root)"
}
}
required: Optional[List[str]] = ["file_path", "content"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
@classmethod
def validate_attributes(cls):
# Skip validation for this tool to allow flexible content types
# This allows us to accept Python objects while maintaining JSON schema compatibility
pass
def __call__(self, file_path: str, content: Any, encoding: str = "utf-8", indent: int = 2,
sheet_name: str = "Sheet1", root_tag: str = "root") -> Dict[str, Any]:
"""
Save content to a file with automatic format detection.
Args:
file_path: Path to the file to save
content: Content to save to the file (string for text, dict/list for JSON, list for CSV/Excel)
encoding: Text encoding for text files
indent: Indentation for JSON files
sheet_name: Sheet name for Excel files
root_tag: Root tag for XML files
Returns:
Dictionary containing the save operation result
"""
try:
# Parse content based on file type
file_extension = self.storage_handler.get_file_type(file_path)
parsed_content = content
# Handle JSON content - convert Python objects to Python objects for StorageToolkit
if file_extension in ['.json', '.yaml', '.yml', '.xml']:
# If content is already a string, try to parse it as JSON
if isinstance(content, str):
try:
import json
parsed_content = json.loads(content)
except json.JSONDecodeError:
# If not valid JSON, use as string
parsed_content = content
else:
# If content is a Python object, pass it directly to StorageToolkit
# StorageToolkit will handle the JSON serialization
parsed_content = content
# Handle CSV content
elif file_extension == '.csv':
# If content is already a list, use it directly
if isinstance(content, list):
parsed_content = content
else:
# Try to parse as JSON first (for structured data)
try:
import json
parsed_content = json.loads(content)
if not isinstance(parsed_content, list):
# If JSON parsing succeeded but it's not a list, treat as raw CSV
parsed_content = content
except json.JSONDecodeError:
# If JSON parsing fails, treat as raw CSV string
parsed_content = content
# Handle Excel content
elif file_extension == '.xlsx':
# If content is already a list, use it directly
if isinstance(content, list):
parsed_content = content
else:
# If content is a string, try to parse it as JSON
try:
import json
parsed_content = json.loads(content)
if not isinstance(parsed_content, list):
return {"success": False, "error": "Excel content must be a list of lists"}
except json.JSONDecodeError:
return {"success": False, "error": "Excel content must be valid JSON array"}
kwargs = {
"encoding": encoding,
"indent": indent,
"sheet_name": sheet_name,
"root_tag": root_tag
}
result = self.storage_handler.save(file_path, parsed_content, **kwargs)
return result
except Exception as e:
logger.error(f"Error in SaveTool: {str(e)}")
return {"success": False, "error": str(e), "file_path": file_path}
class ReadTool(Tool):
name: str = "read"
description: str = "Read content from a file with automatic format detection and support for various file types including documents, data files, images, videos, and sound files"
inputs: Dict[str, Dict[str, str]] = {
"file_path": {
"type": "string",
"description": "Path to the file to read"
},
"encoding": {
"type": "string",
"description": "Text encoding for text files (default: utf-8)"
},
"sheet_name": {
"type": "string",
"description": "Sheet name for Excel files (optional)"
},
"head": {
"type": "integer",
"description": "Number of characters to return from the beginning of the file (default: 0 means return everything)"
}
}
required: Optional[List[str]] = ["file_path"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, file_path: str, encoding: str = "utf-8", sheet_name: str = None, head: int = 0) -> Dict[str, Any]:
"""
Read content from a file with automatic format detection.
Args:
file_path: Path to the file to read
encoding: Text encoding for text files
sheet_name: Sheet name for Excel files
head: Number of characters to return from the beginning
Returns:
Dictionary containing the read operation result
"""
try:
kwargs = {
"encoding": encoding,
"sheet_name": sheet_name,
"head": head
}
result = self.storage_handler.read(file_path, **kwargs)
return result
except Exception as e:
logger.error(f"Error in ReadTool: {str(e)}")
return {"success": False, "error": str(e), "file_path": file_path}
class AppendTool(Tool):
name: str = "append"
description: str = "Append content to a file (only for supported formats: txt, json, csv, yaml, pickle, xlsx)"
inputs: Dict[str, Dict[str, str]] = {
"file_path": {
"type": "string",
"description": "Path to the file to append to"
},
"content": {
"type": "string",
"description": "Content to append to the file (can be JSON string for structured data)"
},
"encoding": {
"type": "string",
"description": "Text encoding for text files (default: utf-8)"
},
"sheet_name": {
"type": "string",
"description": "Sheet name for Excel files (optional)"
}
}
required: Optional[List[str]] = ["file_path", "content"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, file_path: str, content: str, encoding: str = "utf-8", sheet_name: str = None) -> Dict[str, Any]:
"""
Append content to a file with automatic format detection.
Args:
file_path: Path to the file to append to
content: Content to append to the file
encoding: Text encoding for text files
sheet_name: Sheet name for Excel files
Returns:
Dictionary containing the append operation result
"""
try:
# Parse content based on file type
file_extension = self.storage_handler.get_file_type(file_path)
parsed_content = content
# Try to parse JSON content for appropriate file types
if file_extension in ['.json', '.yaml', '.yml']:
try:
import json
parsed_content = json.loads(content)
except json.JSONDecodeError:
# If not valid JSON, use as string
parsed_content = content
# Handle CSV content
elif file_extension == '.csv':
try:
import json
parsed_content = json.loads(content)
if not isinstance(parsed_content, list):
# If JSON parsing succeeded but it's not a list, treat as raw CSV
parsed_content = content
except json.JSONDecodeError:
# If JSON parsing fails, treat as raw CSV string
parsed_content = content
# Handle Excel content
elif file_extension == '.xlsx':
try:
import json
parsed_content = json.loads(content)
if not isinstance(parsed_content, list):
return {"success": False, "error": "Excel content must be a list of lists"}
except json.JSONDecodeError:
return {"success": False, "error": "Excel content must be valid JSON array"}
kwargs = {
"encoding": encoding,
"sheet_name": sheet_name
}
result = self.storage_handler.append(file_path, parsed_content, **kwargs)
return result
except Exception as e:
logger.error(f"Error in AppendTool: {str(e)}")
return {"success": False, "error": str(e), "file_path": file_path}
class DeleteTool(Tool):
name: str = "delete"
description: str = "Delete a file or directory"
inputs: Dict[str, Dict[str, str]] = {
"path": {
"type": "string",
"description": "Path to the file or directory to delete"
}
}
required: Optional[List[str]] = ["path"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, path: str) -> Dict[str, Any]:
"""
Delete a file or directory.
Args:
path: Path to the file or directory to delete
Returns:
Dictionary containing the delete operation result
"""
try:
result = self.storage_handler.delete(path)
return result
except Exception as e:
logger.error(f"Error in DeleteTool: {str(e)}")
return {"success": False, "error": str(e), "path": path}
class MoveTool(Tool):
name: str = "move"
description: str = "Move or rename a file or directory"
inputs: Dict[str, Dict[str, str]] = {
"source": {
"type": "string",
"description": "Source path of the file or directory to move"
},
"destination": {
"type": "string",
"description": "Destination path where to move the file or directory"
}
}
required: Optional[List[str]] = ["source", "destination"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, source: str, destination: str) -> Dict[str, Any]:
"""
Move or rename a file or directory.
Args:
source: Source path of the file or directory to move
destination: Destination path where to move the file or directory
Returns:
Dictionary containing the move operation result
"""
try:
result = self.storage_handler.move(source, destination)
return result
except Exception as e:
logger.error(f"Error in MoveTool: {str(e)}")
return {"success": False, "error": str(e), "source": source, "destination": destination}
class CopyTool(Tool):
name: str = "copy"
description: str = "Copy a file"
inputs: Dict[str, Dict[str, str]] = {
"source": {
"type": "string",
"description": "Source path of the file to copy"
},
"destination": {
"type": "string",
"description": "Destination path where to copy the file"
}
}
required: Optional[List[str]] = ["source", "destination"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, source: str, destination: str) -> Dict[str, Any]:
"""
Copy a file.
Args:
source: Source path of the file to copy
destination: Destination path where to copy the file
Returns:
Dictionary containing the copy operation result
"""
try:
result = self.storage_handler.copy(source, destination)
return result
except Exception as e:
logger.error(f"Error in CopyTool: {str(e)}")
return {"success": False, "error": str(e), "source": source, "destination": destination}
class CreateDirectoryTool(Tool):
name: str = "create_directory"
description: str = "Create a directory"
inputs: Dict[str, Dict[str, str]] = {
"path": {
"type": "string",
"description": "Path of the directory to create"
}
}
required: Optional[List[str]] = ["path"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, path: str) -> Dict[str, Any]:
"""
Create a directory.
Args:
path: Path of the directory to create
Returns:
Dictionary containing the create directory operation result
"""
try:
result = self.storage_handler.create_directory(path)
return result
except Exception as e:
logger.error(f"Error in CreateDirectoryTool: {str(e)}")
return {"success": False, "error": str(e), "path": path}
class ListFileTool(Tool):
name: str = "list_files"
description: str = "List files and directories in a path with structured information"
inputs: Dict[str, Dict[str, str]] = {
"path": {
"type": "string",
"description": "Path to list files from (default: current working directory)"
},
"max_depth": {
"type": "integer",
"description": "Maximum depth to traverse (default: 3)"
},
"include_hidden": {
"type": "boolean",
"description": "Include hidden files and directories (default: false)"
}
}
required: Optional[List[str]] = []
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, path: str = None, max_depth: int = 3, include_hidden: bool = False) -> Dict[str, Any]:
"""
List files and directories in a path.
Args:
path: Path to list files from
max_depth: Maximum depth to traverse
include_hidden: Include hidden files and directories
Returns:
Dictionary containing the list operation result
"""
try:
result = self.storage_handler.list(path, max_depth=max_depth, include_hidden=include_hidden)
return result
except Exception as e:
logger.error(f"Error in ListFileTool: {str(e)}")
return {"success": False, "error": str(e), "path": path}
class ExistsTool(Tool):
name: str = "exists"
description: str = "Check if a file or directory exists"
inputs: Dict[str, Dict[str, str]] = {
"path": {
"type": "string",
"description": "Path to check for existence"
}
}
required: Optional[List[str]] = ["path"]
def __init__(self, storage_handler: FileStorageHandler = None):
super().__init__()
self.storage_handler = storage_handler or LocalStorageHandler()
def __call__(self, path: str) -> Dict[str, Any]:
"""
Check if a file or directory exists.
Args:
path: Path to check for existence
Returns:
Dictionary containing the existence check result
"""
try:
exists = self.storage_handler.exists(path)
return {
"success": True,
"path": path,
"exists": exists
}
except Exception as e:
logger.error(f"Error in ExistsTool: {str(e)}")
return {"success": False, "error": str(e), "path": path}
class StorageToolkit(Toolkit):
"""
Comprehensive storage toolkit with local filesystem operations.
Provides tools for reading, writing, appending, deleting, moving, copying files,
creating directories, and listing files with support for various file formats.
"""
def __init__(self, name: str = "StorageToolkit", base_path: str = "./workplace/storage", storage_handler: LocalStorageHandler = None):
"""
Initialize the storage toolkit.
Args:
name: Name of the toolkit
base_path: Base directory for storage operations (default: ./workplace/storage)
storage_handler: Storage handler instance (defaults to LocalStorageHandler)
"""
if not storage_handler:
storage_handler = LocalStorageHandler(base_path=base_path)
# Create tools with the storage handler
tools = [
SaveTool(storage_handler=storage_handler),
ReadTool(storage_handler=storage_handler),
AppendTool(storage_handler=storage_handler),
DeleteTool(storage_handler=storage_handler),
MoveTool(storage_handler=storage_handler),
CopyTool(storage_handler=storage_handler),
CreateDirectoryTool(storage_handler=storage_handler),
ListFileTool(storage_handler=storage_handler),
ExistsTool(storage_handler=storage_handler)
]
super().__init__(name=name, tools=tools)
self.storage_handler = storage_handler