Files
Anton 052591281d Initial clean version - Agent Maxim
- Complete agent system with planning and execution
- Bridge API with FastAPI server
- WhatsApp-style mobile dashboard
- Enhanced web search with query improvement
- Security guards and policy checks
- Comprehensive documentation
2026-04-09 18:07:43 +03:00

70 lines
2.4 KiB
Python

"""File operation tools — write_file, read_file, finish."""
from __future__ import annotations
from pathlib import Path
from core.state import PlanStep, StepResult, StepStatus
# All file ops are confined to agent/workspace/
# parents: [0]=tools, [1]=runtime, [2]=agent → agent/workspace
WORKSPACE_ROOT: Path = Path(__file__).resolve().parents[2] / "workspace"
def write_file(step: PlanStep) -> StepResult:
"""Write content to a file inside agent/workspace/. Path traversal is blocked."""
rel_path: str = step.payload.get("path", "").strip()
content: str = step.payload.get("content", "")
if not rel_path:
return StepResult(step_id=step.step_id, status=StepStatus.FAILED, error="payload missing 'path'")
target = (WORKSPACE_ROOT / rel_path).resolve()
if not str(target).startswith(str(WORKSPACE_ROOT)):
return StepResult(
step_id=step.step_id,
status=StepStatus.FAILED,
error=f"Path traversal blocked: '{rel_path}' resolves outside workspace",
)
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(content, encoding="utf-8")
return StepResult(
step_id=step.step_id,
status=StepStatus.DONE,
output_text=f"Written {len(content)} chars to {rel_path}",
)
def read_file(step: PlanStep) -> StepResult:
"""Read a file from inside agent/workspace/. Path traversal is blocked."""
rel_path: str = step.payload.get("path", "").strip()
if not rel_path:
return StepResult(step_id=step.step_id, status=StepStatus.FAILED, error="payload missing 'path'")
target = (WORKSPACE_ROOT / rel_path).resolve()
if not str(target).startswith(str(WORKSPACE_ROOT)):
return StepResult(
step_id=step.step_id,
status=StepStatus.FAILED,
error=f"Path traversal blocked: '{rel_path}' resolves outside workspace",
)
if not target.exists():
return StepResult(
step_id=step.step_id,
status=StepStatus.FAILED,
error=f"File not found: {rel_path}",
)
content = target.read_text(encoding="utf-8")
return StepResult(step_id=step.step_id, status=StepStatus.DONE, output_text=content)
def finish_step(step: PlanStep) -> StepResult:
"""Terminal step — signals successful plan completion."""
return StepResult(step_id=step.step_id, status=StepStatus.DONE, output_text="Agent task complete.")