feat: implement edit_message() for Telegram/Discord/Slack and fix fallback regression

Building on PR #288's edit_message() abstraction:

- Telegram: edit_message_text() with MarkdownV2 + plain text fallback
- Discord: channel.fetch_message() + msg.edit() with length capping
- Slack: chat_update() via slack_bolt client

Also fixes the fallback regression in send_progress_messages() where
platforms that don't support editing would receive duplicated accumulated
tool lines. Now uses a can_edit flag — after the first failed edit, falls
back to sending individual lines (matching pre-PR behavior).
This commit is contained in:
teknium1 2026-03-05 03:47:51 -08:00
parent 5702eba93b
commit 1708dcd2b2
4 changed files with 91 additions and 15 deletions

View file

@ -206,7 +206,29 @@ class DiscordAdapter(BasePlatformAdapter):
except Exception as e:
return SendResult(success=False, error=str(e))
async def edit_message(
self,
chat_id: str,
message_id: str,
content: str,
) -> SendResult:
"""Edit a previously sent Discord message."""
if not self._client:
return SendResult(success=False, error="Not connected")
try:
channel = self._client.get_channel(int(chat_id))
if not channel:
channel = await self._client.fetch_channel(int(chat_id))
msg = await channel.fetch_message(int(message_id))
formatted = self.format_message(content)
if len(formatted) > self.MAX_MESSAGE_LENGTH:
formatted = formatted[:self.MAX_MESSAGE_LENGTH - 3] + "..."
await msg.edit(content=formatted)
return SendResult(success=True, message_id=message_id)
except Exception as e:
return SendResult(success=False, error=str(e))
async def send_voice(
self,
chat_id: str,

View file

@ -156,6 +156,25 @@ class SlackAdapter(BasePlatformAdapter):
print(f"[Slack] Send error: {e}")
return SendResult(success=False, error=str(e))
async def edit_message(
self,
chat_id: str,
message_id: str,
content: str,
) -> SendResult:
"""Edit a previously sent Slack message."""
if not self._app:
return SendResult(success=False, error="Not connected")
try:
await self._app.client.chat_update(
channel=chat_id,
ts=message_id,
text=content,
)
return SendResult(success=True, message_id=message_id)
except Exception as e:
return SendResult(success=False, error=str(e))
async def send_typing(self, chat_id: str) -> None:
"""Slack doesn't have a direct typing indicator API for bots."""
pass

View file

@ -218,7 +218,36 @@ class TelegramAdapter(BasePlatformAdapter):
except Exception as e:
return SendResult(success=False, error=str(e))
async def edit_message(
self,
chat_id: str,
message_id: str,
content: str,
) -> SendResult:
"""Edit a previously sent Telegram message."""
if not self._bot:
return SendResult(success=False, error="Not connected")
try:
formatted = self.format_message(content)
try:
await self._bot.edit_message_text(
chat_id=int(chat_id),
message_id=int(message_id),
text=formatted,
parse_mode=ParseMode.MARKDOWN_V2,
)
except Exception:
# Fallback: retry without markdown formatting
await self._bot.edit_message_text(
chat_id=int(chat_id),
message_id=int(message_id),
text=content,
)
return SendResult(success=True, message_id=message_id)
except Exception as e:
return SendResult(success=False, error=str(e))
async def send_voice(
self,
chat_id: str,