""" 应用设计节点 接收LLM生成的应用设计方案,展示给用户确认或编辑 """ import json import logging from typing import Any, Dict, Optional from ..base import BaseNode, NodeContext, NodeResult from ..registry import NodeRegistry logger = logging.getLogger(__name__) @NodeRegistry.register class AppDesignNode(BaseNode): """ 应用设计节点 接收LLM生成的应用设计方案(Markdown格式),展示给用户确认或编辑 用户可以查看设计方案,编辑后确认继续 """ node_type = 'app_design' node_name = '应用设计' node_category = 'application' node_icon = 'layout' node_description = '展示应用设计方案,支持用户确认或编辑' inputs = [ { 'name': 'design_content', 'type': 'string', 'description': '设计方案内容(Markdown格式)', 'required': True, }, { 'name': 'design_title', 'type': 'string', 'description': '设计方案标题', 'required': False, }, ] outputs = [ { 'name': 'design_content', 'type': 'string', 'description': '确认后的设计方案内容', }, { 'name': 'confirmed', 'type': 'boolean', 'description': '是否已确认', }, ] def execute(self, context: NodeContext) -> NodeResult: """执行节点""" try: # 检查是否有用户编辑的数据(从设计预览面板提交) user_input = context.variables.get('__user_input__') if user_input: edited_data = self._parse_user_edit(user_input) if edited_data: logger.info(f'AppDesignNode - 使用用户编辑的数据') # 使用编辑后的数据,清除用户输入 context.variables.pop('__user_input__', None) return self._build_result(edited_data, require_confirmation=False) # 获取输入参数 design_content = context.resolve_template(self.config.get('design_content', '')) design_title = context.resolve_template(self.config.get('design_title', '应用设计方案')) logger.info(f'AppDesignNode - 输入参数: title={design_title}, content_length={len(design_content)}') # 验证必填字段 if not design_content or not design_content.strip(): return NodeResult( success=False, error='设计方案内容不能为空', ) design_content = design_content.strip() design_title = design_title.strip() if design_title else '应用设计方案' # 构建设计数据 design_data = { 'title': design_title, 'content': design_content, } logger.info(f'AppDesignNode - 输出设计方案: title={design_title}') # 检查是否需要确认(支持布尔值、字符串模式和变量引用) require_confirmation = self.resolve_require_confirmation(context, default=True) return self._build_result(design_data, require_confirmation) except Exception as e: logger.exception(f'应用设计节点执行失败: {e}') return NodeResult( success=False, error=f'节点执行失败: {str(e)}', ) async def execute_async(self, context: NodeContext) -> NodeResult: """异步执行节点(直接调用同步方法)""" return self.execute(context) def _parse_user_edit(self, user_input: Any) -> Optional[Dict[str, Any]]: """解析用户编辑的数据""" if isinstance(user_input, dict): # 检查是否包含设计内容字段 if 'content' in user_input: return user_input return None if isinstance(user_input, str): try: data = json.loads(user_input) if isinstance(data, dict) and 'content' in data: return data except (json.JSONDecodeError, TypeError): # 如果不是JSON,可能直接是编辑后的内容 return {'content': user_input, 'title': '应用设计方案'} return None def _build_result(self, design_data: Dict[str, Any], require_confirmation: bool = False) -> NodeResult: """构建节点结果""" title = design_data.get('title', '应用设计方案') content = design_data.get('content', '') # 构建预览数据 preview_data = { 'type': 'app_design', 'title': title, 'data': design_data, 'editable': True, } if require_confirmation else None return NodeResult( success=True, output=design_data, output_variables={ 'design_content': content, 'design_title': title, 'confirmed': not require_confirmation, }, preview=preview_data, waiting_for_input=require_confirmation, waiting_config={ 'type': 'design_preview', 'preview_type': 'app_design', 'title': title, 'message': '请确认或编辑应用设计方案', 'data': design_data, } if require_confirmation else {}, ) @classmethod def get_config_schema(cls) -> Dict[str, Any]: """ 获取节点配置 Schema(供前端表单渲染) Returns: 配置 Schema """ return { 'type': 'object', 'properties': { 'design_content': { 'type': 'string', 'title': '设计方案内容', 'description': '设计方案内容(Markdown格式),支持变量引用如 {{llm_output}}', 'required': True, 'x-component': 'Textarea', 'x-component-props': { 'placeholder': '请输入设计方案内容或使用变量 {{llm_output}}', 'rows': 6, }, }, 'design_title': { 'type': 'string', 'title': '设计方案标题', 'description': '设计方案的标题,支持变量引用', 'required': False, 'default': '应用设计方案', 'x-component': 'Input', 'x-component-props': { 'placeholder': '请输入标题,默认为"应用设计方案"', }, }, 'require_confirmation': { 'type': 'boolean', 'title': '需要确认', 'description': '设计完成后是否暂停等待用户确认或编辑', 'default': True, 'x-component': 'Switch', }, }, 'required': ['design_content'], }