diff --git a/gateway/platforms/base.py b/gateway/platforms/base.py index 4dd9cd25d9..c12d417b3a 100644 --- a/gateway/platforms/base.py +++ b/gateway/platforms/base.py @@ -687,7 +687,8 @@ class BasePlatformAdapter(ABC): self._active_sessions[session_key] = interrupt_event # Start continuous typing indicator (refreshes every 2 seconds) - typing_task = asyncio.create_task(self._keep_typing(event.source.chat_id)) + _thread_metadata = {"thread_id": event.source.thread_id} if event.source.thread_id else None + typing_task = asyncio.create_task(self._keep_typing(event.source.chat_id, metadata=_thread_metadata)) try: # Call the handler (this can take a while with tool calls) @@ -711,7 +712,8 @@ class BasePlatformAdapter(ABC): result = await self.send( chat_id=event.source.chat_id, content=text_content, - reply_to=event.message_id + reply_to=event.message_id, + metadata=_thread_metadata, ) # Log send failures (don't raise - user already saw tool progress) @@ -721,7 +723,8 @@ class BasePlatformAdapter(ABC): fallback_result = await self.send( chat_id=event.source.chat_id, content=f"(Response formatting failed, plain text:)\n\n{text_content[:3500]}", - reply_to=event.message_id + reply_to=event.message_id, + metadata=_thread_metadata, ) if not fallback_result.success: print(f"[{self.name}] Fallback send also failed: {fallback_result.error}") @@ -743,12 +746,14 @@ class BasePlatformAdapter(ABC): chat_id=event.source.chat_id, animation_url=image_url, caption=alt_text if alt_text else None, + metadata=_thread_metadata, ) else: img_result = await self.send_image( chat_id=event.source.chat_id, image_url=image_url, caption=alt_text if alt_text else None, + metadata=_thread_metadata, ) if not img_result.success: logger.error("[%s] Failed to send image: %s", self.name, img_result.error) @@ -769,21 +774,25 @@ class BasePlatformAdapter(ABC): media_result = await self.send_voice( chat_id=event.source.chat_id, audio_path=media_path, + metadata=_thread_metadata, ) elif ext in _VIDEO_EXTS: media_result = await self.send_video( chat_id=event.source.chat_id, video_path=media_path, + metadata=_thread_metadata, ) elif ext in _IMAGE_EXTS: media_result = await self.send_image_file( chat_id=event.source.chat_id, image_path=media_path, + metadata=_thread_metadata, ) else: media_result = await self.send_document( chat_id=event.source.chat_id, file_path=media_path, + metadata=_thread_metadata, ) if not media_result.success: diff --git a/gateway/run.py b/gateway/run.py index 1dabf7266b..cd5c931807 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -2656,6 +2656,8 @@ class GatewayRunner: # Background task to send progress messages # Accumulates tool lines into a single message that gets edited + _progress_metadata = {"thread_id": source.thread_id} if source.thread_id else None + async def send_progress_messages(): if not progress_queue: return @@ -2685,15 +2687,15 @@ class GatewayRunner: # Platform doesn't support editing — stop trying, # send just this new line as a separate message can_edit = False - await adapter.send(chat_id=source.chat_id, content=msg) + await adapter.send(chat_id=source.chat_id, content=msg, metadata=_progress_metadata) else: if can_edit: # First tool: send all accumulated text as new message full_text = "\n".join(progress_lines) - result = await adapter.send(chat_id=source.chat_id, content=full_text) + result = await adapter.send(chat_id=source.chat_id, content=full_text, metadata=_progress_metadata) else: # Editing unsupported: send just this line - result = await adapter.send(chat_id=source.chat_id, content=msg) + result = await adapter.send(chat_id=source.chat_id, content=msg, metadata=_progress_metadata) if result.success and result.message_id: progress_msg_id = result.message_id