diff --git a/backend/controller/conversation_api.py b/backend/controller/conversation_api.py index 41ec198..3a39b31 100644 --- a/backend/controller/conversation_api.py +++ b/backend/controller/conversation_api.py @@ -5,10 +5,7 @@ import json import asyncio import time from typing import Optional, TypedDict, List, Union -import threading -from collections import defaultdict -from sqlalchemy.orm import identity from ..utils.globals import set_language from ..utils.auth_utils import extract_and_store_api_key @@ -20,18 +17,15 @@ import base64 import os import shutil -from ..service.debug_agent import debug_workflow_errors +from ..service.debug_agent import debug_workflow_errors, debug_workflow_errors_single from ..dao.workflow_table import save_workflow_data, get_workflow_data_by_id, update_workflow_ui_by_id from ..service.mcp_client import comfyui_agent_invoke +from ..service.all_in_one_agent import all_in_one_invoke from ..utils.request_context import set_request_context, get_session_id from ..utils.logger import log from ..utils.modelscope_gateway import ModelScopeGateway import folder_paths -# 全局下载进度存储 -download_progress = {} -download_lock = threading.Lock() - # 不再使用内存存储会话消息,改为从前端传递历史消息 # 在文件开头添加 @@ -69,98 +63,6 @@ class ChatResponse(TypedDict): format: str # 返回的格式 ext: Optional[List[ExtItem]] # 扩展信息 -# 下载进度回调类 -class DownloadProgressCallback: - def __init__(self, id: str, filename: str, file_size: int, download_id: str): - self.id = id - self.filename = filename - self.file_size = file_size - self.download_id = download_id - self.progress = 0 - self.status = "downloading" # downloading, completed, failed - self.error_message = None - self.start_time = time.time() - - # 初始化进度记录 - with download_lock: - download_progress[download_id] = { - "id": id, - "filename": filename, - "file_size": file_size, - "progress": 0, - "percentage": 0.0, - "status": "downloading", - "start_time": self.start_time, - "estimated_time": None, - "speed": 0.0, - "error_message": None - } - - def update(self, size: int): - """更新下载进度""" - self.progress += size - current_time = time.time() - elapsed_time = current_time - self.start_time - - # 计算下载速度和预估时间 - if elapsed_time > 0: - speed = self.progress / elapsed_time # bytes per second - if speed > 0 and self.progress < self.file_size: - remaining_bytes = self.file_size - self.progress - estimated_time = remaining_bytes / speed - else: - estimated_time = None - else: - speed = 0.0 - estimated_time = None - - percentage = (self.progress / self.file_size) * 100 if self.file_size > 0 else 0 - - # 更新全局进度 - with download_lock: - if self.download_id in download_progress: - # 直接更新字典的值,而不是调用update方法 - progress_dict = download_progress[self.download_id] - progress_dict["progress"] = self.progress - progress_dict["percentage"] = round(percentage, 2) - progress_dict["speed"] = round(speed, 2) - progress_dict["estimated_time"] = round(estimated_time, 2) if estimated_time else None - - def end(self, success: bool = True, error_message: str = None): - """下载结束回调""" - current_time = time.time() - total_time = current_time - self.start_time - - if success: - self.status = "completed" - # 验证下载完整性 - assert self.progress == self.file_size, f"Download incomplete: {self.progress}/{self.file_size}" - else: - self.status = "failed" - self.error_message = error_message - - # 更新最终状态 - with download_lock: - if self.download_id in download_progress: - # 直接更新字典的值,而不是调用update方法 - progress_dict = download_progress[self.download_id] - progress_dict["status"] = self.status - progress_dict["progress"] = self.file_size if success else self.progress - if self.file_size > 0: - progress_dict["percentage"] = 100.0 if success else (self.progress / self.file_size) * 100 - else: - progress_dict["percentage"] = 0.0 - progress_dict["total_time"] = round(total_time, 2) - progress_dict["error_message"] = self.error_message - - def fail(self, error_message: str): - """下载失败回调""" - self.end(success=False, error_message=error_message) - -# 生成唯一下载ID -def generate_download_id() -> str: - import uuid - return str(uuid.uuid4()) async def upload_to_oss(file_data: bytes, filename: str) -> str: # TODO: Implement your OSS upload logic here @@ -225,9 +127,7 @@ async def invoke_chat(request): await response.prepare(request) session_id = req_json.get('session_id') - prompt = req_json.get('prompt') images = req_json.get('images', []) - intent = req_json.get('intent') ext = req_json.get('ext') historical_messages = req_json.get('messages', []) workflow_checkpoint_id = req_json.get('workflow_checkpoint_id') @@ -279,7 +179,6 @@ async def invoke_chat(request): accumulated_text = "" ext_data = None finished = True # Default to True - has_sent_response = False previous_text_length = 0 log.info(f"config: {config}") @@ -353,6 +252,306 @@ async def invoke_chat(request): return response +@server.PromptServer.instance.routes.post("/api/chat-single/invoke") +async def invoke_chat_single(request): + log.info("Received invoke_chat_single request") + + # Extract and store API key from Authorization header + extract_and_store_api_key(request) + + req_json = await request.json() + log.info("Request JSON:", req_json) + + response = web.StreamResponse( + status=200, + reason='OK', + headers={ + 'Content-Type': 'application/json', + 'X-Content-Type-Options': 'nosniff' + } + ) + await response.prepare(request) + + session_id = req_json.get('session_id') + images = req_json.get('images', []) + ext = req_json.get('ext') + historical_messages = req_json.get('messages', []) + workflow_checkpoint_id = req_json.get('workflow_checkpoint_id') + workflow_data = req_json.get('workflow_data') # Support debug-style payloads + + # Language + language = request.headers.get('Accept-Language', 'en') + set_language(language) + + # Config + config = { + "session_id": session_id, + "workflow_checkpoint_id": workflow_checkpoint_id, + "openai_api_key": request.headers.get('Openai-Api-Key'), + "openai_base_url": request.headers.get('Openai-Base-Url'), + # Optional Workflow LLM settings + "workflow_llm_api_key": request.headers.get('Workflow-LLM-Api-Key'), + "workflow_llm_base_url": request.headers.get('Workflow-LLM-Base-Url'), + "workflow_llm_model": request.headers.get('Workflow-LLM-Model'), + "model_select": next((x['data'][0] for x in ext if x['type'] == 'model_select' and x.get('data')), None) if ext else None + } + + # Set request context (isolation per session) + set_request_context(session_id, workflow_checkpoint_id, config) + + # If workflow_data provided (debug scenario), save it so tools like run_workflow/get_current_workflow can access + try: + if workflow_data: + version_id = save_workflow_data( + session_id=session_id, + workflow_data=workflow_data, + workflow_data_ui=None, + attributes={ + "checkpoint_type": "debug_start_single", + "description": "Initial workflow save for single-agent invoke", + "timestamp": time.time() + } + ) + log.info(f"[Single] Saved incoming workflow_data, version ID: {version_id}") + except Exception as save_err: + log.error(f"[Single] Failed to save workflow_data: {save_err}") + + processed_images = [] + if images and len(images) > 0: + log.info(f"Note: Received {len(images)} images in legacy format, but using OpenAI message format instead") + + # Ensure messages exist and start with a user message (required by agents streaming) + openai_messages = historical_messages if isinstance(historical_messages, list) else [] + needs_user_head = (len(openai_messages) == 0) or (openai_messages[0].get('role') != 'user') + if needs_user_head: + # If workflow_data present, default to a debug instruction; otherwise a generic chat starter + default_user_text = "Validate and debug this ComfyUI workflow." if workflow_data else "Start the conversation." + openai_messages = [{"role": "user", "content": default_user_text}] + openai_messages + + try: + accumulated_text = "" + ext_data = None + finished = True + previous_text_length = 0 + + log.info(f"[Single] config: {config}") + + async for result in all_in_one_invoke(openai_messages, None): + if isinstance(result, tuple) and len(result) == 2: + text, ext_with_finished = result + if text: + accumulated_text = text + if ext_with_finished: + ext_data = ext_with_finished.get("data") + finished = ext_with_finished.get("finished", True) + log.info(f"[Single] -- Received ext: {bool(ext_data)}, finished: {finished}") + else: + text_chunk = result + if text_chunk: + accumulated_text += text_chunk + log.info(f"[Single] -- Received text chunk: '{text_chunk}', total length: {len(accumulated_text)}") + + if accumulated_text and len(accumulated_text) > previous_text_length: + chat_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=False, + type="message", + format="markdown", + ext=None + ) + await response.write(json.dumps(chat_response).encode() + b"\n") + previous_text_length = len(accumulated_text) + await asyncio.sleep(0.01) + + final_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=finished, + type="message", + format="markdown", + ext=ext_data + ) + await response.write(json.dumps(final_response).encode() + b"\n") + + except Exception as e: + log.error(f"Error in invoke_chat_single: {str(e)}") + error_response = ChatResponse( + session_id=session_id, + text=f"I apologize, but an error occurred: {str(e)}", + finished=True, + type="message", + format="text", + ext=None + ) + await response.write(json.dumps(error_response).encode() + b"\n") + + await response.write_eof() + return response + + +@server.PromptServer.instance.routes.post("/api/debug-agent-single") +async def invoke_debug_single(request): + """ + Single-agent Debug endpoint for analyzing ComfyUI workflow errors + """ + log.info("Received debug-agent-single request") + + extract_and_store_api_key(request) + req_json = await request.json() + + response = web.StreamResponse( + status=200, + reason='OK', + headers={ + 'Content-Type': 'application/json', + 'X-Content-Type-Options': 'nosniff' + } + ) + await response.prepare(request) + + session_id = req_json.get('session_id') + workflow_data = req_json.get('workflow_data') + + config = { + "session_id": session_id, + "model": "gemini-2.5-flash", + "openai_api_key": request.headers.get('Openai-Api-Key'), + "openai_base_url": request.headers.get('Openai-Base-Url'), + "workflow_llm_api_key": request.headers.get('Workflow-LLM-Api-Key'), + "workflow_llm_base_url": request.headers.get('Workflow-LLM-Base-Url'), + "workflow_llm_model": request.headers.get('Workflow-LLM-Model'), + } + + language = request.headers.get('Accept-Language', 'en') + set_language(language) + + set_request_context(session_id, None, config) + + log.info(f"Single Debug agent config: {config}") + log.info(f"Session ID: {session_id}") + log.info(f"Workflow nodes: {list(workflow_data.keys()) if workflow_data else 'None'}") + + try: + accumulated_text = "" + final_ext_data = None + finished = False + + async for result in debug_workflow_errors_single(workflow_data): + if isinstance(result, tuple) and len(result) == 2: + text, ext = result + if text: + accumulated_text = text + if ext: + if isinstance(ext, dict) and "data" in ext and "finished" in ext: + final_ext_data = ext["data"] + finished = ext["finished"] + + has_realtime_ext = False + if final_ext_data: + for ext_item in final_ext_data: + if ext_item.get("type") in ["workflow_update", "param_update"]: + has_realtime_ext = True + break + if has_realtime_ext or finished: + chat_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=finished, + type="message", + format="markdown", + ext=final_ext_data + ) + await response.write(json.dumps(chat_response).encode() + b"\n") + elif not finished: + chat_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=False, + type="message", + format="markdown", + ext=None + ) + await response.write(json.dumps(chat_response).encode() + b"\n") + else: + final_ext_data = ext + finished = False + chat_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=False, + type="message", + format="markdown", + ext=ext + ) + await response.write(json.dumps(chat_response).encode() + b"\n") + else: + chat_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=False, + type="message", + format="markdown", + ext=None + ) + await response.write(json.dumps(chat_response).encode() + b"\n") + await asyncio.sleep(0.01) + + final_response = ChatResponse( + session_id=session_id, + text=accumulated_text, + finished=True, + type="message", + format="markdown", + ext=final_ext_data if final_ext_data else [{"type": "debug_complete", "data": {"status": "completed"}}] + ) + + if workflow_data and accumulated_text: + try: + current_session_id = get_session_id() + checkpoint_id = save_workflow_data( + session_id=current_session_id, + workflow_data=workflow_data, + workflow_data_ui=None, + attributes={ + "checkpoint_type": "debug_complete", + "description": "Workflow state after single-agent debug completion", + "timestamp": time.time() + } + ) + if final_response["ext"]: + final_response["ext"].append({ + "type": "debug_checkpoint", + "data": {"checkpoint_id": checkpoint_id, "checkpoint_type": "debug_complete"} + }) + else: + final_response["ext"] = [{ + "type": "debug_checkpoint", + "data": {"checkpoint_id": checkpoint_id, "checkpoint_type": "debug_complete"} + }] + log.info(f"Single Debug completion checkpoint saved with ID: {checkpoint_id}") + except Exception as checkpoint_error: + log.error(f"Failed to save single debug completion checkpoint: {checkpoint_error}") + + await response.write(json.dumps(final_response).encode() + b"\n") + log.info("Single Debug agent processing complete") + + except Exception as e: + log.error(f"Error in single debug agent: {str(e)}") + import traceback + traceback.print_exc() + error_response = ChatResponse( + session_id=session_id, + text=f"❌ Single Debug agent error: {str(e)}", + finished=True, + type="message", + format="text", + ext=[{"type": "error", "data": {"error": str(e)}}] + ) + await response.write(json.dumps(error_response).encode() + b"\n") + + await response.write_eof() + return response @server.PromptServer.instance.routes.post("/api/save-workflow-checkpoint") async def save_workflow_checkpoint(request): """ @@ -723,354 +922,4 @@ async def update_workflow_ui(request): return web.json_response({ "success": False, "message": f"Failed to update workflow UI data: {str(e)}" - }) - -@server.PromptServer.instance.routes.post("/api/download-model") -async def download_model(request): - """ - Download model from ModelScope using SDK - """ - log.info("Received download-model request") - req_json = await request.json() - - try: - id = req_json.get('id') - model_id = req_json.get('model_id') - model_type = req_json.get('model_type') - dest_dir = req_json.get('dest_dir') - - # 验证必需参数 - if not id: - return web.json_response({ - "success": False, - "message": "Missing required parameter: id" - }) - - if not model_id: - return web.json_response({ - "success": False, - "message": "Missing required parameter: model_id" - }) - - if not model_type: - return web.json_response({ - "success": False, - "message": "Missing required parameter: model_type" - }) - - log.info(f"Downloading model: {model_id} (type: {model_type})") - - # 生成下载ID - download_id = generate_download_id() - - # 计算目标目录:优先使用传入的dest_dir,否则使用ComfyUI的models目录下对应类型 - resolved_dest_dir = None - if dest_dir: - resolved_dest_dir = os.path.abspath(os.path.expanduser(f"models/{dest_dir}")) - else: - try: - model_type_paths = folder_paths.get_folder_paths(model_type) - resolved_dest_dir = model_type_paths[0] if model_type_paths else os.path.join(folder_paths.models_dir, model_type) - except Exception: - resolved_dest_dir = os.path.join(folder_paths.models_dir, model_type) - - # 创建进度回调 - progress_callback = DownloadProgressCallback( - id=id, - filename=f"{model_id}.{model_type}", - file_size=0, # 实际大小会在下载过程中获取 - download_id=download_id - ) - - # 启动下载任务(异步执行) - async def download_task(): - try: - # 调用下载方法 - 使用snapshot_download - from modelscope import snapshot_download - - # 创建进度回调包装器 - 实现ModelScope期望的接口 - class ProgressWrapper: - """Factory that returns a per-file progress object with update/end.""" - def __init__(self, download_id: str): - self.download_id = download_id - - def __call__(self, file_name: str, file_size: int): - # Create a per-file progress tracker expected by ModelScope - download_id = self.download_id - - class _PerFileProgress: - def __init__(self, fname: str, fsize: int): - self.file_name = fname - self.file_size = max(int(fsize or 0), 0) - self.progress = 0 - self.last_update_time = time.time() - self.last_downloaded = 0 - with download_lock: - if download_id in download_progress: - # If unknown size, keep 0 to avoid div-by-zero - download_progress[download_id]["file_size"] = self.file_size - - def update(self, size: int): - try: - self.progress += int(size or 0) - now = time.time() - # Update global progress - with download_lock: - if download_id in download_progress: - dp = download_progress[download_id] - dp["progress"] = self.progress - if self.file_size > 0: - dp["percentage"] = round(self.progress * 100.0 / self.file_size, 2) - # speed - elapsed = max(now - self.last_update_time, 1e-6) - speed = (self.progress - self.last_downloaded) / elapsed - dp["speed"] = round(speed, 2) - self.last_update_time = now - self.last_downloaded = self.progress - except Exception as e: - log.error(f"Error in progress update: {e}") - - def end(self): - # Called by modelscope when a file finishes - with download_lock: - if download_id in download_progress: - dp = download_progress[download_id] - if self.file_size > 0: - dp["progress"] = self.file_size - dp["percentage"] = 100.0 - - return _PerFileProgress(file_name, file_size) - - progress_wrapper = ProgressWrapper(download_id) - - # 添加调试日志 - log.info(f"Starting download with progress wrapper: {download_id}") - - # 在线程中执行阻塞的下载,避免阻塞事件循环 - from functools import partial - local_dir = await asyncio.to_thread( - partial( - snapshot_download, - model_id=model_id, - cache_dir=resolved_dest_dir, - progress_callbacks=[progress_wrapper] - ) - ) - - # 下载完成 - progress_callback.end(success=True) - log.info(f"Model downloaded successfully to: {local_dir}") - - # 下载后遍历目录,将所有重要权重/资源文件移动到最外层(与目录同级,即 resolved_dest_dir) - try: - moved_count = 0 - allowed_exts = { - ".safetensors", ".ckpt", ".pt", ".pth", ".bin" - # ".msgpack", ".json", ".yaml", ".yml", ".toml", ".png", ".onnx" - } - for root, dirs, files in os.walk(local_dir): - for name in files: - ext = os.path.splitext(name)[1].lower() - if ext in allowed_exts: - src_path = os.path.join(root, name) - target_dir = resolved_dest_dir - os.makedirs(target_dir, exist_ok=True) - target_path = os.path.join(target_dir, name) - # 如果已经在目标目录则跳过 - if os.path.abspath(os.path.dirname(src_path)) == os.path.abspath(target_dir): - continue - # 处理重名情况:自动追加 _1, _2 ... - if os.path.exists(target_path): - base, ext_real = os.path.splitext(name) - idx = 1 - while True: - candidate = f"{base}_{idx}{ext_real}" - candidate_path = os.path.join(target_dir, candidate) - if not os.path.exists(candidate_path): - target_path = candidate_path - break - idx += 1 - shutil.move(src_path, target_path) - moved_count += 1 - log.info(f"Moved {moved_count} files with extensions {sorted(list(allowed_exts))} to: {resolved_dest_dir}") - except Exception as move_err: - log.error(f"Post-download move failed: {move_err}") - - except Exception as e: - progress_callback.fail(str(e)) - log.error(f"Download failed: {str(e)}") - - # 启动异步下载任务 - asyncio.create_task(download_task()) - - return web.json_response({ - "success": True, - "data": { - "download_id": download_id, - "id": id, - "model_id": model_id, - "model_type": model_type, - "dest_dir": resolved_dest_dir, - "status": "started" - }, - "message": f"Download started for model '{model_id}'" - }) - - except ImportError as e: - log.error(f"ModelScope SDK not installed: {str(e)}") - return web.json_response({ - "success": False, - "message": "ModelScope SDK not installed. Please install with: pip install modelscope" - }) - - except Exception as e: - log.error(f"Error starting download: {str(e)}") - import traceback - traceback.print_exc() - return web.json_response({ - "success": False, - "message": f"Failed to start download: {str(e)}" - }) - -@server.PromptServer.instance.routes.get("/api/download-progress/{download_id}") -async def get_download_progress(request): - """ - Get download progress by download ID - """ - download_id = request.match_info.get('download_id') - - if not download_id: - return web.json_response({ - "success": False, - "message": "Missing download_id parameter" - }) - - with download_lock: - progress_info = download_progress.get(download_id) - - if not progress_info: - return web.json_response({ - "success": False, - "message": f"Download ID {download_id} not found" - }) - - return web.json_response({ - "success": True, - "data": progress_info, - "message": "Download progress retrieved successfully" - }) - -@server.PromptServer.instance.routes.get("/api/download-progress") -async def list_downloads(request): - """ - List all active downloads - """ - with download_lock: - downloads = list(download_progress.keys()) - - return web.json_response({ - "success": True, - "data": { - "downloads": downloads, - "count": len(downloads) - }, - "message": "Download list retrieved successfully" - }) - -@server.PromptServer.instance.routes.delete("/api/download-progress/{download_id}") -async def clear_download_progress(request): - """ - Clear download progress record (for cleanup) - """ - download_id = request.match_info.get('download_id') - - if not download_id: - return web.json_response({ - "success": False, - "message": "Missing download_id parameter" - }) - - with download_lock: - if download_id in download_progress: - del download_progress[download_id] - return web.json_response({ - "success": True, - "message": f"Download progress {download_id} cleared successfully" - }) - else: - return web.json_response({ - "success": False, - "message": f"Download ID {download_id} not found" - }) - -@server.PromptServer.instance.routes.get("/api/model-searchs") -async def model_suggests(request): - """ - Get model search list by keyword - """ - log.info("Received model-search request") - try: - keyword = request.query.get('keyword') - - if not keyword: - return web.json_response({ - "success": False, - "message": "Missing required parameter: keyword" - }) - - # 创建ModelScope网关实例 - gateway = ModelScopeGateway() - - suggests = gateway.search(name=keyword) - - list = suggests["data"] if suggests.get("data") else [] - - return web.json_response({ - "success": True, - "data": { - "searchs": list, - "total": len(list) - }, - "message": f"Get searchs successfully" - }) - - except ImportError as e: - log.error(f"ModelScope SDK not installed: {str(e)}") - return web.json_response({ - "success": False, - "message": "ModelScope SDK not installed. Please install with: pip install modelscope" - }) - - except Exception as e: - log.error(f"Error get model searchs: {str(e)}") - import traceback - traceback.print_exc() - return web.json_response({ - "success": False, - "message": f"Get model searchs failed: {str(e)}" - }) - -@server.PromptServer.instance.routes.get("/api/model-paths") -async def model_paths(request): - """ - Get model paths by type - """ - log.info("Received model-paths request") - try: - model_paths = list(folder_paths.folder_names_and_paths.keys()) - return web.json_response({ - "success": True, - "data": { - "paths": model_paths, - }, - "message": f"Get paths successfully" - }) - - except Exception as e: - log.error(f"Error get model path: {str(e)}") - import traceback - traceback.print_exc() - return web.json_response({ - "success": False, - "message": f"Get model failed: {str(e)}" }) \ No newline at end of file diff --git a/backend/controller/model_api.py b/backend/controller/model_api.py new file mode 100644 index 0000000..bfebc96 --- /dev/null +++ b/backend/controller/model_api.py @@ -0,0 +1,468 @@ +import threading +import asyncio +import time +import server +from aiohttp import web +import os +import shutil +from ..utils.logger import log +from ..utils.modelscope_gateway import ModelScopeGateway +import folder_paths + + +# 全局下载进度存储 +download_progress = {} +download_lock = threading.Lock() + +# 下载进度回调类 +class DownloadProgressCallback: + def __init__(self, id: str, filename: str, file_size: int, download_id: str): + self.id = id + self.filename = filename + self.file_size = file_size + self.download_id = download_id + self.progress = 0 + self.status = "downloading" # downloading, completed, failed + self.error_message = None + self.start_time = time.time() + + # 初始化进度记录 + with download_lock: + download_progress[download_id] = { + "id": id, + "filename": filename, + "file_size": file_size, + "progress": 0, + "percentage": 0.0, + "status": "downloading", + "start_time": self.start_time, + "estimated_time": None, + "speed": 0.0, + "error_message": None + } + + def update(self, size: int): + """更新下载进度""" + self.progress += size + current_time = time.time() + elapsed_time = current_time - self.start_time + + # 计算下载速度和预估时间 + if elapsed_time > 0: + speed = self.progress / elapsed_time # bytes per second + if speed > 0 and self.progress < self.file_size: + remaining_bytes = self.file_size - self.progress + estimated_time = remaining_bytes / speed + else: + estimated_time = None + else: + speed = 0.0 + estimated_time = None + + percentage = (self.progress / self.file_size) * 100 if self.file_size > 0 else 0 + + # 更新全局进度 + with download_lock: + if self.download_id in download_progress: + # 直接更新字典的值,而不是调用update方法 + progress_dict = download_progress[self.download_id] + progress_dict["progress"] = self.progress + progress_dict["percentage"] = round(percentage, 2) + progress_dict["speed"] = round(speed, 2) + progress_dict["estimated_time"] = round(estimated_time, 2) if estimated_time else None + + def end(self, success: bool = True, error_message: str = None): + """下载结束回调""" + current_time = time.time() + total_time = current_time - self.start_time + + if success: + self.status = "completed" + # 验证下载完整性 + assert self.progress == self.file_size, f"Download incomplete: {self.progress}/{self.file_size}" + else: + self.status = "failed" + self.error_message = error_message + + # 更新最终状态 + with download_lock: + if self.download_id in download_progress: + # 直接更新字典的值,而不是调用update方法 + progress_dict = download_progress[self.download_id] + progress_dict["status"] = self.status + progress_dict["progress"] = self.file_size if success else self.progress + if self.file_size > 0: + progress_dict["percentage"] = 100.0 if success else (self.progress / self.file_size) * 100 + else: + progress_dict["percentage"] = 0.0 + progress_dict["total_time"] = round(total_time, 2) + progress_dict["error_message"] = self.error_message + + def fail(self, error_message: str): + """下载失败回调""" + self.end(success=False, error_message=error_message) + + +# 生成唯一下载ID +def generate_download_id() -> str: + import uuid + return str(uuid.uuid4()) + + +@server.PromptServer.instance.routes.post("/api/download-model") +async def download_model(request): + """ + Download model from ModelScope using SDK + """ + log.info("Received download-model request") + req_json = await request.json() + + try: + id = req_json.get('id') + model_id = req_json.get('model_id') + model_type = req_json.get('model_type') + dest_dir = req_json.get('dest_dir') + + # 验证必需参数 + if not id: + return web.json_response({ + "success": False, + "message": "Missing required parameter: id" + }) + + if not model_id: + return web.json_response({ + "success": False, + "message": "Missing required parameter: model_id" + }) + + if not model_type: + return web.json_response({ + "success": False, + "message": "Missing required parameter: model_type" + }) + + log.info(f"Downloading model: {model_id} (type: {model_type})") + + # 生成下载ID + download_id = generate_download_id() + + # 计算目标目录:优先使用传入的dest_dir,否则使用ComfyUI的models目录下对应类型 + resolved_dest_dir = None + if dest_dir: + resolved_dest_dir = os.path.abspath(os.path.expanduser(f"models/{dest_dir}")) + else: + try: + model_type_paths = folder_paths.get_folder_paths(model_type) + resolved_dest_dir = model_type_paths[0] if model_type_paths else os.path.join(folder_paths.models_dir, + model_type) + except Exception: + resolved_dest_dir = os.path.join(folder_paths.models_dir, model_type) + + # 创建进度回调 + progress_callback = DownloadProgressCallback( + id=id, + filename=f"{model_id}.{model_type}", + file_size=0, # 实际大小会在下载过程中获取 + download_id=download_id + ) + + # 启动下载任务(异步执行) + async def download_task(): + try: + # 调用下载方法 - 使用snapshot_download + from modelscope import snapshot_download + + # 创建进度回调包装器 - 实现ModelScope期望的接口 + class ProgressWrapper: + """Factory that returns a per-file progress object with update/end.""" + + def __init__(self, download_id: str): + self.download_id = download_id + + def __call__(self, file_name: str, file_size: int): + # Create a per-file progress tracker expected by ModelScope + download_id = self.download_id + + class _PerFileProgress: + def __init__(self, fname: str, fsize: int): + self.file_name = fname + self.file_size = max(int(fsize or 0), 0) + self.progress = 0 + self.last_update_time = time.time() + self.last_downloaded = 0 + with download_lock: + if download_id in download_progress: + # If unknown size, keep 0 to avoid div-by-zero + download_progress[download_id]["file_size"] = self.file_size + + def update(self, size: int): + try: + self.progress += int(size or 0) + now = time.time() + # Update global progress + with download_lock: + if download_id in download_progress: + dp = download_progress[download_id] + dp["progress"] = self.progress + if self.file_size > 0: + dp["percentage"] = round(self.progress * 100.0 / self.file_size, 2) + # speed + elapsed = max(now - self.last_update_time, 1e-6) + speed = (self.progress - self.last_downloaded) / elapsed + dp["speed"] = round(speed, 2) + self.last_update_time = now + self.last_downloaded = self.progress + except Exception as e: + log.error(f"Error in progress update: {e}") + + def end(self): + # Called by modelscope when a file finishes + with download_lock: + if download_id in download_progress: + dp = download_progress[download_id] + if self.file_size > 0: + dp["progress"] = self.file_size + dp["percentage"] = 100.0 + + return _PerFileProgress(file_name, file_size) + + progress_wrapper = ProgressWrapper(download_id) + + # 添加调试日志 + log.info(f"Starting download with progress wrapper: {download_id}") + + # 在线程中执行阻塞的下载,避免阻塞事件循环 + from functools import partial + local_dir = await asyncio.to_thread( + partial( + snapshot_download, + model_id=model_id, + cache_dir=resolved_dest_dir, + progress_callbacks=[progress_wrapper] + ) + ) + + # 下载完成 + progress_callback.end(success=True) + log.info(f"Model downloaded successfully to: {local_dir}") + + # 下载后遍历目录,将所有重要权重/资源文件移动到最外层(与目录同级,即 resolved_dest_dir) + try: + moved_count = 0 + allowed_exts = { + ".safetensors", ".ckpt", ".pt", ".pth", ".bin" + # ".msgpack", ".json", ".yaml", ".yml", ".toml", ".png", ".onnx" + } + for root, dirs, files in os.walk(local_dir): + for name in files: + ext = os.path.splitext(name)[1].lower() + if ext in allowed_exts: + src_path = os.path.join(root, name) + target_dir = resolved_dest_dir + os.makedirs(target_dir, exist_ok=True) + target_path = os.path.join(target_dir, name) + # 如果已经在目标目录则跳过 + if os.path.abspath(os.path.dirname(src_path)) == os.path.abspath(target_dir): + continue + # 处理重名情况:自动追加 _1, _2 ... + if os.path.exists(target_path): + base, ext_real = os.path.splitext(name) + idx = 1 + while True: + candidate = f"{base}_{idx}{ext_real}" + candidate_path = os.path.join(target_dir, candidate) + if not os.path.exists(candidate_path): + target_path = candidate_path + break + idx += 1 + shutil.move(src_path, target_path) + moved_count += 1 + log.info( + f"Moved {moved_count} files with extensions {sorted(list(allowed_exts))} to: {resolved_dest_dir}") + except Exception as move_err: + log.error(f"Post-download move failed: {move_err}") + + except Exception as e: + progress_callback.fail(str(e)) + log.error(f"Download failed: {str(e)}") + + # 启动异步下载任务 + asyncio.create_task(download_task()) + + return web.json_response({ + "success": True, + "data": { + "download_id": download_id, + "id": id, + "model_id": model_id, + "model_type": model_type, + "dest_dir": resolved_dest_dir, + "status": "started" + }, + "message": f"Download started for model '{model_id}'" + }) + + except ImportError as e: + log.error(f"ModelScope SDK not installed: {str(e)}") + return web.json_response({ + "success": False, + "message": "ModelScope SDK not installed. Please install with: pip install modelscope" + }) + + except Exception as e: + log.error(f"Error starting download: {str(e)}") + import traceback + traceback.print_exc() + return web.json_response({ + "success": False, + "message": f"Failed to start download: {str(e)}" + }) + + +@server.PromptServer.instance.routes.get("/api/download-progress/{download_id}") +async def get_download_progress(request): + """ + Get download progress by download ID + """ + download_id = request.match_info.get('download_id') + + if not download_id: + return web.json_response({ + "success": False, + "message": "Missing download_id parameter" + }) + + with download_lock: + progress_info = download_progress.get(download_id) + + if not progress_info: + return web.json_response({ + "success": False, + "message": f"Download ID {download_id} not found" + }) + + return web.json_response({ + "success": True, + "data": progress_info, + "message": "Download progress retrieved successfully" + }) + + +@server.PromptServer.instance.routes.get("/api/download-progress") +async def list_downloads(request): + """ + List all active downloads + """ + with download_lock: + downloads = list(download_progress.keys()) + + return web.json_response({ + "success": True, + "data": { + "downloads": downloads, + "count": len(downloads) + }, + "message": "Download list retrieved successfully" + }) + + +@server.PromptServer.instance.routes.delete("/api/download-progress/{download_id}") +async def clear_download_progress(request): + """ + Clear download progress record (for cleanup) + """ + download_id = request.match_info.get('download_id') + + if not download_id: + return web.json_response({ + "success": False, + "message": "Missing download_id parameter" + }) + + with download_lock: + if download_id in download_progress: + del download_progress[download_id] + return web.json_response({ + "success": True, + "message": f"Download progress {download_id} cleared successfully" + }) + else: + return web.json_response({ + "success": False, + "message": f"Download ID {download_id} not found" + }) + + +@server.PromptServer.instance.routes.get("/api/model-searchs") +async def model_suggests(request): + """ + Get model search list by keyword + """ + log.info("Received model-search request") + try: + keyword = request.query.get('keyword') + + if not keyword: + return web.json_response({ + "success": False, + "message": "Missing required parameter: keyword" + }) + + # 创建ModelScope网关实例 + gateway = ModelScopeGateway() + + suggests = gateway.search(name=keyword) + + list = suggests["data"] if suggests.get("data") else [] + + return web.json_response({ + "success": True, + "data": { + "searchs": list, + "total": len(list) + }, + "message": f"Get searchs successfully" + }) + + except ImportError as e: + log.error(f"ModelScope SDK not installed: {str(e)}") + return web.json_response({ + "success": False, + "message": "ModelScope SDK not installed. Please install with: pip install modelscope" + }) + + except Exception as e: + log.error(f"Error get model searchs: {str(e)}") + import traceback + traceback.print_exc() + return web.json_response({ + "success": False, + "message": f"Get model searchs failed: {str(e)}" + }) + + +@server.PromptServer.instance.routes.get("/api/model-paths") +async def model_paths(request): + """ + Get model paths by type + """ + log.info("Received model-paths request") + try: + model_paths = list(folder_paths.folder_names_and_paths.keys()) + return web.json_response({ + "success": True, + "data": { + "paths": model_paths, + }, + "message": f"Get paths successfully" + }) + + except Exception as e: + log.error(f"Error get model path: {str(e)}") + import traceback + traceback.print_exc() + return web.json_response({ + "success": False, + "message": f"Get model failed: {str(e)}" + }) \ No newline at end of file diff --git a/backend/service/all_in_one_agent.py b/backend/service/all_in_one_agent.py new file mode 100644 index 0000000..f26031a --- /dev/null +++ b/backend/service/all_in_one_agent.py @@ -0,0 +1,254 @@ +''' +All-in-one Single Agent for Chat + Debug + Rewrite (streaming) +''' +from typing import List, Dict, Any, Optional +import asyncio +import traceback + +from ..utils.globals import BACKEND_BASE_URL, get_comfyui_copilot_api_key, WORKFLOW_MODEL_NAME +from ..utils.logger import log +from ..utils.request_context import get_session_id, get_config +from ..utils.key_utils import workflow_config_adapt + +# OpenAI Agents SDK imports +try: + from agents._config import set_default_openai_api + from agents.items import ItemHelpers + from agents.mcp import MCPServerSse + from agents.run import Runner + from agents.tracing import set_tracing_disabled +except Exception: + raise ImportError( + "Detected incorrect or missing 'agents' package while loading All-in-one agent. " + "Please install 'openai-agents'. Commands:\n" + " python -m pip uninstall -y agents gym tensorflow\n" + " python -m pip install -U openai-agents" + ) + +from openai.types.responses import ResponseTextDeltaEvent + +# Import tools from existing modules +from .debug_agent import run_workflow, analyze_error_type, save_current_workflow +from .link_agent_tools import analyze_missing_connections, apply_connection_fixes +from .workflow_rewrite_tools import get_current_workflow, get_node_info, update_workflow, remove_node +from .parameter_tools import ( + find_matching_parameter_value, + get_model_files, + suggest_model_download, + update_workflow_parameter, +) + +from ..agent_factory import create_agent + + +async def all_in_one_invoke(messages: List[Dict[str, Any]], images: Optional[List[Any]] = None): + """ + Invoke a single agent that can handle chat, debug, and rewrite in one place. + + Yields tuples of (accumulated_text, {"data": ext_or_None, "finished": bool}). + """ + try: + session_id = get_session_id() + config = get_config() + if not session_id: + raise ValueError("No session_id found in request context") + if not config: + raise ValueError("No config found in request context") + + # Adapt config if needed (keys, endpoints, etc.) + config = workflow_config_adapt(config) + + # Prepare MCP servers to expose external tools (recall_workflow, gen_workflow, searches, etc.) + mcp_server = MCPServerSse( + params={ + "url": BACKEND_BASE_URL + "/mcp-server/mcp", + "timeout": 300.0, + "headers": {"X-Session-Id": session_id, "Authorization": f"Bearer {get_comfyui_copilot_api_key()}"} + }, + cache_tools_list=True, + client_session_timeout_seconds=300.0 + ) + + bing_server = MCPServerSse( + params={ + "url": "https://mcp.api-inference.modelscope.net/8c9fe550938e4f/sse", + "timeout": 300.0, + "headers": {"X-Session-Id": session_id, "Authorization": f"Bearer {get_comfyui_copilot_api_key()}"} + }, + cache_tools_list=True, + client_session_timeout_seconds=300.0 + ) + + async with mcp_server, bing_server: + agent = create_agent( + name="ComfyUI-AllInOne", + model=WORKFLOW_MODEL_NAME, + instructions=( + "You are a single powerful assistant for ComfyUI.\n\n" + "- Respond in the user's language.\n" + "- For workflow generation requests, ALWAYS call recall_workflow first, then gen_workflow, and merge results.\n" + "- For debug intents (workflow failed, node error): validate with run_workflow(), analyze with analyze_error_type(), then use link/parameter/rewrite tools accordingly and re-validate.\n" + "- For rewrite intents (modify current canvas): use get_current_workflow(), get_node_info(), update_workflow(), remove_node(), and ensure connections/types are valid.\n" + "- Prefer concise streaming updates.\n" + ), + # Bind ALL local tools + tools=[ + # Debug/validation + run_workflow, analyze_error_type, save_current_workflow, + # Link/connectivity + analyze_missing_connections, apply_connection_fixes, + # Rewrite/structure + get_current_workflow, get_node_info, update_workflow, remove_node, + # Parameters/models + find_matching_parameter_value, get_model_files, suggest_model_download, update_workflow_parameter, + ], + # Expose MCP tool servers for chat/search/workflow tools + mcp_servers=[mcp_server, bing_server], + config={ + "max_tokens": 8192, + **config + } + ) + + # Stream the session + agent_input = messages + result = Runner.run_streamed( + agent, + input=agent_input, + max_turns=30, + ) + + current_text = '' + last_yield_length = 0 + tool_results: Dict[str, Dict[str, Any]] = {} + tool_call_queue: List[str] = [] + workflow_update_ext = None # collect workflow_update/param_update ext from tools + + async for event in result.stream_events(): + if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): + delta_text = event.data.delta + if delta_text: + current_text += delta_text + if len(current_text) > last_yield_length: + last_yield_length = len(current_text) + yield (current_text, None) + continue + + if event.type == "run_item_stream_event": + if event.item.type == "tool_call_item": + tool_name = getattr(event.item.raw_item, 'name', 'unknown_tool') + tool_call_queue.append(tool_name) + log.info(f"[AllInOne] Tool called: {tool_name}") + continue + + if event.item.type == "tool_call_output_item": + tool_output_data_str = str(event.item.output) + # Associate with FIFO queue + if tool_call_queue: + tool_name = tool_call_queue.pop(0) + else: + tool_name = 'unknown_tool' + + # Try to parse output as JSON and capture ext + try: + import json + tool_output_data = json.loads(tool_output_data_str) + if "ext" in tool_output_data and tool_output_data["ext"]: + tool_ext_items = tool_output_data["ext"] + # capture any workflow_update/param_update; keep entire list + for ext_item in tool_ext_items: + if ext_item.get("type") in ["workflow_update", "param_update"]: + workflow_update_ext = tool_ext_items + log.info(f"[AllInOne] Captured workflow-related ext from tool '{tool_name}'") + break + + if "text" in tool_output_data and tool_output_data.get('text'): + parsed_output = json.loads(tool_output_data['text']) + if isinstance(parsed_output, dict): + answer = parsed_output.get("answer") + data = parsed_output.get("data") + tool_ext = parsed_output.get("ext") + else: + answer = None + data = parsed_output if isinstance(parsed_output, list) else None + tool_ext = None + + tool_results[tool_name] = { + "answer": answer, + "data": data, + "ext": tool_ext, + "content_dict": parsed_output + } + except Exception: + # Non-JSON output; store raw preview + tool_results[tool_name] = { + "answer": tool_output_data_str, + "data": None, + "ext": None, + "content_dict": None + } + continue + + # Post-stream processing: merge workflow tool results if present + ext = None + finished = True + + workflow_tools_found = [t for t in ["recall_workflow", "gen_workflow"] if t in tool_results] + if workflow_tools_found: + if "recall_workflow" in tool_results and "gen_workflow" in tool_results: + successful_workflows: List[Dict[str, Any]] = [] + recall_result = tool_results["recall_workflow"] + gen_result = tool_results["gen_workflow"] + if recall_result.get("data"): + successful_workflows.extend(recall_result["data"]) + if gen_result.get("data"): + # prioritize generated ones first + successful_workflows = list(gen_result["data"]) + successful_workflows + + # de-duplicate by id + seen_ids = set() + unique_workflows = [] + for wf in successful_workflows: + wf_id = wf.get('id') + if wf_id and wf_id not in seen_ids: + seen_ids.add(wf_id) + unique_workflows.append(wf) + elif not wf_id: + unique_workflows.append(wf) + + if unique_workflows: + ext = [{"type": "workflow", "data": unique_workflows}] + elif "gen_workflow" in tool_results: + gen_result = tool_results["gen_workflow"] + if gen_result.get("data"): + ext = [{"type": "workflow", "data": gen_result["data"]}] + else: + # only recall_workflow was called; keep unfinished to encourage gen_workflow next time + ext = None + finished = False + + # Include any workflow_update/param_update ext captured during tool calls + final_ext = ext + if workflow_update_ext: + if isinstance(workflow_update_ext, list): + final_ext = workflow_update_ext + (ext if ext else []) + else: + final_ext = [workflow_update_ext] + (ext if ext else []) + + ext_with_finished = {"data": final_ext, "finished": finished} + yield (current_text, ext_with_finished) + + except Exception as e: + log.error(f"Error in all_in_one_invoke: {str(e)}") + log.error(f"Traceback: {traceback.format_exc()}") + error_message = f"I apologize, but an error occurred while processing your request: {str(e)}" + yield (error_message, {"data": None, "finished": True}) + +''' +Author: ai-business-hql ai.bussiness.hql@gmail.com +Date: 2025-10-29 16:51:18 +LastEditors: ai-business-hql ai.bussiness.hql@gmail.com +LastEditTime: 2025-10-29 17:01:17 +FilePath: /ComfyUI-Copilot/backend/service/all_in_one_agent.py +Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE +''' diff --git a/backend/service/debug_agent.py b/backend/service/debug_agent.py index d9c5f09..ab36cec 100644 --- a/backend/service/debug_agent.py +++ b/backend/service/debug_agent.py @@ -1,6 +1,8 @@ ''' Debug Agent for ComfyUI Workflow Error Analysis ''' +import json +from typing import Dict, Any from ..utils.key_utils import workflow_config_adapt from ..agent_factory import create_agent from agents.items import ItemHelpers @@ -706,6 +708,200 @@ Start by validating the workflow to see its current state.""", yield (error_message, ext_with_finished) +async def debug_workflow_errors_single(workflow_data: Dict[str, Any]): + """ + Analyze and debug workflow errors using a single-agent architecture. + The single agent has access to all tools used across the multi-agent system + and iteratively validates, analyzes, fixes, and re-validates until success or limits. + + Args: + workflow_data: Current workflow data from app.graphToPrompt() + + Yields: + tuple: (text, ext) where text is accumulated text and ext is structured data + """ + try: + session_id = get_session_id() + config = get_config() + config = workflow_config_adapt(config) + + if not session_id: + session_id = str(uuid.uuid4()) + + # Save initial workflow snapshot + log.info(f"[SingleAgent] Saving workflow data for session {session_id}") + save_result = save_workflow_data( + session_id, + workflow_data, + attributes={"action": "debug_start_single", "description": "Initial workflow save for single-agent debugging"} + ) + log.info(f"[SingleAgent] Workflow saved with version ID: {save_result}") + + single_agent = create_agent( + name="ComfyUI-Debug-SingleAgent", + instructions=f""" +You are a single ComfyUI workflow debugging expert with access to all specialized tools. + +Your iterative loop (up to 10 cycles): +1) Validate workflow using run_workflow() +2) If errors: analyze with analyze_error_type() and decide fix strategy + - Connection errors: use analyze_missing_connections() then apply_connection_fixes() + - Parameter errors: use find_matching_parameter_value(), get_model_files(), update_workflow_parameter() + • For model downloads required: use suggest_model_download() and STOP (final response) + - Structural issues: use get_current_workflow(), get_node_info(), update_workflow() +3) After any fix, immediately re-run run_workflow() to verify +4) Repeat until validation succeeds or loop limit reached + +Guidelines: +- Be concise and stream updates during the process +- Prefer high-confidence fixes first; add nodes only when necessary +- Do not modify unrelated parameters +- Language: {get_language()} +""", + model=WORKFLOW_MODEL_NAME, + tools=[ + # Coordinator tools + run_workflow, analyze_error_type, save_current_workflow, + # Link/structure tools + analyze_missing_connections, apply_connection_fixes, get_current_workflow, get_node_info, update_workflow, + # Parameter tools + find_matching_parameter_value, get_model_files, suggest_model_download, update_workflow_parameter, + ], + config={ + "max_tokens": 8192, + **config + } + ) + + messages = [{"role": "user", "content": "Validate and debug this ComfyUI workflow using the iterative loop until success."}] + + log.info(f"[SingleAgent] Starting validation process for session {session_id}") + result = Runner.run_streamed( + single_agent, + input=messages, + max_turns=30, + ) + + current_text = '' + current_agent = "ComfyUI-Debug-SingleAgent" + last_yielded_length = 0 + debug_events = [] + workflow_update_ext = None + + async for event in result.stream_events(): + if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): + delta_text = event.data.delta + if delta_text: + current_text += delta_text + if len(current_text) > last_yielded_length: + last_yielded_length = len(current_text) + yield (current_text, None) + elif event.type == "run_item_stream_event": + item_updated = False + if event.item.type == "tool_call_item": + tool_name = getattr(event.item.raw_item, 'name', 'unknown_tool') + log.info(f"[SingleAgent] -- Tool called: {tool_name}") + current_text += f"\n\n⚙ *{current_agent} is using {tool_name}...*\n\n" + item_updated = True + debug_events.append({ + "type": "tool_call", + "tool": tool_name, + "agent": current_agent, + "timestamp": len(current_text) + }) + elif event.item.type == "tool_call_output_item": + output = str(event.item.output) + output_preview = output[:200] + "..." if len(output) > 200 else output + current_text += f"\n\n● *Tool execution completed*\n\n```\n{output_preview}\n```\n\n" + item_updated = True + try: + tool_output_json = json.loads(output) + if "ext" in tool_output_json and tool_output_json["ext"]: + for ext_item in tool_output_json["ext"]: + if ext_item.get("type") == "workflow_update" or ext_item.get("type") == "param_update": + workflow_update_ext = ext_item + log.info(f"[SingleAgent] -- Captured {ext_item.get('type')} ext, yielding immediately") + ext_with_finished = {"data": [ext_item], "finished": False} + yield (current_text, ext_with_finished) + break + except (json.JSONDecodeError, TypeError): + pass + debug_events.append({ + "type": "tool_result", + "output_preview": output_preview, + "agent": current_agent, + "timestamp": len(current_text) + }) + elif event.item.type == "message_output_item": + try: + message_content = ItemHelpers.text_message_output(event.item) + if message_content and message_content.strip(): + if message_content not in current_text: + current_text += f"\n\n{message_content}\n\n" + item_updated = True + debug_events.append({ + "type": "message_complete", + "content_length": len(message_content), + "agent": current_agent, + "timestamp": len(current_text) + }) + except Exception as e: + log.error(f"[SingleAgent] Error processing message output: {str(e)}") + if item_updated: + last_yielded_length = len(current_text) + yield (current_text, None) + + log.info("[SingleAgent] === Debug process complete ===") + + debug_completion_checkpoint_id = None + try: + current_workflow = get_workflow_data(session_id) + if current_workflow: + debug_completion_checkpoint_id = save_workflow_data( + session_id, + current_workflow, + workflow_data_ui=None, + attributes={ + "checkpoint_type": "debug_complete", + "description": "Workflow state after single-agent debug completion", + "action": "debug_complete_single", + "final_agent": current_agent + } + ) + log.info(f"[SingleAgent] Debug completion checkpoint saved with ID: {debug_completion_checkpoint_id}") + except Exception as checkpoint_error: + log.error(f"[SingleAgent] Failed to save debug completion checkpoint: {checkpoint_error}") + + debug_ext = [{ + "type": "debug_complete", + "data": { + "status": "completed", + "final_agent": current_agent, + "events": debug_events, + "total_events": len(debug_events) + } + }] + if debug_completion_checkpoint_id: + debug_ext.append({ + "type": "debug_checkpoint", + "data": { + "checkpoint_id": debug_completion_checkpoint_id, + "checkpoint_type": "debug_complete" + } + }) + final_ext = debug_ext + if workflow_update_ext: + final_ext = [workflow_update_ext] + debug_ext + log.info("[SingleAgent] -- Including workflow_update ext in final response") + ext_with_finished = {"data": final_ext, "finished": True} + yield (current_text, ext_with_finished) + except Exception as e: + log.error(f"[SingleAgent] Error in debug_workflow_errors_single: {str(e)}") + error_message = f"\n\n× Error occurred during single-agent debugging: {str(e)}\n\n" + ext_with_finished = {"finished": True} + yield (error_message, ext_with_finished) + + # Test function async def test_debug(): """Test the debug agent with a sample workflow""" diff --git a/dist/copilot_web/App-fluNqnYs.js b/dist/copilot_web/App-TDLVaCDl.js similarity index 87% rename from dist/copilot_web/App-fluNqnYs.js rename to dist/copilot_web/App-TDLVaCDl.js index 64cb8cc..e821a48 100644 --- a/dist/copilot_web/App-fluNqnYs.js +++ b/dist/copilot_web/App-TDLVaCDl.js @@ -1,7 +1,7 @@ function getImportPath(filename) { return `./${filename}`; } - const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-CTj3qusy.js","copilot_web/vendor-markdown-B4Av9P7l.js","copilot_web/vendor-react-ByKzdfMq.js","copilot_web/message-components-CzGdQ9TQ.js","copilot_web/input.js","copilot_web/assets/input-UcJyCCDl.css","copilot_web/fonts.css"].map(path => { + const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-DCaYfVyA.js","copilot_web/vendor-markdown-B4Av9P7l.js","copilot_web/vendor-react-ByKzdfMq.js","copilot_web/message-components-CDlGtWLl.js","copilot_web/input.js","copilot_web/assets/input-UcJyCCDl.css","copilot_web/fonts.css"].map(path => { const apiBase = window.comfyAPI?.api?.api?.api_base; if (apiBase) { // 有 API base 时,使用完整路径 @@ -11,4 +11,4 @@ function getImportPath(filename) { return `./${path}`; } }))))=>i.map(i=>d[i]); -import{_ as a}from"./input.js";import{j as o}from"./vendor-markdown-B4Av9P7l.js";import{r as t,R as i}from"./vendor-react-ByKzdfMq.js";import{C as n}from"./message-components-CzGdQ9TQ.js";const s={EXPLAIN_NODE:"copilot:explain-node",TOOLBOX_USAGE:"copilot:toolbox-usage",TOOLBOX_PARAMETERS:"copilot:toolbox-parameters",TOOLBOX_DOWNSTREAMNODES:"copilot:toolbox-downstreamnodes"},d=i.lazy(()=>a(()=>import(getImportPath("workflowChat-CTj3qusy.js")).then(e=>e.w),__vite__mapDeps([0,1,2,3,4,5,6])).then(e=>({default:e.default})));function c(){const[e,r]=t.useState(!1);return t.useEffect(()=>{const l=()=>{r(!0)};return window.addEventListener(s.EXPLAIN_NODE,l),()=>window.removeEventListener(s.EXPLAIN_NODE,l)},[]),o.jsx(n,{children:o.jsx("div",{className:"h-full w-full flex flex-col",children:o.jsx(t.Suspense,{fallback:o.jsx("div",{className:"h-full w-full flex items-center justify-center",children:"Loading..."}),children:o.jsx(d,{visible:!0,triggerUsage:e,onUsageTriggered:()=>r(!1)})})})})}const O=Object.freeze(Object.defineProperty({__proto__:null,default:c},Symbol.toStringTag,{value:"Module"}));export{O as A,s as C}; +import{_ as a}from"./input.js";import{j as o}from"./vendor-markdown-B4Av9P7l.js";import{r as t,R as i}from"./vendor-react-ByKzdfMq.js";import{C as n}from"./message-components-CDlGtWLl.js";const s={EXPLAIN_NODE:"copilot:explain-node",TOOLBOX_USAGE:"copilot:toolbox-usage",TOOLBOX_PARAMETERS:"copilot:toolbox-parameters",TOOLBOX_DOWNSTREAMNODES:"copilot:toolbox-downstreamnodes"},d=i.lazy(()=>a(()=>import(getImportPath("workflowChat-DCaYfVyA.js")).then(e=>e.w),__vite__mapDeps([0,1,2,3,4,5,6])).then(e=>({default:e.default})));function c(){const[e,r]=t.useState(!1);return t.useEffect(()=>{const l=()=>{r(!0)};return window.addEventListener(s.EXPLAIN_NODE,l),()=>window.removeEventListener(s.EXPLAIN_NODE,l)},[]),o.jsx(n,{children:o.jsx("div",{className:"h-full w-full flex flex-col",children:o.jsx(t.Suspense,{fallback:o.jsx("div",{className:"h-full w-full flex items-center justify-center",children:"Loading..."}),children:o.jsx(d,{visible:!0,triggerUsage:e,onUsageTriggered:()=>r(!1)})})})})}const O=Object.freeze(Object.defineProperty({__proto__:null,default:c},Symbol.toStringTag,{value:"Module"}));export{O as A,s as C}; diff --git a/dist/copilot_web/DebugGuide-BpkLL6XH.js b/dist/copilot_web/DebugGuide-RaSXIzC5.js similarity index 98% rename from dist/copilot_web/DebugGuide-BpkLL6XH.js rename to dist/copilot_web/DebugGuide-RaSXIzC5.js index 0498837..8605f8b 100644 --- a/dist/copilot_web/DebugGuide-BpkLL6XH.js +++ b/dist/copilot_web/DebugGuide-RaSXIzC5.js @@ -1,5 +1,5 @@ function getImportPath(filename) { return `./${filename}`; } - import{j as s}from"./vendor-markdown-B4Av9P7l.js";import{r as i}from"./vendor-react-ByKzdfMq.js";import{u as A,p as E,R as D,o as m,W as f,a as b}from"./message-components-CzGdQ9TQ.js";function P({content:h,name:k="Assistant",avatar:O,onAddMessage:y,onUpdateMessage:c,messageId:_}){const{dispatch:u,abortControllerRef:l}=A(),[d,w]=i.useState(!1),[T,G]=i.useState(""),[J,S]=i.useState(!1),[j,v]=i.useState(null),r=i.useMemo(()=>{try{return JSON.parse(h)}catch(e){return console.error("Failed to parse message content:",e),null}},[h]),x=i.useMemo(()=>{if(!r||!r.ext)return null;const e=r.ext.find(t=>t.type==="debug_start_checkpoint"||t.type==="debug_checkpoint"&&t.data?.checkpoint_type==="debug_start");return e&&e.data&&e.data.checkpoint_id?e.data.checkpoint_id:null},[r])||j,N=async()=>{if(d)return;const e=m(),t={id:e,role:"ai",content:JSON.stringify({text:`🔍 Starting workflow analysis... + import{j as s}from"./vendor-markdown-B4Av9P7l.js";import{r as i}from"./vendor-react-ByKzdfMq.js";import{u as A,p as E,R as D,o as m,W as f,a as b}from"./message-components-CDlGtWLl.js";function P({content:h,name:k="Assistant",avatar:O,onAddMessage:y,onUpdateMessage:c,messageId:_}){const{dispatch:u,abortControllerRef:l}=A(),[d,w]=i.useState(!1),[T,G]=i.useState(""),[J,S]=i.useState(!1),[j,v]=i.useState(null),r=i.useMemo(()=>{try{return JSON.parse(h)}catch(e){return console.error("Failed to parse message content:",e),null}},[h]),x=i.useMemo(()=>{if(!r||!r.ext)return null;const e=r.ext.find(t=>t.type==="debug_start_checkpoint"||t.type==="debug_checkpoint"&&t.data?.checkpoint_type==="debug_start");return e&&e.data&&e.data.checkpoint_id?e.data.checkpoint_id:null},[r])||j,N=async()=>{if(d)return;const e=m(),t={id:e,role:"ai",content:JSON.stringify({text:`🔍 Starting workflow analysis... `,ext:[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};y?.(t);try{f.trackEvent({event_type:"debug_trigger",message_type:"debug",message_id:e,data:{}}),await C(),u({type:"SET_LOADING",payload:!0}),await I(e)}finally{w(!1)}},C=async()=>{try{const e=await b.graphToPrompt(),t=localStorage.getItem("sessionId")||"";if(t&&e){const n=await f.saveWorkflowCheckpoint(t,e.output,e.workflow,"debug_start");if(v(n.version_id),console.log(`Saved debug start checkpoint: ${n.version_id}`),c&&r){const o=[...r.ext||[]].filter(g=>g.type!=="debug_start_checkpoint"&&!(g.type==="debug_checkpoint"&&g.data?.checkpoint_type==="debug_start"));o.push({type:"debug_start_checkpoint",data:{checkpoint_id:n.version_id,checkpoint_type:"debug_start"}});const p={id:_||m(),role:"ai",content:JSON.stringify({text:r.text,ext:o}),format:"debug_guide",name:"Assistant"};c(p)}}}catch(e){console.error("Failed to save checkpoint before debug:",e)}},I=async e=>{try{const t=await b.graphToPrompt();let n="",a=null;l&&(l.current=new AbortController);for await(const o of f.streamDebugAgent(t,l?.current?.signal||void 0))if(o.text){n=o.text,o.ext&&(a=o.ext);const p={id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};c?.(p)}c?.({id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!0,debugGuide:!0}),u({type:"SET_LOADING",payload:!1}),l.current=null}catch(t){console.error("Error calling debug agent:",t),S(!1);const a={id:e,role:"ai",content:JSON.stringify({text:`I encountered an error while analyzing your workflow: ${t.message||"Unknown error"}`,ext:[]}),format:"markdown",name:"Assistant",finished:!0};c?.(a),u({type:"SET_LOADING",payload:!1}),l.current=null}};return r?s.jsx(E,{name:k,children:s.jsxs("div",{className:"bg-gray-100 pt-4 px-4 pb-3 rounded-lg",children:[s.jsx("div",{className:"flex justify-between items-start",children:s.jsx("p",{className:"text-gray-700 text-sm flex-1",children:r.text})}),s.jsx("div",{className:"flex justify-end mt-4",children:s.jsx("button",{onClick:N,disabled:d,className:`debug-btn bg-debug-btn text-sm text-[#fff] rounded-lg px-4 py-2 ${d?"cursor-not-allowed":"cursor-pointer"}`,children:d?"Analyzing...":"Debug Errors"})}),s.jsx("div",{className:"flex justify-end mt-2",children:!!x&&s.jsx("div",{className:"ml-2 flex-shrink-0",children:s.jsx(D,{checkpointId:x,onRestore:()=>{console.log("Workflow restored from checkpoint")}})})})]})}):null}export{P as DebugGuide}; diff --git a/dist/copilot_web/DebugResult-CWUJVPnw.js b/dist/copilot_web/DebugResult-DhequTBk.js similarity index 95% rename from dist/copilot_web/DebugResult-CWUJVPnw.js rename to dist/copilot_web/DebugResult-DhequTBk.js index f2d4d90..ec3b49c 100644 --- a/dist/copilot_web/DebugResult-CWUJVPnw.js +++ b/dist/copilot_web/DebugResult-DhequTBk.js @@ -1,4 +1,4 @@ function getImportPath(filename) { return `./${filename}`; } - import{j as e}from"./vendor-markdown-B4Av9P7l.js";import{b as u,c as w,p as g,G as k,R as j}from"./message-components-CzGdQ9TQ.js";import{r as p}from"./vendor-react-ByKzdfMq.js";import{B as v,M as N}from"./workflowChat-CTj3qusy.js";import"./input.js";/* empty css */import"./App-fluNqnYs.js";const y=n=>{const{title:a="",isWorkflowUpdate:f=!1,className:d="",children:c}=n,[i,r]=p.useState(!1);return e.jsx(v,{className:"rounded-lg ",borderClassName:"rounded-lg",children:e.jsxs("div",{className:`flex flex-col ${d} ${i?"":"max-h-[200px]"}`,children:[e.jsxs("div",{className:"flex justify-between items-center pb-2 border-b border-gray-100",children:[e.jsx("div",{children:typeof a=="string"?e.jsx("h3",{className:"text-sm text-[#fff] font-medium",children:a}):a}),e.jsx("button",{onClick:()=>{r(!i)},children:i?e.jsx(u,{className:"text-gray-700"}):e.jsx(w,{className:"text-gray-700"})})]}),e.jsx("div",{className:"overflow-hidden flex-1",children:c})]})})};function E({content:n,name:a="Assistant",avatar:f,format:d="markdown"}){const c=p.useRef(null),i=()=>{let r=null,l=!1,o,x=[];try{if(o=JSON.parse(n),o.ext){let t=o.ext.find(s=>s.type==="workflow_rewrite_checkpoint"||s.type==="debug_checkpoint"&&s.data?.checkpoint_type==="workflow_rewrite_start");t&&t.data&&t.data.checkpoint_id?(r=t.data.checkpoint_id,l=!0):(t=o.ext.find(s=>s.type==="workflow_rewrite_complete"),t&&t.data&&t.data.version_id?(r=t.data.version_id,l=!0):(t=o.ext.find(s=>s.type==="debug_checkpoint"),t&&t.data&&t.data.checkpoint_id&&(r=t.data.checkpoint_id,l=!1))),o.ext.find(s=>s.type==="workflow_update")&&(l=!0),x=o.ext.find(s=>s.type==="param_update")?.data?.model_suggest||[]}}catch(t){return console.error("Failed to parse DebugResult content:",t),null}const h=l?e.jsxs("div",{className:"flex items-center text-green-500",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",clipRule:"evenodd"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Successfully"})]}):e.jsxs("div",{className:"flex items-center text-gray-900",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"28108",fill:"currentColor",children:e.jsx("path",{d:"M401.048025 844.855924c0 20.341281 16.643052 36.984333 36.984333 36.984333l147.936307 0c20.341281 0 36.984333-16.643052 36.984333-36.984333L622.952998 807.872614 401.048025 807.872614 401.048025 844.855924zM512 142.159744c-142.943596 0-258.888282 115.944686-258.888282 258.888282 0 88.021729 44.011376 165.503405 110.951975 212.288964l0 83.58365c0 20.341281 16.643052 36.984333 36.984333 36.984333l221.903949 0c20.341281 0 36.984333-16.643052 36.984333-36.984333l0-83.58365c66.941622-46.784536 110.951975-124.266212 110.951975-212.288964C770.888282 258.104429 654.943596 142.159744 512 142.159744zM617.588827 552.682561l-31.621185 22.005176 0 85.248569L438.031335 659.936307l0-85.063351L406.41015 552.866756c-49.743938-34.764781-79.33079-91.350544-79.33079-151.634536 0-101.890598 83.029018-184.92064 184.92064-184.92064s184.92064 83.029018 184.92064 184.92064C696.919617 461.332017 667.332764 517.91778 617.588827 552.682561z","p-id":"28277"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Finished"})]}),m=l?e.jsx("div",{className:"mt-3 text-xs text-gray-700",children:"💡 If you're not satisfied with the changes, click the restore button to revert to the previous version."}):null;return e.jsxs("div",{ref:c,className:"sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden",children:[e.jsx(y,{title:h,isWorkflowUpdate:l,className:"p-4",children:e.jsxs("div",{className:"prose prose-sm max-w-none",children:[d==="markdown"?e.jsx(k,{response:o||{}}):e.jsx("pre",{className:"whitespace-pre-wrap text-gray-700 text-sm leading-relaxed h-full",children:o?.text||""}),m]})}),x?.length>0&&e.jsx(N,{modelList:x,showPagination:!1}),e.jsx("div",{className:"flex justify-end mt-2",children:!!r&&e.jsx("div",{className:"ml-2 flex-shrink-0",children:e.jsx(j,{checkpointId:r,onRestore:()=>{console.log(`Workflow restored from ${l?"workflow update":"debug"} checkpoint`)},title:l?`Restore to this version (Version ${r})`:`Restore checkpoint ${r}`})})})]})};return e.jsx(g,{name:a,children:i()})}export{E as DebugResult}; + import{j as e}from"./vendor-markdown-B4Av9P7l.js";import{b as u,c as w,p as g,G as k,R as j}from"./message-components-CDlGtWLl.js";import{r as p}from"./vendor-react-ByKzdfMq.js";import{B as v,M as N}from"./workflowChat-DCaYfVyA.js";import"./input.js";/* empty css */import"./App-TDLVaCDl.js";const y=n=>{const{title:a="",isWorkflowUpdate:f=!1,className:d="",children:c}=n,[i,r]=p.useState(!1);return e.jsx(v,{className:"rounded-lg ",borderClassName:"rounded-lg",children:e.jsxs("div",{className:`flex flex-col ${d} ${i?"":"max-h-[200px]"}`,children:[e.jsxs("div",{className:"flex justify-between items-center pb-2 border-b border-gray-100",children:[e.jsx("div",{children:typeof a=="string"?e.jsx("h3",{className:"text-sm text-[#fff] font-medium",children:a}):a}),e.jsx("button",{onClick:()=>{r(!i)},children:i?e.jsx(u,{className:"text-gray-700"}):e.jsx(w,{className:"text-gray-700"})})]}),e.jsx("div",{className:"overflow-hidden flex-1",children:c})]})})};function E({content:n,name:a="Assistant",avatar:f,format:d="markdown"}){const c=p.useRef(null),i=()=>{let r=null,l=!1,o,x=[];try{if(o=JSON.parse(n),o.ext){let t=o.ext.find(s=>s.type==="workflow_rewrite_checkpoint"||s.type==="debug_checkpoint"&&s.data?.checkpoint_type==="workflow_rewrite_start");t&&t.data&&t.data.checkpoint_id?(r=t.data.checkpoint_id,l=!0):(t=o.ext.find(s=>s.type==="workflow_rewrite_complete"),t&&t.data&&t.data.version_id?(r=t.data.version_id,l=!0):(t=o.ext.find(s=>s.type==="debug_checkpoint"),t&&t.data&&t.data.checkpoint_id&&(r=t.data.checkpoint_id,l=!1))),o.ext.find(s=>s.type==="workflow_update")&&(l=!0),x=o.ext.find(s=>s.type==="param_update")?.data?.model_suggest||[]}}catch(t){return console.error("Failed to parse DebugResult content:",t),null}const h=l?e.jsxs("div",{className:"flex items-center text-green-500",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",clipRule:"evenodd"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Successfully"})]}):e.jsxs("div",{className:"flex items-center text-gray-900",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"28108",fill:"currentColor",children:e.jsx("path",{d:"M401.048025 844.855924c0 20.341281 16.643052 36.984333 36.984333 36.984333l147.936307 0c20.341281 0 36.984333-16.643052 36.984333-36.984333L622.952998 807.872614 401.048025 807.872614 401.048025 844.855924zM512 142.159744c-142.943596 0-258.888282 115.944686-258.888282 258.888282 0 88.021729 44.011376 165.503405 110.951975 212.288964l0 83.58365c0 20.341281 16.643052 36.984333 36.984333 36.984333l221.903949 0c20.341281 0 36.984333-16.643052 36.984333-36.984333l0-83.58365c66.941622-46.784536 110.951975-124.266212 110.951975-212.288964C770.888282 258.104429 654.943596 142.159744 512 142.159744zM617.588827 552.682561l-31.621185 22.005176 0 85.248569L438.031335 659.936307l0-85.063351L406.41015 552.866756c-49.743938-34.764781-79.33079-91.350544-79.33079-151.634536 0-101.890598 83.029018-184.92064 184.92064-184.92064s184.92064 83.029018 184.92064 184.92064C696.919617 461.332017 667.332764 517.91778 617.588827 552.682561z","p-id":"28277"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Finished"})]}),m=l?e.jsx("div",{className:"mt-3 text-xs text-gray-700",children:"💡 If you're not satisfied with the changes, click the restore button to revert to the previous version."}):null;return e.jsxs("div",{ref:c,className:"sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden",children:[e.jsx(y,{title:h,isWorkflowUpdate:l,className:"p-4",children:e.jsxs("div",{className:"prose prose-sm max-w-none",children:[d==="markdown"?e.jsx(k,{response:o||{}}):e.jsx("pre",{className:"whitespace-pre-wrap text-gray-700 text-sm leading-relaxed h-full",children:o?.text||""}),m]})}),x?.length>0&&e.jsx(N,{modelList:x,showPagination:!1}),e.jsx("div",{className:"flex justify-end mt-2",children:!!r&&e.jsx("div",{className:"ml-2 flex-shrink-0",children:e.jsx(j,{checkpointId:r,onRestore:()=>{console.log(`Workflow restored from ${l?"workflow update":"debug"} checkpoint`)},title:l?`Restore to this version (Version ${r})`:`Restore checkpoint ${r}`})})})]})};return e.jsx(g,{name:a,children:i()})}export{E as DebugResult}; diff --git a/dist/copilot_web/WorkflowOption-CdGtQvHG.js b/dist/copilot_web/WorkflowOption-Co7ClWpe.js similarity index 97% rename from dist/copilot_web/WorkflowOption-CdGtQvHG.js rename to dist/copilot_web/WorkflowOption-Co7ClWpe.js index a3c0428..ce0c550 100644 --- a/dist/copilot_web/WorkflowOption-CdGtQvHG.js +++ b/dist/copilot_web/WorkflowOption-Co7ClWpe.js @@ -1,4 +1,4 @@ function getImportPath(filename) { return `./${filename}`; } - import{j as t}from"./vendor-markdown-B4Av9P7l.js";import{D,W as _,o as C,a as d}from"./message-components-CzGdQ9TQ.js";import{r as h}from"./vendor-react-ByKzdfMq.js";import{A as G}from"./workflowChat-CTj3qusy.js";import"./input.js";/* empty css */import"./App-fluNqnYs.js";function Y({content:v,name:J="Assistant",avatar:P,latestInput:N,installedNodes:A,onAddMessage:y}){const[f,g]=h.useState({}),[E,W]=h.useState(null),[b,M]=h.useState([]);h.useEffect(()=>{const e=JSON.parse(v);W(e),M(e.ext?.find(a=>a.type==="workflow")?.data||[])},[v]);const I=async e=>{if(!e.id){console.error("No workflow id provided");return}const a=String(e.id);if(!f[a]){g(s=>({...s,[a]:!0})),_.trackEvent({event_type:"workflow_accept",message_type:"workflow",message_id:E?.message_id,data:{workflow_id:e.id,workflow_name:e.name}}),window.dispatchEvent(new CustomEvent(G,{}));try{const s=await _.getOptimizedWorkflow(e.id,N);if(s.workflow){const i=new Set;if(s.workflow.nodes)for(const o of s.workflow.nodes)i.add(o.type);else for(const o of Object.values(s.workflow))i.add(o.class_type);const l=Array.from(i).filter(o=>!A.includes(o));if(console.log("[WorkflowOption] Missing node types:",l),l.length>0){try{console.log("[WorkflowOption] Fetching info for missing nodes");const o=await _.batchGetNodeInfo(l);console.log("[WorkflowOption] Received node infos:",o);const p={text:"",ext:[{type:"node_install_guide",data:o.map(r=>({name:r.name,repository_url:r.github_url}))}]},c={id:C(),role:"ai",content:JSON.stringify(p),format:"markdown",name:"Assistant",metadata:{pendingWorkflow:s.workflow,optimizedParams:s.optimized_params}};y?.(c)}catch(o){console.error("[WorkflowOption] Error fetching node info:",o),j(s.workflow,s.optimized_params)}finally{g(o=>({...o,[a]:!1}))}return}j(s.workflow,s.optimized_params)}}catch(s){console.error("Failed to optimize workflow:",s),alert("Failed to optimize workflow. Please try again.")}finally{g(s=>({...s,[a]:!1}))}}},j=(e,a)=>{if(e.nodes)d.loadGraphData(e);else{d.loadApiJson(e);const i=Object.keys(e),l=Object.keys(d.graph._nodes_by_id)[0],o=d.graph._nodes_by_id[l],p=o?o.pos[0]:0,c=o?o.pos[1]:0,r=250,m=60,S=20,F=60,k=50,H=1e3;let z=p,w=c,x=0;for(const T of i){const n=d.graph._nodes_by_id[T];if(n){x>H&&(z+=r+F,x=0,w=c);const V=n.inputs?n.inputs.length:0,L=n.outputs?n.outputs.length:0,q=n.widgets?n.widgets.length:0,B=Math.max(V,L)+q,u=S*B+m;n.size[0]=r,n.size[1]=u,n.pos[0]=z,n.pos[1]=w,x+=u+k,w+=u+k}}}for(const[i,l,o,p,c]of a){const r=d.graph._nodes_by_id[i].widgets;for(const m of r)m.name===p&&(m.value=c)}d.graph.setDirtyCanvas(!1,!0);const s={id:C(),role:"tool",content:JSON.stringify({text:"The workflow has been successfully loaded to the canvas",ext:[]}),format:"markdown",name:"Assistant"};y?.(s)},O=(e,a)=>{const s=e.id?String(e.id):"",i=e?.source==="AI Generated";return t.jsxs("div",{className:`relative flex flex-col items-center gap-4 p-2 rounded-lg border ${i?"shadow-[0_0_12px_2px_#3b82f6] shadow-[0_0_0_4px_rgba(59,130,246,0.15)]":"border-gray-200"} hover:bg-gray-50`,children:[i&&t.jsx("div",{className:"absolute left-1/2 top-[-12px] -translate-x-1/2 rounded-lg flex bg-white",children:t.jsxs("svg",{viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"25237",width:"24",height:"24",children:[t.jsx("path",{d:"M938.656 256A170.656 170.656 0 0 0 768 85.344H256A170.656 170.656 0 0 0 85.344 256v512A170.656 170.656 0 0 0 256 938.656h512A170.656 170.656 0 0 0 938.656 768V256zM256 170.656h512l6.368 0.256A85.344 85.344 0 0 1 853.312 256v512l-0.224 6.4A85.344 85.344 0 0 1 768 853.312H256l-6.336-0.256A85.344 85.344 0 0 1 170.656 768V256l0.224-6.368A85.344 85.344 0 0 1 256 170.656z","p-id":"25238",fill:"#1296db"}),t.jsx("path",{d:"M633.12 718.464h-95.392l-34.368-95.68h-160.288l-34.336 95.68H213.344l154.56-419.808h110.656l154.56 419.808z m-209.888-333.888l-61.056 177.696h120.192l-59.136-177.696z","p-id":"25239",fill:"#1296db"}),t.jsx("path",{d:"M682.656 298.656m0 0l85.344 0q0 0 0 0l0 426.656q0 0 0 0l-85.344 0q0 0 0 0l0-426.656q0 0 0 0Z","p-id":"25240",fill:"#1296db"})]})}),t.jsxs("div",{className:"flex flex-row",children:[t.jsx("h3",{className:"flex-1 font-medium text-sm line-clamp-2 break-all h-10 overflow-hidden",children:e.name}),t.jsx("div",{className:"flex items-start",children:e.description&&t.jsx(D,{arrow:!1,placement:"top",title:t.jsx("div",{className:"bg-gray-900 text-white text-xs rounded-md py-2 px-3 min-w-[400px] whitespace-normal break-words",children:e.description}),children:t.jsx("div",{className:"w-5 h-5 flex items-center justify-center text-gray-500 cursor-help",children:t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:"w-4 h-4",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"})})})})})]}),t.jsx("div",{className:"aspect-[3/4] rounded-lg overflow-hidden flex-1 w-full",children:e.image?t.jsx("img",{src:e.image,alt:e.name,className:"w-full h-full object-cover",onError:l=>{const o=l.target;o.onerror=null,o.src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56' fill='none'%3E%3Crect width='56' height='56' fill='%23F3F4F6'/%3E%3Cpath d='M28 28C30.2091 28 32 26.2091 32 24C32 21.7909 30.2091 20 28 20C25.7909 20 24 21.7909 24 24C24 26.2091 25.7909 28 28 28Z' fill='%239CA3AF'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.7253 37.6307C19.8278 35.1533 22.6897 33.6 26 33.6H30C33.3103 33.6 36.1722 35.1533 37.2747 37.6307C37.6419 38.4561 37.0611 39.2 36.1694 39.2H19.8306C18.9389 39.2 18.3581 38.4561 18.7253 37.6307Z' fill='%239CA3AF'/%3E%3C/svg%3E"}}):t.jsx("div",{className:"w-full h-full flex items-center justify-center",children:t.jsxs("svg",{viewBox:"0 0 1026 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"1875",width:"98",height:"98",children:[t.jsx("path",{d:"M0.003166 0v1024h1024V0H0.003166z m962.692789 61.286783v566.902743l-120.857537-118.426494-186.638683 137.466255-287.435012-237.138993L61.28995 705.410873V61.286783h901.406005zM61.28995 962.692788v-172.195431l309.661685-298.34406 282.164349 232.746773 183.104479-134.89221 126.49592 123.962734v248.722194H61.28995z",fill:"#8a8a8a","p-id":"1876"}),t.jsx("path",{d:"M757.03794 397.199641h0.960159c63.411392 0 118.263062-53.605506 119.733945-117.057756 1.470883-63.901686-51.337895-119.958663-115.321296-122.410134l-4.330933-0.081716c-31.011112 0-61.817935 13.1358-84.555332 36.016199-22.635252 22.819112-35.505476 53.666793-35.301187 84.616619 0.490294 63.942544 54.892529 118.406065 118.814644 118.916788z m-39.999841-160.346653a59.570753 59.570753 0 0 1 42.900748-17.875312h0.143003c30.214384 1.164449 57.098853 29.621945 56.38384 59.734184-0.694584 30.47996-28.00806 57.200998-58.447162 57.200998v30.643391l-0.449436-30.643391c-30.132668-0.245147-57.773007-27.926344-57.997726-58.079442-0.122574-14.749686 6.230823-29.683232 17.466733-40.980428z",fill:"#8a8a8a","p-id":"1877"})]})})}),t.jsx("button",{onClick:()=>I(e),disabled:f[s],className:`w-full px-3 py-1 ${f[s]?"bg-[#d2d2d2] cursor-not-allowed":"bg-[#ffffff] hover:bg-[#eee]"} text-black rounded-lg text-xs`,children:f[s]?"Loading...":"Accept"})]},a)};return t.jsx("div",{className:"space-y-3 flex justify-center",children:b.length>0&&t.jsx("div",{className:"grid grid-cols-[repeat(auto-fill,minmax(120px,1fr))] gap-4",children:b.map((e,a)=>O(e,a))})})}export{Y as WorkflowOption}; + import{j as t}from"./vendor-markdown-B4Av9P7l.js";import{D,W as _,o as C,a as d}from"./message-components-CDlGtWLl.js";import{r as h}from"./vendor-react-ByKzdfMq.js";import{A as G}from"./workflowChat-DCaYfVyA.js";import"./input.js";/* empty css */import"./App-TDLVaCDl.js";function Y({content:v,name:J="Assistant",avatar:P,latestInput:N,installedNodes:A,onAddMessage:y}){const[f,g]=h.useState({}),[E,W]=h.useState(null),[b,M]=h.useState([]);h.useEffect(()=>{const e=JSON.parse(v);W(e),M(e.ext?.find(a=>a.type==="workflow")?.data||[])},[v]);const I=async e=>{if(!e.id){console.error("No workflow id provided");return}const a=String(e.id);if(!f[a]){g(s=>({...s,[a]:!0})),_.trackEvent({event_type:"workflow_accept",message_type:"workflow",message_id:E?.message_id,data:{workflow_id:e.id,workflow_name:e.name}}),window.dispatchEvent(new CustomEvent(G,{}));try{const s=await _.getOptimizedWorkflow(e.id,N);if(s.workflow){const i=new Set;if(s.workflow.nodes)for(const o of s.workflow.nodes)i.add(o.type);else for(const o of Object.values(s.workflow))i.add(o.class_type);const l=Array.from(i).filter(o=>!A.includes(o));if(console.log("[WorkflowOption] Missing node types:",l),l.length>0){try{console.log("[WorkflowOption] Fetching info for missing nodes");const o=await _.batchGetNodeInfo(l);console.log("[WorkflowOption] Received node infos:",o);const p={text:"",ext:[{type:"node_install_guide",data:o.map(r=>({name:r.name,repository_url:r.github_url}))}]},c={id:C(),role:"ai",content:JSON.stringify(p),format:"markdown",name:"Assistant",metadata:{pendingWorkflow:s.workflow,optimizedParams:s.optimized_params}};y?.(c)}catch(o){console.error("[WorkflowOption] Error fetching node info:",o),j(s.workflow,s.optimized_params)}finally{g(o=>({...o,[a]:!1}))}return}j(s.workflow,s.optimized_params)}}catch(s){console.error("Failed to optimize workflow:",s),alert("Failed to optimize workflow. Please try again.")}finally{g(s=>({...s,[a]:!1}))}}},j=(e,a)=>{if(e.nodes)d.loadGraphData(e);else{d.loadApiJson(e);const i=Object.keys(e),l=Object.keys(d.graph._nodes_by_id)[0],o=d.graph._nodes_by_id[l],p=o?o.pos[0]:0,c=o?o.pos[1]:0,r=250,m=60,S=20,F=60,k=50,H=1e3;let z=p,w=c,x=0;for(const T of i){const n=d.graph._nodes_by_id[T];if(n){x>H&&(z+=r+F,x=0,w=c);const V=n.inputs?n.inputs.length:0,L=n.outputs?n.outputs.length:0,q=n.widgets?n.widgets.length:0,B=Math.max(V,L)+q,u=S*B+m;n.size[0]=r,n.size[1]=u,n.pos[0]=z,n.pos[1]=w,x+=u+k,w+=u+k}}}for(const[i,l,o,p,c]of a){const r=d.graph._nodes_by_id[i].widgets;for(const m of r)m.name===p&&(m.value=c)}d.graph.setDirtyCanvas(!1,!0);const s={id:C(),role:"tool",content:JSON.stringify({text:"The workflow has been successfully loaded to the canvas",ext:[]}),format:"markdown",name:"Assistant"};y?.(s)},O=(e,a)=>{const s=e.id?String(e.id):"",i=e?.source==="AI Generated";return t.jsxs("div",{className:`relative flex flex-col items-center gap-4 p-2 rounded-lg border ${i?"shadow-[0_0_12px_2px_#3b82f6] shadow-[0_0_0_4px_rgba(59,130,246,0.15)]":"border-gray-200"} hover:bg-gray-50`,children:[i&&t.jsx("div",{className:"absolute left-1/2 top-[-12px] -translate-x-1/2 rounded-lg flex bg-white",children:t.jsxs("svg",{viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"25237",width:"24",height:"24",children:[t.jsx("path",{d:"M938.656 256A170.656 170.656 0 0 0 768 85.344H256A170.656 170.656 0 0 0 85.344 256v512A170.656 170.656 0 0 0 256 938.656h512A170.656 170.656 0 0 0 938.656 768V256zM256 170.656h512l6.368 0.256A85.344 85.344 0 0 1 853.312 256v512l-0.224 6.4A85.344 85.344 0 0 1 768 853.312H256l-6.336-0.256A85.344 85.344 0 0 1 170.656 768V256l0.224-6.368A85.344 85.344 0 0 1 256 170.656z","p-id":"25238",fill:"#1296db"}),t.jsx("path",{d:"M633.12 718.464h-95.392l-34.368-95.68h-160.288l-34.336 95.68H213.344l154.56-419.808h110.656l154.56 419.808z m-209.888-333.888l-61.056 177.696h120.192l-59.136-177.696z","p-id":"25239",fill:"#1296db"}),t.jsx("path",{d:"M682.656 298.656m0 0l85.344 0q0 0 0 0l0 426.656q0 0 0 0l-85.344 0q0 0 0 0l0-426.656q0 0 0 0Z","p-id":"25240",fill:"#1296db"})]})}),t.jsxs("div",{className:"flex flex-row",children:[t.jsx("h3",{className:"flex-1 font-medium text-sm line-clamp-2 break-all h-10 overflow-hidden",children:e.name}),t.jsx("div",{className:"flex items-start",children:e.description&&t.jsx(D,{arrow:!1,placement:"top",title:t.jsx("div",{className:"bg-gray-900 text-white text-xs rounded-md py-2 px-3 min-w-[400px] whitespace-normal break-words",children:e.description}),children:t.jsx("div",{className:"w-5 h-5 flex items-center justify-center text-gray-500 cursor-help",children:t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:"w-4 h-4",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"})})})})})]}),t.jsx("div",{className:"aspect-[3/4] rounded-lg overflow-hidden flex-1 w-full",children:e.image?t.jsx("img",{src:e.image,alt:e.name,className:"w-full h-full object-cover",onError:l=>{const o=l.target;o.onerror=null,o.src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56' fill='none'%3E%3Crect width='56' height='56' fill='%23F3F4F6'/%3E%3Cpath d='M28 28C30.2091 28 32 26.2091 32 24C32 21.7909 30.2091 20 28 20C25.7909 20 24 21.7909 24 24C24 26.2091 25.7909 28 28 28Z' fill='%239CA3AF'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.7253 37.6307C19.8278 35.1533 22.6897 33.6 26 33.6H30C33.3103 33.6 36.1722 35.1533 37.2747 37.6307C37.6419 38.4561 37.0611 39.2 36.1694 39.2H19.8306C18.9389 39.2 18.3581 38.4561 18.7253 37.6307Z' fill='%239CA3AF'/%3E%3C/svg%3E"}}):t.jsx("div",{className:"w-full h-full flex items-center justify-center",children:t.jsxs("svg",{viewBox:"0 0 1026 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"1875",width:"98",height:"98",children:[t.jsx("path",{d:"M0.003166 0v1024h1024V0H0.003166z m962.692789 61.286783v566.902743l-120.857537-118.426494-186.638683 137.466255-287.435012-237.138993L61.28995 705.410873V61.286783h901.406005zM61.28995 962.692788v-172.195431l309.661685-298.34406 282.164349 232.746773 183.104479-134.89221 126.49592 123.962734v248.722194H61.28995z",fill:"#8a8a8a","p-id":"1876"}),t.jsx("path",{d:"M757.03794 397.199641h0.960159c63.411392 0 118.263062-53.605506 119.733945-117.057756 1.470883-63.901686-51.337895-119.958663-115.321296-122.410134l-4.330933-0.081716c-31.011112 0-61.817935 13.1358-84.555332 36.016199-22.635252 22.819112-35.505476 53.666793-35.301187 84.616619 0.490294 63.942544 54.892529 118.406065 118.814644 118.916788z m-39.999841-160.346653a59.570753 59.570753 0 0 1 42.900748-17.875312h0.143003c30.214384 1.164449 57.098853 29.621945 56.38384 59.734184-0.694584 30.47996-28.00806 57.200998-58.447162 57.200998v30.643391l-0.449436-30.643391c-30.132668-0.245147-57.773007-27.926344-57.997726-58.079442-0.122574-14.749686 6.230823-29.683232 17.466733-40.980428z",fill:"#8a8a8a","p-id":"1877"})]})})}),t.jsx("button",{onClick:()=>I(e),disabled:f[s],className:`w-full px-3 py-1 ${f[s]?"bg-[#d2d2d2] cursor-not-allowed":"bg-[#ffffff] hover:bg-[#eee]"} text-black rounded-lg text-xs`,children:f[s]?"Loading...":"Accept"})]},a)};return t.jsx("div",{className:"space-y-3 flex justify-center",children:b.length>0&&t.jsx("div",{className:"grid grid-cols-[repeat(auto-fill,minmax(120px,1fr))] gap-4",children:b.map((e,a)=>O(e,a))})})}export{Y as WorkflowOption}; diff --git a/dist/copilot_web/input.js b/dist/copilot_web/input.js index 5b84643..02fbb8e 100644 --- a/dist/copilot_web/input.js +++ b/dist/copilot_web/input.js @@ -1,7 +1,7 @@ function getImportPath(filename) { return `./${filename}`; } - const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/App-fluNqnYs.js","copilot_web/vendor-markdown-B4Av9P7l.js","copilot_web/vendor-react-ByKzdfMq.js","copilot_web/message-components-CzGdQ9TQ.js"].map(path => { + const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/App-TDLVaCDl.js","copilot_web/vendor-markdown-B4Av9P7l.js","copilot_web/vendor-react-ByKzdfMq.js","copilot_web/message-components-CDlGtWLl.js"].map(path => { const apiBase = window.comfyAPI?.api?.api?.api_base; if (apiBase) { // 有 API base 时,使用完整路径 @@ -11,7 +11,7 @@ function getImportPath(filename) { return `./${path}`; } }))))=>i.map(i=>d[i]); -import{j as Fu}from"./vendor-markdown-B4Av9P7l.js";import{r as d0,e as Pv,g as ly,R as s0}from"./vendor-react-ByKzdfMq.js";import{w as ay,a as ty}from"./message-components-CzGdQ9TQ.js";/* empty css */const uy="modulepreload",ey=function(l){return"/"+l},Jc={},ny=function(a,t,u){let e=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const f=document.querySelector("meta[property=csp-nonce]"),c=f?.nonce||f?.getAttribute("nonce");e=Promise.allSettled(t.map(i=>{if(i=ey(i),i in Jc)return;Jc[i]=!0;const h=i.endsWith(".css"),b=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${i}"]${b}`))return;const S=document.createElement("link");if(S.rel=h?"stylesheet":uy,h||(S.as="script"),S.crossOrigin="",S.href=i,c&&S.setAttribute("nonce",c),document.head.appendChild(S),h)return new Promise((d,m)=>{S.addEventListener("load",d),S.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${i}`)))})}))}function n(f){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=f,window.dispatchEvent(c),!c.defaultPrevented)throw f}return e.then(f=>{for(const c of f||[])c.status==="rejected"&&n(c.reason);return a().catch(n)})};var m0={exports:{}},an={},S0={exports:{}},b0={};/** +import{j as Fu}from"./vendor-markdown-B4Av9P7l.js";import{r as d0,e as Pv,g as ly,R as s0}from"./vendor-react-ByKzdfMq.js";import{w as ay,a as ty}from"./message-components-CDlGtWLl.js";/* empty css */const uy="modulepreload",ey=function(l){return"/"+l},Jc={},ny=function(a,t,u){let e=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const f=document.querySelector("meta[property=csp-nonce]"),c=f?.nonce||f?.getAttribute("nonce");e=Promise.allSettled(t.map(i=>{if(i=ey(i),i in Jc)return;Jc[i]=!0;const h=i.endsWith(".css"),b=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${i}"]${b}`))return;const S=document.createElement("link");if(S.rel=h?"stylesheet":uy,h||(S.as="script"),S.crossOrigin="",S.href=i,c&&S.setAttribute("nonce",c),document.head.appendChild(S),h)return new Promise((d,m)=>{S.addEventListener("load",d),S.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${i}`)))})}))}function n(f){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=f,window.dispatchEvent(c),!c.defaultPrevented)throw f}return e.then(f=>{for(const c of f||[])c.status==="rejected"&&n(c.reason);return a().catch(n)})};var m0={exports:{}},an={},S0={exports:{}},b0={};/** * @license React * scheduler.production.js * @@ -35,4 +35,4 @@ import{j as Fu}from"./vendor-markdown-B4Av9P7l.js";import{r as d0,e as Pv,g as l `+i[u].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=u&&0<=e);break}}}finally{Mn=!1,Error.prepareStackTrace=t}return(t=l?l.displayName||l.name:"")?ft(t):""}function Ny(l){switch(l.tag){case 26:case 27:case 5:return ft(l.type);case 16:return ft("Lazy");case 13:return ft("Suspense");case 19:return ft("SuspenseList");case 0:case 15:return Dn(l.type,!1);case 11:return Dn(l.type.render,!1);case 1:return Dn(l.type,!0);case 31:return ft("Activity");default:return""}}function Ic(l){try{var a="";do a+=Ny(l),l=l.return;while(l);return a}catch(t){return` Error generating stack: `+t.message+` `+t.stack}}function Rl(l){switch(typeof l){case"bigint":case"boolean":case"number":case"string":case"undefined":return l;case"object":return l;default:return""}}function Y0(l){var a=l.type;return(l=l.nodeName)&&l.toLowerCase()==="input"&&(a==="checkbox"||a==="radio")}function qy(l){var a=Y0(l)?"checked":"value",t=Object.getOwnPropertyDescriptor(l.constructor.prototype,a),u=""+l[a];if(!l.hasOwnProperty(a)&&typeof t<"u"&&typeof t.get=="function"&&typeof t.set=="function"){var e=t.get,n=t.set;return Object.defineProperty(l,a,{configurable:!0,get:function(){return e.call(this)},set:function(f){u=""+f,n.call(this,f)}}),Object.defineProperty(l,a,{enumerable:t.enumerable}),{getValue:function(){return u},setValue:function(f){u=""+f},stopTracking:function(){l._valueTracker=null,delete l[a]}}}}function Ne(l){l._valueTracker||(l._valueTracker=qy(l))}function X0(l){if(!l)return!1;var a=l._valueTracker;if(!a)return!0;var t=a.getValue(),u="";return l&&(u=Y0(l)?l.checked?"true":"false":l.value),l=u,l!==t?(a.setValue(l),!0):!1}function qe(l){if(l=l||(typeof document<"u"?document:void 0),typeof l>"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var Ry=/[\n"\\]/g;function Xl(l){return l.replace(Ry,function(a){return"\\"+a.charCodeAt(0).toString(16)+" "})}function yf(l,a,t,u,e,n,f,c){l.name="",f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?l.type=f:l.removeAttribute("type"),a!=null?f==="number"?(a===0&&l.value===""||l.value!=a)&&(l.value=""+Rl(a)):l.value!==""+Rl(a)&&(l.value=""+Rl(a)):f!=="submit"&&f!=="reset"||l.removeAttribute("value"),a!=null?hf(l,f,Rl(a)):t!=null?hf(l,f,Rl(t)):u!=null&&l.removeAttribute("value"),e==null&&n!=null&&(l.defaultChecked=!!n),e!=null&&(l.checked=e&&typeof e!="function"&&typeof e!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+Rl(c):l.removeAttribute("name")}function G0(l,a,t,u,e,n,f,c){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),a!=null||t!=null){if(!(n!=="submit"&&n!=="reset"||a!=null))return;t=t!=null?""+Rl(t):"",a=a!=null?""+Rl(a):t,c||a===l.value||(l.value=a),l.defaultValue=a}u=u??e,u=typeof u!="function"&&typeof u!="symbol"&&!!u,l.checked=c?l.checked:!!u,l.defaultChecked=!!u,f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"&&(l.name=f)}function hf(l,a,t){a==="number"&&qe(l.ownerDocument)===l||l.defaultValue===""+t||(l.defaultValue=""+t)}function Et(l,a,t,u){if(l=l.options,a){a={};for(var e=0;e"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),sf=!1;if(ca)try{var wt={};Object.defineProperty(wt,"passive",{get:function(){sf=!0}}),window.addEventListener("test",wt,wt),window.removeEventListener("test",wt,wt)}catch{sf=!1}var Ea=null,ec=null,me=null;function V0(){if(me)return me;var l,a=ec,t=a.length,u,e="value"in Ea?Ea.value:Ea.textContent,n=e.length;for(l=0;l=eu),ni=" ",fi=!1;function C0(l,a){switch(l){case"keyup":return nh.indexOf(a.keyCode)!==-1;case"keydown":return a.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function p0(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var st=!1;function ch(l,a){switch(l){case"compositionend":return p0(a);case"keypress":return a.which!==32?null:(fi=!0,ni);case"textInput":return l=a.data,l===ni&&fi?null:l;default:return null}}function ih(l,a){if(st)return l==="compositionend"||!fc&&C0(l,a)?(l=V0(),me=ec=Ea=null,st=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(a.ctrlKey||a.altKey||a.metaKey)||a.ctrlKey&&a.altKey){if(a.char&&1=a)return{node:t,offset:a-l};l=u}l:{for(;t;){if(t.nextSibling){t=t.nextSibling;break l}t=t.parentNode}t=void 0}t=hi(t)}}function w0(l,a){return l&&a?l===a?!0:l&&l.nodeType===3?!1:a&&a.nodeType===3?w0(l,a.parentNode):"contains"in l?l.contains(a):l.compareDocumentPosition?!!(l.compareDocumentPosition(a)&16):!1:!1}function W0(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var a=qe(l.document);a instanceof l.HTMLIFrameElement;){try{var t=typeof a.contentWindow.location.href=="string"}catch{t=!1}if(t)l=a.contentWindow;else break;a=qe(l.document)}return a}function cc(l){var a=l&&l.nodeName&&l.nodeName.toLowerCase();return a&&(a==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||a==="textarea"||l.contentEditable==="true")}var bh=ca&&"documentMode"in document&&11>=document.documentMode,mt=null,mf=null,fu=null,Sf=!1;function si(l,a,t){var u=t.window===t?t.document:t.nodeType===9?t:t.ownerDocument;Sf||mt==null||mt!==qe(u)||(u=mt,"selectionStart"in u&&cc(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),fu&&Tu(fu,u)||(fu=u,u=We(mf,"onSelect"),0>=f,e-=f,aa=1<<32-Ol(a)+e|t<n?n:8;var f=O.T,c={};O.T=c,_c(l,!1,a,t);try{var i=e(),h=O.S;if(h!==null&&h(c,i),i!==null&&typeof i=="object"&&typeof i.then=="function"){var b=Oh(i,u);du(l,a,b,Ul(l))}else du(l,a,u,Ul(l))}catch(S){du(l,a,{then:function(){},status:"rejected",reason:S},Ul())}finally{Q.p=n,O.T=f}}function qh(){}function _f(l,a,t,u){if(l.tag!==5)throw Error(o(476));var e=Y1(l).queue;B1(l,e,a,pa,t===null?qh:function(){return X1(l),t(u)})}function Y1(l){var a=l.memoizedState;if(a!==null)return a;a={memoizedState:pa,baseState:pa,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ia,lastRenderedState:pa},next:null};var t={};return a.next={memoizedState:t,baseState:t,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ia,lastRenderedState:t},next:null},l.memoizedState=a,l=l.alternate,l!==null&&(l.memoizedState=a),a}function X1(l){var a=Y1(l).next.queue;du(l,a,{},Ul())}function Hc(){return sl(_u)}function G1(){return ll().memoizedState}function Q1(){return ll().memoizedState}function Rh(l){for(var a=l.return;a!==null;){switch(a.tag){case 24:case 3:var t=Ul();l=Ua(t);var u=Ha(a,l,t);u!==null&&(Hl(u,a,t),vu(u,a,t)),a={cache:sc()},l.payload=a;return}a=a.return}}function Bh(l,a,t){var u=Ul();t={lane:u,revertLane:0,action:t,hasEagerState:!1,eagerState:null,next:null},dn(l)?x1(a,t):(t=vc(l,a,t,u),t!==null&&(Hl(t,l,u),j1(t,a,u)))}function Z1(l,a,t){var u=Ul();du(l,a,t,u)}function du(l,a,t,u){var e={lane:u,revertLane:0,action:t,hasEagerState:!1,eagerState:null,next:null};if(dn(l))x1(a,e);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=a.lastRenderedReducer,n!==null))try{var f=a.lastRenderedState,c=n(f,t);if(e.hasEagerState=!0,e.eagerState=c,_l(c,f))return cn(l,a,e,0),C===null&&fn(),!1}catch{}finally{}if(t=vc(l,a,e,u),t!==null)return Hl(t,l,u),j1(t,a,u),!0}return!1}function _c(l,a,t,u){if(u={lane:2,revertLane:Qc(),action:u,hasEagerState:!1,eagerState:null,next:null},dn(l)){if(a)throw Error(o(479))}else a=vc(l,t,u,2),a!==null&&Hl(a,l,2)}function dn(l){var a=l.alternate;return l===H||a!==null&&a===H}function x1(l,a){Ot=Qe=!0;var t=l.pending;t===null?a.next=a:(a.next=t.next,t.next=a),l.pending=a}function j1(l,a,t){if(t&4194048){var u=a.lanes;u&=l.pendingLanes,t|=u,a.lanes=t,N0(l,t)}}var xe={readContext:sl,use:yn,useCallback:F,useContext:F,useEffect:F,useImperativeHandle:F,useLayoutEffect:F,useInsertionEffect:F,useMemo:F,useReducer:F,useRef:F,useState:F,useDebugValue:F,useDeferredValue:F,useTransition:F,useSyncExternalStore:F,useId:F,useHostTransitionStatus:F,useFormState:F,useActionState:F,useOptimistic:F,useMemoCache:F,useCacheRefresh:F},V1={readContext:sl,use:yn,useCallback:function(l,a){return Sl().memoizedState=[l,a===void 0?null:a],l},useContext:sl,useEffect:Ni,useImperativeHandle:function(l,a,t){t=t!=null?t.concat([l]):null,ze(4194308,4,H1.bind(null,a,l),t)},useLayoutEffect:function(l,a){return ze(4194308,4,l,a)},useInsertionEffect:function(l,a){ze(4,2,l,a)},useMemo:function(l,a){var t=Sl();a=a===void 0?null:a;var u=l();if(Ia){Ta(!0);try{l()}finally{Ta(!1)}}return t.memoizedState=[u,a],u},useReducer:function(l,a,t){var u=Sl();if(t!==void 0){var e=t(a);if(Ia){Ta(!0);try{t(a)}finally{Ta(!1)}}}else e=a;return u.memoizedState=u.baseState=e,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:e},u.queue=l,l=l.dispatch=Bh.bind(null,H,l),[u.memoizedState,l]},useRef:function(l){var a=Sl();return l={current:l},a.memoizedState=l},useState:function(l){l=Uf(l);var a=l.queue,t=Z1.bind(null,H,a);return a.dispatch=t,[l.memoizedState,t]},useDebugValue:Oc,useDeferredValue:function(l,a){var t=Sl();return Uc(t,l,a)},useTransition:function(){var l=Uf(!1);return l=B1.bind(null,H,l.queue,!0,!1),Sl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,a,t){var u=H,e=Sl();if(G){if(t===void 0)throw Error(o(407));t=t()}else{if(t=a(),C===null)throw Error(o(349));Y&124||s1(u,a,t)}e.memoizedState=t;var n={value:t,getSnapshot:a};return e.queue=n,Ni(S1.bind(null,u,n,l),[l]),u.flags|=2048,Xt(9,hn(),m1.bind(null,u,n,t,a),null),t},useId:function(){var l=Sl(),a=C.identifierPrefix;if(G){var t=ta,u=aa;t=(u&~(1<<32-Ol(u)-1)).toString(32)+t,a="«"+a+"R"+t,t=Ze++,0D?($=T,T=null):$=T.sibling;var B=d(y,T,s[D],g);if(B===null){T===null&&(T=$);break}l&&T&&B.alternate===null&&a(y,T),v=n(B,v,D),U===null?z=B:U.sibling=B,U=B,T=$}if(D===s.length)return t(y,T),G&&Ka(y,D),z;if(T===null){for(;DD?($=T,T=null):$=T.sibling;var Nl=d(y,T,B.value,g);if(Nl===null){T===null&&(T=$);break}l&&T&&Nl.alternate===null&&a(y,T),v=n(Nl,v,D),U===null?z=Nl:U.sibling=Nl,U=Nl,T=$}if(B.done)return t(y,T),G&&Ka(y,D),z;if(T===null){for(;!B.done;D++,B=s.next())B=S(y,B.value,g),B!==null&&(v=n(B,v,D),U===null?z=B:U.sibling=B,U=B);return G&&Ka(y,D),z}for(T=u(T);!B.done;D++,B=s.next())B=m(T,y,D,B.value,g),B!==null&&(l&&B.alternate!==null&&T.delete(B.key===null?D:B.key),v=n(B,v,D),U===null?z=B:U.sibling=B,U=B);return l&&T.forEach(function(da){return a(y,da)}),G&&Ka(y,D),z}function X(y,v,s,g){if(typeof s=="object"&&s!==null&&s.type===vt&&s.key===null&&(s=s.props.children),typeof s=="object"&&s!==null){switch(s.$$typeof){case Iu:l:{for(var z=s.key;v!==null;){if(v.key===z){if(z=s.type,z===vt){if(v.tag===7){t(y,v.sibling),g=e(v,s.props.children),g.return=y,y=g;break l}}else if(v.elementType===z||typeof z=="object"&&z!==null&&z.$$typeof===Sa&&qi(z)===v.type){t(y,v.sibling),g=e(v,s.props),kt(g,s),g.return=y,y=g;break l}t(y,v);break}else a(y,v);v=v.sibling}s.type===vt?(g=La(s.props.children,y.mode,g,s.key),g.return=y,y=g):(g=be(s.type,s.key,s.props,null,y.mode,g),kt(g,s),g.return=y,y=g)}return f(y);case lu:l:{for(z=s.key;v!==null;){if(v.key===z)if(v.tag===4&&v.stateNode.containerInfo===s.containerInfo&&v.stateNode.implementation===s.implementation){t(y,v.sibling),g=e(v,s.children||[]),g.return=y,y=g;break l}else{t(y,v);break}else a(y,v);v=v.sibling}g=Yn(s,y.mode,g),g.return=y,y=g}return f(y);case Sa:return z=s._init,s=z(s._payload),X(y,v,s,g)}if(au(s))return M(y,v,s,g);if(rt(s)){if(z=rt(s),typeof z!="function")throw Error(o(150));return s=z.call(s),E(y,v,s,g)}if(typeof s.then=="function")return X(y,v,ne(s),g);if(s.$$typeof===la)return X(y,v,ue(y,s),g);fe(y,s)}return typeof s=="string"&&s!==""||typeof s=="number"||typeof s=="bigint"?(s=""+s,v!==null&&v.tag===6?(t(y,v.sibling),g=e(v,s),g.return=y,y=g):(t(y,v),g=Bn(s,y.mode,g),g.return=y,y=g),f(y)):t(y,v)}return function(y,v,s,g){try{Du=0;var z=X(y,v,s,g);return Ht=null,z}catch(T){if(T===Ku||T===vn)throw T;var U=Ml(29,T,null,y.mode);return U.lanes=g,U.return=y,U}finally{}}}var Gt=C1(!0),p1=C1(!1),Zl=Wl(null),wl=null;function oa(l){var a=l.alternate;J(tl,tl.current&1),J(Zl,l),wl===null&&(a===null||Yt.current!==null||a.memoizedState!==null)&&(wl=l)}function L1(l){if(l.tag===22){if(J(tl,tl.current),J(Zl,l),wl===null){var a=l.alternate;a!==null&&a.memoizedState!==null&&(wl=l)}}else za()}function za(){J(tl,tl.current),J(Zl,Zl.current)}function ea(l){il(Zl),wl===l&&(wl=null),il(tl)}var tl=Wl(0);function je(l){for(var a=l;a!==null;){if(a.tag===13){var t=a.memoizedState;if(t!==null&&(t=t.dehydrated,t===null||t.data==="$?"||Jf(t)))return a}else if(a.tag===19&&a.memoizedProps.revealOrder!==void 0){if(a.flags&128)return a}else if(a.child!==null){a.child.return=a,a=a.child;continue}if(a===l)break;for(;a.sibling===null;){if(a.return===null||a.return===l)return null;a=a.return}a.sibling.return=a.return,a=a.sibling}return null}function Qn(l,a,t,u){a=l.memoizedState,t=t(u,a),t=t==null?a:p({},a,t),l.memoizedState=t,l.lanes===0&&(l.updateQueue.baseState=t)}var Nf={enqueueSetState:function(l,a,t){l=l._reactInternals;var u=Ul(),e=Ua(u);e.payload=a,t!=null&&(e.callback=t),a=Ha(l,e,u),a!==null&&(Hl(a,l,u),vu(a,l,u))},enqueueReplaceState:function(l,a,t){l=l._reactInternals;var u=Ul(),e=Ua(u);e.tag=1,e.payload=a,t!=null&&(e.callback=t),a=Ha(l,e,u),a!==null&&(Hl(a,l,u),vu(a,l,u))},enqueueForceUpdate:function(l,a){l=l._reactInternals;var t=Ul(),u=Ua(t);u.tag=2,a!=null&&(u.callback=a),a=Ha(l,u,t),a!==null&&(Hl(a,l,t),vu(a,l,t))}};function Ri(l,a,t,u,e,n,f){return l=l.stateNode,typeof l.shouldComponentUpdate=="function"?l.shouldComponentUpdate(u,n,f):a.prototype&&a.prototype.isPureReactComponent?!Tu(t,u)||!Tu(e,n):!0}function Bi(l,a,t,u){l=a.state,typeof a.componentWillReceiveProps=="function"&&a.componentWillReceiveProps(t,u),typeof a.UNSAFE_componentWillReceiveProps=="function"&&a.UNSAFE_componentWillReceiveProps(t,u),a.state!==l&&Nf.enqueueReplaceState(a,a.state,null)}function Pa(l,a){var t=a;if("ref"in a){t={};for(var u in a)u!=="ref"&&(t[u]=a[u])}if(l=l.defaultProps){t===a&&(t=p({},t));for(var e in l)t[e]===void 0&&(t[e]=l[e])}return t}var Ve=typeof reportError=="function"?reportError:function(l){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var a=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof l=="object"&&l!==null&&typeof l.message=="string"?String(l.message):String(l),error:l});if(!window.dispatchEvent(a))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",l);return}console.error(l)};function J1(l){Ve(l)}function r1(l){console.error(l)}function w1(l){Ve(l)}function Ke(l,a){try{var t=l.onUncaughtError;t(a.value,{componentStack:a.stack})}catch(u){setTimeout(function(){throw u})}}function Yi(l,a,t){try{var u=l.onCaughtError;u(t.value,{componentStack:t.stack,errorBoundary:a.tag===1?a.stateNode:null})}catch(e){setTimeout(function(){throw e})}}function qf(l,a,t){return t=Ua(t),t.tag=3,t.payload={element:null},t.callback=function(){Ke(l,a)},t}function W1(l){return l=Ua(l),l.tag=3,l}function $1(l,a,t,u){var e=t.type.getDerivedStateFromError;if(typeof e=="function"){var n=u.value;l.payload=function(){return e(n)},l.callback=function(){Yi(a,t,u)}}var f=t.stateNode;f!==null&&typeof f.componentDidCatch=="function"&&(l.callback=function(){Yi(a,t,u),typeof e!="function"&&(_a===null?_a=new Set([this]):_a.add(this));var c=u.stack;this.componentDidCatch(u.value,{componentStack:c!==null?c:""})})}function Xh(l,a,t,u,e){if(t.flags|=32768,u!==null&&typeof u=="object"&&typeof u.then=="function"){if(a=t.alternate,a!==null&&ju(a,t,e,!0),t=Zl.current,t!==null){switch(t.tag){case 13:return wl===null?xf():t.alternate===null&&W===0&&(W=3),t.flags&=-257,t.flags|=65536,t.lanes=e,u===Ef?t.flags|=16384:(a=t.updateQueue,a===null?t.updateQueue=new Set([u]):a.add(u),wn(l,u,e)),!1;case 22:return t.flags|=65536,u===Ef?t.flags|=16384:(a=t.updateQueue,a===null?(a={transitions:null,markerInstances:null,retryQueue:new Set([u])},t.updateQueue=a):(t=a.retryQueue,t===null?a.retryQueue=new Set([u]):t.add(u)),wn(l,u,e)),!1}throw Error(o(435,t.tag))}return wn(l,u,e),xf(),!1}if(G)return a=Zl.current,a!==null?(!(a.flags&65536)&&(a.flags|=256),a.flags|=65536,a.lanes=e,u!==gf&&(l=Error(o(422),{cause:u}),Eu(Gl(l,t)))):(u!==gf&&(a=Error(o(423),{cause:u}),Eu(Gl(a,t))),l=l.current.alternate,l.flags|=65536,e&=-e,l.lanes|=e,u=Gl(u,t),e=qf(l.stateNode,u,e),Xn(l,e),W!==4&&(W=2)),!1;var n=Error(o(520),{cause:u});if(n=Gl(n,t),Su===null?Su=[n]:Su.push(n),W!==4&&(W=2),a===null)return!0;u=Gl(u,t),t=a;do{switch(t.tag){case 3:return t.flags|=65536,l=e&-e,t.lanes|=l,l=qf(t.stateNode,u,l),Xn(t,l),!1;case 1:if(a=t.type,n=t.stateNode,(t.flags&128)===0&&(typeof a.getDerivedStateFromError=="function"||n!==null&&typeof n.componentDidCatch=="function"&&(_a===null||!_a.has(n))))return t.flags|=65536,e&=-e,t.lanes|=e,e=W1(e),$1(e,l,t,u),Xn(t,e),!1}t=t.return}while(t!==null);return!1}var k1=Error(o(461)),cl=!1;function vl(l,a,t,u){a.child=l===null?p1(a,null,t,u):Gt(a,l.child,t,u)}function Xi(l,a,t,u,e){t=t.render;var n=a.ref;if("ref"in u){var f={};for(var c in u)c!=="ref"&&(f[c]=u[c])}else f=u;return Fa(a),u=oc(l,a,t,f,n,e),c=zc(),l!==null&&!cl?(Ac(l,a,e),va(l,a,e)):(G&&c&&hc(a),a.flags|=1,vl(l,a,u,e),a.child)}function Gi(l,a,t,u,e){if(l===null){var n=t.type;return typeof n=="function"&&!yc(n)&&n.defaultProps===void 0&&t.compare===null?(a.tag=15,a.type=n,F1(l,a,n,u,e)):(l=be(t.type,null,u,a,a.mode,e),l.ref=a.ref,l.return=a,a.child=l)}if(n=l.child,!Nc(l,e)){var f=n.memoizedProps;if(t=t.compare,t=t!==null?t:Tu,t(f,u)&&l.ref===a.ref)return va(l,a,e)}return a.flags|=1,l=na(n,u),l.ref=a.ref,l.return=a,a.child=l}function F1(l,a,t,u,e){if(l!==null){var n=l.memoizedProps;if(Tu(n,u)&&l.ref===a.ref)if(cl=!1,a.pendingProps=u=n,Nc(l,e))l.flags&131072&&(cl=!0);else return a.lanes=l.lanes,va(l,a,e)}return Rf(l,a,t,u,e)}function I1(l,a,t){var u=a.pendingProps,e=u.children,n=l!==null?l.memoizedState:null;if(u.mode==="hidden"){if(a.flags&128){if(u=n!==null?n.baseLanes|t:t,l!==null){for(e=a.child=l.child,n=0;e!==null;)n=n|e.lanes|e.childLanes,e=e.sibling;a.childLanes=n&~u}else a.childLanes=0,a.child=null;return Qi(l,a,u,t)}if(t&536870912)a.memoizedState={baseLanes:0,cachePool:null},l!==null&&ge(a,n!==null?n.cachePool:null),n!==null?Mi(a,n):Of(),L1(a);else return a.lanes=a.childLanes=536870912,Qi(l,a,n!==null?n.baseLanes|t:t,t)}else n!==null?(ge(a,n.cachePool),Mi(a,n),za(),a.memoizedState=null):(l!==null&&ge(a,null),Of(),za());return vl(l,a,e,t),a.child}function Qi(l,a,t,u){var e=mc();return e=e===null?null:{parent:al._currentValue,pool:e},a.memoizedState={baseLanes:t,cachePool:e},l!==null&&ge(a,null),Of(),L1(a),l!==null&&ju(l,a,u,!0),null}function Ae(l,a){var t=a.ref;if(t===null)l!==null&&l.ref!==null&&(a.flags|=4194816);else{if(typeof t!="function"&&typeof t!="object")throw Error(o(284));(l===null||l.ref!==t)&&(a.flags|=4194816)}}function Rf(l,a,t,u,e){return Fa(a),t=oc(l,a,t,u,void 0,e),u=zc(),l!==null&&!cl?(Ac(l,a,e),va(l,a,e)):(G&&u&&hc(a),a.flags|=1,vl(l,a,t,e),a.child)}function Zi(l,a,t,u,e,n){return Fa(a),a.updateQueue=null,t=h1(a,u,t,e),y1(l),u=zc(),l!==null&&!cl?(Ac(l,a,n),va(l,a,n)):(G&&u&&hc(a),a.flags|=1,vl(l,a,t,n),a.child)}function xi(l,a,t,u,e){if(Fa(a),a.stateNode===null){var n=gt,f=t.contextType;typeof f=="object"&&f!==null&&(n=sl(f)),n=new t(u,n),a.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,n.updater=Nf,a.stateNode=n,n._reactInternals=a,n=a.stateNode,n.props=u,n.state=a.memoizedState,n.refs={},Sc(a),f=t.contextType,n.context=typeof f=="object"&&f!==null?sl(f):gt,n.state=a.memoizedState,f=t.getDerivedStateFromProps,typeof f=="function"&&(Qn(a,t,f,u),n.state=a.memoizedState),typeof t.getDerivedStateFromProps=="function"||typeof n.getSnapshotBeforeUpdate=="function"||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(f=n.state,typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount(),f!==n.state&&Nf.enqueueReplaceState(n,n.state,null),hu(a,u,n,e),yu(),n.state=a.memoizedState),typeof n.componentDidMount=="function"&&(a.flags|=4194308),u=!0}else if(l===null){n=a.stateNode;var c=a.memoizedProps,i=Pa(t,c);n.props=i;var h=n.context,b=t.contextType;f=gt,typeof b=="object"&&b!==null&&(f=sl(b));var S=t.getDerivedStateFromProps;b=typeof S=="function"||typeof n.getSnapshotBeforeUpdate=="function",c=a.pendingProps!==c,b||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(c||h!==f)&&Bi(a,n,u,f),ba=!1;var d=a.memoizedState;n.state=d,hu(a,u,n,e),yu(),h=a.memoizedState,c||d!==h||ba?(typeof S=="function"&&(Qn(a,t,S,u),h=a.memoizedState),(i=ba||Ri(a,t,i,u,d,h,f))?(b||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount()),typeof n.componentDidMount=="function"&&(a.flags|=4194308)):(typeof n.componentDidMount=="function"&&(a.flags|=4194308),a.memoizedProps=u,a.memoizedState=h),n.props=u,n.state=h,n.context=f,u=i):(typeof n.componentDidMount=="function"&&(a.flags|=4194308),u=!1)}else{n=a.stateNode,Mf(l,a),f=a.memoizedProps,b=Pa(t,f),n.props=b,S=a.pendingProps,d=n.context,h=t.contextType,i=gt,typeof h=="object"&&h!==null&&(i=sl(h)),c=t.getDerivedStateFromProps,(h=typeof c=="function"||typeof n.getSnapshotBeforeUpdate=="function")||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(f!==S||d!==i)&&Bi(a,n,u,i),ba=!1,d=a.memoizedState,n.state=d,hu(a,u,n,e),yu();var m=a.memoizedState;f!==S||d!==m||ba||l!==null&&l.dependencies!==null&&Xe(l.dependencies)?(typeof c=="function"&&(Qn(a,t,c,u),m=a.memoizedState),(b=ba||Ri(a,t,b,u,d,m,i)||l!==null&&l.dependencies!==null&&Xe(l.dependencies))?(h||typeof n.UNSAFE_componentWillUpdate!="function"&&typeof n.componentWillUpdate!="function"||(typeof n.componentWillUpdate=="function"&&n.componentWillUpdate(u,m,i),typeof n.UNSAFE_componentWillUpdate=="function"&&n.UNSAFE_componentWillUpdate(u,m,i)),typeof n.componentDidUpdate=="function"&&(a.flags|=4),typeof n.getSnapshotBeforeUpdate=="function"&&(a.flags|=1024)):(typeof n.componentDidUpdate!="function"||f===l.memoizedProps&&d===l.memoizedState||(a.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||f===l.memoizedProps&&d===l.memoizedState||(a.flags|=1024),a.memoizedProps=u,a.memoizedState=m),n.props=u,n.state=m,n.context=i,u=b):(typeof n.componentDidUpdate!="function"||f===l.memoizedProps&&d===l.memoizedState||(a.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||f===l.memoizedProps&&d===l.memoizedState||(a.flags|=1024),u=!1)}return n=u,Ae(l,a),u=(a.flags&128)!==0,n||u?(n=a.stateNode,t=u&&typeof t.getDerivedStateFromError!="function"?null:n.render(),a.flags|=1,l!==null&&u?(a.child=Gt(a,l.child,null,e),a.child=Gt(a,null,t,e)):vl(l,a,t,e),a.memoizedState=n.state,l=a.child):l=va(l,a,e),l}function ji(l,a,t,u){return xu(),a.flags|=256,vl(l,a,t,u),a.child}var Zn={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function xn(l){return{baseLanes:l,cachePool:n1()}}function jn(l,a,t){return l=l!==null?l.childLanes&~t:0,a&&(l|=Ql),l}function P1(l,a,t){var u=a.pendingProps,e=!1,n=(a.flags&128)!==0,f;if((f=n)||(f=l!==null&&l.memoizedState===null?!1:(tl.current&2)!==0),f&&(e=!0,a.flags&=-129),f=(a.flags&32)!==0,a.flags&=-33,l===null){if(G){if(e?oa(a):za(),G){var c=w,i;if(i=c){l:{for(i=c,c=pl;i.nodeType!==8;){if(!c){c=null;break l}if(i=Vl(i.nextSibling),i===null){c=null;break l}}c=i}c!==null?(a.memoizedState={dehydrated:c,treeContext:Ja!==null?{id:aa,overflow:ta}:null,retryLane:536870912,hydrationErrors:null},i=Ml(18,null,null,0),i.stateNode=c,i.return=a,a.child=i,ml=a,w=null,i=!0):i=!1}i||ka(a)}if(c=a.memoizedState,c!==null&&(c=c.dehydrated,c!==null))return Jf(c)?a.lanes=32:a.lanes=536870912,null;ea(a)}return c=u.children,u=u.fallback,e?(za(),e=a.mode,c=Ce({mode:"hidden",children:c},e),u=La(u,e,t,null),c.return=a,u.return=a,c.sibling=u,a.child=c,e=a.child,e.memoizedState=xn(t),e.childLanes=jn(l,f,t),a.memoizedState=Zn,u):(oa(a),Bf(a,c))}if(i=l.memoizedState,i!==null&&(c=i.dehydrated,c!==null)){if(n)a.flags&256?(oa(a),a.flags&=-257,a=Vn(l,a,t)):a.memoizedState!==null?(za(),a.child=l.child,a.flags|=128,a=null):(za(),e=u.fallback,c=a.mode,u=Ce({mode:"visible",children:u.children},c),e=La(e,c,t,null),e.flags|=2,u.return=a,e.return=a,u.sibling=e,a.child=u,Gt(a,l.child,null,t),u=a.child,u.memoizedState=xn(t),u.childLanes=jn(l,f,t),a.memoizedState=Zn,a=e);else if(oa(a),Jf(c)){if(f=c.nextSibling&&c.nextSibling.dataset,f)var h=f.dgst;f=h,u=Error(o(419)),u.stack="",u.digest=f,Eu({value:u,source:null,stack:null}),a=Vn(l,a,t)}else if(cl||ju(l,a,t,!1),f=(t&l.childLanes)!==0,cl||f){if(f=C,f!==null&&(u=t&-t,u=u&42?1:Pf(u),u=u&(f.suspendedLanes|t)?0:u,u!==0&&u!==i.retryLane))throw i.retryLane=u,Ct(l,u),Hl(f,l,u),k1;c.data==="$?"||xf(),a=Vn(l,a,t)}else c.data==="$?"?(a.flags|=192,a.child=l.child,a=null):(l=i.treeContext,w=Vl(c.nextSibling),ml=a,G=!0,ra=null,pl=!1,l!==null&&(Bl[Yl++]=aa,Bl[Yl++]=ta,Bl[Yl++]=Ja,aa=l.id,ta=l.overflow,Ja=a),a=Bf(a,u.children),a.flags|=4096);return a}return e?(za(),e=u.fallback,c=a.mode,i=l.child,h=i.sibling,u=na(i,{mode:"hidden",children:u.children}),u.subtreeFlags=i.subtreeFlags&65011712,h!==null?e=na(h,e):(e=La(e,c,t,null),e.flags|=2),e.return=a,u.return=a,u.sibling=e,a.child=u,u=e,e=a.child,c=l.child.memoizedState,c===null?c=xn(t):(i=c.cachePool,i!==null?(h=al._currentValue,i=i.parent!==h?{parent:h,pool:h}:i):i=n1(),c={baseLanes:c.baseLanes|t,cachePool:i}),e.memoizedState=c,e.childLanes=jn(l,f,t),a.memoizedState=Zn,u):(oa(a),t=l.child,l=t.sibling,t=na(t,{mode:"visible",children:u.children}),t.return=a,t.sibling=null,l!==null&&(f=a.deletions,f===null?(a.deletions=[l],a.flags|=16):f.push(l)),a.child=t,a.memoizedState=null,t)}function Bf(l,a){return a=Ce({mode:"visible",children:a},l.mode),a.return=l,l.child=a}function Ce(l,a){return l=Ml(22,l,null,a),l.lanes=0,l.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},l}function Vn(l,a,t){return Gt(a,l.child,null,t),l=Bf(a,a.pendingProps.children),l.flags|=2,a.memoizedState=null,l}function Vi(l,a,t){l.lanes|=a;var u=l.alternate;u!==null&&(u.lanes|=a),zf(l.return,a,t)}function Kn(l,a,t,u,e){var n=l.memoizedState;n===null?l.memoizedState={isBackwards:a,rendering:null,renderingStartTime:0,last:u,tail:t,tailMode:e}:(n.isBackwards=a,n.rendering=null,n.renderingStartTime=0,n.last=u,n.tail=t,n.tailMode=e)}function lv(l,a,t){var u=a.pendingProps,e=u.revealOrder,n=u.tail;if(vl(l,a,u.children,t),u=tl.current,u&2)u=u&1|2,a.flags|=128;else{if(l!==null&&l.flags&128)l:for(l=a.child;l!==null;){if(l.tag===13)l.memoizedState!==null&&Vi(l,t,a);else if(l.tag===19)Vi(l,t,a);else if(l.child!==null){l.child.return=l,l=l.child;continue}if(l===a)break l;for(;l.sibling===null;){if(l.return===null||l.return===a)break l;l=l.return}l.sibling.return=l.return,l=l.sibling}u&=1}switch(J(tl,u),e){case"forwards":for(t=a.child,e=null;t!==null;)l=t.alternate,l!==null&&je(l)===null&&(e=t),t=t.sibling;t=e,t===null?(e=a.child,a.child=null):(e=t.sibling,t.sibling=null),Kn(a,!1,e,t,n);break;case"backwards":for(t=null,e=a.child,a.child=null;e!==null;){if(l=e.alternate,l!==null&&je(l)===null){a.child=e;break}l=e.sibling,e.sibling=t,t=e,e=l}Kn(a,!0,t,null,n);break;case"together":Kn(a,!1,null,null,void 0);break;default:a.memoizedState=null}return a.child}function va(l,a,t){if(l!==null&&(a.dependencies=l.dependencies),Ga|=a.lanes,!(t&a.childLanes))if(l!==null){if(ju(l,a,t,!1),(t&a.childLanes)===0)return null}else return null;if(l!==null&&a.child!==l.child)throw Error(o(153));if(a.child!==null){for(l=a.child,t=na(l,l.pendingProps),a.child=t,t.return=a;l.sibling!==null;)l=l.sibling,t=t.sibling=na(l,l.pendingProps),t.return=a;t.sibling=null}return a.child}function Nc(l,a){return l.lanes&a?!0:(l=l.dependencies,!!(l!==null&&Xe(l)))}function Gh(l,a,t){switch(a.tag){case 3:Ue(a,a.stateNode.containerInfo),ga(a,al,l.memoizedState.cache),xu();break;case 27:case 5:ff(a);break;case 4:Ue(a,a.stateNode.containerInfo);break;case 10:ga(a,a.type,a.memoizedProps.value);break;case 13:var u=a.memoizedState;if(u!==null)return u.dehydrated!==null?(oa(a),a.flags|=128,null):t&a.child.childLanes?P1(l,a,t):(oa(a),l=va(l,a,t),l!==null?l.sibling:null);oa(a);break;case 19:var e=(l.flags&128)!==0;if(u=(t&a.childLanes)!==0,u||(ju(l,a,t,!1),u=(t&a.childLanes)!==0),e){if(u)return lv(l,a,t);a.flags|=128}if(e=a.memoizedState,e!==null&&(e.rendering=null,e.tail=null,e.lastEffect=null),J(tl,tl.current),u)break;return null;case 22:case 23:return a.lanes=0,I1(l,a,t);case 24:ga(a,al,l.memoizedState.cache)}return va(l,a,t)}function av(l,a,t){if(l!==null)if(l.memoizedProps!==a.pendingProps)cl=!0;else{if(!Nc(l,t)&&!(a.flags&128))return cl=!1,Gh(l,a,t);cl=!!(l.flags&131072)}else cl=!1,G&&a.flags&1048576&&u1(a,Ye,a.index);switch(a.lanes=0,a.tag){case 16:l:{l=a.pendingProps;var u=a.elementType,e=u._init;if(u=e(u._payload),a.type=u,typeof u=="function")yc(u)?(l=Pa(u,l),a.tag=1,a=xi(null,a,u,l,t)):(a.tag=0,a=Rf(null,a,u,l,t));else{if(u!=null){if(e=u.$$typeof,e===kf){a.tag=11,a=Xi(null,a,u,l,t);break l}else if(e===Ff){a.tag=14,a=Gi(null,a,u,l,t);break l}}throw a=ef(u)||u,Error(o(306,a,""))}}return a;case 0:return Rf(l,a,a.type,a.pendingProps,t);case 1:return u=a.type,e=Pa(u,a.pendingProps),xi(l,a,u,e,t);case 3:l:{if(Ue(a,a.stateNode.containerInfo),l===null)throw Error(o(387));u=a.pendingProps;var n=a.memoizedState;e=n.element,Mf(l,a),hu(a,u,null,t);var f=a.memoizedState;if(u=f.cache,ga(a,al,u),u!==n.cache&&Af(a,[al],t,!0),yu(),u=f.element,n.isDehydrated)if(n={element:u,isDehydrated:!1,cache:f.cache},a.updateQueue.baseState=n,a.memoizedState=n,a.flags&256){a=ji(l,a,u,t);break l}else if(u!==e){e=Gl(Error(o(424)),a),Eu(e),a=ji(l,a,u,t);break l}else{switch(l=a.stateNode.containerInfo,l.nodeType){case 9:l=l.body;break;default:l=l.nodeName==="HTML"?l.ownerDocument.body:l}for(w=Vl(l.firstChild),ml=a,G=!0,ra=null,pl=!0,t=p1(a,null,u,t),a.child=t;t;)t.flags=t.flags&-3|4096,t=t.sibling}else{if(xu(),u===e){a=va(l,a,t);break l}vl(l,a,u,t)}a=a.child}return a;case 26:return Ae(l,a),l===null?(t=u0(a.type,null,a.pendingProps,null))?a.memoizedState=t:G||(t=a.type,l=a.pendingProps,u=$e(Oa.current).createElement(t),u[dl]=a,u[ol]=l,hl(u,t,l),fl(u),a.stateNode=u):a.memoizedState=u0(a.type,l.memoizedProps,a.pendingProps,l.memoizedState),null;case 27:return ff(a),l===null&&G&&(u=a.stateNode=Kv(a.type,a.pendingProps,Oa.current),ml=a,pl=!0,e=w,Za(a.type)?(rf=e,w=Vl(u.firstChild)):w=e),vl(l,a,a.pendingProps.children,t),Ae(l,a),l===null&&(a.flags|=4194304),a.child;case 5:return l===null&&G&&((e=u=w)&&(u=vd(u,a.type,a.pendingProps,pl),u!==null?(a.stateNode=u,ml=a,w=Vl(u.firstChild),pl=!1,e=!0):e=!1),e||ka(a)),ff(a),e=a.type,n=a.pendingProps,f=l!==null?l.memoizedProps:null,u=n.children,pf(e,n)?u=null:f!==null&&pf(e,f)&&(a.flags|=32),a.memoizedState!==null&&(e=oc(l,a,Hh,null,null,t),_u._currentValue=e),Ae(l,a),vl(l,a,u,t),a.child;case 6:return l===null&&G&&((l=t=w)&&(t=yd(t,a.pendingProps,pl),t!==null?(a.stateNode=t,ml=a,w=null,l=!0):l=!1),l||ka(a)),null;case 13:return P1(l,a,t);case 4:return Ue(a,a.stateNode.containerInfo),u=a.pendingProps,l===null?a.child=Gt(a,null,u,t):vl(l,a,u,t),a.child;case 11:return Xi(l,a,a.type,a.pendingProps,t);case 7:return vl(l,a,a.pendingProps,t),a.child;case 8:return vl(l,a,a.pendingProps.children,t),a.child;case 12:return vl(l,a,a.pendingProps.children,t),a.child;case 10:return u=a.pendingProps,ga(a,a.type,u.value),vl(l,a,u.children,t),a.child;case 9:return e=a.type._context,u=a.pendingProps.children,Fa(a),e=sl(e),u=u(e),a.flags|=1,vl(l,a,u,t),a.child;case 14:return Gi(l,a,a.type,a.pendingProps,t);case 15:return F1(l,a,a.type,a.pendingProps,t);case 19:return lv(l,a,t);case 31:return u=a.pendingProps,t=a.mode,u={mode:u.mode,children:u.children},l===null?(t=Ce(u,t),t.ref=a.ref,a.child=t,t.return=a,a=t):(t=na(l.child,u),t.ref=a.ref,a.child=t,t.return=a,a=t),a;case 22:return I1(l,a,t);case 24:return Fa(a),u=sl(al),l===null?(e=mc(),e===null&&(e=C,n=sc(),e.pooledCache=n,n.refCount++,n!==null&&(e.pooledCacheLanes|=t),e=n),a.memoizedState={parent:u,cache:e},Sc(a),ga(a,al,e)):(l.lanes&t&&(Mf(l,a),hu(a,null,null,t),yu()),e=l.memoizedState,n=a.memoizedState,e.parent!==u?(e={parent:u,cache:u},a.memoizedState=e,a.lanes===0&&(a.memoizedState=a.updateQueue.baseState=e),ga(a,al,u)):(u=n.cache,ga(a,al,u),u!==e.cache&&Af(a,[al],t,!0))),vl(l,a,a.pendingProps.children,t),a.child;case 29:throw a.pendingProps}throw Error(o(156,a.tag))}function Fl(l){l.flags|=4}function Ki(l,a){if(a.type!=="stylesheet"||a.state.loading&4)l.flags&=-16777217;else if(l.flags|=16777216,!Lv(a)){if(a=Zl.current,a!==null&&((Y&4194048)===Y?wl!==null:(Y&62914560)!==Y&&!(Y&536870912)||a!==wl))throw iu=Ef,f1;l.flags|=8192}}function ce(l,a){a!==null&&(l.flags|=4),l.flags&16384&&(a=l.tag!==22?H0():536870912,l.lanes|=a,Qt|=a)}function Ft(l,a){if(!G)switch(l.tailMode){case"hidden":a=l.tail;for(var t=null;a!==null;)a.alternate!==null&&(t=a),a=a.sibling;t===null?l.tail=null:t.sibling=null;break;case"collapsed":t=l.tail;for(var u=null;t!==null;)t.alternate!==null&&(u=t),t=t.sibling;u===null?a||l.tail===null?l.tail=null:l.tail.sibling=null:u.sibling=null}}function r(l){var a=l.alternate!==null&&l.alternate.child===l.child,t=0,u=0;if(a)for(var e=l.child;e!==null;)t|=e.lanes|e.childLanes,u|=e.subtreeFlags&65011712,u|=e.flags&65011712,e.return=l,e=e.sibling;else for(e=l.child;e!==null;)t|=e.lanes|e.childLanes,u|=e.subtreeFlags,u|=e.flags,e.return=l,e=e.sibling;return l.subtreeFlags|=u,l.childLanes=t,a}function Qh(l,a,t){var u=a.pendingProps;switch(dc(a),a.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return r(a),null;case 1:return r(a),null;case 3:return t=a.stateNode,u=null,l!==null&&(u=l.memoizedState.cache),a.memoizedState.cache!==u&&(a.flags|=2048),fa(al),Nt(),t.pendingContext&&(t.context=t.pendingContext,t.pendingContext=null),(l===null||l.child===null)&&($t(a)?Fl(a):l===null||l.memoizedState.isDehydrated&&!(a.flags&256)||(a.flags|=1024,gi())),r(a),null;case 26:return t=a.memoizedState,l===null?(Fl(a),t!==null?(r(a),Ki(a,t)):(r(a),a.flags&=-16777217)):t?t!==l.memoizedState?(Fl(a),r(a),Ki(a,t)):(r(a),a.flags&=-16777217):(l.memoizedProps!==u&&Fl(a),r(a),a.flags&=-16777217),null;case 27:He(a),t=Oa.current;var e=a.type;if(l!==null&&a.stateNode!=null)l.memoizedProps!==u&&Fl(a);else{if(!u){if(a.stateNode===null)throw Error(o(166));return r(a),null}l=Jl.current,$t(a)?Si(a):(l=Kv(e,u,t),a.stateNode=l,Fl(a))}return r(a),null;case 5:if(He(a),t=a.type,l!==null&&a.stateNode!=null)l.memoizedProps!==u&&Fl(a);else{if(!u){if(a.stateNode===null)throw Error(o(166));return r(a),null}if(l=Jl.current,$t(a))Si(a);else{switch(e=$e(Oa.current),l){case 1:l=e.createElementNS("http://www.w3.org/2000/svg",t);break;case 2:l=e.createElementNS("http://www.w3.org/1998/Math/MathML",t);break;default:switch(t){case"svg":l=e.createElementNS("http://www.w3.org/2000/svg",t);break;case"math":l=e.createElementNS("http://www.w3.org/1998/Math/MathML",t);break;case"script":l=e.createElement("div"),l.innerHTML="