Преглед изворни кода

feat(chatto): add chatto_list_room_groups tool

List room groups as configured on the Chatto server. Each group entry
includes ID, name, description, room count, room IDs and sidebar links.
Completes Idea 5 (unused chattolib capabilities) — all S-tasks done.

- chatto_list_room_groups: no parameters, returns full group listing
Paul Klumpp пре 1 недеља
родитељ
комит
6f2c67f9c3
3 измењених фајлова са 62 додато и 0 уклоњено
  1. 60 0
      adapter.py
  2. 1 0
      plugin.yaml
  3. 1 0
      test_adapter.py

+ 60 - 0
adapter.py

@@ -4787,6 +4787,21 @@ CHATTO_GET_MESSAGE_SCHEMA = {
     },
 }
 
+CHATTO_LIST_ROOM_GROUPS_SCHEMA = {
+    "name": "chatto_list_room_groups",
+    "description": (
+        "List room groups as configured on the Chatto server. Each group has an "
+        "ID, name, description, list of rooms, and optional sidebar links. "
+        "Useful for browsing the server's room organisation."
+    ),
+    "parameters": {
+        "type": "object",
+        "properties": {},
+        "required": [],
+        "additionalProperties": False,
+    },
+}
+
 
 CHATTO_GET_HISTORY_SCHEMA = {
     "name": "chatto_get_history",
@@ -6002,6 +6017,28 @@ async def _mark_thread_as_read(args: dict) -> str:
         )
 
 
+async def _list_room_groups(args: dict) -> str:
+    """List room groups. See _handle_chatto_list_room_groups."""
+    async with _tool_client(_chatto_config_for_tools()) as client:
+        groups = await client.list_room_groups()
+        results: list[dict] = []
+        for g in groups:
+            results.append(
+                {
+                    "id": g.id,
+                    "name": g.name,
+                    "description": g.description or "",
+                    "room_count": len(g.rooms),
+                    "room_ids": [rws.room.id for rws in g.rooms if rws.room],
+                    "sidebar_links": [
+                        {"id": l.id, "label": l.label, "url": l.url}
+                        for l in g.sidebar_links
+                    ],
+                }
+            )
+        return json.dumps({"success": True, "groups": results})
+
+
 async def _handle_chatto_fetch_link_preview(args: dict) -> str:
     """Tool handler for chatto_fetch_link_preview.
 
@@ -6074,6 +6111,24 @@ async def _handle_chatto_get_history(args: dict) -> str:
         return json.dumps({"success": False, "error": f"Chatto API error: {exc}"})
 
 
+async def _handle_chatto_list_room_groups(args: dict) -> str:
+    """Tool handler for chatto_list_room_groups.
+
+    Returns a JSON string: Hermes' tool contract accepts no other type, and a
+    dict (or an unflagged coroutine) fails at dispatch with "unsupported result
+    type". Every early exit arrives here as a _ToolRefusal and leaves as that
+    refusal's own JSON, so no path escapes as an unhandled error.
+    """
+    try:
+        return await _list_room_groups(args)
+    except _ToolRefusal as refusal:
+        return refusal.result_json
+    except ChattoAuthError as exc:
+        return json.dumps({"success": False, "error": f"Authentication error: {exc}"})
+    except ChattoError as exc:
+        return json.dumps({"success": False, "error": f"Chatto API error: {exc}"})
+
+
 async def _handle_chatto_list_room_attachments(args: dict) -> str:
     """Tool handler for chatto_list_room_attachments.
 
@@ -6201,6 +6256,11 @@ _PLUGIN_TOOLS = (
         CHATTO_MARK_THREAD_AS_READ_SCHEMA,
         _handle_chatto_mark_thread_as_read,
     ),
+    (
+        "chatto_list_room_groups",
+        CHATTO_LIST_ROOM_GROUPS_SCHEMA,
+        _handle_chatto_list_room_groups,
+    ),
 )
 
 

+ 1 - 0
plugin.yaml

@@ -23,6 +23,7 @@ provides_tools:
   - chatto_delete_custom_status
   - chatto_fetch_link_preview
   - chatto_mark_thread_as_read
+  - chatto_list_room_groups
 requires_env:
   - name: CHATTO_BASE_URL
     description: "Base URL of the Chatto server (e.g. https://chat.example.com) leave blank for ChattoHQ (https://chat.chatto.run)"

+ 1 - 0
test_adapter.py

@@ -4475,6 +4475,7 @@ class TestPluginToolSchemas:
             "chatto_delete_custom_status",
             "chatto_fetch_link_preview",
             "chatto_mark_thread_as_read",
+            "chatto_list_room_groups",
         ]
         for tool in ctx.registered_tools:
             assert tool["is_async"] is True, tool["name"]