diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index d5578961c..2f4ec9329 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -11,6 +11,7 @@ import asyncio import json import logging import os +import html as _html import re from typing import Dict, List, Optional, Any @@ -1129,13 +1130,10 @@ class TelegramAdapter(BasePlatformAdapter): try: cmd_preview = command[:3800] + "..." if len(command) > 3800 else command - # Escape backticks that would break Markdown v1 inline code parsing - safe_cmd = cmd_preview.replace("`", "'") - safe_desc = description.replace("`", "'").replace("*", "∗") text = ( - f"⚠️ *Command Approval Required*\n\n" - f"`{safe_cmd}`\n\n" - f"Reason: {safe_desc}" + f"⚠️ Command Approval Required\n\n" + f"
{_html.escape(cmd_preview)}\n\n"
+ f"Reason: {_html.escape(description)}"
)
# Resolve thread context for thread replies
@@ -1163,7 +1161,7 @@ class TelegramAdapter(BasePlatformAdapter):
kwargs: Dict[str, Any] = {
"chat_id": int(chat_id),
"text": text,
- "parse_mode": ParseMode.MARKDOWN,
+ "parse_mode": ParseMode.HTML,
"reply_markup": keyboard,
**self._link_preview_kwargs(),
}
diff --git a/gateway/run.py b/gateway/run.py
index 7517fdabd..7e4cc26a7 100644
--- a/gateway/run.py
+++ b/gateway/run.py
@@ -8816,7 +8816,7 @@ class GatewayRunner:
# false positives from MagicMock auto-attribute creation in tests.
if getattr(type(_status_adapter), "send_exec_approval", None) is not None:
try:
- asyncio.run_coroutine_threadsafe(
+ _approval_result = asyncio.run_coroutine_threadsafe(
_status_adapter.send_exec_approval(
chat_id=_status_chat_id,
command=cmd,
@@ -8826,7 +8826,12 @@ class GatewayRunner:
),
_loop_for_step,
).result(timeout=15)
- return
+ if _approval_result.success:
+ return
+ logger.warning(
+ "Button-based approval failed (send returned error), falling back to text: %s",
+ _approval_result.error,
+ )
except Exception as _e:
logger.warning(
"Button-based approval failed, falling back to text: %s", _e