| from __future__ import annotations |
| import importlib |
| from typing import Awaitable, Callable, Dict, Tuple |
| from utils.audit import audit_event |
|
|
| Handler = Callable[[str, str], Awaitable[str]] |
|
|
| |
| ROUTE_MAP: Dict[str, Tuple[str, str]] = { |
| "/read": ("tools.fs", "handle_read"), |
| |
|
|
| |
| "/self": ("tools.selfmod", "handle_self_menu"), |
| "/self:analyze": ("tools.selfmod", "handle_self_analyze"), |
| "/self:plan": ("tools.selfmod", "handle_self_plan"), |
| "/self:apply": ("tools.selfmod", "handle_self_apply"), |
| "/self:status": ("tools.selfmod", "handle_self_status"), |
| } |
|
|
| |
| _DYNAMIC_ROUTES: Dict[str, Handler] = {} |
| _HELP: Dict[str, str] = {} |
|
|
| def register(cmd: str, handler: Handler) -> None: |
| _DYNAMIC_ROUTES[cmd.lower()] = handler |
|
|
| def set_help(cmd: str, text: str) -> None: |
| _HELP[cmd.lower()] = text |
|
|
| async def dispatch(message_text: str, block: str) -> str: |
| parts = (message_text or "").split(None, 1) |
| if not parts: |
| return "❓ Vazio. Use /help." |
|
|
| cmd = parts[0].lower() |
| args = parts[1] if len(parts) > 1 else "" |
|
|
| |
| if cmd in _DYNAMIC_ROUTES: |
| try: |
| audit_event("dispatch", {"cmd": cmd, "args_preview": args[:200]}) |
| except Exception: |
| pass |
| try: |
| return await _DYNAMIC_ROUTES[cmd](args, block) |
| except Exception as e: |
| return f"💥 Erro executando `{cmd}`: {e}" |
|
|
| |
| if cmd not in ROUTE_MAP: |
| return f"❌ Comando não reconhecido: {cmd}\nUse /help." |
|
|
| mod_name, fn_name = ROUTE_MAP[cmd] |
| try: |
| mod = importlib.import_module(mod_name) |
| handler: Handler = getattr(mod, fn_name) |
| except Exception as e: |
| return f"💥 Erro ao carregar handler `{mod_name}.{fn_name}`: {e}" |
|
|
| try: |
| audit_event("dispatch", {"cmd": cmd, "args_preview": args[:200]}) |
| except Exception: |
| pass |
|
|
| try: |
| return await handler(args, block) |
| except Exception as e: |
| return f"💥 Erro executando `{cmd}`: {e}" |
|
|
| |
| class _Registry: |
| register = staticmethod(register) |
| set_help = staticmethod(set_help) |
| async def dispatch(self, message_text: str, block: str) -> str: |
| return await dispatch(message_text, block) |
|
|
| registry = _Registry() |
| __all__ = ["dispatch", "registry", "register", "set_help"] |
|
|