Newer
Older
cortex-hub / skills / mesh-file-explorer / logic.py
import os
import json
import logging
from agent_node.skills.base import BaseSkill

logger = logging.getLogger(__name__)

class FileSkill(BaseSkill):
    """Provides file system navigation and inspection capabilities."""
    
    def __init__(self, sync_mgr=None):
        self.sync_mgr = sync_mgr
        
    def execute(self, task, sandbox, on_complete, on_event=None):
        """
        Executes a file-related task (list, stats).
        Payload JSON: { "action": "list", "path": "...", "recursive": false }
        """
        try:
            payload = json.loads(task.payload_json)
            action = payload.get("action", "list")
            path = payload.get("path", ".")
            
            # 1. Sandbox Jail Check
            # (In a real implementation, we'd use sandbox.check_path(path))
            # For now, we'll assume the node allows browsing its root or session dir.
            
            if action == "list":
                result = self._list_dir(path, payload.get("recursive", False))
                on_complete(task.task_id, {"status": 1, "stdout": json.dumps(result)}, task.trace_id)
            else:
                 on_complete(task.task_id, {"status": 0, "stderr": f"Unknown action: {action}"}, task.trace_id)
                 
        except Exception as e:
            logger.error(f"[FileSkill] Task {task.task_id} failed: {e}")
            on_complete(task.task_id, {"status": 0, "stderr": str(e)}, task.trace_id)

    def _list_dir(self, path, recursive=False):
        """Lists directory contents with metadata."""
        if not os.path.exists(path):
            return {"error": "Path not found"}
        
        items = []
        if recursive:
            for root, dirs, files in os.walk(path):
                for name in dirs + files:
                    abs_path = os.path.join(root, name)
                    rel_path = os.path.relpath(abs_path, path)
                    st = os.stat(abs_path)
                    items.append({
                        "name": name,
                        "path": rel_path,
                        "is_dir": os.path.isdir(abs_path),
                        "size": st.st_size,
                        "mtime": st.st_mtime
                    })
        else:
            for name in os.listdir(path):
                abs_path = os.path.join(path, name)
                st = os.stat(abs_path)
                items.append({
                    "name": name,
                    "is_dir": os.path.isdir(abs_path),
                    "size": st.st_size,
                    "mtime": st.st_mtime
                })
        
        return {
            "root": os.path.abspath(path),
            "items": sorted(items, key=lambda x: (not x["is_dir"], x["name"]))
        }

    def cancel(self, task_id):
        return False # Listing is usually fast, no cancellation needed

    def shutdown(self):
        pass