|
|
@@ -357,6 +357,39 @@ class _RoomRoster:
|
|
|
unfetched: int = 0
|
|
|
|
|
|
|
|
|
+@dataclass
|
|
|
+class _ClarifyPrompt:
|
|
|
+ """State for a reaction-driven clarify prompt posted to a Chatto room."""
|
|
|
+
|
|
|
+ clarify_id: str
|
|
|
+ choices: list[str]
|
|
|
+ session_key: str
|
|
|
+ chat_id: str
|
|
|
+ message_id: str
|
|
|
+ resolved: bool = False
|
|
|
+ awaiting_text: bool = False
|
|
|
+ resolved_by: str | None = None
|
|
|
+ resolved_choice: str | None = None
|
|
|
+ expires_at: float = 0.0
|
|
|
+
|
|
|
+
|
|
|
+@dataclass
|
|
|
+class _ApprovalPrompt:
|
|
|
+ """State for a reaction-driven exec-approval prompt posted to a Chatto room."""
|
|
|
+
|
|
|
+ session_key: str
|
|
|
+ chat_id: str
|
|
|
+ message_id: str
|
|
|
+ choices_map: dict[str, str] # emoji -> choice
|
|
|
+ resolved: bool = False
|
|
|
+ resolved_by: str | None = None
|
|
|
+ resolved_choice: str | None = None
|
|
|
+ expires_at: float = 0.0
|
|
|
+
|
|
|
+
|
|
|
+INTERACTIVE_PROMPT_TIMEOUT_SECONDS = 300
|
|
|
+
|
|
|
+
|
|
|
_UNSEEDED: Final = object()
|
|
|
"""Sentinel: nothing is known yet about how far this thread's session reaches.
|
|
|
|
|
|
@@ -482,6 +515,13 @@ class ChattoAdapter(BasePlatformAdapter):
|
|
|
# Member directory cache: user_id -> user info dict
|
|
|
self._user_cache: dict[str, User] = {}
|
|
|
|
|
|
+ # Interactive prompt registries (clarify + exec-approval), keyed by
|
|
|
+ # message_id. Reverse lookup _clarify_id_to_message supports
|
|
|
+ # retire_clarify_card.
|
|
|
+ self._clarify_prompts: dict[str, _ClarifyPrompt] = {}
|
|
|
+ self._approval_prompts: dict[str, _ApprovalPrompt] = {}
|
|
|
+ self._clarify_id_to_message: dict[str, str] = {}
|
|
|
+
|
|
|
# Chattolib client cache and lock for async access.
|
|
|
self._chatto_client: ChattoClient | None = None
|
|
|
self._chatto_client_lock: asyncio.Lock = asyncio.Lock()
|