read and write tools, moved schemas to tool/__init__
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# tools/__init__.py
|
||||
from tools.files import READ_FILE_SCHEMA, WRITE_FILE_SCHEMA, read_file, write_file
|
||||
|
||||
from tools.bash import BASH_SCHEMA, bash
|
||||
|
||||
__all__ = [
|
||||
"bash",
|
||||
"read_file",
|
||||
"write_file",
|
||||
"TOOL_SCHEMAS",
|
||||
]
|
||||
|
||||
TOOL_SCHEMAS = [
|
||||
BASH_SCHEMA,
|
||||
READ_FILE_SCHEMA,
|
||||
WRITE_FILE_SCHEMA,
|
||||
]
|
||||
@@ -25,3 +25,19 @@ async def bash(command: str, sandbox=None) -> str:
|
||||
|
||||
except Exception as e:
|
||||
return f"Error: Unexpected failure: {e}"
|
||||
|
||||
|
||||
BASH_SCHEMA = {
|
||||
"name": "bash",
|
||||
"description": "Execute a bash command in the isolated sandbox environment. Use this to run shell commands, install packages, run scripts, etc.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The bash command to execute (e.g., 'ls -la', 'python script.py', 'pip install requests')",
|
||||
}
|
||||
},
|
||||
"required": ["command"],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
async def read_file(filepath: str, sandbox=None) -> str:
|
||||
"""Read a file from workspace."""
|
||||
if sandbox is None:
|
||||
return "Error: No sandbox available"
|
||||
|
||||
try:
|
||||
result = await asyncio.to_thread(sandbox.run, f"cat {filepath}")
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"Error reading file: {e}"
|
||||
|
||||
|
||||
async def write_file(filepath: str, content: str, sandbox=None) -> str:
|
||||
"""Write content to a file."""
|
||||
if sandbox is None:
|
||||
return "Error: No sandbox available"
|
||||
|
||||
# Validate path
|
||||
if filepath.startswith("/") or ".." in filepath:
|
||||
return f"Error: Invalid path '{filepath}'. Use relative paths within workspace."
|
||||
|
||||
try:
|
||||
# Escape content for shell
|
||||
escaped = content.replace("'", "'\\''")
|
||||
|
||||
# Create parent dirs if needed
|
||||
parent = str(Path(filepath).parent)
|
||||
if parent and parent != ".":
|
||||
await asyncio.to_thread(sandbox.run, f"mkdir -p {parent}")
|
||||
|
||||
# Write file
|
||||
await asyncio.to_thread(
|
||||
sandbox.run, f"cat > {filepath} << 'EOF'\n{content}\nEOF"
|
||||
)
|
||||
|
||||
return f"✓ Wrote {filepath}"
|
||||
except Exception as e:
|
||||
return f"Error writing file: {e}"
|
||||
|
||||
|
||||
# Schemas
|
||||
READ_FILE_SCHEMA = {
|
||||
"name": "read_file",
|
||||
"description": "Read the contents of a file from the workspace",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"filepath": {
|
||||
"type": "string",
|
||||
"description": "Path to file relative to workspace (e.g., 'app.py', 'src/utils.py')",
|
||||
}
|
||||
},
|
||||
"required": ["filepath"],
|
||||
},
|
||||
}
|
||||
|
||||
WRITE_FILE_SCHEMA = {
|
||||
"name": "write_file",
|
||||
"description": "Write content to a file in the workspace. Creates parent directories if needed.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"filepath": {
|
||||
"type": "string",
|
||||
"description": "Path to file relative to workspace (e.g., 'app.py', 'data/config.json')",
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Content to write to the file",
|
||||
},
|
||||
},
|
||||
"required": ["filepath", "content"],
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user