110 lines
3.3 KiB
Python
110 lines
3.3 KiB
Python
# agent/commands.py
|
|
from dataclasses import dataclass
|
|
from typing import Callable, Dict, List
|
|
import os
|
|
|
|
from .memory import Memory
|
|
|
|
@dataclass
|
|
class Command:
|
|
name: str
|
|
description: str
|
|
needs_project_root: bool
|
|
handler: Callable[[List[str], Memory], str]
|
|
|
|
|
|
class CommandRegistry:
|
|
def __init__(self, memory: Memory):
|
|
self.memory = memory
|
|
self.commands: Dict[str, Command] = {}
|
|
self._register_defaults()
|
|
|
|
def _register_defaults(self):
|
|
# /setroot <path>
|
|
def cmd_setroot(args: List[str], mem: Memory) -> str:
|
|
if not args:
|
|
return "Usage: `/setroot <chemin_absolu_vers_projet>`"
|
|
|
|
path = args[0]
|
|
if not os.path.isdir(path):
|
|
return f"Le chemin `{path}` n'existe pas ou n'est pas un dossier."
|
|
|
|
mem.set_project_root(path)
|
|
return f"✅ Chemin du projet défini sur `{path}`."
|
|
|
|
self.register(
|
|
Command(
|
|
name="setroot",
|
|
description="Définit le chemin racine du projet.",
|
|
needs_project_root=False,
|
|
handler=cmd_setroot,
|
|
)
|
|
)
|
|
|
|
# /scan [rel_path]
|
|
def cmd_scan(args: List[str], mem: Memory) -> str:
|
|
root = mem.get_project_root()
|
|
rel = args[0] if args else "."
|
|
full = os.path.abspath(os.path.join(root, rel))
|
|
|
|
# sécurité basique
|
|
if not full.startswith(os.path.abspath(root)):
|
|
return "❌ Tu ne peux pas sortir du project_root."
|
|
|
|
if not os.path.isdir(full):
|
|
return f"❌ `{rel}` n'est pas un dossier dans le projet."
|
|
|
|
entries = sorted(os.listdir(full))
|
|
if not entries:
|
|
return f"📁 `{rel}` est vide."
|
|
|
|
lines = [f"📁 Scan de `{rel}` (dans `{root}`):"]
|
|
for e in entries:
|
|
p = os.path.join(full, e)
|
|
if os.path.isdir(p):
|
|
lines.append(f" 📂 {e}/")
|
|
else:
|
|
lines.append(f" 📄 {e}")
|
|
return "\n".join(lines)
|
|
|
|
self.register(
|
|
Command(
|
|
name="scan",
|
|
description="Liste les fichiers/dossiers du projet.",
|
|
needs_project_root=True,
|
|
handler=cmd_scan,
|
|
)
|
|
)
|
|
|
|
def register(self, cmd: Command):
|
|
self.commands[cmd.name] = cmd
|
|
|
|
def handle(self, raw_input: str) -> str:
|
|
"""
|
|
Parse et exécute une commande du type `/scan src` ou `/setroot /chemin`.
|
|
"""
|
|
text = raw_input.strip()
|
|
if not text.startswith("/"):
|
|
return "Internal error: not a command."
|
|
|
|
parts = text[1:].split()
|
|
if not parts:
|
|
return "Commande vide."
|
|
|
|
name = parts[0]
|
|
args = parts[1:]
|
|
|
|
cmd = self.commands.get(name)
|
|
if not cmd:
|
|
return f"Commande inconnue: `/{name}`.\nCommandes disponibles: {', '.join('/'+n for n in self.commands.keys())}"
|
|
|
|
# dépendance project_root
|
|
if cmd.needs_project_root and not self.memory.get_project_root():
|
|
return (
|
|
"❗ Aucun `project_root` défini pour l'instant.\n"
|
|
"Commence par le définir avec:\n"
|
|
"`/setroot /chemin/vers/ton/projet`"
|
|
)
|
|
|
|
return cmd.handler(args, self.memory)
|