Explorar el Código

feat: chatto_send_room thread support (create_thread / thread_root_event_id)

- create_thread=true posts the message as the root of a new thread
  (first chunk = root, following chunks inside the thread) and follows it
- thread_root_event_id posts the message inside an existing thread
- both are mutually exclusive; validated before any API call
- response now carries thread_root_event_id and created_thread
Liv Klumpp hace 2 semanas
padre
commit
a7568e240a
Se han modificado 1 ficheros con 45 adiciones y 2 borrados
  1. 45 2
      adapter.py

+ 45 - 2
adapter.py

@@ -3589,6 +3589,22 @@ CHATTO_SEND_ROOM_SCHEMA = {
                 "type": "string",
                 "description": "The message text to send (markdown supported).",
             },
+            "thread_root_event_id": {
+                "type": "string",
+                "description": (
+                    "Optional: event ID of the thread-root message. When given, "
+                    "this message is posted INSIDE that thread. Mutually "
+                    "exclusive with `create_thread`."
+                ),
+            },
+            "create_thread": {
+                "type": "boolean",
+                "description": (
+                    "Optional: post this message as the ROOT of a new thread "
+                    "(default false = normal message). Mutually exclusive with "
+                    "`thread_root_event_id`."
+                ),
+            },
             "base_url": {
                 "type": "string",
                 "description": (
@@ -3799,6 +3815,8 @@ async def _handle_chatto_send_room(args: dict) -> dict:
     room_id = args.get("room_id") or ""
     room_name = args.get("room_name") or ""
     message = args.get("message") or ""
+    thread_root_event_id = args.get("thread_root_event_id") or ""
+    create_thread = bool(args.get("create_thread", False))
 
     if not message:
         return json.dumps({"success": False, "error": "message is required"})
@@ -3806,6 +3824,12 @@ async def _handle_chatto_send_room(args: dict) -> dict:
     if not room_id and not room_name:
         return json.dumps({"success": False, "error": "Exactly one of room_id or room_name is required"})
 
+    if thread_root_event_id and create_thread:
+        return json.dumps({
+            "success": False,
+            "error": "thread_root_event_id and create_thread are mutually exclusive",
+        })
+
     # --- Read config: explicit args first, then fall back to resolved config ---
     explicit_token = args.get("token") or ""
 
@@ -3857,9 +3881,26 @@ async def _handle_chatto_send_room(args: dict) -> dict:
             normalised, ChattoConstants.SPLIT_THRESHOLD
         )
         message_ids = []
-        for chunk in chunks:
-            msg = await client.post_message(room_id, chunk)
+        root_message_id = ""
+        for idx, chunk in enumerate(chunks):
+            # First chunk of a new thread IS the thread root; subsequent
+            # chunks land inside the thread. thread_root_event_id given
+            # explicitly puts every chunk inside that existing thread.
+            effective_root = thread_root_event_id or root_message_id
+            msg = await client.post_message(room_id, chunk, thread_root_event_id=effective_root)
             message_ids.append(msg.id)
+            if create_thread and not root_message_id:
+                root_message_id = msg.id
+
+        # 3. A newly created thread should be followed so later activity
+        #    reaches the bot (mirrors the adapter's own thread handling).
+        if create_thread and root_message_id:
+            try:
+                await client.follow_thread(room_id, root_message_id)
+            except Exception:
+                # Follow is best-effort — the thread exists and the message
+                # was delivered; don't fail the tool over a follow hiccup.
+                pass
 
         return json.dumps({
             "success": True,
@@ -3867,6 +3908,8 @@ async def _handle_chatto_send_room(args: dict) -> dict:
             "room_name": room_label,
             "message_ids": message_ids,
             "chunks_sent": len(message_ids),
+            "thread_root_event_id": thread_root_event_id or root_message_id,
+            "created_thread": bool(root_message_id),
         })
 
     except ChattoAuthError as exc: