Files
LangBot/src/langbot/pkg/workflow/nodes/reply_message.py
Typer_Body 192b69b0fb fix
2026-06-02 02:29:35 +08:00

142 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Reply Message Node - reply to the triggering message
Node metadata is loaded from: ../../templates/metadata/nodes/reply_message.yaml
"""
from __future__ import annotations
import logging
from typing import Any
from langbot_plugin.api.entities.builtin.workflow.entities import ExecutionContext
from ..node import WorkflowNode, workflow_node
from .. import monitoring_helper
logger = logging.getLogger(__name__)
@workflow_node('reply_message')
class ReplyMessageNode(WorkflowNode):
"""Reply message node - reply to the triggering message"""
category = 'action'
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
# Priority: content/response (from upstream nodes) > message (original input) > context
message = inputs.get('content')
if message in (None, ''):
message = inputs.get('response')
if message in (None, ''):
message = inputs.get('input')
if message in (None, ''):
message = inputs.get('message')
if message in (None, '') and context.message_context:
message = context.message_context.message_content
if message is None:
message = ''
template = self.get_config('message_template')
if template:
message = template
for key, value in inputs.items():
try:
message = message.replace(f'{{{{{key}}}}}', str(value) if value is not None else '')
except Exception as e:
logger.debug(
'ReplyMessageNode failed to replace input template variable',
extra={'node_id': self.node_id, 'key': str(key), 'error': str(e)},
)
for key, value in context.variables.items():
try:
message = message.replace(f'{{{{variables.{key}}}}}', str(value) if value is not None else '')
except Exception as e:
logger.debug(
'ReplyMessageNode failed to replace context template variable',
extra={'node_id': self.node_id, 'key': str(key), 'error': str(e)},
)
message_str = str(message) if message is not None else ''
logger.info(
'ReplyMessageNode resolved message',
extra={
'node_id': self.node_id,
'execution_id': context.execution_id,
'input_keys': list(inputs.keys()),
'message_preview': message_str[:200],
'has_template': bool(template),
'session_id': context.session_id,
},
)
if not message_str.strip():
logger.warning(
'ReplyMessageNode has empty message after resolution',
extra={
'node_id': self.node_id,
'execution_id': context.execution_id,
'input_keys': list(inputs.keys()),
},
)
# 实际发送消息
send_success = False
send_error = None
if self.ap:
try:
from langbot_plugin.api.entities.builtin.platform.message import MessageChain, Plain
message_chain = MessageChain([Plain(text=message_str)])
# 从 trigger_data 中获取 session_type而不是从未设置的 context.target_type
target_type = 'person'
if context.trigger_data:
target_type = context.trigger_data.get('session_type', 'person') or 'person'
session_id = context.session_id or 'unknown'
target_id = f'websocket_{session_id}'
await self.ap.platform_mgr.websocket_proxy_bot.adapter.send_message(
target_type=target_type,
target_id=target_id,
message=message_chain,
)
send_success = True
except Exception as e:
send_error = str(e)
logger.error('ReplyMessageNode send message failed: %s', e, exc_info=True)
else:
send_error = 'Missing application instance'
logger.warning(
'ReplyMessageNode missing application instance',
extra={
'node_id': self.node_id,
'execution_id': context.execution_id,
},
)
# Record reply log
try:
if self.ap and context.query and send_success:
workflow_id = context.workflow_id or ''
workflow_name = context.variables.get('_workflow_name', 'Workflow')
bot_name = context.variables.get('_bot_name', 'Workflow')
node_name = self.get_config('name', self.node_id)
await monitoring_helper.WorkflowMonitoringHelper.record_reply_log(
ap=self.ap,
query=context.query,
workflow_id=workflow_id,
workflow_name=workflow_name,
node_name=node_name,
reply_content=message_str,
bot_name=bot_name,
context_vars=context.variables,
)
except Exception as e:
logger.warning(f'[ReplyMessage:{self.node_id}] Failed to record reply log: {e}')
return {
'status': 'sent' if send_success else 'failed',
'message_content': message_str,
'message_preview': message_str[:200],
'error': send_error,
}