# File: backend/app/flow_components/chat_output.py (New) # Description: Backend component for ChatOutputNode from .base import BaseComponent, InputField, OutputField, register_component from typing import ClassVar, Dict, Any, Optional, List from sqlalchemy.ext.asyncio import AsyncSession @register_component class ChatOutputNodeComponent(BaseComponent): name: ClassVar[str] = "chatOutputNode" display_name: ClassVar[str] = "Chat Output" description: ClassVar[str] = "在 Playground 显示聊天消息。" icon: ClassVar[str] = "MessageCircleReply" inputs: ClassVar[List[InputField]] = [ InputField(name="message-input", display_name="Message", field_type="message", required=True, is_handle=True, info="连接要显示的消息。"), InputField(name="displayText", display_name="Text", field_type="str", required=False, is_handle=False, info="(可选)覆盖显示的文本。"), ] outputs: ClassVar[List[OutputField]] = [ # This node typically doesn't output further, but could pass through # OutputField(name="output", display_name="Output", field_type="message") ] async def run(self, inputs: Dict[str, Any], db: Optional[AsyncSession] = None) -> Dict[str, Any]: message_input = inputs.get("message-input") display_override = inputs.get("displayText", self.node_data.get("displayText")) # Check UI data too if message_input is None: raise ValueError("ChatOutputNode 未收到输入消息。") # Determine what to "output" (in this context, what the workflow considers the result) final_text = display_override if display_override else str(message_input) print(f"ChatOutputNode ({self.node_data.get('id', 'N/A')}): 最终显示 '{final_text[:50]}...'") # Since this is often a terminal node for execution, return the processed input # The executor will decide how to handle this final output return {"final_output": final_text} # Use a consistent key like 'final_output'