|
@@ -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 = {
|
|
CHATTO_GET_HISTORY_SCHEMA = {
|
|
|
"name": "chatto_get_history",
|
|
"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:
|
|
async def _handle_chatto_fetch_link_preview(args: dict) -> str:
|
|
|
"""Tool handler for chatto_fetch_link_preview.
|
|
"""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}"})
|
|
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:
|
|
async def _handle_chatto_list_room_attachments(args: dict) -> str:
|
|
|
"""Tool handler for chatto_list_room_attachments.
|
|
"""Tool handler for chatto_list_room_attachments.
|
|
|
|
|
|
|
@@ -6201,6 +6256,11 @@ _PLUGIN_TOOLS = (
|
|
|
CHATTO_MARK_THREAD_AS_READ_SCHEMA,
|
|
CHATTO_MARK_THREAD_AS_READ_SCHEMA,
|
|
|
_handle_chatto_mark_thread_as_read,
|
|
_handle_chatto_mark_thread_as_read,
|
|
|
),
|
|
),
|
|
|
|
|
+ (
|
|
|
|
|
+ "chatto_list_room_groups",
|
|
|
|
|
+ CHATTO_LIST_ROOM_GROUPS_SCHEMA,
|
|
|
|
|
+ _handle_chatto_list_room_groups,
|
|
|
|
|
+ ),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|