feat: Enhance TelegramAdapter to handle form action buttons and message threading

This commit is contained in:
fdc310
2026-06-02 00:25:52 +08:00
parent f663d87a60
commit 2b533c4a00
+29 -14
View File
@@ -291,6 +291,7 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
), ),
), ),
message_chain=message_chain, message_chain=message_chain,
source_platform_object=update,
) )
else: else:
synthetic_event = platform_events.FriendMessage( synthetic_event = platform_events.FriendMessage(
@@ -300,6 +301,7 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
remark='', remark='',
), ),
message_chain=message_chain, message_chain=message_chain,
source_platform_object=update,
) )
await self.ap.query_pool.add_query( await self.ap.query_pool.add_query(
@@ -415,7 +417,8 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
update = event.source_platform_object update = event.source_platform_object
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
chat_type = update.effective_chat.type chat_type = update.effective_chat.type
message_thread_id = update.message.message_thread_id effective_message = update.effective_message
message_thread_id = getattr(effective_message, 'message_thread_id', None) if effective_message else None
if chat_type == 'private': if chat_type == 'private':
draft_id = int(time.time() * 1000) draft_id = int(time.time() * 1000)
@@ -443,7 +446,8 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
assert isinstance(message_source.source_platform_object, Update) assert isinstance(message_source.source_platform_object, Update)
update = message_source.source_platform_object update = message_source.source_platform_object
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
message_thread_id = update.message.message_thread_id effective_message = update.effective_message
message_thread_id = getattr(effective_message, 'message_thread_id', None) if effective_message else None
if message_id not in self.msg_stream_id: if message_id not in self.msg_stream_id:
return return
@@ -457,21 +461,32 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
return return
content = components[0]['text'] content = components[0]['text']
form_data = getattr(bot_message, '_form_data', None)
if chat_mode == 'private': if chat_mode == 'private':
if form_data and is_final:
# Suppress the streaming-text materialisation: this chunk's
# content is just a placeholder (e.g. zero-width space, or
# the display_text used to keep ResponseWrapper from dropping
# the chunk). The button card below carries the real prompt.
self.msg_stream_id.pop(message_id, None)
await self._send_form_action_buttons(message_source, form_data)
return
args = self._build_message_args(chat_id, content, message_thread_id, draft_id=draft_id) args = self._build_message_args(chat_id, content, message_thread_id, draft_id=draft_id)
await self.bot.send_message_draft(**args) await self.bot.send_message_draft(**args)
if is_final and bot_message.tool_calls is None: if is_final and bot_message.tool_calls is None:
del args['draft_id'] del args['draft_id']
await self.bot.send_message(**args) await self.bot.send_message(**args)
self.msg_stream_id.pop(message_id) self.msg_stream_id.pop(message_id)
# Send form action buttons if form data is present
form_data = getattr(bot_message, '_form_data', None)
if form_data:
await self._send_form_action_buttons(message_source, form_data)
else: else:
stream_id = draft_id stream_id = draft_id
if form_data and is_final:
# Same suppression as the private branch — don't push the
# placeholder text into the streaming message; render the
# button card instead.
self.msg_stream_id.pop(message_id, None)
await self._send_form_action_buttons(message_source, form_data)
return
if (msg_seq - 1) % 8 == 0 or is_final: if (msg_seq - 1) % 8 == 0 or is_final:
args = { args = {
'message_id': stream_id, 'message_id': stream_id,
@@ -485,11 +500,6 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
if is_final and bot_message.tool_calls is None: if is_final and bot_message.tool_calls is None:
self.msg_stream_id.pop(message_id) self.msg_stream_id.pop(message_id)
# Send form action buttons if form data is present
form_data = getattr(bot_message, '_form_data', None)
if form_data:
await self._send_form_action_buttons(message_source, form_data)
async def _send_form_action_buttons( async def _send_form_action_buttons(
self, self,
message_source: platform_events.MessageEvent, message_source: platform_events.MessageEvent,
@@ -498,6 +508,7 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
"""Send inline keyboard buttons for Dify human_input_required form actions.""" """Send inline keyboard buttons for Dify human_input_required form actions."""
actions = form_data.get('actions', []) actions = form_data.get('actions', [])
node_title = form_data.get('node_title', '') node_title = form_data.get('node_title', '')
form_content = form_data.get('form_content', '')
workflow_run_id = form_data.get('workflow_run_id', '') workflow_run_id = form_data.get('workflow_run_id', '')
# Telegram callback_data is capped at 64 bytes, so we identify the # Telegram callback_data is capped at 64 bytes, so we identify the
# paused workflow by the last 8 chars of workflow_run_id (unique # paused workflow by the last 8 chars of workflow_run_id (unique
@@ -523,11 +534,15 @@ class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
update = message_source.source_platform_object update = message_source.source_platform_object
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
message_thread_id = update.message.message_thread_id effective_message = update.effective_message
message_thread_id = getattr(effective_message, 'message_thread_id', None) if effective_message else None
text_lines = [f'[{node_title}] Please select an action:']
if form_content:
text_lines.insert(0, form_content)
args = { args = {
'chat_id': chat_id, 'chat_id': chat_id,
'text': f'[{node_title}] Please select an action:', 'text': '\n\n'.join(text_lines),
'reply_markup': reply_markup, 'reply_markup': reply_markup,
} }
if message_thread_id: if message_thread_id: