|
@@ -4530,6 +4530,56 @@ CHATTO_PIN_MESSAGE_SCHEMA = {
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+CHATTO_SET_CUSTOM_STATUS_SCHEMA = {
|
|
|
|
|
+ "name": "chatto_set_custom_status",
|
|
|
|
|
+ "description": (
|
|
|
|
|
+ "Set the bot's custom status in Chatto. Shows an emoji and text next "
|
|
|
|
|
+ "to the bot name in the client (e.g. 🛠️ processing, ⏳ awaiting review). "
|
|
|
|
|
+ "Optional ``expires_in_seconds`` auto-clears the status; omit or 0 for "
|
|
|
|
|
+ "manual clearing."
|
|
|
|
|
+ ),
|
|
|
|
|
+ "parameters": {
|
|
|
|
|
+ "type": "object",
|
|
|
|
|
+ "properties": {
|
|
|
|
|
+ "emoji": {
|
|
|
|
|
+ "type": "string",
|
|
|
|
|
+ "description": (
|
|
|
|
|
+ "A single emoji to show next to the status text "
|
|
|
|
|
+ "(e.g. 🛠️, ⏳, 🔴)."
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ "text": {
|
|
|
|
|
+ "type": "string",
|
|
|
|
|
+ "description": (
|
|
|
|
|
+ "The status text to display (e.g. 'processing', 'awaiting review')."
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ "expires_in_seconds": {
|
|
|
|
|
+ "type": "integer",
|
|
|
|
|
+ "description": (
|
|
|
|
|
+ "Optional: auto-clear the status after this many seconds. "
|
|
|
|
|
+ "Omit or 0 to keep the status until cleared."
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "required": ["emoji", "text"],
|
|
|
|
|
+ "additionalProperties": False,
|
|
|
|
|
+ },
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+CHATTO_DELETE_CUSTOM_STATUS_SCHEMA = {
|
|
|
|
|
+ "name": "chatto_delete_custom_status",
|
|
|
|
|
+ "description": (
|
|
|
|
|
+ "Clear the bot's custom status, reverting to no status display."
|
|
|
|
|
+ ),
|
|
|
|
|
+ "parameters": {
|
|
|
|
|
+ "type": "object",
|
|
|
|
|
+ "properties": {},
|
|
|
|
|
+ "required": [],
|
|
|
|
|
+ "additionalProperties": False,
|
|
|
|
|
+ },
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
CHATTO_SEND_DM_SCHEMA = {
|
|
CHATTO_SEND_DM_SCHEMA = {
|
|
|
"name": "chatto_send_dm",
|
|
"name": "chatto_send_dm",
|
|
@@ -5771,6 +5821,81 @@ async def _handle_chatto_list_rooms(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_set_custom_status(args: dict) -> str:
|
|
|
|
|
+ """Tool handler for chatto_set_custom_status.
|
|
|
|
|
+
|
|
|
|
|
+ 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 _set_custom_status(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_delete_custom_status(args: dict) -> str:
|
|
|
|
|
+ """Tool handler for chatto_delete_custom_status.
|
|
|
|
|
+
|
|
|
|
|
+ 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 _delete_custom_status(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 _set_custom_status(args: dict) -> str:
|
|
|
|
|
+ """Set the bot's custom status. See _handle_chatto_set_custom_status."""
|
|
|
|
|
+ emoji = (args.get("emoji") or "").strip()
|
|
|
|
|
+ text = (args.get("text") or "").strip()
|
|
|
|
|
+ expires_in = args.get("expires_in_seconds")
|
|
|
|
|
+ if expires_in is not None:
|
|
|
|
|
+ expires_in = int(expires_in)
|
|
|
|
|
+ if expires_in < 0:
|
|
|
|
|
+ raise _refuse("expires_in_seconds must be non-negative")
|
|
|
|
|
+
|
|
|
|
|
+ if not emoji or not text:
|
|
|
|
|
+ raise _refuse("emoji and text are required")
|
|
|
|
|
+
|
|
|
|
|
+ async with _tool_client(_chatto_config_for_tools()) as client:
|
|
|
|
|
+ expires_at = None
|
|
|
|
|
+ if expires_in and expires_in > 0:
|
|
|
|
|
+ from datetime import UTC, datetime, timedelta
|
|
|
|
|
+
|
|
|
|
|
+ expires_at = datetime.now(UTC) + timedelta(seconds=expires_in)
|
|
|
|
|
+ await client.set_custom_status(emoji, text, expires_at=expires_at)
|
|
|
|
|
+ return json.dumps(
|
|
|
|
|
+ {
|
|
|
|
|
+ "success": True,
|
|
|
|
|
+ "emoji": emoji,
|
|
|
|
|
+ "text": text,
|
|
|
|
|
+ "expires_at": (
|
|
|
|
|
+ _iso_or_none(expires_at) if expires_at else None
|
|
|
|
|
+ ),
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def _delete_custom_status(args: dict) -> str:
|
|
|
|
|
+ """Clear the bot's custom status. See _handle_chatto_delete_custom_status."""
|
|
|
|
|
+ async with _tool_client(_chatto_config_for_tools()) as client:
|
|
|
|
|
+ await client.delete_custom_status()
|
|
|
|
|
+ return json.dumps({"success": True, "message": "Custom status cleared"})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
async def _handle_chatto_get_message(args: dict) -> str:
|
|
async def _handle_chatto_get_message(args: dict) -> str:
|
|
|
"""Tool handler for chatto_get_message.
|
|
"""Tool handler for chatto_get_message.
|
|
|
|
|
|
|
@@ -5914,6 +6039,16 @@ _PLUGIN_TOOLS = (
|
|
|
CHATTO_PIN_MESSAGE_SCHEMA,
|
|
CHATTO_PIN_MESSAGE_SCHEMA,
|
|
|
_handle_chatto_pin_message,
|
|
_handle_chatto_pin_message,
|
|
|
),
|
|
),
|
|
|
|
|
+ (
|
|
|
|
|
+ "chatto_set_custom_status",
|
|
|
|
|
+ CHATTO_SET_CUSTOM_STATUS_SCHEMA,
|
|
|
|
|
+ _handle_chatto_set_custom_status,
|
|
|
|
|
+ ),
|
|
|
|
|
+ (
|
|
|
|
|
+ "chatto_delete_custom_status",
|
|
|
|
|
+ CHATTO_DELETE_CUSTOM_STATUS_SCHEMA,
|
|
|
|
|
+ _handle_chatto_delete_custom_status,
|
|
|
|
|
+ ),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|