File size: 3,803 Bytes
5dc5419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""FileWriteTool - Write content to files for Stack 2.9"""

import os
from datetime import datetime
from pathlib import Path

from .base import BaseTool, ToolResult
from .registry import tool_registry

BACKUP_DIR = Path.home() / ".stack-2.9" / "backups"


class FileWriteTool(BaseTool):
    """Write content to a file."""

    name = "file_write"
    description = "Write content to a file"

    input_schema = {
        "type": "object",
        "properties": {
            "path": {"type": "string", "description": "File path to write"},
            "content": {"type": "string", "description": "Content to write"},
            "append": {"type": "boolean", "default": False, "description": "Append instead of overwrite"},
            "create_backup": {"type": "boolean", "default": True, "description": "Create backup if file exists"}
        },
        "required": ["path", "content"]
    }

    async def execute(self, path: str, content: str, append: bool = False, create_backup: bool = True) -> ToolResult:
        """Write file."""
        file_path = Path(path)

        # Create parent directories if needed
        file_path.parent.mkdir(parents=True, exist_ok=True)

        backup_path = None

        # Backup existing file
        if file_path.exists() and create_backup and not append:
            BACKUP_DIR.mkdir(parents=True, exist_ok=True)
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            backup_name = f"{file_path.name}.{timestamp}.bak"
            backup_path = BACKUP_DIR / backup_name
            backup_path.write_text(file_path.read_text())

        # Write content
        try:
            if append:
                existing = file_path.read_text() if file_path.exists() else ""
                file_path.write_text(existing + content)
            else:
                file_path.write_text(content)
        except Exception as e:
            return ToolResult(success=False, error=f"Cannot write file: {e}")

        return ToolResult(success=True, data={
            "path": str(file_path),
            "bytes_written": len(content),
            "backup": str(backup_path) if backup_path else None,
            "mode": "append" if append else "overwrite"
        })


class FileDeleteTool(BaseTool):
    """Delete a file."""

    name = "file_delete"
    description = "Delete a file"

    input_schema = {
        "type": "object",
        "properties": {
            "path": {"type": "string", "description": "File path to delete"},
            "create_backup": {"type": "boolean", "default": True}
        },
        "required": ["path"]
    }

    async def execute(self, path: str, create_backup: bool = True) -> ToolResult:
        """Delete file."""
        file_path = Path(path)

        if not file_path.exists():
            return ToolResult(success=False, error=f"File not found: {path}")

        if not file_path.is_file():
            return ToolResult(success=False, error=f"Not a file: {path}")

        backup_path = None

        # Backup before delete
        if create_backup:
            BACKUP_DIR.mkdir(parents=True, exist_ok=True)
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            backup_name = f"{file_path.name}.{timestamp}.deleted.bak"
            backup_path = BACKUP_DIR / backup_name
            backup_path.write_text(file_path.read_text())

        try:
            file_path.unlink()
        except Exception as e:
            return ToolResult(success=False, error=f"Cannot delete file: {e}")

        return ToolResult(success=True, data={
            "path": str(file_path),
            "deleted": True,
            "backup": str(backup_path) if backup_path else None
        })


# Register tools
tool_registry.register(FileWriteTool())
tool_registry.register(FileDeleteTool())