from __future__ import annotations import logging from yuxi.channel.extensions.mattermost.client import MattermostClient from yuxi.channel.extensions.mattermost.errors import MattermostError logger = logging.getLogger(__name__) DEFAULT_COMMAND_SPECS = [ {"trigger": "oc_status", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "Show bot status"}, {"trigger": "oc_model", "method": "P", "auto_complete": True, "auto_complete_hint": "[model_name]", "auto_complete_desc": "Switch AI model"}, {"trigger": "oc_models", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "List available models"}, {"trigger": "oc_new", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "Start a new conversation"}, {"trigger": "oc_help", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "Show help information"}, {"trigger": "oc_think", "method": "P", "auto_complete": True, "auto_complete_hint": "[level]", "auto_complete_desc": "Set reasoning level"}, {"trigger": "oc_reasoning", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "Toggle reasoning mode"}, {"trigger": "oc_verbose", "method": "P", "auto_complete": True, "auto_complete_hint": "", "auto_complete_desc": "Toggle verbose mode"}, ] class SlashCommandManager: def __init__(self, client: MattermostClient, account_id: str): self.client = client self.account_id = account_id self._registered: list[dict] = [] async def register_commands( self, callback_url: str, team_ids: list[str], ) -> list[dict]: registered: list[dict] = [] for team_id in team_ids: try: existing = await self.client.list_commands(team_id) existing_triggers = {c["trigger"] for c in existing} for spec in DEFAULT_COMMAND_SPECS: trigger = spec["trigger"] if trigger in existing_triggers: logger.debug("Command %s already registered for team %s", trigger, team_id) continue payload = { "team_id": team_id, "trigger": trigger, "method": spec["method"], "url": f"{callback_url}/{self.account_id}", "auto_complete": spec.get("auto_complete", True), "auto_complete_desc": spec.get("auto_complete_desc", ""), "auto_complete_hint": spec.get("auto_complete_hint", ""), } cmd = await self.client.create_command(payload) cmd["managed"] = True registered.append(cmd) logger.info("Registered command %s for team %s", trigger, team_id) except MattermostError as e: logger.warning("Failed to register commands for team %s: %s", team_id, e) self._registered = registered return registered async def cleanup_commands(self) -> None: for cmd in self._registered: if cmd.get("managed"): try: await self.client.delete_command(cmd["id"]) logger.info("Deleted command %s", cmd.get("trigger", cmd["id"])) except MattermostError: pass self._registered.clear() def get_managed_commands(self) -> list[dict]: return list(cmd for cmd in self._registered if cmd.get("managed"))