Преглед на файлове

feat(chatto): implement reaction-driven exec approval prompts

Paul Klumpp преди 1 седмица
родител
ревизия
d0628416c8
променени са 1 файла, в които са добавени 91 реда и са изтрити 1 реда
  1. 91 1
      adapter.py

+ 91 - 1
adapter.py

@@ -2814,7 +2814,7 @@ class ChattoAdapter(BasePlatformAdapter):
             logger.warning("Chatto: send_clarify post error: %s", e)
             return SendResult(success=False, error=str(e), retryable=False)
 
-        message_id = str(msg.id) if getattr(msg, "id", None) else ""
+        message_id = str(msg.id)
         if message_id:
             self._mark_seen(message_id)
 
@@ -2843,6 +2843,96 @@ class ChattoAdapter(BasePlatformAdapter):
 
         return SendResult(success=True, message_id=message_id)
 
+    async def _send_exec_approval_prompt(self, prompt) -> SendResult:
+        """Post a reaction-driven exec-approval prompt.
+
+        BasePlatformAdapter override
+        """
+        emoji_map = {
+            "once": "✅",
+            "session": "🌀",
+            "always": "♾️",
+            "deny": "❌",
+        }
+        number_emojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"]
+
+        choices = list(prompt.choices)
+        choices_map: dict[str, str] = {}
+        emojis: list[str] = []
+        for i, choice in enumerate(choices):
+            emoji = emoji_map.get(choice)
+            if emoji is None:
+                emoji = number_emojis[i] if i < len(number_emojis) else "🔢"
+            emojis.append(emoji)
+            choices_map[emoji] = choice
+
+        client = await self._get_chatto_client()
+        if client is None:
+            return SendResult(
+                success=False, error="Chatto client not available", retryable=True
+            )
+
+        smart_denied = bool(getattr(prompt, "smart_denied", False))
+        tier = "once"
+        if not smart_denied:
+            if "always" in choices:
+                tier = "always"
+            elif "session" in choices:
+                tier = "session"
+        typed_hints = {
+            "once": "React with ✅ to approve once.",
+            "session": "React with 🌀 to approve for this session.",
+            "always": "React with ♾️ to approve always.",
+        }
+        typed_hint = typed_hints.get(tier, "")
+
+        lines = [str(prompt.text), ""]
+        if typed_hint:
+            lines.append(typed_hint)
+            lines.append("")
+        lines.append("Legend:")
+        for emoji, choice in choices_map.items():
+            lines.append(f"{emoji} {choice}")
+        content = "\n".join(lines)
+
+        try:
+            msg = await client.post_message(
+                room_id=str(prompt.chat_id), body=content
+            )
+        except ChattoError as e:
+            logger.warning("Chatto: send_exec_approval post failed: %s", e)
+            return SendResult(success=False, error=str(e), retryable=True)
+        except Exception as e:
+            logger.warning("Chatto: send_exec_approval post error: %s", e)
+            return SendResult(success=False, error=str(e), retryable=False)
+
+        message_id = str(msg.id)
+        if message_id:
+            self._mark_seen(message_id)
+
+        for emoji in emojis:
+            try:
+                await client.add_reaction(
+                    room_id=str(prompt.chat_id),
+                    message_event_id=message_id,
+                    emoji=emoji,
+                )
+            except Exception:
+                logger.debug(
+                    "Chatto: seed reaction %s failed", emoji, exc_info=True
+                )
+
+        approval_prompt = _ApprovalPrompt(
+            session_key=str(prompt.session_key),
+            chat_id=str(prompt.chat_id),
+            message_id=message_id,
+            choices_map=choices_map,
+            expires_at=time.monotonic() + INTERACTIVE_PROMPT_TIMEOUT_SECONDS,
+        )
+        self._approval_prompts[message_id] = approval_prompt
+
+        return SendResult(success=True, message_id=message_id)
+
     async def edit_message(
         self,
         chat_id: str,