diff --git a/bot/commands.py b/bot/commands.py index e48e2d9..dd406e4 100644 --- a/bot/commands.py +++ b/bot/commands.py @@ -44,14 +44,18 @@ def _perm_label(mode: str) -> str: def parse_command(text: str) -> Optional[Tuple[str, str]]: """ - Parse a slash command from text. + Parse a bot command from text. Returns (command, args) or None if not a command. + Commands must start with COMMAND_PREFIX (default "//"). """ + from config import COMMAND_PREFIX text = text.strip() - if not text.startswith("/"): + if not text.startswith(COMMAND_PREFIX): return None - parts = text.split(None, 1) - cmd = parts[0].lower() + # Strip the prefix, then split into command word and args + body = text[len(COMMAND_PREFIX):] + parts = body.split(None, 1) + cmd = COMMAND_PREFIX + parts[0].lower() args = parts[1] if len(parts) > 1 else "" return (cmd, args) @@ -68,38 +72,39 @@ async def handle_command(user_id: str, text: str) -> Optional[str]: logger.info("Command: %s args=%r user=...%s", cmd, args[:50], user_id[-8:]) # In ROUTER_MODE, only handle router-specific commands locally. - # Session commands (/status, /new, /close, etc.) fall through to node forwarding. - from config import ROUTER_MODE - if ROUTER_MODE and cmd not in ("/nodes", "/node", "/help", "/h", "/?"): + # Session commands (//status, //new, //close, etc.) fall through to node forwarding. + from config import ROUTER_MODE, COMMAND_PREFIX + P = COMMAND_PREFIX + if ROUTER_MODE and cmd not in (P+"nodes", P+"node", P+"help", P+"h", P+"?"): return None set_current_user(user_id) - if cmd in ("/new", "/n"): + if cmd in (P+"new", P+"n"): return await _cmd_new(user_id, args) - elif cmd in ("/status", "/list", "/ls", "/l"): + elif cmd in (P+"status", P+"list", P+"ls", P+"l"): return await _cmd_status(user_id) - elif cmd in ("/close", "/c"): + elif cmd in (P+"close", P+"c"): return await _cmd_close(user_id, args) - elif cmd in ("/switch", "/s"): + elif cmd in (P+"switch", P+"s"): return await _cmd_switch(user_id, args) - elif cmd == "/retry": + elif cmd == P+"retry": return await _cmd_retry(user_id) - elif cmd in ("/help", "/h", "/?"): + elif cmd in (P+"help", P+"h", P+"?"): return _cmd_help() - elif cmd == "/direct": + elif cmd == P+"direct": return _cmd_direct(user_id) - elif cmd == "/smart": + elif cmd == P+"smart": return _cmd_smart(user_id) - elif cmd == "/tasks": + elif cmd == P+"tasks": return _cmd_tasks() - elif cmd == "/shell": + elif cmd == P+"shell": return await _cmd_shell(args) - elif cmd == "/remind": + elif cmd == P+"remind": return await _cmd_remind(args) - elif cmd == "/perm": + elif cmd == P+"perm": return await _cmd_perm(user_id, args) - elif cmd in ("/nodes", "/node"): + elif cmd in (P+"nodes", P+"node"): return await _cmd_nodes(user_id, args) else: return None @@ -431,23 +436,24 @@ async def _cmd_nodes(user_id: str, args: str) -> str: def _cmd_help() -> str: """Show help.""" - return """**Commands:** -/new [msg] [--timeout N] [--idle N] [--perm MODE] - Create session -/status - Show sessions and current mode -/close [n] - Close session (active or by number) -/switch - Switch to session by number -/perm [conv_id] - Set permission mode (bypass/accept/plan) -/direct - Direct mode: messages → Claude Code (no LLM overhead) -/smart - Smart mode: messages → LLM routing (default) -/shell - Run shell command (bypasses LLM) -/remind