From 78e087e256824b30d73e2835342b37444d92ab72 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 12:16:10 +0800 Subject: [PATCH 01/78] =?UTF-8?q?=E9=80=82=E9=85=8Drag=E7=9A=84=E4=BD=9C?= =?UTF-8?q?=E8=80=85=E5=92=8C=E5=88=9B=E5=BB=BA=E6=97=B6=E9=97=B4=E7=9A=84?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/scheduler/context.py | 3 +++ apps/scheduler/scheduler/message.py | 9 +-------- apps/schemas/record.py | 6 +++++- apps/services/document.py | 4 ++++ apps/services/rag.py | 3 +++ 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index b7088d8d..4c2c4cf0 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -114,11 +114,14 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: used_docs.append( RecordGroupDocument( _id=docs["id"], + author=docs.get("author", ""), + order=docs.get("order", 0), name=docs["name"], abstract=docs.get("abstract", ""), extension=docs.get("extension", ""), size=docs.get("size", 0), associated="answer", + created_at=docs.get("created_at", round(datetime.now(UTC).timestamp(), 3)), ) ) if docs.get("order") is not None: diff --git a/apps/scheduler/scheduler/message.py b/apps/scheduler/scheduler/message.py index c89fdd10..5997b48f 100644 --- a/apps/scheduler/scheduler/message.py +++ b/apps/scheduler/scheduler/message.py @@ -71,14 +71,7 @@ async def push_rag_message( # 如果是文本消息,直接拼接到答案中 full_answer += content_obj.content elif content_obj.event_type == EventType.DOCUMENT_ADD.value: - task.runtime.documents.append({ - "id": content_obj.content.get("id", ""), - "order": content_obj.content.get("order", 0), - "name": content_obj.content.get("name", ""), - "abstract": content_obj.content.get("abstract", ""), - "extension": content_obj.content.get("extension", ""), - "size": content_obj.content.get("size", 0), - }) + task.runtime.documents.append(content_obj.content) # 保存答案 task.runtime.answer = full_answer await TaskManager.save_task(task.id, task) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index d7acd368..e1a995f8 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -17,8 +17,9 @@ class RecordDocument(Document): """GET /api/record/{conversation_id} Result中的document数据结构""" id: str = Field(alias="_id", default="") + order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") - user_sub: None = None + author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] class Config: @@ -103,11 +104,14 @@ class RecordGroupDocument(BaseModel): """RecordGroup关联的文件""" id: str = Field(default_factory=lambda: str(uuid.uuid4()), alias="_id") + order: int = Field(default=0, description="文档顺序") + author: str = Field(default="", description="文档作者") name: str = Field(default="", description="文档名称") abstract: str = Field(default="", description="文档摘要") extension: str = Field(default="", description="文档扩展名") size: int = Field(default=0, description="文档大小,单位是KB") associated: Literal["question", "answer"] + created_at: float = Field(default=0.0, description="文档创建时间") class Record(RecordData): diff --git a/apps/services/document.py b/apps/services/document.py index 203162da..451423a9 100644 --- a/apps/services/document.py +++ b/apps/services/document.py @@ -2,6 +2,7 @@ """文件Manager""" import base64 +from datetime import UTC, datetime import logging import uuid @@ -131,12 +132,15 @@ class DocumentManager: return [ RecordDocument( _id=doc.id, + order=doc.order, + author=doc.author, abstract=doc.abstract, name=doc.name, type=doc.extension, size=doc.size, conversation_id=record_group.get("conversation_id", ""), associated=doc.associated, + created_at=doc.created_at or round(datetime.now(tz=UTC).timestamp(), 3) ) for doc in docs if type is None or doc.associated == type ] diff --git a/apps/services/rag.py b/apps/services/rag.py index 6b6c843d..efbdfe94 100644 --- a/apps/services/rag.py +++ b/apps/services/rag.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """对接Euler Copilot RAG""" +from datetime import UTC, datetime import json import logging from collections.abc import AsyncGenerator @@ -156,9 +157,11 @@ class RAG: "id": doc_chunk["docId"], "order": doc_cnt, "name": doc_chunk.get("docName", ""), + "author": doc_chunk.get("docAuthor", ""), "extension": doc_chunk.get("docExtension", ""), "abstract": doc_chunk.get("docAbstract", ""), "size": doc_chunk.get("docSize", 0), + "created_at": doc_chunk.get("docCreatedAt", round(datetime.now(UTC).timestamp(), 3)), }) doc_id_map[doc_chunk["docId"]] = doc_cnt doc_index = doc_id_map[doc_chunk["docId"]] -- Gitee From c930151094eef40aa9f4e01e1ec59bd56ef75a21 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:40:30 +0800 Subject: [PATCH 02/78] =?UTF-8?q?=E5=AF=B9rag=E7=9A=84team=E5=92=8C?= =?UTF-8?q?=E5=9B=A2=E9=98=9F=E8=8E=B7=E5=8F=96=E5=A2=9E=E5=8A=A0=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/services/conversation.py | 6 +++++- apps/services/knowledge.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/services/conversation.py b/apps/services/conversation.py index 4bcade45..bac964db 100644 --- a/apps/services/conversation.py +++ b/apps/services/conversation.py @@ -59,7 +59,11 @@ class ConversationManager: model_name=llm.model_name, ) kb_item_list = [] - team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + try: + team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + except: + logger.error("[ConversationManager] 获取团队知识库列表失败") + team_kb_list = [] for team_kb in team_kb_list: for kb in team_kb["kbList"]: if str(kb["kbId"]) in kb_ids: diff --git a/apps/services/knowledge.py b/apps/services/knowledge.py index 9b4077f9..bd8dfc9e 100644 --- a/apps/services/knowledge.py +++ b/apps/services/knowledge.py @@ -138,7 +138,11 @@ class KnowledgeBaseManager: return [] kb_ids_update_success = [] kb_item_dict_list = [] - team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + try: + team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + except Exception as e: + logger.error(f"[KnowledgeBaseManager] 获取团队知识库列表失败: {e}") + team_kb_list = [] for team_kb in team_kb_list: for kb in team_kb["kbList"]: if str(kb["kbId"]) in kb_ids: -- Gitee From 059bf35ef464b8165ea1c816566c9c35c4bc742b Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:53:07 +0800 Subject: [PATCH 03/78] =?UTF-8?q?=E5=AE=8C=E5=96=84RecordDocument=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/schemas/record.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index e1a995f8..6e9617a3 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -19,6 +19,7 @@ class RecordDocument(Document): id: str = Field(alias="_id", default="") order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") + user_sub: None | None author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] -- Gitee From eefe717400bca7606c0c722d5e506fd9d9704c14 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:56:50 +0800 Subject: [PATCH 04/78] =?UTF-8?q?=E5=AE=8C=E5=96=84RecordDocument=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/schemas/record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 6e9617a3..b5e1b0c5 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -19,7 +19,7 @@ class RecordDocument(Document): id: str = Field(alias="_id", default="") order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") - user_sub: None | None + user_sub: None = None author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] -- Gitee From 60ea73002a36aa3452997caa649c9b80993ea2bd Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 16:21:07 +0800 Subject: [PATCH 05/78] =?UTF-8?q?=E5=AE=8C=E5=96=84DocumentAddContent?= =?UTF-8?q?=E7=9A=84=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/scheduler/message.py | 2 ++ apps/schemas/message.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/scheduler/scheduler/message.py b/apps/scheduler/scheduler/message.py index 5997b48f..a2a45e41 100644 --- a/apps/scheduler/scheduler/message.py +++ b/apps/scheduler/scheduler/message.py @@ -108,10 +108,12 @@ async def _push_rag_chunk(task: Task, queue: MessageQueue, content: str) -> tupl data=DocumentAddContent( documentId=content_obj.content.get("id", ""), documentOrder=content_obj.content.get("order", 0), + documentAuthor=content_obj.content.get("author", ""), documentName=content_obj.content.get("name", ""), documentAbstract=content_obj.content.get("abstract", ""), documentType=content_obj.content.get("extension", ""), documentSize=content_obj.content.get("size", 0), + createdAt=round(datetime.now(tz=UTC).timestamp(), 3), ).model_dump(exclude_none=True, by_alias=True), ) except Exception: diff --git a/apps/schemas/message.py b/apps/schemas/message.py index d0661224..5f0aee8a 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -2,7 +2,7 @@ """队列中的消息结构""" from typing import Any - +from datetime import UTC, datetime from pydantic import BaseModel, Field from apps.schemas.enum_var import EventType, StepStatus @@ -60,10 +60,14 @@ class DocumentAddContent(BaseModel): document_id: str = Field(description="文档UUID", alias="documentId") document_order: int = Field(description="文档在对话中的顺序,从1开始", alias="documentOrder") + document_author: str = Field(description="文档作者", alias="documentAuthor", default="") document_name: str = Field(description="文档名称", alias="documentName") document_abstract: str = Field(description="文档摘要", alias="documentAbstract", default="") document_type: str = Field(description="文档MIME类型", alias="documentType", default="") document_size: float = Field(ge=0, description="文档大小,单位是KB,保留两位小数", alias="documentSize", default=0) + created_at: float = Field( + description="文档创建时间,单位是秒", alias="createdAt", default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3) + ) class FlowStartContent(BaseModel): -- Gitee From 7b57aa351af2a882d5059e5f5b3a618d2238deec Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 24 Jul 2025 19:22:36 +0800 Subject: [PATCH 06/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=97=A0=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/dependency/user.py | 8 +++++++ apps/routers/api_key.py | 1 + apps/routers/auth.py | 3 +-- apps/scheduler/executor/step.py | 38 ++++++++++++++++----------------- apps/schemas/config.py | 9 +++++++- apps/schemas/message.py | 2 ++ apps/schemas/request_data.py | 4 ++-- 7 files changed, 41 insertions(+), 24 deletions(-) diff --git a/apps/dependency/user.py b/apps/dependency/user.py index fce67e51..87cbd290 100644 --- a/apps/dependency/user.py +++ b/apps/dependency/user.py @@ -5,10 +5,12 @@ import logging from fastapi import Depends from fastapi.security import OAuth2PasswordBearer +import secrets from starlette import status from starlette.exceptions import HTTPException from starlette.requests import HTTPConnection +from apps.common.config import Config from apps.services.api_key import ApiKeyManager from apps.services.session import SessionManager @@ -48,6 +50,9 @@ async def get_session(request: HTTPConnection) -> str: :param request: HTTP请求 :return: Session ID """ + if Config().get_config().no_auth.enable: + # 如果启用了无认证访问,直接返回调试用户 + return secrets.token_hex(16) session_id = await _get_session_id_from_request(request) if not session_id: raise HTTPException( @@ -69,6 +74,9 @@ async def get_user(request: HTTPConnection) -> str: :param request: HTTP请求体 :return: 用户sub """ + if Config().get_config().no_auth.enable: + # 如果启用了无认证访问,直接返回调试用户 + return Config().get_config().no_auth.user_sub session_id = await _get_session_id_from_request(request) if not session_id: raise HTTPException( diff --git a/apps/routers/api_key.py b/apps/routers/api_key.py index 158cfc13..51366a21 100644 --- a/apps/routers/api_key.py +++ b/apps/routers/api_key.py @@ -6,6 +6,7 @@ from typing import Annotated from fastapi import APIRouter, Depends, status from fastapi.responses import JSONResponse + from apps.dependency.user import get_user, verify_user from apps.schemas.api_key import GetAuthKeyRsp, PostAuthKeyMsg, PostAuthKeyRsp from apps.schemas.response_data import ResponseData diff --git a/apps/routers/auth.py b/apps/routers/auth.py index 1cba5ed6..4a3f8293 100644 --- a/apps/routers/auth.py +++ b/apps/routers/auth.py @@ -9,6 +9,7 @@ from fastapi import APIRouter, Depends, Request, status from fastapi.responses import HTMLResponse, JSONResponse from fastapi.templating import Jinja2Templates +from apps.common.config import Config from apps.common.oidc import oidc_provider from apps.dependency import get_session, get_user, verify_user from apps.schemas.collection import Audit @@ -47,8 +48,6 @@ async def oidc_login(request: Request, code: str) -> HTMLResponse: user_info = await oidc_provider.get_oidc_user(token["access_token"]) user_sub: str | None = user_info.get("user_sub", None) - if user_sub: - await oidc_provider.set_token(user_sub, token["access_token"], token["refresh_token"]) except Exception as e: logger.exception("User login failed") status_code = status.HTTP_400_BAD_REQUEST if "auth error" in str(e) else status.HTTP_403_FORBIDDEN diff --git a/apps/scheduler/executor/step.py b/apps/scheduler/executor/step.py index 6b3451fa..506f3bb1 100644 --- a/apps/scheduler/executor/step.py +++ b/apps/scheduler/executor/step.py @@ -86,8 +86,8 @@ class StepExecutor(BaseExecutor): logger.info("[StepExecutor] 初始化步骤 %s", self.step.step.name) # State写入ID和运行状态 - self.task.state.step_id = self.step.step_id # type: ignore[arg-type] - self.task.state.step_name = self.step.step.name # type: ignore[arg-type] + self.task.state.step_id = self.step.step_id # type: ignore[arg-type] + self.task.state.step_name = self.step.step.name # type: ignore[arg-type] # 获取并验证Call类 node_id = self.step.step.node @@ -127,13 +127,13 @@ class StepExecutor(BaseExecutor): return # 暂存旧数据 - current_step_id = self.task.state.step_id # type: ignore[arg-type] - current_step_name = self.task.state.step_name # type: ignore[arg-type] + current_step_id = self.task.state.step_id # type: ignore[arg-type] + current_step_name = self.task.state.step_name # type: ignore[arg-type] # 更新State - self.task.state.step_id = str(uuid.uuid4()) # type: ignore[arg-type] - self.task.state.step_name = "自动参数填充" # type: ignore[arg-type] - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.step_id = str(uuid.uuid4()) # type: ignore[arg-type] + self.task.state.step_name = "自动参数填充" # type: ignore[arg-type] + self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 初始化填参 @@ -156,17 +156,17 @@ class StepExecutor(BaseExecutor): # 如果没有填全,则状态设置为待填参 if result.remaining_schema: - self.task.state.status = StepStatus.PARAM # type: ignore[arg-type] + self.task.state.status = StepStatus.PARAM # type: ignore[arg-type] else: - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, result.model_dump(by_alias=True, exclude_none=True)) # 更新输入 self.obj.input.update(result.slot_data) # 恢复State - self.task.state.step_id = current_step_id # type: ignore[arg-type] - self.task.state.step_name = current_step_name # type: ignore[arg-type] + self.task.state.step_id = current_step_id # type: ignore[arg-type] + self.task.state.step_name = current_step_name # type: ignore[arg-type] self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens @@ -212,7 +212,7 @@ class StepExecutor(BaseExecutor): await self._run_slot_filling() # 更新状态 - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 推送输入 await self.push_message(EventType.STEP_INPUT.value, self.obj.input) @@ -224,22 +224,22 @@ class StepExecutor(BaseExecutor): content = await self._process_chunk(iterator, to_user=self.obj.to_user) except Exception as e: logger.exception("[StepExecutor] 运行步骤失败,进行异常处理步骤") - self.task.state.status = StepStatus.ERROR # type: ignore[arg-type] + self.task.state.status = StepStatus.ERROR # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, {}) if isinstance(e, CallError): - self.task.state.error_info = { # type: ignore[arg-type] + self.task.state.error_info = { # type: ignore[arg-type] "err_msg": e.message, "data": e.data, } else: - self.task.state.error_info = { # type: ignore[arg-type] + self.task.state.error_info = { # type: ignore[arg-type] "err_msg": str(e), "data": {}, } return # 更新执行状态 - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens self.task.tokens.full_time += round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.time @@ -253,12 +253,12 @@ class StepExecutor(BaseExecutor): # 更新context history = FlowStepHistory( task_id=self.task.id, - flow_id=self.task.state.flow_id, # type: ignore[arg-type] - flow_name=self.task.state.flow_name, # type: ignore[arg-type] + flow_id=self.task.state.flow_id, # type: ignore[arg-type] + flow_name=self.task.state.flow_name, # type: ignore[arg-type] step_id=self.step.step_id, step_name=self.step.step.name, step_description=self.step.step.description, - status=self.task.state.status, # type: ignore[arg-type] + status=self.task.state.status, # type: ignore[arg-type] input_data=self.obj.input, output_data=output_data, ) diff --git a/apps/schemas/config.py b/apps/schemas/config.py index b88a81f1..99bcccde 100644 --- a/apps/schemas/config.py +++ b/apps/schemas/config.py @@ -6,6 +6,13 @@ from typing import Literal from pydantic import BaseModel, Field +class NoauthConfig(BaseModel): + """无认证配置""" + + enable: bool = Field(description="是否启用无认证访问", default=False) + user_sub: str = Field(description="调试用户的sub", default="admin") + + class DeployConfig(BaseModel): """部署配置""" @@ -122,7 +129,7 @@ class ExtraConfig(BaseModel): class ConfigModel(BaseModel): """配置文件的校验Class""" - + no_auth: NoauthConfig deploy: DeployConfig login: LoginConfig embedding: EmbeddingConfig diff --git a/apps/schemas/message.py b/apps/schemas/message.py index 5f0aee8a..cf70a82b 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -24,6 +24,8 @@ class MessageFlow(BaseModel): flow_id: str = Field(description="Flow ID", alias="flowId") step_id: str = Field(description="当前步骤ID", alias="stepId") step_name: str = Field(description="当前步骤名称", alias="stepName") + sub_step_id: str | None = Field(description="当前子步骤ID", alias="subStepId", default=None) + sub_step_name: str | None = Field(description="当前子步骤名称", alias="subStepName", default=None) step_status: StepStatus = Field(description="当前步骤状态", alias="stepStatus") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 2305dd93..5d6dc7fc 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -16,8 +16,8 @@ class RequestDataApp(BaseModel): """模型对话中包含的app信息""" app_id: str = Field(description="应用ID", alias="appId") - flow_id: str = Field(description="Flow ID", alias="flowId") - params: dict[str, Any] = Field(description="插件参数") + flow_id: str | None = Field(default=None, description="Flow ID", alias="flowId") + params: dict[str, Any] | None = Field(default=None, description="插件参数") class MockRequestData(BaseModel): -- Gitee From f02748f597d63b3b072b0749681bf1827283987e Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 24 Jul 2025 21:13:04 +0800 Subject: [PATCH 07/78] =?UTF-8?q?=E5=AE=8C=E5=96=84Agent=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=8F=91&=E4=BF=AE=E5=A4=8Dmcp=E6=B3=A8=E5=86=8C=E6=97=B6?= =?UTF-8?q?=E5=80=99=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/chat.py | 11 ++++++++--- apps/scheduler/call/mcp/mcp.py | 7 ------- apps/scheduler/executor/agent.py | 28 +++++++++------------------ apps/scheduler/pool/loader/mcp.py | 1 - apps/scheduler/scheduler/scheduler.py | 2 +- apps/schemas/enum_var.py | 3 +++ apps/schemas/mcp.py | 3 ++- apps/schemas/request_data.py | 1 + apps/schemas/task.py | 3 +++ apps/services/task.py | 9 --------- 10 files changed, 27 insertions(+), 41 deletions(-) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 7fe5162c..589000be 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -36,11 +36,16 @@ async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> T # 生成group_id if not post_body.group_id: post_body.group_id = str(uuid.uuid4()) - # 创建或还原Task + if post_body.new_task: + # 创建或还原Task + task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) + if task: + await TaskManager.delete_task_by_task_id(task.id) task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) # 更改信息并刷新数据库 - task.runtime.question = post_body.question - task.ids.group_id = post_body.group_id + if post_body.new_task: + task.runtime.question = post_body.question + task.ids.group_id = post_body.group_id return task diff --git a/apps/scheduler/call/mcp/mcp.py b/apps/scheduler/call/mcp/mcp.py index 661e9ada..4e6a1bb7 100644 --- a/apps/scheduler/call/mcp/mcp.py +++ b/apps/scheduler/call/mcp/mcp.py @@ -35,7 +35,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): text_output: bool = Field(description="是否将结果以文本形式返回", default=True) to_user: bool = Field(description="是否将结果返回给用户", default=True) - @classmethod def info(cls) -> CallInfo: """ @@ -46,7 +45,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): """ return CallInfo(name="MCP", description="调用MCP Server,执行工具") - async def _init(self, call_vars: CallVars) -> MCPInput: """初始化MCP""" # 获取MCP交互类 @@ -63,7 +61,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): return MCPInput(avaliable_tools=avaliable_tools, max_steps=self.max_steps) - async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """执行MCP""" # 生成计划 @@ -80,7 +77,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): async for chunk in self._generate_answer(): yield chunk - async def _generate_plan(self) -> AsyncGenerator[CallOutputChunk, None]: """生成执行计划""" # 开始提示 @@ -103,7 +99,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): data=self._plan.model_dump(), ) - async def _execute_plan_item(self, plan_item: MCPPlanItem) -> AsyncGenerator[CallOutputChunk, None]: """执行单个计划项""" # 判断是否为Final @@ -141,7 +136,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): }, ) - async def _generate_answer(self) -> AsyncGenerator[CallOutputChunk, None]: """生成总结""" # 提示开始总结 @@ -163,7 +157,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): ).model_dump(), ) - def _create_output( self, text: str, diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index f6814dd3..2ff4f3d3 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -7,6 +7,8 @@ from pydantic import Field from apps.scheduler.executor.base import BaseExecutor from apps.scheduler.mcp_agent.agent.mcp import MCPAgent +from apps.schemas.task import ExecutorState, StepQueueItem +from apps.services.task import TaskManager logger = logging.getLogger(__name__) @@ -15,26 +17,14 @@ class MCPAgentExecutor(BaseExecutor): """MCP Agent执行器""" question: str = Field(description="用户输入") - max_steps: int = Field(default=10, description="最大步数") + max_steps: int = Field(default=20, description="最大步数") servers_id: list[str] = Field(description="MCP server id") agent_id: str = Field(default="", description="Agent ID") agent_description: str = Field(default="", description="Agent描述") - async def run(self) -> None: - """运行MCP Agent""" - agent = await MCPAgent.create( - servers_id=self.servers_id, - max_steps=self.max_steps, - task=self.task, - msg_queue=self.msg_queue, - question=self.question, - agent_id=self.agent_id, - description=self.agent_description, - ) - - try: - answer = await agent.run(self.question) - self.task = agent.task - self.task.runtime.answer = answer - except Exception as e: - logger.error(f"Error: {str(e)}") + async def load_state(self) -> None: + """从数据库中加载FlowExecutor的状态""" + logger.info("[FlowExecutor] 加载Executor状态") + # 尝试恢复State + if self.task.state: + self.task.context = await TaskManager.get_context_by_task_id(self.task.id) diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index 66a516e7..1463d0a1 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -153,7 +153,6 @@ class MCPLoader(metaclass=SingletonMeta): # 检查目录 template_path = MCP_PATH / "template" / mcp_id await Path.mkdir(template_path, parents=True, exist_ok=True) - ProcessHandler.clear_finished_tasks() # 安装MCP模板 if not ProcessHandler.add_task(mcp_id, MCPLoader._install_template_task, mcp_id, config): err = f"安装任务无法执行,请稍后重试: {mcp_id}" diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index ed73638c..417f93d2 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -206,7 +206,7 @@ class Scheduler: task=self.task, msg_queue=queue, question=post_body.question, - max_steps=app_metadata.history_len, + history_len=app_metadata.history_len, servers_id=servers_id, background=background, agent_id=app_info.app_id, diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 9a20ba84..a84dc3a3 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -15,6 +15,7 @@ class SlotType(str, Enum): class StepStatus(str, Enum): """步骤状态""" + WAITING = "waiting" RUNNING = "running" SUCCESS = "success" ERROR = "error" @@ -38,6 +39,8 @@ class EventType(str, Enum): TEXT_ADD = "text.add" GRAPH = "graph" DOCUMENT_ADD = "document.add" + STEP_WAITING_FOR_START = "step.waiting_for_start" + STEP_WAITING_FOR_PARAM = "step.waiting_for_param" FLOW_START = "flow.start" STEP_INPUT = "step.input" STEP_OUTPUT = "step.output" diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 44021b0e..60c8f17b 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP 相关数据结构""" +import uuid from enum import Enum from typing import Any @@ -117,7 +118,7 @@ class MCPToolSelectResult(BaseModel): class MCPPlanItem(BaseModel): """MCP 计划""" - + id: str = Field(default_factory=lambda: str(uuid.uuid4())) content: str = Field(description="计划内容") tool: str = Field(description="工具名称") instruction: str = Field(description="工具指令") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 5d6dc7fc..a3a8848c 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -46,6 +46,7 @@ class RequestData(BaseModel): files: list[str] = Field(default=[], description="文件列表") app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") + new_task: bool = Field(default=True, description="是否新建任务") class QuestionBlacklistRequest(BaseModel): diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 8efcb599..37fdebbf 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -9,6 +9,7 @@ from pydantic import BaseModel, Field from apps.schemas.enum_var import StepStatus from apps.schemas.flow import Step +from apps.schemas.mcp import MCPPlan class FlowStepHistory(BaseModel): @@ -42,6 +43,7 @@ class ExecutorState(BaseModel): # 附加信息 step_id: str = Field(description="当前步骤ID") step_name: str = Field(description="当前步骤名称") + step_description: str = Field(description="当前步骤描述", default="") app_id: str = Field(description="应用ID") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) error_info: dict[str, Any] = Field(description="错误信息", default={}) @@ -75,6 +77,7 @@ class TaskRuntime(BaseModel): summary: str = Field(description="摘要", default="") filled: dict[str, Any] = Field(description="填充的槽位", default={}) documents: list[dict[str, Any]] = Field(description="文档列表", default=[]) + temporary_plans: MCPPlan | None = Field(description="临时计划列表", default=None) class Task(BaseModel): diff --git a/apps/services/task.py b/apps/services/task.py index 1e672be6..2456d96b 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -45,7 +45,6 @@ class TaskManager: return Task.model_validate(task) - @staticmethod async def get_task_by_group_id(group_id: str, conversation_id: str) -> Task | None: """获取组ID的最后一条问答组关联的任务""" @@ -58,7 +57,6 @@ class TaskManager: task = await task_collection.find_one({"_id": record_group_obj.task_id}) return Task.model_validate(task) - @staticmethod async def get_task_by_task_id(task_id: str) -> Task | None: """根据task_id获取任务""" @@ -68,7 +66,6 @@ class TaskManager: return None return Task.model_validate(task) - @staticmethod async def get_context_by_record_id(record_group_id: str, record_id: str) -> list[dict[str, Any]]: """根据record_group_id获取flow信息""" @@ -95,7 +92,6 @@ class TaskManager: else: return flow_context_list - @staticmethod async def get_context_by_task_id(task_id: str, length: int = 0) -> list[dict[str, Any]]: """根据task_id获取flow信息""" @@ -115,7 +111,6 @@ class TaskManager: else: return flow_context - @staticmethod async def save_flow_context(task_id: str, flow_context: list[dict[str, Any]]) -> None: """保存flow信息到flow_context""" @@ -137,7 +132,6 @@ class TaskManager: except Exception: logger.exception("[TaskManager] 保存flow执行记录失败") - @staticmethod async def delete_task_by_task_id(task_id: str) -> None: """通过task_id删除Task信息""" @@ -148,7 +142,6 @@ class TaskManager: if task: await task_collection.delete_one({"_id": task_id}) - @staticmethod async def delete_tasks_by_conversation_id(conversation_id: str) -> None: """通过ConversationID删除Task信息""" @@ -167,7 +160,6 @@ class TaskManager: await task_collection.delete_many({"conversation_id": conversation_id}, session=session) await flow_context_collection.delete_many({"task_id": {"$in": task_ids}}, session=session) - @classmethod async def get_task( cls, @@ -212,7 +204,6 @@ class TaskManager: runtime=TaskRuntime(), ) - @classmethod async def save_task(cls, task_id: str, task: Task) -> None: """保存任务块""" -- Gitee From b929ed4ead156f6d7008ec575830375b7beb0218 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 12:16:10 +0800 Subject: [PATCH 08/78] =?UTF-8?q?=E9=80=82=E9=85=8Drag=E7=9A=84=E4=BD=9C?= =?UTF-8?q?=E8=80=85=E5=92=8C=E5=88=9B=E5=BB=BA=E6=97=B6=E9=97=B4=E7=9A=84?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/scheduler/context.py | 3 +++ apps/scheduler/scheduler/message.py | 9 +-------- apps/schemas/record.py | 6 +++++- apps/services/document.py | 4 ++++ apps/services/rag.py | 3 +++ 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index b7088d8d..4c2c4cf0 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -114,11 +114,14 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: used_docs.append( RecordGroupDocument( _id=docs["id"], + author=docs.get("author", ""), + order=docs.get("order", 0), name=docs["name"], abstract=docs.get("abstract", ""), extension=docs.get("extension", ""), size=docs.get("size", 0), associated="answer", + created_at=docs.get("created_at", round(datetime.now(UTC).timestamp(), 3)), ) ) if docs.get("order") is not None: diff --git a/apps/scheduler/scheduler/message.py b/apps/scheduler/scheduler/message.py index c89fdd10..5997b48f 100644 --- a/apps/scheduler/scheduler/message.py +++ b/apps/scheduler/scheduler/message.py @@ -71,14 +71,7 @@ async def push_rag_message( # 如果是文本消息,直接拼接到答案中 full_answer += content_obj.content elif content_obj.event_type == EventType.DOCUMENT_ADD.value: - task.runtime.documents.append({ - "id": content_obj.content.get("id", ""), - "order": content_obj.content.get("order", 0), - "name": content_obj.content.get("name", ""), - "abstract": content_obj.content.get("abstract", ""), - "extension": content_obj.content.get("extension", ""), - "size": content_obj.content.get("size", 0), - }) + task.runtime.documents.append(content_obj.content) # 保存答案 task.runtime.answer = full_answer await TaskManager.save_task(task.id, task) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index d7acd368..e1a995f8 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -17,8 +17,9 @@ class RecordDocument(Document): """GET /api/record/{conversation_id} Result中的document数据结构""" id: str = Field(alias="_id", default="") + order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") - user_sub: None = None + author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] class Config: @@ -103,11 +104,14 @@ class RecordGroupDocument(BaseModel): """RecordGroup关联的文件""" id: str = Field(default_factory=lambda: str(uuid.uuid4()), alias="_id") + order: int = Field(default=0, description="文档顺序") + author: str = Field(default="", description="文档作者") name: str = Field(default="", description="文档名称") abstract: str = Field(default="", description="文档摘要") extension: str = Field(default="", description="文档扩展名") size: int = Field(default=0, description="文档大小,单位是KB") associated: Literal["question", "answer"] + created_at: float = Field(default=0.0, description="文档创建时间") class Record(RecordData): diff --git a/apps/services/document.py b/apps/services/document.py index 203162da..451423a9 100644 --- a/apps/services/document.py +++ b/apps/services/document.py @@ -2,6 +2,7 @@ """文件Manager""" import base64 +from datetime import UTC, datetime import logging import uuid @@ -131,12 +132,15 @@ class DocumentManager: return [ RecordDocument( _id=doc.id, + order=doc.order, + author=doc.author, abstract=doc.abstract, name=doc.name, type=doc.extension, size=doc.size, conversation_id=record_group.get("conversation_id", ""), associated=doc.associated, + created_at=doc.created_at or round(datetime.now(tz=UTC).timestamp(), 3) ) for doc in docs if type is None or doc.associated == type ] diff --git a/apps/services/rag.py b/apps/services/rag.py index 6b6c843d..efbdfe94 100644 --- a/apps/services/rag.py +++ b/apps/services/rag.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """对接Euler Copilot RAG""" +from datetime import UTC, datetime import json import logging from collections.abc import AsyncGenerator @@ -156,9 +157,11 @@ class RAG: "id": doc_chunk["docId"], "order": doc_cnt, "name": doc_chunk.get("docName", ""), + "author": doc_chunk.get("docAuthor", ""), "extension": doc_chunk.get("docExtension", ""), "abstract": doc_chunk.get("docAbstract", ""), "size": doc_chunk.get("docSize", 0), + "created_at": doc_chunk.get("docCreatedAt", round(datetime.now(UTC).timestamp(), 3)), }) doc_id_map[doc_chunk["docId"]] = doc_cnt doc_index = doc_id_map[doc_chunk["docId"]] -- Gitee From 755d5c315b6d9c0d3833383a790b188b0f53b28d Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:40:30 +0800 Subject: [PATCH 09/78] =?UTF-8?q?=E5=AF=B9rag=E7=9A=84team=E5=92=8C?= =?UTF-8?q?=E5=9B=A2=E9=98=9F=E8=8E=B7=E5=8F=96=E5=A2=9E=E5=8A=A0=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/services/conversation.py | 6 +++++- apps/services/knowledge.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/services/conversation.py b/apps/services/conversation.py index 4bcade45..bac964db 100644 --- a/apps/services/conversation.py +++ b/apps/services/conversation.py @@ -59,7 +59,11 @@ class ConversationManager: model_name=llm.model_name, ) kb_item_list = [] - team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + try: + team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + except: + logger.error("[ConversationManager] 获取团队知识库列表失败") + team_kb_list = [] for team_kb in team_kb_list: for kb in team_kb["kbList"]: if str(kb["kbId"]) in kb_ids: diff --git a/apps/services/knowledge.py b/apps/services/knowledge.py index 9b4077f9..bd8dfc9e 100644 --- a/apps/services/knowledge.py +++ b/apps/services/knowledge.py @@ -138,7 +138,11 @@ class KnowledgeBaseManager: return [] kb_ids_update_success = [] kb_item_dict_list = [] - team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + try: + team_kb_list = await KnowledgeBaseManager.get_team_kb_list_from_rag(user_sub, None, None) + except Exception as e: + logger.error(f"[KnowledgeBaseManager] 获取团队知识库列表失败: {e}") + team_kb_list = [] for team_kb in team_kb_list: for kb in team_kb["kbList"]: if str(kb["kbId"]) in kb_ids: -- Gitee From d4ec596d65a0f0dfe4b4b442454da0a39b8b1325 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:53:07 +0800 Subject: [PATCH 10/78] =?UTF-8?q?=E5=AE=8C=E5=96=84RecordDocument=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/schemas/record.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index e1a995f8..6e9617a3 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -19,6 +19,7 @@ class RecordDocument(Document): id: str = Field(alias="_id", default="") order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") + user_sub: None | None author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] -- Gitee From 5fa678be223c4ed7eead9744074fb5402584247d Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 15:56:50 +0800 Subject: [PATCH 11/78] =?UTF-8?q?=E5=AE=8C=E5=96=84RecordDocument=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/schemas/record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 6e9617a3..b5e1b0c5 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -19,7 +19,7 @@ class RecordDocument(Document): id: str = Field(alias="_id", default="") order: int = Field(default=0, description="文档顺序") abstract: str = Field(default="", description="文档摘要") - user_sub: None | None + user_sub: None = None author: str = Field(default="", description="文档作者") associated: Literal["question", "answer"] -- Gitee From b407dc0ce2f530220448ac87544f861f3a8d4513 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 23 Jul 2025 16:21:07 +0800 Subject: [PATCH 12/78] =?UTF-8?q?=E5=AE=8C=E5=96=84DocumentAddContent?= =?UTF-8?q?=E7=9A=84=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/scheduler/message.py | 2 ++ apps/schemas/message.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/scheduler/scheduler/message.py b/apps/scheduler/scheduler/message.py index 5997b48f..a2a45e41 100644 --- a/apps/scheduler/scheduler/message.py +++ b/apps/scheduler/scheduler/message.py @@ -108,10 +108,12 @@ async def _push_rag_chunk(task: Task, queue: MessageQueue, content: str) -> tupl data=DocumentAddContent( documentId=content_obj.content.get("id", ""), documentOrder=content_obj.content.get("order", 0), + documentAuthor=content_obj.content.get("author", ""), documentName=content_obj.content.get("name", ""), documentAbstract=content_obj.content.get("abstract", ""), documentType=content_obj.content.get("extension", ""), documentSize=content_obj.content.get("size", 0), + createdAt=round(datetime.now(tz=UTC).timestamp(), 3), ).model_dump(exclude_none=True, by_alias=True), ) except Exception: diff --git a/apps/schemas/message.py b/apps/schemas/message.py index d0661224..5f0aee8a 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -2,7 +2,7 @@ """队列中的消息结构""" from typing import Any - +from datetime import UTC, datetime from pydantic import BaseModel, Field from apps.schemas.enum_var import EventType, StepStatus @@ -60,10 +60,14 @@ class DocumentAddContent(BaseModel): document_id: str = Field(description="文档UUID", alias="documentId") document_order: int = Field(description="文档在对话中的顺序,从1开始", alias="documentOrder") + document_author: str = Field(description="文档作者", alias="documentAuthor", default="") document_name: str = Field(description="文档名称", alias="documentName") document_abstract: str = Field(description="文档摘要", alias="documentAbstract", default="") document_type: str = Field(description="文档MIME类型", alias="documentType", default="") document_size: float = Field(ge=0, description="文档大小,单位是KB,保留两位小数", alias="documentSize", default=0) + created_at: float = Field( + description="文档创建时间,单位是秒", alias="createdAt", default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3) + ) class FlowStartContent(BaseModel): -- Gitee From af1b364f950f18d5c6165438ea9a04fe6697e070 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 24 Jul 2025 19:22:36 +0800 Subject: [PATCH 13/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=97=A0=E9=89=B4?= =?UTF-8?q?=E6=9D=83=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/dependency/user.py | 8 +++++++ apps/routers/api_key.py | 1 + apps/routers/auth.py | 3 +-- apps/scheduler/executor/step.py | 38 ++++++++++++++++----------------- apps/schemas/config.py | 9 +++++++- apps/schemas/message.py | 2 ++ apps/schemas/request_data.py | 4 ++-- 7 files changed, 41 insertions(+), 24 deletions(-) diff --git a/apps/dependency/user.py b/apps/dependency/user.py index fce67e51..87cbd290 100644 --- a/apps/dependency/user.py +++ b/apps/dependency/user.py @@ -5,10 +5,12 @@ import logging from fastapi import Depends from fastapi.security import OAuth2PasswordBearer +import secrets from starlette import status from starlette.exceptions import HTTPException from starlette.requests import HTTPConnection +from apps.common.config import Config from apps.services.api_key import ApiKeyManager from apps.services.session import SessionManager @@ -48,6 +50,9 @@ async def get_session(request: HTTPConnection) -> str: :param request: HTTP请求 :return: Session ID """ + if Config().get_config().no_auth.enable: + # 如果启用了无认证访问,直接返回调试用户 + return secrets.token_hex(16) session_id = await _get_session_id_from_request(request) if not session_id: raise HTTPException( @@ -69,6 +74,9 @@ async def get_user(request: HTTPConnection) -> str: :param request: HTTP请求体 :return: 用户sub """ + if Config().get_config().no_auth.enable: + # 如果启用了无认证访问,直接返回调试用户 + return Config().get_config().no_auth.user_sub session_id = await _get_session_id_from_request(request) if not session_id: raise HTTPException( diff --git a/apps/routers/api_key.py b/apps/routers/api_key.py index 158cfc13..51366a21 100644 --- a/apps/routers/api_key.py +++ b/apps/routers/api_key.py @@ -6,6 +6,7 @@ from typing import Annotated from fastapi import APIRouter, Depends, status from fastapi.responses import JSONResponse + from apps.dependency.user import get_user, verify_user from apps.schemas.api_key import GetAuthKeyRsp, PostAuthKeyMsg, PostAuthKeyRsp from apps.schemas.response_data import ResponseData diff --git a/apps/routers/auth.py b/apps/routers/auth.py index 1cba5ed6..4a3f8293 100644 --- a/apps/routers/auth.py +++ b/apps/routers/auth.py @@ -9,6 +9,7 @@ from fastapi import APIRouter, Depends, Request, status from fastapi.responses import HTMLResponse, JSONResponse from fastapi.templating import Jinja2Templates +from apps.common.config import Config from apps.common.oidc import oidc_provider from apps.dependency import get_session, get_user, verify_user from apps.schemas.collection import Audit @@ -47,8 +48,6 @@ async def oidc_login(request: Request, code: str) -> HTMLResponse: user_info = await oidc_provider.get_oidc_user(token["access_token"]) user_sub: str | None = user_info.get("user_sub", None) - if user_sub: - await oidc_provider.set_token(user_sub, token["access_token"], token["refresh_token"]) except Exception as e: logger.exception("User login failed") status_code = status.HTTP_400_BAD_REQUEST if "auth error" in str(e) else status.HTTP_403_FORBIDDEN diff --git a/apps/scheduler/executor/step.py b/apps/scheduler/executor/step.py index 6b3451fa..506f3bb1 100644 --- a/apps/scheduler/executor/step.py +++ b/apps/scheduler/executor/step.py @@ -86,8 +86,8 @@ class StepExecutor(BaseExecutor): logger.info("[StepExecutor] 初始化步骤 %s", self.step.step.name) # State写入ID和运行状态 - self.task.state.step_id = self.step.step_id # type: ignore[arg-type] - self.task.state.step_name = self.step.step.name # type: ignore[arg-type] + self.task.state.step_id = self.step.step_id # type: ignore[arg-type] + self.task.state.step_name = self.step.step.name # type: ignore[arg-type] # 获取并验证Call类 node_id = self.step.step.node @@ -127,13 +127,13 @@ class StepExecutor(BaseExecutor): return # 暂存旧数据 - current_step_id = self.task.state.step_id # type: ignore[arg-type] - current_step_name = self.task.state.step_name # type: ignore[arg-type] + current_step_id = self.task.state.step_id # type: ignore[arg-type] + current_step_name = self.task.state.step_name # type: ignore[arg-type] # 更新State - self.task.state.step_id = str(uuid.uuid4()) # type: ignore[arg-type] - self.task.state.step_name = "自动参数填充" # type: ignore[arg-type] - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.step_id = str(uuid.uuid4()) # type: ignore[arg-type] + self.task.state.step_name = "自动参数填充" # type: ignore[arg-type] + self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 初始化填参 @@ -156,17 +156,17 @@ class StepExecutor(BaseExecutor): # 如果没有填全,则状态设置为待填参 if result.remaining_schema: - self.task.state.status = StepStatus.PARAM # type: ignore[arg-type] + self.task.state.status = StepStatus.PARAM # type: ignore[arg-type] else: - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, result.model_dump(by_alias=True, exclude_none=True)) # 更新输入 self.obj.input.update(result.slot_data) # 恢复State - self.task.state.step_id = current_step_id # type: ignore[arg-type] - self.task.state.step_name = current_step_name # type: ignore[arg-type] + self.task.state.step_id = current_step_id # type: ignore[arg-type] + self.task.state.step_name = current_step_name # type: ignore[arg-type] self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens @@ -212,7 +212,7 @@ class StepExecutor(BaseExecutor): await self._run_slot_filling() # 更新状态 - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 推送输入 await self.push_message(EventType.STEP_INPUT.value, self.obj.input) @@ -224,22 +224,22 @@ class StepExecutor(BaseExecutor): content = await self._process_chunk(iterator, to_user=self.obj.to_user) except Exception as e: logger.exception("[StepExecutor] 运行步骤失败,进行异常处理步骤") - self.task.state.status = StepStatus.ERROR # type: ignore[arg-type] + self.task.state.status = StepStatus.ERROR # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, {}) if isinstance(e, CallError): - self.task.state.error_info = { # type: ignore[arg-type] + self.task.state.error_info = { # type: ignore[arg-type] "err_msg": e.message, "data": e.data, } else: - self.task.state.error_info = { # type: ignore[arg-type] + self.task.state.error_info = { # type: ignore[arg-type] "err_msg": str(e), "data": {}, } return # 更新执行状态 - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens self.task.tokens.full_time += round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.time @@ -253,12 +253,12 @@ class StepExecutor(BaseExecutor): # 更新context history = FlowStepHistory( task_id=self.task.id, - flow_id=self.task.state.flow_id, # type: ignore[arg-type] - flow_name=self.task.state.flow_name, # type: ignore[arg-type] + flow_id=self.task.state.flow_id, # type: ignore[arg-type] + flow_name=self.task.state.flow_name, # type: ignore[arg-type] step_id=self.step.step_id, step_name=self.step.step.name, step_description=self.step.step.description, - status=self.task.state.status, # type: ignore[arg-type] + status=self.task.state.status, # type: ignore[arg-type] input_data=self.obj.input, output_data=output_data, ) diff --git a/apps/schemas/config.py b/apps/schemas/config.py index b88a81f1..99bcccde 100644 --- a/apps/schemas/config.py +++ b/apps/schemas/config.py @@ -6,6 +6,13 @@ from typing import Literal from pydantic import BaseModel, Field +class NoauthConfig(BaseModel): + """无认证配置""" + + enable: bool = Field(description="是否启用无认证访问", default=False) + user_sub: str = Field(description="调试用户的sub", default="admin") + + class DeployConfig(BaseModel): """部署配置""" @@ -122,7 +129,7 @@ class ExtraConfig(BaseModel): class ConfigModel(BaseModel): """配置文件的校验Class""" - + no_auth: NoauthConfig deploy: DeployConfig login: LoginConfig embedding: EmbeddingConfig diff --git a/apps/schemas/message.py b/apps/schemas/message.py index 5f0aee8a..cf70a82b 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -24,6 +24,8 @@ class MessageFlow(BaseModel): flow_id: str = Field(description="Flow ID", alias="flowId") step_id: str = Field(description="当前步骤ID", alias="stepId") step_name: str = Field(description="当前步骤名称", alias="stepName") + sub_step_id: str | None = Field(description="当前子步骤ID", alias="subStepId", default=None) + sub_step_name: str | None = Field(description="当前子步骤名称", alias="subStepName", default=None) step_status: StepStatus = Field(description="当前步骤状态", alias="stepStatus") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 2305dd93..5d6dc7fc 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -16,8 +16,8 @@ class RequestDataApp(BaseModel): """模型对话中包含的app信息""" app_id: str = Field(description="应用ID", alias="appId") - flow_id: str = Field(description="Flow ID", alias="flowId") - params: dict[str, Any] = Field(description="插件参数") + flow_id: str | None = Field(default=None, description="Flow ID", alias="flowId") + params: dict[str, Any] | None = Field(default=None, description="插件参数") class MockRequestData(BaseModel): -- Gitee From 9653ef8e6c3d6ba15aba377b9721a1f605f7cff7 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 24 Jul 2025 21:13:04 +0800 Subject: [PATCH 14/78] =?UTF-8?q?=E5=AE=8C=E5=96=84Agent=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=8F=91&=E4=BF=AE=E5=A4=8Dmcp=E6=B3=A8=E5=86=8C=E6=97=B6?= =?UTF-8?q?=E5=80=99=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/chat.py | 11 ++++++++--- apps/scheduler/call/mcp/mcp.py | 7 ------- apps/scheduler/executor/agent.py | 28 +++++++++------------------ apps/scheduler/scheduler/scheduler.py | 2 +- apps/schemas/enum_var.py | 3 +++ apps/schemas/mcp.py | 3 ++- apps/schemas/request_data.py | 1 + apps/schemas/task.py | 3 +++ apps/services/task.py | 9 --------- 9 files changed, 27 insertions(+), 40 deletions(-) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 7fe5162c..589000be 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -36,11 +36,16 @@ async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> T # 生成group_id if not post_body.group_id: post_body.group_id = str(uuid.uuid4()) - # 创建或还原Task + if post_body.new_task: + # 创建或还原Task + task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) + if task: + await TaskManager.delete_task_by_task_id(task.id) task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) # 更改信息并刷新数据库 - task.runtime.question = post_body.question - task.ids.group_id = post_body.group_id + if post_body.new_task: + task.runtime.question = post_body.question + task.ids.group_id = post_body.group_id return task diff --git a/apps/scheduler/call/mcp/mcp.py b/apps/scheduler/call/mcp/mcp.py index 661e9ada..4e6a1bb7 100644 --- a/apps/scheduler/call/mcp/mcp.py +++ b/apps/scheduler/call/mcp/mcp.py @@ -35,7 +35,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): text_output: bool = Field(description="是否将结果以文本形式返回", default=True) to_user: bool = Field(description="是否将结果返回给用户", default=True) - @classmethod def info(cls) -> CallInfo: """ @@ -46,7 +45,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): """ return CallInfo(name="MCP", description="调用MCP Server,执行工具") - async def _init(self, call_vars: CallVars) -> MCPInput: """初始化MCP""" # 获取MCP交互类 @@ -63,7 +61,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): return MCPInput(avaliable_tools=avaliable_tools, max_steps=self.max_steps) - async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """执行MCP""" # 生成计划 @@ -80,7 +77,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): async for chunk in self._generate_answer(): yield chunk - async def _generate_plan(self) -> AsyncGenerator[CallOutputChunk, None]: """生成执行计划""" # 开始提示 @@ -103,7 +99,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): data=self._plan.model_dump(), ) - async def _execute_plan_item(self, plan_item: MCPPlanItem) -> AsyncGenerator[CallOutputChunk, None]: """执行单个计划项""" # 判断是否为Final @@ -141,7 +136,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): }, ) - async def _generate_answer(self) -> AsyncGenerator[CallOutputChunk, None]: """生成总结""" # 提示开始总结 @@ -163,7 +157,6 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): ).model_dump(), ) - def _create_output( self, text: str, diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index f6814dd3..2ff4f3d3 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -7,6 +7,8 @@ from pydantic import Field from apps.scheduler.executor.base import BaseExecutor from apps.scheduler.mcp_agent.agent.mcp import MCPAgent +from apps.schemas.task import ExecutorState, StepQueueItem +from apps.services.task import TaskManager logger = logging.getLogger(__name__) @@ -15,26 +17,14 @@ class MCPAgentExecutor(BaseExecutor): """MCP Agent执行器""" question: str = Field(description="用户输入") - max_steps: int = Field(default=10, description="最大步数") + max_steps: int = Field(default=20, description="最大步数") servers_id: list[str] = Field(description="MCP server id") agent_id: str = Field(default="", description="Agent ID") agent_description: str = Field(default="", description="Agent描述") - async def run(self) -> None: - """运行MCP Agent""" - agent = await MCPAgent.create( - servers_id=self.servers_id, - max_steps=self.max_steps, - task=self.task, - msg_queue=self.msg_queue, - question=self.question, - agent_id=self.agent_id, - description=self.agent_description, - ) - - try: - answer = await agent.run(self.question) - self.task = agent.task - self.task.runtime.answer = answer - except Exception as e: - logger.error(f"Error: {str(e)}") + async def load_state(self) -> None: + """从数据库中加载FlowExecutor的状态""" + logger.info("[FlowExecutor] 加载Executor状态") + # 尝试恢复State + if self.task.state: + self.task.context = await TaskManager.get_context_by_task_id(self.task.id) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index ed73638c..417f93d2 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -206,7 +206,7 @@ class Scheduler: task=self.task, msg_queue=queue, question=post_body.question, - max_steps=app_metadata.history_len, + history_len=app_metadata.history_len, servers_id=servers_id, background=background, agent_id=app_info.app_id, diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 9a20ba84..a84dc3a3 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -15,6 +15,7 @@ class SlotType(str, Enum): class StepStatus(str, Enum): """步骤状态""" + WAITING = "waiting" RUNNING = "running" SUCCESS = "success" ERROR = "error" @@ -38,6 +39,8 @@ class EventType(str, Enum): TEXT_ADD = "text.add" GRAPH = "graph" DOCUMENT_ADD = "document.add" + STEP_WAITING_FOR_START = "step.waiting_for_start" + STEP_WAITING_FOR_PARAM = "step.waiting_for_param" FLOW_START = "flow.start" STEP_INPUT = "step.input" STEP_OUTPUT = "step.output" diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 44021b0e..60c8f17b 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP 相关数据结构""" +import uuid from enum import Enum from typing import Any @@ -117,7 +118,7 @@ class MCPToolSelectResult(BaseModel): class MCPPlanItem(BaseModel): """MCP 计划""" - + id: str = Field(default_factory=lambda: str(uuid.uuid4())) content: str = Field(description="计划内容") tool: str = Field(description="工具名称") instruction: str = Field(description="工具指令") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 5d6dc7fc..a3a8848c 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -46,6 +46,7 @@ class RequestData(BaseModel): files: list[str] = Field(default=[], description="文件列表") app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") + new_task: bool = Field(default=True, description="是否新建任务") class QuestionBlacklistRequest(BaseModel): diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 8efcb599..37fdebbf 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -9,6 +9,7 @@ from pydantic import BaseModel, Field from apps.schemas.enum_var import StepStatus from apps.schemas.flow import Step +from apps.schemas.mcp import MCPPlan class FlowStepHistory(BaseModel): @@ -42,6 +43,7 @@ class ExecutorState(BaseModel): # 附加信息 step_id: str = Field(description="当前步骤ID") step_name: str = Field(description="当前步骤名称") + step_description: str = Field(description="当前步骤描述", default="") app_id: str = Field(description="应用ID") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) error_info: dict[str, Any] = Field(description="错误信息", default={}) @@ -75,6 +77,7 @@ class TaskRuntime(BaseModel): summary: str = Field(description="摘要", default="") filled: dict[str, Any] = Field(description="填充的槽位", default={}) documents: list[dict[str, Any]] = Field(description="文档列表", default=[]) + temporary_plans: MCPPlan | None = Field(description="临时计划列表", default=None) class Task(BaseModel): diff --git a/apps/services/task.py b/apps/services/task.py index 1e672be6..2456d96b 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -45,7 +45,6 @@ class TaskManager: return Task.model_validate(task) - @staticmethod async def get_task_by_group_id(group_id: str, conversation_id: str) -> Task | None: """获取组ID的最后一条问答组关联的任务""" @@ -58,7 +57,6 @@ class TaskManager: task = await task_collection.find_one({"_id": record_group_obj.task_id}) return Task.model_validate(task) - @staticmethod async def get_task_by_task_id(task_id: str) -> Task | None: """根据task_id获取任务""" @@ -68,7 +66,6 @@ class TaskManager: return None return Task.model_validate(task) - @staticmethod async def get_context_by_record_id(record_group_id: str, record_id: str) -> list[dict[str, Any]]: """根据record_group_id获取flow信息""" @@ -95,7 +92,6 @@ class TaskManager: else: return flow_context_list - @staticmethod async def get_context_by_task_id(task_id: str, length: int = 0) -> list[dict[str, Any]]: """根据task_id获取flow信息""" @@ -115,7 +111,6 @@ class TaskManager: else: return flow_context - @staticmethod async def save_flow_context(task_id: str, flow_context: list[dict[str, Any]]) -> None: """保存flow信息到flow_context""" @@ -137,7 +132,6 @@ class TaskManager: except Exception: logger.exception("[TaskManager] 保存flow执行记录失败") - @staticmethod async def delete_task_by_task_id(task_id: str) -> None: """通过task_id删除Task信息""" @@ -148,7 +142,6 @@ class TaskManager: if task: await task_collection.delete_one({"_id": task_id}) - @staticmethod async def delete_tasks_by_conversation_id(conversation_id: str) -> None: """通过ConversationID删除Task信息""" @@ -167,7 +160,6 @@ class TaskManager: await task_collection.delete_many({"conversation_id": conversation_id}, session=session) await flow_context_collection.delete_many({"task_id": {"$in": task_ids}}, session=session) - @classmethod async def get_task( cls, @@ -212,7 +204,6 @@ class TaskManager: runtime=TaskRuntime(), ) - @classmethod async def save_task(cls, task_id: str, task: Task) -> None: """保存任务块""" -- Gitee From 23fd74f6c25e2dd98bb487b485e42663da1a2369 Mon Sep 17 00:00:00 2001 From: zengxianghuai Date: Fri, 25 Jul 2025 17:34:51 +0800 Subject: [PATCH 15/78] =?UTF-8?q?=E5=A2=9E=E5=8A=A0choice=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E4=BB=A5=E5=8F=8A=E7=9B=B8=E5=85=B3=E8=8E=B7=E5=8F=96?= =?UTF-8?q?step=5Fid=E5=92=8C=E6=93=8D=E4=BD=9C=E7=AC=A6=E7=9A=84=E8=B7=AF?= =?UTF-8?q?=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/parameter.py | 143 ++++++++++++++ apps/scheduler/call/choice/choice.py | 79 +++++++- .../call/choice/condition_handler.py | 184 ++++++++++++++++++ apps/scheduler/call/choice/schema.py | 66 +++++++ apps/scheduler/executor/flow.py | 9 + apps/schemas/response_data.py | 18 ++ apps/services/flow.py | 26 ++- 7 files changed, 516 insertions(+), 9 deletions(-) create mode 100644 apps/routers/parameter.py create mode 100644 apps/scheduler/call/choice/condition_handler.py diff --git a/apps/routers/parameter.py b/apps/routers/parameter.py new file mode 100644 index 00000000..33789dfd --- /dev/null +++ b/apps/routers/parameter.py @@ -0,0 +1,143 @@ +from typing import Annotated + +from fastapi import APIRouter, Depends, Query, status +from fastapi.responses import JSONResponse + +from apps.dependency import get_user +from apps.dependency.user import verify_user +from apps.scheduler.call.choice.choice import Choice +from apps.schemas.response_data import ( + FlowStructureGetMsg, + FlowStructureGetRsp, + GetParamsMsg, + GetParamsRsp, + ResponseData, +) +from apps.services.application import AppManager +from apps.services.flow import FlowManager + +router = APIRouter( + prefix="/api/parameter", + tags=["parameter"], + dependencies=[ + Depends(verify_user), + ], +) + + +@router.get("", response_model={ + status.HTTP_403_FORBIDDEN: {"model": ResponseData}, + status.HTTP_404_NOT_FOUND: {"model": ResponseData}, + },) +async def get_parameters( + user_sub: Annotated[str, Depends(get_user)], + app_id: Annotated[str, Query(alias="appId")], + flow_id: Annotated[str, Query(alias="flowId")], + step_id: Annotated[str, Query(alias="stepId")], +) -> JSONResponse: + """Get parameters for node choice.""" + if not await AppManager.validate_user_app_access(user_sub, app_id): + return JSONResponse( + status_code=status.HTTP_403_FORBIDDEN, + content=FlowStructureGetRsp( + code=status.HTTP_403_FORBIDDEN, + message="用户没有权限访问该流", + result=FlowStructureGetMsg(), + ).model_dump(exclude_none=True, by_alias=True), + ) + flow = await FlowManager.get_flow_by_app_and_flow_id(app_id, flow_id) + if not flow: + return JSONResponse( + status_code=status.HTTP_404_NOT_FOUND, + content=FlowStructureGetRsp( + code=status.HTTP_404_NOT_FOUND, + message="未找到该流", + result={}, + ).model_dump(exclude_none=True, by_alias=True), + ) + result = await FlowManager.get_step_by_flow_and_step_id(flow, step_id) + if not result: + return JSONResponse( + status_code=status.HTTP_404_NOT_FOUND, + content=FlowStructureGetRsp( + code=status.HTTP_404_NOT_FOUND, + message="未找到该节点", + result={}, + ).model_dump(exclude_none=True, by_alias=True), + ) + return JSONResponse( + status_code=status.HTTP_200_OK, + content=GetParamsRsp( + code=status.HTTP_200_OK, + message="获取参数成功", + result=GetParamsMsg(result=result), + ).model_dump(exclude_none=True, by_alias=True), + ) + +async def operate_parameters(operate: str) -> list[str] | None: + """ + 根据操作类型获取对应的操作符参数列表 + + Args: + operate: 操作类型,支持 'int', 'str', 'bool' + + Returns: + 对应的操作符参数列表,若类型不支持则返回None + + """ + string = [ + "equal", + "not_equal", + "great",#长度大于 + "great_equals",#长度大于等于 + "less",#长度小于 + "less_equals",#长度小于等于 + "greater", + "greater_equals", + "smaller", + "smaller_equals", + ] + integer = [ + "equal", + "not_equal", + "great", + "great_equals", + "less", + "less_equals", + ] + boolen = ["equal", "not_equal", "is_empty", "not_empty"] + if operate in string: + return string + if operate in integer: + return integer + if operate in boolen: + return boolen + return None + +@router.get("/operate", response_model={ + status.HTTP_200_OK: {"model": ResponseData}, + status.HTTP_404_NOT_FOUND: {"model": ResponseData}, + },) +async def get_operate_parameters( + user_sub: Annotated[str, Depends(get_user)], + operate: Annotated[str, Query(alias="operate")] +) -> JSONResponse: + """Get parameters for node choice.""" + result = await operate_parameters(operate) + if not result: + return JSONResponse( + status_code=status.HTTP_404_NOT_FOUND, + content=ResponseData( + code=status.HTTP_404_NOT_FOUND, + message="未找到该符号", + result=[], + ).model_dump(exclude_none=True, by_alias=True), + ) + return JSONResponse( + status_code=status.HTTP_200_OK, + content=ResponseData( + code=status.HTTP_200_OK, + message="获取参数成功", + result=result, + ).model_dump(exclude_none=True, by_alias=True), + ) \ No newline at end of file diff --git a/apps/scheduler/call/choice/choice.py b/apps/scheduler/call/choice/choice.py index a5edf21a..e9cd7d41 100644 --- a/apps/scheduler/call/choice/choice.py +++ b/apps/scheduler/call/choice/choice.py @@ -1,19 +1,82 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """使用大模型或使用程序做出判断""" -from enum import Enum - -from apps.scheduler.call.choice.schema import ChoiceInput, ChoiceOutput -from apps.scheduler.call.core import CoreCall +import logging +from collections.abc import AsyncGenerator +from typing import Any +from pydantic import Field -class Operator(str, Enum): - """Choice工具支持的运算符""" +from apps.scheduler.call.choice.condition_handler import ConditionHandler +from apps.scheduler.call.choice.schema import ( + ChoiceBranch, + ChoiceInput, + ChoiceOutput, + Logic, +) +from apps.scheduler.call.core import CoreCall +from apps.schemas.enum_var import CallOutputType +from apps.schemas.scheduler import ( + CallError, + CallInfo, + CallOutputChunk, + CallVars, +) - pass +logger = logging.getLogger(__name__) class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): """Choice工具""" - pass + to_user: bool = Field(default=False) + choices: list[ChoiceBranch] = Field(description="分支", default=[]) + + @classmethod + def info(cls) -> CallInfo: + """返回Call的名称和描述""" + return CallInfo(name="Choice", description="使用大模型或使用程序做出判断") + + async def _prepare_message(self, call_vars: CallVars) -> list[dict[str, Any]]: + """替换choices中的系统变量""" + valid_choices = [] + for choice in self.choices: + if choice.logic not in [Logic.AND, Logic.OR]: + logger.warning("分支 %s 的逻辑运算符 %s 无效,已跳过",choice.branch_id, choice.logic) + continue + valid_conditions = [] + for condition in choice.conditions: + if condition.left.step_id: + condition.left.value = self._extract_history_variables( + condition.left.step_id, call_vars.history, + ) + valid_conditions.append(condition) + else: + logger.warning("条件 %s 的左侧变量 %s 无效,已跳过", condition.condition_id, condition.left) + continue + choice.conditions = valid_conditions + valid_choices.append(choice.dict()) + return valid_choices + + async def _init(self, call_vars: CallVars) -> ChoiceInput: + """初始化Choice工具""" + return ChoiceInput( + choices=await self._prepare_message(call_vars), + ) + + async def _exec( + self, input_data: dict[str, Any] + ) -> AsyncGenerator[CallOutputChunk, None]: + """执行Choice工具""" + # 解析输入数据 + data = ChoiceInput(**input_data) + ret: CallOutputChunk = CallOutputChunk( + type=CallOutputType.DATA, + content=None, + ) + condition_handler = ConditionHandler() + try: + ret.content = condition_handler.handler(data.choices) + yield ret + except Exception as e: + raise CallError(message=f"选择工具调用失败:{e!s}", data={}) from e diff --git a/apps/scheduler/call/choice/condition_handler.py b/apps/scheduler/call/choice/condition_handler.py new file mode 100644 index 00000000..feab5c64 --- /dev/null +++ b/apps/scheduler/call/choice/condition_handler.py @@ -0,0 +1,184 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""处理条件分支的工具""" + +import logging + +from pydantic import BaseModel + +from apps.scheduler.call.choice.schema import ChoiceBranch, ChoiceOutput, Condition, Logic, Operator, Type, Value + +logger = logging.getLogger(__name__) + + +class ConditionHandler(BaseModel): + """条件分支处理器""" + + def handler(self, choices: list[ChoiceBranch]) -> ChoiceOutput: + """处理条件""" + default_branch = [c for c in choices if c.is_default] + + for block_judgement in choices: + results = [] + if block_judgement.is_default: + continue + for condition in block_judgement.conditions: + result = self._judge_condition(condition) + results.append(result) + if block_judgement.logic == Logic.AND: + final_result = all(results) + elif block_judgement.logic == Logic.OR: + final_result = any(results) + + if final_result: + return { + "branch_id": block_judgement.branch_id, + "message": f"选择分支:{block_judgement.branch_id}", + } + + # 如果没有匹配的分支,选择默认分支 + if default_branch: + return { + "branch_id": default_branch[0].branch_id, + "message": f"选择默认分支:{default_branch[0].branch_id}", + } + return { + "branch_id": "", + "message": "没有匹配的分支,且没有默认分支", + } + + def _judge_condition(self, condition: Condition) -> bool: + """ + 判断条件是否成立。 + + Args: + condition (Condition): 'left', 'operator', 'right', 'type' + + Returns: + bool + + """ + left = condition.left + operator = condition.operator + right = condition.right + value_type = condition.type + + result = None + if value_type == Type.STRING: + result = self._judge_string_condition(left, operator, right) + elif value_type == Type.INT: + result = self._judge_int_condition(left, operator, right) + elif value_type == Type.BOOL: + result = self._judge_bool_condition(left, operator, right) + else: + logger.error("不支持的数据类型: %s", value_type) + msg = f"不支持的数据类型: {value_type}" + raise ValueError(msg) + return result + + def _judge_string_condition(self, left: Value, operator: Operator, right: Value) -> bool: + """ + 判断字符串类型的条件。 + + Args: + left (Value): 左值,包含 'value' 键。 + operator (Operator): 操作符 + right (Value): 右值,包含 'value' 键。 + + Returns: + bool + + """ + left_value = left.value + if not isinstance(left_value, str): + logger.error("左值不是字符串类型: %s", left_value) + msg = "左值必须是字符串类型" + raise TypeError(msg) + right_value = right.value + result = False + if operator == Operator.EQUAL: + result = left_value == right_value + elif operator == Operator.NEQUAL: + result = left_value != right_value + elif operator == Operator.GREAT: + result = len(left_value) > len(right_value) + elif operator == Operator.GREAT_EQUALS: + result = len(left_value) >= len(right_value) + elif operator == Operator.LESS: + result = len(left_value) < len(right_value) + elif operator == Operator.LESS_EQUALS: + result = len(left_value) <= len(right_value) + elif operator == Operator.GREATER: + result = left_value > right_value + elif operator == Operator.GREATER_EQUALS: + result = left_value >= right_value + elif operator == Operator.SMALLER: + result = left_value < right_value + elif operator == Operator.SMALLER_EQUALS: + result = left_value <= right_value + elif operator == Operator.CONTAINS: + result = right_value in left_value + elif operator == Operator.NOT_CONTAINS: + result = right_value not in left_value + return result + + def _judge_int_condition(self, left: Value, operator: Operator, right: Value) -> bool: # noqa: PLR0911 + """ + 判断整数类型的条件。 + + Args: + left (Value): 左值,包含 'value' 键。 + operator (Operator): 操作符 + right (Value): 右值,包含 'value' 键。 + + Returns: + bool + + """ + left_value = left.value + if not isinstance(left_value, int): + logger.error("左值不是整数类型: %s", left_value) + msg = "左值必须是整数类型" + raise TypeError(msg) + right_value = right.value + if operator == Operator.EQUAL: + return left_value == right_value + if operator == Operator.NEQUAL: + return left_value != right_value + if operator == Operator.GREAT: + return left_value > right_value + if operator == Operator.GREAT_EQUALS: + return left_value >= right_value + if operator == Operator.LESS: + return left_value < right_value + if operator == Operator.LESS_EQUALS: + return left_value <= right_value + return False + + def _judge_bool_condition(self, left: Value, operator: Operator, right: Value) -> bool: + """ + 判断布尔类型的条件。 + + Args: + left (Value): 左值,包含 'value' 键。 + operator (Operator): 操作符 + right (Value): 右值,包含 'value' 键。 + + Returns: + bool + + """ + left_value = left.value + if not isinstance(left_value, bool): + logger.error("左值不是布尔类型: %s", left_value) + msg = "左值必须是布尔类型" + raise TypeError(msg) + right_value = right.value + if operator == Operator.EQUAL: + return left_value == right_value + if operator == Operator.NEQUAL: + return left_value != right_value + if operator == Operator.IS_EMPTY: + return left_value == "" + if operator == Operator.NOT_EMPTY: + return left_value != "" + return False diff --git a/apps/scheduler/call/choice/schema.py b/apps/scheduler/call/choice/schema.py index 60b62d09..ed1c628c 100644 --- a/apps/scheduler/call/choice/schema.py +++ b/apps/scheduler/call/choice/schema.py @@ -1,12 +1,78 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Choice Call的输入和输出""" +from enum import Enum + +from pydantic import BaseModel, Field + from apps.scheduler.call.core import DataBase +class Operator(str, Enum): + """Choice Call支持的运算符""" + + EQUAL = "equal" + NEQUAL = "not_equal" + GREAT = "great" + GREAT_EQUALS = "great_equals" + LESS = "less" + LESS_EQUALS = "less_equals" + # string + CONTAINS = "contains" + NOT_CONTAINS = "not_contains" + GREATER = "greater" + GREATER_EQUALS = "greater_equals" + SMALLER = "smaller" + SMALLER_EQUALS = "smaller_equals" + # bool + IS_EMPTY = "is_empty" + NOT_EMPTY = "not_empty" + + +class Logic(str, Enum): + """Choice 工具支持的逻辑运算符""" + + AND = "and" + OR = "or" + + +class Type(str, Enum): + """Choice 工具支持的类型""" + + STRING = "string" + INT = "int" + BOOL = "bool" + + +class Value(BaseModel): + """值的结构""" + + step_id: str = Field(description="步骤id", default="") + value: str | int | bool = Field(description="值", default=None) + + +class Condition(BaseModel): + """单个条件""" + + type: Type = Field(description="值的类型", default=Type.STRING) + left: Value = Field(description="左值") + right: Value = Field(description="右值") + operator: Operator = Field(description="运算符", default="equal") + id: int = Field(description="条件ID") + + +class ChoiceBranch(BaseModel): + """子分支""" + + branch_id: str = Field(description="分支ID", default="") + logic: Logic = Field(description="逻辑运算符", default=Logic.AND) + conditions: list[Condition] = Field(description="条件列表", default=[]) + is_default: bool = Field(description="是否为默认分支", default=False) class ChoiceInput(DataBase): """Choice Call的输入""" + choices: list[ChoiceBranch] = Field(description="分支", default=[]) + class ChoiceOutput(DataBase): """Choice Call的输出""" diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index a70d0d70..d8d22c46 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -117,6 +117,15 @@ class FlowExecutor(BaseExecutor): # 如果当前步骤为结束,则直接返回 if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] return [] + if self.task.state.step_name == "Choice": + # 如果是choice节点,获取分支ID + branch_id = self.task.context[-1]["output_data"].get("branch_id", None) + if branch_id: + self.task.state.step_id = self.task.state.step_id + "." + branch_id + logger.info("[FlowExecutor] 分支ID:%s", branch_id) + else: + logger.warning("[FlowExecutor] 没有找到分支ID,返回空列表") + return [] next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] # 如果step没有任何出边,直接跳到end diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index b2a18729..20d7ad9b 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -628,3 +628,21 @@ class ListLLMRsp(ResponseData): """GET /api/llm 返回数据结构""" result: list[LLMProviderInfo] = Field(default=[], title="Result") + +class Params(BaseModel): + """参数数据结构""" + + id: str = Field(..., description="StepID") + name: str = Field(..., description="Step名称") + parameters: dict[str, Any] = Field(..., description="参数") + operate: str = Field(..., description="比较符") + +class GetParamsMsg(BaseModel): + """GET /api/params 返回数据结构""" + + result: list[Params] = Field(..., title="Result") + +class GetParamsRsp(ResponseData): + """GET /api/params 返回数据结构""" + + result: GetParamsMsg \ No newline at end of file diff --git a/apps/services/flow.py b/apps/services/flow.py index 9275fc60..0a253c31 100644 --- a/apps/services/flow.py +++ b/apps/services/flow.py @@ -20,7 +20,7 @@ from apps.schemas.flow_topology import ( PositionItem, ) from apps.services.node import NodeManager - +from apps.schemas.response_data import Params logger = logging.getLogger(__name__) @@ -470,3 +470,27 @@ class FlowManager: return False else: return True + + @staticmethod + async def get_step_by_flow_and_step_id(flow: FlowItem, step_id: str) -> list[Params] | None: + """ + 寻找stepID对应的节点之前的所有节点的参数 + """ + params = [] + try: + for edge in flow.edges: + if edge.target_node == step_id: + id = edge.source_node + if id == "start": + break + params.append(Params( + id = id, + name = flow.nodes[id].name, + parameters = flow.nodes[id].parameters.get("parameters", {}) + )) + step_id = edge.source_node + return params + except Exception: + logger.exception("[FlowManager] 获取节点失败") + return None + \ No newline at end of file -- Gitee From 884000ea5b1287f8d86b9a137d116ed503e4e3c7 Mon Sep 17 00:00:00 2001 From: zengxianghuai Date: Fri, 25 Jul 2025 17:55:41 +0800 Subject: [PATCH 16/78] =?UTF-8?q?=E5=A2=9E=E5=8A=A0choice=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=8D=95=E8=8E=B7=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/call/choice/choice.py | 53 ++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/apps/scheduler/call/choice/choice.py b/apps/scheduler/call/choice/choice.py index e9cd7d41..24df0dae 100644 --- a/apps/scheduler/call/choice/choice.py +++ b/apps/scheduler/call/choice/choice.py @@ -37,25 +37,50 @@ class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): """返回Call的名称和描述""" return CallInfo(name="Choice", description="使用大模型或使用程序做出判断") + def _raise_value_error(self, msg: str) -> None: + """统一处理 ValueError 异常抛出""" + logger.warning(msg) + raise ValueError(msg) + async def _prepare_message(self, call_vars: CallVars) -> list[dict[str, Any]]: """替换choices中的系统变量""" valid_choices = [] + for choice in self.choices: - if choice.logic not in [Logic.AND, Logic.OR]: - logger.warning("分支 %s 的逻辑运算符 %s 无效,已跳过",choice.branch_id, choice.logic) + try: + # 验证逻辑运算符 + if choice.logic not in [Logic.AND, Logic.OR]: + msg = f"无效的逻辑运算符: {choice.logic}" + self._raise_value_error(msg) + + valid_conditions = [] + for condition in choice.conditions: + # 处理左值 + if condition.left.step_id: + condition.left.value = self._extract_history_variables(condition.left.step_id, call_vars.history) + # 检查历史变量是否成功提取 + if condition.left.value is None: + msg = f"步骤 {condition.left.step_id} 的历史变量不存在" + self._raise_value_error(msg) + else: + msg = "左侧变量缺少step_id" + self._raise_value_error(msg) + + valid_conditions.append(condition) + + # 如果所有条件都无效,抛出异常 + if not valid_conditions: + msg = "分支没有有效条件" + self._raise_value_error(msg) + + # 更新有效条件 + choice.conditions = valid_conditions + valid_choices.append(choice.dict()) + + except ValueError as e: + logger.warning("分支 %s 处理失败: %s,已跳过", choice.branch_id, str(e)) continue - valid_conditions = [] - for condition in choice.conditions: - if condition.left.step_id: - condition.left.value = self._extract_history_variables( - condition.left.step_id, call_vars.history, - ) - valid_conditions.append(condition) - else: - logger.warning("条件 %s 的左侧变量 %s 无效,已跳过", condition.condition_id, condition.left) - continue - choice.conditions = valid_conditions - valid_choices.append(choice.dict()) + return valid_choices async def _init(self, call_vars: CallVars) -> ChoiceInput: -- Gitee From b51ed5f71018454a29c6dc0bee93593f4c92e177 Mon Sep 17 00:00:00 2001 From: zengxianghuai Date: Fri, 25 Jul 2025 18:45:20 +0800 Subject: [PATCH 17/78] =?UTF-8?q?=E4=BF=AE=E6=94=B9get=5Fparams=5Fby=5Fflo?= =?UTF-8?q?w=5Fand=5Fstep=5Fid=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/parameter.py | 4 +-- apps/services/flow.py | 63 ++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/apps/routers/parameter.py b/apps/routers/parameter.py index 33789dfd..538c2556 100644 --- a/apps/routers/parameter.py +++ b/apps/routers/parameter.py @@ -55,7 +55,7 @@ async def get_parameters( result={}, ).model_dump(exclude_none=True, by_alias=True), ) - result = await FlowManager.get_step_by_flow_and_step_id(flow, step_id) + result = await FlowManager.get_params_by_flow_and_step_id(flow, step_id) if not result: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, @@ -120,7 +120,7 @@ async def operate_parameters(operate: str) -> list[str] | None: },) async def get_operate_parameters( user_sub: Annotated[str, Depends(get_user)], - operate: Annotated[str, Query(alias="operate")] + operate: Annotated[str, Query(alias="operate")], ) -> JSONResponse: """Get parameters for node choice.""" result = await operate_parameters(operate) diff --git a/apps/services/flow.py b/apps/services/flow.py index 0a253c31..cb8ad57f 100644 --- a/apps/services/flow.py +++ b/apps/services/flow.py @@ -472,25 +472,46 @@ class FlowManager: return True @staticmethod - async def get_step_by_flow_and_step_id(flow: FlowItem, step_id: str) -> list[Params] | None: - """ - 寻找stepID对应的节点之前的所有节点的参数 - """ + async def get_params_by_flow_and_step_id( + flow: FlowItem, step_id: str + ) -> list[Params] | None: + """递归收集指定节点之前所有路径上的节点参数""" params = [] - try: - for edge in flow.edges: - if edge.target_node == step_id: - id = edge.source_node - if id == "start": - break - params.append(Params( - id = id, - name = flow.nodes[id].name, - parameters = flow.nodes[id].parameters.get("parameters", {}) - )) - step_id = edge.source_node - return params - except Exception: - logger.exception("[FlowManager] 获取节点失败") - return None - \ No newline at end of file + collected = set() # 记录已收集参数的节点 + + async def backtrack(current_id: str, visited: set) -> None: + # 避免循环递归 + if current_id in visited: + return + visited.add(current_id) + + # 获取所有指向当前节点的边 + incoming_edges = [ + edge for edge in flow.edges if edge.target_node == current_id + ] + + for edge in incoming_edges: + source_id = edge.source_node + + # 跳过起始节点 + if source_id == "start": + continue + + # 收集当前节点的参数(如果未被收集过) + if source_id not in collected: + node = flow.nodes.get(source_id) + if node: + collected.add(source_id) + params.append( + Params( + id=source_id, + name=node.name, + parameters=node.parameters.get("parameters", {}), + ), + ) + + # 继续回溯,传递当前路径的visited集合副本 + await backtrack(source_id, visited.copy()) + + await backtrack(step_id, set()) + return params -- Gitee From e4dfb413f4147e9cee2fb570a89b05f9fdc57331 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 25 Jul 2025 19:09:10 +0800 Subject: [PATCH 18/78] =?UTF-8?q?=E5=AE=8C=E5=96=84mcp=20agent=E7=9A=84?= =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/queue.py | 2 +- apps/routers/record.py | 21 +- apps/scheduler/call/mcp/mcp.py | 2 +- apps/scheduler/executor/agent.py | 2 +- apps/scheduler/executor/flow.py | 28 +- apps/scheduler/executor/step.py | 18 +- apps/scheduler/mcp/host.py | 9 +- apps/scheduler/mcp_agent/__init__.py | 8 + apps/scheduler/mcp_agent/agent/base.py | 196 -------------- apps/scheduler/mcp_agent/agent/mcp.py | 81 ------ apps/scheduler/mcp_agent/agent/react.py | 35 --- apps/scheduler/mcp_agent/agent/toolcall.py | 238 ----------------- apps/scheduler/mcp_agent/host.py | 190 ++++++++++++++ apps/scheduler/mcp_agent/plan.py | 110 ++++++++ apps/scheduler/mcp_agent/prompt.py | 240 ++++++++++++++++++ apps/scheduler/mcp_agent/schema.py | 148 ----------- apps/scheduler/mcp_agent/select.py | 185 ++++++++++++++ apps/scheduler/mcp_agent/tool/__init__.py | 9 - apps/scheduler/mcp_agent/tool/base.py | 73 ------ apps/scheduler/mcp_agent/tool/terminate.py | 25 -- .../mcp_agent/tool/tool_collection.py | 55 ---- apps/scheduler/scheduler/context.py | 2 +- apps/schemas/enum_var.py | 11 + apps/schemas/record.py | 1 + apps/schemas/task.py | 12 +- tests/common/test_queue.py | 4 +- 26 files changed, 792 insertions(+), 913 deletions(-) create mode 100644 apps/scheduler/mcp_agent/__init__.py delete mode 100644 apps/scheduler/mcp_agent/agent/base.py delete mode 100644 apps/scheduler/mcp_agent/agent/mcp.py delete mode 100644 apps/scheduler/mcp_agent/agent/react.py delete mode 100644 apps/scheduler/mcp_agent/agent/toolcall.py create mode 100644 apps/scheduler/mcp_agent/host.py create mode 100644 apps/scheduler/mcp_agent/plan.py create mode 100644 apps/scheduler/mcp_agent/prompt.py delete mode 100644 apps/scheduler/mcp_agent/schema.py create mode 100644 apps/scheduler/mcp_agent/select.py delete mode 100644 apps/scheduler/mcp_agent/tool/__init__.py delete mode 100644 apps/scheduler/mcp_agent/tool/base.py delete mode 100644 apps/scheduler/mcp_agent/tool/terminate.py delete mode 100644 apps/scheduler/mcp_agent/tool/tool_collection.py diff --git a/apps/common/queue.py b/apps/common/queue.py index 5601c93a..911485b3 100644 --- a/apps/common/queue.py +++ b/apps/common/queue.py @@ -58,7 +58,7 @@ class MessageQueue: flowId=task.state.flow_id, stepId=task.state.step_id, stepName=task.state.step_name, - stepStatus=task.state.status, + stepStatus=task.state.step_status ) else: flow = None diff --git a/apps/routers/record.py b/apps/routers/record.py index 7384793b..f357f0de 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -83,22 +83,23 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ tmp_record.document = await DocumentManager.get_used_docs_by_record_group(user_sub, record_group.id) # 获得Record关联的flow数据 - flow_list = await TaskManager.get_context_by_record_id(record_group.id, record.id) - if flow_list: - first_flow = FlowStepHistory.model_validate(flow_list[0]) + flow_step_list = await TaskManager.get_context_by_record_id(record_group.id, record.id) + if flow_step_list: + first_step_history = FlowStepHistory.model_validate(flow_step_list[0]) tmp_record.flow = RecordFlow( - id=first_flow.flow_name, #TODO: 此处前端应该用name + id=first_step_history.flow_name, # TODO: 此处前端应该用name recordId=record.id, - flowId=first_flow.id, - stepNum=len(flow_list), + flowStatus=first_step_history.flow_status, + flowId=first_step_history.id, + stepNum=len(flow_step_list), steps=[], ) - for flow in flow_list: - flow_step = FlowStepHistory.model_validate(flow) + for flow_step in flow_step_list: + flow_step = FlowStepHistory.model_validate(flow_step) tmp_record.flow.steps.append( RecordFlowStep( - stepId=flow_step.step_name, #TODO: 此处前端应该用name - stepStatus=flow_step.status, + stepId=flow_step.step_name, # TODO: 此处前端应该用name + stepStatus=flow_step.step_status, input=flow_step.input_data, output=flow_step.output_data, ), diff --git a/apps/scheduler/call/mcp/mcp.py b/apps/scheduler/call/mcp/mcp.py index 4e6a1bb7..bd0257b4 100644 --- a/apps/scheduler/call/mcp/mcp.py +++ b/apps/scheduler/call/mcp/mcp.py @@ -31,7 +31,7 @@ class MCP(CoreCall, input_model=MCPInput, output_model=MCPOutput): """MCP工具""" mcp_list: list[str] = Field(description="MCP Server ID列表", max_length=5, min_length=1) - max_steps: int = Field(description="最大步骤数", default=6) + max_steps: int = Field(description="最大步骤数", default=20) text_output: bool = Field(description="是否将结果以文本形式返回", default=True) to_user: bool = Field(description="是否将结果返回给用户", default=True) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 2ff4f3d3..cb8e183e 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -6,7 +6,7 @@ import logging from pydantic import Field from apps.scheduler.executor.base import BaseExecutor -from apps.scheduler.mcp_agent.agent.mcp import MCPAgent +from apps.scheduler.mcp_agent import host, plan, select from apps.schemas.task import ExecutorState, StepQueueItem from apps.services.task import TaskManager diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index a70d0d70..e5381a4a 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -11,7 +11,7 @@ from pydantic import Field from apps.scheduler.call.llm.prompt import LLM_ERROR_PROMPT from apps.scheduler.executor.base import BaseExecutor from apps.scheduler.executor.step import StepExecutor -from apps.schemas.enum_var import EventType, SpecialCallType, StepStatus +from apps.schemas.enum_var import EventType, SpecialCallType, FlowStatus, StepStatus from apps.schemas.flow import Flow, Step from apps.schemas.request_data import RequestDataApp from apps.schemas.task import ExecutorState, StepQueueItem @@ -47,7 +47,6 @@ class FlowExecutor(BaseExecutor): question: str = Field(description="用户输入") post_body_app: RequestDataApp = Field(description="请求体中的app信息") - async def load_state(self) -> None: """从数据库中加载FlowExecutor的状态""" logger.info("[FlowExecutor] 加载Executor状态") @@ -59,8 +58,9 @@ class FlowExecutor(BaseExecutor): self.task.state = ExecutorState( flow_id=str(self.flow_id), flow_name=self.flow.name, + flow_status=FlowStatus.RUNNING, description=str(self.flow.description), - status=StepStatus.RUNNING, + step_status=StepStatus.RUNNING, app_id=str(self.post_body_app.app_id), step_id="start", step_name="开始", @@ -70,7 +70,6 @@ class FlowExecutor(BaseExecutor): self._reached_end: bool = False self.step_queue: deque[StepQueueItem] = deque() - async def _invoke_runner(self, queue_item: StepQueueItem) -> None: """单一Step执行""" # 创建步骤Runner @@ -90,7 +89,6 @@ class FlowExecutor(BaseExecutor): # 更新Task(已存过库) self.task = step_runner.task - async def _step_process(self) -> None: """执行当前queue里面的所有步骤(在用户看来是单一Step)""" while True: @@ -102,7 +100,6 @@ class FlowExecutor(BaseExecutor): # 执行Step await self._invoke_runner(queue_item) - async def _find_next_id(self, step_id: str) -> list[str]: """查找下一个节点""" next_ids = [] @@ -111,14 +108,13 @@ class FlowExecutor(BaseExecutor): next_ids += [edge.edge_to] return next_ids - async def _find_flow_next(self) -> list[StepQueueItem]: """在当前步骤执行前,尝试获取下一步""" # 如果当前步骤为结束,则直接返回 - if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] + if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] return [] - next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] + next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] # 如果step没有任何出边,直接跳到end if not next_steps: return [ @@ -137,7 +133,6 @@ class FlowExecutor(BaseExecutor): for next_step in next_steps ] - async def run(self) -> None: """ 运行流,返回各步骤结果,直到无法继续执行 @@ -150,8 +145,8 @@ class FlowExecutor(BaseExecutor): # 获取首个步骤 first_step = StepQueueItem( - step_id=self.task.state.step_id, # type: ignore[arg-type] - step=self.flow.steps[self.task.state.step_id], # type: ignore[arg-type] + step_id=self.task.state.step_id, # type: ignore[arg-type] + step=self.flow.steps[self.task.state.step_id], # type: ignore[arg-type] ) # 头插开始前的系统步骤,并执行 @@ -166,11 +161,11 @@ class FlowExecutor(BaseExecutor): # 插入首个步骤 self.step_queue.append(first_step) - + self.task.state.flow_status = FlowStatus.RUNNING # type: ignore[arg-type] # 运行Flow(未达终点) while not self._reached_end: # 如果当前步骤出错,执行错误处理步骤 - if self.task.state.status == StepStatus.ERROR: # type: ignore[arg-type] + if self.task.state.step_status == StepStatus.ERROR: # type: ignore[arg-type] logger.warning("[FlowExecutor] Executor出错,执行错误处理步骤") self.step_queue.clear() self.step_queue.appendleft(StepQueueItem( @@ -183,13 +178,14 @@ class FlowExecutor(BaseExecutor): params={ "user_prompt": LLM_ERROR_PROMPT.replace( "{{ error_info }}", - self.task.state.error_info["err_msg"], # type: ignore[arg-type] + self.task.state.error_info["err_msg"], # type: ignore[arg-type] ), }, ), enable_filling=False, to_user=False, )) + self.task.state.flow_status = FlowStatus.ERROR # type: ignore[arg-type] # 错误处理后结束 self._reached_end = True @@ -216,3 +212,5 @@ class FlowExecutor(BaseExecutor): self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.full_time # 推送Flow停止消息 await self.push_message(EventType.FLOW_STOP.value) + # 更新Task状态 + self.task.state.flow_status = FlowStatus.SUCCESS # type: ignore[arg-type] diff --git a/apps/scheduler/executor/step.py b/apps/scheduler/executor/step.py index 506f3bb1..377a4c6e 100644 --- a/apps/scheduler/executor/step.py +++ b/apps/scheduler/executor/step.py @@ -119,7 +119,6 @@ class StepExecutor(BaseExecutor): logger.exception("[StepExecutor] 初始化Call失败") raise - async def _run_slot_filling(self) -> None: """运行自动参数填充;相当于特殊Step,但是不存库""" # 判断是否需要进行自动参数填充 @@ -133,7 +132,7 @@ class StepExecutor(BaseExecutor): # 更新State self.task.state.step_id = str(uuid.uuid4()) # type: ignore[arg-type] self.task.state.step_name = "自动参数填充" # type: ignore[arg-type] - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.step_status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 初始化填参 @@ -156,9 +155,9 @@ class StepExecutor(BaseExecutor): # 如果没有填全,则状态设置为待填参 if result.remaining_schema: - self.task.state.status = StepStatus.PARAM # type: ignore[arg-type] + self.task.state.step_status = StepStatus.PARAM # type: ignore[arg-type] else: - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.step_status = StepStatus.SUCCESS # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, result.model_dump(by_alias=True, exclude_none=True)) # 更新输入 @@ -170,7 +169,6 @@ class StepExecutor(BaseExecutor): self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens - async def _process_chunk( self, iterator: AsyncGenerator[CallOutputChunk, None], @@ -202,7 +200,6 @@ class StepExecutor(BaseExecutor): return content - async def run(self) -> None: """运行单个步骤""" self.validate_flow_state(self.task) @@ -212,7 +209,7 @@ class StepExecutor(BaseExecutor): await self._run_slot_filling() # 更新状态 - self.task.state.status = StepStatus.RUNNING # type: ignore[arg-type] + self.task.state.step_status = StepStatus.RUNNING # type: ignore[arg-type] self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) # 推送输入 await self.push_message(EventType.STEP_INPUT.value, self.obj.input) @@ -224,7 +221,7 @@ class StepExecutor(BaseExecutor): content = await self._process_chunk(iterator, to_user=self.obj.to_user) except Exception as e: logger.exception("[StepExecutor] 运行步骤失败,进行异常处理步骤") - self.task.state.status = StepStatus.ERROR # type: ignore[arg-type] + self.task.state.step_status = StepStatus.ERROR # type: ignore[arg-type] await self.push_message(EventType.STEP_OUTPUT.value, {}) if isinstance(e, CallError): self.task.state.error_info = { # type: ignore[arg-type] @@ -239,7 +236,7 @@ class StepExecutor(BaseExecutor): return # 更新执行状态 - self.task.state.status = StepStatus.SUCCESS # type: ignore[arg-type] + self.task.state.step_status = StepStatus.SUCCESS # type: ignore[arg-type] self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens self.task.tokens.full_time += round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.time @@ -255,10 +252,11 @@ class StepExecutor(BaseExecutor): task_id=self.task.id, flow_id=self.task.state.flow_id, # type: ignore[arg-type] flow_name=self.task.state.flow_name, # type: ignore[arg-type] + flow_status=self.task.state.flow_status, # type: ignore[arg-type] step_id=self.step.step_id, step_name=self.step.step.name, step_description=self.step.step.description, - status=self.task.state.status, # type: ignore[arg-type] + step_status=self.task.state.step_status, input_data=self.obj.input, output_data=output_data, ) diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py index 78aa7bc3..acdd4871 100644 --- a/apps/scheduler/mcp/host.py +++ b/apps/scheduler/mcp/host.py @@ -40,7 +40,6 @@ class MCPHost: lstrip_blocks=True, ) - async def get_client(self, mcp_id: str) -> MCPClient | None: """获取MCP客户端""" mongo = MongoDB() @@ -59,7 +58,6 @@ class MCPHost: logger.warning("用户 %s 的MCP %s 没有运行中的实例,请检查环境", self._user_sub, mcp_id) return None - async def assemble_memory(self) -> str: """组装记忆""" task = await TaskManager.get_task_by_task_id(self._task_id) @@ -78,7 +76,6 @@ class MCPHost: context_list=context_list, ) - async def _save_memory( self, tool: MCPTool, @@ -105,11 +102,12 @@ class MCPHost: task_id=self._task_id, flow_id=self._runtime_id, flow_name=self._runtime_name, + flow_status=StepStatus.SUCCESS, step_id=tool.name, step_name=tool.name, # description是规划的实际内容 step_description=plan_item.content, - status=StepStatus.SUCCESS, + step_status=StepStatus.SUCCESS, input_data=input_data, output_data=output_data, ) @@ -125,7 +123,6 @@ class MCPHost: return output_data - async def _fill_params(self, tool: MCPTool, query: str) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate @@ -146,7 +143,6 @@ class MCPHost: ) return await json_generator.generate() - async def call_tool(self, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: """调用工具""" # 拿到Client @@ -170,7 +166,6 @@ class MCPHost: return processed_result - async def get_tool_list(self, mcp_id_list: list[str]) -> list[MCPTool]: """获取工具列表""" mongo = MongoDB() diff --git a/apps/scheduler/mcp_agent/__init__.py b/apps/scheduler/mcp_agent/__init__.py new file mode 100644 index 00000000..12f5cb68 --- /dev/null +++ b/apps/scheduler/mcp_agent/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""Scheduler MCP 模块""" + +from apps.scheduler.mcp.host import MCPHost +from apps.scheduler.mcp.plan import MCPPlanner +from apps.scheduler.mcp.select import MCPSelector + +__all__ = ["MCPHost", "MCPPlanner", "MCPSelector"] diff --git a/apps/scheduler/mcp_agent/agent/base.py b/apps/scheduler/mcp_agent/agent/base.py deleted file mode 100644 index eccb58a9..00000000 --- a/apps/scheduler/mcp_agent/agent/base.py +++ /dev/null @@ -1,196 +0,0 @@ -"""MCP Agent基类""" -import logging -from abc import ABC, abstractmethod -from contextlib import asynccontextmanager - -from pydantic import BaseModel, Field, model_validator - -from apps.common.queue import MessageQueue -from apps.schemas.enum_var import AgentState -from apps.schemas.task import Task -from apps.llm.reasoning import ReasoningLLM -from apps.scheduler.mcp_agent.schema import Memory, Message, Role -from apps.services.activity import Activity - -logger = logging.getLogger(__name__) - - -class BaseAgent(BaseModel, ABC): - """ - 用于管理代理状态和执行的抽象基类。 - - 为状态转换、内存管理、 - 以及分步执行循环。子类必须实现`step`方法。 - """ - - msg_queue: MessageQueue - task: Task - name: str = Field(..., description="Agent名称") - agent_id: str = Field(default="", description="Agent ID") - description: str = Field(default="", description="Agent描述") - question: str - # Prompts - next_step_prompt: str | None = Field( - None, description="判断下一步动作的提示" - ) - - # Dependencies - llm: ReasoningLLM = Field(default_factory=ReasoningLLM, description="大模型实例") - memory: Memory = Field(default_factory=Memory, description="Agent记忆库") - state: AgentState = Field( - default=AgentState.IDLE, description="Agent状态" - ) - servers_id: list[str] = Field(default_factory=list, description="MCP server id") - - # Execution control - max_steps: int = Field(default=10, description="终止前的最大步长") - current_step: int = Field(default=0, description="执行中的当前步骤") - - duplicate_threshold: int = 2 - - user_prompt: str = r""" - 当前步骤:{step} 工具输出结果:{result} - 请总结当前正在执行的步骤和对应的工具输出结果,内容包括当前步骤是多少,执行的工具是什么,输出是什么。 - 最终以报告的形式展示。 - 如果工具输出结果中执行的工具为terminate,请按照状态输出本次交互过程最终结果并完成对整个报告的总结,不需要输出你的分析过程。 - """ - """用户提示词""" - - class Config: - arbitrary_types_allowed = True - extra = "allow" # Allow extra fields for flexibility in subclasses - - @model_validator(mode="after") - def initialize_agent(self) -> "BaseAgent": - """初始化Agent""" - if self.llm is None or not isinstance(self.llm, ReasoningLLM): - self.llm = ReasoningLLM() - if not isinstance(self.memory, Memory): - self.memory = Memory() - return self - - @asynccontextmanager - async def state_context(self, new_state: AgentState): - """ - Agent状态转换上下文管理器 - - Args: - new_state: 要转变的状态 - - :return: None - :raise ValueError: 如果new_state无效 - """ - if not isinstance(new_state, AgentState): - raise ValueError(f"无效状态: {new_state}") - - previous_state = self.state - self.state = new_state - try: - yield - except Exception as e: - self.state = AgentState.ERROR # Transition to ERROR on failure - raise e - finally: - self.state = previous_state # Revert to previous state - - def update_memory( - self, - role: Role, - content: str, - **kwargs, - ) -> None: - """添加信息到Agent的memory中""" - message_map = { - "user": Message.user_message, - "system": Message.system_message, - "assistant": Message.assistant_message, - "tool": lambda content, **kw: Message.tool_message(content, **kw), - } - - if role not in message_map: - raise ValueError(f"不支持的消息角色: {role}") - - # Create message with appropriate parameters based on role - kwargs = {**(kwargs if role == "tool" else {})} - self.memory.add_message(message_map[role](content, **kwargs)) - - async def run(self, request: str | None = None) -> str: - """异步执行Agent的主循环""" - self.task.runtime.question = request - if self.state != AgentState.IDLE: - raise RuntimeError(f"无法从以下状态运行智能体: {self.state}") - - if request: - self.update_memory("user", request) - - results: list[str] = [] - async with self.state_context(AgentState.RUNNING): - while ( - self.current_step < self.max_steps and self.state != AgentState.FINISHED - ): - if not await Activity.is_active(self.task.ids.user_sub): - logger.info("用户终止会话,任务停止!") - return "" - self.current_step += 1 - logger.info(f"执行步骤{self.current_step}/{self.max_steps}") - step_result = await self.step() - - # Check for stuck state - if self.is_stuck(): - self.handle_stuck_state() - result = f"Step {self.current_step}: {step_result}" - results.append(result) - - if self.current_step >= self.max_steps: - self.current_step = 0 - self.state = AgentState.IDLE - result = f"任务终止: 已达到最大步数 ({self.max_steps})" - await self.msg_queue.push_output( - self.task, - event_type="text.add", - data={"text": result}, # type: ignore[arg-type] - ) - results.append(result) - return "\n".join(results) if results else "未执行任何步骤" - - @abstractmethod - async def step(self) -> str: - """ - 执行代理工作流程中的单个步骤。 - - 必须由子类实现,以定义具体的行为。 - """ - - def handle_stuck_state(self): - """通过添加更改策略的提示来处理卡住状态""" - stuck_prompt = "\ - 观察到重复响应。考虑新策略,避免重复已经尝试过的无效路径" - self.next_step_prompt = f"{stuck_prompt}\n{self.next_step_prompt}" - logger.warning(f"检测到智能体处于卡住状态。新增提示:{stuck_prompt}") - - def is_stuck(self) -> bool: - """通过检测重复内容来检查代理是否卡在循环中""" - if len(self.memory.messages) < 2: - return False - - last_message = self.memory.messages[-1] - if not last_message.content: - return False - - duplicate_count = sum( - 1 - for msg in reversed(self.memory.messages[:-1]) - if msg.role == "assistant" and msg.content == last_message.content - ) - - return duplicate_count >= self.duplicate_threshold - - @property - def messages(self) -> list[Message]: - """从Agent memory中检索消息列表""" - return self.memory.messages - - @messages.setter - def messages(self, value: list[Message]) -> None: - """设置Agent memory的消息列表""" - self.memory.messages = value diff --git a/apps/scheduler/mcp_agent/agent/mcp.py b/apps/scheduler/mcp_agent/agent/mcp.py deleted file mode 100644 index 378da368..00000000 --- a/apps/scheduler/mcp_agent/agent/mcp.py +++ /dev/null @@ -1,81 +0,0 @@ -"""MCP Agent""" -import logging - -from pydantic import Field - -from apps.scheduler.mcp.host import MCPHost -from apps.scheduler.mcp_agent.agent.toolcall import ToolCallAgent -from apps.scheduler.mcp_agent.tool import Terminate, ToolCollection - -logger = logging.getLogger(__name__) - - -class MCPAgent(ToolCallAgent): - """ - 用于与MCP(模型上下文协议)服务器交互。 - - 使用SSE或stdio传输连接到MCP服务器 - 并使服务器的工具 - """ - - name: str = "MCPAgent" - description: str = "一个多功能的智能体,能够使用多种工具(包括基于MCP的工具)解决各种任务" - - # Add general-purpose tools to the tool collection - available_tools: ToolCollection = Field( - default_factory=lambda: ToolCollection( - Terminate(), - ), - ) - - special_tool_names: list[str] = Field(default_factory=lambda: [Terminate().name]) - - _initialized: bool = False - - @classmethod - async def create(cls, **kwargs) -> "MCPAgent": # noqa: ANN003 - """创建并初始化MCP Agent实例""" - instance = cls(**kwargs) - await instance.initialize_mcp_servers() - instance._initialized = True - return instance - - async def initialize_mcp_servers(self) -> None: - """初始化与已配置的MCP服务器的连接""" - mcp_host = MCPHost( - self.task.ids.user_sub, - self.task.id, - self.agent_id, - self.description, - ) - mcps = {} - for mcp_id in self.servers_id: - client = await mcp_host.get_client(mcp_id) - if client: - mcps[mcp_id] = client - - for mcp_id, mcp_client in mcps.items(): - new_tools = [] - for tool in mcp_client.tools: - original_name = tool.name - # Always prefix with server_id to ensure uniqueness - tool_name = f"mcp_{mcp_id}_{original_name}" - - server_tool = MCPClientTool( - name=tool_name, - description=tool.description, - parameters=tool.inputSchema, - session=mcp_client.session, - server_id=mcp_id, - original_name=original_name, - ) - new_tools.append(server_tool) - self.available_tools.add_tools(*new_tools) - - async def think(self) -> bool: - """使用适当的上下文处理当前状态并决定下一步操作""" - if not self._initialized: - await self.initialize_mcp_servers() - self._initialized = True - - return await super().think() diff --git a/apps/scheduler/mcp_agent/agent/react.py b/apps/scheduler/mcp_agent/agent/react.py deleted file mode 100644 index b56efd8b..00000000 --- a/apps/scheduler/mcp_agent/agent/react.py +++ /dev/null @@ -1,35 +0,0 @@ -from abc import ABC, abstractmethod - -from pydantic import Field - -from apps.schemas.enum_var import AgentState -from apps.llm.reasoning import ReasoningLLM -from apps.scheduler.mcp_agent.agent.base import BaseAgent -from apps.scheduler.mcp_agent.schema import Memory - - -class ReActAgent(BaseAgent, ABC): - name: str - description: str | None = None - - system_prompt: str | None = None - next_step_prompt: str | None = None - - llm: ReasoningLLM | None = Field(default_factory=ReasoningLLM) - memory: Memory = Field(default_factory=Memory) - state: AgentState = AgentState.IDLE - - @abstractmethod - async def think(self) -> bool: - """处理当前状态并决定下一步操作""" - - @abstractmethod - async def act(self) -> str: - """执行已决定的行动""" - - async def step(self) -> str: - """执行一个步骤:思考和行动""" - should_act = await self.think() - if not should_act: - return "思考完成-无需采取任何行动" - return await self.act() diff --git a/apps/scheduler/mcp_agent/agent/toolcall.py b/apps/scheduler/mcp_agent/agent/toolcall.py deleted file mode 100644 index 1e22099c..00000000 --- a/apps/scheduler/mcp_agent/agent/toolcall.py +++ /dev/null @@ -1,238 +0,0 @@ -import asyncio -import json -import logging -from typing import Any, Optional - -from pydantic import Field - -from apps.schemas.enum_var import AgentState -from apps.llm.function import JsonGenerator -from apps.llm.patterns import Select -from apps.scheduler.mcp_agent.agent.react import ReActAgent -from apps.scheduler.mcp_agent.schema import Function, Message, ToolCall -from apps.scheduler.mcp_agent.tool import Terminate, ToolCollection - -logger = logging.getLogger(__name__) - - -class ToolCallAgent(ReActAgent): - """用于处理工具/函数调用的基本Agent类""" - - name: str = "toolcall" - description: str = "可以执行工具调用的智能体" - - available_tools: ToolCollection = ToolCollection( - Terminate(), - ) - tool_choices: str = "auto" - special_tool_names: list[str] = Field(default_factory=lambda: [Terminate().name]) - - tool_calls: list[ToolCall] = Field(default_factory=list) - _current_base64_image: str | None = None - - max_observe: int | bool | None = None - - async def think(self) -> bool: - """使用工具处理当前状态并决定下一步行动""" - messages = [] - for message in self.messages: - if isinstance(message, Message): - message = message.to_dict() - messages.append(message) - try: - # 通过工具获得响应 - select_obj = Select() - choices = [] - for available_tool in self.available_tools.to_params(): - choices.append(available_tool.get("function")) - - tool = await select_obj.generate(question=self.question, choices=choices) - if tool in self.available_tools.tool_map: - schema = self.available_tools.tool_map[tool].parameters - json_generator = JsonGenerator( - query="根据跟定的信息,获取工具参数", - conversation=messages, - schema=schema, - ) # JsonGenerator - parameters = await json_generator.generate() - - else: - raise ValueError(f"尝试调用不存在的工具: {tool}") - except Exception as e: - raise - self.tool_calls = tool_calls = [ToolCall(id=tool, function=Function(name=tool, arguments=parameters))] - content = f"选择的执行工具为:{tool}, 参数为{parameters}" - - logger.info( - f"{self.name} 选择 {len(tool_calls) if tool_calls else 0}个工具执行" - ) - if tool_calls: - logger.info( - f"准备使用的工具: {[call.function.name for call in tool_calls]}" - ) - logger.info(f"工具参数: {tool_calls[0].function.arguments}") - - try: - - assistant_msg = ( - Message.from_tool_calls(content=content, tool_calls=self.tool_calls) - if self.tool_calls - else Message.assistant_message(content) - ) - self.memory.add_message(assistant_msg) - - if not self.tool_calls: - return bool(content) - - return bool(self.tool_calls) - except Exception as e: - logger.error(f"{self.name}的思考过程遇到了问题:: {e}") - self.memory.add_message( - Message.assistant_message( - f"处理时遇到错误: {str(e)}" - ) - ) - return False - - async def act(self) -> str: - """执行工具调用并处理其结果""" - if not self.tool_calls: - # 如果没有工具调用,则返回最后的消息内容 - return self.messages[-1].content or "没有要执行的内容或命令" - - results = [] - for command in self.tool_calls: - await self.msg_queue.push_output( - self.task, - event_type="text.add", - data={"text": f"正在执行工具{command.function.name}"} - ) - - self._current_base64_image = None - - result = await self.execute_tool(command) - - if self.max_observe: - result = result[: self.max_observe] - - push_result = "" - async for chunk in self.llm.call( - messages=[{"role": "system", "content": "You are a helpful asistant."}, - {"role": "user", "content": self.user_prompt.format( - step=self.current_step, - result=result, - )}, ], streaming=False - ): - push_result += chunk - self.task.tokens.input_tokens += self.llm.input_tokens - self.task.tokens.output_tokens += self.llm.output_tokens - await self.msg_queue.push_output( - self.task, - event_type="text.add", - data={"text": push_result}, # type: ignore[arg-type] - ) - - await self.msg_queue.push_output( - self.task, - event_type="text.add", - data={"text": f"工具{command.function.name}执行完成"}, # type: ignore[arg-type] - ) - - logger.info( - f"工具'{command.function.name}'执行完成! 执行结果为: {result}" - ) - - # 将工具响应添加到内存 - tool_msg = Message.tool_message( - content=result, - tool_call_id=command.id, - name=command.function.name, - ) - self.memory.add_message(tool_msg) - results.append(result) - self.question += ( - f"\n已执行工具{command.function.name}, " - f"作用是{self.available_tools.tool_map[command.function.name].description},结果为{result}" - ) - - return "\n\n".join(results) - - async def execute_tool(self, command: ToolCall) -> str: - """执行单个工具调用""" - if not command or not command.function or not command.function.name: - return "错误:无效的命令格式" - - name = command.function.name - if name not in self.available_tools.tool_map: - return f"错误:未知工具 '{name}'" - - try: - # 解析参数 - args = command.function.arguments - # 执行工具 - logger.info(f"激活工具:'{name}'...") - result = await self.available_tools.execute(name=name, tool_input=args) - - # 执行特殊工具 - await self._handle_special_tool(name=name, result=result) - - # 格式化结果 - observation = ( - f"观察到执行的工具 `{name}`的输出:\n{str(result)}" - if result - else f"工具 `{name}` 已完成,无输出" - ) - - return observation - except json.JSONDecodeError: - error_msg = f"解析{name}的参数时出错:JSON格式无效" - logger.error( - f"{name}”的参数没有意义-无效的JSON,参数:{command.function.arguments}" - ) - return f"错误: {error_msg}" - except Exception as e: - error_msg = f"工具 '{name}' 遇到问题: {str(e)}" - logger.exception(error_msg) - return f"错误: {error_msg}" - - async def _handle_special_tool(self, name: str, result: Any, **kwargs): - """处理特殊工具的执行和状态变化""" - if not self._is_special_tool(name): - return - - if self._should_finish_execution(name=name, result=result, **kwargs): - # 将智能体状态设为finished - logger.info(f"特殊工具'{name}'已完成任务!") - self.state = AgentState.FINISHED - - @staticmethod - def _should_finish_execution(**kwargs) -> bool: - """确定工具执行是否应完成""" - return True - - def _is_special_tool(self, name: str) -> bool: - """检查工具名称是否在特殊工具列表中""" - return name.lower() in [n.lower() for n in self.special_tool_names] - - async def cleanup(self): - """清理Agent工具使用的资源。""" - logger.info(f"正在清理智能体的资源'{self.name}'...") - for tool_name, tool_instance in self.available_tools.tool_map.items(): - if hasattr(tool_instance, "cleanup") and asyncio.iscoroutinefunction( - tool_instance.cleanup - ): - try: - logger.debug(f"清理工具: {tool_name}") - await tool_instance.cleanup() - except Exception as e: - logger.error( - f"清理工具时发生错误'{tool_name}': {e}", exc_info=True - ) - logger.info(f"智能体清理完成'{self.name}'.") - - async def run(self, request: Optional[str] = None) -> str: - """运行Agent""" - try: - return await super().run(request) - finally: - await self.cleanup() diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py new file mode 100644 index 00000000..acdd4871 --- /dev/null +++ b/apps/scheduler/mcp_agent/host.py @@ -0,0 +1,190 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""MCP宿主""" + +import json +import logging +from typing import Any + +from jinja2 import BaseLoader +from jinja2.sandbox import SandboxedEnvironment +from mcp.types import TextContent + +from apps.common.mongo import MongoDB +from apps.llm.function import JsonGenerator +from apps.scheduler.mcp.prompt import MEMORY_TEMPLATE +from apps.scheduler.pool.mcp.client import MCPClient +from apps.scheduler.pool.mcp.pool import MCPPool +from apps.schemas.enum_var import StepStatus +from apps.schemas.mcp import MCPPlanItem, MCPTool +from apps.schemas.task import FlowStepHistory +from apps.services.task import TaskManager + +logger = logging.getLogger(__name__) + + +class MCPHost: + """MCP宿主服务""" + + def __init__(self, user_sub: str, task_id: str, runtime_id: str, runtime_name: str) -> None: + """初始化MCP宿主""" + self._user_sub = user_sub + self._task_id = task_id + # 注意:runtime在工作流中是flow_id和step_description,在Agent中可为标识Agent的id和description + self._runtime_id = runtime_id + self._runtime_name = runtime_name + self._context_list = [] + self._env = SandboxedEnvironment( + loader=BaseLoader(), + autoescape=False, + trim_blocks=True, + lstrip_blocks=True, + ) + + async def get_client(self, mcp_id: str) -> MCPClient | None: + """获取MCP客户端""" + mongo = MongoDB() + mcp_collection = mongo.get_collection("mcp") + + # 检查用户是否启用了这个mcp + mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": self._user_sub}) + if not mcp_db_result: + logger.warning("用户 %s 未启用MCP %s", self._user_sub, mcp_id) + return None + + # 获取MCP配置 + try: + return await MCPPool().get(mcp_id, self._user_sub) + except KeyError: + logger.warning("用户 %s 的MCP %s 没有运行中的实例,请检查环境", self._user_sub, mcp_id) + return None + + async def assemble_memory(self) -> str: + """组装记忆""" + task = await TaskManager.get_task_by_task_id(self._task_id) + if not task: + logger.error("任务 %s 不存在", self._task_id) + return "" + + context_list = [] + for ctx_id in self._context_list: + context = next((ctx for ctx in task.context if ctx["_id"] == ctx_id), None) + if not context: + continue + context_list.append(context) + + return self._env.from_string(MEMORY_TEMPLATE).render( + context_list=context_list, + ) + + async def _save_memory( + self, + tool: MCPTool, + plan_item: MCPPlanItem, + input_data: dict[str, Any], + result: str, + ) -> dict[str, Any]: + """保存记忆""" + try: + output_data = json.loads(result) + except Exception: # noqa: BLE001 + logger.warning("[MCPHost] 得到的数据不是dict格式!尝试转换为str") + output_data = { + "message": result, + } + + if not isinstance(output_data, dict): + output_data = { + "message": result, + } + + # 创建context;注意用法 + context = FlowStepHistory( + task_id=self._task_id, + flow_id=self._runtime_id, + flow_name=self._runtime_name, + flow_status=StepStatus.SUCCESS, + step_id=tool.name, + step_name=tool.name, + # description是规划的实际内容 + step_description=plan_item.content, + step_status=StepStatus.SUCCESS, + input_data=input_data, + output_data=output_data, + ) + + # 保存到task + task = await TaskManager.get_task_by_task_id(self._task_id) + if not task: + logger.error("任务 %s 不存在", self._task_id) + return {} + self._context_list.append(context.id) + task.context.append(context.model_dump(by_alias=True, exclude_none=True)) + await TaskManager.save_task(self._task_id, task) + + return output_data + + async def _fill_params(self, tool: MCPTool, query: str) -> dict[str, Any]: + """填充工具参数""" + # 更清晰的输入·指令,这样可以调用generate + llm_query = rf""" + 请使用参数生成工具,生成满足以下目标的工具参数: + + {query} + """ + + # 进行生成 + json_generator = JsonGenerator( + llm_query, + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": await self.assemble_memory()}, + ], + tool.input_schema, + ) + return await json_generator.generate() + + async def call_tool(self, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: + """调用工具""" + # 拿到Client + client = await MCPPool().get(tool.mcp_id, self._user_sub) + if client is None: + err = f"[MCPHost] MCP Server不合法: {tool.mcp_id}" + logger.error(err) + raise ValueError(err) + + # 填充参数 + params = await self._fill_params(tool, plan_item.instruction) + # 调用工具 + result = await client.call_tool(tool.name, params) + # 保存记忆 + processed_result = [] + for item in result.content: + if not isinstance(item, TextContent): + logger.error("MCP结果类型不支持: %s", item) + continue + processed_result.append(await self._save_memory(tool, plan_item, params, item.text)) + + return processed_result + + async def get_tool_list(self, mcp_id_list: list[str]) -> list[MCPTool]: + """获取工具列表""" + mongo = MongoDB() + mcp_collection = mongo.get_collection("mcp") + + # 获取工具列表 + tool_list = [] + for mcp_id in mcp_id_list: + # 检查用户是否启用了这个mcp + mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": self._user_sub}) + if not mcp_db_result: + logger.warning("用户 %s 未启用MCP %s", self._user_sub, mcp_id) + continue + # 获取MCP工具配置 + try: + for tool in mcp_db_result["tools"]: + tool_list.extend([MCPTool.model_validate(tool)]) + except KeyError: + logger.warning("用户 %s 的MCP Tool %s 配置错误", self._user_sub, mcp_id) + continue + + return tool_list diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py new file mode 100644 index 00000000..cd4f5975 --- /dev/null +++ b/apps/scheduler/mcp_agent/plan.py @@ -0,0 +1,110 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""MCP 用户目标拆解与规划""" + +from jinja2 import BaseLoader +from jinja2.sandbox import SandboxedEnvironment + +from apps.llm.function import JsonGenerator +from apps.llm.reasoning import ReasoningLLM +from apps.scheduler.mcp.prompt import CREATE_PLAN, FINAL_ANSWER +from apps.schemas.mcp import MCPPlan, MCPTool + + +class MCPPlanner: + """MCP 用户目标拆解与规划""" + + def __init__(self, user_goal: str) -> None: + """初始化MCP规划器""" + self.user_goal = user_goal + self._env = SandboxedEnvironment( + loader=BaseLoader, + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, + ) + self.input_tokens = 0 + self.output_tokens = 0 + + + async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: + """规划下一步的执行流程,并输出""" + # 获取推理结果 + result = await self._get_reasoning_plan(tool_list, max_steps) + + # 解析为结构化数据 + return await self._parse_plan_result(result, max_steps) + + + async def _get_reasoning_plan(self, tool_list: list[MCPTool], max_steps: int) -> str: + """获取推理大模型的结果""" + # 格式化Prompt + template = self._env.from_string(CREATE_PLAN) + prompt = template.render( + goal=self.user_goal, + tools=tool_list, + max_num=max_steps, + ) + + # 调用推理大模型 + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, + ] + reasoning_llm = ReasoningLLM() + result = "" + async for chunk in reasoning_llm.call( + message, + streaming=False, + temperature=0.07, + result_only=True, + ): + result += chunk + + # 保存token用量 + self.input_tokens = reasoning_llm.input_tokens + self.output_tokens = reasoning_llm.output_tokens + + return result + + + async def _parse_plan_result(self, result: str, max_steps: int) -> MCPPlan: + """将推理结果解析为结构化数据""" + # 格式化Prompt + schema = MCPPlan.model_json_schema() + schema["properties"]["plans"]["maxItems"] = max_steps + + # 使用Function模型解析结果 + json_generator = JsonGenerator( + result, + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": result}, + ], + schema, + ) + plan = await json_generator.generate() + return MCPPlan.model_validate(plan) + + + async def generate_answer(self, plan: MCPPlan, memory: str) -> str: + """生成最终回答""" + template = self._env.from_string(FINAL_ANSWER) + prompt = template.render( + plan=plan, + memory=memory, + goal=self.user_goal, + ) + + llm = ReasoningLLM() + result = "" + async for chunk in llm.call( + [{"role": "user", "content": prompt}], + streaming=False, + temperature=0.07, + ): + result += chunk + + self.input_tokens = llm.input_tokens + self.output_tokens = llm.output_tokens + + return result diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py new file mode 100644 index 00000000..b322fb08 --- /dev/null +++ b/apps/scheduler/mcp_agent/prompt.py @@ -0,0 +1,240 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""MCP相关的大模型Prompt""" + +from textwrap import dedent + +MCP_SELECT = dedent(r""" + 你是一个乐于助人的智能助手。 + 你的任务是:根据当前目标,选择最合适的MCP Server。 + + ## 选择MCP Server时的注意事项: + + 1. 确保充分理解当前目标,选择最合适的MCP Server。 + 2. 请在给定的MCP Server列表中选择,不要自己生成MCP Server。 + 3. 请先给出你选择的理由,再给出你的选择。 + 4. 当前目标将在下面给出,MCP Server列表也会在下面给出。 + 请将你的思考过程放在"思考过程"部分,将你的选择放在"选择结果"部分。 + 5. 选择必须是JSON格式,严格按照下面的模板,不要输出任何其他内容: + + ```json + { + "mcp": "你选择的MCP Server的名称" + } + ``` + + 6. 下面的示例仅供参考,不要将示例中的内容作为选择MCP Server的依据。 + + ## 示例 + + ### 目标 + + 我需要一个MCP Server来完成一个任务。 + + ### MCP Server列表 + + - **mcp_1**: "MCP Server 1";MCP Server 1的描述 + - **mcp_2**: "MCP Server 2";MCP Server 2的描述 + + ### 请一步一步思考: + + 因为当前目标需要一个MCP Server来完成一个任务,所以选择mcp_1。 + + ### 选择结果 + + ```json + { + "mcp": "mcp_1" + } + ``` + + ## 现在开始! + + ### 目标 + + {{goal}} + + ### MCP Server列表 + + {% for mcp in mcp_list %} + - **{{mcp.id}}**: "{{mcp.name}}";{{mcp.description}} + {% endfor %} + + ### 请一步一步思考: + +""") +CREATE_PLAN = dedent(r""" + 你是一个计划生成器。 + 请分析用户的目标,并生成一个计划。你后续将根据这个计划,一步一步地完成用户的目标。 + + # 一个好的计划应该: + + 1. 能够成功完成用户的目标 + 2. 计划中的每一个步骤必须且只能使用一个工具。 + 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 + 4. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + + # 生成计划时的注意事项: + + - 每一条计划包含3个部分: + - 计划内容:描述单个计划步骤的大致内容 + - 工具ID:必须从下文的工具列表中选择 + - 工具指令:改写用户的目标,使其更符合工具的输入要求 + - 必须按照如下格式生成计划,不要输出任何额外数据: + + ```json + { + "plans": [ + { + "content": "计划内容", + "tool": "工具ID", + "instruction": "工具指令" + } + ] + } + ``` + + - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。\ +思考过程应放置在 XML标签中。 + - 计划内容中,可以使用"Result[]"来引用之前计划步骤的结果。例如:"Result[3]"表示引用第三条计划执行后的结果。 + - 计划不得多于{{ max_num }}条,且每条计划内容应少于150字。 + + # 工具 + + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + + + {% for tool in tools %} + - {{ tool.id }}{{tool.name}};{{ tool.description }} + {% endfor %} + - Final结束步骤,当执行到这一步时,\ +表示计划执行结束,所得到的结果将作为最终结果。 + + + # 样例 + + ## 目标 + + 在后台运行一个新的alpine:latest容器,将主机/root文件夹挂载至/data,并执行top命令。 + + ## 计划 + + + 1. 这个目标需要使用Docker来完成,首先需要选择合适的MCP Server + 2. 目标可以拆解为以下几个部分: + - 运行alpine:latest容器 + - 挂载主机目录 + - 在后台运行 + - 执行top命令 + 3. 需要先选择MCP Server,然后生成Docker命令,最后执行命令 + + + ```json + { + "plans": [ + { + "content": "选择一个支持Docker的MCP Server", + "tool": "mcp_selector", + "instruction": "需要一个支持Docker容器运行的MCP Server" + }, + { + "content": "使用Result[0]中选择的MCP Server,生成Docker命令", + "tool": "command_generator", + "instruction": "生成Docker命令:在后台运行alpine:latest容器,挂载/root到/data,执行top命令" + }, + { + "content": "在Result[0]的MCP Server上执行Result[1]生成的命令", + "tool": "command_executor", + "instruction": "执行Docker命令" + }, + { + "content": "任务执行完成,容器已在后台运行,结果为Result[2]", + "tool": "Final", + "instruction": "" + } + ] + } + ``` + + # 现在开始生成计划: + + ## 目标 + + {{goal}} + + # 计划 +""") +EVALUATE_PLAN = dedent(r""" + 你是一个计划评估器。 + 请根据给定的计划,和当前计划执行的实际情况,分析当前计划是否合理和完整,并生成改进后的计划。 + + # 一个好的计划应该: + + 1. 能够成功完成用户的目标 + 2. 计划中的每一个步骤必须且只能使用一个工具。 + 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 + 4. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + + # 你此前的计划是: + + {{ plan }} + + # 这个计划的执行情况是: + + 计划的执行情况将放置在 XML标签中。 + + + {{ memory }} + + + # 进行评估时的注意事项: + + - 请一步一步思考,解析用户的目标,并指导你接下来的生成。思考过程应放置在 XML标签中。 + - 评估结果分为两个部分: + - 计划评估的结论 + - 改进后的计划 + - 请按照以下JSON格式输出评估结果: + + ```json + { + "evaluation": "评估结果", + "plans": [ + { + "content": "改进后的计划内容", + "tool": "工具ID", + "instruction": "工具指令" + } + ] + } + ``` + + # 现在开始评估计划: + +""") +FINAL_ANSWER = dedent(r""" + 综合理解计划执行结果和背景信息,向用户报告目标的完成情况。 + + # 用户目标 + + {{ goal }} + + # 计划执行情况 + + 为了完成上述目标,你实施了以下计划: + + {{ memory }} + + # 其他背景信息: + + {{ status }} + + # 现在,请根据以上信息,向用户报告目标的完成情况: + +""") +MEMORY_TEMPLATE = dedent(r""" + {% for ctx in context_list %} + - 第{{ loop.index }}步:{{ ctx.step_description }} + - 调用工具 `{{ ctx.step_id }}`,并提供参数 `{{ ctx.input_data }}` + - 执行状态:{{ ctx.status }} + - 得到数据:`{{ ctx.output_data }}` + {% endfor %} +""") diff --git a/apps/scheduler/mcp_agent/schema.py b/apps/scheduler/mcp_agent/schema.py deleted file mode 100644 index 61413907..00000000 --- a/apps/scheduler/mcp_agent/schema.py +++ /dev/null @@ -1,148 +0,0 @@ -"""MCP Agent执行数据结构""" -from typing import Any, Self - -from pydantic import BaseModel, Field - -from apps.schemas.enum_var import Role - - -class Function(BaseModel): - """工具函数""" - - name: str - arguments: dict[str, Any] - - -class ToolCall(BaseModel): - """Represents a tool/function call in a message""" - - id: str - type: str = "function" - function: Function - - -class Message(BaseModel): - """Represents a chat message in the conversation""" - - role: Role = Field(...) - content: str | None = Field(default=None) - tool_calls: list[ToolCall] | None = Field(default=None) - name: str | None = Field(default=None) - tool_call_id: str | None = Field(default=None) - - def __add__(self, other) -> list["Message"]: - """支持 Message + list 或 Message + Message 的操作""" - if isinstance(other, list): - return [self] + other - elif isinstance(other, Message): - return [self, other] - else: - raise TypeError( - f"unsupported operand type(s) for +: '{type(self).__name__}' and '{type(other).__name__}'" - ) - - def __radd__(self, other) -> list["Message"]: - """支持 list + Message 的操作""" - if isinstance(other, list): - return other + [self] - else: - raise TypeError( - f"unsupported operand type(s) for +: '{type(other).__name__}' and '{type(self).__name__}'" - ) - - def to_dict(self) -> dict: - """Convert message to dictionary format""" - message = {"role": self.role} - if self.content is not None: - message["content"] = self.content - if self.tool_calls is not None: - message["tool_calls"] = [tool_call.dict() for tool_call in self.tool_calls] - if self.name is not None: - message["name"] = self.name - if self.tool_call_id is not None: - message["tool_call_id"] = self.tool_call_id - return message - - @classmethod - def user_message(cls, content: str) -> Self: - """Create a user message""" - return cls(role=Role.USER, content=content) - - @classmethod - def system_message(cls, content: str) -> Self: - """Create a system message""" - return cls(role=Role.SYSTEM, content=content) - - @classmethod - def assistant_message( - cls, content: str | None = None, - ) -> Self: - """Create an assistant message""" - return cls(role=Role.ASSISTANT, content=content) - - @classmethod - def tool_message( - cls, content: str, name: str, tool_call_id: str, - ) -> Self: - """Create a tool message""" - return cls( - role=Role.TOOL, - content=content, - name=name, - tool_call_id=tool_call_id, - ) - - @classmethod - def from_tool_calls( - cls, - tool_calls: list[Any], - content: str | list[str] = "", - **kwargs, # noqa: ANN003 - ) -> Self: - """Create ToolCallsMessage from raw tool calls. - - Args: - tool_calls: Raw tool calls from LLM - content: Optional message content - """ - formatted_calls = [ - {"id": call.id, "function": call.function.model_dump(), "type": "function"} - for call in tool_calls - ] - return cls( - role=Role.ASSISTANT, - content=content, - tool_calls=formatted_calls, - **kwargs, - ) - - -class Memory(BaseModel): - messages: list[Message] = Field(default_factory=list) - max_messages: int = Field(default=100) - - def add_message(self, message: Message) -> None: - """Add a message to memory""" - self.messages.append(message) - # Optional: Implement message limit - if len(self.messages) > self.max_messages: - self.messages = self.messages[-self.max_messages:] - - def add_messages(self, messages: list[Message]) -> None: - """Add multiple messages to memory""" - self.messages.extend(messages) - # Optional: Implement message limit - if len(self.messages) > self.max_messages: - self.messages = self.messages[-self.max_messages:] - - def clear(self) -> None: - """Clear all messages""" - self.messages.clear() - - def get_recent_messages(self, n: int) -> list[Message]: - """Get n most recent messages""" - return self.messages[-n:] - - def to_dict_list(self) -> list[dict]: - """Convert messages to list of dicts""" - return [msg.to_dict() for msg in self.messages] diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py new file mode 100644 index 00000000..2ff50344 --- /dev/null +++ b/apps/scheduler/mcp_agent/select.py @@ -0,0 +1,185 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""选择MCP Server及其工具""" + +import logging + +from jinja2 import BaseLoader +from jinja2.sandbox import SandboxedEnvironment + +from apps.common.lance import LanceDB +from apps.common.mongo import MongoDB +from apps.llm.embedding import Embedding +from apps.llm.function import FunctionLLM +from apps.llm.reasoning import ReasoningLLM +from apps.scheduler.mcp.prompt import ( + MCP_SELECT, +) +from apps.schemas.mcp import ( + MCPCollection, + MCPSelectResult, + MCPTool, +) + +logger = logging.getLogger(__name__) + + +class MCPSelector: + """MCP选择器""" + + def __init__(self) -> None: + """初始化助手类""" + self.input_tokens = 0 + self.output_tokens = 0 + + @staticmethod + def _assemble_sql(mcp_list: list[str]) -> str: + """组装SQL""" + sql = "(" + for mcp_id in mcp_list: + sql += f"'{mcp_id}', " + return sql.rstrip(", ") + ")" + + + async def _get_top_mcp_by_embedding( + self, + query: str, + mcp_list: list[str], + ) -> list[dict[str, str]]: + """通过向量检索获取Top5 MCP Server""" + logger.info("[MCPHelper] 查询MCP Server向量: %s, %s", query, mcp_list) + mcp_table = await LanceDB().get_table("mcp") + query_embedding = await Embedding.get_embedding([query]) + mcp_vecs = await (await mcp_table.search( + query=query_embedding, + vector_column_name="embedding", + )).where(f"id IN {MCPSelector._assemble_sql(mcp_list)}").limit(5).to_list() + + # 拿到名称和description + logger.info("[MCPHelper] 查询MCP Server名称和描述: %s", mcp_vecs) + mcp_collection = MongoDB().get_collection("mcp") + llm_mcp_list: list[dict[str, str]] = [] + for mcp_vec in mcp_vecs: + mcp_id = mcp_vec["id"] + mcp_data = await mcp_collection.find_one({"_id": mcp_id}) + if not mcp_data: + logger.warning("[MCPHelper] 查询MCP Server名称和描述失败: %s", mcp_id) + continue + mcp_data = MCPCollection.model_validate(mcp_data) + llm_mcp_list.extend([{ + "id": mcp_id, + "name": mcp_data.name, + "description": mcp_data.description, + }]) + return llm_mcp_list + + + async def _get_mcp_by_llm( + self, + query: str, + mcp_list: list[dict[str, str]], + mcp_ids: list[str], + ) -> MCPSelectResult: + """通过LLM选择最合适的MCP Server""" + # 初始化jinja2环境 + env = SandboxedEnvironment( + loader=BaseLoader, + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, + ) + template = env.from_string(MCP_SELECT) + # 渲染模板 + mcp_prompt = template.render( + mcp_list=mcp_list, + goal=query, + ) + + # 调用大模型进行推理 + result = await self._call_reasoning(mcp_prompt) + + # 使用小模型提取JSON + return await self._call_function_mcp(result, mcp_ids) + + + async def _call_reasoning(self, prompt: str) -> str: + """调用大模型进行推理""" + logger.info("[MCPHelper] 调用推理大模型") + llm = ReasoningLLM() + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, + ] + result = "" + async for chunk in llm.call(message): + result += chunk + self.input_tokens += llm.input_tokens + self.output_tokens += llm.output_tokens + return result + + + async def _call_function_mcp(self, reasoning_result: str, mcp_ids: list[str]) -> MCPSelectResult: + """调用结构化输出小模型提取JSON""" + logger.info("[MCPHelper] 调用结构化输出小模型") + llm = FunctionLLM() + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": reasoning_result}, + ] + schema = MCPSelectResult.model_json_schema() + # schema中加入选项 + schema["properties"]["mcp_id"]["enum"] = mcp_ids + result = await llm.call(messages=message, schema=schema) + try: + result = MCPSelectResult.model_validate(result) + except Exception: + logger.exception("[MCPHelper] 解析MCP Select Result失败") + raise + return result + + + async def select_top_mcp( + self, + query: str, + mcp_list: list[str], + ) -> MCPSelectResult: + """ + 选择最合适的MCP Server + + 先通过Embedding选择Top5,然后通过LLM选择Top 1 + """ + # 通过向量检索获取Top5 + llm_mcp_list = await self._get_top_mcp_by_embedding(query, mcp_list) + + # 通过LLM选择最合适的 + return await self._get_mcp_by_llm(query, llm_mcp_list, mcp_list) + + + @staticmethod + async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTool]: + """选择最合适的工具""" + tool_vector = await LanceDB().get_table("mcp_tool") + query_embedding = await Embedding.get_embedding([query]) + tool_vecs = await (await tool_vector.search( + query=query_embedding, + vector_column_name="embedding", + )).where(f"mcp_id IN {MCPSelector._assemble_sql(mcp_list)}").limit(top_n).to_list() + + # 拿到工具 + tool_collection = MongoDB().get_collection("mcp") + llm_tool_list = [] + + for tool_vec in tool_vecs: + # 到MongoDB里找对应的工具 + logger.info("[MCPHelper] 查询MCP Tool名称和描述: %s", tool_vec["mcp_id"]) + tool_data = await tool_collection.aggregate([ + {"$match": {"_id": tool_vec["mcp_id"]}}, + {"$unwind": "$tools"}, + {"$match": {"tools.id": tool_vec["id"]}}, + {"$project": {"_id": 0, "tools": 1}}, + {"$replaceRoot": {"newRoot": "$tools"}}, + ]) + async for tool in tool_data: + tool_obj = MCPTool.model_validate(tool) + llm_tool_list.append(tool_obj) + + return llm_tool_list diff --git a/apps/scheduler/mcp_agent/tool/__init__.py b/apps/scheduler/mcp_agent/tool/__init__.py deleted file mode 100644 index 4593f317..00000000 --- a/apps/scheduler/mcp_agent/tool/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from apps.scheduler.mcp_agent.tool.base import BaseTool -from apps.scheduler.mcp_agent.tool.terminate import Terminate -from apps.scheduler.mcp_agent.tool.tool_collection import ToolCollection - -__all__ = [ - "BaseTool", - "Terminate", - "ToolCollection", -] diff --git a/apps/scheduler/mcp_agent/tool/base.py b/apps/scheduler/mcp_agent/tool/base.py deleted file mode 100644 index 04ad45c4..00000000 --- a/apps/scheduler/mcp_agent/tool/base.py +++ /dev/null @@ -1,73 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Any, Dict, Optional - -from pydantic import BaseModel, Field - - -class BaseTool(ABC, BaseModel): - name: str - description: str - parameters: Optional[dict] = None - - class Config: - arbitrary_types_allowed = True - - async def __call__(self, **kwargs) -> Any: - return await self.execute(**kwargs) - - @abstractmethod - async def execute(self, **kwargs) -> Any: - """使用给定的参数执行工具""" - - def to_param(self) -> Dict: - """将工具转换为函数调用格式""" - return { - "type": "function", - "function": { - "name": self.name, - "description": self.description, - "parameters": self.parameters, - }, - } - - -class ToolResult(BaseModel): - """表示工具执行的结果""" - - output: Any = Field(default=None) - error: Optional[str] = Field(default=None) - system: Optional[str] = Field(default=None) - - class Config: - arbitrary_types_allowed = True - - def __bool__(self): - return any(getattr(self, field) for field in self.__fields__) - - def __add__(self, other: "ToolResult"): - def combine_fields( - field: Optional[str], other_field: Optional[str], concatenate: bool = True - ): - if field and other_field: - if concatenate: - return field + other_field - raise ValueError("Cannot combine tool results") - return field or other_field - - return ToolResult( - output=combine_fields(self.output, other.output), - error=combine_fields(self.error, other.error), - system=combine_fields(self.system, other.system), - ) - - def __str__(self): - return f"Error: {self.error}" if self.error else self.output - - def replace(self, **kwargs): - """返回一个新的ToolResult,其中替换了给定的字段""" - # return self.copy(update=kwargs) - return type(self)(**{**self.dict(), **kwargs}) - - -class ToolFailure(ToolResult): - """表示失败的ToolResult""" diff --git a/apps/scheduler/mcp_agent/tool/terminate.py b/apps/scheduler/mcp_agent/tool/terminate.py deleted file mode 100644 index 84aa1203..00000000 --- a/apps/scheduler/mcp_agent/tool/terminate.py +++ /dev/null @@ -1,25 +0,0 @@ -from apps.scheduler.mcp_agent.tool.base import BaseTool - - -_TERMINATE_DESCRIPTION = """当请求得到满足或助理无法继续处理任务时,终止交互。 -当您完成所有任务后,调用此工具结束工作。""" - - -class Terminate(BaseTool): - name: str = "terminate" - description: str = _TERMINATE_DESCRIPTION - parameters: dict = { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "交互的完成状态", - "enum": ["success", "failure"], - } - }, - "required": ["status"], - } - - async def execute(self, status: str) -> str: - """Finish the current execution""" - return f"交互已完成,状态为: {status}" diff --git a/apps/scheduler/mcp_agent/tool/tool_collection.py b/apps/scheduler/mcp_agent/tool/tool_collection.py deleted file mode 100644 index 95bda317..00000000 --- a/apps/scheduler/mcp_agent/tool/tool_collection.py +++ /dev/null @@ -1,55 +0,0 @@ -"""用于管理多个工具的集合类""" -import logging -from typing import Any - -from apps.scheduler.mcp_agent.tool.base import BaseTool, ToolFailure, ToolResult - -logger = logging.getLogger(__name__) - - -class ToolCollection: - """定义工具的集合""" - - class Config: - arbitrary_types_allowed = True - - def __init__(self, *tools: BaseTool): - self.tools = tools - self.tool_map = {tool.name: tool for tool in tools} - - def __iter__(self): - return iter(self.tools) - - def to_params(self) -> list[dict[str, Any]]: - return [tool.to_param() for tool in self.tools] - - async def execute( - self, *, name: str, tool_input: dict[str, Any] = None - ) -> ToolResult: - tool = self.tool_map.get(name) - if not tool: - return ToolFailure(error=f"Tool {name} is invalid") - try: - result = await tool(**tool_input) - return result - except Exception as e: - return ToolFailure(error=f"Failed to execute tool {name}: {e}") - - def add_tool(self, tool: BaseTool): - """ - 将单个工具添加到集合中。 - - 如果已存在同名工具,则将跳过该工具并记录警告。 - """ - if tool.name in self.tool_map: - logger.warning(f"Tool {tool.name} already exists in collection, skipping") - return self - - self.tools += (tool,) - self.tool_map[tool.name] = tool - return self - - def add_tools(self, *tools: BaseTool): - for tool in tools: - self.add_tool(tool) - return self diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index 4c2c4cf0..32331cf3 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -214,7 +214,7 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: await AppCenterManager.update_recent_app(user_sub, post_body.app.app_id) # 若状态为成功,删除Task - if not task.state or task.state.status == StepStatus.SUCCESS: + if not task.state or task.state.flow_status == StepStatus.SUCCESS or task.state.flow_status == StepStatus.ERROR or task.state.flow_status == StepStatus.CANCELLED: await TaskManager.delete_task_by_task_id(task.id) else: # 更新Task diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index a84dc3a3..20e9c0f9 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -20,6 +20,17 @@ class StepStatus(str, Enum): SUCCESS = "success" ERROR = "error" PARAM = "param" + CANCELLED = "cancelled" + + +class FlowStatus(str, Enum): + """Flow状态""" + + WAITING = "waiting" + RUNNING = "running" + SUCCESS = "success" + ERROR = "error" + CANCELLED = "cancelled" class DocumentStatus(str, Enum): diff --git a/apps/schemas/record.py b/apps/schemas/record.py index b5e1b0c5..0c3d7185 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -44,6 +44,7 @@ class RecordFlow(BaseModel): id: str record_id: str = Field(alias="recordId") flow_id: str = Field(alias="flowId") + flow_status: StepStatus = Field(alias="flowStatus", default=StepStatus.SUCCESS) step_num: int = Field(alias="stepNum") steps: list[RecordFlowStep] diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 37fdebbf..98d8c6b3 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -7,7 +7,7 @@ from typing import Any from pydantic import BaseModel, Field -from apps.schemas.enum_var import StepStatus +from apps.schemas.enum_var import FlowStatus, StepStatus from apps.schemas.flow import Step from apps.schemas.mcp import MCPPlan @@ -23,10 +23,11 @@ class FlowStepHistory(BaseModel): task_id: str = Field(description="任务ID") flow_id: str = Field(description="FlowID") flow_name: str = Field(description="Flow名称") + flow_status: FlowStatus = Field(description="Flow状态") step_id: str = Field(description="当前步骤名称") step_name: str = Field(description="当前步骤名称") - step_description: str = Field(description="当前步骤描述") - status: StepStatus = Field(description="当前步骤状态") + step_description: str = Field(description="当前步骤描述", default="") + step_status: StepStatus = Field(description="当前步骤状态") input_data: dict[str, Any] = Field(description="当前Step执行的输入", default={}) output_data: dict[str, Any] = Field(description="当前Step执行后的结果", default={}) created_at: float = Field(default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3)) @@ -39,10 +40,11 @@ class ExecutorState(BaseModel): flow_id: str = Field(description="Flow ID") flow_name: str = Field(description="Flow名称") description: str = Field(description="Flow描述") - status: StepStatus = Field(description="Flow执行状态") - # 附加信息 + flow_status: FlowStatus = Field(description="Flow状态") + # 任务级数据 step_id: str = Field(description="当前步骤ID") step_name: str = Field(description="当前步骤名称") + step_status: StepStatus = Field(description="当前步骤状态") step_description: str = Field(description="当前步骤描述", default="") app_id: str = Field(description="应用ID") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) diff --git a/tests/common/test_queue.py b/tests/common/test_queue.py index 5375180a..db1f5ead 100644 --- a/tests/common/test_queue.py +++ b/tests/common/test_queue.py @@ -74,8 +74,8 @@ async def test_push_output_with_flow(message_queue, mock_task): mock_task.state.flow_id = "flow_id" mock_task.state.step_id = "step_id" mock_task.state.step_name = "step_name" - mock_task.state.status = "running" - + mock_task.state.step_status = "running" + await message_queue.init("test_task") await message_queue.push_output(mock_task, EventType.TEXT_ADD, {}) -- Gitee From 4a58ac8a819e5cacc6401aeb3caf868b86be36ce Mon Sep 17 00:00:00 2001 From: zxstty Date: Sun, 27 Jul 2025 15:33:20 +0800 Subject: [PATCH 19/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/main.py | 2 + apps/routers/parameter.py | 100 ++----- apps/scheduler/call/__init__.py | 3 +- apps/scheduler/call/choice/choice.py | 95 ++++-- .../call/choice/condition_handler.py | 272 +++++++++++++----- apps/scheduler/call/choice/schema.py | 63 ++-- apps/scheduler/call/core.py | 26 +- apps/scheduler/executor/flow.py | 20 +- apps/scheduler/executor/step.py | 3 - apps/scheduler/slot/slot.py | 43 ++- apps/schemas/config.py | 2 +- apps/schemas/parameters.py | 69 +++++ apps/schemas/response_data.py | 47 ++- apps/services/flow.py | 46 --- apps/services/node.py | 6 +- apps/services/parameter.py | 86 ++++++ 16 files changed, 564 insertions(+), 319 deletions(-) create mode 100644 apps/schemas/parameters.py create mode 100644 apps/services/parameter.py diff --git a/apps/main.py b/apps/main.py index c4ca2bfb..c26e5e47 100644 --- a/apps/main.py +++ b/apps/main.py @@ -36,6 +36,7 @@ from apps.routers import ( record, service, user, + parameter ) from apps.scheduler.pool.pool import Pool @@ -66,6 +67,7 @@ app.include_router(llm.router) app.include_router(mcp_service.router) app.include_router(flow.router) app.include_router(user.router) +app.include_router(parameter.router) # logger配置 LOGGER_FORMAT = "%(funcName)s() - %(message)s" diff --git a/apps/routers/parameter.py b/apps/routers/parameter.py index 538c2556..6edbe2e1 100644 --- a/apps/routers/parameter.py +++ b/apps/routers/parameter.py @@ -5,13 +5,10 @@ from fastapi.responses import JSONResponse from apps.dependency import get_user from apps.dependency.user import verify_user -from apps.scheduler.call.choice.choice import Choice +from apps.services.parameter import ParameterManager from apps.schemas.response_data import ( - FlowStructureGetMsg, - FlowStructureGetRsp, - GetParamsMsg, - GetParamsRsp, - ResponseData, + GetOperaRsp, + GetParamsRsp ) from apps.services.application import AppManager from apps.services.flow import FlowManager @@ -25,10 +22,7 @@ router = APIRouter( ) -@router.get("", response_model={ - status.HTTP_403_FORBIDDEN: {"model": ResponseData}, - status.HTTP_404_NOT_FOUND: {"model": ResponseData}, - },) +@router.get("", response_model=GetParamsRsp) async def get_parameters( user_sub: Annotated[str, Depends(get_user)], app_id: Annotated[str, Query(alias="appId")], @@ -39,105 +33,45 @@ async def get_parameters( if not await AppManager.validate_user_app_access(user_sub, app_id): return JSONResponse( status_code=status.HTTP_403_FORBIDDEN, - content=FlowStructureGetRsp( + content=GetParamsRsp( code=status.HTTP_403_FORBIDDEN, message="用户没有权限访问该流", - result=FlowStructureGetMsg(), + result=[], ).model_dump(exclude_none=True, by_alias=True), ) flow = await FlowManager.get_flow_by_app_and_flow_id(app_id, flow_id) if not flow: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, - content=FlowStructureGetRsp( + content=GetParamsRsp( code=status.HTTP_404_NOT_FOUND, message="未找到该流", - result={}, - ).model_dump(exclude_none=True, by_alias=True), - ) - result = await FlowManager.get_params_by_flow_and_step_id(flow, step_id) - if not result: - return JSONResponse( - status_code=status.HTTP_404_NOT_FOUND, - content=FlowStructureGetRsp( - code=status.HTTP_404_NOT_FOUND, - message="未找到该节点", - result={}, + result=[], ).model_dump(exclude_none=True, by_alias=True), ) + result = await ParameterManager.get_pre_params_by_flow_and_step_id(flow, step_id) return JSONResponse( status_code=status.HTTP_200_OK, content=GetParamsRsp( code=status.HTTP_200_OK, message="获取参数成功", - result=GetParamsMsg(result=result), + result=result ).model_dump(exclude_none=True, by_alias=True), ) -async def operate_parameters(operate: str) -> list[str] | None: - """ - 根据操作类型获取对应的操作符参数列表 - - Args: - operate: 操作类型,支持 'int', 'str', 'bool' - - Returns: - 对应的操作符参数列表,若类型不支持则返回None - """ - string = [ - "equal", - "not_equal", - "great",#长度大于 - "great_equals",#长度大于等于 - "less",#长度小于 - "less_equals",#长度小于等于 - "greater", - "greater_equals", - "smaller", - "smaller_equals", - ] - integer = [ - "equal", - "not_equal", - "great", - "great_equals", - "less", - "less_equals", - ] - boolen = ["equal", "not_equal", "is_empty", "not_empty"] - if operate in string: - return string - if operate in integer: - return integer - if operate in boolen: - return boolen - return None - -@router.get("/operate", response_model={ - status.HTTP_200_OK: {"model": ResponseData}, - status.HTTP_404_NOT_FOUND: {"model": ResponseData}, - },) +@router.get("/operate", response_model=GetOperaRsp) async def get_operate_parameters( user_sub: Annotated[str, Depends(get_user)], - operate: Annotated[str, Query(alias="operate")], + param_type: Annotated[str, Query(alias="ParamType")], ) -> JSONResponse: """Get parameters for node choice.""" - result = await operate_parameters(operate) - if not result: - return JSONResponse( - status_code=status.HTTP_404_NOT_FOUND, - content=ResponseData( - code=status.HTTP_404_NOT_FOUND, - message="未找到该符号", - result=[], - ).model_dump(exclude_none=True, by_alias=True), - ) + result = await ParameterManager.get_operate_and_bind_type(param_type) return JSONResponse( status_code=status.HTTP_200_OK, - content=ResponseData( + content=GetOperaRsp( code=status.HTTP_200_OK, - message="获取参数成功", - result=result, + message="获取操作成功", + result=result ).model_dump(exclude_none=True, by_alias=True), - ) \ No newline at end of file + ) diff --git a/apps/scheduler/call/__init__.py b/apps/scheduler/call/__init__.py index 2ee8b862..c5a6f054 100644 --- a/apps/scheduler/call/__init__.py +++ b/apps/scheduler/call/__init__.py @@ -8,7 +8,7 @@ from apps.scheduler.call.mcp.mcp import MCP from apps.scheduler.call.rag.rag import RAG from apps.scheduler.call.sql.sql import SQL from apps.scheduler.call.suggest.suggest import Suggestion - +from apps.scheduler.call.choice.choice import Choice # 只包含需要在编排界面展示的工具 __all__ = [ "API", @@ -18,4 +18,5 @@ __all__ = [ "SQL", "Graph", "Suggestion", + "Choice" ] diff --git a/apps/scheduler/call/choice/choice.py b/apps/scheduler/call/choice/choice.py index 24df0dae..8cab8288 100644 --- a/apps/scheduler/call/choice/choice.py +++ b/apps/scheduler/call/choice/choice.py @@ -1,6 +1,8 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """使用大模型或使用程序做出判断""" +import ast +import copy import logging from collections.abc import AsyncGenerator from typing import Any @@ -9,11 +11,13 @@ from pydantic import Field from apps.scheduler.call.choice.condition_handler import ConditionHandler from apps.scheduler.call.choice.schema import ( + Condition, ChoiceBranch, ChoiceInput, ChoiceOutput, Logic, ) +from apps.schemas.parameters import Type from apps.scheduler.call.core import CoreCall from apps.schemas.enum_var import CallOutputType from apps.schemas.scheduler import ( @@ -30,17 +34,13 @@ class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): """Choice工具""" to_user: bool = Field(default=False) - choices: list[ChoiceBranch] = Field(description="分支", default=[]) + choices: list[ChoiceBranch] = Field(description="分支", default=[ChoiceBranch(), + ChoiceBranch(conditions=[Condition()], is_default=False)]) @classmethod def info(cls) -> CallInfo: """返回Call的名称和描述""" - return CallInfo(name="Choice", description="使用大模型或使用程序做出判断") - - def _raise_value_error(self, msg: str) -> None: - """统一处理 ValueError 异常抛出""" - logger.warning(msg) - raise ValueError(msg) + return CallInfo(name="选择器", description="使用大模型或使用程序做出判断") async def _prepare_message(self, call_vars: CallVars) -> list[dict[str, Any]]: """替换choices中的系统变量""" @@ -51,31 +51,76 @@ class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): # 验证逻辑运算符 if choice.logic not in [Logic.AND, Logic.OR]: msg = f"无效的逻辑运算符: {choice.logic}" - self._raise_value_error(msg) + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue valid_conditions = [] - for condition in choice.conditions: + for i in range(len(choice.conditions)): + condition = copy.deepcopy(choice.conditions[i]) # 处理左值 - if condition.left.step_id: - condition.left.value = self._extract_history_variables(condition.left.step_id, call_vars.history) + if condition.left.step_id is not None: + condition.left.value = self._extract_history_variables( + condition.left.step_id+'/'+condition.left.value, call_vars.history) # 检查历史变量是否成功提取 - if condition.left.value is None: - msg = f"步骤 {condition.left.step_id} 的历史变量不存在" - self._raise_value_error(msg) + if condition.left.value is None: + msg = f"步骤 {condition.left.step_id} 的历史变量不存在" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + if not ConditionHandler.check_value_type( + condition.left.value, condition.left.type): + msg = f"左值类型不匹配: {condition.left.value} 应为 {condition.left.type.value}" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue else: msg = "左侧变量缺少step_id" - self._raise_value_error(msg) - - valid_conditions.append(condition) + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + # 处理右值 + if condition.right.step_id is not None: + condition.right.value = self._extract_history_variables( + condition.right.step_id+'/'+condition.right.value, call_vars.history) + # 检查历史变量是否成功提取 + if condition.right.value is None: + msg = f"步骤 {condition.right.step_id} 的历史变量不存在" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + if not ConditionHandler.check_value_type( + condition.right.value, condition.right.type): + msg = f"右值类型不匹配: {condition.right.value} 应为 {condition.right.type.value}" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + else: + # 如果右值没有step_id,尝试从call_vars中获取 + right_value_type = await ConditionHandler.get_value_type_from_operate( + condition.operate) + if right_value_type is None: + msg = f"不支持的运算符: {condition.operate}" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + if condition.right.type != right_value_type: + msg = f"右值类型不匹配: {condition.right.value} 应为 {right_value_type.value}" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + if right_value_type == Type.STRING: + condition.right.value = str(condition.right.value) + else: + condition.right.value = ast.literal_eval(condition.right.value) + if not ConditionHandler.check_value_type( + condition.right.value, condition.right.type): + msg = f"右值类型不匹配: {condition.right.value} 应为 {condition.right.type.value}" + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue + valid_conditions.append(condition) # 如果所有条件都无效,抛出异常 if not valid_conditions: msg = "分支没有有效条件" - self._raise_value_error(msg) + logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") + continue # 更新有效条件 choice.conditions = valid_conditions - valid_choices.append(choice.dict()) + valid_choices.append(choice) except ValueError as e: logger.warning("分支 %s 处理失败: %s,已跳过", choice.branch_id, str(e)) @@ -95,13 +140,11 @@ class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): """执行Choice工具""" # 解析输入数据 data = ChoiceInput(**input_data) - ret: CallOutputChunk = CallOutputChunk( - type=CallOutputType.DATA, - content=None, - ) - condition_handler = ConditionHandler() try: - ret.content = condition_handler.handler(data.choices) - yield ret + branch_id = ConditionHandler.handler(data.choices) + yield CallOutputChunk( + type=CallOutputType.DATA, + content=ChoiceOutput(branch_id=branch_id).model_dump(exclude_none=True, by_alias=True), + ) except Exception as e: raise CallError(message=f"选择工具调用失败:{e!s}", data={}) from e diff --git a/apps/scheduler/call/choice/condition_handler.py b/apps/scheduler/call/choice/condition_handler.py index feab5c64..7542f294 100644 --- a/apps/scheduler/call/choice/condition_handler.py +++ b/apps/scheduler/call/choice/condition_handler.py @@ -1,19 +1,79 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """处理条件分支的工具""" + import logging from pydantic import BaseModel -from apps.scheduler.call.choice.schema import ChoiceBranch, ChoiceOutput, Condition, Logic, Operator, Type, Value +from apps.schemas.parameters import ( + Type, + NumberOperate, + StringOperate, + ListOperate, + BoolOperate, + DictOperate, +) + +from apps.scheduler.call.choice.schema import ( + ChoiceBranch, + Condition, + Logic, + Value +) logger = logging.getLogger(__name__) class ConditionHandler(BaseModel): """条件分支处理器""" + @staticmethod + async def get_value_type_from_operate(operate: NumberOperate | StringOperate | ListOperate | + BoolOperate | DictOperate) -> Type: + """获取右值的类型""" + if isinstance(operate, NumberOperate): + return Type.NUMBER + if operate in [ + StringOperate.EQUAL, StringOperate.NOT_EQUAL, StringOperate.CONTAINS, StringOperate.NOT_CONTAINS, + StringOperate.STARTS_WITH, StringOperate.ENDS_WITH, StringOperate.REGEX_MATCH]: + return Type.STRING + if operate in [StringOperate.LENGTH_EQUAL, StringOperate.LENGTH_GREATER_THAN, + StringOperate.LENGTH_GREATER_THAN_OR_EQUAL, StringOperate.LENGTH_LESS_THAN, + StringOperate.LENGTH_LESS_THAN_OR_EQUAL]: + return Type.NUMBER + if operate in [ListOperate.EQUAL, ListOperate.NOT_EQUAL]: + return Type.LIST + if operate in [ListOperate.CONTAINS, ListOperate.NOT_CONTAINS]: + return Type.STRING + if operate in [ListOperate.LENGTH_EQUAL, ListOperate.LENGTH_GREATER_THAN, + ListOperate.LENGTH_GREATER_THAN_OR_EQUAL, ListOperate.LENGTH_LESS_THAN, + ListOperate.LENGTH_LESS_THAN_OR_EQUAL]: + return Type.NUMBER + if operate in [BoolOperate.EQUAL, BoolOperate.NOT_EQUAL]: + return Type.BOOL + if operate in [DictOperate.EQUAL, DictOperate.NOT_EQUAL]: + return Type.DICT + if operate in [DictOperate.CONTAINS_KEY, DictOperate.NOT_CONTAINS_KEY]: + return Type.STRING + return None + + @staticmethod + def check_value_type(value: Value, expected_type: Type) -> bool: + """检查值的类型是否符合预期""" + if expected_type == Type.STRING and isinstance(value.value, str): + return True + if expected_type == Type.NUMBER and isinstance(value.value, (int, float)): + return True + if expected_type == Type.LIST and isinstance(value.value, list): + return True + if expected_type == Type.DICT and isinstance(value.value, dict): + return True + if expected_type == Type.BOOL and isinstance(value.value, bool): + return True + return False - def handler(self, choices: list[ChoiceBranch]) -> ChoiceOutput: + @staticmethod + def handler(choices: list[ChoiceBranch]) -> str: """处理条件""" default_branch = [c for c in choices if c.is_default] @@ -22,7 +82,7 @@ class ConditionHandler(BaseModel): if block_judgement.is_default: continue for condition in block_judgement.conditions: - result = self._judge_condition(condition) + result = ConditionHandler._judge_condition(condition) results.append(result) if block_judgement.logic == Logic.AND: final_result = all(results) @@ -30,58 +90,55 @@ class ConditionHandler(BaseModel): final_result = any(results) if final_result: - return { - "branch_id": block_judgement.branch_id, - "message": f"选择分支:{block_judgement.branch_id}", - } + return block_judgement.branch_id # 如果没有匹配的分支,选择默认分支 if default_branch: - return { - "branch_id": default_branch[0].branch_id, - "message": f"选择默认分支:{default_branch[0].branch_id}", - } - return { - "branch_id": "", - "message": "没有匹配的分支,且没有默认分支", - } - - def _judge_condition(self, condition: Condition) -> bool: + return default_branch[0].branch_id + return "" + + @staticmethod + def _judge_condition(condition: Condition) -> bool: """ 判断条件是否成立。 Args: - condition (Condition): 'left', 'operator', 'right', 'type' + condition (Condition): 'left', 'operate', 'right', 'type' Returns: bool """ left = condition.left - operator = condition.operator + operate = condition.operate right = condition.right value_type = condition.type result = None if value_type == Type.STRING: - result = self._judge_string_condition(left, operator, right) - elif value_type == Type.INT: - result = self._judge_int_condition(left, operator, right) + result = ConditionHandler._judge_string_condition(left, operate, right) + elif value_type == Type.NUMBER: + result = ConditionHandler._judge_int_condition(left, operate, right) elif value_type == Type.BOOL: - result = self._judge_bool_condition(left, operator, right) + result = ConditionHandler._judge_bool_condition(left, operate, right) + elif value_type == Type.LIST: + result = ConditionHandler._judge_list_condition(left, operate, right) + elif value_type == Type.DICT: + result = ConditionHandler._judge_dict_condition(left, operate, right) else: logger.error("不支持的数据类型: %s", value_type) msg = f"不支持的数据类型: {value_type}" raise ValueError(msg) return result - def _judge_string_condition(self, left: Value, operator: Operator, right: Value) -> bool: + @staticmethod + def _judge_string_condition(left: Value, operate: StringOperate, right: Value) -> bool: """ 判断字符串类型的条件。 Args: left (Value): 左值,包含 'value' 键。 - operator (Operator): 操作符 + operate (Operate): 操作符 right (Value): 右值,包含 'value' 键。 Returns: @@ -95,39 +152,41 @@ class ConditionHandler(BaseModel): raise TypeError(msg) right_value = right.value result = False - if operator == Operator.EQUAL: - result = left_value == right_value - elif operator == Operator.NEQUAL: - result = left_value != right_value - elif operator == Operator.GREAT: - result = len(left_value) > len(right_value) - elif operator == Operator.GREAT_EQUALS: - result = len(left_value) >= len(right_value) - elif operator == Operator.LESS: - result = len(left_value) < len(right_value) - elif operator == Operator.LESS_EQUALS: - result = len(left_value) <= len(right_value) - elif operator == Operator.GREATER: - result = left_value > right_value - elif operator == Operator.GREATER_EQUALS: - result = left_value >= right_value - elif operator == Operator.SMALLER: - result = left_value < right_value - elif operator == Operator.SMALLER_EQUALS: - result = left_value <= right_value - elif operator == Operator.CONTAINS: - result = right_value in left_value - elif operator == Operator.NOT_CONTAINS: - result = right_value not in left_value - return result + if operate == StringOperate.EQUAL: + return left_value == right_value + elif operate == StringOperate.NOT_EQUAL: + return left_value != right_value + elif operate == StringOperate.CONTAINS: + return right_value in left_value + elif operate == StringOperate.NOT_CONTAINS: + return right_value not in left_value + elif operate == StringOperate.STARTS_WITH: + return left_value.startswith(right_value) + elif operate == StringOperate.ENDS_WITH: + return left_value.endswith(right_value) + elif operate == StringOperate.REGEX_MATCH: + import re + return bool(re.match(right_value, left_value)) + elif operate == StringOperate.LENGTH_EQUAL: + return len(left_value) == right_value + elif operate == StringOperate.LENGTH_GREATER_THAN: + return len(left_value) > right_value + elif operate == StringOperate.LENGTH_GREATER_THAN_OR_EQUAL: + return len(left_value) >= right_value + elif operate == StringOperate.LENGTH_LESS_THAN: + return len(left_value) < right_value + elif operate == StringOperate.LENGTH_LESS_THAN_OR_EQUAL: + return len(left_value) <= right_value + return False - def _judge_int_condition(self, left: Value, operator: Operator, right: Value) -> bool: # noqa: PLR0911 + @staticmethod + def _judge_number_condition(left: Value, operate: NumberOperate, right: Value) -> bool: # noqa: PLR0911 """ - 判断整数类型的条件。 + 判断数字类型的条件。 Args: left (Value): 左值,包含 'value' 键。 - operator (Operator): 操作符 + operate (Operate): 操作符 right (Value): 右值,包含 'value' 键。 Returns: @@ -135,32 +194,33 @@ class ConditionHandler(BaseModel): """ left_value = left.value - if not isinstance(left_value, int): - logger.error("左值不是整数类型: %s", left_value) - msg = "左值必须是整数类型" + if not isinstance(left_value, (int, float)): + logger.error("左值不是数字类型: %s", left_value) + msg = "左值必须是数字类型" raise TypeError(msg) right_value = right.value - if operator == Operator.EQUAL: + if operate == NumberOperate.EQUAL: return left_value == right_value - if operator == Operator.NEQUAL: + elif operate == NumberOperate.NOT_EQUAL: return left_value != right_value - if operator == Operator.GREAT: + elif operate == NumberOperate.GREATER_THAN: return left_value > right_value - if operator == Operator.GREAT_EQUALS: - return left_value >= right_value - if operator == Operator.LESS: + elif operate == NumberOperate.LESS_THAN: # noqa: PLR2004 return left_value < right_value - if operator == Operator.LESS_EQUALS: + elif operate == NumberOperate.GREATER_THAN_OR_EQUAL: + return left_value >= right_value + elif operate == NumberOperate.LESS_THAN_OR_EQUAL: return left_value <= right_value return False - def _judge_bool_condition(self, left: Value, operator: Operator, right: Value) -> bool: + @staticmethod + def _judge_bool_condition(left: Value, operate: BoolOperate, right: Value) -> bool: """ 判断布尔类型的条件。 Args: left (Value): 左值,包含 'value' 键。 - operator (Operator): 操作符 + operate (Operate): 操作符 right (Value): 右值,包含 'value' 键。 Returns: @@ -173,12 +233,82 @@ class ConditionHandler(BaseModel): msg = "左值必须是布尔类型" raise TypeError(msg) right_value = right.value - if operator == Operator.EQUAL: + if operate == BoolOperate.EQUAL: + return left_value == right_value + elif operate == BoolOperate.NOT_EQUAL: + return left_value != right_value + elif operate == BoolOperate.IS_EMPTY: + return not left_value + elif operate == BoolOperate.NOT_EMPTY: + return left_value + return False + + @staticmethod + def _judge_list_condition(left: Value, operate: ListOperate, right: Value): + """ + 判断列表类型的条件。 + + Args: + left (Value): 左值,包含 'value' 键。 + operate (Operate): 操作符 + right (Value): 右值,包含 'value' 键。 + + Returns: + bool + + """ + left_value = left.value + if not isinstance(left_value, list): + logger.error("左值不是列表类型: %s", left_value) + msg = "左值必须是列表类型" + raise TypeError(msg) + right_value = right.value + if operate == ListOperate.EQUAL: + return left_value == right_value + elif operate == ListOperate.NOT_EQUAL: + return left_value != right_value + elif operate == ListOperate.CONTAINS: + return right_value in left_value + elif operate == ListOperate.NOT_CONTAINS: + return right_value not in left_value + elif operate == ListOperate.LENGTH_EQUAL: + return len(left_value) == right_value + elif operate == ListOperate.LENGTH_GREATER_THAN: + return len(left_value) > right_value + elif operate == ListOperate.LENGTH_GREATER_THAN_OR_EQUAL: + return len(left_value) >= right_value + elif operate == ListOperate.LENGTH_LESS_THAN: + return len(left_value) < right_value + elif operate == ListOperate.LENGTH_LESS_THAN_OR_EQUAL: + return len(left_value) <= right_value + return False + + @staticmethod + def _judge_dict_condition(left: Value, operate: DictOperate, right: Value): + """ + 判断字典类型的条件。 + + Args: + left (Value): 左值,包含 'value' 键。 + operate (Operate): 操作符 + right (Value): 右值,包含 'value' 键。 + + Returns: + bool + + """ + left_value = left.value + if not isinstance(left_value, dict): + logger.error("左值不是字典类型: %s", left_value) + msg = "左值必须是字典类型" + raise TypeError(msg) + right_value = right.value + if operate == DictOperate.EQUAL: return left_value == right_value - if operator == Operator.NEQUAL: + elif operate == DictOperate.NOT_EQUAL: return left_value != right_value - if operator == Operator.IS_EMPTY: - return left_value == "" - if operator == Operator.NOT_EMPTY: - return left_value != "" + elif operate == DictOperate.CONTAINS_KEY: + return right_value in left_value + elif operate == DictOperate.NOT_CONTAINS_KEY: + return right_value not in left_value return False diff --git a/apps/scheduler/call/choice/schema.py b/apps/scheduler/call/choice/schema.py index ed1c628c..b95b1668 100644 --- a/apps/scheduler/call/choice/schema.py +++ b/apps/scheduler/call/choice/schema.py @@ -1,30 +1,20 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Choice Call的输入和输出""" +import uuid from enum import Enum from pydantic import BaseModel, Field +from apps.schemas.parameters import ( + Type, + NumberOperate, + StringOperate, + ListOperate, + BoolOperate, + DictOperate, +) from apps.scheduler.call.core import DataBase -class Operator(str, Enum): - """Choice Call支持的运算符""" - - EQUAL = "equal" - NEQUAL = "not_equal" - GREAT = "great" - GREAT_EQUALS = "great_equals" - LESS = "less" - LESS_EQUALS = "less_equals" - # string - CONTAINS = "contains" - NOT_CONTAINS = "not_contains" - GREATER = "greater" - GREATER_EQUALS = "greater_equals" - SMALLER = "smaller" - SMALLER_EQUALS = "smaller_equals" - # bool - IS_EMPTY = "is_empty" - NOT_EMPTY = "not_empty" class Logic(str, Enum): @@ -34,38 +24,31 @@ class Logic(str, Enum): OR = "or" -class Type(str, Enum): - """Choice 工具支持的类型""" - - STRING = "string" - INT = "int" - BOOL = "bool" - - -class Value(BaseModel): +class Value(DataBase): """值的结构""" - step_id: str = Field(description="步骤id", default="") - value: str | int | bool = Field(description="值", default=None) + step_id: str | None = Field(description="步骤id", default=None) + type: Type | None = Field(description="值的类型", default=None) + value: str | float | int | bool | list | dict | None = Field(description="值", default=None) -class Condition(BaseModel): +class Condition(DataBase): """单个条件""" - type: Type = Field(description="值的类型", default=Type.STRING) - left: Value = Field(description="左值") - right: Value = Field(description="右值") - operator: Operator = Field(description="运算符", default="equal") - id: int = Field(description="条件ID") + left: Value = Field(description="左值", default=Value()) + right: Value = Field(description="右值", default=Value()) + operate: NumberOperate | StringOperate | ListOperate | BoolOperate | DictOperate | None = Field( + description="运算符", default=None) + id: str = Field(description="条件ID", default_factory=lambda: str(uuid.uuid4())) -class ChoiceBranch(BaseModel): +class ChoiceBranch(DataBase): """子分支""" - branch_id: str = Field(description="分支ID", default="") + branch_id: str = Field(description="分支ID", default_factory=lambda: str(uuid.uuid4())) logic: Logic = Field(description="逻辑运算符", default=Logic.AND) conditions: list[Condition] = Field(description="条件列表", default=[]) - is_default: bool = Field(description="是否为默认分支", default=False) + is_default: bool = Field(description="是否为默认分支", default=True) class ChoiceInput(DataBase): @@ -76,3 +59,5 @@ class ChoiceInput(DataBase): class ChoiceOutput(DataBase): """Choice Call的输出""" + + branch_id: str = Field(description="分支ID", default="") diff --git a/apps/scheduler/call/core.py b/apps/scheduler/call/core.py index 2b1cbba8..af28c6a3 100644 --- a/apps/scheduler/call/core.py +++ b/apps/scheduler/call/core.py @@ -76,21 +76,18 @@ class CoreCall(BaseModel): extra="allow", ) - def __init_subclass__(cls, input_model: type[DataBase], output_model: type[DataBase], **kwargs: Any) -> None: """初始化子类""" super().__init_subclass__(**kwargs) cls.input_model = input_model cls.output_model = output_model - @classmethod def info(cls) -> CallInfo: """返回Call的名称和描述""" err = "[CoreCall] 必须手动实现info方法" raise NotImplementedError(err) - @staticmethod def _assemble_call_vars(executor: "StepExecutor") -> CallVars: """组装CallVars""" @@ -120,7 +117,6 @@ class CoreCall(BaseModel): summary=executor.task.runtime.summary, ) - @staticmethod def _extract_history_variables(path: str, history: dict[str, FlowStepHistory]) -> Any: """ @@ -131,18 +127,16 @@ class CoreCall(BaseModel): :return: 变量 """ split_path = path.split("/") + if len(split_path) < 2: + err = f"[CoreCall] 路径格式错误: {path}" + logger.error(err) + return None if split_path[0] not in history: err = f"[CoreCall] 步骤{split_path[0]}不存在" logger.error(err) - raise CallError( - message=err, - data={ - "step_id": split_path[0], - }, - ) - + return None data = history[split_path[0]].output_data - for key in split_path[1:]: + for key in split_path[2:]: if key not in data: err = f"[CoreCall] 输出Key {key} 不存在" logger.error(err) @@ -156,7 +150,6 @@ class CoreCall(BaseModel): data = data[key] return data - @classmethod async def instance(cls, executor: "StepExecutor", node: NodePool | None, **kwargs: Any) -> Self: """实例化Call类""" @@ -170,36 +163,30 @@ class CoreCall(BaseModel): await obj._set_input(executor) return obj - async def _set_input(self, executor: "StepExecutor") -> None: """获取Call的输入""" self._sys_vars = self._assemble_call_vars(executor) input_data = await self._init(self._sys_vars) self.input = input_data.model_dump(by_alias=True, exclude_none=True) - async def _init(self, call_vars: CallVars) -> DataBase: """初始化Call类,并返回Call的输入""" err = "[CoreCall] 初始化方法必须手动实现" raise NotImplementedError(err) - async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """Call类实例的流式输出方法""" yield CallOutputChunk(type=CallOutputType.TEXT, content="") - async def _after_exec(self, input_data: dict[str, Any]) -> None: """Call类实例的执行后方法""" - async def exec(self, executor: "StepExecutor", input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """Call类实例的执行方法""" async for chunk in self._exec(input_data): yield chunk await self._after_exec(input_data) - async def _llm(self, messages: list[dict[str, Any]]) -> str: """Call可直接使用的LLM非流式调用""" result = "" @@ -210,7 +197,6 @@ class CoreCall(BaseModel): self.output_tokens = llm.output_tokens return result - async def _json(self, messages: list[dict[str, Any]], schema: type[BaseModel]) -> BaseModel: """Call可直接使用的JSON生成""" json = FunctionLLM() diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index d8d22c46..a86ec4ac 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -47,7 +47,6 @@ class FlowExecutor(BaseExecutor): question: str = Field(description="用户输入") post_body_app: RequestDataApp = Field(description="请求体中的app信息") - async def load_state(self) -> None: """从数据库中加载FlowExecutor的状态""" logger.info("[FlowExecutor] 加载Executor状态") @@ -70,7 +69,6 @@ class FlowExecutor(BaseExecutor): self._reached_end: bool = False self.step_queue: deque[StepQueueItem] = deque() - async def _invoke_runner(self, queue_item: StepQueueItem) -> None: """单一Step执行""" # 创建步骤Runner @@ -90,7 +88,6 @@ class FlowExecutor(BaseExecutor): # 更新Task(已存过库) self.task = step_runner.task - async def _step_process(self) -> None: """执行当前queue里面的所有步骤(在用户看来是单一Step)""" while True: @@ -102,7 +99,6 @@ class FlowExecutor(BaseExecutor): # 执行Step await self._invoke_runner(queue_item) - async def _find_next_id(self, step_id: str) -> list[str]: """查找下一个节点""" next_ids = [] @@ -111,15 +107,14 @@ class FlowExecutor(BaseExecutor): next_ids += [edge.edge_to] return next_ids - async def _find_flow_next(self) -> list[StepQueueItem]: """在当前步骤执行前,尝试获取下一步""" # 如果当前步骤为结束,则直接返回 - if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] + if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] return [] if self.task.state.step_name == "Choice": # 如果是choice节点,获取分支ID - branch_id = self.task.context[-1]["output_data"].get("branch_id", None) + branch_id = self.task.context[-1]["output_data"]["branch_id"] if branch_id: self.task.state.step_id = self.task.state.step_id + "." + branch_id logger.info("[FlowExecutor] 分支ID:%s", branch_id) @@ -127,7 +122,7 @@ class FlowExecutor(BaseExecutor): logger.warning("[FlowExecutor] 没有找到分支ID,返回空列表") return [] - next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] + next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] # 如果step没有任何出边,直接跳到end if not next_steps: return [ @@ -146,7 +141,6 @@ class FlowExecutor(BaseExecutor): for next_step in next_steps ] - async def run(self) -> None: """ 运行流,返回各步骤结果,直到无法继续执行 @@ -159,8 +153,8 @@ class FlowExecutor(BaseExecutor): # 获取首个步骤 first_step = StepQueueItem( - step_id=self.task.state.step_id, # type: ignore[arg-type] - step=self.flow.steps[self.task.state.step_id], # type: ignore[arg-type] + step_id=self.task.state.step_id, # type: ignore[arg-type] + step=self.flow.steps[self.task.state.step_id], # type: ignore[arg-type] ) # 头插开始前的系统步骤,并执行 @@ -179,7 +173,7 @@ class FlowExecutor(BaseExecutor): # 运行Flow(未达终点) while not self._reached_end: # 如果当前步骤出错,执行错误处理步骤 - if self.task.state.status == StepStatus.ERROR: # type: ignore[arg-type] + if self.task.state.status == StepStatus.ERROR: # type: ignore[arg-type] logger.warning("[FlowExecutor] Executor出错,执行错误处理步骤") self.step_queue.clear() self.step_queue.appendleft(StepQueueItem( @@ -192,7 +186,7 @@ class FlowExecutor(BaseExecutor): params={ "user_prompt": LLM_ERROR_PROMPT.replace( "{{ error_info }}", - self.task.state.error_info["err_msg"], # type: ignore[arg-type] + self.task.state.error_info["err_msg"], # type: ignore[arg-type] ), }, ), diff --git a/apps/scheduler/executor/step.py b/apps/scheduler/executor/step.py index 506f3bb1..f3aeb82c 100644 --- a/apps/scheduler/executor/step.py +++ b/apps/scheduler/executor/step.py @@ -119,7 +119,6 @@ class StepExecutor(BaseExecutor): logger.exception("[StepExecutor] 初始化Call失败") raise - async def _run_slot_filling(self) -> None: """运行自动参数填充;相当于特殊Step,但是不存库""" # 判断是否需要进行自动参数填充 @@ -170,7 +169,6 @@ class StepExecutor(BaseExecutor): self.task.tokens.input_tokens += self.obj.tokens.input_tokens self.task.tokens.output_tokens += self.obj.tokens.output_tokens - async def _process_chunk( self, iterator: AsyncGenerator[CallOutputChunk, None], @@ -202,7 +200,6 @@ class StepExecutor(BaseExecutor): return content - async def run(self) -> None: """运行单个步骤""" self.validate_flow_state(self.task) diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 4caab4d2..89433cad 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -12,6 +12,8 @@ from jsonschema.exceptions import ValidationError from jsonschema.protocols import Validator from jsonschema.validators import extend +from apps.schemas.response_data import ParamsNode +from apps.scheduler.call.choice.schema import Type from apps.scheduler.slot.parser import ( SlotConstParser, SlotDateParser, @@ -221,6 +223,45 @@ class Slot: return data return _extract_type_desc(self._schema) + def get_params_node_from_schema(self, root: str = "") -> ParamsNode: + """从JSON Schema中提取ParamsNode""" + def _extract_params_node(schema_node: dict[str, Any], name: str = "", path: str = "") -> ParamsNode: + """递归提取ParamsNode""" + if "type" not in schema_node: + return None + + param_type = schema_node["type"] + if param_type == "object": + param_type = Type.DICT + elif param_type == "array": + param_type = Type.LIST + elif param_type == "string": + param_type = Type.STRING + elif param_type == "number": + param_type = Type.NUMBER + elif param_type == "boolean": + param_type = Type.BOOL + else: + logger.warning(f"[Slot] 不支持的参数类型: {param_type}") + return None + sub_params = [] + + if param_type == "object" and "properties" in schema_node: + for key, value in schema_node["properties"].items(): + sub_params.append(_extract_params_node(value, name=key, path=f"{path}/{key}")) + else: + # 对于非对象类型,直接返回空子参数 + sub_params = None + return ParamsNode(paramName=name, + paramPath=path, + paramType=param_type, + subParams=sub_params) + try: + return _extract_params_node(self._schema, name=root, path=root) + except Exception as e: + logger.error(f"[Slot] 提取ParamsNode失败: {e!s}\n{traceback.format_exc()}") + return None + def _flatten_schema(self, schema: dict[str, Any]) -> tuple[dict[str, Any], list[str]]: """将JSON Schema扁平化""" result = {} @@ -276,7 +317,6 @@ class Slot: logger.exception("[Slot] 错误schema不合法: %s", error.schema) return {}, [] - def _assemble_patch( self, key: str, @@ -329,7 +369,6 @@ class Slot: logger.info("[Slot] 组装patch: %s", patch_list) return patch_list - def convert_json(self, json_data: str | dict[str, Any]) -> dict[str, Any]: """将用户手动填充的参数专为真实JSON""" json_dict = json.loads(json_data) if isinstance(json_data, str) else json_data diff --git a/apps/schemas/config.py b/apps/schemas/config.py index 99bcccde..e91f5f75 100644 --- a/apps/schemas/config.py +++ b/apps/schemas/config.py @@ -129,7 +129,7 @@ class ExtraConfig(BaseModel): class ConfigModel(BaseModel): """配置文件的校验Class""" - no_auth: NoauthConfig + no_auth: NoauthConfig = Field(description="无认证配置", default=NoauthConfig()) deploy: DeployConfig login: LoginConfig embedding: EmbeddingConfig diff --git a/apps/schemas/parameters.py b/apps/schemas/parameters.py new file mode 100644 index 00000000..bd908d23 --- /dev/null +++ b/apps/schemas/parameters.py @@ -0,0 +1,69 @@ +from enum import Enum + + +class NumberOperate(str, Enum): + """Choice 工具支持的数字运算符""" + + EQUAL = "number_equal" + NOT_EQUAL = "number_not_equal" + GREATER_THAN = "number_greater_than" + LESS_THAN = "number_less_than" + GREATER_THAN_OR_EQUAL = "number_greater_than_or_equal" + LESS_THAN_OR_EQUAL = "number_less_than_or_equal" + + +class StringOperate(str, Enum): + """Choice 工具支持的字符串运算符""" + + EQUAL = "string_equal" + NOT_EQUAL = "string_not_equal" + CONTAINS = "string_contains" + NOT_CONTAINS = "string_not_contains" + STARTS_WITH = "string_starts_with" + ENDS_WITH = "string_ends_with" + LENGTH_EQUAL = "string_length_equal" + LENGTH_GREATER_THAN = "string_length_greater_than" + LENGTH_GREATER_THAN_OR_EQUAL = "string_length_greater_than_or_equal" + LENGTH_LESS_THAN = "string_length_less_than" + LENGTH_LESS_THAN_OR_EQUAL = "string_length_less_than_or_equal" + REGEX_MATCH = "string_regex_match" + + +class ListOperate(str, Enum): + """Choice 工具支持的列表运算符""" + + EQUAL = "list_equal" + NOT_EQUAL = "list_not_equal" + CONTAINS = "list_contains" + NOT_CONTAINS = "list_not_contains" + LENGTH_EQUAL = "list_length_equal" + LENGTH_GREATER_THAN = "list_length_greater_than" + LENGTH_GREATER_THAN_OR_EQUAL = "list_length_greater_than_or_equal" + LENGTH_LESS_THAN = "list_length_less_than" + LENGTH_LESS_THAN_OR_EQUAL = "list_length_less_than_or_equal" + + +class BoolOperate(str, Enum): + """Choice 工具支持的布尔运算符""" + + EQUAL = "bool_equal" + NOT_EQUAL = "bool_not_equal" + + +class DictOperate(str, Enum): + """Choice 工具支持的字典运算符""" + + EQUAL = "dict_equal" + NOT_EQUAL = "dict_not_equal" + CONTAINS_KEY = "dict_contains_key" + NOT_CONTAINS_KEY = "dict_not_contains_key" + + +class Type(str, Enum): + """Choice 工具支持的类型""" + + STRING = "string" + NUMBER = "number" + LIST = "list" + DICT = "dict" + BOOL = "bool" diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index 20d7ad9b..b1dc77b7 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -14,6 +14,14 @@ from apps.schemas.flow_topology import ( NodeServiceItem, PositionItem, ) +from apps.schemas.parameters import ( + Type, + NumberOperate, + StringOperate, + ListOperate, + BoolOperate, + DictOperate, +) from apps.schemas.mcp import MCPInstallStatus, MCPTool, MCPType from apps.schemas.record import RecordData from apps.schemas.user import UserInfo @@ -629,20 +637,41 @@ class ListLLMRsp(ResponseData): result: list[LLMProviderInfo] = Field(default=[], title="Result") -class Params(BaseModel): + +class ParamsNode(BaseModel): """参数数据结构""" + param_name: str = Field(..., description="参数名称", alias="paramName") + param_path: str = Field(..., description="参数路径", alias="paramPath") + param_type: Type = Field(..., description="参数类型", alias="paramType") + sub_params: list["ParamsNode"] | None = Field( + default=None, description="子参数列表", alias="subParams" + ) - id: str = Field(..., description="StepID") - name: str = Field(..., description="Step名称") - parameters: dict[str, Any] = Field(..., description="参数") - operate: str = Field(..., description="比较符") -class GetParamsMsg(BaseModel): - """GET /api/params 返回数据结构""" +class StepParams(BaseModel): + """参数数据结构""" + step_id: str = Field(..., description="步骤ID", alias="stepId") + name: str = Field(..., description="Step名称") + params_node: ParamsNode | None = Field( + default=None, description="参数节点", alias="paramsNode") - result: list[Params] = Field(..., title="Result") class GetParamsRsp(ResponseData): """GET /api/params 返回数据结构""" - result: GetParamsMsg \ No newline at end of file + result: list[StepParams] = Field( + default=[], description="参数列表", alias="result" + ) + + +class OperateAndBindType(BaseModel): + """操作和绑定类型数据结构""" + + operate: NumberOperate | StringOperate | ListOperate | BoolOperate | DictOperate = Field(description="操作类型") + bind_type: Type = Field(description="绑定类型") + + +class GetOperaRsp(ResponseData): + """GET /api/operate 返回数据结构""" + + result: list[OperateAndBindType] = Field(..., title="Result") diff --git a/apps/services/flow.py b/apps/services/flow.py index cb8ad57f..c9fd86fd 100644 --- a/apps/services/flow.py +++ b/apps/services/flow.py @@ -20,7 +20,6 @@ from apps.schemas.flow_topology import ( PositionItem, ) from apps.services.node import NodeManager -from apps.schemas.response_data import Params logger = logging.getLogger(__name__) @@ -470,48 +469,3 @@ class FlowManager: return False else: return True - - @staticmethod - async def get_params_by_flow_and_step_id( - flow: FlowItem, step_id: str - ) -> list[Params] | None: - """递归收集指定节点之前所有路径上的节点参数""" - params = [] - collected = set() # 记录已收集参数的节点 - - async def backtrack(current_id: str, visited: set) -> None: - # 避免循环递归 - if current_id in visited: - return - visited.add(current_id) - - # 获取所有指向当前节点的边 - incoming_edges = [ - edge for edge in flow.edges if edge.target_node == current_id - ] - - for edge in incoming_edges: - source_id = edge.source_node - - # 跳过起始节点 - if source_id == "start": - continue - - # 收集当前节点的参数(如果未被收集过) - if source_id not in collected: - node = flow.nodes.get(source_id) - if node: - collected.add(source_id) - params.append( - Params( - id=source_id, - name=node.name, - parameters=node.parameters.get("parameters", {}), - ), - ) - - # 继续回溯,传递当前路径的visited集合副本 - await backtrack(source_id, visited.copy()) - - await backtrack(step_id, set()) - return params diff --git a/apps/services/node.py b/apps/services/node.py index 6f0d492e..bf48e71f 100644 --- a/apps/services/node.py +++ b/apps/services/node.py @@ -16,6 +16,7 @@ NODE_TYPE_MAP = { "API": APINode, } + class NodeManager: """Node管理器""" @@ -29,7 +30,6 @@ class NodeManager: raise ValueError(err) return node["call_id"] - @staticmethod async def get_node(node_id: str) -> NodePool: """获取Node的类型""" @@ -40,7 +40,6 @@ class NodeManager: raise ValueError(err) return NodePool.model_validate(node) - @staticmethod async def get_node_name(node_id: str) -> str: """获取node的名称""" @@ -52,7 +51,6 @@ class NodeManager: return "" return node_doc["name"] - @staticmethod def merge_params_schema(params_schema: dict[str, Any], known_params: dict[str, Any]) -> dict[str, Any]: """递归合并参数Schema,将known_params中的值填充到params_schema的对应位置""" @@ -75,7 +73,6 @@ class NodeManager: return params_schema - @staticmethod async def get_node_params(node_id: str) -> tuple[dict[str, Any], dict[str, Any]]: """获取Node数据""" @@ -100,7 +97,6 @@ class NodeManager: err = f"[NodeManager] Call {call_id} 不存在" logger.error(err) raise ValueError(err) - # 返回参数Schema return ( NodeManager.merge_params_schema(call_class.model_json_schema(), node_data.known_params or {}), diff --git a/apps/services/parameter.py b/apps/services/parameter.py new file mode 100644 index 00000000..ae375e97 --- /dev/null +++ b/apps/services/parameter.py @@ -0,0 +1,86 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""flow Manager""" + +import logging + +from pymongo import ASCENDING + +from apps.services.node import NodeManager +from apps.schemas.flow_topology import FlowItem +from apps.scheduler.slot.slot import Slot +from apps.scheduler.call.choice.condition_handler import ConditionHandler +from apps.scheduler.call.choice.schema import ( + NumberOperate, + StringOperate, + ListOperate, + BoolOperate, + DictOperate, + Type +) +from apps.schemas.response_data import ( + OperateAndBindType, + ParamsNode, + StepParams, +) +from apps.services.node import NodeManager +logger = logging.getLogger(__name__) + + +class ParameterManager: + """Parameter Manager""" + @staticmethod + async def get_operate_and_bind_type(param_type: Type) -> list[OperateAndBindType]: + """Get operate and bind type""" + result = [] + operate = None + if param_type == Type.NUMBER: + operate = NumberOperate + elif param_type == Type.STRING: + operate = StringOperate + elif param_type == Type.LIST: + operate = ListOperate + elif param_type == Type.BOOL: + operate = BoolOperate + elif param_type == Type.DICT: + operate = DictOperate + if operate: + for item in operate: + result.append(OperateAndBindType( + operate=item, + bind_type=ConditionHandler.get_value_type_from_operate(item))) + return result + + @staticmethod + async def get_pre_params_by_flow_and_step_id(flow: FlowItem, step_id: str) -> list[StepParams]: + """Get pre params by flow and step id""" + index = 0 + q = [step_id] + in_edges = {} + step_id_to_node_id = {} + for step in flow.nodes: + step_id_to_node_id[step.step_id] = step.node_id + for edge in flow.edges: + if edge.target_node not in in_edges: + in_edges[edge.target_node] = [] + in_edges[edge.target_node].append(edge.source_node) + while index < len(q): + tmp_step_id = q[index] + index += 1 + for i in range(len(in_edges.get(tmp_step_id, []))): + pre_node_id = in_edges[tmp_step_id][i] + if pre_node_id not in q: + q.append(pre_node_id) + pre_step_params = [] + for step_id in q: + node_id = step_id_to_node_id.get(step_id) + params_schema, output_schema = await NodeManager.get_node_params(node_id) + slot = Slot(output_schema) + params_node = slot.get_params_node_from_schema(root='/output') + pre_step_params.append( + StepParams( + stepId=node_id, + name=params_schema.get("name", ""), + paramsNode=params_node + ) + ) + return pre_step_params -- Gitee From 09f16bad671439d7d6e33e7d10405b1b5dfc78e4 Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 28 Jul 2025 14:52:27 +0800 Subject: [PATCH 20/78] =?UTF-8?q?=E5=AE=8C=E5=96=84Agent=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/schemas/enum_var.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 20e9c0f9..578d8121 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -56,6 +56,8 @@ class EventType(str, Enum): STEP_INPUT = "step.input" STEP_OUTPUT = "step.output" FLOW_STOP = "flow.stop" + FLOW_FAILED = "flow.failed" + FLOW_CANCELLED = "flow.cancelled" DONE = "done" -- Gitee From 36b0e9b2bd6472758fa9409edfb9cbe64c24e7f3 Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 28 Jul 2025 16:42:58 +0800 Subject: [PATCH 21/78] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=97=A0=E9=89=B4=E6=9D=83=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/main.py | 16 ++++++++ .../call/choice/condition_handler.py | 41 ++++++++++--------- apps/schemas/request_data.py | 1 + 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/apps/main.py b/apps/main.py index c26e5e47..17d4abb4 100644 --- a/apps/main.py +++ b/apps/main.py @@ -83,12 +83,28 @@ logging.basicConfig( ) +async def add_no_auth_user() -> None: + """ + 添加无认证用户 + """ + from apps.common.mongo import MongoDB + from apps.schemas.collection import User + mongo = MongoDB() + user_collection = mongo.get_collection("user") + await user_collection.insert_one(User( + _id=Config().get_config().no_auth.user_sub, + is_admin=True, + ).model_dump(by_alias=True)) + + async def init_resources() -> None: """初始化必要资源""" WordsCheck() await LanceDB().init() await Pool.init() TokenCalculator() + if Config().get_config().no_auth.enable: + await add_no_auth_user() # 运行 if __name__ == "__main__": diff --git a/apps/scheduler/call/choice/condition_handler.py b/apps/scheduler/call/choice/condition_handler.py index 7542f294..6111ba90 100644 --- a/apps/scheduler/call/choice/condition_handler.py +++ b/apps/scheduler/call/choice/condition_handler.py @@ -83,7 +83,11 @@ class ConditionHandler(BaseModel): continue for condition in block_judgement.conditions: result = ConditionHandler._judge_condition(condition) - results.append(result) + if result is not None: + results.append(result) + if not results: + logger.warning(f"[Choice] 分支 {block_judgement.branch_id} 条件处理失败: 没有有效的条件") + continue if block_judgement.logic == Logic.AND: final_result = all(results) elif block_judgement.logic == Logic.OR: @@ -118,7 +122,7 @@ class ConditionHandler(BaseModel): if value_type == Type.STRING: result = ConditionHandler._judge_string_condition(left, operate, right) elif value_type == Type.NUMBER: - result = ConditionHandler._judge_int_condition(left, operate, right) + result = ConditionHandler._judge_number_condition(left, operate, right) elif value_type == Type.BOOL: result = ConditionHandler._judge_bool_condition(left, operate, right) elif value_type == Type.LIST: @@ -126,9 +130,9 @@ class ConditionHandler(BaseModel): elif value_type == Type.DICT: result = ConditionHandler._judge_dict_condition(left, operate, right) else: - logger.error("不支持的数据类型: %s", value_type) msg = f"不支持的数据类型: {value_type}" - raise ValueError(msg) + logger.error(f"[Choice] 条件处理失败: {msg}") + return None return result @staticmethod @@ -147,11 +151,10 @@ class ConditionHandler(BaseModel): """ left_value = left.value if not isinstance(left_value, str): - logger.error("左值不是字符串类型: %s", left_value) - msg = "左值必须是字符串类型" - raise TypeError(msg) + msg = f"左值必须是字符串类型 ({left_value})" + logger.warning(msg) + return None right_value = right.value - result = False if operate == StringOperate.EQUAL: return left_value == right_value elif operate == StringOperate.NOT_EQUAL: @@ -195,9 +198,9 @@ class ConditionHandler(BaseModel): """ left_value = left.value if not isinstance(left_value, (int, float)): - logger.error("左值不是数字类型: %s", left_value) - msg = "左值必须是数字类型" - raise TypeError(msg) + msg = f"左值必须是数字类型 ({left_value})" + logger.warning(msg) + return None right_value = right.value if operate == NumberOperate.EQUAL: return left_value == right_value @@ -229,9 +232,9 @@ class ConditionHandler(BaseModel): """ left_value = left.value if not isinstance(left_value, bool): - logger.error("左值不是布尔类型: %s", left_value) msg = "左值必须是布尔类型" - raise TypeError(msg) + logger.warning(msg) + return None right_value = right.value if operate == BoolOperate.EQUAL: return left_value == right_value @@ -259,9 +262,9 @@ class ConditionHandler(BaseModel): """ left_value = left.value if not isinstance(left_value, list): - logger.error("左值不是列表类型: %s", left_value) - msg = "左值必须是列表类型" - raise TypeError(msg) + msg = f"左值必须是列表类型 ({left_value})" + logger.warning(msg) + return None right_value = right.value if operate == ListOperate.EQUAL: return left_value == right_value @@ -299,9 +302,9 @@ class ConditionHandler(BaseModel): """ left_value = left.value if not isinstance(left_value, dict): - logger.error("左值不是字典类型: %s", left_value) - msg = "左值必须是字典类型" - raise TypeError(msg) + msg = f"左值必须是字典类型 ({left_value})" + logger.warning(msg) + return None right_value = right.value if operate == DictOperate.EQUAL: return left_value == right_value diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index a3a8848c..af0d4a01 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -107,6 +107,7 @@ class ActiveMCPServiceRequest(BaseModel): """POST /api/mcp/{serviceId} 请求数据结构""" active: bool = Field(description="是否激活mcp服务") + mcp_env: dict[str, Any] | None = Field(default=None, description="MCP服务环境变量", alias="mcpEnv") class UpdateServiceRequest(BaseModel): -- Gitee From e89bb6612f8bb9b406a17bfd5e92cd30d65e7c54 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 09:58:02 +0800 Subject: [PATCH 22/78] =?UTF-8?q?=E5=AE=8C=E5=96=84mcp=20agent=E7=9A=84pro?= =?UTF-8?q?mt&=E4=BF=AE=E5=A4=8D=E5=8E=BB=E9=99=A4=E5=86=97=E4=BD=99?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=88=86=E6=94=AF=E8=8A=82=E7=82=B9=E7=9B=B8?= =?UTF-8?q?=E5=85=B3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/mcp_service.py | 3 +- apps/scheduler/mcp_agent/plan.py | 9 +- apps/scheduler/mcp_agent/prompt.py | 330 ++++++++++++++++++++++++++--- apps/scheduler/mcp_agent/select.py | 30 +-- apps/scheduler/pool/loader/mcp.py | 18 +- apps/schemas/enum_var.py | 2 +- apps/schemas/mcp.py | 4 +- apps/schemas/request_data.py | 2 +- apps/services/flow_validate.py | 20 +- apps/services/mcp_service.py | 4 +- 10 files changed, 356 insertions(+), 66 deletions(-) diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index a845a376..de484e78 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -36,6 +36,7 @@ router = APIRouter( dependencies=[Depends(verify_user)], ) + async def _check_user_admin(user_sub: str) -> None: user = await UserManager.get_userinfo_by_user_sub(user_sub) if not user: @@ -282,7 +283,7 @@ async def active_or_deactivate_mcp_service( """激活/取消激活mcp""" try: if data.active: - await MCPServiceManager.active_mcpservice(user_sub, service_id) + await MCPServiceManager.active_mcpservice(user_sub, service_id, data.mcp_env) else: await MCPServiceManager.deactive_mcpservice(user_sub, service_id) except Exception as e: diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index cd4f5975..47e803f6 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -25,7 +25,6 @@ class MCPPlanner: self.input_tokens = 0 self.output_tokens = 0 - async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: """规划下一步的执行流程,并输出""" # 获取推理结果 @@ -34,8 +33,10 @@ class MCPPlanner: # 解析为结构化数据 return await self._parse_plan_result(result, max_steps) - - async def _get_reasoning_plan(self, tool_list: list[MCPTool], max_steps: int) -> str: + async def _get_reasoning_plan( + self, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan = MCPPlan(), + tool_list: list[MCPTool] = [], + max_steps: int = 10) -> str: """获取推理大模型的结果""" # 格式化Prompt template = self._env.from_string(CREATE_PLAN) @@ -66,7 +67,6 @@ class MCPPlanner: return result - async def _parse_plan_result(self, result: str, max_steps: int) -> MCPPlan: """将推理结果解析为结构化数据""" # 格式化Prompt @@ -85,7 +85,6 @@ class MCPPlanner: plan = await json_generator.generate() return MCPPlan.model_validate(plan) - async def generate_answer(self, plan: MCPPlan, memory: str) -> str: """生成最终回答""" template = self._env.from_string(FINAL_ANSWER) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index b322fb08..649a67a9 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -61,6 +61,53 @@ MCP_SELECT = dedent(r""" ### 请一步一步思考: +""") +EVALUATE_GAOL = dedent(r""" + 你是一个计划评估器。 + 请根据用户的目标和当前的工具集合以及一些附加信息,判断基于当前的工具集合,是否能够完成用户的目标。 + 如果能够完成,请返回`true`,否则返回`false`。 + 推理过程必须清晰明了,能够让人理解你的判断依据。 + 必须按照以下格式回答: + ```json + { + "can_complete": true/false, + "resoning": "你的推理过程" + } + ``` + + # 样例 + ## 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈,并调优 + + ## 工具集合 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + + - mysql_analyzer分析MySQL数据库性能 + - performance_tuner调优数据库性能 + - Final结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + + + ## 附加信息 + 1. 当前MySQL数据库的版本是8.0.26 + 2. 当前MySQL数据库的配置文件路径是/etc/my.cnf + + ## + ```json + { + "can_complete": true, + "resoning": "当前的工具集合中包含mysql_analyzer和performance_tuner,能够完成对MySQL数据库的性能分析和调优,因此可以完成用户的目标。" + } + ``` + + # 目标 + {{ goal }} + + # 工具集合 + {{ tools }} + + # 附加信息 + {{ additional_info }} + """) CREATE_PLAN = dedent(r""" 你是一个计划生成器。 @@ -163,78 +210,299 @@ CREATE_PLAN = dedent(r""" # 计划 """) -EVALUATE_PLAN = dedent(r""" - 你是一个计划评估器。 - 请根据给定的计划,和当前计划执行的实际情况,分析当前计划是否合理和完整,并生成改进后的计划。 +RECREATE_PLAN = dedent(r""" + 你是一个计划重建器。 + 请根据用户的目标、当前计划和运行报错,重新生成一个计划。 # 一个好的计划应该: 1. 能够成功完成用户的目标 2. 计划中的每一个步骤必须且只能使用一个工具。 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 - 4. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + 4. 你的计划必须避免之前的错误,并且能够成功执行。 + 5. 计划中的最后一步必须是Final工具,以确保计划执行结束。 - # 你此前的计划是: + # 生成计划时的注意事项: - {{ plan }} + - 每一条计划包含3个部分: + - 计划内容:描述单个计划步骤的大致内容 + - 工具ID:必须从下文的工具列表中选择 + - 工具指令:改写用户的目标,使其更符合工具的输入要求 + - 必须按照如下格式生成计划,不要输出任何额外数据: - # 这个计划的执行情况是: + ```json + { + "plans": [ + { + "content": "计划内容", + "tool": "工具ID", + "instruction": "工具指令" + } + ] + } + ``` - 计划的执行情况将放置在 XML标签中。 + - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。\ +思考过程应放置在 XML标签中。 + - 计划内容中,可以使用"Result[]"来引用之前计划步骤的结果。例如:"Result[3]"表示引用第三条计划执行后的结果。 + - 计划不得多于{{ max_num }}条,且每条计划内容应少于150字。 - - {{ memory }} - + # 样例 - # 进行评估时的注意事项: + ## 目标 - - 请一步一步思考,解析用户的目标,并指导你接下来的生成。思考过程应放置在 XML标签中。 - - 评估结果分为两个部分: - - 计划评估的结论 - - 改进后的计划 - - 请按照以下JSON格式输出评估结果: + 请帮我扫描一下192.168.1.1的这台机器的端口,看看有哪些端口开放。 + ## 工具 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + + - command_generator生成命令行指令 + - tool_selector选择合适的工具 + - command_executor执行命令行指令 + - Final结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + + ## 当前计划 ```json { - "evaluation": "评估结果", "plans": [ { - "content": "改进后的计划内容", - "tool": "工具ID", - "instruction": "工具指令" + "content": "生成端口扫描命令", + "tool": "command_generator", + "instruction": "生成端口扫描命令:扫描192.168.1.1的开放端口" + }, + { + "content": "在执行Result[0]生成的命令", + "tool": "command_executor", + "instruction": "执行端口扫描命令" + }, + { + "content": "任务执行完成,端口扫描结果为Result[2]", + "tool": "Final", + "instruction": "" + } + ] + } + ``` + ## 运行报错 + 执行端口扫描命令时,出现了错误:`-bash: curl: command not found`。 + ## 重新生成的计划 + + + 1. 这个目标需要使用网络扫描工具来完成,首先需要选择合适的网络扫描工具 + 2. 目标可以拆解为以下几个部分: + - 生成端口扫描命令 + - 执行端口扫描命令 + 3.但是在执行端口扫描命令时,出现了错误:`-bash: curl: command not found`。 + 4.我将计划调整为: + - 需要先生成一个命令,查看当前机器支持哪些网络扫描工具 + - 执行这个命令,查看当前机器支持哪些网络扫描工具 + - 然后从中选择一个网络扫描工具 + - 基于选择的网络扫描工具,生成端口扫描命令 + - 执行端口扫描命令 + + + ```json + { + "plans": [ + { + "content": "需要生成一条命令查看当前机器支持哪些网络扫描工具", + "tool": "command_generator", + "instruction": "选择一个前机器支持哪些网络扫描工具" + }, + { + "content": "执行Result[0]中生成的命令,查看当前机器支持哪些网络扫描工具", + "tool": "command_executor", + "instruction": "执行Result[0]中生成的命令" + }, + { + "content": "从Result[1]中选择一个网络扫描工具,生成端口扫描命令", + "tool": "tool_selector", + "instruction": "选择一个网络扫描工具,生成端口扫描命令" + }, + { + "content": "基于result[2]中选择的网络扫描工具,生成端口扫描命令", + "tool": "command_generator", + "instruction": "生成端口扫描命令:扫描192.168.1.1的开放端口" + }, + { + "content": "在Result[0]的MCP Server上执行Result[3]生成的命令", + "tool": "command_executor", + "instruction": "执行端口扫描命令" + }, + { + "content": "任务执行完成,端口扫描结果为Result[4]", + "tool": "Final", + "instruction": "" } ] } ``` - # 现在开始评估计划: + # 现在开始重新生成计划: + + # 目标 + + {{goal}} + + # 工具 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + + + {% for tool in tools %} + - {{ tool.id }}{{tool.name}};{{ tool.description }} + {% endfor %} + - Final结束步骤,当执行到这一步时,\ +表示计划执行结束,所得到的结果将作为最终结果。 + + + # 当前计划 + {{ current_plan }} + + # 运行报错 + {{ error_message }} + + # 重新生成的计划 """) +RISK_EVALUATE = dedent(r""" + 你是一个工具执行计划评估器。 + 你的任务是根据当前工具的名称、描述和入参以及附加信息,判断当前工具执行的风险并输出提示。 + ```json + { + "risk": "高/中/低", + "message": "提示信息" + } + ``` + # 样例 + ## 工具名称 + mysql_analyzer + ## 工具描述 + 分析MySQL数据库性能 + ## 工具入参 + { + "host": "192.0.0.1", + "port": 3306, + "username": "root", + "password": "password" + } + ## 附加信息 + 1. 当前MySQL数据库的版本是8.0.26 + 2. 当前MySQL数据库的配置文件路径是/etc/my.cnf,并含有以下配置项 + ```ini + [mysqld] + innodb_buffer_pool_size=1G + innodb_log_file_size=256M + ``` + ## 输出 + ```json + { + "risk": "中", + "message": "当前工具将连接到MySQL数据库并分析性能,可能会对数据库性能产生一定影响。请确保在非生产环境中执行此操作。" + } + ``` + # 工具名称 + {{ tool_name }} + # 工具描述 + {{ tool_description }} + # 工具入参 + {{ tool_input }} + # 附加信息 + {{ additional_info }} + # 输出 + """ + ) + +# 获取缺失的参数的json结构体 +GET_MISSING_PARAMS = dedent(r""" + 你是一个工具参数获取器。 + 你的任务是根据当前工具的名称、描述和入参和入参的schema以及运行报错,获取当前工具缺失的参数并输出提示。 + ```json + { + "host": "请补充主机地址", + "port": "请补充端口号", + "username": "请补充用户名", + "password": "请补充密码" + } + ``` + # 样例 + ## 工具名称 + mysql_analyzer + ## 工具描述 + 分析MySQL数据库性能 + ## 工具入参 + { + "host": "192.0.0.1", + "port": 3306, + "username": "root", + "password": "password" + } + ## 工具入参schema + { + "type": "object", + "properties": { + "host": {"type": "string", "description": "MySQL数据库的主机地址"}, + "port": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ], + "description": "MySQL数据库的端口号(可以是数字或字符串)" + }, + "username": {"type": "string", "description": "MySQL数据库的用户名"}, + "password": {"type": "string", "description": "MySQL数据库的密码"} + }, + "required": ["host", "port", "username", "password"] + } + ## 运行报错 + 执行端口扫描命令时,出现了错误:`password is not correct`。 + ## 输出 + ```json + { + "host": "192.0.0.1", + "port": 3306, + "username": "请补充用户名", + "password": "请补充密码" + } + ``` + # 工具名称 + {{ tool_name }} + # 工具描述 + {{ tool_description }} + # 工具入参 + {{ tool_input }} + # 工具入参schema + {{ tool_input_schema }} + # 运行报错 + {{ error_message }} + # 输出 + """ + ) FINAL_ANSWER = dedent(r""" 综合理解计划执行结果和背景信息,向用户报告目标的完成情况。 # 用户目标 - {{ goal }} + {{goal}} # 计划执行情况 为了完成上述目标,你实施了以下计划: - {{ memory }} + {{memory}} # 其他背景信息: - {{ status }} + {{status}} # 现在,请根据以上信息,向用户报告目标的完成情况: """) + MEMORY_TEMPLATE = dedent(r""" - {% for ctx in context_list %} - - 第{{ loop.index }}步:{{ ctx.step_description }} - - 调用工具 `{{ ctx.step_id }}`,并提供参数 `{{ ctx.input_data }}` - - 执行状态:{{ ctx.status }} - - 得到数据:`{{ ctx.output_data }}` - {% endfor %} + { % for ctx in context_list % } + - 第{{loop.index}}步:{{ctx.step_description}} + - 调用工具 `{{ctx.step_id}}`,并提供参数 `{{ctx.input_data}}` + - 执行状态:{{ctx.status}} + - 得到数据:`{{ctx.output_data}}` + { % endfor % } """) diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 2ff50344..95f588e2 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -2,9 +2,10 @@ """选择MCP Server及其工具""" import logging - +import uuid from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment +from typing import AsyncGenerator from apps.common.lance import LanceDB from apps.common.mongo import MongoDB @@ -39,7 +40,6 @@ class MCPSelector: sql += f"'{mcp_id}', " return sql.rstrip(", ") + ")" - async def _get_top_mcp_by_embedding( self, query: str, @@ -72,7 +72,6 @@ class MCPSelector: }]) return llm_mcp_list - async def _get_mcp_by_llm( self, query: str, @@ -100,8 +99,7 @@ class MCPSelector: # 使用小模型提取JSON return await self._call_function_mcp(result, mcp_ids) - - async def _call_reasoning(self, prompt: str) -> str: + async def _call_reasoning(self, prompt: str) -> AsyncGenerator[str, None]: """调用大模型进行推理""" logger.info("[MCPHelper] 调用推理大模型") llm = ReasoningLLM() @@ -109,13 +107,8 @@ class MCPSelector: {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt}, ] - result = "" async for chunk in llm.call(message): - result += chunk - self.input_tokens += llm.input_tokens - self.output_tokens += llm.output_tokens - return result - + yield chunk async def _call_function_mcp(self, reasoning_result: str, mcp_ids: list[str]) -> MCPSelectResult: """调用结构化输出小模型提取JSON""" @@ -136,7 +129,6 @@ class MCPSelector: raise return result - async def select_top_mcp( self, query: str, @@ -153,7 +145,6 @@ class MCPSelector: # 通过LLM选择最合适的 return await self._get_mcp_by_llm(query, llm_mcp_list, mcp_list) - @staticmethod async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTool]: """选择最合适的工具""" @@ -181,5 +172,16 @@ class MCPSelector: async for tool in tool_data: tool_obj = MCPTool.model_validate(tool) llm_tool_list.append(tool_obj) - + llm_tool_list.append( + MCPTool( + id="00000000-0000-0000-0000-000000000000", + name="Final", + description="It is the final step, indicating the end of the plan execution.") + ) + llm_tool_list.append( + MCPTool( + id="00000000-0000-0000-0000-000000000001", + name="Chat", + description="It is a chat tool to communicate with the user.") + ) return llm_tool_list diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index 1463d0a1..648baa53 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -11,6 +11,7 @@ import shutil import asyncer from anyio import Path from sqids.sqids import Sqids +from typing import Any from apps.common.lance import LanceDB from apps.common.mongo import MongoDB @@ -391,7 +392,7 @@ class MCPLoader(metaclass=SingletonMeta): ) @staticmethod - async def user_active_template(user_sub: str, mcp_id: str) -> None: + async def user_active_template(user_sub: str, mcp_id: str, mcp_env: dict[str, Any]) -> None: """ 用户激活MCP模板 @@ -409,7 +410,8 @@ class MCPLoader(metaclass=SingletonMeta): if await user_path.exists(): err = f"MCP模板“{mcp_id}”已存在或有同名文件,无法激活" raise FileExistsError(err) - + mcp_config = await MCPLoader.get_config(mcp_id) + mcp_config.config.env.update(mcp_env) # 拷贝文件 await asyncer.asyncify(shutil.copytree)( template_path.as_posix(), @@ -417,7 +419,17 @@ class MCPLoader(metaclass=SingletonMeta): dirs_exist_ok=True, symlinks=True, ) - + user_config_path = user_path / "config.json" + # 更新用户配置 + f = await user_config_path.open("w", encoding="utf-8", errors="ignore") + await f.write( + json.dumps( + mcp_config.model_dump(by_alias=True, exclude_none=True), + indent=4, + ensure_ascii=False, + ) + ) + await f.aclose() # 更新数据库 mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 578d8121..d50eeaf7 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -97,7 +97,7 @@ class NodeType(str, Enum): START = "start" END = "end" NORMAL = "normal" - CHOICE = "choice" + CHOICE = "Choice" class SaveType(str, Enum): diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 60c8f17b..693caa09 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -118,7 +118,7 @@ class MCPToolSelectResult(BaseModel): class MCPPlanItem(BaseModel): """MCP 计划""" - id: str = Field(default_factory=lambda: str(uuid.uuid4())) + step_id: str = Field(description="步骤的ID", default="") content: str = Field(description="计划内容") tool: str = Field(description="工具名称") instruction: str = Field(description="工具指令") @@ -127,4 +127,4 @@ class MCPPlanItem(BaseModel): class MCPPlan(BaseModel): """MCP 计划""" - plans: list[MCPPlanItem] = Field(description="计划列表") + plans: list[MCPPlanItem] = Field(description="计划列表", default=[]) diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index af0d4a01..793ff456 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -107,7 +107,7 @@ class ActiveMCPServiceRequest(BaseModel): """POST /api/mcp/{serviceId} 请求数据结构""" active: bool = Field(description="是否激活mcp服务") - mcp_env: dict[str, Any] | None = Field(default=None, description="MCP服务环境变量", alias="mcpEnv") + mcp_env: dict[str, Any] = Field(default={}, description="MCP服务环境变量", alias="mcpEnv") class UpdateServiceRequest(BaseModel): diff --git a/apps/services/flow_validate.py b/apps/services/flow_validate.py index 78e8d340..d799c5dc 100644 --- a/apps/services/flow_validate.py +++ b/apps/services/flow_validate.py @@ -52,18 +52,26 @@ class FlowService: if node.call_id == NodeType.CHOICE.value: node.parameters = node.parameters["input_parameters"] if "choices" not in node.parameters: - node.parameters["choices"] = [] + logger.error(f"[FlowService] 节点{node.name}的分支字段缺失") + raise FlowBranchValidationError(f"[FlowService] 节点{node.name}的分支字段缺失") + if not node.parameters["choices"]: + logger.error(f"[FlowService] 节点{node.name}的分支字段为空") + raise FlowBranchValidationError(f"[FlowService] 节点{node.name}的分支字段为空") for choice in node.parameters["choices"]: - if choice["branchId"] in node_branch_map[node.step_id]: - err = f"[FlowService] 节点{node.name}的分支{choice['branchId']}重复" + if "branch_id" not in choice: + err = f"[FlowService] 节点{node.name}的分支choice缺少branch_id字段" + logger.error(err) + raise FlowBranchValidationError(err) + if choice["branch_id"] in node_branch_map[node.step_id]: + err = f"[FlowService] 节点{node.name}的分支{choice['branch_id']}重复" logger.error(err) raise Exception(err) for illegal_char in branch_illegal_chars: - if illegal_char in choice["branchId"]: - err = f"[FlowService] 节点{node.name}的分支{choice['branchId']}名称中含有非法字符" + if illegal_char in choice["branch_id"]: + err = f"[FlowService] 节点{node.name}的分支{choice['branch_id']}名称中含有非法字符" logger.error(err) raise Exception(err) - node_branch_map[node.step_id].add(choice["branchId"]) + node_branch_map[node.step_id].add(choice["branch_id"]) else: node_branch_map[node.step_id].add("") valid_edges = [] diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index 7cb880c0..2c84a211 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -198,7 +198,6 @@ class MCPServiceManager: base_filters = {"author": {"$regex": keyword, "$options": "i"}} return base_filters - @staticmethod async def create_mcpservice(data: UpdateMCPServiceRequest, user_sub: str) -> str: """ @@ -297,6 +296,7 @@ class MCPServiceManager: async def active_mcpservice( user_sub: str, service_id: str, + mcp_env: dict[str, Any] = {}, ) -> None: """ 激活MCP服务 @@ -310,7 +310,7 @@ class MCPServiceManager: for item in status: mcp_status = item.get("status", MCPInstallStatus.INSTALLING) if mcp_status == MCPInstallStatus.READY: - await MCPLoader.user_active_template(user_sub, service_id) + await MCPLoader.user_active_template(user_sub, service_id, mcp_env) else: err = "[MCPServiceManager] MCP服务未准备就绪" raise RuntimeError(err) -- Gitee From 7f48934e3c1bb5d240912a5da746cb01b93d8bdf Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 11:06:54 +0800 Subject: [PATCH 23/78] =?UTF-8?q?=E5=AE=8C=E5=96=84parameter=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/mcp_agent/prompt.py | 38 ++++++++++++++++++++++-------- apps/scheduler/slot/slot.py | 2 +- apps/services/parameter.py | 11 +++++---- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 649a67a9..579a5081 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -437,19 +437,37 @@ GET_MISSING_PARAMS = dedent(r""" "password": "password" } ## 工具入参schema - { - "type": "object", - "properties": { - "host": {"type": "string", "description": "MySQL数据库的主机地址"}, + { + "type": "object", + "properties": { + "host": { + "anyOf": [ + {"type": "string"}, + {"type": "null"} + ], + "description": "MySQL数据库的主机地址(可以为字符串或null)" + }, "port": { "anyOf": [ {"type": "string"}, - {"type": "integer"}, + {"type": "null"} ], - "description": "MySQL数据库的端口号(可以是数字或字符串)" + "description": "MySQL数据库的端口号(可以是数字、字符串或null)" }, - "username": {"type": "string", "description": "MySQL数据库的用户名"}, - "password": {"type": "string", "description": "MySQL数据库的密码"} + "username": { + "anyOf": [ + {"type": "string"}, + {"type": "null"} + ], + "description": "MySQL数据库的用户名(可以为字符串或null)" + }, + "password": { + "anyOf": [ + {"type": "string"}, + {"type": "null"} + ], + "description": "MySQL数据库的密码(可以为字符串或null)" + } }, "required": ["host", "port", "username", "password"] } @@ -460,8 +478,8 @@ GET_MISSING_PARAMS = dedent(r""" { "host": "192.0.0.1", "port": 3306, - "username": "请补充用户名", - "password": "请补充密码" + "username": null, + "password": null } ``` # 工具名称 diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 89433cad..c1b27abf 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -257,7 +257,7 @@ class Slot: paramType=param_type, subParams=sub_params) try: - return _extract_params_node(self._schema, name=root, path=root) + return _extract_params_node(self._schema, name=root, path="/"+root) except Exception as e: logger.error(f"[Slot] 提取ParamsNode失败: {e!s}\n{traceback.format_exc()}") return None diff --git a/apps/services/parameter.py b/apps/services/parameter.py index ae375e97..259c4e45 100644 --- a/apps/services/parameter.py +++ b/apps/services/parameter.py @@ -57,8 +57,10 @@ class ParameterManager: q = [step_id] in_edges = {} step_id_to_node_id = {} + step_id_to_node_name = {} for step in flow.nodes: step_id_to_node_id[step.step_id] = step.node_id + step_id_to_node_name[step.step_id] = step.name for edge in flow.edges: if edge.target_node not in in_edges: in_edges[edge.target_node] = [] @@ -71,15 +73,16 @@ class ParameterManager: if pre_node_id not in q: q.append(pre_node_id) pre_step_params = [] - for step_id in q: + for i in range(1, len(q)): + step_id = q[i] node_id = step_id_to_node_id.get(step_id) params_schema, output_schema = await NodeManager.get_node_params(node_id) slot = Slot(output_schema) - params_node = slot.get_params_node_from_schema(root='/output') + params_node = slot.get_params_node_from_schema(root='output') pre_step_params.append( StepParams( - stepId=node_id, - name=params_schema.get("name", ""), + stepId=step_id, + name=step_id_to_node_name.get(step_id), paramsNode=params_node ) ) -- Gitee From 74e54c0851b960bf6cd686e83637eaea5f96f82a Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 11:58:41 +0800 Subject: [PATCH 24/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B5=81=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/services/flow_validate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/services/flow_validate.py b/apps/services/flow_validate.py index d799c5dc..0b3a3e6e 100644 --- a/apps/services/flow_validate.py +++ b/apps/services/flow_validate.py @@ -141,7 +141,6 @@ class FlowService: branches = {} in_deg = {} out_deg = {} - for e in edges: if e.edge_id in ids: err = f"[FlowService] 边{e.edge_id}的id重复" -- Gitee From 62b13cba494a4412efbab1226bdd457106231f5b Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 15:05:18 +0800 Subject: [PATCH 25/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dchoice=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E4=BF=9D=E5=AD=98=E5=8F=82=E6=95=B0=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/flow.py | 6 ++++++ apps/services/flow.py | 1 + apps/services/flow_validate.py | 8 ++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/routers/flow.py b/apps/routers/flow.py index fc38c1bf..68c0c9f3 100644 --- a/apps/routers/flow.py +++ b/apps/routers/flow.py @@ -2,6 +2,7 @@ """FastAPI Flow拓扑结构展示API""" from typing import Annotated +import logging from fastapi import APIRouter, Body, Depends, Query, status from fastapi.responses import JSONResponse @@ -25,6 +26,8 @@ from apps.services.application import AppManager from apps.services.flow import FlowManager from apps.services.flow_validate import FlowService +logger = logging.getLogger(__name__) + router = APIRouter( prefix="/api/flow", tags=["flow"], @@ -130,8 +133,11 @@ async def put_flow( ).model_dump(exclude_none=True, by_alias=True), ) put_body.flow = await FlowService.remove_excess_structure_from_flow(put_body.flow) + logger.error(f'{put_body.flow}') await FlowService.validate_flow_illegal(put_body.flow) + logger.error(f'{put_body.flow}') put_body.flow.connectivity = await FlowService.validate_flow_connectivity(put_body.flow) + logger.error(f'{put_body.flow}') result = await FlowManager.put_flow_by_app_and_flow_id(app_id, flow_id, put_body.flow) if result is None: return JSONResponse( diff --git a/apps/services/flow.py b/apps/services/flow.py index c9fd86fd..097908cd 100644 --- a/apps/services/flow.py +++ b/apps/services/flow.py @@ -413,6 +413,7 @@ class FlowManager: flow_config.debug = await FlowManager.is_flow_config_equal(old_flow_config, flow_config) else: flow_config.debug = False + logger.error(f'{flow_config}') await flow_loader.save(app_id, flow_id, flow_config) except Exception: logger.exception("[FlowManager] 存储/更新流失败") diff --git a/apps/services/flow_validate.py b/apps/services/flow_validate.py index 0b3a3e6e..66a2d087 100644 --- a/apps/services/flow_validate.py +++ b/apps/services/flow_validate.py @@ -50,14 +50,14 @@ class FlowService: logger.error(f"[FlowService] 获取步骤的call_id失败{node.call_id}由于:{e}") node_branch_map[node.step_id] = set() if node.call_id == NodeType.CHOICE.value: - node.parameters = node.parameters["input_parameters"] - if "choices" not in node.parameters: + input_parameters = node.parameters["input_parameters"] + if "choices" not in input_parameters: logger.error(f"[FlowService] 节点{node.name}的分支字段缺失") raise FlowBranchValidationError(f"[FlowService] 节点{node.name}的分支字段缺失") - if not node.parameters["choices"]: + if not input_parameters["choices"]: logger.error(f"[FlowService] 节点{node.name}的分支字段为空") raise FlowBranchValidationError(f"[FlowService] 节点{node.name}的分支字段为空") - for choice in node.parameters["choices"]: + for choice in input_parameters["choices"]: if "branch_id" not in choice: err = f"[FlowService] 节点{node.name}的分支choice缺少branch_id字段" logger.error(err) -- Gitee From ddbb1f864d841d8edf8af0ccfe29255cb458dc63 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 16:44:28 +0800 Subject: [PATCH 26/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGET=20/api/parameters?= =?UTF-8?q?=E6=97=B6=E7=94=B1=E7=A9=BA=E8=8A=82=E7=82=B9=E5=BC=95=E8=B5=B7?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/call/facts/facts.py | 9 +-- apps/scheduler/executor/flow.py | 16 +++- apps/scheduler/mcp/host.py | 2 +- apps/scheduler/mcp_agent/host.py | 4 +- apps/scheduler/mcp_agent/plan.py | 119 +++++++++++++++++++---------- apps/scheduler/mcp_agent/prompt.py | 41 ++++++++-- apps/scheduler/slot/slot.py | 6 +- apps/schemas/enum_var.py | 1 + apps/schemas/flow_topology.py | 5 +- apps/schemas/mcp.py | 7 ++ apps/services/flow.py | 5 +- apps/services/flow_validate.py | 7 +- apps/services/node.py | 5 +- 13 files changed, 156 insertions(+), 71 deletions(-) diff --git a/apps/scheduler/call/facts/facts.py b/apps/scheduler/call/facts/facts.py index f8aebcd7..2b9df0c6 100644 --- a/apps/scheduler/call/facts/facts.py +++ b/apps/scheduler/call/facts/facts.py @@ -30,13 +30,11 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): answer: str = Field(description="用户输入") - @classmethod def info(cls) -> CallInfo: """返回Call的名称和描述""" return CallInfo(name="提取事实", description="从对话上下文和文档片段中提取事实。") - @classmethod async def instance(cls, executor: "StepExecutor", node: NodePool | None, **kwargs: Any) -> Self: """初始化工具""" @@ -51,7 +49,6 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): await obj._set_input(executor) return obj - async def _init(self, call_vars: CallVars) -> FactsInput: """初始化工具""" # 组装必要变量 @@ -65,7 +62,6 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): message=message, ) - async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """执行工具""" data = FactsInput(**input_data) @@ -83,7 +79,7 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): facts_obj: FactsGen = await self._json([ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": facts_prompt}, - ], FactsGen) # type: ignore[arg-type] + ], FactsGen) # type: ignore[arg-type] # 更新用户画像 domain_tpl = env.from_string(DOMAIN_PROMPT) @@ -91,7 +87,7 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): domain_list: DomainGen = await self._json([ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": domain_prompt}, - ], DomainGen) # type: ignore[arg-type] + ], DomainGen) # type: ignore[arg-type] for domain in domain_list.keywords: await UserDomainManager.update_user_domain_by_user_sub_and_domain_name(data.user_sub, domain) @@ -104,7 +100,6 @@ class FactsCall(CoreCall, input_model=FactsInput, output_model=FactsOutput): ).model_dump(by_alias=True, exclude_none=True), ) - async def exec(self, executor: "StepExecutor", input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """执行工具""" async for chunk in self._exec(input_data): diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index fbae705d..382ef929 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -172,6 +172,7 @@ class FlowExecutor(BaseExecutor): self.step_queue.append(first_step) self.task.state.flow_status = FlowStatus.RUNNING # type: ignore[arg-type] # 运行Flow(未达终点) + is_error = False while not self._reached_end: # 如果当前步骤出错,执行错误处理步骤 if self.task.state.step_status == StepStatus.ERROR: # type: ignore[arg-type] @@ -194,7 +195,7 @@ class FlowExecutor(BaseExecutor): enable_filling=False, to_user=False, )) - self.task.state.flow_status = FlowStatus.ERROR # type: ignore[arg-type] + is_error = True # 错误处理后结束 self._reached_end = True @@ -209,6 +210,12 @@ class FlowExecutor(BaseExecutor): for step in next_step: self.step_queue.append(step) + # 更新Task状态 + if is_error: + self.task.state.flow_status = FlowStatus.ERROR # type: ignore[arg-type] + else: + self.task.state.flow_status = FlowStatus.SUCCESS # type: ignore[arg-type] + # 尾插运行结束后的系统步骤 for step in FIXED_STEPS_AFTER_END: self.step_queue.append(StepQueueItem( @@ -220,6 +227,7 @@ class FlowExecutor(BaseExecutor): # FlowStop需要返回总时间,需要倒推最初的开始时间(当前时间减去当前已用总时间) self.task.tokens.time = round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.full_time # 推送Flow停止消息 - await self.push_message(EventType.FLOW_STOP.value) - # 更新Task状态 - self.task.state.flow_status = FlowStatus.SUCCESS # type: ignore[arg-type] + if is_error: + await self.push_message(EventType.FLOW_FAILED.value) + else: + await self.push_message(EventType.FLOW_SUCCESS.value) diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py index acdd4871..aa196112 100644 --- a/apps/scheduler/mcp/host.py +++ b/apps/scheduler/mcp/host.py @@ -102,7 +102,7 @@ class MCPHost: task_id=self._task_id, flow_id=self._runtime_id, flow_name=self._runtime_name, - flow_status=StepStatus.SUCCESS, + flow_status=StepStatus.RUNNING, step_id=tool.name, step_name=tool.name, # description是规划的实际内容 diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index acdd4871..a8ebec7b 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -123,7 +123,7 @@ class MCPHost: return output_data - async def _fill_params(self, tool: MCPTool, query: str) -> dict[str, Any]: + async def _fill_params(self, schema: dict[str, Any], query: str) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" @@ -139,7 +139,7 @@ class MCPHost: {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": await self.assemble_memory()}, ], - tool.input_schema, + schema, ) return await json_generator.generate() diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 47e803f6..771115d2 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -1,19 +1,23 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP 用户目标拆解与规划""" - +from typing import Any from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment -from apps.llm.function import JsonGenerator from apps.llm.reasoning import ReasoningLLM -from apps.scheduler.mcp.prompt import CREATE_PLAN, FINAL_ANSWER -from apps.schemas.mcp import MCPPlan, MCPTool +from apps.llm.function import JsonGenerator +from apps.scheduler.mcp_agent.prompt import EVALUATE_GAOL, CREATE_PLAN, RECREATE_PLAN, FINAL_ANSWER +from apps.schemas.mcp import ( + GoalEvaluationResult, + MCPPlan, + MCPTool +) class MCPPlanner: """MCP 用户目标拆解与规划""" - def __init__(self, user_goal: str) -> None: + def __init__(self, user_goal: str, resoning_llm: ReasoningLLM = None) -> None: """初始化MCP规划器""" self.user_goal = user_goal self._env = SandboxedEnvironment( @@ -24,36 +28,17 @@ class MCPPlanner: ) self.input_tokens = 0 self.output_tokens = 0 + self.resoning_llm = resoning_llm or ReasoningLLM() - async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: - """规划下一步的执行流程,并输出""" - # 获取推理结果 - result = await self._get_reasoning_plan(tool_list, max_steps) - - # 解析为结构化数据 - return await self._parse_plan_result(result, max_steps) - - async def _get_reasoning_plan( - self, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan = MCPPlan(), - tool_list: list[MCPTool] = [], - max_steps: int = 10) -> str: - """获取推理大模型的结果""" - # 格式化Prompt - template = self._env.from_string(CREATE_PLAN) - prompt = template.render( - goal=self.user_goal, - tools=tool_list, - max_num=max_steps, - ) - + async def get_resoning_result(self, prompt: str) -> str: + """获取推理结果""" # 调用推理大模型 message = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt}, ] - reasoning_llm = ReasoningLLM() result = "" - async for chunk in reasoning_llm.call( + async for chunk in self.resoning_llm.call( message, streaming=False, temperature=0.07, @@ -62,18 +47,12 @@ class MCPPlanner: result += chunk # 保存token用量 - self.input_tokens = reasoning_llm.input_tokens - self.output_tokens = reasoning_llm.output_tokens - + self.input_tokens = self.resoning_llm.input_tokens + self.output_tokens = self.resoning_llm.output_tokens return result - async def _parse_plan_result(self, result: str, max_steps: int) -> MCPPlan: - """将推理结果解析为结构化数据""" - # 格式化Prompt - schema = MCPPlan.model_json_schema() - schema["properties"]["plans"]["maxItems"] = max_steps - - # 使用Function模型解析结果 + async def _parse_result(self, result: str, schema: dict[str, Any]) -> str: + """解析推理结果""" json_generator = JsonGenerator( result, [ @@ -82,7 +61,69 @@ class MCPPlanner: ], schema, ) - plan = await json_generator.generate() + json_result = await json_generator.generate() + return json_result + + async def evaluate_goal(self, tool_list: list[MCPTool]) -> str: + pass + + async def _get_reasoning_evaluation(self, tool_list: list[MCPTool]) -> str: + """获取推理大模型的评估结果""" + template = self._env.from_string(EVALUATE_GAOL) + prompt = template.render( + goal=self.user_goal, + tools=tool_list, + ) + result = await self.get_resoning_result(prompt) + return result + + async def _parse_evaluation_result(self, result: str) -> str: + """将推理结果解析为结构化数据""" + schema = GoalEvaluationResult.model_json_schema() + evaluation = await self._parse_result(result, schema) + # 使用GoalEvaluationResult模型解析结果 + return GoalEvaluationResult.model_validate(evaluation) + + async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: + """规划下一步的执行流程,并输出""" + # 获取推理结果 + result = await self._get_reasoning_plan(tool_list, max_steps) + + # 解析为结构化数据 + return await self._parse_plan_result(result, max_steps) + + async def _get_reasoning_plan( + self, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan = MCPPlan(), + tool_list: list[MCPTool] = [], + max_steps: int = 10) -> str: + """获取推理大模型的结果""" + # 格式化Prompt + if is_replan: + template = self._env.from_string(RECREATE_PLAN) + prompt = template.render( + current_plan=current_plan, + error_message=error_message, + goal=self.user_goal, + tools=tool_list, + max_num=max_steps, + ) + else: + template = self._env.from_string(CREATE_PLAN) + prompt = template.render( + goal=self.user_goal, + tools=tool_list, + max_num=max_steps, + ) + result = await self.get_resoning_result(prompt) + return result + + async def _parse_plan_result(self, result: str, max_steps: int) -> MCPPlan: + """将推理结果解析为结构化数据""" + # 格式化Prompt + schema = MCPPlan.model_json_schema() + schema["properties"]["plans"]["maxItems"] = max_steps + plan = await self._parse_result(result, schema) + # 使用Function模型解析结果 return MCPPlan.model_validate(plan) async def generate_answer(self, plan: MCPPlan, memory: str) -> str: diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 579a5081..7cef9e11 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -103,12 +103,45 @@ EVALUATE_GAOL = dedent(r""" {{ goal }} # 工具集合 - {{ tools }} + + {% for tool in tools %} + - {{ tool.id }}{{tool.name}};{{ tool.description }} + {% endfor %} + # 附加信息 {{ additional_info }} """) +GENERATE_FLOW_NAME = dedent(r""" + 你是一个智能助手,你的任务是根据用户的目标,生成一个合适的流程名称。 + + # 生成流程名称时的注意事项: + 1. 流程名称应该简洁明了,能够准确表达达成用户目标的过程。 + 2. 流程名称应该包含关键的操作或步骤,例如“扫描”、“分析”、“调优”等。 + 3. 流程名称应该避免使用过于复杂或专业的术语,以便用户能够理解。 + 4. 流程名称应该尽量简短,小于20个字或者单词。 + + - 必须按照如下格式生成流程名称,不要输出任何额外数据: + ```json + { + "flow_name": "生成的流程名称" + } + ``` + # 样例 + ## 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈,并调优 + ## 输出 + ```json + { + "flow_name": "MySQL性能分析与调优" + } + ``` + # 现在开始生成流程名称: + # 目标 + {{ goal }} + # 输出 + """) CREATE_PLAN = dedent(r""" 你是一个计划生成器。 请分析用户的目标,并生成一个计划。你后续将根据这个计划,一步一步地完成用户的目标。 @@ -153,8 +186,6 @@ CREATE_PLAN = dedent(r""" {% for tool in tools %} - {{ tool.id }}{{tool.name}};{{ tool.description }} {% endfor %} - - Final结束步骤,当执行到这一步时,\ -表示计划执行结束,所得到的结果将作为最终结果。 # 样例 @@ -352,8 +383,6 @@ RECREATE_PLAN = dedent(r""" {% for tool in tools %} - {{ tool.id }}{{tool.name}};{{ tool.description }} {% endfor %} - - Final结束步骤,当执行到这一步时,\ -表示计划执行结束,所得到的结果将作为最终结果。 # 当前计划 @@ -415,7 +444,7 @@ RISK_EVALUATE = dedent(r""" # 获取缺失的参数的json结构体 GET_MISSING_PARAMS = dedent(r""" 你是一个工具参数获取器。 - 你的任务是根据当前工具的名称、描述和入参和入参的schema以及运行报错,获取当前工具缺失的参数并输出提示。 + 你的任务是根据当前工具的名称、描述和入参和入参的schema以及运行报错,将当前缺失的参数设置为null,并输出一个JSON格式的字符串。 ```json { "host": "请补充主机地址", diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index c1b27abf..045c4862 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -248,7 +248,9 @@ class Slot: if param_type == "object" and "properties" in schema_node: for key, value in schema_node["properties"].items(): - sub_params.append(_extract_params_node(value, name=key, path=f"{path}/{key}")) + sub_param = _extract_params_node(value, name=key, path=f"{path}/{key}") + if sub_param: + sub_params.append(sub_param) else: # 对于非对象类型,直接返回空子参数 sub_params = None @@ -257,7 +259,7 @@ class Slot: paramType=param_type, subParams=sub_params) try: - return _extract_params_node(self._schema, name=root, path="/"+root) + return _extract_params_node(self._schema, name=root, path="/" + root) except Exception as e: logger.error(f"[Slot] 提取ParamsNode失败: {e!s}\n{traceback.format_exc()}") return None diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index d50eeaf7..8458e103 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -57,6 +57,7 @@ class EventType(str, Enum): STEP_OUTPUT = "step.output" FLOW_STOP = "flow.stop" FLOW_FAILED = "flow.failed" + FLOW_SUCCESS = "flow.success" FLOW_CANCELLED = "flow.cancelled" DONE = "done" diff --git a/apps/schemas/flow_topology.py b/apps/schemas/flow_topology.py index d0ab666a..fecf2160 100644 --- a/apps/schemas/flow_topology.py +++ b/apps/schemas/flow_topology.py @@ -5,6 +5,7 @@ from typing import Any from pydantic import BaseModel, Field +from apps.schemas.enum_var import SpecialCallType from apps.schemas.enum_var import EdgeType @@ -51,7 +52,7 @@ class NodeItem(BaseModel): service_id: str = Field(alias="serviceId", default="") node_id: str = Field(alias="nodeId", default="") name: str = Field(default="") - call_id: str = Field(alias="callId", default="Empty") + call_id: str = Field(alias="callId", default=SpecialCallType.EMPTY.value) description: str = Field(default="") enable: bool = Field(default=True) parameters: dict[str, Any] = Field(default={}) @@ -81,6 +82,6 @@ class FlowItem(BaseModel): nodes: list[NodeItem] = Field(default=[]) edges: list[EdgeItem] = Field(default=[]) created_at: float | None = Field(alias="createdAt", default=0) - connectivity: bool = Field(default=False,description="图的开始节点和结束节点是否联通,并且除结束节点都有出边") + connectivity: bool = Field(default=False, description="图的开始节点和结束节点是否联通,并且除结束节点都有出边") focus_point: PositionItem = Field(alias="focusPoint", default=PositionItem()) debug: bool = Field(default=False) diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 693caa09..2ee50061 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -104,6 +104,13 @@ class MCPToolVector(LanceModel): embedding: Vector(dim=1024) = Field(description="MCP工具描述的向量信息") # type: ignore[call-arg] +class GoalEvaluationResult(BaseModel): + """MCP 目标评估结果""" + + can_complete: bool = Field(description="是否可以完成目标") + reason: str = Field(description="评估原因") + + class MCPSelectResult(BaseModel): """MCP选择结果""" diff --git a/apps/services/flow.py b/apps/services/flow.py index 097908cd..4d682e5a 100644 --- a/apps/services/flow.py +++ b/apps/services/flow.py @@ -257,10 +257,7 @@ class FlowManager: ) for node_id, node_config in flow_config.steps.items(): input_parameters = node_config.params - if node_config.node not in ("Empty"): - _, output_parameters = await NodeManager.get_node_params(node_config.node) - else: - output_parameters = {} + _, output_parameters = await NodeManager.get_node_params(node_config.node) parameters = { "input_parameters": input_parameters, "output_parameters": Slot(output_parameters).extract_type_desc_from_schema(), diff --git a/apps/services/flow_validate.py b/apps/services/flow_validate.py index 66a2d087..16c23053 100644 --- a/apps/services/flow_validate.py +++ b/apps/services/flow_validate.py @@ -4,6 +4,7 @@ import collections import logging +from apps.schemas.enum_var import SpecialCallType from apps.exceptions import FlowBranchValidationError, FlowEdgeValidationError, FlowNodeValidationError from apps.schemas.enum_var import NodeType from apps.schemas.flow_topology import EdgeItem, FlowItem, NodeItem @@ -38,14 +39,14 @@ class FlowService: for node in flow_item.nodes: from apps.scheduler.pool.pool import Pool from pydantic import BaseModel - if node.node_id != 'start' and node.node_id != 'end' and node.node_id != 'Empty': + if node.node_id != 'start' and node.node_id != 'end' and node.node_id != SpecialCallType.EMPTY.value: try: call_class: type[BaseModel] = await Pool().get_call(node.call_id) if not call_class: - node.node_id = 'Empty' + node.node_id = SpecialCallType.EMPTY.value node.description = '【对应的api工具被删除!节点不可用!请联系相关人员!】\n\n'+node.description except Exception as e: - node.node_id = 'Empty' + node.node_id = SpecialCallType.EMPTY.value node.description = '【对应的api工具被删除!节点不可用!请联系相关人员!】\n\n'+node.description logger.error(f"[FlowService] 获取步骤的call_id失败{node.call_id}由于:{e}") node_branch_map[node.step_id] = set() diff --git a/apps/services/node.py b/apps/services/node.py index bf48e71f..3fb311bf 100644 --- a/apps/services/node.py +++ b/apps/services/node.py @@ -4,6 +4,7 @@ import logging from typing import TYPE_CHECKING, Any +from apps.schemas.enum_var import SpecialCallType from apps.common.mongo import MongoDB from apps.schemas.node import APINode from apps.schemas.pool import NodePool @@ -77,7 +78,9 @@ class NodeManager: async def get_node_params(node_id: str) -> tuple[dict[str, Any], dict[str, Any]]: """获取Node数据""" from apps.scheduler.pool.pool import Pool - + if node_id == SpecialCallType.EMPTY.value: + # 如果是空节点,返回空Schema + return {}, {} # 查找Node信息 logger.info("[NodeManager] 获取节点 %s", node_id) node_collection = MongoDB().get_collection("node") -- Gitee From e133af5d656ec84f1e09c40d9ce36ce3ccd9b07b Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 17:07:22 +0800 Subject: [PATCH 27/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=90=E5=8F=96node?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/slot/slot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 045c4862..58c90bac 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -246,7 +246,7 @@ class Slot: return None sub_params = [] - if param_type == "object" and "properties" in schema_node: + if param_type == Type.DICT and "properties" in schema_node: for key, value in schema_node["properties"].items(): sub_param = _extract_params_node(value, name=key, path=f"{path}/{key}") if sub_param: -- Gitee From b9efb73808405a6f6516a00e34355c00de03979b Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 17:12:57 +0800 Subject: [PATCH 28/78] =?UTF-8?q?choice=E7=9A=84=E5=88=86=E6=94=AF?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/call/choice/schema.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/scheduler/call/choice/schema.py b/apps/scheduler/call/choice/schema.py index b95b1668..d97a0c8d 100644 --- a/apps/scheduler/call/choice/schema.py +++ b/apps/scheduler/call/choice/schema.py @@ -29,6 +29,7 @@ class Value(DataBase): step_id: str | None = Field(description="步骤id", default=None) type: Type | None = Field(description="值的类型", default=None) + name: str | None = Field(description="值的名称", default=None) value: str | float | int | bool | list | dict | None = Field(description="值", default=None) -- Gitee From 3948571b23607a587ddeb56c212f8ff831bbb08a Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 17:32:04 +0800 Subject: [PATCH 29/78] =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E7=94=A8=E6=88=B7=E5=90=8D=E7=A7=B0=E7=AD=89=E4=BA=8E?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/dependency/user.py | 9 ++++++--- apps/main.py | 8 +++++++- apps/schemas/config.py | 1 - 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/dependency/user.py b/apps/dependency/user.py index 87cbd290..8f5848a3 100644 --- a/apps/dependency/user.py +++ b/apps/dependency/user.py @@ -1,6 +1,6 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """用户鉴权""" - +import os import logging from fastapi import Depends @@ -75,8 +75,11 @@ async def get_user(request: HTTPConnection) -> str: :return: 用户sub """ if Config().get_config().no_auth.enable: - # 如果启用了无认证访问,直接返回调试用户 - return Config().get_config().no_auth.user_sub + # 如果启用了无认证访问,直接返回当前操作系统用户的名称 + username = os.environ.get('USERNAME') # 适用于 Windows 系统 + if not username: + username = os.environ.get('USER') # 适用于 Linux 和 macOS 系统 + return username or "admin" session_id = await _get_session_id_from_request(request) if not session_id: raise HTTPException( diff --git a/apps/main.py b/apps/main.py index 17d4abb4..1646f671 100644 --- a/apps/main.py +++ b/apps/main.py @@ -89,10 +89,16 @@ async def add_no_auth_user() -> None: """ from apps.common.mongo import MongoDB from apps.schemas.collection import User + import os mongo = MongoDB() user_collection = mongo.get_collection("user") + username = os.environ.get('USERNAME') # 适用于 Windows 系统 + if not username: + username = os.environ.get('USER') # 适用于 Linux 和 macOS 系统 + if not username: + username = "admin" await user_collection.insert_one(User( - _id=Config().get_config().no_auth.user_sub, + _id=username, is_admin=True, ).model_dump(by_alias=True)) diff --git a/apps/schemas/config.py b/apps/schemas/config.py index e91f5f75..675a9ba7 100644 --- a/apps/schemas/config.py +++ b/apps/schemas/config.py @@ -10,7 +10,6 @@ class NoauthConfig(BaseModel): """无认证配置""" enable: bool = Field(description="是否启用无认证访问", default=False) - user_sub: str = Field(description="调试用户的sub", default="admin") class DeployConfig(BaseModel): -- Gitee From ba0b20901eea32adf4363f7c7a6de8d31aa0b754 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 21:36:36 +0800 Subject: [PATCH 30/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=87=BA=E5=8F=82?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E3=80=81=E5=87=BA=E9=A4=90=E5=85=B3=E8=81=94?= =?UTF-8?q?=E5=92=8C=E9=BB=98=E8=AE=A4=E5=8F=82=E6=95=B0=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/call/core.py | 4 +- apps/scheduler/call/slot/slot.py | 4 - apps/scheduler/mcp_agent/plan.py | 21 +++++- apps/scheduler/mcp_agent/prompt.py | 2 +- apps/scheduler/slot/slot.py | 115 ++++++++++++++++++++++------- apps/services/parameter.py | 2 +- 6 files changed, 109 insertions(+), 39 deletions(-) diff --git a/apps/scheduler/call/core.py b/apps/scheduler/call/core.py index af28c6a3..5bed8030 100644 --- a/apps/scheduler/call/core.py +++ b/apps/scheduler/call/core.py @@ -127,7 +127,7 @@ class CoreCall(BaseModel): :return: 变量 """ split_path = path.split("/") - if len(split_path) < 2: + if len(split_path) < 1: err = f"[CoreCall] 路径格式错误: {path}" logger.error(err) return None @@ -136,7 +136,7 @@ class CoreCall(BaseModel): logger.error(err) return None data = history[split_path[0]].output_data - for key in split_path[2:]: + for key in split_path[1:]: if key not in data: err = f"[CoreCall] 输出Key {key} 不存在" logger.error(err) diff --git a/apps/scheduler/call/slot/slot.py b/apps/scheduler/call/slot/slot.py index 4f8e1010..d24e1661 100644 --- a/apps/scheduler/call/slot/slot.py +++ b/apps/scheduler/call/slot/slot.py @@ -32,13 +32,11 @@ class Slot(CoreCall, input_model=SlotInput, output_model=SlotOutput): facts: list[str] = Field(description="事实信息", default=[]) step_num: int = Field(description="历史步骤数", default=1) - @classmethod def info(cls) -> CallInfo: """返回Call的名称和描述""" return CallInfo(name="参数自动填充", description="根据步骤历史,自动填充参数") - async def _llm_slot_fill(self, remaining_schema: dict[str, Any]) -> tuple[str, dict[str, Any]]: """使用大模型填充参数;若大模型解析度足够,则直接返回结果""" env = SandboxedEnvironment( @@ -106,7 +104,6 @@ class Slot(CoreCall, input_model=SlotInput, output_model=SlotOutput): await obj._set_input(executor) return obj - async def _init(self, call_vars: CallVars) -> SlotInput: """初始化""" self._flow_history = [] @@ -126,7 +123,6 @@ class Slot(CoreCall, input_model=SlotInput, output_model=SlotOutput): remaining_schema=remaining_schema, ) - async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: """执行参数填充""" data = SlotInput(**input_data) diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 771115d2..40bec6ef 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -6,7 +6,12 @@ from jinja2.sandbox import SandboxedEnvironment from apps.llm.reasoning import ReasoningLLM from apps.llm.function import JsonGenerator -from apps.scheduler.mcp_agent.prompt import EVALUATE_GAOL, CREATE_PLAN, RECREATE_PLAN, FINAL_ANSWER +from apps.scheduler.mcp_agent.prompt import ( + EVALUATE_GOAL, + CREATE_PLAN, + RECREATE_PLAN, + FINAL_ANSWER +) from apps.schemas.mcp import ( GoalEvaluationResult, MCPPlan, @@ -64,8 +69,16 @@ class MCPPlanner: json_result = await json_generator.generate() return json_result - async def evaluate_goal(self, tool_list: list[MCPTool]) -> str: - pass + async def evaluate_goal(self, tool_list: list[MCPTool]) -> GoalEvaluationResult: + """评估用户目标的可行性""" + # 获取推理结果 + result = await self._get_reasoning_evaluation(tool_list) + + # 解析为结构化数据 + evaluation = await self._parse_evaluation_result(result) + + # 返回评估结果 + return evaluation async def _get_reasoning_evaluation(self, tool_list: list[MCPTool]) -> str: """获取推理大模型的评估结果""" @@ -77,7 +90,7 @@ class MCPPlanner: result = await self.get_resoning_result(prompt) return result - async def _parse_evaluation_result(self, result: str) -> str: + async def _parse_evaluation_result(self, result: str) -> GoalEvaluationResult: """将推理结果解析为结构化数据""" schema = GoalEvaluationResult.model_json_schema() evaluation = await self._parse_result(result, schema) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 7cef9e11..8933f69a 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -62,7 +62,7 @@ MCP_SELECT = dedent(r""" ### 请一步一步思考: """) -EVALUATE_GAOL = dedent(r""" +EVALUATE_GOAL = dedent(r""" 你是一个计划评估器。 请根据用户的目标和当前的工具集合以及一些附加信息,判断基于当前的工具集合,是否能够完成用户的目标。 如果能够完成,请返回`true`,否则返回`false`。 diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 58c90bac..f5e5354f 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -128,7 +128,7 @@ class Slot: # Schema标准 return [_process_json_value(item, spec_data["items"]) for item in json_value] if spec_data["type"] == "object" and isinstance(json_value, dict): - # 若Schema不标准,则不进行处理 + # 若Schema不标准,则不进行处理F if "properties" not in spec_data: return json_value # Schema标准 @@ -156,35 +156,60 @@ class Slot: @staticmethod def _generate_example(schema_node: dict) -> Any: # noqa: PLR0911 """根据schema生成示例值""" + if "anyOf" in schema_node or "oneOf" in schema_node: + # 如果有anyOf,随机返回一个示例 + for item in schema_node["anyOf"] if "anyOf" in schema_node else schema_node["oneOf"]: + example = Slot._generate_example(item) + if example is not None: + return example + + if "allOf" in schema_node: + # 如果有allOf,返回所有示例的合并 + example = None + for item in schema_node["allOf"]: + if example is None: + example = Slot._generate_example(item) + else: + other_example = Slot._generate_example(item) + if isinstance(example, dict) and isinstance(other_example, dict): + example.update(other_example) + else: + example = None + break + return example + if "default" in schema_node: return schema_node["default"] if "type" not in schema_node: return None - + type_value = schema_node["type"] + if isinstance(type_value, list): + # 如果是多类型,随机返回一个示例 + if len(type_value) > 1: + type_value = type_value[0] # 处理类型为 object 的节点 - if schema_node["type"] == "object": + if type_value == "object": data = {} properties = schema_node.get("properties", {}) for name, schema in properties.items(): data[name] = Slot._generate_example(schema) return data - # 处理类型为 array 的节点 - if schema_node["type"] == "array": + elif type_value == "array": items_schema = schema_node.get("items", {}) return [Slot._generate_example(items_schema)] # 处理类型为 string 的节点 - if schema_node["type"] == "string": + elif type_value == "string": return "" # 处理类型为 number 或 integer 的节点 - if schema_node["type"] in ["number", "integer"]: + elif type_value in ["number", "integer"]: return 0 # 处理类型为 boolean 的节点 - if schema_node["type"] == "boolean": + elif type_value == "boolean": return False # 处理其他类型或未定义类型 @@ -198,29 +223,63 @@ class Slot: """从JSON Schema中提取类型描述""" def _extract_type_desc(schema_node: dict[str, Any]) -> dict[str, Any]: - if "type" not in schema_node and "anyOf" not in schema_node: - return {} - data = {"type": schema_node.get("type", ""), "description": schema_node.get("description", "")} - if "anyOf" in schema_node: - data["type"] = "anyOf" - # 处理类型为 object 的节点 - if "anyOf" in schema_node: - data["items"] = {} - type_index = 0 - for type_index, sub_schema in enumerate(schema_node["anyOf"]): - sub_result = _extract_type_desc(sub_schema) - if sub_result: - data["items"]["type_"+str(type_index)] = sub_result - if schema_node.get("type", "") == "object": + # 处理组合关键字 + special_keys = ["anyOf", "allOf", "oneOf"] + for key in special_keys: + if key in schema_node: + data = { + "type": key, + "description": schema_node.get("description", ""), + "items": {}, + } + type_index = 0 + for item in schema_node[key]: + if isinstance(item, dict): + data["items"][f"item_{type_index}"] = _extract_type_desc(item) + else: + data["items"][f"item_{type_index}"] = {"type": item, "description": ""} + type_index += 1 + return data + # 处理基本类型 + type_val = schema_node.get("type", "") + description = schema_node.get("description", "") + + # 处理多类型数组 + if isinstance(type_val, list): + if len(type_val) > 1: + data = {"type": "union", "description": description, "items": {}} + type_index = 0 + for t in type_val: + if t == "object": + tmp_dict = {} + for key, val in schema_node.get("properties", {}).items(): + tmp_dict[key] = _extract_type_desc(val) + data["items"][f"item_{type_index}"] = tmp_dict + elif t == "array": + items_schema = schema_node.get("items", {}) + data["items"][f"item_{type_index}"] = _extract_type_desc(items_schema) + else: + data["items"][f"item_{type_index}"] = {"type": t, "description": description} + type_index += 1 + return data + elif len(type_val) == 1: + type_val = type_val[0] + else: + type_val = "" + + data = {"type": type_val, "description": description} + + # 递归处理对象和数组 + if type_val == "object": data["items"] = {} for key, val in schema_node.get("properties", {}).items(): data["items"][key] = _extract_type_desc(val) - - # 处理类型为 array 的节点 - if schema_node.get("type", "") == "array": + elif type_val == "array": items_schema = schema_node.get("items", {}) - data["items"] = _extract_type_desc(items_schema) + data["items"]["items"] = _extract_type_desc(items_schema) + return data + return _extract_type_desc(self._schema) def get_params_node_from_schema(self, root: str = "") -> ParamsNode: @@ -231,13 +290,15 @@ class Slot: return None param_type = schema_node["type"] + if isinstance(param_type, list): + return None # 不支持多类型 if param_type == "object": param_type = Type.DICT elif param_type == "array": param_type = Type.LIST elif param_type == "string": param_type = Type.STRING - elif param_type == "number": + elif param_type in ["number", "integer"]: param_type = Type.NUMBER elif param_type == "boolean": param_type = Type.BOOL diff --git a/apps/services/parameter.py b/apps/services/parameter.py index 259c4e45..c58fb39b 100644 --- a/apps/services/parameter.py +++ b/apps/services/parameter.py @@ -78,7 +78,7 @@ class ParameterManager: node_id = step_id_to_node_id.get(step_id) params_schema, output_schema = await NodeManager.get_node_params(node_id) slot = Slot(output_schema) - params_node = slot.get_params_node_from_schema(root='output') + params_node = slot.get_params_node_from_schema() pre_step_params.append( StepParams( stepId=step_id, -- Gitee From e36416e01b26c6082aa45755fa2be81feb40d3ae Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 29 Jul 2025 22:18:35 +0800 Subject: [PATCH 31/78] =?UTF-8?q?=E5=AE=8C=E5=96=84mcp=20agent=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/mcp_agent/plan.py | 69 +++++++++++++++++++++++++++++- apps/scheduler/mcp_agent/prompt.py | 42 ++++++++---------- apps/scheduler/mcp_agent/select.py | 7 +-- apps/scheduler/slot/slot.py | 52 ++++++++++++++++++++++ apps/schemas/mcp.py | 15 +++++++ 5 files changed, 155 insertions(+), 30 deletions(-) diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 40bec6ef..a7c1f132 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -8,15 +8,20 @@ from apps.llm.reasoning import ReasoningLLM from apps.llm.function import JsonGenerator from apps.scheduler.mcp_agent.prompt import ( EVALUATE_GOAL, + GENERATE_FLOW_NAME, CREATE_PLAN, RECREATE_PLAN, + RISK_EVALUATE, + GET_MISSING_PARAMS, FINAL_ANSWER ) from apps.schemas.mcp import ( GoalEvaluationResult, + ToolRisk, MCPPlan, MCPTool ) +from apps.scheduler.slot.slot import Slot class MCPPlanner: @@ -31,9 +36,9 @@ class MCPPlanner: trim_blocks=True, lstrip_blocks=True, ) + self.resoning_llm = resoning_llm or ReasoningLLM() self.input_tokens = 0 self.output_tokens = 0 - self.resoning_llm = resoning_llm or ReasoningLLM() async def get_resoning_result(self, prompt: str) -> str: """获取推理结果""" @@ -82,7 +87,7 @@ class MCPPlanner: async def _get_reasoning_evaluation(self, tool_list: list[MCPTool]) -> str: """获取推理大模型的评估结果""" - template = self._env.from_string(EVALUATE_GAOL) + template = self._env.from_string(EVALUATE_GOAL) prompt = template.render( goal=self.user_goal, tools=tool_list, @@ -97,6 +102,18 @@ class MCPPlanner: # 使用GoalEvaluationResult模型解析结果 return GoalEvaluationResult.model_validate(evaluation) + async def get_flow_name(self) -> str: + """获取当前流程的名称""" + result = await self._get_reasoning_flow_name() + return result + + async def _get_reasoning_flow_name(self) -> str: + """获取推理大模型的流程名称""" + template = self._env.from_string(GENERATE_FLOW_NAME) + prompt = template.render(goal=self.user_goal) + result = await self.get_resoning_result(prompt) + return result + async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: """规划下一步的执行流程,并输出""" # 获取推理结果 @@ -139,6 +156,54 @@ class MCPPlanner: # 使用Function模型解析结果 return MCPPlan.model_validate(plan) + async def get_tool_risk(self, tool: MCPTool, input_parm: dict[str, Any], additional_info: str = "") -> ToolRisk: + """获取MCP工具的风险评估结果""" + # 获取推理结果 + result = await self._get_reasoning_risk(tool, input_parm, additional_info) + + # 解析为结构化数据 + risk = await self._parse_risk_result(result) + + # 返回风险评估结果 + return risk + + async def _get_reasoning_risk(self, tool: MCPTool, input_param: dict[str, Any], additional_info: str) -> str: + """获取推理大模型的风险评估结果""" + template = self._env.from_string(RISK_EVALUATE) + prompt = template.render( + tool=tool, + input_param=input_param, + additional_info=additional_info, + ) + result = await self.get_resoning_result(prompt) + return result + + async def _parse_risk_result(self, result: str) -> ToolRisk: + """将推理结果解析为结构化数据""" + schema = ToolRisk.model_json_schema() + risk = await self._parse_result(result, schema) + # 使用ToolRisk模型解析结果 + return ToolRisk.model_validate(risk) + + async def get_missing_param( + self, tool: MCPTool, schema: dict[str, Any], + input_param: dict[str, Any], + error_message: str) -> list[str]: + """获取缺失的参数""" + slot = Slot(schema=schema) + schema_with_null = slot.add_null_to_basic_types() + template = self._env.from_string(GET_MISSING_PARAMS) + prompt = template.render( + tool=tool, + input_param=input_param, + schema=schema_with_null, + error_message=error_message, + ) + result = await self.get_resoning_result(prompt) + # 解析为结构化数据 + input_param_with_null = await self._parse_result(result, schema_with_null) + return input_param_with_null + async def generate_answer(self, plan: MCPPlan, memory: str) -> str: """生成最终回答""" template = self._env.from_string(FINAL_ANSWER) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 8933f69a..74dd06c0 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -121,22 +121,12 @@ GENERATE_FLOW_NAME = dedent(r""" 2. 流程名称应该包含关键的操作或步骤,例如“扫描”、“分析”、“调优”等。 3. 流程名称应该避免使用过于复杂或专业的术语,以便用户能够理解。 4. 流程名称应该尽量简短,小于20个字或者单词。 - - - 必须按照如下格式生成流程名称,不要输出任何额外数据: - ```json - { - "flow_name": "生成的流程名称" - } - ``` + 5. 只输出流程名称,不要输出其他内容。 # 样例 ## 目标 我需要扫描当前mysql数据库,分析性能瓶颈,并调优 ## 输出 - ```json - { - "flow_name": "MySQL性能分析与调优" - } - ``` + 扫描MySQL数据库并分析性能瓶颈,进行调优 # 现在开始生成流程名称: # 目标 {{ goal }} @@ -398,7 +388,7 @@ RISK_EVALUATE = dedent(r""" 你的任务是根据当前工具的名称、描述和入参以及附加信息,判断当前工具执行的风险并输出提示。 ```json { - "risk": "高/中/低", + "risk": "low/medium/high", "message": "提示信息" } ``` @@ -429,12 +419,13 @@ RISK_EVALUATE = dedent(r""" "message": "当前工具将连接到MySQL数据库并分析性能,可能会对数据库性能产生一定影响。请确保在非生产环境中执行此操作。" } ``` - # 工具名称 - {{ tool_name }} - # 工具描述 - {{ tool_description }} + # 工具 + + {{ tool.name }} + {{ tool.description }} + # 工具入参 - {{ tool_input }} + {{ input_param }} # 附加信息 {{ additional_info }} # 输出 @@ -511,14 +502,15 @@ GET_MISSING_PARAMS = dedent(r""" "password": null } ``` - # 工具名称 - {{ tool_name }} - # 工具描述 - {{ tool_description }} + # 工具 + + {{ tool.name }} + {{ tool.description }} + # 工具入参 - {{ tool_input }} - # 工具入参schema - {{ tool_input_schema }} + {{ input_param }} + # 工具入参schema(部分字段允许为null) + {{ input_schema }} # 运行报错 {{ error_message }} # 输出 diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 95f588e2..37d1e752 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -7,6 +7,7 @@ from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment from typing import AsyncGenerator +from apps.llm.reasoning import ReasoningLLM from apps.common.lance import LanceDB from apps.common.mongo import MongoDB from apps.llm.embedding import Embedding @@ -27,8 +28,9 @@ logger = logging.getLogger(__name__) class MCPSelector: """MCP选择器""" - def __init__(self) -> None: + def __init__(self, resoning_llm: ReasoningLLM = None) -> None: """初始化助手类""" + self.resoning_llm = resoning_llm or ReasoningLLM() self.input_tokens = 0 self.output_tokens = 0 @@ -102,12 +104,11 @@ class MCPSelector: async def _call_reasoning(self, prompt: str) -> AsyncGenerator[str, None]: """调用大模型进行推理""" logger.info("[MCPHelper] 调用推理大模型") - llm = ReasoningLLM() message = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt}, ] - async for chunk in llm.call(message): + async for chunk in self.resoning_llm.call(message): yield chunk async def _call_function_mcp(self, reasoning_result: str, mcp_ids: list[str]) -> MCPSelectResult: diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index f5e5354f..40aaffce 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """参数槽位管理""" +import copy import json import logging import traceback @@ -475,3 +476,54 @@ class Slot: return schema_template return {} + + def add_null_to_basic_types(self) -> dict[str, Any]: + """ + 递归地为 JSON Schema 中的基础类型(bool、number等)添加 null 选项 + """ + def add_null_to_basic_types(schema: dict[str, Any]) -> dict[str, Any]: + """ + 递归地为 JSON Schema 中的基础类型(bool、number等)添加 null 选项 + + 参数: + schema (dict): 原始 JSON Schema + + 返回: + dict: 修改后的 JSON Schema + """ + # 如果不是字典类型(schema),直接返回 + if not isinstance(schema, dict): + return schema + + # 处理当前节点的 type 字段 + if 'type' in schema: + # 处理单一类型字符串 + if isinstance(schema['type'], str): + if schema['type'] in ['boolean', 'number', 'string', 'integer']: + schema['type'] = [schema['type'], 'null'] + + # 处理类型数组 + elif isinstance(schema['type'], list): + for i, t in enumerate(schema['type']): + if isinstance(t, str) and t in ['boolean', 'number', 'string', 'integer']: + if 'null' not in schema['type']: + schema['type'].append('null') + break + + # 递归处理 properties 字段(对象类型) + if 'properties' in schema: + for prop, prop_schema in schema['properties'].items(): + schema['properties'][prop] = add_null_to_basic_types(prop_schema) + + # 递归处理 items 字段(数组类型) + if 'items' in schema: + schema['items'] = add_null_to_basic_types(schema['items']) + + # 递归处理 anyOf, oneOf, allOf 字段 + for keyword in ['anyOf', 'oneOf', 'allOf']: + if keyword in schema: + schema[keyword] = [add_null_to_basic_types(sub_schema) for sub_schema in schema[keyword]] + + return schema + schema_copy = copy.deepcopy(self._schema) + return add_null_to_basic_types(schema_copy) diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 2ee50061..959a273c 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -111,6 +111,21 @@ class GoalEvaluationResult(BaseModel): reason: str = Field(description="评估原因") +class Risk(Enum, str): + """MCP工具风险类型""" + + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + + +class ToolRisk(BaseModel): + """MCP工具风险评估结果""" + + risk: Risk = Field(description="风险类型", default=Risk.LOW) + reason: str = Field(description="风险原因", default="") + + class MCPSelectResult(BaseModel): """MCP选择结果""" -- Gitee From 734c8c0cc8b22e9eeebd4a772336ffc508bac123 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 09:32:22 +0800 Subject: [PATCH 32/78] fix bug --- apps/schemas/mcp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 959a273c..368865ac 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -111,7 +111,7 @@ class GoalEvaluationResult(BaseModel): reason: str = Field(description="评估原因") -class Risk(Enum, str): +class Risk(str, Enum): """MCP工具风险类型""" LOW = "low" -- Gitee From e377e5aca1555e184195ed0e5f522181567aed03 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 09:35:23 +0800 Subject: [PATCH 33/78] fix bug --- apps/scheduler/slot/slot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 40aaffce..74ea3da8 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -321,7 +321,7 @@ class Slot: paramType=param_type, subParams=sub_params) try: - return _extract_params_node(self._schema, name=root, path="/" + root) + return _extract_params_node(self._schema, name=root, path=root) except Exception as e: logger.error(f"[Slot] 提取ParamsNode失败: {e!s}\n{traceback.format_exc()}") return None -- Gitee From adcf1eb10ea8e3ad10acd4065d64e1dd77124f07 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 09:46:30 +0800 Subject: [PATCH 34/78] fix bug --- apps/scheduler/slot/slot.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 74ea3da8..41c516d2 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -268,17 +268,23 @@ class Slot: else: type_val = "" - data = {"type": type_val, "description": description} + data = {"type": type_val, "description": description, " items": {}} # 递归处理对象和数组 if type_val == "object": - data["items"] = {} for key, val in schema_node.get("properties", {}).items(): data["items"][key] = _extract_type_desc(val) elif type_val == "array": items_schema = schema_node.get("items", {}) - data["items"]["items"] = _extract_type_desc(items_schema) - + if isinstance(items_schema, list): + item_index = 0 + for item in items_schema: + data["items"][f"item_{item_index}"] = _extract_type_desc(item) + item_index += 1 + else: + data["items"]["item"] = _extract_type_desc(items_schema) + if data["items"] == {}: + del data["items"] return data return _extract_type_desc(self._schema) -- Gitee From 254fdc62a44fcfe00381269e9f7facc1e0971be7 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 09:51:57 +0800 Subject: [PATCH 35/78] fix bug --- apps/scheduler/slot/slot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scheduler/slot/slot.py b/apps/scheduler/slot/slot.py index 41c516d2..7a6313a1 100644 --- a/apps/scheduler/slot/slot.py +++ b/apps/scheduler/slot/slot.py @@ -268,7 +268,7 @@ class Slot: else: type_val = "" - data = {"type": type_val, "description": description, " items": {}} + data = {"type": type_val, "description": description, "items": {}} # 递归处理对象和数组 if type_val == "object": -- Gitee From 52564e5c7e1f1b967e5453ccd23eca88767f5e2f Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 12:05:16 +0800 Subject: [PATCH 36/78] =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=9B=91=E8=A7=86?= =?UTF-8?q?=E6=9C=BA=E5=88=B6=E6=9D=A5=E6=9A=82=E5=81=9C=E9=97=AE=E7=AD=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/chat.py | 5 +- apps/routers/record.py | 18 +++-- apps/scheduler/mcp_agent/prompt.py | 97 ++++++++++++++++++++++----- apps/scheduler/scheduler/context.py | 8 ++- apps/scheduler/scheduler/message.py | 25 ++++--- apps/scheduler/scheduler/scheduler.py | 57 ++++++++++++++-- apps/schemas/enum_var.py | 3 +- apps/schemas/record.py | 13 +++- apps/schemas/task.py | 16 +++-- apps/services/rag.py | 3 - apps/services/task.py | 2 +- 11 files changed, 190 insertions(+), 57 deletions(-) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 589000be..26a87481 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -13,6 +13,7 @@ from fastapi.responses import JSONResponse, StreamingResponse from apps.common.queue import MessageQueue from apps.common.wordscheck import WordsCheck from apps.dependency import get_session, get_user +from apps.schemas.enum_var import FlowStatus from apps.scheduler.scheduler import Scheduler from apps.scheduler.scheduler.context import save_data from apps.schemas.request_data import RequestData @@ -82,8 +83,8 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) # 获取最终答案 task = scheduler.task - if not task.runtime.answer: - logger.error("[Chat] 答案为空") + if task.state.flow_status == FlowStatus.ERROR: + logger.error("[Chat] 生成答案失败") yield "data: [ERROR]\n\n" await Activity.remove_active(user_sub) return diff --git a/apps/routers/record.py b/apps/routers/record.py index f357f0de..367138e2 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -81,19 +81,17 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ # 获得Record关联的文档 tmp_record.document = await DocumentManager.get_used_docs_by_record_group(user_sub, record_group.id) - + tmp_record.flow = RecordFlow( + id=record.flow_history.flow_id, # TODO: 此处前端应该用name + recordId=record.id, + flowStatus=record.flow_history.flow_staus, + flowId=record.flow_history.flow_id, + stepNum=len(flow_step_list), + steps=[], + ) # 获得Record关联的flow数据 flow_step_list = await TaskManager.get_context_by_record_id(record_group.id, record.id) if flow_step_list: - first_step_history = FlowStepHistory.model_validate(flow_step_list[0]) - tmp_record.flow = RecordFlow( - id=first_step_history.flow_name, # TODO: 此处前端应该用name - recordId=record.id, - flowStatus=first_step_history.flow_status, - flowId=first_step_history.id, - stepNum=len(flow_step_list), - steps=[], - ) for flow_step in flow_step_list: flow_step = FlowStepHistory.model_validate(flow_step) tmp_record.flow.steps.append( diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 74dd06c0..cf05afc8 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -115,7 +115,7 @@ EVALUATE_GOAL = dedent(r""" """) GENERATE_FLOW_NAME = dedent(r""" 你是一个智能助手,你的任务是根据用户的目标,生成一个合适的流程名称。 - + # 生成流程名称时的注意事项: 1. 流程名称应该简洁明了,能够准确表达达成用户目标的过程。 2. 流程名称应该包含关键的操作或步骤,例如“扫描”、“分析”、“调优”等。 @@ -431,7 +431,74 @@ RISK_EVALUATE = dedent(r""" # 输出 """ ) - +# 根据当前计划和报错信息决定下一步执行,具体计划有需要用户补充工具入参、重计划当前步骤、重计划接下来的所有计划 +JUDGE_NEXT_STEP = dedent(r""" + 你是一个计划决策器。 + 你的任务是根据当前计划、当前使用的工具、工具入参和工具运行报错,决定下一步执行的操作。 + 请根据以下规则进行判断: + 1. 仅通过补充工具入参来解决问题的,返回 fill_params; + 2. 需要重计划当前步骤的,返回 replan_current_step; + 3. 需要重计划接下来的所有计划的,返回 replan_all_steps; + 你的输出要以json格式返回,格式如下: + ```json + { + "next_step": "fill_params/replan_current_step/replan_all_steps", + "reason": "你的判断依据" + } + ``` + 注意: + reason字段必须清晰明了,能够让人理解你的判断依据,并且不超过50个中文字或者100个英文单词。 + # 样例 + ## 当前计划 + {"plans": [ + { + "content": "生成端口扫描命令", + "tool": "command_generator", + "instruction": "生成端口扫描命令:扫描192.168.1.1的开放端口" + }, + { + "content": "在执行Result[0]生成的命令", + "tool": "command_executor", + "instruction": "执行端口扫描命令" + }, + { + "content": "任务执行完成,端口扫描结果为Result[2]", + "tool": "Final", + "instruction": "" + } + ]} + ## 当前使用的工具 + + command_executor + 执行命令行指令 + + ## 工具入参 + { + "command": "nmap -sS -p--open 192.168.1.1" + } + ## 工具运行报错 + 执行端口扫描命令时,出现了错误:`-bash: nmap: command not found`。 + ## 输出 + ```json + { + "next_step": "replan_all_steps", + "reason": "当前工具执行报错,提示nmap命令未找到,需要增加command_generator和command_executor的步骤,生成nmap安装命令并执行,之后再生成端口扫描命令并执行。" + } + ``` + # 当前计划 + {{ current_plan }} + # 当前使用的工具 + + {{ tool.name }} + {{ tool.description }} + + # 工具入参 + {{ input_param }} + # 工具运行报错 + {{ error_message }} + # 输出 + """ + ) # 获取缺失的参数的json结构体 GET_MISSING_PARAMS = dedent(r""" 你是一个工具参数获取器。 @@ -445,18 +512,18 @@ GET_MISSING_PARAMS = dedent(r""" } ``` # 样例 - ## 工具名称 + # 工具名称 mysql_analyzer - ## 工具描述 + # 工具描述 分析MySQL数据库性能 - ## 工具入参 + # 工具入参 { "host": "192.0.0.1", "port": 3306, "username": "root", "password": "password" } - ## 工具入参schema + # 工具入参schema { "type": "object", "properties": { @@ -491,9 +558,9 @@ GET_MISSING_PARAMS = dedent(r""" }, "required": ["host", "port", "username", "password"] } - ## 运行报错 + # 运行报错 执行端口扫描命令时,出现了错误:`password is not correct`。 - ## 输出 + # 输出 ```json { "host": "192.0.0.1", @@ -503,16 +570,16 @@ GET_MISSING_PARAMS = dedent(r""" } ``` # 工具 - - {{ tool.name }} - {{ tool.description }} - + < tool > + < name > {{tool.name}} < /name > + < description > {{tool.description}} < /description > + < / tool > # 工具入参 - {{ input_param }} + {{input_param}} # 工具入参schema(部分字段允许为null) - {{ input_schema }} + {{input_schema}} # 运行报错 - {{ error_message }} + {{error_message}} # 输出 """ ) diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index 32331cf3..d7ce8652 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -10,6 +10,7 @@ from apps.llm.patterns.facts import Facts from apps.schemas.collection import Document from apps.schemas.enum_var import StepStatus from apps.schemas.record import ( + FlowHistory, Record, RecordContent, RecordDocument, @@ -188,7 +189,12 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: feature={}, ), createdAt=current_time, - flow=[i["_id"] for i in task.context], + flow_history=FlowHistory( + flow_id=task.state.flow_id, + flow_name=task.state.flow_name, + flow_status=task.state.flow_status, + history_ids=[context["_id"] for context in task.context], + ) ) # 检查是否存在group_id diff --git a/apps/scheduler/scheduler/message.py b/apps/scheduler/scheduler/message.py index a2a45e41..d43ba7fb 100644 --- a/apps/scheduler/scheduler/message.py +++ b/apps/scheduler/scheduler/message.py @@ -15,6 +15,7 @@ from apps.schemas.message import ( InitContentFeature, TextAddContent, ) +from apps.schemas.enum_var import FlowStatus from apps.schemas.rag_data import RAGEventData, RAGQueryReq from apps.schemas.record import RecordDocument from apps.schemas.task import Task @@ -61,21 +62,25 @@ async def push_init_message( async def push_rag_message( task: Task, queue: MessageQueue, user_sub: str, llm: LLM, history: list[dict[str, str]], doc_ids: list[str], - rag_data: RAGQueryReq,) -> Task: + rag_data: RAGQueryReq,) -> None: """推送RAG消息""" full_answer = "" - - async for chunk in RAG.chat_with_llm_base_on_rag(user_sub, llm, history, doc_ids, rag_data): - task, content_obj = await _push_rag_chunk(task, queue, chunk) - if content_obj.event_type == EventType.TEXT_ADD.value: - # 如果是文本消息,直接拼接到答案中 - full_answer += content_obj.content - elif content_obj.event_type == EventType.DOCUMENT_ADD.value: - task.runtime.documents.append(content_obj.content) + try: + async for chunk in RAG.chat_with_llm_base_on_rag(user_sub, llm, history, doc_ids, rag_data): + task, content_obj = await _push_rag_chunk(task, queue, chunk) + if content_obj.event_type == EventType.TEXT_ADD.value: + # 如果是文本消息,直接拼接到答案中 + full_answer += content_obj.content + elif content_obj.event_type == EventType.DOCUMENT_ADD.value: + task.runtime.documents.append(content_obj.content) + task.state.flow_status = FlowStatus.SUCCESS + except Exception as e: + logger.error(f"[Scheduler] RAG服务发生错误: {e}") + task.state.flow_status = FlowStatus.ERROR # 保存答案 task.runtime.answer = full_answer + task.tokens.full_time = round(datetime.now(UTC).timestamp(), 2) - task.tokens.time await TaskManager.save_task(task.id, task) - return task async def _push_rag_chunk(task: Task, queue: MessageQueue, content: str) -> tuple[Task, RAGEventData]: diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index 417f93d2..91930f8c 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -1,6 +1,7 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Scheduler模块""" +import asyncio import logging from datetime import UTC, datetime @@ -17,11 +18,12 @@ from apps.scheduler.scheduler.message import ( push_rag_message, ) from apps.schemas.collection import LLM -from apps.schemas.enum_var import AppType, EventType +from apps.schemas.enum_var import FlowStatus, AppType, EventType from apps.schemas.pool import AppPool from apps.schemas.rag_data import RAGQueryReq from apps.schemas.request_data import RequestData from apps.schemas.scheduler import ExecutorBackground +from apps.services.activity import Activity from apps.schemas.task import Task from apps.services.appcenter import AppCenterManager from apps.services.knowledge import KnowledgeBaseManager @@ -41,10 +43,30 @@ class Scheduler: """初始化""" self.used_docs = [] self.task = task - self.queue = queue self.post_body = post_body + async def _monitor_activity(self, kill_event, user_sub): + """监控用户活动状态,不活跃时终止工作流""" + try: + check_interval = 0.5 # 每0.5秒检查一次 + + while not kill_event.is_set(): + # 检查用户活动状态 + is_active = await Activity.is_active(user_sub) + + if not is_active: + logger.warning("[Scheduler] 用户 %s 不活跃,终止工作流", user_sub) + kill_event.set() + break + + # 控制检查频率 + await asyncio.sleep(check_interval) + except asyncio.CancelledError: + logger.info("[Scheduler] 活动监控任务已取消") + except Exception as e: + logger.error(f"[Scheduler] 活动监控过程中发生错误: {e}") + async def run(self) -> None: # noqa: PLR0911 """运行调度器""" try: @@ -95,6 +117,9 @@ class Scheduler: # 如果是智能问答,直接执行 logger.info("[Scheduler] 开始执行") + # 创建用于通信的事件 + kill_event = asyncio.Event() + monitor = asyncio.create_task(self._monitor_activity(kill_event, self.task.ids.user_sub)) if not self.post_body.app or self.post_body.app.app_id == "": self.task = await push_init_message(self.task, self.queue, 3, is_flow=False) rag_data = RAGQueryReq( @@ -102,8 +127,11 @@ class Scheduler: query=self.post_body.question, tokensLimit=llm.max_tokens, ) - self.task = await push_rag_message(self.task, self.queue, self.task.ids.user_sub, llm, history, doc_ids, rag_data) - self.task.tokens.full_time = round(datetime.now(UTC).timestamp(), 2) - self.task.tokens.time + + # 启动监控任务和主任务 + main_task = asyncio.create_task(push_rag_message( + self.task, self.queue, self.task.ids.user_sub, llm, history, doc_ids, rag_data)) + else: # 查找对应的App元数据 app_data = await AppCenterManager.fetch_app_data_by_id(self.post_body.app.app_id) @@ -127,8 +155,27 @@ class Scheduler: conversation=context, facts=facts, ) - await self.run_executor(self.queue, self.post_body, executor_background) + # 启动监控任务和主任务 + main_task = asyncio.create_task(self.run_executor(self.queue, self.post_body, executor_background)) + # 等待任一任务完成 + done, pending = await asyncio.wait( + [main_task, monitor], + return_when=asyncio.FIRST_COMPLETED + ) + + # 如果是监控任务触发,终止主任务 + if kill_event.is_set(): + logger.warning("[Scheduler] 用户活动状态检测不活跃,正在终止工作流执行...") + main_task.cancel() + need_change_cancel_flow_state = [FlowStatus.RUNNING, FlowStatus.WAITING] + if self.task.state.flow_status in need_change_cancel_flow_state: + self.task.state.flow_status = FlowStatus.CANCELLED + try: + await main_task + logger.info("[Scheduler] 工作流执行已被终止") + except Exception as e: + logger.error(f"[Scheduler] 终止工作流时发生错误: {e}") # 更新Task,发送结束消息 logger.info("[Scheduler] 发送结束消息") await self.queue.push_output(self.task, event_type=EventType.DONE.value, data={}) diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 8458e103..49a6c250 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -14,7 +14,7 @@ class SlotType(str, Enum): class StepStatus(str, Enum): """步骤状态""" - + UNKNOWN = "unknown" WAITING = "waiting" RUNNING = "running" SUCCESS = "success" @@ -26,6 +26,7 @@ class StepStatus(str, Enum): class FlowStatus(str, Enum): """Flow状态""" + UNKNOWN = "unknown" WAITING = "waiting" RUNNING = "running" SUCCESS = "success" diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 0c3d7185..3dd81ca9 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -10,7 +10,7 @@ from pydantic import BaseModel, Field from apps.schemas.collection import ( Document, ) -from apps.schemas.enum_var import CommentType, StepStatus +from apps.schemas.enum_var import CommentType, FlowStatus, StepStatus class RecordDocument(Document): @@ -116,6 +116,14 @@ class RecordGroupDocument(BaseModel): created_at: float = Field(default=0.0, description="文档创建时间") +class FlowHistory(BaseModel): + """Flow执行历史""" + flow_id: str = Field(default_factory=lambda: str(uuid.uuid4()), alias="_id") + flow_name: str = Field(default="", description="Flow名称") + flow_staus: FlowStatus = Field(default=FlowStatus.SUCCESS, description="Flow执行状态") + history_ids: list[str] = Field(default=[], description="Flow执行历史ID列表") + + class Record(RecordData): """问答,用于保存在MongoDB中""" @@ -123,7 +131,8 @@ class Record(RecordData): key: dict[str, Any] = {} content: str comment: RecordComment = Field(default=RecordComment()) - flow: list[str] = Field(default=[]) + flow_history: FlowHistory = Field( + default=FlowHistory(), description="Flow执行历史信息") class RecordGroup(BaseModel): diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 98d8c6b3..586ed1da 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -37,15 +37,17 @@ class ExecutorState(BaseModel): """FlowExecutor状态""" # 执行器级数据 - flow_id: str = Field(description="Flow ID") - flow_name: str = Field(description="Flow名称") - description: str = Field(description="Flow描述") - flow_status: FlowStatus = Field(description="Flow状态") + flow_id: str = Field(description="Flow ID", default="") + flow_name: str = Field(description="Flow名称", default="") + description: str = Field(description="Flow描述", default="") + flow_status: FlowStatus = Field(description="Flow状态", default=FlowStatus.UNKNOWN) # 任务级数据 - step_id: str = Field(description="当前步骤ID") - step_name: str = Field(description="当前步骤名称") - step_status: StepStatus = Field(description="当前步骤状态") + step_id: str = Field(description="当前步骤ID", default="") + step_name: str = Field(description="当前步骤名称", default="") + step_status: StepStatus = Field(description="当前步骤状态", default=StepStatus.UNKNOWN) step_description: str = Field(description="当前步骤描述", default="") + retry_times: int = Field(description="当前步骤重试次数", default=0) + error_message: str = Field(description="当前步骤错误信息", default="") app_id: str = Field(description="应用ID") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) error_info: dict[str, Any] = Field(description="错误信息", default={}) diff --git a/apps/services/rag.py b/apps/services/rag.py index efbdfe94..8b95d2b1 100644 --- a/apps/services/rag.py +++ b/apps/services/rag.py @@ -18,7 +18,6 @@ from apps.schemas.collection import LLM from apps.schemas.config import LLMConfig from apps.schemas.enum_var import EventType from apps.schemas.rag_data import RAGQueryReq -from apps.services.activity import Activity from apps.services.session import SessionManager logger = logging.getLogger(__name__) @@ -257,8 +256,6 @@ class RAG: result_only=False, model=llm.model_name, ): - if not await Activity.is_active(user_sub): - return chunk = buffer + chunk # 防止脚注被截断 if len(chunk) >= 2 and chunk[-2:] != "]]": diff --git a/apps/services/task.py b/apps/services/task.py index 2456d96b..39085305 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -82,7 +82,7 @@ class TaskManager: return [] flow_context_list = [] - for flow_context_id in records[0]["records"]["flow"]: + for flow_context_id in records[0]["records"]["flow_history"]["history_ids"]: flow_context = await flow_context_collection.find_one({"_id": flow_context_id}) if flow_context: flow_context_list.append(flow_context) -- Gitee From eb97467fcfc56ae939c4b6b3aec2ee18c5ebd5ac Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 15:39:53 +0800 Subject: [PATCH 37/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=90=E7=AE=97?= =?UTF-8?q?=E7=AC=A6=E5=8F=B7=E8=BF=94=E5=9B=9Ebug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/services/parameter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/services/parameter.py b/apps/services/parameter.py index c58fb39b..8f83eab0 100644 --- a/apps/services/parameter.py +++ b/apps/services/parameter.py @@ -47,7 +47,7 @@ class ParameterManager: for item in operate: result.append(OperateAndBindType( operate=item, - bind_type=ConditionHandler.get_value_type_from_operate(item))) + bind_type=(await ConditionHandler.get_value_type_from_operate(item)))) return result @staticmethod -- Gitee From 86397ffb313882c0f113bfd92ab945936ee7a874 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 30 Jul 2025 16:39:32 +0800 Subject: [PATCH 38/78] =?UTF-8?q?=E5=AE=8C=E5=96=84record=E6=94=B9?= =?UTF-8?q?=E9=80=A0=E5=90=8E=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/record.py | 16 ++++++++-------- apps/scheduler/scheduler/context.py | 2 +- apps/schemas/record.py | 2 +- apps/schemas/task.py | 4 ++-- apps/services/task.py | 3 +-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps/routers/record.py b/apps/routers/record.py index 367138e2..29ff68e0 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -81,17 +81,17 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ # 获得Record关联的文档 tmp_record.document = await DocumentManager.get_used_docs_by_record_group(user_sub, record_group.id) - tmp_record.flow = RecordFlow( - id=record.flow_history.flow_id, # TODO: 此处前端应该用name - recordId=record.id, - flowStatus=record.flow_history.flow_staus, - flowId=record.flow_history.flow_id, - stepNum=len(flow_step_list), - steps=[], - ) # 获得Record关联的flow数据 flow_step_list = await TaskManager.get_context_by_record_id(record_group.id, record.id) if flow_step_list: + tmp_record.flow = RecordFlow( + id=record.flow.flow_id, # TODO: 此处前端应该用name + recordId=record.id, + flowStatus=record.flow.flow_staus, + flowId=record.flow.flow_id, + stepNum=len(flow_step_list), + steps=[], + ) for flow_step in flow_step_list: flow_step = FlowStepHistory.model_validate(flow_step) tmp_record.flow.steps.append( diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index d7ce8652..109a5456 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -189,7 +189,7 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: feature={}, ), createdAt=current_time, - flow_history=FlowHistory( + flow=FlowHistory( flow_id=task.state.flow_id, flow_name=task.state.flow_name, flow_status=task.state.flow_status, diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 3dd81ca9..d3222762 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -131,7 +131,7 @@ class Record(RecordData): key: dict[str, Any] = {} content: str comment: RecordComment = Field(default=RecordComment()) - flow_history: FlowHistory = Field( + flow: FlowHistory = Field( default=FlowHistory(), description="Flow执行历史信息") diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 586ed1da..e1901416 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -48,7 +48,7 @@ class ExecutorState(BaseModel): step_description: str = Field(description="当前步骤描述", default="") retry_times: int = Field(description="当前步骤重试次数", default=0) error_message: str = Field(description="当前步骤错误信息", default="") - app_id: str = Field(description="应用ID") + app_id: str = Field(description="应用ID", default="") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) error_info: dict[str, Any] = Field(description="错误信息", default={}) @@ -94,7 +94,7 @@ class Task(BaseModel): id: str = Field(default_factory=lambda: str(uuid.uuid4()), alias="_id") ids: TaskIds = Field(description="任务涉及的各种ID") context: list[dict[str, Any]] = Field(description="Flow的步骤执行信息", default=[]) - state: ExecutorState | None = Field(description="Flow的状态", default=None) + state: ExecutorState = Field(description="Flow的状态", default=ExecutorState()) tokens: TaskTokens = Field(description="Token信息") runtime: TaskRuntime = Field(description="任务运行时数据") created_at: float = Field(default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3)) diff --git a/apps/services/task.py b/apps/services/task.py index 39085305..dceee324 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -82,7 +82,7 @@ class TaskManager: return [] flow_context_list = [] - for flow_context_id in records[0]["records"]["flow_history"]["history_ids"]: + for flow_context_id in records[0]["records"]["flow"]["history_ids"]: flow_context = await flow_context_collection.find_one({"_id": flow_context_id}) if flow_context: flow_context_list.append(flow_context) @@ -199,7 +199,6 @@ class TaskManager: conversation_id=post_body.conversation_id, group_id=post_body.group_id if post_body.group_id else "", ), - state=None, tokens=TaskTokens(), runtime=TaskRuntime(), ) -- Gitee From f9cfd5975219b2f00e3026162918fd5281105568 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 31 Jul 2025 00:09:40 +0800 Subject: [PATCH 39/78] =?UTF-8?q?=E5=AE=8C=E5=96=84choice=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E9=BB=98=E8=AE=A4=E5=88=86=E6=94=AF=E7=9A=84=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/call/choice/choice.py | 2 +- apps/scheduler/call/choice/condition_handler.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/scheduler/call/choice/choice.py b/apps/scheduler/call/choice/choice.py index 8cab8288..01ac7106 100644 --- a/apps/scheduler/call/choice/choice.py +++ b/apps/scheduler/call/choice/choice.py @@ -113,7 +113,7 @@ class Choice(CoreCall, input_model=ChoiceInput, output_model=ChoiceOutput): valid_conditions.append(condition) # 如果所有条件都无效,抛出异常 - if not valid_conditions: + if not valid_conditions and not choice.is_default: msg = "分支没有有效条件" logger.warning(f"[Choice] 分支 {choice.branch_id} 条件处理失败: {msg}") continue diff --git a/apps/scheduler/call/choice/condition_handler.py b/apps/scheduler/call/choice/condition_handler.py index 6111ba90..6f10f2c8 100644 --- a/apps/scheduler/call/choice/condition_handler.py +++ b/apps/scheduler/call/choice/condition_handler.py @@ -75,12 +75,11 @@ class ConditionHandler(BaseModel): @staticmethod def handler(choices: list[ChoiceBranch]) -> str: """处理条件""" - default_branch = [c for c in choices if c.is_default] - for block_judgement in choices: + for block_judgement in choices[::-1]: results = [] if block_judgement.is_default: - continue + return block_judgement.branch_id for condition in block_judgement.conditions: result = ConditionHandler._judge_condition(condition) if result is not None: @@ -96,9 +95,6 @@ class ConditionHandler(BaseModel): if final_result: return block_judgement.branch_id - # 如果没有匹配的分支,选择默认分支 - if default_branch: - return default_branch[0].branch_id return "" @staticmethod -- Gitee From cf4d309de30a924705a02194aae4568ad4459c21 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 31 Jul 2025 15:15:08 +0800 Subject: [PATCH 40/78] =?UTF-8?q?=E5=9F=BA=E4=BA=8E=E5=BD=93=E5=89=8Dnode?= =?UTF-8?q?=E7=9A=84type=E5=88=A4=E6=96=AD=E6=80=8E=E4=B9=88=E8=B5=B0?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/flow.py | 22 +++++++++++++--------- apps/schemas/enum_var.py | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index 382ef929..157c9159 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -46,6 +46,10 @@ class FlowExecutor(BaseExecutor): flow_id: str = Field(description="Flow ID") question: str = Field(description="用户输入") post_body_app: RequestDataApp = Field(description="请求体中的app信息") + current_step: StepQueueItem | None = Field( + description="当前执行的步骤", + default=None + ) async def load_state(self) -> None: """从数据库中加载FlowExecutor的状态""" @@ -70,13 +74,13 @@ class FlowExecutor(BaseExecutor): self._reached_end: bool = False self.step_queue: deque[StepQueueItem] = deque() - async def _invoke_runner(self, queue_item: StepQueueItem) -> None: + async def _invoke_runner(self) -> None: """单一Step执行""" # 创建步骤Runner step_runner = StepExecutor( msg_queue=self.msg_queue, task=self.task, - step=queue_item, + step=self.current_step, background=self.background, question=self.question, ) @@ -84,8 +88,8 @@ class FlowExecutor(BaseExecutor): # 初始化步骤 await step_runner.init() # 运行Step - await step_runner.run() + await step_runner.run() # 更新Task(已存过库) self.task = step_runner.task @@ -93,12 +97,12 @@ class FlowExecutor(BaseExecutor): """执行当前queue里面的所有步骤(在用户看来是单一Step)""" while True: try: - queue_item = self.step_queue.pop() + self.current_step = self.step_queue.pop() except IndexError: break # 执行Step - await self._invoke_runner(queue_item) + await self._invoke_runner() async def _find_next_id(self, step_id: str) -> list[str]: """查找下一个节点""" @@ -113,17 +117,17 @@ class FlowExecutor(BaseExecutor): # 如果当前步骤为结束,则直接返回 if self.task.state.step_id == "end" or not self.task.state.step_id: # type: ignore[arg-type] return [] - if self.task.state.step_name == "Choice": + if self.current_step.step.type == SpecialCallType.CHOICE.value: # 如果是choice节点,获取分支ID branch_id = self.task.context[-1]["output_data"]["branch_id"] if branch_id: - self.task.state.step_id = self.task.state.step_id + "." + branch_id + next_steps = await self._find_next_id(self.task.state.step_id + "." + branch_id) logger.info("[FlowExecutor] 分支ID:%s", branch_id) else: logger.warning("[FlowExecutor] 没有找到分支ID,返回空列表") return [] - - next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] + else: + next_steps = await self._find_next_id(self.task.state.step_id) # type: ignore[arg-type] # 如果step没有任何出边,直接跳到end if not next_steps: return [ diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 49a6c250..5ff3381c 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -162,7 +162,7 @@ class SpecialCallType(str, Enum): LLM = "LLM" START = "start" END = "end" - CHOICE = "choice" + CHOICE = "Choice" class CommentType(str, Enum): -- Gitee From d95f677fdfd555405fba8aafc49861e39d9e24d9 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 31 Jul 2025 16:22:09 +0800 Subject: [PATCH 41/78] =?UTF-8?q?context=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/flow.py | 2 +- apps/scheduler/scheduler/context.py | 2 +- apps/schemas/task.py | 2 +- apps/services/task.py | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index 157c9159..d8400fdf 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -119,7 +119,7 @@ class FlowExecutor(BaseExecutor): return [] if self.current_step.step.type == SpecialCallType.CHOICE.value: # 如果是choice节点,获取分支ID - branch_id = self.task.context[-1]["output_data"]["branch_id"] + branch_id = self.task.context[-1].output_data["branch_id"] if branch_id: next_steps = await self._find_next_id(self.task.state.step_id + "." + branch_id) logger.info("[FlowExecutor] 分支ID:%s", branch_id) diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index 109a5456..72f64a71 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -193,7 +193,7 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: flow_id=task.state.flow_id, flow_name=task.state.flow_name, flow_status=task.state.flow_status, - history_ids=[context["_id"] for context in task.context], + history_ids=[context.id for context in task.context], ) ) diff --git a/apps/schemas/task.py b/apps/schemas/task.py index e1901416..9e9f1531 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -93,7 +93,7 @@ class Task(BaseModel): id: str = Field(default_factory=lambda: str(uuid.uuid4()), alias="_id") ids: TaskIds = Field(description="任务涉及的各种ID") - context: list[dict[str, Any]] = Field(description="Flow的步骤执行信息", default=[]) + context: list[FlowStepHistory] = Field(description="Flow的步骤执行信息", default=[]) state: ExecutorState = Field(description="Flow的状态", default=ExecutorState()) tokens: TaskTokens = Field(description="Token信息") runtime: TaskRuntime = Field(description="任务运行时数据") diff --git a/apps/services/task.py b/apps/services/task.py index dceee324..0f237a3f 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -13,6 +13,7 @@ from apps.schemas.task import ( TaskIds, TaskRuntime, TaskTokens, + FlowStepHistory ) from apps.services.record import RecordManager @@ -67,7 +68,7 @@ class TaskManager: return Task.model_validate(task) @staticmethod - async def get_context_by_record_id(record_group_id: str, record_id: str) -> list[dict[str, Any]]: + async def get_context_by_record_id(record_group_id: str, record_id: str) -> FlowStepHistory: """根据record_group_id获取flow信息""" record_group_collection = MongoDB().get_collection("record_group") flow_context_collection = MongoDB().get_collection("flow_context") @@ -85,7 +86,7 @@ class TaskManager: for flow_context_id in records[0]["records"]["flow"]["history_ids"]: flow_context = await flow_context_collection.find_one({"_id": flow_context_id}) if flow_context: - flow_context_list.append(flow_context) + flow_context_list.append(FlowStepHistory.model_validate(flow_context)) except Exception: logger.exception("[TaskManager] 获取record_id的flow信息失败") return [] -- Gitee From ff332ab39f2e264f792bf5b08e959e3b67a2f89f Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 31 Jul 2025 16:24:13 +0800 Subject: [PATCH 42/78] =?UTF-8?q?context=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/record.py | 1 - apps/services/task.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/routers/record.py b/apps/routers/record.py index 29ff68e0..f73e6c98 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -93,7 +93,6 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ steps=[], ) for flow_step in flow_step_list: - flow_step = FlowStepHistory.model_validate(flow_step) tmp_record.flow.steps.append( RecordFlowStep( stepId=flow_step.step_name, # TODO: 此处前端应该用name diff --git a/apps/services/task.py b/apps/services/task.py index 0f237a3f..93604a93 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -68,7 +68,7 @@ class TaskManager: return Task.model_validate(task) @staticmethod - async def get_context_by_record_id(record_group_id: str, record_id: str) -> FlowStepHistory: + async def get_context_by_record_id(record_group_id: str, record_id: str) -> list[FlowStepHistory]: """根据record_group_id获取flow信息""" record_group_collection = MongoDB().get_collection("record_group") flow_context_collection = MongoDB().get_collection("flow_context") -- Gitee From 15dc14679a106bef9ffa66b9f31cc1d9b4aaf502 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 31 Jul 2025 22:26:56 +0800 Subject: [PATCH 43/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=A4=B1=E8=B4=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/main.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/main.py b/apps/main.py index 1646f671..58e2bd40 100644 --- a/apps/main.py +++ b/apps/main.py @@ -97,10 +97,13 @@ async def add_no_auth_user() -> None: username = os.environ.get('USER') # 适用于 Linux 和 macOS 系统 if not username: username = "admin" - await user_collection.insert_one(User( - _id=username, - is_admin=True, - ).model_dump(by_alias=True)) + try: + await user_collection.insert_one(User( + _id=username, + is_admin=True, + ).model_dump(by_alias=True)) + except Exception as e: + logging.warning(f"添加无认证用户失败: {e}") async def init_resources() -> None: -- Gitee From 65953620cfa12b8153732a0c2bb05b78610be1a4 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 11:13:52 +0800 Subject: [PATCH 44/78] fix buh --- apps/scheduler/scheduler/scheduler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index 91930f8c..f6325369 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -229,7 +229,8 @@ class Scheduler: # 初始化Executor logger.info("[Scheduler] 初始化Executor") - + logger.error(f"{flow_data}") + logger.error(f"{self.task}") flow_exec = FlowExecutor( flow_id=flow_id, flow=flow_data, -- Gitee From 3b1fb85f828acd35c1e3b4c68afb092455b04868 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 11:38:56 +0800 Subject: [PATCH 45/78] fix bug --- apps/scheduler/executor/flow.py | 2 +- apps/schemas/enum_var.py | 1 + apps/schemas/task.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/scheduler/executor/flow.py b/apps/scheduler/executor/flow.py index d8400fdf..ebd4da8e 100644 --- a/apps/scheduler/executor/flow.py +++ b/apps/scheduler/executor/flow.py @@ -55,7 +55,7 @@ class FlowExecutor(BaseExecutor): """从数据库中加载FlowExecutor的状态""" logger.info("[FlowExecutor] 加载Executor状态") # 尝试恢复State - if self.task.state: + if self.task.state and self.task.state.flow_status != FlowStatus.INIT: self.task.context = await TaskManager.get_context_by_task_id(self.task.id) else: # 创建ExecutorState diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 5ff3381c..3fb65028 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -27,6 +27,7 @@ class FlowStatus(str, Enum): """Flow状态""" UNKNOWN = "unknown" + INIT = "init" WAITING = "waiting" RUNNING = "running" SUCCESS = "success" diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 9e9f1531..602123e7 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -40,7 +40,7 @@ class ExecutorState(BaseModel): flow_id: str = Field(description="Flow ID", default="") flow_name: str = Field(description="Flow名称", default="") description: str = Field(description="Flow描述", default="") - flow_status: FlowStatus = Field(description="Flow状态", default=FlowStatus.UNKNOWN) + flow_status: FlowStatus = Field(description="Flow状态", default=FlowStatus.INIT) # 任务级数据 step_id: str = Field(description="当前步骤ID", default="") step_name: str = Field(description="当前步骤名称", default="") -- Gitee From 6168945d3c707522480dbbecc9c9eda18e844871 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 11:42:59 +0800 Subject: [PATCH 46/78] fix bug --- apps/scheduler/executor/step.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scheduler/executor/step.py b/apps/scheduler/executor/step.py index 377a4c6e..5a95e407 100644 --- a/apps/scheduler/executor/step.py +++ b/apps/scheduler/executor/step.py @@ -260,7 +260,7 @@ class StepExecutor(BaseExecutor): input_data=self.obj.input, output_data=output_data, ) - self.task.context.append(history.model_dump(exclude_none=True, by_alias=True)) + self.task.context.append(history) # 推送输出 await self.push_message(EventType.STEP_OUTPUT.value, output_data) -- Gitee From 9a0c015e79f3dc5302f1669cfed1b46347b3fcf7 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 11:48:26 +0800 Subject: [PATCH 47/78] fix bug --- apps/services/task.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/services/task.py b/apps/services/task.py index 93604a93..d133cbfb 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -94,7 +94,7 @@ class TaskManager: return flow_context_list @staticmethod - async def get_context_by_task_id(task_id: str, length: int = 0) -> list[dict[str, Any]]: + async def get_context_by_task_id(task_id: str, length: int = 0) -> list[FlowStepHistory]: """根据task_id获取flow信息""" flow_context_collection = MongoDB().get_collection("flow_context") @@ -105,7 +105,8 @@ class TaskManager: ).sort( "created_at", -1, ).limit(length): - flow_context += [history] + for i in range(len(flow_context)): + flow_context.append(FlowStepHistory.model_validate(history)) except Exception: logger.exception("[TaskManager] 获取task_id的flow信息失败") return [] @@ -113,7 +114,7 @@ class TaskManager: return flow_context @staticmethod - async def save_flow_context(task_id: str, flow_context: list[dict[str, Any]]) -> None: + async def save_flow_context(task_id: str, flow_context: list[FlowStepHistory]) -> None: """保存flow信息到flow_context""" flow_context_collection = MongoDB().get_collection("flow_context") try: @@ -121,12 +122,12 @@ class TaskManager: # 查找是否存在 current_context = await flow_context_collection.find_one({ "task_id": task_id, - "_id": history["_id"], + "_id": history.id, }) if current_context: await flow_context_collection.update_one( {"_id": current_context["_id"]}, - {"$set": history}, + {"$set": history.model_dump(exclude_none=True, by_alias=True)}, ) else: await flow_context_collection.insert_one(history) -- Gitee From c83aced55db60209d6c8d5cad3e33088e93121b6 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 11:53:33 +0800 Subject: [PATCH 48/78] fix bug --- apps/services/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/services/task.py b/apps/services/task.py index d133cbfb..a8cb1848 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -130,7 +130,7 @@ class TaskManager: {"$set": history.model_dump(exclude_none=True, by_alias=True)}, ) else: - await flow_context_collection.insert_one(history) + await flow_context_collection.insert_one(history.model_dump(exclude_none=True, by_alias=True)) except Exception: logger.exception("[TaskManager] 保存flow执行记录失败") -- Gitee From 75f1670dcdeb04676b27e0bb7ee68ffeb52c8d91 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 1 Aug 2025 17:43:45 +0800 Subject: [PATCH 49/78] =?UTF-8?q?=E5=AE=8C=E5=96=84mcp=20agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/auth.py | 5 ++-- apps/routers/user.py | 26 ++++++++++++++++++-- apps/scheduler/executor/agent.py | 42 +++++++++++++++++++++++++++++--- apps/scheduler/mcp/host.py | 4 +-- apps/scheduler/mcp_agent/host.py | 6 ++--- apps/schemas/collection.py | 1 + apps/schemas/message.py | 6 +++++ apps/schemas/request_data.py | 9 ++++++- apps/schemas/response_data.py | 1 + apps/schemas/task.py | 2 +- apps/schemas/user.py | 1 + apps/services/record.py | 5 +++- apps/services/user.py | 22 ++++++++++++++++- tests/manager/test_user.py | 2 +- 14 files changed, 115 insertions(+), 17 deletions(-) diff --git a/apps/routers/auth.py b/apps/routers/auth.py index 4a3f8293..72416fa3 100644 --- a/apps/routers/auth.py +++ b/apps/routers/auth.py @@ -74,7 +74,7 @@ async def oidc_login(request: Request, code: str) -> HTMLResponse: status_code=status.HTTP_403_FORBIDDEN, ) - await UserManager.update_userinfo_by_user_sub(user_sub) + await UserManager.update_refresh_revision_by_user_sub(user_sub) current_session = await SessionManager.create_session(user_host, user_sub) @@ -177,6 +177,7 @@ async def userinfo( user_sub=user_sub, revision=user.is_active, is_admin=user.is_admin, + auto_execute=user.auto_execute, ), ).model_dump(exclude_none=True, by_alias=True), ) @@ -192,7 +193,7 @@ async def userinfo( ) async def update_revision_number(request: Request, user_sub: Annotated[str, Depends(get_user)]) -> JSONResponse: # noqa: ARG001 """更新用户协议信息""" - ret: bool = await UserManager.update_userinfo_by_user_sub(user_sub, refresh_revision=True) + ret: bool = await UserManager.update_refresh_revision_by_user_sub(user_sub, refresh_revision=True) if not ret: return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, diff --git a/apps/routers/user.py b/apps/routers/user.py index 54e12f44..8c197204 100644 --- a/apps/routers/user.py +++ b/apps/routers/user.py @@ -3,10 +3,11 @@ from typing import Annotated -from fastapi import APIRouter, Depends, status +from fastapi import APIRouter, Body, Depends, status from fastapi.responses import JSONResponse from apps.dependency import get_user +from apps.schemas.request_data import UserUpdateRequest from apps.schemas.response_data import UserGetMsp, UserGetRsp from apps.schemas.user import UserInfo from apps.services.user import UserManager @@ -18,7 +19,7 @@ router = APIRouter( @router.get("") -async def chat( +async def get_user_sub( user_sub: Annotated[str, Depends(get_user)], ) -> JSONResponse: """查询所有用户接口""" @@ -42,3 +43,24 @@ async def chat( result=UserGetMsp(userInfoList=user_info_list), ).model_dump(exclude_none=True, by_alias=True), ) + + +@router.post("") +async def update_user_info( + user_sub: Annotated[str, Depends(get_user)], + *, + data: Annotated[UserUpdateRequest, Body(..., description="用户更新信息")], +) -> JSONResponse: + """更新用户信息接口""" + # 更新用户信息 + + result = await UserManager.update_userinfo_by_user_sub(user_sub, data) + if not result: + return JSONResponse( + status_code=status.HTTP_200_OK, + content={"code": status.HTTP_200_OK, "message": "用户信息更新成功"}, + ) + return JSONResponse( + status_code=status.HTTP_404_NOT_FOUND, + content={"code": status.HTTP_404_NOT_FOUND, "message": "用户信息更新失败"}, + ) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index cb8e183e..d6ed5917 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -6,25 +6,61 @@ import logging from pydantic import Field from apps.scheduler.executor.base import BaseExecutor +from apps.schemas.enum_var import EventType, SpecialCallType, FlowStatus, StepStatus from apps.scheduler.mcp_agent import host, plan, select +from apps.schemas.mcp import MCPServerConfig, MCPTool from apps.schemas.task import ExecutorState, StepQueueItem +from apps.schemas.message import param from apps.services.task import TaskManager - +from apps.services.appcenter import AppCenterManager +from apps.services.mcp_service import MCPServiceManager logger = logging.getLogger(__name__) class MCPAgentExecutor(BaseExecutor): """MCP Agent执行器""" - question: str = Field(description="用户输入") max_steps: int = Field(default=20, description="最大步数") servers_id: list[str] = Field(description="MCP server id") agent_id: str = Field(default="", description="Agent ID") agent_description: str = Field(default="", description="Agent描述") + mcp_list: list[MCPServerConfig] = Field(description="MCP服务器列表", default=[]) + tool_list: list[MCPTool] = Field(description="MCP工具列表", default=[]) + params: param | None = Field( + default=None, description="流执行过程中的参数补充", alias="params" + ) + + async def load_mcp_list(self) -> None: + """加载MCP服务器列表""" + logger.info("[MCPAgentExecutor] 加载MCP服务器列表") + # 获取MCP服务器列表 + app = await AppCenterManager.fetch_app_data_by_id(self.agent_id) + mcp_ids = app.mcp_service + for mcp_id in mcp_ids: + self.mcp_list.append( + await MCPServiceManager.get_mcp_service(mcp_id) + ) + + async def load_tools(self) -> None: + """加载MCP工具列表""" + logger.info("[MCPAgentExecutor] 加载MCP工具列表") + # 获取工具列表 + mcp_ids = [mcp.id for mcp in self.mcp_list] + for mcp_id in mcp_ids: + if not await MCPServiceManager.is_mcp_enabled(mcp_id, self.agent_id): + logger.warning("MCP %s 未启用,跳过工具加载", mcp_id) + continue + # 获取MCP工具 + tools = await MCPServiceManager.get_mcp_tools(mcp_id) + self.tool_list.extend(tools) async def load_state(self) -> None: """从数据库中加载FlowExecutor的状态""" logger.info("[FlowExecutor] 加载Executor状态") # 尝试恢复State - if self.task.state: + if self.task.state and self.task.state.flow_status != FlowStatus.INIT: self.task.context = await TaskManager.get_context_by_task_id(self.task.id) + + async def run(self) -> None: + """执行MCP Agent的主逻辑""" + # 初始化MCP服务 diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py index aa196112..8e110839 100644 --- a/apps/scheduler/mcp/host.py +++ b/apps/scheduler/mcp/host.py @@ -67,7 +67,7 @@ class MCPHost: context_list = [] for ctx_id in self._context_list: - context = next((ctx for ctx in task.context if ctx["_id"] == ctx_id), None) + context = next((ctx for ctx in task.context if ctx.id == ctx_id), None) if not context: continue context_list.append(context) @@ -118,7 +118,7 @@ class MCPHost: logger.error("任务 %s 不存在", self._task_id) return {} self._context_list.append(context.id) - task.context.append(context.model_dump(by_alias=True, exclude_none=True)) + task.context.append(context.model_dump(exclude_none=True, by_alias=True)) await TaskManager.save_task(self._task_id, task) return output_data diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index a8ebec7b..f05d8957 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -67,10 +67,10 @@ class MCPHost: context_list = [] for ctx_id in self._context_list: - context = next((ctx for ctx in task.context if ctx["_id"] == ctx_id), None) + context = next((ctx for ctx in task.context if ctx.id == ctx_id), None) if not context: continue - context_list.append(context) + context_list.append(context.model_dump(exclude_none=True, by_alias=True)) return self._env.from_string(MEMORY_TEMPLATE).render( context_list=context_list, @@ -118,7 +118,7 @@ class MCPHost: logger.error("任务 %s 不存在", self._task_id) return {} self._context_list.append(context.id) - task.context.append(context.model_dump(by_alias=True, exclude_none=True)) + task.context.append(context) await TaskManager.save_task(self._task_id, task) return output_data diff --git a/apps/schemas/collection.py b/apps/schemas/collection.py index 0ff66c72..a2991f85 100644 --- a/apps/schemas/collection.py +++ b/apps/schemas/collection.py @@ -61,6 +61,7 @@ class User(BaseModel): fav_apps: list[str] = [] fav_services: list[str] = [] is_admin: bool = Field(default=False, description="是否为管理员") + auto_execute: bool = Field(default=True, description="是否自动执行任务") class LLM(BaseModel): diff --git a/apps/schemas/message.py b/apps/schemas/message.py index cf70a82b..1e58fb1b 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -9,6 +9,12 @@ from apps.schemas.enum_var import EventType, StepStatus from apps.schemas.record import RecordMetadata +class param(BaseModel): + """流执行过程中的参数补充""" + content: dict[str, Any] | bool = Field(default={}, description="流执行过程中的参数补充内容") + description: str = Field(default="", description="流执行过程中的参数补充描述") + + class HeartbeatData(BaseModel): """心跳事件的数据结构""" diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 793ff456..7bb5ac76 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -10,6 +10,7 @@ from apps.schemas.appcenter import AppData from apps.schemas.enum_var import CommentType from apps.schemas.flow_topology import FlowItem from apps.schemas.mcp import MCPType +from apps.schemas.message import param class RequestDataApp(BaseModel): @@ -17,7 +18,7 @@ class RequestDataApp(BaseModel): app_id: str = Field(description="应用ID", alias="appId") flow_id: str | None = Field(default=None, description="Flow ID", alias="flowId") - params: dict[str, Any] | None = Field(default=None, description="插件参数") + params: param | None = Field(default=None, description="流执行过程中的参数补充", alias="params") class MockRequestData(BaseModel): @@ -185,3 +186,9 @@ class UpdateKbReq(BaseModel): """更新知识库请求体""" kb_ids: list[str] = Field(description="知识库ID列表", alias="kbIds", default=[]) + + +class UserUpdateRequest(BaseModel): + """更新用户信息请求体""" + + auto_execute: bool = Field(default=False, description="是否自动执行", alias="autoExecute") diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index b1dc77b7..7f162326 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -55,6 +55,7 @@ class AuthUserMsg(BaseModel): user_sub: str revision: bool is_admin: bool + auto_execute: bool class AuthUserRsp(ResponseData): diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 602123e7..b08da0a8 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -50,7 +50,7 @@ class ExecutorState(BaseModel): error_message: str = Field(description="当前步骤错误信息", default="") app_id: str = Field(description="应用ID", default="") slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) - error_info: dict[str, Any] = Field(description="错误信息", default={}) + error_info: str = Field(description="错误信息", default="") class TaskIds(BaseModel): diff --git a/apps/schemas/user.py b/apps/schemas/user.py index 61aa2587..debb3446 100644 --- a/apps/schemas/user.py +++ b/apps/schemas/user.py @@ -9,3 +9,4 @@ class UserInfo(BaseModel): user_sub: str = Field(alias="userSub", default="") user_name: str = Field(alias="userName", default="") + auto_execute: bool = Field(alias="autoExecute", default=False) diff --git a/apps/services/record.py b/apps/services/record.py index 5c8a89df..e1925ef6 100644 --- a/apps/services/record.py +++ b/apps/services/record.py @@ -49,6 +49,10 @@ class RecordManager: mongo = MongoDB() group_collection = mongo.get_collection("record_group") try: + await group_collection.update_one( + {"_id": group_id, "user_sub": user_sub}, + {"$pull": {"records": {"id": record.id}}} + ) await group_collection.update_one( {"_id": group_id, "user_sub": user_sub}, {"$push": {"records": record.model_dump(by_alias=True)}}, @@ -151,7 +155,6 @@ class RecordManager: logger.exception("[RecordManager] 验证记录是否在组中失败") return False - @staticmethod async def check_group_id(group_id: str, user_sub: str) -> bool: """检查group_id是否存在""" diff --git a/apps/services/user.py b/apps/services/user.py index 2721d377..476f1ef4 100644 --- a/apps/services/user.py +++ b/apps/services/user.py @@ -4,6 +4,7 @@ import logging from datetime import UTC, datetime +from apps.schemas.request_data import UserUpdateRequest from apps.common.mongo import MongoDB from apps.schemas.collection import User from apps.services.conversation import ConversationManager @@ -52,7 +53,26 @@ class UserManager: return User(**user_data) if user_data else None @staticmethod - async def update_userinfo_by_user_sub(user_sub: str, *, refresh_revision: bool = False) -> bool: + async def update_userinfo_by_user_sub(user_sub: str, data: UserUpdateRequest) -> bool: + """ + 根据用户sub更新用户信息 + + :param user_sub: 用户sub + :param data: 用户更新信息 + :return: 是否更新成功 + """ + mongo = MongoDB() + user_collection = mongo.get_collection("user") + update_dict = { + "$set": { + "auto_execute": data.auto_execute, + } + } + result = await user_collection.update_one({"_id": user_sub}, update_dict) + return result.modified_count > 0 + + @staticmethod + async def update_refresh_revision_by_user_sub(user_sub: str, *, refresh_revision: bool = False) -> bool: """ 根据用户sub更新用户信息 diff --git a/tests/manager/test_user.py b/tests/manager/test_user.py index d350ca30..ab6eeab4 100644 --- a/tests/manager/test_user.py +++ b/tests/manager/test_user.py @@ -73,7 +73,7 @@ class TestUserManager(unittest.TestCase): mock_mysql_db_instance.get_session.return_value = mock_session # 调用被测方法 - updated_userinfo = UserManager.update_userinfo_by_user_sub(userinfo, refresh_revision=True) + updated_userinfo = UserManager.update_refresh_revision_by_user_sub(userinfo, refresh_revision=True) # 断言返回的用户信息的 revision_number 是否与原始用户信息一致 self.assertEqual(updated_userinfo.revision_number, userinfo.revision_number) -- Gitee From dc80695ae21a3fc59058fb03a4cc49d3c587c73c Mon Sep 17 00:00:00 2001 From: zxstty Date: Sat, 2 Aug 2025 17:20:11 +0800 Subject: [PATCH 50/78] =?UTF-8?q?=E5=AE=8C=E5=96=84task=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E5=92=8Cmcp=20agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/queue.py | 2 + apps/routers/chat.py | 35 +++--- apps/routers/record.py | 5 +- apps/scheduler/executor/agent.py | 58 +++++----- apps/scheduler/mcp_agent/host.py | 165 ++++++++++------------------ apps/scheduler/mcp_agent/plan.py | 26 ++--- apps/scheduler/mcp_agent/prompt.py | 101 ++++++++++++++--- apps/scheduler/scheduler/context.py | 15 ++- apps/schemas/message.py | 4 +- apps/schemas/record.py | 3 +- apps/schemas/request_data.py | 1 + apps/schemas/task.py | 7 +- apps/services/conversation.py | 2 +- apps/services/record.py | 18 ++- apps/services/task.py | 85 +++++++------- 15 files changed, 289 insertions(+), 238 deletions(-) diff --git a/apps/common/queue.py b/apps/common/queue.py index 911485b3..089d475e 100644 --- a/apps/common/queue.py +++ b/apps/common/queue.py @@ -56,6 +56,8 @@ class MessageQueue: flow = MessageFlow( appId=task.state.app_id, flowId=task.state.flow_id, + flowName=task.state.flow_name, + flowStatus=task.state.flow_status, stepId=task.state.step_id, stepName=task.state.step_name, stepStatus=task.state.step_status diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 26a87481..06bc2dd7 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -22,6 +22,8 @@ from apps.schemas.task import Task from apps.services.activity import Activity from apps.services.blacklist import QuestionBlacklistManager, UserBlacklistManager from apps.services.flow import FlowManager +from apps.services.conversation import ConversationManager +from apps.services.record import RecordManager from apps.services.task import TaskManager RECOMMEND_TRES = 5 @@ -32,25 +34,33 @@ router = APIRouter( ) -async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> Task: +async def init_task(post_body: RequestData, user_sub: str) -> Task: """初始化Task""" # 生成group_id if not post_body.group_id: post_body.group_id = str(uuid.uuid4()) - if post_body.new_task: - # 创建或还原Task - task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) - if task: - await TaskManager.delete_task_by_task_id(task.id) - task = await TaskManager.get_task(session_id=session_id, post_body=post_body, user_sub=user_sub) + # 更改信息并刷新数据库 if post_body.new_task: - task.runtime.question = post_body.question - task.ids.group_id = post_body.group_id + conversation = await ConversationManager.get_conversation_by_conversation_id( + user_sub=user_sub, + conversation_id=post_body.conversation_id, + ) + if not conversation: + err = "[Chat] 用户没有权限访问该对话!" + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=err) + task_ids = await TaskManager.delete_tasks_by_conversation_id(post_body.conversation_id) + await RecordManager.update_record_flow_status_to_cancelled_by_task_ids(task_ids) + task = await TaskManager.init_new_task(user_sub=user_sub, conversation_id=post_body.conversation_id, post_body=post_body) + else: + if not post_body.task_id: + err = "[Chat] task_id 不可为空!" + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="task_id cannot be empty") + task = await TaskManager.get_task_by_conversation_id(post_body.task_id) return task -async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) -> AsyncGenerator[str, None]: +async def chat_generator(post_body: RequestData, user_sub: str) -> AsyncGenerator[str, None]: """进行实际问答,并从MQ中获取消息""" try: await Activity.set_active(user_sub) @@ -62,7 +72,7 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) await Activity.remove_active(user_sub) return - task = await init_task(post_body, user_sub, session_id) + task = await init_task(post_body, user_sub) # 创建queue;由Scheduler进行关闭 queue = MessageQueue() @@ -120,7 +130,6 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) async def chat( post_body: RequestData, user_sub: Annotated[str, Depends(get_user)], - session_id: Annotated[str, Depends(get_session)], ) -> StreamingResponse: """LLM流式对话接口""" # 问题黑名单检测 @@ -133,7 +142,7 @@ async def chat( if await Activity.is_active(user_sub): raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests") - res = chat_generator(post_body, user_sub, session_id) + res = chat_generator(post_body, user_sub) return StreamingResponse( content=res, media_type="text/event-stream", diff --git a/apps/routers/record.py b/apps/routers/record.py index f73e6c98..8d0105ff 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -65,7 +65,7 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ tmp_record = RecordData( id=record.id, groupId=record_group.id, - taskId=record_group.task_id, + taskId=record.task_id, conversationId=conversation_id, content=record_data, metadata=record.metadata @@ -87,8 +87,9 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ tmp_record.flow = RecordFlow( id=record.flow.flow_id, # TODO: 此处前端应该用name recordId=record.id, - flowStatus=record.flow.flow_staus, flowId=record.flow.flow_id, + flowName=record.flow.flow_name, + flowStatus=record.flow.flow_staus, stepNum=len(flow_step_list), steps=[], ) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index d6ed5917..603ea65b 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -5,10 +5,13 @@ import logging from pydantic import Field +from apps.llm.reasoning import ReasoningLLM from apps.scheduler.executor.base import BaseExecutor from apps.schemas.enum_var import EventType, SpecialCallType, FlowStatus, StepStatus -from apps.scheduler.mcp_agent import host, plan, select -from apps.schemas.mcp import MCPServerConfig, MCPTool +from apps.scheduler.mcp_agent.host import MCPHost +from apps.scheduler.mcp_agent.plan import MCPPlanner +from apps.scheduler.pool.mcp.client import MCPClient +from apps.schemas.mcp import MCPCollection, MCPTool from apps.schemas.task import ExecutorState, StepQueueItem from apps.schemas.message import param from apps.services.task import TaskManager @@ -24,43 +27,48 @@ class MCPAgentExecutor(BaseExecutor): servers_id: list[str] = Field(description="MCP server id") agent_id: str = Field(default="", description="Agent ID") agent_description: str = Field(default="", description="Agent描述") - mcp_list: list[MCPServerConfig] = Field(description="MCP服务器列表", default=[]) + mcp_list: list[MCPCollection] = Field(description="MCP服务器列表", default=[]) + mcp_client: dict[str, MCPClient] = Field( + description="MCP客户端列表,key为mcp_id", default={} + ) tool_list: list[MCPTool] = Field(description="MCP工具列表", default=[]) params: param | None = Field( default=None, description="流执行过程中的参数补充", alias="params" ) + resoning_llm: ReasoningLLM = Field( + default=ReasoningLLM(), + description="推理大模型", + ) + + async def load_state(self) -> None: + """从数据库中加载FlowExecutor的状态""" + logger.info("[FlowExecutor] 加载Executor状态") + # 尝试恢复State + if self.task.state and self.task.state.flow_status != FlowStatus.INIT: + self.task.context = await TaskManager.get_context_by_task_id(self.task.id) - async def load_mcp_list(self) -> None: + async def load_mcp(self) -> None: """加载MCP服务器列表""" logger.info("[MCPAgentExecutor] 加载MCP服务器列表") # 获取MCP服务器列表 app = await AppCenterManager.fetch_app_data_by_id(self.agent_id) mcp_ids = app.mcp_service for mcp_id in mcp_ids: - self.mcp_list.append( - await MCPServiceManager.get_mcp_service(mcp_id) - ) - - async def load_tools(self) -> None: - """加载MCP工具列表""" - logger.info("[MCPAgentExecutor] 加载MCP工具列表") - # 获取工具列表 - mcp_ids = [mcp.id for mcp in self.mcp_list] - for mcp_id in mcp_ids: - if not await MCPServiceManager.is_mcp_enabled(mcp_id, self.agent_id): - logger.warning("MCP %s 未启用,跳过工具加载", mcp_id) + mcp_service = await MCPServiceManager.get_mcp_service(mcp_id) + if self.task.ids.user_sub not in mcp_service.activated: + logger.warning( + "[MCPAgentExecutor] 用户 %s 未启用MCP %s", + self.task.ids.user_sub, + mcp_id, + ) continue - # 获取MCP工具 - tools = await MCPServiceManager.get_mcp_tools(mcp_id) - self.tool_list.extend(tools) - async def load_state(self) -> None: - """从数据库中加载FlowExecutor的状态""" - logger.info("[FlowExecutor] 加载Executor状态") - # 尝试恢复State - if self.task.state and self.task.state.flow_status != FlowStatus.INIT: - self.task.context = await TaskManager.get_context_by_task_id(self.task.id) + self.mcp_list.append(mcp_service) + self.mcp_client[mcp_id] = await MCPHost.get_client(self.task.ids.user_sub, mcp_id) + self.tool_list.extend(mcp_service.tools) async def run(self) -> None: """执行MCP Agent的主逻辑""" # 初始化MCP服务 + self.load_state() + self.load_mcp() diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index f05d8957..3217f539 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -14,116 +14,53 @@ from apps.llm.function import JsonGenerator from apps.scheduler.mcp.prompt import MEMORY_TEMPLATE from apps.scheduler.pool.mcp.client import MCPClient from apps.scheduler.pool.mcp.pool import MCPPool +from apps.scheduler.mcp_agent.prompt import REPAIR_PARAMS from apps.schemas.enum_var import StepStatus from apps.schemas.mcp import MCPPlanItem, MCPTool -from apps.schemas.task import FlowStepHistory +from apps.schemas.task import Task, FlowStepHistory from apps.services.task import TaskManager logger = logging.getLogger(__name__) +_env = SandboxedEnvironment( + loader=BaseLoader, + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, +) + class MCPHost: """MCP宿主服务""" - def __init__(self, user_sub: str, task_id: str, runtime_id: str, runtime_name: str) -> None: - """初始化MCP宿主""" - self._user_sub = user_sub - self._task_id = task_id - # 注意:runtime在工作流中是flow_id和step_description,在Agent中可为标识Agent的id和description - self._runtime_id = runtime_id - self._runtime_name = runtime_name - self._context_list = [] - self._env = SandboxedEnvironment( - loader=BaseLoader(), - autoescape=False, - trim_blocks=True, - lstrip_blocks=True, - ) - - async def get_client(self, mcp_id: str) -> MCPClient | None: + @staticmethod + async def get_client(user_sub, mcp_id: str) -> MCPClient | None: """获取MCP客户端""" mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") # 检查用户是否启用了这个mcp - mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": self._user_sub}) + mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": user_sub}) if not mcp_db_result: - logger.warning("用户 %s 未启用MCP %s", self._user_sub, mcp_id) + logger.warning("用户 %s 未启用MCP %s", user_sub, mcp_id) return None # 获取MCP配置 try: - return await MCPPool().get(mcp_id, self._user_sub) + return await MCPPool().get(mcp_id, user_sub) except KeyError: - logger.warning("用户 %s 的MCP %s 没有运行中的实例,请检查环境", self._user_sub, mcp_id) + logger.warning("用户 %s 的MCP %s 没有运行中的实例,请检查环境", user_sub, mcp_id) return None - async def assemble_memory(self) -> str: + @staticmethod + async def assemble_memory(task: Task) -> str: """组装记忆""" - task = await TaskManager.get_task_by_task_id(self._task_id) - if not task: - logger.error("任务 %s 不存在", self._task_id) - return "" - - context_list = [] - for ctx_id in self._context_list: - context = next((ctx for ctx in task.context if ctx.id == ctx_id), None) - if not context: - continue - context_list.append(context.model_dump(exclude_none=True, by_alias=True)) - return self._env.from_string(MEMORY_TEMPLATE).render( - context_list=context_list, - ) - - async def _save_memory( - self, - tool: MCPTool, - plan_item: MCPPlanItem, - input_data: dict[str, Any], - result: str, - ) -> dict[str, Any]: - """保存记忆""" - try: - output_data = json.loads(result) - except Exception: # noqa: BLE001 - logger.warning("[MCPHost] 得到的数据不是dict格式!尝试转换为str") - output_data = { - "message": result, - } - - if not isinstance(output_data, dict): - output_data = { - "message": result, - } - - # 创建context;注意用法 - context = FlowStepHistory( - task_id=self._task_id, - flow_id=self._runtime_id, - flow_name=self._runtime_name, - flow_status=StepStatus.SUCCESS, - step_id=tool.name, - step_name=tool.name, - # description是规划的实际内容 - step_description=plan_item.content, - step_status=StepStatus.SUCCESS, - input_data=input_data, - output_data=output_data, + return _env.from_string(MEMORY_TEMPLATE).render( + context_list=task.context, ) - # 保存到task - task = await TaskManager.get_task_by_task_id(self._task_id) - if not task: - logger.error("任务 %s 不存在", self._task_id) - return {} - self._context_list.append(context.id) - task.context.append(context) - await TaskManager.save_task(self._task_id, task) - - return output_data - - async def _fill_params(self, schema: dict[str, Any], query: str) -> dict[str, Any]: + async def _get_first_input_params(schema: dict[str, Any], query: str) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" @@ -137,23 +74,48 @@ class MCPHost: llm_query, [ {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": await self.assemble_memory()}, + {"role": "user", "content": await MCPHost.assemble_memory()}, + ], + schema, + ) + return await json_generator.generate() + + async def _fill_params(mcp_tool: MCPTool, schema: dict[str, Any], + current_input: dict[str, Any], + error_message: str = "", params: dict[str, Any] = {}, + params_description: str = "") -> dict[str, Any]: + llm_query = "请生成修复之后的工具参数" + prompt = _env.from_string(REPAIR_PARAMS).render( + tool_name=mcp_tool.name, + tool_description=mcp_tool.description, + input_schema=schema, + current_input=current_input, + error_message=error_message, + params=params, + params_description=params_description, + ) + + json_generator = JsonGenerator( + llm_query, + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, ], schema, ) return await json_generator.generate() - async def call_tool(self, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: + async def call_tool(user_sub: str, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: """调用工具""" # 拿到Client - client = await MCPPool().get(tool.mcp_id, self._user_sub) + client = await MCPPool().get(tool.mcp_id, user_sub) if client is None: err = f"[MCPHost] MCP Server不合法: {tool.mcp_id}" logger.error(err) raise ValueError(err) # 填充参数 - params = await self._fill_params(tool, plan_item.instruction) + params = await MCPHost._fill_params(tool, plan_item.instruction) # 调用工具 result = await client.call_tool(tool.name, params) # 保存记忆 @@ -162,29 +124,12 @@ class MCPHost: if not isinstance(item, TextContent): logger.error("MCP结果类型不支持: %s", item) continue - processed_result.append(await self._save_memory(tool, plan_item, params, item.text)) - - return processed_result - - async def get_tool_list(self, mcp_id_list: list[str]) -> list[MCPTool]: - """获取工具列表""" - mongo = MongoDB() - mcp_collection = mongo.get_collection("mcp") - - # 获取工具列表 - tool_list = [] - for mcp_id in mcp_id_list: - # 检查用户是否启用了这个mcp - mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": self._user_sub}) - if not mcp_db_result: - logger.warning("用户 %s 未启用MCP %s", self._user_sub, mcp_id) - continue - # 获取MCP工具配置 + result = item.text try: - for tool in mcp_db_result["tools"]: - tool_list.extend([MCPTool.model_validate(tool)]) - except KeyError: - logger.warning("用户 %s 的MCP Tool %s 配置错误", self._user_sub, mcp_id) + json_result = json.loads(result) + except Exception as e: + logger.error("MCP结果解析失败: %s, 错误: %s", result, e) continue + processed_result.append(json_result) - return tool_list + return processed_result diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index a7c1f132..13e7a98d 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -1,6 +1,6 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP 用户目标拆解与规划""" -from typing import Any +from typing import Any, AsyncGenerator from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment @@ -57,8 +57,8 @@ class MCPPlanner: result += chunk # 保存token用量 - self.input_tokens = self.resoning_llm.input_tokens - self.output_tokens = self.resoning_llm.output_tokens + self.input_tokens += self.resoning_llm.input_tokens + self.output_tokens += self.resoning_llm.output_tokens return result async def _parse_result(self, result: str, schema: dict[str, Any]) -> str: @@ -171,7 +171,8 @@ class MCPPlanner: """获取推理大模型的风险评估结果""" template = self._env.from_string(RISK_EVALUATE) prompt = template.render( - tool=tool, + tool_name=tool.name, + tool_description=tool.description, input_param=input_param, additional_info=additional_info, ) @@ -194,7 +195,8 @@ class MCPPlanner: schema_with_null = slot.add_null_to_basic_types() template = self._env.from_string(GET_MISSING_PARAMS) prompt = template.render( - tool=tool, + tool_name=tool.name, + tool_description=tool.description, input_param=input_param, schema=schema_with_null, error_message=error_message, @@ -204,7 +206,7 @@ class MCPPlanner: input_param_with_null = await self._parse_result(result, schema_with_null) return input_param_with_null - async def generate_answer(self, plan: MCPPlan, memory: str) -> str: + async def generate_answer(self, plan: MCPPlan, memory: str) -> AsyncGenerator[str, None]: """生成最终回答""" template = self._env.from_string(FINAL_ANSWER) prompt = template.render( @@ -213,16 +215,12 @@ class MCPPlanner: goal=self.user_goal, ) - llm = ReasoningLLM() - result = "" - async for chunk in llm.call( + async for chunk in self.resoning_llm.call( [{"role": "user", "content": prompt}], streaming=False, temperature=0.07, ): - result += chunk + yield chunk - self.input_tokens = llm.input_tokens - self.output_tokens = llm.output_tokens - - return result + self.input_tokens = self.resoning_llm.input_tokens + self.output_tokens = self.resoning_llm.output_tokens diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index cf05afc8..9cbc2f5b 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -421,8 +421,8 @@ RISK_EVALUATE = dedent(r""" ``` # 工具 - {{ tool.name }} - {{ tool.description }} + {{ tool_name }} + {{ tool_description }} # 工具入参 {{ input_param }} @@ -464,7 +464,7 @@ JUDGE_NEXT_STEP = dedent(r""" { "content": "任务执行完成,端口扫描结果为Result[2]", "tool": "Final", - "instruction": "" + "instruction": "" } ]} ## 当前使用的工具 @@ -489,8 +489,8 @@ JUDGE_NEXT_STEP = dedent(r""" {{ current_plan }} # 当前使用的工具 - {{ tool.name }} - {{ tool.description }} + {{ tool_name }} + {{ tool_description }} # 工具入参 {{ input_param }} @@ -571,8 +571,8 @@ GET_MISSING_PARAMS = dedent(r""" ``` # 工具 < tool > - < name > {{tool.name}} < /name > - < description > {{tool.description}} < /description > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > < / tool > # 工具入参 {{input_param}} @@ -583,32 +583,107 @@ GET_MISSING_PARAMS = dedent(r""" # 输出 """ ) +REPAIR_PARAMS = dedent(r""" + 你是一个工具参数修复器。 + 你的任务是根据当前的工具信息、工具入参的schema、工具当前的入参、工具的报错、补充的参数和补充的参数描述,修复当前工具的入参。 + + # 样例 + ## 工具信息 + + mysql_analyzer + 分析MySQL数据库性能 + + ## 工具入参的schema + { + "type": "object", + "properties": { + "host": { + "type": "string", + "description": "MySQL数据库的主机地址" + }, + "port": { + "type": "integer", + "description": "MySQL数据库的端口号" + }, + "username": { + "type": "string", + "description": "MySQL数据库的用户名" + }, + "password": { + "type": "string", + "description": "MySQL数据库的密码" + } + }, + "required": ["host", "port", "username", "password"] + } + ## 工具当前的入参 + { + "host": "192.0.0.1", + "port": 3306, + "username": "root", + "password": "password" + } + ## 工具的报错 + 执行端口扫描命令时,出现了错误:`password is not correct`。 + ## 补充的参数 + { + "username": "admin", + "password": "admin123" + } + ## 补充的参数描述 + 用户希望使用admin用户和admin123密码来连接MySQL数据库。 + # 输出 + ```json + { + "host": "192.0.0.1", + "port": 3306, + "username": "admin", + "password": "admin123" + } + ``` + # 工具 + + {{tool_name}} + {{tool_description}} + + # 工具入参scheme + {{input_schema}} + # 工具入参 + {{input_param}} + # 运行报错 + {{error_message}} + # 补充的参数 + {{params}} + # 补充的参数描述 + {{params_description}} + # 输出 + """ + ) FINAL_ANSWER = dedent(r""" 综合理解计划执行结果和背景信息,向用户报告目标的完成情况。 # 用户目标 - {{goal}} + {{ goal }} # 计划执行情况 为了完成上述目标,你实施了以下计划: - {{memory}} + {{ memory }} # 其他背景信息: - {{status}} + {{ status }} # 现在,请根据以上信息,向用户报告目标的完成情况: """) - MEMORY_TEMPLATE = dedent(r""" - { % for ctx in context_list % } + {% for ctx in context_list % } - 第{{loop.index}}步:{{ctx.step_description}} - 调用工具 `{{ctx.step_id}}`,并提供参数 `{{ctx.input_data}}` - 执行状态:{{ctx.status}} - 得到数据:`{{ctx.output_data}}` - { % endfor % } + {% endfor % } """) diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index 72f64a71..3b26f42f 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -199,21 +199,21 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: # 检查是否存在group_id if not await RecordManager.check_group_id(task.ids.group_id, user_sub): - record_group = await RecordManager.create_record_group( - task.ids.group_id, user_sub, post_body.conversation_id, task.id, + record_group_id = await RecordManager.create_record_group( + task.ids.group_id, user_sub, post_body.conversation_id ) - if not record_group: + if not record_group_id: logger.error("[Scheduler] 创建问答组失败") return else: - record_group = task.ids.group_id + record_group_id = task.ids.group_id # 修改文件状态 - await DocumentManager.change_doc_status(user_sub, post_body.conversation_id, record_group) + await DocumentManager.change_doc_status(user_sub, post_body.conversation_id, record_group_id) # 保存Record - await RecordManager.insert_record_data_into_record_group(user_sub, record_group, record) + await RecordManager.insert_record_data_into_record_group(user_sub, record_group_id, record) # 保存与答案关联的文件 - await DocumentManager.save_answer_doc(user_sub, record_group, used_docs) + await DocumentManager.save_answer_doc(user_sub, record_group_id, used_docs) if post_body.app and post_body.app.app_id: # 更新最近使用的应用 @@ -223,5 +223,4 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: if not task.state or task.state.flow_status == StepStatus.SUCCESS or task.state.flow_status == StepStatus.ERROR or task.state.flow_status == StepStatus.CANCELLED: await TaskManager.delete_task_by_task_id(task.id) else: - # 更新Task await TaskManager.save_task(task.id, task) diff --git a/apps/schemas/message.py b/apps/schemas/message.py index 1e58fb1b..e7341324 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -5,7 +5,7 @@ from typing import Any from datetime import UTC, datetime from pydantic import BaseModel, Field -from apps.schemas.enum_var import EventType, StepStatus +from apps.schemas.enum_var import EventType, FlowStatus, StepStatus from apps.schemas.record import RecordMetadata @@ -28,6 +28,8 @@ class MessageFlow(BaseModel): app_id: str = Field(description="插件ID", alias="appId") flow_id: str = Field(description="Flow ID", alias="flowId") + flow_name: str = Field(description="Flow名称", alias="flowName") + flow_status: FlowStatus = Field(description="Flow状态", alias="flowStatus", default=FlowStatus.UNKNOWN) step_id: str = Field(description="当前步骤ID", alias="stepId") step_name: str = Field(description="当前步骤名称", alias="stepName") sub_step_id: str | None = Field(description="当前子步骤ID", alias="subStepId", default=None) diff --git a/apps/schemas/record.py b/apps/schemas/record.py index d3222762..6a394375 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -44,6 +44,7 @@ class RecordFlow(BaseModel): id: str record_id: str = Field(alias="recordId") flow_id: str = Field(alias="flowId") + flow_name: str = Field(alias="flowName", default="") flow_status: StepStatus = Field(alias="flowStatus", default=StepStatus.SUCCESS) step_num: int = Field(alias="stepNum") steps: list[RecordFlowStep] @@ -129,6 +130,7 @@ class Record(RecordData): user_sub: str key: dict[str, Any] = {} + task_id: str content: str comment: RecordComment = Field(default=RecordComment()) flow: FlowHistory = Field( @@ -149,5 +151,4 @@ class RecordGroup(BaseModel): records: list[Record] = [] docs: list[RecordGroupDocument] = [] # 问题不变,所用到的文档不变 conversation_id: str - task_id: str created_at: float = Field(default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3)) diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 7bb5ac76..8719c2e9 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -47,6 +47,7 @@ class RequestData(BaseModel): files: list[str] = Field(default=[], description="文件列表") app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") + task_id: str | None = Field(default=None, alias="taskId", description="任务ID") new_task: bool = Field(default=True, description="是否新建任务") diff --git a/apps/schemas/task.py b/apps/schemas/task.py index b08da0a8..eccc95a5 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -46,11 +46,12 @@ class ExecutorState(BaseModel): step_name: str = Field(description="当前步骤名称", default="") step_status: StepStatus = Field(description="当前步骤状态", default=StepStatus.UNKNOWN) step_description: str = Field(description="当前步骤描述", default="") - retry_times: int = Field(description="当前步骤重试次数", default=0) - error_message: str = Field(description="当前步骤错误信息", default="") app_id: str = Field(description="应用ID", default="") - slot: dict[str, Any] = Field(description="待填充参数的JSON Schema", default={}) + current_input: dict[str, Any] = Field(description="当前输入数据", default={}) + params: dict[str, Any] = Field(description="补充的参数", default={}) + params_description: str = Field(description="补充的参数描述", default="") error_info: str = Field(description="错误信息", default="") + retry_times: int = Field(description="当前步骤重试次数", default=0) class TaskIds(BaseModel): diff --git a/apps/services/conversation.py b/apps/services/conversation.py index bac964db..6bacb727 100644 --- a/apps/services/conversation.py +++ b/apps/services/conversation.py @@ -140,4 +140,4 @@ class ConversationManager: await record_group_collection.delete_many({"conversation_id": conversation_id}, session=session) await session.commit_transaction() - await TaskManager.delete_tasks_by_conversation_id(conversation_id) + await TaskManager.delete_tasks_and_flow_context_by_conversation_id(conversation_id) diff --git a/apps/services/record.py b/apps/services/record.py index e1925ef6..6b61f91e 100644 --- a/apps/services/record.py +++ b/apps/services/record.py @@ -9,7 +9,7 @@ from apps.schemas.record import ( Record, RecordGroup, ) - +from apps.schemas.enum_var import FlowStatus logger = logging.getLogger(__name__) @@ -17,7 +17,7 @@ class RecordManager: """问答对相关操作""" @staticmethod - async def create_record_group(group_id: str, user_sub: str, conversation_id: str, task_id: str) -> str | None: + async def create_record_group(group_id: str, user_sub: str, conversation_id: str) -> str | None: """创建问答组""" mongo = MongoDB() record_group_collection = mongo.get_collection("record_group") @@ -26,7 +26,6 @@ class RecordManager: _id=group_id, user_sub=user_sub, conversation_id=conversation_id, - task_id=task_id, ) try: @@ -137,6 +136,19 @@ class RecordManager: logger.exception("[RecordManager] 查询问答组失败") return [] + @staticmethod + async def update_record_flow_status_to_cancelled_by_task_ids(task_ids: list[str]) -> None: + """更新Record关联的Flow状态""" + record_group_collection = MongoDB().get_collection("record_group") + try: + await record_group_collection.update_many( + {"records.flow.flow_id": {"$in": task_ids}, "records.flow.flow_status": {"$nin": [FlowStatus.ERROR.value, FlowStatus.SUCCESS.value]}}, + {"$set": {"records.$[elem].flow.flow_status": FlowStatus.CANCELLED}}, + array_filters=[{"elem.flow.flow_id": {"$in": task_ids}}], + ) + except Exception: + logger.exception("[RecordManager] 更新Record关联的Flow状态失败") + @staticmethod async def verify_record_in_group(group_id: str, record_id: str, user_sub: str) -> bool: """ diff --git a/apps/services/task.py b/apps/services/task.py index a8cb1848..2f75a8c3 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -113,6 +113,28 @@ class TaskManager: else: return flow_context + @staticmethod + async def init_new_task( + cls, + user_sub: str, + session_id: str | None = None, + post_body: RequestData | None = None, + ) -> Task: + """获取任务块""" + return Task( + _id=str(uuid.uuid4()), + ids=TaskIds( + user_sub=user_sub if user_sub else "", + session_id=session_id if session_id else "", + conversation_id=post_body.conversation_id, + group_id=post_body.group_id if post_body.group_id else "", + ), + question=post_body.question if post_body else "", + group_id=post_body.group_id if post_body else "", + tokens=TaskTokens(), + runtime=TaskRuntime(), + ) + @staticmethod async def save_flow_context(task_id: str, flow_context: list[FlowStepHistory]) -> None: """保存flow信息到flow_context""" @@ -145,7 +167,25 @@ class TaskManager: await task_collection.delete_one({"_id": task_id}) @staticmethod - async def delete_tasks_by_conversation_id(conversation_id: str) -> None: + async def delete_tasks_by_conversation_id(conversation_id: str) -> list[str]: + """通过ConversationID删除Task信息""" + mongo = MongoDB() + task_collection = mongo.get_collection("task") + task_ids = [] + try: + async for task in task_collection.find( + {"conversation_id": conversation_id}, + {"_id": 1}, + ): + task_ids.append(task["_id"]) + if task_ids: + await task_collection.delete_many({"conversation_id": conversation_id}) + except Exception: + logger.exception("[TaskManager] 删除ConversationID的Task信息失败") + return [] + + @staticmethod + async def delete_tasks_and_flow_context_by_conversation_id(conversation_id: str) -> None: """通过ConversationID删除Task信息""" mongo = MongoDB() task_collection = mongo.get_collection("task") @@ -162,49 +202,6 @@ class TaskManager: await task_collection.delete_many({"conversation_id": conversation_id}, session=session) await flow_context_collection.delete_many({"task_id": {"$in": task_ids}}, session=session) - @classmethod - async def get_task( - cls, - task_id: str | None = None, - session_id: str | None = None, - post_body: RequestData | None = None, - user_sub: str | None = None, - ) -> Task: - """获取任务块""" - if task_id: - try: - task = await cls.get_task_by_task_id(task_id) - if task: - return task - except Exception: - logger.exception("[TaskManager] 通过task_id获取任务失败") - - logger.info("[TaskManager] 未提供task_id,通过session_id获取任务") - if not session_id or not post_body: - err = ( - "session_id 和 conversation_id 或 group_id 和 conversation_id 是恢复/创建任务的必要条件。" - ) - raise ValueError(err) - - if post_body.group_id: - task = await cls.get_task_by_group_id(post_body.group_id, post_body.conversation_id) - else: - task = await cls.get_task_by_conversation_id(post_body.conversation_id) - - if task: - return task - return Task( - _id=str(uuid.uuid4()), - ids=TaskIds( - user_sub=user_sub if user_sub else "", - session_id=session_id if session_id else "", - conversation_id=post_body.conversation_id, - group_id=post_body.group_id if post_body.group_id else "", - ), - tokens=TaskTokens(), - runtime=TaskRuntime(), - ) - @classmethod async def save_task(cls, task_id: str, task: Task) -> None: """保存任务块""" -- Gitee From ea68121853eac7182da40f046682fc202aef8439 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 5 Aug 2025 11:14:56 +0800 Subject: [PATCH 51/78] =?UTF-8?q?=E5=AE=8C=E5=96=84Agent=20=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 389 +++++++++++++++++++++++++- apps/scheduler/mcp/select.py | 6 - apps/scheduler/mcp_agent/host.py | 12 +- apps/scheduler/mcp_agent/plan.py | 220 ++++++++++----- apps/scheduler/mcp_agent/prompt.py | 340 ++++++++++++++-------- apps/scheduler/mcp_agent/select.py | 240 ++++++---------- apps/scheduler/scheduler/scheduler.py | 56 +++- apps/schemas/enum_var.py | 6 +- apps/schemas/mcp.py | 27 ++ apps/schemas/message.py | 4 +- apps/schemas/pool.py | 3 + apps/schemas/task.py | 6 +- 12 files changed, 933 insertions(+), 376 deletions(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 603ea65b..4db38587 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -2,21 +2,34 @@ """MCP Agent执行器""" import logging - +import uuid from pydantic import Field - +from typing import Any +from apps.llm.patterns.rewrite import QuestionRewrite from apps.llm.reasoning import ReasoningLLM from apps.scheduler.executor.base import BaseExecutor from apps.schemas.enum_var import EventType, SpecialCallType, FlowStatus, StepStatus from apps.scheduler.mcp_agent.host import MCPHost from apps.scheduler.mcp_agent.plan import MCPPlanner +from apps.scheduler.mcp_agent.select import FINAL_TOOL_ID, MCPSelector from apps.scheduler.pool.mcp.client import MCPClient -from apps.schemas.mcp import MCPCollection, MCPTool -from apps.schemas.task import ExecutorState, StepQueueItem +from apps.schemas.mcp import ( + GoalEvaluationResult, + RestartStepIndex, + ToolRisk, + ErrorType, + ToolExcutionErrorType, + MCPPlan, + MCPCollection, + MCPTool +) +from apps.schemas.task import ExecutorState, FlowStepHistory, StepQueueItem from apps.schemas.message import param from apps.services.task import TaskManager from apps.services.appcenter import AppCenterManager from apps.services.mcp_service import MCPServiceManager +from apps.services.task import TaskManager +from apps.services.user import UserManager logger = logging.getLogger(__name__) @@ -31,7 +44,9 @@ class MCPAgentExecutor(BaseExecutor): mcp_client: dict[str, MCPClient] = Field( description="MCP客户端列表,key为mcp_id", default={} ) - tool_list: list[MCPTool] = Field(description="MCP工具列表", default=[]) + tools: dict[str, MCPTool] = Field( + description="MCP工具列表,key为tool_id", default={} + ) params: param | None = Field( default=None, description="流执行过程中的参数补充", alias="params" ) @@ -65,10 +80,372 @@ class MCPAgentExecutor(BaseExecutor): self.mcp_list.append(mcp_service) self.mcp_client[mcp_id] = await MCPHost.get_client(self.task.ids.user_sub, mcp_id) - self.tool_list.extend(mcp_service.tools) + for tool in mcp_service.tools: + self.tools[tool.id] = tool + + async def plan(self, is_replan: bool = False, start_index: int | None = None) -> None: + if is_replan: + error_message = "之前的计划遇到以下报错\n\n"+self.task.state.error_message + else: + error_message = "初始化计划" + tools = MCPSelector.select_top_tool( + self.task.runtime.question, list(self.tools.values()), + additional_info=error_message, top_n=40) + if is_replan: + logger.info("[MCPAgentExecutor] 重新规划流程") + if not start_index: + start_index = await MCPPlanner.get_replan_start_step_index(self.task.runtime.question, + self.task.state.error_message, + self.task.runtime.temporary_plans, + self.resoning_llm) + current_plan = self.task.runtime.temporary_plans.plans[start_index:] + error_message = self.task.state.error_message + temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, + is_replan=is_replan, + error_message=error_message, + current_plan=current_plan, + tool_list=tools, + max_steps=self.max_steps-start_index-1, + reasoning_llm=self.resoning_llm + ) + self.msg_queue.push_output( + self.task, + EventType.STEP_CANCEL, + data={} + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + self.task.context[-1].step_status = StepStatus.CANCELLED + self.task.runtime.temporary_plans = self.task.runtime.temporary_plans.plans[:start_index] + temporary_plans.plans + self.task.state.step_index = start_index + else: + start_index = 0 + self.task.runtime.temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, tool_list=tools, max_steps=self.max_steps, reasoning_llm=self.resoning_llm) + for i in range(start_index, len(self.task.runtime.temporary_plans.plans)): + self.task.runtime.temporary_plans.plans[i].step_id = str(uuid.uuid4()) + + async def get_tool_input_param(self, is_first: bool) -> dict[str, Any]: + if is_first: + # 获取第一个输入参数 + self.task.state.current_input = await MCPHost._get_first_input_params(self.tools[self.task.state.step_id], self.task.runtime.question, self.task) + else: + # 获取后续输入参数 + if isinstance(self.params, param): + params = self.params.content + params_description = self.params.description + else: + params = {} + params_description = "" + self.task.state.current_input = await MCPHost._fill_params(self.tools[self.task.state.step_id], self.task.state.current_input, self.task.state.error_message, params, params_description) + + async def reset_step_to_index(self, start_index: int) -> None: + """重置步骤到开始""" + logger.info("[MCPAgentExecutor] 重置步骤到索引 %d", start_index) + if self.task.runtime.temporary_plans: + self.task.state.flow_status = FlowStatus.RUNNING + self.task.state.step_id = self.task.runtime.temporary_plans.plans[start_index].step_id + self.task.state.step_index = 0 + self.task.state.step_name = self.task.runtime.temporary_plans.plans[start_index].tool + self.task.state.step_description = self.task.runtime.temporary_plans.plans[start_index].content + self.task.state.step_status = StepStatus.RUNNING + self.task.state.retry_times = 0 + else: + self.task.state.flow_status = FlowStatus.SUCCESS + self.task.state.step_id = FINAL_TOOL_ID + + async def confirm_before_step(self) -> None: + logger.info("[MCPAgentExecutor] 等待用户确认步骤 %d", self.task.state.step_index) + # 发送确认消息 + confirm_message = await MCPPlanner.get_tool_risk(self.tools[self.task.state.step_id], self.task.state.current_input, "", self.resoning_llm) + self.msg_queue.push_output(self.task, EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( + exclude_none=True, by_alias=True)) + self.msg_queue.push_output(self.task, EventType.FLOW_STOP, {}) + self.task.state.flow_status = FlowStatus.WAITING + self.task.state.step_status = StepStatus.WAITING + self.task.context.append( + FlowStepHistory( + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=self.task.state.step_status, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data={}, + output_data={}, + ex_data=confirm_message.model_dump(exclude_none=True, by_alias=True), + ) + ) + + async def run_step(self): + """执行步骤""" + self.task.state.flow_status = FlowStatus.RUNNING + self.task.state.step_status = StepStatus.RUNNING + logger.info("[MCPAgentExecutor] 执行步骤 %d", self.task.state.step_index) + # 获取MCP客户端 + mcp_tool = self.tools[self.task.state.step_id] + mcp_client = self.mcp_client[mcp_tool.mcp_id] + if not mcp_client: + logger.error("[MCPAgentExecutor] MCP客户端未找到: %s", mcp_tool.mcp_id) + self.task.state.flow_status = FlowStatus.ERROR + error = "[MCPAgentExecutor] MCP客户端未找到: {}".format(mcp_tool.mcp_id) + raise Exception(error) + try: + output_params = await mcp_client.call_tool(mcp_tool.name, self.task.state.current_input) + self.msg_queue.push_output( + self.task, + EventType.STEP_INPUT, + self.task.state.current_input + ) + self.msg_queue.push_output( + self.task, + EventType.STEP_OUTPUT, + output_params + ) + self.task.context.append( + FlowStepHistory( + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=StepStatus.SUCCESS, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data=self.task.state.current_input, + output_data=output_params, + ) + ) + self.task.state.step_status = StepStatus.SUCCESS + except Exception as e: + logging.warning("[MCPAgentExecutor] 执行步骤 %s 失败: %s", mcp_tool.name, str(e)) + import traceback + self.task.state.error_message = traceback.format_exc() + self.task.state.step_status = StepStatus.ERROR + + async def generate_params_with_null(self) -> None: + """生成参数补充""" + mcp_tool = self.tools[self.task.state.step_id] + params_with_null = await MCPPlanner.get_missing_param( + mcp_tool, + self.task.state.current_input, + self.task.state.error_message, + self.resoning_llm + ) + self.msg_queue.push_output( + self.task, + EventType.STEP_WAITING_FOR_PARAM, + data={ + "message": "当运行产生如下报错:\n" + self.task.state.error_message, + "params": params_with_null + } + ) + self.task.state.flow_status = FlowStatus.WAITING + self.task.state.step_status = StepStatus.PARAM + self.task.context.append( + FlowStepHistory( + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=self.task.state.step_status, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data={}, + output_data={}, + ex_data={ + "message": "当运行产生如下报错:\n" + self.task.state.error_message, + "params": params_with_null + } + ) + ) + + async def get_next_step(self) -> None: + self.task.state.step_index += 1 + if self.task.state.step_index < len(self.task.runtime.temporary_plans): + if self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id == FINAL_TOOL_ID: + # 最后一步 + self.task.state.flow_status = FlowStatus.SUCCESS + self.task.state.step_status = StepStatus.SUCCESS + self.msg_queue.push_output( + self.task, + EventType.FLOW_SUCCESS, + data={} + ) + return + self.task.state.step_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id + self.task.state.step_name = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + self.task.state.step_description = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content + self.task.state.step_status = StepStatus.INIT + self.task.state.current_input = {} + self.msg_queue.push_output( + self.task, + EventType.STEP_INIT, + data={} + ) + else: + # 没有下一步了,结束流程 + self.task.state.flow_status = FlowStatus.SUCCESS + self.task.state.step_status = StepStatus.SUCCESS + self.msg_queue.push_output( + self.task, + EventType.FLOW_SUCCESS, + data={} + ) + return + + async def error_handle_after_step(self) -> None: + """步骤执行失败后的错误处理""" + self.task.state.step_status = StepStatus.ERROR + self.task.state.flow_status = FlowStatus.ERROR + self.msg_queue.push_output( + self.task, + EventType.FLOW_FAILED, + data={} + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + del self.task.context[-1] + self.task.context.append( + FlowStepHistory( + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=self.task.state.step_status, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data={}, + output_data={}, + ) + ) + + async def work(self) -> None: + """执行当前步骤""" + if self.task.state.step_status == StepStatus.INIT: + self.get_tool_input_param(is_first=True) + user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) + if not user_info.auto_execute: + # 等待用户确认 + await self.confirm_before_step() + return + self.step.state.step_status = StepStatus.RUNNING + elif self.task.state.step_status in [StepStatus.PARAM, StepStatus.WAITING, StepStatus.RUNNING]: + if self.task.context[-1].step_status == StepStatus.PARAM: + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + del self.task.context[-1] + elif self.task.state.step_status == StepStatus.WAITING: + if self.params.content: + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + del self.task.context[-1] + else: + self.task.state.flow_status = FlowStatus.CANCELLED + self.task.state.step_status = StepStatus.CANCELLED + self.msg_queue.push_output( + self.task, + EventType.STEP_CANCEL, + data={} + ) + self.msg_queue.push_output( + self.task, + EventType.FLOW_CANCEL, + data={} + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + self.task.context[-1].step_status = StepStatus.CANCELLED + if self.task.state.step_status == StepStatus.PARAM: + self.get_tool_input_param(is_first=False) + max_retry = 5 + for i in range(max_retry): + if i != 0: + self.get_tool_input_param(is_first=False) + await self.run_step() + if self.task.state.step_status == StepStatus.SUCCESS: + break + elif self.task.state.step_status == StepStatus.ERROR: + # 错误处理 + if self.task.state.retry_times >= 3: + await self.error_handle_after_step() + else: + user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) + mcp_tool = self.tools[self.task.state.step_id] + error_type = await MCPPlanner.get_tool_execute_error_type( + self.task.runtime.question, + self.task.runtime.temporary_plans, + mcp_tool, + self.task.state.current_input, + self.task.state.error_message, + self.resoning_llm + ) + if error_type.type == ErrorType.DECORRECT_PLAN or user_info.auto_execute: + await self.plan(is_replan=True) + self.reset_step_to_index(self.task.state.step_index) + elif error_type.type == ErrorType.MISSING_PARAM: + await self.generate_params_with_null() + elif self.task.state.step_status == StepStatus.SUCCESS: + await self.get_next_step() + + async def summarize(self) -> None: + async for chunk in MCPPlanner.generate_answer( + self.task.runtime.question, + self.task.runtime.temporary_plans, + (await MCPHost.assemble_memory(self.task)), + self.resoning_llm + ): + self.msg_queue.push_output( + self.task, + EventType.TEXT_ADD, + data=chunk + ) + self.task.runtime.answer += chunk async def run(self) -> None: """执行MCP Agent的主逻辑""" # 初始化MCP服务 self.load_state() self.load_mcp() + if self.task.state.flow_status == FlowStatus.INIT: + # 初始化状态 + self.task.state.flow_id = str(uuid.uuid4()) + self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) + self.task.runtime.temporary_plans = await self.plan(is_replan=False) + self.reset_step_to_index(0) + TaskManager.save_task(self.task.id, self.task) + self.task.state.flow_status = FlowStatus.RUNNING + self.msg_queue.push_output( + self.task, + EventType.FLOW_START, + data={} + ) + try: + while self.task.state.step_index < len(self.task.runtime.temporary_plans) and \ + self.task.state.flow_status == FlowStatus.RUNNING: + self.work() + TaskManager.save_task(self.task.id, self.task) + except Exception as e: + logger.error("[MCPAgentExecutor] 执行过程中发生错误: %s", str(e)) + self.task.state.flow_status = FlowStatus.ERROR + self.task.state.error_message = str(e) + self.task.state.step_status = StepStatus.ERROR + self.msg_queue.push_output( + self.task, + EventType.STEP_ERROR, + data={} + ) + self.msg_queue.push_output( + self.task, + EventType.FLOW_FAILED, + data={} + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + del self.task.context[-1] + self.task.context.append( + FlowStepHistory( + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=self.task.state.step_status, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data={}, + output_data={}, + ) + ) diff --git a/apps/scheduler/mcp/select.py b/apps/scheduler/mcp/select.py index 2ff50344..f3d6e0d4 100644 --- a/apps/scheduler/mcp/select.py +++ b/apps/scheduler/mcp/select.py @@ -39,7 +39,6 @@ class MCPSelector: sql += f"'{mcp_id}', " return sql.rstrip(", ") + ")" - async def _get_top_mcp_by_embedding( self, query: str, @@ -72,7 +71,6 @@ class MCPSelector: }]) return llm_mcp_list - async def _get_mcp_by_llm( self, query: str, @@ -100,7 +98,6 @@ class MCPSelector: # 使用小模型提取JSON return await self._call_function_mcp(result, mcp_ids) - async def _call_reasoning(self, prompt: str) -> str: """调用大模型进行推理""" logger.info("[MCPHelper] 调用推理大模型") @@ -116,7 +113,6 @@ class MCPSelector: self.output_tokens += llm.output_tokens return result - async def _call_function_mcp(self, reasoning_result: str, mcp_ids: list[str]) -> MCPSelectResult: """调用结构化输出小模型提取JSON""" logger.info("[MCPHelper] 调用结构化输出小模型") @@ -136,7 +132,6 @@ class MCPSelector: raise return result - async def select_top_mcp( self, query: str, @@ -153,7 +148,6 @@ class MCPSelector: # 通过LLM选择最合适的 return await self._get_mcp_by_llm(query, llm_mcp_list, mcp_list) - @staticmethod async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTool]: """选择最合适的工具""" diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index 3217f539..ced175ef 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -60,7 +60,7 @@ class MCPHost: context_list=task.context, ) - async def _get_first_input_params(schema: dict[str, Any], query: str) -> dict[str, Any]: + async def _get_first_input_params(mcp_tool: MCPTool, query: str, task: Task) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" @@ -74,13 +74,13 @@ class MCPHost: llm_query, [ {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": await MCPHost.assemble_memory()}, + {"role": "user", "content": await MCPHost.assemble_memory(task)}, ], - schema, + mcp_tool.input_schema, ) return await json_generator.generate() - async def _fill_params(mcp_tool: MCPTool, schema: dict[str, Any], + async def _fill_params(mcp_tool: MCPTool, current_input: dict[str, Any], error_message: str = "", params: dict[str, Any] = {}, params_description: str = "") -> dict[str, Any]: @@ -88,7 +88,7 @@ class MCPHost: prompt = _env.from_string(REPAIR_PARAMS).render( tool_name=mcp_tool.name, tool_description=mcp_tool.description, - input_schema=schema, + input_schema=mcp_tool.input_schema, current_input=current_input, error_message=error_message, params=params, @@ -101,7 +101,7 @@ class MCPHost: {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt}, ], - schema, + mcp_tool.input_schema, ) return await json_generator.generate() diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 13e7a98d..91d293fb 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -9,38 +9,36 @@ from apps.llm.function import JsonGenerator from apps.scheduler.mcp_agent.prompt import ( EVALUATE_GOAL, GENERATE_FLOW_NAME, + GET_REPLAN_START_STEP_INDEX, CREATE_PLAN, RECREATE_PLAN, RISK_EVALUATE, + TOOL_EXECUTE_ERROR_TYPE_ANALYSIS, GET_MISSING_PARAMS, FINAL_ANSWER ) from apps.schemas.mcp import ( GoalEvaluationResult, + RestartStepIndex, ToolRisk, + ToolExcutionErrorType, MCPPlan, MCPTool ) from apps.scheduler.slot.slot import Slot +_env = SandboxedEnvironment( + loader=BaseLoader, + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, +) + class MCPPlanner: """MCP 用户目标拆解与规划""" - - def __init__(self, user_goal: str, resoning_llm: ReasoningLLM = None) -> None: - """初始化MCP规划器""" - self.user_goal = user_goal - self._env = SandboxedEnvironment( - loader=BaseLoader, - autoescape=True, - trim_blocks=True, - lstrip_blocks=True, - ) - self.resoning_llm = resoning_llm or ReasoningLLM() - self.input_tokens = 0 - self.output_tokens = 0 - - async def get_resoning_result(self, prompt: str) -> str: + @staticmethod + async def get_resoning_result(prompt: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取推理结果""" # 调用推理大模型 message = [ @@ -48,7 +46,7 @@ class MCPPlanner: {"role": "user", "content": prompt}, ] result = "" - async for chunk in self.resoning_llm.call( + async for chunk in resoning_llm.call( message, streaming=False, temperature=0.07, @@ -56,12 +54,10 @@ class MCPPlanner: ): result += chunk - # 保存token用量 - self.input_tokens += self.resoning_llm.input_tokens - self.output_tokens += self.resoning_llm.output_tokens return result - async def _parse_result(self, result: str, schema: dict[str, Any]) -> str: + @staticmethod + async def _parse_result(result: str, schema: dict[str, Any]) -> str: """解析推理结果""" json_generator = JsonGenerator( result, @@ -74,126 +70,210 @@ class MCPPlanner: json_result = await json_generator.generate() return json_result - async def evaluate_goal(self, tool_list: list[MCPTool]) -> GoalEvaluationResult: + @staticmethod + async def evaluate_goal( + tool_list: list[MCPTool], + resoning_llm: ReasoningLLM = ReasoningLLM()) -> GoalEvaluationResult: """评估用户目标的可行性""" # 获取推理结果 - result = await self._get_reasoning_evaluation(tool_list) + result = await MCPPlanner._get_reasoning_evaluation(tool_list, resoning_llm) # 解析为结构化数据 - evaluation = await self._parse_evaluation_result(result) + evaluation = await MCPPlanner._parse_evaluation_result(result) # 返回评估结果 return evaluation - async def _get_reasoning_evaluation(self, tool_list: list[MCPTool]) -> str: + @staticmethod + async def _get_reasoning_evaluation( + goal, tool_list: list[MCPTool], + resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取推理大模型的评估结果""" - template = self._env.from_string(EVALUATE_GOAL) + template = _env.from_string(EVALUATE_GOAL) prompt = template.render( - goal=self.user_goal, + goal=goal, tools=tool_list, ) - result = await self.get_resoning_result(prompt) + result = await MCPPlanner.get_resoning_result(prompt, resoning_llm) return result - async def _parse_evaluation_result(self, result: str) -> GoalEvaluationResult: + @staticmethod + async def _parse_evaluation_result(result: str) -> GoalEvaluationResult: """将推理结果解析为结构化数据""" schema = GoalEvaluationResult.model_json_schema() - evaluation = await self._parse_result(result, schema) + evaluation = await MCPPlanner._parse_result(result, schema) # 使用GoalEvaluationResult模型解析结果 return GoalEvaluationResult.model_validate(evaluation) - async def get_flow_name(self) -> str: + async def get_flow_name(user_goal: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取当前流程的名称""" - result = await self._get_reasoning_flow_name() + result = await MCPPlanner._get_reasoning_flow_name(user_goal, resoning_llm) return result - async def _get_reasoning_flow_name(self) -> str: + @staticmethod + async def _get_reasoning_flow_name(user_goal: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取推理大模型的流程名称""" - template = self._env.from_string(GENERATE_FLOW_NAME) - prompt = template.render(goal=self.user_goal) - result = await self.get_resoning_result(prompt) + template = _env.from_string(GENERATE_FLOW_NAME) + prompt = template.render(goal=user_goal) + result = await MCPPlanner.get_resoning_result(prompt, resoning_llm) return result - async def create_plan(self, tool_list: list[MCPTool], max_steps: int = 6) -> MCPPlan: + @staticmethod + async def get_replan_start_step_index( + user_goal: str, error_message: str, current_plan: MCPPlan | None = None, + history: str = "", + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> MCPPlan: + """获取重新规划的步骤索引""" + # 获取推理结果 + template = _env.from_string(GET_REPLAN_START_STEP_INDEX) + prompt = template.render( + goal=user_goal, + error_message=error_message, + current_plan=current_plan.model_dump(exclude_none=True, by_alias=True), + history=history, + ) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + # 解析为结构化数据 + schema = RestartStepIndex.model_json_schema() + schema["properties"]["start_index"]["maximum"] = len(current_plan.plans) - 1 + schema["properties"]["start_index"]["minimum"] = 0 + restart_index = await MCPPlanner._parse_result(result, schema) + # 使用RestartStepIndex模型解析结果 + return RestartStepIndex.model_validate(restart_index) + + @staticmethod + async def create_plan( + user_goal: str, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan | None = None, + tool_list: list[MCPTool] = [], + max_steps: int = 6, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> MCPPlan: """规划下一步的执行流程,并输出""" # 获取推理结果 - result = await self._get_reasoning_plan(tool_list, max_steps) + result = await MCPPlanner._get_reasoning_plan(user_goal, is_replan, error_message, current_plan, tool_list, max_steps, reasoning_llm) # 解析为结构化数据 - return await self._parse_plan_result(result, max_steps) + return await MCPPlanner._parse_plan_result(result, max_steps) + @staticmethod async def _get_reasoning_plan( - self, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan = MCPPlan(), + user_goal: str, is_replan: bool = False, error_message: str = "", current_plan: MCPPlan | None = None, tool_list: list[MCPTool] = [], - max_steps: int = 10) -> str: + max_steps: int = 10, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取推理大模型的结果""" # 格式化Prompt if is_replan: - template = self._env.from_string(RECREATE_PLAN) + template = _env.from_string(RECREATE_PLAN) prompt = template.render( - current_plan=current_plan, + current_plan=current_plan.model_dump(exclude_none=True, by_alias=True), error_message=error_message, - goal=self.user_goal, + goal=user_goal, tools=tool_list, max_num=max_steps, ) else: - template = self._env.from_string(CREATE_PLAN) + template = _env.from_string(CREATE_PLAN) prompt = template.render( - goal=self.user_goal, + goal=user_goal, tools=tool_list, max_num=max_steps, ) - result = await self.get_resoning_result(prompt) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) return result - async def _parse_plan_result(self, result: str, max_steps: int) -> MCPPlan: + @staticmethod + async def _parse_plan_result(result: str, max_steps: int) -> MCPPlan: """将推理结果解析为结构化数据""" # 格式化Prompt schema = MCPPlan.model_json_schema() schema["properties"]["plans"]["maxItems"] = max_steps - plan = await self._parse_result(result, schema) + plan = await MCPPlanner._parse_result(result, schema) # 使用Function模型解析结果 return MCPPlan.model_validate(plan) - async def get_tool_risk(self, tool: MCPTool, input_parm: dict[str, Any], additional_info: str = "") -> ToolRisk: + @staticmethod + async def get_tool_risk( + tool: MCPTool, input_parm: dict[str, Any], + additional_info: str = "", resoning_llm: ReasoningLLM = ReasoningLLM()) -> ToolRisk: """获取MCP工具的风险评估结果""" # 获取推理结果 - result = await self._get_reasoning_risk(tool, input_parm, additional_info) + result = await MCPPlanner._get_reasoning_risk(tool, input_parm, additional_info, resoning_llm) # 解析为结构化数据 - risk = await self._parse_risk_result(result) + risk = await MCPPlanner._parse_risk_result(result) # 返回风险评估结果 return risk - async def _get_reasoning_risk(self, tool: MCPTool, input_param: dict[str, Any], additional_info: str) -> str: + @staticmethod + async def _get_reasoning_risk( + tool: MCPTool, input_param: dict[str, Any], + additional_info: str, resoning_llm: ReasoningLLM) -> str: """获取推理大模型的风险评估结果""" - template = self._env.from_string(RISK_EVALUATE) + template = _env.from_string(RISK_EVALUATE) prompt = template.render( tool_name=tool.name, tool_description=tool.description, input_param=input_param, additional_info=additional_info, ) - result = await self.get_resoning_result(prompt) + result = await MCPPlanner.get_resoning_result(prompt, resoning_llm) return result - async def _parse_risk_result(self, result: str) -> ToolRisk: + @staticmethod + async def _parse_risk_result(result: str) -> ToolRisk: """将推理结果解析为结构化数据""" schema = ToolRisk.model_json_schema() - risk = await self._parse_result(result, schema) + risk = await MCPPlanner._parse_result(result, schema) # 使用ToolRisk模型解析结果 return ToolRisk.model_validate(risk) + @staticmethod + async def _get_reasoning_tool_execute_error_type( + user_goal: str, current_plan: MCPPlan, + tool: MCPTool, input_param: dict[str, Any], + error_message: str, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> str: + """获取推理大模型的工具执行错误类型""" + template = _env.from_string(TOOL_EXECUTE_ERROR_TYPE_ANALYSIS) + prompt = template.render( + goal=user_goal, + current_plan=current_plan.model_dump(exclude_none=True, by_alias=True), + tool_name=tool.name, + tool_description=tool.description, + input_param=input_param, + error_message=error_message, + ) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + return result + + @staticmethod + async def _parse_tool_execute_error_type_result(result: str) -> ToolExcutionErrorType: + """将推理结果解析为工具执行错误类型""" + schema = ToolExcutionErrorType.model_json_schema() + error_type = await MCPPlanner._parse_result(result, schema) + # 使用ToolExcutionErrorType模型解析结果 + return ToolExcutionErrorType.model_validate(error_type) + + @staticmethod + async def get_tool_execute_error_type( + user_goal: str, current_plan: MCPPlan, + tool: MCPTool, input_param: dict[str, Any], + error_message: str, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> ToolExcutionErrorType: + """获取MCP工具执行错误类型""" + # 获取推理结果 + result = await MCPPlanner._get_reasoning_tool_execute_error_type( + user_goal, current_plan, tool, input_param, error_message, reasoning_llm) + error_type = await MCPPlanner._parse_tool_execute_error_type_result(result) + # 返回工具执行错误类型 + return error_type + + @staticmethod async def get_missing_param( - self, tool: MCPTool, schema: dict[str, Any], + tool: MCPTool, input_param: dict[str, Any], - error_message: str) -> list[str]: + error_message: str, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> list[str]: """获取缺失的参数""" - slot = Slot(schema=schema) + slot = Slot(schema=tool.input_schema) + template = _env.from_string(GET_MISSING_PARAMS) schema_with_null = slot.add_null_to_basic_types() - template = self._env.from_string(GET_MISSING_PARAMS) prompt = template.render( tool_name=tool.name, tool_description=tool.description, @@ -201,26 +281,26 @@ class MCPPlanner: schema=schema_with_null, error_message=error_message, ) - result = await self.get_resoning_result(prompt) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) # 解析为结构化数据 - input_param_with_null = await self._parse_result(result, schema_with_null) + input_param_with_null = await MCPPlanner._parse_result(result, schema_with_null) return input_param_with_null - async def generate_answer(self, plan: MCPPlan, memory: str) -> AsyncGenerator[str, None]: + @staticmethod + async def generate_answer( + user_goal: str, plan: MCPPlan, memory: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> AsyncGenerator[ + str, None]: """生成最终回答""" - template = self._env.from_string(FINAL_ANSWER) + template = _env.from_string(FINAL_ANSWER) prompt = template.render( - plan=plan, + plan=plan.model_dump(exclude_none=True, by_alias=True), memory=memory, - goal=self.user_goal, + goal=user_goal, ) - async for chunk in self.resoning_llm.call( + async for chunk in resoning_llm.call( [{"role": "user", "content": prompt}], streaming=False, temperature=0.07, ): yield chunk - - self.input_tokens = self.resoning_llm.input_tokens - self.output_tokens = self.resoning_llm.output_tokens diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 9cbc2f5b..b5bc085c 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -62,6 +62,62 @@ MCP_SELECT = dedent(r""" ### 请一步一步思考: """) +TOOL_SELECT = dedent(r""" + 你是一个乐于助人的智能助手。 + 你的任务是:根据当前目标,附加信息,选择最合适的MCP工具。 + ## 选择MCP工具时的注意事项: + 1. 确保充分理解当前目标,选择实现目标所需的MCP工具。 + 2. 请在给定的MCP工具列表中选择,不要自己生成MCP工具。 + 3. 可以选择一些辅助工具,但必须确保这些工具与当前目标相关。 + 必须按照以下格式生成选择结果,不要输出任何其他内容: + ```json + { + "tool_ids": ["工具ID1", "工具ID2", ...] + } + ``` + + # 示例 + ## 目标 + 调优mysql性能 + ## MCP工具列表 + + - mcp_tool_1 MySQL链接池工具;用于优化MySQL链接池 + - mcp_tool_2 MySQL性能调优工具;用于分析MySQL性能瓶颈 + - mcp_tool_3 MySQL查询优化工具;用于优化MySQL查询语句 + - mcp_tool_4 MySQL索引优化工具;用于优化MySQL索引 + - mcp_tool_5 文件存储工具;用于存储文件 + - mcp_tool_6 mongoDB工具;用于操作MongoDB数据库 + + ## 附加信息 + 1. 当前MySQL数据库的版本是8.0.26 + 2. 当前MySQL数据库的配置文件路径是/etc/my.cnf,并含有以下配置项 + ```json + { + "max_connections": 1000, + "innodb_buffer_pool_size": "1G", + "query_cache_size": "64M" + } + ##输出 + ```json + { + "tool_ids": ["mcp_tool_1", "mcp_tool_2", "mcp_tool_3", "mcp_tool_4"] + } + ``` + # 现在开始! + ## 目标 + {{goal}} + ## MCP工具列表 + + {% for tool in tools %} + - {{tool.id}} {{tool.name}};{{tool.description}} + {% endfor %} + + ## 附加信息 + {{additional_info}} + # 输出 + """ + ) + EVALUATE_GOAL = dedent(r""" 你是一个计划评估器。 请根据用户的目标和当前的工具集合以及一些附加信息,判断基于当前的工具集合,是否能够完成用户的目标。 @@ -76,18 +132,18 @@ EVALUATE_GOAL = dedent(r""" ``` # 样例 - ## 目标 - 我需要扫描当前mysql数据库,分析性能瓶颈,并调优 + # 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 - ## 工具集合 - 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + # 工具集合 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - - mysql_analyzer分析MySQL数据库性能 - - performance_tuner调优数据库性能 - - Final结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + - mysql_analyzer 分析MySQL数据库性能 + - performance_tuner 调优数据库性能 + - Final 结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 - ## 附加信息 + # 附加信息 1. 当前MySQL数据库的版本是8.0.26 2. 当前MySQL数据库的配置文件路径是/etc/my.cnf @@ -100,17 +156,17 @@ EVALUATE_GOAL = dedent(r""" ``` # 目标 - {{ goal }} + {{goal}} # 工具集合 - {% for tool in tools %} - - {{ tool.id }}{{tool.name}};{{ tool.description }} - {% endfor %} + { % for tool in tools % } + - {{tool.id}} {{tool.name}};{{tool.description}} + { % endfor % } # 附加信息 - {{ additional_info }} + {{additional_info}} """) GENERATE_FLOW_NAME = dedent(r""" @@ -123,15 +179,79 @@ GENERATE_FLOW_NAME = dedent(r""" 4. 流程名称应该尽量简短,小于20个字或者单词。 5. 只输出流程名称,不要输出其他内容。 # 样例 - ## 目标 - 我需要扫描当前mysql数据库,分析性能瓶颈,并调优 - ## 输出 + # 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 输出 扫描MySQL数据库并分析性能瓶颈,进行调优 # 现在开始生成流程名称: # 目标 - {{ goal }} + {{goal}} # 输出 """) +GET_REPLAN_START_STEP_INDEX = dedent(r""" + 你是一个智能助手,你的任务是根据用户的目标、报错信息和当前计划和历史,获取重新规划的步骤起始索引。 + + # 样例 + # 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 报错信息 + 执行端口扫描命令时,出现了错误:`- bash: curl: command not found`。 + # 当前计划 + ```json + { + "plans": [ + { + "step_id": "step_1", + "content": "生成端口扫描命令", + "tool": "command_generator", + "instruction": "生成端口扫描命令:扫描 + }, + { + "step_id": "step_2", + "content": "在执行Result[0]生成的命令", + "tool": "command_executor", + "instruction": "执行端口扫描命令" + } + ] + } + # 历史 + [ + { + id: "0", + task_id: "task_1", + flow_id: "flow_1", + flow_name: "MYSQL性能调优", + flow_status: "RUNNING", + step_id: "step_1", + step_name: "生成端口扫描命令", + step_description: "生成端口扫描命令:扫描当前MySQL数据库的端口", + step_status: "FAILED", + input_data: { + "command": "nmap -p 3306 + "target": "localhost" + }, + output_data: { + "error": "- bash: curl: command not found" + } + } + ] + # 输出 + { + "start_index": 0, + "reasoning": "当前计划的第一步就失败了,报错信息显示curl命令未找到,可能是因为没有安装curl工具,因此需要从第一步重新规划。" + } + # 现在开始获取重新规划的步骤起始索引: + # 目标 + {{goal}} + # 报错信息 + {{error_message}} + # 当前计划 + {{current_plan}} + # 历史 + {{history}} + # 输出 + """) + CREATE_PLAN = dedent(r""" 你是一个计划生成器。 请分析用户的目标,并生成一个计划。你后续将根据这个计划,一步一步地完成用户的目标。 @@ -163,40 +283,38 @@ CREATE_PLAN = dedent(r""" } ``` - - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。\ -思考过程应放置在 XML标签中。 + - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。 +思考过程应放置在 XML标签中。 - 计划内容中,可以使用"Result[]"来引用之前计划步骤的结果。例如:"Result[3]"表示引用第三条计划执行后的结果。 - - 计划不得多于{{ max_num }}条,且每条计划内容应少于150字。 + - 计划不得多于{{max_num}}条,且每条计划内容应少于150字。 # 工具 - 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - {% for tool in tools %} - - {{ tool.id }}{{tool.name}};{{ tool.description }} - {% endfor %} + { % for tool in tools % } + - {{tool.id}} {{tool.name}};{{tool.description}} + { % endfor % } # 样例 - ## 目标 + # 目标 - 在后台运行一个新的alpine:latest容器,将主机/root文件夹挂载至/data,并执行top命令。 + 在后台运行一个新的alpine: latest容器,将主机/root文件夹挂载至/data,并执行top命令。 - ## 计划 + # 计划 - 1. 这个目标需要使用Docker来完成,首先需要选择合适的MCP Server + 1. 这个目标需要使用Docker来完成, 首先需要选择合适的MCP Server 2. 目标可以拆解为以下几个部分: - - 运行alpine:latest容器 + - 运行alpine: latest容器 - 挂载主机目录 - 在后台运行 - 执行top命令 - 3. 需要先选择MCP Server,然后生成Docker命令,最后执行命令 - - - ```json + 3. 需要先选择MCP Server, 然后生成Docker命令, 最后执行命令 + ```json { "plans": [ { @@ -225,7 +343,7 @@ CREATE_PLAN = dedent(r""" # 现在开始生成计划: - ## 目标 + # 目标 {{goal}} @@ -263,26 +381,24 @@ RECREATE_PLAN = dedent(r""" } ``` - - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。\ -思考过程应放置在 XML标签中。 + - 在生成计划之前,请一步一步思考,解析用户的目标,并指导你接下来的生成。 +思考过程应放置在 XML标签中。 - 计划内容中,可以使用"Result[]"来引用之前计划步骤的结果。例如:"Result[3]"表示引用第三条计划执行后的结果。 - - 计划不得多于{{ max_num }}条,且每条计划内容应少于150字。 + - 计划不得多于{{max_num}}条,且每条计划内容应少于150字。 # 样例 - ## 目标 + # 目标 请帮我扫描一下192.168.1.1的这台机器的端口,看看有哪些端口开放。 - ## 工具 - 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + # 工具 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - - command_generator生成命令行指令 - - tool_selector选择合适的工具 - - command_executor执行命令行指令 - - Final结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 - - - ## 当前计划 + - command_generator 生成命令行指令 + - tool_selector 选择合适的工具 + - command_executor 执行命令行指令 + - Final 结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + # 当前计划 ```json { "plans": [ @@ -304,25 +420,23 @@ RECREATE_PLAN = dedent(r""" ] } ``` - ## 运行报错 - 执行端口扫描命令时,出现了错误:`-bash: curl: command not found`。 - ## 重新生成的计划 + # 运行报错 + 执行端口扫描命令时,出现了错误:`- bash: curl: command not found`。 + # 重新生成的计划 - 1. 这个目标需要使用网络扫描工具来完成,首先需要选择合适的网络扫描工具 + 1. 这个目标需要使用网络扫描工具来完成, 首先需要选择合适的网络扫描工具 2. 目标可以拆解为以下几个部分: - 生成端口扫描命令 - 执行端口扫描命令 - 3.但是在执行端口扫描命令时,出现了错误:`-bash: curl: command not found`。 + 3.但是在执行端口扫描命令时,出现了错误:`- bash: curl: command not found`。 4.我将计划调整为: - 需要先生成一个命令,查看当前机器支持哪些网络扫描工具 - 执行这个命令,查看当前机器支持哪些网络扫描工具 - 然后从中选择一个网络扫描工具 - 基于选择的网络扫描工具,生成端口扫描命令 - 执行端口扫描命令 - - - ```json + ```json { "plans": [ { @@ -367,19 +481,19 @@ RECREATE_PLAN = dedent(r""" # 工具 - 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 + 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - {% for tool in tools %} - - {{ tool.id }}{{tool.name}};{{ tool.description }} - {% endfor %} + { % for tool in tools % } + - {{tool.id}} {{tool.name}};{{tool.description}} + { % endfor % } # 当前计划 - {{ current_plan }} + {{current_plan}} # 运行报错 - {{ error_message }} + {{error_message}} # 重新生成的计划 """) @@ -393,18 +507,18 @@ RISK_EVALUATE = dedent(r""" } ``` # 样例 - ## 工具名称 + # 工具名称 mysql_analyzer - ## 工具描述 + # 工具描述 分析MySQL数据库性能 - ## 工具入参 + # 工具入参 { "host": "192.0.0.1", "port": 3306, "username": "root", "password": "password" } - ## 附加信息 + # 附加信息 1. 当前MySQL数据库的版本是8.0.26 2. 当前MySQL数据库的配置文件路径是/etc/my.cnf,并含有以下配置项 ```ini @@ -412,7 +526,7 @@ RISK_EVALUATE = dedent(r""" innodb_buffer_pool_size=1G innodb_log_file_size=256M ``` - ## 输出 + # 输出 ```json { "risk": "中", @@ -421,35 +535,35 @@ RISK_EVALUATE = dedent(r""" ``` # 工具 - {{ tool_name }} - {{ tool_description }} + {{tool_name}} + {{tool_description}} # 工具入参 - {{ input_param }} + {{input_param}} # 附加信息 - {{ additional_info }} + {{additional_info}} # 输出 """ ) # 根据当前计划和报错信息决定下一步执行,具体计划有需要用户补充工具入参、重计划当前步骤、重计划接下来的所有计划 -JUDGE_NEXT_STEP = dedent(r""" +TOOL_EXECUTE_ERROR_TYPE_ANALYSIS = dedent(r""" 你是一个计划决策器。 - 你的任务是根据当前计划、当前使用的工具、工具入参和工具运行报错,决定下一步执行的操作。 + 你的任务是根据用户目标、当前计划、当前使用的工具、工具入参和工具运行报错,决定下一步执行的操作。 请根据以下规则进行判断: - 1. 仅通过补充工具入参来解决问题的,返回 fill_params; - 2. 需要重计划当前步骤的,返回 replan_current_step; - 3. 需要重计划接下来的所有计划的,返回 replan_all_steps; + 1. 仅通过补充工具入参来解决问题的,返回 missing_param; + 2. 需要重计划当前步骤的,返回 decorrect_plan + 3.推理过程必须清晰明了,能够让人理解你的判断依据,并且不超过100字。 你的输出要以json格式返回,格式如下: ```json { - "next_step": "fill_params/replan_current_step/replan_all_steps", - "reason": "你的判断依据" + "error_type": "missing_param/decorrect_plan, + "reason": "你的推理过程" } ``` - 注意: - reason字段必须清晰明了,能够让人理解你的判断依据,并且不超过50个中文字或者100个英文单词。 # 样例 - ## 当前计划 + # 用户目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 当前计划 {"plans": [ { "content": "生成端口扫描命令", @@ -467,38 +581,40 @@ JUDGE_NEXT_STEP = dedent(r""" "instruction": "" } ]} - ## 当前使用的工具 + # 当前使用的工具 - command_executor - 执行命令行指令 + command_executor + 执行命令行指令 - ## 工具入参 + # 工具入参 { "command": "nmap -sS -p--open 192.168.1.1" } - ## 工具运行报错 - 执行端口扫描命令时,出现了错误:`-bash: nmap: command not found`。 - ## 输出 + # 工具运行报错 + 执行端口扫描命令时,出现了错误:`- bash: nmap: command not found`。 + # 输出 ```json { - "next_step": "replan_all_steps", - "reason": "当前工具执行报错,提示nmap命令未找到,需要增加command_generator和command_executor的步骤,生成nmap安装命令并执行,之后再生成端口扫描命令并执行。" + "error_type": "decorrect_plan", + "reason": "当前计划的第二步执行失败,报错信息显示nmap命令未找到,可能是因为没有安装nmap工具,因此需要重计划当前步骤。" } ``` + # 用户目标 + {{goal}} # 当前计划 - {{ current_plan }} + {{current_plan}} # 当前使用的工具 - {{ tool_name }} - {{ tool_description }} + {{tool_name}} + {{tool_description}} # 工具入参 - {{ input_param }} + {{input_param}} # 工具运行报错 - {{ error_message }} + {{error_message}} # 输出 """ - ) + ) # 获取缺失的参数的json结构体 GET_MISSING_PARAMS = dedent(r""" 你是一个工具参数获取器。 @@ -570,10 +686,10 @@ GET_MISSING_PARAMS = dedent(r""" } ``` # 工具 - < tool > - < name > {{tool_name}} < /name > - < description > {{tool_description}} < /description > - < / tool > + + {{tool_name}} + {{tool_description}} + # 工具入参 {{input_param}} # 工具入参schema(部分字段允许为null) @@ -588,12 +704,12 @@ REPAIR_PARAMS = dedent(r""" 你的任务是根据当前的工具信息、工具入参的schema、工具当前的入参、工具的报错、补充的参数和补充的参数描述,修复当前工具的入参。 # 样例 - ## 工具信息 + # 工具信息 - mysql_analyzer - 分析MySQL数据库性能 + mysql_analyzer + 分析MySQL数据库性能 - ## 工具入参的schema + # 工具入参的schema { "type": "object", "properties": { @@ -616,21 +732,21 @@ REPAIR_PARAMS = dedent(r""" }, "required": ["host", "port", "username", "password"] } - ## 工具当前的入参 + # 工具当前的入参 { "host": "192.0.0.1", "port": 3306, "username": "root", "password": "password" } - ## 工具的报错 + # 工具的报错 执行端口扫描命令时,出现了错误:`password is not correct`。 - ## 补充的参数 + # 补充的参数 { "username": "admin", "password": "admin123" } - ## 补充的参数描述 + # 补充的参数描述 用户希望使用admin用户和admin123密码来连接MySQL数据库。 # 输出 ```json @@ -643,8 +759,8 @@ REPAIR_PARAMS = dedent(r""" ``` # 工具 - {{tool_name}} - {{tool_description}} + {{tool_name}} + {{tool_description}} # 工具入参scheme {{input_schema}} @@ -664,17 +780,17 @@ FINAL_ANSWER = dedent(r""" # 用户目标 - {{ goal }} + {{goal}} # 计划执行情况 为了完成上述目标,你实施了以下计划: - {{ memory }} + {{memory}} # 其他背景信息: - {{ status }} + {{status}} # 现在,请根据以上信息,向用户报告目标的完成情况: diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 37d1e752..933527c3 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -2,7 +2,7 @@ """选择MCP Server及其工具""" import logging -import uuid +import random from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment from typing import AsyncGenerator @@ -13,176 +13,94 @@ from apps.common.mongo import MongoDB from apps.llm.embedding import Embedding from apps.llm.function import FunctionLLM from apps.llm.reasoning import ReasoningLLM -from apps.scheduler.mcp.prompt import ( - MCP_SELECT, -) +from apps.llm.token import TokenCalculator +from apps.scheduler.mcp_agent.prompt import TOOL_SELECT from apps.schemas.mcp import ( + BaseModel, MCPCollection, MCPSelectResult, MCPTool, + MCPToolIdsSelectResult ) - +from apps.common.config import Config logger = logging.getLogger(__name__) +_env = SandboxedEnvironment( + loader=BaseLoader, + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, +) -class MCPSelector: - """MCP选择器""" - - def __init__(self, resoning_llm: ReasoningLLM = None) -> None: - """初始化助手类""" - self.resoning_llm = resoning_llm or ReasoningLLM() - self.input_tokens = 0 - self.output_tokens = 0 - - @staticmethod - def _assemble_sql(mcp_list: list[str]) -> str: - """组装SQL""" - sql = "(" - for mcp_id in mcp_list: - sql += f"'{mcp_id}', " - return sql.rstrip(", ") + ")" - - async def _get_top_mcp_by_embedding( - self, - query: str, - mcp_list: list[str], - ) -> list[dict[str, str]]: - """通过向量检索获取Top5 MCP Server""" - logger.info("[MCPHelper] 查询MCP Server向量: %s, %s", query, mcp_list) - mcp_table = await LanceDB().get_table("mcp") - query_embedding = await Embedding.get_embedding([query]) - mcp_vecs = await (await mcp_table.search( - query=query_embedding, - vector_column_name="embedding", - )).where(f"id IN {MCPSelector._assemble_sql(mcp_list)}").limit(5).to_list() - - # 拿到名称和description - logger.info("[MCPHelper] 查询MCP Server名称和描述: %s", mcp_vecs) - mcp_collection = MongoDB().get_collection("mcp") - llm_mcp_list: list[dict[str, str]] = [] - for mcp_vec in mcp_vecs: - mcp_id = mcp_vec["id"] - mcp_data = await mcp_collection.find_one({"_id": mcp_id}) - if not mcp_data: - logger.warning("[MCPHelper] 查询MCP Server名称和描述失败: %s", mcp_id) - continue - mcp_data = MCPCollection.model_validate(mcp_data) - llm_mcp_list.extend([{ - "id": mcp_id, - "name": mcp_data.name, - "description": mcp_data.description, - }]) - return llm_mcp_list - - async def _get_mcp_by_llm( - self, - query: str, - mcp_list: list[dict[str, str]], - mcp_ids: list[str], - ) -> MCPSelectResult: - """通过LLM选择最合适的MCP Server""" - # 初始化jinja2环境 - env = SandboxedEnvironment( - loader=BaseLoader, - autoescape=True, - trim_blocks=True, - lstrip_blocks=True, - ) - template = env.from_string(MCP_SELECT) - # 渲染模板 - mcp_prompt = template.render( - mcp_list=mcp_list, - goal=query, - ) - - # 调用大模型进行推理 - result = await self._call_reasoning(mcp_prompt) - - # 使用小模型提取JSON - return await self._call_function_mcp(result, mcp_ids) - - async def _call_reasoning(self, prompt: str) -> AsyncGenerator[str, None]: - """调用大模型进行推理""" - logger.info("[MCPHelper] 调用推理大模型") - message = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": prompt}, - ] - async for chunk in self.resoning_llm.call(message): - yield chunk - - async def _call_function_mcp(self, reasoning_result: str, mcp_ids: list[str]) -> MCPSelectResult: - """调用结构化输出小模型提取JSON""" - logger.info("[MCPHelper] 调用结构化输出小模型") - llm = FunctionLLM() - message = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": reasoning_result}, - ] - schema = MCPSelectResult.model_json_schema() - # schema中加入选项 - schema["properties"]["mcp_id"]["enum"] = mcp_ids - result = await llm.call(messages=message, schema=schema) - try: - result = MCPSelectResult.model_validate(result) - except Exception: - logger.exception("[MCPHelper] 解析MCP Select Result失败") - raise - return result - - async def select_top_mcp( - self, - query: str, - mcp_list: list[str], - ) -> MCPSelectResult: - """ - 选择最合适的MCP Server +FINAL_TOOL_ID = "FIANL" +SUMMARIZE_TOOL_ID = "SUMMARIZE" - 先通过Embedding选择Top5,然后通过LLM选择Top 1 - """ - # 通过向量检索获取Top5 - llm_mcp_list = await self._get_top_mcp_by_embedding(query, mcp_list) - # 通过LLM选择最合适的 - return await self._get_mcp_by_llm(query, llm_mcp_list, mcp_list) +class MCPSelector: + """MCP选择器""" @staticmethod - async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTool]: + async def select_top_tool( + goal: str, tool_list: list[MCPTool], + additional_info: str | None = None, top_n: int | None = None) -> list[MCPTool]: """选择最合适的工具""" - tool_vector = await LanceDB().get_table("mcp_tool") - query_embedding = await Embedding.get_embedding([query]) - tool_vecs = await (await tool_vector.search( - query=query_embedding, - vector_column_name="embedding", - )).where(f"mcp_id IN {MCPSelector._assemble_sql(mcp_list)}").limit(top_n).to_list() - - # 拿到工具 - tool_collection = MongoDB().get_collection("mcp") - llm_tool_list = [] - - for tool_vec in tool_vecs: - # 到MongoDB里找对应的工具 - logger.info("[MCPHelper] 查询MCP Tool名称和描述: %s", tool_vec["mcp_id"]) - tool_data = await tool_collection.aggregate([ - {"$match": {"_id": tool_vec["mcp_id"]}}, - {"$unwind": "$tools"}, - {"$match": {"tools.id": tool_vec["id"]}}, - {"$project": {"_id": 0, "tools": 1}}, - {"$replaceRoot": {"newRoot": "$tools"}}, - ]) - async for tool in tool_data: - tool_obj = MCPTool.model_validate(tool) - llm_tool_list.append(tool_obj) - llm_tool_list.append( - MCPTool( - id="00000000-0000-0000-0000-000000000000", - name="Final", - description="It is the final step, indicating the end of the plan execution.") - ) - llm_tool_list.append( - MCPTool( - id="00000000-0000-0000-0000-000000000001", - name="Chat", - description="It is a chat tool to communicate with the user.") - ) - return llm_tool_list + random.shuffle(tool_list) + max_tokens = Config().get_config().function_call.max_tokens + template = _env.from_string(TOOL_SELECT) + if TokenCalculator.calculate_token_length( + messages=[{"role": "user", "content": template.render( + goal=goal, tools=[], additional_info=additional_info + )}], + pure_text=True) > max_tokens: + logger.warning("[MCPSelector] 工具选择模板长度超过最大令牌数,无法进行选择") + return [] + llm = FunctionLLM() + current_index = 0 + tool_ids = [] + while current_index < len(tool_list): + index = current_index + sub_tools = [] + while index < len(tool_list): + tool = tool_list[index] + tokens = TokenCalculator.calculate_token_length( + messages=[{"role": "user", "content": template.render( + goal=goal, tools=[tool], + additional_info=additional_info + )}], + pure_text=True + ) + if tokens > max_tokens: + continue + sub_tools.append(tool) + + tokens = TokenCalculator.calculate_token_length(messages=[{"role": "user", "content": template.render( + goal=goal, tools=sub_tools, additional_info=additional_info)}, ], pure_text=True) + if tokens > max_tokens: + del sub_tools[-1] + break + else: + index += 1 + current_index = index + if sub_tools: + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": template.render(tools=sub_tools)}, + ] + schema = MCPToolIdsSelectResult.model_json_schema() + schema["properties"]["tool_ids"]["enum"] = [tool.id for tool in sub_tools] + result = await llm.call(messages=message, schema=schema) + try: + result = MCPToolIdsSelectResult.model_validate(result) + tool_ids.extend(result.tool_ids) + except Exception: + logger.exception("[MCPSelector] 解析MCP工具ID选择结果失败") + continue + mcp_tools = [tool for tool in tool_list if tool.id in tool_ids] + + if top_n is not None: + mcp_tools = mcp_tools[:top_n] + mcp_tools.append(MCPTool(id=FINAL_TOOL_ID, name="Final", + description="终止", mcp_id=FINAL_TOOL_ID, input_schema={})) + # mcp_tools.append(MCPTool(id=SUMMARIZE_TOOL_ID, name="Summarize", + # description="总结工具", mcp_id=SUMMARIZE_TOOL_ID, input_schema={})) + return mcp_tools diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index f6325369..b8144847 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -4,7 +4,9 @@ import asyncio import logging from datetime import UTC, datetime - +from apps.llm.reasoning import ReasoningLLM +from apps.schemas.config import LLMConfig +from apps.llm.patterns.rewrite import QuestionRewrite from apps.common.config import Config from apps.common.mongo import MongoDB from apps.common.queue import MessageQueue @@ -67,8 +69,8 @@ class Scheduler: except Exception as e: logger.error(f"[Scheduler] 活动监控过程中发生错误: {e}") - async def run(self) -> None: # noqa: PLR0911 - """运行调度器""" + async def get_llm_use_in_chat_with_rag(self) -> LLM: + """获取RAG大模型""" try: # 获取当前会话使用的大模型 llm_id = await LLMManager.get_llm_id_by_conversation_id( @@ -97,14 +99,25 @@ class Scheduler: logger.exception("[Scheduler] 获取大模型失败") await self.queue.close() return + + async def get_kb_ids_use_in_chat_with_rag(self) -> list[str]: + """获取知识库ID列表""" try: - # 获取当前会话使用的知识库 kb_ids = await KnowledgeBaseManager.get_kb_ids_by_conversation_id( - self.task.ids.user_sub, self.task.ids.conversation_id) + self.task.ids.user_sub, self.task.ids.conversation_id, + ) + if not kb_ids: + logger.error("[Scheduler] 获取知识库ID失败") + await self.queue.close() + return [] + return kb_ids except Exception: logger.exception("[Scheduler] 获取知识库ID失败") await self.queue.close() - return + return [] + + async def run(self) -> None: # noqa: PLR0911 + """运行调度器""" try: # 获取当前问答可供关联的文档 docs, doc_ids = await get_docs(self.task.ids.user_sub, self.post_body) @@ -114,13 +127,18 @@ class Scheduler: return history, _ = await get_context(self.task.ids.user_sub, self.post_body, 3) # 已使用文档 - # 如果是智能问答,直接执行 logger.info("[Scheduler] 开始执行") # 创建用于通信的事件 kill_event = asyncio.Event() monitor = asyncio.create_task(self._monitor_activity(kill_event, self.task.ids.user_sub)) if not self.post_body.app or self.post_body.app.app_id == "": + llm = await self.get_llm_use_in_chat_with_rag() + kb_ids = await self.get_kb_ids_use_in_chat_with_rag() + if not llm: + logger.error("[Scheduler] 获取大模型失败") + await self.queue.close() + return self.task = await push_init_message(self.task, self.queue, 3, is_flow=False) rag_data = RAGQueryReq( kbIds=kb_ids, @@ -199,6 +217,27 @@ class Scheduler: if not app_metadata: logger.error("[Scheduler] 未找到Agent应用") return + llm = await LLMManager.get_llm_by_id( + self.task.ids.user_sub, app_metadata.llm_id, + ) + if not llm: + logger.error("[Scheduler] 获取大模型失败") + await self.queue.close() + return + reasion_llm = ReasoningLLM( + LLMConfig( + endpoint=llm.openai_base_url, + key=llm.openai_api_key, + model=llm.model_name, + max_tokens=llm.max_tokens, + ) + ) + if background.conversation: + try: + question_obj = QuestionRewrite() + post_body.question = await question_obj.generate(history=background.conversation, question=post_body.question, llm=reasion_llm) + except Exception: + logger.exception("[Scheduler] 问题重写失败") if app_metadata.app_type == AppType.FLOW.value: logger.info("[Scheduler] 获取工作流元数据") flow_info = await Pool().get_flow_metadata(app_info.app_id) @@ -229,8 +268,6 @@ class Scheduler: # 初始化Executor logger.info("[Scheduler] 初始化Executor") - logger.error(f"{flow_data}") - logger.error(f"{self.task}") flow_exec = FlowExecutor( flow_id=flow_id, flow=flow_data, @@ -258,6 +295,7 @@ class Scheduler: servers_id=servers_id, background=background, agent_id=app_info.app_id, + params=post_body.app.params ) # 开始运行 logger.info("[Scheduler] 运行Executor") diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 3fb65028..3bcabd57 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -15,6 +15,7 @@ class SlotType(str, Enum): class StepStatus(str, Enum): """步骤状态""" UNKNOWN = "unknown" + INIT = "init" WAITING = "waiting" RUNNING = "running" SUCCESS = "success" @@ -55,12 +56,15 @@ class EventType(str, Enum): STEP_WAITING_FOR_START = "step.waiting_for_start" STEP_WAITING_FOR_PARAM = "step.waiting_for_param" FLOW_START = "flow.start" + STEP_INIT = "step.init" STEP_INPUT = "step.input" STEP_OUTPUT = "step.output" + STEP_CANCEL = "step.cancel" + STEP_ERROR = "step.error" FLOW_STOP = "flow.stop" FLOW_FAILED = "flow.failed" FLOW_SUCCESS = "flow.success" - FLOW_CANCELLED = "flow.cancelled" + FLOW_CANCEL = "flow.cancel" DONE = "done" diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 368865ac..21c403d4 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -111,6 +111,13 @@ class GoalEvaluationResult(BaseModel): reason: str = Field(description="评估原因") +class RestartStepIndex(BaseModel): + """MCP重新规划的步骤索引""" + + start_index: int = Field(description="重新规划的起始步骤索引") + reasoning: str = Field(description="重新规划的原因") + + class Risk(str, Enum): """MCP工具风险类型""" @@ -126,6 +133,20 @@ class ToolRisk(BaseModel): reason: str = Field(description="风险原因", default="") +class ErrorType(str, Enum): + """MCP工具错误类型""" + + MISSING_PARAM = "missing_param" + DECORRECT_PLAN = "decorrect_plan" + + +class ToolExcutionErrorType(BaseModel): + """MCP工具执行错误""" + + type: ErrorType = Field(description="错误类型", default=ErrorType.MISSING_PARAM) + reason: str = Field(description="错误原因", default="") + + class MCPSelectResult(BaseModel): """MCP选择结果""" @@ -138,6 +159,12 @@ class MCPToolSelectResult(BaseModel): name: str = Field(description="工具名称") +class MCPToolIdsSelectResult(BaseModel): + """MCP工具ID选择结果""" + + tool_ids: list[str] = Field(description="工具ID列表") + + class MCPPlanItem(BaseModel): """MCP 计划""" step_id: str = Field(description="步骤的ID", default="") diff --git a/apps/schemas/message.py b/apps/schemas/message.py index e7341324..1f46ff57 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -84,7 +84,7 @@ class FlowStartContent(BaseModel): """flow.start消息的content""" question: str = Field(description="用户问题") - params: dict[str, Any] = Field(description="预先提供的参数") + params: dict[str, Any] | None = Field(description="预先提供的参数", default=None) class MessageBase(HeartbeatData): @@ -95,5 +95,5 @@ class MessageBase(HeartbeatData): conversation_id: str = Field(min_length=36, max_length=36, alias="conversationId") task_id: str = Field(min_length=36, max_length=36, alias="taskId") flow: MessageFlow | None = None - content: dict[str, Any] = {} + content: Any | None = Field(default=None, description="消息内容") metadata: MessageMetadata diff --git a/apps/schemas/pool.py b/apps/schemas/pool.py index 27e16b37..7df6dab8 100644 --- a/apps/schemas/pool.py +++ b/apps/schemas/pool.py @@ -110,3 +110,6 @@ class AppPool(BaseData): flows: list[AppFlow] = Field(description="Flow列表", default=[]) hashes: dict[str, str] = Field(description="关联文件的hash值", default={}) mcp_service: list[str] = Field(default=[], alias="mcpService", description="MCP服务id列表") + llm_id: str = Field( + default="empty", alias="llmId", description="应用使用的大模型ID(如果有的话)" + ) diff --git a/apps/schemas/task.py b/apps/schemas/task.py index eccc95a5..336bfedc 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -30,6 +30,7 @@ class FlowStepHistory(BaseModel): step_status: StepStatus = Field(description="当前步骤状态") input_data: dict[str, Any] = Field(description="当前Step执行的输入", default={}) output_data: dict[str, Any] = Field(description="当前Step执行后的结果", default={}) + ex_data: dict[str, Any] | None = Field(description="额外数据", default=None) created_at: float = Field(default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3)) @@ -43,14 +44,13 @@ class ExecutorState(BaseModel): flow_status: FlowStatus = Field(description="Flow状态", default=FlowStatus.INIT) # 任务级数据 step_id: str = Field(description="当前步骤ID", default="") + step_index: int = Field(description="当前步骤索引", default=0) step_name: str = Field(description="当前步骤名称", default="") step_status: StepStatus = Field(description="当前步骤状态", default=StepStatus.UNKNOWN) step_description: str = Field(description="当前步骤描述", default="") app_id: str = Field(description="应用ID", default="") current_input: dict[str, Any] = Field(description="当前输入数据", default={}) - params: dict[str, Any] = Field(description="补充的参数", default={}) - params_description: str = Field(description="补充的参数描述", default="") - error_info: str = Field(description="错误信息", default="") + error_message: str = Field(description="错误信息", default="") retry_times: int = Field(description="当前步骤重试次数", default=0) -- Gitee From 842104a97f5ffb8096a9ab4d7a16e224cbf95981 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 5 Aug 2025 14:41:59 +0800 Subject: [PATCH 52/78] =?UTF-8?q?=E5=AE=8C=E5=96=84app=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?&record=E7=9A=84rask=E5=8F=AF=E4=BB=A5=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=BAnone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/appcenter.py | 15 ++++++++++++--- apps/routers/mcp_service.py | 2 ++ apps/schemas/appcenter.py | 10 +++++++++- apps/schemas/record.py | 4 ++-- apps/services/mcp_service.py | 6 ++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index 0ec4db91..df540eaf 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -9,7 +9,7 @@ from fastapi.responses import JSONResponse from apps.dependency.user import get_user, verify_user from apps.exceptions import InstancePermissionError -from apps.schemas.appcenter import AppFlowInfo, AppPermissionData +from apps.schemas.appcenter import AppFlowInfo, AppMcpServiceInfo, AppPermissionData from apps.schemas.enum_var import AppFilterType, AppType from apps.schemas.request_data import CreateAppRequest, ModFavAppRequest from apps.schemas.response_data import ( @@ -25,7 +25,7 @@ from apps.schemas.response_data import ( ResponseData, ) from apps.services.appcenter import AppCenterManager - +from apps.services.mcp_service import MCPServiceManager logger = logging.getLogger(__name__) router = APIRouter( prefix="/api/app", @@ -214,6 +214,15 @@ async def get_application( ) for flow in app_data.flows ] + mcp_service = [] + if app_data.mcp_service: + for service in app_data.mcp_service: + mcp_collection = await MCPServiceManager.get_mcp_service(service) + mcp_service.append(AppMcpServiceInfo( + id=mcp_collection.id, + name=mcp_collection.name, + description=mcp_collection.description, + )) return JSONResponse( status_code=status.HTTP_200_OK, content=GetAppPropertyRsp( @@ -234,7 +243,7 @@ async def get_application( authorizedUsers=app_data.permission.users, ), workflows=workflows, - mcpService=app_data.mcp_service, + mcpService=mcp_service, ), ).model_dump(exclude_none=True, by_alias=True), ) diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index de484e78..848780e2 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -53,6 +53,7 @@ async def get_mcpservice_list( ] = SearchType.ALL, keyword: Annotated[str | None, Query(..., alias="keyword", description="搜索关键字")] = None, page: Annotated[int, Query(..., alias="page", ge=1, description="页码")] = 1, + is_active: Annotated[bool | None, Query(None, alias="isActive", description="是否激活")] = None, ) -> JSONResponse: """获取服务列表""" try: @@ -61,6 +62,7 @@ async def get_mcpservice_list( user_sub, keyword, page, + is_active ) except Exception as e: err = f"[MCPServiceCenter] 获取MCP服务列表失败: {e}" diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index a89f39df..a65fffb2 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -50,6 +50,14 @@ class AppFlowInfo(BaseModel): debug: bool = Field(..., description="是否经过调试") +class AppMcpServiceInfo(BaseModel): + """应用关联的MCP服务信息""" + + id: str = Field(..., description="MCP服务ID") + name: str = Field(..., description="MCP服务名称") + description: str = Field(..., description="MCP服务简介") + + class AppData(BaseModel): """应用信息数据结构""" @@ -64,4 +72,4 @@ class AppData(BaseModel): permission: AppPermissionData = Field( default_factory=lambda: AppPermissionData(authorizedUsers=None), description="权限配置") workflows: list[AppFlowInfo] = Field(default=[], description="工作流信息列表") - mcp_service: list[str] = Field(default=[], alias="mcpService", description="MCP服务id列表") + mcp_service: list[AppMcpServiceInfo] = Field(default=[], alias="mcpService", description="MCP服务id列表") diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 6a394375..144a6c57 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -130,8 +130,8 @@ class Record(RecordData): user_sub: str key: dict[str, Any] = {} - task_id: str - content: str + task_id: str | None = Field(default=None, description="任务ID") + content: str = Field(default="", description="Record内容,已加密") comment: RecordComment = Field(default=RecordComment()) flow: FlowHistory = Field( default=FlowHistory(), description="Flow执行历史信息") diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index 2c84a211..ba510350 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -78,6 +78,7 @@ class MCPServiceManager: user_sub: str, keyword: str | None, page: int, + is_active: bool | None = None, ) -> list[MCPServiceCardItem]: """ 获取所有MCP服务列表 @@ -89,6 +90,11 @@ class MCPServiceManager: :return: MCP服务列表 """ filters = MCPServiceManager._build_filters(search_type, keyword) + if is_active is not None: + if is_active: + filters["activated"] = {"$in": [user_sub]} + else: + filters["activated"] = {"$nin": [user_sub]} mcpservice_pools = await MCPServiceManager._search_mcpservice(filters, page) return [ MCPServiceCardItem( -- Gitee From a537bf5ea71f958fdaa47b72997ea4b8d9381b9e Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 5 Aug 2025 14:58:39 +0800 Subject: [PATCH 53/78] =?UTF-8?q?=E5=8E=BB=E9=99=A4chat=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E7=9A=84new=5Ftask=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/chat.py | 2 +- apps/schemas/request_data.py | 1 - apps/services/record.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 06bc2dd7..f92efd45 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -41,7 +41,7 @@ async def init_task(post_body: RequestData, user_sub: str) -> Task: post_body.group_id = str(uuid.uuid4()) # 更改信息并刷新数据库 - if post_body.new_task: + if post_body.task_id is None: conversation = await ConversationManager.get_conversation_by_conversation_id( user_sub=user_sub, conversation_id=post_body.conversation_id, diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 8719c2e9..8d053e1c 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -48,7 +48,6 @@ class RequestData(BaseModel): app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") task_id: str | None = Field(default=None, alias="taskId", description="任务ID") - new_task: bool = Field(default=True, description="是否新建任务") class QuestionBlacklistRequest(BaseModel): diff --git a/apps/services/record.py b/apps/services/record.py index 6b61f91e..cf8373b0 100644 --- a/apps/services/record.py +++ b/apps/services/record.py @@ -142,7 +142,7 @@ class RecordManager: record_group_collection = MongoDB().get_collection("record_group") try: await record_group_collection.update_many( - {"records.flow.flow_id": {"$in": task_ids}, "records.flow.flow_status": {"$nin": [FlowStatus.ERROR.value, FlowStatus.SUCCESS.value]}}, + {"records.task_id": {"$in": task_ids}, "records.flow.flow_status": {"$nin": [FlowStatus.ERROR.value, FlowStatus.SUCCESS.value]}}, {"$set": {"records.$[elem].flow.flow_status": FlowStatus.CANCELLED}}, array_filters=[{"elem.flow.flow_id": {"$in": task_ids}}], ) -- Gitee From ed0d8fcbb1377b7aa9be9d467b2ffd5efe31816f Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 6 Aug 2025 11:15:21 +0800 Subject: [PATCH 54/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtask=E5=92=8Cscheduler?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/chat.py | 14 +++-- apps/routers/mcp_service.py | 2 +- apps/scheduler/executor/agent.py | 81 +++++++++++++-------------- apps/scheduler/executor/base.py | 6 +- apps/scheduler/scheduler/context.py | 1 - apps/scheduler/scheduler/scheduler.py | 20 ++----- apps/schemas/record.py | 2 +- apps/services/activity.py | 4 +- apps/services/task.py | 2 +- 9 files changed, 62 insertions(+), 70 deletions(-) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index f92efd45..5e035475 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -34,7 +34,7 @@ router = APIRouter( ) -async def init_task(post_body: RequestData, user_sub: str) -> Task: +async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> Task: """初始化Task""" # 生成group_id if not post_body.group_id: @@ -51,7 +51,9 @@ async def init_task(post_body: RequestData, user_sub: str) -> Task: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=err) task_ids = await TaskManager.delete_tasks_by_conversation_id(post_body.conversation_id) await RecordManager.update_record_flow_status_to_cancelled_by_task_ids(task_ids) - task = await TaskManager.init_new_task(user_sub=user_sub, conversation_id=post_body.conversation_id, post_body=post_body) + task = await TaskManager.init_new_task(user_sub=user_sub, session_id=session_id, post_body=post_body) + task.runtime.question = post_body.question + task.ids.group_id = post_body.group_id else: if not post_body.task_id: err = "[Chat] task_id 不可为空!" @@ -60,7 +62,7 @@ async def init_task(post_body: RequestData, user_sub: str) -> Task: return task -async def chat_generator(post_body: RequestData, user_sub: str) -> AsyncGenerator[str, None]: +async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) -> AsyncGenerator[str, None]: """进行实际问答,并从MQ中获取消息""" try: await Activity.set_active(user_sub) @@ -72,7 +74,7 @@ async def chat_generator(post_body: RequestData, user_sub: str) -> AsyncGenerato await Activity.remove_active(user_sub) return - task = await init_task(post_body, user_sub) + task = await init_task(post_body, user_sub, session_id) # 创建queue;由Scheduler进行关闭 queue = MessageQueue() @@ -80,6 +82,7 @@ async def chat_generator(post_body: RequestData, user_sub: str) -> AsyncGenerato # 在单独Task中运行Scheduler,拉齐queue.get的时机 scheduler = Scheduler(task, queue, post_body) + logger.info(f"[Chat] 用户是否活跃: {await Activity.is_active(user_sub)}") scheduler_task = asyncio.create_task(scheduler.run()) # 处理每一条消息 @@ -130,6 +133,7 @@ async def chat_generator(post_body: RequestData, user_sub: str) -> AsyncGenerato async def chat( post_body: RequestData, user_sub: Annotated[str, Depends(get_user)], + session_id: Annotated[str, Depends(get_session)], ) -> StreamingResponse: """LLM流式对话接口""" # 问题黑名单检测 @@ -142,7 +146,7 @@ async def chat( if await Activity.is_active(user_sub): raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests") - res = chat_generator(post_body, user_sub) + res = chat_generator(post_body, user_sub, session_id) return StreamingResponse( content=res, media_type="text/event-stream", diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index 848780e2..82fa72de 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -53,7 +53,7 @@ async def get_mcpservice_list( ] = SearchType.ALL, keyword: Annotated[str | None, Query(..., alias="keyword", description="搜索关键字")] = None, page: Annotated[int, Query(..., alias="page", ge=1, description="页码")] = 1, - is_active: Annotated[bool | None, Query(None, alias="isActive", description="是否激活")] = None, + is_active: Annotated[bool | None, Query(..., alias="isActive", description="是否激活")] = None, ) -> JSONResponse: """获取服务列表""" try: diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 4db38587..fc799fa1 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -28,7 +28,6 @@ from apps.schemas.message import param from apps.services.task import TaskManager from apps.services.appcenter import AppCenterManager from apps.services.mcp_service import MCPServiceManager -from apps.services.task import TaskManager from apps.services.user import UserManager logger = logging.getLogger(__name__) @@ -55,6 +54,12 @@ class MCPAgentExecutor(BaseExecutor): description="推理大模型", ) + async def update_tokens(self) -> None: + """更新令牌数""" + self.task.tokens.input_tokens = self.resoning_llm.input_tokens + self.task.tokens.output_tokens = self.resoning_llm.output_tokens + await TaskManager.save_task(self.task.id, self.task) + async def load_state(self) -> None: """从数据库中加载FlowExecutor的状态""" logger.info("[FlowExecutor] 加载Executor状态") @@ -108,8 +113,8 @@ class MCPAgentExecutor(BaseExecutor): max_steps=self.max_steps-start_index-1, reasoning_llm=self.resoning_llm ) - self.msg_queue.push_output( - self.task, + self.update_tokens() + self.push_message( EventType.STEP_CANCEL, data={} ) @@ -123,7 +128,7 @@ class MCPAgentExecutor(BaseExecutor): for i in range(start_index, len(self.task.runtime.temporary_plans.plans)): self.task.runtime.temporary_plans.plans[i].step_id = str(uuid.uuid4()) - async def get_tool_input_param(self, is_first: bool) -> dict[str, Any]: + async def get_tool_input_param(self, is_first: bool) -> None: if is_first: # 获取第一个输入参数 self.task.state.current_input = await MCPHost._get_first_input_params(self.tools[self.task.state.step_id], self.task.runtime.question, self.task) @@ -156,9 +161,10 @@ class MCPAgentExecutor(BaseExecutor): logger.info("[MCPAgentExecutor] 等待用户确认步骤 %d", self.task.state.step_index) # 发送确认消息 confirm_message = await MCPPlanner.get_tool_risk(self.tools[self.task.state.step_id], self.task.state.current_input, "", self.resoning_llm) - self.msg_queue.push_output(self.task, EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( + self.update_tokens() + self.push_message(EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( exclude_none=True, by_alias=True)) - self.msg_queue.push_output(self.task, EventType.FLOW_STOP, {}) + self.push_message(EventType.FLOW_STOP, {}) self.task.state.flow_status = FlowStatus.WAITING self.task.state.step_status = StepStatus.WAITING self.task.context.append( @@ -188,16 +194,15 @@ class MCPAgentExecutor(BaseExecutor): logger.error("[MCPAgentExecutor] MCP客户端未找到: %s", mcp_tool.mcp_id) self.task.state.flow_status = FlowStatus.ERROR error = "[MCPAgentExecutor] MCP客户端未找到: {}".format(mcp_tool.mcp_id) - raise Exception(error) + self.task.state.error_message = error try: output_params = await mcp_client.call_tool(mcp_tool.name, self.task.state.current_input) - self.msg_queue.push_output( - self.task, + self.update_tokens() + self.push_message( EventType.STEP_INPUT, self.task.state.current_input ) - self.msg_queue.push_output( - self.task, + self.push_message( EventType.STEP_OUTPUT, output_params ) @@ -216,7 +221,7 @@ class MCPAgentExecutor(BaseExecutor): ) self.task.state.step_status = StepStatus.SUCCESS except Exception as e: - logging.warning("[MCPAgentExecutor] 执行步骤 %s 失败: %s", mcp_tool.name, str(e)) + logger.warning("[MCPAgentExecutor] 执行步骤 %s 失败: %s", mcp_tool.name, str(e)) import traceback self.task.state.error_message = traceback.format_exc() self.task.state.step_status = StepStatus.ERROR @@ -230,14 +235,18 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.error_message, self.resoning_llm ) - self.msg_queue.push_output( - self.task, + self.update_tokens() + self.push_message( EventType.STEP_WAITING_FOR_PARAM, data={ "message": "当运行产生如下报错:\n" + self.task.state.error_message, "params": params_with_null } ) + self.push_message( + EventType.FLOW_STOP, + data={} + ) self.task.state.flow_status = FlowStatus.WAITING self.task.state.step_status = StepStatus.PARAM self.task.context.append( @@ -265,8 +274,7 @@ class MCPAgentExecutor(BaseExecutor): # 最后一步 self.task.state.flow_status = FlowStatus.SUCCESS self.task.state.step_status = StepStatus.SUCCESS - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_SUCCESS, data={} ) @@ -276,8 +284,7 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.step_description = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content self.task.state.step_status = StepStatus.INIT self.task.state.current_input = {} - self.msg_queue.push_output( - self.task, + self.push_message( EventType.STEP_INIT, data={} ) @@ -285,8 +292,7 @@ class MCPAgentExecutor(BaseExecutor): # 没有下一步了,结束流程 self.task.state.flow_status = FlowStatus.SUCCESS self.task.state.step_status = StepStatus.SUCCESS - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_SUCCESS, data={} ) @@ -296,8 +302,7 @@ class MCPAgentExecutor(BaseExecutor): """步骤执行失败后的错误处理""" self.task.state.step_status = StepStatus.ERROR self.task.state.flow_status = FlowStatus.ERROR - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_FAILED, data={} ) @@ -320,13 +325,13 @@ class MCPAgentExecutor(BaseExecutor): async def work(self) -> None: """执行当前步骤""" if self.task.state.step_status == StepStatus.INIT: - self.get_tool_input_param(is_first=True) + await self.get_tool_input_param(is_first=True) user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) if not user_info.auto_execute: # 等待用户确认 await self.confirm_before_step() return - self.step.state.step_status = StepStatus.RUNNING + self.task.state.step_status = StepStatus.RUNNING elif self.task.state.step_status in [StepStatus.PARAM, StepStatus.WAITING, StepStatus.RUNNING]: if self.task.context[-1].step_status == StepStatus.PARAM: if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: @@ -338,24 +343,22 @@ class MCPAgentExecutor(BaseExecutor): else: self.task.state.flow_status = FlowStatus.CANCELLED self.task.state.step_status = StepStatus.CANCELLED - self.msg_queue.push_output( - self.task, + self.push_message( EventType.STEP_CANCEL, data={} ) - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_CANCEL, data={} ) if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: self.task.context[-1].step_status = StepStatus.CANCELLED if self.task.state.step_status == StepStatus.PARAM: - self.get_tool_input_param(is_first=False) - max_retry = 5 + await self.get_tool_input_param(is_first=False) + max_retry = 5 for i in range(max_retry): if i != 0: - self.get_tool_input_param(is_first=False) + await self.get_tool_input_param(is_first=False) await self.run_step() if self.task.state.step_status == StepStatus.SUCCESS: break @@ -389,8 +392,7 @@ class MCPAgentExecutor(BaseExecutor): (await MCPHost.assemble_memory(self.task)), self.resoning_llm ): - self.msg_queue.push_output( - self.task, + self.push_message( EventType.TEXT_ADD, data=chunk ) @@ -405,32 +407,29 @@ class MCPAgentExecutor(BaseExecutor): # 初始化状态 self.task.state.flow_id = str(uuid.uuid4()) self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) - self.task.runtime.temporary_plans = await self.plan(is_replan=False) + await self.plan(is_replan=False) self.reset_step_to_index(0) TaskManager.save_task(self.task.id, self.task) self.task.state.flow_status = FlowStatus.RUNNING - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_START, data={} ) try: while self.task.state.step_index < len(self.task.runtime.temporary_plans) and \ self.task.state.flow_status == FlowStatus.RUNNING: - self.work() + await self.work() TaskManager.save_task(self.task.id, self.task) except Exception as e: logger.error("[MCPAgentExecutor] 执行过程中发生错误: %s", str(e)) self.task.state.flow_status = FlowStatus.ERROR self.task.state.error_message = str(e) self.task.state.step_status = StepStatus.ERROR - self.msg_queue.push_output( - self.task, + self.push_message( EventType.STEP_ERROR, data={} ) - self.msg_queue.push_output( - self.task, + self.push_message( EventType.FLOW_FAILED, data={} ) diff --git a/apps/scheduler/executor/base.py b/apps/scheduler/executor/base.py index cf2f4e68..8dcb99c7 100644 --- a/apps/scheduler/executor/base.py +++ b/apps/scheduler/executor/base.py @@ -49,10 +49,8 @@ class BaseExecutor(BaseModel, ABC): question=self.question, params=self.task.runtime.filled, ).model_dump(exclude_none=True, by_alias=True) - elif event_type == EventType.FLOW_STOP.value: - data = {} elif event_type == EventType.TEXT_ADD.value and isinstance(data, str): - data=TextAddContent(text=data).model_dump(exclude_none=True, by_alias=True) + data = TextAddContent(text=data).model_dump(exclude_none=True, by_alias=True) if data is None: data = {} @@ -62,7 +60,7 @@ class BaseExecutor(BaseModel, ABC): await self.msg_queue.push_output( self.task, event_type=event_type, - data=data, # type: ignore[arg-type] + data=data, # type: ignore[arg-type] ) @abstractmethod diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index 3b26f42f..dc35d4bd 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -158,7 +158,6 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: facts=task.runtime.facts, data={}, ) - try: # 加密Record数据 encrypt_data, encrypt_config = Security.encrypt(record_content.model_dump_json(by_alias=True)) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index b8144847..13eb7ee0 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -56,7 +56,6 @@ class Scheduler: while not kill_event.is_set(): # 检查用户活动状态 is_active = await Activity.is_active(user_sub) - if not is_active: logger.warning("[Scheduler] 用户 %s 不活跃,终止工作流", user_sub) kill_event.set() @@ -78,8 +77,7 @@ class Scheduler: ) if not llm_id: logger.error("[Scheduler] 获取大模型ID失败") - await self.queue.close() - return + return None if llm_id == "empty": llm = LLM( _id="empty", @@ -89,16 +87,16 @@ class Scheduler: model_name=Config().get_config().llm.model, max_tokens=Config().get_config().llm.max_tokens, ) + return llm else: llm = await LLMManager.get_llm_by_id(self.task.ids.user_sub, llm_id) if not llm: logger.error("[Scheduler] 获取大模型失败") - await self.queue.close() - return + return None + return llm except Exception: logger.exception("[Scheduler] 获取大模型失败") - await self.queue.close() - return + return None async def get_kb_ids_use_in_chat_with_rag(self) -> list[str]: """获取知识库ID列表""" @@ -106,10 +104,6 @@ class Scheduler: kb_ids = await KnowledgeBaseManager.get_kb_ids_by_conversation_id( self.task.ids.user_sub, self.task.ids.conversation_id, ) - if not kb_ids: - logger.error("[Scheduler] 获取知识库ID失败") - await self.queue.close() - return [] return kb_ids except Exception: logger.exception("[Scheduler] 获取知识库ID失败") @@ -135,10 +129,6 @@ class Scheduler: if not self.post_body.app or self.post_body.app.app_id == "": llm = await self.get_llm_use_in_chat_with_rag() kb_ids = await self.get_kb_ids_use_in_chat_with_rag() - if not llm: - logger.error("[Scheduler] 获取大模型失败") - await self.queue.close() - return self.task = await push_init_message(self.task, self.queue, 3, is_flow=False) rag_data = RAGQueryReq( kbIds=kb_ids, diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 144a6c57..dbc06b10 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -94,7 +94,7 @@ class RecordData(BaseModel): id: str group_id: str = Field(alias="groupId") conversation_id: str = Field(alias="conversationId") - task_id: str = Field(alias="taskId") + task_id: str | None = Field(default=None, alias="taskId") document: list[RecordDocument] = [] flow: RecordFlow | None = None content: RecordContent diff --git a/apps/services/activity.py b/apps/services/activity.py index 299a49a6..88142b9e 100644 --- a/apps/services/activity.py +++ b/apps/services/activity.py @@ -3,11 +3,13 @@ import uuid from datetime import UTC, datetime - +import logging from apps.common.mongo import MongoDB from apps.constants import SLIDE_WINDOW_QUESTION_COUNT, SLIDE_WINDOW_TIME from apps.exceptions import ActivityError +logger = logging.getLogger(__name__) + class Activity: """用户活动控制,限制单用户同一时间只能提问一个问题""" diff --git a/apps/services/task.py b/apps/services/task.py index 2f75a8c3..eec4e197 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -115,7 +115,6 @@ class TaskManager: @staticmethod async def init_new_task( - cls, user_sub: str, session_id: str | None = None, post_body: RequestData | None = None, @@ -180,6 +179,7 @@ class TaskManager: task_ids.append(task["_id"]) if task_ids: await task_collection.delete_many({"conversation_id": conversation_id}) + return task_ids except Exception: logger.exception("[TaskManager] 删除ConversationID的Task信息失败") return [] -- Gitee From 3197e3839a93b8e047e242d4982feb626dec5b00 Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 6 Aug 2025 20:26:45 +0800 Subject: [PATCH 55/78] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=A7=E6=A8=A1?= =?UTF-8?q?=E5=9E=8Burl=E5=A4=9A=E4=BD=99=E7=9A=84v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/mcp_agent/plan.py | 3 ++- deploy/chart/euler_copilot/configs/rag/.env | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 91d293fb..2d68dd59 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -72,11 +72,12 @@ class MCPPlanner: @staticmethod async def evaluate_goal( + goal: str, tool_list: list[MCPTool], resoning_llm: ReasoningLLM = ReasoningLLM()) -> GoalEvaluationResult: """评估用户目标的可行性""" # 获取推理结果 - result = await MCPPlanner._get_reasoning_evaluation(tool_list, resoning_llm) + result = await MCPPlanner._get_reasoning_evaluation(goal, tool_list, resoning_llm) # 解析为结构化数据 evaluation = await MCPPlanner._parse_evaluation_result(result) diff --git a/deploy/chart/euler_copilot/configs/rag/.env b/deploy/chart/euler_copilot/configs/rag/.env index 5e83f3f4..0708fd07 100644 --- a/deploy/chart/euler_copilot/configs/rag/.env +++ b/deploy/chart/euler_copilot/configs/rag/.env @@ -52,7 +52,7 @@ HALF_KEY3=${halfKey3} #LLM config MODEL_NAME={{ .Values.models.answer.name }} -OPENAI_API_BASE={{ .Values.models.answer.endpoint }}/v1 +OPENAI_API_BASE={{ .Values.models.answer.endpoint }} OPENAI_API_KEY={{ default "" .Values.models.answer.key }} MAX_TOKENS={{ default 2048 .Values.models.answer.maxTokens }} -- Gitee From 7f13e7239524cd495beaf571ba9ad6f7c81dd4ef Mon Sep 17 00:00:00 2001 From: zxstty Date: Wed, 6 Aug 2025 20:58:49 +0800 Subject: [PATCH 56/78] =?UTF-8?q?app=E5=A2=9E=E5=8A=A0llm=20id=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/scheduler/scheduler.py | 16 +++++++++++++--- apps/schemas/agent.py | 3 ++- apps/schemas/appcenter.py | 1 + apps/schemas/flow.py | 1 + apps/services/appcenter.py | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index 13eb7ee0..523587e3 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -207,9 +207,19 @@ class Scheduler: if not app_metadata: logger.error("[Scheduler] 未找到Agent应用") return - llm = await LLMManager.get_llm_by_id( - self.task.ids.user_sub, app_metadata.llm_id, - ) + if app_metadata.llm_id == "empty": + llm = LLM( + _id="empty", + user_sub=self.task.ids.user_sub, + openai_base_url=Config().get_config().llm.endpoint, + openai_api_key=Config().get_config().llm.key, + model_name=Config().get_config().llm.model, + max_tokens=Config().get_config().llm.max_tokens, + ) + else: + llm = await LLMManager.get_llm_by_id( + self.task.ids.user_sub, app_metadata.llm_id, + ) if not llm: logger.error("[Scheduler] 获取大模型失败") await self.queue.close() diff --git a/apps/schemas/agent.py b/apps/schemas/agent.py index b52f5e1c..16e818e4 100644 --- a/apps/schemas/agent.py +++ b/apps/schemas/agent.py @@ -17,6 +17,7 @@ class AgentAppMetadata(MetadataBase): app_type: AppType = Field(default=AppType.AGENT, description="应用类型", frozen=True) published: bool = Field(description="是否发布", default=False) history_len: int = Field(description="对话轮次", default=3, le=10) - mcp_service: list[str] = Field(default=[], alias="mcpService", description="MCP服务id列表") + mcp_service: list[str] = Field(default=[], description="MCP服务id列表") + llm_id: str = Field(default="empty", description="大模型ID") permission: Permission | None = Field(description="应用权限配置", default=None) version: str = Field(description="元数据版本") diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index a65fffb2..2f0549b2 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -69,6 +69,7 @@ class AppData(BaseModel): first_questions: list[str] = Field( default=[], alias="recommendedQuestions", description="推荐问题", max_length=3) history_len: int = Field(3, alias="dialogRounds", ge=1, le=10, description="对话轮次(1~10)") + llm_id: str = Field(default="empty", alias="llmId", description="大模型ID") permission: AppPermissionData = Field( default_factory=lambda: AppPermissionData(authorizedUsers=None), description="权限配置") workflows: list[AppFlowInfo] = Field(default=[], description="工作流信息列表") diff --git a/apps/schemas/flow.py b/apps/schemas/flow.py index 2646d043..dfffd1f1 100644 --- a/apps/schemas/flow.py +++ b/apps/schemas/flow.py @@ -136,6 +136,7 @@ class AppMetadata(MetadataBase): published: bool = Field(description="是否发布", default=False) links: list[AppLink] = Field(description="相关链接", default=[]) first_questions: list[str] = Field(description="首次提问", default=[]) + llm_id: str = Field(description="大模型ID", default="empty") history_len: int = Field(description="对话轮次", default=3, le=10) permission: Permission | None = Field(description="应用权限配置", default=None) flows: list[AppFlow] = Field(description="Flow列表", default=[]) diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index e256ab55..559accc2 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -409,6 +409,7 @@ class AppCenterManager: "name": source.name, "description": source.description, "history_len": source.history_len, + "llm_id": source.llm_id, } @staticmethod -- Gitee From cdcededc1c2c7cc2942755950ec69c82daa0f142 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 7 Aug 2025 22:22:47 +0800 Subject: [PATCH 57/78] =?UTF-8?q?=E5=B0=86mcp=E6=B3=A8=E5=86=8C&=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E6=8B=86=E5=88=86=E4=B8=BA=E4=B8=A4=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/llm/embedding.py | 24 ++- apps/main.py | 1 + apps/routers/mcp_service.py | 31 +++- .../call/choice/condition_handler.py | 4 - apps/scheduler/executor/agent.py | 3 + apps/scheduler/pool/loader/mcp.py | 168 ++++++++++-------- apps/scheduler/pool/loader/service.py | 8 +- apps/scheduler/pool/mcp/client.py | 25 ++- apps/scheduler/pool/mcp/install.py | 83 +++++---- apps/scheduler/pool/pool.py | 11 +- apps/schemas/appcenter.py | 12 +- apps/schemas/mcp.py | 10 +- apps/schemas/request_data.py | 4 +- apps/schemas/response_data.py | 9 + apps/services/appcenter.py | 4 +- apps/services/mcp_service.py | 62 +++++-- apps/services/parameter.py | 2 +- openapi.json | 1 + pyproject.toml | 2 +- 19 files changed, 300 insertions(+), 164 deletions(-) create mode 100644 openapi.json diff --git a/apps/llm/embedding.py b/apps/llm/embedding.py index 28ab86b4..df13044a 100644 --- a/apps/llm/embedding.py +++ b/apps/llm/embedding.py @@ -1,8 +1,9 @@ """Embedding模型""" import httpx - +import logging from apps.common.config import Config +logger = logging.getLogger(__name__) class Embedding: @@ -15,7 +16,6 @@ class Embedding: embedding = await cls.get_embedding(["测试文本"]) return len(embedding[0]) - @classmethod async def _get_openai_embedding(cls, text: list[str]) -> list[list[float]]: """访问OpenAI兼容的Embedding API,获得向量化数据""" @@ -75,10 +75,18 @@ class Embedding: :param text: 待向量化文本(多条文本组成List) :return: 文本对应的向量(顺序与text一致,也为List) """ - if Config().get_config().embedding.type == "openai": - return await cls._get_openai_embedding(text) - if Config().get_config().embedding.type == "mindie": - return await cls._get_tei_embedding(text) + try: + if Config().get_config().embedding.type == "openai": + return await cls._get_openai_embedding(text) + if Config().get_config().embedding.type == "mindie": + return await cls._get_tei_embedding(text) - err = f"不支持的Embedding API类型: {Config().get_config().embedding.type}" - raise ValueError(err) + err = f"不支持的Embedding API类型: {Config().get_config().embedding.type}" + raise ValueError(err) + except Exception as e: + err = f"获取Embedding失败: {e}" + logger.error(err) + rt = [] + for i in range(len(text)): + rt.append([0.0]*1024) + return rt diff --git a/apps/main.py b/apps/main.py index 58e2bd40..3c869d3a 100644 --- a/apps/main.py +++ b/apps/main.py @@ -101,6 +101,7 @@ async def add_no_auth_user() -> None: await user_collection.insert_one(User( _id=username, is_admin=True, + auto_execute=False ).model_dump(by_alias=True)) except Exception as e: logging.warning(f"添加无认证用户失败: {e}") diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index 82fa72de..411b9963 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -92,7 +92,7 @@ async def get_mcpservice_list( @router.post("", response_model=UpdateMCPServiceRsp) async def create_or_update_mcpservice( user_sub: Annotated[str, Depends(get_user)], # TODO: get_user直接获取所有用户信息 - data: UpdateMCPServiceRequest, + data: UpdateMCPServiceRequest ) -> JSONResponse: """新建或更新MCP服务""" await _check_user_admin(user_sub) @@ -133,6 +133,35 @@ async def create_or_update_mcpservice( ).model_dump(exclude_none=True, by_alias=True)) +@router.post("/{serviceId}/install") +async def install_mcp_service( + user_sub: Annotated[str, Depends(get_user)], + service_id: Annotated[str, Path(..., alias="serviceId", description="服务ID")], + install: Annotated[bool, Query(..., description="是否安装")] = True, +) -> JSONResponse: + try: + await MCPServiceManager.install_mcpservice(user_sub, service_id, install) + except Exception as e: + err = f"[MCPService] 安装mcp服务失败: {e!s}" if install else f"[MCPService] 卸载mcp服务失败: {e!s}" + logger.exception(err) + return JSONResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content=ResponseData( + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + message=err, + result={}, + ).model_dump(exclude_none=True, by_alias=True), + ) + return JSONResponse( + status_code=status.HTTP_200_OK, + content=ResponseData( + code=status.HTTP_200_OK, + message="OK", + result={}, + ).model_dump(exclude_none=True, by_alias=True), + ) + + @router.get("/{serviceId}", response_model=GetMCPServiceDetailRsp) async def get_service_detail( user_sub: Annotated[str, Depends(get_user)], diff --git a/apps/scheduler/call/choice/condition_handler.py b/apps/scheduler/call/choice/condition_handler.py index 6f10f2c8..261809ad 100644 --- a/apps/scheduler/call/choice/condition_handler.py +++ b/apps/scheduler/call/choice/condition_handler.py @@ -236,10 +236,6 @@ class ConditionHandler(BaseModel): return left_value == right_value elif operate == BoolOperate.NOT_EQUAL: return left_value != right_value - elif operate == BoolOperate.IS_EMPTY: - return not left_value - elif operate == BoolOperate.NOT_EMPTY: - return left_value return False @staticmethod diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index fc799fa1..aaa088ec 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -448,3 +448,6 @@ class MCPAgentExecutor(BaseExecutor): output_data={}, ) ) + finally: + for client in self.mcp_client.values(): + await client.stop() diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index 648baa53..2be0fe5d 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -92,48 +92,48 @@ class MCPLoader(metaclass=SingletonMeta): :param MCPServerConfig config: MCP配置 :return: 无 """ - if not config.config.auto_install: - print(f"[Installer] MCP模板无需安装: {mcp_id}") # noqa: T201 - - elif isinstance(config.config, MCPServerStdioConfig): - print(f"[Installer] Stdio方式的MCP模板,开始自动安装: {mcp_id}") # noqa: T201 - if "uv" in config.config.command: - new_config = await install_uvx(mcp_id, config.config) - elif "npx" in config.config.command: - new_config = await install_npx(mcp_id, config.config) - - if new_config is None: - logger.error("[MCPLoader] MCP模板安装失败: %s", mcp_id) - await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.FAILED) - return - - config.config = new_config - - # 重新保存config - template_config = MCP_PATH / "template" / mcp_id / "config.json" - f = await template_config.open("w+", encoding="utf-8") - config_data = config.model_dump(by_alias=True, exclude_none=True) - await f.write(json.dumps(config_data, indent=4, ensure_ascii=False)) - await f.aclose() - - else: - print(f"[Installer] SSE/StreamableHTTP方式的MCP模板,无需安装: {mcp_id}") # noqa: T201 - config.config.auto_install = False - - print(f"[Installer] MCP模板安装成功: {mcp_id}") # noqa: T201 - await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.READY) - await MCPLoader._insert_template_tool(mcp_id, config) + try: + if not config.config.auto_install: + print(f"[Installer] MCP模板无需安装: {mcp_id}") # noqa: T201 + + elif isinstance(config.config, MCPServerStdioConfig): + print(f"[Installer] Stdio方式的MCP模板,开始自动安装: {mcp_id}") # noqa: T201 + if "uv" in config.config.command: + new_config = await install_uvx(mcp_id, config.config) + elif "npx" in config.config.command: + new_config = await install_npx(mcp_id, config.config) + + if new_config is None: + logger.error("[MCPLoader] MCP模板安装失败: %s", mcp_id) + await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.FAILED) + return + + config.config = new_config + + # 重新保存config + template_config = MCP_PATH / "template" / mcp_id / "config.json" + f = await template_config.open("w+", encoding="utf-8") + config_data = config.model_dump(by_alias=True, exclude_none=True) + await f.write(json.dumps(config_data, indent=4, ensure_ascii=False)) + await f.aclose() + + else: + logger.info(f"[Installer] SSE/StreamableHTTP方式的MCP模板,无需安装: {mcp_id}") # noqa: T201 + config.config.auto_install = False + + await MCPLoader._insert_template_tool(mcp_id, config) + await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.READY) + logger.info(f"[Installer] MCP模板安装成功: {mcp_id}") # noqa: T201 + except Exception as e: + logger.error("[MCPLoader] MCP模板安装失败: %s, 错误: %s", mcp_id, e) + await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.FAILED) + raise @staticmethod - async def init_one_template(mcp_id: str, config: MCPServerConfig) -> None: + async def clear_ready_or_failed_mcp_installation() -> None: """ - 初始化单个MCP模板 - - :param str mcp_id: MCP模板ID - :param MCPServerConfig config: MCP配置 - :return: 无 + 清除状态为ready或failed的MCP安装任务 """ - # 删除完成或者失败的MCP安装任务 mcp_collection = MongoDB().get_collection("mcp") mcp_ids = ProcessHandler.get_all_task_ids() # 检索_id在mcp_ids且状态为ready或者failed的MCP的内容 @@ -148,8 +148,17 @@ class MCPLoader(metaclass=SingletonMeta): continue ProcessHandler.remove_task(item.id) logger.info("[MCPLoader] 删除已完成或失败的MCP安装进程: %s", item.id) - # 插入数据库;这里用旧的config就可以 - await MCPLoader._insert_template_db(mcp_id, config) + + @staticmethod + async def init_one_template(mcp_id: str, config: MCPServerConfig) -> None: + """ + 初始化单个MCP模板 + + :param str mcp_id: MCP模板ID + :param MCPServerConfig config: MCP配置 + :return: 无 + """ + await MCPLoader.clear_ready_or_failed_mcp_installation() # 检查目录 template_path = MCP_PATH / "template" / mcp_id @@ -159,37 +168,31 @@ class MCPLoader(metaclass=SingletonMeta): err = f"安装任务无法执行,请稍后重试: {mcp_id}" logger.error(err) raise RuntimeError(err) + # 将installing状态的安装任务的状态变为cancelled @staticmethod - async def _init_all_template() -> None: + async def cancel_all_installing_task() -> None: """ - 初始化所有MCP模板 - - 遍历 ``template`` 目录下的所有MCP模板,并初始化。在Framework启动时进行此流程,确保所有MCP均可正常使用。 - 这一过程会与数据库内的条目进行对比,若发生修改,则重新创建数据库条目。 + 取消正在安装的MCP模板任务 """ template_path = MCP_PATH / "template" logger.info("[MCPLoader] 初始化所有MCP模板: %s", template_path) - + mongo = MongoDB() + mcp_collection = mongo.get_collection("mcp") # 遍历所有模板 + mcp_ids = [] async for mcp_dir in template_path.iterdir(): # 不是目录 if not await mcp_dir.is_dir(): logger.warning("[MCPLoader] 跳过非目录: %s", mcp_dir.as_posix()) continue - # 检查配置文件是否存在 - config_path = mcp_dir / "config.json" - if not await config_path.exists(): - logger.warning("[MCPLoader] 跳过没有配置文件的MCP模板: %s", mcp_dir.as_posix()) - continue - - # 读取配置并加载 - config = await MCPLoader._load_config(config_path) - - # 初始化第一个MCP Server - logger.info("[MCPLoader] 初始化MCP模板: %s", mcp_dir.as_posix()) - await MCPLoader.init_one_template(mcp_dir.name, config) + mcp_ids.append(mcp_dir.name) + # 更新数据库状态 + await mcp_collection.update_many( + {"_id": {"$in": mcp_ids}, "status": MCPInstallStatus.INSTALLING}, + {"$set": {"status": MCPInstallStatus.CANCELLED}}, + ) @staticmethod async def _get_template_tool( @@ -392,7 +395,7 @@ class MCPLoader(metaclass=SingletonMeta): ) @staticmethod - async def user_active_template(user_sub: str, mcp_id: str, mcp_env: dict[str, Any]) -> None: + async def user_active_template(user_sub: str, mcp_id: str, mcp_env: dict[str, Any] | None = None) -> None: """ 用户激活MCP模板 @@ -411,7 +414,6 @@ class MCPLoader(metaclass=SingletonMeta): err = f"MCP模板“{mcp_id}”已存在或有同名文件,无法激活" raise FileExistsError(err) mcp_config = await MCPLoader.get_config(mcp_id) - mcp_config.config.env.update(mcp_env) # 拷贝文件 await asyncer.asyncify(shutil.copytree)( template_path.as_posix(), @@ -419,17 +421,19 @@ class MCPLoader(metaclass=SingletonMeta): dirs_exist_ok=True, symlinks=True, ) - user_config_path = user_path / "config.json" - # 更新用户配置 - f = await user_config_path.open("w", encoding="utf-8", errors="ignore") - await f.write( - json.dumps( - mcp_config.model_dump(by_alias=True, exclude_none=True), - indent=4, - ensure_ascii=False, + if mcp_env is not None: + mcp_config.config.env.update(mcp_env) + user_config_path = user_path / "config.json" + # 更新用户配置 + f = await user_config_path.open("w", encoding="utf-8", errors="ignore") + await f.write( + json.dumps( + mcp_config.model_dump(by_alias=True, exclude_none=True), + indent=4, + ensure_ascii=False, + ) ) - ) - await f.aclose() + await f.aclose() # 更新数据库 mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") @@ -480,6 +484,26 @@ class MCPLoader(metaclass=SingletonMeta): logger.info("[MCPLoader] 这些MCP在文件系统中被删除: %s", deleted_mcp_list) return deleted_mcp_list + @staticmethod + async def cancel_installing_task(cancel_mcp_list: list[str]) -> None: + """ + 取消正在安装的MCP模板任务 + + :param list[str] cancel_mcp_list: 需要取消的MCP列表 + :return: 无 + """ + mongo = MongoDB() + mcp_collection = mongo.get_collection("mcp") + # 更新数据库状态 + cancel_mcp_list = await mcp_collection.distinct("_id", {"_id": {"$in": cancel_mcp_list}, "status": MCPInstallStatus.INSTALLING}) + await mcp_collection.update_many( + {"_id": {"$in": cancel_mcp_list}, "status": MCPInstallStatus.INSTALLING}, + {"$set": {"status": MCPInstallStatus.CANCELLED}}, + ) + for mcp_id in cancel_mcp_list: + ProcessHandler.remove_task(mcp_id) + logger.info("[MCPLoader] 取消这些正在安装的MCP模板任务: %s", cancel_mcp_list) + @staticmethod async def remove_deleted_mcp(deleted_mcp_list: list[str]) -> None: """ @@ -585,8 +609,8 @@ class MCPLoader(metaclass=SingletonMeta): # 检查目录 await MCPLoader._check_dir() - # 初始化所有模板 - await MCPLoader._init_all_template() + # 暂停所有安装任务 + await MCPLoader.cancel_all_installing_task() # 加载用户MCP await MCPLoader._load_user_mcp() diff --git a/apps/scheduler/pool/loader/service.py b/apps/scheduler/pool/loader/service.py index 2b906046..2d84069c 100644 --- a/apps/scheduler/pool/loader/service.py +++ b/apps/scheduler/pool/loader/service.py @@ -3,6 +3,7 @@ import asyncio import logging +import os import shutil from anyio import Path @@ -30,6 +31,9 @@ class ServiceLoader: """加载单个Service""" service_path = BASE_PATH / service_id # 载入元数据 + if not os.path.exists(service_path / "metadata.yaml"): + logger.error("[ServiceLoader] Service %s 的元数据不存在", service_id) + return metadata = await MetadataLoader().load_one(service_path / "metadata.yaml") if not isinstance(metadata, ServiceMetadata): err = f"[ServiceLoader] 元数据类型错误: {service_path}/metadata.yaml" @@ -48,7 +52,6 @@ class ServiceLoader: # 更新数据库 await self._update_db(nodes, metadata) - async def save(self, service_id: str, metadata: ServiceMetadata, data: dict) -> None: """在文件系统上保存Service,并更新数据库""" service_path = BASE_PATH / service_id @@ -67,7 +70,6 @@ class ServiceLoader: await file_checker.diff_one(service_path) await self.load(service_id, file_checker.hashes[f"service/{service_id}"]) - async def delete(self, service_id: str, *, is_reload: bool = False) -> None: """删除Service,并更新数据库""" mongo = MongoDB() @@ -95,7 +97,6 @@ class ServiceLoader: if await path.exists(): shutil.rmtree(path) - async def _update_db(self, nodes: list[NodePool], metadata: ServiceMetadata) -> None: # noqa: C901, PLR0912, PLR0915 """更新数据库""" if not metadata.hashes: @@ -197,4 +198,3 @@ class ServiceLoader: await asyncio.sleep(0.01) else: raise - diff --git a/apps/scheduler/pool/mcp/client.py b/apps/scheduler/pool/mcp/client.py index 092bac89..f2fd4400 100644 --- a/apps/scheduler/pool/mcp/client.py +++ b/apps/scheduler/pool/mcp/client.py @@ -29,6 +29,7 @@ class MCPClient: mcp_id: str task: asyncio.Task ready_sign: asyncio.Event + error_sign: asyncio.Event stop_sign: asyncio.Event client: ClientSession status: MCPStatus @@ -64,7 +65,6 @@ class MCPClient: else: cwd = MCP_PATH / "template" / mcp_id / "project" await cwd.mkdir(parents=True, exist_ok=True) - client = stdio_client(server=StdioServerParameters( command=config.command, args=config.args, @@ -72,6 +72,7 @@ class MCPClient: cwd=cwd.as_posix(), )) else: + self.error_sign.set() err = f"[MCPClient] MCP {mcp_id}:未知的MCP服务类型“{config.type}”" logger.error(err) raise TypeError(err) @@ -85,6 +86,8 @@ class MCPClient: # 初始化Client await session.initialize() except Exception: + self.error_sign.set() + self.status = MCPStatus.STOPPED logger.exception("[MCPClient] MCP %s:初始化失败", mcp_id) raise @@ -96,12 +99,11 @@ class MCPClient: # 关闭Client try: - await exit_stack.aclose() # type: ignore[attr-defined] + await exit_stack.aclose() # type: ignore[attr-defined] self.status = MCPStatus.STOPPED except Exception: logger.exception("[MCPClient] MCP %s:关闭失败", mcp_id) - async def init(self, user_sub: str | None, mcp_id: str, config: MCPServerSSEConfig | MCPServerStdioConfig) -> None: """ 初始化 MCP Client类 @@ -116,23 +118,30 @@ class MCPClient: # 初始化变量 self.mcp_id = mcp_id self.ready_sign = asyncio.Event() + self.error_sign = asyncio.Event() self.stop_sign = asyncio.Event() # 创建协程 self.task = asyncio.create_task(self._main_loop(user_sub, mcp_id, config)) # 等待初始化完成 - await self.ready_sign.wait() - - # 获取工具列表 + done, pending = await asyncio.wait( + [asyncio.create_task(self.ready_sign.wait()), + asyncio.create_task(self.error_sign.wait())], + return_when=asyncio.FIRST_COMPLETED + ) + if self.error_sign.is_set(): + self.status = MCPStatus.ERROR + logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) + raise Exception(f"MCP {mcp_id} 初始化失败") + + # 获取工具列表 self.tools = (await self.client.list_tools()).tools - async def call_tool(self, tool_name: str, params: dict) -> "CallToolResult": """调用MCP Server的工具""" return await self.client.call_tool(tool_name, params) - async def stop(self) -> None: """停止MCP Client""" self.stop_sign.set() diff --git a/apps/scheduler/pool/mcp/install.py b/apps/scheduler/pool/mcp/install.py index 1b6c3ede..2b15cd69 100644 --- a/apps/scheduler/pool/mcp/install.py +++ b/apps/scheduler/pool/mcp/install.py @@ -3,12 +3,16 @@ from asyncio import subprocess from typing import TYPE_CHECKING - +import logging +import os +import shutil from apps.constants import MCP_PATH if TYPE_CHECKING: from apps.schemas.mcp import MCPServerStdioConfig +logger = logging.getLogger(__name__) + async def install_uvx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServerStdioConfig | None": """ @@ -23,27 +27,35 @@ async def install_uvx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer :rtype: MCPServerStdioConfig :raises ValueError: 未找到MCP Server对应的Python包 """ - # 创建文件夹 - mcp_path = MCP_PATH / "template" / mcp_id / "project" - await mcp_path.mkdir(parents=True, exist_ok=True) - + uv_path = shutil.which('uv') + if uv_path is None: + error = "[Installer] 未找到uv命令,请先安装uv包管理器: pip install uv" + logging.error(error) + raise Exception(error) # 找到包名 - package = "" + package = None for arg in config.args: if not arg.startswith("-"): package = arg break - + logger.error(f"[Installer] MCP包名: {package}") if not package: print("[Installer] 未找到包名") # noqa: T201 return None - + # 创建文件夹 + mcp_path = MCP_PATH / "template" / mcp_id / "project" + logger.error(f"[Installer] MCP安装路径: {mcp_path}") + await mcp_path.mkdir(parents=True, exist_ok=True) # 如果有pyproject.toml文件,则使用sync + flag = await (mcp_path / "pyproject.toml").exists() + logger.error(f"[Installer] MCP安装标志: {flag}") if await (mcp_path / "pyproject.toml").exists(): + shell_command = f"{uv_path} venv; {uv_path} sync --index-url https://pypi.tuna.tsinghua.edu.cn/simple --active --no-install-project --no-cache" + logger.error(f"[Installer] MCP安装命令: {shell_command}") pipe = await subprocess.create_subprocess_shell( ( - "uv venv; " - "uv sync --index-url https://pypi.tuna.tsinghua.edu.cn/simple --active " + f"{uv_path} venv; " + f"{uv_path} sync --index-url https://pypi.tuna.tsinghua.edu.cn/simple --active " "--no-install-project --no-cache" ), stdout=subprocess.PIPE, @@ -57,19 +69,20 @@ async def install_uvx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer return None print(f"[Installer] 检查依赖成功: {mcp_path}; {stdout.decode() if stdout else '(无输出信息)'}") # noqa: T201 - config.command = "uv" - config.args = ["run", *config.args] + config.command = uv_path + if "run" not in config.args: + config.args = ["run", *config.args] config.auto_install = False - + logger.error(f"[Installer] MCP安装配置更新成功: {config}") return config # 否则,初始化uv项目 pipe = await subprocess.create_subprocess_shell( ( - f"uv init; " - f"uv venv; " - f"uv add --index-url https://pypi.tuna.tsinghua.edu.cn/simple {package}; " - f"uv sync --index-url https://pypi.tuna.tsinghua.edu.cn/simple --active " + f"{uv_path} init; " + f"{uv_path} venv; " + f"{uv_path} add --index-url https://pypi.tuna.tsinghua.edu.cn/simple {package}; " + f"{uv_path} sync --index-url https://pypi.tuna.tsinghua.edu.cn/simple --active " f"--no-install-project --no-cache" ), stdout=subprocess.PIPE, @@ -84,8 +97,9 @@ async def install_uvx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer print(f"[Installer] 安装 {package} 成功: {mcp_path}; {stdout.decode() if stdout else '(无输出信息)'}") # noqa: T201 # 更新配置 - config.command = "uv" - config.args = ["run", *config.args] + config.command = uv_path + if "run" not in config.args: + config.args = ["run", *config.args] config.auto_install = False return config @@ -103,17 +117,13 @@ async def install_npx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer :rtype: MCPServerStdioConfig :raises ValueError: 未找到MCP Server对应的npm包 """ - mcp_path = MCP_PATH / "template" / mcp_id / "project" - await mcp_path.mkdir(parents=True, exist_ok=True) - - # 如果有node_modules文件夹,则认为已安装 - if await (mcp_path / "node_modules").exists(): - config.command = "npm" - config.args = ["exec", *config.args] - return config - + npm_path = shutil.which('npm') + if npm_path is None: + error = "[Installer] 未找到npm命令,请先安装Node.js和npm" + logging.error(error) + raise Exception(error) # 查找package name - package = "" + package = None for arg in config.args: if not arg.startswith("-"): package = arg @@ -122,10 +132,18 @@ async def install_npx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer if not package: print("[Installer] 未找到包名") # noqa: T201 return None + mcp_path = MCP_PATH / "template" / mcp_id / "project" + await mcp_path.mkdir(parents=True, exist_ok=True) + # 如果有node_modules文件夹,则认为已安装 + if await (mcp_path / "node_modules").exists(): + config.command = npm_path + if "exec" not in config.args: + config.args = ["exec", *config.args] + return config # 安装NPM包 pipe = await subprocess.create_subprocess_shell( - f"npm install {package}", + f"{npm_path} install {package}", stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=mcp_path, @@ -137,8 +155,9 @@ async def install_npx(mcp_id: str, config: "MCPServerStdioConfig") -> "MCPServer print(f"[Installer] 安装 {package} 成功: {mcp_path}; {stdout.decode() if stdout else '(无输出信息)'}") # noqa: T201 # 更新配置 - config.command = "npm" - config.args = ["exec", *config.args] + config.command = npm_path + if "exec" not in config.args: + config.args = ["exec", *config.args] config.auto_install = False return config diff --git a/apps/scheduler/pool/pool.py b/apps/scheduler/pool/pool.py index 7710d24d..ead552fc 100644 --- a/apps/scheduler/pool/pool.py +++ b/apps/scheduler/pool/pool.py @@ -60,7 +60,6 @@ class Pool: await Path(root_dir + "mcp").unlink(missing_ok=True) await Path(root_dir + "mcp").mkdir(parents=True, exist_ok=True) - @staticmethod async def init() -> None: """ @@ -121,13 +120,15 @@ class Pool: for app in changed_app: hash_key = Path("app/" + app).as_posix() if hash_key in checker.hashes: - await app_loader.load(app, checker.hashes[hash_key]) - + try: + await app_loader.load(app, checker.hashes[hash_key]) + except Exception as e: + await app_loader.delete(app, is_reload=True) + logger.warning("[Pool] 加载App %s 失败: %s", app, e) # 载入MCP logger.info("[Pool] 载入MCP") await MCPLoader.init() - async def get_flow_metadata(self, app_id: str) -> list[AppFlow]: """从数据库中获取特定App的全部Flow的元数据""" mongo = MongoDB() @@ -145,14 +146,12 @@ class Pool: else: return flow_metadata_list - async def get_flow(self, app_id: str, flow_id: str) -> Flow | None: """从文件系统中获取单个Flow的全部数据""" logger.info("[Pool] 获取工作流 %s", flow_id) flow_loader = FlowLoader() return await flow_loader.load(app_id, flow_id) - async def get_call(self, call_id: str) -> Any: """[Exception] 拿到Call的信息""" # 从MongoDB里拿到数据 diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index 2f0549b2..b33bfa2f 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -45,17 +45,17 @@ class AppFlowInfo(BaseModel): """应用工作流数据结构""" id: str = Field(..., description="工作流ID") - name: str = Field(..., description="工作流名称") - description: str = Field(..., description="工作流简介") - debug: bool = Field(..., description="是否经过调试") + name: str = Field(default="", description="工作流名称") + description: str = Field(default="", description="工作流简介") + debug: bool = Field(default=False, description="是否经过调试") class AppMcpServiceInfo(BaseModel): """应用关联的MCP服务信息""" id: str = Field(..., description="MCP服务ID") - name: str = Field(..., description="MCP服务名称") - description: str = Field(..., description="MCP服务简介") + name: str = Field(default="", description="MCP服务名称") + description: str = Field(default="", description="MCP服务简介") class AppData(BaseModel): @@ -73,4 +73,4 @@ class AppData(BaseModel): permission: AppPermissionData = Field( default_factory=lambda: AppPermissionData(authorizedUsers=None), description="权限配置") workflows: list[AppFlowInfo] = Field(default=[], description="工作流信息列表") - mcp_service: list[AppMcpServiceInfo] = Field(default=[], alias="mcpService", description="MCP服务id列表") + mcp_service: list[str] = Field(default=[], alias="mcpService", description="MCP服务id列表") diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 21c403d4..674acf9c 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -11,8 +11,9 @@ from pydantic import BaseModel, Field class MCPInstallStatus(str, Enum): """MCP 服务状态""" - + INIT = "init" INSTALLING = "installing" + CANCELLED = "cancelled" READY = "ready" FAILED = "failed" @@ -23,6 +24,7 @@ class MCPStatus(str, Enum): UNINITIALIZED = "uninitialized" RUNNING = "running" STOPPED = "stopped" + ERROR = "error" class MCPType(str, Enum): @@ -39,7 +41,9 @@ class MCPBasicConfig(BaseModel): env: dict[str, str] = Field(description="MCP 服务器环境变量", default={}) auto_approve: list[str] = Field(description="自动批准的MCP工具ID列表", default=[], alias="autoApprove") disabled: bool = Field(description="MCP 服务器是否禁用", default=False) - auto_install: bool = Field(description="是否自动安装MCP服务器", default=True, alias="autoInstall") + auto_install: bool = Field(description="是否自动安装MCP服务器", default=True) + timeout: int = Field(description="MCP 服务器超时时间(秒)", default=60, alias="timeout") + description: str = Field(description="MCP 服务器自然语言描述", default="") class MCPServerStdioConfig(MCPBasicConfig): @@ -85,7 +89,7 @@ class MCPCollection(BaseModel): type: MCPType = Field(description="MCP 类型", default=MCPType.SSE) activated: list[str] = Field(description="激活该MCP的用户ID列表", default=[]) tools: list[MCPTool] = Field(description="MCP工具列表", default=[]) - status: MCPInstallStatus = Field(description="MCP服务状态", default=MCPInstallStatus.INSTALLING) + status: MCPInstallStatus = Field(description="MCP服务状态", default=MCPInstallStatus.INIT) author: str = Field(description="MCP作者", default="") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 8d053e1c..3bddfc64 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -100,7 +100,7 @@ class UpdateMCPServiceRequest(BaseModel): name: str = Field(..., description="MCP服务名称") description: str = Field(..., description="MCP服务描述") overview: str = Field(..., description="MCP服务概述") - config: str = Field(..., description="MCP服务配置") + config: dict[str, Any] = Field(..., description="MCP服务配置") mcp_type: MCPType = Field(description="MCP传输协议(Stdio/SSE/Streamable)", default=MCPType.STDIO, alias="mcpType") @@ -108,7 +108,7 @@ class ActiveMCPServiceRequest(BaseModel): """POST /api/mcp/{serviceId} 请求数据结构""" active: bool = Field(description="是否激活mcp服务") - mcp_env: dict[str, Any] = Field(default={}, description="MCP服务环境变量", alias="mcpEnv") + mcp_env: dict[str, Any] | None = Field(default=None, description="MCP服务环境变量", alias="mcpEnv") class UpdateServiceRequest(BaseModel): diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index 7f162326..85816033 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -281,11 +281,20 @@ class BaseAppOperationRsp(ResponseData): result: BaseAppOperationMsg +class AppMcpServiceInfo(BaseModel): + """应用关联的MCP服务信息""" + + id: str = Field(..., description="MCP服务ID") + name: str = Field(default="", description="MCP服务名称") + description: str = Field(default="", description="MCP服务简介") + + class GetAppPropertyMsg(AppData): """GET /api/app/{appId} Result数据结构""" app_id: str = Field(..., alias="appId", description="应用ID") published: bool = Field(..., description="是否已发布") + mcp_service: list[AppMcpServiceInfo] = Field(default=[], alias="mcpService", description="MCP服务信息列表") class GetAppPropertyRsp(ResponseData): diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index 559accc2..e37aaa96 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -59,7 +59,7 @@ class AppCenterManager: } user_favorite_app_ids = await AppCenterManager._get_favorite_app_ids_by_user(user_sub) - + logger.info("[AppCenterManager] 获取应用列表: %s", filters) if filter_type == AppFilterType.ALL: # 获取所有已发布的应用 filters["published"] = True @@ -72,7 +72,6 @@ class AppCenterManager: "_id": {"$in": user_favorite_app_ids}, "published": True, } - # 添加关键字搜索条件 if keyword: filters["$or"] = [ @@ -84,7 +83,6 @@ class AppCenterManager: # 添加应用类型过滤条件 if app_type is not None: filters["app_type"] = app_type.value - # 获取应用列表 apps, total_apps = await AppCenterManager._search_apps_by_filter(filters, page, SERVICE_PAGE_SIZE) diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index ba510350..bf7f5995 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -2,6 +2,7 @@ """MCP服务管理器""" import logging +from logging import config import random import re from typing import Any @@ -30,6 +31,7 @@ from apps.schemas.mcp import ( ) from apps.schemas.request_data import UpdateMCPServiceRequest from apps.schemas.response_data import MCPServiceCardItem +from apps.constants import MCP_PATH logger = logging.getLogger(__name__) sqids = Sqids(min_length=6) @@ -66,10 +68,8 @@ class MCPServiceManager: mcp_list = await mcp_collection.find({"_id": mcp_id}, {"status": True}).to_list(None) for db_item in mcp_list: status = db_item.get("status") - if MCPInstallStatus.READY.value == status: - return MCPInstallStatus.READY - if MCPInstallStatus.INSTALLING.value == status: - return MCPInstallStatus.INSTALLING + if status in MCPInstallStatus.__members__.values(): + return status return MCPInstallStatus.FAILED @staticmethod @@ -214,9 +214,9 @@ class MCPServiceManager: """ # 检查config if data.mcp_type == MCPType.SSE: - config = MCPServerSSEConfig.model_validate_json(data.config) + config = MCPServerSSEConfig.model_validate(data.config) else: - config = MCPServerStdioConfig.model_validate_json(data.config) + config = MCPServerStdioConfig.model_validate(data.config) # 构造Server mcp_server = MCPServerConfig( @@ -238,8 +238,17 @@ class MCPServiceManager: # 保存并载入配置 logger.info("[MCPServiceManager] 创建mcp:%s", mcp_server.name) + mcp_path = MCP_PATH / "template" / mcp_id / "project" + index = None + for i in range(len(config.args)): + if not config.args[i].startswith("-"): + index = i + break + if index is not None: + config.args[index] = str(mcp_path) + await MCPLoader._insert_template_db(mcp_id=mcp_id, config=mcp_server) await MCPLoader.save_one(mcp_id, mcp_server) - await MCPLoader.init_one_template(mcp_id=mcp_id, config=mcp_server) + await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.INIT) return mcp_id @staticmethod @@ -263,19 +272,21 @@ class MCPServiceManager: db_service = MCPCollection.model_validate(db_service) for user_id in db_service.activated: await MCPServiceManager.deactive_mcpservice(user_sub=user_id, service_id=data.service_id) - - await MCPLoader.init_one_template(mcp_id=data.service_id, config=MCPServerConfig( + mcp_config = MCPServerConfig( name=data.name, overview=data.overview, description=data.description, - config=MCPServerStdioConfig.model_validate_json( + config=MCPServerStdioConfig.model_validate( data.config, - ) if data.mcp_type == MCPType.STDIO else MCPServerSSEConfig.model_validate_json( + ) if data.mcp_type == MCPType.STDIO else MCPServerSSEConfig.model_validate( data.config, ), type=data.mcp_type, author=user_sub, - )) + ) + await MCPLoader._insert_template_db(mcp_id=data.service_id, config=mcp_config) + await MCPLoader.save_one(mcp_id=data.service_id, config=mcp_config) + await MCPLoader.update_template_status(data.service_id, MCPInstallStatus.INIT) # 返回服务ID return data.service_id @@ -302,7 +313,7 @@ class MCPServiceManager: async def active_mcpservice( user_sub: str, service_id: str, - mcp_env: dict[str, Any] = {}, + mcp_env: dict[str, Any] | None = None, ) -> None: """ 激活MCP服务 @@ -377,3 +388,28 @@ class MCPServiceManager: image.save(MCP_ICON_PATH / f"{service_id}.png", format="PNG", optimize=True, compress_level=9) return f"/static/mcp/{service_id}.png" + + @staticmethod + async def install_mcpservice(user_sub: str, service_id: str, install: bool) -> None: + """ + 安装或卸载MCP服务 + + :param user_sub: str: 用户ID + :param service_id: str: MCP服务ID + :param install: bool: 是否安装 + :return: 无 + """ + service_collection = MongoDB().get_collection("mcp") + db_service = await service_collection.find_one({"_id": service_id, "author": user_sub}) + db_service = MCPCollection.model_validate(db_service) + if install: + if db_service.status == MCPInstallStatus.INSTALLING or db_service.status == MCPInstallStatus.READY: + err = "[MCPServiceManager] MCP服务已处于安装中或已准备就绪" + raise Exception(err) + mcp_config = await MCPLoader.get_config(service_id) + await MCPLoader.init_one_template(mcp_id=service_id, config=mcp_config) + else: + if db_service.status != MCPInstallStatus.INSTALLING: + err = "[MCPServiceManager] 只能卸载处于安装中的MCP服务" + raise Exception(err) + await MCPLoader.cancel_installing_task([service_id]) diff --git a/apps/services/parameter.py b/apps/services/parameter.py index 8f83eab0..2b85c62e 100644 --- a/apps/services/parameter.py +++ b/apps/services/parameter.py @@ -76,7 +76,7 @@ class ParameterManager: for i in range(1, len(q)): step_id = q[i] node_id = step_id_to_node_id.get(step_id) - params_schema, output_schema = await NodeManager.get_node_params(node_id) + _, output_schema = await NodeManager.get_node_params(node_id) slot = Slot(output_schema) params_node = slot.get_params_node_from_schema() pre_step_params.append( diff --git a/openapi.json b/openapi.json new file mode 100644 index 00000000..17fb18bd --- /dev/null +++ b/openapi.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/conversation":{"get":{"tags":["conversation"],"summary":"Get Conversation List","description":"获取对话列表","operationId":"get_conversation_list_api_conversation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListRsp"}}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"}}},"post":{"tags":["conversation"],"summary":"Add Conversation","description":"手动创建新对话","operationId":"add_conversation_api_conversation_post","parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string","default":"","title":"Appid"}},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Debug"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_conversation_api_conversation_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["conversation"],"summary":"Update Conversation","description":"更新特定Conversation的数据","operationId":"update_conversation_api_conversation_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["conversation"],"summary":"Delete Conversation","description":"删除特定对话","operationId":"delete_conversation_api_conversation_delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/login":{"get":{"tags":["auth"],"summary":"Oidc Login","description":"OIDC login\n\n:param request: Request object\n:param code: OIDC code\n:return: HTMLResponse","operationId":"oidc_login_api_auth_login_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"get":{"tags":["auth"],"summary":"Logout","description":"用户登出EulerCopilot","operationId":"logout_api_auth_logout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}},"post":{"tags":["auth"],"summary":"Oidc Logout","description":"OIDC主动触发登出","operationId":"oidc_logout_api_auth_logout_post","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/redirect":{"get":{"tags":["auth"],"summary":"Oidc Redirect","description":"OIDC重定向URL","operationId":"oidc_redirect_api_auth_redirect_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRedirectRsp"}}}}}}},"/api/auth/user":{"get":{"tags":["auth"],"summary":"Userinfo","description":"获取用户信息","operationId":"userinfo_api_auth_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}}}}},"/api/auth/update_revision_number":{"post":{"tags":["auth"],"summary":"Update Revision Number","description":"更新用户协议信息","operationId":"update_revision_number_api_auth_update_revision_number_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/auth/key":{"get":{"tags":["key"],"summary":"Check Api Key Existence","description":"检查API密钥是否存在","operationId":"check_api_key_existence_api_auth_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAuthKeyRsp"}}}}}},"post":{"tags":["key"],"summary":"Manage Api Key","description":"管理用户的API密钥","operationId":"manage_api_key_api_auth_key_post","parameters":[{"name":"action","in":"query","required":true,"schema":{"type":"string","title":"Action"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAuthKeyRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app":{"get":{"tags":["appcenter"],"summary":"Get Applications","description":"获取应用列表","operationId":"get_applications_api_app_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"appType","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AppType"},{"type":"null"}],"description":"应用类型","title":"Apptype"},"description":"应用类型"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Applications Api App Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Create Or Update Application","description":"创建或更新应用","operationId":"create_or_update_application_api_app_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Create Or Update Application Api App Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/recent":{"get":{"tags":["appcenter"],"summary":"Get Recently Used Applications","description":"获取最近使用的应用","operationId":"get_recently_used_applications_api_app_recent_get","parameters":[{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":1,"default":5,"title":"Count"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetRecentAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Recently Used Applications Api App Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/{appId}":{"get":{"tags":["appcenter"],"summary":"Get Application","description":"获取应用详情","operationId":"get_application_api_app__appId__get","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppPropertyRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Application Api App Appid Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["appcenter"],"summary":"Delete Application","description":"删除应用","operationId":"delete_application_api_app__appId__delete","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Delete Application Api App Appid Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Publish Application","description":"发布应用","operationId":"publish_application_api_app__appId__post","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseAppOperationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["appcenter"],"summary":"Modify Favorite Application","description":"更改应用收藏状态","operationId":"modify_favorite_application_api_app__appId__put","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ModFavAppRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Modify Favorite Application Api App Appid Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service":{"get":{"tags":["service-center"],"summary":"Get Service List","description":"获取服务列表","operationId":"get_service_list_api_service_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"每页数量","default":16,"title":"Pagesize"},"description":"每页数量"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Service List Api Service Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["service-center"],"summary":"Update Service","description":"上传并解析服务","operationId":"update_service_api_service_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest","description":"上传 YAML 文本对应数据对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service/{serviceId}":{"get":{"tags":["service-center"],"summary":"Get Service Detail","description":"获取服务详情","operationId":"get_service_detail_api_service__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["service-center"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_service__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["service-center"],"summary":"Modify Favorite Service","description":"修改服务收藏状态","operationId":"modify_favorite_service_api_service__serviceId__put","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRequest","description":"更改收藏状态请求对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comment":{"post":{"tags":["comment"],"summary":"Add Comment","description":"给Record添加评论","operationId":"add_comment_api_comment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCommentData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/record/{conversation_id}":{"get":{"tags":["record"],"summary":"Get Record","description":"获取某个对话的所有问答对","operationId":"get_record_api_record__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordListRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_check":{"get":{"tags":["health_check"],"summary":"Health Check","description":"健康检查接口","operationId":"health_check_health_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckRsp"}}}}}}},"/api/chat":{"post":{"tags":["chat"],"summary":"Chat","description":"LLM流式对话接口","operationId":"chat_api_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stop":{"post":{"tags":["chat"],"summary":"Stop Generation","description":"停止生成","operationId":"stop_generation_api_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/blacklist/user":{"get":{"tags":["blacklist"],"summary":"Get Blacklist User","description":"获取黑名单用户","operationId":"get_blacklist_user_api_blacklist_user_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistUserRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist User","description":"操作黑名单用户","operationId":"change_blacklist_user_api_blacklist_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/question":{"get":{"tags":["blacklist"],"summary":"Get Blacklist Question","description":"获取黑名单问题\n\n目前情况下,先直接输出问题,不做用户类型校验","operationId":"get_blacklist_question_api_blacklist_question_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist Question","description":"黑名单问题检测或操作","operationId":"change_blacklist_question_api_blacklist_question_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/complaint":{"post":{"tags":["blacklist"],"summary":"Abuse Report","description":"用户实施举报","operationId":"abuse_report_api_blacklist_complaint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/abuse":{"get":{"tags":["blacklist"],"summary":"Get Abuse Report","description":"获取待审核的问答对","operationId":"get_abuse_report_api_blacklist_abuse_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Abuse Report","description":"对被举报问答对进行操作","operationId":"change_abuse_report_api_blacklist_abuse_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseProcessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{conversation_id}":{"post":{"tags":["document"],"summary":"Document Upload","description":"上传文档","operationId":"document_upload_api_document__conversation_id__post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_document_upload_api_document__conversation_id__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["document"],"summary":"Get Document List","description":"获取文档列表","operationId":"get_document_list_api_document__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"used","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Used"}},{"name":"unused","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Unused"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDocumentRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{document_id}":{"delete":{"tags":["document"],"summary":"Delete Single Document","description":"删除单个文件","operationId":"delete_single_document_api_document__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge":{"get":{"tags":["knowledge"],"summary":"List Kb","description":"获取当前用户的知识库ID","operationId":"list_kb_api_knowledge_get","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}},{"name":"kbId","in":"query","required":false,"schema":{"type":"string","title":"Kbid"}},{"name":"kbName","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kbname"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamKnowledgeRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["knowledge"],"summary":"Update Conversation Kb","description":"更新当前用户的知识库ID","operationId":"update_conversation_kb_api_knowledge_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKbReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/provider":{"get":{"tags":["llm"],"summary":"List Llm Provider","description":"获取大模型提供商列表","operationId":"list_llm_provider_api_llm_provider_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMProviderRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/llm":{"get":{"tags":["llm"],"summary":"List Llm","description":"获取大模型列表","operationId":"list_llm_api_llm_get","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["llm"],"summary":"Create Llm","description":"创建或更新大模型配置","operationId":"create_llm_api_llm_put","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLLMReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["llm"],"summary":"Delete Llm","description":"删除大模型配置","operationId":"delete_llm_api_llm_delete","parameters":[{"name":"llmId","in":"query","required":true,"schema":{"type":"string","description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/conv":{"put":{"tags":["llm"],"summary":"Update Conv Llm","description":"更新对话的知识库","operationId":"update_conv_llm_api_llm_conv_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","description":"对话ID","title":"Conversationid"},"description":"对话ID"},{"name":"llmId","in":"query","required":false,"schema":{"type":"string","description":"llm ID","default":"empty","title":"Llmid"},"description":"llm ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp":{"get":{"tags":["mcp-service"],"summary":"Get Mcpservice List","description":"获取服务列表","operationId":"get_mcpservice_list_api_mcp_get","parameters":[{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"isActive","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否激活","title":"Isactive"},"description":"是否激活"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Mcpservice List Api Mcp Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Create Or Update Mcpservice","description":"新建或更新MCP服务","operationId":"create_or_update_mcpservice_api_mcp_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}/install":{"post":{"tags":["mcp-service"],"summary":"Install Mcp Service","operationId":"install_mcp_service_api_mcp__serviceId__install_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"install","in":"query","required":false,"schema":{"type":"boolean","description":"是否安装","default":true,"title":"Install"},"description":"是否安装"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}":{"get":{"tags":["mcp-service"],"summary":"Get Service Detail","description":"获取MCP服务详情","operationId":"get_service_detail_api_mcp__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMCPServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["mcp-service"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_mcp__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Active Or Deactivate Mcp Service","description":"激活/取消激活mcp","operationId":"active_or_deactivate_mcp_service_api_mcp__serviceId__post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/icon":{"post":{"tags":["mcp-service"],"summary":"Update Mcp Icon","description":"更新MCP服务图标","operationId":"update_mcp_icon_api_mcp_icon_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_mcp_icon_api_mcp_icon_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/flow/service":{"get":{"tags":["flow"],"summary":"Get Services","description":"获取用户可访问的节点元数据所在服务的信息","operationId":"get_services_api_flow_service_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeServiceListRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/flow":{"get":{"tags":["flow"],"summary":"Get Flow","description":"获取流拓扑结构","operationId":"get_flow_api_flow_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureGetRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["flow"],"summary":"Put Flow","description":"修改流拓扑结构","operationId":"put_flow_api_flow_put","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutFlowReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructurePutRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["flow"],"summary":"Delete Flow","description":"删除流拓扑结构","operationId":"delete_flow_api_flow_delete","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureDeleteRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"get":{"tags":["user"],"summary":"Get User Sub","description":"查询所有用户接口","operationId":"get_user_sub_api_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["user"],"summary":"Update User Info","description":"更新用户信息接口","operationId":"update_user_info_api_user_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest","description":"用户更新信息"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter":{"get":{"tags":["parameter"],"summary":"Get Parameters","description":"Get parameters for node choice.","operationId":"get_parameters_api_parameter_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}},{"name":"stepId","in":"query","required":true,"schema":{"type":"string","title":"Stepid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetParamsRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter/operate":{"get":{"tags":["parameter"],"summary":"Get Operate Parameters","description":"Get parameters for node choice.","operationId":"get_operate_parameters_api_parameter_operate_get","parameters":[{"name":"ParamType","in":"query","required":true,"schema":{"type":"string","title":"Paramtype"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOperaRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbuseProcessRequest":{"properties":{"id":{"type":"string","title":"Id"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","is_deletion"],"title":"AbuseProcessRequest","description":"POST /api/blacklist/abuse 请求数据结构"},"AbuseRequest":{"properties":{"record_id":{"type":"string","title":"Record Id"},"reason":{"type":"string","title":"Reason"},"reason_type":{"type":"string","title":"Reason Type"}},"type":"object","required":["record_id","reason","reason_type"],"title":"AbuseRequest","description":"POST /api/blacklist/complaint 请求数据结构"},"ActiveMCPServiceRequest":{"properties":{"active":{"type":"boolean","title":"Active","description":"是否激活mcp服务"},"mcpEnv":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mcpenv","description":"MCP服务环境变量"}},"type":"object","required":["active"],"title":"ActiveMCPServiceRequest","description":"POST /api/mcp/{serviceId} 请求数据结构"},"ActiveMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ActiveMCPServiceRsp","description":"POST /api/mcp/active/{serviceId} 返回数据结构"},"AddCommentData":{"properties":{"record_id":{"type":"string","title":"Record Id"},"group_id":{"type":"string","title":"Group Id"},"comment":{"$ref":"#/components/schemas/CommentType"},"dislike_reason":{"type":"string","maxLength":200,"title":"Dislike Reason","default":""},"reason_link":{"type":"string","maxLength":200,"title":"Reason Link","default":""},"reason_description":{"type":"string","maxLength":500,"title":"Reason Description","default":""}},"type":"object","required":["record_id","group_id","comment"],"title":"AddCommentData","description":"添加评论"},"AddConversationMsg":{"properties":{"conversationId":{"type":"string","title":"Conversationid"}},"type":"object","required":["conversationId"],"title":"AddConversationMsg","description":"POST /api/conversation Result数据结构"},"AddConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AddConversationMsg"}},"type":"object","required":["code","message","result"],"title":"AddConversationRsp","description":"POST /api/conversation 返回数据结构"},"AppCenterCardItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"应用图标"},"name":{"type":"string","title":"Name","description":"应用名称"},"description":{"type":"string","title":"Description","description":"应用简介"},"author":{"type":"string","title":"Author","description":"应用作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"},"published":{"type":"boolean","title":"Published","description":"是否已发布","default":true}},"type":"object","required":["appId","appType","icon","name","description","author","favorited"],"title":"AppCenterCardItem","description":"应用中心卡片数据结构"},"AppFlowInfo":{"properties":{"id":{"type":"string","title":"Id","description":"工作流ID"},"name":{"type":"string","title":"Name","description":"工作流名称"},"description":{"type":"string","title":"Description","description":"工作流简介"},"debug":{"type":"boolean","title":"Debug","description":"是否经过调试"}},"type":"object","required":["id","name","description","debug"],"title":"AppFlowInfo","description":"应用工作流数据结构"},"AppLink":{"properties":{"title":{"type":"string","title":"Title","description":"链接标题"},"url":{"type":"string","pattern":"^(https|http)://.*$","title":"Url","description":"链接地址"}},"type":"object","required":["title","url"],"title":"AppLink","description":"App的相关链接"},"AppMcpServiceInfo":{"properties":{"id":{"type":"string","title":"Id","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务简介"}},"type":"object","required":["id","name","description"],"title":"AppMcpServiceInfo","description":"应用关联的MCP服务信息"},"AppPermissionData":{"properties":{"visibility":{"$ref":"#/components/schemas/PermissionType","description":"可见性(public/private/protected)","default":"private"},"authorizedUsers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Authorizedusers","description":"附加人员名单(如果可见性为部分人可见)"}},"type":"object","title":"AppPermissionData","description":"应用权限数据结构"},"AppType":{"type":"string","enum":["flow","agent"],"title":"AppType","description":"应用中心应用类型"},"AuthUserMsg":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"revision":{"type":"boolean","title":"Revision"},"is_admin":{"type":"boolean","title":"Is Admin"},"auto_execute":{"type":"boolean","title":"Auto Execute"}},"type":"object","required":["user_sub","revision","is_admin","auto_execute"],"title":"AuthUserMsg","description":"GET /api/auth/user Result数据结构"},"AuthUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AuthUserMsg"}},"type":"object","required":["code","message","result"],"title":"AuthUserRsp","description":"GET /api/auth/user 返回数据结构"},"BaseAppOperationMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"}},"type":"object","required":["appId"],"title":"BaseAppOperationMsg","description":"基础应用操作Result数据结构"},"BaseAppOperationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseAppOperationMsg"}},"type":"object","required":["code","message","result"],"title":"BaseAppOperationRsp","description":"基础应用操作返回数据结构"},"BaseMCPServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseMCPServiceOperationMsg","description":"插件中心:MCP服务操作Result数据结构"},"BaseServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseServiceOperationMsg","description":"语义接口中心:基础服务操作Result数据结构"},"Blacklist":{"properties":{"_id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_audited":{"type":"boolean","title":"Is Audited","default":false},"reason_type":{"type":"string","title":"Reason Type","default":""},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"updated_at":{"type":"number","title":"Updated At"}},"type":"object","required":["question","answer"],"title":"Blacklist","description":"黑名单\n\nCollection: blacklist"},"Body_add_conversation_api_conversation_post":{"properties":{"llm_id":{"type":"string","title":"Llm Id","default":"empty"},"kb_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Kb Ids"}},"type":"object","title":"Body_add_conversation_api_conversation_post"},"Body_document_upload_api_document__conversation_id__post":{"properties":{"documents":{"items":{"type":"string","format":"binary"},"type":"array","title":"Documents"}},"type":"object","required":["documents"],"title":"Body_document_upload_api_document__conversation_id__post"},"Body_update_mcp_icon_api_mcp_icon_post":{"properties":{"icon":{"type":"string","format":"binary","title":"Icon","description":"图标文件"}},"type":"object","required":["icon"],"title":"Body_update_mcp_icon_api_mcp_icon_post"},"BoolOperate":{"type":"string","enum":["bool_equal","bool_not_equal"],"title":"BoolOperate","description":"Choice 工具支持的布尔运算符"},"CommentType":{"type":"string","enum":["liked","disliked","none"],"title":"CommentType","description":"点赞点踩类型"},"ConversationDocumentItem":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"type":"null","title":"Conversation Id"},"status":{"$ref":"#/components/schemas/DocumentStatus"}},"type":"object","required":["name","type","size","status"],"title":"ConversationDocumentItem","description":"GET /api/document/{conversation_id} Result内元素数据结构"},"ConversationDocumentMsg":{"properties":{"documents":{"items":{"$ref":"#/components/schemas/ConversationDocumentItem"},"type":"array","title":"Documents","default":[]}},"type":"object","title":"ConversationDocumentMsg","description":"GET /api/document/{conversation_id} Result数据结构"},"ConversationDocumentRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationDocumentMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationDocumentRsp","description":"GET /api/document/{conversation_id} 返回数据结构"},"ConversationListItem":{"properties":{"conversationId":{"type":"string","title":"Conversationid"},"title":{"type":"string","title":"Title"},"docCount":{"type":"integer","title":"Doccount"},"createdTime":{"type":"string","title":"Createdtime"},"appId":{"type":"string","title":"Appid"},"debug":{"type":"boolean","title":"Debug"},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"kbList":{"items":{"$ref":"#/components/schemas/KbIteam"},"type":"array","title":"Kblist","default":[]}},"type":"object","required":["conversationId","title","docCount","createdTime","appId","debug"],"title":"ConversationListItem","description":"GET /api/conversation Result数据结构"},"ConversationListMsg":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationListItem"},"type":"array","title":"Conversations"}},"type":"object","required":["conversations"],"title":"ConversationListMsg","description":"GET /api/conversation Result数据结构"},"ConversationListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationListRsp","description":"GET /api/conversation 返回数据结构"},"CreateAppRequest":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llmId":{"type":"string","title":"Llmid","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appid","description":"应用ID"}},"type":"object","required":["appType","name","description"],"title":"CreateAppRequest","description":"POST /api/app 请求数据结构"},"DeleteConversationData":{"properties":{"conversationList":{"items":{"type":"string"},"type":"array","title":"Conversationlist"}},"type":"object","required":["conversationList"],"title":"DeleteConversationData","description":"删除会话"},"DeleteMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteMCPServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DeleteServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DependencyItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"type":{"type":"string","title":"Type"}},"type":"object","required":["nodeId","type"],"title":"DependencyItem","description":"请求/响应中的节点依赖变量类"},"DictOperate":{"type":"string","enum":["dict_equal","dict_not_equal","dict_contains_key","dict_not_contains_key"],"title":"DictOperate","description":"Choice 工具支持的字典运算符"},"DocumentStatus":{"type":"string","enum":["used","unused","processing","failed"],"title":"DocumentStatus","description":"文档状态"},"EdgeItem":{"properties":{"edgeId":{"type":"string","title":"Edgeid"},"sourceNode":{"type":"string","title":"Sourcenode"},"targetNode":{"type":"string","title":"Targetnode"},"type":{"type":"string","title":"Type","default":"normal"},"branchId":{"type":"string","title":"Branchid"}},"type":"object","required":["edgeId","sourceNode","targetNode","branchId"],"title":"EdgeItem","description":"请求/响应中的边变量类"},"EditMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"data":{"type":"string","title":"Data","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType"}},"type":"object","required":["serviceId","name","description","overview","data","mcpType"],"title":"EditMCPServiceMsg","description":"编辑MCP服务"},"FlowItem-Input":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowItem-Output":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowStructureDeleteMsg":{"properties":{"flowId":{"type":"string","title":"Flowid","default":""}},"type":"object","title":"FlowStructureDeleteMsg","description":"DELETE /api/flow/ result"},"FlowStructureDeleteRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureDeleteMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureDeleteRsp","description":"DELETE /api/flow/ 返回数据结构"},"FlowStructureGetMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructureGetMsg","description":"GET /api/flow result"},"FlowStructureGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureGetMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureGetRsp","description":"GET /api/flow 返回数据结构"},"FlowStructurePutMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructurePutMsg","description":"PUT /api/flow result"},"FlowStructurePutRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructurePutMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructurePutRsp","description":"PUT /api/flow 返回数据结构"},"FootNoteMetaData":{"properties":{"releatedId":{"type":"string","title":"Releatedid","description":"相关ID","default":""},"insertPosition":{"type":"integer","title":"Insertposition","description":"插入位置","default":0},"footSource":{"type":"string","title":"Footsource","description":"脚注来源","default":""},"footType":{"type":"string","title":"Foottype","description":"脚注类型","default":""}},"type":"object","title":"FootNoteMetaData","description":"Record表子项:Record的脚注元信息"},"GetAppListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalApps":{"type":"integer","title":"Totalapps","description":"总应用数"},"applications":{"items":{"$ref":"#/components/schemas/AppCenterCardItem"},"type":"array","title":"Applications","description":"应用列表"}},"type":"object","required":["currentPage","totalApps","applications"],"title":"GetAppListMsg","description":"GET /api/app Result数据结构"},"GetAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppListMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppListRsp","description":"GET /api/app 返回数据结构"},"GetAppPropertyMsg":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llmId":{"type":"string","title":"Llmid","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"type":"string","title":"Appid","description":"应用ID"},"published":{"type":"boolean","title":"Published","description":"是否已发布"}},"type":"object","required":["appType","name","description","appId","published"],"title":"GetAppPropertyMsg","description":"GET /api/app/{appId} Result数据结构"},"GetAppPropertyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppPropertyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppPropertyRsp","description":"GET /api/app/{appId} 返回数据结构"},"GetAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/_GetAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAuthKeyRsp","description":"GET /api/auth/key 返回数据结构"},"GetBlacklistQuestionMsg":{"properties":{"question_list":{"items":{"$ref":"#/components/schemas/Blacklist"},"type":"array","title":"Question List"}},"type":"object","required":["question_list"],"title":"GetBlacklistQuestionMsg","description":"GET /api/blacklist/question Result数据结构"},"GetBlacklistQuestionRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistQuestionMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistQuestionRsp","description":"GET /api/blacklist/question 返回数据结构"},"GetBlacklistUserMsg":{"properties":{"user_subs":{"items":{"type":"string"},"type":"array","title":"User Subs"}},"type":"object","required":["user_subs"],"title":"GetBlacklistUserMsg","description":"GET /api/blacklist/user Result数据结构"},"GetBlacklistUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistUserMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistUserRsp","description":"GET /api/blacklist/user 返回数据结构"},"GetMCPServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"tools":{"items":{"$ref":"#/components/schemas/MCPTool"},"type":"array","title":"Tools","description":"MCP服务Tools列表","default":[]}},"type":"object","required":["serviceId","name","description","overview"],"title":"GetMCPServiceDetailMsg","description":"GET /api/mcp_service/{serviceId} Result数据结构"},"GetMCPServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceDetailMsg"},{"$ref":"#/components/schemas/EditMCPServiceMsg"}],"title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetMCPServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"services":{"items":{"$ref":"#/components/schemas/MCPServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","services"],"title":"GetMCPServiceListMsg","description":"GET /api/service Result数据结构"},"GetMCPServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetMCPServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceListRsp","description":"GET /api/service 返回数据结构"},"GetOperaRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/OperateAndBindType"},"type":"array","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetOperaRsp","description":"GET /api/operate 返回数据结构"},"GetParamsRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/StepParams"},"type":"array","title":"Result","description":"参数列表","default":[]}},"type":"object","required":["code","message"],"title":"GetParamsRsp","description":"GET /api/params 返回数据结构"},"GetRecentAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecentAppList"}},"type":"object","required":["code","message","result"],"title":"GetRecentAppListRsp","description":"GET /api/app/recent 返回数据结构"},"GetServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array"},{"type":"null"}],"title":"Apis","description":"解析后的接口列表"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data","description":"YAML 内容数据对象"}},"type":"object","required":["serviceId","name"],"title":"GetServiceDetailMsg","description":"GET /api/service/{serviceId} Result数据结构"},"GetServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceDetailMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalCount":{"type":"integer","title":"Totalcount","description":"总服务数"},"services":{"items":{"$ref":"#/components/schemas/ServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","totalCount","services"],"title":"GetServiceListMsg","description":"GET /api/service Result数据结构"},"GetServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceListRsp","description":"GET /api/service 返回数据结构"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthCheckRsp":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HealthCheckRsp","description":"GET /health_check 返回数据结构"},"KbIteam":{"properties":{"kbId":{"type":"string","title":"Kbid"},"kbName":{"type":"string","title":"Kbname"}},"type":"object","required":["kbId","kbName"],"title":"KbIteam","description":"GET /api/conversation Result数据结构"},"KnowledgeBaseItem":{"properties":{"kbId":{"type":"string","title":"Kbid","description":"知识库ID"},"kbName":{"type":"string","title":"Kbname","description":"知识库名称"},"description":{"type":"string","title":"Description","description":"知识库描述"},"isUsed":{"type":"boolean","title":"Isused","description":"是否使用"}},"type":"object","required":["kbId","kbName","description","isUsed"],"title":"KnowledgeBaseItem","description":"知识库列表项数据结构"},"LLMIteam":{"properties":{"icon":{"type":"string","title":"Icon","default":"data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIGZpbGwtcnVsZT0iZXZlbm9kZCIgaGVpZ2h0PSIxZW0iIHN0eWxlPSJmbGV4Om5vbmU7bGluZS1oZWlnaHQ6MSIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMWVtIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5PbGxhbWE8L3RpdGxlPjxwYXRoIGQ9Ik03LjkwNSAxLjA5Yy4yMTYuMDg1LjQxMS4yMjUuNTg4LjQxLjI5NS4zMDYuNTQ0Ljc0NC43MzQgMS4yNjMuMTkxLjUyMi4zMTUgMS4xLjM2MiAxLjY4YTUuMDU0IDUuMDU0IDAgMDEyLjA0OS0uNjM2bC4wNTEtLjAwNGMuODctLjA3IDEuNzMuMDg3IDIuNDguNDc0LjEwMS4wNTMuMi4xMS4yOTcuMTcuMDUtLjU2OS4xNzItMS4xMzQuMzYtMS42NDQuMTktLjUyLjQzOS0uOTU3LjczMy0xLjI2NGExLjY3IDEuNjcgMCAwMS41ODktLjQxYy4yNTctLjEuNTMtLjExOC43OTYtLjA0Mi40MDEuMTE0Ljc0NS4zNjggMS4wMTYuNzM3LjI0OC4zMzcuNDM0Ljc2OS41NjEgMS4yODcuMjMuOTM0LjI3IDIuMTYzLjExNSAzLjY0NWwuMDUzLjA0LjAyNi4wMTljLjc1Ny41NzYgMS4yODQgMS4zOTcgMS41NjMgMi4zNS40MzUgMS40ODcuMjE2IDMuMTU1LS41MzQgNC4wODhsLS4wMTguMDIxLjAwMi4wMDNjLjQxNy43NjIuNjcgMS41NjcuNzI0IDIuNGwuMDAyLjAzYy4wNjQgMS4wNjUtLjIgMi4xMzctLjgxNCAzLjE5bC0uMDA3LjAxLjAxLjAyNGMuNDcyIDEuMTU3LjYyIDIuMzIyLjQzOCAzLjQ4NmwtLjAwNi4wMzlhLjY1MS42NTEgMCAwMS0uNzQ3LjUzNi42NDguNjQ4IDAgMDEtLjU0LS43NDJjLjE2Ny0xLjAzMy4wMS0yLjA2OS0uNDgtMy4xMjNhLjY0My42NDMgMCAwMS4wNC0uNjE3bC4wMDQtLjAwNmMuNjA0LS45MjQuODU0LTEuODMuOC0yLjcyLS4wNDYtLjc3OS0uMzI1LTEuNTQ0LS44LTIuMjczYS42NDQuNjQ0IDAgMDEuMTgtLjg4NmwuMDA5LS4wMDZjLjI0My0uMTU5LjQ2Ny0uNTY1LjU4LTEuMTJhNC4yMjkgNC4yMjkgMCAwMC0uMDk1LTEuOTc0Yy0uMjA1LS43LS41OC0xLjI4NC0xLjEwNS0xLjY4My0uNTk1LS40NTQtMS4zODMtLjY3My0yLjM4LS42MWEuNjUzLjY1MyAwIDAxLS42MzItLjM3MWMtLjMxNC0uNjY1LS43NzItMS4xNDEtMS4zNDMtMS40MzZhMy4yODggMy4yODggMCAwMC0xLjc3Mi0uMzMyYy0xLjI0NS4wOTktMi4zNDMuODAxLTIuNjcgMS42ODZhLjY1Mi42NTIgMCAwMS0uNjEuNDI1Yy0xLjA2Ny4wMDItMS44OTMuMjUyLTIuNDk3LjcwMy0uNTIyLjM5LS44NzguOTM1LTEuMDY2IDEuNTg4YTQuMDcgNC4wNyAwIDAwLS4wNjggMS44ODZjLjExMi41NTguMzMxIDEuMDIuNTgyIDEuMjY5bC4wMDguMDA3Yy4yMTIuMjA3LjI1Ny41My4xMDkuNzg1LS4zNi42MjItLjYyOSAxLjU0OS0uNjczIDIuNDQtLjA1IDEuMDE4LjE4NiAxLjkwMi43MTkgMi41MzZsLjAxNi4wMTlhLjY0My42NDMgMCAwMS4wOTUuNjljLS41NzYgMS4yMzYtLjc1MyAyLjI1Mi0uNTYyIDMuMDUyYS42NTIuNjUyIDAgMDEtMS4yNjkuMjk4Yy0uMjQzLTEuMDE4LS4wNzgtMi4xODQuNDczLTMuNDk4bC4wMTQtLjAzNS0uMDA4LS4wMTJhNC4zMzkgNC4zMzkgMCAwMS0uNTk4LTEuMzA5bC0uMDA1LS4wMTlhNS43NjQgNS43NjQgMCAwMS0uMTc3LTEuNzg1Yy4wNDQtLjkxLjI3OC0xLjg0Mi42MjItMi41OWwuMDEyLS4wMjYtLjAwMi0uMDAyYy0uMjkzLS40MTgtLjUxLS45NTMtLjYzLTEuNTQ1bC0uMDA1LS4wMjRhNS4zNTIgNS4zNTIgMCAwMS4wOTMtMi40OWMuMjYyLS45MTUuNzc3LTEuNzAxIDEuNTM2LTIuMjY5LjA2LS4wNDUuMTIzLS4wOS4xODYtLjEzMi0uMTU5LTEuNDkzLS4xMTktMi43My4xMTItMy42Ny4xMjctLjUxOC4zMTQtLjk1LjU2Mi0xLjI4Ny4yNy0uMzY4LjYxNC0uNjIyIDEuMDE1LS43MzcuMjY2LS4wNzYuNTQtLjA1OS43OTcuMDQyem00LjExNiA5LjA5Yy45MzYgMCAxLjguMzEzIDIuNDQ2Ljg1NS42My41MjcgMS4wMDUgMS4yMzUgMS4wMDUgMS45NCAwIC44ODgtLjQwNiAxLjU4LTEuMTMzIDIuMDIyLS42Mi4zNzUtMS40NTEuNTU3LTIuNDAzLjU1Ny0xLjAwOSAwLTEuODcxLS4yNTktMi40OTMtLjczNC0uNjE3LS40Ny0uOTYzLTEuMTMtLjk2My0xLjg0NSAwLS43MDcuMzk4LTEuNDE3IDEuMDU2LTEuOTQ2LjY2OC0uNTM3IDEuNTUtLjg0OSAyLjQ4NS0uODQ5em0wIC44OTZhMy4wNyAzLjA3IDAgMDAtMS45MTYuNjVjLS40NjEuMzctLjcyMi44MzUtLjcyMiAxLjI1IDAgLjQyOC4yMS44MjkuNjEgMS4xMzQuNDU1LjM0NyAxLjEyNC41NDggMS45NDMuNTQ4Ljc5OSAwIDEuNDczLS4xNDcgMS45MzItLjQyNi40NjMtLjI4LjctLjY4Ni43LTEuMjU3IDAtLjQyMy0uMjQ2LS44OS0uNjgzLTEuMjU2LS40ODQtLjQwNS0xLjE0LS42NDMtMS44NjQtLjY0M3ptLjY2MiAxLjIxbC4wMDQuMDA0Yy4xMi4xNTEuMDk1LjM3LS4wNTYuNDlsLS4yOTIuMjN2LjQ0NmEuMzc1LjM3NSAwIDAxLS4zNzYuMzczLjM3NS4zNzUgMCAwMS0uMzc2LS4zNzN2LS40NmwtLjI3MS0uMjE4YS4zNDcuMzQ3IDAgMDEtLjA1Mi0uNDkuMzUzLjM1MyAwIDAxLjQ5NC0uMDUxbC4yMTUuMTcyLjIyLS4xNzRhLjM1My4zNTMgMCAwMS40OS4wNTF6bS01LjA0LTEuOTE5Yy40NzggMCAuODY3LjM5Ljg2Ny44NzFhLjg3Ljg3IDAgMDEtLjg2OC44NzEuODcuODcgMCAwMS0uODY3LS44Ny44Ny44NyAwIDAxLjg2Ny0uODcyem04LjcwNiAwYy40OCAwIC44NjguMzkuODY4Ljg3MWEuODcuODcgMCAwMS0uODY4Ljg3MS44Ny44NyAwIDAxLS44NjctLjg3Ljg3Ljg3IDAgMDEuODY3LS44NzJ6TTcuNDQgMi4zbC0uMDAzLjAwMmEuNjU5LjY1OSAwIDAwLS4yODUuMjM4bC0uMDA1LjAwNmMtLjEzOC4xODktLjI1OC40NjctLjM0OC44MzItLjE3LjY5Mi0uMjE2IDEuNjMxLS4xMjQgMi43ODIuNDMtLjEyOC44OTktLjIwOCAxLjQwNC0uMjM3bC4wMS0uMDAxLjAxOS0uMDM0Yy4wNDYtLjA4Mi4wOTUtLjE2MS4xNDgtLjIzOS4xMjMtLjc3MS4wMjItMS42OTItLjI1My0yLjQ0NC0uMTM0LS4zNjQtLjI5Ny0uNjUtLjQ1My0uODEzYS42MjguNjI4IDAgMDAtLjEwNy0uMDlMNy40NCAyLjN6bTkuMTc0LjA0bC0uMDAyLjAwMWEuNjI4LjYyOCAwIDAwLS4xMDcuMDljLS4xNTYuMTYzLS4zMi40NS0uNDUzLjgxNC0uMjkuNzk0LS4zODcgMS43NzYtLjIzIDIuNTcybC4wNTguMDk3LjAwOC4wMTRoLjAzYTUuMTg0IDUuMTg0IDAgMDExLjQ2Ni4yMTJjLjA4Ni0xLjEyNC4wMzgtMi4wNDMtLjEyOC0yLjcyMi0uMDktLjM2NS0uMjEtLjY0My0uMzQ5LS44MzJsLS4wMDQtLjAwNmEuNjU5LjY1OSAwIDAwLS4yODUtLjIzOWgtLjAwNHoiPjwvcGF0aD48L3N2Zz4="},"llmId":{"type":"string","title":"Llmid","default":"empty"},"modelName":{"type":"string","title":"Modelname","default":"Ollama LLM"}},"type":"object","title":"LLMIteam","description":"GET /api/conversation Result数据结构"},"LLMProvider":{"properties":{"provider":{"type":"string","title":"Provider","description":"LLM提供商"},"description":{"type":"string","title":"Description","description":"LLM提供商描述"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"LLM提供商URL"},"icon":{"type":"string","title":"Icon","description":"LLM提供商图标"}},"type":"object","required":["provider","description","icon"],"title":"LLMProvider","description":"LLM提供商数据结构"},"LLMProviderInfo":{"properties":{"llmId":{"type":"string","title":"Llmid","description":"LLM ID"},"icon":{"type":"string","maxLength":25536,"title":"Icon","description":"LLM图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":"https://api.openai.com/v1"},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称"},"maxTokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokens","description":"最大token数"},"isEditable":{"type":"boolean","title":"Iseditable","description":"是否可编辑","default":true}},"type":"object","required":["llmId","modelName"],"title":"LLMProviderInfo","description":"LLM数据结构"},"ListLLMProviderRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProvider"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMProviderRsp","description":"GET /api/llm/provider 返回数据结构"},"ListLLMRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProviderInfo"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMRsp","description":"GET /api/llm 返回数据结构"},"ListOperate":{"type":"string","enum":["list_equal","list_not_equal","list_contains","list_not_contains","list_length_equal","list_length_greater_than","list_length_greater_than_or_equal","list_length_less_than","list_length_less_than_or_equal"],"title":"ListOperate","description":"Choice 工具支持的列表运算符"},"ListTeamKnowledgeMsg":{"properties":{"teamKbList":{"items":{"$ref":"#/components/schemas/TeamKnowledgeBaseItem"},"type":"array","title":"Teamkblist","description":"团队知识库列表","default":[]}},"type":"object","title":"ListTeamKnowledgeMsg","description":"GET /api/knowledge Result数据结构"},"ListTeamKnowledgeRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ListTeamKnowledgeMsg"}},"type":"object","required":["code","message","result"],"title":"ListTeamKnowledgeRsp","description":"GET /api/knowledge 返回数据结构"},"MCPInstallStatus":{"type":"string","enum":["init","installing","cancelled","ready","failed"],"title":"MCPInstallStatus","description":"MCP 服务状态"},"MCPServiceCardItem":{"properties":{"mcpserviceId":{"type":"string","title":"Mcpserviceid","description":"mcp服务ID"},"name":{"type":"string","title":"Name","description":"mcp服务名称"},"description":{"type":"string","title":"Description","description":"mcp服务简介"},"icon":{"type":"string","title":"Icon","description":"mcp服务图标"},"author":{"type":"string","title":"Author","description":"mcp服务作者"},"isActive":{"type":"boolean","title":"Isactive","description":"mcp服务是否激活","default":false},"status":{"$ref":"#/components/schemas/MCPInstallStatus","description":"mcp服务状态","default":"installing"}},"type":"object","required":["mcpserviceId","name","description","icon","author"],"title":"MCPServiceCardItem","description":"插件中心:MCP服务卡片数据结构"},"MCPTool":{"properties":{"id":{"type":"string","title":"Id","description":"MCP工具ID"},"name":{"type":"string","title":"Name","description":"MCP工具名称"},"description":{"type":"string","title":"Description","description":"MCP工具描述"},"mcp_id":{"type":"string","title":"Mcp Id","description":"MCP ID"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"MCP工具输入参数"}},"type":"object","required":["id","name","description","mcp_id","input_schema"],"title":"MCPTool","description":"MCP工具"},"MCPType":{"type":"string","enum":["sse","stdio","stream"],"title":"MCPType","description":"MCP 类型"},"ModFavAppMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["appId","favorited"],"title":"ModFavAppMsg","description":"PUT /api/app/{appId} Result数据结构"},"ModFavAppRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavAppRequest","description":"PUT /api/app/{appId} 请求数据结构"},"ModFavAppRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavAppMsg"}},"type":"object","required":["code","message","result"],"title":"ModFavAppRsp","description":"PUT /api/app/{appId} 返回数据结构"},"ModFavServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","favorited"],"title":"ModFavServiceMsg","description":"PUT /api/service/{serviceId} Result数据结构"},"ModFavServiceRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavServiceRequest","description":"PUT /api/service/{serviceId} 请求数据结构"},"ModFavServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ModFavServiceRsp","description":"PUT /api/service/{serviceId} 返回数据结构"},"ModifyConversationData":{"properties":{"title":{"type":"string","maxLength":2000,"minLength":1,"title":"Title"}},"type":"object","required":["title"],"title":"ModifyConversationData","description":"修改会话信息"},"NodeItem":{"properties":{"stepId":{"type":"string","title":"Stepid","default":""},"serviceId":{"type":"string","title":"Serviceid","default":""},"nodeId":{"type":"string","title":"Nodeid","default":""},"name":{"type":"string","title":"Name","default":""},"callId":{"type":"string","title":"Callid","default":"Empty"},"description":{"type":"string","title":"Description","default":""},"enable":{"type":"boolean","title":"Enable","default":true},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","default":{}},"depedency":{"anyOf":[{"$ref":"#/components/schemas/DependencyItem"},{"type":"null"}]},"position":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"editable":{"type":"boolean","title":"Editable","default":true}},"type":"object","title":"NodeItem","description":"请求/响应中的节点变量类"},"NodeMetaDataItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"callId":{"type":"string","title":"Callid"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"editable":{"type":"boolean","title":"Editable","default":true},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat"}},"type":"object","required":["nodeId","callId","name","description","parameters","createdAt"],"title":"NodeMetaDataItem","description":"节点元数据类"},"NodeServiceItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"type":{"type":"string","title":"Type","description":"服务类型"},"nodeMetaDatas":{"items":{"$ref":"#/components/schemas/NodeMetaDataItem"},"type":"array","title":"Nodemetadatas","default":[]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdat","description":"创建时间"}},"type":"object","required":["serviceId","name","type"],"title":"NodeServiceItem","description":"GET /api/flow/service 中单个service信息以及service下的节点元数据的信息"},"NodeServiceListMsg":{"properties":{"services":{"items":{"$ref":"#/components/schemas/NodeServiceItem"},"type":"array","title":"Services","description":"服务列表","default":[]}},"type":"object","title":"NodeServiceListMsg","description":"GET /api/flow/service result"},"NodeServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/NodeServiceListMsg"}},"type":"object","required":["code","message","result"],"title":"NodeServiceListRsp","description":"GET /api/flow/service 返回数据结构"},"NumberOperate":{"type":"string","enum":["number_equal","number_not_equal","number_greater_than","number_less_than","number_greater_than_or_equal","number_less_than_or_equal"],"title":"NumberOperate","description":"Choice 工具支持的数字运算符"},"OidcRedirectMsg":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"OidcRedirectMsg","description":"GET /api/auth/redirect Result数据结构"},"OidcRedirectRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/OidcRedirectMsg"}},"type":"object","required":["code","message","result"],"title":"OidcRedirectRsp","description":"GET /api/auth/redirect 返回数据结构"},"OperateAndBindType":{"properties":{"operate":{"anyOf":[{"$ref":"#/components/schemas/NumberOperate"},{"$ref":"#/components/schemas/StringOperate"},{"$ref":"#/components/schemas/ListOperate"},{"$ref":"#/components/schemas/BoolOperate"},{"$ref":"#/components/schemas/DictOperate"}],"title":"Operate","description":"操作类型"},"bind_type":{"$ref":"#/components/schemas/Type","description":"绑定类型"}},"type":"object","required":["operate","bind_type"],"title":"OperateAndBindType","description":"操作和绑定类型数据结构"},"ParamsNode":{"properties":{"paramName":{"type":"string","title":"Paramname","description":"参数名称"},"paramPath":{"type":"string","title":"Parampath","description":"参数路径"},"paramType":{"$ref":"#/components/schemas/Type","description":"参数类型"},"subParams":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParamsNode"},"type":"array"},{"type":"null"}],"title":"Subparams","description":"子参数列表"}},"type":"object","required":["paramName","paramPath","paramType"],"title":"ParamsNode","description":"参数数据结构"},"PermissionType":{"type":"string","enum":["protected","public","private"],"title":"PermissionType","description":"权限类型"},"PositionItem":{"properties":{"x":{"type":"number","title":"X","default":0.0},"y":{"type":"number","title":"Y","default":0.0}},"type":"object","title":"PositionItem","description":"请求/响应中的前端相对位置变量类"},"PostAuthKeyMsg":{"properties":{"api_key":{"type":"string","title":"Api Key"}},"type":"object","required":["api_key"],"title":"PostAuthKeyMsg","description":"POST /api/auth/key Result数据结构"},"PostAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/PostAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"PostAuthKeyRsp","description":"POST /api/auth/key 返回数据结构"},"PutFlowReq":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Input"}},"type":"object","required":["flow"],"title":"PutFlowReq","description":"创建/修改流拓扑结构"},"QuestionBlacklistRequest":{"properties":{"id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","question","answer","is_deletion"],"title":"QuestionBlacklistRequest","description":"POST /api/blacklist/question 请求数据结构"},"RecentAppList":{"properties":{"applications":{"items":{"$ref":"#/components/schemas/RecentAppListItem"},"type":"array","title":"Applications","description":"最近使用的应用列表"}},"type":"object","required":["applications"],"title":"RecentAppList","description":"GET /api/app/recent Result数据结构"},"RecentAppListItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"name":{"type":"string","title":"Name","description":"应用名称"}},"type":"object","required":["appId","name"],"title":"RecentAppListItem","description":"GET /api/app/recent 列表项数据结构"},"RecordContent":{"properties":{"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"data":{"additionalProperties":true,"type":"object","title":"Data","default":{}},"facts":{"items":{"type":"string"},"type":"array","title":"Facts","description":"[运行后修改]与Record关联的事实信息","default":[]}},"type":"object","required":["question","answer"],"title":"RecordContent","description":"Record表子项:Record加密前的数据结构"},"RecordData":{"properties":{"id":{"type":"string","title":"Id"},"groupId":{"type":"string","title":"Groupid"},"conversationId":{"type":"string","title":"Conversationid"},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid"},"document":{"items":{"$ref":"#/components/schemas/RecordDocument"},"type":"array","title":"Document","default":[]},"flow":{"anyOf":[{"$ref":"#/components/schemas/RecordFlow"},{"type":"null"}]},"content":{"$ref":"#/components/schemas/RecordContent"},"metadata":{"$ref":"#/components/schemas/RecordMetadata"},"comment":{"$ref":"#/components/schemas/CommentType","default":"none"},"createdAt":{"type":"number","title":"Createdat"}},"type":"object","required":["id","groupId","conversationId","content","metadata","createdAt"],"title":"RecordData","description":"GET /api/record/{conversation_id} Result内元素数据结构"},"RecordDocument":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"order":{"type":"integer","title":"Order","description":"文档顺序","default":0},"abstract":{"type":"string","title":"Abstract","description":"文档摘要","default":""},"author":{"type":"string","title":"Author","description":"文档作者","default":""},"associated":{"type":"string","enum":["question","answer"],"title":"Associated"}},"type":"object","required":["name","type","size","associated"],"title":"RecordDocument","description":"GET /api/record/{conversation_id} Result中的document数据结构"},"RecordFlow":{"properties":{"id":{"type":"string","title":"Id"},"recordId":{"type":"string","title":"Recordid"},"flowId":{"type":"string","title":"Flowid"},"flowName":{"type":"string","title":"Flowname","default":""},"flowStatus":{"$ref":"#/components/schemas/StepStatus","default":"success"},"stepNum":{"type":"integer","title":"Stepnum"},"steps":{"items":{"$ref":"#/components/schemas/RecordFlowStep"},"type":"array","title":"Steps"}},"type":"object","required":["id","recordId","flowId","stepNum","steps"],"title":"RecordFlow","description":"Flow的执行信息"},"RecordFlowStep":{"properties":{"stepId":{"type":"string","title":"Stepid"},"stepStatus":{"$ref":"#/components/schemas/StepStatus"},"input":{"additionalProperties":true,"type":"object","title":"Input"},"output":{"additionalProperties":true,"type":"object","title":"Output"}},"type":"object","required":["stepId","stepStatus","input","output"],"title":"RecordFlowStep","description":"Record表子项:flow的单步数据结构"},"RecordListMsg":{"properties":{"records":{"items":{"$ref":"#/components/schemas/RecordData"},"type":"array","title":"Records"}},"type":"object","required":["records"],"title":"RecordListMsg","description":"GET /api/record/{conversation_id} Result数据结构"},"RecordListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecordListMsg"}},"type":"object","required":["code","message","result"],"title":"RecordListRsp","description":"GET /api/record/{conversation_id} 返回数据结构"},"RecordMetadata":{"properties":{"inputTokens":{"type":"integer","title":"Inputtokens","default":0},"outputTokens":{"type":"integer","title":"Outputtokens","default":0},"timeCost":{"type":"number","title":"Timecost","default":0},"feature":{"additionalProperties":true,"type":"object","title":"Feature","default":{}},"footNoteMetadataList":{"items":{"$ref":"#/components/schemas/FootNoteMetaData"},"type":"array","title":"Footnotemetadatalist","description":"脚注元信息列表","default":[]}},"type":"object","title":"RecordMetadata","description":"Record表子项:Record的元信息"},"RequestData":{"properties":{"question":{"type":"string","maxLength":2000,"title":"Question","description":"用户输入"},"conversationId":{"type":"string","title":"Conversationid","description":"聊天ID","default":""},"groupId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupid","description":"问答组ID"},"language":{"type":"string","title":"Language","description":"语言","default":"zh"},"files":{"items":{"type":"string"},"type":"array","title":"Files","description":"文件列表","default":[]},"app":{"anyOf":[{"$ref":"#/components/schemas/RequestDataApp"},{"type":"null"}],"description":"应用"},"debug":{"type":"boolean","title":"Debug","description":"是否调试","default":false},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid","description":"任务ID"}},"type":"object","required":["question"],"title":"RequestData","description":"POST /api/chat 请求的总的数据结构"},"RequestDataApp":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","description":"Flow ID"},"params":{"anyOf":[{"$ref":"#/components/schemas/param"},{"type":"null"}],"description":"流执行过程中的参数补充"}},"type":"object","required":["appId"],"title":"RequestDataApp","description":"模型对话中包含的app信息"},"ResponseData":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"title":"Result"}},"type":"object","required":["code","message","result"],"title":"ResponseData","description":"基础返回数据结构"},"SearchType":{"type":"string","enum":["all","name","description","author"],"title":"SearchType","description":"搜索类型"},"ServiceApiData":{"properties":{"name":{"type":"string","title":"Name","description":"接口名称"},"path":{"type":"string","title":"Path","description":"接口路径"},"description":{"type":"string","title":"Description","description":"接口描述"}},"type":"object","required":["name","path","description"],"title":"ServiceApiData","description":"语义接口中心:服务 API 接口属性数据结构"},"ServiceCardItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"description":{"type":"string","title":"Description","description":"服务简介"},"icon":{"type":"string","title":"Icon","description":"服务图标"},"author":{"type":"string","title":"Author","description":"服务作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","name","description","icon","author","favorited"],"title":"ServiceCardItem","description":"语义接口中心:服务卡片数据结构"},"StepParams":{"properties":{"stepId":{"type":"string","title":"Stepid","description":"步骤ID"},"name":{"type":"string","title":"Name","description":"Step名称"},"paramsNode":{"anyOf":[{"$ref":"#/components/schemas/ParamsNode"},{"type":"null"}],"description":"参数节点"}},"type":"object","required":["stepId","name"],"title":"StepParams","description":"参数数据结构"},"StepStatus":{"type":"string","enum":["unknown","init","waiting","running","success","error","param","cancelled"],"title":"StepStatus","description":"步骤状态"},"StringOperate":{"type":"string","enum":["string_equal","string_not_equal","string_contains","string_not_contains","string_starts_with","string_ends_with","string_length_equal","string_length_greater_than","string_length_greater_than_or_equal","string_length_less_than","string_length_less_than_or_equal","string_regex_match"],"title":"StringOperate","description":"Choice 工具支持的字符串运算符"},"TeamKnowledgeBaseItem":{"properties":{"teamId":{"type":"string","title":"Teamid","description":"团队ID"},"teamName":{"type":"string","title":"Teamname","description":"团队名称"},"kb_list":{"items":{"$ref":"#/components/schemas/KnowledgeBaseItem"},"type":"array","title":"Kb List","description":"知识库列表","default":[]}},"type":"object","required":["teamId","teamName"],"title":"TeamKnowledgeBaseItem","description":"团队知识库列表项数据结构"},"Type":{"type":"string","enum":["string","number","list","dict","bool"],"title":"Type","description":"Choice 工具支持的类型"},"UpdateConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListItem"}},"type":"object","required":["code","message","result"],"title":"UpdateConversationRsp","description":"POST /api/conversation 返回数据结构"},"UpdateKbReq":{"properties":{"kbIds":{"items":{"type":"string"},"type":"array","title":"Kbids","description":"知识库ID列表","default":[]}},"type":"object","title":"UpdateKbReq","description":"更新知识库请求体"},"UpdateLLMReq":{"properties":{"icon":{"type":"string","title":"Icon","description":"图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":""},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称","default":""},"maxTokens":{"type":"integer","title":"Maxtokens","description":"最大token数","default":8192}},"type":"object","title":"UpdateLLMReq","description":"更新大模型请求体"},"UpdateMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"}},"type":"object","required":["serviceId","name"],"title":"UpdateMCPServiceMsg","description":"插件中心:MCP服务属性数据结构"},"UpdateMCPServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"config":{"additionalProperties":true,"type":"object","title":"Config","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType","description":"MCP传输协议(Stdio/SSE/Streamable)","default":"stdio"}},"type":"object","required":["name","description","overview","config"],"title":"UpdateMCPServiceRequest","description":"POST /api/mcpservice 请求数据结构"},"UpdateMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateMCPServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateMCPServiceRsp","description":"POST /api/mcp_service 返回数据结构"},"UpdateServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array","title":"Apis","description":"解析后的接口列表"}},"type":"object","required":["serviceId","name","apis"],"title":"UpdateServiceMsg","description":"语义接口中心:服务属性数据结构"},"UpdateServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"data":{"additionalProperties":true,"type":"object","title":"Data","description":"对应 YAML 内容的数据对象"}},"type":"object","required":["data"],"title":"UpdateServiceRequest","description":"POST /api/service 请求数据结构"},"UpdateServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateServiceRsp","description":"POST /api/service 返回数据结构"},"UserBlacklistRequest":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"is_ban":{"type":"integer","title":"Is Ban"}},"type":"object","required":["user_sub","is_ban"],"title":"UserBlacklistRequest","description":"POST /api/blacklist/user 请求数据结构"},"UserUpdateRequest":{"properties":{"autoExecute":{"type":"boolean","title":"Autoexecute","description":"是否自动执行","default":false}},"type":"object","title":"UserUpdateRequest","description":"更新用户信息请求体"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"_GetAuthKeyMsg":{"properties":{"api_key_exists":{"type":"boolean","title":"Api Key Exists"}},"type":"object","required":["api_key_exists"],"title":"_GetAuthKeyMsg","description":"GET /api/auth/key Result数据结构"},"param":{"properties":{"content":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"boolean"}],"title":"Content","description":"流执行过程中的参数补充内容","default":{}},"description":{"type":"string","title":"Description","description":"流执行过程中的参数补充描述","default":""}},"type":"object","title":"param","description":"流执行过程中的参数补充"}}}} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 681ea9fb..22b07eac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,4 +50,4 @@ dev = [ "ruff==0.11.2", "sphinx==8.2.3", "sphinx-rtd-theme==3.0.2", -] +] \ No newline at end of file -- Gitee From e257863f2fffd69769044d7252008f844d799b46 Mon Sep 17 00:00:00 2001 From: zxstty Date: Thu, 7 Aug 2025 22:49:31 +0800 Subject: [PATCH 58/78] =?UTF-8?q?=E5=AE=8C=E5=96=84app=E7=9A=84=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E9=85=8D=E7=BD=AE=E8=BF=94=E5=9B=9E=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/appcenter.py | 12 ++++++++++++ apps/schemas/appcenter.py | 2 +- apps/schemas/response_data.py | 4 +++- apps/services/appcenter.py | 14 +++++++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index df540eaf..88df7cb1 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -13,6 +13,7 @@ from apps.schemas.appcenter import AppFlowInfo, AppMcpServiceInfo, AppPermission from apps.schemas.enum_var import AppFilterType, AppType from apps.schemas.request_data import CreateAppRequest, ModFavAppRequest from apps.schemas.response_data import ( + LLMIteam, BaseAppOperationMsg, BaseAppOperationRsp, GetAppListMsg, @@ -25,6 +26,7 @@ from apps.schemas.response_data import ( ResponseData, ) from apps.services.appcenter import AppCenterManager +from apps.services.llm import LLMManager from apps.services.mcp_service import MCPServiceManager logger = logging.getLogger(__name__) router = APIRouter( @@ -223,6 +225,15 @@ async def get_application( name=mcp_collection.name, description=mcp_collection.description, )) + if app_data.llm_id == "empty": + llm_item = LLMIteam() + else: + llm_collection = await LLMManager.get_llm_by_id(app_data.user_sub, app_data.llm_id) + llm_item = LLMIteam( + llmId=llm_collection.id, + modelName=llm_collection.model_name, + icon=llm_collection.icon + ) return JSONResponse( status_code=status.HTTP_200_OK, content=GetAppPropertyRsp( @@ -244,6 +255,7 @@ async def get_application( ), workflows=workflows, mcpService=mcp_service, + llm=llm_item, ), ).model_dump(exclude_none=True, by_alias=True), ) diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index b33bfa2f..773e41cd 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -69,7 +69,7 @@ class AppData(BaseModel): first_questions: list[str] = Field( default=[], alias="recommendedQuestions", description="推荐问题", max_length=3) history_len: int = Field(3, alias="dialogRounds", ge=1, le=10, description="对话轮次(1~10)") - llm_id: str = Field(default="empty", alias="llmId", description="大模型ID") + llm: str = Field(default="empty", description="大模型ID") permission: AppPermissionData = Field( default_factory=lambda: AppPermissionData(authorizedUsers=None), description="权限配置") workflows: list[AppFlowInfo] = Field(default=[], description="工作流信息列表") diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index 85816033..0dcc04ea 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -26,6 +26,7 @@ from apps.schemas.mcp import MCPInstallStatus, MCPTool, MCPType from apps.schemas.record import RecordData from apps.schemas.user import UserInfo from apps.templates.generate_llm_operator_config import llm_provider_dict +from apps.common.config import Config class ResponseData(BaseModel): @@ -99,7 +100,7 @@ class LLMIteam(BaseModel): icon: str = Field(default=llm_provider_dict["ollama"]["icon"]) llm_id: str = Field(alias="llmId", default="empty") - model_name: str = Field(alias="modelName", default="Ollama LLM") + model_name: str = Field(alias="modelName", default=Config().get_config().llm.model) class KbIteam(BaseModel): @@ -295,6 +296,7 @@ class GetAppPropertyMsg(AppData): app_id: str = Field(..., alias="appId", description="应用ID") published: bool = Field(..., description="是否已发布") mcp_service: list[AppMcpServiceInfo] = Field(default=[], alias="mcpService", description="MCP服务信息列表") + llm: LLMIteam | None = Field(alias="llm", default=None) class GetAppPropertyRsp(ResponseData): diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index e37aaa96..85cdba8f 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -483,7 +483,19 @@ class AppCenterManager: else: # 在预期的条件下,如果在 data 或 app_data 中找不到 mcp_service,则默认回退为空列表。 metadata.mcp_service = [] - + # 处理llm_id字段 + if data is not None and hasattr(data, "llm") and data.llm: + # 创建应用场景,验证传入的 llm_id 状态 (create_app) + metadata.llm_id = data.llm.llm_id if data.llm.llm_id else "empty" + elif data is not None and hasattr(data, "llm_id"): + # 更新应用场景,使用 data 中的 llm_id (update_app) + metadata.llm_id = data.llm_id if data.llm_id else "empty" + elif app_data is not None and hasattr(app_data, "llm_id"): + # 更新应用发布状态场景,使用 app_data 中的 llm_id (update_app_publish_status) + metadata.llm_id = app_data.llm_id if app_data.llm_id else "empty" + else: + # 在预期的条件下,如果在 data 或 app_data 中找不到 llm_id,则默认回退为 "empty"。 + metadata.llm_id = "empty" # Agent 应用的发布状态逻辑 if published is not None: # 从 update_app_publish_status 调用,'published' 参数已提供 metadata.published = published -- Gitee From 962a543706986f0aee7e12576b4efa740660d177 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 8 Aug 2025 10:58:37 +0800 Subject: [PATCH 59/78] =?UTF-8?q?=E5=AE=8C=E5=96=84chat=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/mcp_service.py | 2 ++ apps/schemas/request_data.py | 6 +++--- apps/services/mcp_service.py | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index 411b9963..62b6453e 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -53,6 +53,7 @@ async def get_mcpservice_list( ] = SearchType.ALL, keyword: Annotated[str | None, Query(..., alias="keyword", description="搜索关键字")] = None, page: Annotated[int, Query(..., alias="page", ge=1, description="页码")] = 1, + is_installed: Annotated[bool | None, Query(..., alias="isInstall", description="是否已安装")] = None, is_active: Annotated[bool | None, Query(..., alias="isActive", description="是否激活")] = None, ) -> JSONResponse: """获取服务列表""" @@ -62,6 +63,7 @@ async def get_mcpservice_list( user_sub, keyword, page, + is_installed, is_active ) except Exception as e: diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 3bddfc64..7c2d1a96 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -18,7 +18,6 @@ class RequestDataApp(BaseModel): app_id: str = Field(description="应用ID", alias="appId") flow_id: str | None = Field(default=None, description="Flow ID", alias="flowId") - params: param | None = Field(default=None, description="流执行过程中的参数补充", alias="params") class MockRequestData(BaseModel): @@ -40,14 +39,15 @@ class RequestDataFeatures(BaseModel): class RequestData(BaseModel): """POST /api/chat 请求的总的数据结构""" - question: str = Field(max_length=2000, description="用户输入") - conversation_id: str = Field(default="", alias="conversationId", description="聊天ID") + question: str | None = Field(default=None, max_length=2000, description="用户输入") + conversation_id: str | None = Field(default=None, alias="conversationId", description="聊天ID") group_id: str | None = Field(default=None, alias="groupId", description="问答组ID") language: str = Field(default="zh", description="语言") files: list[str] = Field(default=[], description="文件列表") app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") task_id: str | None = Field(default=None, alias="taskId", description="任务ID") + params: param | None = Field(default=None, description="流执行过程中的参数补充", alias="params") class QuestionBlacklistRequest(BaseModel): diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index bf7f5995..d15ca7a4 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -29,6 +29,7 @@ from apps.schemas.mcp import ( MCPTool, MCPType, ) +from apps.services.user import UserManager from apps.schemas.request_data import UpdateMCPServiceRequest from apps.schemas.response_data import MCPServiceCardItem from apps.constants import MCP_PATH @@ -78,6 +79,7 @@ class MCPServiceManager: user_sub: str, keyword: str | None, page: int, + is_installed: bool | None = None, is_active: bool | None = None, ) -> list[MCPServiceCardItem]: """ @@ -95,6 +97,12 @@ class MCPServiceManager: filters["activated"] = {"$in": [user_sub]} else: filters["activated"] = {"$nin": [user_sub]} + if not is_installed: + user_info = await UserManager.get_user_info(user_sub) + if not user_info.is_admin: + filters["status"] = MCPInstallStatus.READY.value + else: + filters["status"] = MCPInstallStatus.READY.value mcpservice_pools = await MCPServiceManager._search_mcpservice(filters, page) return [ MCPServiceCardItem( -- Gitee From 4ae64e994fd874b21bf518ed4bb44e2b3b8e25a5 Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 8 Aug 2025 12:07:29 +0800 Subject: [PATCH 60/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E7=94=9F=E6=88=90=E7=9A=84prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/user.py | 10 ++++++---- apps/scheduler/executor/agent.py | 22 ++++++++++++++++------ apps/scheduler/mcp_agent/prompt.py | 16 ++++++++-------- apps/scheduler/scheduler/scheduler.py | 2 +- apps/schemas/message.py | 2 +- apps/schemas/request_data.py | 2 +- apps/schemas/response_data.py | 2 +- apps/schemas/user.py | 2 +- apps/services/appcenter.py | 1 - apps/services/user.py | 10 ++++++++-- openapi.json | 2 +- 11 files changed, 44 insertions(+), 27 deletions(-) diff --git a/apps/routers/user.py b/apps/routers/user.py index 8c197204..0a2995dd 100644 --- a/apps/routers/user.py +++ b/apps/routers/user.py @@ -3,7 +3,7 @@ from typing import Annotated -from fastapi import APIRouter, Body, Depends, status +from fastapi import APIRouter, Body, Depends, status, Query from fastapi.responses import JSONResponse from apps.dependency import get_user @@ -18,12 +18,14 @@ router = APIRouter( ) -@router.get("") +@router.get("", response_model=UserGetRsp) async def get_user_sub( user_sub: Annotated[str, Depends(get_user)], + page_size: Annotated[int, Query(description="每页用户数量")] = 20, + page_cnt: Annotated[int, Query(description="当前页码")] = 1, ) -> JSONResponse: """查询所有用户接口""" - user_list = await UserManager.get_all_user_sub() + user_list, total = await UserManager.get_all_user_sub(page_cnt=page_cnt, page_size=page_size, filter_user_subs=[user_sub]) user_info_list = [] for user in user_list: # user_info = await UserManager.get_userinfo_by_user_sub(user) 暂时不需要查询user_name @@ -40,7 +42,7 @@ async def get_user_sub( content=UserGetRsp( code=status.HTTP_200_OK, message="用户数据详细信息获取成功", - result=UserGetMsp(userInfoList=user_info_list), + result=UserGetMsp(userInfoList=user_info_list, total=total), ).model_dump(exclude_none=True, by_alias=True), ) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index aaa088ec..9ced57f9 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -46,7 +46,7 @@ class MCPAgentExecutor(BaseExecutor): tools: dict[str, MCPTool] = Field( description="MCP工具列表,key为tool_id", default={} ) - params: param | None = Field( + params: param | bool | None = Field( default=None, description="流执行过程中的参数补充", alias="params" ) resoning_llm: ReasoningLLM = Field( @@ -405,11 +405,21 @@ class MCPAgentExecutor(BaseExecutor): self.load_mcp() if self.task.state.flow_status == FlowStatus.INIT: # 初始化状态 - self.task.state.flow_id = str(uuid.uuid4()) - self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) - await self.plan(is_replan=False) - self.reset_step_to_index(0) - TaskManager.save_task(self.task.id, self.task) + try: + self.task.state.flow_id = str(uuid.uuid4()) + self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) + await self.plan(is_replan=False) + self.reset_step_to_index(0) + TaskManager.save_task(self.task.id, self.task) + except Exception as e: + logger.error("[MCPAgentExecutor] 初始化失败: %s", str(e)) + self.task.state.flow_status = FlowStatus.ERROR + self.task.state.error_message = str(e) + self.push_message( + EventType.FLOW_FAILED, + data={} + ) + return self.task.state.flow_status = FlowStatus.RUNNING self.push_message( EventType.FLOW_START, diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index b5bc085c..01d5dbf9 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -160,9 +160,9 @@ EVALUATE_GOAL = dedent(r""" # 工具集合 - { % for tool in tools % } + {% for tool in tools %} - {{tool.id}} {{tool.name}};{{tool.description}} - { % endfor % } + {% endfor %} # 附加信息 @@ -293,9 +293,9 @@ CREATE_PLAN = dedent(r""" 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - { % for tool in tools % } + {% for tool in tools %} - {{tool.id}} {{tool.name}};{{tool.description}} - { % endfor % } + {% endfor %} # 样例 @@ -484,9 +484,9 @@ RECREATE_PLAN = dedent(r""" 你可以访问并使用一些工具,这些工具将在 XML标签中给出。 - { % for tool in tools % } + {% for tool in tools %} - {{tool.id}} {{tool.name}};{{tool.description}} - { % endfor % } + {% endfor %} # 当前计划 @@ -796,10 +796,10 @@ FINAL_ANSWER = dedent(r""" """) MEMORY_TEMPLATE = dedent(r""" - {% for ctx in context_list % } + {% for ctx in context_list %} - 第{{loop.index}}步:{{ctx.step_description}} - 调用工具 `{{ctx.step_id}}`,并提供参数 `{{ctx.input_data}}` - 执行状态:{{ctx.status}} - 得到数据:`{{ctx.output_data}}` - {% endfor % } + {% endfor %} """) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index 523587e3..7731dd85 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -295,7 +295,7 @@ class Scheduler: servers_id=servers_id, background=background, agent_id=app_info.app_id, - params=post_body.app.params + params=post_body.params ) # 开始运行 logger.info("[Scheduler] 运行Executor") diff --git a/apps/schemas/message.py b/apps/schemas/message.py index 1f46ff57..c55fc6d1 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -11,7 +11,7 @@ from apps.schemas.record import RecordMetadata class param(BaseModel): """流执行过程中的参数补充""" - content: dict[str, Any] | bool = Field(default={}, description="流执行过程中的参数补充内容") + content: dict[str, Any] = Field(default={}, description="流执行过程中的参数补充内容") description: str = Field(default="", description="流执行过程中的参数补充描述") diff --git a/apps/schemas/request_data.py b/apps/schemas/request_data.py index 7c2d1a96..3fd5a67f 100644 --- a/apps/schemas/request_data.py +++ b/apps/schemas/request_data.py @@ -47,7 +47,7 @@ class RequestData(BaseModel): app: RequestDataApp | None = Field(default=None, description="应用") debug: bool = Field(default=False, description="是否调试") task_id: str | None = Field(default=None, alias="taskId", description="任务ID") - params: param | None = Field(default=None, description="流执行过程中的参数补充", alias="params") + params: param | bool | None = Field(default=None, description="流执行过程中的参数补充", alias="params") class QuestionBlacklistRequest(BaseModel): diff --git a/apps/schemas/response_data.py b/apps/schemas/response_data.py index 0dcc04ea..542dac88 100644 --- a/apps/schemas/response_data.py +++ b/apps/schemas/response_data.py @@ -593,7 +593,7 @@ class FlowStructureDeleteRsp(ResponseData): class UserGetMsp(BaseModel): """GET /api/user result""" - + total: int = Field(default=0) user_info_list: list[UserInfo] = Field(alias="userInfoList", default=[]) diff --git a/apps/schemas/user.py b/apps/schemas/user.py index debb3446..ebea6692 100644 --- a/apps/schemas/user.py +++ b/apps/schemas/user.py @@ -9,4 +9,4 @@ class UserInfo(BaseModel): user_sub: str = Field(alias="userSub", default="") user_name: str = Field(alias="userName", default="") - auto_execute: bool = Field(alias="autoExecute", default=False) + auto_execute: bool | None = Field(alias="autoExecute", default=False) diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index 85cdba8f..6b6e3171 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -59,7 +59,6 @@ class AppCenterManager: } user_favorite_app_ids = await AppCenterManager._get_favorite_app_ids_by_user(user_sub) - logger.info("[AppCenterManager] 获取应用列表: %s", filters) if filter_type == AppFilterType.ALL: # 获取所有已发布的应用 filters["published"] = True diff --git a/apps/services/user.py b/apps/services/user.py index 476f1ef4..ef50e9e3 100644 --- a/apps/services/user.py +++ b/apps/services/user.py @@ -29,7 +29,7 @@ class UserManager: ).model_dump(by_alias=True)) @staticmethod - async def get_all_user_sub() -> list[str]: + async def get_all_user_sub(page_size: int = 20, page_cnt: int = 1, filter_user_subs: list[str] = []) -> tuple[list[str], int]: """ 获取所有用户的sub @@ -37,7 +37,13 @@ class UserManager: """ mongo = MongoDB() user_collection = mongo.get_collection("user") - return [user["_id"] async for user in user_collection.find({}, {"_id": 1})] + total = await user_collection.count_documents({}) - len(filter_user_subs) + + users = await user_collection.find( + {"_id": {"$nin": filter_user_subs}}, + {"_id": 1}, + ).skip((page_cnt - 1) * page_size).limit(page_size).to_list(length=page_size) + return [user["_id"] for user in users], total @staticmethod async def get_userinfo_by_user_sub(user_sub: str) -> User | None: diff --git a/openapi.json b/openapi.json index 17fb18bd..e8ffc33b 100644 --- a/openapi.json +++ b/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/conversation":{"get":{"tags":["conversation"],"summary":"Get Conversation List","description":"获取对话列表","operationId":"get_conversation_list_api_conversation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListRsp"}}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"}}},"post":{"tags":["conversation"],"summary":"Add Conversation","description":"手动创建新对话","operationId":"add_conversation_api_conversation_post","parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string","default":"","title":"Appid"}},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Debug"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_conversation_api_conversation_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["conversation"],"summary":"Update Conversation","description":"更新特定Conversation的数据","operationId":"update_conversation_api_conversation_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["conversation"],"summary":"Delete Conversation","description":"删除特定对话","operationId":"delete_conversation_api_conversation_delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/login":{"get":{"tags":["auth"],"summary":"Oidc Login","description":"OIDC login\n\n:param request: Request object\n:param code: OIDC code\n:return: HTMLResponse","operationId":"oidc_login_api_auth_login_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"get":{"tags":["auth"],"summary":"Logout","description":"用户登出EulerCopilot","operationId":"logout_api_auth_logout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}},"post":{"tags":["auth"],"summary":"Oidc Logout","description":"OIDC主动触发登出","operationId":"oidc_logout_api_auth_logout_post","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/redirect":{"get":{"tags":["auth"],"summary":"Oidc Redirect","description":"OIDC重定向URL","operationId":"oidc_redirect_api_auth_redirect_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRedirectRsp"}}}}}}},"/api/auth/user":{"get":{"tags":["auth"],"summary":"Userinfo","description":"获取用户信息","operationId":"userinfo_api_auth_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}}}}},"/api/auth/update_revision_number":{"post":{"tags":["auth"],"summary":"Update Revision Number","description":"更新用户协议信息","operationId":"update_revision_number_api_auth_update_revision_number_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/auth/key":{"get":{"tags":["key"],"summary":"Check Api Key Existence","description":"检查API密钥是否存在","operationId":"check_api_key_existence_api_auth_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAuthKeyRsp"}}}}}},"post":{"tags":["key"],"summary":"Manage Api Key","description":"管理用户的API密钥","operationId":"manage_api_key_api_auth_key_post","parameters":[{"name":"action","in":"query","required":true,"schema":{"type":"string","title":"Action"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAuthKeyRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app":{"get":{"tags":["appcenter"],"summary":"Get Applications","description":"获取应用列表","operationId":"get_applications_api_app_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"appType","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AppType"},{"type":"null"}],"description":"应用类型","title":"Apptype"},"description":"应用类型"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Applications Api App Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Create Or Update Application","description":"创建或更新应用","operationId":"create_or_update_application_api_app_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Create Or Update Application Api App Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/recent":{"get":{"tags":["appcenter"],"summary":"Get Recently Used Applications","description":"获取最近使用的应用","operationId":"get_recently_used_applications_api_app_recent_get","parameters":[{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":1,"default":5,"title":"Count"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetRecentAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Recently Used Applications Api App Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/{appId}":{"get":{"tags":["appcenter"],"summary":"Get Application","description":"获取应用详情","operationId":"get_application_api_app__appId__get","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppPropertyRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Application Api App Appid Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["appcenter"],"summary":"Delete Application","description":"删除应用","operationId":"delete_application_api_app__appId__delete","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Delete Application Api App Appid Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Publish Application","description":"发布应用","operationId":"publish_application_api_app__appId__post","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseAppOperationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["appcenter"],"summary":"Modify Favorite Application","description":"更改应用收藏状态","operationId":"modify_favorite_application_api_app__appId__put","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ModFavAppRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Modify Favorite Application Api App Appid Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service":{"get":{"tags":["service-center"],"summary":"Get Service List","description":"获取服务列表","operationId":"get_service_list_api_service_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"每页数量","default":16,"title":"Pagesize"},"description":"每页数量"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Service List Api Service Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["service-center"],"summary":"Update Service","description":"上传并解析服务","operationId":"update_service_api_service_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest","description":"上传 YAML 文本对应数据对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service/{serviceId}":{"get":{"tags":["service-center"],"summary":"Get Service Detail","description":"获取服务详情","operationId":"get_service_detail_api_service__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["service-center"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_service__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["service-center"],"summary":"Modify Favorite Service","description":"修改服务收藏状态","operationId":"modify_favorite_service_api_service__serviceId__put","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRequest","description":"更改收藏状态请求对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comment":{"post":{"tags":["comment"],"summary":"Add Comment","description":"给Record添加评论","operationId":"add_comment_api_comment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCommentData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/record/{conversation_id}":{"get":{"tags":["record"],"summary":"Get Record","description":"获取某个对话的所有问答对","operationId":"get_record_api_record__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordListRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_check":{"get":{"tags":["health_check"],"summary":"Health Check","description":"健康检查接口","operationId":"health_check_health_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckRsp"}}}}}}},"/api/chat":{"post":{"tags":["chat"],"summary":"Chat","description":"LLM流式对话接口","operationId":"chat_api_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stop":{"post":{"tags":["chat"],"summary":"Stop Generation","description":"停止生成","operationId":"stop_generation_api_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/blacklist/user":{"get":{"tags":["blacklist"],"summary":"Get Blacklist User","description":"获取黑名单用户","operationId":"get_blacklist_user_api_blacklist_user_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistUserRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist User","description":"操作黑名单用户","operationId":"change_blacklist_user_api_blacklist_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/question":{"get":{"tags":["blacklist"],"summary":"Get Blacklist Question","description":"获取黑名单问题\n\n目前情况下,先直接输出问题,不做用户类型校验","operationId":"get_blacklist_question_api_blacklist_question_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist Question","description":"黑名单问题检测或操作","operationId":"change_blacklist_question_api_blacklist_question_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/complaint":{"post":{"tags":["blacklist"],"summary":"Abuse Report","description":"用户实施举报","operationId":"abuse_report_api_blacklist_complaint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/abuse":{"get":{"tags":["blacklist"],"summary":"Get Abuse Report","description":"获取待审核的问答对","operationId":"get_abuse_report_api_blacklist_abuse_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Abuse Report","description":"对被举报问答对进行操作","operationId":"change_abuse_report_api_blacklist_abuse_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseProcessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{conversation_id}":{"post":{"tags":["document"],"summary":"Document Upload","description":"上传文档","operationId":"document_upload_api_document__conversation_id__post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_document_upload_api_document__conversation_id__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["document"],"summary":"Get Document List","description":"获取文档列表","operationId":"get_document_list_api_document__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"used","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Used"}},{"name":"unused","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Unused"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDocumentRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{document_id}":{"delete":{"tags":["document"],"summary":"Delete Single Document","description":"删除单个文件","operationId":"delete_single_document_api_document__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge":{"get":{"tags":["knowledge"],"summary":"List Kb","description":"获取当前用户的知识库ID","operationId":"list_kb_api_knowledge_get","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}},{"name":"kbId","in":"query","required":false,"schema":{"type":"string","title":"Kbid"}},{"name":"kbName","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kbname"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamKnowledgeRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["knowledge"],"summary":"Update Conversation Kb","description":"更新当前用户的知识库ID","operationId":"update_conversation_kb_api_knowledge_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKbReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/provider":{"get":{"tags":["llm"],"summary":"List Llm Provider","description":"获取大模型提供商列表","operationId":"list_llm_provider_api_llm_provider_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMProviderRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/llm":{"get":{"tags":["llm"],"summary":"List Llm","description":"获取大模型列表","operationId":"list_llm_api_llm_get","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["llm"],"summary":"Create Llm","description":"创建或更新大模型配置","operationId":"create_llm_api_llm_put","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLLMReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["llm"],"summary":"Delete Llm","description":"删除大模型配置","operationId":"delete_llm_api_llm_delete","parameters":[{"name":"llmId","in":"query","required":true,"schema":{"type":"string","description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/conv":{"put":{"tags":["llm"],"summary":"Update Conv Llm","description":"更新对话的知识库","operationId":"update_conv_llm_api_llm_conv_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","description":"对话ID","title":"Conversationid"},"description":"对话ID"},{"name":"llmId","in":"query","required":false,"schema":{"type":"string","description":"llm ID","default":"empty","title":"Llmid"},"description":"llm ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp":{"get":{"tags":["mcp-service"],"summary":"Get Mcpservice List","description":"获取服务列表","operationId":"get_mcpservice_list_api_mcp_get","parameters":[{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"isActive","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否激活","title":"Isactive"},"description":"是否激活"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Mcpservice List Api Mcp Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Create Or Update Mcpservice","description":"新建或更新MCP服务","operationId":"create_or_update_mcpservice_api_mcp_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}/install":{"post":{"tags":["mcp-service"],"summary":"Install Mcp Service","operationId":"install_mcp_service_api_mcp__serviceId__install_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"install","in":"query","required":false,"schema":{"type":"boolean","description":"是否安装","default":true,"title":"Install"},"description":"是否安装"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}":{"get":{"tags":["mcp-service"],"summary":"Get Service Detail","description":"获取MCP服务详情","operationId":"get_service_detail_api_mcp__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMCPServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["mcp-service"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_mcp__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Active Or Deactivate Mcp Service","description":"激活/取消激活mcp","operationId":"active_or_deactivate_mcp_service_api_mcp__serviceId__post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/icon":{"post":{"tags":["mcp-service"],"summary":"Update Mcp Icon","description":"更新MCP服务图标","operationId":"update_mcp_icon_api_mcp_icon_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_mcp_icon_api_mcp_icon_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/flow/service":{"get":{"tags":["flow"],"summary":"Get Services","description":"获取用户可访问的节点元数据所在服务的信息","operationId":"get_services_api_flow_service_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeServiceListRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/flow":{"get":{"tags":["flow"],"summary":"Get Flow","description":"获取流拓扑结构","operationId":"get_flow_api_flow_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureGetRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["flow"],"summary":"Put Flow","description":"修改流拓扑结构","operationId":"put_flow_api_flow_put","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutFlowReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructurePutRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["flow"],"summary":"Delete Flow","description":"删除流拓扑结构","operationId":"delete_flow_api_flow_delete","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureDeleteRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"get":{"tags":["user"],"summary":"Get User Sub","description":"查询所有用户接口","operationId":"get_user_sub_api_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["user"],"summary":"Update User Info","description":"更新用户信息接口","operationId":"update_user_info_api_user_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest","description":"用户更新信息"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter":{"get":{"tags":["parameter"],"summary":"Get Parameters","description":"Get parameters for node choice.","operationId":"get_parameters_api_parameter_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}},{"name":"stepId","in":"query","required":true,"schema":{"type":"string","title":"Stepid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetParamsRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter/operate":{"get":{"tags":["parameter"],"summary":"Get Operate Parameters","description":"Get parameters for node choice.","operationId":"get_operate_parameters_api_parameter_operate_get","parameters":[{"name":"ParamType","in":"query","required":true,"schema":{"type":"string","title":"Paramtype"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOperaRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbuseProcessRequest":{"properties":{"id":{"type":"string","title":"Id"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","is_deletion"],"title":"AbuseProcessRequest","description":"POST /api/blacklist/abuse 请求数据结构"},"AbuseRequest":{"properties":{"record_id":{"type":"string","title":"Record Id"},"reason":{"type":"string","title":"Reason"},"reason_type":{"type":"string","title":"Reason Type"}},"type":"object","required":["record_id","reason","reason_type"],"title":"AbuseRequest","description":"POST /api/blacklist/complaint 请求数据结构"},"ActiveMCPServiceRequest":{"properties":{"active":{"type":"boolean","title":"Active","description":"是否激活mcp服务"},"mcpEnv":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mcpenv","description":"MCP服务环境变量"}},"type":"object","required":["active"],"title":"ActiveMCPServiceRequest","description":"POST /api/mcp/{serviceId} 请求数据结构"},"ActiveMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ActiveMCPServiceRsp","description":"POST /api/mcp/active/{serviceId} 返回数据结构"},"AddCommentData":{"properties":{"record_id":{"type":"string","title":"Record Id"},"group_id":{"type":"string","title":"Group Id"},"comment":{"$ref":"#/components/schemas/CommentType"},"dislike_reason":{"type":"string","maxLength":200,"title":"Dislike Reason","default":""},"reason_link":{"type":"string","maxLength":200,"title":"Reason Link","default":""},"reason_description":{"type":"string","maxLength":500,"title":"Reason Description","default":""}},"type":"object","required":["record_id","group_id","comment"],"title":"AddCommentData","description":"添加评论"},"AddConversationMsg":{"properties":{"conversationId":{"type":"string","title":"Conversationid"}},"type":"object","required":["conversationId"],"title":"AddConversationMsg","description":"POST /api/conversation Result数据结构"},"AddConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AddConversationMsg"}},"type":"object","required":["code","message","result"],"title":"AddConversationRsp","description":"POST /api/conversation 返回数据结构"},"AppCenterCardItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"应用图标"},"name":{"type":"string","title":"Name","description":"应用名称"},"description":{"type":"string","title":"Description","description":"应用简介"},"author":{"type":"string","title":"Author","description":"应用作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"},"published":{"type":"boolean","title":"Published","description":"是否已发布","default":true}},"type":"object","required":["appId","appType","icon","name","description","author","favorited"],"title":"AppCenterCardItem","description":"应用中心卡片数据结构"},"AppFlowInfo":{"properties":{"id":{"type":"string","title":"Id","description":"工作流ID"},"name":{"type":"string","title":"Name","description":"工作流名称"},"description":{"type":"string","title":"Description","description":"工作流简介"},"debug":{"type":"boolean","title":"Debug","description":"是否经过调试"}},"type":"object","required":["id","name","description","debug"],"title":"AppFlowInfo","description":"应用工作流数据结构"},"AppLink":{"properties":{"title":{"type":"string","title":"Title","description":"链接标题"},"url":{"type":"string","pattern":"^(https|http)://.*$","title":"Url","description":"链接地址"}},"type":"object","required":["title","url"],"title":"AppLink","description":"App的相关链接"},"AppMcpServiceInfo":{"properties":{"id":{"type":"string","title":"Id","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务简介"}},"type":"object","required":["id","name","description"],"title":"AppMcpServiceInfo","description":"应用关联的MCP服务信息"},"AppPermissionData":{"properties":{"visibility":{"$ref":"#/components/schemas/PermissionType","description":"可见性(public/private/protected)","default":"private"},"authorizedUsers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Authorizedusers","description":"附加人员名单(如果可见性为部分人可见)"}},"type":"object","title":"AppPermissionData","description":"应用权限数据结构"},"AppType":{"type":"string","enum":["flow","agent"],"title":"AppType","description":"应用中心应用类型"},"AuthUserMsg":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"revision":{"type":"boolean","title":"Revision"},"is_admin":{"type":"boolean","title":"Is Admin"},"auto_execute":{"type":"boolean","title":"Auto Execute"}},"type":"object","required":["user_sub","revision","is_admin","auto_execute"],"title":"AuthUserMsg","description":"GET /api/auth/user Result数据结构"},"AuthUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AuthUserMsg"}},"type":"object","required":["code","message","result"],"title":"AuthUserRsp","description":"GET /api/auth/user 返回数据结构"},"BaseAppOperationMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"}},"type":"object","required":["appId"],"title":"BaseAppOperationMsg","description":"基础应用操作Result数据结构"},"BaseAppOperationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseAppOperationMsg"}},"type":"object","required":["code","message","result"],"title":"BaseAppOperationRsp","description":"基础应用操作返回数据结构"},"BaseMCPServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseMCPServiceOperationMsg","description":"插件中心:MCP服务操作Result数据结构"},"BaseServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseServiceOperationMsg","description":"语义接口中心:基础服务操作Result数据结构"},"Blacklist":{"properties":{"_id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_audited":{"type":"boolean","title":"Is Audited","default":false},"reason_type":{"type":"string","title":"Reason Type","default":""},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"updated_at":{"type":"number","title":"Updated At"}},"type":"object","required":["question","answer"],"title":"Blacklist","description":"黑名单\n\nCollection: blacklist"},"Body_add_conversation_api_conversation_post":{"properties":{"llm_id":{"type":"string","title":"Llm Id","default":"empty"},"kb_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Kb Ids"}},"type":"object","title":"Body_add_conversation_api_conversation_post"},"Body_document_upload_api_document__conversation_id__post":{"properties":{"documents":{"items":{"type":"string","format":"binary"},"type":"array","title":"Documents"}},"type":"object","required":["documents"],"title":"Body_document_upload_api_document__conversation_id__post"},"Body_update_mcp_icon_api_mcp_icon_post":{"properties":{"icon":{"type":"string","format":"binary","title":"Icon","description":"图标文件"}},"type":"object","required":["icon"],"title":"Body_update_mcp_icon_api_mcp_icon_post"},"BoolOperate":{"type":"string","enum":["bool_equal","bool_not_equal"],"title":"BoolOperate","description":"Choice 工具支持的布尔运算符"},"CommentType":{"type":"string","enum":["liked","disliked","none"],"title":"CommentType","description":"点赞点踩类型"},"ConversationDocumentItem":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"type":"null","title":"Conversation Id"},"status":{"$ref":"#/components/schemas/DocumentStatus"}},"type":"object","required":["name","type","size","status"],"title":"ConversationDocumentItem","description":"GET /api/document/{conversation_id} Result内元素数据结构"},"ConversationDocumentMsg":{"properties":{"documents":{"items":{"$ref":"#/components/schemas/ConversationDocumentItem"},"type":"array","title":"Documents","default":[]}},"type":"object","title":"ConversationDocumentMsg","description":"GET /api/document/{conversation_id} Result数据结构"},"ConversationDocumentRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationDocumentMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationDocumentRsp","description":"GET /api/document/{conversation_id} 返回数据结构"},"ConversationListItem":{"properties":{"conversationId":{"type":"string","title":"Conversationid"},"title":{"type":"string","title":"Title"},"docCount":{"type":"integer","title":"Doccount"},"createdTime":{"type":"string","title":"Createdtime"},"appId":{"type":"string","title":"Appid"},"debug":{"type":"boolean","title":"Debug"},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"kbList":{"items":{"$ref":"#/components/schemas/KbIteam"},"type":"array","title":"Kblist","default":[]}},"type":"object","required":["conversationId","title","docCount","createdTime","appId","debug"],"title":"ConversationListItem","description":"GET /api/conversation Result数据结构"},"ConversationListMsg":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationListItem"},"type":"array","title":"Conversations"}},"type":"object","required":["conversations"],"title":"ConversationListMsg","description":"GET /api/conversation Result数据结构"},"ConversationListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationListRsp","description":"GET /api/conversation 返回数据结构"},"CreateAppRequest":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llmId":{"type":"string","title":"Llmid","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appid","description":"应用ID"}},"type":"object","required":["appType","name","description"],"title":"CreateAppRequest","description":"POST /api/app 请求数据结构"},"DeleteConversationData":{"properties":{"conversationList":{"items":{"type":"string"},"type":"array","title":"Conversationlist"}},"type":"object","required":["conversationList"],"title":"DeleteConversationData","description":"删除会话"},"DeleteMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteMCPServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DeleteServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DependencyItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"type":{"type":"string","title":"Type"}},"type":"object","required":["nodeId","type"],"title":"DependencyItem","description":"请求/响应中的节点依赖变量类"},"DictOperate":{"type":"string","enum":["dict_equal","dict_not_equal","dict_contains_key","dict_not_contains_key"],"title":"DictOperate","description":"Choice 工具支持的字典运算符"},"DocumentStatus":{"type":"string","enum":["used","unused","processing","failed"],"title":"DocumentStatus","description":"文档状态"},"EdgeItem":{"properties":{"edgeId":{"type":"string","title":"Edgeid"},"sourceNode":{"type":"string","title":"Sourcenode"},"targetNode":{"type":"string","title":"Targetnode"},"type":{"type":"string","title":"Type","default":"normal"},"branchId":{"type":"string","title":"Branchid"}},"type":"object","required":["edgeId","sourceNode","targetNode","branchId"],"title":"EdgeItem","description":"请求/响应中的边变量类"},"EditMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"data":{"type":"string","title":"Data","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType"}},"type":"object","required":["serviceId","name","description","overview","data","mcpType"],"title":"EditMCPServiceMsg","description":"编辑MCP服务"},"FlowItem-Input":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowItem-Output":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowStructureDeleteMsg":{"properties":{"flowId":{"type":"string","title":"Flowid","default":""}},"type":"object","title":"FlowStructureDeleteMsg","description":"DELETE /api/flow/ result"},"FlowStructureDeleteRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureDeleteMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureDeleteRsp","description":"DELETE /api/flow/ 返回数据结构"},"FlowStructureGetMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructureGetMsg","description":"GET /api/flow result"},"FlowStructureGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureGetMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureGetRsp","description":"GET /api/flow 返回数据结构"},"FlowStructurePutMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructurePutMsg","description":"PUT /api/flow result"},"FlowStructurePutRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructurePutMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructurePutRsp","description":"PUT /api/flow 返回数据结构"},"FootNoteMetaData":{"properties":{"releatedId":{"type":"string","title":"Releatedid","description":"相关ID","default":""},"insertPosition":{"type":"integer","title":"Insertposition","description":"插入位置","default":0},"footSource":{"type":"string","title":"Footsource","description":"脚注来源","default":""},"footType":{"type":"string","title":"Foottype","description":"脚注类型","default":""}},"type":"object","title":"FootNoteMetaData","description":"Record表子项:Record的脚注元信息"},"GetAppListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalApps":{"type":"integer","title":"Totalapps","description":"总应用数"},"applications":{"items":{"$ref":"#/components/schemas/AppCenterCardItem"},"type":"array","title":"Applications","description":"应用列表"}},"type":"object","required":["currentPage","totalApps","applications"],"title":"GetAppListMsg","description":"GET /api/app Result数据结构"},"GetAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppListMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppListRsp","description":"GET /api/app 返回数据结构"},"GetAppPropertyMsg":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llmId":{"type":"string","title":"Llmid","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"type":"string","title":"Appid","description":"应用ID"},"published":{"type":"boolean","title":"Published","description":"是否已发布"}},"type":"object","required":["appType","name","description","appId","published"],"title":"GetAppPropertyMsg","description":"GET /api/app/{appId} Result数据结构"},"GetAppPropertyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppPropertyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppPropertyRsp","description":"GET /api/app/{appId} 返回数据结构"},"GetAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/_GetAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAuthKeyRsp","description":"GET /api/auth/key 返回数据结构"},"GetBlacklistQuestionMsg":{"properties":{"question_list":{"items":{"$ref":"#/components/schemas/Blacklist"},"type":"array","title":"Question List"}},"type":"object","required":["question_list"],"title":"GetBlacklistQuestionMsg","description":"GET /api/blacklist/question Result数据结构"},"GetBlacklistQuestionRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistQuestionMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistQuestionRsp","description":"GET /api/blacklist/question 返回数据结构"},"GetBlacklistUserMsg":{"properties":{"user_subs":{"items":{"type":"string"},"type":"array","title":"User Subs"}},"type":"object","required":["user_subs"],"title":"GetBlacklistUserMsg","description":"GET /api/blacklist/user Result数据结构"},"GetBlacklistUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistUserMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistUserRsp","description":"GET /api/blacklist/user 返回数据结构"},"GetMCPServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"tools":{"items":{"$ref":"#/components/schemas/MCPTool"},"type":"array","title":"Tools","description":"MCP服务Tools列表","default":[]}},"type":"object","required":["serviceId","name","description","overview"],"title":"GetMCPServiceDetailMsg","description":"GET /api/mcp_service/{serviceId} Result数据结构"},"GetMCPServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceDetailMsg"},{"$ref":"#/components/schemas/EditMCPServiceMsg"}],"title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetMCPServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"services":{"items":{"$ref":"#/components/schemas/MCPServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","services"],"title":"GetMCPServiceListMsg","description":"GET /api/service Result数据结构"},"GetMCPServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetMCPServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceListRsp","description":"GET /api/service 返回数据结构"},"GetOperaRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/OperateAndBindType"},"type":"array","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetOperaRsp","description":"GET /api/operate 返回数据结构"},"GetParamsRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/StepParams"},"type":"array","title":"Result","description":"参数列表","default":[]}},"type":"object","required":["code","message"],"title":"GetParamsRsp","description":"GET /api/params 返回数据结构"},"GetRecentAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecentAppList"}},"type":"object","required":["code","message","result"],"title":"GetRecentAppListRsp","description":"GET /api/app/recent 返回数据结构"},"GetServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array"},{"type":"null"}],"title":"Apis","description":"解析后的接口列表"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data","description":"YAML 内容数据对象"}},"type":"object","required":["serviceId","name"],"title":"GetServiceDetailMsg","description":"GET /api/service/{serviceId} Result数据结构"},"GetServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceDetailMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalCount":{"type":"integer","title":"Totalcount","description":"总服务数"},"services":{"items":{"$ref":"#/components/schemas/ServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","totalCount","services"],"title":"GetServiceListMsg","description":"GET /api/service Result数据结构"},"GetServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceListRsp","description":"GET /api/service 返回数据结构"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthCheckRsp":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HealthCheckRsp","description":"GET /health_check 返回数据结构"},"KbIteam":{"properties":{"kbId":{"type":"string","title":"Kbid"},"kbName":{"type":"string","title":"Kbname"}},"type":"object","required":["kbId","kbName"],"title":"KbIteam","description":"GET /api/conversation Result数据结构"},"KnowledgeBaseItem":{"properties":{"kbId":{"type":"string","title":"Kbid","description":"知识库ID"},"kbName":{"type":"string","title":"Kbname","description":"知识库名称"},"description":{"type":"string","title":"Description","description":"知识库描述"},"isUsed":{"type":"boolean","title":"Isused","description":"是否使用"}},"type":"object","required":["kbId","kbName","description","isUsed"],"title":"KnowledgeBaseItem","description":"知识库列表项数据结构"},"LLMIteam":{"properties":{"icon":{"type":"string","title":"Icon","default":"data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIGZpbGwtcnVsZT0iZXZlbm9kZCIgaGVpZ2h0PSIxZW0iIHN0eWxlPSJmbGV4Om5vbmU7bGluZS1oZWlnaHQ6MSIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMWVtIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5PbGxhbWE8L3RpdGxlPjxwYXRoIGQ9Ik03LjkwNSAxLjA5Yy4yMTYuMDg1LjQxMS4yMjUuNTg4LjQxLjI5NS4zMDYuNTQ0Ljc0NC43MzQgMS4yNjMuMTkxLjUyMi4zMTUgMS4xLjM2MiAxLjY4YTUuMDU0IDUuMDU0IDAgMDEyLjA0OS0uNjM2bC4wNTEtLjAwNGMuODctLjA3IDEuNzMuMDg3IDIuNDguNDc0LjEwMS4wNTMuMi4xMS4yOTcuMTcuMDUtLjU2OS4xNzItMS4xMzQuMzYtMS42NDQuMTktLjUyLjQzOS0uOTU3LjczMy0xLjI2NGExLjY3IDEuNjcgMCAwMS41ODktLjQxYy4yNTctLjEuNTMtLjExOC43OTYtLjA0Mi40MDEuMTE0Ljc0NS4zNjggMS4wMTYuNzM3LjI0OC4zMzcuNDM0Ljc2OS41NjEgMS4yODcuMjMuOTM0LjI3IDIuMTYzLjExNSAzLjY0NWwuMDUzLjA0LjAyNi4wMTljLjc1Ny41NzYgMS4yODQgMS4zOTcgMS41NjMgMi4zNS40MzUgMS40ODcuMjE2IDMuMTU1LS41MzQgNC4wODhsLS4wMTguMDIxLjAwMi4wMDNjLjQxNy43NjIuNjcgMS41NjcuNzI0IDIuNGwuMDAyLjAzYy4wNjQgMS4wNjUtLjIgMi4xMzctLjgxNCAzLjE5bC0uMDA3LjAxLjAxLjAyNGMuNDcyIDEuMTU3LjYyIDIuMzIyLjQzOCAzLjQ4NmwtLjAwNi4wMzlhLjY1MS42NTEgMCAwMS0uNzQ3LjUzNi42NDguNjQ4IDAgMDEtLjU0LS43NDJjLjE2Ny0xLjAzMy4wMS0yLjA2OS0uNDgtMy4xMjNhLjY0My42NDMgMCAwMS4wNC0uNjE3bC4wMDQtLjAwNmMuNjA0LS45MjQuODU0LTEuODMuOC0yLjcyLS4wNDYtLjc3OS0uMzI1LTEuNTQ0LS44LTIuMjczYS42NDQuNjQ0IDAgMDEuMTgtLjg4NmwuMDA5LS4wMDZjLjI0My0uMTU5LjQ2Ny0uNTY1LjU4LTEuMTJhNC4yMjkgNC4yMjkgMCAwMC0uMDk1LTEuOTc0Yy0uMjA1LS43LS41OC0xLjI4NC0xLjEwNS0xLjY4My0uNTk1LS40NTQtMS4zODMtLjY3My0yLjM4LS42MWEuNjUzLjY1MyAwIDAxLS42MzItLjM3MWMtLjMxNC0uNjY1LS43NzItMS4xNDEtMS4zNDMtMS40MzZhMy4yODggMy4yODggMCAwMC0xLjc3Mi0uMzMyYy0xLjI0NS4wOTktMi4zNDMuODAxLTIuNjcgMS42ODZhLjY1Mi42NTIgMCAwMS0uNjEuNDI1Yy0xLjA2Ny4wMDItMS44OTMuMjUyLTIuNDk3LjcwMy0uNTIyLjM5LS44NzguOTM1LTEuMDY2IDEuNTg4YTQuMDcgNC4wNyAwIDAwLS4wNjggMS44ODZjLjExMi41NTguMzMxIDEuMDIuNTgyIDEuMjY5bC4wMDguMDA3Yy4yMTIuMjA3LjI1Ny41My4xMDkuNzg1LS4zNi42MjItLjYyOSAxLjU0OS0uNjczIDIuNDQtLjA1IDEuMDE4LjE4NiAxLjkwMi43MTkgMi41MzZsLjAxNi4wMTlhLjY0My42NDMgMCAwMS4wOTUuNjljLS41NzYgMS4yMzYtLjc1MyAyLjI1Mi0uNTYyIDMuMDUyYS42NTIuNjUyIDAgMDEtMS4yNjkuMjk4Yy0uMjQzLTEuMDE4LS4wNzgtMi4xODQuNDczLTMuNDk4bC4wMTQtLjAzNS0uMDA4LS4wMTJhNC4zMzkgNC4zMzkgMCAwMS0uNTk4LTEuMzA5bC0uMDA1LS4wMTlhNS43NjQgNS43NjQgMCAwMS0uMTc3LTEuNzg1Yy4wNDQtLjkxLjI3OC0xLjg0Mi42MjItMi41OWwuMDEyLS4wMjYtLjAwMi0uMDAyYy0uMjkzLS40MTgtLjUxLS45NTMtLjYzLTEuNTQ1bC0uMDA1LS4wMjRhNS4zNTIgNS4zNTIgMCAwMS4wOTMtMi40OWMuMjYyLS45MTUuNzc3LTEuNzAxIDEuNTM2LTIuMjY5LjA2LS4wNDUuMTIzLS4wOS4xODYtLjEzMi0uMTU5LTEuNDkzLS4xMTktMi43My4xMTItMy42Ny4xMjctLjUxOC4zMTQtLjk1LjU2Mi0xLjI4Ny4yNy0uMzY4LjYxNC0uNjIyIDEuMDE1LS43MzcuMjY2LS4wNzYuNTQtLjA1OS43OTcuMDQyem00LjExNiA5LjA5Yy45MzYgMCAxLjguMzEzIDIuNDQ2Ljg1NS42My41MjcgMS4wMDUgMS4yMzUgMS4wMDUgMS45NCAwIC44ODgtLjQwNiAxLjU4LTEuMTMzIDIuMDIyLS42Mi4zNzUtMS40NTEuNTU3LTIuNDAzLjU1Ny0xLjAwOSAwLTEuODcxLS4yNTktMi40OTMtLjczNC0uNjE3LS40Ny0uOTYzLTEuMTMtLjk2My0xLjg0NSAwLS43MDcuMzk4LTEuNDE3IDEuMDU2LTEuOTQ2LjY2OC0uNTM3IDEuNTUtLjg0OSAyLjQ4NS0uODQ5em0wIC44OTZhMy4wNyAzLjA3IDAgMDAtMS45MTYuNjVjLS40NjEuMzctLjcyMi44MzUtLjcyMiAxLjI1IDAgLjQyOC4yMS44MjkuNjEgMS4xMzQuNDU1LjM0NyAxLjEyNC41NDggMS45NDMuNTQ4Ljc5OSAwIDEuNDczLS4xNDcgMS45MzItLjQyNi40NjMtLjI4LjctLjY4Ni43LTEuMjU3IDAtLjQyMy0uMjQ2LS44OS0uNjgzLTEuMjU2LS40ODQtLjQwNS0xLjE0LS42NDMtMS44NjQtLjY0M3ptLjY2MiAxLjIxbC4wMDQuMDA0Yy4xMi4xNTEuMDk1LjM3LS4wNTYuNDlsLS4yOTIuMjN2LjQ0NmEuMzc1LjM3NSAwIDAxLS4zNzYuMzczLjM3NS4zNzUgMCAwMS0uMzc2LS4zNzN2LS40NmwtLjI3MS0uMjE4YS4zNDcuMzQ3IDAgMDEtLjA1Mi0uNDkuMzUzLjM1MyAwIDAxLjQ5NC0uMDUxbC4yMTUuMTcyLjIyLS4xNzRhLjM1My4zNTMgMCAwMS40OS4wNTF6bS01LjA0LTEuOTE5Yy40NzggMCAuODY3LjM5Ljg2Ny44NzFhLjg3Ljg3IDAgMDEtLjg2OC44NzEuODcuODcgMCAwMS0uODY3LS44Ny44Ny44NyAwIDAxLjg2Ny0uODcyem04LjcwNiAwYy40OCAwIC44NjguMzkuODY4Ljg3MWEuODcuODcgMCAwMS0uODY4Ljg3MS44Ny44NyAwIDAxLS44NjctLjg3Ljg3Ljg3IDAgMDEuODY3LS44NzJ6TTcuNDQgMi4zbC0uMDAzLjAwMmEuNjU5LjY1OSAwIDAwLS4yODUuMjM4bC0uMDA1LjAwNmMtLjEzOC4xODktLjI1OC40NjctLjM0OC44MzItLjE3LjY5Mi0uMjE2IDEuNjMxLS4xMjQgMi43ODIuNDMtLjEyOC44OTktLjIwOCAxLjQwNC0uMjM3bC4wMS0uMDAxLjAxOS0uMDM0Yy4wNDYtLjA4Mi4wOTUtLjE2MS4xNDgtLjIzOS4xMjMtLjc3MS4wMjItMS42OTItLjI1My0yLjQ0NC0uMTM0LS4zNjQtLjI5Ny0uNjUtLjQ1My0uODEzYS42MjguNjI4IDAgMDAtLjEwNy0uMDlMNy40NCAyLjN6bTkuMTc0LjA0bC0uMDAyLjAwMWEuNjI4LjYyOCAwIDAwLS4xMDcuMDljLS4xNTYuMTYzLS4zMi40NS0uNDUzLjgxNC0uMjkuNzk0LS4zODcgMS43NzYtLjIzIDIuNTcybC4wNTguMDk3LjAwOC4wMTRoLjAzYTUuMTg0IDUuMTg0IDAgMDExLjQ2Ni4yMTJjLjA4Ni0xLjEyNC4wMzgtMi4wNDMtLjEyOC0yLjcyMi0uMDktLjM2NS0uMjEtLjY0My0uMzQ5LS44MzJsLS4wMDQtLjAwNmEuNjU5LjY1OSAwIDAwLS4yODUtLjIzOWgtLjAwNHoiPjwvcGF0aD48L3N2Zz4="},"llmId":{"type":"string","title":"Llmid","default":"empty"},"modelName":{"type":"string","title":"Modelname","default":"Ollama LLM"}},"type":"object","title":"LLMIteam","description":"GET /api/conversation Result数据结构"},"LLMProvider":{"properties":{"provider":{"type":"string","title":"Provider","description":"LLM提供商"},"description":{"type":"string","title":"Description","description":"LLM提供商描述"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"LLM提供商URL"},"icon":{"type":"string","title":"Icon","description":"LLM提供商图标"}},"type":"object","required":["provider","description","icon"],"title":"LLMProvider","description":"LLM提供商数据结构"},"LLMProviderInfo":{"properties":{"llmId":{"type":"string","title":"Llmid","description":"LLM ID"},"icon":{"type":"string","maxLength":25536,"title":"Icon","description":"LLM图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":"https://api.openai.com/v1"},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称"},"maxTokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokens","description":"最大token数"},"isEditable":{"type":"boolean","title":"Iseditable","description":"是否可编辑","default":true}},"type":"object","required":["llmId","modelName"],"title":"LLMProviderInfo","description":"LLM数据结构"},"ListLLMProviderRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProvider"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMProviderRsp","description":"GET /api/llm/provider 返回数据结构"},"ListLLMRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProviderInfo"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMRsp","description":"GET /api/llm 返回数据结构"},"ListOperate":{"type":"string","enum":["list_equal","list_not_equal","list_contains","list_not_contains","list_length_equal","list_length_greater_than","list_length_greater_than_or_equal","list_length_less_than","list_length_less_than_or_equal"],"title":"ListOperate","description":"Choice 工具支持的列表运算符"},"ListTeamKnowledgeMsg":{"properties":{"teamKbList":{"items":{"$ref":"#/components/schemas/TeamKnowledgeBaseItem"},"type":"array","title":"Teamkblist","description":"团队知识库列表","default":[]}},"type":"object","title":"ListTeamKnowledgeMsg","description":"GET /api/knowledge Result数据结构"},"ListTeamKnowledgeRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ListTeamKnowledgeMsg"}},"type":"object","required":["code","message","result"],"title":"ListTeamKnowledgeRsp","description":"GET /api/knowledge 返回数据结构"},"MCPInstallStatus":{"type":"string","enum":["init","installing","cancelled","ready","failed"],"title":"MCPInstallStatus","description":"MCP 服务状态"},"MCPServiceCardItem":{"properties":{"mcpserviceId":{"type":"string","title":"Mcpserviceid","description":"mcp服务ID"},"name":{"type":"string","title":"Name","description":"mcp服务名称"},"description":{"type":"string","title":"Description","description":"mcp服务简介"},"icon":{"type":"string","title":"Icon","description":"mcp服务图标"},"author":{"type":"string","title":"Author","description":"mcp服务作者"},"isActive":{"type":"boolean","title":"Isactive","description":"mcp服务是否激活","default":false},"status":{"$ref":"#/components/schemas/MCPInstallStatus","description":"mcp服务状态","default":"installing"}},"type":"object","required":["mcpserviceId","name","description","icon","author"],"title":"MCPServiceCardItem","description":"插件中心:MCP服务卡片数据结构"},"MCPTool":{"properties":{"id":{"type":"string","title":"Id","description":"MCP工具ID"},"name":{"type":"string","title":"Name","description":"MCP工具名称"},"description":{"type":"string","title":"Description","description":"MCP工具描述"},"mcp_id":{"type":"string","title":"Mcp Id","description":"MCP ID"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"MCP工具输入参数"}},"type":"object","required":["id","name","description","mcp_id","input_schema"],"title":"MCPTool","description":"MCP工具"},"MCPType":{"type":"string","enum":["sse","stdio","stream"],"title":"MCPType","description":"MCP 类型"},"ModFavAppMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["appId","favorited"],"title":"ModFavAppMsg","description":"PUT /api/app/{appId} Result数据结构"},"ModFavAppRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavAppRequest","description":"PUT /api/app/{appId} 请求数据结构"},"ModFavAppRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavAppMsg"}},"type":"object","required":["code","message","result"],"title":"ModFavAppRsp","description":"PUT /api/app/{appId} 返回数据结构"},"ModFavServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","favorited"],"title":"ModFavServiceMsg","description":"PUT /api/service/{serviceId} Result数据结构"},"ModFavServiceRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavServiceRequest","description":"PUT /api/service/{serviceId} 请求数据结构"},"ModFavServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ModFavServiceRsp","description":"PUT /api/service/{serviceId} 返回数据结构"},"ModifyConversationData":{"properties":{"title":{"type":"string","maxLength":2000,"minLength":1,"title":"Title"}},"type":"object","required":["title"],"title":"ModifyConversationData","description":"修改会话信息"},"NodeItem":{"properties":{"stepId":{"type":"string","title":"Stepid","default":""},"serviceId":{"type":"string","title":"Serviceid","default":""},"nodeId":{"type":"string","title":"Nodeid","default":""},"name":{"type":"string","title":"Name","default":""},"callId":{"type":"string","title":"Callid","default":"Empty"},"description":{"type":"string","title":"Description","default":""},"enable":{"type":"boolean","title":"Enable","default":true},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","default":{}},"depedency":{"anyOf":[{"$ref":"#/components/schemas/DependencyItem"},{"type":"null"}]},"position":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"editable":{"type":"boolean","title":"Editable","default":true}},"type":"object","title":"NodeItem","description":"请求/响应中的节点变量类"},"NodeMetaDataItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"callId":{"type":"string","title":"Callid"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"editable":{"type":"boolean","title":"Editable","default":true},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat"}},"type":"object","required":["nodeId","callId","name","description","parameters","createdAt"],"title":"NodeMetaDataItem","description":"节点元数据类"},"NodeServiceItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"type":{"type":"string","title":"Type","description":"服务类型"},"nodeMetaDatas":{"items":{"$ref":"#/components/schemas/NodeMetaDataItem"},"type":"array","title":"Nodemetadatas","default":[]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdat","description":"创建时间"}},"type":"object","required":["serviceId","name","type"],"title":"NodeServiceItem","description":"GET /api/flow/service 中单个service信息以及service下的节点元数据的信息"},"NodeServiceListMsg":{"properties":{"services":{"items":{"$ref":"#/components/schemas/NodeServiceItem"},"type":"array","title":"Services","description":"服务列表","default":[]}},"type":"object","title":"NodeServiceListMsg","description":"GET /api/flow/service result"},"NodeServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/NodeServiceListMsg"}},"type":"object","required":["code","message","result"],"title":"NodeServiceListRsp","description":"GET /api/flow/service 返回数据结构"},"NumberOperate":{"type":"string","enum":["number_equal","number_not_equal","number_greater_than","number_less_than","number_greater_than_or_equal","number_less_than_or_equal"],"title":"NumberOperate","description":"Choice 工具支持的数字运算符"},"OidcRedirectMsg":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"OidcRedirectMsg","description":"GET /api/auth/redirect Result数据结构"},"OidcRedirectRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/OidcRedirectMsg"}},"type":"object","required":["code","message","result"],"title":"OidcRedirectRsp","description":"GET /api/auth/redirect 返回数据结构"},"OperateAndBindType":{"properties":{"operate":{"anyOf":[{"$ref":"#/components/schemas/NumberOperate"},{"$ref":"#/components/schemas/StringOperate"},{"$ref":"#/components/schemas/ListOperate"},{"$ref":"#/components/schemas/BoolOperate"},{"$ref":"#/components/schemas/DictOperate"}],"title":"Operate","description":"操作类型"},"bind_type":{"$ref":"#/components/schemas/Type","description":"绑定类型"}},"type":"object","required":["operate","bind_type"],"title":"OperateAndBindType","description":"操作和绑定类型数据结构"},"ParamsNode":{"properties":{"paramName":{"type":"string","title":"Paramname","description":"参数名称"},"paramPath":{"type":"string","title":"Parampath","description":"参数路径"},"paramType":{"$ref":"#/components/schemas/Type","description":"参数类型"},"subParams":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParamsNode"},"type":"array"},{"type":"null"}],"title":"Subparams","description":"子参数列表"}},"type":"object","required":["paramName","paramPath","paramType"],"title":"ParamsNode","description":"参数数据结构"},"PermissionType":{"type":"string","enum":["protected","public","private"],"title":"PermissionType","description":"权限类型"},"PositionItem":{"properties":{"x":{"type":"number","title":"X","default":0.0},"y":{"type":"number","title":"Y","default":0.0}},"type":"object","title":"PositionItem","description":"请求/响应中的前端相对位置变量类"},"PostAuthKeyMsg":{"properties":{"api_key":{"type":"string","title":"Api Key"}},"type":"object","required":["api_key"],"title":"PostAuthKeyMsg","description":"POST /api/auth/key Result数据结构"},"PostAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/PostAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"PostAuthKeyRsp","description":"POST /api/auth/key 返回数据结构"},"PutFlowReq":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Input"}},"type":"object","required":["flow"],"title":"PutFlowReq","description":"创建/修改流拓扑结构"},"QuestionBlacklistRequest":{"properties":{"id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","question","answer","is_deletion"],"title":"QuestionBlacklistRequest","description":"POST /api/blacklist/question 请求数据结构"},"RecentAppList":{"properties":{"applications":{"items":{"$ref":"#/components/schemas/RecentAppListItem"},"type":"array","title":"Applications","description":"最近使用的应用列表"}},"type":"object","required":["applications"],"title":"RecentAppList","description":"GET /api/app/recent Result数据结构"},"RecentAppListItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"name":{"type":"string","title":"Name","description":"应用名称"}},"type":"object","required":["appId","name"],"title":"RecentAppListItem","description":"GET /api/app/recent 列表项数据结构"},"RecordContent":{"properties":{"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"data":{"additionalProperties":true,"type":"object","title":"Data","default":{}},"facts":{"items":{"type":"string"},"type":"array","title":"Facts","description":"[运行后修改]与Record关联的事实信息","default":[]}},"type":"object","required":["question","answer"],"title":"RecordContent","description":"Record表子项:Record加密前的数据结构"},"RecordData":{"properties":{"id":{"type":"string","title":"Id"},"groupId":{"type":"string","title":"Groupid"},"conversationId":{"type":"string","title":"Conversationid"},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid"},"document":{"items":{"$ref":"#/components/schemas/RecordDocument"},"type":"array","title":"Document","default":[]},"flow":{"anyOf":[{"$ref":"#/components/schemas/RecordFlow"},{"type":"null"}]},"content":{"$ref":"#/components/schemas/RecordContent"},"metadata":{"$ref":"#/components/schemas/RecordMetadata"},"comment":{"$ref":"#/components/schemas/CommentType","default":"none"},"createdAt":{"type":"number","title":"Createdat"}},"type":"object","required":["id","groupId","conversationId","content","metadata","createdAt"],"title":"RecordData","description":"GET /api/record/{conversation_id} Result内元素数据结构"},"RecordDocument":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"order":{"type":"integer","title":"Order","description":"文档顺序","default":0},"abstract":{"type":"string","title":"Abstract","description":"文档摘要","default":""},"author":{"type":"string","title":"Author","description":"文档作者","default":""},"associated":{"type":"string","enum":["question","answer"],"title":"Associated"}},"type":"object","required":["name","type","size","associated"],"title":"RecordDocument","description":"GET /api/record/{conversation_id} Result中的document数据结构"},"RecordFlow":{"properties":{"id":{"type":"string","title":"Id"},"recordId":{"type":"string","title":"Recordid"},"flowId":{"type":"string","title":"Flowid"},"flowName":{"type":"string","title":"Flowname","default":""},"flowStatus":{"$ref":"#/components/schemas/StepStatus","default":"success"},"stepNum":{"type":"integer","title":"Stepnum"},"steps":{"items":{"$ref":"#/components/schemas/RecordFlowStep"},"type":"array","title":"Steps"}},"type":"object","required":["id","recordId","flowId","stepNum","steps"],"title":"RecordFlow","description":"Flow的执行信息"},"RecordFlowStep":{"properties":{"stepId":{"type":"string","title":"Stepid"},"stepStatus":{"$ref":"#/components/schemas/StepStatus"},"input":{"additionalProperties":true,"type":"object","title":"Input"},"output":{"additionalProperties":true,"type":"object","title":"Output"}},"type":"object","required":["stepId","stepStatus","input","output"],"title":"RecordFlowStep","description":"Record表子项:flow的单步数据结构"},"RecordListMsg":{"properties":{"records":{"items":{"$ref":"#/components/schemas/RecordData"},"type":"array","title":"Records"}},"type":"object","required":["records"],"title":"RecordListMsg","description":"GET /api/record/{conversation_id} Result数据结构"},"RecordListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecordListMsg"}},"type":"object","required":["code","message","result"],"title":"RecordListRsp","description":"GET /api/record/{conversation_id} 返回数据结构"},"RecordMetadata":{"properties":{"inputTokens":{"type":"integer","title":"Inputtokens","default":0},"outputTokens":{"type":"integer","title":"Outputtokens","default":0},"timeCost":{"type":"number","title":"Timecost","default":0},"feature":{"additionalProperties":true,"type":"object","title":"Feature","default":{}},"footNoteMetadataList":{"items":{"$ref":"#/components/schemas/FootNoteMetaData"},"type":"array","title":"Footnotemetadatalist","description":"脚注元信息列表","default":[]}},"type":"object","title":"RecordMetadata","description":"Record表子项:Record的元信息"},"RequestData":{"properties":{"question":{"type":"string","maxLength":2000,"title":"Question","description":"用户输入"},"conversationId":{"type":"string","title":"Conversationid","description":"聊天ID","default":""},"groupId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupid","description":"问答组ID"},"language":{"type":"string","title":"Language","description":"语言","default":"zh"},"files":{"items":{"type":"string"},"type":"array","title":"Files","description":"文件列表","default":[]},"app":{"anyOf":[{"$ref":"#/components/schemas/RequestDataApp"},{"type":"null"}],"description":"应用"},"debug":{"type":"boolean","title":"Debug","description":"是否调试","default":false},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid","description":"任务ID"}},"type":"object","required":["question"],"title":"RequestData","description":"POST /api/chat 请求的总的数据结构"},"RequestDataApp":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","description":"Flow ID"},"params":{"anyOf":[{"$ref":"#/components/schemas/param"},{"type":"null"}],"description":"流执行过程中的参数补充"}},"type":"object","required":["appId"],"title":"RequestDataApp","description":"模型对话中包含的app信息"},"ResponseData":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"title":"Result"}},"type":"object","required":["code","message","result"],"title":"ResponseData","description":"基础返回数据结构"},"SearchType":{"type":"string","enum":["all","name","description","author"],"title":"SearchType","description":"搜索类型"},"ServiceApiData":{"properties":{"name":{"type":"string","title":"Name","description":"接口名称"},"path":{"type":"string","title":"Path","description":"接口路径"},"description":{"type":"string","title":"Description","description":"接口描述"}},"type":"object","required":["name","path","description"],"title":"ServiceApiData","description":"语义接口中心:服务 API 接口属性数据结构"},"ServiceCardItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"description":{"type":"string","title":"Description","description":"服务简介"},"icon":{"type":"string","title":"Icon","description":"服务图标"},"author":{"type":"string","title":"Author","description":"服务作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","name","description","icon","author","favorited"],"title":"ServiceCardItem","description":"语义接口中心:服务卡片数据结构"},"StepParams":{"properties":{"stepId":{"type":"string","title":"Stepid","description":"步骤ID"},"name":{"type":"string","title":"Name","description":"Step名称"},"paramsNode":{"anyOf":[{"$ref":"#/components/schemas/ParamsNode"},{"type":"null"}],"description":"参数节点"}},"type":"object","required":["stepId","name"],"title":"StepParams","description":"参数数据结构"},"StepStatus":{"type":"string","enum":["unknown","init","waiting","running","success","error","param","cancelled"],"title":"StepStatus","description":"步骤状态"},"StringOperate":{"type":"string","enum":["string_equal","string_not_equal","string_contains","string_not_contains","string_starts_with","string_ends_with","string_length_equal","string_length_greater_than","string_length_greater_than_or_equal","string_length_less_than","string_length_less_than_or_equal","string_regex_match"],"title":"StringOperate","description":"Choice 工具支持的字符串运算符"},"TeamKnowledgeBaseItem":{"properties":{"teamId":{"type":"string","title":"Teamid","description":"团队ID"},"teamName":{"type":"string","title":"Teamname","description":"团队名称"},"kb_list":{"items":{"$ref":"#/components/schemas/KnowledgeBaseItem"},"type":"array","title":"Kb List","description":"知识库列表","default":[]}},"type":"object","required":["teamId","teamName"],"title":"TeamKnowledgeBaseItem","description":"团队知识库列表项数据结构"},"Type":{"type":"string","enum":["string","number","list","dict","bool"],"title":"Type","description":"Choice 工具支持的类型"},"UpdateConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListItem"}},"type":"object","required":["code","message","result"],"title":"UpdateConversationRsp","description":"POST /api/conversation 返回数据结构"},"UpdateKbReq":{"properties":{"kbIds":{"items":{"type":"string"},"type":"array","title":"Kbids","description":"知识库ID列表","default":[]}},"type":"object","title":"UpdateKbReq","description":"更新知识库请求体"},"UpdateLLMReq":{"properties":{"icon":{"type":"string","title":"Icon","description":"图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":""},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称","default":""},"maxTokens":{"type":"integer","title":"Maxtokens","description":"最大token数","default":8192}},"type":"object","title":"UpdateLLMReq","description":"更新大模型请求体"},"UpdateMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"}},"type":"object","required":["serviceId","name"],"title":"UpdateMCPServiceMsg","description":"插件中心:MCP服务属性数据结构"},"UpdateMCPServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"config":{"additionalProperties":true,"type":"object","title":"Config","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType","description":"MCP传输协议(Stdio/SSE/Streamable)","default":"stdio"}},"type":"object","required":["name","description","overview","config"],"title":"UpdateMCPServiceRequest","description":"POST /api/mcpservice 请求数据结构"},"UpdateMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateMCPServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateMCPServiceRsp","description":"POST /api/mcp_service 返回数据结构"},"UpdateServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array","title":"Apis","description":"解析后的接口列表"}},"type":"object","required":["serviceId","name","apis"],"title":"UpdateServiceMsg","description":"语义接口中心:服务属性数据结构"},"UpdateServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"data":{"additionalProperties":true,"type":"object","title":"Data","description":"对应 YAML 内容的数据对象"}},"type":"object","required":["data"],"title":"UpdateServiceRequest","description":"POST /api/service 请求数据结构"},"UpdateServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateServiceRsp","description":"POST /api/service 返回数据结构"},"UserBlacklistRequest":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"is_ban":{"type":"integer","title":"Is Ban"}},"type":"object","required":["user_sub","is_ban"],"title":"UserBlacklistRequest","description":"POST /api/blacklist/user 请求数据结构"},"UserUpdateRequest":{"properties":{"autoExecute":{"type":"boolean","title":"Autoexecute","description":"是否自动执行","default":false}},"type":"object","title":"UserUpdateRequest","description":"更新用户信息请求体"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"_GetAuthKeyMsg":{"properties":{"api_key_exists":{"type":"boolean","title":"Api Key Exists"}},"type":"object","required":["api_key_exists"],"title":"_GetAuthKeyMsg","description":"GET /api/auth/key Result数据结构"},"param":{"properties":{"content":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"boolean"}],"title":"Content","description":"流执行过程中的参数补充内容","default":{}},"description":{"type":"string","title":"Description","description":"流执行过程中的参数补充描述","default":""}},"type":"object","title":"param","description":"流执行过程中的参数补充"}}}} \ No newline at end of file +{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/conversation":{"get":{"tags":["conversation"],"summary":"Get Conversation List","description":"获取对话列表","operationId":"get_conversation_list_api_conversation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListRsp"}}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"}}},"post":{"tags":["conversation"],"summary":"Add Conversation","description":"手动创建新对话","operationId":"add_conversation_api_conversation_post","parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string","default":"","title":"Appid"}},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Debug"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_conversation_api_conversation_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["conversation"],"summary":"Update Conversation","description":"更新特定Conversation的数据","operationId":"update_conversation_api_conversation_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["conversation"],"summary":"Delete Conversation","description":"删除特定对话","operationId":"delete_conversation_api_conversation_delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/login":{"get":{"tags":["auth"],"summary":"Oidc Login","description":"OIDC login\n\n:param request: Request object\n:param code: OIDC code\n:return: HTMLResponse","operationId":"oidc_login_api_auth_login_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"get":{"tags":["auth"],"summary":"Logout","description":"用户登出EulerCopilot","operationId":"logout_api_auth_logout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}},"post":{"tags":["auth"],"summary":"Oidc Logout","description":"OIDC主动触发登出","operationId":"oidc_logout_api_auth_logout_post","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/redirect":{"get":{"tags":["auth"],"summary":"Oidc Redirect","description":"OIDC重定向URL","operationId":"oidc_redirect_api_auth_redirect_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRedirectRsp"}}}}}}},"/api/auth/user":{"get":{"tags":["auth"],"summary":"Userinfo","description":"获取用户信息","operationId":"userinfo_api_auth_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}}}}},"/api/auth/update_revision_number":{"post":{"tags":["auth"],"summary":"Update Revision Number","description":"更新用户协议信息","operationId":"update_revision_number_api_auth_update_revision_number_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/auth/key":{"get":{"tags":["key"],"summary":"Check Api Key Existence","description":"检查API密钥是否存在","operationId":"check_api_key_existence_api_auth_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAuthKeyRsp"}}}}}},"post":{"tags":["key"],"summary":"Manage Api Key","description":"管理用户的API密钥","operationId":"manage_api_key_api_auth_key_post","parameters":[{"name":"action","in":"query","required":true,"schema":{"type":"string","title":"Action"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAuthKeyRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app":{"get":{"tags":["appcenter"],"summary":"Get Applications","description":"获取应用列表","operationId":"get_applications_api_app_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"appType","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AppType"},{"type":"null"}],"description":"应用类型","title":"Apptype"},"description":"应用类型"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Applications Api App Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Create Or Update Application","description":"创建或更新应用","operationId":"create_or_update_application_api_app_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Create Or Update Application Api App Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/recent":{"get":{"tags":["appcenter"],"summary":"Get Recently Used Applications","description":"获取最近使用的应用","operationId":"get_recently_used_applications_api_app_recent_get","parameters":[{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":1,"default":5,"title":"Count"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetRecentAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Recently Used Applications Api App Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/{appId}":{"get":{"tags":["appcenter"],"summary":"Get Application","description":"获取应用详情","operationId":"get_application_api_app__appId__get","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppPropertyRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Application Api App Appid Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["appcenter"],"summary":"Delete Application","description":"删除应用","operationId":"delete_application_api_app__appId__delete","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Delete Application Api App Appid Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Publish Application","description":"发布应用","operationId":"publish_application_api_app__appId__post","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseAppOperationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["appcenter"],"summary":"Modify Favorite Application","description":"更改应用收藏状态","operationId":"modify_favorite_application_api_app__appId__put","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ModFavAppRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Modify Favorite Application Api App Appid Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service":{"get":{"tags":["service-center"],"summary":"Get Service List","description":"获取服务列表","operationId":"get_service_list_api_service_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"每页数量","default":16,"title":"Pagesize"},"description":"每页数量"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Service List Api Service Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["service-center"],"summary":"Update Service","description":"上传并解析服务","operationId":"update_service_api_service_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest","description":"上传 YAML 文本对应数据对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service/{serviceId}":{"get":{"tags":["service-center"],"summary":"Get Service Detail","description":"获取服务详情","operationId":"get_service_detail_api_service__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["service-center"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_service__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["service-center"],"summary":"Modify Favorite Service","description":"修改服务收藏状态","operationId":"modify_favorite_service_api_service__serviceId__put","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRequest","description":"更改收藏状态请求对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comment":{"post":{"tags":["comment"],"summary":"Add Comment","description":"给Record添加评论","operationId":"add_comment_api_comment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCommentData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/record/{conversation_id}":{"get":{"tags":["record"],"summary":"Get Record","description":"获取某个对话的所有问答对","operationId":"get_record_api_record__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordListRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_check":{"get":{"tags":["health_check"],"summary":"Health Check","description":"健康检查接口","operationId":"health_check_health_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckRsp"}}}}}}},"/api/chat":{"post":{"tags":["chat"],"summary":"Chat","description":"LLM流式对话接口","operationId":"chat_api_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stop":{"post":{"tags":["chat"],"summary":"Stop Generation","description":"停止生成","operationId":"stop_generation_api_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/blacklist/user":{"get":{"tags":["blacklist"],"summary":"Get Blacklist User","description":"获取黑名单用户","operationId":"get_blacklist_user_api_blacklist_user_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistUserRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist User","description":"操作黑名单用户","operationId":"change_blacklist_user_api_blacklist_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/question":{"get":{"tags":["blacklist"],"summary":"Get Blacklist Question","description":"获取黑名单问题\n\n目前情况下,先直接输出问题,不做用户类型校验","operationId":"get_blacklist_question_api_blacklist_question_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist Question","description":"黑名单问题检测或操作","operationId":"change_blacklist_question_api_blacklist_question_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/complaint":{"post":{"tags":["blacklist"],"summary":"Abuse Report","description":"用户实施举报","operationId":"abuse_report_api_blacklist_complaint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/abuse":{"get":{"tags":["blacklist"],"summary":"Get Abuse Report","description":"获取待审核的问答对","operationId":"get_abuse_report_api_blacklist_abuse_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Abuse Report","description":"对被举报问答对进行操作","operationId":"change_abuse_report_api_blacklist_abuse_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseProcessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{conversation_id}":{"post":{"tags":["document"],"summary":"Document Upload","description":"上传文档","operationId":"document_upload_api_document__conversation_id__post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_document_upload_api_document__conversation_id__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["document"],"summary":"Get Document List","description":"获取文档列表","operationId":"get_document_list_api_document__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"used","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Used"}},{"name":"unused","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Unused"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDocumentRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{document_id}":{"delete":{"tags":["document"],"summary":"Delete Single Document","description":"删除单个文件","operationId":"delete_single_document_api_document__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge":{"get":{"tags":["knowledge"],"summary":"List Kb","description":"获取当前用户的知识库ID","operationId":"list_kb_api_knowledge_get","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}},{"name":"kbId","in":"query","required":false,"schema":{"type":"string","title":"Kbid"}},{"name":"kbName","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kbname"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamKnowledgeRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["knowledge"],"summary":"Update Conversation Kb","description":"更新当前用户的知识库ID","operationId":"update_conversation_kb_api_knowledge_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKbReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/provider":{"get":{"tags":["llm"],"summary":"List Llm Provider","description":"获取大模型提供商列表","operationId":"list_llm_provider_api_llm_provider_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMProviderRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/llm":{"get":{"tags":["llm"],"summary":"List Llm","description":"获取大模型列表","operationId":"list_llm_api_llm_get","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["llm"],"summary":"Create Llm","description":"创建或更新大模型配置","operationId":"create_llm_api_llm_put","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLLMReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["llm"],"summary":"Delete Llm","description":"删除大模型配置","operationId":"delete_llm_api_llm_delete","parameters":[{"name":"llmId","in":"query","required":true,"schema":{"type":"string","description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/conv":{"put":{"tags":["llm"],"summary":"Update Conv Llm","description":"更新对话的知识库","operationId":"update_conv_llm_api_llm_conv_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","description":"对话ID","title":"Conversationid"},"description":"对话ID"},{"name":"llmId","in":"query","required":false,"schema":{"type":"string","description":"llm ID","default":"empty","title":"Llmid"},"description":"llm ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp":{"get":{"tags":["mcp-service"],"summary":"Get Mcpservice List","description":"获取服务列表","operationId":"get_mcpservice_list_api_mcp_get","parameters":[{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"isInstall","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否已安装","title":"Isinstall"},"description":"是否已安装"},{"name":"isActive","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否激活","title":"Isactive"},"description":"是否激活"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Mcpservice List Api Mcp Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Create Or Update Mcpservice","description":"新建或更新MCP服务","operationId":"create_or_update_mcpservice_api_mcp_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}/install":{"post":{"tags":["mcp-service"],"summary":"Install Mcp Service","operationId":"install_mcp_service_api_mcp__serviceId__install_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"install","in":"query","required":false,"schema":{"type":"boolean","description":"是否安装","default":true,"title":"Install"},"description":"是否安装"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}":{"get":{"tags":["mcp-service"],"summary":"Get Service Detail","description":"获取MCP服务详情","operationId":"get_service_detail_api_mcp__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMCPServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["mcp-service"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_mcp__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Active Or Deactivate Mcp Service","description":"激活/取消激活mcp","operationId":"active_or_deactivate_mcp_service_api_mcp__serviceId__post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/icon":{"post":{"tags":["mcp-service"],"summary":"Update Mcp Icon","description":"更新MCP服务图标","operationId":"update_mcp_icon_api_mcp_icon_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_mcp_icon_api_mcp_icon_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/flow/service":{"get":{"tags":["flow"],"summary":"Get Services","description":"获取用户可访问的节点元数据所在服务的信息","operationId":"get_services_api_flow_service_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeServiceListRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/flow":{"get":{"tags":["flow"],"summary":"Get Flow","description":"获取流拓扑结构","operationId":"get_flow_api_flow_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureGetRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["flow"],"summary":"Put Flow","description":"修改流拓扑结构","operationId":"put_flow_api_flow_put","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutFlowReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructurePutRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["flow"],"summary":"Delete Flow","description":"删除流拓扑结构","operationId":"delete_flow_api_flow_delete","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureDeleteRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"get":{"tags":["user"],"summary":"Get User Sub","description":"查询所有用户接口","operationId":"get_user_sub_api_user_get","parameters":[{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","description":"每页用户数量","default":20,"title":"Page Size"},"description":"每页用户数量"},{"name":"page_cnt","in":"query","required":false,"schema":{"type":"integer","description":"当前页码","default":1,"title":"Page Cnt"},"description":"当前页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGetRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["user"],"summary":"Update User Info","description":"更新用户信息接口","operationId":"update_user_info_api_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest","description":"用户更新信息"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter":{"get":{"tags":["parameter"],"summary":"Get Parameters","description":"Get parameters for node choice.","operationId":"get_parameters_api_parameter_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}},{"name":"stepId","in":"query","required":true,"schema":{"type":"string","title":"Stepid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetParamsRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter/operate":{"get":{"tags":["parameter"],"summary":"Get Operate Parameters","description":"Get parameters for node choice.","operationId":"get_operate_parameters_api_parameter_operate_get","parameters":[{"name":"ParamType","in":"query","required":true,"schema":{"type":"string","title":"Paramtype"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOperaRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbuseProcessRequest":{"properties":{"id":{"type":"string","title":"Id"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","is_deletion"],"title":"AbuseProcessRequest","description":"POST /api/blacklist/abuse 请求数据结构"},"AbuseRequest":{"properties":{"record_id":{"type":"string","title":"Record Id"},"reason":{"type":"string","title":"Reason"},"reason_type":{"type":"string","title":"Reason Type"}},"type":"object","required":["record_id","reason","reason_type"],"title":"AbuseRequest","description":"POST /api/blacklist/complaint 请求数据结构"},"ActiveMCPServiceRequest":{"properties":{"active":{"type":"boolean","title":"Active","description":"是否激活mcp服务"},"mcpEnv":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mcpenv","description":"MCP服务环境变量"}},"type":"object","required":["active"],"title":"ActiveMCPServiceRequest","description":"POST /api/mcp/{serviceId} 请求数据结构"},"ActiveMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ActiveMCPServiceRsp","description":"POST /api/mcp/active/{serviceId} 返回数据结构"},"AddCommentData":{"properties":{"record_id":{"type":"string","title":"Record Id"},"group_id":{"type":"string","title":"Group Id"},"comment":{"$ref":"#/components/schemas/CommentType"},"dislike_reason":{"type":"string","maxLength":200,"title":"Dislike Reason","default":""},"reason_link":{"type":"string","maxLength":200,"title":"Reason Link","default":""},"reason_description":{"type":"string","maxLength":500,"title":"Reason Description","default":""}},"type":"object","required":["record_id","group_id","comment"],"title":"AddCommentData","description":"添加评论"},"AddConversationMsg":{"properties":{"conversationId":{"type":"string","title":"Conversationid"}},"type":"object","required":["conversationId"],"title":"AddConversationMsg","description":"POST /api/conversation Result数据结构"},"AddConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AddConversationMsg"}},"type":"object","required":["code","message","result"],"title":"AddConversationRsp","description":"POST /api/conversation 返回数据结构"},"AppCenterCardItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"应用图标"},"name":{"type":"string","title":"Name","description":"应用名称"},"description":{"type":"string","title":"Description","description":"应用简介"},"author":{"type":"string","title":"Author","description":"应用作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"},"published":{"type":"boolean","title":"Published","description":"是否已发布","default":true}},"type":"object","required":["appId","appType","icon","name","description","author","favorited"],"title":"AppCenterCardItem","description":"应用中心卡片数据结构"},"AppFlowInfo":{"properties":{"id":{"type":"string","title":"Id","description":"工作流ID"},"name":{"type":"string","title":"Name","description":"工作流名称","default":""},"description":{"type":"string","title":"Description","description":"工作流简介","default":""},"debug":{"type":"boolean","title":"Debug","description":"是否经过调试","default":false}},"type":"object","required":["id"],"title":"AppFlowInfo","description":"应用工作流数据结构"},"AppLink":{"properties":{"title":{"type":"string","title":"Title","description":"链接标题"},"url":{"type":"string","pattern":"^(https|http)://.*$","title":"Url","description":"链接地址"}},"type":"object","required":["title","url"],"title":"AppLink","description":"App的相关链接"},"AppMcpServiceInfo":{"properties":{"id":{"type":"string","title":"Id","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称","default":""},"description":{"type":"string","title":"Description","description":"MCP服务简介","default":""}},"type":"object","required":["id"],"title":"AppMcpServiceInfo","description":"应用关联的MCP服务信息"},"AppPermissionData":{"properties":{"visibility":{"$ref":"#/components/schemas/PermissionType","description":"可见性(public/private/protected)","default":"private"},"authorizedUsers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Authorizedusers","description":"附加人员名单(如果可见性为部分人可见)"}},"type":"object","title":"AppPermissionData","description":"应用权限数据结构"},"AppType":{"type":"string","enum":["flow","agent"],"title":"AppType","description":"应用中心应用类型"},"AuthUserMsg":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"revision":{"type":"boolean","title":"Revision"},"is_admin":{"type":"boolean","title":"Is Admin"},"auto_execute":{"type":"boolean","title":"Auto Execute"}},"type":"object","required":["user_sub","revision","is_admin","auto_execute"],"title":"AuthUserMsg","description":"GET /api/auth/user Result数据结构"},"AuthUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AuthUserMsg"}},"type":"object","required":["code","message","result"],"title":"AuthUserRsp","description":"GET /api/auth/user 返回数据结构"},"BaseAppOperationMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"}},"type":"object","required":["appId"],"title":"BaseAppOperationMsg","description":"基础应用操作Result数据结构"},"BaseAppOperationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseAppOperationMsg"}},"type":"object","required":["code","message","result"],"title":"BaseAppOperationRsp","description":"基础应用操作返回数据结构"},"BaseMCPServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseMCPServiceOperationMsg","description":"插件中心:MCP服务操作Result数据结构"},"BaseServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseServiceOperationMsg","description":"语义接口中心:基础服务操作Result数据结构"},"Blacklist":{"properties":{"_id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_audited":{"type":"boolean","title":"Is Audited","default":false},"reason_type":{"type":"string","title":"Reason Type","default":""},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"updated_at":{"type":"number","title":"Updated At"}},"type":"object","required":["question","answer"],"title":"Blacklist","description":"黑名单\n\nCollection: blacklist"},"Body_add_conversation_api_conversation_post":{"properties":{"llm_id":{"type":"string","title":"Llm Id","default":"empty"},"kb_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Kb Ids"}},"type":"object","title":"Body_add_conversation_api_conversation_post"},"Body_document_upload_api_document__conversation_id__post":{"properties":{"documents":{"items":{"type":"string","format":"binary"},"type":"array","title":"Documents"}},"type":"object","required":["documents"],"title":"Body_document_upload_api_document__conversation_id__post"},"Body_update_mcp_icon_api_mcp_icon_post":{"properties":{"icon":{"type":"string","format":"binary","title":"Icon","description":"图标文件"}},"type":"object","required":["icon"],"title":"Body_update_mcp_icon_api_mcp_icon_post"},"BoolOperate":{"type":"string","enum":["bool_equal","bool_not_equal"],"title":"BoolOperate","description":"Choice 工具支持的布尔运算符"},"CommentType":{"type":"string","enum":["liked","disliked","none"],"title":"CommentType","description":"点赞点踩类型"},"ConversationDocumentItem":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"type":"null","title":"Conversation Id"},"status":{"$ref":"#/components/schemas/DocumentStatus"}},"type":"object","required":["name","type","size","status"],"title":"ConversationDocumentItem","description":"GET /api/document/{conversation_id} Result内元素数据结构"},"ConversationDocumentMsg":{"properties":{"documents":{"items":{"$ref":"#/components/schemas/ConversationDocumentItem"},"type":"array","title":"Documents","default":[]}},"type":"object","title":"ConversationDocumentMsg","description":"GET /api/document/{conversation_id} Result数据结构"},"ConversationDocumentRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationDocumentMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationDocumentRsp","description":"GET /api/document/{conversation_id} 返回数据结构"},"ConversationListItem":{"properties":{"conversationId":{"type":"string","title":"Conversationid"},"title":{"type":"string","title":"Title"},"docCount":{"type":"integer","title":"Doccount"},"createdTime":{"type":"string","title":"Createdtime"},"appId":{"type":"string","title":"Appid"},"debug":{"type":"boolean","title":"Debug"},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"kbList":{"items":{"$ref":"#/components/schemas/KbIteam"},"type":"array","title":"Kblist","default":[]}},"type":"object","required":["conversationId","title","docCount","createdTime","appId","debug"],"title":"ConversationListItem","description":"GET /api/conversation Result数据结构"},"ConversationListMsg":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationListItem"},"type":"array","title":"Conversations"}},"type":"object","required":["conversations"],"title":"ConversationListMsg","description":"GET /api/conversation Result数据结构"},"ConversationListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationListRsp","description":"GET /api/conversation 返回数据结构"},"CreateAppRequest":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llm":{"type":"string","title":"Llm","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"type":"string"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appid","description":"应用ID"}},"type":"object","required":["appType","name","description"],"title":"CreateAppRequest","description":"POST /api/app 请求数据结构"},"DeleteConversationData":{"properties":{"conversationList":{"items":{"type":"string"},"type":"array","title":"Conversationlist"}},"type":"object","required":["conversationList"],"title":"DeleteConversationData","description":"删除会话"},"DeleteMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteMCPServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DeleteServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DependencyItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"type":{"type":"string","title":"Type"}},"type":"object","required":["nodeId","type"],"title":"DependencyItem","description":"请求/响应中的节点依赖变量类"},"DictOperate":{"type":"string","enum":["dict_equal","dict_not_equal","dict_contains_key","dict_not_contains_key"],"title":"DictOperate","description":"Choice 工具支持的字典运算符"},"DocumentStatus":{"type":"string","enum":["used","unused","processing","failed"],"title":"DocumentStatus","description":"文档状态"},"EdgeItem":{"properties":{"edgeId":{"type":"string","title":"Edgeid"},"sourceNode":{"type":"string","title":"Sourcenode"},"targetNode":{"type":"string","title":"Targetnode"},"type":{"type":"string","title":"Type","default":"normal"},"branchId":{"type":"string","title":"Branchid"}},"type":"object","required":["edgeId","sourceNode","targetNode","branchId"],"title":"EdgeItem","description":"请求/响应中的边变量类"},"EditMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"data":{"type":"string","title":"Data","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType"}},"type":"object","required":["serviceId","name","description","overview","data","mcpType"],"title":"EditMCPServiceMsg","description":"编辑MCP服务"},"FlowItem-Input":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowItem-Output":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowStructureDeleteMsg":{"properties":{"flowId":{"type":"string","title":"Flowid","default":""}},"type":"object","title":"FlowStructureDeleteMsg","description":"DELETE /api/flow/ result"},"FlowStructureDeleteRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureDeleteMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureDeleteRsp","description":"DELETE /api/flow/ 返回数据结构"},"FlowStructureGetMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructureGetMsg","description":"GET /api/flow result"},"FlowStructureGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureGetMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureGetRsp","description":"GET /api/flow 返回数据结构"},"FlowStructurePutMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructurePutMsg","description":"PUT /api/flow result"},"FlowStructurePutRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructurePutMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructurePutRsp","description":"PUT /api/flow 返回数据结构"},"FootNoteMetaData":{"properties":{"releatedId":{"type":"string","title":"Releatedid","description":"相关ID","default":""},"insertPosition":{"type":"integer","title":"Insertposition","description":"插入位置","default":0},"footSource":{"type":"string","title":"Footsource","description":"脚注来源","default":""},"footType":{"type":"string","title":"Foottype","description":"脚注类型","default":""}},"type":"object","title":"FootNoteMetaData","description":"Record表子项:Record的脚注元信息"},"GetAppListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalApps":{"type":"integer","title":"Totalapps","description":"总应用数"},"applications":{"items":{"$ref":"#/components/schemas/AppCenterCardItem"},"type":"array","title":"Applications","description":"应用列表"}},"type":"object","required":["currentPage","totalApps","applications"],"title":"GetAppListMsg","description":"GET /api/app Result数据结构"},"GetAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppListMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppListRsp","description":"GET /api/app 返回数据结构"},"GetAppPropertyMsg":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务信息列表","default":[]},"appId":{"type":"string","title":"Appid","description":"应用ID"},"published":{"type":"boolean","title":"Published","description":"是否已发布"}},"type":"object","required":["appType","name","description","appId","published"],"title":"GetAppPropertyMsg","description":"GET /api/app/{appId} Result数据结构"},"GetAppPropertyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppPropertyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppPropertyRsp","description":"GET /api/app/{appId} 返回数据结构"},"GetAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/_GetAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAuthKeyRsp","description":"GET /api/auth/key 返回数据结构"},"GetBlacklistQuestionMsg":{"properties":{"question_list":{"items":{"$ref":"#/components/schemas/Blacklist"},"type":"array","title":"Question List"}},"type":"object","required":["question_list"],"title":"GetBlacklistQuestionMsg","description":"GET /api/blacklist/question Result数据结构"},"GetBlacklistQuestionRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistQuestionMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistQuestionRsp","description":"GET /api/blacklist/question 返回数据结构"},"GetBlacklistUserMsg":{"properties":{"user_subs":{"items":{"type":"string"},"type":"array","title":"User Subs"}},"type":"object","required":["user_subs"],"title":"GetBlacklistUserMsg","description":"GET /api/blacklist/user Result数据结构"},"GetBlacklistUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistUserMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistUserRsp","description":"GET /api/blacklist/user 返回数据结构"},"GetMCPServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"tools":{"items":{"$ref":"#/components/schemas/MCPTool"},"type":"array","title":"Tools","description":"MCP服务Tools列表","default":[]}},"type":"object","required":["serviceId","name","description","overview"],"title":"GetMCPServiceDetailMsg","description":"GET /api/mcp_service/{serviceId} Result数据结构"},"GetMCPServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceDetailMsg"},{"$ref":"#/components/schemas/EditMCPServiceMsg"}],"title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetMCPServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"services":{"items":{"$ref":"#/components/schemas/MCPServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","services"],"title":"GetMCPServiceListMsg","description":"GET /api/service Result数据结构"},"GetMCPServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetMCPServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceListRsp","description":"GET /api/service 返回数据结构"},"GetOperaRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/OperateAndBindType"},"type":"array","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetOperaRsp","description":"GET /api/operate 返回数据结构"},"GetParamsRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/StepParams"},"type":"array","title":"Result","description":"参数列表","default":[]}},"type":"object","required":["code","message"],"title":"GetParamsRsp","description":"GET /api/params 返回数据结构"},"GetRecentAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecentAppList"}},"type":"object","required":["code","message","result"],"title":"GetRecentAppListRsp","description":"GET /api/app/recent 返回数据结构"},"GetServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array"},{"type":"null"}],"title":"Apis","description":"解析后的接口列表"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data","description":"YAML 内容数据对象"}},"type":"object","required":["serviceId","name"],"title":"GetServiceDetailMsg","description":"GET /api/service/{serviceId} Result数据结构"},"GetServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceDetailMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalCount":{"type":"integer","title":"Totalcount","description":"总服务数"},"services":{"items":{"$ref":"#/components/schemas/ServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","totalCount","services"],"title":"GetServiceListMsg","description":"GET /api/service Result数据结构"},"GetServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceListRsp","description":"GET /api/service 返回数据结构"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthCheckRsp":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HealthCheckRsp","description":"GET /health_check 返回数据结构"},"KbIteam":{"properties":{"kbId":{"type":"string","title":"Kbid"},"kbName":{"type":"string","title":"Kbname"}},"type":"object","required":["kbId","kbName"],"title":"KbIteam","description":"GET /api/conversation Result数据结构"},"KnowledgeBaseItem":{"properties":{"kbId":{"type":"string","title":"Kbid","description":"知识库ID"},"kbName":{"type":"string","title":"Kbname","description":"知识库名称"},"description":{"type":"string","title":"Description","description":"知识库描述"},"isUsed":{"type":"boolean","title":"Isused","description":"是否使用"}},"type":"object","required":["kbId","kbName","description","isUsed"],"title":"KnowledgeBaseItem","description":"知识库列表项数据结构"},"LLMIteam":{"properties":{"icon":{"type":"string","title":"Icon","default":"data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIGZpbGwtcnVsZT0iZXZlbm9kZCIgaGVpZ2h0PSIxZW0iIHN0eWxlPSJmbGV4Om5vbmU7bGluZS1oZWlnaHQ6MSIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMWVtIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5PbGxhbWE8L3RpdGxlPjxwYXRoIGQ9Ik03LjkwNSAxLjA5Yy4yMTYuMDg1LjQxMS4yMjUuNTg4LjQxLjI5NS4zMDYuNTQ0Ljc0NC43MzQgMS4yNjMuMTkxLjUyMi4zMTUgMS4xLjM2MiAxLjY4YTUuMDU0IDUuMDU0IDAgMDEyLjA0OS0uNjM2bC4wNTEtLjAwNGMuODctLjA3IDEuNzMuMDg3IDIuNDguNDc0LjEwMS4wNTMuMi4xMS4yOTcuMTcuMDUtLjU2OS4xNzItMS4xMzQuMzYtMS42NDQuMTktLjUyLjQzOS0uOTU3LjczMy0xLjI2NGExLjY3IDEuNjcgMCAwMS41ODktLjQxYy4yNTctLjEuNTMtLjExOC43OTYtLjA0Mi40MDEuMTE0Ljc0NS4zNjggMS4wMTYuNzM3LjI0OC4zMzcuNDM0Ljc2OS41NjEgMS4yODcuMjMuOTM0LjI3IDIuMTYzLjExNSAzLjY0NWwuMDUzLjA0LjAyNi4wMTljLjc1Ny41NzYgMS4yODQgMS4zOTcgMS41NjMgMi4zNS40MzUgMS40ODcuMjE2IDMuMTU1LS41MzQgNC4wODhsLS4wMTguMDIxLjAwMi4wMDNjLjQxNy43NjIuNjcgMS41NjcuNzI0IDIuNGwuMDAyLjAzYy4wNjQgMS4wNjUtLjIgMi4xMzctLjgxNCAzLjE5bC0uMDA3LjAxLjAxLjAyNGMuNDcyIDEuMTU3LjYyIDIuMzIyLjQzOCAzLjQ4NmwtLjAwNi4wMzlhLjY1MS42NTEgMCAwMS0uNzQ3LjUzNi42NDguNjQ4IDAgMDEtLjU0LS43NDJjLjE2Ny0xLjAzMy4wMS0yLjA2OS0uNDgtMy4xMjNhLjY0My42NDMgMCAwMS4wNC0uNjE3bC4wMDQtLjAwNmMuNjA0LS45MjQuODU0LTEuODMuOC0yLjcyLS4wNDYtLjc3OS0uMzI1LTEuNTQ0LS44LTIuMjczYS42NDQuNjQ0IDAgMDEuMTgtLjg4NmwuMDA5LS4wMDZjLjI0My0uMTU5LjQ2Ny0uNTY1LjU4LTEuMTJhNC4yMjkgNC4yMjkgMCAwMC0uMDk1LTEuOTc0Yy0uMjA1LS43LS41OC0xLjI4NC0xLjEwNS0xLjY4My0uNTk1LS40NTQtMS4zODMtLjY3My0yLjM4LS42MWEuNjUzLjY1MyAwIDAxLS42MzItLjM3MWMtLjMxNC0uNjY1LS43NzItMS4xNDEtMS4zNDMtMS40MzZhMy4yODggMy4yODggMCAwMC0xLjc3Mi0uMzMyYy0xLjI0NS4wOTktMi4zNDMuODAxLTIuNjcgMS42ODZhLjY1Mi42NTIgMCAwMS0uNjEuNDI1Yy0xLjA2Ny4wMDItMS44OTMuMjUyLTIuNDk3LjcwMy0uNTIyLjM5LS44NzguOTM1LTEuMDY2IDEuNTg4YTQuMDcgNC4wNyAwIDAwLS4wNjggMS44ODZjLjExMi41NTguMzMxIDEuMDIuNTgyIDEuMjY5bC4wMDguMDA3Yy4yMTIuMjA3LjI1Ny41My4xMDkuNzg1LS4zNi42MjItLjYyOSAxLjU0OS0uNjczIDIuNDQtLjA1IDEuMDE4LjE4NiAxLjkwMi43MTkgMi41MzZsLjAxNi4wMTlhLjY0My42NDMgMCAwMS4wOTUuNjljLS41NzYgMS4yMzYtLjc1MyAyLjI1Mi0uNTYyIDMuMDUyYS42NTIuNjUyIDAgMDEtMS4yNjkuMjk4Yy0uMjQzLTEuMDE4LS4wNzgtMi4xODQuNDczLTMuNDk4bC4wMTQtLjAzNS0uMDA4LS4wMTJhNC4zMzkgNC4zMzkgMCAwMS0uNTk4LTEuMzA5bC0uMDA1LS4wMTlhNS43NjQgNS43NjQgMCAwMS0uMTc3LTEuNzg1Yy4wNDQtLjkxLjI3OC0xLjg0Mi42MjItMi41OWwuMDEyLS4wMjYtLjAwMi0uMDAyYy0uMjkzLS40MTgtLjUxLS45NTMtLjYzLTEuNTQ1bC0uMDA1LS4wMjRhNS4zNTIgNS4zNTIgMCAwMS4wOTMtMi40OWMuMjYyLS45MTUuNzc3LTEuNzAxIDEuNTM2LTIuMjY5LjA2LS4wNDUuMTIzLS4wOS4xODYtLjEzMi0uMTU5LTEuNDkzLS4xMTktMi43My4xMTItMy42Ny4xMjctLjUxOC4zMTQtLjk1LjU2Mi0xLjI4Ny4yNy0uMzY4LjYxNC0uNjIyIDEuMDE1LS43MzcuMjY2LS4wNzYuNTQtLjA1OS43OTcuMDQyem00LjExNiA5LjA5Yy45MzYgMCAxLjguMzEzIDIuNDQ2Ljg1NS42My41MjcgMS4wMDUgMS4yMzUgMS4wMDUgMS45NCAwIC44ODgtLjQwNiAxLjU4LTEuMTMzIDIuMDIyLS42Mi4zNzUtMS40NTEuNTU3LTIuNDAzLjU1Ny0xLjAwOSAwLTEuODcxLS4yNTktMi40OTMtLjczNC0uNjE3LS40Ny0uOTYzLTEuMTMtLjk2My0xLjg0NSAwLS43MDcuMzk4LTEuNDE3IDEuMDU2LTEuOTQ2LjY2OC0uNTM3IDEuNTUtLjg0OSAyLjQ4NS0uODQ5em0wIC44OTZhMy4wNyAzLjA3IDAgMDAtMS45MTYuNjVjLS40NjEuMzctLjcyMi44MzUtLjcyMiAxLjI1IDAgLjQyOC4yMS44MjkuNjEgMS4xMzQuNDU1LjM0NyAxLjEyNC41NDggMS45NDMuNTQ4Ljc5OSAwIDEuNDczLS4xNDcgMS45MzItLjQyNi40NjMtLjI4LjctLjY4Ni43LTEuMjU3IDAtLjQyMy0uMjQ2LS44OS0uNjgzLTEuMjU2LS40ODQtLjQwNS0xLjE0LS42NDMtMS44NjQtLjY0M3ptLjY2MiAxLjIxbC4wMDQuMDA0Yy4xMi4xNTEuMDk1LjM3LS4wNTYuNDlsLS4yOTIuMjN2LjQ0NmEuMzc1LjM3NSAwIDAxLS4zNzYuMzczLjM3NS4zNzUgMCAwMS0uMzc2LS4zNzN2LS40NmwtLjI3MS0uMjE4YS4zNDcuMzQ3IDAgMDEtLjA1Mi0uNDkuMzUzLjM1MyAwIDAxLjQ5NC0uMDUxbC4yMTUuMTcyLjIyLS4xNzRhLjM1My4zNTMgMCAwMS40OS4wNTF6bS01LjA0LTEuOTE5Yy40NzggMCAuODY3LjM5Ljg2Ny44NzFhLjg3Ljg3IDAgMDEtLjg2OC44NzEuODcuODcgMCAwMS0uODY3LS44Ny44Ny44NyAwIDAxLjg2Ny0uODcyem04LjcwNiAwYy40OCAwIC44NjguMzkuODY4Ljg3MWEuODcuODcgMCAwMS0uODY4Ljg3MS44Ny44NyAwIDAxLS44NjctLjg3Ljg3Ljg3IDAgMDEuODY3LS44NzJ6TTcuNDQgMi4zbC0uMDAzLjAwMmEuNjU5LjY1OSAwIDAwLS4yODUuMjM4bC0uMDA1LjAwNmMtLjEzOC4xODktLjI1OC40NjctLjM0OC44MzItLjE3LjY5Mi0uMjE2IDEuNjMxLS4xMjQgMi43ODIuNDMtLjEyOC44OTktLjIwOCAxLjQwNC0uMjM3bC4wMS0uMDAxLjAxOS0uMDM0Yy4wNDYtLjA4Mi4wOTUtLjE2MS4xNDgtLjIzOS4xMjMtLjc3MS4wMjItMS42OTItLjI1My0yLjQ0NC0uMTM0LS4zNjQtLjI5Ny0uNjUtLjQ1My0uODEzYS42MjguNjI4IDAgMDAtLjEwNy0uMDlMNy40NCAyLjN6bTkuMTc0LjA0bC0uMDAyLjAwMWEuNjI4LjYyOCAwIDAwLS4xMDcuMDljLS4xNTYuMTYzLS4zMi40NS0uNDUzLjgxNC0uMjkuNzk0LS4zODcgMS43NzYtLjIzIDIuNTcybC4wNTguMDk3LjAwOC4wMTRoLjAzYTUuMTg0IDUuMTg0IDAgMDExLjQ2Ni4yMTJjLjA4Ni0xLjEyNC4wMzgtMi4wNDMtLjEyOC0yLjcyMi0uMDktLjM2NS0uMjEtLjY0My0uMzQ5LS44MzJsLS4wMDQtLjAwNmEuNjU5LjY1OSAwIDAwLS4yODUtLjIzOWgtLjAwNHoiPjwvcGF0aD48L3N2Zz4="},"llmId":{"type":"string","title":"Llmid","default":"empty"},"modelName":{"type":"string","title":"Modelname","default":"qwen2.5-72b-instruct"}},"type":"object","title":"LLMIteam","description":"GET /api/conversation Result数据结构"},"LLMProvider":{"properties":{"provider":{"type":"string","title":"Provider","description":"LLM提供商"},"description":{"type":"string","title":"Description","description":"LLM提供商描述"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"LLM提供商URL"},"icon":{"type":"string","title":"Icon","description":"LLM提供商图标"}},"type":"object","required":["provider","description","icon"],"title":"LLMProvider","description":"LLM提供商数据结构"},"LLMProviderInfo":{"properties":{"llmId":{"type":"string","title":"Llmid","description":"LLM ID"},"icon":{"type":"string","maxLength":25536,"title":"Icon","description":"LLM图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":"https://api.openai.com/v1"},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称"},"maxTokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokens","description":"最大token数"},"isEditable":{"type":"boolean","title":"Iseditable","description":"是否可编辑","default":true}},"type":"object","required":["llmId","modelName"],"title":"LLMProviderInfo","description":"LLM数据结构"},"ListLLMProviderRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProvider"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMProviderRsp","description":"GET /api/llm/provider 返回数据结构"},"ListLLMRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProviderInfo"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMRsp","description":"GET /api/llm 返回数据结构"},"ListOperate":{"type":"string","enum":["list_equal","list_not_equal","list_contains","list_not_contains","list_length_equal","list_length_greater_than","list_length_greater_than_or_equal","list_length_less_than","list_length_less_than_or_equal"],"title":"ListOperate","description":"Choice 工具支持的列表运算符"},"ListTeamKnowledgeMsg":{"properties":{"teamKbList":{"items":{"$ref":"#/components/schemas/TeamKnowledgeBaseItem"},"type":"array","title":"Teamkblist","description":"团队知识库列表","default":[]}},"type":"object","title":"ListTeamKnowledgeMsg","description":"GET /api/knowledge Result数据结构"},"ListTeamKnowledgeRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ListTeamKnowledgeMsg"}},"type":"object","required":["code","message","result"],"title":"ListTeamKnowledgeRsp","description":"GET /api/knowledge 返回数据结构"},"MCPInstallStatus":{"type":"string","enum":["init","installing","cancelled","ready","failed"],"title":"MCPInstallStatus","description":"MCP 服务状态"},"MCPServiceCardItem":{"properties":{"mcpserviceId":{"type":"string","title":"Mcpserviceid","description":"mcp服务ID"},"name":{"type":"string","title":"Name","description":"mcp服务名称"},"description":{"type":"string","title":"Description","description":"mcp服务简介"},"icon":{"type":"string","title":"Icon","description":"mcp服务图标"},"author":{"type":"string","title":"Author","description":"mcp服务作者"},"isActive":{"type":"boolean","title":"Isactive","description":"mcp服务是否激活","default":false},"status":{"$ref":"#/components/schemas/MCPInstallStatus","description":"mcp服务状态","default":"installing"}},"type":"object","required":["mcpserviceId","name","description","icon","author"],"title":"MCPServiceCardItem","description":"插件中心:MCP服务卡片数据结构"},"MCPTool":{"properties":{"id":{"type":"string","title":"Id","description":"MCP工具ID"},"name":{"type":"string","title":"Name","description":"MCP工具名称"},"description":{"type":"string","title":"Description","description":"MCP工具描述"},"mcp_id":{"type":"string","title":"Mcp Id","description":"MCP ID"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"MCP工具输入参数"}},"type":"object","required":["id","name","description","mcp_id","input_schema"],"title":"MCPTool","description":"MCP工具"},"MCPType":{"type":"string","enum":["sse","stdio","stream"],"title":"MCPType","description":"MCP 类型"},"ModFavAppMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["appId","favorited"],"title":"ModFavAppMsg","description":"PUT /api/app/{appId} Result数据结构"},"ModFavAppRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavAppRequest","description":"PUT /api/app/{appId} 请求数据结构"},"ModFavAppRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavAppMsg"}},"type":"object","required":["code","message","result"],"title":"ModFavAppRsp","description":"PUT /api/app/{appId} 返回数据结构"},"ModFavServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","favorited"],"title":"ModFavServiceMsg","description":"PUT /api/service/{serviceId} Result数据结构"},"ModFavServiceRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavServiceRequest","description":"PUT /api/service/{serviceId} 请求数据结构"},"ModFavServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ModFavServiceRsp","description":"PUT /api/service/{serviceId} 返回数据结构"},"ModifyConversationData":{"properties":{"title":{"type":"string","maxLength":2000,"minLength":1,"title":"Title"}},"type":"object","required":["title"],"title":"ModifyConversationData","description":"修改会话信息"},"NodeItem":{"properties":{"stepId":{"type":"string","title":"Stepid","default":""},"serviceId":{"type":"string","title":"Serviceid","default":""},"nodeId":{"type":"string","title":"Nodeid","default":""},"name":{"type":"string","title":"Name","default":""},"callId":{"type":"string","title":"Callid","default":"Empty"},"description":{"type":"string","title":"Description","default":""},"enable":{"type":"boolean","title":"Enable","default":true},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","default":{}},"depedency":{"anyOf":[{"$ref":"#/components/schemas/DependencyItem"},{"type":"null"}]},"position":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"editable":{"type":"boolean","title":"Editable","default":true}},"type":"object","title":"NodeItem","description":"请求/响应中的节点变量类"},"NodeMetaDataItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"callId":{"type":"string","title":"Callid"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"editable":{"type":"boolean","title":"Editable","default":true},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat"}},"type":"object","required":["nodeId","callId","name","description","parameters","createdAt"],"title":"NodeMetaDataItem","description":"节点元数据类"},"NodeServiceItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"type":{"type":"string","title":"Type","description":"服务类型"},"nodeMetaDatas":{"items":{"$ref":"#/components/schemas/NodeMetaDataItem"},"type":"array","title":"Nodemetadatas","default":[]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdat","description":"创建时间"}},"type":"object","required":["serviceId","name","type"],"title":"NodeServiceItem","description":"GET /api/flow/service 中单个service信息以及service下的节点元数据的信息"},"NodeServiceListMsg":{"properties":{"services":{"items":{"$ref":"#/components/schemas/NodeServiceItem"},"type":"array","title":"Services","description":"服务列表","default":[]}},"type":"object","title":"NodeServiceListMsg","description":"GET /api/flow/service result"},"NodeServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/NodeServiceListMsg"}},"type":"object","required":["code","message","result"],"title":"NodeServiceListRsp","description":"GET /api/flow/service 返回数据结构"},"NumberOperate":{"type":"string","enum":["number_equal","number_not_equal","number_greater_than","number_less_than","number_greater_than_or_equal","number_less_than_or_equal"],"title":"NumberOperate","description":"Choice 工具支持的数字运算符"},"OidcRedirectMsg":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"OidcRedirectMsg","description":"GET /api/auth/redirect Result数据结构"},"OidcRedirectRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/OidcRedirectMsg"}},"type":"object","required":["code","message","result"],"title":"OidcRedirectRsp","description":"GET /api/auth/redirect 返回数据结构"},"OperateAndBindType":{"properties":{"operate":{"anyOf":[{"$ref":"#/components/schemas/NumberOperate"},{"$ref":"#/components/schemas/StringOperate"},{"$ref":"#/components/schemas/ListOperate"},{"$ref":"#/components/schemas/BoolOperate"},{"$ref":"#/components/schemas/DictOperate"}],"title":"Operate","description":"操作类型"},"bind_type":{"$ref":"#/components/schemas/Type","description":"绑定类型"}},"type":"object","required":["operate","bind_type"],"title":"OperateAndBindType","description":"操作和绑定类型数据结构"},"ParamsNode":{"properties":{"paramName":{"type":"string","title":"Paramname","description":"参数名称"},"paramPath":{"type":"string","title":"Parampath","description":"参数路径"},"paramType":{"$ref":"#/components/schemas/Type","description":"参数类型"},"subParams":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParamsNode"},"type":"array"},{"type":"null"}],"title":"Subparams","description":"子参数列表"}},"type":"object","required":["paramName","paramPath","paramType"],"title":"ParamsNode","description":"参数数据结构"},"PermissionType":{"type":"string","enum":["protected","public","private"],"title":"PermissionType","description":"权限类型"},"PositionItem":{"properties":{"x":{"type":"number","title":"X","default":0.0},"y":{"type":"number","title":"Y","default":0.0}},"type":"object","title":"PositionItem","description":"请求/响应中的前端相对位置变量类"},"PostAuthKeyMsg":{"properties":{"api_key":{"type":"string","title":"Api Key"}},"type":"object","required":["api_key"],"title":"PostAuthKeyMsg","description":"POST /api/auth/key Result数据结构"},"PostAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/PostAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"PostAuthKeyRsp","description":"POST /api/auth/key 返回数据结构"},"PutFlowReq":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Input"}},"type":"object","required":["flow"],"title":"PutFlowReq","description":"创建/修改流拓扑结构"},"QuestionBlacklistRequest":{"properties":{"id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","question","answer","is_deletion"],"title":"QuestionBlacklistRequest","description":"POST /api/blacklist/question 请求数据结构"},"RecentAppList":{"properties":{"applications":{"items":{"$ref":"#/components/schemas/RecentAppListItem"},"type":"array","title":"Applications","description":"最近使用的应用列表"}},"type":"object","required":["applications"],"title":"RecentAppList","description":"GET /api/app/recent Result数据结构"},"RecentAppListItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"name":{"type":"string","title":"Name","description":"应用名称"}},"type":"object","required":["appId","name"],"title":"RecentAppListItem","description":"GET /api/app/recent 列表项数据结构"},"RecordContent":{"properties":{"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"data":{"additionalProperties":true,"type":"object","title":"Data","default":{}},"facts":{"items":{"type":"string"},"type":"array","title":"Facts","description":"[运行后修改]与Record关联的事实信息","default":[]}},"type":"object","required":["question","answer"],"title":"RecordContent","description":"Record表子项:Record加密前的数据结构"},"RecordData":{"properties":{"id":{"type":"string","title":"Id"},"groupId":{"type":"string","title":"Groupid"},"conversationId":{"type":"string","title":"Conversationid"},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid"},"document":{"items":{"$ref":"#/components/schemas/RecordDocument"},"type":"array","title":"Document","default":[]},"flow":{"anyOf":[{"$ref":"#/components/schemas/RecordFlow"},{"type":"null"}]},"content":{"$ref":"#/components/schemas/RecordContent"},"metadata":{"$ref":"#/components/schemas/RecordMetadata"},"comment":{"$ref":"#/components/schemas/CommentType","default":"none"},"createdAt":{"type":"number","title":"Createdat"}},"type":"object","required":["id","groupId","conversationId","content","metadata","createdAt"],"title":"RecordData","description":"GET /api/record/{conversation_id} Result内元素数据结构"},"RecordDocument":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"order":{"type":"integer","title":"Order","description":"文档顺序","default":0},"abstract":{"type":"string","title":"Abstract","description":"文档摘要","default":""},"author":{"type":"string","title":"Author","description":"文档作者","default":""},"associated":{"type":"string","enum":["question","answer"],"title":"Associated"}},"type":"object","required":["name","type","size","associated"],"title":"RecordDocument","description":"GET /api/record/{conversation_id} Result中的document数据结构"},"RecordFlow":{"properties":{"id":{"type":"string","title":"Id"},"recordId":{"type":"string","title":"Recordid"},"flowId":{"type":"string","title":"Flowid"},"flowName":{"type":"string","title":"Flowname","default":""},"flowStatus":{"$ref":"#/components/schemas/StepStatus","default":"success"},"stepNum":{"type":"integer","title":"Stepnum"},"steps":{"items":{"$ref":"#/components/schemas/RecordFlowStep"},"type":"array","title":"Steps"}},"type":"object","required":["id","recordId","flowId","stepNum","steps"],"title":"RecordFlow","description":"Flow的执行信息"},"RecordFlowStep":{"properties":{"stepId":{"type":"string","title":"Stepid"},"stepStatus":{"$ref":"#/components/schemas/StepStatus"},"input":{"additionalProperties":true,"type":"object","title":"Input"},"output":{"additionalProperties":true,"type":"object","title":"Output"}},"type":"object","required":["stepId","stepStatus","input","output"],"title":"RecordFlowStep","description":"Record表子项:flow的单步数据结构"},"RecordListMsg":{"properties":{"records":{"items":{"$ref":"#/components/schemas/RecordData"},"type":"array","title":"Records"}},"type":"object","required":["records"],"title":"RecordListMsg","description":"GET /api/record/{conversation_id} Result数据结构"},"RecordListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecordListMsg"}},"type":"object","required":["code","message","result"],"title":"RecordListRsp","description":"GET /api/record/{conversation_id} 返回数据结构"},"RecordMetadata":{"properties":{"inputTokens":{"type":"integer","title":"Inputtokens","default":0},"outputTokens":{"type":"integer","title":"Outputtokens","default":0},"timeCost":{"type":"number","title":"Timecost","default":0},"feature":{"additionalProperties":true,"type":"object","title":"Feature","default":{}},"footNoteMetadataList":{"items":{"$ref":"#/components/schemas/FootNoteMetaData"},"type":"array","title":"Footnotemetadatalist","description":"脚注元信息列表","default":[]}},"type":"object","title":"RecordMetadata","description":"Record表子项:Record的元信息"},"RequestData":{"properties":{"question":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Question","description":"用户输入"},"conversationId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversationid","description":"聊天ID"},"groupId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupid","description":"问答组ID"},"language":{"type":"string","title":"Language","description":"语言","default":"zh"},"files":{"items":{"type":"string"},"type":"array","title":"Files","description":"文件列表","default":[]},"app":{"anyOf":[{"$ref":"#/components/schemas/RequestDataApp"},{"type":"null"}],"description":"应用"},"debug":{"type":"boolean","title":"Debug","description":"是否调试","default":false},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid","description":"任务ID"},"params":{"anyOf":[{"$ref":"#/components/schemas/param"},{"type":"boolean"},{"type":"null"}],"title":"Params","description":"流执行过程中的参数补充"}},"type":"object","title":"RequestData","description":"POST /api/chat 请求的总的数据结构"},"RequestDataApp":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","description":"Flow ID"}},"type":"object","required":["appId"],"title":"RequestDataApp","description":"模型对话中包含的app信息"},"ResponseData":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"title":"Result"}},"type":"object","required":["code","message","result"],"title":"ResponseData","description":"基础返回数据结构"},"SearchType":{"type":"string","enum":["all","name","description","author"],"title":"SearchType","description":"搜索类型"},"ServiceApiData":{"properties":{"name":{"type":"string","title":"Name","description":"接口名称"},"path":{"type":"string","title":"Path","description":"接口路径"},"description":{"type":"string","title":"Description","description":"接口描述"}},"type":"object","required":["name","path","description"],"title":"ServiceApiData","description":"语义接口中心:服务 API 接口属性数据结构"},"ServiceCardItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"description":{"type":"string","title":"Description","description":"服务简介"},"icon":{"type":"string","title":"Icon","description":"服务图标"},"author":{"type":"string","title":"Author","description":"服务作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","name","description","icon","author","favorited"],"title":"ServiceCardItem","description":"语义接口中心:服务卡片数据结构"},"StepParams":{"properties":{"stepId":{"type":"string","title":"Stepid","description":"步骤ID"},"name":{"type":"string","title":"Name","description":"Step名称"},"paramsNode":{"anyOf":[{"$ref":"#/components/schemas/ParamsNode"},{"type":"null"}],"description":"参数节点"}},"type":"object","required":["stepId","name"],"title":"StepParams","description":"参数数据结构"},"StepStatus":{"type":"string","enum":["unknown","init","waiting","running","success","error","param","cancelled"],"title":"StepStatus","description":"步骤状态"},"StringOperate":{"type":"string","enum":["string_equal","string_not_equal","string_contains","string_not_contains","string_starts_with","string_ends_with","string_length_equal","string_length_greater_than","string_length_greater_than_or_equal","string_length_less_than","string_length_less_than_or_equal","string_regex_match"],"title":"StringOperate","description":"Choice 工具支持的字符串运算符"},"TeamKnowledgeBaseItem":{"properties":{"teamId":{"type":"string","title":"Teamid","description":"团队ID"},"teamName":{"type":"string","title":"Teamname","description":"团队名称"},"kb_list":{"items":{"$ref":"#/components/schemas/KnowledgeBaseItem"},"type":"array","title":"Kb List","description":"知识库列表","default":[]}},"type":"object","required":["teamId","teamName"],"title":"TeamKnowledgeBaseItem","description":"团队知识库列表项数据结构"},"Type":{"type":"string","enum":["string","number","list","dict","bool"],"title":"Type","description":"Choice 工具支持的类型"},"UpdateConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListItem"}},"type":"object","required":["code","message","result"],"title":"UpdateConversationRsp","description":"POST /api/conversation 返回数据结构"},"UpdateKbReq":{"properties":{"kbIds":{"items":{"type":"string"},"type":"array","title":"Kbids","description":"知识库ID列表","default":[]}},"type":"object","title":"UpdateKbReq","description":"更新知识库请求体"},"UpdateLLMReq":{"properties":{"icon":{"type":"string","title":"Icon","description":"图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":""},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称","default":""},"maxTokens":{"type":"integer","title":"Maxtokens","description":"最大token数","default":8192}},"type":"object","title":"UpdateLLMReq","description":"更新大模型请求体"},"UpdateMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"}},"type":"object","required":["serviceId","name"],"title":"UpdateMCPServiceMsg","description":"插件中心:MCP服务属性数据结构"},"UpdateMCPServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"config":{"additionalProperties":true,"type":"object","title":"Config","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType","description":"MCP传输协议(Stdio/SSE/Streamable)","default":"stdio"}},"type":"object","required":["name","description","overview","config"],"title":"UpdateMCPServiceRequest","description":"POST /api/mcpservice 请求数据结构"},"UpdateMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateMCPServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateMCPServiceRsp","description":"POST /api/mcp_service 返回数据结构"},"UpdateServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array","title":"Apis","description":"解析后的接口列表"}},"type":"object","required":["serviceId","name","apis"],"title":"UpdateServiceMsg","description":"语义接口中心:服务属性数据结构"},"UpdateServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"data":{"additionalProperties":true,"type":"object","title":"Data","description":"对应 YAML 内容的数据对象"}},"type":"object","required":["data"],"title":"UpdateServiceRequest","description":"POST /api/service 请求数据结构"},"UpdateServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateServiceRsp","description":"POST /api/service 返回数据结构"},"UserBlacklistRequest":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"is_ban":{"type":"integer","title":"Is Ban"}},"type":"object","required":["user_sub","is_ban"],"title":"UserBlacklistRequest","description":"POST /api/blacklist/user 请求数据结构"},"UserGetMsp":{"properties":{"total":{"type":"integer","title":"Total","default":0},"userInfoList":{"items":{"$ref":"#/components/schemas/UserInfo"},"type":"array","title":"Userinfolist","default":[]}},"type":"object","title":"UserGetMsp","description":"GET /api/user result"},"UserGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UserGetMsp"}},"type":"object","required":["code","message","result"],"title":"UserGetRsp","description":"GET /api/user 返回数据结构"},"UserInfo":{"properties":{"userSub":{"type":"string","title":"Usersub","default":""},"userName":{"type":"string","title":"Username","default":""},"autoExecute":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Autoexecute","default":false}},"type":"object","title":"UserInfo","description":"用户信息数据结构"},"UserUpdateRequest":{"properties":{"autoExecute":{"type":"boolean","title":"Autoexecute","description":"是否自动执行","default":false}},"type":"object","title":"UserUpdateRequest","description":"更新用户信息请求体"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"_GetAuthKeyMsg":{"properties":{"api_key_exists":{"type":"boolean","title":"Api Key Exists"}},"type":"object","required":["api_key_exists"],"title":"_GetAuthKeyMsg","description":"GET /api/auth/key Result数据结构"},"param":{"properties":{"content":{"additionalProperties":true,"type":"object","title":"Content","description":"流执行过程中的参数补充内容","default":{}},"description":{"type":"string","title":"Description","description":"流执行过程中的参数补充描述","default":""}},"type":"object","title":"param","description":"流执行过程中的参数补充"}}}} \ No newline at end of file -- Gitee From 0f7019869a9393aa2f3e2d9aaa188dfd57afdd9f Mon Sep 17 00:00:00 2001 From: zxstty Date: Fri, 8 Aug 2025 17:55:22 +0800 Subject: [PATCH 61/78] fix bug --- apps/routers/appcenter.py | 3 +- apps/routers/chat.py | 1 + apps/scheduler/executor/agent.py | 87 +++++++++++++++++++----------- apps/scheduler/mcp_agent/select.py | 7 +-- apps/scheduler/pool/loader/app.py | 4 +- apps/scheduler/pool/loader/mcp.py | 13 +++++ apps/schemas/appcenter.py | 8 --- apps/schemas/pool.py | 4 +- apps/services/appcenter.py | 6 +-- apps/services/mcp_service.py | 21 +++++--- nohup.out | 4 ++ 11 files changed, 102 insertions(+), 56 deletions(-) create mode 100644 nohup.out diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index 88df7cb1..36815743 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -9,10 +9,11 @@ from fastapi.responses import JSONResponse from apps.dependency.user import get_user, verify_user from apps.exceptions import InstancePermissionError -from apps.schemas.appcenter import AppFlowInfo, AppMcpServiceInfo, AppPermissionData +from apps.schemas.appcenter import AppFlowInfo, AppPermissionData from apps.schemas.enum_var import AppFilterType, AppType from apps.schemas.request_data import CreateAppRequest, ModFavAppRequest from apps.schemas.response_data import ( + AppMcpServiceInfo, LLMIteam, BaseAppOperationMsg, BaseAppOperationRsp, diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 5e035475..5a5a7593 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -54,6 +54,7 @@ async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> T task = await TaskManager.init_new_task(user_sub=user_sub, session_id=session_id, post_body=post_body) task.runtime.question = post_body.question task.ids.group_id = post_body.group_id + task.state.app_id = post_body.app.app_id if post_body.app else "" else: if not post_body.task_id: err = "[Chat] task_id 不可为空!" diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 9ced57f9..b313d555 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -93,7 +93,7 @@ class MCPAgentExecutor(BaseExecutor): error_message = "之前的计划遇到以下报错\n\n"+self.task.state.error_message else: error_message = "初始化计划" - tools = MCPSelector.select_top_tool( + tools = await MCPSelector.select_top_tool( self.task.runtime.question, list(self.tools.values()), additional_info=error_message, top_n=40) if is_replan: @@ -114,16 +114,19 @@ class MCPAgentExecutor(BaseExecutor): reasoning_llm=self.resoning_llm ) self.update_tokens() - self.push_message( + await self.push_message( EventType.STEP_CANCEL, data={} ) if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: self.task.context[-1].step_status = StepStatus.CANCELLED - self.task.runtime.temporary_plans = self.task.runtime.temporary_plans.plans[:start_index] + temporary_plans.plans + self.task.runtime.temporary_plans.plans = self.task.runtime.temporary_plans.plans[ + : start_index] + temporary_plans.plans self.task.state.step_index = start_index else: start_index = 0 + logger.error( + f"各个字段的类型: {type(self.task.runtime.question)}, {type(tools)}, {type(self.max_steps)}, {type(self.resoning_llm)}") self.task.runtime.temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, tool_list=tools, max_steps=self.max_steps, reasoning_llm=self.resoning_llm) for i in range(start_index, len(self.task.runtime.temporary_plans.plans)): self.task.runtime.temporary_plans.plans[i].step_id = str(uuid.uuid4()) @@ -145,7 +148,8 @@ class MCPAgentExecutor(BaseExecutor): async def reset_step_to_index(self, start_index: int) -> None: """重置步骤到开始""" logger.info("[MCPAgentExecutor] 重置步骤到索引 %d", start_index) - if self.task.runtime.temporary_plans: + + if start_index < len(self.task.runtime.temporary_plans.plans): self.task.state.flow_status = FlowStatus.RUNNING self.task.state.step_id = self.task.runtime.temporary_plans.plans[start_index].step_id self.task.state.step_index = 0 @@ -154,7 +158,6 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.step_status = StepStatus.RUNNING self.task.state.retry_times = 0 else: - self.task.state.flow_status = FlowStatus.SUCCESS self.task.state.step_id = FINAL_TOOL_ID async def confirm_before_step(self) -> None: @@ -162,13 +165,14 @@ class MCPAgentExecutor(BaseExecutor): # 发送确认消息 confirm_message = await MCPPlanner.get_tool_risk(self.tools[self.task.state.step_id], self.task.state.current_input, "", self.resoning_llm) self.update_tokens() - self.push_message(EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( + await self.push_message(EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( exclude_none=True, by_alias=True)) - self.push_message(EventType.FLOW_STOP, {}) + await self.push_message(EventType.FLOW_STOP, {}) self.task.state.flow_status = FlowStatus.WAITING self.task.state.step_status = StepStatus.WAITING self.task.context.append( FlowStepHistory( + task_id=self.task.id, step_id=self.task.state.step_id, step_name=self.task.state.step_name, step_description=self.task.state.step_description, @@ -198,16 +202,17 @@ class MCPAgentExecutor(BaseExecutor): try: output_params = await mcp_client.call_tool(mcp_tool.name, self.task.state.current_input) self.update_tokens() - self.push_message( + await self.push_message( EventType.STEP_INPUT, self.task.state.current_input ) - self.push_message( + await self.push_message( EventType.STEP_OUTPUT, output_params ) self.task.context.append( FlowStepHistory( + task_id=self.task.id, step_id=self.task.state.step_id, step_name=self.task.state.step_name, step_description=self.task.state.step_description, @@ -236,14 +241,14 @@ class MCPAgentExecutor(BaseExecutor): self.resoning_llm ) self.update_tokens() - self.push_message( + await self.push_message( EventType.STEP_WAITING_FOR_PARAM, data={ "message": "当运行产生如下报错:\n" + self.task.state.error_message, "params": params_with_null } ) - self.push_message( + await self.push_message( EventType.FLOW_STOP, data={} ) @@ -251,6 +256,7 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.step_status = StepStatus.PARAM self.task.context.append( FlowStepHistory( + task_id=self.task.id, step_id=self.task.state.step_id, step_name=self.task.state.step_name, step_description=self.task.state.step_description, @@ -274,7 +280,7 @@ class MCPAgentExecutor(BaseExecutor): # 最后一步 self.task.state.flow_status = FlowStatus.SUCCESS self.task.state.step_status = StepStatus.SUCCESS - self.push_message( + await self.push_message( EventType.FLOW_SUCCESS, data={} ) @@ -284,25 +290,20 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.step_description = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content self.task.state.step_status = StepStatus.INIT self.task.state.current_input = {} - self.push_message( + await self.push_message( EventType.STEP_INIT, data={} ) else: # 没有下一步了,结束流程 - self.task.state.flow_status = FlowStatus.SUCCESS - self.task.state.step_status = StepStatus.SUCCESS - self.push_message( - EventType.FLOW_SUCCESS, - data={} - ) + self.task.state.step_id = FINAL_TOOL_ID return async def error_handle_after_step(self) -> None: """步骤执行失败后的错误处理""" self.task.state.step_status = StepStatus.ERROR self.task.state.flow_status = FlowStatus.ERROR - self.push_message( + await self.push_message( EventType.FLOW_FAILED, data={} ) @@ -310,6 +311,7 @@ class MCPAgentExecutor(BaseExecutor): del self.task.context[-1] self.task.context.append( FlowStepHistory( + task_id=self.task.id, step_id=self.task.state.step_id, step_name=self.task.state.step_name, step_description=self.task.state.step_description, @@ -343,11 +345,11 @@ class MCPAgentExecutor(BaseExecutor): else: self.task.state.flow_status = FlowStatus.CANCELLED self.task.state.step_status = StepStatus.CANCELLED - self.push_message( + await self.push_message( EventType.STEP_CANCEL, data={} ) - self.push_message( + await self.push_message( EventType.FLOW_CANCEL, data={} ) @@ -392,7 +394,7 @@ class MCPAgentExecutor(BaseExecutor): (await MCPHost.assemble_memory(self.task)), self.resoning_llm ): - self.push_message( + await self.push_message( EventType.TEXT_ADD, data=chunk ) @@ -409,37 +411,59 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.flow_id = str(uuid.uuid4()) self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) await self.plan(is_replan=False) - self.reset_step_to_index(0) - TaskManager.save_task(self.task.id, self.task) + await self.reset_step_to_index(0) + await TaskManager.save_task(self.task.id, self.task) except Exception as e: + import traceback + logger.error("[MCPAgentExecutor] 初始化失败: %s", traceback.format_exc()) logger.error("[MCPAgentExecutor] 初始化失败: %s", str(e)) self.task.state.flow_status = FlowStatus.ERROR self.task.state.error_message = str(e) - self.push_message( + await self.push_message( EventType.FLOW_FAILED, data={} ) return self.task.state.flow_status = FlowStatus.RUNNING - self.push_message( + await self.push_message( EventType.FLOW_START, data={} ) + if self.task.state.step_id == FINAL_TOOL_ID: + # 如果已经是最后一步,直接结束 + self.task.state.flow_status = FlowStatus.SUCCESS + await self.push_message( + EventType.FLOW_SUCCESS, + data={} + ) + await self.summarize() + return try: - while self.task.state.step_index < len(self.task.runtime.temporary_plans) and \ + while len(self.task.runtime.temporary_plans.plans) and \ + self.task.state.step_index < len(self.task.runtime.temporary_plans.plans) and \ + self.task.state.step_id != FINAL_TOOL_ID and \ self.task.state.flow_status == FlowStatus.RUNNING: await self.work() - TaskManager.save_task(self.task.id, self.task) + await TaskManager.save_task(self.task.id, self.task) + if self.task.state.step_id == FINAL_TOOL_ID: + # 如果已经是最后一步,直接结束 + self.task.state.flow_status = FlowStatus.SUCCESS + self.task.state.step_status = StepStatus.SUCCESS + await self.push_message( + EventType.FLOW_SUCCESS, + data={} + ) + await self.summarize() except Exception as e: logger.error("[MCPAgentExecutor] 执行过程中发生错误: %s", str(e)) self.task.state.flow_status = FlowStatus.ERROR self.task.state.error_message = str(e) self.task.state.step_status = StepStatus.ERROR - self.push_message( + await self.push_message( EventType.STEP_ERROR, data={} ) - self.push_message( + await self.push_message( EventType.FLOW_FAILED, data={} ) @@ -447,6 +471,7 @@ class MCPAgentExecutor(BaseExecutor): del self.task.context[-1] self.task.context.append( FlowStepHistory( + task_id=self.task.id, step_id=self.task.state.step_id, step_name=self.task.state.step_name, step_description=self.task.state.step_description, diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 933527c3..67411a3a 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -47,7 +47,8 @@ class MCPSelector: random.shuffle(tool_list) max_tokens = Config().get_config().function_call.max_tokens template = _env.from_string(TOOL_SELECT) - if TokenCalculator.calculate_token_length( + token_calculator = TokenCalculator() + if token_calculator.calculate_token_length( messages=[{"role": "user", "content": template.render( goal=goal, tools=[], additional_info=additional_info )}], @@ -62,7 +63,7 @@ class MCPSelector: sub_tools = [] while index < len(tool_list): tool = tool_list[index] - tokens = TokenCalculator.calculate_token_length( + tokens = token_calculator.calculate_token_length( messages=[{"role": "user", "content": template.render( goal=goal, tools=[tool], additional_info=additional_info @@ -73,7 +74,7 @@ class MCPSelector: continue sub_tools.append(tool) - tokens = TokenCalculator.calculate_token_length(messages=[{"role": "user", "content": template.render( + tokens = token_calculator.calculate_token_length(messages=[{"role": "user", "content": template.render( goal=goal, tools=sub_tools, additional_info=additional_info)}, ], pure_text=True) if tokens > max_tokens: del sub_tools[-1] diff --git a/apps/scheduler/pool/loader/app.py b/apps/scheduler/pool/loader/app.py index a85395bf..49407ba9 100644 --- a/apps/scheduler/pool/loader/app.py +++ b/apps/scheduler/pool/loader/app.py @@ -78,6 +78,7 @@ class AppLoader: # 加载模型 try: metadata = AgentAppMetadata.model_validate(metadata) + logger.info(f"[AppLoader] Agent应用元数据验证成功: {metadata}") except Exception as e: err = "[AppLoader] Agent应用元数据验证失败" logger.exception(err) @@ -102,7 +103,6 @@ class AppLoader: await file_checker.diff_one(app_path) await self.load(app_id, file_checker.hashes[f"app/{app_id}"]) - @staticmethod async def delete(app_id: str, *, is_reload: bool = False) -> None: """ @@ -157,5 +157,7 @@ class AppLoader: }, upsert=True, ) + app_pool = await app_collection.find_one({"_id": metadata.id}) + logger.error(f"[AppLoader] 更新 MongoDB 成功: {app_pool}") except Exception: logger.exception("[AppLoader] 更新 MongoDB 失败") diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index 2be0fe5d..bf007fc8 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -434,6 +434,19 @@ class MCPLoader(metaclass=SingletonMeta): ) ) await f.aclose() + if mcp_config.type == MCPType.STDIO: + index = None + for i in range(len(mcp_config.config.args)): + if mcp_config.config.args[i] == "--directory": + index = i + 1 + break + if index is not None: + if index < len(mcp_config.config.args): + mcp_config.config.args[index] = str(user_path)+'/project' + else: + mcp_config.config.args.append(str(user_path)+'/project') + else: + mcp_config.config.args = ["--directory", str(user_path)+'/project'] + mcp_config.config.args # 更新数据库 mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index 773e41cd..e3bb896e 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -50,14 +50,6 @@ class AppFlowInfo(BaseModel): debug: bool = Field(default=False, description="是否经过调试") -class AppMcpServiceInfo(BaseModel): - """应用关联的MCP服务信息""" - - id: str = Field(..., description="MCP服务ID") - name: str = Field(default="", description="MCP服务名称") - description: str = Field(default="", description="MCP服务简介") - - class AppData(BaseModel): """应用信息数据结构""" diff --git a/apps/schemas/pool.py b/apps/schemas/pool.py index 7df6dab8..3532b6e2 100644 --- a/apps/schemas/pool.py +++ b/apps/schemas/pool.py @@ -109,7 +109,7 @@ class AppPool(BaseData): permission: Permission = Field(description="应用权限配置", default=Permission()) flows: list[AppFlow] = Field(description="Flow列表", default=[]) hashes: dict[str, str] = Field(description="关联文件的hash值", default={}) - mcp_service: list[str] = Field(default=[], alias="mcpService", description="MCP服务id列表") + mcp_service: list[str] = Field(default=[], description="MCP服务id列表") llm_id: str = Field( - default="empty", alias="llmId", description="应用使用的大模型ID(如果有的话)" + default="empty", description="应用使用的大模型ID(如果有的话)" ) diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index 6b6e3171..4e0d00d0 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -83,6 +83,7 @@ class AppCenterManager: if app_type is not None: filters["app_type"] = app_type.value # 获取应用列表 + logger.error(f"[AppCenterManager] 搜索条件: {filters}, 页码: {page}, 每页大小: {SERVICE_PAGE_SIZE}") apps, total_apps = await AppCenterManager._search_apps_by_filter(filters, page, SERVICE_PAGE_SIZE) # 构建返回的应用卡片列表 @@ -406,7 +407,6 @@ class AppCenterManager: "name": source.name, "description": source.description, "history_len": source.history_len, - "llm_id": source.llm_id, } @staticmethod @@ -485,10 +485,10 @@ class AppCenterManager: # 处理llm_id字段 if data is not None and hasattr(data, "llm") and data.llm: # 创建应用场景,验证传入的 llm_id 状态 (create_app) - metadata.llm_id = data.llm.llm_id if data.llm.llm_id else "empty" + metadata.llm_id = data.llm if data.llm else "empty" elif data is not None and hasattr(data, "llm_id"): # 更新应用场景,使用 data 中的 llm_id (update_app) - metadata.llm_id = data.llm_id if data.llm_id else "empty" + metadata.llm_id = data.llm if data.llm else "empty" elif app_data is not None and hasattr(app_data, "llm_id"): # 更新应用发布状态场景,使用 app_data 中的 llm_id (update_app_publish_status) metadata.llm_id = app_data.llm_id if app_data.llm_id else "empty" diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index d15ca7a4..434c8750 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -98,7 +98,7 @@ class MCPServiceManager: else: filters["activated"] = {"$nin": [user_sub]} if not is_installed: - user_info = await UserManager.get_user_info(user_sub) + user_info = await UserManager.get_userinfo_by_user_sub(user_sub) if not user_info.is_admin: filters["status"] = MCPInstallStatus.READY.value else: @@ -247,13 +247,20 @@ class MCPServiceManager: # 保存并载入配置 logger.info("[MCPServiceManager] 创建mcp:%s", mcp_server.name) mcp_path = MCP_PATH / "template" / mcp_id / "project" - index = None - for i in range(len(config.args)): - if not config.args[i].startswith("-"): - index = i + if isinstance(config, MCPServerStdioConfig): + index = None + for i in range(len(config.args)): + if not config.args[i] == "--directory": + continue + index = i + 1 break - if index is not None: - config.args[index] = str(mcp_path) + if index is not None: + if index >= len(config.args): + config.args.append(str(mcp_path)) + else: + config.args[index+1] = str(mcp_path) + else: + config.args += ["--directory", str(mcp_path)] await MCPLoader._insert_template_db(mcp_id=mcp_id, config=mcp_server) await MCPLoader.save_one(mcp_id, mcp_server) await MCPLoader.update_template_status(mcp_id, MCPInstallStatus.INIT) diff --git a/nohup.out b/nohup.out new file mode 100644 index 00000000..d2093b27 --- /dev/null +++ b/nohup.out @@ -0,0 +1,4 @@ +Traceback (most recent call last): + File "/home/zjq/euler-copilot-framework_1/apps/main.py", line 18, in + from apps.common.config import Config +ModuleNotFoundError: No module named 'apps' -- Gitee From 85bf0d23fe9fc6543d44f962c90bd286919601ae Mon Sep 17 00:00:00 2001 From: zxstty Date: Sat, 9 Aug 2025 22:05:44 +0800 Subject: [PATCH 62/78] =?UTF-8?q?=E5=AE=8C=E5=96=84mcp=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/constants.py | 2 +- apps/main.py | 12 +- apps/routers/chat.py | 11 +- apps/scheduler/executor/agent.py | 177 +++++++++++++++----------- apps/scheduler/mcp_agent/host.py | 48 ------- apps/scheduler/mcp_agent/plan.py | 6 +- apps/scheduler/mcp_agent/prompt.py | 5 +- apps/scheduler/mcp_agent/select.py | 53 ++++++-- apps/scheduler/pool/mcp/client.py | 9 +- apps/scheduler/pool/mcp/pool.py | 16 +-- apps/scheduler/scheduler/context.py | 1 - apps/scheduler/scheduler/scheduler.py | 9 +- apps/schemas/task.py | 1 + apps/services/task.py | 15 +-- nohup.out | 4 - 15 files changed, 201 insertions(+), 168 deletions(-) delete mode 100644 nohup.out diff --git a/apps/constants.py b/apps/constants.py index 58158b33..710060b3 100644 --- a/apps/constants.py +++ b/apps/constants.py @@ -11,7 +11,7 @@ from apps.common.config import Config # 新对话默认标题 NEW_CHAT = "新对话" # 滑动窗口限流 默认窗口期 -SLIDE_WINDOW_TIME = 60 +SLIDE_WINDOW_TIME = 600 # OIDC 访问Token 过期时间(分钟) OIDC_ACCESS_TOKEN_EXPIRE_TIME = 30 # OIDC 刷新Token 过期时间(分钟) diff --git a/apps/main.py b/apps/main.py index 3c869d3a..547cb681 100644 --- a/apps/main.py +++ b/apps/main.py @@ -107,6 +107,16 @@ async def add_no_auth_user() -> None: logging.warning(f"添加无认证用户失败: {e}") +async def clear_user_activity() -> None: + """清除所有用户的活跃状态""" + from apps.services.activity import Activity + from apps.common.mongo import MongoDB + mongo = MongoDB() + activity_collection = mongo.get_collection("activity") + await activity_collection.delete_many({}) + logging.info("清除所有用户活跃状态完成") + + async def init_resources() -> None: """初始化必要资源""" WordsCheck() @@ -115,7 +125,7 @@ async def init_resources() -> None: TokenCalculator() if Config().get_config().no_auth.enable: await add_no_auth_user() - + await clear_user_activity() # 运行 if __name__ == "__main__": # 初始化必要资源 diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 5a5a7593..9a45c2d5 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -16,7 +16,7 @@ from apps.dependency import get_session, get_user from apps.schemas.enum_var import FlowStatus from apps.scheduler.scheduler import Scheduler from apps.scheduler.scheduler.context import save_data -from apps.schemas.request_data import RequestData +from apps.schemas.request_data import RequestData, RequestDataApp from apps.schemas.response_data import ResponseData from apps.schemas.task import Task from apps.services.activity import Activity @@ -59,7 +59,12 @@ async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> T if not post_body.task_id: err = "[Chat] task_id 不可为空!" raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="task_id cannot be empty") - task = await TaskManager.get_task_by_conversation_id(post_body.task_id) + task = await TaskManager.get_task_by_task_id(post_body.task_id) + post_body.app = RequestDataApp(appId=task.state.app_id) + post_body.group_id = task.ids.group_id + post_body.conversation_id = task.ids.conversation_id + post_body.language = task.language + post_body.question = task.runtime.question return task @@ -138,7 +143,7 @@ async def chat( ) -> StreamingResponse: """LLM流式对话接口""" # 问题黑名单检测 - if not await QuestionBlacklistManager.check_blacklisted_questions(input_question=post_body.question): + if post_body.question is not None and not await QuestionBlacklistManager.check_blacklisted_questions(input_question=post_body.question): # 用户扣分 await UserBlacklistManager.change_blacklisted_users(user_sub, -10) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="question is blacklisted") diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index b313d555..632cf9e3 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -1,10 +1,12 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP Agent执行器""" +import anyio import logging import uuid from pydantic import Field from typing import Any +from mcp.types import TextContent from apps.llm.patterns.rewrite import QuestionRewrite from apps.llm.reasoning import ReasoningLLM from apps.scheduler.executor.base import BaseExecutor @@ -23,6 +25,7 @@ from apps.schemas.mcp import ( MCPCollection, MCPTool ) +from apps.scheduler.pool.mcp.pool import MCPPool from apps.schemas.task import ExecutorState, FlowStepHistory, StepQueueItem from apps.schemas.message import param from apps.services.task import TaskManager @@ -40,9 +43,7 @@ class MCPAgentExecutor(BaseExecutor): agent_id: str = Field(default="", description="Agent ID") agent_description: str = Field(default="", description="Agent描述") mcp_list: list[MCPCollection] = Field(description="MCP服务器列表", default=[]) - mcp_client: dict[str, MCPClient] = Field( - description="MCP客户端列表,key为mcp_id", default={} - ) + mcp_pool: MCPPool = Field(description="MCP池", default=MCPPool()) tools: dict[str, MCPTool] = Field( description="MCP工具列表,key为tool_id", default={} ) @@ -84,7 +85,7 @@ class MCPAgentExecutor(BaseExecutor): continue self.mcp_list.append(mcp_service) - self.mcp_client[mcp_id] = await MCPHost.get_client(self.task.ids.user_sub, mcp_id) + await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) for tool in mcp_service.tools: self.tools[tool.id] = tool @@ -95,7 +96,7 @@ class MCPAgentExecutor(BaseExecutor): error_message = "初始化计划" tools = await MCPSelector.select_top_tool( self.task.runtime.question, list(self.tools.values()), - additional_info=error_message, top_n=40) + additional_info=error_message, top_n=40, reasoning_llm=self.resoning_llm) if is_replan: logger.info("[MCPAgentExecutor] 重新规划流程") if not start_index: @@ -103,7 +104,8 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.error_message, self.task.runtime.temporary_plans, self.resoning_llm) - current_plan = self.task.runtime.temporary_plans.plans[start_index:] + start_index = start_index.start_index + current_plan = MCPPlan(plans=self.task.runtime.temporary_plans.plans[start_index:]) error_message = self.task.state.error_message temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, is_replan=is_replan, @@ -113,7 +115,7 @@ class MCPAgentExecutor(BaseExecutor): max_steps=self.max_steps-start_index-1, reasoning_llm=self.resoning_llm ) - self.update_tokens() + await self.update_tokens() await self.push_message( EventType.STEP_CANCEL, data={} @@ -134,7 +136,9 @@ class MCPAgentExecutor(BaseExecutor): async def get_tool_input_param(self, is_first: bool) -> None: if is_first: # 获取第一个输入参数 - self.task.state.current_input = await MCPHost._get_first_input_params(self.tools[self.task.state.step_id], self.task.runtime.question, self.task) + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] + self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, self.task.runtime.question, self.task) else: # 获取后续输入参数 if isinstance(self.params, param): @@ -143,7 +147,9 @@ class MCPAgentExecutor(BaseExecutor): else: params = {} params_description = "" - self.task.state.current_input = await MCPHost._fill_params(self.tools[self.task.state.step_id], self.task.state.current_input, self.task.state.error_message, params, params_description) + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] + self.task.state.current_input = await MCPHost._fill_params(mcp_tool, self.task.state.current_input, self.task.state.error_message, params, params_description) async def reset_step_to_index(self, start_index: int) -> None: """重置步骤到开始""" @@ -153,9 +159,9 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.flow_status = FlowStatus.RUNNING self.task.state.step_id = self.task.runtime.temporary_plans.plans[start_index].step_id self.task.state.step_index = 0 - self.task.state.step_name = self.task.runtime.temporary_plans.plans[start_index].tool + self.task.state.step_name = self.tools[self.task.runtime.temporary_plans.plans[start_index].tool].name self.task.state.step_description = self.task.runtime.temporary_plans.plans[start_index].content - self.task.state.step_status = StepStatus.RUNNING + self.task.state.step_status = StepStatus.INIT self.task.state.retry_times = 0 else: self.task.state.step_id = FINAL_TOOL_ID @@ -163,8 +169,10 @@ class MCPAgentExecutor(BaseExecutor): async def confirm_before_step(self) -> None: logger.info("[MCPAgentExecutor] 等待用户确认步骤 %d", self.task.state.step_index) # 发送确认消息 - confirm_message = await MCPPlanner.get_tool_risk(self.tools[self.task.state.step_id], self.task.state.current_input, "", self.resoning_llm) - self.update_tokens() + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] + confirm_message = await MCPPlanner.get_tool_risk(mcp_tool, self.task.state.current_input, "", self.resoning_llm) + await self.update_tokens() await self.push_message(EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( exclude_none=True, by_alias=True)) await self.push_message(EventType.FLOW_STOP, {}) @@ -192,55 +200,77 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.step_status = StepStatus.RUNNING logger.info("[MCPAgentExecutor] 执行步骤 %d", self.task.state.step_index) # 获取MCP客户端 - mcp_tool = self.tools[self.task.state.step_id] - mcp_client = self.mcp_client[mcp_tool.mcp_id] - if not mcp_client: - logger.error("[MCPAgentExecutor] MCP客户端未找到: %s", mcp_tool.mcp_id) - self.task.state.flow_status = FlowStatus.ERROR - error = "[MCPAgentExecutor] MCP客户端未找到: {}".format(mcp_tool.mcp_id) - self.task.state.error_message = error + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] + mcp_client = (await self.mcp_pool.get(mcp_tool.mcp_id, self.task.ids.user_sub)) try: output_params = await mcp_client.call_tool(mcp_tool.name, self.task.state.current_input) - self.update_tokens() - await self.push_message( - EventType.STEP_INPUT, - self.task.state.current_input - ) - await self.push_message( - EventType.STEP_OUTPUT, - output_params - ) - self.task.context.append( - FlowStepHistory( - task_id=self.task.id, - step_id=self.task.state.step_id, - step_name=self.task.state.step_name, - step_description=self.task.state.step_description, - step_status=StepStatus.SUCCESS, - flow_id=self.task.state.flow_id, - flow_name=self.task.state.flow_name, - flow_status=self.task.state.flow_status, - input_data=self.task.state.current_input, - output_data=output_params, - ) - ) - self.task.state.step_status = StepStatus.SUCCESS + except anyio.ClosedResourceError as e: + import traceback + logger.error("[MCPAgentExecutor] MCP客户端连接已关闭: %s, 错误: %s", mcp_tool.mcp_id, traceback.format_exc()) + await self.mcp_pool.stop(mcp_tool.mcp_id, self.task.ids.user_sub) + await self.mcp_pool._init_mcp(mcp_tool.mcp_id, self.task.ids.user_sub) + logger.error("[MCPAgentExecutor] MCP客户端连接已关闭: %s, 错误: %s", mcp_tool.mcp_id, str(e)) + self.task.state.step_status = StepStatus.ERROR + return except Exception as e: - logger.warning("[MCPAgentExecutor] 执行步骤 %s 失败: %s", mcp_tool.name, str(e)) import traceback - self.task.state.error_message = traceback.format_exc() + logger.exception("[MCPAgentExecutor] 执行步骤 %s 时发生错误: %s", mcp_tool.name, traceback.format_exc()) self.task.state.step_status = StepStatus.ERROR + self.task.state.error_message = str(e) + return + if output_params.isError: + err = "" + for output in output_params.content: + if isinstance(output, TextContent): + err += output.text + self.task.state.step_status = StepStatus.ERROR + self.task.state.error_message = err + return + message = "" + for output in output_params.content: + if isinstance(output, TextContent): + message += output.text + output_params = { + "message": message, + } + + await self.update_tokens() + await self.push_message( + EventType.STEP_INPUT, + self.task.state.current_input + ) + await self.push_message( + EventType.STEP_OUTPUT, + output_params + ) + self.task.context.append( + FlowStepHistory( + task_id=self.task.id, + step_id=self.task.state.step_id, + step_name=self.task.state.step_name, + step_description=self.task.state.step_description, + step_status=StepStatus.SUCCESS, + flow_id=self.task.state.flow_id, + flow_name=self.task.state.flow_name, + flow_status=self.task.state.flow_status, + input_data=self.task.state.current_input, + output_data=output_params, + ) + ) + self.task.state.step_status = StepStatus.SUCCESS async def generate_params_with_null(self) -> None: """生成参数补充""" - mcp_tool = self.tools[self.task.state.step_id] + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] params_with_null = await MCPPlanner.get_missing_param( mcp_tool, self.task.state.current_input, self.task.state.error_message, self.resoning_llm ) - self.update_tokens() + await self.update_tokens() await self.push_message( EventType.STEP_WAITING_FOR_PARAM, data={ @@ -275,25 +305,16 @@ class MCPAgentExecutor(BaseExecutor): async def get_next_step(self) -> None: self.task.state.step_index += 1 - if self.task.state.step_index < len(self.task.runtime.temporary_plans): - if self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id == FINAL_TOOL_ID: - # 最后一步 - self.task.state.flow_status = FlowStatus.SUCCESS - self.task.state.step_status = StepStatus.SUCCESS - await self.push_message( - EventType.FLOW_SUCCESS, - data={} - ) + if self.task.state.step_index < len(self.task.runtime.temporary_plans.plans): + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + if tool_id == FINAL_TOOL_ID: return self.task.state.step_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id - self.task.state.step_name = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + self.task.state.step_name = self.tools[self.task.runtime.temporary_plans.plans + [self.task.state.step_index].tool].name self.task.state.step_description = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content self.task.state.step_status = StepStatus.INIT self.task.state.current_input = {} - await self.push_message( - EventType.STEP_INIT, - data={} - ) else: # 没有下一步了,结束流程 self.task.state.step_id = FINAL_TOOL_ID @@ -327,6 +348,10 @@ class MCPAgentExecutor(BaseExecutor): async def work(self) -> None: """执行当前步骤""" if self.task.state.step_status == StepStatus.INIT: + await self.push_message( + EventType.STEP_INIT, + data={} + ) await self.get_tool_input_param(is_first=True) user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) if not user_info.auto_execute: @@ -335,11 +360,11 @@ class MCPAgentExecutor(BaseExecutor): return self.task.state.step_status = StepStatus.RUNNING elif self.task.state.step_status in [StepStatus.PARAM, StepStatus.WAITING, StepStatus.RUNNING]: - if self.task.context[-1].step_status == StepStatus.PARAM: + if self.task.state.step_status == StepStatus.PARAM: if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: del self.task.context[-1] elif self.task.state.step_status == StepStatus.WAITING: - if self.params.content: + if self.params: if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: del self.task.context[-1] else: @@ -370,7 +395,8 @@ class MCPAgentExecutor(BaseExecutor): await self.error_handle_after_step() else: user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) - mcp_tool = self.tools[self.task.state.step_id] + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + mcp_tool = self.tools[tool_id] error_type = await MCPPlanner.get_tool_execute_error_type( self.task.runtime.question, self.task.runtime.temporary_plans, @@ -403,8 +429,8 @@ class MCPAgentExecutor(BaseExecutor): async def run(self) -> None: """执行MCP Agent的主逻辑""" # 初始化MCP服务 - self.load_state() - self.load_mcp() + await self.load_state() + await self.load_mcp() if self.task.state.flow_status == FlowStatus.INIT: # 初始化状态 try: @@ -441,11 +467,14 @@ class MCPAgentExecutor(BaseExecutor): try: while len(self.task.runtime.temporary_plans.plans) and \ self.task.state.step_index < len(self.task.runtime.temporary_plans.plans) and \ - self.task.state.step_id != FINAL_TOOL_ID and \ self.task.state.flow_status == FlowStatus.RUNNING: + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + if tool_id == FINAL_TOOL_ID: + break await self.work() await TaskManager.save_task(self.task.id, self.task) - if self.task.state.step_id == FINAL_TOOL_ID: + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + if tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 self.task.state.flow_status = FlowStatus.SUCCESS self.task.state.step_status = StepStatus.SUCCESS @@ -455,6 +484,8 @@ class MCPAgentExecutor(BaseExecutor): ) await self.summarize() except Exception as e: + import traceback + logger.error("[MCPAgentExecutor] 执行过程中发生错误: %s", traceback.format_exc()) logger.error("[MCPAgentExecutor] 执行过程中发生错误: %s", str(e)) self.task.state.flow_status = FlowStatus.ERROR self.task.state.error_message = str(e) @@ -484,5 +515,9 @@ class MCPAgentExecutor(BaseExecutor): ) ) finally: - for client in self.mcp_client.values(): - await client.stop() + for mcp_service in self.mcp_list: + try: + await self.mcp_pool.stop(mcp_service.id, self.task.ids.user_sub) + except Exception as e: + import traceback + logger.error("[MCPAgentExecutor] 停止MCP客户端时发生错误: %s", traceback.format_exc()) diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index ced175ef..2701477c 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -33,25 +33,6 @@ _env = SandboxedEnvironment( class MCPHost: """MCP宿主服务""" - @staticmethod - async def get_client(user_sub, mcp_id: str) -> MCPClient | None: - """获取MCP客户端""" - mongo = MongoDB() - mcp_collection = mongo.get_collection("mcp") - - # 检查用户是否启用了这个mcp - mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": user_sub}) - if not mcp_db_result: - logger.warning("用户 %s 未启用MCP %s", user_sub, mcp_id) - return None - - # 获取MCP配置 - try: - return await MCPPool().get(mcp_id, user_sub) - except KeyError: - logger.warning("用户 %s 的MCP %s 没有运行中的实例,请检查环境", user_sub, mcp_id) - return None - @staticmethod async def assemble_memory(task: Task) -> str: """组装记忆""" @@ -104,32 +85,3 @@ class MCPHost: mcp_tool.input_schema, ) return await json_generator.generate() - - async def call_tool(user_sub: str, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: - """调用工具""" - # 拿到Client - client = await MCPPool().get(tool.mcp_id, user_sub) - if client is None: - err = f"[MCPHost] MCP Server不合法: {tool.mcp_id}" - logger.error(err) - raise ValueError(err) - - # 填充参数 - params = await MCPHost._fill_params(tool, plan_item.instruction) - # 调用工具 - result = await client.call_tool(tool.name, params) - # 保存记忆 - processed_result = [] - for item in result.content: - if not isinstance(item, TextContent): - logger.error("MCP结果类型不支持: %s", item) - continue - result = item.text - try: - json_result = json.loads(result) - except Exception as e: - logger.error("MCP结果解析失败: %s, 错误: %s", result, e) - continue - processed_result.append(json_result) - - return processed_result diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 2d68dd59..977dfda1 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -63,7 +63,7 @@ class MCPPlanner: result, [ {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": result}, + {"role": "user", "content": "请提取下面内容中的json\n\n"+result}, ], schema, ) @@ -123,7 +123,7 @@ class MCPPlanner: async def get_replan_start_step_index( user_goal: str, error_message: str, current_plan: MCPPlan | None = None, history: str = "", - reasoning_llm: ReasoningLLM = ReasoningLLM()) -> MCPPlan: + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> RestartStepIndex: """获取重新规划的步骤索引""" # 获取推理结果 template = _env.from_string(GET_REPLAN_START_STEP_INDEX) @@ -301,7 +301,7 @@ class MCPPlanner: async for chunk in resoning_llm.call( [{"role": "user", "content": prompt}], - streaming=False, + streaming=True, temperature=0.07, ): yield chunk diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 01d5dbf9..139e8e37 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -69,6 +69,7 @@ TOOL_SELECT = dedent(r""" 1. 确保充分理解当前目标,选择实现目标所需的MCP工具。 2. 请在给定的MCP工具列表中选择,不要自己生成MCP工具。 3. 可以选择一些辅助工具,但必须确保这些工具与当前目标相关。 + 4. 注意,返回的工具ID必须是MCP工具的ID,而不是名称。 必须按照以下格式生成选择结果,不要输出任何其他内容: ```json { @@ -503,7 +504,7 @@ RISK_EVALUATE = dedent(r""" ```json { "risk": "low/medium/high", - "message": "提示信息" + "reason": "提示信息" } ``` # 样例 @@ -530,7 +531,7 @@ RISK_EVALUATE = dedent(r""" ```json { "risk": "中", - "message": "当前工具将连接到MySQL数据库并分析性能,可能会对数据库性能产生一定影响。请确保在非生产环境中执行此操作。" + "reason": "当前工具将连接到MySQL数据库并分析性能,可能会对数据库性能产生一定影响。请确保在非生产环境中执行此操作。" } ``` # 工具 diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 67411a3a..0ae54dca 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -5,8 +5,9 @@ import logging import random from jinja2 import BaseLoader from jinja2.sandbox import SandboxedEnvironment -from typing import AsyncGenerator +from typing import AsyncGenerator, Any +from apps.llm.function import JsonGenerator from apps.llm.reasoning import ReasoningLLM from apps.common.lance import LanceDB from apps.common.mongo import MongoDB @@ -38,14 +39,47 @@ SUMMARIZE_TOOL_ID = "SUMMARIZE" class MCPSelector: """MCP选择器""" + @staticmethod + async def get_resoning_result(prompt: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: + """获取推理结果""" + # 调用推理大模型 + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, + ] + result = "" + async for chunk in resoning_llm.call( + message, + streaming=False, + temperature=0.07, + result_only=True, + ): + result += chunk + + return result + + @staticmethod + async def _parse_result(result: str, schema: dict[str, Any]) -> str: + """解析推理结果""" + json_generator = JsonGenerator( + result, + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "请提取下面内容中的json\n\n"+result}, + ], + schema, + ) + json_result = await json_generator.generate() + return json_result @staticmethod async def select_top_tool( goal: str, tool_list: list[MCPTool], - additional_info: str | None = None, top_n: int | None = None) -> list[MCPTool]: + additional_info: str | None = None, top_n: int | None = None, + reasoning_llm: ReasoningLLM | None = None) -> list[MCPTool]: """选择最合适的工具""" random.shuffle(tool_list) - max_tokens = Config().get_config().function_call.max_tokens + max_tokens = reasoning_llm._config.max_tokens template = _env.from_string(TOOL_SELECT) token_calculator = TokenCalculator() if token_calculator.calculate_token_length( @@ -55,7 +89,6 @@ class MCPSelector: pure_text=True) > max_tokens: logger.warning("[MCPSelector] 工具选择模板长度超过最大令牌数,无法进行选择") return [] - llm = FunctionLLM() current_index = 0 tool_ids = [] while current_index < len(tool_list): @@ -83,13 +116,13 @@ class MCPSelector: index += 1 current_index = index if sub_tools: - message = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": template.render(tools=sub_tools)}, - ] schema = MCPToolIdsSelectResult.model_json_schema() - schema["properties"]["tool_ids"]["enum"] = [tool.id for tool in sub_tools] - result = await llm.call(messages=message, schema=schema) + if "items" not in schema["properties"]["tool_ids"]: + schema["properties"]["tool_ids"]["items"] = {} + # 将enum添加到items中,限制数组元素的可选值 + schema["properties"]["tool_ids"]["items"]["enum"] = [tool.id for tool in sub_tools] + result = await MCPSelector.get_resoning_result(template.render(goal=goal, tools=sub_tools, additional_info="请根据目标选择对应的工具"), reasoning_llm) + result = await MCPSelector._parse_result(result, schema) try: result = MCPToolIdsSelectResult.model_validate(result) tool_ids.extend(result.tool_ids) diff --git a/apps/scheduler/pool/mcp/client.py b/apps/scheduler/pool/mcp/client.py index f2fd4400..0ced05e8 100644 --- a/apps/scheduler/pool/mcp/client.py +++ b/apps/scheduler/pool/mcp/client.py @@ -55,9 +55,10 @@ class MCPClient: """ # 创建Client if isinstance(config, MCPServerSSEConfig): + env = config.env or {} client = sse_client( url=config.url, - headers=config.env, + headers=env, ) elif isinstance(config, MCPServerStdioConfig): if user_sub: @@ -93,9 +94,9 @@ class MCPClient: self.ready_sign.set() self.status = MCPStatus.RUNNING - # 等待关闭信号 await self.stop_sign.wait() + logger.error("[MCPClient] MCP %s:收到停止信号,正在关闭", mcp_id) # 关闭Client try: @@ -147,5 +148,5 @@ class MCPClient: self.stop_sign.set() try: await self.task - except Exception: - logger.exception("[MCPClient] MCP %s:停止失败", self.mcp_id) + except Exception as e: + logger.warning("[MCPClient] MCP %s:停止时发生异常:%s", self.mcp_id, e) diff --git a/apps/scheduler/pool/mcp/pool.py b/apps/scheduler/pool/mcp/pool.py index 91cde4d9..bf0320f4 100644 --- a/apps/scheduler/pool/mcp/pool.py +++ b/apps/scheduler/pool/mcp/pool.py @@ -21,16 +21,13 @@ class MCPPool(metaclass=SingletonMeta): """初始化MCP池""" self.pool = {} - async def _init_mcp(self, mcp_id: str, user_sub: str) -> MCPClient | None: """初始化MCP池""" - mcp_math = MCP_USER_PATH / user_sub / mcp_id / "project" config_path = MCP_USER_PATH / user_sub / mcp_id / "config.json" - - if not await mcp_math.exists() or not await mcp_math.is_dir(): - logger.warning("[MCPPool] 用户 %s 的MCP %s 未激活", user_sub, mcp_id) + flag = (await config_path.exists()) + if not flag: + logger.warning("[MCPPool] 用户 %s 的MCP %s 配置文件不存在", user_sub, mcp_id) return None - config = MCPServerConfig.model_validate_json(await config_path.read_text()) if config.type in (MCPType.SSE, MCPType.STDIO): @@ -40,9 +37,11 @@ class MCPPool(metaclass=SingletonMeta): return None await client.init(user_sub, mcp_id, config.config) + if user_sub not in self.pool: + self.pool[user_sub] = {} + self.pool[user_sub][mcp_id] = client return client - async def _get_from_dict(self, mcp_id: str, user_sub: str) -> MCPClient | None: """从字典中获取MCP客户端""" if user_sub not in self.pool: @@ -53,7 +52,6 @@ class MCPPool(metaclass=SingletonMeta): return self.pool[user_sub][mcp_id] - async def _validate_user(self, mcp_id: str, user_sub: str) -> bool: """验证用户是否已激活""" mongo = MongoDB() @@ -61,7 +59,6 @@ class MCPPool(metaclass=SingletonMeta): mcp_db_result = await mcp_collection.find_one({"_id": mcp_id, "activated": user_sub}) return mcp_db_result is not None - async def get(self, mcp_id: str, user_sub: str) -> MCPClient | None: """获取MCP客户端""" item = await self._get_from_dict(mcp_id, user_sub) @@ -83,7 +80,6 @@ class MCPPool(metaclass=SingletonMeta): return item - async def stop(self, mcp_id: str, user_sub: str) -> None: """停止MCP客户端""" await self.pool[user_sub][mcp_id].stop() diff --git a/apps/scheduler/scheduler/context.py b/apps/scheduler/scheduler/context.py index dc35d4bd..6e737314 100644 --- a/apps/scheduler/scheduler/context.py +++ b/apps/scheduler/scheduler/context.py @@ -217,7 +217,6 @@ async def save_data(task: Task, user_sub: str, post_body: RequestData) -> None: if post_body.app and post_body.app.app_id: # 更新最近使用的应用 await AppCenterManager.update_recent_app(user_sub, post_body.app.app_id) - # 若状态为成功,删除Task if not task.state or task.state.flow_status == StepStatus.SUCCESS or task.state.flow_status == StepStatus.ERROR or task.state.flow_status == StepStatus.CANCELLED: await TaskManager.delete_task_by_task_id(task.id) diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index 7731dd85..a5e14b7f 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -126,7 +126,12 @@ class Scheduler: # 创建用于通信的事件 kill_event = asyncio.Event() monitor = asyncio.create_task(self._monitor_activity(kill_event, self.task.ids.user_sub)) - if not self.post_body.app or self.post_body.app.app_id == "": + rag_method = True + if self.post_body.app and self.post_body.app.app_id: + rag_method = False + if self.task.state.app_id: + rag_method = False + if rag_method: llm = await self.get_llm_use_in_chat_with_rag() kb_ids = await self.get_kb_ids_use_in_chat_with_rag() self.task = await push_init_message(self.task, self.queue, 3, is_flow=False) @@ -232,7 +237,7 @@ class Scheduler: max_tokens=llm.max_tokens, ) ) - if background.conversation: + if background.conversation and self.task.state.flow_status == FlowStatus.INIT: try: question_obj = QuestionRewrite() post_body.question = await question_obj.generate(history=background.conversation, question=post_body.question, llm=reasion_llm) diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 336bfedc..197f439d 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -98,6 +98,7 @@ class Task(BaseModel): state: ExecutorState = Field(description="Flow的状态", default=ExecutorState()) tokens: TaskTokens = Field(description="Token信息") runtime: TaskRuntime = Field(description="任务运行时数据") + language: str = Field(description="语言", default="zh") created_at: float = Field(default_factory=lambda: round(datetime.now(tz=UTC).timestamp(), 3)) diff --git a/apps/services/task.py b/apps/services/task.py index eec4e197..ad20f51f 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -94,19 +94,18 @@ class TaskManager: return flow_context_list @staticmethod - async def get_context_by_task_id(task_id: str, length: int = 0) -> list[FlowStepHistory]: + async def get_context_by_task_id(task_id: str, length: int | None = None) -> list[FlowStepHistory]: """根据task_id获取flow信息""" flow_context_collection = MongoDB().get_collection("flow_context") flow_context = [] try: - async for history in flow_context_collection.find( - {"task_id": task_id}, - ).sort( - "created_at", -1, - ).limit(length): - for i in range(len(flow_context)): - flow_context.append(FlowStepHistory.model_validate(history)) + if length is None: + async for context in flow_context_collection.find({"task_id": task_id}): + flow_context.append(FlowStepHistory.model_validate(context)) + else: + async for context in flow_context_collection.find({"task_id": task_id}).limit(length): + flow_context.append(FlowStepHistory.model_validate(context)) except Exception: logger.exception("[TaskManager] 获取task_id的flow信息失败") return [] diff --git a/nohup.out b/nohup.out deleted file mode 100644 index d2093b27..00000000 --- a/nohup.out +++ /dev/null @@ -1,4 +0,0 @@ -Traceback (most recent call last): - File "/home/zjq/euler-copilot-framework_1/apps/main.py", line 18, in - from apps.common.config import Config -ModuleNotFoundError: No module named 'apps' -- Gitee From bf5da6dae33a8ab8036b2c66056c79617719936f Mon Sep 17 00:00:00 2001 From: zxstty Date: Sun, 10 Aug 2025 17:53:38 +0800 Subject: [PATCH 63/78] =?UTF-8?q?=E5=AE=8C=E5=96=84Agent=E8=B0=83=E7=94=A8?= =?UTF-8?q?=EF=BC=8C=E9=99=8D=E4=BD=8E=E8=AE=A1=E5=88=92=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=97=B6=E5=BB=B6=EF=BC=8840s=3D>20s=EF=BC=89,=E9=99=8D?= =?UTF-8?q?=E4=BD=8E=E6=AF=8F=E6=AC=A1json=E7=94=9F=E6=88=90=E7=9A=84?= =?UTF-8?q?=E5=BC=80=E9=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/llm/function.py | 14 ++----- apps/routers/chat.py | 6 +-- apps/scheduler/executor/agent.py | 13 ++++-- apps/scheduler/mcp/prompt.py | 4 +- apps/scheduler/mcp_agent/base.py | 61 +++++++++++++++++++++++++++ apps/scheduler/mcp_agent/host.py | 9 +++- apps/scheduler/mcp_agent/plan.py | 52 +++++++++-------------- apps/scheduler/mcp_agent/prompt.py | 66 ++++++++++++++++++++++++++++++ apps/scheduler/mcp_agent/select.py | 35 +--------------- apps/services/activity.py | 8 ---- apps/services/task.py | 19 +++------ 11 files changed, 181 insertions(+), 106 deletions(-) create mode 100644 apps/scheduler/mcp_agent/base.py diff --git a/apps/llm/function.py b/apps/llm/function.py index 1f995fe7..6165dc45 100644 --- a/apps/llm/function.py +++ b/apps/llm/function.py @@ -68,7 +68,6 @@ class FunctionLLM: api_key=self._config.api_key, ) - async def _call_openai( self, messages: list[dict[str, str]], @@ -123,7 +122,7 @@ class FunctionLLM: }, ] - response = await self._client.chat.completions.create(**self._params) # type: ignore[arg-type] + response = await self._client.chat.completions.create(**self._params) # type: ignore[arg-type] try: logger.info("[FunctionCall] 大模型输出:%s", response.choices[0].message.tool_calls[0].function.arguments) return response.choices[0].message.tool_calls[0].function.arguments @@ -132,7 +131,6 @@ class FunctionLLM: logger.info("[FunctionCall] 大模型输出:%s", ans) return await FunctionLLM.process_response(ans) - @staticmethod async def process_response(response: str) -> str: """处理大模型的输出""" @@ -169,7 +167,6 @@ class FunctionLLM: return json_str - async def _call_ollama( self, messages: list[dict[str, str]], @@ -196,10 +193,9 @@ class FunctionLLM: "format": schema, }) - response = await self._client.chat(**self._params) # type: ignore[arg-type] + response = await self._client.chat(**self._params) # type: ignore[arg-type] return await self.process_response(response.message.content or "") - async def call( self, messages: list[dict[str, Any]], @@ -254,7 +250,6 @@ class JsonGenerator: ) self._err_info = "" - async def _assemble_message(self) -> str: """组装消息""" # 检查类型 @@ -275,13 +270,12 @@ class JsonGenerator: """单次尝试""" prompt = await self._assemble_message() messages = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": prompt}, + {"role": "system", "content": prompt}, + {"role": "user", "content": "please generate a JSON response based on the above information and schema."}, ] function = FunctionLLM() return await function.call(messages, self._schema, max_tokens, temperature) - async def generate(self) -> dict[str, Any]: """生成JSON""" Draft7Validator.check_schema(self._schema) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 9a45c2d5..68a5b4af 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -148,9 +148,9 @@ async def chat( await UserBlacklistManager.change_blacklisted_users(user_sub, -10) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="question is blacklisted") - # 限流检查 - if await Activity.is_active(user_sub): - raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests") + # # 限流检查 + # if await Activity.is_active(user_sub): + # raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests") res = chat_generator(post_body, user_sub, session_id) return StreamingResponse( diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 632cf9e3..60394bd7 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -137,8 +137,9 @@ class MCPAgentExecutor(BaseExecutor): if is_first: # 获取第一个输入参数 tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] mcp_tool = self.tools[tool_id] - self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, self.task.runtime.question, self.task) + self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, step.instruction, self.task) else: # 获取后续输入参数 if isinstance(self.params, param): @@ -271,10 +272,16 @@ class MCPAgentExecutor(BaseExecutor): self.resoning_llm ) await self.update_tokens() + error_message = MCPPlanner.change_err_message_to_description( + error_message=self.task.state.error_message, + tool=mcp_tool, + input_params=self.task.state.current_input, + reasoning_llm=self.resoning_llm + ) await self.push_message( EventType.STEP_WAITING_FOR_PARAM, data={ - "message": "当运行产生如下报错:\n" + self.task.state.error_message, + "message": error_message, "params": params_with_null } ) @@ -297,7 +304,7 @@ class MCPAgentExecutor(BaseExecutor): input_data={}, output_data={}, ex_data={ - "message": "当运行产生如下报错:\n" + self.task.state.error_message, + "message": error_message, "params": params_with_null } ) diff --git a/apps/scheduler/mcp/prompt.py b/apps/scheduler/mcp/prompt.py index b322fb08..d6ff72b4 100644 --- a/apps/scheduler/mcp/prompt.py +++ b/apps/scheduler/mcp/prompt.py @@ -233,8 +233,8 @@ FINAL_ANSWER = dedent(r""" MEMORY_TEMPLATE = dedent(r""" {% for ctx in context_list %} - 第{{ loop.index }}步:{{ ctx.step_description }} - - 调用工具 `{{ ctx.step_id }}`,并提供参数 `{{ ctx.input_data }}` + - 调用工具 `{{ ctx.step_name }}`,并提供参数 `{{ ctx.input_data|tojson }}`。 - 执行状态:{{ ctx.status }} - - 得到数据:`{{ ctx.output_data }}` + - 得到数据:`{{ ctx.output_data|tojson }}` {% endfor %} """) diff --git a/apps/scheduler/mcp_agent/base.py b/apps/scheduler/mcp_agent/base.py new file mode 100644 index 00000000..ac3829b4 --- /dev/null +++ b/apps/scheduler/mcp_agent/base.py @@ -0,0 +1,61 @@ +from typing import Any +import json +from jsonschema import validate +import logging +from apps.llm.function import JsonGenerator +from apps.llm.reasoning import ReasoningLLM + +logger = logging.getLogger(__name__) + + +class McpBase: + @staticmethod + async def get_resoning_result(prompt: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: + """获取推理结果""" + # 调用推理大模型 + message = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, + ] + result = "" + async for chunk in resoning_llm.call( + message, + streaming=False, + temperature=0.07, + result_only=True, + ): + result += chunk + + return result + + @staticmethod + async def _parse_result(result: str, schema: dict[str, Any], left_str: str = '{', right_str: str = '}') -> str: + """解析推理结果""" + left_index = result.find(left_str) + right_index = result.rfind(right_str) + flag = True + if left_str == -1 or right_str == -1: + flag = False + + if left_index > right_index: + flag = False + if flag: + try: + tmp_js = json.loads(result[left_index:right_index + 1]) + validate(instance=tmp_js, schema=schema) + except Exception as e: + logger.error("[McpBase] 解析结果失败: %s", e) + flag = False + if not flag: + json_generator = JsonGenerator( + "请提取下面内容中的json\n\n", + [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "请提取下面内容中的json\n\n"+result}, + ], + schema, + ) + json_result = await json_generator.generate() + else: + json_result = json.loads(result[left_index:right_index + 1]) + return json_result diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index 2701477c..85d992c8 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -24,12 +24,19 @@ logger = logging.getLogger(__name__) _env = SandboxedEnvironment( loader=BaseLoader, - autoescape=True, + autoescape=False, trim_blocks=True, lstrip_blocks=True, ) +def tojson_filter(value): + return json.dumps(value, ensure_ascii=False, separators=(',', ':')) + + +_env.filters['tojson'] = tojson_filter + + class MCPHost: """MCP宿主服务""" diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 977dfda1..35c44030 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -6,6 +6,7 @@ from jinja2.sandbox import SandboxedEnvironment from apps.llm.reasoning import ReasoningLLM from apps.llm.function import JsonGenerator +from apps.scheduler.mcp_agent.base import McpBase from apps.scheduler.mcp_agent.prompt import ( EVALUATE_GOAL, GENERATE_FLOW_NAME, @@ -14,6 +15,7 @@ from apps.scheduler.mcp_agent.prompt import ( RECREATE_PLAN, RISK_EVALUATE, TOOL_EXECUTE_ERROR_TYPE_ANALYSIS, + CHANGE_ERROR_MESSAGE_TO_DESCRIPTION, GET_MISSING_PARAMS, FINAL_ANSWER ) @@ -35,40 +37,8 @@ _env = SandboxedEnvironment( ) -class MCPPlanner: +class MCPPlanner(McpBase): """MCP 用户目标拆解与规划""" - @staticmethod - async def get_resoning_result(prompt: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: - """获取推理结果""" - # 调用推理大模型 - message = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": prompt}, - ] - result = "" - async for chunk in resoning_llm.call( - message, - streaming=False, - temperature=0.07, - result_only=True, - ): - result += chunk - - return result - - @staticmethod - async def _parse_result(result: str, schema: dict[str, Any]) -> str: - """解析推理结果""" - json_generator = JsonGenerator( - result, - [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "请提取下面内容中的json\n\n"+result}, - ], - schema, - ) - json_result = await json_generator.generate() - return json_result @staticmethod async def evaluate_goal( @@ -266,6 +236,22 @@ class MCPPlanner: # 返回工具执行错误类型 return error_type + @staticmethod + async def change_err_message_to_description( + error_message: str, tool: MCPTool, input_params: dict[str, Any], + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> str: + """将错误信息转换为工具描述""" + template = _env.from_string(CHANGE_ERROR_MESSAGE_TO_DESCRIPTION) + prompt = template.render( + error_message=error_message, + tool_name=tool.name, + tool_description=tool.description, + input_schema=tool.input_schema, + input_params=input_params, + ) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + return result + @staticmethod async def get_missing_param( tool: MCPTool, diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 139e8e37..365179f6 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -70,6 +70,7 @@ TOOL_SELECT = dedent(r""" 2. 请在给定的MCP工具列表中选择,不要自己生成MCP工具。 3. 可以选择一些辅助工具,但必须确保这些工具与当前目标相关。 4. 注意,返回的工具ID必须是MCP工具的ID,而不是名称。 + 5. 不要选择不存在的工具。 必须按照以下格式生成选择结果,不要输出任何其他内容: ```json { @@ -616,6 +617,71 @@ TOOL_EXECUTE_ERROR_TYPE_ANALYSIS = dedent(r""" # 输出 """ ) +# 将当前程序运行的报错转换为自然语言 +CHANGE_ERROR_MESSAGE_TO_DESCRIPTION = dedent(r""" + 你是一个智能助手,你的任务是将当前程序运行的报错转换为自然语言描述。 + 请根据以下规则进行转换: + 1. 将报错信息转换为自然语言描述,描述应该简洁明了,能够让人理解报错的原因和影响。 + 2. 描述应该包含报错的具体内容和可能的解决方案。 + 3. 描述应该避免使用过于专业的术语,以便用户能够理解。 + 4. 描述应该尽量简短,控制在50字以内。 + 5. 只输出自然语言描述,不要输出其他内容。 + # 样例 + # 工具信息 + + port_scanner + 扫描主机端口 + + { + "type": "object", + "properties": { + "host": { + "type": "string", + "description": "主机地址" + }, + "port": { + "type": "integer", + "description": "端口号" + }, + "username": { + "type": "string", + "description": "用户名" + }, + "password": { + "type": "string", + "description": "密码" + } + }, + "required": ["host", "port", "username", "password"] + } + + + # 工具入参 + { + "host": "192.0.0.1", + "port": 3306, + "username": "root", + "password": "password" + } + # 报错信息 + 执行端口扫描命令时,出现了错误:`password is not correct`。 + # 输出 + 扫描端口时发生错误:密码不正确。请检查输入的密码是否正确,并重试。 + # 现在开始转换报错信息: + # 工具信息 + + {{tool_name}} + {{tool_description}} + + {{input_schema}} + + + # 工具入参 + {{input_params}} + # 报错信息 + {{error_message}} + # 输出 + """) # 获取缺失的参数的json结构体 GET_MISSING_PARAMS = dedent(r""" 你是一个工具参数获取器。 diff --git a/apps/scheduler/mcp_agent/select.py b/apps/scheduler/mcp_agent/select.py index 0ae54dca..075e08f0 100644 --- a/apps/scheduler/mcp_agent/select.py +++ b/apps/scheduler/mcp_agent/select.py @@ -15,6 +15,7 @@ from apps.llm.embedding import Embedding from apps.llm.function import FunctionLLM from apps.llm.reasoning import ReasoningLLM from apps.llm.token import TokenCalculator +from apps.scheduler.mcp_agent.base import McpBase from apps.scheduler.mcp_agent.prompt import TOOL_SELECT from apps.schemas.mcp import ( BaseModel, @@ -37,40 +38,8 @@ FINAL_TOOL_ID = "FIANL" SUMMARIZE_TOOL_ID = "SUMMARIZE" -class MCPSelector: +class MCPSelector(McpBase): """MCP选择器""" - @staticmethod - async def get_resoning_result(prompt: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> str: - """获取推理结果""" - # 调用推理大模型 - message = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": prompt}, - ] - result = "" - async for chunk in resoning_llm.call( - message, - streaming=False, - temperature=0.07, - result_only=True, - ): - result += chunk - - return result - - @staticmethod - async def _parse_result(result: str, schema: dict[str, Any]) -> str: - """解析推理结果""" - json_generator = JsonGenerator( - result, - [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "请提取下面内容中的json\n\n"+result}, - ], - schema, - ) - json_result = await json_generator.generate() - return json_result @staticmethod async def select_top_tool( diff --git a/apps/services/activity.py b/apps/services/activity.py index 88142b9e..df322cc8 100644 --- a/apps/services/activity.py +++ b/apps/services/activity.py @@ -22,14 +22,6 @@ class Activity: :param user_sub: 用户实体ID :return: 判断结果,正在提问则返回True """ - time = round(datetime.now(UTC).timestamp(), 3) - - # 检查窗口内总请求数 - count = await MongoDB().get_collection("activity").count_documents( - {"timestamp": {"$gte": time - SLIDE_WINDOW_TIME, "$lte": time}}, - ) - if count >= SLIDE_WINDOW_QUESTION_COUNT: - return True # 检查用户是否正在提问 active = await MongoDB().get_collection("activity").find_one( diff --git a/apps/services/task.py b/apps/services/task.py index ad20f51f..38022f40 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -138,19 +138,12 @@ class TaskManager: """保存flow信息到flow_context""" flow_context_collection = MongoDB().get_collection("flow_context") try: - for history in flow_context: - # 查找是否存在 - current_context = await flow_context_collection.find_one({ - "task_id": task_id, - "_id": history.id, - }) - if current_context: - await flow_context_collection.update_one( - {"_id": current_context["_id"]}, - {"$set": history.model_dump(exclude_none=True, by_alias=True)}, - ) - else: - await flow_context_collection.insert_one(history.model_dump(exclude_none=True, by_alias=True)) + # 删除旧的flow_context + await flow_context_collection.delete_many({"task_id": task_id}) + await flow_context_collection.insert_many( + [history.model_dump(exclude_none=True, by_alias=True) for history in flow_context], + ordered=False, + ) except Exception: logger.exception("[TaskManager] 保存flow执行记录失败") -- Gitee From c6c0c5f6b342eeb028ae632e6eefeff7fb559e0e Mon Sep 17 00:00:00 2001 From: zxstty Date: Sun, 10 Aug 2025 18:09:14 +0800 Subject: [PATCH 64/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=B7=BB=E5=8A=A0=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/main.py b/apps/main.py index 547cb681..99b7de0c 100644 --- a/apps/main.py +++ b/apps/main.py @@ -39,7 +39,7 @@ from apps.routers import ( parameter ) from apps.scheduler.pool.pool import Pool - +logger = logging.getLogger(__name__) # 定义FastAPI app app = FastAPI(redoc_url=None) # 定义FastAPI全局中间件 @@ -104,7 +104,7 @@ async def add_no_auth_user() -> None: auto_execute=False ).model_dump(by_alias=True)) except Exception as e: - logging.warning(f"添加无认证用户失败: {e}") + logger.error(f"[add_no_auth_user] 默认用户 {username} 已存在") async def clear_user_activity() -> None: -- Gitee From 964a0e98938dbbfb394c4e179959d98a9d2a703d Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 11 Aug 2025 19:20:14 +0800 Subject: [PATCH 65/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=8D=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=8F=82=E6=95=B0=E7=9A=84bug&=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=99=90=E6=B5=81=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/constants.py | 2 +- apps/routers/chat.py | 26 ++++++++--------- apps/routers/record.py | 1 + apps/routers/user.py | 8 +++--- apps/scheduler/executor/agent.py | 3 +- apps/scheduler/mcp_agent/host.py | 2 ++ apps/scheduler/mcp_agent/prompt.py | 11 +++++-- apps/scheduler/scheduler/scheduler.py | 8 +++--- apps/schemas/enum_var.py | 2 +- apps/schemas/record.py | 1 + apps/schemas/task.py | 1 + apps/services/activity.py | 41 ++++++++++++++------------- apps/services/task.py | 2 ++ openapi.json | 1 - 14 files changed, 61 insertions(+), 48 deletions(-) delete mode 100644 openapi.json diff --git a/apps/constants.py b/apps/constants.py index 710060b3..20cb79b5 100644 --- a/apps/constants.py +++ b/apps/constants.py @@ -11,7 +11,7 @@ from apps.common.config import Config # 新对话默认标题 NEW_CHAT = "新对话" # 滑动窗口限流 默认窗口期 -SLIDE_WINDOW_TIME = 600 +SLIDE_WINDOW_TIME = 15 # OIDC 访问Token 过期时间(分钟) OIDC_ACCESS_TOKEN_EXPIRE_TIME = 30 # OIDC 刷新Token 过期时间(分钟) diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 68a5b4af..75b82921 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -7,7 +7,7 @@ import uuid from collections.abc import AsyncGenerator from typing import Annotated -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, Query from fastapi.responses import JSONResponse, StreamingResponse from apps.common.queue import MessageQueue @@ -71,24 +71,23 @@ async def init_task(post_body: RequestData, user_sub: str, session_id: str) -> T async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) -> AsyncGenerator[str, None]: """进行实际问答,并从MQ中获取消息""" try: - await Activity.set_active(user_sub) + active_id = await Activity.set_active(user_sub) # 敏感词检查 if await WordsCheck().check(post_body.question) != 1: yield "data: [SENSITIVE]\n\n" logger.info("[Chat] 问题包含敏感词!") - await Activity.remove_active(user_sub) + await Activity.remove_active(active_id) return task = await init_task(post_body, user_sub, session_id) - + task.ids.active_id = active_id # 创建queue;由Scheduler进行关闭 queue = MessageQueue() await queue.init() # 在单独Task中运行Scheduler,拉齐queue.get的时机 scheduler = Scheduler(task, queue, post_body) - logger.info(f"[Chat] 用户是否活跃: {await Activity.is_active(user_sub)}") scheduler_task = asyncio.create_task(scheduler.run()) # 处理每一条消息 @@ -105,14 +104,14 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) if task.state.flow_status == FlowStatus.ERROR: logger.error("[Chat] 生成答案失败") yield "data: [ERROR]\n\n" - await Activity.remove_active(user_sub) + await Activity.remove_active(active_id) return # 对结果进行敏感词检查 if await WordsCheck().check(task.runtime.answer) != 1: yield "data: [SENSITIVE]\n\n" logger.info("[Chat] 答案包含敏感词!") - await Activity.remove_active(user_sub) + await Activity.remove_active(active_id) return # 创建新Record,存入数据库 @@ -132,7 +131,7 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) yield "data: [ERROR]\n\n" finally: - await Activity.remove_active(user_sub) + await Activity.remove_active(active_id) @router.post("/chat") @@ -148,10 +147,6 @@ async def chat( await UserBlacklistManager.change_blacklisted_users(user_sub, -10) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="question is blacklisted") - # # 限流检查 - # if await Activity.is_active(user_sub): - # raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Too many requests") - res = chat_generator(post_body, user_sub, session_id) return StreamingResponse( content=res, @@ -163,9 +158,12 @@ async def chat( @router.post("/stop", response_model=ResponseData) -async def stop_generation(user_sub: Annotated[str, Depends(get_user)]): # noqa: ANN201 +async def stop_generation(user_sub: Annotated[str, Depends(get_user)], + task_id: Annotated[str, Query(..., alias="taskId")] = "") -> JSONResponse: """停止生成""" - await Activity.remove_active(user_sub) + task = await TaskManager.get_task_by_task_id(task_id) + if task: + await Activity.remove_active(task.activity_id) return JSONResponse( status_code=status.HTTP_200_OK, content=ResponseData( diff --git a/apps/routers/record.py b/apps/routers/record.py index 8d0105ff..ed994f6f 100644 --- a/apps/routers/record.py +++ b/apps/routers/record.py @@ -100,6 +100,7 @@ async def get_record(conversation_id: str, user_sub: Annotated[str, Depends(get_ stepStatus=flow_step.step_status, input=flow_step.input_data, output=flow_step.output_data, + exData=flow_step.ex_data ), ) diff --git a/apps/routers/user.py b/apps/routers/user.py index 0a2995dd..3bc1e06c 100644 --- a/apps/routers/user.py +++ b/apps/routers/user.py @@ -59,10 +59,10 @@ async def update_user_info( result = await UserManager.update_userinfo_by_user_sub(user_sub, data) if not result: return JSONResponse( - status_code=status.HTTP_200_OK, - content={"code": status.HTTP_200_OK, "message": "用户信息更新成功"}, + status_code=status.HTTP_404_NOT_FOUND, + content={"code": status.HTTP_404_NOT_FOUND, "message": "用户信息更新失败"}, ) return JSONResponse( - status_code=status.HTTP_404_NOT_FOUND, - content={"code": status.HTTP_404_NOT_FOUND, "message": "用户信息更新失败"}, + status_code=status.HTTP_200_OK, + content={"code": status.HTTP_200_OK, "message": "用户信息更新成功"}, ) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 60394bd7..5c5bcda2 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -150,7 +150,8 @@ class MCPAgentExecutor(BaseExecutor): params_description = "" tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool mcp_tool = self.tools[tool_id] - self.task.state.current_input = await MCPHost._fill_params(mcp_tool, self.task.state.current_input, self.task.state.error_message, params, params_description) + step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] + self.task.state.current_input = await MCPHost._fill_params(mcp_tool, step.instruction, self.task.state.current_input, self.task.state.error_message, params, params_description) async def reset_step_to_index(self, start_index: int) -> None: """重置步骤到开始""" diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index 85d992c8..e414e17f 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -69,12 +69,14 @@ class MCPHost: return await json_generator.generate() async def _fill_params(mcp_tool: MCPTool, + goal: str, current_input: dict[str, Any], error_message: str = "", params: dict[str, Any] = {}, params_description: str = "") -> dict[str, Any]: llm_query = "请生成修复之后的工具参数" prompt = _env.from_string(REPAIR_PARAMS).render( tool_name=mcp_tool.name, + gaol=goal, tool_description=mcp_tool.description, input_schema=mcp_tool.input_schema, current_input=current_input, diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 365179f6..469ad2f2 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -768,14 +768,19 @@ GET_MISSING_PARAMS = dedent(r""" ) REPAIR_PARAMS = dedent(r""" 你是一个工具参数修复器。 - 你的任务是根据当前的工具信息、工具入参的schema、工具当前的入参、工具的报错、补充的参数和补充的参数描述,修复当前工具的入参。 - + 你的任务是根据当前的工具信息、目标、工具入参的schema、工具当前的入参、工具的报错、补充的参数和补充的参数描述,修复当前工具的入参。 + + 注意: + 1.最终修复的参数要符合目标和工具入参的schema。 + # 样例 # 工具信息 mysql_analyzer 分析MySQL数据库性能 + # 目标 + 我要连接MySQL数据库,分析性能瓶颈,并调优。 # 工具入参的schema { "type": "object", @@ -829,6 +834,8 @@ REPAIR_PARAMS = dedent(r""" {{tool_name}} {{tool_description}} + # 目标 + {{goal}} # 工具入参scheme {{input_schema}} # 工具入参 diff --git a/apps/scheduler/scheduler/scheduler.py b/apps/scheduler/scheduler/scheduler.py index a5e14b7f..b524d249 100644 --- a/apps/scheduler/scheduler/scheduler.py +++ b/apps/scheduler/scheduler/scheduler.py @@ -48,16 +48,16 @@ class Scheduler: self.queue = queue self.post_body = post_body - async def _monitor_activity(self, kill_event, user_sub): + async def _monitor_activity(self, kill_event): """监控用户活动状态,不活跃时终止工作流""" try: check_interval = 0.5 # 每0.5秒检查一次 while not kill_event.is_set(): # 检查用户活动状态 - is_active = await Activity.is_active(user_sub) + is_active = await Activity.is_active(self.task.ids.active_id) if not is_active: - logger.warning("[Scheduler] 用户 %s 不活跃,终止工作流", user_sub) + logger.warning("[Scheduler] 用户 %s 不活跃,终止工作流", self.task.ids.user_sub) kill_event.set() break @@ -125,7 +125,7 @@ class Scheduler: logger.info("[Scheduler] 开始执行") # 创建用于通信的事件 kill_event = asyncio.Event() - monitor = asyncio.create_task(self._monitor_activity(kill_event, self.task.ids.user_sub)) + monitor = asyncio.create_task(self._monitor_activity(kill_event)) rag_method = True if self.post_body.app and self.post_body.app.app_id: rag_method = False diff --git a/apps/schemas/enum_var.py b/apps/schemas/enum_var.py index 3bcabd57..3ae7c425 100644 --- a/apps/schemas/enum_var.py +++ b/apps/schemas/enum_var.py @@ -49,7 +49,7 @@ class EventType(str, Enum): """事件类型""" HEARTBEAT = "heartbeat" - INIT = "init", + INIT = "init" TEXT_ADD = "text.add" GRAPH = "graph" DOCUMENT_ADD = "document.add" diff --git a/apps/schemas/record.py b/apps/schemas/record.py index dbc06b10..b6b70dd6 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -36,6 +36,7 @@ class RecordFlowStep(BaseModel): step_status: StepStatus = Field(alias="stepStatus") input: dict[str, Any] output: dict[str, Any] + ex_data: dict[str, Any] | None = Field(default=None, alias="exData") class RecordFlow(BaseModel): diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 197f439d..9b9a2543 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -62,6 +62,7 @@ class TaskIds(BaseModel): conversation_id: str = Field(description="对话ID") record_id: str = Field(description="记录ID", default_factory=lambda: str(uuid.uuid4())) user_sub: str = Field(description="用户ID") + active_id: str = Field(description="活动ID", default_factory=lambda: str(uuid.uuid4())) class TaskTokens(BaseModel): diff --git a/apps/services/activity.py b/apps/services/activity.py index df322cc8..7ba20cbb 100644 --- a/apps/services/activity.py +++ b/apps/services/activity.py @@ -12,10 +12,10 @@ logger = logging.getLogger(__name__) class Activity: - """用户活动控制,限制单用户同一时间只能提问一个问题""" + """用户活动控制,限制单用户同一时间只能有SLIDE_WINDOW_QUESTION_COUNT个请求""" @staticmethod - async def is_active(user_sub: str) -> bool: + async def is_active(active_id: str) -> bool: """ 判断当前用户是否正在提问(占用GPU资源) @@ -25,42 +25,43 @@ class Activity: # 检查用户是否正在提问 active = await MongoDB().get_collection("activity").find_one( - {"user_sub": user_sub}, + {"_id": active_id}, ) return bool(active) @staticmethod - async def set_active(user_sub: str) -> None: + async def set_active(user_sub: str) -> str: """设置用户的活跃标识""" time = round(datetime.now(UTC).timestamp(), 3) # 设置用户活跃状态 collection = MongoDB().get_collection("activity") - active = await collection.find_one({"user_sub": user_sub}) - if active: - err = "用户正在提问" + # 查看用户活跃标识是否在滑动窗口内 + + if await collection.count_documents({"user_sub": user_sub, "timestamp": {"$gt": time - SLIDE_WINDOW_TIME}}) >= SLIDE_WINDOW_QUESTION_COUNT: + err = "[Activity] 用户在滑动窗口内提问次数超过限制,请稍后再试。" raise ActivityError(err) + await collection.delete_many( + {"user_sub": user_sub, "timestamp": {"$lte": time - SLIDE_WINDOW_TIME}}, + ) + # 插入新的活跃记录 + tmp_record = { + "_id": str(uuid.uuid4()), + "user_sub": user_sub, + "timestamp": time, + } await collection.insert_one( - { - "_id": str(uuid.uuid4()), - "user_sub": user_sub, - "timestamp": time, - }, + tmp_record ) + return tmp_record["_id"] @staticmethod - async def remove_active(user_sub: str) -> None: + async def remove_active(active_id: str) -> None: """ 清除用户的活跃标识,释放GPU资源 :param user_sub: 用户实体ID """ - time = round(datetime.now(UTC).timestamp(), 3) # 清除用户当前活动标识 await MongoDB().get_collection("activity").delete_one( - {"user_sub": user_sub}, - ) - - # 清除超出窗口范围的请求记录 - await MongoDB().get_collection("activity").delete_many( - {"timestamp": {"$lte": time - SLIDE_WINDOW_TIME}}, + {"_id": active_id}, ) diff --git a/apps/services/task.py b/apps/services/task.py index 38022f40..49c9f4b0 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -140,6 +140,8 @@ class TaskManager: try: # 删除旧的flow_context await flow_context_collection.delete_many({"task_id": task_id}) + if not flow_context: + return await flow_context_collection.insert_many( [history.model_dump(exclude_none=True, by_alias=True) for history in flow_context], ordered=False, diff --git a/openapi.json b/openapi.json deleted file mode 100644 index e8ffc33b..00000000 --- a/openapi.json +++ /dev/null @@ -1 +0,0 @@ -{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/conversation":{"get":{"tags":["conversation"],"summary":"Get Conversation List","description":"获取对话列表","operationId":"get_conversation_list_api_conversation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListRsp"}}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"}}},"post":{"tags":["conversation"],"summary":"Add Conversation","description":"手动创建新对话","operationId":"add_conversation_api_conversation_post","parameters":[{"name":"appId","in":"query","required":false,"schema":{"type":"string","default":"","title":"Appid"}},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Debug"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_conversation_api_conversation_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["conversation"],"summary":"Update Conversation","description":"更新特定Conversation的数据","operationId":"update_conversation_api_conversation_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConversationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["conversation"],"summary":"Delete Conversation","description":"删除特定对话","operationId":"delete_conversation_api_conversation_delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteConversationData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/login":{"get":{"tags":["auth"],"summary":"Oidc Login","description":"OIDC login\n\n:param request: Request object\n:param code: OIDC code\n:return: HTMLResponse","operationId":"oidc_login_api_auth_login_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"get":{"tags":["auth"],"summary":"Logout","description":"用户登出EulerCopilot","operationId":"logout_api_auth_logout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}},"post":{"tags":["auth"],"summary":"Oidc Logout","description":"OIDC主动触发登出","operationId":"oidc_logout_api_auth_logout_post","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/redirect":{"get":{"tags":["auth"],"summary":"Oidc Redirect","description":"OIDC重定向URL","operationId":"oidc_redirect_api_auth_redirect_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRedirectRsp"}}}}}}},"/api/auth/user":{"get":{"tags":["auth"],"summary":"Userinfo","description":"获取用户信息","operationId":"userinfo_api_auth_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}}}}},"/api/auth/update_revision_number":{"post":{"tags":["auth"],"summary":"Update Revision Number","description":"更新用户协议信息","operationId":"update_revision_number_api_auth_update_revision_number_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUserRsp"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/auth/key":{"get":{"tags":["key"],"summary":"Check Api Key Existence","description":"检查API密钥是否存在","operationId":"check_api_key_existence_api_auth_key_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAuthKeyRsp"}}}}}},"post":{"tags":["key"],"summary":"Manage Api Key","description":"管理用户的API密钥","operationId":"manage_api_key_api_auth_key_post","parameters":[{"name":"action","in":"query","required":true,"schema":{"type":"string","title":"Action"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAuthKeyRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app":{"get":{"tags":["appcenter"],"summary":"Get Applications","description":"获取应用列表","operationId":"get_applications_api_app_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"appType","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AppType"},{"type":"null"}],"description":"应用类型","title":"Apptype"},"description":"应用类型"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Applications Api App Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Create Or Update Application","description":"创建或更新应用","operationId":"create_or_update_application_api_app_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Create Or Update Application Api App Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/recent":{"get":{"tags":["appcenter"],"summary":"Get Recently Used Applications","description":"获取最近使用的应用","operationId":"get_recently_used_applications_api_app_recent_get","parameters":[{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":10,"minimum":1,"default":5,"title":"Count"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetRecentAppListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Recently Used Applications Api App Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/app/{appId}":{"get":{"tags":["appcenter"],"summary":"Get Application","description":"获取应用详情","operationId":"get_application_api_app__appId__get","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetAppPropertyRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Application Api App Appid Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["appcenter"],"summary":"Delete Application","description":"删除应用","operationId":"delete_application_api_app__appId__delete","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BaseAppOperationRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Delete Application Api App Appid Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["appcenter"],"summary":"Publish Application","description":"发布应用","operationId":"publish_application_api_app__appId__post","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseAppOperationRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["appcenter"],"summary":"Modify Favorite Application","description":"更改应用收藏状态","operationId":"modify_favorite_application_api_app__appId__put","parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","description":"应用ID","title":"Appid"},"description":"应用ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavAppRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ModFavAppRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Modify Favorite Application Api App Appid Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service":{"get":{"tags":["service-center"],"summary":"Get Service List","description":"获取服务列表","operationId":"get_service_list_api_service_get","parameters":[{"name":"createdByMe","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我创建的","default":false,"title":"Createdbyme"},"description":"筛选我创建的"},{"name":"favorited","in":"query","required":false,"schema":{"type":"boolean","description":"筛选我收藏的","default":false,"title":"Favorited"},"description":"筛选我收藏的"},{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"每页数量","default":16,"title":"Pagesize"},"description":"每页数量"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Service List Api Service Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["service-center"],"summary":"Update Service","description":"上传并解析服务","operationId":"update_service_api_service_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest","description":"上传 YAML 文本对应数据对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/service/{serviceId}":{"get":{"tags":["service-center"],"summary":"Get Service Detail","description":"获取服务详情","operationId":"get_service_detail_api_service__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["service-center"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_service__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["service-center"],"summary":"Modify Favorite Service","description":"修改服务收藏状态","operationId":"modify_favorite_service_api_service__serviceId__put","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRequest","description":"更改收藏状态请求对象"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModFavServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/comment":{"post":{"tags":["comment"],"summary":"Add Comment","description":"给Record添加评论","operationId":"add_comment_api_comment_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCommentData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/record/{conversation_id}":{"get":{"tags":["record"],"summary":"Get Record","description":"获取某个对话的所有问答对","operationId":"get_record_api_record__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordListRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_check":{"get":{"tags":["health_check"],"summary":"Health Check","description":"健康检查接口","operationId":"health_check_health_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckRsp"}}}}}}},"/api/chat":{"post":{"tags":["chat"],"summary":"Chat","description":"LLM流式对话接口","operationId":"chat_api_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stop":{"post":{"tags":["chat"],"summary":"Stop Generation","description":"停止生成","operationId":"stop_generation_api_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/blacklist/user":{"get":{"tags":["blacklist"],"summary":"Get Blacklist User","description":"获取黑名单用户","operationId":"get_blacklist_user_api_blacklist_user_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistUserRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist User","description":"操作黑名单用户","operationId":"change_blacklist_user_api_blacklist_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/question":{"get":{"tags":["blacklist"],"summary":"Get Blacklist Question","description":"获取黑名单问题\n\n目前情况下,先直接输出问题,不做用户类型校验","operationId":"get_blacklist_question_api_blacklist_question_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Blacklist Question","description":"黑名单问题检测或操作","operationId":"change_blacklist_question_api_blacklist_question_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionBlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/complaint":{"post":{"tags":["blacklist"],"summary":"Abuse Report","description":"用户实施举报","operationId":"abuse_report_api_blacklist_complaint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blacklist/abuse":{"get":{"tags":["blacklist"],"summary":"Get Abuse Report","description":"获取待审核的问答对","operationId":"get_abuse_report_api_blacklist_abuse_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBlacklistQuestionRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["blacklist"],"summary":"Change Abuse Report","description":"对被举报问答对进行操作","operationId":"change_abuse_report_api_blacklist_abuse_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseProcessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{conversation_id}":{"post":{"tags":["document"],"summary":"Document Upload","description":"上传文档","operationId":"document_upload_api_document__conversation_id__post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_document_upload_api_document__conversation_id__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["document"],"summary":"Get Document List","description":"获取文档列表","operationId":"get_document_list_api_document__conversation_id__get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"used","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Used"}},{"name":"unused","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Unused"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDocumentRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/document/{document_id}":{"delete":{"tags":["document"],"summary":"Delete Single Document","description":"删除单个文件","operationId":"delete_single_document_api_document__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge":{"get":{"tags":["knowledge"],"summary":"List Kb","description":"获取当前用户的知识库ID","operationId":"list_kb_api_knowledge_get","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}},{"name":"kbId","in":"query","required":false,"schema":{"type":"string","title":"Kbid"}},{"name":"kbName","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kbname"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamKnowledgeRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["knowledge"],"summary":"Update Conversation Kb","description":"更新当前用户的知识库ID","operationId":"update_conversation_kb_api_knowledge_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","title":"Conversationid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKbReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/provider":{"get":{"tags":["llm"],"summary":"List Llm Provider","description":"获取大模型提供商列表","operationId":"list_llm_provider_api_llm_provider_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMProviderRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/llm":{"get":{"tags":["llm"],"summary":"List Llm","description":"获取大模型列表","operationId":"list_llm_api_llm_get","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLLMRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["llm"],"summary":"Create Llm","description":"创建或更新大模型配置","operationId":"create_llm_api_llm_put","parameters":[{"name":"llmId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLLMReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["llm"],"summary":"Delete Llm","description":"删除大模型配置","operationId":"delete_llm_api_llm_delete","parameters":[{"name":"llmId","in":"query","required":true,"schema":{"type":"string","description":"大模型ID","title":"Llmid"},"description":"大模型ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/llm/conv":{"put":{"tags":["llm"],"summary":"Update Conv Llm","description":"更新对话的知识库","operationId":"update_conv_llm_api_llm_conv_put","parameters":[{"name":"conversationId","in":"query","required":true,"schema":{"type":"string","description":"对话ID","title":"Conversationid"},"description":"对话ID"},{"name":"llmId","in":"query","required":false,"schema":{"type":"string","description":"llm ID","default":"empty","title":"Llmid"},"description":"llm ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp":{"get":{"tags":["mcp-service"],"summary":"Get Mcpservice List","description":"获取服务列表","operationId":"get_mcpservice_list_api_mcp_get","parameters":[{"name":"searchType","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SearchType","description":"搜索类型","default":"all"},"description":"搜索类型"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"搜索关键字","title":"Keyword"},"description":"搜索关键字"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"页码","default":1,"title":"Page"},"description":"页码"},{"name":"isInstall","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否已安装","title":"Isinstall"},"description":"是否已安装"},{"name":"isActive","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"是否激活","title":"Isactive"},"description":"是否激活"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceListRsp"},{"$ref":"#/components/schemas/ResponseData"}],"title":"Response Get Mcpservice List Api Mcp Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Create Or Update Mcpservice","description":"新建或更新MCP服务","operationId":"create_or_update_mcpservice_api_mcp_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}/install":{"post":{"tags":["mcp-service"],"summary":"Install Mcp Service","operationId":"install_mcp_service_api_mcp__serviceId__install_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"install","in":"query","required":false,"schema":{"type":"boolean","description":"是否安装","default":true,"title":"Install"},"description":"是否安装"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/{serviceId}":{"get":{"tags":["mcp-service"],"summary":"Get Service Detail","description":"获取MCP服务详情","operationId":"get_service_detail_api_mcp__serviceId__get","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"},{"name":"edit","in":"query","required":false,"schema":{"type":"boolean","description":"是否为编辑模式","default":false,"title":"Edit"},"description":"是否为编辑模式"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMCPServiceDetailRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["mcp-service"],"summary":"Delete Service","description":"删除服务","operationId":"delete_service_api_mcp__serviceId__delete","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["mcp-service"],"summary":"Active Or Deactivate Mcp Service","description":"激活/取消激活mcp","operationId":"active_or_deactivate_mcp_service_api_mcp__serviceId__post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/icon":{"post":{"tags":["mcp-service"],"summary":"Update Mcp Icon","description":"更新MCP服务图标","operationId":"update_mcp_icon_api_mcp_icon_post","parameters":[{"name":"serviceId","in":"path","required":true,"schema":{"type":"string","description":"服务ID","title":"Serviceid"},"description":"服务ID"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_mcp_icon_api_mcp_icon_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMCPServiceRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/flow/service":{"get":{"tags":["flow"],"summary":"Get Services","description":"获取用户可访问的节点元数据所在服务的信息","operationId":"get_services_api_flow_service_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeServiceListRsp"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}}}}}},"/api/flow":{"get":{"tags":["flow"],"summary":"Get Flow","description":"获取流拓扑结构","operationId":"get_flow_api_flow_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureGetRsp"}}}},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["flow"],"summary":"Put Flow","description":"修改流拓扑结构","operationId":"put_flow_api_flow_put","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutFlowReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructurePutRsp"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Internal Server Error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["flow"],"summary":"Delete Flow","description":"删除流拓扑结构","operationId":"delete_flow_api_flow_delete","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStructureDeleteRsp"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseData"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"get":{"tags":["user"],"summary":"Get User Sub","description":"查询所有用户接口","operationId":"get_user_sub_api_user_get","parameters":[{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","description":"每页用户数量","default":20,"title":"Page Size"},"description":"每页用户数量"},{"name":"page_cnt","in":"query","required":false,"schema":{"type":"integer","description":"当前页码","default":1,"title":"Page Cnt"},"description":"当前页码"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGetRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["user"],"summary":"Update User Info","description":"更新用户信息接口","operationId":"update_user_info_api_user_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest","description":"用户更新信息"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter":{"get":{"tags":["parameter"],"summary":"Get Parameters","description":"Get parameters for node choice.","operationId":"get_parameters_api_parameter_get","parameters":[{"name":"appId","in":"query","required":true,"schema":{"type":"string","title":"Appid"}},{"name":"flowId","in":"query","required":true,"schema":{"type":"string","title":"Flowid"}},{"name":"stepId","in":"query","required":true,"schema":{"type":"string","title":"Stepid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetParamsRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/parameter/operate":{"get":{"tags":["parameter"],"summary":"Get Operate Parameters","description":"Get parameters for node choice.","operationId":"get_operate_parameters_api_parameter_operate_get","parameters":[{"name":"ParamType","in":"query","required":true,"schema":{"type":"string","title":"Paramtype"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOperaRsp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbuseProcessRequest":{"properties":{"id":{"type":"string","title":"Id"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","is_deletion"],"title":"AbuseProcessRequest","description":"POST /api/blacklist/abuse 请求数据结构"},"AbuseRequest":{"properties":{"record_id":{"type":"string","title":"Record Id"},"reason":{"type":"string","title":"Reason"},"reason_type":{"type":"string","title":"Reason Type"}},"type":"object","required":["record_id","reason","reason_type"],"title":"AbuseRequest","description":"POST /api/blacklist/complaint 请求数据结构"},"ActiveMCPServiceRequest":{"properties":{"active":{"type":"boolean","title":"Active","description":"是否激活mcp服务"},"mcpEnv":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mcpenv","description":"MCP服务环境变量"}},"type":"object","required":["active"],"title":"ActiveMCPServiceRequest","description":"POST /api/mcp/{serviceId} 请求数据结构"},"ActiveMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ActiveMCPServiceRsp","description":"POST /api/mcp/active/{serviceId} 返回数据结构"},"AddCommentData":{"properties":{"record_id":{"type":"string","title":"Record Id"},"group_id":{"type":"string","title":"Group Id"},"comment":{"$ref":"#/components/schemas/CommentType"},"dislike_reason":{"type":"string","maxLength":200,"title":"Dislike Reason","default":""},"reason_link":{"type":"string","maxLength":200,"title":"Reason Link","default":""},"reason_description":{"type":"string","maxLength":500,"title":"Reason Description","default":""}},"type":"object","required":["record_id","group_id","comment"],"title":"AddCommentData","description":"添加评论"},"AddConversationMsg":{"properties":{"conversationId":{"type":"string","title":"Conversationid"}},"type":"object","required":["conversationId"],"title":"AddConversationMsg","description":"POST /api/conversation Result数据结构"},"AddConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AddConversationMsg"}},"type":"object","required":["code","message","result"],"title":"AddConversationRsp","description":"POST /api/conversation 返回数据结构"},"AppCenterCardItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"应用图标"},"name":{"type":"string","title":"Name","description":"应用名称"},"description":{"type":"string","title":"Description","description":"应用简介"},"author":{"type":"string","title":"Author","description":"应用作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"},"published":{"type":"boolean","title":"Published","description":"是否已发布","default":true}},"type":"object","required":["appId","appType","icon","name","description","author","favorited"],"title":"AppCenterCardItem","description":"应用中心卡片数据结构"},"AppFlowInfo":{"properties":{"id":{"type":"string","title":"Id","description":"工作流ID"},"name":{"type":"string","title":"Name","description":"工作流名称","default":""},"description":{"type":"string","title":"Description","description":"工作流简介","default":""},"debug":{"type":"boolean","title":"Debug","description":"是否经过调试","default":false}},"type":"object","required":["id"],"title":"AppFlowInfo","description":"应用工作流数据结构"},"AppLink":{"properties":{"title":{"type":"string","title":"Title","description":"链接标题"},"url":{"type":"string","pattern":"^(https|http)://.*$","title":"Url","description":"链接地址"}},"type":"object","required":["title","url"],"title":"AppLink","description":"App的相关链接"},"AppMcpServiceInfo":{"properties":{"id":{"type":"string","title":"Id","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称","default":""},"description":{"type":"string","title":"Description","description":"MCP服务简介","default":""}},"type":"object","required":["id"],"title":"AppMcpServiceInfo","description":"应用关联的MCP服务信息"},"AppPermissionData":{"properties":{"visibility":{"$ref":"#/components/schemas/PermissionType","description":"可见性(public/private/protected)","default":"private"},"authorizedUsers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Authorizedusers","description":"附加人员名单(如果可见性为部分人可见)"}},"type":"object","title":"AppPermissionData","description":"应用权限数据结构"},"AppType":{"type":"string","enum":["flow","agent"],"title":"AppType","description":"应用中心应用类型"},"AuthUserMsg":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"revision":{"type":"boolean","title":"Revision"},"is_admin":{"type":"boolean","title":"Is Admin"},"auto_execute":{"type":"boolean","title":"Auto Execute"}},"type":"object","required":["user_sub","revision","is_admin","auto_execute"],"title":"AuthUserMsg","description":"GET /api/auth/user Result数据结构"},"AuthUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/AuthUserMsg"}},"type":"object","required":["code","message","result"],"title":"AuthUserRsp","description":"GET /api/auth/user 返回数据结构"},"BaseAppOperationMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"}},"type":"object","required":["appId"],"title":"BaseAppOperationMsg","description":"基础应用操作Result数据结构"},"BaseAppOperationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseAppOperationMsg"}},"type":"object","required":["code","message","result"],"title":"BaseAppOperationRsp","description":"基础应用操作返回数据结构"},"BaseMCPServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseMCPServiceOperationMsg","description":"插件中心:MCP服务操作Result数据结构"},"BaseServiceOperationMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"}},"type":"object","required":["serviceId"],"title":"BaseServiceOperationMsg","description":"语义接口中心:基础服务操作Result数据结构"},"Blacklist":{"properties":{"_id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_audited":{"type":"boolean","title":"Is Audited","default":false},"reason_type":{"type":"string","title":"Reason Type","default":""},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"updated_at":{"type":"number","title":"Updated At"}},"type":"object","required":["question","answer"],"title":"Blacklist","description":"黑名单\n\nCollection: blacklist"},"Body_add_conversation_api_conversation_post":{"properties":{"llm_id":{"type":"string","title":"Llm Id","default":"empty"},"kb_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Kb Ids"}},"type":"object","title":"Body_add_conversation_api_conversation_post"},"Body_document_upload_api_document__conversation_id__post":{"properties":{"documents":{"items":{"type":"string","format":"binary"},"type":"array","title":"Documents"}},"type":"object","required":["documents"],"title":"Body_document_upload_api_document__conversation_id__post"},"Body_update_mcp_icon_api_mcp_icon_post":{"properties":{"icon":{"type":"string","format":"binary","title":"Icon","description":"图标文件"}},"type":"object","required":["icon"],"title":"Body_update_mcp_icon_api_mcp_icon_post"},"BoolOperate":{"type":"string","enum":["bool_equal","bool_not_equal"],"title":"BoolOperate","description":"Choice 工具支持的布尔运算符"},"CommentType":{"type":"string","enum":["liked","disliked","none"],"title":"CommentType","description":"点赞点踩类型"},"ConversationDocumentItem":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"type":"null","title":"Conversation Id"},"status":{"$ref":"#/components/schemas/DocumentStatus"}},"type":"object","required":["name","type","size","status"],"title":"ConversationDocumentItem","description":"GET /api/document/{conversation_id} Result内元素数据结构"},"ConversationDocumentMsg":{"properties":{"documents":{"items":{"$ref":"#/components/schemas/ConversationDocumentItem"},"type":"array","title":"Documents","default":[]}},"type":"object","title":"ConversationDocumentMsg","description":"GET /api/document/{conversation_id} Result数据结构"},"ConversationDocumentRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationDocumentMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationDocumentRsp","description":"GET /api/document/{conversation_id} 返回数据结构"},"ConversationListItem":{"properties":{"conversationId":{"type":"string","title":"Conversationid"},"title":{"type":"string","title":"Title"},"docCount":{"type":"integer","title":"Doccount"},"createdTime":{"type":"string","title":"Createdtime"},"appId":{"type":"string","title":"Appid"},"debug":{"type":"boolean","title":"Debug"},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"kbList":{"items":{"$ref":"#/components/schemas/KbIteam"},"type":"array","title":"Kblist","default":[]}},"type":"object","required":["conversationId","title","docCount","createdTime","appId","debug"],"title":"ConversationListItem","description":"GET /api/conversation Result数据结构"},"ConversationListMsg":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationListItem"},"type":"array","title":"Conversations"}},"type":"object","required":["conversations"],"title":"ConversationListMsg","description":"GET /api/conversation Result数据结构"},"ConversationListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListMsg"}},"type":"object","required":["code","message","result"],"title":"ConversationListRsp","description":"GET /api/conversation 返回数据结构"},"CreateAppRequest":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llm":{"type":"string","title":"Llm","description":"大模型ID","default":"empty"},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"type":"string"},"type":"array","title":"Mcpservice","description":"MCP服务id列表","default":[]},"appId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appid","description":"应用ID"}},"type":"object","required":["appType","name","description"],"title":"CreateAppRequest","description":"POST /api/app 请求数据结构"},"DeleteConversationData":{"properties":{"conversationList":{"items":{"type":"string"},"type":"array","title":"Conversationlist"}},"type":"object","required":["conversationList"],"title":"DeleteConversationData","description":"删除会话"},"DeleteMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseMCPServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteMCPServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DeleteServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/BaseServiceOperationMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"DeleteServiceRsp","description":"DELETE /api/service/{serviceId} 返回数据结构"},"DependencyItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"type":{"type":"string","title":"Type"}},"type":"object","required":["nodeId","type"],"title":"DependencyItem","description":"请求/响应中的节点依赖变量类"},"DictOperate":{"type":"string","enum":["dict_equal","dict_not_equal","dict_contains_key","dict_not_contains_key"],"title":"DictOperate","description":"Choice 工具支持的字典运算符"},"DocumentStatus":{"type":"string","enum":["used","unused","processing","failed"],"title":"DocumentStatus","description":"文档状态"},"EdgeItem":{"properties":{"edgeId":{"type":"string","title":"Edgeid"},"sourceNode":{"type":"string","title":"Sourcenode"},"targetNode":{"type":"string","title":"Targetnode"},"type":{"type":"string","title":"Type","default":"normal"},"branchId":{"type":"string","title":"Branchid"}},"type":"object","required":["edgeId","sourceNode","targetNode","branchId"],"title":"EdgeItem","description":"请求/响应中的边变量类"},"EditMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"data":{"type":"string","title":"Data","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType"}},"type":"object","required":["serviceId","name","description","overview","data","mcpType"],"title":"EditMCPServiceMsg","description":"编辑MCP服务"},"FlowItem-Input":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowItem-Output":{"properties":{"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","default":"工作流ID"},"name":{"type":"string","title":"Name","default":"工作流名称"},"description":{"type":"string","title":"Description","default":"工作流描述"},"enable":{"type":"boolean","title":"Enable","default":true},"editable":{"type":"boolean","title":"Editable","default":true},"nodes":{"items":{"$ref":"#/components/schemas/NodeItem"},"type":"array","title":"Nodes","default":[]},"edges":{"items":{"$ref":"#/components/schemas/EdgeItem"},"type":"array","title":"Edges","default":[]},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat","default":0},"connectivity":{"type":"boolean","title":"Connectivity","description":"图的开始节点和结束节点是否联通,并且除结束节点都有出边","default":false},"focusPoint":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"debug":{"type":"boolean","title":"Debug","default":false}},"type":"object","title":"FlowItem","description":"请求/响应中的流变量类"},"FlowStructureDeleteMsg":{"properties":{"flowId":{"type":"string","title":"Flowid","default":""}},"type":"object","title":"FlowStructureDeleteMsg","description":"DELETE /api/flow/ result"},"FlowStructureDeleteRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureDeleteMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureDeleteRsp","description":"DELETE /api/flow/ 返回数据结构"},"FlowStructureGetMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructureGetMsg","description":"GET /api/flow result"},"FlowStructureGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructureGetMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructureGetRsp","description":"GET /api/flow 返回数据结构"},"FlowStructurePutMsg":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Output","default":{"flowId":"工作流ID","name":"工作流名称","description":"工作流描述","enable":true,"editable":true,"nodes":[],"edges":[],"createdAt":0.0,"connectivity":false,"focusPoint":{"x":0.0,"y":0.0},"debug":false}}},"type":"object","title":"FlowStructurePutMsg","description":"PUT /api/flow result"},"FlowStructurePutRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/FlowStructurePutMsg"}},"type":"object","required":["code","message","result"],"title":"FlowStructurePutRsp","description":"PUT /api/flow 返回数据结构"},"FootNoteMetaData":{"properties":{"releatedId":{"type":"string","title":"Releatedid","description":"相关ID","default":""},"insertPosition":{"type":"integer","title":"Insertposition","description":"插入位置","default":0},"footSource":{"type":"string","title":"Footsource","description":"脚注来源","default":""},"footType":{"type":"string","title":"Foottype","description":"脚注类型","default":""}},"type":"object","title":"FootNoteMetaData","description":"Record表子项:Record的脚注元信息"},"GetAppListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalApps":{"type":"integer","title":"Totalapps","description":"总应用数"},"applications":{"items":{"$ref":"#/components/schemas/AppCenterCardItem"},"type":"array","title":"Applications","description":"应用列表"}},"type":"object","required":["currentPage","totalApps","applications"],"title":"GetAppListMsg","description":"GET /api/app Result数据结构"},"GetAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppListMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppListRsp","description":"GET /api/app 返回数据结构"},"GetAppPropertyMsg":{"properties":{"appType":{"$ref":"#/components/schemas/AppType","description":"应用类型"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","maxLength":20,"title":"Name","description":"应用名称"},"description":{"type":"string","maxLength":150,"title":"Description","description":"应用简介"},"links":{"items":{"$ref":"#/components/schemas/AppLink"},"type":"array","maxItems":5,"title":"Links","description":"相关链接","default":[]},"recommendedQuestions":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Recommendedquestions","description":"推荐问题","default":[]},"dialogRounds":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Dialogrounds","description":"对话轮次(1~10)","default":3},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMIteam"},{"type":"null"}]},"permission":{"$ref":"#/components/schemas/AppPermissionData","description":"权限配置"},"workflows":{"items":{"$ref":"#/components/schemas/AppFlowInfo"},"type":"array","title":"Workflows","description":"工作流信息列表","default":[]},"mcpService":{"items":{"$ref":"#/components/schemas/AppMcpServiceInfo"},"type":"array","title":"Mcpservice","description":"MCP服务信息列表","default":[]},"appId":{"type":"string","title":"Appid","description":"应用ID"},"published":{"type":"boolean","title":"Published","description":"是否已发布"}},"type":"object","required":["appType","name","description","appId","published"],"title":"GetAppPropertyMsg","description":"GET /api/app/{appId} Result数据结构"},"GetAppPropertyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetAppPropertyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAppPropertyRsp","description":"GET /api/app/{appId} 返回数据结构"},"GetAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/_GetAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"GetAuthKeyRsp","description":"GET /api/auth/key 返回数据结构"},"GetBlacklistQuestionMsg":{"properties":{"question_list":{"items":{"$ref":"#/components/schemas/Blacklist"},"type":"array","title":"Question List"}},"type":"object","required":["question_list"],"title":"GetBlacklistQuestionMsg","description":"GET /api/blacklist/question Result数据结构"},"GetBlacklistQuestionRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistQuestionMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistQuestionRsp","description":"GET /api/blacklist/question 返回数据结构"},"GetBlacklistUserMsg":{"properties":{"user_subs":{"items":{"type":"string"},"type":"array","title":"User Subs"}},"type":"object","required":["user_subs"],"title":"GetBlacklistUserMsg","description":"GET /api/blacklist/user Result数据结构"},"GetBlacklistUserRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetBlacklistUserMsg"}},"type":"object","required":["code","message","result"],"title":"GetBlacklistUserRsp","description":"GET /api/blacklist/user 返回数据结构"},"GetMCPServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"icon":{"type":"string","title":"Icon","description":"图标","default":""},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"tools":{"items":{"$ref":"#/components/schemas/MCPTool"},"type":"array","title":"Tools","description":"MCP服务Tools列表","default":[]}},"type":"object","required":["serviceId","name","description","overview"],"title":"GetMCPServiceDetailMsg","description":"GET /api/mcp_service/{serviceId} Result数据结构"},"GetMCPServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"anyOf":[{"$ref":"#/components/schemas/GetMCPServiceDetailMsg"},{"$ref":"#/components/schemas/EditMCPServiceMsg"}],"title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetMCPServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"services":{"items":{"$ref":"#/components/schemas/MCPServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","services"],"title":"GetMCPServiceListMsg","description":"GET /api/service Result数据结构"},"GetMCPServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetMCPServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetMCPServiceListRsp","description":"GET /api/service 返回数据结构"},"GetOperaRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/OperateAndBindType"},"type":"array","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetOperaRsp","description":"GET /api/operate 返回数据结构"},"GetParamsRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/StepParams"},"type":"array","title":"Result","description":"参数列表","default":[]}},"type":"object","required":["code","message"],"title":"GetParamsRsp","description":"GET /api/params 返回数据结构"},"GetRecentAppListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecentAppList"}},"type":"object","required":["code","message","result"],"title":"GetRecentAppListRsp","description":"GET /api/app/recent 返回数据结构"},"GetServiceDetailMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array"},{"type":"null"}],"title":"Apis","description":"解析后的接口列表"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data","description":"YAML 内容数据对象"}},"type":"object","required":["serviceId","name"],"title":"GetServiceDetailMsg","description":"GET /api/service/{serviceId} Result数据结构"},"GetServiceDetailRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceDetailMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceDetailRsp","description":"GET /api/service/{serviceId} 返回数据结构"},"GetServiceListMsg":{"properties":{"currentPage":{"type":"integer","title":"Currentpage","description":"当前页码"},"totalCount":{"type":"integer","title":"Totalcount","description":"总服务数"},"services":{"items":{"$ref":"#/components/schemas/ServiceCardItem"},"type":"array","title":"Services","description":"解析后的服务列表"}},"type":"object","required":["currentPage","totalCount","services"],"title":"GetServiceListMsg","description":"GET /api/service Result数据结构"},"GetServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/GetServiceListMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"GetServiceListRsp","description":"GET /api/service 返回数据结构"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthCheckRsp":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HealthCheckRsp","description":"GET /health_check 返回数据结构"},"KbIteam":{"properties":{"kbId":{"type":"string","title":"Kbid"},"kbName":{"type":"string","title":"Kbname"}},"type":"object","required":["kbId","kbName"],"title":"KbIteam","description":"GET /api/conversation Result数据结构"},"KnowledgeBaseItem":{"properties":{"kbId":{"type":"string","title":"Kbid","description":"知识库ID"},"kbName":{"type":"string","title":"Kbname","description":"知识库名称"},"description":{"type":"string","title":"Description","description":"知识库描述"},"isUsed":{"type":"boolean","title":"Isused","description":"是否使用"}},"type":"object","required":["kbId","kbName","description","isUsed"],"title":"KnowledgeBaseItem","description":"知识库列表项数据结构"},"LLMIteam":{"properties":{"icon":{"type":"string","title":"Icon","default":"data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIGZpbGwtcnVsZT0iZXZlbm9kZCIgaGVpZ2h0PSIxZW0iIHN0eWxlPSJmbGV4Om5vbmU7bGluZS1oZWlnaHQ6MSIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMWVtIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5PbGxhbWE8L3RpdGxlPjxwYXRoIGQ9Ik03LjkwNSAxLjA5Yy4yMTYuMDg1LjQxMS4yMjUuNTg4LjQxLjI5NS4zMDYuNTQ0Ljc0NC43MzQgMS4yNjMuMTkxLjUyMi4zMTUgMS4xLjM2MiAxLjY4YTUuMDU0IDUuMDU0IDAgMDEyLjA0OS0uNjM2bC4wNTEtLjAwNGMuODctLjA3IDEuNzMuMDg3IDIuNDguNDc0LjEwMS4wNTMuMi4xMS4yOTcuMTcuMDUtLjU2OS4xNzItMS4xMzQuMzYtMS42NDQuMTktLjUyLjQzOS0uOTU3LjczMy0xLjI2NGExLjY3IDEuNjcgMCAwMS41ODktLjQxYy4yNTctLjEuNTMtLjExOC43OTYtLjA0Mi40MDEuMTE0Ljc0NS4zNjggMS4wMTYuNzM3LjI0OC4zMzcuNDM0Ljc2OS41NjEgMS4yODcuMjMuOTM0LjI3IDIuMTYzLjExNSAzLjY0NWwuMDUzLjA0LjAyNi4wMTljLjc1Ny41NzYgMS4yODQgMS4zOTcgMS41NjMgMi4zNS40MzUgMS40ODcuMjE2IDMuMTU1LS41MzQgNC4wODhsLS4wMTguMDIxLjAwMi4wMDNjLjQxNy43NjIuNjcgMS41NjcuNzI0IDIuNGwuMDAyLjAzYy4wNjQgMS4wNjUtLjIgMi4xMzctLjgxNCAzLjE5bC0uMDA3LjAxLjAxLjAyNGMuNDcyIDEuMTU3LjYyIDIuMzIyLjQzOCAzLjQ4NmwtLjAwNi4wMzlhLjY1MS42NTEgMCAwMS0uNzQ3LjUzNi42NDguNjQ4IDAgMDEtLjU0LS43NDJjLjE2Ny0xLjAzMy4wMS0yLjA2OS0uNDgtMy4xMjNhLjY0My42NDMgMCAwMS4wNC0uNjE3bC4wMDQtLjAwNmMuNjA0LS45MjQuODU0LTEuODMuOC0yLjcyLS4wNDYtLjc3OS0uMzI1LTEuNTQ0LS44LTIuMjczYS42NDQuNjQ0IDAgMDEuMTgtLjg4NmwuMDA5LS4wMDZjLjI0My0uMTU5LjQ2Ny0uNTY1LjU4LTEuMTJhNC4yMjkgNC4yMjkgMCAwMC0uMDk1LTEuOTc0Yy0uMjA1LS43LS41OC0xLjI4NC0xLjEwNS0xLjY4My0uNTk1LS40NTQtMS4zODMtLjY3My0yLjM4LS42MWEuNjUzLjY1MyAwIDAxLS42MzItLjM3MWMtLjMxNC0uNjY1LS43NzItMS4xNDEtMS4zNDMtMS40MzZhMy4yODggMy4yODggMCAwMC0xLjc3Mi0uMzMyYy0xLjI0NS4wOTktMi4zNDMuODAxLTIuNjcgMS42ODZhLjY1Mi42NTIgMCAwMS0uNjEuNDI1Yy0xLjA2Ny4wMDItMS44OTMuMjUyLTIuNDk3LjcwMy0uNTIyLjM5LS44NzguOTM1LTEuMDY2IDEuNTg4YTQuMDcgNC4wNyAwIDAwLS4wNjggMS44ODZjLjExMi41NTguMzMxIDEuMDIuNTgyIDEuMjY5bC4wMDguMDA3Yy4yMTIuMjA3LjI1Ny41My4xMDkuNzg1LS4zNi42MjItLjYyOSAxLjU0OS0uNjczIDIuNDQtLjA1IDEuMDE4LjE4NiAxLjkwMi43MTkgMi41MzZsLjAxNi4wMTlhLjY0My42NDMgMCAwMS4wOTUuNjljLS41NzYgMS4yMzYtLjc1MyAyLjI1Mi0uNTYyIDMuMDUyYS42NTIuNjUyIDAgMDEtMS4yNjkuMjk4Yy0uMjQzLTEuMDE4LS4wNzgtMi4xODQuNDczLTMuNDk4bC4wMTQtLjAzNS0uMDA4LS4wMTJhNC4zMzkgNC4zMzkgMCAwMS0uNTk4LTEuMzA5bC0uMDA1LS4wMTlhNS43NjQgNS43NjQgMCAwMS0uMTc3LTEuNzg1Yy4wNDQtLjkxLjI3OC0xLjg0Mi42MjItMi41OWwuMDEyLS4wMjYtLjAwMi0uMDAyYy0uMjkzLS40MTgtLjUxLS45NTMtLjYzLTEuNTQ1bC0uMDA1LS4wMjRhNS4zNTIgNS4zNTIgMCAwMS4wOTMtMi40OWMuMjYyLS45MTUuNzc3LTEuNzAxIDEuNTM2LTIuMjY5LjA2LS4wNDUuMTIzLS4wOS4xODYtLjEzMi0uMTU5LTEuNDkzLS4xMTktMi43My4xMTItMy42Ny4xMjctLjUxOC4zMTQtLjk1LjU2Mi0xLjI4Ny4yNy0uMzY4LjYxNC0uNjIyIDEuMDE1LS43MzcuMjY2LS4wNzYuNTQtLjA1OS43OTcuMDQyem00LjExNiA5LjA5Yy45MzYgMCAxLjguMzEzIDIuNDQ2Ljg1NS42My41MjcgMS4wMDUgMS4yMzUgMS4wMDUgMS45NCAwIC44ODgtLjQwNiAxLjU4LTEuMTMzIDIuMDIyLS42Mi4zNzUtMS40NTEuNTU3LTIuNDAzLjU1Ny0xLjAwOSAwLTEuODcxLS4yNTktMi40OTMtLjczNC0uNjE3LS40Ny0uOTYzLTEuMTMtLjk2My0xLjg0NSAwLS43MDcuMzk4LTEuNDE3IDEuMDU2LTEuOTQ2LjY2OC0uNTM3IDEuNTUtLjg0OSAyLjQ4NS0uODQ5em0wIC44OTZhMy4wNyAzLjA3IDAgMDAtMS45MTYuNjVjLS40NjEuMzctLjcyMi44MzUtLjcyMiAxLjI1IDAgLjQyOC4yMS44MjkuNjEgMS4xMzQuNDU1LjM0NyAxLjEyNC41NDggMS45NDMuNTQ4Ljc5OSAwIDEuNDczLS4xNDcgMS45MzItLjQyNi40NjMtLjI4LjctLjY4Ni43LTEuMjU3IDAtLjQyMy0uMjQ2LS44OS0uNjgzLTEuMjU2LS40ODQtLjQwNS0xLjE0LS42NDMtMS44NjQtLjY0M3ptLjY2MiAxLjIxbC4wMDQuMDA0Yy4xMi4xNTEuMDk1LjM3LS4wNTYuNDlsLS4yOTIuMjN2LjQ0NmEuMzc1LjM3NSAwIDAxLS4zNzYuMzczLjM3NS4zNzUgMCAwMS0uMzc2LS4zNzN2LS40NmwtLjI3MS0uMjE4YS4zNDcuMzQ3IDAgMDEtLjA1Mi0uNDkuMzUzLjM1MyAwIDAxLjQ5NC0uMDUxbC4yMTUuMTcyLjIyLS4xNzRhLjM1My4zNTMgMCAwMS40OS4wNTF6bS01LjA0LTEuOTE5Yy40NzggMCAuODY3LjM5Ljg2Ny44NzFhLjg3Ljg3IDAgMDEtLjg2OC44NzEuODcuODcgMCAwMS0uODY3LS44Ny44Ny44NyAwIDAxLjg2Ny0uODcyem04LjcwNiAwYy40OCAwIC44NjguMzkuODY4Ljg3MWEuODcuODcgMCAwMS0uODY4Ljg3MS44Ny44NyAwIDAxLS44NjctLjg3Ljg3Ljg3IDAgMDEuODY3LS44NzJ6TTcuNDQgMi4zbC0uMDAzLjAwMmEuNjU5LjY1OSAwIDAwLS4yODUuMjM4bC0uMDA1LjAwNmMtLjEzOC4xODktLjI1OC40NjctLjM0OC44MzItLjE3LjY5Mi0uMjE2IDEuNjMxLS4xMjQgMi43ODIuNDMtLjEyOC44OTktLjIwOCAxLjQwNC0uMjM3bC4wMS0uMDAxLjAxOS0uMDM0Yy4wNDYtLjA4Mi4wOTUtLjE2MS4xNDgtLjIzOS4xMjMtLjc3MS4wMjItMS42OTItLjI1My0yLjQ0NC0uMTM0LS4zNjQtLjI5Ny0uNjUtLjQ1My0uODEzYS42MjguNjI4IDAgMDAtLjEwNy0uMDlMNy40NCAyLjN6bTkuMTc0LjA0bC0uMDAyLjAwMWEuNjI4LjYyOCAwIDAwLS4xMDcuMDljLS4xNTYuMTYzLS4zMi40NS0uNDUzLjgxNC0uMjkuNzk0LS4zODcgMS43NzYtLjIzIDIuNTcybC4wNTguMDk3LjAwOC4wMTRoLjAzYTUuMTg0IDUuMTg0IDAgMDExLjQ2Ni4yMTJjLjA4Ni0xLjEyNC4wMzgtMi4wNDMtLjEyOC0yLjcyMi0uMDktLjM2NS0uMjEtLjY0My0uMzQ5LS44MzJsLS4wMDQtLjAwNmEuNjU5LjY1OSAwIDAwLS4yODUtLjIzOWgtLjAwNHoiPjwvcGF0aD48L3N2Zz4="},"llmId":{"type":"string","title":"Llmid","default":"empty"},"modelName":{"type":"string","title":"Modelname","default":"qwen2.5-72b-instruct"}},"type":"object","title":"LLMIteam","description":"GET /api/conversation Result数据结构"},"LLMProvider":{"properties":{"provider":{"type":"string","title":"Provider","description":"LLM提供商"},"description":{"type":"string","title":"Description","description":"LLM提供商描述"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"LLM提供商URL"},"icon":{"type":"string","title":"Icon","description":"LLM提供商图标"}},"type":"object","required":["provider","description","icon"],"title":"LLMProvider","description":"LLM提供商数据结构"},"LLMProviderInfo":{"properties":{"llmId":{"type":"string","title":"Llmid","description":"LLM ID"},"icon":{"type":"string","maxLength":25536,"title":"Icon","description":"LLM图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":"https://api.openai.com/v1"},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称"},"maxTokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokens","description":"最大token数"},"isEditable":{"type":"boolean","title":"Iseditable","description":"是否可编辑","default":true}},"type":"object","required":["llmId","modelName"],"title":"LLMProviderInfo","description":"LLM数据结构"},"ListLLMProviderRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProvider"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMProviderRsp","description":"GET /api/llm/provider 返回数据结构"},"ListLLMRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"items":{"$ref":"#/components/schemas/LLMProviderInfo"},"type":"array","title":"Result","default":[]}},"type":"object","required":["code","message"],"title":"ListLLMRsp","description":"GET /api/llm 返回数据结构"},"ListOperate":{"type":"string","enum":["list_equal","list_not_equal","list_contains","list_not_contains","list_length_equal","list_length_greater_than","list_length_greater_than_or_equal","list_length_less_than","list_length_less_than_or_equal"],"title":"ListOperate","description":"Choice 工具支持的列表运算符"},"ListTeamKnowledgeMsg":{"properties":{"teamKbList":{"items":{"$ref":"#/components/schemas/TeamKnowledgeBaseItem"},"type":"array","title":"Teamkblist","description":"团队知识库列表","default":[]}},"type":"object","title":"ListTeamKnowledgeMsg","description":"GET /api/knowledge Result数据结构"},"ListTeamKnowledgeRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ListTeamKnowledgeMsg"}},"type":"object","required":["code","message","result"],"title":"ListTeamKnowledgeRsp","description":"GET /api/knowledge 返回数据结构"},"MCPInstallStatus":{"type":"string","enum":["init","installing","cancelled","ready","failed"],"title":"MCPInstallStatus","description":"MCP 服务状态"},"MCPServiceCardItem":{"properties":{"mcpserviceId":{"type":"string","title":"Mcpserviceid","description":"mcp服务ID"},"name":{"type":"string","title":"Name","description":"mcp服务名称"},"description":{"type":"string","title":"Description","description":"mcp服务简介"},"icon":{"type":"string","title":"Icon","description":"mcp服务图标"},"author":{"type":"string","title":"Author","description":"mcp服务作者"},"isActive":{"type":"boolean","title":"Isactive","description":"mcp服务是否激活","default":false},"status":{"$ref":"#/components/schemas/MCPInstallStatus","description":"mcp服务状态","default":"installing"}},"type":"object","required":["mcpserviceId","name","description","icon","author"],"title":"MCPServiceCardItem","description":"插件中心:MCP服务卡片数据结构"},"MCPTool":{"properties":{"id":{"type":"string","title":"Id","description":"MCP工具ID"},"name":{"type":"string","title":"Name","description":"MCP工具名称"},"description":{"type":"string","title":"Description","description":"MCP工具描述"},"mcp_id":{"type":"string","title":"Mcp Id","description":"MCP ID"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"MCP工具输入参数"}},"type":"object","required":["id","name","description","mcp_id","input_schema"],"title":"MCPTool","description":"MCP工具"},"MCPType":{"type":"string","enum":["sse","stdio","stream"],"title":"MCPType","description":"MCP 类型"},"ModFavAppMsg":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["appId","favorited"],"title":"ModFavAppMsg","description":"PUT /api/app/{appId} Result数据结构"},"ModFavAppRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavAppRequest","description":"PUT /api/app/{appId} 请求数据结构"},"ModFavAppRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavAppMsg"}},"type":"object","required":["code","message","result"],"title":"ModFavAppRsp","description":"PUT /api/app/{appId} 返回数据结构"},"ModFavServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","favorited"],"title":"ModFavServiceMsg","description":"PUT /api/service/{serviceId} Result数据结构"},"ModFavServiceRequest":{"properties":{"favorited":{"type":"boolean","title":"Favorited","description":"是否收藏"}},"type":"object","required":["favorited"],"title":"ModFavServiceRequest","description":"PUT /api/service/{serviceId} 请求数据结构"},"ModFavServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ModFavServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"ModFavServiceRsp","description":"PUT /api/service/{serviceId} 返回数据结构"},"ModifyConversationData":{"properties":{"title":{"type":"string","maxLength":2000,"minLength":1,"title":"Title"}},"type":"object","required":["title"],"title":"ModifyConversationData","description":"修改会话信息"},"NodeItem":{"properties":{"stepId":{"type":"string","title":"Stepid","default":""},"serviceId":{"type":"string","title":"Serviceid","default":""},"nodeId":{"type":"string","title":"Nodeid","default":""},"name":{"type":"string","title":"Name","default":""},"callId":{"type":"string","title":"Callid","default":"Empty"},"description":{"type":"string","title":"Description","default":""},"enable":{"type":"boolean","title":"Enable","default":true},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","default":{}},"depedency":{"anyOf":[{"$ref":"#/components/schemas/DependencyItem"},{"type":"null"}]},"position":{"$ref":"#/components/schemas/PositionItem","default":{"x":0.0,"y":0.0}},"editable":{"type":"boolean","title":"Editable","default":true}},"type":"object","title":"NodeItem","description":"请求/响应中的节点变量类"},"NodeMetaDataItem":{"properties":{"nodeId":{"type":"string","title":"Nodeid"},"callId":{"type":"string","title":"Callid"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"editable":{"type":"boolean","title":"Editable","default":true},"createdAt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Createdat"}},"type":"object","required":["nodeId","callId","name","description","parameters","createdAt"],"title":"NodeMetaDataItem","description":"节点元数据类"},"NodeServiceItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"type":{"type":"string","title":"Type","description":"服务类型"},"nodeMetaDatas":{"items":{"$ref":"#/components/schemas/NodeMetaDataItem"},"type":"array","title":"Nodemetadatas","default":[]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdat","description":"创建时间"}},"type":"object","required":["serviceId","name","type"],"title":"NodeServiceItem","description":"GET /api/flow/service 中单个service信息以及service下的节点元数据的信息"},"NodeServiceListMsg":{"properties":{"services":{"items":{"$ref":"#/components/schemas/NodeServiceItem"},"type":"array","title":"Services","description":"服务列表","default":[]}},"type":"object","title":"NodeServiceListMsg","description":"GET /api/flow/service result"},"NodeServiceListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/NodeServiceListMsg"}},"type":"object","required":["code","message","result"],"title":"NodeServiceListRsp","description":"GET /api/flow/service 返回数据结构"},"NumberOperate":{"type":"string","enum":["number_equal","number_not_equal","number_greater_than","number_less_than","number_greater_than_or_equal","number_less_than_or_equal"],"title":"NumberOperate","description":"Choice 工具支持的数字运算符"},"OidcRedirectMsg":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"OidcRedirectMsg","description":"GET /api/auth/redirect Result数据结构"},"OidcRedirectRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/OidcRedirectMsg"}},"type":"object","required":["code","message","result"],"title":"OidcRedirectRsp","description":"GET /api/auth/redirect 返回数据结构"},"OperateAndBindType":{"properties":{"operate":{"anyOf":[{"$ref":"#/components/schemas/NumberOperate"},{"$ref":"#/components/schemas/StringOperate"},{"$ref":"#/components/schemas/ListOperate"},{"$ref":"#/components/schemas/BoolOperate"},{"$ref":"#/components/schemas/DictOperate"}],"title":"Operate","description":"操作类型"},"bind_type":{"$ref":"#/components/schemas/Type","description":"绑定类型"}},"type":"object","required":["operate","bind_type"],"title":"OperateAndBindType","description":"操作和绑定类型数据结构"},"ParamsNode":{"properties":{"paramName":{"type":"string","title":"Paramname","description":"参数名称"},"paramPath":{"type":"string","title":"Parampath","description":"参数路径"},"paramType":{"$ref":"#/components/schemas/Type","description":"参数类型"},"subParams":{"anyOf":[{"items":{"$ref":"#/components/schemas/ParamsNode"},"type":"array"},{"type":"null"}],"title":"Subparams","description":"子参数列表"}},"type":"object","required":["paramName","paramPath","paramType"],"title":"ParamsNode","description":"参数数据结构"},"PermissionType":{"type":"string","enum":["protected","public","private"],"title":"PermissionType","description":"权限类型"},"PositionItem":{"properties":{"x":{"type":"number","title":"X","default":0.0},"y":{"type":"number","title":"Y","default":0.0}},"type":"object","title":"PositionItem","description":"请求/响应中的前端相对位置变量类"},"PostAuthKeyMsg":{"properties":{"api_key":{"type":"string","title":"Api Key"}},"type":"object","required":["api_key"],"title":"PostAuthKeyMsg","description":"POST /api/auth/key Result数据结构"},"PostAuthKeyRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/PostAuthKeyMsg"}},"type":"object","required":["code","message","result"],"title":"PostAuthKeyRsp","description":"POST /api/auth/key 返回数据结构"},"PutFlowReq":{"properties":{"flow":{"$ref":"#/components/schemas/FlowItem-Input"}},"type":"object","required":["flow"],"title":"PutFlowReq","description":"创建/修改流拓扑结构"},"QuestionBlacklistRequest":{"properties":{"id":{"type":"string","title":"Id"},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"is_deletion":{"type":"integer","title":"Is Deletion"}},"type":"object","required":["id","question","answer","is_deletion"],"title":"QuestionBlacklistRequest","description":"POST /api/blacklist/question 请求数据结构"},"RecentAppList":{"properties":{"applications":{"items":{"$ref":"#/components/schemas/RecentAppListItem"},"type":"array","title":"Applications","description":"最近使用的应用列表"}},"type":"object","required":["applications"],"title":"RecentAppList","description":"GET /api/app/recent Result数据结构"},"RecentAppListItem":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"name":{"type":"string","title":"Name","description":"应用名称"}},"type":"object","required":["appId","name"],"title":"RecentAppListItem","description":"GET /api/app/recent 列表项数据结构"},"RecordContent":{"properties":{"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"data":{"additionalProperties":true,"type":"object","title":"Data","default":{}},"facts":{"items":{"type":"string"},"type":"array","title":"Facts","description":"[运行后修改]与Record关联的事实信息","default":[]}},"type":"object","required":["question","answer"],"title":"RecordContent","description":"Record表子项:Record加密前的数据结构"},"RecordData":{"properties":{"id":{"type":"string","title":"Id"},"groupId":{"type":"string","title":"Groupid"},"conversationId":{"type":"string","title":"Conversationid"},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid"},"document":{"items":{"$ref":"#/components/schemas/RecordDocument"},"type":"array","title":"Document","default":[]},"flow":{"anyOf":[{"$ref":"#/components/schemas/RecordFlow"},{"type":"null"}]},"content":{"$ref":"#/components/schemas/RecordContent"},"metadata":{"$ref":"#/components/schemas/RecordMetadata"},"comment":{"$ref":"#/components/schemas/CommentType","default":"none"},"createdAt":{"type":"number","title":"Createdat"}},"type":"object","required":["id","groupId","conversationId","content","metadata","createdAt"],"title":"RecordData","description":"GET /api/record/{conversation_id} Result内元素数据结构"},"RecordDocument":{"properties":{"_id":{"type":"string","title":"Id","default":""},"user_sub":{"type":"null","title":"User Sub"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"size":{"type":"number","title":"Size"},"created_at":{"type":"number","title":"Created At"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"order":{"type":"integer","title":"Order","description":"文档顺序","default":0},"abstract":{"type":"string","title":"Abstract","description":"文档摘要","default":""},"author":{"type":"string","title":"Author","description":"文档作者","default":""},"associated":{"type":"string","enum":["question","answer"],"title":"Associated"}},"type":"object","required":["name","type","size","associated"],"title":"RecordDocument","description":"GET /api/record/{conversation_id} Result中的document数据结构"},"RecordFlow":{"properties":{"id":{"type":"string","title":"Id"},"recordId":{"type":"string","title":"Recordid"},"flowId":{"type":"string","title":"Flowid"},"flowName":{"type":"string","title":"Flowname","default":""},"flowStatus":{"$ref":"#/components/schemas/StepStatus","default":"success"},"stepNum":{"type":"integer","title":"Stepnum"},"steps":{"items":{"$ref":"#/components/schemas/RecordFlowStep"},"type":"array","title":"Steps"}},"type":"object","required":["id","recordId","flowId","stepNum","steps"],"title":"RecordFlow","description":"Flow的执行信息"},"RecordFlowStep":{"properties":{"stepId":{"type":"string","title":"Stepid"},"stepStatus":{"$ref":"#/components/schemas/StepStatus"},"input":{"additionalProperties":true,"type":"object","title":"Input"},"output":{"additionalProperties":true,"type":"object","title":"Output"}},"type":"object","required":["stepId","stepStatus","input","output"],"title":"RecordFlowStep","description":"Record表子项:flow的单步数据结构"},"RecordListMsg":{"properties":{"records":{"items":{"$ref":"#/components/schemas/RecordData"},"type":"array","title":"Records"}},"type":"object","required":["records"],"title":"RecordListMsg","description":"GET /api/record/{conversation_id} Result数据结构"},"RecordListRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/RecordListMsg"}},"type":"object","required":["code","message","result"],"title":"RecordListRsp","description":"GET /api/record/{conversation_id} 返回数据结构"},"RecordMetadata":{"properties":{"inputTokens":{"type":"integer","title":"Inputtokens","default":0},"outputTokens":{"type":"integer","title":"Outputtokens","default":0},"timeCost":{"type":"number","title":"Timecost","default":0},"feature":{"additionalProperties":true,"type":"object","title":"Feature","default":{}},"footNoteMetadataList":{"items":{"$ref":"#/components/schemas/FootNoteMetaData"},"type":"array","title":"Footnotemetadatalist","description":"脚注元信息列表","default":[]}},"type":"object","title":"RecordMetadata","description":"Record表子项:Record的元信息"},"RequestData":{"properties":{"question":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Question","description":"用户输入"},"conversationId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversationid","description":"聊天ID"},"groupId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupid","description":"问答组ID"},"language":{"type":"string","title":"Language","description":"语言","default":"zh"},"files":{"items":{"type":"string"},"type":"array","title":"Files","description":"文件列表","default":[]},"app":{"anyOf":[{"$ref":"#/components/schemas/RequestDataApp"},{"type":"null"}],"description":"应用"},"debug":{"type":"boolean","title":"Debug","description":"是否调试","default":false},"taskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Taskid","description":"任务ID"},"params":{"anyOf":[{"$ref":"#/components/schemas/param"},{"type":"boolean"},{"type":"null"}],"title":"Params","description":"流执行过程中的参数补充"}},"type":"object","title":"RequestData","description":"POST /api/chat 请求的总的数据结构"},"RequestDataApp":{"properties":{"appId":{"type":"string","title":"Appid","description":"应用ID"},"flowId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flowid","description":"Flow ID"}},"type":"object","required":["appId"],"title":"RequestDataApp","description":"模型对话中包含的app信息"},"ResponseData":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"title":"Result"}},"type":"object","required":["code","message","result"],"title":"ResponseData","description":"基础返回数据结构"},"SearchType":{"type":"string","enum":["all","name","description","author"],"title":"SearchType","description":"搜索类型"},"ServiceApiData":{"properties":{"name":{"type":"string","title":"Name","description":"接口名称"},"path":{"type":"string","title":"Path","description":"接口路径"},"description":{"type":"string","title":"Description","description":"接口描述"}},"type":"object","required":["name","path","description"],"title":"ServiceApiData","description":"语义接口中心:服务 API 接口属性数据结构"},"ServiceCardItem":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"description":{"type":"string","title":"Description","description":"服务简介"},"icon":{"type":"string","title":"Icon","description":"服务图标"},"author":{"type":"string","title":"Author","description":"服务作者"},"favorited":{"type":"boolean","title":"Favorited","description":"是否已收藏"}},"type":"object","required":["serviceId","name","description","icon","author","favorited"],"title":"ServiceCardItem","description":"语义接口中心:服务卡片数据结构"},"StepParams":{"properties":{"stepId":{"type":"string","title":"Stepid","description":"步骤ID"},"name":{"type":"string","title":"Name","description":"Step名称"},"paramsNode":{"anyOf":[{"$ref":"#/components/schemas/ParamsNode"},{"type":"null"}],"description":"参数节点"}},"type":"object","required":["stepId","name"],"title":"StepParams","description":"参数数据结构"},"StepStatus":{"type":"string","enum":["unknown","init","waiting","running","success","error","param","cancelled"],"title":"StepStatus","description":"步骤状态"},"StringOperate":{"type":"string","enum":["string_equal","string_not_equal","string_contains","string_not_contains","string_starts_with","string_ends_with","string_length_equal","string_length_greater_than","string_length_greater_than_or_equal","string_length_less_than","string_length_less_than_or_equal","string_regex_match"],"title":"StringOperate","description":"Choice 工具支持的字符串运算符"},"TeamKnowledgeBaseItem":{"properties":{"teamId":{"type":"string","title":"Teamid","description":"团队ID"},"teamName":{"type":"string","title":"Teamname","description":"团队名称"},"kb_list":{"items":{"$ref":"#/components/schemas/KnowledgeBaseItem"},"type":"array","title":"Kb List","description":"知识库列表","default":[]}},"type":"object","required":["teamId","teamName"],"title":"TeamKnowledgeBaseItem","description":"团队知识库列表项数据结构"},"Type":{"type":"string","enum":["string","number","list","dict","bool"],"title":"Type","description":"Choice 工具支持的类型"},"UpdateConversationRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/ConversationListItem"}},"type":"object","required":["code","message","result"],"title":"UpdateConversationRsp","description":"POST /api/conversation 返回数据结构"},"UpdateKbReq":{"properties":{"kbIds":{"items":{"type":"string"},"type":"array","title":"Kbids","description":"知识库ID列表","default":[]}},"type":"object","title":"UpdateKbReq","description":"更新知识库请求体"},"UpdateLLMReq":{"properties":{"icon":{"type":"string","title":"Icon","description":"图标","default":""},"openaiBaseUrl":{"type":"string","title":"Openaibaseurl","description":"OpenAI API Base URL","default":""},"openaiApiKey":{"type":"string","title":"Openaiapikey","description":"OpenAI API Key","default":""},"modelName":{"type":"string","title":"Modelname","description":"模型名称","default":""},"maxTokens":{"type":"integer","title":"Maxtokens","description":"最大token数","default":8192}},"type":"object","title":"UpdateLLMReq","description":"更新大模型请求体"},"UpdateMCPServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"MCP服务ID"},"name":{"type":"string","title":"Name","description":"MCP服务名称"}},"type":"object","required":["serviceId","name"],"title":"UpdateMCPServiceMsg","description":"插件中心:MCP服务属性数据结构"},"UpdateMCPServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"name":{"type":"string","title":"Name","description":"MCP服务名称"},"description":{"type":"string","title":"Description","description":"MCP服务描述"},"overview":{"type":"string","title":"Overview","description":"MCP服务概述"},"config":{"additionalProperties":true,"type":"object","title":"Config","description":"MCP服务配置"},"mcpType":{"$ref":"#/components/schemas/MCPType","description":"MCP传输协议(Stdio/SSE/Streamable)","default":"stdio"}},"type":"object","required":["name","description","overview","config"],"title":"UpdateMCPServiceRequest","description":"POST /api/mcpservice 请求数据结构"},"UpdateMCPServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateMCPServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateMCPServiceRsp","description":"POST /api/mcp_service 返回数据结构"},"UpdateServiceMsg":{"properties":{"serviceId":{"type":"string","title":"Serviceid","description":"服务ID"},"name":{"type":"string","title":"Name","description":"服务名称"},"apis":{"items":{"$ref":"#/components/schemas/ServiceApiData"},"type":"array","title":"Apis","description":"解析后的接口列表"}},"type":"object","required":["serviceId","name","apis"],"title":"UpdateServiceMsg","description":"语义接口中心:服务属性数据结构"},"UpdateServiceRequest":{"properties":{"serviceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serviceid","description":"服务ID(更新时传递)"},"data":{"additionalProperties":true,"type":"object","title":"Data","description":"对应 YAML 内容的数据对象"}},"type":"object","required":["data"],"title":"UpdateServiceRequest","description":"POST /api/service 请求数据结构"},"UpdateServiceRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UpdateServiceMsg","title":"Result"}},"type":"object","required":["code","message","result"],"title":"UpdateServiceRsp","description":"POST /api/service 返回数据结构"},"UserBlacklistRequest":{"properties":{"user_sub":{"type":"string","title":"User Sub"},"is_ban":{"type":"integer","title":"Is Ban"}},"type":"object","required":["user_sub","is_ban"],"title":"UserBlacklistRequest","description":"POST /api/blacklist/user 请求数据结构"},"UserGetMsp":{"properties":{"total":{"type":"integer","title":"Total","default":0},"userInfoList":{"items":{"$ref":"#/components/schemas/UserInfo"},"type":"array","title":"Userinfolist","default":[]}},"type":"object","title":"UserGetMsp","description":"GET /api/user result"},"UserGetRsp":{"properties":{"code":{"type":"integer","title":"Code"},"message":{"type":"string","title":"Message"},"result":{"$ref":"#/components/schemas/UserGetMsp"}},"type":"object","required":["code","message","result"],"title":"UserGetRsp","description":"GET /api/user 返回数据结构"},"UserInfo":{"properties":{"userSub":{"type":"string","title":"Usersub","default":""},"userName":{"type":"string","title":"Username","default":""},"autoExecute":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Autoexecute","default":false}},"type":"object","title":"UserInfo","description":"用户信息数据结构"},"UserUpdateRequest":{"properties":{"autoExecute":{"type":"boolean","title":"Autoexecute","description":"是否自动执行","default":false}},"type":"object","title":"UserUpdateRequest","description":"更新用户信息请求体"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"_GetAuthKeyMsg":{"properties":{"api_key_exists":{"type":"boolean","title":"Api Key Exists"}},"type":"object","required":["api_key_exists"],"title":"_GetAuthKeyMsg","description":"GET /api/auth/key Result数据结构"},"param":{"properties":{"content":{"additionalProperties":true,"type":"object","title":"Content","description":"流执行过程中的参数补充内容","default":{}},"description":{"type":"string","title":"Description","description":"流执行过程中的参数补充描述","default":""}},"type":"object","title":"param","description":"流执行过程中的参数补充"}}}} \ No newline at end of file -- Gitee From ffdaf8272e146617f2d11651004e6556c3f01872 Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 11 Aug 2025 19:21:57 +0800 Subject: [PATCH 66/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=9B=B4=E6=96=B0=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/routers/user.py | 7 +------ apps/services/user.py | 5 ++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/apps/routers/user.py b/apps/routers/user.py index 3bc1e06c..537f1bf3 100644 --- a/apps/routers/user.py +++ b/apps/routers/user.py @@ -56,12 +56,7 @@ async def update_user_info( """更新用户信息接口""" # 更新用户信息 - result = await UserManager.update_userinfo_by_user_sub(user_sub, data) - if not result: - return JSONResponse( - status_code=status.HTTP_404_NOT_FOUND, - content={"code": status.HTTP_404_NOT_FOUND, "message": "用户信息更新失败"}, - ) + await UserManager.update_userinfo_by_user_sub(user_sub, data) return JSONResponse( status_code=status.HTTP_200_OK, content={"code": status.HTTP_200_OK, "message": "用户信息更新成功"}, diff --git a/apps/services/user.py b/apps/services/user.py index ef50e9e3..1b96df18 100644 --- a/apps/services/user.py +++ b/apps/services/user.py @@ -59,7 +59,7 @@ class UserManager: return User(**user_data) if user_data else None @staticmethod - async def update_userinfo_by_user_sub(user_sub: str, data: UserUpdateRequest) -> bool: + async def update_userinfo_by_user_sub(user_sub: str, data: UserUpdateRequest) -> None: """ 根据用户sub更新用户信息 @@ -74,8 +74,7 @@ class UserManager: "auto_execute": data.auto_execute, } } - result = await user_collection.update_one({"_id": user_sub}, update_dict) - return result.modified_count > 0 + await user_collection.update_one({"_id": user_sub}, update_dict) @staticmethod async def update_refresh_revision_by_user_sub(user_sub: str, *, refresh_revision: bool = False) -> bool: -- Gitee From d7312fdb1826520ddc12ba55ac268044ecd87128 Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 11 Aug 2025 21:06:57 +0800 Subject: [PATCH 67/78] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmcp=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 2 +- apps/scheduler/pool/loader/mcp.py | 24 ++++++++++++------------ apps/services/mcp_service.py | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 5c5bcda2..5fbaef9e 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -273,7 +273,7 @@ class MCPAgentExecutor(BaseExecutor): self.resoning_llm ) await self.update_tokens() - error_message = MCPPlanner.change_err_message_to_description( + error_message = await MCPPlanner.change_err_message_to_description( error_message=self.task.state.error_message, tool=mcp_tool, input_params=self.task.state.current_input, diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index bf007fc8..1da06b53 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -95,7 +95,6 @@ class MCPLoader(metaclass=SingletonMeta): try: if not config.config.auto_install: print(f"[Installer] MCP模板无需安装: {mcp_id}") # noqa: T201 - elif isinstance(config.config, MCPServerStdioConfig): print(f"[Installer] Stdio方式的MCP模板,开始自动安装: {mcp_id}") # noqa: T201 if "uv" in config.config.command: @@ -388,6 +387,7 @@ class MCPLoader(metaclass=SingletonMeta): # 更新数据库 mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") + logger.info("[MCPLoader] 更新MCP模板状态: %s -> %s", mcp_id, status) await mcp_collection.update_one( {"_id": mcp_id}, {"$set": {"status": status}}, @@ -423,17 +423,6 @@ class MCPLoader(metaclass=SingletonMeta): ) if mcp_env is not None: mcp_config.config.env.update(mcp_env) - user_config_path = user_path / "config.json" - # 更新用户配置 - f = await user_config_path.open("w", encoding="utf-8", errors="ignore") - await f.write( - json.dumps( - mcp_config.model_dump(by_alias=True, exclude_none=True), - indent=4, - ensure_ascii=False, - ) - ) - await f.aclose() if mcp_config.type == MCPType.STDIO: index = None for i in range(len(mcp_config.config.args)): @@ -447,6 +436,17 @@ class MCPLoader(metaclass=SingletonMeta): mcp_config.config.args.append(str(user_path)+'/project') else: mcp_config.config.args = ["--directory", str(user_path)+'/project'] + mcp_config.config.args + user_config_path = user_path / "config.json" + # 更新用户配置 + f = await user_config_path.open("w", encoding="utf-8", errors="ignore") + await f.write( + json.dumps( + mcp_config.model_dump(by_alias=True, exclude_none=True), + indent=4, + ensure_ascii=False, + ) + ) + await f.aclose() # 更新数据库 mongo = MongoDB() mcp_collection = mongo.get_collection("mcp") diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index 434c8750..324ba70d 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -258,7 +258,7 @@ class MCPServiceManager: if index >= len(config.args): config.args.append(str(mcp_path)) else: - config.args[index+1] = str(mcp_path) + config.args[index] = str(mcp_path) else: config.args += ["--directory", str(mcp_path)] await MCPLoader._insert_template_db(mcp_id=mcp_id, config=mcp_server) -- Gitee From 524655b61eebc0b47854340af59ea8216a58c8c6 Mon Sep 17 00:00:00 2001 From: zxstty Date: Mon, 11 Aug 2025 22:37:20 +0800 Subject: [PATCH 68/78] =?UTF-8?q?=E5=AE=8C=E5=96=84agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/llm/prompt.py | 2 +- apps/routers/chat.py | 1 - apps/scheduler/executor/agent.py | 6 +++--- apps/scheduler/mcp_agent/host.py | 9 +++++---- apps/scheduler/mcp_agent/plan.py | 3 +-- apps/scheduler/mcp_agent/prompt.py | 10 +++++++--- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/llm/prompt.py b/apps/llm/prompt.py index 7cf555be..7702f6d0 100644 --- a/apps/llm/prompt.py +++ b/apps/llm/prompt.py @@ -19,7 +19,7 @@ JSON_GEN_BASIC = dedent(r""" Background information is given in XML tags. - Here are the conversations between you and the user: + Here are the background information between you and the user: {% if conversation|length > 0 %} {% for message in conversation %} diff --git a/apps/routers/chat.py b/apps/routers/chat.py index 75b82921..888fbd04 100644 --- a/apps/routers/chat.py +++ b/apps/routers/chat.py @@ -113,7 +113,6 @@ async def chat_generator(post_body: RequestData, user_sub: str, session_id: str) logger.info("[Chat] 答案包含敏感词!") await Activity.remove_active(active_id) return - # 创建新Record,存入数据库 await save_data(task, user_sub, post_body) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 5fbaef9e..b09d8f6c 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -139,7 +139,7 @@ class MCPAgentExecutor(BaseExecutor): tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] mcp_tool = self.tools[tool_id] - self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, step.instruction, self.task) + self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, self.task.runtime.question, step.instruction, self.task) else: # 获取后续输入参数 if isinstance(self.params, param): @@ -151,7 +151,7 @@ class MCPAgentExecutor(BaseExecutor): tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool mcp_tool = self.tools[tool_id] step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] - self.task.state.current_input = await MCPHost._fill_params(mcp_tool, step.instruction, self.task.state.current_input, self.task.state.error_message, params, params_description) + self.task.state.current_input = await MCPHost._fill_params(mcp_tool, self.task.runtime.question, step.instruction, self.task.state.current_input, self.task.state.error_message, params, params_description) async def reset_step_to_index(self, start_index: int) -> None: """重置步骤到开始""" @@ -415,7 +415,7 @@ class MCPAgentExecutor(BaseExecutor): ) if error_type.type == ErrorType.DECORRECT_PLAN or user_info.auto_execute: await self.plan(is_replan=True) - self.reset_step_to_index(self.task.state.step_index) + await self.reset_step_to_index(self.task.state.step_index) elif error_type.type == ErrorType.MISSING_PARAM: await self.generate_params_with_null() elif self.task.state.step_status == StepStatus.SUCCESS: diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index e414e17f..0674415c 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -48,12 +48,11 @@ class MCPHost: context_list=task.context, ) - async def _get_first_input_params(mcp_tool: MCPTool, query: str, task: Task) -> dict[str, Any]: + async def _get_first_input_params(mcp_tool: MCPTool, goal: str, query: str, task: Task) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" - 请使用参数生成工具,生成满足以下目标的工具参数: - + 请充分利用背景中的信息,生成满足以下目标的工具参数: {query} """ @@ -62,7 +61,7 @@ class MCPHost: llm_query, [ {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": await MCPHost.assemble_memory(task)}, + {"role": "user", "content": "用户的总目标是:\n"+goal+(await MCPHost.assemble_memory(task))}, ], mcp_tool.input_schema, ) @@ -70,6 +69,7 @@ class MCPHost: async def _fill_params(mcp_tool: MCPTool, goal: str, + current_goal: str, current_input: dict[str, Any], error_message: str = "", params: dict[str, Any] = {}, params_description: str = "") -> dict[str, Any]: @@ -77,6 +77,7 @@ class MCPHost: prompt = _env.from_string(REPAIR_PARAMS).render( tool_name=mcp_tool.name, gaol=goal, + current_goal=current_goal, tool_description=mcp_tool.description, input_schema=mcp_tool.input_schema, current_input=current_input, diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 35c44030..1243abcf 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -31,7 +31,7 @@ from apps.scheduler.slot.slot import Slot _env = SandboxedEnvironment( loader=BaseLoader, - autoescape=True, + autoescape=False, trim_blocks=True, lstrip_blocks=True, ) @@ -284,7 +284,6 @@ class MCPPlanner(McpBase): memory=memory, goal=user_goal, ) - async for chunk in resoning_llm.call( [{"role": "user", "content": prompt}], streaming=True, diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 469ad2f2..77374f4c 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -779,7 +779,9 @@ REPAIR_PARAMS = dedent(r""" mysql_analyzer 分析MySQL数据库性能 - # 目标 + # 总目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 当前阶段目标 我要连接MySQL数据库,分析性能瓶颈,并调优。 # 工具入参的schema { @@ -834,8 +836,10 @@ REPAIR_PARAMS = dedent(r""" {{tool_name}} {{tool_description}} - # 目标 + # 总目标 {{goal}} + # 当前阶段目标 + {{current_goal}} # 工具入参scheme {{input_schema}} # 工具入参 @@ -873,7 +877,7 @@ MEMORY_TEMPLATE = dedent(r""" {% for ctx in context_list %} - 第{{loop.index}}步:{{ctx.step_description}} - 调用工具 `{{ctx.step_id}}`,并提供参数 `{{ctx.input_data}}` - - 执行状态:{{ctx.status}} + - 执行状态:{{ctx.step_status}} - 得到数据:`{{ctx.output_data}}` {% endfor %} """) -- Gitee From 3142b1c88cf4b2bf7d27cc61d8d70f97657930ac Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 10:25:00 +0800 Subject: [PATCH 69/78] =?UTF-8?q?step=E8=BF=94=E5=9B=9E=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/queue.py | 1 + apps/schemas/message.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/apps/common/queue.py b/apps/common/queue.py index 089d475e..6e82af91 100644 --- a/apps/common/queue.py +++ b/apps/common/queue.py @@ -60,6 +60,7 @@ class MessageQueue: flowStatus=task.state.flow_status, stepId=task.state.step_id, stepName=task.state.step_name, + stepDescription=task.state.step_description, stepStatus=task.state.step_status ) else: diff --git a/apps/schemas/message.py b/apps/schemas/message.py index c55fc6d1..5b465ee5 100644 --- a/apps/schemas/message.py +++ b/apps/schemas/message.py @@ -34,6 +34,11 @@ class MessageFlow(BaseModel): step_name: str = Field(description="当前步骤名称", alias="stepName") sub_step_id: str | None = Field(description="当前子步骤ID", alias="subStepId", default=None) sub_step_name: str | None = Field(description="当前子步骤名称", alias="subStepName", default=None) + step_description: str | None = Field( + description="当前步骤描述", + alias="stepDescription", + default=None, + ) step_status: StepStatus = Field(description="当前步骤状态", alias="stepStatus") -- Gitee From ebe0d4f7a0225be3d209558881b68268fc8aad8e Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 10:41:03 +0800 Subject: [PATCH 70/78] =?UTF-8?q?flow=E5=BC=80=E5=A7=8B=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E5=80=99=E8=BF=94=E5=9B=9E=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 16 +++++++++++++++- apps/scheduler/executor/base.py | 7 +------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index b09d8f6c..a7c0b1ce 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -459,9 +459,23 @@ class MCPAgentExecutor(BaseExecutor): ) return self.task.state.flow_status = FlowStatus.RUNNING + plan = { + "plans": [] + } + for p in self.task.runtime.temporary_plans.plans: + if p.tool == FINAL_TOOL_ID: + continue + mcp_tool = self.tools.get(p.tool, None) + plan["plans"].append( + { + "stepId": p.step_id, + "stepName": mcp_tool.name, + "stepDescription": p.content + } + ) await self.push_message( EventType.FLOW_START, - data={} + data=plan ) if self.task.state.step_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 diff --git a/apps/scheduler/executor/base.py b/apps/scheduler/executor/base.py index 8dcb99c7..877341f0 100644 --- a/apps/scheduler/executor/base.py +++ b/apps/scheduler/executor/base.py @@ -44,12 +44,7 @@ class BaseExecutor(BaseModel, ABC): :param event_type: 事件类型 :param data: 消息数据,如果是FLOW_START事件且data为None,则自动构建FlowStartContent """ - if event_type == EventType.FLOW_START.value and isinstance(data, dict): - data = FlowStartContent( - question=self.question, - params=self.task.runtime.filled, - ).model_dump(exclude_none=True, by_alias=True) - elif event_type == EventType.TEXT_ADD.value and isinstance(data, str): + if event_type == EventType.TEXT_ADD.value and isinstance(data, str): data = TextAddContent(text=data).model_dump(exclude_none=True, by_alias=True) if data is None: -- Gitee From c66e25290b6be0082752651b977bd1a17d4695e4 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 16:18:55 +0800 Subject: [PATCH 71/78] =?UTF-8?q?=E5=AE=8C=E5=96=84prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 2 +- apps/scheduler/mcp_agent/host.py | 6 +++++- apps/scheduler/mcp_agent/plan.py | 1 + apps/scheduler/mcp_agent/prompt.py | 6 ++++-- perf.data | Bin 0 -> 32600 bytes 5 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 perf.data diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index a7c0b1ce..55a817e6 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -393,7 +393,7 @@ class MCPAgentExecutor(BaseExecutor): max_retry = 5 for i in range(max_retry): if i != 0: - await self.get_tool_input_param(is_first=False) + await self.get_tool_input_param(is_first=True) await self.run_step() if self.task.state.step_status == StepStatus.SUCCESS: break diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index 0674415c..a244d8a9 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -52,8 +52,12 @@ class MCPHost: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" - 请充分利用背景中的信息,生成满足以下目标的工具参数: + 你是一个MCP工具参数生成器,你的任务是根据用户的目标和查询,生成MCP工具的输入参数。 + 请充分利用背景中的信息,生成满足以下目标的工具参数: {query} + 注意: + 1. 你需要根据工具的输入schema来生成参数。 + 2. 如果工具的输入schema中有枚举类型的字段,请确保生成的参数符合这些枚举值。 """ # 进行生成 diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 1243abcf..245ed654 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -131,6 +131,7 @@ class MCPPlanner(McpBase): max_steps: int = 10, reasoning_llm: ReasoningLLM = ReasoningLLM()) -> str: """获取推理大模型的结果""" # 格式化Prompt + tool_ids = [tool.id for tool in tool_list] if is_replan: template = _env.from_string(RECREATE_PLAN) prompt = template.render( diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 77374f4c..e91fb0a5 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -263,7 +263,8 @@ CREATE_PLAN = dedent(r""" 1. 能够成功完成用户的目标 2. 计划中的每一个步骤必须且只能使用一个工具。 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 - 4. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + 4. 不要选择不存在的工具。 + 5. 计划中的最后一步必须是Final工具,以确保计划执行结束。 # 生成计划时的注意事项: @@ -361,7 +362,8 @@ RECREATE_PLAN = dedent(r""" 2. 计划中的每一个步骤必须且只能使用一个工具。 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 4. 你的计划必须避免之前的错误,并且能够成功执行。 - 5. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + 5. 不要选择不存在的工具。 + 6. 计划中的最后一步必须是Final工具,以确保计划执行结束。 # 生成计划时的注意事项: diff --git a/perf.data b/perf.data new file mode 100644 index 0000000000000000000000000000000000000000..f319e212c75a402bbf0ff2e488552bad93ff5b8b GIT binary patch literal 32600 zcmc&-33wd!bsu7`1VV)4CWLUvt+_4l?9Q>Xr3vx{HrOD{rC?xoPHF5t#(T&TIAl%S zlmyeN;WEWg1(M*_6hvYuZ3tBpYA7Gcrxa6MAfQknP#iEv2`TQEzW=%Qe{&R)4{d18>l*QkBm;ky7e84`A+s6m(;}7iP5A7p?ub>F)ee5%MahR>w!S?Uw+32R;q}_}S|O)p7Oj^unc_&cc%@j4 zX^XROj%5rvmd&f>j8=?si{jiOx+fk_^bBY@tzalIgo~*KV@N9$V{#_1tdHrLylIXs zTAz0#;&}kK`*_6d^WHm4+^hAhj3Um+uOXvQGV-FFSs!XM(ItT2)g1*su^)a!xA}h4t?K~K$8G$|Cq4Ji zlIH_v8FDR4eu(LXMIK>r5y0&|-M0G^o?B;$J7}me_#v3n;kx2Iwh(c9J+M@BxK6pL z8}4AddwURnyd}GhoLMeG{VNx>m|3)r;W`BTPSH{D4eDC9oGBSlV+ILu+3QUw-Y&mS z+PM3@ch1u9gy(ja!D+b376969QdZkRKADWS5_i(tz>iW;n1m7ri+C=3=>+0g45-;W zOMA1LYDlqy0{?nQeG7wj+3UjZWm<`|QW!Byd1yAJ^;$v}?N*hbhqRqUfq?zvHhydI zM*9^_!Rihtbv%Ih*Vp3R#kCS|r{6GSs9HXz%c?eHw=c3-94U%=-YkY{640a49z8$_ zBRe2xtQ-i5NkEVNwjQnZX9E5JJ#-_JDQHS~HU{)C`L@Ib^icBVh*Z#|#^N$z>oMW< zm@!9ZnV+t9Ph6iZii29l#LmaGdbsj*^i1?eYjuLOgXN-JI}j&Wogg%;`i}8%^}ELY z1o6|=Tdb2=`T^R5f@G*Pfwk1|N^|Ois~&fKsTEwiJ`LwB8v%DlyzwaTELf|z5sv5b ztNG*)8s};MYf-)Ez z7Wi1z0np&~m`VnE8=*P`@F#8j3em3iYLL%<{NkV#?#Qs8>0Y#dqJ~Y* z8pLFrj-`ft#qp=@<`GIi>#tNu*d_!EbC9MNDL{C<$MV$SF>awRf#l&9+9yYg>rCE7nlJX3o$ zh)??Yq#@(+T|@=|eoYdd1^hmGUiA5w)w0U8^HnbX?YHsMUQHXcJDmTPCq(Gm<%dF( z0HDwhE*12Khk7*@ij9l1U}#-e)UAfS7Pj74$AKDGxmDGmGPm|VY|0q?Rr|lYU#s5ybQB;aX3?}UiMH2_5oSK0K zjC>}lgQAovhtClakE1@W{)}ns)7x}Bg8s1DQLz>p(8nv?(Zl7JiI((e#4pg?G?%Z9_@$sq^&NwJan-Hvt8M-^)!%~#n536@zc&7cx(_Ktd)(No-K)4 zqiA{CURv@>bMnGv_kJ6PA?c?A*Y-@mlZ1$u+K^Z$dpL znu-(Y@0Kz}@@DuKet~trdP$^?=P~ zB@y-rSgjRI&v>nJ{OxM5CbzX}KOovuLc=91DWO8t$;uG?@!JufZYtgm?{FPD2M0sy zu{Rz0O}DNwFI|4`x}z2Qt98+yFHp=f?mqH^Bd*Ku6&ts?ehP_q&F?uK&S76+{cUE! zdf2@k?e1!NJnhDxW<-ac2-x2{){5W#_7mcjVO1b(i90;*qb=hP>!g1GZ!m%!$P>l` z{)};_zk_y16L%}&VAECO`8H|e_j)y*MZK%V9r9gL)k0~+th*5@kZ;|0qy1w|yh@VJPSYg<}W;YSj!P!$#@mW|0!FKv8Kkw{``mZ&*e%5NwG>GOgQ;< z2;h%?ztwnn@?h5ZQ#O7SbpZ0P1TBwh&83oVPd)ox?Ox?xw12|usaf!#WRnbUg!Xm=xKl0TTK5CAbI<%I2a5l^QgEcoJXUMQZj*qt(GK{RIdCbW6gR7r6rJx>B zFBWaLE!CN>yvJ{?;z@M>)d`U*}n5=>$rkiaZ1|KTLZ@u z-^!*gnuYv;D9Nm>uv~(Xle)&sto?WX!(8hF)aUklx~ZM#J-+75uf4v@f1iW*#^X|C zcy~8|clh~gWO(MPVdP&={I!b&1yEBFr}Ain>;SRLz?xJSf)Idze!1#&yZQlYM$~ z2}RWzT1_NnCCTV1QOl7%LcqIXK2t7f=oV1lat|aX%=*BHYed{=fV(nUPRy4ByOAA# znbZ~E!hK;E`FR}|1YJnPHA$fvLEt%frVm;@5&}hn4NKyBZA8=y`K%u|#76RwoBx-7 zbv{MCdeU#Mx%E?r`EPgpJoYyFotCS@ar4f%8v!-{JAARYJMymK)Idf$BSEVeYBJO z_zLjjp@-(Y@z6VuAst*KarklECve^JU4Q+c<)oToR3@R*2~}m`@m!~UfkjG9%$r)y zC9Zmka?{lQi*Ic!Kkj=9*LkDn$H9;Mt)=(6ll=Lj#}g?=;**KE#Bd57ar?4tXXp8G zIq+lm+=)M)@cDjD-Iu_RjI?0bK zfFE6xhl~QkDpIRuOUeABVS3g)mSK_?D$h6LJitO)yD1$I-<`)Xr4nL0T zJ=q$EwX1$~YbZZzer(;0ay!kBV}63To#e-rz>n8{{y%3v|K_}<{!lvgqw*T+#r=Vg zAG|K{QbJ~QRi@*TmJ)~bB0MrFsY9YRY=n%|5W(Tc)?;zKs9pRplPEuGejKYa$&Nq$@f{NUfpzx~8l6z^nvHP8E~i65h0m-xrsET`x)mrC(^Tu7#PxyBDa)vRlW z7sp(O>kIAT#r1noepI}0&j*O$uQxwkGSWZ!`EtLJXkQ;yDJ{0@V)=8ve4<&66I6j` zX+>qVIAi&1BTN`+Lw;H0+VNNAK9tukf9?1w%8$xlsP`~6`74y$={%Y^71u91nMY~h z#SO>Z`>i{6fAT4REFE4vxfJzkyv~M~S%(*!PQ!JIcJX4@4^V#8yg2w9xW3V8UK}%l zxSiyMG-G}3r=ETj^=iDn!oU}%P5nG`uB-ewa(P?(XM^)mepLK$*IBuNI=gQv;?JVa zIxg}Y9e-`#&|ZIS+7_+9Q14-?^p7aF)A>|+4{Xh5N6cdbAhuU-pk1RXM@)36^6xPLg?!@%WF7 zAN>;X+VPukO?&-D-4w0gocy}tVU*kH{Mz?1;&w8>bl}G+=BkhX;{F@Y@<$W>(MOGb zVTHy2HU4oUBTI~~(>%>`azak2qG)~bDA@-LdqMr;s`*L@D6d_0_q+Wlza9BB0RB4U zuFJoD@S4{@@*9Z$>Zhg(h=28wzIIDsSYB2cPSxWw7uPkfzv{MGPCjkBsl9&N`e3wv zbMon!XHagZ^J(6al@@P1nNNejkDGt^tF;&H-U73<-j|b4-D%V-kWWdnB*yB%4qi$n zSjFatq$rwMV!guP%HhR|Z=$?*<641V5{jvQuV?I6dYJ2^5-<)$T{zc_CC!cnmhH^WdPg}Bx+sS-d z2mJU>_NK2N`%X{Y_UVxd>b36(U%idTX+}@-uq=|4RW7bsyO_y9AzK{qlg*V+)OS%{ zyYgw<6DU7wUTk><<#w7Ek1jZ`<8^jD@Z$2y_{xQIUO2%YN~dl-y%O~bj0*%hPRlTY zq;*+H(kf^10=`0W2zW8gl#EkvcStC=UHsUz8RbXC5BGQ=1AbeloqQCteDuzGe*5Td z#4r2nEiLm2g-$j)(Me8@G-VPtS%HnsY^J?!Z z#O-9g%>qCE>tEwv`o)V&t`6r%A9eUT)a%dSF@4Xx3~WWFITq52XJNmBloZumv2H8u z-Jh8Q-1WT|_kFmUzPBFk=w`&d$-n*$>zW)V2rwAobwJld>l-Hu@U=Kn@F|&Ezp3kC zl-I62R`;U(sPfq1wF$~anFJAoCWi9@<}WTqz4CB_hmWej zsuIu2ahB8Ac!IINX3rX=!puADlZGwzeyLtwnt;D|_4m)4ch%xQ^52Q^=%==ri2qaA zS?s}wtr$E9L*sZ{OK>U32mG2p#D{Vj4sZAChpA1sq1-^6lUy=MrzA$@@|Cb6O4}}1jTaS&P$6Z?%JotsDJ|y(^yd2&gnA>O7n*%5M^xzmNr7Q60 zPa?reoK{Bu#xY$9)9!_`|hZzJ2NLWp&4|Q~!o~T}O26*wbL#q~fyr4;y*HL%Z(e>LDQ{L#;L9JT5nE(rI-3hIOYH5Tup zc>eI&=jYG({NcqfA>JvF?4Eq*WLSpcQnIc{oWiSt4uWlf+rF1ym`|KoZ^G|SK~5~;^T=QuWFi}WVoc3l%Z=x`vut7ZoFRuUiR(Za@St7Ja9Ya z=?ZH6lIZZ>XaH}|M#PJPFK;#wzda{!vG(mp;m_YRU|(f%ba-z!fY+DC@5N^Q{G>HS zrQwN7nP(V*PK6B7EXKI`@($n~^|QnN{$Zx_*M53AeCgi0DKdZVZ@|92_e6*HZUcB@ z-Cwrs7)XF3F6nCN-Ij^HS9_-V--Jk9u)FwfW_pXFm7V z;&tA;oPNg&YWwG}weX^7Z|4HuOwarGEy3s3(|*1r1W8E2)+%_^8J;Oo!+Ve3{>1Ts zcj}JO{v(+27wg&A`!M=*z8_B!WHu?K=!70u6kd@10_CwE;v8ar Date: Tue, 12 Aug 2025 19:40:41 +0800 Subject: [PATCH 72/78] test --- apps/routers/mcp_service.py | 4 ++-- apps/scheduler/executor/agent.py | 1 + apps/scheduler/mcp_agent/prompt.py | 4 ++-- apps/services/mcp_service.py | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index 62b6453e..99cc6dfd 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -53,7 +53,7 @@ async def get_mcpservice_list( ] = SearchType.ALL, keyword: Annotated[str | None, Query(..., alias="keyword", description="搜索关键字")] = None, page: Annotated[int, Query(..., alias="page", ge=1, description="页码")] = 1, - is_installed: Annotated[bool | None, Query(..., alias="isInstall", description="是否已安装")] = None, + is_install: Annotated[bool | None, Query(..., alias="isInstall", description="是否已安装")] = None, is_active: Annotated[bool | None, Query(..., alias="isActive", description="是否激活")] = None, ) -> JSONResponse: """获取服务列表""" @@ -63,7 +63,7 @@ async def get_mcpservice_list( user_sub, keyword, page, - is_installed, + is_install, is_active ) except Exception as e: diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 55a817e6..93409319 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -495,6 +495,7 @@ class MCPAgentExecutor(BaseExecutor): break await self.work() await TaskManager.save_task(self.task.id, self.task) + logger.error({self.task}) tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool if tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index e91fb0a5..6cc8d9c0 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -67,10 +67,10 @@ TOOL_SELECT = dedent(r""" 你的任务是:根据当前目标,附加信息,选择最合适的MCP工具。 ## 选择MCP工具时的注意事项: 1. 确保充分理解当前目标,选择实现目标所需的MCP工具。 - 2. 请在给定的MCP工具列表中选择,不要自己生成MCP工具。 + 2. 不要选择不存在的工具。 3. 可以选择一些辅助工具,但必须确保这些工具与当前目标相关。 4. 注意,返回的工具ID必须是MCP工具的ID,而不是名称。 - 5. 不要选择不存在的工具。 + 5. 可以多选择一些工具,用于应对不同的情况。 必须按照以下格式生成选择结果,不要输出任何其他内容: ```json { diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index 324ba70d..3c7ab3c5 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -79,7 +79,7 @@ class MCPServiceManager: user_sub: str, keyword: str | None, page: int, - is_installed: bool | None = None, + is_install: bool | None = None, is_active: bool | None = None, ) -> list[MCPServiceCardItem]: """ @@ -97,7 +97,7 @@ class MCPServiceManager: filters["activated"] = {"$in": [user_sub]} else: filters["activated"] = {"$nin": [user_sub]} - if not is_installed: + if not is_install: user_info = await UserManager.get_userinfo_by_user_sub(user_sub) if not user_info.is_admin: filters["status"] = MCPInstallStatus.READY.value -- Gitee From c53fb56c22d53e8c9fdd5c8a278b06799b19d001 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 19:44:01 +0800 Subject: [PATCH 73/78] test --- apps/scheduler/executor/agent.py | 2 +- apps/scheduler/mcp/prompt.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 93409319..9e025ab2 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -495,7 +495,7 @@ class MCPAgentExecutor(BaseExecutor): break await self.work() await TaskManager.save_task(self.task.id, self.task) - logger.error({self.task}) + logger.error(f"{self.task}") tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool if tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 diff --git a/apps/scheduler/mcp/prompt.py b/apps/scheduler/mcp/prompt.py index d6ff72b4..871f7f82 100644 --- a/apps/scheduler/mcp/prompt.py +++ b/apps/scheduler/mcp/prompt.py @@ -72,7 +72,8 @@ CREATE_PLAN = dedent(r""" 2. 计划中的每一个步骤必须且只能使用一个工具。 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 4. 计划中的最后一步必须是Final工具,以确保计划执行结束。 - + 5.生成的计划必须要覆盖用户的目标,不能遗漏任何用户目标中的内容。 + # 生成计划时的注意事项: - 每一条计划包含3个部分: -- Gitee From c42bd3013a2f09f18f1ec1b34715288492b4d54c Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 20:45:32 +0800 Subject: [PATCH 74/78] test --- apps/scheduler/executor/agent.py | 12 +- apps/scheduler/mcp/prompt.py | 2 +- apps/scheduler/mcp_agent/host.py | 5 +- apps/scheduler/mcp_agent/plan.py | 31 +- apps/scheduler/mcp_agent/prompt.py | 142 +- apps/schemas/mcp.py | 6 + nohup.out | 5936 ++++++++++++++++++++++++++++ 7 files changed, 6088 insertions(+), 46 deletions(-) create mode 100644 nohup.out diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 9e025ab2..2c8574b0 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -356,6 +356,17 @@ class MCPAgentExecutor(BaseExecutor): async def work(self) -> None: """执行当前步骤""" if self.task.state.step_status == StepStatus.INIT: + tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + # if tool_id != FINAL_TOOL_ID: + # step_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id + # tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + # step_name = self.tools[tool_id].name + # step_instruction = self.task.runtime.temporary_plans.plans[self.task.state.step_index].instruction + # step_content = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content + # tool_skip = await MCPPlanner.tool_skip(self.task, step_id, step_name, step_instruction, step_content, self.resoning_llm) + # if tool_skip.skip: + # await self.get_next_step() + # return await self.push_message( EventType.STEP_INIT, data={} @@ -495,7 +506,6 @@ class MCPAgentExecutor(BaseExecutor): break await self.work() await TaskManager.save_task(self.task.id, self.task) - logger.error(f"{self.task}") tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool if tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 diff --git a/apps/scheduler/mcp/prompt.py b/apps/scheduler/mcp/prompt.py index 871f7f82..b906fb8f 100644 --- a/apps/scheduler/mcp/prompt.py +++ b/apps/scheduler/mcp/prompt.py @@ -235,7 +235,7 @@ MEMORY_TEMPLATE = dedent(r""" {% for ctx in context_list %} - 第{{ loop.index }}步:{{ ctx.step_description }} - 调用工具 `{{ ctx.step_name }}`,并提供参数 `{{ ctx.input_data|tojson }}`。 - - 执行状态:{{ ctx.status }} + - 执行状态:{{ ctx.step_status }} - 得到数据:`{{ ctx.output_data|tojson }}` {% endfor %} """) diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index a244d8a9..44b04d1f 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -58,6 +58,9 @@ class MCPHost: 注意: 1. 你需要根据工具的输入schema来生成参数。 2. 如果工具的输入schema中有枚举类型的字段,请确保生成的参数符合这些枚举值。 + 下面是工具的简介: + 工具名称:{mcp_tool.name} + 工具描述:{mcp_tool.description} """ # 进行生成 @@ -80,7 +83,7 @@ class MCPHost: llm_query = "请生成修复之后的工具参数" prompt = _env.from_string(REPAIR_PARAMS).render( tool_name=mcp_tool.name, - gaol=goal, + goal=goal, current_goal=current_goal, tool_description=mcp_tool.description, input_schema=mcp_tool.input_schema, diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 245ed654..fbdebff5 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -13,18 +13,22 @@ from apps.scheduler.mcp_agent.prompt import ( GET_REPLAN_START_STEP_INDEX, CREATE_PLAN, RECREATE_PLAN, + TOOL_SKIP, RISK_EVALUATE, TOOL_EXECUTE_ERROR_TYPE_ANALYSIS, CHANGE_ERROR_MESSAGE_TO_DESCRIPTION, GET_MISSING_PARAMS, FINAL_ANSWER ) +from apps.schemas.task import Task from apps.schemas.mcp import ( GoalEvaluationResult, RestartStepIndex, + ToolSkip, ToolRisk, ToolExcutionErrorType, MCPPlan, + MCPPlanItem, MCPTool ) from apps.scheduler.slot.slot import Slot @@ -161,9 +165,34 @@ class MCPPlanner(McpBase): # 使用Function模型解析结果 return MCPPlan.model_validate(plan) + @staticmethod + async def tool_skip( + task: Task, step_id: str, step_name: str, step_instruction: str, step_content: str, + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> ToolSkip: + """判断当前步骤是否需要跳过""" + # 获取推理结果 + template = _env.from_string(TOOL_SKIP) + from apps.scheduler.mcp_agent.host import MCPHost + history = await MCPHost.assemble_memory(task) + prompt = template.render( + step_id=step_id, + step_name=step_name, + step_instruction=step_instruction, + step_content=step_content, + history=history, + goal=task.runtime.question + ) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + + # 解析为结构化数据 + schema = ToolSkip.model_json_schema() + skip_result = await MCPPlanner._parse_result(result, schema) + # 使用ToolSkip模型解析结果 + return ToolSkip.model_validate(skip_result) + @staticmethod async def get_tool_risk( - tool: MCPTool, input_parm: dict[str, Any], + tool: MCPTool, input_parm: dict[str, Any], additional_info: str = "", resoning_llm: ReasoningLLM = ReasoningLLM()) -> ToolRisk: """获取MCP工具的风险评估结果""" # 获取推理结果 diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 6cc8d9c0..b4022c01 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -265,6 +265,7 @@ CREATE_PLAN = dedent(r""" 3. 计划中的步骤必须具有清晰和逻辑的步骤,没有冗余或不必要的步骤。 4. 不要选择不存在的工具。 5. 计划中的最后一步必须是Final工具,以确保计划执行结束。 + 6. 生成的计划必须要覆盖用户的目标,当然需要考虑一些意外情况,可以有一定的冗余步骤。 # 生成计划时的注意事项: @@ -364,7 +365,7 @@ RECREATE_PLAN = dedent(r""" 4. 你的计划必须避免之前的错误,并且能够成功执行。 5. 不要选择不存在的工具。 6. 计划中的最后一步必须是Final工具,以确保计划执行结束。 - + 7. 生成的计划必须要覆盖用户的目标,当然需要考虑一些意外情况,可以有一定的冗余步骤。 # 生成计划时的注意事项: - 每一条计划包含3个部分: @@ -501,6 +502,61 @@ RECREATE_PLAN = dedent(r""" # 重新生成的计划 """) +TOOL_SKIP = dedent(r""" + 你是一个计划执行器。 + 你的任务是根据当前的计划和用户目标,判断当前步骤是否需要跳过。 + 如果需要跳过,请返回`true`,否则返回`false`。 + 必须按照以下格式回答: + ```json + { + "skip": true/false, + } + ``` + 注意: + 1.你的判断要谨慎,在历史消息中有足够的上下文信息时,才可以判断是否跳过当前步骤。 + # 样例 + # 用户目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 历史 + 第1步:生成端口扫描命令 + - 调用工具 `command_generator`,并提供参数 `{"command": "nmap -sS -p--open 192.168.1.1"}` + - 执行状态:成功 + - 得到数据:`{"command": "nmap -sS -p--open 192.168.1.1"}` + 第2步:执行端口扫描命令 + - 调用工具 `command_executor`,并提供参数 `{"command": "nmap -sS -p--open 192.168.1.1"}` + - 执行状态:成功 + - 得到数据:`{"result": "success"}` + 第3步:分析端口扫描结果 + - 调用工具 `mysql_analyzer`,并提供参数 `{"host": "192.168.1.1", "port": 3306, "username": "root", "password": "password"}` + - 执行状态:成功 + - 得到数据:`{"performance": "good", "bottleneck": "none"}` + # 当前步骤 + + step_4 + command_generator + 生成MySQL性能调优命令 + 生成MySQL性能调优命令:调优MySQL数据库性能 + + # 输出 + ```json + { + "skip": true + } + ``` + # 用户目标 + {{goal}} + # 历史 + {{history}} + # 当前步骤 + + {{step_id}} + {{step_name}} + {{step_instruction}} + {{step_content}} + + # 输出 + """ + ) RISK_EVALUATE = dedent(r""" 你是一个工具执行计划评估器。 你的任务是根据当前工具的名称、描述和入参以及附加信息,判断当前工具执行的风险并输出提示。 @@ -538,10 +594,10 @@ RISK_EVALUATE = dedent(r""" } ``` # 工具 - - {{tool_name}} - {{tool_description}} - + < tool > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > + < / tool > # 工具入参 {{input_param}} # 附加信息 @@ -586,10 +642,10 @@ TOOL_EXECUTE_ERROR_TYPE_ANALYSIS = dedent(r""" } ]} # 当前使用的工具 - - command_executor - 执行命令行指令 - + < tool > + < name > command_executor < /name > + < description > 执行命令行指令 < /description > + < / tool > # 工具入参 { "command": "nmap -sS -p--open 192.168.1.1" @@ -608,10 +664,10 @@ TOOL_EXECUTE_ERROR_TYPE_ANALYSIS = dedent(r""" # 当前计划 {{current_plan}} # 当前使用的工具 - - {{tool_name}} - {{tool_description}} - + < tool > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > + < / tool > # 工具入参 {{input_param}} # 工具运行报错 @@ -630,10 +686,10 @@ CHANGE_ERROR_MESSAGE_TO_DESCRIPTION = dedent(r""" 5. 只输出自然语言描述,不要输出其他内容。 # 样例 # 工具信息 - - port_scanner - 扫描主机端口 - + < tool > + < name > port_scanner < /name > + < description > 扫描主机端口 < /description > + < input_schema > { "type": "object", "properties": { @@ -651,13 +707,13 @@ CHANGE_ERROR_MESSAGE_TO_DESCRIPTION = dedent(r""" }, "password": { "type": "string", - "description": "密码" + "description": "密码" } }, "required": ["host", "port", "username", "password"] } - - + < /input_schema > + < / tool > # 工具入参 { "host": "192.0.0.1", @@ -671,13 +727,13 @@ CHANGE_ERROR_MESSAGE_TO_DESCRIPTION = dedent(r""" 扫描端口时发生错误:密码不正确。请检查输入的密码是否正确,并重试。 # 现在开始转换报错信息: # 工具信息 - - {{tool_name}} - {{tool_description}} - + < tool > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > + < input_schema > {{input_schema}} - - + < /input_schema > + < / tool > # 工具入参 {{input_params}} # 报错信息 @@ -755,10 +811,10 @@ GET_MISSING_PARAMS = dedent(r""" } ``` # 工具 - - {{tool_name}} - {{tool_description}} - + < tool > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > + < / tool > # 工具入参 {{input_param}} # 工具入参schema(部分字段允许为null) @@ -771,16 +827,16 @@ GET_MISSING_PARAMS = dedent(r""" REPAIR_PARAMS = dedent(r""" 你是一个工具参数修复器。 你的任务是根据当前的工具信息、目标、工具入参的schema、工具当前的入参、工具的报错、补充的参数和补充的参数描述,修复当前工具的入参。 - + 注意: 1.最终修复的参数要符合目标和工具入参的schema。 - + # 样例 # 工具信息 - - mysql_analyzer - 分析MySQL数据库性能 - + < tool > + < name > mysql_analyzer < /name > + < description > 分析MySQL数据库性能 < /description > + < / tool > # 总目标 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 # 当前阶段目标 @@ -834,10 +890,10 @@ REPAIR_PARAMS = dedent(r""" } ``` # 工具 - - {{tool_name}} - {{tool_description}} - + < tool > + < name > {{tool_name}} < /name > + < description > {{tool_description}} < /description > + < / tool > # 总目标 {{goal}} # 当前阶段目标 @@ -846,6 +902,8 @@ REPAIR_PARAMS = dedent(r""" {{input_schema}} # 工具入参 {{input_param}} + # 工具描述 + {{tool_description}} # 运行报错 {{error_message}} # 补充的参数 @@ -876,10 +934,10 @@ FINAL_ANSWER = dedent(r""" """) MEMORY_TEMPLATE = dedent(r""" - {% for ctx in context_list %} + { % for ctx in context_list % } - 第{{loop.index}}步:{{ctx.step_description}} - 调用工具 `{{ctx.step_id}}`,并提供参数 `{{ctx.input_data}}` - 执行状态:{{ctx.step_status}} - 得到数据:`{{ctx.output_data}}` - {% endfor %} + { % endfor % } """) diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 674acf9c..022eb00f 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -130,6 +130,12 @@ class Risk(str, Enum): HIGH = "high" +class ToolSkip(BaseModel): + """MCP工具跳过执行结果""" + + skip: bool = Field(description="是否跳过当前步骤", default=False) + + class ToolRisk(BaseModel): """MCP工具风险评估结果""" diff --git a/nohup.out b/nohup.out new file mode 100644 index 00000000..a90c116a --- /dev/null +++ b/nohup.out @@ -0,0 +1,5936 @@ +nohup: ignoring input +# jionlp - 微信公众号: JioNLP Github: `https://github.com/dongrixinyu/JioNLP`. +# jiojio - Successfully load C funcs for CWS and POS acceleration. +25-Aug-12 20:14:55 INFO  init() - [Pool] 载入Call ]8;id=961416;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=784982;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#84\84]8;;\ +25-Aug-12 20:14:56 INFO  _send_single_request() - HTTP Request: POST https://api.siliconflow.cn/v1/embeddings "HTTP/1.1 200 OK" ]8;id=703354;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=405600;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  INFO  init() - [Pool] 检查文件变动 ]8;id=424382;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=70264;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#88\88]8;;\ +  INFO  diff() - [FileChecker] 文件变动: [];文件删除: [] ]8;id=371800;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py\check.py]8;;\:]8;id=454754;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py#83\83]8;;\ +  INFO  init() - [Pool] 载入Service ]8;id=789812;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=970989;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#93\93]8;;\ +  INFO  init() - [Pool] 载入App ]8;id=525784;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=617349;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#109\109]8;;\ +  INFO  diff() - [FileChecker] 文件变动: [];文件删除: [] ]8;id=850578;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py\check.py]8;;\:]8;id=670212;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py#83\83]8;;\ +  ERROR  load_one() - [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=621739;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py\metadata.py]8;;\:]8;id=469007;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py#61\61]8;;\ +  ╭──────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py:58 in load_one │   +  │ │   +  │  55 │ │ │ else: │   +  │  56 │ │ │ │ try: │   +  │  57 │ │ │ │ │ app_id = file_path.parent.name │   +  │ ❱  58 │ │ │ │ │ metadata = AgentAppMetadata(id=app_id, **metadata_dict) │   +  │  59 │ │ │ │ except Exception as e: │   +  │  60 │ │ │ │ │ err = "[MetadataLoader] Agent app metadata.yaml格式错误" │   +  │  61 │ │ │ │ │ logger.exception(err) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py:253 in __init__ │   +  │ │   +  │  250 │ │ """ │   +  │  251 │ │ # `__tracebackhide__` tells pytest and some other tools to omit this function  │   +  │ from tracebacks │   +  │  252 │ │ __tracebackhide__ = True │   +  │ ❱  253 │ │ validated_self = self.__pydantic_validator__.validate_python(data,  │   +  │ self_instance=self) │   +  │  254 │ │ if self is not validated_self: │   +  │  255 │ │ │ warnings.warn( │   +  │  256 │ │ │ │ 'A custom validator is returning a value other than `self`.\n' │   +  ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ValidationError: 1 validation error for AgentAppMetadata   +  mcp_service.0   +  Input should be a valid string [type=string_type, input_value={'id': 'W785k0', 'name': '', 'description': ''},   +  input_type=dict]   +  For further information visit https://errors.pydantic.dev/2.11/v/string_type   +  WARNING  init() - [Pool] 加载App 2793ab12-0ea2-4314-b709-938245e9154d 失败: [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=44584;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=238803;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#127\127]8;;\ +  ERROR  load_one() - [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=261651;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py\metadata.py]8;;\:]8;id=837901;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py#61\61]8;;\ +  ╭──────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py:58 in load_one │   +  │ │   +  │  55 │ │ │ else: │   +  │  56 │ │ │ │ try: │   +  │  57 │ │ │ │ │ app_id = file_path.parent.name │   +  │ ❱  58 │ │ │ │ │ metadata = AgentAppMetadata(id=app_id, **metadata_dict) │   +  │  59 │ │ │ │ except Exception as e: │   +  │  60 │ │ │ │ │ err = "[MetadataLoader] Agent app metadata.yaml格式错误" │   +  │  61 │ │ │ │ │ logger.exception(err) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py:253 in __init__ │   +  │ │   +  │  250 │ │ """ │   +  │  251 │ │ # `__tracebackhide__` tells pytest and some other tools to omit this function  │   +  │ from tracebacks │   +  │  252 │ │ __tracebackhide__ = True │   +  │ ❱  253 │ │ validated_self = self.__pydantic_validator__.validate_python(data,  │   +  │ self_instance=self) │   +  │  254 │ │ if self is not validated_self: │   +  │  255 │ │ │ warnings.warn( │   +  │  256 │ │ │ │ 'A custom validator is returning a value other than `self`.\n' │   +  ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ValidationError: 1 validation error for AgentAppMetadata   +  mcp_service.0   +  Input should be a valid string [type=string_type, input_value={'id': 'W785k0', 'name': ...ne, 'description': None},   +  input_type=dict]   +  For further information visit https://errors.pydantic.dev/2.11/v/string_type   +  WARNING  init() - [Pool] 加载App ecd9e9fb-821f-4f91-8f29-120048515604 失败: [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=896261;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=52563;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#127\127]8;;\ +  INFO  init() - [Pool] 载入MCP ]8;id=882128;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=66910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#129\129]8;;\ +  INFO  _find_deleted_mcp() - [MCPLoader] 这些MCP在文件系统中被删除: [] ]8;id=804315;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=339566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#497\497]8;;\ +  INFO  remove_deleted_mcp() - [MCPLoader] 清除数据库中无效的MCP ]8;id=925474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=354589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#539\539]8;;\ +  INFO  remove_deleted_mcp() - [MCPLoader] 清除LanceDB中无效的MCP ]8;id=667208;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=529433;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#554\554]8;;\ +  INFO  cancel_all_installing_task() - [MCPLoader] 初始化所有MCP模板: /opt/copilot/semantics/mcp/template ]8;id=467500;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=174523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#178\178]8;;\ +  ERROR  add_no_auth_user() - [add_no_auth_user] 默认用户 root 已存在 ]8;id=668910;file:///home/zjq/euler-copilot-framework_1/apps/main.py\main.py]8;;\:]8;id=227704;file:///home/zjq/euler-copilot-framework_1/apps/main.py#107\107]8;;\ +  INFO  clear_user_activity() - 清除所有用户活跃状态完成 ]8;id=169828;file:///home/zjq/euler-copilot-framework_1/apps/main.py\main.py]8;;\:]8;id=627525;file:///home/zjq/euler-copilot-framework_1/apps/main.py#117\117]8;;\ +  INFO  _serve() - Started server process [885153] ]8;id=609070;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py\server.py]8;;\:]8;id=581876;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py#83\83]8;;\ +  INFO  startup() - Waiting for application startup. ]8;id=184477;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py\on.py]8;;\:]8;id=47674;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py#48\48]8;;\ +  INFO  startup() - Application startup complete. ]8;id=254881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py\on.py]8;;\:]8;id=977726;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py#62\62]8;;\ +  INFO  _log_started_message() - Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit) ]8;id=775711;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py\server.py]8;;\:]8;id=221767;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py#215\215]8;;\ +25-Aug-12 20:14:57 ERROR  fetch_apps() - [AppCenterManager] 搜索条件: {'$or': [{'permission.type': 'public'}, {'$and': [{'permission.type': ]8;id=24219;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=174432;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#86\86]8;;\ +  'protected'}, {'permission.users': {'$in': ['root']}}]}, {'$and': [{'permission.type': 'private'}, {'author':   +  'root'}]}], 'published': True}, 页码: 1, 每页大小: 16   +  INFO  send() - 124.70.231.10:13355 - "GET /api/app?page=1 HTTP/1.1" 200 ]8;id=756810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=595720;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:14:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=67625;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=254111;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=918049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=6244;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=76551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=493979;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=651850;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=542329;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=554165;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=718295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47665 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=817505;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=404771;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=3598;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=589191;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=822127;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=861551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=956993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=614453;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=202308;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=709923;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=871547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=98206;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47666 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=907441;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=136190;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=97226;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=882698;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=828167;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=310020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=814743;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=372894;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=770814;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252799;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=499414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=338155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47667 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=559642;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=678808;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:09 INFO  send() - 124.70.231.10:13356 - "GET /api/conversation HTTP/1.1" 200 ]8;id=674212;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=395403;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.10:13356 - "GET /api/record/0abebf87-4b93-4adc-a8e6-491e7db2f0d6 HTTP/1.1" 200 ]8;id=556412;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=787425;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:10 ERROR  add_conversation_by_user_sub() - [ConversationManager] 获取团队知识库列表失败 ]8;id=983788;file:///home/zjq/euler-copilot-framework_1/apps/services/conversation.py\conversation.py]8;;\:]8;id=844204;file:///home/zjq/euler-copilot-framework_1/apps/services/conversation.py#65\65]8;;\ +  INFO  send() - 124.70.231.10:13356 - "POST /api/conversation HTTP/1.1" 200 ]8;id=852938;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=102457;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.10:13356 - "POST /api/chat HTTP/1.1" 200 ]8;id=77838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=825234;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 56a6f6af-43d1-4b6e-b5fd-12ace83bcf07 ]8;id=620052;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=606323;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ +  INFO  run() - [Scheduler] 开始执行 ]8;id=933007;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=130131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ +  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=902686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=452843;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ +  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=545926;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=737856;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ +  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=156049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=526610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ +  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=133196;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=39998;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ +  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=699627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=278575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ +  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=262316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=935136;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ +  INFO  run() - [Scheduler] 发送结束消息 ]8;id=374628;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=587898;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=255541;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=56233;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-3346' coro=<Scheduler.run_executor() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    +  初始化失败')>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   +  │ │   +  │ 304 │ │ │ ) │   +  │ 305 │ │ │ # 开始运行 │   +  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   +  │ ❱ 307 │ │ │ await agent_exec.run() │   +  │ 308 │ │ │ self.task = agent_exec.task │   +  │ 309 │ │ else: │   +  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   +  │ │   +  │ 444 │ │ """执行MCP Agent的主逻辑""" │   +  │ 445 │ │ # 初始化MCP服务 │   +  │ 446 │ │ await self.load_state() │   +  │ ❱ 447 │ │ await self.load_mcp() │   +  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   +  │ 449 │ │ │ # 初始化状态 │   +  │ 450 │ │ │ try: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   +  │ │   +  │  85 │ │ │ │ continue │   +  │  86 │ │ │  │   +  │  87 │ │ │ self.mcp_list.append(mcp_service) │   +  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   +  │  89 │ │ │ for tool in mcp_service.tools: │   +  │  90 │ │ │ │ self.tools[tool.id] = tool │   +  │  91  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   +  │ │   +  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   +  │ 37 │ │ │ return None │   +  │ 38 │ │  │   +  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   +  │ 40 │ │ if user_sub not in self.pool: │   +  │ 41 │ │ │ self.pool[user_sub] = {} │   +  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   +  │ │   +  │ 134 │ │ if self.error_sign.is_set(): │   +  │ 135 │ │ │ self.status = MCPStatus.ERROR │   +  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   +  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   +  │ 138 │ │ │  │   +  │ 139 │ │ │ # 获取工具列表 │   +  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  Exception: MCP 6Zn8Gg 初始化失败   +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=976252;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=9033;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=97128;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=441682;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=55227;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=250535;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=241386;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=366041;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=895447;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=22566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:15:11 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=850260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=849417;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47668 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=659496;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=369594;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=26883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=18689;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ +25-Aug-12 20:15:12 INFO  send() - 124.70.231.47:14920 - "POST /api/chat HTTP/1.1" 200 ]8;id=204921;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=950848;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 39f8af6c-d918-405f-a931-d99ad0f7d46b ]8;id=958052;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=956234;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ +  INFO  run() - [Scheduler] 开始执行 ]8;id=229397;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=500295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ +25-Aug-12 20:15:14 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=21017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=221518;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  call() - [Reasoning] 推理内容: ]8;id=341974;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=747613;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  {   +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。"   +  }   +  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=303994;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=162298;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ +  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   +  'QuestionRewriteResult', 'type': 'object'}   +  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=550733;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=779360;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=520881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=400410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-3407' coro=<MCPClient._main_loop() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    +  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   +  │ __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=926298;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=669941;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  task: <Task pending name='Task-3408' coro=<Event.wait() running at    +  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=570711;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=48996;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=472832;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=546316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=341520;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=152956;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=509442;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=59199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=41578;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=135906;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47669 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=238531;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=622245;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:15 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=796703;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=553771;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=987685;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=534590;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。"   +  }   +  INFO  generate() - [JSONGenerator] 得到:{'question': ]8;id=894118;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=890685;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ +  '帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。'}   +  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=352135;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=36297;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ +  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=113463;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=553945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ +  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=280176;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=298620;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ +  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=300816;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=943320;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ +  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=673292;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=119155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ +  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=923238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=503907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ +  INFO  run() - [Scheduler] 发送结束消息 ]8;id=429436;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=587388;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=784760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=315286;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-4169' coro=<Scheduler.run_executor() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    +  初始化失败')>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   +  │ │   +  │ 304 │ │ │ ) │   +  │ 305 │ │ │ # 开始运行 │   +  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   +  │ ❱ 307 │ │ │ await agent_exec.run() │   +  │ 308 │ │ │ self.task = agent_exec.task │   +  │ 309 │ │ else: │   +  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   +  │ │   +  │ 444 │ │ """执行MCP Agent的主逻辑""" │   +  │ 445 │ │ # 初始化MCP服务 │   +  │ 446 │ │ await self.load_state() │   +  │ ❱ 447 │ │ await self.load_mcp() │   +  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   +  │ 449 │ │ │ # 初始化状态 │   +  │ 450 │ │ │ try: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   +  │ │   +  │  85 │ │ │ │ continue │   +  │  86 │ │ │  │   +  │  87 │ │ │ self.mcp_list.append(mcp_service) │   +  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   +  │  89 │ │ │ for tool in mcp_service.tools: │   +  │  90 │ │ │ │ self.tools[tool.id] = tool │   +  │  91  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   +  │ │   +  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   +  │ 37 │ │ │ return None │   +  │ 38 │ │  │   +  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   +  │ 40 │ │ if user_sub not in self.pool: │   +  │ 41 │ │ │ self.pool[user_sub] = {} │   +  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   +  │ │   +  │ 134 │ │ if self.error_sign.is_set(): │   +  │ 135 │ │ │ self.status = MCPStatus.ERROR │   +  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   +  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   +  │ 138 │ │ │  │   +  │ 139 │ │ │ # 获取工具列表 │   +  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  Exception: MCP 6Zn8Gg 初始化失败   +25-Aug-12 20:15:16 INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=961140;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=127564;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ +  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=397415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=211760;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ +25-Aug-12 20:15:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=264236;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=573865;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=294474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=324847;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=859116;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=569726;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=740445;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=123049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=113725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=920499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47670 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=83817;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=887428;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=428971;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=794439;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=71104;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=103013;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=689407;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=147001;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=887536;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=841409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=826966;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=307909;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47671 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=73844;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=32377;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=759079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=811210;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=329569;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=791730;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=971615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=695138;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=688082;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=682687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=924239;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=729283;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47672 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=661420;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=802096;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=829915;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=881665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=258779;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=250365;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=91627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=470737;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=538883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=951869;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=466375;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=852160;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47673 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=23697;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=158545;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=731084;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=786530;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=880532;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=863816;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=356417;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=830238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=281500;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=564576;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=896701;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47674 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=910944;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=45222;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=335313;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=519314;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=109176;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=244217;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=343035;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=257344;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=251412;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=462336;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=792467;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=466637;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47675 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=865612;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=57822;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=495669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=905458;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=411696;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=795706;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=532462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=6671;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=516039;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=435035;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=697;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=101766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47676 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=863663;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=348405;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.47:14921 - "POST /api/chat HTTP/1.1" 200 ]8;id=158710;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=345725;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 6c7d1f55-d8b5-4166-bb5d-284bb3391bb3 ]8;id=266751;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=474121;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ +25-Aug-12 20:15:43 INFO  run() - [Scheduler] 开始执行 ]8;id=313017;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=37232;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ +  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=14960;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=411743;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +25-Aug-12 20:15:44 INFO  call() - [Reasoning] 推理内容: ]8;id=857664;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=990218;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  {   +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。"   +  }   +  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=114415;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=419042;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ +  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   +  'QuestionRewriteResult', 'type': 'object'}   +  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=479257;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=566913;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ +25-Aug-12 20:15:45 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=721310;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=246536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=631247;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=202158;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。"   +  }   +  INFO  generate() - [JSONGenerator] 得到:{'question': ]8;id=476993;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=287409;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ +  '帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。'}   +  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=858248;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=422635;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ +  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=248653;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=280460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ +  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=308460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=657225;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ +  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=858367;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=920944;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ +  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=664586;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=123451;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ +  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=483781;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=531817;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ +  INFO  run() - [Scheduler] 发送结束消息 ]8;id=87156;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=686427;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=156487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=943984;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-6790' coro=<Scheduler.run_executor() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    +  初始化失败')>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   +  │ │   +  │ 304 │ │ │ ) │   +  │ 305 │ │ │ # 开始运行 │   +  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   +  │ ❱ 307 │ │ │ await agent_exec.run() │   +  │ 308 │ │ │ self.task = agent_exec.task │   +  │ 309 │ │ else: │   +  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   +  │ │   +  │ 444 │ │ """执行MCP Agent的主逻辑""" │   +  │ 445 │ │ # 初始化MCP服务 │   +  │ 446 │ │ await self.load_state() │   +  │ ❱ 447 │ │ await self.load_mcp() │   +  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   +  │ 449 │ │ │ # 初始化状态 │   +  │ 450 │ │ │ try: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   +  │ │   +  │  85 │ │ │ │ continue │   +  │  86 │ │ │  │   +  │  87 │ │ │ self.mcp_list.append(mcp_service) │   +  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   +  │  89 │ │ │ for tool in mcp_service.tools: │   +  │  90 │ │ │ │ self.tools[tool.id] = tool │   +  │  91  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   +  │ │   +  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   +  │ 37 │ │ │ return None │   +  │ 38 │ │  │   +  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   +  │ 40 │ │ if user_sub not in self.pool: │   +  │ 41 │ │ │ self.pool[user_sub] = {} │   +  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   +  │ │   +  │ 134 │ │ if self.error_sign.is_set(): │   +  │ 135 │ │ │ self.status = MCPStatus.ERROR │   +  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   +  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   +  │ 138 │ │ │  │   +  │ 139 │ │ │ # 获取工具列表 │   +  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  Exception: MCP 6Zn8Gg 初始化失败   +  INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=165968;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=390285;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ +25-Aug-12 20:15:46 WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=127833;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=529156;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=447011;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=694036;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=283805;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=922713;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=194367;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=966919;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=735579;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=330589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=381798;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=783492;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47677 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=649585;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=656005;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=590061;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=556589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=559215;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=989817;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=776199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=578521;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=254413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=684927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=469224;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=698110;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47678 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=387169;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=814308;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=871189;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=976613;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=437233;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=652996;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=75289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=19303;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=984686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=168950;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=237397;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=991716;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:47679 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=578987;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=592301;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:15:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=434180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=701562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=947268;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=404514;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10425;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=749952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=929925;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=825421;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=723712;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=408626;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48176 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=294777;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=525958;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=553362;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=51964;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=354131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=599776;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=202065;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=138472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=822932;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=850900;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=223025;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=140712;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48177 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=83810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=213593;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=986939;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=781879;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=725743;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=84898;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=534047;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=848989;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=871472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=268311;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=11444;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=697539;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48178 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=390097;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=815221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:10 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=641049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=202882;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=907933;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=496338;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=560548;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=172861;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=387536;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=212272;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=565042;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=394409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48179 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=558229;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=626925;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:12 INFO  send() - 124.70.231.10:13357 - "POST /api/stop HTTP/1.1" 200 ]8;id=729916;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=168600;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.10:13357 - "POST /api/chat HTTP/1.1" 200 ]8;id=464430;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=401123;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: ba8c8052-60bd-4384-adb2-4445b54cd877 ]8;id=652450;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=904281;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ +  INFO  run() - [Scheduler] 开始执行 ]8;id=553112;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=240242;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ +  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=574615;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=958799;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  call() - [Reasoning] 推理内容: ]8;id=753639;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=970479;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  {   +  "question": "如何查看 test.py 的性能分析?"   +  }   +  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=921665;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=916309;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ +  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   +  'QuestionRewriteResult', 'type': 'object'}   +  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=107255;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=489416;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ +25-Aug-12 20:16:13 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=300429;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=355039;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=743709;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=777666;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ +  "question": "如何查看 test.py 的性能分析?"   +  }   +  INFO  generate() - [JSONGenerator] 得到:{'question': '如何查看 test.py 的性能分析?'} ]8;id=529687;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=116977;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ +  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=62178;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=873458;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ +  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=141575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=313747;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ +  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=146505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=262838;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ +  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=394452;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=875961;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ +  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=798033;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=889366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ +  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=380155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=469347;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ +  INFO  run() - [Scheduler] 发送结束消息 ]8;id=79903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=759366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=751424;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=505292;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-9142' coro=<Scheduler.run_executor() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    +  初始化失败')>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   +  │ │   +  │ 304 │ │ │ ) │   +  │ 305 │ │ │ # 开始运行 │   +  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   +  │ ❱ 307 │ │ │ await agent_exec.run() │   +  │ 308 │ │ │ self.task = agent_exec.task │   +  │ 309 │ │ else: │   +  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   +  │ │   +  │ 444 │ │ """执行MCP Agent的主逻辑""" │   +  │ 445 │ │ # 初始化MCP服务 │   +  │ 446 │ │ await self.load_state() │   +  │ ❱ 447 │ │ await self.load_mcp() │   +  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   +  │ 449 │ │ │ # 初始化状态 │   +  │ 450 │ │ │ try: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   +  │ │   +  │  85 │ │ │ │ continue │   +  │  86 │ │ │  │   +  │  87 │ │ │ self.mcp_list.append(mcp_service) │   +  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   +  │  89 │ │ │ for tool in mcp_service.tools: │   +  │  90 │ │ │ │ self.tools[tool.id] = tool │   +  │  91  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   +  │ │   +  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   +  │ 37 │ │ │ return None │   +  │ 38 │ │  │   +  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   +  │ 40 │ │ if user_sub not in self.pool: │   +  │ 41 │ │ │ self.pool[user_sub] = {} │   +  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   +  │ │   +  │ 134 │ │ if self.error_sign.is_set(): │   +  │ 135 │ │ │ self.status = MCPStatus.ERROR │   +  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   +  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   +  │ 138 │ │ │  │   +  │ 139 │ │ │ # 获取工具列表 │   +  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  Exception: MCP 6Zn8Gg 初始化失败   +25-Aug-12 20:16:14 INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=128889;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=446477;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=690954;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=473060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=911931;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=493828;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=876081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=573349;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=433650;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=551348;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=356153;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=686134;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=969199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=839566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48180 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=596184;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=976536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=260123;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=253024;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=120456;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=954430;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=646268;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=41547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=846429;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=153728;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=76250;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=522222;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48181 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=333841;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=651347;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=54415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=586185;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=48617;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=46496;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=834755;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=825949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=554414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=705780;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=930911;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=503205;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48182 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=566209;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=392011;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=197705;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=947191;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=22255;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=755119;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=182418;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=166950;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=83486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=749976;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=982835;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=567722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48183 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=352221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=500436;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=786359;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=72953;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=326615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=412952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=271450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=266055;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=841261;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=121311;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=833516;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=421273;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48184 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=189269;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=23233;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=863393;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=641896;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=595113;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=932575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=783109;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=928511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=530063;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=295131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=745907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=637413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48185 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=212487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=428753;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=142721;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=77686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=585305;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=901835;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=339393;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=612389;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=378523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=600190;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=971878;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=773631;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48186 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=858211;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=814884;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=924170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=282044;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=394565;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=466157;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=779559;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=373558;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=758545;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=992416;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=595610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=320994;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48187 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=670870;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=341251;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=591044;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=123443;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=962886;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=599057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=816608;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=478561;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=262819;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=913011;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=804141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=879856;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48188 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=270250;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=578667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:47 INFO  send() - 124.70.231.47:14922 - "POST /api/chat HTTP/1.1" 200 ]8;id=875128;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=228325;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: d28646fb-c4de-45c4-ae94-57d96b9b9613 ]8;id=465045;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=137753;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ +  INFO  run() - [Scheduler] 开始执行 ]8;id=133567;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=208172;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ +25-Aug-12 20:16:48 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=598579;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=892311;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +25-Aug-12 20:16:49 INFO  call() - [Reasoning] 推理内容: ]8;id=696022;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=764830;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  {   +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图"   +  }   +  ```   +  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=692588;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=957447;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ +  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   +  'QuestionRewriteResult', 'type': 'object'}   +  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=932434;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=313220;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ +25-Aug-12 20:16:50 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=509418;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=928526;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=162273;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=156948;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ +  "question": "帮忙分析test.py进程的性能情况,并生成火焰图"   +  }   +  INFO  generate() - [JSONGenerator] 得到:{'question': '帮忙分析test.py进程的性能情况,并生成火焰图'} ]8;id=688673;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=287373;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ +  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=490811;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=660918;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ +  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=189183;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=162289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ +  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=488137;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=482180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ +  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=807892;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=252603;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ +  INFO  _send_single_request() - HTTP Request: GET http://0.0.0.0:12141/sse "HTTP/1.1 200 OK" ]8;id=967715;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=667838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  INFO  sse_reader() - Received endpoint URL: http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 ]8;id=822394;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=286082;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#65\65]8;;\ +  INFO  sse_client() - Starting post writer with endpoint URL: ]8;id=655685;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=872284;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#135\135]8;;\ +  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75   +  INFO  _send_single_request() - HTTP Request: POST ]8;id=704110;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=787841;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   +  INFO  _send_single_request() - HTTP Request: POST ]8;id=7807;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=559667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   +  INFO  _send_single_request() - HTTP Request: POST ]8;id=612044;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=288352;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=672339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=692574;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=331049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=387460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=883688;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=182122;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=653168;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=967773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=699030;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=509380;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48189 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=102883;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=710150;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=488690;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=263847;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  call() - [Reasoning] 推理内容: ]8;id=932254;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=121001;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  分析test.py进程性能并生成火焰图   +25-Aug-12 20:16:51 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=495294;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=468536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +  INFO  call() - [Reasoning] 推理内容: ]8;id=367218;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=249659;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  ```json   +  {   +  "tool_ids": ["IorUzv", "jeDuwL"]   +  }   +  ```   +  ERROR  plan() - 各个字段的类型: <class 'str'>, , ,  ]8;id=123778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=716490;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#130\130]8;;\ +25-Aug-12 20:16:52 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=162399;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=912611;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ +  "HTTP/1.1 200 OK"   +25-Aug-12 20:16:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=357067;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=3753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=268036;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=805006;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=312696;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=70241;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=539627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=765791;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=669954;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=534939;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48190 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=326712;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=767558;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:16:56 INFO  call() - [Reasoning] 推理内容: ]8;id=135251;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=358931;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ +    +  <thinking>   +  1. 用户的目标是分析 `test.py` 进程的性能情况并生成火焰图。   +  2. 首先需要使用 `perf` 工具采集该进程的性能数据,这可以通过 `perf_collect_tool` 完成,传入进程名称 `test.py`。   +  3. 采集完成后会生成 `perf.data` 文件。   +  4. 接着使用 `generate_flamegraph_tool` 来处理 `perf.data` 并生成火焰图 `perf.svg`。   +  5. 最后使用 `Final` 工具结束整个流程。   +  </thinking>   +  ```json   +  {   +  "plans": [   +  {   +  "content": "使用 perf_collect_tool 采集 test.py 进程的性能数据",   +  "tool": "IorUzv",   +  "instruction": "采集进程名称为 test.py 的性能数据并保存为 perf.data"   +  },   +  {   +  "content": "使用 generate_flamegraph_tool 处理 perf.data 并生成火焰图",   +  "tool": "jeDuwL",   +  "instruction": "处理当前目录下的 perf.data 文件,生成火焰图 perf.svg"   +  },   +  {   +  "content": "任务完成,火焰图已生成,路径为 Result[1]",   +  "tool": "FIANL",   +  "instruction": ""   +  }   +  ]   +  }   +  ```   +  INFO  reset_step_to_index() - [MCPAgentExecutor] 重置步骤到索引 0 ]8;id=629127;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=262165;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#158\158]8;;\ +  ERROR  run() - [MCPAgentExecutor] 执行过程中发生错误: Traceback (most recent call last): ]8;id=90626;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=219138;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#517\517]8;;\ +  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py", line 502, in run   +  await self.work()   +  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py", line 361, in work   +  tool_skip = await MCPPlanner.tool_skip(self.task,   +  self.task.runtime.temporary_plans.plans[self.task.state.step_index], self.resoning_llm)   +  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   +  ^^^^^^^^^^^^^^^^^^^^^^   +  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/mcp_agent/plan.py", line 176, in tool_skip   +  step_id=step.id,   +  ^^^^^^^   +  File "/root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py", line 991, in   +  __getattr__   +  raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')   +  AttributeError: 'MCPPlanItem' object has no attribute 'id'   +    +  ERROR  run() - [MCPAgentExecutor] 执行过程中发生错误: 'MCPPlanItem' object has no attribute 'id' ]8;id=328494;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=321505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#518\518]8;;\ +  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:收到停止信号,正在关闭 ]8;id=721141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=271429;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#99\99]8;;\ +  INFO  run() - [Scheduler] 发送结束消息 ]8;id=510749;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=208833;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ +  ERROR  chat_generator() - [Chat] 生成答案失败 ]8;id=687598;file:///home/zjq/euler-copilot-framework_1/apps/routers/chat.py\chat.py]8;;\:]8;id=549286;file:///home/zjq/euler-copilot-framework_1/apps/routers/chat.py#105\105]8;;\ +  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=3383;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=883002;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ +25-Aug-12 20:16:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=136486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=830722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=134934;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=862413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=360313;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=29105;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=508760;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=288687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=956075;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=248186;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48191 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=533028;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=654773;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=351595;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=446571;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=513695;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=673841;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=560029;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=796160;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=885379;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=820530;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=207649;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=638775;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48192 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=113490;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=340422;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=921081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=57208;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=138736;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=74475;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=32969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=930339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=986681;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=842685;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=722746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=239686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48193 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=223873;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=76460;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:10 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=958081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=186983;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=785319;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=808665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=895949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=326258;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=441493;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=166394;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=388378;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=587562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48194 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=773038;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=625329;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:14 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=995389;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=965711;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=492658;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=639078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=136857;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=354332;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=777703;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=529282;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=961870;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=161225;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48195 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=749307;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=845574;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=791684;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831255;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=173654;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=900662;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=896740;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=20263;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=532100;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=632942;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=434992;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=59366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48196 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=97564;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=352404;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=528360;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=606032;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=714746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=240242;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=35645;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=241276;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=514118;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=277705;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=539831;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48197 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=311548;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=347274;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=932766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=938404;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=156460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=491886;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=233021;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=561825;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=459786;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=28499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=804521;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=975434;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48198 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=912451;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=720846;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=662258;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=310244;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=36368;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=992057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=45174;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=857184;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=931407;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=168260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=920052;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=810885;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48199 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=50655;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=572545;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=119346;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=307205;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=3899;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=977740;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=918010;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=456298;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=252863;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=86357;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=952089;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=807252;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48200 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=13137;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=258319;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=538354;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=403022;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=953821;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=881439;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=467714;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=177878;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=226060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=239346;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=910078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=293345;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48201 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=102913;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=772703;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=97511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=672690;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=698110;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=882196;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=355846;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=794986;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=529915;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=189029;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=289144;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=120816;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48202 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=175692;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=270656;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=53369;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=276475;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=987464;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=598753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=351836;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=92562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=180747;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=959669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=911688;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=202428;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48203 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=253598;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=197509;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:49 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=964707;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=323623;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=486658;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=847190;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=44831;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=122100;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:17:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=626210;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=775341;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=19722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=396725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48204 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=260062;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=268881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=876806;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=998081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=925014;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=203792;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=532292;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=757713;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=678428;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=478825;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=647865;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=473610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48205 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=377224;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=692350;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=736675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=613773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48206 - "GET /api/mcp/W785k0?edit=true HTTP/1.1" 200 ]8;id=19173;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=575247;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:56 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=497610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=339730;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=778441;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=70851;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=614237;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=915694;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=689340;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=140535;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=14998;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=629945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48207 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=199661;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=930562;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:17:59 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=402882;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=546892;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:18:00 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=314936;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=955684;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=463522;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=800925;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=264481;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=711733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=582182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48208 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=57337;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=625221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:03 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=549523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=521774;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=518304;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=159777;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=452182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=600920;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=609118;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=884125;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=104162;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=73910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48209 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=846018;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=314350;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  deactive_mcpservice() - [MCPServiceManager] MCP服务无进程 ]8;id=296394;file:///home/zjq/euler-copilot-framework_1/apps/services/mcp_service.py\mcp_service.py]8;;\:]8;id=329917;file:///home/zjq/euler-copilot-framework_1/apps/services/mcp_service.py#366\366]8;;\ +  INFO  update_template_status() - [MCPLoader] 更新MCP模板状态: W785k0 -> MCPInstallStatus.INIT ]8;id=179691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=566797;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#390\390]8;;\ +  INFO  send() - 124.70.231.34:48210 - "POST /api/mcp?Content-Type=application%2Fjson HTTP/1.1" 200 ]8;id=791699;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=503157;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:04 INFO  send() - 124.70.231.34:48211 - "POST /api/mcp?serviceId=W785k0 HTTP/1.1" 500 ]8;id=970310;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=86710;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=498021;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=709301;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-4577' coro=<MCPClient._main_loop() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    +  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   +  │ __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=322927;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=779032;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  task: <Task pending name='Task-4578' coro=<Event.wait() running at    +  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=937095;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=322051;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-6935' coro=<MCPClient._main_loop() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    +  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   +  │ __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=712365;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=907769;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  task: <Task pending name='Task-6936' coro=<Event.wait() running at    +  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   +  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=87390;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=528830;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  future: <Task finished name='Task-9248' coro=<MCPClient._main_loop() done, defined at    +  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    +  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   +  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   +  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   +  │ │   +  │  81 │ │ # 创建Client、Session │   +  │  82 │ │ try: │   +  │  83 │ │ │ exit_stack = AsyncExitStack() │   +  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   +  │  85 │ │ │ self.client = ClientSession(read, write) │   +  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   +  │  87 │ │ │ # 初始化Client │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   +  │ │   +  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   +  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   +  │ 649 │ │ │ │ │ │ ) from None │   +  │ ❱ 650 │ │ result = await _enter(cm) │   +  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   +  │ 652 │ │ return result │   +  │ 653  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   +  │ │   +  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   +  │ 208 │ │ del self.args, self.kwds, self.func │   +  │ 209 │ │ try: │   +  │ ❱ 210 │ │ │ return await anext(self.gen) │   +  │ 211 │ │ except StopAsyncIteration: │   +  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   +  │ 213  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   +  │ │   +  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   +  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   +  │  42 │  │   +  │ ❱  43 │ async with anyio.create_task_group() as tg: │   +  │  44 │ │ try: │   +  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   +  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   +  │ __aexit__ │   +  │ │   +  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   +  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   +  │  771 │ │ │ │ │ # for each nesting level. │   +  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   +  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   +  │  774 │ │ │ │ │ ) from None │   +  │  775 │ │ │ │ elif exc_val: │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   +  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=697550;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=933544;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  task: <Task pending name='Task-9249' coro=<Event.wait() running at    +  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   +  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=938522;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=375977;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ +  task: <Task pending name='Task-12134' coro=<Event.wait() running at    +  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=831420;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=59960;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:346 in app │   +  │ │   +  │  343 │ │ │ │ validation_error = RequestValidationError( │   +  │  344 │ │ │ │ │ _normalize_errors(errors), body=body │   +  │  345 │ │ │ │ ) │   +  │ ❱  346 │ │ │ │ raise validation_error │   +  │  347 │ │ if response is None: │   +  │  348 │ │ │ raise FastAPIError( │   +  │  349 │ │ │ │ "No response object was returned. There's a high chance that the " │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  RequestValidationError: [{'type': 'model_attributes_type', 'loc': ('body',), 'msg': 'Input should be a valid    +  dictionary or object to extract fields from', 'input':   +  b'------WebKitFormBoundaryAIGBXkBO7yWnYuGc\r\nContent-Disposition: form-data; name="icon";    +  filename="openEuler.png"\r\nContent-Type:    +  image/png\r\n\r\n\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe2\x01\xd8ICC_PROFILE\x00   +  \x01\x01\x00\x00\x01\xc8\x00\x00\x00\x00\x040\x00\x00mntrRGB XYZ    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00acsp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tdesc\x00\x00\x00\xf0\x00\x00\x00$rXYZ\x00\x00\x01   +  \x14\x00\x00\x00\x14gXYZ\x00\x00\x01(\x00\x00\x00\x14bXYZ\x00\x00\x01<\x00\x00\x00\x14wtpt\x00\x00\x01P\x00\x00\x00\   +  x14rTRC\x00\x00\x01d\x00\x00\x00(gTRC\x00\x00\x01d\x00\x00\x00(bTRC\x00\x00\x01d\x00\x00\x00(cprt\x00\x00\x01\x8c\x0   +  0\x00\x00!\x8a\x   +  d9\xab\x1fl\xad\xb5\xdbk\xa6hV\xf3w\xb7\x1c\x12]\x17\xcek\xe6\xda\xefn\xebU\xab:\x16\xb3J\xdb\xa7\x14^\x19\x8e5Mj\xf   +  f\x00U\xb8\x95K\xcb\x9a\x93\x8b\xf8\xb2y:\xb7\xfaN.\x1e^\x07\xa7\xe0\xf4\xca\xc7\x9b4\xb2g\xdb\x9ds\xa8WugQ\xd5\x9dn   +  7\x9f\xceI\xbc}\xa5\x9e/)\x89\xbe\xbe\x1d\xc5\xbaX\x9byX\x19\xc4\xda]\x0e\xcdp\xd6\x9e\x9a\xb6\xbe\xd7*\xcb\x8dtH\xb   +  6\x91[(}L\x93,3\x1a\x18\x00\x85v    +  \xc19D\xa5\x18+\x8c\xb1\x1c`\xa5`\x95\xd4\xa4\xd7r\x10\xf3^q\x9fYEX\xb9I5\xcb\xd4\\\x06X\xad{u)\x89\xd3\xb0\xd15\xcb   +  \xed"\xe25m\xaa\xcf\x93\xce8\x9e\x0c\xdb\xb0\xdb\xe8\x8bt\xed\xf5\x99\xc2\x9b\xe9\xcb\x99\x80Y0\x92R\xe4\xb1%\xcf\'#   +  \x97\xc2\xae_P\xd9\xc5\x97M\xf4\xd9\xfdn\xcfU\xb5\x8dkJ\xbcqh\xed\xdc\xdb\xe8h\xde\xcb\xed\xc6\xa9\xa1\xdd\xc2P\xadV   +  t\xa3\xf13\xc8\xcf\xbb\r\xbd\x9bMEB\x95\xe5HR\x9c\xb9sg\x9b\xe4t\xebb\x99\x98o\xd34i\x99\xd3e|G_c}B\xea\x84jQ\xa8\xa   +  7\x17\xd1\xa3\x95\xc6\x97Vr2c\x9a\xcb,e\xda\xf2eI\x96\xa3$\xfa\x15\xa7\x82\xb1:^\'j\xf2IG\x12%4^%e@\x8c\x92XH\x00\x8   +  4\x80\x01\x00\x00$0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x0   +  0\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00dd\x01\x19\'$"\x92!\x96\xd9q\xf4-K)\x8f+D\xe9L\xde9\xf5-y\x   +  cf\x9f\x17\x9b\xe0U^\xb5:t\xa5)\xca1\xc7\x8b\xc1\x8e6\xc7y\x9af\x84\xa7M\xd4\xcdn\x8b\x85\xe5d\xcf\x8f\x05\xb2N\xa1\   +  x83.X\x87\xbd\xbc\xd4m\xech\xca\xa5z\xb0\x82K\xa3x1.\xdco\x87O\xd3\x1dJv\xb0u*\xae\\Py0\xee\xdao\'T\xd6\xee*B\x15\xb   +  f\xab\xbe\x98\xe4c\xca\xeeUf\xe596\xdf\x8b;\xbcn\x95:\x8bY\xa3\x97\x93\xb8\xd4=V\xd7\xed\x9e\xa1\xaf\xd4\x94\xe5q/#.   +  |\x0c\xf2I\xe5e\x94\xc6\x1c/(\xb9\x9c\x9d\xee?\x1f\xf1\xfd9\xf3(    +  \x91\x83z#F\xc8\xf2\xe8U\x8e\xf21\x80\x11\xb4\xe4\x13\x82\tD\xce\xc0\xc0!\x08\x03\xbc\x92\x12\x13\x82\tD\tD\x90\x89\   +  x02\x08}J\x8aq\xcci0\xa2M\xae\x85\xea\x15\xbc\x9e%o\xf9\xba\xab\xe3\x14\xf2)q\xf01d\xc3\x19!\x922L2\x1e\xc4o;S\xd1\x   +  ebB\x85\xedy\xd5\xa3\x17\x8c#b\xb6?o\xf4\xcdr\xde\x1cuaNmt\x94\xb9\x9aa\xc2\xa2\xf33\x97\xa6j\x17\x1671\xa9B\xa4\x92   +  O+\x99\xc8\xe4\xf4\xa8\xbcxe\xaef\xfe\xd1\xadN\xad>*RN>)\x97a\x9e\xf7\x93Wv;{\xf7\x96J\x9d\x1dN\xaeh.\\\x973=\xec\xe   +  6\xd5\xd8\xeb\x16t\xaaZ\xd5\x8f\x9c\xb3\x87%\x93\xce\xf2x\x16\xc7\xee\x1b\xf8\xb2\xc4\xbdQT;\xce\x1d\n\x95%.&\xd3\x8   +  3\xe9\x83\x97\x13N)\xdb\xe1\xb5\x13\xb5h\xa9\x14&U\x91+*\x059%\x15\x12\xd9\x19\x00@\x90\x01    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x19)\x93\x0c\xa5\xb2$3\x828\x88\x93\xe4Q\x92;\xa3\xec\xdc/E\xe49$q\xf3%\xcd?\xd8uZ\xce\xb   +  9e\xa7R\x95K\xab\x88SqY\xc4\x9fS%)\xdf>\x14\xb5\xe2\x1d\xd3\xab\x1f\x13\xc8m^\xd9\xe9\x9a\rY~Sp\xa3U/E\x98\xafo\xb7\   +  xcdN\x959\xda\xe9\xf4\xd3\x93\xe5\xe5    +  \xff\x00\xe4\xc0\x9a\xee\xd0\xdf\xeaWrw5\xeaUr\xe7\x96\xfa\x1dn\'L\x9b\xce\xed\xe9\xa7\x97\x931\xf1d\xfd\xe2o\x92\xe   +  e\xfeU-t\xde\x17M\xf2\xe2\x8b\xc31%\xe5\xed\xcd\xf4\xddK\x8a\xb3\x94\xa5\xe3,\x9cO&\xf8\xb8\xa5\xd5\x97\x0e\xf6\x1e\   +  x1dq\xfa\x86\x95\xf3\xcd\x88.\x1eY\xc9,&\x0e\xbe9\x88\x8di\xaf1\xb9\xda\x02$\x94[\xd8\x0f\xd82TU\x1bR\xc1$\x81\x19    +  \x96A(\x00\x00C\' \x15J2J`\r\x1bNFH\x19\x1a6\x91\x92224\x84\x93\x9c\x14\xe4\r\n\x9e\'\xe9\x14\xc9pz<\xc0&    +  \x85\xb9Jr\xe4\xf9\x1d\xe6\xce\xed.\xa3\xa3V\x8c\xa8\xd5\x9b\x8c_$\xe4\xf0t\xf8\x1d\xc6\xb6n-s{e\xaeY\xaf\xa6\xc8\xe   +  e\xf7|6\xd7\x0e\x145\xda\xb0\xa1\xdd\x16\xbb\xd9\x9b4\x9d^\xd7R\xb6\x8dkZ\x8at\xdfFh\x04\xa37\x89S\x93\x8c\xa3\xcd4z   +  \xed\x90\xde\x16\xb1\xa0W\x84[\xadqI|\\\xf2<\xf73\xa5\xc5\'uob\xe4\xcc\xb7\x92-4R\xe6\xb3\x8c\x98\x9baw\xb5\xa7\xea\   +  xb4\xa1J\xf2T\xed\xea\xf4\xc4\x9f3\'\xda\xdd\xd1\xbc\xa5\x1a\x94\'\x19E\xf3M\x1c\x0c\x98\xedI\xd4\xba\x18\xef\x16\xf   +  6\xe5\xa9s+\xe2H\xb1\xdc\x13q\xee\xe2(\xc9i\x8f\xa7\'9\x05\xaak\x0b9.\xa2\x15\x89H\x00$\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\   +  xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08r#bAG\x11*Dw\n\x88c$9`\x98\x9d\x   +  a2F[\x93\xc1\n\xb4d\xf0\xb2[\xadV0\x8b\x94\xa4\x92^,\x99\xac\xcf\xa6+^!2\x97\x89\xc5\xba\xbd\xa1kI\xd4\xadR0\x8a\xf1   +  x\x87Y.|+<_\xff\x00\x87\x7f\x87\xd3#\xba;\xdc\   +  xdc\x99\x9c\x8b\xeb\xeb\xdb\xdb\x89U\xb8\xab:\x9c\\\xf1)d\xe299zK\x87\xd4\\\x92qK\x85\xf1|\xc8\x86\xd2\xe5>O\xe7=\x1   +  6<\x14\xc5\xf1`\x9c\xbbYqI\xf2\x93c\x05R\x8bO\x9a    +  \xb4\xfbc\x9bl!\xf5*\xc1\x1d\xe2\x15B\x0c\x90N\xc4`\x12C%;\x02\x04\xa2\xc8\x18\xef\x0c\x8e\xf0$\x94\x10DJFGqS)k\x91\   +  x00\x08\xef$    +  \x00\x00\x00\x00\x00\x00\x00\x00d\x90\xc9\x00\x00\x00\x00\x00\x00\x00R\xca\x88\xc6J\xc8\xa5\xac\x95E\xf0<\xc6M\xb2\x   +  1a\x18\xc31[\x0fz\xd0\xef4=\xa4\xd54\xdb\x98T\xb7\xabS\x86/\xd1R\xe4\xcc\xe7\xb0\x9b\xdf\xa1_\xc9\xda\xea\xf5!E\xf4\   +  xcey\x9a\xe5\x1a\x93\x8fD\xc2^w\x1a\x9f\x0c\xd74\xceg/\xa6\xc4\xc6\xf4\xdd\xc5\x9b\xb64\xdfm/R\xb5\xd4-\xa3+:\xbeV2]   +  N\xce\x85?&\xb9\xb7\xcc\xd2\xbd\x8c\xdb\xcdOC\xad\x0e+\x8a\xb5)\'\xe8\xe4\xd8}\x8a\xde\x85\x86\xb3\nq\xb8\xa9\n5zp\x   +  c9\xf3g\x9a\xcd\xc2\xbd\'\xd3k\x1eX\xb4\xb2\x9a*G\x12\x85\xe5+\x8aq\x9d\t\xa9&\xb3\x94rb\xf2\x8d\x1bW^\xdb1\xe1^I)*"   +  \x16\x81\x01\xde\x18H\x08\x00\xda\xa4\x08\x89!    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i   +  \xbe\xab\xf8\xaa@v\xa3\xf8\t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C`Ce.X\r\x96\xdc\x8aM\xa7j\xcd\xb4\xb9\x1a\x89\xbcd\x8a\x92\x   +  e1Y8\x93\xa9Iq9K\x18\xf9\xcf\x15\xb6;\xc4\xd34\n2\x8dj\xdez\xe4\xb1\xcf\x99\xb1\x8b\x15\xaf:\x88W\xf2C\xd9\xd6\xd4h\   +  xd2M\xd5\x92\x82]\xf2x1\x9e\xde\xeff\xc7C\x84\xe8\xdb\xb9N\xab\xe4\x9d7\x9c}\x86\x18\xdb}\xeak\x1a\xadI\xd3\xa0\xe0\   +  xad\x1fF\xb93\x1dN\xeaW^R\xac\xe7)\xcf\xab\xe2y;U*\x8a\x0f\xcc\xe4\xc7\x14f\xf3Q7/\x12\xdb\x05\xf5\xa4B\xb77\'\x87\xd1t    +  \x81\x96\x04\xb6Gx\x00\x00\x00\x08d\x82E%H\x02v\x0c\x00H\x9c\x8c\x84IT\x8c\xa5\xe4\xa8\x80mN\x19$\x80\x84\x02@\x10\t   +  d\x00\x00\x00\x00\x00\'$\x00\'#$\x00\'#$\x00\'#$\x01\x02r@\x19b`\x00\x05\xab\xe1;Jmt!\xc1>o\xa91%\x91o\xdb\xda{\xa5J   +  n=\x19z\xd2\xb5Kj\xca\xbd\xbc\xd4+\xc7\xa4\x99d\xa2t\x94\xfa7\xc4k_\x8bKG\x96|Y;gl\xb3\xb1\x1b\xdc\xd44y\xc2\x8e\xa7   +  V\xa5j]<\xc4\xfa\x1b\x0b\xb2[w\xa7k\xb6\xb0\x9d)\xa8I\xae\x92\x973I\xa8\xd5t\xa0\xe9\xcd.}\xe7c\xa3kw\xda=\xd2\xabmR   +  X\xcf%\xc4\xce\x1f/\xa6\xd2\xde\x9b\x7f\xc8o\xbd\x1b\x88UY\x8b\xca\xf5\x97<\xaa5\x9fb\xf7\xcd:\x15)\xd1\xd6\xa6\xa3G   +  \xa6b\xb9\x99\xd3g\xf6\x9a\xcb^\xb7\x8dk\x1a\xaaT\xf1\xde\xce\x16n\x1d\xf1{\x8f\x0c\xf4\xcb\xdc\xf4\xaa\xa6I\xe3,A\x   +  a6\xb9\x15\xa3B\xdb\x89l\xc4\xf8]\xe2\t\xe5\x94\xa2\xa4<\xa5Rx*L\xa3%H\x91    +  \x02R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\   +  x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef"O\x11l\xa1TMe\xf5    +  VNKq\x9e{\xb0O\x11*\xef\xca\xa6\xcbre5*\xa8\xe1`\xeb\xb5\x1d^\xd6\xc6\x12\x95\xcdXS\xc2\xefe\xabY\xbf\xa2m\x10\xe6\x   +  d5\x97\x0cr\xfa\x1eo^\xda\xbd3I\xa5\'qs\x18I.\x8c\xc6\xdb\xc6\xde\xed\xb5\xa5\x1a\x96\x9a\x7f\x9dS\xfb\xc83\x01\xeb\   +  x9bQ{\xabV\x94\xae*\xceQ}\xcc\xea\xf1z^L\x9f\xb5\xa1\xa3\x9f\xe2\xecd\xd2\xc7q\xe9\xb8\xdd?\x1d#\xcb\x04\x   +  e7^m\xb5\x86\xf9\x14%\xc3\x94\xb9d\x85"M\xc8\xc5Z\xfaj\xe4\xc9\xb4\xe0`d\x93$0\xed\x0f\xa1K*l\x86JT\xb2\t\x04J@\x00@   +  \x00\x00\x00$\x00\x00\x02\x01\x018C\x081\xcc%\x08\x9c"\x9c\x95\xacx\x90\x00ex\x8c\x8d\xa7@\xe4:\x81\xb5NC\x91\x12\xf   +  9\x87>\xf1\x1e@\x86K \x99\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x01    +  \x00\x02bTS\x12\xa2\x042;\xc9\x04Jv\xa6Q\xcf6R\xf2\xber\xe0\xc7#\x1c\xe3\x89\xf6E\xa4\x8c!%\xc5)b^\x07}\xb3\xdba\xa9   +  \xe87\x10\x9d\xbdJ\x92\xa7\x1f\x8b\xc5\xc8\xf3\xcda\x86\xfc\xdc\x1a\xf9\xb0V\xf5\xd6\x99\xa9\x92b[=\xbb\xfd\xefP\xbe   +  \x84i\xea2\x85)t\xe6\xcc\xc1\xa6\xea\xb6\xda\x8d\x15V\xd6\xa2\x9c_L\x1a\x05J\xa5J3\x8c\xa9I\xc5\xa3\xdelN\xf1\xf5\x1   +  d\x12\xea1\xa9V\xa5J+\x0b\x87=\x0f=\xcc\xe9\x9a\xfd\xa9\x0e\x86<\xde4\xdc\xf5R_$\xae-\xb3\x19\xec^\xf2\xf4\xedf0\x85   +  z\xd0\xa3Q\xf7J\\\xcc\x87kwJ\xe2\x1a\x8dw\x18\xb3{[p\xf4m>\xad\xb5\x94\xa2\xee$\xb9&l\xe2\xc79   +  &+\rk[\xcb\x9d\xb6\xdb\xce\xd3vuN\x9dI9\xd5|\xa3\xc0\xf3\x86k\x8e\xddo+U\xd7.\xaa*u\xa4\xad\x9b\xe4\x9ay<\x9e\xaf\xa   +  8\xcfR\xbd\x95\xc5\xd5Y\xba\xed\xe5\xc7\x89\xb4q%/(\xf8\x9aG\xa4\xe2t\xce\xcf-\\\x99US\x94\xabA\xd4\xaa\xf3&\xc9e+\x   +  97"N\xfe*vWN}\xed\xdd*pN\x03$\xc8\xa6\xc4T\x88D\xa0\x84\x92S\x92r \x19ISd2E \x02%    +  \x040$\x11\x81\xde\x12\x90\x01(\x00\x00\x02\x00\x03\t\xe0\x02\x16\x88\x1c\x93X!A.r\xe80S<,d\xc394\x98\x85\xc4\xa2\xf   +  a&9"\x98T\x92\xe5\x18\xe7\xf6\x1c\xaa67wo\x14\xe97\x9f\x98\xc5~LS\xdb$Q\xc7!\xac\xf7\x9d\xd5-\x94\xd5\xea,\xc6\xdf+\   +  xf6\x95Oeu(E\xba\x94Z\xc7\xac\xc7\xfc\xda\x7f\xab~\'D\xa3\xc1\xcd\xbc\x95J\xa2}\x0eM[\n\xb6\xef\xf3\x91\x92\xc1\xc3\   +  xad5\xc4\x94\x11\x9f\x1f&\x8aN9O0\\\x82\xab\xc0\xdf\n\xc1h\xda\x9b\xc5\xfd1\xcdt\xa8\x10I\x08\x00\x01\x00\x00\x00\x0   +  0\x01\x01\x84\x13\x01$ud\x93\x04\x80w\x01\x08\x00\x04\x89\x89QLJ\x88\x02\t\x04H\x00\x08\x14\xb4R\xca\xc8eS\n\x19W\x0   +  2\x8cx\xa3\xe90\\\x8d4\x96rR\xd5\x8bx\x96H\xbe\x91m}\xf9%UR\x82\x9ck\xa7\xe9w\x19s`\xb7\xb3}\xa6J\x9d-N\xac\xa7o\xd1   +  \xa8\xe4\xc4.|\xf9\xc5\x15q>\xe3G?\x06\x99#\xcb%s7\x8bfv\x9a\xcf^\xb6\x85{i\xa4\x9a\xce\x1b\xe6zH\xc9I\xf1.\x8c\xd2\   +  x8d\x80\xdb\x8b\x9d\x07Q\x82\xabQ\xaa\x1c\\\xf2\xfb\x8d\xb8\xd9\x1dr\xdf]\xd1h\xdd\xdb\xcf\x8a3\\\x8f-\xcc\xe2\xfe)\   +  xf0\xe8\xe1\xcc\xf4\x89\xa4T\x8e\x1cd\xf3\xe7z^\x076\x9f\xa2\xb2r\xab\xefM\xd8\xb6\xd2\x91Q\x08\x93"\x12\x80@\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\xa3\xf8\   +  t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18   +  \x0c\x8c\x90\x02\x06P\xd1[(l\xc7oi\xfauz\xe5\xcc,\xac\xea\xd7\x9b\xc6"\xcd+\xdeF\xd0\xd6\xd6\xb5\xea\xf9\x93\x84i\xc   +  d\xa5\xcf\xa9\xb3\xbb\xf3\xd5e\xa6l\x8dZ\x94\xb3\xc6\xde9\x1aus\'sq:\xd2y\x94\x9eY\xe8\xfaO\x1e/=\xd2\xe6\xf2-1>\x11   +  \x07\x14\xb9\xc57\xe2C\xc3yK\x01\x12z\xda\xc4G\xa7:o2\x84H\x05\xb6\xa0\x00 2J\xcb \x01<\xc9)\x02\x04\xb1\x92\x07y    +  \t\x0b\xa0\x0c\x11\x86H#B0\xc6\t\x04\xa4\xc3\x18`\x04\x18c\x0c\x00    +  \x98\xa4\xb2\xd9\x1d\xe4\xfajH\xac\xcaajS\xc2\xe2\xee+R\x8b\x86s\xcc\xa3\x19\xa4\xa0\xd6p\xce\xcfJ\xd2\xaakW\xf4m\xa   +  c\xa2\xd4\xa5\xc9\xb4\x8cW\xc9\x14\x8d\xcb5+\xb7\x1e\xda\xd6\xa5\xd4\xe3\x0bh\xba\x95\x1fr26\xc9n\xa7P\xd5\xf8*^S\xa   +  9F\x1dy\xa3.n\xe3u\xd6ZM\xad\x1b\x9b\xfaP\xabZI<\xe3\x9a2\xbd\xbc)[\xc1B\x95Q0\xfek\xaf8\xa2   +  =W\x7f\x81\x9b\xf7\x01\xb4\xb5hj2\xd3\xebM\xba1\x8f\x9b\x96a\x1f\x8a\xdb\xee=\x0e\xc1\xeas\   +  xd3\xf5\xcbi\xc1\xb4\xe75\x16ry\xfch\xb5&[Xg\xcbyh\xf9\xd0\x8c\xfcN]>\x87]\xa2\xcdV\xd3\xa8O9\xcc\x13\xff\x00C\xb0H\   +  xf1\x13^\xdb\xcb\xab\x8f\xd2\xe1=J\x17R\xa4Y\x99$\x90H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    +  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x06\x04\x00\x02\x14\xc   +  8\xb7.E\xd6[\x911\t\xfaa\xde\xd0\xf2\xe1\xd9*\x8d\xf8\x9a\x9dO\xcd\xe2\xf9\xcd\xb1\xed\x17\x1c\xec\x85Oh\xd5\'\x1eH\   +  xf5\x9d\x1a?G\'\x93\xed\x08\x92\x11\'\xa1s\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xde\x07x\x12\x00\x00\x00\x00\x00\x00\   +  x03    +  \t\x0c\x82{\x80\x80\xb9>@\xa6S\x8cZM\xf5)x\xff\x00\x13\x11\xb9SVn\x1e\x8f\x7f#g#\xaa\xe4\xed\xc7\xa8oa\xa3:\xd2q\x8d5\x95\xe6\xf   +  7"\xec\x13\xeb\xf1J\xe9\xd3\xc2\xe6K\x8f\x81\xe3\xad\xe5\xd4\xc7\x8e\x10\xa2\xb3\x92\xe4y\x14\xa4\xc9\xc3K,\xc7\xdb\   +  x10\xcf\xa8\x85dL\x88\xce$\xe52{UP\xf0\xc8\xc7"\xbe\x1c\xf4!\xc4\xa5\xad\xda\x8f\x0e\x9fht{mcO\xabmu\x0e(N8f\xb5m\xe   +  6\xe8\xabi\xf5jW\xd1i\xa5K9\xc3\xe6\xcd\xab\xc1b\xad\xb5:\x99\xe3\x84d\xbeu\x93w\x85\xce\xb6?Ml\xf8{\xfd4\n\xff\x00I   +  \xba\xb4\xb8t\xee-\xeb:\xab\xbdA\xe0\xb7\x1byF\x0f\x8e\x95O\xddf\xf4\xea{1\xa6\xdf\xc1\xc6\xa5\xa5\x14\xdf\xc6T\xd6O   +  /[u:5Y\xc9\xbc\xac\xf8D\xecS\xabx\xf2\xd4\x9c\x1et\xd3\x97C\xc2\x9dO\xddd\xd3\xb5\xad9b\x9d\x1a\x8f\xff\x00\x16n\n\x   +  dd\x06\x89\xf2\xa5\xfb\xbf\xf2v:~\xec\xb4k)\'\x18\xa9c\xc6%g\xaa\xaf\xfcYj\x05\xa6\xcf\xeaW\r([\xd5\xe7\xff\x00c;J;\   +  x0b\xacW~m&\xbdqf\xeaYhZ}\xb4\x14aiA\xe3\xbd\xd3G*Z]\x9c\x97+zK\xd5\x04a\x9e\xadm\x9f\xc5\x96\x95\xcfw:\xd4)q8/\xb0\   +  xe9/\xf6SU\xb3NS\xa36\x97\x84\x19\xbd\xbf\xc9\xb6\xc9c\xc8\xd3k\xe7\x8a,\xdch\xd65\xe9\xb8N\xd6\x8e\x1f\xff\x00\xad\   +  x11\xff\x00Zw\xe5Y\xe2\xd9\xa11\x84\xa8>\x1b\x8as\x8b\xf9\xe2\xd1fm96\xba\x1b\x85\xaf\xee\x8fE\xd5\xa7*\x93\x94\xa9\   +  xb7\xdd\x08\xe3\xff\x00\xf4\xc0[w\xbb=CB\xb8\xafV\xde\x8c\xa5g\x16\xda\x94\xb3\xd0\xeb\xf0\xba\x96<\x93\xad\xb0_\x04   +  \xd7\xdb\x1c\xa2s\x82\x1ajmx\x15c=N\xdcZ/\xe6\x1a\xd7\x8d#    +  \x9c\x13\x82\xd1\n\xa0\x13\x82\x1a-\x10i(\x04\x80\xd0\x00\x08\xdc\xc2\x0e\xe2\x19$H\x8e\xe9\x10A$`\xb4X\x11$"H\x94!\   +  x82C!*N\xcbg\x17\xfdb\xd3\xe9#\xf7\x9dn\x0e\xc7g\xbd\xd9\xb4\xfaX\xfd\xe6\x0edG\xe3g\xc3>[\xcf\xb2\x9e\xe3\xdb\xfb\x   +  0b\xee;\x94t\xbb+\xeeM\xba\xff\x00\xb1}\xc7w\x86|\xfb<\x7f\xe4\x99v1\xfaLz\x95"\x12\xc1(\xc4\xcc\x92H$\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\xa3\xf8\t\xdao\   +  xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x03\x02\x0   +  0\x01\x08}\n\x1a.2\x86L\'\xe9\x87{E\xbcl\x8dOh\xd5\x07,\xa3k;F\xfb\xd2\xa9\xed\x1a\xa0\xba\x1e\xb7\xa3|\x1c\x9eO\xb5   +  H\x92\x17RN\xfe\xdc\xf0\x00\x00\x00H\x00\x00\x00\x00\x0e\xf0;\xc0\x90\x08`H\x18\x03@\x06F@\x0c\x00\xc8\xd8\x82y\x90\   +  nM\xc1\x919E\xf0\xb7\x15\xe6\xf3$\xe7\xd8\xe97Z\x85ZT\xedhT\xa9\xc6\xf0\xdcVpV\xdc\xaab\x8d\xd9\x97\x1cyN\x8bm=_S\xa   +  7J\xd6\x8f\x1c\xa4\xd2j>\x06\xe0n\xb3e\xe9\xec\xbe\x85\x18\xac9\xd4JMc\xa1\xe2\xf7I\xbb\xaa\x1aLi\xdd\\\xd1^]\xae\xa   +  d\x19\x92\x9a\xc4U/\xb0\xf2]K\x99\xf9\xed\xaa\xfat\xf0\xc6\x9c\xd8IJ)\xf4%\xb4\x8e,\xe9UIp\xcd$\x8e\x16\xa7\xabZ\xe9   +  \xb6\xfcw5`\x9a\xf1\x96\x0e-)kKfrv\xbbg\xd3=\x0b\x15.iQM\xd5\xaa\x92^&\x1f\xda\xfd\xf1\xd9Xq\xd1\xb5\x8c\xa7>\x89\xc   +  1\xe4\xc3\xbbE\xbc\xedr\xed\xcf\xc8^\xca\x11\x97D\xfb\x8e\x86.\x9d{\xfbb\xb7#M\xaa\xd46\xafG\xb3\xfd=\xe5*~\xb6us\xd   +  e\x1e\xceC)\xea\x96\xf9]\xd94\xd2\xf3_\xd4\xef\x9bw\xb7\x0e\xa9\xc0s\x84\xa5\xc5(>/\x13\xa1\x8f\xa4Z}\xb0\xdb\x96\xd   +  d\x15\xbc\xfd\t\x7f\xf7(\xfd\xa7.\xc7x\xda\r\xd4\xf8]\xfd\x04\xdfvM%\xeb\xd3\x90\x84\xea\xd1\x9a\x95)bK\xbc\xc9~\x8d   +  \x1ab\x9ed\xb7\xf6\xcfW\xb1\xbd\x8av\xf5\xe1<\xf8\x1c\xde\\9\xcf#Ft]\xbb\xd7t\xba\xb4\xfc\x9d\xdc\x958\xbei\x19\xe3w   +  \xbb\xd7\xa7\xa8:t/\xe4\xddG\xcb\xceg77M\xb6/5la\xe4w\xb3dd\xa5\xd1\xe4\xa8\xe3Z\xd4\xa7V\x94gK\x1c2Y9\x08\xe6\xda\x   +  b3\x12\xd9\x8a\xef\xca\xa4N\x08Ei\x06X\x8d&+\x91(\x95\xd0r+"\x99.e%M\x94\xe0\xc7h\x99\x14\xb3\xa4\xd5\xb4\xdaZ\xbd\x   +  bdZ\x17\x14\xa2\xa2\xd62\xce\xf1\xa2\xdd\\p\xbf\x136\t\xb5\x1a\xb9a\xa6\x9b\xd7\xd9\xc5\xa1\xeb\x95\xa3J\tQ\xe2\xe4\   +  xd7C\xc1\x19\xcf\xb45j\x12\x9a\xa7\x1cyU>|\xcc\x18\x8fy\xd3/7\xc3\x13.F_gp\x083~gJD!\xbc!\x19\'\xd1\x89`\x9a6W\x15\x   +  a5\x8bzso\xe6F)\xcd\xa5\xe2\xa3Mu!\xc9.\xac\xe7\xd3\xd0\xf5Yc6\xb5\xe5\x9f\x083\x99Ke\xb5J\x91\xcf\xe4W\x1f\xb8\xcd{   +  \xf3\xebY\xd4\xca\xdf\x8d\xd1\xf1\xc7\xc4\xa9sGkq\xb2\xfa\xa5/\xfe\x95\xc7\xee3\x85SI\xd4\xa8\xa6\xe7i]%\xde\xe0\xcb   +  c\xe7R\xf3\xa5f\x9aq\xfa\x11\xd4\x89)\xc1\xb58I?\x9d\x04\xcd\x8f\xcdU41\x94\x19\x06H\x98\x9fJ\xa7    +  \x84H\x94\x00\x00!\x9d\x86\xcf\xfb\xb5g\xf4\xb1\xfb\xce\xbc\xec6{\xdd\xab?\xa5\x8f\xdek\xf3?\xad\x9f\x07\xb6\xf3\xec   +  \xc7\xb9\x96\xde\xc2\xfb\x8e\xed\x1d&\xcc{\x99m\xecG\xee;\xd4|\xff\x007\xce]\xac~\x80\x89\xc012\x84\x84\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\   +  x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  `0    +  \x00\x10\x87\xd0\xa5\xf4*}\x0bl\x98O\xd3\x0e\xf6\x8c\xf7\xa5S\xda5C\xb8\xdb\x0e\xd1k\xfb#S\xda5C\x1c\x8fY\xd1\xbe\x0   +  eO\'\xd8\x10\x08\xef\xc3\x9e\x90\x01    +  \x00$\x00\x00\x00\x00\x07x\x1d\xe0H`0%4\xba\xf4"i\xc99C\xd1]CI\xfaO\x08:\x9eE.\x1eqeo~\xd4\xc4nV<\xae_.\x85m\xcaX\xe   +  0\xe6s\xf4M\x16\xef[\xbf\x8d\x1bZNI\xbe\xe3:\xec~\xe4\xe9\xbaT\xee/\xe5R59>\x1e\xe3\x99\xc8\xea\x15\xc5\xf6\xd9\xa6\   +  x1e\xefM~\xa7\n\xce/4j7\xdd\x88\xb3\x91o\xa6_\xdc\xbf\xcdP\xa9\xfb`\xcd\xcd\xd2w\x7f\xa5YS\x8av\xf4\xa6\xd2\xf8\xd0G   +  yGf\xb4\xca},\xad\xd7\xfe\x08\xe7[\xadk\xd3   +  \xd0\x89\xbcs\xefE\xfd&\xe6v\xda\x85\x1a\xf0\x93RRY\xc3,Ie\x14P\x92\x8d\\M\xe1w\x1a\xbc\x9c1j\xf8\x86\xce\x0bv\xb7Sv   +  z\xc4\xb5]\x02\x94\x94\xb3$\x92=\xbcs$\xb0\xfdf\xac\xeeko\xe9\xe8\x97\x10\xb1\xbe\xa8\xa1m\'\x9e6\xcd\x94\xd2\xb5;}Z   +  \x9ckZTR\xa7\x8c\xe5\x1e\x1f\x9d\x82\xd5\xbc\xba\xd8\xb2\xf8v\xc8\xb9\x06[\x89W\x12]\xe7?\xcb7\xe4]!\xf4(RD:\x89ub"v   +  w\xc2d\xcbnO\xb8JI\xf48\xd7\x93\x8c)fR\xe1H\xc9\xd9\xbf\x08\x9c\x90\xb9:\xd2Q\xcfr<\xee\xd2m\x15\x1d\x1a\xc6\xad\xc5   +  \xd5D\xb8Vb\xb2u[W\xbc\x1d\'D\xb7\x9cgq\x1f,\x97(\xbe\xf3Y7\x83\xb7\xf7{A{,I\xc6\x8c_\x9a\xa2\xf94t8]>\xf9\'\xcbS6G\   +  x13x;A=\xa2\xda\x0b\x8b\x8ar\xcd&\xf9d\xf2\xae\\\x1dJ\xb8<\xb4|\xaep\xdfTS\tc\x92\\O\xe7=\x7f\x1f\x1cq1\xea\\\xdbGt\   +  x94\xdb\x94\xb8>3\xe8w{9\xb3z\x86\xb7s*6\xf4\x9eS\xc6Zx=N\xeb\xb6\x02\xe3ikyk\xa8J\x9d\x08\xcb\x9c\x91\xb4\x1b3\xb26   +  \x1a=\xa5*tiA\xb8\xafM\xc7\x9b9\x1c\xce\xaf\x15\x9dU\xb3\x8f\x0e\xd8[dw)V\xb7\rM^\x0b\xc9\xfc\xcc\xc9\xdaN\xeb4\x1d?   +  \x85\xd2\xa5.%\xe2d\'\x04\xa0\xa3\x15\x84\xbc\x02\\\x8e&N\xa1\x96\xf3\xf2\xd3n0\xc4:Km\x9b\xd3\xe8$\xa3F<\xbcb\x8e\x   +  c6\x8e\x9bk\x05\x85F\x9f\xee\xa3\x96\x93\xc9Z\\\xcd[f\xb5\xbd\xca\xd1\x8a\x1c\x1a\xbaM\xa5X\xf9\xd4i\xfe\xea:\x8dGd\   +  xec.\xe9\xca\x9c\xa8G\x85\xf5\xc4Q\xea;\x8a$\x85s^\xbebSl5\x98\xf4\xc4\xba\xb6\xe6\xb4;\xaau%N\x94\x95g\xd3\x9f#\x10   +  m\xa6\xe9u=-\xca\xa5\x9d4\xe8\xae~<\x8d\xb7\x92}\xc7\x1e\xb5\nu\xa2\xe1^\x9ce\x17\xe2\xb2l\xd3\x9b\x92\xbe\xe5\x8f\x   +  f8\xf5\xff\x00\x1a\x03\x7fesg6\xaa\xc2Q\xc3\xc74qr\xd3J]Y\xb6\x1b\xcd\xdd\xd5\rJ\x85[\x8bJ*2I\xbcE`\xd5\xddkN\xaf\xa   +  6\xea3\xa1u\x0e\t&\xd2G\xa5\xe0\xf3c$G\x97?.)\xac\xfaqP%$0wfbk\xb8`0C$3\x19\xa5\'a\xb3\xde\xedY\xfd,~\xf3\xafga\xb3\   +  xde\xedY\xfd,~\xf3\x073\xfa\xd9\xb0\xfbo>\xcc{\x99m\xec/\xb8\xefbt;1\xeee\xbf\xb0\xbe\xe3\xbe\x89\xf3\xec\xdf9v1zH\x   +  00\xc4\xcc\x94\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;   +  M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x000\x18\x10\x00\x08C\xe8[e\xc6Q!\x1e\xc9\x9f\x0c;\xda/\xde\x8dOh\xd5\x05\xd0\xda\xfe\xd1~\xf4*{F\xa8.\   +  x87\xac\xe8\xdf\x07#\x93>@\x81\'\xa0\x86\x88\x00$\x00\x04\x80\x00\x00\x00\x00\xef\x03\xbc\t\x0c\x00!\xf9\xdc\x8b\x96   +  \xb6\xf2\xbc\xb8\x85\xbc3\xc4\xde\x16\x0e<\x9c\xbc\xaa\x8c\x1e$zm\xdf\xd2\xa7[j\xac!%\x97\xe5\x17\x11\xcf\xe6\xe4\xe   +  d\xac\xcbc\x156\xd8\xcd\xcdle\xb6\x99\xa2\xd1\xba\xba\xa3\x19Wk\xe3.fX\xb6\x97\x1c=\x0e\x04\xb9`\xe3iV\xf4\xe9\xda\x   +  d3\x84#\x88\xa4\x8e\xcb\x87\x1d\x0f\x0f\xc8\xcd7\xbc\xed\xd9\xc3\x8e+\n\tL\xab\x84`\xc1\xe5\x9f\xf5R\xf9\x04N\x06\x0   +  6\x94\x98\x80\x87\xcc\xa8\x8c\x16\xf0F\x90\xde\x11\xe1\xf7\xa3\x7f[O\xd9\xbb\x8a\xf4\xf3\xc9w\x1e\xe5\xc7\'\x8c\xde\   +  xa5\x95]Cf.-\xa8\xf3mt\xc1zO\x98b\xc8\xd2\xddZ\xb4\xae\xb5*\xf5\xe7\xceS\x96K*/\x07#\\\xb3\xafc\xaaN\x9c\xe1$\xa3,>E   +  \x89\xcf\x97#\xdbpiX\xa499be\x1d\x01C\x99\x1c|\xba3\xa7Jy\xdc\xb5\xbb%Y%\x11\xa9\x97\xd1\xa2\xac\x97\x9dA\xdb#\x00\x   +  14\x9b\xc4#R\x896\xba,\x92\xaaAG\xce\xa6\x9c\x82\xcey<\x13(\xe3\x9b\xe7\xea+7\x89\x8d-\x111\xe4\xa3\tK\xf3\xaa\\\rtG   +  \xb5\xd9\r\xe2\xea;;QE\xd4\xa9^\x9a~\x8eO\x12\xeag\xa2\xc1o\x81g\'7?\x162\xb3W7ket\x1d\xf7R\xad\x8f\xcam\xd4=o\xfeOk   +  g\xbd\r\x1a\xe6\x92\x95K\x9a\x14\xdb\xeel\xd3g\xcd\x11\x84h\xcfG\xac\xf9f\x8eCt\xe3\xbc=\t>\'\xa9\xdb\xbf\x9b,\xe0\x   +  df\xefKG\xa5\x9f\'^\x8c\xfdL\xd3w\x08\xf5h\xaa).\x82:\x1c\xcd\xac]2\x94\xfaD\xf2\\\xdb\xdb\xeb\xcdZR\xa9wu7\'\xd1H\xe2   +  \xd3\xa8\xa3\xe6T\xa3\x9c|g\xdeB\x8f\x9c\x9f\x81rM\xcb\xa9\xbfN?g\xc5\xaf|\xdbZ\x93\x92\x9ec\xca\x1e\x07q\xb2\xda\x1   +  c\xb5\xedb\x8d*5x^SqK\xa9\xd5\xf9HRX\x9a\xca|\x8c\x83\xb8\xbat\xe9m\xbd:\x95q\xe4\xdc{\xcc<\xfb\xcdqN\xd9\xb0F\xfc\x   +  b6\x87d\xb4:\x1a~\x93kJ\xde\x9a\xa4\xd4\x12\x9e;\xd9\xe9a\x17\x0eM\xe7\x05\xabg\x1f\'\x19C\xa69\x17\xe3\x96\xf9\x9e\   +  x1e\xfa\x9byuqR!R\xe6JA"LV\x88e\xd4%"\xa4\x8aQRe"UOB\x19QK/\x12\x98Q(\xe7\xbf\x05\x18q\xe7\xe9\x17Z(\xc6\r|\xb6\x98\   +  xf4\xbf\x85\x9a\xb0W\x14\xdc%\x1c&\x8dh\xdf\xfe\xca\xabk\xef\xcbhS\xf3\x12\xcbi\x1b1Zj\x0f+\x9b0\xfe\xff\x00u\n\x14\   +  xf4*\xb6\xf3k\xca\xcdrY:\x9d2\xf6\xef\x86\xb7#\x1cv\xed\xab\x08\x94\x01\xefqO\xe8\xe1_\xc5\x92C\x19)e\xd1\xb43\xb0\x   +  d9\xdfv\xac\xfe\x96?y\xd7\x9d\x86\xcf{\xb5g\xf4\xb1\xfb\xcc\x1c\xcf\xeblb\xf6\xdem\x99\xf72\xdb\xd8\x8f\xdcw\xd1\xe8   +  t;1\xeee\xb7\xb0\xbe\xe3\xbe\x89\xf3\xfc\xff\x009u\xf0\xfaH\x00\xc2\xcc\x94\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x18\x10\x00\x08D\xba\x14H\xae]\n\x18\   +  xfbV\xde\x98w\xb4_\xbd\n\x9e\xd1\xaa\x1d\xc6\xd7\xf6\x8b\xf7\xa3S\xda5A\x1e\xaf\xa3|\\~G\xb1\x12\x01\xe8\xb4\xd4\x00   +  \x00\x00\x04\x80\x00\x00\x00\x00\xef\x00\t\x04dd\x08\x8c%\xe5\x95E\xd1\x1e\x83w\x95\xe1Gl\xac\\\xf3\xe7UG\x9f\x9c\xf   +  c\xc7\x15\xd5\x9e\xbbv\x9az\xbc\xda;\x19%\x99S\xa8\xb2rz\x84\xc7l\xb78\xfe\xdb\xa5\xa6\xd4R\xa1NK\xa3H\xec\xd7DuV\xb   +  0t\xad)/\x99\x1d\x959\xe5#\xc3d\x98\xfc\x8e\xddc\xf5V\xcaJ\xdb!\x92\x89P\xc1,\x05%\x18 \xab    +  +\xb5%\x9a\xd4#Y8\xcd&\x9f\x89\xc8    +  \x88\x9d\x13\x1ba\r\xe5\xee\xb5\xea.\xad\xc6\x99I:\x92\xcby5\xff\x00^\xd8\xfd[G\xa9(\xdcQ|\xbc\x13f\xf6\xb4\xa5\xc9\   +  xa3\xaa\xd4\xb4{\x1b\xa5\xf9\xdbZSo\xabq:\x98:\x95\xe9\x1d\xb2\xc1l[hD(\xd6s\xe1\xf2s\xca\xf1\x8b*\xc5X\xbcy9}\x86\x   +  ea\xea;\xbf\xd2n\x17\x15;jPo\xc2\'V\xf7]\xa5\xbe|\x10\xcf\xb2t+\xd5\xa5\x8ap\xb4\xf9F\xac\x9e\x159~\xe9\xcf\xb5\xd1\   +  xef.Z\xf2te\xcf\xe6f\xdb\xda\xee\xdfK\xb7\x9e|\x8d9z\xe2z\x1b\x1d\x98\xd3\xad\xe9\xe26T\x1f\xcf\xc2V\xddV~\x91\x186\   +  xd4+}\x83\xd6\xab\xa5\xc1G\xa9z\xb6\xee\xf5\xda0\xe2\x9d\x15\x83p\xa8h\xd6\x94\x9e|\x94\x17\xec9\x8e\xca\xcd\xc7\x0e   +  \x8d9z\xd1\x82\xddZ\xcc\xd1\xc5\x86\x89\xdfh7\xd6\x92j\xb5\x19\xf2\xf0\x8b:\xe5\tS\x9f\x0f\x0c\x93\xf9\xd1\xbew:\x06   +  \x9bq\t)XPy\xef\xe0<\x1e\xd4n\x9bJ\xd5\xa17I\xaa\x15z\xa5\x08\xe0\xcd\x83\xab\x7f\xf4\xad\xb8\xda\x86\xa5\\R\xa9N\xac\x94{\xac7\x8b\xd5\xc9\x9fi*\xc1J+#H\x94\x12\x18A\x12\x0c\x82\x19(2%\xcd   +  s\x081\xaf+B\x9cbI\xf7\xa3\xbb\xd0u\xcb\xfd2\xa3\x95\xa5\xd4\xa8\xae\xf4\xbb\xce\x95\xa2\x1a}\xc6,\xb8\xa3$jYk\x92a\   +  x99\xf6c|\xd5\xb4\xf7\x1aWt\xe7Y\xae\xb2l\xc9\x9a&\xf8\xb4\xeb\xb7\x15Z0\xa5\x9e\xf93R\x1d\x19qg(\xe4\xc5A%\xc5\x9f\   +  xd8\xce\x1f#\xa6V\xde\x99\xa3<\xb7\x82\xcfot:\xf0M\xdf\xdb\xc5\xf89\x1c\xd5\xb5\xda\x1b\x8eV\xa7o\xfb\xc6\x8a:\xb1\x   +  82\xfc\xdf\x12d;\xdb\x95\xca5\x1e=f\x9f\xfcy\x9fL\x91\xc8\x96\xf0\\\xed\xde\x85E<\xea6\xef\xff\x00#\xcc\xeb{\xdd\xd2   +  \xac\x1bt\'N\xba_&F\x9f\xd4\x94\xea\xaf>M\xfe\xd2\xca\xa3%/5\xf9\xbe\xb3%:<}\x93\x9d\x9ev\x9f~\x95o8\xe8\xd9\xdbT\xa   +  3\xdd\xc4\x9f\xfc\x98\xc7_\xda\xbdGYN5\xee\xe6\xe0\xfb\x9b<\xd2XXqe^J/\xb8\xeb\xf1zu1\xc7\xa6\t\xcfi\xfbS\x18F\x1d\x   +  1a*\x8c\x9cSQ|\x88\xe0K\xa07?\x15k>!\x8am\xb3\x1c\xf3\xdeU\x9c\xf5    +  w\x19!IJ\xc1\x0c~\xc0\xcbB\x03\xb0\xd9\xefv\xac\xfe\x96?y\xd7\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb\xcd~g\xf5\xcbc\x0by\xb6c   +  \xdc\xcboa}\xc7}\x13\xa1\xd9\x8fs-\xbd\x85\xf7\x1d\xf4O\x9f\xe7\xf9\xcb\xaf\x87\xd2@\x06\x16d\xa0\x10\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\   +  x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00    +  \x00\x10\x87\xdeS"\xa6R\xc6\xfc\x93\xe9\x87{E{\xd1\xa9\xed\x1a\xa3\xdcm\x7fh\xafz5=\xa3T\x17C\xd6ti\xfd\\~Dy\x10\x00   +  \xf4-    +  \x02:\xb0$dr#\x8b\x02$NFDc\xe5;\xf0[\xa9\xf9\xa9\xa8\xc5\xf17\xdca\xcb\x9e1\xadZ\xcd\x95\xe4\x1d\xc6\x99\xb3\x1a\xbe   +  \xb0\xa1\xf9\r\x9c\xea.\xfc\x19\x1bf\xf73}\xa8(\xca\xf7\xca\xd0\xf9\xb0sr\xf3\xeb\x1ev\xd8\xaf\x1ae\x88Ro\xa2l\xbbom   +  V\xb5h\xc6\x9c$\xe6\xfa,r6gF\xdc\x9d\x9d\x94\xa3*\xd5\xddLwI\x1e\xfbE\xd8\x8d\x1bO\x8f;J\x15%\xdc\xdcN~~\xa9\xfa\xfe   +  \xac\xb5\xe2\xccN\xda\xd5\xb3;\xad\xd56\x81\xd2\x9d\xd5\x07\n-\xe71m\x19\xfba\xf7a\xa7\xec\xf5(5\x0e9\xa5\x9f=d\xf7\   +  xb6\xd6t-\xe2\x95\nQ\x82]\xc9\x1c\xa8\xe5.\xa7#/2\xf7\xfbn\xe3\xa4C\x8bF\x94i\xc7\x821Q\x8a\xf0X.\xa8\xe7\x94\xbd\x1   +  e\xe6V\xd2\xc9\xc7\xbf\xb9\x85\xa5\xb4\xea\xd4iF+&\xa5m7\xb6\x99\xed\xa8\x85\x9dJ\xfe\xdfM\xb4\xa9V\xac\xf0\xa1\x17\   +  '\x93\\\xb7\x87\xbd\xaa\xba\x8dj\xb6zt\xe3\xf9*n.K\x93\xc9\xc5\xdf&\xf0*\xea\xb7\x95t\xcb\n\xae\x9ci\xber\x83\xea\x8   +  c2\xa5\x96\xf9\xe5\xe7\x99\xe8\xb8\x1d7z\xbd\xdc\xec\xd7\x98\xf4\xe6j\x17\x95.\xa79:\xf5g9<\xe2Rl\xe0\xc2U\xa9\xfaqE   +  is\xcfyS\xe7\xd4\xefS\x8dJ\xfd5\'$\xa3\xcbN]b\xb1\xf3\x10\xe9\xd2|\xe4\xdeI\xc7\x81\x0e&~\xd8\x88\xf0\xa4\xdeTz<\xa9   +  \xf3\xf5\x97a\x18\xd4Xy\xe2]\xc5)a\x93\x1eO+\xa9Y\x89Gr*Fu\x17\x92K\x92/Y\xb8\xdbT\x8b\x95I\xd3i\xe70x(\xcb\xce{\xc8   +  \x92\xcf^f\x0c\xb8"\xd1;g\xc7\x93M\xaf\xdcf\xd5S\xd6\xb4\xb7m\x1a\x8en\x82Qm\xf52\xef\xc4F\xa9v|\xd5!a\xa8\xd5\xa1)(   +  \xca\xb4\xb0\x97\x89\xb54\x9bt\xa3\x9e\xa7\x89\xe4\xe3\xec\xbc\xbaX\xaf\xb8W\x12\xb4Q\x12\xa3Z[\x11\xe1^y\x04B\xf9\x   +  c9+&\xd2Gx\x05$D\xb9\xa6Y\x97\x9c\x92]Qu\x96\xe4\xb9\xe4\xaf~\xbc\'~\x14\xd4\x8ec\x95\xd4\xc3\x1b\xfc\xd5i\xd9\xe9r\   +  xb5\x93\\Uc\xc8\xca\xfa\xde\xa3GL\xb0\xa9qqQB\x11]Y\xa7\xfb\xe0\xdb\x19\xed\x16\xb4\xa0\xb9S\xa4\xdcSO\xaa;\x1d7\r\x   +  b2\xda%\xa5\x9e\xde\x1e\x03\xabeH\x84I\xec\xf8\xf8\xad\x8a<\xb9R\x15\x10\x91&\xce\x95\x999\x92B$\x84\x042@\x11\xe0K\   +  xeaAV\x02\xcaB*\xc2\t\x11$\x98]\xe4a.q\'\x19\x18\xe6SJ\xa8r\x93\xea\x81[)h\xb4j\x16\xdc\xa9\xc1TV9\xae\xa0\x94\xb0D\   +  xca&W<\xadlp\xf0\xc7\x87\xc7\x05=:\x92\x99\x12\x1f\xb1\xedK    +  \x96A:\x90\x1f\xb4\x02}\x00$\x86;\x90\x1d\x86\xcf{\xb5g\xf4\xb1\xfb\xce\xbf\xbc\xec6{\xdd\xab?\xa5\x8f\xde`\xe6\x7f[   +  g\x0by\xb6c\xdc\xcboa}\xc7}\x13\xa1\xd9\x8fs-\xbd\x85\xf7\x1d\xf4O\x9f\xe7\xf9\xcb\xaf\x87\xd2@\x06\x16d\xa0\x10\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa   +  8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00    +  \x00\x10\x89\x14\xb2\xa6R\xc7\xdag\xd3\x0fv\x8b\xf7\xa3S\xda5At6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa\x0b\xa1\xea\xfa7\xc5\x   +  c8\xe4\xfb\x00@\xf4M\x042H\x05fD\x94\xceJ\x0b-d\x9c\x9d\xe6\xcal\xc5\xee\xd2_\xc6\x85\xa4\x1e3\x96\xda\xe5\x83_>X\xa   +  5&v\xc9\x8e\xbd\xd6\xd3\x87\xa2i\x17Z\xc5eN\xd2\x12\xcb\xe5\xc9\x19\xbfw\xbb\x97\xe0\x94.u\x8a\xb0\xac\xa5\xe7(It2\x   +  16\xed\xf7{\xa7\xe8\x16\x90\xabZ\x8f\xf5\x85\xd5\x99\x066\xe9\xb5\xe4\x96\x12<\xa7+\xa8M\xa6b\x1dl\\h\x87O\xa4l\xa5\   +  x96\x90\x97\xe4T\xe3M|\xc7\xa0\xa5\x05\x08a!\t\xe7\xcc}Qq,\x1ck\xf2-y\xf2\xda\xfcq\n\x14y\xf9\xdc\xc9p\x8fr*$\xbcL\x   +  a3\xb5m"\xa4\xb9\x15p\x8c\x04kN=\xc5GN\x98v\x80O\xed\x01Y\x95=\xe4\xa1\xde0\x08H`\x89<\x111\xb8\   +  xd2\xf1.\xefb\xf5\x85\xa3m%\x9d\xd5^P\x84\xf2\xd3\xef7?e\xb6\x92\xd7\\\xd3i\\P\x94s%\xe8\xa6h}u\xe5\xda\xe2\xf8\xbd\   +  x0c\x83\xbb\x8d\xe0\\\xec\xe5x\xd2\x9dG\xf9\x19d\xd6\xfd\xc3\xedE*UU\xa5\xc4\xf8q\   +  x85\x1c\xbc\x1b#J\xacjSR\x8bM5\xdcx\x9e\xa3[~I\x97W\x0c\xc4\xc2\xe1Re9\'\'9\xb5\x1a\x1b\x19\x00\xb6\x93\xe0\x19\x0c\   +  xa1\x89\x84\xf8V\x999-\xe4\xa9>EM\xc2*\xf4\xcfy\xd6\xea4iW\xa5\xe4\xae)\xf9HO\x93Gc.da\x13[LJ\xb6\x88\x96\x16\xdb\xa   +  d\xd1Zj\xb2\x95{\np\xa37\xcf\xa1\x876\x8bu\xfa\xa6\x9fRT\x94%W\xe7\x8cM\xccqMsE\xa9[R\x9b\xf3\xa1\x16\xfett0\xf3\xef   +  \x89\xad|\x11-\x0c\x9e\xc9\xeb4$\xe3\xf9\r\xc3K\xc2\x0c\xb6\xf6sW\xff\x00.\xb9\xfd\xc6o\x9c\xacm\xfb\xe8\xd3\xfd\xd4   +  [\xfc\x82\xdb\xfb\x9a\x7f\xba\x8d\x9f\xfa\xf7b\xfe44\x97I\xd8=kPq\xcd\xbdZi\xfc\xa8\x1e\xca\xcbq\xba\xa5\xcd%7^1o\xb   +  9\xa3k\xe8\xdaP\x87\xa3J\x0b\xff\x00\x14_T\xe2\xba%\xf6\x18\xe7\xaa\xe4^8\x90\xd5\x1f\xe8\x17U\xff\x00\x17O\xec8z\x8   +  6\xe5\xf5K*N^YT\xc7tQ\xb7N\x11\xf0E\xb9\xd1\x83\xeb\x14\xff\x00`\xafV\xbcO\x95g\x8b\x10\xd1M_d\xb5-;\xa3\x06\xc7s\x0e\xd1\xfbA)\x12;\xb6\x9d\xa9\xc0eDr\x1a\x996\xa5\x82\xa7\x82\x9c\x13\xa0\xef$\x80I\xa4\x80\x   +  02\x02\t\x01(\x04\x80l\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x042Hb\x04\x1d\x8e\xc   +  f{\xb5g\xf4\xb1\xfb\xce\xb8\xecv{\xdd\xab?\xa5\x8f\xdek\xf3\x7f\xae[8[\xcd\xb3>\xe5\xdb{\x0b\xee;\xe8\x9d\x0e\xcc\xf   +  b\x97m\xec/\xb8\xef\xa2|\xf7\x91?\xbc\xba\xf8\xbd$\x00`\xdb2P\x08\x12\x00\x02@\x00\x00\x00H\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x04"]\n\x19[\xe8P\xc4{V\xde   +  \x98{\xb4W\xbd\n\x9e\xd1\xaaK\xa26\xb7\xb4W\xbd\n\x9e\xd1\xaaK\xa1\xea\xfa7\xc5\xc7\xe4{I\x03#\'\xa2j)\x96q\xe6\xac\   +  xb2\xba\x91T\xe7MK\x92\x97R\x14\xb8I\x9e+4\xe4\xf1\x82\x93^\xe9LN\xa5\xca\xb4\xd5+i\x97\x94k[I\xae\x19g\x93\xc6M\x83   +  \xdd\xf6\xf7hy8Q\xd5\xaa\xc2\x9aK\xaeMp\xa9\x15\xe6\xac\xe4\xa5\xd4\x95\x1a\xbcPm\xa3\x97\xcd\xe0FF\xc6<\xb3\r\xe6\x   +  d2v\xd3L\xd4\x92\xfc\x9e\xba\x96N\xe3\xf9R\x9aYrX4N\xdf_\xd4m\x9av\xf7Ui\xfc\xc9\x9c\xaf\xe7^\xbd\x9c\xff\x00*\xdc5\   +  xe1\x94r\xbf\xe4L\xb3\x7f&[\xbf=r\xd2\x11nU\x12\xc1\xd0\xea{\xc3\xd1l\x1bU\xae\xa3\x1cz\x8d@{U\xac\xcdbZ\x85o\xb5\x1   +  d}\xd6\xa9w]\xbf-^u=l\xb4tr92\xdb9o\x93f\x93k\xf2\xe8r\xf9\x97\xfb\x97m\xb7\xbd\xb35\xa5\x87\x7f\x1f\xb1\x7f\xb9\xa7   +  .Ym\xb1\x07(\xcdJ2k\x05\xe7\xa4C$r\x1b\xd7\xa5\xed~\x95\xaa%\xf9\x15\xc2\xa8\xdfC\xbbUk[U\xbft$\x00U\x92P\xfa\x14\x95\xa2xB\x8abVBXD\x85\xe1\x01\xa09\x94\x9   +  a\xed:\xda\xdc\xe3\x94\xd1\xc5\x95\xbaP\x92k\x8b>\';\x048\x99+\xba\xb0d\xc7\xb6\xb6o\xe3a\xe4\xa4\xb5\x1b*]<\xe9\xe1   +  \x18\x0e\xe5(B-\xf2\xa9\x9eh\xde=\xbc\xb4W\x1a\r\xdd9\xc7\x8b\x8a\x1d\xfd\xc6\x96mE\x05k\xaa\xd6\xa2\x92\xe4\xcfO\xd   +  33M\xe2"Z9i\x10\xebT\xb8\xe5\x92\xb2\x8a+\x0b\x99p\xf4\xb3\x1e\x1c\xfbB\t\xe6\x03!P\x86\xb22R\xd9x\x13\x82\x18M\x06\   +  xc2\xd0\x80\x01 \x89 \x9c\xa2\x11    +  \x19\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x0c\x92\x18\x81\x07c\xb   +  3\xde\xedY\xfd,~\xf3\xae;\x1d\x9e\xf7j\xcf\xe9c\xf7\x9a\xfc\xdf\xeb\x96\xce\x16\xf3l\xc7\xb9v\xde\xc4~\xe3\xbe\x8fq\   +  xd0\xec\xc7\xb9v\xde\xc4~\xe3\xbe\x8fq\xf3\xceG\xce]|^\x92\x0003%\x00\x81h\x00\x01    +  \x00\x00\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}   +  W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x02\   +  x06[\x97B\xb6S"a\x16\xf4\xc3\xbd\xa2\xbd\xe8T\xf6\x8dQ\xf8\xa6\xd7v\x8a\xf7\xa3S\xda5G\xb8\xf5}\x1b\xe2\xe3\xf2=\xa1   +  \x12\xc0=\x0bQ\x03\x04\x80\x18)\x92+)\x91:J\x06\x00\xee\'P    +  \x9c\x02J\xcc\x08\xc0A\x84A\x12\x94\xd2y}\x0b\xaa\xa3U\x15Z\x0f\x12E\x96\xb3\x1c\n\x19\xa3\xe8\xff\x00\xa9\x83\x91\x   +  87\xbe\xabm\xb1\xbb\x86\xda\xc9\xd6\xa0\xec\xaef\xdc\xdb\xc2\xc9\x9f\xe8\xbcE<\xf54\xc3s\xf75^\xdaY\xc1\xcbi\xd4\xe3O\xea\xe5\x82"V\x91\xce\x8fM\xff\x00\xa1t%\x04\x8a\xb0B\x9aS\x80\x91V\x08ad\   +  x10N\x18\xc10D\xa00\xf9\x16\xe4\xc4\x92\xe8\xf6\xbaq\xa3\xa3\xdcJ~\x87\x0f3Kv\xf6tj\xebu\xe7G\x0f2\xeef\xd3\xef{\\Z~   +  \x81sBrJU`\xd4M9\xba\x9b\x9d\xe5I\xd5m\xe5\x9e\x87\xa4SS\xb7\'\x91>QO\xa1Se+/\xd1\x1c\xfb\xcfY\xdd\xb8\xd3BUd\x890\x   +  84\x86\xd3\xa5\x19\x19\x18\x04wTH\x00\x9e\xfa\xa4\x00\x0e\xfa\x80\x00D\xa2B\xae\xe2\x92\xae\xe2v\xaa\x11$"B\x00\x01\   +  x02\x18\x0c\x12\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86I\x0c@\x83\xb1\xd9\xefv\xac\xfe\x96?y   +  \xd7\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb\xcd~o\xf5\xcbg\x0by\xb6c\xdc\xbbob?q\xdfG\xb8\xe8vc\xdc\xbbob?q\xdfG\xa1\xf3\xdeG   +  \xce]|^\x92\x000C2P\x08\x16\x00\x00\x00\x00\x00\x01    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x   +  8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00    +  \x00\x10\x86R\xca\x99K\x1b\xf2O\xa6\x1d\xed\x15\xefF\xa7\xb4j\x8a6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa\x08\xf5}\x1b\xe2\xe3   +  \xf2#\xc8\x00=\x1e\x9ac    +  \x12\x89\xd1\xb4\x10\xc9\xef\x0cm\x1bA\x05D"6\x91\x12\x01\x02;\xc9\x04"\x04\x80\x83/\xbd\xc2^\xf3s\x0e+m\xec\xb8\xbe   +  Q\xba\x14\x9c]\x18\xe3\xc0\xd1M\x84\xbf\xfeM\xda\x0b{\x9f\x92\xcd\xd0\xd9\x8b\xcf\xe5\x1d"\xda\xe1O\xd2\x8epx\xae\xb   +  1I\x8c\x93gO\x8d}F\x9d\xe7\x17\n\xcb.\xc7\x9f3\x8d\x1fI\xf1t\xee/R|\x8e\x15f}K\xa1\x13\x1a^H2\x10,\x93#%\r\xf3##HW\x   +  94C\x91A\r\x91\xe4\xde\x959d\xe2^\xddR\xb6\x84\xa5VX\xc2\xc8\xbb\xbc\xa5iM\xd4\xad5\x18\xa5\xd5\x98\x0b|\xfb\xcc\xa7   +  \x1a5,4\xd9\xf9\xf2\xe5\xe5`\xfa\x1bx0NY\xd3\r\xf2D\x93K\xa1\x9f\x1fS\xdc\xeeI\xe2CP2\xb8\x9a}Q9X2F\xden\xc3P\xd1j\xb9\xda\xc2\xa5\xc4S\xe6\x   +  e2\x8f\x01:3\xa3Q\xc2\xbd7NK\xb9\x9d\xbe?6\xb9>\xda\xb90\xf6\xaca\xae\xa1\x15s\xe1|_\xb0\xa4\xe8D\xc5\xbd5\xe64\x902   +  \tT\x00\x10!\x80\xc1)\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x0c\x92\x18\x81\x07c\xb3\xde\xedY\   +  xfd,~\xf3\xae;\x1d\x9e\xf7j\xcf\xe9c\xf7\x9a\xfc\xdf\xeb\x96\xce\x16\xf3l\xcf\xb9v\xde\xc2\xfb\x8e\xfa=\x0e\x87f}\xc   +  b\xb6\xf6\x17\xdcw\xd1>{\xc8\xf9\xcb\xaf\x8b\xd2@\x06\x16d\xa0\x10\'`\x00\x00\x00\x00\x00$\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x02\x11"\x96T\xca\x1b\x1fi\xfaa\xfe\xd1~\xf   +  4j{F\xa8.\x86\xd7v\x8b\x7f\xd9\x1a\x9e\xd1\xaa\t\xf2=_F\xf8\xb9\x1c\x9ff@\x07\xa4\x86\x80I\x04\xe4\x91\x00\x06T\x08D   +  \x90\x99\tH\x19\x19\x00;\xc6Gx\x13\x802C`]\xb6\xa8\xe9\xd6\x8c\x97s\xe8lV\xe6v\xfe\x12\x84l/*4\xa3\x88\xc7\x89\xe0\x   +  d6\xfao\x86\xb4g\xdc\x8eU\xb6\xa5^\xd6\xee5\xa8\xc9\xc5\xc5\xe5a\xe0\xe6s8u\xcdY\xdb>;\xf6\xb7\xde5\xbc\xa2\x8c\xe3%   +  *o\xa6\x1eNu\'\x98\xa3Y6\x07|_\x91\xd2\x85\xbe\xb1Q*1]R\xcb3\x1e\x83\xbc\x9d\x9f\xd4\xe8\xa9Z\xdc7\x9f\x1c\x1e;?\x0f   +  %/\xe9\xd1\xc5\x9a\'\xdb\xde\xae\x80\xeb\xeduk[\x88qS\xab\x16\x9f\xce\x8b\xff\x00\x96Q\xfe\xf2?i\x83\xb2\xd1>a\xb3\x   +  19+\xfe\xb9\x0c\xa2Y\xee8wZ\x95\xb5\xbd7:\x95b\x92\xf9\xd1\xe5\xf5=\xe3\xe8Zz\x97\x95\xae\xf2\xbc0d\xae+\xdb\xd4"r\x   +  d6=\xcb\xd8\xf3\x8f\xa4tz\xde\xd0\xd9\xe9T\xeaT\xb8\xab\x08\xa8,\xe1\xc9,\x98wk\xb7\xdb\xe4\xdc\x96\x938K\xc3\x89\x1   +  8_j\xf6\xdbS\xdaj\xaf\xf2\xd9\xb8G9\\\x12\xc1\xbd\xc5\xe0\xdb%\xbfhb\xc9\x9e\xb1\xeaY\'z\x1b\xd6\x96\xa3\x19\xdbi5%\   +  x08g\x1c\xf9\x98N\xea\xac\xee\xa7)\xd6|R\x93\xcbe\n\x10K\x8b\x8aN\x7f;\x07\xa4\xe2\xf0\xabH\xd3\x9b\x97,\xcc\x9d#\xc   +  2\xba\x14I\xf0\xac\xb2\xb8\xae\'\x85\xd4\xa9R\xe3\xad\x1aM7)\x88\xb5qK\xcb\xc2t\xea\xc585\x8e   +  h\xd9\xe3\xf2\xaf\x8ew\x0cy1D\xb4\x02\xfe\xda\xb5\xa5\xcc\xa9WX\x94^9\xa2\xc1\x9aw\xe7\xb1\x15,n\xe7\xa8\xdbS\xc5\xb   +  a\xe6\xda0\xac^Y\xec\xfao"2\xe3\xf2\xe5g\xc7\xdb)$\x82Q\xd2\xee\x89j\xca;\xc9D\x12\x88\x11    +  $\x0b\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x92C\x10    +  \xecv{\xdd\xab?\xa5\x8f\xdeu\xc7c\xb3\xde\xedY\xfd,~\xf3_\x9b\xfdr\xd9\xc2\xdem\x99\xf7.\xdb\xd8_q\xdfD\xe8vc\xdc\xc   +  boa}\xc7|\x8f\x9fg\xf9\xcb\xaf\x8b\xd2@\x06&d\xa0\x10    +  \x00\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\x   +  a3\xf8\t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x06\x03\x02\x00\x01\x08}\n\x19q\xf4-\xb2c\xd9\xf4\xc3\xbd\xa2\xfd\xe8\xd4\xf6\x8dP\xee6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa   +  \x1d\xc7\xab\xe8\xdf\x17\'\x93\xed    +  \x84I\xe8\x9a\x00\x00\x80\x04\x00\x94\x80\x02\x00\x00\x00\x00\xd0\x00C\x1a\x02\t\x05\xa7\x1e\xe10\x82\xed\x0b\x9b\x9   +  a\x12N\x85\xcdJK\xc2,\xb6F\x11\xa5\x93\x8f\x16\xf6\xbc_N\xfe\xd3j\xb5kT\xb8o\xee\x1a_\xf7\x1c\xcf\xe7\xe6\xad\xfe2\x   +  b7\xef\x1eT\xa7\x85x\x18\xa3\x83O\xf1x\xc8\xf4W\x1bQ\xaa\xddI\xcaZ\x8d\xc2\x8b\xee\xe2:\xdb\x8b\xfa\xd5\xf3\xe5n\xa7   +  ,\xf8\xb3\x80\xb9,"\x97\x1ey2W\x85H\xfaD\xdbi\xa9\x0e\'\x9e6\xc8\x8cx{\xc9H\x94d\xa7\x1e\xb8\xfc\xc2\xb3)D\xbe\x9c\x   +  82\x0c\xc9\xa5HK\xc9\xc2y\xf4\xbb\x8c\x87\xb9\xcd\x96\x9e\xbd\xacF\xa5x7\nmK\x9a1\xed\x08\xab\x86\xe0\xbd.\xe3lw%\xa   +  2\xc2\xc7f\xad\xae\x14\x12\xabR8l\xe3\xf5\x1c\xfd\xb5na\xab\'\xe8\xd6\xb4,\xec\xe9\xd2\xb7\x8cTb\xb1\xc9\x1d\x91\xc6   +  \xb4\xa7\xc1\x13\x90y\x1b\xce\xe5\xd5\xc7\xe8h\x8c\x15\x02\xac\xaap0TIUv\xa1\xaeE8.`\x86\xb2B\x14\x00\xd70\x972\x04c   +  \x998\xca%\xa2W"\xd0<\x9e\xf0\xf4xj\xfb?^\x84\xe2\xb2\xd6s\x83J\xb5\xdaQ\xd3\xb5\xda\xf6\xcdaFn&\xfcj1U-\xaa&\xbb\x9   +  9\xa5\x9b\xd6\xd1\xfc\x86\xb9yYrnm\xa3\xd0tl\xba\x9e\xd7?\x95\x11\xb7\x8d\xac\xd3\xa8\xf8z\x14\xa2\xdd\xb6|\x9f\x9f\   +  xd4\xae=\x0fW\x82\x9d\xd12\xe5\xda<\xa4    +  \x87"P\x89\x00\xc1`\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x042Hb\x04\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb   +  \xce\xb8\xecv{\xdd\xab?\xa5\x8f\xdek\xf3\x7f\xae[8[\xcd\xb3\x1e\xe6[{\x0b\xee;\xe8\x9d\x0e\xcc{\x97m\xec/\xb8\xef\x9   +  1\xf3\xfc\xff\x009u\xf0\xfaH\x00\xc2\xcc\x94\x02\x04\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0`@\x00!\x0f\xa1m\x97\x1a(do\xca&|0\xefh\xbfz5=\xa3T;\x8d\xa   +  f\xed\x17\xefF\xa7\xb4j\x87q\xeb:4\xfe\xae?"|\x99\x19\x18\x18=\x1bM \x02\x00\x00\r\x80\x00\x00\x0e\xe0##    +  \x16\xd0dd\x01\xa0\x04\x90O|\xeb@\x16\x001\xcf\x918    +  e\x82\x00\x86H-\xb4\xed\x18\'\xb8\x9e\xe29\x84\x88\x92;\xca\x99\x13\x08\xfbv[1m\n\xfa\xe5\xb5&\xb9\xceF\xe8\xec5\xa2   +  \xb6\xd0\xad\xa8\xae\x91]\xc6\x9blb\xfe\xd0Z\xc9\xfcY\x9b\xab\xb1\xdev\x8fB^(\xf2\xdd^t\xe8\xe0\x87\xa0\x8f$TB%\x1en   +  \xce\x85\x120\x06Y]\xb2l$\x02\xd0\x81\x90H\x02\x86\xb9\x90\xf9\x15\x90\xda\xef+"\x9c\xe5d\xa2U\x141\x91\x87\x9c\xae\   +  x852\xf3\x99Z\xee}\x8an\xe6\xbc\x8c\xb3\xf2Y\xa6\xdb\xda\xbew;E^\x8d7\x84\xa6\xd3\xc9\xb6{G~\xac\xb4\xaa\xd5\xa4\xd2   +  QM\x1aQ\xb6\xb7\x9f\x97m%\xd4\xe0\xff\x00\xf9\x19\xe8\xbaF)\x9bw49N\x92\xb4<\x9c\xa3\x1f\x9c\x9a\xab\x12\xc2\xe8%\x1   +  97\xe7uDg\x8b\x9b=\x87\x1eu\x13\x0e]\x91\x81\x82\xa0\xfa\x16\xadbfHRFJ\x88*\x80\x04\t@\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00C$\x86    +  A\xd8\xec\xf7\xbbV\x7fK\x1f\xbc\xeb\xce\xc3g\xbd\xda\xb3\xfaX\xfd\xe6\xbf7\xfa\xe5\xb3\x87\xdby\xb6g\xdc\xbboa}\xc7}   +  \x13\xa1\xd9\x9fs-\xbd\x88\xfd\xc7}\x13\xe7\xbc\x8f\x9c\xba\xf8\xbd$\x00`fJ\x01\x02@\x00H\x00\x00\x00\t\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    +  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00    +  \x13\x81\x80\x85/\xa1C+|\x8a\x19\x1fj\xdb\xd3\x0fv\x8a\xf7\xa3S\xda5?\xb8\xda\xbe\xd1U\x17\xf3^\xa5>\xfe#U\x1e1\xd4\   +  xf5\x9d\x1e?W+\x91\x1b\x94"JQQ\xe8\xe2Zr\x94\x08D\x90\xac\x80\x00\x80\x00\x12\x0e\xe0\x00\x80\x01m\x80\x00\x91$`\x90   +  PF\x06\t\x00F\x06\t\x00F\x06\t\x00F\t\x00\x00\x00\x94\xc2\xf5\x84\xe7m\xa8Q\xaf\t4\xa0\xf2\xf0n\x86\xe9\xf5*z\x86\xc   +  b\xda\xca3N|<\xd1\xa5\xb0\x9a\xf2SO\xbc\xcd\xbd\x9f\xb6\xb9Y\xdd\xbb;\xba\x89S\xc6"\x9b\xef<\xd7V\xe3\xde\xd1\xb8\x8   +  7K\x04\xb6\x81\x15\x1cZ7*\xa55(\xac\xa6\xb2^\x8c\xfcO+\x925\xed\xd0\xaa\xe1\x01I\x15u)\x13\xb5\xb4    +  \x10\xc9h\x022\x01a\x0f\xe6\x1dHl\xb79\xb4D\xa7K\xb8X8\xf5\xe7\xc0\x9bH\x8f/\x87\x86\xb2yM\xba\xda\x8a\x1a\x15\x85Z\   +  x95$\xb8\x9cZK&\\8\xa6\xf3\xa8R\xd7\x8a\xfbc\xfd\xfam\x95;=.\xae\x9bBIU\x9a\xea\x9f3X\xae\xaa\xb9U\x8c\xdb\xf3\xa5\x   +  cd\xb3\xbc\xdb]z\xa6\xb9\xab\xd4\xadRN\\\xde\x0f=U98\xbf\x03\xda\xf4\x9e4c\xa7\xec\xe6\xf2r\xd6\xd3\xe1q\xb7&\x9f\xd   +  aU&\xb3\xe6\xa2\x9arQO(\x88\xbeGV\xb1\x112\xe7\xca\xa4\xc3|\x88\x05\xab\xe2e1>\x12Gx\xe2\x19\xe6PF\t!\xf3$\x94\x00\x   +  00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86I\x0c\x01\xd8l\xef\xbb6\x7fK\x1f\xbc\xeby\x9d\x9e\xcfc\xf9f\xcf\x9   +  a\xfd,~\xf3S\x9bh\xec\x96\xc6\x1fm\xe6\xd9\x9fs-\xbd\x85\xf7\x1d\xec{\x8e\x8bf=\xcc\xb6\xf6#\xf7\x1d\xea<\x07#\xe7.\   +  xce(\xf0\x90\x01\x81\x95(\x04\t\x80\x00\x12\x00\x00\x00\x02@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xe   +  dG\xf0\x13\xb4\xdfU\xfcU    +  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00D\x8br.2\xdb#\xed[zb\x0e\xd0\xb6n{)R\xaaY\xf3\xb0j]\xcd\xbc\xad\xea\xac\xfcnf\xf6m\xee\x8e\xb5\x9d\   +  n\xb5\xbb\x8ey6i>\xd2XJ\xcbV\xb9\xa5W)\xc2m$z.\x93\x9f_\xab\x9d\x9e\x1dX\x08\x94z\xb8\x97>\xde\xc4TRT\x14\x00\x04\x9   +  a\x00\x00\x00\x00\x08d\x8c\x12 \x0c\x0c\x13\xb1    +  \x02\xa0\x00\x1a\x00\x00\xd0\x00\x00\x00\t\x00\xfa\x80\xfa\x81)6\xd3\x8f\xa0\xbd"\xfd\x85\xfc\xec/\xa9\\P\x93\x8a\x8   +  c\x93E\x8au\x9d\x1c\xac&\x9f\x89[\xa5\x18\xc1\xd5o\xd3]\r^E{\xe3M\xacY4\xdb\r\xd5\xef\x0e\x86\xad\xa7R\xa1uU~P\x962\   +  xde\x0c\xa3F\xe2\x15\x92qi\x9a\x07\xa5\xea\x17z<\xa3^\xd6\xa4\xf2\xa5\xf2\xb0g\x9d\x80\xdf\x05%J\x95\x1dr\xa4(\xb4\x   +  92Mw\x9eW\x99\xd3\xa7\xdd]\x0cy\x9b\x14\xa4\xb3\x84\xd1Z\x9e:\x9eoA\xd6\xac\xb5x*\xf65\xbc\xa4\x1f3\xbb\xab%8\xac7\x   +  c8\xe2\xdf\x8fj\xce\x99\xe3$9\x89\xe4\x96qiU\xe8\x99\xc8O(v\xe9m\xa7!\xb2\x8a\x99\xc7#\x8f\x99E\x91\xdb3(\x9bi~R]\xe   +  5\x12\x9aK\x9f$tZ\xee\xb9g\xa6E\xca\xf2\xb7\x93H\xc4\xdbm\xbe\x9b;[z\x944\xaa\xb4\xea\xd5K\x0b8\xeama\xe2_$\xc6\x94\   +  xb6^\xd8d\x8d\xb2\xda\xfb\r\x9f\xb3\xa9:\xb5\x13\xac\xd3\xe1Qi\xf35sx\x1bm}\xb4\x15\xaayZ\x99\xa0\xdf%\xdey\xfdw_\xb   +  e\xd6\xae\xa5wV\xac\xdc\xa4\xf2\xe1\xc4\xf0\x8e\xaaugY\xe5\xa5\x9e\xf4z>\x17N\xfcs\xb9s\xf3g\xefY\x8c    +  \xe2\xe5\x1c\xfe\xd0W,(\xf9\x9c\xd7yGS\xbd\x8e\x9d\xb0\xd2\x99\xf2    +  I\x0c\xc8\xa8\x86B\x02\x00!\x82p\x12\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00$\x03x\x04d\x81.I\xacw\x   +  9c\xad\x02\x94\xff\x00\x97,Z\xcbN\xaczz\xce<    +  \xb8\\\xbb\xd1\x90\xb7)\xb3\xf5\xb5\xad\xa3R\xabK4\xa9\xe2I\x9cn\xa1\x97U\x96|\x1el\xdb]\n\x9f\x93\xd1\xed\x9a\xeb\x   +  e4\xe3\xf7\x1d\xc5?E\x1c\x0be\xe4U*)r\x8cR;\x18\xf4(\xc6\xbbs\xbb\x1d3\\U+N\x   +  96+\xbek\x87\x91\x95\\<9\x16%Eq6\xf9\x99\xf0\xe7\xb5\'lY1\xc4\xb4\xc7l7{\xa8\xe8s\x9do$\xdd\x08\xf4\xc2\xcb<,\xa3\x9   +  9\xb8\xce./\xe7X7\xf6\xf7L\xb5\xba\xa3(V\xa1Ni\xfc\xa5\x93\x0cm\xfe\xe8\xad\xaf\xbc\xa5{\x15(\xd4|\xd4`\xb0w\xb8}N\x   +  bf\x1b9\xf9x\xf3\xbf\re\x9c8\x1f.\x84\'\x93\xd1\xed\x1e\xcaj:\rW\x0b\x9a2T\xd3\xc7\x13<\xef\x93\x93\x9f\x98\xb3\x13\   +  xb1\x87<^|KVqL$!\x8cz]Ix\xee:\x15\xf2\xc5h\xd2\x18%\x91\x83$B\xa0*\xc3\xc1KD$\x08\x12\x91\x12\x80\x13\x81\x82\x04\x0   +  2p@\x00\x00\x00\x00\x00\x00\x02H\x19\x02\xa42B\x00T\xc8\xc8\xc9\x19f;\xcd\xbf\xf5L\'$I\x8c\x90\xcbR\xd3\xf6mHC\x03\x   +  06n\xe8N\xd5\xae\x84\xe4\xa5\x13\x82\xb3dm#\xbc\x8c1\xcc\xae\xf6m#$s\x00\xd9\x92\x1fRp0\x10\x82\x19V\x08\xc0\x01\x81   +  \xcc%\x90\x93\xa1\x03\x1c\xc9\xc1h\x81\x03$\x91\x810\x84\x80\x90(\x00\x0c\x04\x800\x00\x86H+3\xa4    +  d\xa9S\x94\xa3\x98\xac\x95*q\x94xb\xf3U\xf4\x89K^+\x1b\x96J\xe3\x9bz[g&\xce\xd6\xbd\xd5HS\x8d9K\x89\xe28M\xf3=\xbe\x   +  c5n\xd3S\xd7e\t\xdcP\x9c(\xcb\xe3/\x03`\xb6#v\x96:\x14    +  \xeaRU\xa4\xbe\\rr\xb9\x9dB\x94\x8dD\xf9lc\xe2\xd9\x87\xf6\x13sw\xda\x8dZw\x1a\xd4\x17\xe4\xaf\x9f\x9a\xf9\x9b\x03\x   +  b2[\x1b\xa5l\xe5\xba\xa7eK\xaf^$\x99\xe9i\xda\xc2\x9c\x14i\xc5F+\xb9r.\xa8._1\xe5\xf9<\xbb\xe4\xfboS\x0e\x91\x18\xa8   +  \xfa)%\xf3\x15c\x1c\xca\xd4CY4\xbb\xa6[T\xacB\x94T\x87\t)\x08\x86]\xaaD\x91\xccs,\xa2\xa4\x02\xe8\x00\x00\x08\x00\x0   +  0\x00\x01    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x   +  8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x18!\xa2@\x14\xb2\x96\x8b\x8c\xa1\x89\x14\xa4\x9fR\xcd\xc5$\xd7B\xebx)\xcey2\x9d\xf6\xaf\xa2i\xb8y\xddsf4\xed   +  V\xdaj\xe6\xde\x9c\xe4\xd7,\x98\x1bo\xf7A^\x9a\x9d\xde\x97&\x96s\xe4\xa0\x8d\x9b\xe0E\x15    +  \xb8Zx\xe6m\xe0\xe7_\x1c\xb5o\x87m\x08\xd4\xf4\xbb\xdb\t\xca\x95\xdd\x9dJx\xf8\xd2GV\xe5\x18\xf2\xc9\xbb{S\xb1:f\xbf   +  Jj\xb5\xba\x95F\xba\xb3]\xf6\xdbu\x17\x9aUj\xd5\xa8\xc5J\x8e[Q\x8a\xcb\xc1\xe8\xf8}O\xbf\xc4\xcbO.\x16-\xceRh\x17\xa   +  e\xecn,\xaa5Z\x9c\xe1\x1e\xe5%\x82\xc9\xdc\xa6~\xe8i\xda\xba\x94\xfe\xd2\x00\xef2E\xf6\xac\xa4\x062Z\'j\x80d"@\x82H\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x0c\x90\x00\x00\x1d\xe0   +  \x0f\xd86\x94\x0c\x93\x81\x81\xde\x84\x00\xf9\x01\xdc%\x10\xc0\xee    +  ;\xc9D\x0c\x91\xb4\xc2_B\x96\xf0\xb2IC\xcf\x7f4"\xd1\x1ee\x92\xb5\xeeJ\x9a}\xe4\xd3~R|\x10\xf3\xa5\xe0\x8e^\x99\xa2\   +  xdej\x170\x85\xad\n\x8f\x89\xf5Ql\xcd\xbb\x03\xb9\xc9IB\xf3P\x8c\x1ey\xe1\xf2g7\x99\xce\xa6?\xb6Z\xe1b\xbd\x0bd5mj\x   +  a4)\xd2\xa1Z\x9d6\xfd4\xb9\x19\xff\x00w{\xa3\xb4\xb0\xa7N\xbe\xa6\xa1^}q4d\xad\x9f\xd9\xfb]2\xd64\xe8R\xe1H\xee\x94\   +  xf8ZXx<\xcf#\xa8\xde\xfb\x88\x96\xee\x1c?\xea\xd5\x8e\x9dmiMB\xda\x8ciF+\t#\x9b\x1eE\xbf;\x1cY\xf3|\n\xe3\x86\xb2\x8   +  et\xdeg\xdb~+\xa8V\xc8@\x98\xf5)2\x8d*D\x90\x89*\x94\x13\x80\t\x84\xa4\x022H\xa9t\x01t\x04    +  \x00\x00\x00\r\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0   +  e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x06R\xd1Q\x00[\x91F\x0b\xad"\x9c\x110\x98\x95\x1c\xcag\x0e%\xcc\xb8\xc8#\xb6\x15\x9f$V\x   +  160q\xae\xec\xa8\xdd,U\x84e\xebG(\x17\xad\xa6\xbe\x98\xe6\xbbb\xdd\xbf\xddu\x86\xb9G\x8e\x84\x1a\xaa\xb9\xf9\xbc\x8d   +  x\xdbM\x81\xd4v~\xb4\xa7*O\xc8.\xf5\x96n\xbc\x92k\x99\xd4j\x9ae\xb5\xfd)S\xb8\xb6\xa7Q>\xf9,\x9d>7?%}\xc8\xf7[\x13\xb0Z\xa6\xbd8\xaa\x96\xf3\x85\x19u\x92\xeeF\xaf#\x95JW{e\xa6=   +  \xbc=\x1bK\x9b\x9a\xaa\x16\xf0ro\xe62f\xc2\xee\xb6\xff\x00Xp\xabyE\xaa\x19\xe6f\xed\x88\xddn\x9f\xa1\xc2\x12\xab\x8a   +  \xd2\xef\xe3FB\x85\xa5+jJ\x9d\xb5\x18B?\xf6\xa3\xccr\xba\x9d\xa6uItp`\x88\x9f//\xb2;\r\xa7h4)\xf9*Q\x94\xb1\xcf\x89&   +  {\x0f#\x07\x14\x94TR\xf0X"\x87\x12X\x92/\xa3\x93|\x96\xc9;\xb4\xb7?\x1dH\xc5Ea\x10\xe0\xba\xe0\xab\x91/\xa1\x8fI\x88   +  \xd2\xdf\x02*H\x90VS2\x8c\x15$A(\x81RC\x01\x12L\x06\x060J H \x01\x08H \x94J@\x01    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x0   +  2v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x94\xf0\xb2\xb6\x88\x02\xde\x06\n\xf0F0\x10\x8c\x11\x8eED\x10\x85\r\x14?Qy\x   +  a28H\xf3\xf4\xbf\x8d8\x93\x87\x1eq\xe6\x9d\x16\xbd\xb2\xfan\xb3o8]Z\xc2u1\x857\xdcz\x87M0\xe0\xb1\x84_\x1d\xefY\xf6\   +  xc1l{j\xc6\xf17Swc)\xdci\xed\xd4\x8fU\x08#\x10\xdd\xd8\xdd\xdaT\x94/\xad\xaaS\x92\xf9H\xdf\xea\xb6\xf1\x94Z\xc6rxm\x   +  ae\xdd\xd6\x95\xae\xa9\xce\xad\xbau_\x7f#\xb1\xc7\xea\x13O\x93Z\xfcY\x9fM,mg\x902\x9e\xdf\xee\xb6\xebAs\xadkO\x8a\x9   +  2\xe7\x88,\xbf\xf41L\xa9WU\xa7\tBt\xb8~\\Z\xfb\xcfA\xc7\xea4\xbcD4\xef\xc6\xb5WS$\xb5\x19\xe1\xf0\xcb-\xf8\x97\x94\x   +  1e3\x95\x83\xa9Y\x8bF\xe1\xadj\xf6\xa1\x90\x1c\x92\xee!<\x97\x88\x84D$\x92\tDJd\x00\x10\xa8\x00\x00\x00\x00\x00@\x01   +  8\x18\x02\x018\x18\x02\x00h\x00\x00\x00\x00\x00d\x90\xc9\x00\xfa\x05\xd0\x80LF\xd3\x06I\xc8    +  Z4\xb4\x03\xd6C\x0f\x93\xe1|\xdf\x89\x8f\xba\x0e\xd4\x8c,6\xdf5\xdcQJ\xaas\xe0q\x96|N\xcbN\xd2\xae5\x1b\x88\xd2\xa1F   +  \xa3\x93xO\x85\xb4b\xcb\x9e\xb5\xae\xf6\xcb\x8f\x1c\xcc\xe9\xd7Sn\xb3\xe1qq\xf0;\xfd\x9c\xd9}GS\xba\x8d*V\xf5\\%\xf1   +  \xd2\xe4em\x84\xdc\xf5{\xa9S\xaf\xab\xc6\x13\xa5\xc9\xe3\xa33\xde\x81\xb2\xdan\x8dJ\x11\xb3\xa2\xa2\xd2<\xf7/\xa9\xd   +  60\xb9\xd4\x1c+\xb7\xe7p5\xd0\xcb\xbav\x97icN1\xb3\xa7\x1aIuH\xeda\x04\xb9$\x15\x18\xa9g   +  \x1c\xce\x16^U\xf2O\x99g\xa6\r\t$\x89\xc1V\tH\xd7\xde\xdbU\xae\x94\xe0a\x95a\x13\x82R\xa5&N\t\'\x04\nR\x18*\xc0\xc1\   +  x08S\x82R\'\x03\x04hJ\x01\x13\x82a" \x90\xc9B\x00\x18    +  2J\x18\x00\x00\x04\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5   +  \x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00`\x86H`A\x04\xe0`\x1aF\x06\t\xc0\xc0\x102\xbc\t\xc0#b\x1e   +  \n\\Wy^\x08\xc1\x1d\xfa\x1c+\xbb*\x17Pp\xadN\x12\x8b\xf1\x8af)\xde\x1e\xe8\xf4\xedj\x94\xaa\xd9\xc6Q\xae\xb9\xa5\x05   +  \x84\xdf\xec2\xfc\x91nk\x933b\xe4Z\x93\xb8\x96;\xd3p\xd1\xfd\xa8\xd8-cg\xeaIW\xb7\xc54\xfa\xf3\xf3`\xb6\x0fu\xd6:\x1d8J\xea\x11\xad%\xcf3\x89\xc8\xe4\xf5\x18\xc7\xb8l\xd3\x17w\x98a\xad\x81\   +  xdd\x8e\xa1\xab\xd5\x84\xb5*\x1c\x14\x1b\xea\xba\xe0\xcf\xfb+\xb0zf\x89\x18\xaa4\xd4\xa4\xba\xb9G\'\xaf\xb7\xb6\xb7\   +  xa3\x15\x1bZQ\x8a\\\xb9#\x98\xa1\x88\xa7\x8eg\x0b?:\xf7lS\x17l\xedE:q\xa5MF\x9cRK\xc1\x17c\xd0\xa7\x05i\x1c\xdb[\xb9   +  \xb5\x1eS\x1e\xa5e1Ei\x15\x85\xe1\x18a\x12\xc1+\x0f\x01\x0c\x13\xd0 H<\x04\xc0\x00\tA\x08\xc0\xc1    +  i"\x00\x12\x01\x80\x04w\x92\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    +  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x8d\x08\xc0$\x11\xda-\xc9\x14\xb8\xe4\xba\xd1\x0cD\x12\xb2\xa0   +  \xa2\xf9"\x8a\xb1RM9,\x17\xe4q\xea\xd3\xcb\xca,\xa4\xc3\xccm&\xcbi\xda\xcd\xb4\xe9\xdc[FR\x92\xe5&k\xfe\xde\xee\x86\   +  xf2\xc6S\xafaQJ\x97U\x08#i\xd48\xbc\xd7\x8c\x14\xd6\xb5\xa5R\x9b\x8b\x8a~\xb3\xa1\xc6\xe7_\x04\xf8\x96\xbd\xf0\xf7\x   +  b4\x06\xfbM\xba\xb3\xab*U\xe8N\x94\xa3\xdf%\x83\xae\x83\x9b\xa9\x87\x9c\x1b\x9d\xb6{\xbb\xd3\xb5\xbaS\x94\xe8\xfe}\x   +  f7\xa3_6\xd3vz\xae\x8dVuh\xc1J\xd9wEe\x9e\x83\x8f\xd5#\'\x89j\xdf\x8f\xa6;%"\xaa\xf4\xeaP\x93\x8dXN-|\xa8\xb4[S\xca\   +  xe4u\xb1\xe6\x8b\xfai\xda\x9a\x95x    +  \xa3\x8c\xad34Z\x15\x93\x18\'\x04\x12\x89\xda\xa6\x10\x00\x94!\x82z\x90L\x00\x00\x90d\x12\xc8\x00\x89!\x12T\x00\x00\   +  x19-y\xb9\xe2\xe7\xe0    +  \x9b\x96#\xd4\xaa4x\xa7\x8c\xa5/\x9c\xc5\x93,R\x16\xacmz\xde\x84j\xc3.J/\xc1\x96\'(\xd1\xaf\xc3\xc3\xe5\x17\x82/\xdb   +  i\xf7w\x97q\xa1mNr\x93x\xca\x8bh\xcc\xfb\xbd\xdc\xf5[\xa9\xd3\xb9\xd5a\x19A\xf3\xc7y\xcb\xcf\xd4\xabF\xd50\xcc\xb1V\   +  x89\xb3z\x86\xbbUF\xda\xda\xac"\xdf\xa5\xc2gM\xdcn\x86\x8d\x93\x85\xc6\xad\x18Vo\x0f\x12]\x0c\xb9\xb3\xfb+c\xa2\xd0P   +  \xb5\xa2\xa2\xd7\xccw\xdeM8\xe1\xa3\x87\xc9\xeaV\xc9\xe2\xad\x8aa\xd4\xf9u\xfa^\x97cb\xd5;J\n\x9cW\x81\xdba8\xe1\xae   +  E\x9aPq\x9b\xf09\x11\xe8q\xef\x92m;n\xd2"!M:Q\x87\xa2\xb0L\xd1Zd>effW\xd2\xde>b\xb4\x89EEt\x9d#\x04\xa4H%&\x08\xc1$\   +  x12#\x03\x04\x80\x80\x00\x80\x9c\x002JF@\x00J\x04"r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\xfcU    +  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\r\x12\x00\xa1\x96\xa4\   +  xe7\x9e\x9c\x8b\xed\x10\xd0D\xc6\xdc~\x18\xbe\xf7\x92\xa4]\xe0^\x03\x84\x9f\x0bWP\xb3(\xa9uG\x0e\xe6\xc2\x8dd\xd5JP\   +  x9a}\xd2\x8agd\xa2O\th\xbe\xbd+z\xc5\x98_x\x1b\xa9\xb1\xd6\xd4\xabZ\xc6Q\xaa\xb9\xf0\xc1a\x7f\xa1\xaf\xdbW\xb1\x17\x   +  9b=ZJ\xa59(\'\xd5\xb3y\xdd(\xe1\xf2\\\xcf9\xafhV:\xb4gJ\xe6\xd6\x9e\x1f\xc6h\xe9\xf0\xfa\x8c\xe2\x9f\xdb\xcc4\xb2q\x   +  bb\x9a \xe7\x0c\xf0\xfca\xcd3`v\xfbs1JwZl\xdb}x`\x8c/\xaa\xe8:\x86\x9b]\xd2\xb9\xb5\x9c    +  \xbe;G\xa0\xc1\xce\xa6_R\xd3\xbe\x19\xaf\x87O\x90\x993\x84!&\x9c\xc8j+\xa4\xb2uk1\xad\xed\xafjL\x1c\xc0L\x17\x8d)\t    +  \x02\x93m$D\xf7\x90\x892\xc4\xaa\x86A<\xbcBQ\xf9DL\xa6!\x08\x92p\xbb\x9eJ\x963\xcc\xa4\xdbQ\xb4-\xb6@t\xe5R\xae!\x97   +  \xe0\xbcOU\xb2{\r\xabm\x15\xdc#+Z\xb4h\x7fx\x97#G/>\xb8\xd9\xa9\x8el\xf3v\x94\xddZ\xca1\xea\xcc\x97\xb1\xfb\xad\xbc\   +  xda\x0e\x19\xdc\xc2p\xb7\x7f\x1a-\xf43\x16\xc0\xee\xa2\xc3J\xf2u\xaf8.$\xbe,\xd1\x95\xad,-\xad    +  \xa1mF\x14\xe3\xe1\x13\x85\xcc\xea\xdd\xf3\xaa\xc3{\x17\x17\xed\xe0v7w\xda~\xce[\xc2\x14)\xaa\xd3K\r\xd5\x8eY\xefm-\   +  xd5\x18$\xa1\x18\xfc\xc9\x1c\x95\x04\xbb\x8a\xb0p\xb2\xe4\xb5\xe7{oS\x1cUN\x08\xc1^\x08\xc72\xabZ\xb0\x84\x8a\xd1\x1   +  8%\x14\x98Ea8\x18$\x05\xc4\x02\'\x00\x00\x00\x08$\x01\x00\x01\xa4\x01u%\x00\x04\x120JP\t\xc0\xc0\x10\t\xc0\xc0\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\   +  xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    +  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01L\xbar,J\x1cO\xce\xe6\x   +  8eC)hyVVeN..-r<\xb6\xd2\xecn\x9b\xacP\x9cj[\xc5\xcd\xae\xac\xf5\x92E\xb9\x19)\x92\xd4\x9d\xc1\x18\xa2\xde\xda\x9b\xb   +  7\x9b\xa4\xbc\xd3*\xd6\xb9\xb6\xfc\xe5<\xb6\xa3\x05\x9c\x18\xae\xe2\xce\xad\xb5WN\xe2\x94\xe95\xf2\x96\r\xff\x00\xaf   +  o\xe5b\xd7\x0cZ}r\xb2c\xcd\xb3\xddV\x95\xafS\xa9W\xc95r\xd6V9,\x9d\x8c\x1dN\xd1\xe2\xd2\xd3\xcb\x82>\x9ayS\xf3r\xc7U   +  \xe2\x13\xca=\xfe\xd8n\xd3W\xd0\xaaO\x8a\x9a\x95\x05\xcdp\xac\xb3\xc1U\xa5:2q\x9cd\x9a\xe5\xcd\x1d\xee?./\x1e\xdc\xe   +  b\xe3\xed\x94&2R\x89\xc9\xd0\xa6\xad\xe5\x8eaR%\x91\x90\x99\x9b\xc4+\xa9CE\r\xc6=Qv/\x99\xca\xb6\xb0\xad\xa8VT\xad\x   +  a9\xceS}\xea-\xa3_7"\xb8\xfd\xca\xd4\xac\xcb\x81\t\xc78\xe8w\x9a.\xcf\xdfj\xb7\xb4h\xdb\xdb\xd5\x94\'\xf1\xd4r\x91\x   +  92v\x0fs7z\x9f\x05}b\x0b\xc8u\xc2\xe4\xcd\x82\xd9\x1d\x95\xd3t\x0buF\xca\x8a\xc2XnI3\x85\xcb\xea\xb1\x111V\xdd8\xdb\   +  xf3,[\xb0{\xa2\xa3NQ\xab\xa9\xd2\x8dLs\xc3Fd\xd3t[m:\xde4\xac\xe9\xaaq]\xc7i4\xa1\x1f\xcd\xa4\x85)I\xfaG\x9e\xcb\xca   +  \xb6I\xdc\xcbw\x16\x18\xaa\xbat\xd4R.\xa2\x11TQ\xaf3\xb6\xd4F\x92\x06\x06\x08H\x06\x06\x00\x12\x88\xc1Q\x00\x00\x00\   +  x00\x00\x00\x00\x00\x01\x81\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\   +  xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x08h\x90\r-   +  \xc9\x10\xa2\\k%8\t\xda00T@Va\xc3\xbe\xb0\xb6\xba\xa5(\xd7\xa3\t\xa6\xb1\xe7G&\x17\xdb\x9d\xd3[_\xba\xb54\xe8\xb79e\   +  xe2+\x06p\x92e\x97K\x1d\x0c\xf8\xb3\xdb\x1c\xf8\x96\xb6lqf\x92\xed\x06\xc1\xebZ\x15Y\xf9{F\xa8\xfc\xa7\xe0x\xfb\x98\   +  xc6\x15\x1c\x13\xf3\xfb\xd1\xbf\xb7zM\x9d\xec\\o(B\xaa\x7f(\xf3\xd7\xfb\xbc\xd9\xfb\x85.\r2\xde\x13\x7f\x1b\x0c\xeb\   +  xe0\xea\xb3O\x12\xd6\xfc\r!\x8d\xbc\xbe3i\x1c\xcb+J\xb5\xea\xaav\xf1\xe3l\xdb\x8b]\xd4\xe9\x94\xaa9T\xa5J\xa2\xcfF\x   +  8fA\xa7\xec.\x89i%(\xe9\xf42\xbb\xf0\xcc\xf9:\xbe\xe3\xc2k\x85\xad;+\xba\xbdKW\x9ce^\x8c\xe1F}d\xb3\xc9\x19\xff\x00a   +  ww\xa5l\xdd\xbc\x14\xa2\xaa\xd4K\xadH\xe5\x9e\xe6\x8d\x95\n\x10P\xb7\xa6\xa9\xa5\xdc\x8b\xf4\xe9\xa5\xe9sg\x1f\x93\x   +  cd\xb6i\xde\xd9\xeb\x8e!n\x95:t\xe3\x8aQ\x8cc\xe0\x96\x0b\xd0ItE\\\tt*K\x91\xa5\xdd2\xcdZ\x8a9\x1c(\xad\x10\xd1\x0b\   +  xc4h]\n\x91\t\x15"V\x01 \x08\x04\x80    +  \x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d   +  \xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x03 \x91\x80    +  \x82\xac\x06\x05\xb6\x8a\x1a.\xb4R\xd10\xafj\xde\tH\xab\x04\xa4N\xd1\xda\x84\xbeb\x1a.`\x86\x88\x99\xd9\xda\xb5\x82\   +  xa4\x8a\xb0JE;S\xda\x84\x8a\x92\x18*\'I\xd2\x9c\x0c\x15`\x80    +  \x94J\x04\x80\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5   +  \x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06A#\x00F\x06\t\xc0\xc0\x10\t\xc0\xc0\x10H\xc0\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8   +  \xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8   +  \xaa@\x0c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x02\x1bK\xa9\x1ck\xc4\xa2\xb6_4\xfa\x16s\xc4\xd2K\x84\x0eWR:\x11\x17\xc8\xa2\xac\xbc\xdc.\xa0\\SNXO\x98\x95H\x   +  c5\xe1\xb3\xcek\x9bO\xa6h6\xd3\xa9wsJ5\x12\xcf\x0bxl\xc3Z\xb7h\xbd:\xcbU\x95/\xe4\xf9T\x86q\xc4\x9f    +  6!M>\xf2x\x91\x8ev\x1bz\x1a.\xd3\xd1O\xca\xd2\xb6\xa8\xfaBR\xe6{\xeau\xa1Y)R\x92\x94_z\x03\x90\x89)]\t@H\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00o\x00\xb7]f\x9b\xc3\   +  xc7\xce\x02\xa5hS\xc7\x13\xc6J\xa1R3Y\x8b\xca<~\xad\xb6Z6\x9bU\xdb\xdf]\xd0U"\xf1\x89H\xe1Gx\xbb?\x15\x88\xea6\xd1^\   +  x1c`{\xec\xa1\xc4\xbcO\x03\xfd$\xe8\x0b\xff\x00\xc9[?\xfc\xc7\xf4\x95\xb3\xff\x00\xe66\xdf\xbe\x07\xbe\xe2^#\x89x\x9   +  e\x0b\xfaK\xd9\xef\xf3\x0bo\xdf\x1f\xd2^\xcf\x7f\x98[~\xf8\x1e\xf7\x89x\x8e%\xe2x/\xe9/g\xbf\xcc-\xbf|\x7fI{=\xfeam\   +  xfb\xe0{\xde%\xe28\x97\x89\xe0\xbf\xa4\xbd\x9e\xff\x000\xb6\xfd\xf1\xfd%\xec\xf7\xf9\x85\xb7\xef\x81\xefx\x97\x88\xe   +  2G\x82\xfe\x92\xf6{\xfc\xc2\xdb\xf7\xc8\xfe\x926}\xf4\xd4\xad\x97\xfe`{\xd74\xbb\xc9R^\'\x82\x86\xf2t\tT\x8d5}o)I\xe   +  3\x94\xcfQmq\x0b\xeaq\xabi^2\xa6\xd6|\xd0;\\\xe4\x16\xe94\xd68\xb2\xd1p\t\xc8    +  \x94\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\xd2Yd\xb7\x85\xcc\xf3:\xde\xd6iZEeN\xf2\xf6\x8c\x1b\xee\x94\xb0   +  \x07\xa4\x8c\xd3\xe8TxW\xbc}\x9d\x8f\xa3\xa8\xdb~\xf8\xfe\x92v\x7f\xfc\xc2\xdb\xf7\xc0\xf7\x0e\xa4T\xb8[\xe6Kh\xf16\   +  xfb\xc2\xd0.k(\xd3\xbe\xb7\x94\xdfLL\xf5v\x95\xe3^\x94j\xc2JP\x92\xcah\x0eX)L\x9c\x81P!\x12\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\xfcU    +  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00o\x08\xa1TM<\x01X)R\xca\'    +  H!\xbc\x10\xa6\x80\xa2x\xc9i\xa9\xb7\xd5`_W\x8d\nnRiEuf/\xdb\xbd\xebh\xdb3J\xa7\x05\xd2w\x0b\xa4^:\x81\x91\xf5\rJ\xd   +  6\xc2\x84\xa7qV\x9d\x7f\xef\xea\xe2\xaa\xdb\xddB\nrQ\x8dNK&2\x9dj\xb2\x96]   +  I}\xa6H\xdf\xd7\xc2\x0e\xa7\xed\x98\xd0\n\xbc\xa5O\x97/\xb4yI\xfc\xb9}\xa5\x00\n\xfc\xa4\xfe\\\xbe\xd1\xe5\'\xf2\xe5   +  \xf6\x94\x00+\xf2\x93\xf9r\xfbG\x94\x9f\xcb\x97\xdaP\x00\xaf\xcaO\xe5\xcb\xed\x1eR\x7f._i@\x02\xbf)?\x97/\xb4yJ\x9f.   +  _i@\x03\x97\xa7\xd6\xab\x0b\xea\rT\x96T\xd7y\xbe\xfb\x84\xb8\xa9u\xb2\x14\xe5Y\xf15\x84h%\x97\xebt}\xa4o\x9fg\xa9\x7   +  fca\xeb@eZtcM\xb7\x1e\xf2\xe6\x02\xe8\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x15\xbfE?Q\xa4\xdd\xa6\xa   +  aN\x9e\xbf\x08\xc2m\'\x9e\xf3vk~\x8a~\xa3H\xbbO?\xed\x15?\xda\x06\x12UjG\x9a\xa9/\xb5\x87qW\x1f\xa4\x97\xdaZO\x90o\x   +  90\x1d\x9e\x83wZ\x86\xa7Bt\xeaIK\x89w\xfc\xe7\xd1m\x80\x9c\xaal\x9e\x979\xbc\xc9\xd1\x8eO\x9c:G\xeb\xf4}\xb5\xf7\x9f   +  Gwx\x9b\xd8\xbd/\x1d|\x84~\xe0=\x14d\xfc\xa3O\xa1x\xb5\x86\xa2\xb3\xd4\xae=\x00\xa9u$\x84H\x12\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca   +  \xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\xac\xfc\xdeE\x8f\x8c\xb8zw   +  \x97\xaat-\xa4\xa2\x9e\x00\xba\xb1\x8eD\x9cg6\xb9\'\xcc\xea\xf5\x9d\xa2\xb0\xd1m\xe7;\xdb\x9aPqY\xc4\xa5\x8c\x81\xde   +  \xc9\xa5\x16\xdfDx\xad\xae\xdb\xed#gm\xaaJ\xad\xd5/+\x15\xe86aM\xe3\xef\xf6\x14\xa5V\xd7JS\x84\xf9\xa58\xbeF\xb8\xed   +  \x16\xd3\xea:\xed\xcdJ\x97\xb7\x12\xa8\xa4\xf3\x86\x06\\\xden\xfc/5\xb9\xce\xdbNn\x84"\xdaR\xa7.\xa6\x16\xbc\xd4\xae   +  \xb5\x1a\xd2\x9d\xfd\xc4\xe7\x9e~s:\xe5\x14\xba\x13<\xc9a\x81\x15\xe5\xe7at-\xa6\x92\xe8K\\\xc4p\xa5\xcc\x02I\xf5x\x   +  08\xbb\xc2\xaa\xc9B\x94\x1b\x93\xf0=6\x99\xb1Z\xbd\xe5\x8b\xafN\xc2\xbb\x8e3\x95\x00<\xa9\'*\xf2\xca\xbd\x8dYS\xb9\x   +  a3:rO\xe3,\x1c&\xf2\xc0\xb9\xc8\xae\x95YS\xa8\xa5\t\xb8I|dX\xc8|\xc0\xc8\xfb\x19\xbd\x1d[f+\xd3j\xbd[\x9aI\xfa\x0e\\   +  \x8d\x9d\xdd\xde\xf8\xb4\xcdv\x84?/\xb8\xa5m_\x1c\xa0\xdfVh\xd6\x0eE\xa5\xddkJ\xb1\xa9o7\t\xc5\xe54\x07\xd3\xad>\xf2   +  \x95\xf5\x18\xd7\xa7%*R\xe8\xd1\xc9\xff\x00\xe4\xf3}\x13Hw{\xbe\xcdOF\xf26\xda\x85Z\xb5\xa8&\x96<\r\xa5\xd8\xad\xe2i   +  \x1bAeNq\xb9\xa5J\xab\xf8\x92\x9f0=\xf1(\xe2\xaa\xaar\x84\xa9\xc98>\xf4rS\xe4\x05D\x94\x92\x04\x80\x80\x00\x00\x00\x   +  08\x93\xc0\x12\x0bnm\xf4L\x98\xbf\x16\x05`\xb76\xfb\x99\x11\x93]@\xba\nS\xc9    +  H\x00\x00\x00\x00\x00\x00\x19\x00\x00\x0f\xa0\x00Q\x17\xe2R\xa7\xc6\xdaO\xa0\x17A\xc7\x94jqr|\x8b\x8f-u\xc3\x02\xe0\   +  xc9\xc7P\xa8\xfe1qFX\xe6\x05\xc0B%\x00\x00\x00\x00d\x00\x03    +  \x03\x19\x0f\xa0\x14\x02@\x04T\x8a\x1c\x92\xea\xc9R\xf0\x02\xa0[r\nO\xbc\x0b\x80\xa1>ey\x00\x00\x00SS\xd0~\xa2\xa2\x   +  9a\x9e\x83\xf5\x01\xf3\xeb\x7f_\x08:\x9f\xb6cS%o\xeb\xe1\x07S\xf6\xccj\x00\x0c|\xe5\xf8Q\x8c\xa7\x08\xa9.`X\x06j\xd9   +  \x1d\xc6\xea\x1bI\xa4\xd1\xbe\xa1u\x08B\xaa\xcaM\x1d\xbc\xbb5k\x1cxW\xf4\xf1\xea\x03_\x81\xb0\x7f\xfai\xd5\xff\x00\x   +  cc)}\x83\xff\x00M:\xbf\xf9\x85/\xb0\r|\x06\xc1\xff\x00\xe9\xa7W\xff\x000\xa5\xf6\x0f\xfd4\xea\xff\x00\xe6\x14\xbe\xc   +  05\xf0\x1b\x07\xff\x00\xa6\x9d_\xfc\xc2\x97\xd8\x1ff\xbdZ1\x7f\xd7\xe9\xb7\xea\x03\x01Y\xfe\xb7G\xdaF\xf7\xf6{\xf7\x   +  9d\x0fY\x84,;7\xea\xd4\xee\xe9\xce\xad\xf57\x15$\xfa\x1b7\xbb\xcd\x98{/\xa0\xc6\xcau#9u\xca\x03\xd7A\xf2*8p\x94\xe3.   +  yh\xbe\xaa\xe7\xb9\x81t\x14\'\x90\xe5\x80+\x05\xbf)\xf3\x15\'\x90*\x04"@\x00q\xddf\xaa8\xf0\xbfX\x1c\x80q\x93\x93\xa   +  d\x9e/7\xc0\xbe\xe4\xb1\xd4\n\x81b\x9b\x92\x9br|\xbb\x8a\xa5\'\x90*\xac\xff\x005?S4\x7f\xb4\xf3\xfe\xd1S\xfd\xa6\xed   +  \xd5\x93\xf2R\xf53H\xfbN\xaf\xed\x15?\xda\x06\x10A\x84\x18\x1c\xbd\'\xf5\xfa>\xda\xfb\xcf\xa4;\xb7\xf7\x9b\xa5}\x04~   +  \xe3\xe6\xf6\x93\xfa\xfd\x1fm}\xe7\xd2\x1d\xdb\xfb\xcd\xd2\xbe\x82?p\x1e\x9d\xa4A#\x00@\'\x03\x00\x00\x00\x00o\x1dKS   +  \x9f\x83\x02\xe88\xf1\xe2\x7f\x18\xaeJN>l\xb9\x81t\x16#\x19\xafJY.\xc4\n\x81\x04\x80\x03#    +  \x00\xc8\x00\x0b\x15\xe7(\xce8\xce\n\xdc\xf2\xb90.\x02\xde%\xe2D\xb8\x94^:\x81td\xb1Jo\xe3d\xb9\x9c\xf4\x02\xbc\x82\   +  x85\x92\xa0$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\x   +  b4\xdfU\xfcU    +  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  3\x00\nd\xb2P\xd1q\x90\xda\x03\x1c\xef_m\xe8lf\x9e\xea6\xd5j\x8b\xcd\xf5\x9ag\xbc-\xe2j\xdbSu5q]\xf9\x1c\xe5a\xb4g^\   +  xd7u$\xa8Y(7\xcf\xa9\xa9\xd2o8\x97P"s\x9dIfM\xb7\xf3\x95E\xf8\x94\xa6J`W\xc5\xcf\x05S\x8bK%\xb8\xc3\x8a]y\x1d\x8e\x9   +  f\xa6\\j\x15\xa1J\xc6.\xac\xe4\xf0\x90\x1dn[|\x93;\xcd\x9c\xd9mKh.#J\xca\x8c\xf2\xde2\xe2\xf0f\xbd\xdc\xee&\xee\xfet   +  \xae6\x82\x8dKx\xbc?7=\r\x93\xd9=\x8f\xd1\xf6z\xde4\xad\xe8\xd3\x94\xa2\xb1\xc5(,\x81\x847e\xb8Jv\xea\x8d\xd6\xd0\xd   +  2R\x97&\xb8Y\xb0\xdaf\x87i\xa6\xd8+;Z0Tq\x8eqGc.\x19(\xacp\xa5\xd1"\xfa\xe8\x06%\xdb\xfd\xcch\xbbAmV\xb5\n\x18\xbc|\   +  xd3\xe4\x91\xab\x9b}\xba=gf\xa7R\xab\xa6\xa5Ae\xae\x05\x9eF\xfc\xce\xa3R\xe1}\x19\xc4\xd4t\xbb[\xebi\xd3\xadF\x9dE5\   +  x87\xc5\x14\xc0\xf9\x8b:u)\xb6\xa7\tE\xae\xe6\xb0S\x14\xe4\xf0\x8d\xc6\xde>\xe2\xacu\x05R\xebLS\xfc\xa2\\\xf8"\xb0\x   +  8dj\xda\xfd\x84\xd4\xf6Z\xeaq\xd4\xe8J\x95%\xd1\xe4\x0f%\x1a2\x94\x1c\x97DP^\xabQ/6\x1e\x8b,\xb0+\x85N\x15\x87\xd0\x   +  ectMr\xebH\xbb\x8d\xcd\xadY\xc6\xa4zsx:\xa6\x88`m\x8e\xe37\xc3u\xab^Q\xd2\xb5\x9a\x8eu\xa6\xf8i\xe1w\x1b9FJPM\x1fv\xbdGP\xcf;\xcb\x8f\xe22\x97\xaaj\x0b\xff\x00\xb9q\xfcF\x07\xd1z[}\xa3T\x9ca\x1b\x88e\xbczh\xf5\x14n\xa9\xd6\x8   +  4eNI\xc6K)\xa6|\xc6\xb3\xd6o\xe9]R\x9b\xbc\xaf\x88\xc9?\xd23d\xf6s}\xd6zN\xca\xaar\xb9\x8c\xefc\x14\x94f\xf3\xdc\x06   +  \xd0_\xeav\xb6T\'V\xbdzqQYi\xcd#\x1a\xed.\xfb\xf6kE\xe2\x85iT\x94\xd7/1\xe4\xd4\xed\xb0\xden\xab\xb45k\xba\x95\xe7J\   +  r\xbe\x15\t\xb5\x93\xc0\xd7\xba\xb9\x9cx\xabT\x9dL\xf7\xcaY\x03lo\xbbHi|\xff\x00\'\x95U\xe1\x94t\xb5\xbbF\xc5\xcf\xf   +  3u&\xa3\xea5m\xb6\xd8\x03k-;G[\xaa\x91\xf2\xf3\x9b\x8f~\x11\xect>\xd0\xdb5{UR\xaa\xeb)\xbeYk\xfe\r"+\xa7)FY\x84\x9ce   +  \xe2\x98\x1fJt\x1d\xb0\xd2\xb5\x9aQ\x9d\xb5zi>\xe9Md\xf4Tj\xc2\xa2\xcd9)/\x14\xf2|\xd0\xd16\x93S\xd2.\xa3R\x95\xdd~_   +  \x17\xca<\x19\xefw{\xfa\xb9\xb3\x9d+MM\xd3\x8d\'\xc9\xc9\xbc\xb06\xd6\xa5X\xc3\x19&5\x14\x8f\'\xb2\xdbOc\xb54\xa3Z\x   +  d2\xb2\x9f\n\xcf#\xd4z\\\xba    +  /e\x12\x8b0\xca\x96\x174^\x00\xca[%\x94I\x81-\xe0B\xa2\x93h\xb7\'\xc8\xe3Qu*NNK\x1c/\x96;\xc0\xe7JI\x16\xae.\xa8\xd0   +  \xa6\xe5V\xa4"\x97\x8bH\xf1\xfbm\xb7\xdaN\xca\xdaJW\xf7*\x9dly\xa9\xf8\x9a\xb5\xbc\x8d\xf4\xea:\xc5j\xb4l\xa4\xa3A\x   +  f4\x94%\x86\x06\xcd\xed>\xf4t\x1d\x06\x13\xfc\xa6\xb7\x13\x8f\xc8\x92f-\xd6{Fh\xb4\xa5%\xa7:\xca_:52\xf7S\xbd\xbc\xa   +  b)W\xb9\xad>\'\x9c9\xb6q%\x17\x9e}@\xd8\x8dW\xb4v\xb0\xe6\xff\x00!\xac\x94{\xb2\x8bZ\x7fh\xbdo\x8f\xfa\xddd\xd7\xcc\   +  x8d|I\x15r\xc0\x1ba\xa3v\x8e\xb4\x84s\xa8J\xa3\xf5#!l\xe6\xfcvwZq\x85)\xce2}x\xb9\x1a\x1c\x94\xa5\x16\xf1\xe6\x95\xd   +  1\xba\xabl\xf3B\xb4\xe2\xff\x00\xed\x96\x00\xfas\xa6\xeb\x16z\x85\xbcj\xdb\xd7\xa7%.\xee5\x93\x9f\xc6\xb1\x9c\xf2>w\   +  xecV\xf2u]\x02\xe6-\xdcT\xa9\x08\xf4S\x9bh\xd9\xbd\xd9\xef\xaa\xcbh\xdd+=N\xb4)\\>\x8a8\x03;9\xa4\xb2G\x94X82\xadNj\   +  x94\xe9\xc9\xb5%\x98\xfc\xe5\xde\x14\xd7\x13o\x8b\xc0\x0eG\x1aee\x8am\xb5\x96\x8b\xb9x\x02rFH\xc9N@\xad>d\xf1\xac\xe   +  0\xe3Wu1\xf9\xb5\x96yM\xb6\xdb]7dt\xf9\xd4\xbd\xb8P\xac\x96R`z\xda\xf7Th&\xea\xd4\x84\x12\xf9O\x07\x85\xda\xcd\xeah;   +  9\x95sW\x8eK\x97\x99$\xcdc\xde.\xfbu\x1d\xa0\xa9R\x85\x94\xa3\n+*2\xa6\xf0\xda\xfd\x86\x1c\xbf\xd4o\xee\xaaJw5\xea\x   +  cf?*m\x81\xb6z\xafh\xbd\x13\xcaJ6\xee\xb2}\xdc\x8e\x86]\xa4"\xa4\xd4\'>\x1e\xeeF\xae(\xb9so\x99C\xea\x06\xda\xe9\x1d   +  \xa3\xac\xa7S\x17\xb3\xa8\xd7\xcc\x8fw\xa4o\xd7f\xaf|\x9c8\xaa)\xc9\xe3\x99\xa2\x11\xeb\xd7\x05\xfau\xebSy\xa7RK\x1d   +  \xe9\x81\xf4\xcfJ\xd6\xecu*\x11\xabm^\x9c\x93\xff\x00\xbdd\xedT\xe2\xe3\x94\xf2\x8f\x9d\xdb!\xbc=Sg\xa9\xc6t\xae*U\x   +  92~\x8c\xe6\xda6\x97t\x9b\xdd\xb2\xda\x1a\x10\xb4\xd4\xebB\x9d\xe4\xf9F\x11\xef\x035yU\x8fYZ\x91\xc6\xa0\xe1(\xe6\x0   +  f(\xbc\x9a\xc8\x172EOB^\xa22D\xdf\x99/P\x1f>\xf7\xf7\xf0\x85\xa9}!\x8d\x97#$\xef\xef\xe1\x0bR\xfaC\x1b\x01TR\x94\xb0   +  \xcb\x96\x91N\xea+\xbb%\xa8r\x91z\xcf\x9d\xc2\xf5\x81\xbf\xfb\x96Q\xa5\xbb\xad1\xd3\\\xdcL\x85E9\xd3\xf3\xd2\xc9\x8e   +  \xb7\x1f\x99\xee\xff\x00LO\xa2\x89\x92\xa2\xb0\xb9\x01O\x92\x88\xf2Q\xf0.\x00-\xf9(\xf8\x0f%\x1f\x02\xe0\x02\xdf\x92   +  \x8f\x81D\xa1\x89.\x14\x8b\xe5\x0f\xa8\x14\xd4YK\x85$U\xe4\xd2\x8eHo\x05M\xe6\x00a\xfd\xefoR\x9e\xc4\xde\xd0\xa0\xe5   +  $\xea,\xf2F3\x9fh\xee~mI~\xe9\xd3v\xbb\x7f\xf5\xdb\x1fd\xd7v\x06\xd0.\xd2\x13\xfe\xf2_a~\xcb\xb4l*\\\xc1W\xa9>\x06\x   +  d2\xe4\x8dU/\xda~\x9e\x9f\xb4\xbe\xf0>\x96l\xae\xb1\xfc\xb3\xa5[\xdeA\xbe\n\xb0RY;\xe5\xd0\xf0\xdb\xa6\xf7\x9b\xa6}\   +  x0cOp\x98\x15"\xac\x94\x92\x04\x98\xdb{[}Kb,!qq\x95\x1a\x8f\x0b\x85\x19$\xd6\xbe\xd8~\xf7l\xbe\x90\x0f?>\xd1x\xa8\xf   +  8jO\x87\xd4U\xff\x00\xa8\xcf\xff\x00d\xbe\xc3W\x99\x00m\x05\x0e\xd1\xd2\xf2\xeb\xcbT\x97\x93\xcfr3\xf6\xee\xb6\xae\x   +  1bW\xa3R\xbe\xa4\xdb\x84\xd7y\xf3\x84\xde\xbe\xcc\xfe\xf1l\xfd@f\x1a\xbf\xa2\x97\xa8\xd2^\xd3\x9e\xf8i\xfe\xd3w+/\xc   +  dK\xd4\xcd$\xed:\xb1\xb44\xff\x00h\x185\x06J\x0f\xa0\x1c\xad\'\xf5\xfa>\xda\xfb\xcf\xa4;\xb7\xf7\x9b\xa5}\x0cO\x9b\x   +  faG\xeb\xf4}\xb5\xf7\x9fH7o\xef;K\xfa\x18\x81\xe9\xa5\xc9\x14yL,\xb2\xb7\xd0\xe3\xbeS\xcb\xe8\x05\xe7Q(\xe4F\xa2\x91   +  k\x83/\x8b,\xa2\xe2Q\x857VO\n    +  re4\xba\xb3\xad\xd5\xf5\xcb\x1d.\xdeUnn)$\xba\xae5\x93\r\xef3}\x1av\x83:\xd6zu\xc4*_G*P\x969\x1a\xb5\xb6\x9b{\xab\xe   +  d\x15\xf4\xea\xd4\xb9\xabI?\x8b\n\x8d    +  6\xd7h\xb7\xfb\xb3\x16\x0e\xa5\x04\xea\xba\xab\x96W4c\x9dk\xb4M4\xdf\xf2t\xe6\x9fvQ\xacu\xaej\xd4\x8f\x9d)I\xf7\xb6\   +  xf2q\xd4[\xea\x06z\x97h\x8d\xa0\xfc\xa1\xb8\xd7\x8f\x93\xf5\x1d\xc5\x87h\xddB2_\x95U\xca\xef\xc25\xc1@\xa2k\x98\x1b\   +  x89\xa0\xf6\x8d\xd1\xea\xce1\xbfu\x9b~\x08\xcb[-\xbc-\x17h)\xc6V\x95\xe3\x1c\xf7NI\x1f9\xe9f\x97\x9e\x8e\xcfO\xd6\xa   +  f\xackF\xb5\xad\xd5h\xf0\xbc\xb8\xa9\xb4\x80\xfaeJ\xe2\x95W\xf9\xba\x91\x97\xa9\xe4\xb9R\\1\xc9\xa5{\xbd\xdf\xa6\xa1   +  \xa5\xd7\xa3J\xf1\xc2T\xb2\x94\xa57\x9eF\xd5l\x9e\xdb\xe8\xfbOiNz}\xca\xab6\x97\x12X\xe4\xc0\xf51\x96VJ\x8bI\xa2\xa4   +  \xc0\xb8;\x8aS\xc9=\xc0b\xed\xf2o\x11lL(,\xb5*\x8b+\x08\xc1\xd5\xbbD\xdf\xf9f\xe9\xd5j>\xa3\xd1\xf6\xc2Yz\x7f\xb2\xc   +  dNK\x9b\x03d\xd7h\xdb\xfc~\x95\xfe\xe9\xdal\xff\x00hj\xd77\xf4\xe9]T\x93\x8c\x9e9#V\x0e\xdbe\xe9\xd4\xab\xacP\x85(\x   +  f1I\xc9\x01\xf4\x87C\xd5\xa3\xa9i6\xf7qM\xc6\xacT\x91\xd8*\xb1Q\xe2\x94\xe3\x15\xff\x00s\xc1\x8f\xf4\x9d\xa7\xb0\xd9   +  m\x83\xb0\xa9\xaa\xd4\x8d)*)\xa4\xcc\x15\xbcm\xfa\\\xdf:\x96\xfa,\xa1*K\xe3E\xe1\x81\xb5:\x8e\xbba\xa7\xd1u+\xdc\xd1   +  \xc2\xeeSG\x91\xb8\xde\xde\xce\xd0\xad\xe4\xe5U\xb9g\x1c\x9a4_S\xda\xfd[P\x94\x9d[\xdb\x85\x97\xd1Tx:\xab[\xcb\xba\x   +  97p\xcd\xc5V\xdc\x97Y0>\x99\xe9Z\xa5\rJ\xc6\x8d\xd5\xbe]:\xab19\xe7\x83\xdd\x07\x13\xd8=1\xc9\xb9K\xc9.\xa7\xb9\xa6\   +  xdb^wP+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7   +  f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\xc0`Q&P\xdbe\xc6P\xd0\x1a\xbf\xdb!\xf0P\xd3\\yg\xc0\xd5\x1c\xf8\x9b_\xdb/\xf5}0\xd5\x00\x19\x08\x82\xe7\x0f8\x8   +  1\x93\xb7_\xba\xeb\xad\xaf\xaa\xa7\xe5gN\x9a\xe7\x9ce3k6\x07uZV\xcd\xd0\xa7*\xd4)\\U]\xee<\xce\x8b\xb3M*+giJ\x11\xc4   +  \xdc\x16Y\x9b\x1c$\xc0\xb5J\x8d8AF\x10Q\x8aXI\x15\xaap\xcf\xa2\x8a\xd4pH\x14\xb8/\x02pU\x81\x80(pO\xaa\rar+\xc1\rd\x   +  0bN)\xf5<\xfe\xd4\xec\x8e\x99\xb4V\x93\xa5ykJS\x97\xc7\x92=\'\x01O\x93\x9b\x97\'\xc8\rF\xde\x8e\xe2\xe5\xa5S\xad\x7f   +  \xa6\xd5u\xe3\x1e~N\x11\xff\x00\x83^/-j\xdb\xdeN\x8dx\xbar\x8b\xc3O\xb8\xfaO\xb5\xf4\xf8tZ\xef\xbb\x85\xe4\xf9\xeb\x   +  bc)\xaf\xe7^\xa1\x95\xff\x00\xc8\xf0\x07\x9b\x94xe\x8c\xe4\xa1\xaeeI\xe4\x890=\xb6\xe6\x97\xf6\xfbN\xf6\x8f\xa1ZO\xe   +  a4\xbdG\xcfm\xccs\xdb\xfd;\xda>\x86iQ\xfe\xa3K\xd4\x07!\xb3V\xfbW6\xabK\x1f$\xday#U{X\xc9+\x89G\xbf\x84\rZ\xcb\xf1\x   +  04dd\t\xc1<\xdfVB*\xe1~\x0c\tJ]q\x94\x8a\xaaNU#\x85\x17\x84B\x94\xe1\xc9g\x0c\x99NQ\\\x93Y\x02\xce\x02*\xa7\tTx\x8am   +  \x9c\xa8\xe9\xd7nm\x9d\xce\xf0\xb6\xae\x8e\xccl\x   +  c5\xcd\xe5y\xaf)\x1c\xa5\x14\xf9\x9a)\xb6\xdbMy\xb4\xba\xd5K\x9b\x9a\x8et\x94\xdb\x82}\xc8\t\xdb\r\xab\xd46\x92\xfe\   +  xa5\xc5\xddz\x8e\x12yT\xe4\xfa\x1enM\xbe\xac\x99\xbe)\xb7\xdcC\x02\xde\x12e3y.\xd2\x83\xab"\xe3\   +  xf4_\xa8\x0f\x9f\xbb\xfa\xf8B\xd4\xbe\x90\xc6\xe8\xc9[\xfa_\xfb\x83\xa9{f4o\x0c\x03\xe4\xf9\x17\xad\xb9M2\xc6J\xe9\x   +  d4\xe0\xee\x03\xe8.\xe2%O\xfa8\xd3\x1b\x92\xcf\x01\x91UZ\x7f)\x1f;4}\xe9\xedN\x8faN\xcfO\xd4\'J\xde\x9a\xc4b\xb3\xcb   +  \xfdNz\xdf>\xda\x7f\x9bO\xfd\x7f\xdc\x0f\xa0\xdeV\x9f\xca\x1eV\x9f\x89\xf3\xf1o\xa7m\x17\xff\x00\x96\x9f\xfa\xff\x00   +  \xb9?\xd3V\xda\x7f\x9bO\xfd\x7f\xdc\x0f\xa0^V\x9f\x88\xf2\xb4\xfcO\x9f\xbf\xd3V\xda\x7f\x9bO\xfd\x7f\xdc\x7fM[i\xfem   +  ?\xf5\xff\x00p>\x81yZ~%\xaa\xf8\x9c[\x8c\xb1\x83@\xbf\xa6\xad\xb4\xff\x006\x9f\xfa\xff\x00\xb90\xdff\xdaF\xa4s\xaa\x   +  d4p\xef\\\xf9\xff\x00\xa8\x1b\xf5E\xa9R^vYs>c1\x0e\xe36\xb6\xf3it\x9au/jJsk-\xb3/\xa5\xf9\xb6\x06\x9c\xf6\xba\x7f\xf   +  5\xcb\x1fd\xd7\x8c\x9b\x11\xda\xed\x7f\xd7l}\x93]\xc0\x82\xfd\xa7\xe9\xe9\xfbK\xef,\x97\xed?OK\xdb_x\x1fD7O\xef3L\xf   +  a\x18\x9e\xdd\x1e\'t\xfe\xf3t\xcf\xa1\x89\xee\x17@\x08\x90\x00\x9e\xe3Z\xfba\xfb\xde\xb2\xfaCe;\x8dk\xed\x87\xefv\xc   +  b\xe9\x00\xd4\x16A,\x80\x06\xf5\xf6g\xf7\x8bg\xea4P\xde\xbe\xcc\xfe\xf1l\xfd@fJ\xdf\xa2\x97\xa9\x9aI\xda{\xdf\r?\xda   +  n\xddo\xd1K\xd4\xcd$\xed=\xef\x86\x9f\xed\x03\x07    +  \xd7!\x12_@9ZB\xfe\xbdG\xdb_y\xf4\x7fw\\\xb6;J\xfa\x08\x9f8t\x7f\xd7h\xfbk\xef>\x8e\xee\xed\xe3ct\xaf\xa0\x8f\xdc\x0   +  7\xa5m\xe0\xb7\xc3\xcb\x99[e\xa9TQ\xe2\xcfD\xb3\x908\xfa\x85zV\x94\xa5^\xbdUN\x9cW<\x9a\xc5\xbf-\xefJS\x9d\x86\x8d]\   +  xc1\xac\xc5\xce\x9c\x8e\xd3\xb4^\xf3\xff\x00\x93\xb8\xf4\x8d>\xab\xe3\x9a\xf4\xa2\xf2\x91\xa9\xd7U\xea]\\J\xbdifryl\   +  x0b\xf7\x97U\xefngquVUj\xcb\xac\xa5\xd5\x9cf\xb8\xa5\xe1\xf3\x85.E2\x92\xef\x02q\x8e\xbc\x89E\x11|r\xc390\xb6\xadRIS   +  \x84\xa7\x9f\x04\x05\x92$\xb2sg\xa5\xdf\xa7\x85g]\xfc\xea\x0c\xa6Z}\xe4#\xc5;j\xb1_\xe9\x92[\r\xa6c\xfb\xb4{X\xf4<6\xe9\xaaI\xec^\x9b\x19BPj\x9a\xe4\xd   +  1\xeec\xd0\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\x   +  d5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\xc0\x02\x92\x1a\xe6T\xc6\x00\xd5\xde\xd9k\xfa\xbe\x9aj~\r\xb2\xed\x95\xfa\r4\xd4\xfc\x01Iw>\x89o\x04\xfcd\   +  x06\xef\xf6h\xe7\xb3\xb4\xbd\x84g\x14\xb9s0ofo{\xf4\xfd\x84g\x16\xf2\x044\x12\xc1    +  \x00\x00\x00\x04\xa0\x18\t\x02r\x07G\xb6~\xe1\\{,\xf9\xd9\xbc/}W\xff\x00H\xcf\xa2[d\xff\x00\xe8W\x1e\xcb>v\xef\x0b\x   +  dfU\xff\x00\xd20<\xe2\x12!\x06\x07\xba\xdc\xaf\xc2\x06\x9d\xed\x1fC\xb4\xa5\xfdJ\x9f\xa8\xf9\xe7\xb95\x9d\xe0i\xde\x   +  d1\xf47K\xfdN\x9f\xa8\x0eQ\xaa\x1d\xad?]~\xc9\xb5\xe6\xa8v\xb5\xfdu\xfb    +  j\xd0\x00\t\xef\xe4_\x8dJ\x98\xe5\x82\xc1v\x94\x1bY\xcb\x02\xed>)T\x8eb\xdc\xbb\x92FH\xd8\xad\xd6k{]*u(QJ\xdda\xcb\x   +  89c\x91\xe97\x11\xbbYm\x15\xeco\xef!/%FI\xa5\x8c\xa6\x8d\xc1\xd14\xcb]2\xda4-\xe8S\xa4\xa2\xb1\x98\xc7\x19\x03\x0bl\   +  xa7g\xfd\x06\x95(\xd4\xbd\xa7S\xca\xa5\xcf\x0f\xbc\xf6\x96{\xa6\xd9\xca\x14\xdd5FO\xd6\x8c\x8f\x18\xe3\xa2\xe4\x14V@   +  \xc5\xfa\x8e\xe4vb\xfa\x94\xbc\xa5)\xa6\xfa`\xc5;q\xd9\xe9\xd1\xa39\xe8\x14\xfas\xf3\x99\xb5\x04J*K\x12Y^\x0c\x0f\x9   +  a\x9bO\xb3z\x86\xcd\xdf\xca\xd7P\xa5%5\xde\x93\xc1\xd3\x1b\xf3\xbdm\x80\xb3\xda\xbd6\xb5\x1f!\nuRrU!\x1ef\x8f\xedn\x   +  87q\xa2j\xb5\xadn)\xb8F\x9c\x9cb\xdfz\x03\xa5\xee+\xa5W\x9a\x8c\xb9c\xa3-t\r\xe5au\x03d;7m\xd4\xed/\xe9h\xd7u_\x0c\x   +  b9\xac\xb3m\xed\xaa\xaa\x90\x8c\xd78\xc9e\x1f4\xf6KU\xad\xa4\xeb\x14+\xd2o\x8dI.\xbf9\xf4\x1fwz\xcc5m\x9c\xb3\xa8\xe   +  4\x9c\xd55\xc4\x07\xacG\x1e\xf6\xb4h[\xd4\xab7\xe6\xc192\xf6O\x1d\xbd\r\xa0\x86\x81\xb3W5j4\xb8\xe0\xe2\xb3\xea\x03U   +  \xfbFm\xd3\xd6\xb5\xd9Y\xd8Tn\xde+\x86K=\xe6\x10M\xae\xa7+[\xba\x9d\xd6\xadu^RrR\xa8\xda\xcb\xf9\xce\x0f\x16@\xbb\x9   +  4\x1f4Z\xe2\xe6\x8fK\xb1;1{\xb5\x1a\xdd+-:\x94\xaa\xbc\xa7,w    +  *\xd8\xfd\x90\xd4\xf6\xa2\xf2\x16\xdae&\xe7\'\xd5\xa7\x83cv3\xb3\xcd\xbciR\xa9\xaf\xd3~U/\x8a\xcc\xb5\xbb]\x88\xd3\x   +  b6_E\xa5N\x9d8J\xe5\xc59I\xc7\x9ag\xb7M\xa5\x80<&\x97\xba\xbd\x9d\xd3\xe9ES\xa2\xde\x876\xa3\xc8\xf1\x1b\xc8\xd9\x1b]\xa1\xd1\xae<\xb5(\xba\x8a\r\xc5\xe3\xbc\x0f\x9d\xde%,\xef6\xb7G\x   +  a9\xa0\xeb\x95\xad\xab\xc5\xc7\xcexO\xc3\'B\xde[\x02s\x87\x93`{/\xedD\xed5\xf9Z\xd7\x9e(p\xe1,\x9a\xf8z\x9d\x80\xd5\   +  xe7\xa6\xeb\xf6n\x9b\xe1\xe2\xa9\x14\xf1\xeb\x03\xe9\r\x19\xc6\xa58\xca=\x1a\xc9\\\xbd\x17\xea:\xdd\x9f\xac\xab\xe8\   +  xf6\x93\x8b\xcei\xc5\xbf\xb0\xec\xdf\xa2\xfd@|\xff\x00\xdf\xd7\xc2\x0e\xa5\xf4\x8c\xc6R\xf4\x8c\x9b\xbf\x9c\x7fH:\x9   +  7\xd2\x18\xca^\x90\x14\x82Y\x00\n\xd1J$\t\x00\x00\x00\x00)\x97R\xa2\x99u\x03r{,\xf3\xd1\xa9\xfb&\xc2\xa5\xe63^\xbb,{   +  \x8dO\xd96\x19z\x0c\r:\xedv\xbf\xeb\xb6>\xc9\xae\xed\x1b\x13\xda\xef\xdd\xdb\x1fd\xd7v\x058/\xda/\xcf\xd2\xf6\xd7\xd   +  eY/\xd9\xfe\x9e\x97\xb6\xbe\xf0>\x88\xee\x9d\x7fct\xcf\xa1\x89\xed\xd2\xe4x\x9d\xd3\xfb\xcd\xd3>\x86\'\xb7\x020H\x00   +  \rk\xed\x87\xefv\xcb\xe9\r\x945\xaf\xb6\x1f\xbd\xdb/\xa4\x03PY\x04\xb2\x00\x1b\xd7\xd9\x9f\xde-\x9f\xa8\xd1Cz\xfb3\x   +  fb\xc5\xb3\xf5\x01\x99+~\x8a^\xa6i\'i\xef|4\xff\x00i\xbbu\xbfE/S4\x93\xb4\xf7\xbe\x1a\x7f\xb4\x0c\x1d\x12_B"K\xe8\x0   +  7/G\xfdv\x8f\xb6\xbe\xf3\xe8\xe6\xef=\xe6\xe9_C\x1f\xb8\xf9\xc7\xa3\xfe\xbbG\xdb_y\xf4sw\x9e\xf3t\xaf\xa1\x8f\xdc\x0   +  7\xa4|\xd1\xe2\xb7\xa5\xb4\x90\xd9\x8d\x9c\xadr\xe6\x93\x9aqG\xb5}\rO\xedC\xb5R\xafySD\x8c\xf0\xe1\xe7a05\xf7kuk\x8d   +  cY\xafqq.,\xcd\xb5\xcf\xb8\xe9\x912\x93ry\t6\xf0\xba\x80.\xc2\x87\x94\x8aT\xe3)To\x1c\x96Kq\xa7\x99(\xb7\x89x\x19\xe   +  fp\xfb\xb9\xad\xaaN\x9d\xfd\xe5\xbems\xe95\x94\x07\x9d\xdd\x9e\xe6\xb5]\xa5\xabN\xe2\xe2\x9aV\x7f\x1b<\x99\xb0\xfb5\   +  xb8\xcd\x13N\x8a\x9dzRr\x8f\xed2~\x8b\xa6Z\xe9\xd4)\xd3\xb5\x8ca\x18\xac5\x15\x83\xb9N8\xea\x07\x85\xa5\xbb\xfd\n+\x   +  86\x9d\x0e\x7f\x86,\xabQ\xd6\xab)\xcb\xbd\xe4\xb5\xc8g\xe7\x0   +  2\xb1\x92\x8c\x93\x902F\xe3uu\xa4ml*5\x9e6\xa2o\xb6\x97u\xf9M\x85\x19\xb8\xf0\xf1E3\xe6\xe6\xc7\xdcJ\x8e\xd0\xd98ef\   +  xacW\xfa\x9fF\xf6\x7f\xcf\xd1l\xa4\x9f\xff\x00\x14~\xe0;\x19z/\xd4hWhJ\xbc[u\x7f\x1ct\x99\xbe\xb2~k\xf5\x1a\t\xda\t\   +  xff\x00o\xb5\x0fl\x0ca\xdeTR\xfa\x86\xc0\xef\xb62\x9cn\xb6\x9a\xc6\x8dH\xa7\x07<4\xcf\xa1\x1b\x01e\x1b=\x9c\xb5\xa7I   +  %\x05\x1eI\x1f>\xb7}\xef\xbbO\xfaD}\x13\xd8\xd5\xff\x00@\xb6\xf6@\xee\x11RD\xe1\x00"Q\xcf\xac\xa6T\xd4\xa2\xe3>q}Qp\   +  x01\xa4]\xab,h[m\xbbt)\xa8\'\x0e\xe3\x05\x1b\x01\xda\xd7\xdf\xa7\xfe\x06\xbf\x809\xda\x1c\xb8u{F\xba\xaa\x8b\xef8\'3   +  G\xf7V\xd7\xe9\x10\x1fDwU^w\x1b1o*\x8d\xb6\xa2\x97\xfa\x1e\xce^\x8b\xf5\x1e#t+\xfb+C\xd9_q\xeejz\x0f\xd4\x07\xcf\xbd   +  \xfd?\xfd\xc1\xd4\xbd\xb3\x19\xb7\x93%o\xef\xe1\x0bS\xf6\xd9\x8d@\x98G\x89\xe1\x15\xf9\x1c\xbc\'\xcf\xc0\xa6\x9c\xb8   +  %\x93\x91c\x0f)r\xa4\xfad\x0e\xd2\xd7c\xf5\xdb\xcbx\xd6\xb4\xd3n+S\x97IEu9\x11\xd8=\xa7\x7f\xfe\x1a\xef\xf7W\xfb\x9b   +  \xbb\xb9;+\x7f\xe6\x06\x9dQ\xc32q=\xed+5\xe5x\xb9p\xf8\x01\xf3\xa3\xf9\x81\xb4\xff\x00\xe4\xb7\x7f\xba\xbf\xdc\x7f06   +  \x9f\xfc\x96\xef\xf7W\xfb\x9fH\xbf&\xa5\xe0?&\xa5\xe0\x07\xcd\xdf\xe6\x06\xd3\xff\x00\x92\xdd\xfe\xea\xff\x00q\xfc\x   +  c0\xda\x7f\xf2[\xbf\xdd_\xee}"\xfc\x9a\x97\x80\xfc\x9a\x9f\x80\x1f7\x7f\x98\x1bO\xfeKw\xfb\xab\xfd\xc9\x8e\xef\xb6\x   +  9eRI\xe8\xd7i{+\xfd\xcf\xa4?\x93S\xf0-V\xa1Ma(\xf5\x03\n\xf6r\xd0\xaf\xf4}*\x9c/\xad\xeaQ|?\x19\x19\xc5z\x0c\xa2\x85   +  ?\'\x1cg\x91>w\x0b\xe6\x06\x9e\xf6\xbb\xf7v\xc7\xd95\xdc\xd8~\xd7|K\\\xb1\xf6Mw\xe6\x04\x97\xec\xff\x00OK\xdb_y\xc7\   +  xe6r,\xff\x00OK\xdb_x\x1fD\xb7O\xef7L\xfa\x18\x9e\xdc\xf1\x1b\xa7\xf7\x9b\xa6}\x0cOn\x00\x00\x00\xd6\xbe\xd8~\xf7l\x   +  be\x90\xd9CZ\xfba\xfb\xdd\xb2\xfa@5\x05\x90K    +  \x01\xbd}\x99\xfd\xe2\xd9\xfa\x8d\x147\xaf\xb3?\xbc[?P\x19\x92\xb7\xe8\xa5\xeaf\x92v\x9e\xf7\xc3O\xf6\x9b\xb7[\xf4R\   +  xf53I;O{\xe1\xa7\xfb@\xc1\xd1%\xf4"$\xbe\x80r\xf4\x7f\xd7h\xfbk\xef>\x8en\xf3\xden\x95\xf41\xfb\x8f\x9cz?\xeb\xb4}\x   +  b5\xf7\x9fG7y\xef7J\xfa\x18\xfd\xc0w:\xadwma^\xb2\xf8\x91l\xd0]\xf8j\x92\xd46\xe2\xe2\xbfG\xd0\xde\xfd\xaa\x97\x06\x   +  cf\xde\xcb\xc2\x9b>w\xef\x0e\xb3\xb8\xda[\x89g>s\xfb\xc0\xf3\xf5\xb1\xc4\xb0\xba\x94G\x93L\xa6rm\xa0\x98\x17\xa9MB\x   +  ba\xa9%\x9c3,l\xa6\xf8n6{F\x8d\x85\x0bi\xe1w\xa7\xff\x00&#]\n\xba\x81\x9b\xe1\xbf\xeb\xfaI\xaf!U\xe7\xe7\xff\x00\x91   +  \xff\x00\xa8-C\xfb\x8a\xbfo\xfc\x982\xa2\xc7R\xd8\x19\xde]\xa0\xb5\'\xd2\x8dU\xff\x00\x97\xfc\x94\xff\x00\xea\x07R\x   +  fe\xee\xb7\xef\x7f\xc9\x82\x80\x19\xd7\xff\x00P:\x96?E[\xf7\xbf\xe4K\xb4\x06\xa2\xf8qF\xaa\xc7\xfd\xdd\x7f\xd4\xc1@\   +  x0fY\xb7\x1b[Sj\xb5)\xdd\xd6\xa6\xe39x\x9ei?\x02\xca*\x8b\x02\xe6Y\x0er\x8bN/\x0c"b\x93\xfd\x80nOf-^W;7F\xc2^\x94y\x   +  f1\x19\xfb\x1c\x91\xaa\xdd\x95\xae\x9f\xe5\x8a\x8a\xee\x89\xb5+\x9a\x03X\xfb^\xf5\xb0\xf6MP^\x936\xc3\xb5\xe2\xe7a\x   +  ec\x9a\xa1\xf1\xd8\x14\xa6^\xa5O\x8e\x9e\x13\xe6\xde\x0b\'e\xa0Q\xf2\xf7\xf4\xa0\xfd\x17$\x06\xd5\xf6h\xd8Jzu\x8b\xd   +  4.\xe9\xaa\xd3\xac\x94\xa0\xe4\xbd\x13ch\xd2\xe0\x97\x17y\xe5wYmN\xdfc\xb4\xe5Ma\xf9%\x93\xd8\x00k$`\xa9u%\xa0(H\x94   +  0J@J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x   +  15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x03\x002S&Q\xc4\x06\xb2v\xc9\xfd_M5A\xf56\xb7\xb6D\xbf3\xa6\x1a\xa7>\x80RW\x18\xe1\xaf\x06\xca\n\x9c\x9f\x0e\x00\x   +  dd\x0e\xcd\xfa\x85\xac\xf4Z4T\xd2\x9cb\xb9d\xce\xd5+F\x9a\\]\x19\xf3\x97a\xf6\xe6\xff\x00en\xe1V\xdeR\x9cS\xcf\x0b|\   +  x8d\xa4\xdd\xee\xfc\xb4\xfdj\x9d:Z\xc4\xe9[O\xa7\xed\x03h#\x83\xa5jV\xba\x95\x18\xd4\xb4\xaa\xaaA\xf7\xa3\x9a\x9f   +  <\x01QR)*\xee\x02AO\x1a\xf1#8\xe8\x05}\xc5\x8a\x93\x8e\\~0\xa9s\ni\xba\x92I#\xc1m\xd6\xf34}\x9c\xa3?\xeb\x14\xa5r\xb   +  e#\x03\xb8\xda\xda\x94\xec\xf4K\x99U\x9aM\xa7\xd5\x9a\x03\xb7\x9c56\x9e\xfe\xa2i\xa9Tx2\x0e\xf4w\xc9\xa8m7\x94\xa1l\   +  xbc\x8d.\x99\x84\x8c5Z\xadJ\xd3s\xab7)>\xad\xb0(k\x0c\x82F\x00\xf7\xbb\x92x\xde\x06\x9d\xed\x9fB\xf4\xcf\xd4\xe9\xfa   +  \x8f\x9e{\x96\xe5\xb7\xfaw\xb4}\n\xd2\xdf\xf5:^\xa09\x8c\xd5\x0e\xd6\x9f\xae\xbfd\xda\xf6\xcdO\xedi\xfa\xeb\xf6@\xd5   +  \xc0\x00\x035\xf6d\x94!\xb7V\x89\xbef\x142>\xe2\xb5%\xa6m\xcd\xad\xc5ip\xd2\\\x9b`}\x08\xe1]QR:\xed\x1a\xf27\x96t\xa   +  bA\xe62YL\xec\x1b}\xc0TIo\x89\xf8\x15$\xc0\x96\x88\xc18\x18`P\xcf\x0b\xbez\x8a\x8e\xc1j\x13}\x14Ou7\xc2\xb2\xcc\'\xd   +  a+jiYl\xb5\xd6\x9b7\x15:\xd1\xe5\xe2\x06\x96\xea\xf5U[\xf9\xcdt\xc9\xc5|\xdeH\xa8\xf8\xa6\xdb\xf1\x11\x02\x99\xf46{\   +  xb2O\x9fJ\xe1\xf7)\x9a\xc94\xe4\xb0\xba\x9bU\xd9\x0e\xc6Q\xd2\xef\xeaTMK\x8b\x92\xf1\x03f\xe3\xe7L\xd4\xde\xd5\xb6\x   +  cd\\\xce\xafsf\xd7\xd2m7\xc5\xc9\x9a\xe1\xda\xc6\xc5GC\x8d\xc3\xef\x98\x1a\x8c\x89!\xfc\xc4\x810%\xa9I\xf2\x8b\x7f\x   +  b0S\xf4\xd1\xb1\xdb\x94\xdd\xe6\x87\xb5:U:\xb7\x17\t\\\xbe\xb0\xc0\x1a\xe2\xa9\xd4\x7f\x12_a>F\x7f&_a\xbc\xf1\xdcV\x   +  8b\x8f\xd2/\xdd\'\xfa\n\xd1\x7f\xbc_\xba\x06\x8b\xf9\x19\xfc\x99}\x83\xc8\xcf\xe4\xcb\xec7\xa3\xfa\n\xd1\x7f\xbc_\xb   +  a?\xa0\xad\x17\xfb\xc5\xfb\xa0h\xbf\x91\x9f\xc9\x97\xd8<\x8c\xfeL\xbe\xc3z?\xa0\xad\x17\xfb\xc5\xfb\xa4\x7fAZ/\xcb_\   +  xba\x06\x8cy\x19\xfc\x99}\x83\xc8\xcf\xe4\xcb\xec7\x96[\x8c\xd1\xba)\xac\xfb$\xff\x00Az\'\xf7\x8b\xf7@\xd1\x9f#?\x93   +  /\xb0y\x19\xfc\x99}\x86\xf3-\xc5\xe8\xad\xfak\xf7J\xd6\xe24_\x96\xbft\r0\xd9\x18Vz\xf5\x8ccM\xfe\x96=\xdf9\xf4_gZ\x8   +  6\x8fe\x1ey\xf2Q\xfb\x8f\x19\xa1\xeewF\xd2\xaecZ1\x84\xe5\x17\x95\x98\x99&\x95\xbc)S\x84"\x92QX@S&\xf8_\xa8\xd0^\xd0   +  \x1e\xff\x00\xb5\x1fl\xdf\xe9G\xcd~\xa3@{@\xacm\xfe\xa3\xed\x81\x8c\x1b\xe62\x1fQ\x80=\x16\xefW\xf6\xbbO\xfaD}\x14\x   +  d8\xefp-\xbd\x93\xe7n\xef\x17\xf6\xb7O\xfaD}\x14\xd8\xdfpm\xbd\x90;\x91\x82\xa1\x80)\xc0\xc1V\x08\xc0\x1aY\xda\xd7\x   +  df\xa3\xf6\r\x7f6\x07\xb5\xb2\xfe\xda?`\xd7\xf0    +  \xe6h\xfe\xea\xda\xfd"8\x989\x9a?\xba\xb6\xbfH\x80\xfa\x19\xba\x0fz\xb4=\x95\xf7\x1e\xe6\xa7\xa0\xfdG\x86\xdd\x07\xb   +  dZ\x1e\xca\xfb\x8fsS\xd0~\xa0>|\xef\xef\xe1\x0bS\xf6\xd9\x8dL\x95\xbf\xbf\x84-O\xdbf5\x02i\xfag&\xd3\x95u\xeb8\xd0\x   +  f4\x8eM\xb7+\x88z\xc0\xdf\xfd\xc6\xc7\xff\x00o4\xd6\xfeA\x90\x8f\x03\xb8\xe5\xff\x00\xb7:g\xb0{\xf4\x80\x95\x92\xa5\   +  xd0$N\x18\x02H\xc1    +  \x0br\xea\\(\x92\x02\x87\xd0\x84\xff\x006\xca\x9fB\x8cy\xad\x01\xa8\x1d\xaf_\xfdn\xc3\xd95\xd8\xd8\xfe\xd7\xb4[\xd6t   +  \xfcu\xe15\xd2\x14\xf3\xc5\xc4\xf0\xd0\x16\xcb\xf6\x7f\xa7\xa5\xed\xaf\xbc\xe3\xe4\xbbl\xdf\xe5\x14\xbd\xa5\xf7\x81\   +  xf4Wt\xfe\xf3t\xcf\xa1\x89\xed\xcf\x0b\xbaJ\x91\x96\xc5\xe9\xdc\xf9\xaa1=\xa7\x94\xf1\xe8\x05\xe0ZRy\xe6\xb9\x13\xc4   +  \xf3\xcb\xa0\x17\rk\xed\x87\xefz\xcb\xe9\r\x93\xcf#[;_5W@\xb4\x8cy\xc9O\x9a\x03PY\x04\xb4\xd3\xc3\'\x0c\nM\xeb\xec\x   +  cf\xef\x16\xcf\xd4h\xba\x83\x97N\xe3z\xbb5E\xc7`\xec\xdfv\x00\xccU\xbfE/S4\x93\xb4\xf7\xbe\x1a\x7f\xb4\xdd\x9a\xaf\x   +  f3R\xf5\x1aK\xdau\xff\x00hi\xfe\xd00|I}\nb\xca\x9f@9z?\xeb\xb4}\xb5\xf7\x9fG7y\xef7J\xfa\x18\xfd\xc7\xce=\x1f\xf5\xd   +  a>\xda\xfb\xcf\xa3\x9b\xbc\xf7\x9b\xa5}\x0c~\xe09[b\xb8\xb6kPK\xfb\xa9\x1f;\xb6\xb9y\x1d~\xe5K\xaf\x13\xeb\xeb>\x8c\   +  xed\x15\'_E\xbb\xa6\xba\xca\x9bG\xcfm\xeb\xd8\xca\xc3j\xee)\xc9a\xe5\xbc\x01\xe3d\xf3&B\xeb\xcf\xa0\x00r8\xe3\xc1\xc   +  3\x1c\xe4\xa2\x9a\xa9Ny\xe0\x97\xd8w\x9b\x19iF\xf3Y\xb7\xa1]\xae\n\x93Qo\xc0\xdb\xdd#r\xba%\xd6\x9dJt\xea)\xa9E6\xf8   +  @\xd2z\xdcu%\x9e\t}\x85\xaf\'?\x91/\xb0\xde\xd8\xee+D\xf2n.q\xe7\xdf\xc2[{\x86\xd1?\xbd_\xba\x06\x8by9\xfc\x89}\x83\   +  xc9\xcf\xe4K\xec7\x9d\xee#E\xcf\xe9\x17\xee\x90\xf7\x13\xa1\xae\xb5W\xee\x81\xa3>N\x7f"_`\xf2s\xf9\x12\xfb\r\xe5\xfe   +  \x824W\xe8\xd4O\xff\x00\x12?\xa0\x8d\x1f\xe5\xaf\xdd\x03G8%\xf2%\xf6\x15F\x94\xbeL\xbe\xc3x\xe3\xb8\xad\x0f8\xf2\xab   +  >\x1c%kq:/\xf7\x8b\xf7@\xd1\xc5J_&_a\x12\xa7%\xf1e\xf6\x1b\xcb\x1d\xc5h\xbf\xde/\xdd&[\x87\xd1e\xff\x00\xc8\xbft\x0c   +  e\xd9R\x8b\xa7|\xaa\xca2I\xc7\xbd\x1b^\xb9\xa3\xcb\xecf\xc4\xd8l\xbd\xba\xa7i\x18\xb6\xbe60z\xbc`\ra\xedy\xd6\xc3\xd   +  95?\xe3\xc8\xdb\x0e\xd8\x1c\x9e\x9f\xec\xb3S\x97\xa4\xc0\x8c\x1d\xc6\xcc{\xa9F+\xbeH\xe9\xf2v\xfb,\xff\x00\xeb4=\xa4   +  \x07\xd0\xdd\xda\xae\r\x91\xd3\xf3\xfd\xda=b<\xae\xef^vOM\xc7\xf7h\xf5h\x01(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8\   +  xaa@\x0c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x0c\n\x1a\xc9C.\x14   +  \xc905\x93\xb6\r\xbdj\xf6\xfat\xa9S\x94\xa3\x1e\xadw\x1a\xa5Qr\xe5\xd4\xfa=\xb6\xfb)e\xb5z]kk\x8a\\UxZ\x83}\x134\xf3   +  x\xfb\x9b\xd5\xf6r\xbdZ\xf4b\xa7C/\n\x9a\xe2k\xec\x03\x0f\xe4\x9c\x95\xdd[V\xb6\xa8\xe1Z\x9c\xe2\xd3\xef\x8bE\x94\x0   +  5x\xe2\xef\xc1\xc8\xb4\xba\x95\xb5E(da    +  *\xac\xb89\'\x9c\x96pW"\x90!&\xfa"R\xe7\x86_\xb5\x84\xa7)*~\x96\x0fE\xb2;\x13\xabm6\xa1\n\x16\xb4g\x0c\xbfJpi}\xa0v\   +  xfb\x95\xb6\xabWot\xf9R\xa7)EK\x9bG\xd0]2.6t\x94\x96\x1aF\x1d\xdc\xde\xea-\xb6V\x9d;\x9b\xfaQ\x95\xe7&\xa5\x1c\x19\x   +  b2+\x92\xc0\x07\xd4\xd5\x0e\xd6\x9f\xaf?e\x1b`\xd1\xaa\x1d\xad?^~\xc8\x1a\xb6\x00\x00s,k\xd6\xb4\xa9\x1a\xb4j8\xca->   +  G\x0c\xb9\x16\x06\xf1n\x03x6z\xee\x89N\xca\xe2\xa4i\\P\x8a\x82R|\xe6\xcc\xd2\xf9\xac\xa6|\xd4\xd9]\xa0\xbb\xd9\xfdB\   +  x9d\xcd\x95G\n\x90yL\xdc]\xd1\xef~\xc7h\xec)Y\xdf\xd5\xe1\xbf\x82\xf3\xe7R\\)\xfd\xa0f>\x19g\xd3+\xc3K.E\x8a\x176\x9   +  5\x92t\xee(\xcf\xd9\xa8\x99u\xd4\x8c\x96"\xd0\x17#%\x8e\xa4\xf1/\x13\x8a\xe7\ny\xe3\xabN+\xe7\x92GC\xb4\x9bW\xa6l\xf   +  5\xac\xae.\xae)N\x18\xf4aQ6\x07k\xac\xea\xb6z}\xa5J\xd7u\xe9\xd3\x8cSy\x934o\x7f\x1b}\x1d\xab\xd7\xe5\x0bzN\x9d*\r\x   +  c39\xe5/\x9c\xf4\x1b\xe9\xde\xd2\xda\n\xd5-t\x99\xd4\x85\x9fG\x19g\xa9\x83\xeb\xcaW\x12\xf2\x8f\xfd@\xb2\xb9\x95&\x8   +  8\xc7!J9\x9b\xc8\x17\xad\xa2\xe7qJ)e\xb9%\xfe\xa6\xfbn?f\xe3\xa3\xec\xcd\xbdh\xc5E\xd6\xa6\xa4\xcdJ\xdc\xb6\xc8\xcfi   +  \xf6\xb2\x85*\x90\xe2\xa1\xd7\x9a\xe4o\x8e\x93h\xf4\xdb\x1b[Jk\x10\xa5\x05\x109\x93\x8e%\x93\x15v\x85\xd0^\xb7\xb2\x   +  0e\x10\x87\x14\xa1\x99rFY\x92\xcb:\xfdn\xce\x17\x9a]\xcd\x19\xa4\xf8\xa9\xb4\xbe\xc0>e][\xba7uh\xb5\x87\x194Xk\x0f\x   +  06@\xde\xa6\xcfOg\xf6\x8e\xe23\xa6\xd2\x9c\x9c\x97/\x9c\xf0\x13y\x93~    +  Bx2\xa6\xe2\xb6\xe6[/\xb4\xb4\xdd\xcbr\xb6\x97\x9b\xc3\x9eH\xc5e\xcaM\xc2\xa4d\xba\xa7\x90>\x9c\xe8z\xa5\xbe\xadaJ\x   +  e6\xd6\xa4g\x19\xc57\xc2\xfa\x1d\x81\xa5\x9b\x9e\xdf\x1d]\x9d\xb8\xa3i\xa8\xd4\xa9+>\x8e+&\xd8\xec\xee\xd9iZ\xf5\xa4   +  +\xda\xdc\xd1\x82\x92\xce%Qd\x0fDCh\xb1\xf9]\x16\xb3\x1b\x8aM?\t\xa1:\xb4\xb8\x7fMMz\xe4\x80\xbc\xe7\x15\xd5\xa4D\xa   +  a\xc21rrX]Y\xd6\xdc\xdfX\xd1M\xd7\xba\xb7O\xe7\xaa\x91\x82\xf7\xbd\xbek]&\x9d[\x1d\x1a\xabU\xf9\xc6R\x8b\xcao\xf6\x0   +  1\x9e\xe8\xea\x16\xb5\xab8\xd1\xaf\t\xcf\xbe)\xf49\x91K\xaeO\x9f:v\xf6\xb6\xa6\xcbR\x9d\xcd\xad\xea\x8b\x93\xe7\x94\   +  xfa}\xa6f\xdd\xee\xff\x00\xe3p\xe9\xdb\xebu*N\xbb~\x974\x80\xdaX\xa5\xdcU\xd0\xf3{;\xb5\x9af\xb1o\t\xdb\xdc\xd2M\xae   +  \x8e\xa2\xc9\xdeN\xe2)f-I|\xcf    +  _\xc8-Q\x9f\x1cs\x86\x8b\x80\'\x8e\x16|\xff\x00\xed\x07\xf0\x81\xa8\xfbg\xd0\tz/\xd4|\xfe\xed\x05\xf0\x81\xa8\xfb`b\   +  xf7\xd4d2\x00\xf4\xdb\xbb\x7f\xda\xdd?\xe9\x11\xf4Oc\xbd\xc1\xb6\xf6O\x9d{\xbc\xf7\xdb\xa7\xfd">\x8alo\xb86\xde\xc8\   +  x1d\xd8\x00\x00\x00\r-\xedk\xef\xcf\xff\x00\x03_\xbb\xcd\x81\xedi\xef\xcd\xfb\x06\xbf.\xa0I\xca\xd1\xfd\xd5\xb5\xfaD   +  qY\xcb\xd1\xfd\xd5\xb5\xfaD\x07\xd0\xcd\xd0{\xd5\xa1\xec\xaf\xb8\xf75=\x07\xea<6\xe8=\xea\xd0\xf6W\xdc{\x9a\x9e\x83\   +  xf5\x01\xf3\xe7\x7f\x7f\x08Z\x9f\xb6\xccjd\xad\xfd\xfc!j~\xdb1\xa8\x13\x1fI\x1c\xba\x14\xe4\xee)\xb5\x16\xd6N%8\xb9\   +  xcb\t\xe0\xe6\xdaV\xa9J\xe6\x9c\\\x962\x07\xd0\r\xc8\xb5\r\xdc\xe9\x9c\\\xbc\xde\xf3\xdf\xc6Qk)\x98\xd7r\xb7\xb6\x95   +  v\x07N\xa7V\xe2\x8aj=\x1c\xd22\x14n,\xa1\x0cF\xe6\x86>\x91\x01\xcaR^#\x8e>\'\x13\xf2\xab?\xf14?\x88\x88\xfc\xaa\xcd\   +  x7f\xf6\xa8\x7f\x11\x01\xcc\xe2^$\xa6\x8e\x17\xe5\x96k\xff\x00\xb5C\xf8\x88\x95\x7ff\xbf\xfb4?\x88\x80\xe6\xe5\x14\x   +  c9\xa5\xd4\xe2\xff\x00(\xd9\xff\x00\x8a\xa1\xfcDQR\xfa\xd2o\n\xea\x87\xf1\x10\x1c\xae(>I\xa6D\xa2\xf2q]\xc5\x9c0\xe1   +  sC/\xc2\xa2/?)S\x0e\x9c\xe2\xe3\xf3<\x81\xac\x9d\xad,jN\xee\xce\xea4\xdb\x8d8sf\xaeW\x96s4\xb1\xc4o\x86\xfe4\x17\xaa   +  \xec\xa5\xcc\x92R\xa9\x08r4WQ\xa5\xf9%y\xdb\xd5^t\x1e\x00\xeb\xcb\xb4e\xc1\xc3/\x06\x99A]$\x9b\xc3\xe8\x06\xe5vf\xdb   +  \x1aZ\x9e\x91;;\xba\xd1\xa7:IF\x11\x93\xe7/Q\x9e%\x88\xf3\x97G\xd0\xf9\xc7\xb1\x1bOq\xb3z\xc5\x1b\xbaSq\x859e\xa4nf\   +  xef7\xa1\xa6\xedM\x8d\x08\xd5\xaf\x1au\xf1\xe7:\x93Q\xcf\xda\x06T\x8b\xe3\x8e\x17\xdaT\xbc\xc7\x86q(_\xd9\xe5F\x17T\   +  x1a\xc7uD\xcb:\x86\xb9\xa7Y\xc1\xba\xb7T0\x96\x7fJ\x80\xeckV\xa7J\x9b\x9dI(\xc1ul\xd2\xce\xd2\x1b\\\xaf\xf6\x82\xbe\   +  x9fJ~R\x959ri\xf22\x0e\xf87\xd7ooJ\xb6\x9d\xa4T\x92\xa9$\xe3\xc4\x9eQ\xaa\xba\xc6\xa1q\xa9_T\xb8\xba\x9f\x1dY<\xb6\x   +  07\n\xae\x1dND\xe1`\x84\xb9\xe4\xa8\x0b\xb6Q\xe3\xa9\xe4\x92\xcb\x97$o\xb7g\xeb_\xc9wyc\t\xacO\x1d\r(\xdd\xf6\x93-Si   +  \xec\xa9B9\x8b\xa8\x93\xca>\x82\xecf\x95\x1d+D\xb7\xa1\x14\x96"\x80\xef*\xbf\xcdK\xd4i/i\xdf|4\xff\x00i\xbb5\x7fE/S4   +  \x97\xb4\xef\xbe*\x7f\xb4\x0c!\x12[\xe4R\xba\x95>\x80r\xf4w\xfdz\x8f\xb6\xbe\xf3\xe8\xee\xef=\xe6\xe9_C\x1f\xb8\xf9\   +  xc3\xa4{\xa1G\xdb_y\xf4{w~\xf3\xb4\xaf\xa0\x8f\xdc\x07\xa2\xa9\x0588\xcb\x9a}M\'\xed=\xa0\xca\xd7k+^\xd3\xa6\xd5\'\x   +  cb8\xe4n\xd3\xe8\xcc5\xda\x1bd\x96\xb9\xb2\xf3\x9d\xad?\xcfE\xf17\x804g\xd2\x0b\x0b\xafB\xfd\xed\xbc\xad\xae\xaaQ\x9   +  7XI\xa6Y\xc0\x1c\x9b[\xc9ZV\xa7Z\x83\xe1\x9c^y\x1b\x89\xd9\xefx\xb4\xb5M\x1e\x96\x9d{]+\x95\xdf\'\xcc\xd3\x17\x13\xb   +  6\xd9\xbdn\xf7A\xd4awaW\xc9\xd5\x8b\xeb\xf3\x01\xf4\xc7\x8b\x94\\^S]J\xb3\x93\x02n\x8b|\xf6\xfa\xbd\xbd+MV\xab\xf2\x   +  cb\x11\xe2\x93\xc2\xff\x00S5[kz}j|t\xae(\xc9|\xd5\x13\x03\xb0o\x1dH|=\xeb%\xbaW\x14k\xc7\x8dT\x86=\xa4U;\x9bh,J\xbd%   +  \xeb\x9a\x02p\xe5\xe8\xf2E\x8a\xf7\x94(.\x1a\xf5\xa1M\xf8\xb6y\xdd\xa7\xdb}+g(J\xad\xcd\xcd\x1a\x89,\xe2\x9dD\xd9\xa   +  a\xfb\xd1\xdfU\xce\xa7\xa8N\x1a-Y\xd3\xa5\x19|d\xc0\xdc\xcbj\xd6\xf5\xa2\xa7F\xacj|\xe8\xbe\xe7\x14\xf0\xdaF\x89l\x9   +  e\xfb\xb6\x8bI\xb8\x8f\xe5\x17nV\xcb\xacRy6#w\xfb\xe8\xd0\xf6\x924\xe9\xdcq\xc2\xe1\xf2r\x9b\xe1_\xea\x06fR\x8a\xea\   +  xf1\x92\xec^y\xa3\xa7\xb6\xbf\xb4\xbbQ\x95:\xf4\xaa\'\xd1Bi\x9d\xa5\x06\x9a\xe5\xd0\x0b\xc1\xa0\x00\xd5\xfe\xd8>\x96   +  \x9f\xec\xb3SW\xa4\xcd\xb3\xed\x81\xd6\xc3\xd9f\xa6\xafI\x81\x07m\xb2\xfe\xecP\xf6\x91\xd5\x1d\xb6\xcb\xfb\xb1C\xda@   +  }\x0e\xdd\xd7\xbd=7\xe8\xd1\xebQ\xe4\xf7v\xbf\xb2:w\xd1\xa3\xd5    +  *\x04\x12\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x   +  02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   +  00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xc0%\x90\x04F)<\x9cmB\xce\x85\xdd\t\xd3\xadJ\x9c\xe3%\x87\xc5\x14\xceYEX\xe5r   +  \x03\x03o\x0fq\xfa^\xb3\x1a\xb5\xac#?\xca\x1eZ\x8cV\x17\xfa\x1a\xbb\xb6[\xbc\xd6vf\xf2\xa4n\xed\xdch\xa6\xf8_>\x87\x   +  d1g\x1c\xacc\x07M\xadl\xf6\x9f\xab\xdb\xce\x9d\xe5\xa5*\x92|\xb8\xa4\xb2\x07\xcdem%\x9e5\x8c\x16%\xc9\xb4m\x86\xf37\   +  t\n\x8a\xa5\xe6\x95VnO2\xf2P\\\x8ds\xda]\x94\xd4t:\xd2\x85\xed\xb4\xe9\xa8\xbfJ@y\xa4\xca\x94\x9aM.\xf2#\tJ\\1Ya\xc5   +  \xc5\xe2K\x0c\t\x84\xe5\x07\x98\xb6\x8e]=V\xfa\x9c8auq\x18\xf8*\x8d#\x86\xca@\xbdZ\xe2\xadw\x9a\x93\x94\x9f\x8c\x9eK   +  qmd\x84JY\xe4\x80\xa92\xb4\xe1\xc3\xcd\xf3-\xf4x}NV\x9fcq{p\xa9[Ru*?\x8a\x80\xe2\xf3\x93\xe5\xcc\xed4M\n\xff\x00Z\xb   +  8Tl)9\xd4o\x08\xca\xbb\xbb\xdc\xbe\xa9\xad^\xd1\xa9\xa9P\xabkA\xf3\xce\r\xa0\xd8\xfd\xddi[9B0\xa7oJ\xadD\xb1\xc6\xe3   +  \xcc\x0c\x15\xbb\x8d\xc2;\x98\xd0\xb8\xd7!R\x95D\xd4\x9a\x8bx6gg\xb6SM\xd1,\xe1F\xd6\x85?5/9\xc1d\xed)[\xc6\x8d4\xa9   +  \xacz\x8eE$\xf1\xe7\x01>M$\xb0\xba\x17#\xd0\x82P\x06j\x87kO\xd7\x9f\xb2m{5C\xb5\xa7\xeb\xcf\xd9@j\xe0\x00\t*\x8fR\x8   +  2\xa8\'\'\xc9d\x0b\xa9\xe1\xe7\xbd\x17\xa8]\xdc[\xd5U(V\xa9NK\xe4I\xaf\xb8\xe3\xf4|\xc9l\x0c\x81\xb3\xbb\xd7\xda\r\r   +  E[\xd4\xf2\x98\xfe\xf2m\x9e\xb6\x87h\xed\xab\xa5\x1e\x15B\xd9\xafR\xff\x00c\x08\xf1\x0e    +  2\xe6\xa9\xbfm\xa6\xd4b\xd5H\xd2\x86~K\xff\x00\x83\xc1k{S\xa9\xeb\x15\x1c\xaen*\xf3\xee\xe3x:\x1c\x8c\xa0*\x93r\xea\   +  xdb\xf5\x8a\xb5\x1c\xd2\xca\xc6<\n[&1\x94\x97%\x90)I\xe3\xce9z}\xad{\xbb\x9aT(\xc3\x8aS\x92\x8a\xc1j\x85\n\xb5\xebF\   +  x8d(\xb9\xd4\x9b\xc2F\xcdn\x03u\xb3\x85Jz\x96\xadA\xe1\xac\xa8\xcdt\x03    +  vz\xd8\x1f\xe4\r\x16\x9d\xdd\xf57\x0b\xb7\xcdz\x8c\xdb\x84Y\xb5\xa5J\x8d\x18S\xa5\x14\x94V0\x8b\xe0[}J*AIa\x97\xb0\x   +  88|8\x03\x07\xef\xf7v\xf4\xb5\xed\x1e\xb6\xa3gM\xcbQ\x82\xf3b\xba`\xd2\xfdSO\xadeuR\x85X\xf0\xd5\xa6\xf1%\xf3\x9fL\x   +  eb\xd2U3\n\x91S\x83]\xe6\xb2\xef\xebur\xa8\xea\xeaZe&\xb1\x99\xc9A\x01\xab1\x8e:\x95\xa4r/(N\xd6n\x95x\xf0\xce=S,&\x   +  9f@\x12\x9c\xb8p\xb9|\xe8\xec\xb4}\xa3\xd4\xb4\x99\xf1[\\\xd6\xe5\xdc\xea<\x1d[e\xb6\x06I\xb4\xdf\x16\xd1Z\xc21\x8c\   +  x94\x94|dr\xae\xf7\xdf\xb4\xb71\xe1\x97\x93\x8a\xf9\x9f\xfc\x18\xad\x90\x07\xb0\xd6v\xff\x00Z\xd5`\xe3Z\xe2\xa4\x13\   +  xf95\x1a<\xadj\xb5kI\xca\xadI\xcd\xbe\xf9I\xb2\xd9    +  F\x19r\nq\xf3\xd4\x9cW\x8ax(\xc9S\x8b\xe1\xc6y\xf8\x01\xe8\xb6kiu\x8d\x16\xe25\xac\xab\xd5\x97\x0b\xcaR\xa8\xf0m\xbf   +  g\x9d\xb7\xd6\xb6\xae5\xa9\xea\xf4\xa1\x18R\x8f\x9a\xd7\x7f\xfa\x1a\xe5\xba}\x82\xbf\xda\xab\xfaO\xc9N6\xaa^t\xd2\xe   +  4\x8d\xd8\xd8\xdd\x97\xb4\xd9\xbd*\x8d\x0bZpU#\x1cJia\xb0=B\x8e:\x13\x82!,\xaeeY\x02%\xe8\xbfQ\xf3\xfb\xb4\x17\xc2\x   +  06\xa3\xed\x9f@e\xe8\xbfQ\xf3\xfb\xb4\x17\xc2\x06\xa3\xed\x81\x8b\xd9\x04\xb2\x00\xf4\xbb\xbc\xf7\xdb\xa7\xfd">\x8al   +  o\xb86\xde\xc9\xf3\xafw\x9e\xfbt\xff\x00\xa4G\xd1M\x8d\xf7\x06\xdb\xd9\x03\xbb\x00\x00\x00\x01\xa5\xbd\xad=\xfa?`\xd   +  7\xee\xf3`{Z{\xf4~\xc1\xaf\xdd\xe0\x19\xcb\xd1\xfd\xd4\xb5\xfaE\xf7\x9cC\x99\xa3\xfb\xabk\xf4\x88\x0f\xa1{\xa1\xf7\x   +  abC\xd9_q\xeej?\xcd\xbfQ\xe1\xb7C\xefV\x87\xb2\xbe\xe3\xdcT\x7f\x9b~\xa0>|\xef\xed\xff\x00\xee\x16\xa5\xf4\x8c\xc6\x   +  e6G\xdf\xd3\xff\x00\xdc-K\xe9\x0cn\x00\x96\xdb\xc7\x8a\x00\x0fS\xa4m\xc6\xad\xa5[B\x85\xb5Y(G\xa2\xe3gh\xf7\xa5\xaf\   +  xb8\xf0\xf9g\x8fm\x9e\x08\x01\xee\xbf\xa4\xfd{\xfb\xe9~\xfb!\xef7]\x7f\xfc\xd2\xfd\xf6x`\x07\xb8\xfe\x92\xf5\xdf\xef   +  \xa5\xfb\xec\x8f\xe9+]\x7f\xfc\xd2\xfd\xf6x\x80\x07\xb7\xfe\x92\xb5\xcf\xef\xe5\xfb\xec\x98\xef3]\x8ax\xad.\x7f\xf7\   +  xb3\xc3\x802\x06\x9f\xbc\xcdu^\xd1\xfc\xf4\x9ar\\\xb8\xd9\xba\x1b\x9c\xd6\xaeu\xad\x99\x85k\xacq\xf2\\\x8f\x9e\xd6?\   +  xaeP\xf6\xd1\xbe\xbd\x9f\xbd\xe8S\xf5\xaf\xb8\x0f}\xac\xe9\xd4\xb5\r>\xbd\xad\\\xb5Q`\xd1\r\xf6lm\xd6\xce\xed%\xc5YS   +  \xc5\xb5I\xbe\x07\xe2o\xfc\xa5\x89\xe3\x1dLo\xbem\x86\xa3\xb5z\x1dGN\x0b\xf2\x9aQn).m\x81\xa0<1\\\xa4\xdeH\x9aq\xe4w   +  \x1bE\xa4\xddhZ\x9d[+\xfa\x0e\x9dX\xb7\xca]N\x9e\xa2i\xe79@\x1c\x9bX.\xda\xde\xddZ\xcdJ\x85\xc5Zm|\x99\xb4X\xc8\x03\   +  xdaXo#\\\xb2\xa2\xa9\xc2\xbc\xe4\x97|\xa6\xce\xbfX\xdb]_S\x8bU\xaej\xc5?\x93Q\x9ei\xa2\x90+\xa9V\xa5YqT\xa99\xcb\xc6   +  O"\t\xcb\xa1Az\x8c%<\xf0\xa7\xc8\x08\x8ce7\xe6\xa2\xe5.\x0c\xf0\xcd\xbc\x94\xa6\xd4\xb3\xd1\x19\x03t\xbb\ry\xb5\xfa\   +  xfd\x08\xc6\x84\x9d\x97\x17\x9fU.H\x0c\xad\xd9\xbfb%Z\xab\xd4/\xe98\xd3X\x959%\xd4\xda{~8\xe21_\x9aK\x93:\xdd\x97\xd   +  9\xebm\x03G\xa3eB1\xf3#\xc3\xc4\x97S\xb9\xa7\x1e\x18$\x04V\xfd\x14\xbdL\xd2N\xd3\x9e\xf8i\xfe\xd3v\xeb~\x8a^\xa6i\'i   +  \xcf|T\xbfh\x18E\x06\x10`s4\x9f\xd7\xe8\xfbk\xef>\x8en\xef\xdev\x95\xf4\x11\xfb\x8f\x9cZO\xeb\xf4}\xb5\xf7\x9fGww\xe   +  f;J\xfa\x08\xfd\xc0ztq5\x1bX\xdd\xdaV\xa38\xa6\xa7\x17\x1eh\xe5\xc7\xa1\x0f\xa8\x1a)\xbfM\xdc\xd7\xd9\xadf\xb5\xdd\x   +  a59;Z\x8d\xceR}\xcd\x98\x87\x9e9\x9fH\xb6\xebem6\xa3G\xadgq\x08\xc5\xc9r\xa9\x8eh\xd1\xdd\xeb\xec%\xee\xca\xea\x93\x   +  8b\xa35n\xe4\xf8f\xd7T\x06>\xc9\x1c\xd3\xc9\x19D\x81v\x95\xe5z2N\x8dI\xd3k\xbe2h\xf5:6\xf0\xb5\xad*)Q\xaf9\xa5\xf2\x   +  a6\xd9\xe3\x99\x00e\x9a;\xf3\xdajT\xf8"\xa9c\xd7\xff\x00\x07\x0bQ\xdf\x1e\xd1_Sp\xa9(\xc5?\x93,\x18\xcc\x01\xdajZ\xd   +  5\xfe\xa3VS\xb8\xba\xae\xf3\xdc\xea6\x8e\xb5\xe5\xbc\xb7\x96\x00\x15)4\xb0_\xb7\xba\xadC\x9d\x1a\x93\xa6\xff\x00\xed   +  \x93G\x1d,\xb4\xbb\xcem\xa5\x85\xc5\xcd\xcc(R\xa6\xe5R]\x12\x03!\xee\xd3y:\xf6\x91\xaaP\xb7\xb5\x93\xac\xa5$\xb1RNF\   +  xf2lv\xa1s\xaahV\xd7w\xb0\x8ckN9\x92\x8fC]\xf7\x13\xb9\xff\x00$\xe9\xea\x9a\xbc\x1ce\x1cJ0\x9a\xeal\xf5\xa5*v\xf4cN\   +  x94Tc\x15\x84\x90\x17\xc0\xc8\x03X;`u\xb0\xf6Y\xa9\xab\xd2f\xd9v\xc1xz\x7f\xb2\xcdM^\x93\x00v\x9b1\xee\xcd\x0fi\x1dV   +  N\xd3f}\xd8\xa1\xed    +  >\x8a\xee\xe1gdt\xef\xa3G\xa8<\xc6\xed\xfd\xe8i\xdfF\x8fQ\x80\x18\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@\x0   +  c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f@\x00\xa5\x   +  94\xb4V\xc8\x02\xcdNqk\xb8\xf1[Y\xb0\xda^\xd0\xd2\x9cn\xada9\xb5\xc9\xb3\xdb\xca<\xc8Q\x03L\xf7\x99\xb9[\xdd\x1eu.\x   +  f4\xc4\xe5Ms\xe0\x84L\x1f\xaa\xe9\xd7z}g\x0b\xdaS\xa7,\xf2\xe2X>\x9c\xdcP\xa5qM\xc2\xacT\xa2\xfec\x19m\xee\xe7t-\xa5   +  \xa5:\xae\x87\xf5\xa4\xbc\xc7\x94\xb9\x81\xa0\xa0\xcb\x1b\xc1\xdc\xf6\xad\xb3U\xaa\xd6PR\xb6O\xcdPY\x7f\xe8c\tZU\x8c   +  \x9ceF\xaak\xb9\xc5\x81\xc6+\xa3\t\xce\xaccN.R}\x12=\x06\xcdlv\xa9\xb47P\xa3gB\xa4x\x9e3(<\x1b-\xbb=\xc1P\xb3To5\xea   +  Q\x9dU\x89G\x85\x81\x836\x1fvZ\xb6\xd2]\xc1\xca\x85Z4\xdf\xc6\x94y\x1bG\xbb\xcd\xcc\xe9\x9a\r\nuo)R\xadr\xb9\xf1\x99   +  ?I\xd2\xadt\xcbx\xd1\xb5\xa7\x18\xc2+\x0b\x92;\x18Ec\x00q\xe8\xdbS\xb5\xa5\x1atR\x8c\x12\xc6\x11z(\xba\xe0\x92)H\t\x   +  89q\x14"\xb4\x04\xe0\x00\x043T;Z~\xbc\xfd\x94m{5C\xb5\xa7\xeb\xcf\xd9@j\xe0\x00\n\xe9A\xd4\xa9\x18.\xb2x=t\xb6\x1bV\   +  xa7\xa7\xab\xcat*\xbax\xceTO/\xa76\xaf\xed\xda\xeb\xc6\x8d\xed\xdd]\x95\r_c!CR\xa6\xa7\x17\x14\xb9/\x98\r\x14\xba\xa   +  5:3p\xa9\x17\x19\xae\xb98\xf27?n7\x0b\xa6jj\xa5m&\x8a\x8dis\xf3\x9a\xea`\x9d\xa4\xdc\x86\xd1i\x93\xab5\x18J\x9cy\xe2   +  <\xc0\xc4\x81\x1d\xd5\xce\xcc\xea\x94%%;J\xef\x0f\x1c\xa9\xc8\xe0\xd4\xd3/\xa9\xcb\x12\xb3\xb8\xcf\xd1K\xfd\x80\xe2\   +  xf7\x13\xdcs\xe8\xe8\xd7\xf5zY\xdc\x7f\n_\xecz\x8d\x9e\xdd\x96\xbd\xaeJ*\xd6\x8b\x86~\\Z\x03\xc3\xe1\xfa\xce\xdfE\xd   +  1\xb5\x1dR\xe6\x14l\xed\xea\xcb\x89\xe31\x8eL\xf5\xb1\xbd\x9d\xf5\x178K\\\x8d)S\xea\xd4Y\x9f6Cw:\x0e\xcd\xce\x8b\xb4   +  \xb6j\xb4{\xdf>`a\xed\xce\xeeeY\xd4\xa7\x7f\xaeS\x8dY)e,#\x94R\xa0\x97B\xa4\x05,\xa1\xa2\xebE-    +  ,\xb4q\xaf\xac\xe8\xde\xd0\x95\x1b\x84\xa5NK\x12O\xbc\xe64D\xa8\xc6k\xce\x03Z\xb7\xbb\xb8\xf8\xeaUj\xde\xe9\x1c\x14\   +  x96\\\xb8b\xba\x9a\xcf\xb4{7\xa8h\x972\xa3^\xda\xacT^8\x9cy\x1fK*Q\xcd>\x14\x93G\x87\xdb=\xdfi\x1bEBQ\xbb\xa0\x9c\x9   +  f\x86\x00\xf9\xdd\xcf<\xc86Sm\xfb>]S\x94\xa7\xa2\xc2\x11\x8fU\x96c-ct\x9a\xfe\x92\x97\xe5\x10So\xe4E\xb01\xbb    +  \xf4\x17\x9b+\xaa[I\xa9Z\xd6~\xaal\xb3Kg5*\xaf\x10\xb3\xb8^\xbaR\x03\xa6$\xf6zN\xee\xf5\xadE\xa8\xd3\xa18\xc9\xf4\xe   +  2\x83FF\xd9^\xcf\x1a\xf5\xddHU\xbf\xf2>E\xf3k8x\xfb@\xc1\xd6\x96U\xee\xea([R\x95I\xf8E\x19\x83u\xdb\x9e\xd46\x82\xbd   +  *\xd7\xd0\x95\ny\xe9R86\x13bw%\xa2h\x95!Z\xbd\xbej\xaf\x9d>fW\xb5\xd3\xed\xed`\xa3F\n),,    +  :\r\x8e\xd9[-\x9a\xb0\xa5oaJ4\xdaIM\xc7\xe33\xd4`F\x9a\x8fB\xac\x01\x11*!\x12\x02^\x83\xf5\x1f?\xbbA|    +  j>\xd9\xf4\x06^\x8b\xf5\x1aC\xbe\xdd\x8b\xd65\r\xb7\xd4nh\xd2r\xa5)\xe5b-\x81\x83\x19\x07\xa6\x96\xc5\xeb\n|?\x93U\x   +  cf\xd1\xb2\x7f\x99Z\xbf\xf8j\xbf\xc3`S\xbb\xcf}\xba\x7f\xd2#\xe8\xa6\xc6\xfb\x83m\xec\x9a)\xbb\xed\x86\xd5\xe7\xb4\x   +  b6U#FpP\x9f7(4on\xcb[\xd4\xb4\xd1\xa8Q\xad\x8e8\xae`w    +  \xa52r\x04\x80D\xb3\xc2\xf1\xd4\r.\xedi\xef\xd1\xfb\x06\xbe\x9b9\xdage\xb5MWj]\xc5\xbd7*|=\xd1l\xc1\xafb5e4\xbf\'\xa   +  b\xfb\x8c\x0f*s\xf4U\xff\x00V\xb5\xfaDw\x0fb\xf5|\xbf\xea\xd5y\x7f\xfa\xd9\xdb\xec\xe6\xc1k\x15u\x1bj\xae\x84\xd4\x1   +  4\xd7X07gt\x9c\xb6b\x87\xb2\xbe\xe3\xdcT\xf4\x1f\xa8\xf2\x9b\xbd\xb0\x9e\x9f\xa0P\xa3QbJ+\xee=5V\xfc\x9c\xb8z\xe0\x0   +  f\x9f\xdb\xfa\xf8B\xd4\xbe\x90\xc6\xe8\xcd[\xee\xd8\xfdR\xe7l\xef\xaeiQ\x9c\xa19\xe5b\r\x98\xf6\x8e\xc5j\xd3\xcbv\xd   +  5q\xf4l\x0f0\x0fO\xfc\xc9\xd5\xf0\xff\x00\xabU\xcf\xd1\xb2\x9f\xe6N\xb1\xfe\x1a\xaf\xf0\xd8\x1eh\x1e\x97\xf9\x93\xac   +  \x7f\x86\xab\xfc6?\x99:\xc7\xf8j\xbf\xc3`y\xa0z_\xe6N\xb1\xfe\x1a\xaf\xf0\xd8\xfed\xeb\x1f\xe1\xaa\xff\x00\r\x81\xe6   +  \x81\xe9\x7f\x99:\xc7\xf8j\xbf\xc3c\xf9\x93\xac\x7f\x86\xab\xfc6\x07\x9a\x07\xa5\xfed\xeb\x1f\xe1\xaa\xff\x00\r\x94\   +  xbd\x8c\xd5\xd3\xfdV\xaf\xf0\xd8\x1d\x1d\x8f\xeb\x94}\xb4o\xafg\xefz\x14\xfdk\xee4\xc3N\xd8\x8dbw\x94\x7f\xab\xd4^r\   +  xeb\x06n\xde\xe5\xb4\xbb\xad\'f)\xd2\xbb\xc2|\x9e\x00\xc83k\x8f\x18\xe7\xe2[I\xc6\xa4\xb8\xbc\xe5\xe0rb\x94\x9eQ\x1e   +  J)\xb7\xe2\x06\'\xde\xd6\xea\xb4\xed\xaf\xb4\xa9skF\x9d\x1b\xf5\xcd\xd5}Y\xa7{m\xb1\x9a\x9e\xcfj\x13\xa3R\xd6\xac\xa   +  9E\xfaj<\x8f\xa3\x9c\tG\x1d\xc7\x9e\xda]\x95\xd2\xf6\x82\xdeT\xaf\xe8)&\xbb\x92\x03\xe6\xd5Jj\x18\xca\xc3\xf0-\xc8\x   +  db\r\xb8\xec\xf3\x1b\x99\xce\xa6\x85\x08A\xbek\x8d\xa3\x12k{\x8f\xdam)9\xd6T\xe7\x15\xf2\x16@\xc5\x0c\xa5\x9e\xbe\xb   +  6\xc4j\x91\x9b\x82\xb6\xab\xc5\xec3\x95a\xbb-z\xf6\xacaN\x8bM\xf8\xc5\x81\xe1NM\x92\xadR\xa2\xa7B2\x94\xa5\xcb\x08\x   +  cc\xfa\x1e\xe0u\xfb\xbcyo%\x87\xe3\xff\x00\xfd3&\xc3n\x1fJ\xd3#J\xa6\xa3AJ\xea8m\xa7\xc8\x0c\x19\xbb\xad\xd3\xea;IqM   +  V\xa5:4\x9b\xcb\x94\xe3\xc9\x9bu\xbb\xbd\x92\xb1\xd9M:6\xb6\x94#Nx\xf3\x9a\xefg\xa8\xd2\xb4\xcb}2\xda4m\xa9\xa8\xc1/   +  \x03\x98\xe9\xa75.\xf0    +  \x82\xe3\x8f2\x1cP\x16k/\xcdK\xd4\xcd$\xed9\xef\x8a\x97\xed7z\xacsNIx\x1a\x8d\xda\x1bdu\rOY\x8d[jr\x92Y\xe9\x16\xc0\   +  xd6\xc0\xcfL\xf67T\x84\xb8em[+\xff\x00\xd6\xca\x96\xc5j\xd3Y\x8d\xbdE\xff\x00\x83\x03\xa2\xd2\x7f_\xa3\xed\xaf\xbc\x   +  fa;\xbb\xbfy\xdaW\xd0G\xee4K@\xdd\xfe\xb3swI\xc2\x84\xe2\xd4\xd7X?\x13}v&\xd2v{-\xa6\xd0\xab\xfaHRI\x81\xdf\xc3\xa0h   +  \x98t\'\x00X\xa9NNY\xcf\x9b\xe0y\r\xb4\xd9+\x1d\xae\xb0\xadB\xf2\x84]D\xb1\tK\xb8\xf6\xb2Y\xe4R\xe0\x80\xd1\x8d\xe5n   +  \x92\xf7D\xadQ\xdaP\x9c\xe1\x17\xd6\x11\xe4b\x1b\xabZ\xf6\x95\x1c.)\xca\r|\xa4};\xd4,(_Q\x95+\x88FQk\x0f\x91\x87\xb6   +  \xebr:F\xb1)\xd5\xb5\xa0\x95W\xd1\xe5\x01\xa3\xb2    +  \xcd\xfbK\xb8\x1d\xa0\xb1\xab:\x94<\x93\xa2\xba%\xcd\xfd\xe7\x81\xd5\xb7}\xadi\xcd\xf9Ky\xcb\x1f&\r\x81\xe3I;\x95\xb   +  3Z\xa7\xf8:\xff\x00\xc3\x91z\xd7d\xb5k\x9a\xaa\x9c-k&\xfci\xb0:\x12T[i.\xac\xc9z>\xe6\xb6\x93S\xc3\xa5\x08\xc5?\x94\   +  xb0e}\x89\xec\xf8\xe1R\x94\xb5\xc8Bx\xeb\xc2\xc0\xc0Z\x06\xc7\xea:\xcdJj\xd6\x95I6\xfb\xa3\x9c\x1bC\xb9\xfd\xd0R\xd2   +  \xe8\xd3\xbf\xd6\xe1\x1a\xf5\xa3\xd15\xcd\x19cd\xf6\x07E\xd9\xacKO\xa1\xc3\x12\xe5en\xfdt\xd1\xce\x93J\xa7\x13\x   +  97"\xa4\xb3\xcf<\x80\xeb\xe3\xa5X9K66\xd8\x7f\xfe\xb4Lt\xbb*mpZP^\xaah\xe7\xb4\x00\xa21\x8cc\x88\xa4\x97\xcc&\xe4\xa   +  0\xdc\x16dW\x82Ty\x01\xc1\xab\xa7[\\\xc5J\xe2\xd6\x84\xaaw\xf1A2\x9f\xe4\x9b\x08A(\xd8\xdbg\xe8\xd1\xd9\xa5\xc8`\x0e   +  \xbf\xf9.\xc7\x96,m\xbf\x85\x12\xaf\xe4\xab\x0f\xf06\xdf\xc2G=\x05\xd4\x0e\x07\xf2U\x87\xf8\x1bo\xe1D\x7f%X\x7f\x81\   +  xb6\xfe\x14N\xc0\x01\xd7\xff\x00%X\x7f\x81\xb6\xfe\x14G\xf2U\x87\xf8\x1bo\xe1D\xec\x00\x1d\x7f\xf2U\x87\xf8\x1bo\xe1   +  D\x7f%X\x7f\x81\xb6\xfe\x14\x7f\xd8\xec00\x07_\xfc\x95a\xfe\x06\xdb\xf8Q\xff\x00b\x97\xa5X\x7f\x81\xb5\xfe\x12\xff\x   +  00c\xb2\xc1n\xa4r\xf9K\x00pV\x95\xa7\xe7?\x91\xdb\xa6\xbc)\xa2\xf3\xa3\x184\xa9EF>\x0b\x91{-r\xc6J\xa3\xcdt\xc0\x13O   +  \n(\xa9\x91\x82@\xa5\x96g9\'\xc9"\xfb\xe8[\x92\xc0\x16\x1d77\x99e\x15J\xda\x8c\xe3\xc3R\x94&\xbf\xee\x8ae\xd4\xb9\x1   +  5\xc5\x01\xd6\xcfH\xb0\xce\x7f"\xb7\xcf\xd1\xa1KN\xb5\x84\xd3\x8d\xad\x08\xfa\xa0\x8e\xc7\x03\x84\x0bq\xb7\xa5\x1fF\   +  x11\x8f\xa9\n\x8ePK\x81&^\xc1L\x96@\x8aO1\xcb.d\xa1G\x1d\n\x80\x90\x10\x02\x1a8u\xf4\xfbk\x8a\x8aU\xa8R\x9b_*)\x9c\x   +  d6F\x00\xeb\'\xa3\xe9\xeeM\xfeCm\xfc(\x94\xbd\x0bN\x93\xcf\xe4v\xeb\xd5M\x1d\xae\x06\x00\xeb\xe9\xe9VT\xda\x94m(E\xa   +  f\nh\xe5\xc6<+\t$\xbc\x11w\x044\x02<\x91Q\x18%\x01\x0c\x12\x00\x82\xdc\xb3\x9e\x85\xd1\x808\xb3\xa6\xaaK\x15i\xc1\xc   +  7\xe7Y-\xd4\xd3l\'\xe9\xd9\xdb\xcb\xd7M3\x9b\x8c\x91$\xb0\x07U-\x1fM\xe2\xe5\xa7\xda\x7f\n?\xecL4k\x08\xbc\xab\x0bU\   +  xf3\xaaQ;\x1c\xff\x00\xda8[\xf8\xc0X\xa7mB\x92\xfc\xdd\nQ\xf5E"\xe4i\xc5<\xf4\xf9\x8b\xaa\x1f9*\x00S\xc5\xf3\x15E\xe   +  4p\x92\x96\x00\x94N\x08$\x00\x00\x0e\x0e\xa1gF\xeb\n\xbd\nuR\xf9qL\xe1\xc7@\xd2\xf3\x97aj\xdf\xcfJ\'o%\x92\x89\xa6\x   +  97    +  :\xef\xe4=.?\xfe>\xd3\xf8Q\xff\x00b#\xa2\xe9\xbcI\xc2\xca\xda/\xe6\xa6\x91\xd8\xc3?\x1f\xa1_\x99\xdc\x05\x14a\x1aqQ\   +  x84Tb\xba$\x8b\xc9\xf2#\x04\x81    +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\   +  xfcU    +  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x0000\x00\x10\t\xc0\xc0\x10F\n\xb00\x04\x02@\x14\xe0\x92p0\x04\x02F\x00\x82p\x00\x0c\x0c\x   +  00\x05\xba\x9c\xb0j\x9fk?\xd7\x1f\xb2\x8d\xad\xaa\x9bK\x06\xa9v\xb1\xfdu\xae\xfe\x105l\x15`\x8c\x01\xc8\xd3\xbf^\xa1   +  \xed\xa3\xe8\x06\xe3W\xf6R\x97\xa9\x1f?\xf4\xfeW\xd4=\xb4o\xee\xe2\xe6\xa5\xb2\xb4\xb1\xe0\x80\xc94\xfd&\\(\xa6\xb0\   +  xd9s\x00S\x81\x82\xac\x0c\x01N\x06\n\xb00\x04"P\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x020\t\x18\x02\x9c\x0c\x15``\np0   +  U\x81\x80(h(\xac\x95\xe0`\n\\\x13\n)t*\x00\x00\x0000\x00\x0c\x10H\xc0\x14\xb4G\t^\x06\x00\xa3\x85\x0e\x04V\x00\xa5,\   +  x12N\x06\x00`>`\x01C\xa5\x16\xb0\xd7"p\x97$T0\x05\x18\xe48pU\x82@\xa7\x03\x05X\x18\x02\x01    +  \x06\x06\x00\x00\x00\x00\x00\x00\x00\x00F2H\x02\x12\xc0\xc1 \x08\'\x00\x01\rr)h\xac`\n\x12*D\xe0`\np0U\x81\x80    +  2p0\x058$\x9c\x0c\x01\x04\xe0\x00\x18 \x91\x80 \x13\x81\x80 \x13\x81\x80    +  `\x9c\x00\x18\x18\x00\x06\x06\x00\x01\x81\x80\x00`\xa7\x85\x15\x00    +  \x94\x00\x11\x80H\x01\x80\x00\x00\x00\x10\xc8H\xa8\x01\x0e)\xaee<\x11L\xac\x01\x04\xe0`\x00\x00\x00\x00\x00\x00\x00\   +  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x   +  7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\xab\xb6\xa3\xc8\xd5\x1e\xd54jU\   +  xd4_/\x8am\x9bI\xf5:\x8d[f\xf4\x9d^\\Z\x95\x8d\x1b\x87\xe34\x07\xcc\xcf\xc9*x2?$\xa9\xe0}!\xfe\x8fvW\xfc\x92\xd3\xec   +  \x7f\xee?\xa3\xdd\x95\xff\x00$\xb4\xfb\x1f\xfb\x81\xf3\x9bN\xb4\xa9\xf9}\xba\xe1\xf8\xe8\xdf\x8d\xccR\xfc\x9be\xe8\x   +  a7\xf2Q\xe8c\xbb\xed\x96\x8c\x94\xa3\xa2\xda\xa6\xb9\xa7\x86w\xf6z}\xb5\x9d%N\xda\x94i\xd3_\x16 r    +  \xf2\x93+!$\x97"@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   +  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xf   +  a\xaf\xe2\xa9\x00?\xff\xd9\r\n------WebKitFormBoundaryAIGBXkBO7yWnYuGc--\r\n'}]   +    +  During handling of the above exception, another exception occurred:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:93 in │   +  │ __call__ │   +  │ │   +  │  90 │ │ │ await response(scope, receive, send) │   +  │  91 │ │ │ return │   +  │  92 │ │  │   +  │ ❱  93 │ │ await self.simple_response(scope, receive, send, request_headers=headers) │   +  │  94 │  │   +  │  95 │ def is_allowed_origin(self, origin: str) -> bool: │   +  │  96 │ │ if self.allow_all_origins: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:144 in │   +  │ simple_response │   +  │ │   +  │ 141 │  │   +  │ 142 │ async def simple_response(self, scope: Scope, receive: Receive, send: Send, │   +  │ request_headers: Headers) -> None: │   +  │ 143 │ │ send = functools.partial(self.send, send=send, request_headers=request_headers) │   +  │ ❱ 144 │ │ await self.app(scope, receive, send) │   +  │ 145 │  │   +  │ 146 │ async def send(self, message: Message, send: Send, request_headers: Headers) -> │   +  │ None: │   +  │ 147 │ │ if message["type"] != "http.response.start": │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:59 in │   +  │ wrapped_app │   +  │ │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ 57 │ │ │  │   +  │ 58 │ │ │ if is_async_callable(handler): │   +  │ ❱ 59 │ │ │ │ response = await handler(conn, exc) │   +  │ 60 │ │ │ else: │   +  │ 61 │ │ │ │ response = await run_in_threadpool(handler, conn, exc) # type: ignore │   +  │ 62 │ │ │ if response is not None: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/exception_handlers.py:25 in │   +  │ request_validation_exception_handler │   +  │ │   +  │ 22 ) -> JSONResponse: │   +  │ 23 │ return JSONResponse( │   +  │ 24 │ │ status_code=HTTP_422_UNPROCESSABLE_ENTITY, │   +  │ ❱ 25 │ │ content={"detail": jsonable_encoder(exc.errors())}, │   +  │ 26 │ ) │   +  │ 27  │   +  │ 28  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:303 in │   +  │ jsonable_encoder │   +  │ │   +  │ 300 │ │ encoded_list = [] │   +  │ 301 │ │ for item in obj: │   +  │ 302 │ │ │ encoded_list.append( │   +  │ ❱ 303 │ │ │ │ jsonable_encoder( │   +  │ 304 │ │ │ │ │ item, │   +  │ 305 │ │ │ │ │ include=include, │   +  │ 306 │ │ │ │ │ exclude=exclude, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:289 in │   +  │ jsonable_encoder │   +  │ │   +  │ 286 │ │ │ │ │ custom_encoder=custom_encoder, │   +  │ 287 │ │ │ │ │ sqlalchemy_safe=sqlalchemy_safe, │   +  │ 288 │ │ │ │ ) │   +  │ ❱ 289 │ │ │ │ encoded_value = jsonable_encoder( │   +  │ 290 │ │ │ │ │ value, │   +  │ 291 │ │ │ │ │ by_alias=by_alias, │   +  │ 292 │ │ │ │ │ exclude_unset=exclude_unset, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:318 in │   +  │ jsonable_encoder │   +  │ │   +  │ 315 │ │ return encoded_list │   +  │ 316 │  │   +  │ 317 │ if type(obj) in ENCODERS_BY_TYPE: │   +  │ ❱ 318 │ │ return ENCODERS_BY_TYPE[type(obj)](obj) │   +  │ 319 │ for encoder, classes_tuple in encoders_by_class_tuples.items(): │   +  │ 320 │ │ if isinstance(obj, classes_tuple): │   +  │ 321 │ │ │ return encoder(obj) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:59 in  │   +  │ │   +  │  56  │   +  │  57  │   +  │  58 ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { │   +  │ ❱  59 │ bytes: lambda o: o.decode(), │   +  │  60 │ Color: str, │   +  │  61 │ datetime.date: isoformat, │   +  │  62 │ datetime.datetime: isoformat, │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 140: invalid start byte   +25-Aug-12 20:18:05 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=86609;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=648296;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=458907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=222483;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=350635;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=689697;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=271170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=634748;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48212 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=984017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=346992;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:08 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=280289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=401479;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=111468;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=340078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=634020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=61193;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=750499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=85754;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48213 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=806073;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=342863;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:11 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=816927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=775280;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=343687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=866951;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=607324;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=299883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=775811;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=334784;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48214 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=569906;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=609404;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:14 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=33236;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=274409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=924845;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=509306;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:18:15 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=595086;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=733238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=660778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=55056;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48215 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=681553;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=718623;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=712132;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=619079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=379660;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=536503;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=637731;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=394501;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=356449;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=843910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48216 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=649952;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=848693;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:21 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=408677;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=51146;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=680438;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=305395;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=447981;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=903477;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=592350;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=520497;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48217 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=510539;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=257793;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=219518;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=91676;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=447767;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=176528;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=372672;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=330251;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=614288;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602735;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48218 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=287866;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=394835;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:27 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=956675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=320155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:18:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=627289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=738978;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=326573;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=754286;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=876329;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=548104;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48219 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=405344;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=478061;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=583970;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=650746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=361043;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=375203;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=968800;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=712718;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=509055;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=37930;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48220 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=837625;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=321076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:34 INFO  send() - 124.70.231.45:20909 - "GET /api/conversation HTTP/1.1" 200 ]8;id=367126;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=615135;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=771057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=880356;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=613508;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995794;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=520260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=49670;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=398612;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=61854;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48221 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=590412;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=89813;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:36 INFO  send() - 124.70.231.34:48222 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=701254;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=536824;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:37 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=270786;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=684000;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=910492;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=353379;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=378541;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=228071;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=625693;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=666715;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48223 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=180472;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=286248;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:40 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=498129;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=15034;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=498726;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=172669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=459877;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=230632;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=164069;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=603543;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48224 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=987842;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=41209;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:43 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=195903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=430093;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=468468;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=331514;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=593966;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995243;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:18:44 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=236319;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=606247;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48225 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=669007;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=952699;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:47 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=746929;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831823;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=124505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=92564;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=566615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=81874;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=409382;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=244922;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48226 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=162304;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=17278;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=535444;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=161691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=772495;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21787;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=989409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=875114;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=889689;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=108041;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48227 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=837263;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=405655;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=817906;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=211643;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=534368;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=427198;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=76949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=631446;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=976018;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=729543;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48228 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=283711;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=470976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:18:57 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=66643;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=985764;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=90554;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=588472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=530038;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=540472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=496170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=727768;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48229 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=387987;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=282778;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:00 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=419414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=24673;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=931130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=978746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=790739;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=414668;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=676622;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=3812;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48230 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=460634;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=436011;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:03 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=205136;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=449386;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=397050;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=744067;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831541;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=910773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=543001;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48231 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=151903;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=77410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=206364;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=179601;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=831600;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=812604;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=842580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=580969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=898356;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=604787;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48232 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=422462;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=207748;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:08 INFO  send() - 124.70.231.34:48234 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=527182;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=809936;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48233 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=754313;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=985669;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48235 - "POST /api/stop HTTP/1.1" 200 ]8;id=492950;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=630481;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:09 INFO  send() - 124.70.231.34:48734 - "GET /api/llm HTTP/1.1" 200 ]8;id=163;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=779505;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=61285;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=98867;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:48237 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=535687;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=700363;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48735 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=252040;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=208398;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48736 - "POST /api/stop HTTP/1.1" 200 ]8;id=437147;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=514030;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48737 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=363592;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=181825;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:10 INFO  send() - 124.70.231.34:48740 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=747220;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=340945;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=987293;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=947747;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:48738 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=217919;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=666643;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48739 - "GET /api/llm HTTP/1.1" 200 ]8;id=231921;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=905147;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48742 - "POST /api/stop HTTP/1.1" 200 ]8;id=868976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=148094;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48741 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=530487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=406446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=786484;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=534027;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=394020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=200438;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:19:11 INFO  send() - 124.70.231.34:48236 - "GET /api/conversation HTTP/1.1" 200 ]8;id=18126;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=752245;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=34462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995171;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=116450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=796547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48743 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=135017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=378040;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:12 INFO  send() - 124.70.231.34:48745 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=960520;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=292898;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:13 INFO  send() - 124.70.231.34:48744 - "GET /api/conversation HTTP/1.1" 200 ]8;id=406872;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=325331;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:14 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=78664;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=670040;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:48749 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=340334;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=740131;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  INFO  send() - 124.70.231.34:48748 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=384689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=393991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=843523;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=810508;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:19:16 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=118668;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=762723;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48747 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=541683;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=388446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10633;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=903663;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=458278;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=36767;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=168334;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=206293;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48750 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=65599;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=253665;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:17 INFO  send() - 124.70.231.34:48746 - "GET /api/conversation HTTP/1.1" 200 ]8;id=461940;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=326548;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48752 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=284409;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=29725;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:19 INFO  send() - 124.70.231.34:48751 - "GET /api/conversation HTTP/1.1" 200 ]8;id=773152;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=873667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=511288;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=78197;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:48756 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=983931;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=296797;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=38733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=765189;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48755 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=873861;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851199;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=2076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=720814;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:19:21 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=786628;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=555143;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48754 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=182213;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=308418;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=649993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=227834;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=698516;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=645960;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48757 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=863206;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=582195;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:22 INFO  send() - 124.70.231.34:48753 - "GET /api/conversation HTTP/1.1" 200 ]8;id=309338;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=116381;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:23 INFO  send() - 124.70.231.34:48759 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=223446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=902826;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=995345;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=875257;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=750212;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=922665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48758 - "GET /api/conversation HTTP/1.1" 200 ]8;id=338854;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=344243;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=131043;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=82209;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=216082;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=639525;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:19:25 INFO  send() - 124.70.231.34:48760 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=843951;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=297132;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48762 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=754760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=311487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=763251;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=212524;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48763 - "GET /api/mcp/xDhQ7o?edit=true HTTP/1.1" 200 ]8;id=811302;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=929895;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48761 - "GET /api/conversation HTTP/1.1" 200 ]8;id=638733;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=297289;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:27 INFO  send() - 124.70.231.34:48764 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=978225;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=311743;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=446471;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=432180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=811188;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=629974;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=173916;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=757063;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=996464;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48765 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=481605;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=412322;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=764753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=213903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=547729;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=793742;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=40734;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=732342;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=638103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=480264;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48766 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=22810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=862332;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=876283;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=323303;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=297539;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=918533;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=272936;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=90070;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=998942;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=778562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48767 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=670739;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=33647;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=499872;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=665223;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=780131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=853897;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=550511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=773762;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=668220;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=230019;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48768 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=94636;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=101941;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=29103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=844257;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=269061;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=427839;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=401450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=189288;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=297141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=373949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48769 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=886006;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=477087;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=695702;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=744042;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=222342;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=641700;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=861875;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=827083;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=373716;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=454124;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48770 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=913316;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=579487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=769230;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=874880;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=825235;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=772504;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=204182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=886612;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=516218;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=309879;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48771 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=640491;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=449629;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=30987;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=605901;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=738617;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=137829;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=236927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=739725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=18435;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=113474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48772 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=45356;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=176336;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:19:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=353952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=10943;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=336553;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=703512;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=761555;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=495383;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=472580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=238433;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48773 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=718038;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=766153;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=417332;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=694933;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=907004;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=258580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=265065;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=748525;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=339562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=719870;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48774 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=580793;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=545936;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=608868;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=964779;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=717963;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=964476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=81551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=154051;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=749445;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=90147;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:48775 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=951426;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=861779;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:10 INFO  send() - 124.70.231.34:48776 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=780447;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=259264;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48777 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=588180;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=45740;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:44 INFO  send() - 124.70.231.34:48778 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=299923;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=428323;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48779 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=946106;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=849193;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:50 INFO  send() - 124.70.231.34:48781 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=714847;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=169464;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48780 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=488238;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=580400;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48782 - "POST /api/stop HTTP/1.1" 200 ]8;id=706435;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=161070;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:51 INFO  send() - 124.70.231.34:48785 - "GET /api/llm HTTP/1.1" 200 ]8;id=364073;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=743285;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48784 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=652689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=853910;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=41787;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=252610;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:48786 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=64189;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=11210;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48788 - "POST /api/stop HTTP/1.1" 200 ]8;id=526980;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=368355;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48787 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=259737;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=875239;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=768102;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=948592;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:48789 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=996723;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=707159;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48790 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=314101;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=46320;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48791 - "GET /api/llm HTTP/1.1" 200 ]8;id=221398;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=73991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48793 - "POST /api/stop HTTP/1.1" 200 ]8;id=159226;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=773939;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:48792 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=622080;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=970817;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:52 INFO  send() - 124.70.231.34:48783 - "GET /api/conversation HTTP/1.1" 200 ]8;id=585006;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=867379;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:53 INFO  send() - 124.70.231.34:48795 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=634567;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=36150;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:54 INFO  send() - 124.70.231.34:48794 - "GET /api/conversation HTTP/1.1" 200 ]8;id=760745;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=216352;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:55 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=797077;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=153628;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:49295 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=698379;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=606732;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  INFO  send() - 124.70.231.34:49294 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=652444;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=186518;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=543308;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=184789;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:20:57 INFO  send() - 124.70.231.34:49293 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=281408;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=470566;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:58 INFO  send() - 124.70.231.34:49292 - "GET /api/conversation HTTP/1.1" 200 ]8;id=438891;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=286837;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:20:59 INFO  send() - 124.70.231.34:49297 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=932234;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=562962;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:00 INFO  send() - 124.70.231.34:49296 - "GET /api/conversation HTTP/1.1" 200 ]8;id=621482;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=12454;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:01 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=381136;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=918606;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:49301 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=933937;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=484333;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  INFO  send() - 124.70.231.34:49300 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=690814;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=643886;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=713261;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=594737;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:21:04 INFO  send() - 124.70.231.34:49299 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=477092;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=989480;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:05 INFO  send() - 124.70.231.34:49298 - "GET /api/conversation HTTP/1.1" 200 ]8;id=726842;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=771456;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:06 INFO  send() - 124.70.231.34:49303 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=859495;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=12864;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:08 INFO  send() - 124.70.231.34:49302 - "GET /api/conversation HTTP/1.1" 200 ]8;id=228843;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=56992;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49305 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=726502;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=40071;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:10 INFO  send() - 124.70.231.34:49304 - "GET /api/conversation HTTP/1.1" 200 ]8;id=368745;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=819107;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49307 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=374290;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=505213;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49306 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=10403;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=184682;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49308 - "POST /api/stop HTTP/1.1" 200 ]8;id=266235;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=587071;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=117000;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=446945;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:49311 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=621976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=978080;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49310 - "GET /api/llm HTTP/1.1" 200 ]8;id=651076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=933151;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49312 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=175656;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=149159;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:11 INFO  send() - 124.70.231.34:49313 - "POST /api/stop HTTP/1.1" 200 ]8;id=335083;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=695096;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49314 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=874624;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=564764;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:12 INFO  send() - 124.70.231.34:49315 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=349727;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=465395;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=814376;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=636982;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ +  INFO  send() - 124.70.231.34:49316 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=525430;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851628;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49317 - "GET /api/llm HTTP/1.1" 200 ]8;id=430838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=829634;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=798476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=349045;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49320 - "POST /api/stop HTTP/1.1" 200 ]8;id=253773;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=149060;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49319 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=213964;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=940494;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=608462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=204744;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=343046;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602446;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=175017;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=403323;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49318 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=119802;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=249593;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:13 INFO  send() - 124.70.231.34:49309 - "GET /api/conversation HTTP/1.1" 200 ]8;id=911552;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=97453;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49322 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=762930;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=767513;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:14 INFO  send() - 124.70.231.34:49321 - "GET /api/conversation HTTP/1.1" 200 ]8;id=972959;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=296053;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:15 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=405416;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=701978;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:49324 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=878300;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=819907;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  INFO  send() - 124.70.231.34:49325 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=606111;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=257782;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=166016;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=123468;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:21:17 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=124240;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=556135;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49326 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=182426;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=987519;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=295778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=464640;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=42941;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=408926;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=407483;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=648098;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49327 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=474645;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=785529;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:18 INFO  send() - 124.70.231.34:49323 - "GET /api/conversation HTTP/1.1" 200 ]8;id=965194;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=712338;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:19 INFO  send() - 124.70.231.34:49329 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=497644;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851104;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:21 INFO  send() - 124.70.231.34:49328 - "GET /api/conversation HTTP/1.1" 200 ]8;id=879529;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=737580;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=113744;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=841295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=63766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=404592;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=131526;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=232511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=824927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=743748;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49330 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=323047;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=245103;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=229006;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=666828;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ +  INFO  send() - 124.70.231.34:49334 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=443727;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=694192;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 200   +  INFO  send() - 124.70.231.34:49333 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=432971;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=391979;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  HTTP/1.1" 500   +  ERROR  run_asgi() - Exception in ASGI application ]8;id=60569;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=110663;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   +  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   +  │ 100 │ try: │   +  │ ❱ 101 │ │ yield │   +  │ 102 │ except Exception as exc: │   +  │ 103 │ │ mapped_exc = None │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   +  │ handle_async_request │   +  │ │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ 393 │ │ with map_httpcore_exceptions(): │   +  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ 397  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   +  │ handle_async_request │   +  │ │   +  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   +  │ 254 │ │ │  │   +  │ 255 │ │ │ await self._close_connections(closing) │   +  │ ❱ 256 │ │ │ raise exc from None │   +  │ 257 │ │  │   +  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   +  │ 259 │ │ # the point at which the response is closed. │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   +  │ handle_async_request │   +  │ │   +  │ 233 │ │ │ │  │   +  │ 234 │ │ │ │ try: │   +  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   +  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   +  │ 237 │ │ │ │ │ │ pool_request.request │   +  │ 238 │ │ │ │ │ ) │   +  │ 239 │ │ │ │ except ConnectionNotAvailable: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   +  │ handle_async_request │   +  │ │   +  │  98 │ │ │ │ │ │ ) │   +  │  99 │ │ except BaseException as exc: │   +  │ 100 │ │ │ self._connect_failed = True │   +  │ ❱ 101 │ │ │ raise exc │   +  │ 102 │ │  │   +  │ 103 │ │ return await self._connection.handle_async_request(request) │   +  │ 104  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   +  │ handle_async_request │   +  │ │   +  │  75 │ │ try: │   +  │  76 │ │ │ async with self._request_lock: │   +  │  77 │ │ │ │ if self._connection is None: │   +  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   +  │  79 │ │ │ │ │  │   +  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   +  │  81 │ │ │ │ │ http2_negotiated = ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   +  │ _connect │   +  │ │   +  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   +  │ 122 │ │ │ │ │ } │   +  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   +  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   +  │ 125 │ │ │ │ │ │ trace.return_value = stream │   +  │ 126 │ │ │ │ else: │   +  │ 127 │ │ │ │ │ kwargs = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   +  │ connect_tcp │   +  │ │   +  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   +  │ 29 │ ) -> AsyncNetworkStream: │   +  │ 30 │ │ await self._init_backend() │   +  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   +  │ 32 │ │ │ host, │   +  │ 33 │ │ │ port, │   +  │ 34 │ │ │ timeout=timeout, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   +  │ connect_tcp │   +  │ │   +  │ 110 │ │ │ OSError: ConnectError, │   +  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   +  │ 112 │ │ } │   +  │ ❱ 113 │ │ with map_exceptions(exc_map): │   +  │ 114 │ │ │ with anyio.fail_after(timeout): │   +  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   +  │ 116 │ │ │ │ │ remote_host=host, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   +  │ map_exceptions │   +  │ │   +  │ 11 │ except Exception as exc: # noqa: PIE786 │   +  │ 12 │ │ for from_exc, to_exc in map.items(): │   +  │ 13 │ │ │ if isinstance(exc, from_exc): │   +  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   +  │ 15 │ │ raise # pragma: nocover │   +  │ 16  │   +  │ 17  │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +    +  The above exception was the direct cause of the following exception:   +    +  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   +  │ run_asgi │   +  │ │   +  │ 400 │ # ASGI exception wrapper │   +  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   +  │ 402 │ │ try: │   +  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   +  │ 404 │ │ │ │ self.scope, self.receive, self.send │   +  │ 405 │ │ │ ) │   +  │ 406 │ │ except BaseException as exc: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   +  │ __call__ │   +  │ │   +  │  57 │ │ │ │ │ port = 0 │   +  │  58 │ │ │ │ │ scope["client"] = (host, port) │   +  │  59 │ │  │   +  │ ❱  60 │ │ return await self.app(scope, receive, send) │   +  │  61  │   +  │  62  │   +  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   +  │ │   +  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 1052 │ │ if self.root_path: │   +  │ 1053 │ │ │ scope["root_path"] = self.root_path │   +  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   +  │ 1055 │  │   +  │ 1056 │ def add_api_route( │   +  │ 1057 │ │ self, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   +  │ │   +  │ 109 │ │ scope["app"] = self │   +  │ 110 │ │ if self.middleware_stack is None: │   +  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   +  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 113 │  │   +  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   +  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   +  │ __call__ │   +  │ │   +  │ 184 │ │ │ # We always continue to raise the exception. │   +  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   +  │ 186 │ │ │ # to optionally raise the error within the test case. │   +  │ ❱ 187 │ │ │ raise exc │   +  │ 188 │  │   +  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   +  │ str: │   +  │ 190 │ │ values = { │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   +  │ __call__ │   +  │ │   +  │ 162 │ │ │ await send(message) │   +  │ 163 │ │  │   +  │ 164 │ │ try: │   +  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   +  │ 166 │ │ except Exception as exc: │   +  │ 167 │ │ │ request = Request(scope) │   +  │ 168 │ │ │ if self.debug: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   +  │ __call__ │   +  │ │   +  │  82 │ │ origin = headers.get("origin") │   +  │  83 │ │  │   +  │  84 │ │ if origin is None: │   +  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   +  │  86 │ │ │ return │   +  │  87 │ │  │   +  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   +  │ __call__ │   +  │ │   +  │ 59 │ │ else: │   +  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   +  │ 61 │ │  │   +  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   +  │ 63 │  │   +  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   +  │ 65 │ │ assert isinstance(exc, HTTPException) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   +  │ │   +  │ 711 │ │ """ │   +  │ 712 │ │ The main entry point to the Router class. │   +  │ 713 │ │ """ │   +  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   +  │ 715 │  │   +  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   +  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   +  │ │   +  │ 731 │ │ │ match, child_scope = route.matches(scope) │   +  │ 732 │ │ │ if match == Match.FULL: │   +  │ 733 │ │ │ │ scope.update(child_scope) │   +  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   +  │ 735 │ │ │ │ return │   +  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   +  │ 737 │ │ │ │ partial = route │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   +  │ │   +  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   +  │ headers=headers) │   +  │ 286 │ │ │ await response(scope, receive, send) │   +  │ 287 │ │ else: │   +  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   +  │ 289 │  │   +  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   +  │ 291 │ │ return ( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   +  │ │   +  │  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │  77 │  │   +  │  78 │ return app │   +  │  79  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   +  │ wrapped_app │   +  │ │   +  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   +  │ 51 │ │ │  │   +  │ 52 │ │ │ if handler is None: │   +  │ ❱ 53 │ │ │ │ raise exc │   +  │ 54 │ │ │  │   +  │ 55 │ │ │ if response_started: │   +  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   +  │ started.") from exc │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   +  │ wrapped_app │   +  │ │   +  │ 39 │ │ │ await send(message) │   +  │ 40 │ │  │   +  │ 41 │ │ try: │   +  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   +  │ 43 │ │ except Exception as exc: │   +  │ 44 │ │ │ handler = None │   +  │ 45  │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   +  │ │   +  │  70 │ │ request = Request(scope, receive, send) │   +  │  71 │ │  │   +  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   +  │ ❱  73 │ │ │ response = await f(request) │   +  │  74 │ │ │ await response(scope, receive, send) │   +  │  75 │ │  │   +  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   +  │ │   +  │  298 │ │ │ │ ) │   +  │  299 │ │ │ │ errors = solved_result.errors │   +  │  300 │ │ │ │ if not errors: │   +  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   +  │  302 │ │ │ │ │ │ dependant=dependant, │   +  │  303 │ │ │ │ │ │ values=solved_result.values, │   +  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   +  │ run_endpoint_function │   +  │ │   +  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   +  │  210 │  │   +  │  211 │ if is_coroutine: │   +  │ ❱  212 │ │ return await dependant.call(**values) │   +  │  213 │ else: │   +  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   +  │  215  │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   +  │ │   +  │  93 │ if unused: │   +  │  94 │ │ # 拿到所有未使用的文档 │   +  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   +  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   +  │ [item.id for item in unused_docs]) │   +  │  97 │ │ for current_doc in unused_docs: │   +  │  98 │ │ │ for status_item in doc_status: │   +  │  99 │ │ │ │ if current_doc.id != status_item.id: │   +  │ │   +  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   +  │ │   +  │ 73 │ │ } │   +  │ 74 │ │ post_data = {"ids": doc_ids} │   +  │ 75 │ │ async with httpx.AsyncClient() as client: │   +  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   +  │ json=post_data, timeout=30.0) │   +  │ 77 │ │ │ resp_data = resp.json() │   +  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   +  │ 79 │ │ │ │ return [] │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   +  │ │   +  │ 1856 │ │  │   +  │ 1857 │ │ **Parameters**: See `httpx.request`. │   +  │ 1858 │ │ """ │   +  │ ❱ 1859 │ │ return await self.request( │   +  │ 1860 │ │ │ "POST", │   +  │ 1861 │ │ │ url, │   +  │ 1862 │ │ │ content=content, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   +  │ │   +  │ 1537 │ │ │ timeout=timeout, │   +  │ 1538 │ │ │ extensions=extensions, │   +  │ 1539 │ │ ) │   +  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   +  │ 1541 │  │   +  │ 1542 │ @asynccontextmanager │   +  │ 1543 │ async def stream( │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   +  │ │   +  │ 1626 │ │  │   +  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   +  │ 1628 │ │  │   +  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   +  │ 1630 │ │ │ request, │   +  │ 1631 │ │ │ auth=auth, │   +  │ 1632 │ │ │ follow_redirects=follow_redirects, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   +  │ _send_handling_auth │   +  │ │   +  │ 1654 │ │ │ request = await auth_flow.__anext__() │   +  │ 1655 │ │ │  │   +  │ 1656 │ │ │ while True: │   +  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   +  │ 1658 │ │ │ │ │ request, │   +  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   +  │ 1660 │ │ │ │ │ history=history, │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   +  │ _send_handling_redirects │   +  │ │   +  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   +  │ 1692 │ │ │ │ await hook(request) │   +  │ 1693 │ │ │  │   +  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   +  │ 1695 │ │ │ try: │   +  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   +  │ 1697 │ │ │ │ │ await hook(response) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   +  │ _send_single_request │   +  │ │   +  │ 1727 │ │ │ ) │   +  │ 1728 │ │  │   +  │ 1729 │ │ with request_context(request=request): │   +  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   +  │ 1731 │ │  │   +  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   +  │ 1733 │ │ response.request = request │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   +  │ handle_async_request │   +  │ │   +  │ 390 │ │ │ content=request.stream, │   +  │ 391 │ │ │ extensions=request.extensions, │   +  │ 392 │ │ ) │   +  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   +  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   +  │ 395 │ │  │   +  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   +  │ │   +  │ 155 │ │ │ │ # tell if we get the same exception back │   +  │ 156 │ │ │ │ value = typ() │   +  │ 157 │ │ │ try: │   +  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   +  │ 159 │ │ │ except StopIteration as exc: │   +  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   +  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   +  │ │   +  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   +  │ map_httpcore_exceptions │   +  │ │   +  │ 115 │ │ │ raise │   +  │ 116 │ │  │   +  │ 117 │ │ message = str(exc) │   +  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   +  │ 119  │   +  │ 120  │   +  │ 121 class ResponseStream(SyncByteStream): │   +  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   +  ConnectError: All connection attempts failed   +25-Aug-12 20:21:23 INFO  send() - 124.70.231.34:49332 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=965528;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=728341;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=862805;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=920109;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=956002;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=223299;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=402572;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=558679;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=215339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=120022;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49335 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=197827;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=334689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:25 INFO  send() - 124.70.231.34:49331 - "GET /api/conversation HTTP/1.1" 200 ]8;id=668330;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=101957;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49337 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=387684;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=663568;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:26 INFO  send() - 124.70.231.34:49336 - "GET /api/conversation HTTP/1.1" 200 ]8;id=321373;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=135896;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:27 INFO  send() - 124.70.231.34:49339 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=62709;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=139932;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=64678;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=769884;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=120465;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=366336;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=52914;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=500386;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=743476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=810424;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49340 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=213221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=559760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +  INFO  send() - 124.70.231.34:49338 - "GET /api/conversation HTTP/1.1" 200 ]8;id=308878;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=104305;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:29 INFO  send() - 124.70.231.34:49341 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=476360;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=499021;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=998929;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=399486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10214;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=272279;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=308654;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=697314;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=335121;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=193852;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49342 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=123709;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=515022;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:35 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=660969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=769415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=536505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=353060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=977970;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=495195;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=549799;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=836861;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49343 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=213023;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=512435;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=551836;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=869305;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=624478;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=577130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +25-Aug-12 20:21:39 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=466195;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=895732;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=987595;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=242923;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49344 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=408991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=103151;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=733562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=169691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=400302;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=854310;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=76653;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=976850;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=815076;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=856404;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49345 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=114580;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=982410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:45 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=922040;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=548675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=287291;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=997707;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=593810;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=181919;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=472132;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=436316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49346 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=822625;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=992628;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:49 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=848528;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=788025;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=9526;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=24552;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=81785;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=722376;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=139079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=576866;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49347 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=296964;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=165145;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ +25-Aug-12 20:21:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=269564;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=666040;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=998984;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=762824;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=497623;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=888593;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=195181;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ +  INFO  send() - 124.70.231.34:49348 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=251138;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=677327;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -- Gitee From 521b4f28ec1162a3439648afe0601038d94f0886 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 20:55:45 +0800 Subject: [PATCH 75/78] test --- apps/scheduler/mcp_agent/prompt.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index b4022c01..45ddc021 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -327,17 +327,17 @@ CREATE_PLAN = dedent(r""" "instruction": "需要一个支持Docker容器运行的MCP Server" }, { - "content": "使用Result[0]中选择的MCP Server,生成Docker命令", + "content": "使用第一步选择的MCP Server,生成Docker命令", "tool": "command_generator", "instruction": "生成Docker命令:在后台运行alpine:latest容器,挂载/root到/data,执行top命令" }, { - "content": "在Result[0]的MCP Server上执行Result[1]生成的命令", + "content": "执行第二步生成的Docker命令", "tool": "command_executor", "instruction": "执行Docker命令" }, { - "content": "任务执行完成,容器已在后台运行,结果为Result[2]", + "content": "任务执行完成,容器已在后台运行", "tool": "Final", "instruction": "" } @@ -413,12 +413,12 @@ RECREATE_PLAN = dedent(r""" "instruction": "生成端口扫描命令:扫描192.168.1.1的开放端口" }, { - "content": "在执行Result[0]生成的命令", + "content": "在执行第一步生成的命令", "tool": "command_executor", "instruction": "执行端口扫描命令" }, { - "content": "任务执行完成,端口扫描结果为Result[2]", + "content": "任务执行完成", "tool": "Final", "instruction": "" } @@ -450,27 +450,27 @@ RECREATE_PLAN = dedent(r""" "instruction": "选择一个前机器支持哪些网络扫描工具" }, { - "content": "执行Result[0]中生成的命令,查看当前机器支持哪些网络扫描工具", + "content": "执行第一步中生成的命令,查看当前机器支持哪些网络扫描工具", "tool": "command_executor", - "instruction": "执行Result[0]中生成的命令" + "instruction": "执行第一步中生成的命令" }, { - "content": "从Result[1]中选择一个网络扫描工具,生成端口扫描命令", + "content": "从第二步执行结果中选择一个网络扫描工具,生成端口扫描命令", "tool": "tool_selector", "instruction": "选择一个网络扫描工具,生成端口扫描命令" }, { - "content": "基于result[2]中选择的网络扫描工具,生成端口扫描命令", + "content": "基于第三步中选择的网络扫描工具,生成端口扫描命令", "tool": "command_generator", "instruction": "生成端口扫描命令:扫描192.168.1.1的开放端口" }, { - "content": "在Result[0]的MCP Server上执行Result[3]生成的命令", + "content": "执行第四步中生成的端口扫描命令", "tool": "command_executor", "instruction": "执行端口扫描命令" }, { - "content": "任务执行完成,端口扫描结果为Result[4]", + "content": "任务执行完成", "tool": "Final", "instruction": "" } -- Gitee From 8c45e928c55d360821559155efaf7a3a30c909d5 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 22:34:39 +0800 Subject: [PATCH 76/78] =?UTF-8?q?=E5=AE=9E=E6=97=B6=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 219 +- apps/scheduler/mcp_agent/plan.py | 44 + apps/scheduler/mcp_agent/prompt.py | 109 + apps/schemas/mcp.py | 12 + apps/schemas/task.py | 4 +- nohup.out | 5936 ---------------------------- 6 files changed, 249 insertions(+), 6075 deletions(-) delete mode 100644 nohup.out diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 2c8574b0..3c6ef8e5 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -23,7 +23,8 @@ from apps.schemas.mcp import ( ToolExcutionErrorType, MCPPlan, MCPCollection, - MCPTool + MCPTool, + Step ) from apps.scheduler.pool.mcp.pool import MCPPool from apps.schemas.task import ExecutorState, FlowStepHistory, StepQueueItem @@ -47,6 +48,9 @@ class MCPAgentExecutor(BaseExecutor): tools: dict[str, MCPTool] = Field( description="MCP工具列表,key为tool_id", default={} ) + tool_list: list[MCPTool] = Field( + description="MCP工具列表,包含所有MCP工具", default=[] + ) params: param | bool | None = Field( default=None, description="流执行过程中的参数补充", alias="params" ) @@ -88,58 +92,13 @@ class MCPAgentExecutor(BaseExecutor): await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) for tool in mcp_service.tools: self.tools[tool.id] = tool - - async def plan(self, is_replan: bool = False, start_index: int | None = None) -> None: - if is_replan: - error_message = "之前的计划遇到以下报错\n\n"+self.task.state.error_message - else: - error_message = "初始化计划" - tools = await MCPSelector.select_top_tool( - self.task.runtime.question, list(self.tools.values()), - additional_info=error_message, top_n=40, reasoning_llm=self.resoning_llm) - if is_replan: - logger.info("[MCPAgentExecutor] 重新规划流程") - if not start_index: - start_index = await MCPPlanner.get_replan_start_step_index(self.task.runtime.question, - self.task.state.error_message, - self.task.runtime.temporary_plans, - self.resoning_llm) - start_index = start_index.start_index - current_plan = MCPPlan(plans=self.task.runtime.temporary_plans.plans[start_index:]) - error_message = self.task.state.error_message - temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, - is_replan=is_replan, - error_message=error_message, - current_plan=current_plan, - tool_list=tools, - max_steps=self.max_steps-start_index-1, - reasoning_llm=self.resoning_llm - ) - await self.update_tokens() - await self.push_message( - EventType.STEP_CANCEL, - data={} - ) - if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: - self.task.context[-1].step_status = StepStatus.CANCELLED - self.task.runtime.temporary_plans.plans = self.task.runtime.temporary_plans.plans[ - : start_index] + temporary_plans.plans - self.task.state.step_index = start_index - else: - start_index = 0 - logger.error( - f"各个字段的类型: {type(self.task.runtime.question)}, {type(tools)}, {type(self.max_steps)}, {type(self.resoning_llm)}") - self.task.runtime.temporary_plans = await MCPPlanner.create_plan(self.task.runtime.question, tool_list=tools, max_steps=self.max_steps, reasoning_llm=self.resoning_llm) - for i in range(start_index, len(self.task.runtime.temporary_plans.plans)): - self.task.runtime.temporary_plans.plans[i].step_id = str(uuid.uuid4()) + self.tool_list.extend(mcp_service.tools) async def get_tool_input_param(self, is_first: bool) -> None: if is_first: # 获取第一个输入参数 - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] - mcp_tool = self.tools[tool_id] - self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, self.task.runtime.question, step.instruction, self.task) + mcp_tool = self.tools[self.task.state.tool_id] + self.task.state.current_input = await MCPHost._get_first_input_params(mcp_tool, self.task.runtime.question, self.task.state.step_description, self.task) else: # 获取后续输入参数 if isinstance(self.params, param): @@ -148,31 +107,12 @@ class MCPAgentExecutor(BaseExecutor): else: params = {} params_description = "" - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - mcp_tool = self.tools[tool_id] - step = self.task.runtime.temporary_plans.plans[self.task.state.step_index] - self.task.state.current_input = await MCPHost._fill_params(mcp_tool, self.task.runtime.question, step.instruction, self.task.state.current_input, self.task.state.error_message, params, params_description) - - async def reset_step_to_index(self, start_index: int) -> None: - """重置步骤到开始""" - logger.info("[MCPAgentExecutor] 重置步骤到索引 %d", start_index) - - if start_index < len(self.task.runtime.temporary_plans.plans): - self.task.state.flow_status = FlowStatus.RUNNING - self.task.state.step_id = self.task.runtime.temporary_plans.plans[start_index].step_id - self.task.state.step_index = 0 - self.task.state.step_name = self.tools[self.task.runtime.temporary_plans.plans[start_index].tool].name - self.task.state.step_description = self.task.runtime.temporary_plans.plans[start_index].content - self.task.state.step_status = StepStatus.INIT - self.task.state.retry_times = 0 - else: - self.task.state.step_id = FINAL_TOOL_ID + mcp_tool = self.tools[self.task.state.tool_id] + self.task.state.current_input = await MCPHost._fill_params(mcp_tool, self.task.runtime.question, self.task.state.step_description, self.task.state.current_input, self.task.state.error_message, params, params_description) async def confirm_before_step(self) -> None: - logger.info("[MCPAgentExecutor] 等待用户确认步骤 %d", self.task.state.step_index) # 发送确认消息 - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - mcp_tool = self.tools[tool_id] + mcp_tool = self.tools[self.task.state.tool_id] confirm_message = await MCPPlanner.get_tool_risk(mcp_tool, self.task.state.current_input, "", self.resoning_llm) await self.update_tokens() await self.push_message(EventType.STEP_WAITING_FOR_START, confirm_message.model_dump( @@ -200,10 +140,7 @@ class MCPAgentExecutor(BaseExecutor): """执行步骤""" self.task.state.flow_status = FlowStatus.RUNNING self.task.state.step_status = StepStatus.RUNNING - logger.info("[MCPAgentExecutor] 执行步骤 %d", self.task.state.step_index) - # 获取MCP客户端 - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - mcp_tool = self.tools[tool_id] + mcp_tool = self.tools[self.task.state.tool_id] mcp_client = (await self.mcp_pool.get(mcp_tool.mcp_id, self.task.ids.user_sub)) try: output_params = await mcp_client.call_tool(mcp_tool.name, self.task.state.current_input) @@ -264,8 +201,7 @@ class MCPAgentExecutor(BaseExecutor): async def generate_params_with_null(self) -> None: """生成参数补充""" - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - mcp_tool = self.tools[tool_id] + mcp_tool = self.tools[self.task.state.tool_id] params_with_null = await MCPPlanner.get_missing_param( mcp_tool, self.task.state.current_input, @@ -312,21 +248,36 @@ class MCPAgentExecutor(BaseExecutor): ) async def get_next_step(self) -> None: - self.task.state.step_index += 1 - if self.task.state.step_index < len(self.task.runtime.temporary_plans.plans): - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + if self.task.state.step_cnt < self.max_steps: + self.task.state.step_cnt += 1 + history = await MCPHost.assemble_memory(self.task) + max_retry = 3 + step = None + for i in range(max_retry): + step = await MCPPlanner.create_next_step(self.task.runtime.question, history, self.tool_list) + if step.tool_id in self.tools.keys(): + break + if step is None or step.tool_id not in self.tools.keys(): + step = Step( + tool_id=FINAL_TOOL_ID, + step_description=FINAL_TOOL_ID + ) + tool_id = step.tool_id if tool_id == FINAL_TOOL_ID: - return - self.task.state.step_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id - self.task.state.step_name = self.tools[self.task.runtime.temporary_plans.plans - [self.task.state.step_index].tool].name - self.task.state.step_description = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content + step_name = FINAL_TOOL_ID + else: + step_name = self.tools[tool_id].name + step_description = step.description + self.task.state.step_id = str(uuid.uuid4()) + self.task.state.tool_id = tool_id + self.task.state.step_name = step_name + self.task.state.step_description = step_description self.task.state.step_status = StepStatus.INIT self.task.state.current_input = {} else: # 没有下一步了,结束流程 - self.task.state.step_id = FINAL_TOOL_ID - return + self.task.state.tool_id = FINAL_TOOL_ID + return async def error_handle_after_step(self) -> None: """步骤执行失败后的错误处理""" @@ -356,17 +307,6 @@ class MCPAgentExecutor(BaseExecutor): async def work(self) -> None: """执行当前步骤""" if self.task.state.step_status == StepStatus.INIT: - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - # if tool_id != FINAL_TOOL_ID: - # step_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].step_id - # tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - # step_name = self.tools[tool_id].name - # step_instruction = self.task.runtime.temporary_plans.plans[self.task.state.step_index].instruction - # step_content = self.task.runtime.temporary_plans.plans[self.task.state.step_index].content - # tool_skip = await MCPPlanner.tool_skip(self.task, step_id, step_name, step_instruction, step_content, self.resoning_llm) - # if tool_skip.skip: - # await self.get_next_step() - # return await self.push_message( EventType.STEP_INIT, data={} @@ -414,21 +354,45 @@ class MCPAgentExecutor(BaseExecutor): await self.error_handle_after_step() else: user_info = await UserManager.get_userinfo_by_user_sub(self.task.ids.user_sub) - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - mcp_tool = self.tools[tool_id] - error_type = await MCPPlanner.get_tool_execute_error_type( - self.task.runtime.question, - self.task.runtime.temporary_plans, - mcp_tool, - self.task.state.current_input, - self.task.state.error_message, - self.resoning_llm - ) - if error_type.type == ErrorType.DECORRECT_PLAN or user_info.auto_execute: - await self.plan(is_replan=True) - await self.reset_step_to_index(self.task.state.step_index) - elif error_type.type == ErrorType.MISSING_PARAM: - await self.generate_params_with_null() + if user_info.auto_execute: + self.push_message( + EventType.STEP_ERROR, + data={ + "message": self.task.state.error_message, + } + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + self.task.context[-1].step_status = StepStatus.ERROR + self.task.context[-1].output_data = { + "message": self.task.state.error_message, + } + await self.get_next_step() + else: + mcp_tool = self.tools[self.task.state.tool_id] + is_param_error = await MCPPlanner.is_param_error( + self.task.runtime.question, + await MCPHost.assemble_memory(self.task), + self.task.state.error_message, + mcp_tool, + self.task.state.step_description, + self.task.state.current_input, + ) + if is_param_error.is_param_error: + # 如果是参数错误,生成参数补充 + await self.generate_params_with_null() + else: + self.push_message( + EventType.STEP_ERROR, + data={ + "message": self.task.state.error_message, + } + ) + if len(self.task.context) and self.task.context[-1].step_id == self.task.state.step_id: + self.task.context[-1].step_status = StepStatus.ERROR + self.task.context[-1].output_data = { + "message": self.task.state.error_message, + } + await self.get_next_step() elif self.task.state.step_status == StepStatus.SUCCESS: await self.get_next_step() @@ -455,8 +419,6 @@ class MCPAgentExecutor(BaseExecutor): try: self.task.state.flow_id = str(uuid.uuid4()) self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) - await self.plan(is_replan=False) - await self.reset_step_to_index(0) await TaskManager.save_task(self.task.id, self.task) except Exception as e: import traceback @@ -470,25 +432,11 @@ class MCPAgentExecutor(BaseExecutor): ) return self.task.state.flow_status = FlowStatus.RUNNING - plan = { - "plans": [] - } - for p in self.task.runtime.temporary_plans.plans: - if p.tool == FINAL_TOOL_ID: - continue - mcp_tool = self.tools.get(p.tool, None) - plan["plans"].append( - { - "stepId": p.step_id, - "stepName": mcp_tool.name, - "stepDescription": p.content - } - ) await self.push_message( EventType.FLOW_START, - data=plan + data={} ) - if self.task.state.step_id == FINAL_TOOL_ID: + if self.task.state.tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 self.task.state.flow_status = FlowStatus.SUCCESS await self.push_message( @@ -498,15 +446,12 @@ class MCPAgentExecutor(BaseExecutor): await self.summarize() return try: - while len(self.task.runtime.temporary_plans.plans) and \ - self.task.state.step_index < len(self.task.runtime.temporary_plans.plans) and \ - self.task.state.flow_status == FlowStatus.RUNNING: - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool - if tool_id == FINAL_TOOL_ID: + while 1: + if self.task.state.tool_id == FINAL_TOOL_ID: break await self.work() await TaskManager.save_task(self.task.id, self.task) - tool_id = self.task.runtime.temporary_plans.plans[self.task.state.step_index].tool + tool_id = self.task.state.tool_id if tool_id == FINAL_TOOL_ID: # 如果已经是最后一步,直接结束 self.task.state.flow_status = FlowStatus.SUCCESS diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index fbdebff5..9fee0b78 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -13,9 +13,11 @@ from apps.scheduler.mcp_agent.prompt import ( GET_REPLAN_START_STEP_INDEX, CREATE_PLAN, RECREATE_PLAN, + GEN_STEP, TOOL_SKIP, RISK_EVALUATE, TOOL_EXECUTE_ERROR_TYPE_ANALYSIS, + IS_PARAM_ERROR, CHANGE_ERROR_MESSAGE_TO_DESCRIPTION, GET_MISSING_PARAMS, FINAL_ANSWER @@ -26,8 +28,10 @@ from apps.schemas.mcp import ( RestartStepIndex, ToolSkip, ToolRisk, + IsParamError, ToolExcutionErrorType, MCPPlan, + Step, MCPPlanItem, MCPTool ) @@ -165,6 +169,22 @@ class MCPPlanner(McpBase): # 使用Function模型解析结果 return MCPPlan.model_validate(plan) + @staticmethod + async def create_next_step( + goal: str, history: str, tools: list[MCPTool], + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> Step: + """创建下一步的执行步骤""" + # 获取推理结果 + template = _env.from_string(GEN_STEP) + prompt = template.render(goal=goal, history=history, tools=tools) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + + # 解析为结构化数据 + schema = Step.model_json_schema() + step = await MCPPlanner._parse_result(result, schema) + # 使用Step模型解析结果 + return Step.model_validate(step) + @staticmethod async def tool_skip( task: Task, step_id: str, step_name: str, step_instruction: str, step_content: str, @@ -266,6 +286,30 @@ class MCPPlanner(McpBase): # 返回工具执行错误类型 return error_type + @staticmethod + async def is_param_error( + goal: str, history: str, error_message: str, tool: MCPTool, step_description: str, input_params: dict + [str, Any], + reasoning_llm: ReasoningLLM = ReasoningLLM()) -> IsParamError: + """判断错误信息是否是参数错误""" + tmplate = _env.from_string(IS_PARAM_ERROR) + prompt = tmplate.render( + goal=goal, + history=history, + error_message=error_message, + step_id=tool.id, + step_name=tool.name, + step_description=step_description, + input_params=input_params, + error_message=error_message, + ) + result = await MCPPlanner.get_resoning_result(prompt, reasoning_llm) + # 解析为结构化数据 + schema = IsParamError.model_json_schema() + is_param_error = await MCPPlanner._parse_result(result, schema) + # 使用IsParamError模型解析结果 + return IsParamError.model_validate(is_param_error) + @staticmethod async def change_err_message_to_description( error_message: str, tool: MCPTool, input_params: dict[str, Any], diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index 45ddc021..b7cf10e8 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -502,6 +502,55 @@ RECREATE_PLAN = dedent(r""" # 重新生成的计划 """) +GEN_STEP = dedent(r""" + 你是一个计划生成器。 + 请根据用户的目标、当前计划和历史,生成一个新的步骤。 + + # 一个好的计划步骤应该: + 1.使用最适合的工具来完成当前步骤。 + 2.能够基于当前的计划和历史,完成阶段性的任务。 + 3.不要选择不存在的工具。 + 4.如果你认为当前已经达成了用户的目标,可以直接返回Final工具,表示计划执行结束。 + + # 样例 + # 目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 历史记录 + 第1步:生成端口扫描命令 + - 调用工具 `command_generator`,并提供参数 `帮我生成一个mysql端口扫描命令` + - 执行状态:成功 + - 得到数据:`{"command": "nmap -sS -p--open 192.168.1.1"}` + 第2步:执行端口扫描命令 + - 调用工具 `command_executor`,并提供参数 `{"command": "nmap -sS -p--open 192.168.1.1"}` + - 执行状态:成功 + - 得到数据:`{"result": "success"}` + # 工具 + + - mcp_tool_1 mysql_analyzer;用于分析数据库性能/description> + - mcp_tool_2 文件存储工具;用于存储文件 + - mcp_tool_3 mongoDB工具;用于操作MongoDB数据库 + - Final 结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + + # 输出 + ```json + { + "tool_id": "mcp_tool", // 选择的工具ID + "step_description": "分析MySQL数据库性能" // 对当前步骤的描述 + } + ``` + # 现在开始生成步骤: + # 目标 + {{goal}} + # 历史记录 + {{history}} + # 工具 + + {% for tool in tools %} + - {{tool.id}} {{tool.name}};{{tool.description}} + {% endfor %} + +""") + TOOL_SKIP = dedent(r""" 你是一个计划执行器。 你的任务是根据当前的计划和用户目标,判断当前步骤是否需要跳过。 @@ -675,6 +724,66 @@ TOOL_EXECUTE_ERROR_TYPE_ANALYSIS = dedent(r""" # 输出 """ ) +IS_PARAM_ERROR = dedent(r""" + 你是一个计划执行专家,你的任务是判断当前的步骤执行失败是否是因为参数错误导致的, + 如果是,请返回`true`,否则返回`false`。 + 必须按照以下格式回答: + ```json + { + "is_param_error": true/false, + } + ``` + # 样例 + # 用户目标 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + # 历史 + 第1步:生成端口扫描命令 + - 调用工具 `command_generator`,并提供参数 `{"command": "nmap -sS -p--open 192.168.1.1"}` + - 执行状态:成功 + - 得到数据:`{"command": "nmap -sS -p--open 192.168.1.1"}` + 第2步:执行端口扫描命令 + - 调用工具 `command_executor`,并提供参数 `{"command": "nmap -sS -p--open 192.168.1.1"}` + - 执行状态:成功 + - 得到数据:`{"result": "success"}` + # 当前步骤 + + step_3 + mysql_analyzer + 分析MySQL数据库性能 + + # 工具入参 + { + "host": "192.0.0.1", + "port": 3306, + "username": "root", + "password": "password" + } + # 工具运行报错 + 执行MySQL性能分析命令时,出现了错误:`host is not correct`。 + + # 输出 + ```json + { + "is_param_error": true + } + ``` + # 用户目标 + {{goal}} + # 历史 + {{history}} + # 当前步骤 + + {{step_id}} + {{step_name}} + {{step_instruction}} + + # 工具入参 + {{input_param}} + # 工具运行报错 + {{error_message}} + # 输出 + """ + ) # 将当前程序运行的报错转换为自然语言 CHANGE_ERROR_MESSAGE_TO_DESCRIPTION = dedent(r""" 你是一个智能助手,你的任务是将当前程序运行的报错转换为自然语言描述。 diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 022eb00f..d27a5b46 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -157,6 +157,11 @@ class ToolExcutionErrorType(BaseModel): reason: str = Field(description="错误原因", default="") +class IsParamError(BaseModel): + """MCP工具参数错误""" + + is_param_error: bool = Field(description="是否是参数错误", default=False) + class MCPSelectResult(BaseModel): """MCP选择结果""" @@ -187,3 +192,10 @@ class MCPPlan(BaseModel): """MCP 计划""" plans: list[MCPPlanItem] = Field(description="计划列表", default=[]) + + +class Step(BaseModel): + """MCP步骤""" + + tool_id: str = Field(description="工具ID") + description: str = Field(description="步骤描述") diff --git a/apps/schemas/task.py b/apps/schemas/task.py index 9b9a2543..d3e7b036 100644 --- a/apps/schemas/task.py +++ b/apps/schemas/task.py @@ -43,8 +43,9 @@ class ExecutorState(BaseModel): description: str = Field(description="Flow描述", default="") flow_status: FlowStatus = Field(description="Flow状态", default=FlowStatus.INIT) # 任务级数据 + step_cnt: int = Field(description="当前步骤数量", default=0) step_id: str = Field(description="当前步骤ID", default="") - step_index: int = Field(description="当前步骤索引", default=0) + tool_id: str = Field(description="当前工具ID", default="") step_name: str = Field(description="当前步骤名称", default="") step_status: StepStatus = Field(description="当前步骤状态", default=StepStatus.UNKNOWN) step_description: str = Field(description="当前步骤描述", default="") @@ -83,7 +84,6 @@ class TaskRuntime(BaseModel): summary: str = Field(description="摘要", default="") filled: dict[str, Any] = Field(description="填充的槽位", default={}) documents: list[dict[str, Any]] = Field(description="文档列表", default=[]) - temporary_plans: MCPPlan | None = Field(description="临时计划列表", default=None) class Task(BaseModel): diff --git a/nohup.out b/nohup.out deleted file mode 100644 index a90c116a..00000000 --- a/nohup.out +++ /dev/null @@ -1,5936 +0,0 @@ -nohup: ignoring input -# jionlp - 微信公众号: JioNLP Github: `https://github.com/dongrixinyu/JioNLP`. -# jiojio - Successfully load C funcs for CWS and POS acceleration. -25-Aug-12 20:14:55 INFO  init() - [Pool] 载入Call ]8;id=961416;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=784982;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#84\84]8;;\ -25-Aug-12 20:14:56 INFO  _send_single_request() - HTTP Request: POST https://api.siliconflow.cn/v1/embeddings "HTTP/1.1 200 OK" ]8;id=703354;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=405600;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  INFO  init() - [Pool] 检查文件变动 ]8;id=424382;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=70264;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#88\88]8;;\ -  INFO  diff() - [FileChecker] 文件变动: [];文件删除: [] ]8;id=371800;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py\check.py]8;;\:]8;id=454754;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py#83\83]8;;\ -  INFO  init() - [Pool] 载入Service ]8;id=789812;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=970989;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#93\93]8;;\ -  INFO  init() - [Pool] 载入App ]8;id=525784;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=617349;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#109\109]8;;\ -  INFO  diff() - [FileChecker] 文件变动: [];文件删除: [] ]8;id=850578;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py\check.py]8;;\:]8;id=670212;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/check.py#83\83]8;;\ -  ERROR  load_one() - [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=621739;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py\metadata.py]8;;\:]8;id=469007;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py#61\61]8;;\ -  ╭──────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py:58 in load_one │   -  │ │   -  │  55 │ │ │ else: │   -  │  56 │ │ │ │ try: │   -  │  57 │ │ │ │ │ app_id = file_path.parent.name │   -  │ ❱  58 │ │ │ │ │ metadata = AgentAppMetadata(id=app_id, **metadata_dict) │   -  │  59 │ │ │ │ except Exception as e: │   -  │  60 │ │ │ │ │ err = "[MetadataLoader] Agent app metadata.yaml格式错误" │   -  │  61 │ │ │ │ │ logger.exception(err) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py:253 in __init__ │   -  │ │   -  │  250 │ │ """ │   -  │  251 │ │ # `__tracebackhide__` tells pytest and some other tools to omit this function  │   -  │ from tracebacks │   -  │  252 │ │ __tracebackhide__ = True │   -  │ ❱  253 │ │ validated_self = self.__pydantic_validator__.validate_python(data,  │   -  │ self_instance=self) │   -  │  254 │ │ if self is not validated_self: │   -  │  255 │ │ │ warnings.warn( │   -  │  256 │ │ │ │ 'A custom validator is returning a value other than `self`.\n' │   -  ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ValidationError: 1 validation error for AgentAppMetadata   -  mcp_service.0   -  Input should be a valid string [type=string_type, input_value={'id': 'W785k0', 'name': '', 'description': ''},   -  input_type=dict]   -  For further information visit https://errors.pydantic.dev/2.11/v/string_type   -  WARNING  init() - [Pool] 加载App 2793ab12-0ea2-4314-b709-938245e9154d 失败: [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=44584;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=238803;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#127\127]8;;\ -  ERROR  load_one() - [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=261651;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py\metadata.py]8;;\:]8;id=837901;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py#61\61]8;;\ -  ╭──────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/metadata.py:58 in load_one │   -  │ │   -  │  55 │ │ │ else: │   -  │  56 │ │ │ │ try: │   -  │  57 │ │ │ │ │ app_id = file_path.parent.name │   -  │ ❱  58 │ │ │ │ │ metadata = AgentAppMetadata(id=app_id, **metadata_dict) │   -  │  59 │ │ │ │ except Exception as e: │   -  │  60 │ │ │ │ │ err = "[MetadataLoader] Agent app metadata.yaml格式错误" │   -  │  61 │ │ │ │ │ logger.exception(err) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py:253 in __init__ │   -  │ │   -  │  250 │ │ """ │   -  │  251 │ │ # `__tracebackhide__` tells pytest and some other tools to omit this function  │   -  │ from tracebacks │   -  │  252 │ │ __tracebackhide__ = True │   -  │ ❱  253 │ │ validated_self = self.__pydantic_validator__.validate_python(data,  │   -  │ self_instance=self) │   -  │  254 │ │ if self is not validated_self: │   -  │  255 │ │ │ warnings.warn( │   -  │  256 │ │ │ │ 'A custom validator is returning a value other than `self`.\n' │   -  ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ValidationError: 1 validation error for AgentAppMetadata   -  mcp_service.0   -  Input should be a valid string [type=string_type, input_value={'id': 'W785k0', 'name': ...ne, 'description': None},   -  input_type=dict]   -  For further information visit https://errors.pydantic.dev/2.11/v/string_type   -  WARNING  init() - [Pool] 加载App ecd9e9fb-821f-4f91-8f29-120048515604 失败: [MetadataLoader] Agent app metadata.yaml格式错误 ]8;id=896261;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=52563;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#127\127]8;;\ -  INFO  init() - [Pool] 载入MCP ]8;id=882128;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py\pool.py]8;;\:]8;id=66910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/pool.py#129\129]8;;\ -  INFO  _find_deleted_mcp() - [MCPLoader] 这些MCP在文件系统中被删除: [] ]8;id=804315;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=339566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#497\497]8;;\ -  INFO  remove_deleted_mcp() - [MCPLoader] 清除数据库中无效的MCP ]8;id=925474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=354589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#539\539]8;;\ -  INFO  remove_deleted_mcp() - [MCPLoader] 清除LanceDB中无效的MCP ]8;id=667208;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=529433;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#554\554]8;;\ -  INFO  cancel_all_installing_task() - [MCPLoader] 初始化所有MCP模板: /opt/copilot/semantics/mcp/template ]8;id=467500;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=174523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#178\178]8;;\ -  ERROR  add_no_auth_user() - [add_no_auth_user] 默认用户 root 已存在 ]8;id=668910;file:///home/zjq/euler-copilot-framework_1/apps/main.py\main.py]8;;\:]8;id=227704;file:///home/zjq/euler-copilot-framework_1/apps/main.py#107\107]8;;\ -  INFO  clear_user_activity() - 清除所有用户活跃状态完成 ]8;id=169828;file:///home/zjq/euler-copilot-framework_1/apps/main.py\main.py]8;;\:]8;id=627525;file:///home/zjq/euler-copilot-framework_1/apps/main.py#117\117]8;;\ -  INFO  _serve() - Started server process [885153] ]8;id=609070;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py\server.py]8;;\:]8;id=581876;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py#83\83]8;;\ -  INFO  startup() - Waiting for application startup. ]8;id=184477;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py\on.py]8;;\:]8;id=47674;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py#48\48]8;;\ -  INFO  startup() - Application startup complete. ]8;id=254881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py\on.py]8;;\:]8;id=977726;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/lifespan/on.py#62\62]8;;\ -  INFO  _log_started_message() - Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit) ]8;id=775711;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py\server.py]8;;\:]8;id=221767;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/server.py#215\215]8;;\ -25-Aug-12 20:14:57 ERROR  fetch_apps() - [AppCenterManager] 搜索条件: {'$or': [{'permission.type': 'public'}, {'$and': [{'permission.type': ]8;id=24219;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=174432;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#86\86]8;;\ -  'protected'}, {'permission.users': {'$in': ['root']}}]}, {'$and': [{'permission.type': 'private'}, {'author':   -  'root'}]}], 'published': True}, 页码: 1, 每页大小: 16   -  INFO  send() - 124.70.231.10:13355 - "GET /api/app?page=1 HTTP/1.1" 200 ]8;id=756810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=595720;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:14:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=67625;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=254111;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=918049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=6244;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=76551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=493979;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=651850;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=542329;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=554165;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=718295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47665 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=817505;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=404771;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=3598;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=589191;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=822127;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=861551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=956993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=614453;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=202308;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=709923;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=871547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=98206;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47666 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=907441;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=136190;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=97226;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=882698;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=828167;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=310020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=814743;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=372894;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=770814;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252799;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=499414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=338155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47667 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=559642;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=678808;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:09 INFO  send() - 124.70.231.10:13356 - "GET /api/conversation HTTP/1.1" 200 ]8;id=674212;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=395403;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.10:13356 - "GET /api/record/0abebf87-4b93-4adc-a8e6-491e7db2f0d6 HTTP/1.1" 200 ]8;id=556412;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=787425;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:10 ERROR  add_conversation_by_user_sub() - [ConversationManager] 获取团队知识库列表失败 ]8;id=983788;file:///home/zjq/euler-copilot-framework_1/apps/services/conversation.py\conversation.py]8;;\:]8;id=844204;file:///home/zjq/euler-copilot-framework_1/apps/services/conversation.py#65\65]8;;\ -  INFO  send() - 124.70.231.10:13356 - "POST /api/conversation HTTP/1.1" 200 ]8;id=852938;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=102457;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.10:13356 - "POST /api/chat HTTP/1.1" 200 ]8;id=77838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=825234;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 56a6f6af-43d1-4b6e-b5fd-12ace83bcf07 ]8;id=620052;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=606323;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ -  INFO  run() - [Scheduler] 开始执行 ]8;id=933007;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=130131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ -  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=902686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=452843;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ -  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=545926;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=737856;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ -  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=156049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=526610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ -  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=133196;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=39998;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ -  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=699627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=278575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ -  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=262316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=935136;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ -  INFO  run() - [Scheduler] 发送结束消息 ]8;id=374628;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=587898;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=255541;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=56233;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-3346' coro=<Scheduler.run_executor() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    -  初始化失败')>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   -  │ │   -  │ 304 │ │ │ ) │   -  │ 305 │ │ │ # 开始运行 │   -  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   -  │ ❱ 307 │ │ │ await agent_exec.run() │   -  │ 308 │ │ │ self.task = agent_exec.task │   -  │ 309 │ │ else: │   -  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   -  │ │   -  │ 444 │ │ """执行MCP Agent的主逻辑""" │   -  │ 445 │ │ # 初始化MCP服务 │   -  │ 446 │ │ await self.load_state() │   -  │ ❱ 447 │ │ await self.load_mcp() │   -  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   -  │ 449 │ │ │ # 初始化状态 │   -  │ 450 │ │ │ try: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   -  │ │   -  │  85 │ │ │ │ continue │   -  │  86 │ │ │  │   -  │  87 │ │ │ self.mcp_list.append(mcp_service) │   -  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   -  │  89 │ │ │ for tool in mcp_service.tools: │   -  │  90 │ │ │ │ self.tools[tool.id] = tool │   -  │  91  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   -  │ │   -  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   -  │ 37 │ │ │ return None │   -  │ 38 │ │  │   -  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   -  │ 40 │ │ if user_sub not in self.pool: │   -  │ 41 │ │ │ self.pool[user_sub] = {} │   -  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   -  │ │   -  │ 134 │ │ if self.error_sign.is_set(): │   -  │ 135 │ │ │ self.status = MCPStatus.ERROR │   -  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   -  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   -  │ 138 │ │ │  │   -  │ 139 │ │ │ # 获取工具列表 │   -  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  Exception: MCP 6Zn8Gg 初始化失败   -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=976252;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=9033;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=97128;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=441682;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=55227;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=250535;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=241386;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=366041;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=895447;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=22566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:15:11 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=850260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=849417;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47668 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=659496;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=369594;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=26883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=18689;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ -25-Aug-12 20:15:12 INFO  send() - 124.70.231.47:14920 - "POST /api/chat HTTP/1.1" 200 ]8;id=204921;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=950848;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 39f8af6c-d918-405f-a931-d99ad0f7d46b ]8;id=958052;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=956234;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ -  INFO  run() - [Scheduler] 开始执行 ]8;id=229397;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=500295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ -25-Aug-12 20:15:14 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=21017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=221518;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  call() - [Reasoning] 推理内容: ]8;id=341974;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=747613;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  {   -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。"   -  }   -  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=303994;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=162298;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ -  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   -  'QuestionRewriteResult', 'type': 'object'}   -  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=550733;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=779360;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=520881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=400410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-3407' coro=<MCPClient._main_loop() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    -  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   -  │ __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  [1;91mExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=926298;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=669941;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  task: <Task pending name='Task-3408' coro=<Event.wait() running at    -  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=570711;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=48996;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=472832;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=546316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=341520;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=152956;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=509442;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=59199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=41578;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=135906;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47669 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=238531;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=622245;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:15 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=796703;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=553771;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=987685;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=534590;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。"   -  }   -  INFO  generate() - [JSONGenerator] 得到:{'question': ]8;id=894118;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=890685;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ -  '帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能数据采集和火焰图生成两个步骤。'}   -  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=352135;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=36297;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ -  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=113463;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=553945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ -  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=280176;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=298620;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ -  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=300816;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=943320;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ -  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=673292;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=119155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ -  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=923238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=503907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ -  INFO  run() - [Scheduler] 发送结束消息 ]8;id=429436;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=587388;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=784760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=315286;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-4169' coro=<Scheduler.run_executor() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    -  初始化失败')>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   -  │ │   -  │ 304 │ │ │ ) │   -  │ 305 │ │ │ # 开始运行 │   -  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   -  │ ❱ 307 │ │ │ await agent_exec.run() │   -  │ 308 │ │ │ self.task = agent_exec.task │   -  │ 309 │ │ else: │   -  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   -  │ │   -  │ 444 │ │ """执行MCP Agent的主逻辑""" │   -  │ 445 │ │ # 初始化MCP服务 │   -  │ 446 │ │ await self.load_state() │   -  │ ❱ 447 │ │ await self.load_mcp() │   -  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   -  │ 449 │ │ │ # 初始化状态 │   -  │ 450 │ │ │ try: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   -  │ │   -  │  85 │ │ │ │ continue │   -  │  86 │ │ │  │   -  │  87 │ │ │ self.mcp_list.append(mcp_service) │   -  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   -  │  89 │ │ │ for tool in mcp_service.tools: │   -  │  90 │ │ │ │ self.tools[tool.id] = tool │   -  │  91  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   -  │ │   -  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   -  │ 37 │ │ │ return None │   -  │ 38 │ │  │   -  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   -  │ 40 │ │ if user_sub not in self.pool: │   -  │ 41 │ │ │ self.pool[user_sub] = {} │   -  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   -  │ │   -  │ 134 │ │ if self.error_sign.is_set(): │   -  │ 135 │ │ │ self.status = MCPStatus.ERROR │   -  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   -  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   -  │ 138 │ │ │  │   -  │ 139 │ │ │ # 获取工具列表 │   -  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  Exception: MCP 6Zn8Gg 初始化失败   -25-Aug-12 20:15:16 INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=961140;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=127564;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ -  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=397415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=211760;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ -25-Aug-12 20:15:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=264236;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=573865;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=294474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=324847;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=859116;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=569726;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=740445;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=123049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=113725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=920499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47670 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=83817;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=887428;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=428971;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=794439;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=71104;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=103013;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=689407;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=147001;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=887536;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=841409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=826966;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=307909;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47671 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=73844;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=32377;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=759079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=811210;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=329569;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=791730;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=971615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=695138;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=688082;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=682687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=924239;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=729283;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47672 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=661420;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=802096;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=829915;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=881665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=258779;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=250365;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=91627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=470737;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=538883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=951869;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=466375;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=852160;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47673 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=23697;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=158545;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=731084;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=786530;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=880532;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=863816;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=356417;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=830238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=281500;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=564576;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=896701;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47674 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=910944;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=45222;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=335313;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=519314;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=109176;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=244217;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=343035;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=257344;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=251412;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=462336;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=792467;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=466637;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47675 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=865612;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=57822;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=495669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=905458;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=411696;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=795706;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=532462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=6671;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=516039;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=435035;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=697;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=101766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47676 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=863663;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=348405;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.47:14921 - "POST /api/chat HTTP/1.1" 200 ]8;id=158710;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=345725;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: 6c7d1f55-d8b5-4166-bb5d-284bb3391bb3 ]8;id=266751;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=474121;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ -25-Aug-12 20:15:43 INFO  run() - [Scheduler] 开始执行 ]8;id=313017;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=37232;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ -  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=14960;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=411743;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -25-Aug-12 20:15:44 INFO  call() - [Reasoning] 推理内容: ]8;id=857664;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=990218;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  {   -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。"   -  }   -  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=114415;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=419042;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ -  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   -  'QuestionRewriteResult', 'type': 'object'}   -  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=479257;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=566913;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ -25-Aug-12 20:15:45 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=721310;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=246536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=631247;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=202158;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。"   -  }   -  INFO  generate() - [JSONGenerator] 得到:{'question': ]8;id=476993;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=287409;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ -  '帮忙分析test.py进程的性能情况,并生成火焰图,具体包括性能瓶颈和函数调用关系的可视化分析。'}   -  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=858248;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=422635;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ -  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=248653;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=280460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ -  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=308460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=657225;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ -  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=858367;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=920944;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ -  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=664586;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=123451;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ -  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=483781;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=531817;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ -  INFO  run() - [Scheduler] 发送结束消息 ]8;id=87156;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=686427;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=156487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=943984;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-6790' coro=<Scheduler.run_executor() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    -  初始化失败')>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   -  │ │   -  │ 304 │ │ │ ) │   -  │ 305 │ │ │ # 开始运行 │   -  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   -  │ ❱ 307 │ │ │ await agent_exec.run() │   -  │ 308 │ │ │ self.task = agent_exec.task │   -  │ 309 │ │ else: │   -  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   -  │ │   -  │ 444 │ │ """执行MCP Agent的主逻辑""" │   -  │ 445 │ │ # 初始化MCP服务 │   -  │ 446 │ │ await self.load_state() │   -  │ ❱ 447 │ │ await self.load_mcp() │   -  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   -  │ 449 │ │ │ # 初始化状态 │   -  │ 450 │ │ │ try: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   -  │ │   -  │  85 │ │ │ │ continue │   -  │  86 │ │ │  │   -  │  87 │ │ │ self.mcp_list.append(mcp_service) │   -  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   -  │  89 │ │ │ for tool in mcp_service.tools: │   -  │  90 │ │ │ │ self.tools[tool.id] = tool │   -  │  91  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   -  │ │   -  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   -  │ 37 │ │ │ return None │   -  │ 38 │ │  │   -  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   -  │ 40 │ │ if user_sub not in self.pool: │   -  │ 41 │ │ │ self.pool[user_sub] = {} │   -  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   -  │ │   -  │ 134 │ │ if self.error_sign.is_set(): │   -  │ 135 │ │ │ self.status = MCPStatus.ERROR │   -  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   -  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   -  │ 138 │ │ │  │   -  │ 139 │ │ │ # 获取工具列表 │   -  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  Exception: MCP 6Zn8Gg 初始化失败   -  INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=165968;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=390285;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ -25-Aug-12 20:15:46 WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=127833;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=529156;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=447011;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=694036;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=283805;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=922713;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=194367;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=966919;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=735579;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=330589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=381798;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=783492;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47677 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=649585;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=656005;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=590061;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=556589;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=559215;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=989817;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=776199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=578521;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=254413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=684927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=469224;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=698110;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47678 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=387169;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=814308;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=871189;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=976613;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=437233;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=652996;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=75289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=19303;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=984686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=168950;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=237397;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=991716;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:47679 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=578987;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=592301;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:15:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=434180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=701562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=947268;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=404514;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10425;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=749952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=929925;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=825421;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=723712;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=408626;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48176 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=294777;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=525958;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=553362;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=51964;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=354131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=599776;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=202065;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=138472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=822932;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=850900;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=223025;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=140712;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48177 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=83810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=213593;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=986939;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=781879;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=725743;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=84898;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=534047;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=848989;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=871472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=268311;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=11444;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=697539;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48178 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=390097;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=815221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:10 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=641049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=202882;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=907933;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=496338;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=560548;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=172861;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=387536;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=212272;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=565042;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=394409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48179 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=558229;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=626925;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:12 INFO  send() - 124.70.231.10:13357 - "POST /api/stop HTTP/1.1" 200 ]8;id=729916;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=168600;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.10:13357 - "POST /api/chat HTTP/1.1" 200 ]8;id=464430;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=401123;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: ba8c8052-60bd-4384-adb2-4445b54cd877 ]8;id=652450;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=904281;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ -  INFO  run() - [Scheduler] 开始执行 ]8;id=553112;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=240242;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ -  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=574615;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=958799;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  call() - [Reasoning] 推理内容: ]8;id=753639;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=970479;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  {   -  "question": "如何查看 test.py 的性能分析?"   -  }   -  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=921665;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=916309;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ -  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   -  'QuestionRewriteResult', 'type': 'object'}   -  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=107255;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=489416;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ -25-Aug-12 20:16:13 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=300429;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=355039;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=743709;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=777666;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ -  "question": "如何查看 test.py 的性能分析?"   -  }   -  INFO  generate() - [JSONGenerator] 得到:{'question': '如何查看 test.py 的性能分析?'} ]8;id=529687;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=116977;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ -  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=62178;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=873458;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ -  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=141575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=313747;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ -  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=146505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=262838;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ -  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=394452;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=875961;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ -  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=798033;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=889366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#92\92]8;;\ -  ╭───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  init() - [MCPClient] MCP 6Zn8Gg:初始化失败 ]8;id=380155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=469347;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#136\136]8;;\ -  INFO  run() - [Scheduler] 发送结束消息 ]8;id=79903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=759366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=751424;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=505292;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-9142' coro=<Scheduler.run_executor() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:200> exception=Exception('MCP 6Zn8Gg    -  初始化失败')>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py:307 in run_executor │   -  │ │   -  │ 304 │ │ │ ) │   -  │ 305 │ │ │ # 开始运行 │   -  │ 306 │ │ │ logger.info("[Scheduler] 运行Executor") │   -  │ ❱ 307 │ │ │ await agent_exec.run() │   -  │ 308 │ │ │ self.task = agent_exec.task │   -  │ 309 │ │ else: │   -  │ 310 │ │ │ logger.error("[Scheduler] 无效的应用类型") │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:447 in run │   -  │ │   -  │ 444 │ │ """执行MCP Agent的主逻辑""" │   -  │ 445 │ │ # 初始化MCP服务 │   -  │ 446 │ │ await self.load_state() │   -  │ ❱ 447 │ │ await self.load_mcp() │   -  │ 448 │ │ if self.task.state.flow_status == FlowStatus.INIT: │   -  │ 449 │ │ │ # 初始化状态 │   -  │ 450 │ │ │ try: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py:88 in load_mcp │   -  │ │   -  │  85 │ │ │ │ continue │   -  │  86 │ │ │  │   -  │  87 │ │ │ self.mcp_list.append(mcp_service) │   -  │ ❱  88 │ │ │ await self.mcp_pool._init_mcp(mcp_id, self.task.ids.user_sub) │   -  │  89 │ │ │ for tool in mcp_service.tools: │   -  │  90 │ │ │ │ self.tools[tool.id] = tool │   -  │  91  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/pool.py:39 in _init_mcp │   -  │ │   -  │ 36 │ │ │ logger.warning("[MCPPool] 用户 %s 的MCP %s 类型错误", user_sub, mcp_id) │   -  │ 37 │ │ │ return None │   -  │ 38 │ │  │   -  │ ❱ 39 │ │ await client.init(user_sub, mcp_id, config.config) │   -  │ 40 │ │ if user_sub not in self.pool: │   -  │ 41 │ │ │ self.pool[user_sub] = {} │   -  │ 42 │ │ self.pool[user_sub][mcp_id] = client │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:137 in init │   -  │ │   -  │ 134 │ │ if self.error_sign.is_set(): │   -  │ 135 │ │ │ self.status = MCPStatus.ERROR │   -  │ 136 │ │ │ logger.error("[MCPClient] MCP %s:初始化失败", mcp_id) │   -  │ ❱ 137 │ │ │ raise Exception(f"MCP {mcp_id} 初始化失败") │   -  │ 138 │ │ │  │   -  │ 139 │ │ │ # 获取工具列表 │   -  │ 140 │ │ self.tools = (await self.client.list_tools()).tools │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  Exception: MCP 6Zn8Gg 初始化失败   -25-Aug-12 20:16:14 INFO  update_recent_app() - [AppCenterManager] 更新用户最近使用应用: root ]8;id=128889;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py\appcenter.py]8;;\:]8;id=446477;file:///home/zjq/euler-copilot-framework_1/apps/services/appcenter.py#323\323]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=690954;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=473060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=911931;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=493828;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=876081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=573349;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=433650;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=551348;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=356153;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=686134;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=969199;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=839566;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48180 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=596184;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=976536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=260123;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=253024;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=120456;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=954430;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=646268;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=41547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=846429;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=153728;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=76250;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=522222;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48181 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=333841;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=651347;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=54415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=586185;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=48617;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=46496;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=834755;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=825949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=554414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=705780;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=930911;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=503205;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48182 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=566209;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=392011;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=197705;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=947191;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=22255;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=755119;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=182418;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=166950;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=83486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=749976;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=982835;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=567722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48183 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=352221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=500436;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=786359;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=72953;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=326615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=412952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=271450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=266055;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=841261;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=121311;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=833516;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=421273;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48184 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=189269;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=23233;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=863393;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=641896;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=595113;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=932575;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=783109;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=928511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=530063;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=295131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=745907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=637413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48185 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=212487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=428753;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=142721;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=77686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=585305;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=901835;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=339393;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=612389;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=378523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=600190;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=971878;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=773631;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48186 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=858211;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=814884;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=924170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=282044;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=394565;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=466157;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=779559;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=373558;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=758545;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=992416;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=595610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=320994;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48187 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=670870;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=341251;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=591044;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=123443;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=962886;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=599057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=816608;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=478561;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=262819;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=913011;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=804141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=879856;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48188 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=270250;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=578667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:47 INFO  send() - 124.70.231.47:14922 - "POST /api/chat HTTP/1.1" 200 ]8;id=875128;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=228325;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  get_used_docs_by_record_group() - [DocumentManager] 记录组不存在: d28646fb-c4de-45c4-ae94-57d96b9b9613 ]8;id=465045;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py\document.py]8;;\:]8;id=137753;file:///home/zjq/euler-copilot-framework_1/apps/services/document.py#120\120]8;;\ -  INFO  run() - [Scheduler] 开始执行 ]8;id=133567;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=208172;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#125\125]8;;\ -25-Aug-12 20:16:48 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=598579;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=892311;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -25-Aug-12 20:16:49 INFO  call() - [Reasoning] 推理内容: ]8;id=696022;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=764830;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  {   -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图"   -  }   -  ```   -  INFO  generate() - [JSONGenerator] Schema:{'description': '问题补全与重写结果', 'properties': {'question': ]8;id=692588;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=957447;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#283\283]8;;\ -  {'description': '补全后的问题', 'title': 'Question', 'type': 'string'}}, 'required': ['question'], 'title':   -  'QuestionRewriteResult', 'type': 'object'}   -  WARNING  _call_openai() - [FunctionCall] function_call无法确保一定调用工具,使用效果将受到影响 ]8;id=932434;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=313220;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#113\113]8;;\ -25-Aug-12 20:16:50 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=509418;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=928526;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  _call_openai() - [FunctionCall] 大模型输出:{ ]8;id=162273;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=156948;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#131\131]8;;\ -  "question": "帮忙分析test.py进程的性能情况,并生成火焰图"   -  }   -  INFO  generate() - [JSONGenerator] 得到:{'question': '帮忙分析test.py进程的性能情况,并生成火焰图'} ]8;id=688673;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py\function.py]8;;\:]8;id=287373;file:///home/zjq/euler-copilot-framework_1/apps/llm/function.py#288\288]8;;\ -  INFO  run_executor() - [Scheduler] 运行Executor ]8;id=490811;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=660918;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#306\306]8;;\ -  INFO  load_state() - [FlowExecutor] 加载Executor状态 ]8;id=189183;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=162289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#66\66]8;;\ -  INFO  load_mcp() - [MCPAgentExecutor] 加载MCP服务器列表 ]8;id=488137;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=482180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#73\73]8;;\ -  INFO  sse_client() - Connecting to SSE endpoint: http://0.0.0.0:12141/sse ]8;id=807892;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=252603;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#45\45]8;;\ -  INFO  _send_single_request() - HTTP Request: GET http://0.0.0.0:12141/sse "HTTP/1.1 200 OK" ]8;id=967715;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=667838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  INFO  sse_reader() - Received endpoint URL: http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 ]8;id=822394;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=286082;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#65\65]8;;\ -  INFO  sse_client() - Starting post writer with endpoint URL: ]8;id=655685;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py\sse.py]8;;\:]8;id=872284;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py#135\135]8;;\ -  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75   -  INFO  _send_single_request() - HTTP Request: POST ]8;id=704110;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=787841;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   -  INFO  _send_single_request() - HTTP Request: POST ]8;id=7807;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=559667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   -  INFO  _send_single_request() - HTTP Request: POST ]8;id=612044;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=288352;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  http://0.0.0.0:12141/messages/?session_id=8eea538cbf7c4cf2bb44b63a8d8d9e75 "HTTP/1.1 202 Accepted"   -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=672339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=692574;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=331049;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=387460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=883688;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=182122;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=653168;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=967773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=699030;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=509380;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48189 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=102883;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=710150;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=488690;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=263847;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  call() - [Reasoning] 推理内容: ]8;id=932254;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=121001;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  分析test.py进程性能并生成火焰图   -25-Aug-12 20:16:51 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=495294;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=468536;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -  INFO  call() - [Reasoning] 推理内容: ]8;id=367218;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=249659;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  ```json   -  {   -  "tool_ids": ["IorUzv", "jeDuwL"]   -  }   -  ```   -  ERROR  plan() - 各个字段的类型: <class 'str'>, , ,  ]8;id=123778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=716490;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#130\130]8;;\ -25-Aug-12 20:16:52 INFO  _send_single_request() - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions ]8;id=162399;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py\_client.py]8;;\:]8;id=912611;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py#1740\1740]8;;\ -  "HTTP/1.1 200 OK"   -25-Aug-12 20:16:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=357067;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=3753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=268036;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=805006;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=312696;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=70241;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=539627;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=765791;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=669954;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=534939;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48190 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=326712;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=767558;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:16:56 INFO  call() - [Reasoning] 推理内容: ]8;id=135251;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py\reasoning.py]8;;\:]8;id=358931;file:///home/zjq/euler-copilot-framework_1/apps/llm/reasoning.py#205\205]8;;\ -    -  <thinking>   -  1. 用户的目标是分析 `test.py` 进程的性能情况并生成火焰图。   -  2. 首先需要使用 `perf` 工具采集该进程的性能数据,这可以通过 `perf_collect_tool` 完成,传入进程名称 `test.py`。   -  3. 采集完成后会生成 `perf.data` 文件。   -  4. 接着使用 `generate_flamegraph_tool` 来处理 `perf.data` 并生成火焰图 `perf.svg`。   -  5. 最后使用 `Final` 工具结束整个流程。   -  </thinking>   -  ```json   -  {   -  "plans": [   -  {   -  "content": "使用 perf_collect_tool 采集 test.py 进程的性能数据",   -  "tool": "IorUzv",   -  "instruction": "采集进程名称为 test.py 的性能数据并保存为 perf.data"   -  },   -  {   -  "content": "使用 generate_flamegraph_tool 处理 perf.data 并生成火焰图",   -  "tool": "jeDuwL",   -  "instruction": "处理当前目录下的 perf.data 文件,生成火焰图 perf.svg"   -  },   -  {   -  "content": "任务完成,火焰图已生成,路径为 Result[1]",   -  "tool": "FIANL",   -  "instruction": ""   -  }   -  ]   -  }   -  ```   -  INFO  reset_step_to_index() - [MCPAgentExecutor] 重置步骤到索引 0 ]8;id=629127;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=262165;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#158\158]8;;\ -  ERROR  run() - [MCPAgentExecutor] 执行过程中发生错误: Traceback (most recent call last): ]8;id=90626;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=219138;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#517\517]8;;\ -  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py", line 502, in run   -  await self.work()   -  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py", line 361, in work   -  tool_skip = await MCPPlanner.tool_skip(self.task,   -  self.task.runtime.temporary_plans.plans[self.task.state.step_index], self.resoning_llm)   -  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   -  ^^^^^^^^^^^^^^^^^^^^^^   -  File "/home/zjq/euler-copilot-framework_1/apps/scheduler/mcp_agent/plan.py", line 176, in tool_skip   -  step_id=step.id,   -  ^^^^^^^   -  File "/root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/pydantic/main.py", line 991, in   -  __getattr__   -  raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')   -  AttributeError: 'MCPPlanItem' object has no attribute 'id'   -    -  ERROR  run() - [MCPAgentExecutor] 执行过程中发生错误: 'MCPPlanItem' object has no attribute 'id' ]8;id=328494;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py\agent.py]8;;\:]8;id=321505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/executor/agent.py#518\518]8;;\ -  ERROR  _main_loop() - [MCPClient] MCP 6Zn8Gg:收到停止信号,正在关闭 ]8;id=721141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py\client.py]8;;\:]8;id=271429;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py#99\99]8;;\ -  INFO  run() - [Scheduler] 发送结束消息 ]8;id=510749;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=208833;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#193\193]8;;\ -  ERROR  chat_generator() - [Chat] 生成答案失败 ]8;id=687598;file:///home/zjq/euler-copilot-framework_1/apps/routers/chat.py\chat.py]8;;\:]8;id=549286;file:///home/zjq/euler-copilot-framework_1/apps/routers/chat.py#105\105]8;;\ -  WARNING  _monitor_activity() - [Scheduler] 用户 root 不活跃,终止工作流 ]8;id=3383;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py\scheduler.py]8;;\:]8;id=883002;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/scheduler/scheduler.py#60\60]8;;\ -25-Aug-12 20:16:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=136486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=830722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=134934;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=862413;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=360313;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=29105;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=508760;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=288687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=956075;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=248186;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48191 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=533028;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=654773;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=351595;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=446571;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=513695;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=673841;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=560029;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=796160;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=885379;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=820530;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=207649;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=638775;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48192 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=113490;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=340422;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=921081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=57208;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=138736;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=74475;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=32969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=930339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=986681;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=842685;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=722746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=239686;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48193 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=223873;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=76460;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:10 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=958081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=186983;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=785319;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=808665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=895949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=326258;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=441493;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=166394;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=388378;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=587562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48194 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=773038;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=625329;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:14 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=995389;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=965711;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=492658;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=639078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=136857;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=354332;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=777703;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=529282;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=961870;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=161225;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48195 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=749307;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=845574;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=791684;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831255;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=173654;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=900662;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=896740;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=20263;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=532100;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=632942;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=434992;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=59366;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48196 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=97564;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=352404;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:22 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=528360;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=606032;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=714746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=240242;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=35645;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=241276;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=514118;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=277705;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=539831;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48197 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=311548;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=347274;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=932766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=938404;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=156460;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=491886;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=233021;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=561825;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=459786;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=28499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=804521;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=975434;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48198 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=912451;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=720846;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:30 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=662258;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=310244;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=36368;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=992057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=45174;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=857184;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=931407;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=168260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=920052;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=810885;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48199 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=50655;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=572545;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=119346;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=307205;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=3899;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=977740;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=918010;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=456298;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=252863;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=86357;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=952089;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=807252;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48200 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=13137;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=258319;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=538354;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=403022;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=953821;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=881439;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=467714;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=177878;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=226060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=239346;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=910078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=293345;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48201 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=102913;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=772703;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=97511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=672690;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=698110;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=882196;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=355846;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=794986;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=529915;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=189029;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=289144;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=120816;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48202 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=175692;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=270656;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=53369;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=276475;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=987464;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=598753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=351836;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=92562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=180747;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=959669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=911688;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=202428;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48203 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=253598;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=197509;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:49 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=964707;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=323623;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=486658;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=847190;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=44831;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=122100;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:17:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=626210;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=775341;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=19722;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=396725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48204 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=260062;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=268881;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=876806;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=998081;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=925014;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=203792;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=532292;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=757713;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=678428;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=478825;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=647865;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=473610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48205 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=377224;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=692350;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=736675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=613773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48206 - "GET /api/mcp/W785k0?edit=true HTTP/1.1" 200 ]8;id=19173;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=575247;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:56 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=497610;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=339730;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=778441;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=70851;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=614237;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=915694;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=689340;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=140535;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=14998;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=629945;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48207 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=199661;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=930562;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:17:59 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=402882;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=546892;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:18:00 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=314936;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=955684;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=463522;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=800925;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=264481;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=711733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=582182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48208 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=57337;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=625221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:03 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: W785k0 ]8;id=549523;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=521774;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=518304;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=159777;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=452182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=600920;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=609118;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=884125;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=104162;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=73910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48209 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=846018;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=314350;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  deactive_mcpservice() - [MCPServiceManager] MCP服务无进程 ]8;id=296394;file:///home/zjq/euler-copilot-framework_1/apps/services/mcp_service.py\mcp_service.py]8;;\:]8;id=329917;file:///home/zjq/euler-copilot-framework_1/apps/services/mcp_service.py#366\366]8;;\ -  INFO  update_template_status() - [MCPLoader] 更新MCP模板状态: W785k0 -> MCPInstallStatus.INIT ]8;id=179691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=566797;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#390\390]8;;\ -  INFO  send() - 124.70.231.34:48210 - "POST /api/mcp?Content-Type=application%2Fjson HTTP/1.1" 200 ]8;id=791699;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=503157;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:04 INFO  send() - 124.70.231.34:48211 - "POST /api/mcp?serviceId=W785k0 HTTP/1.1" 500 ]8;id=970310;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=86710;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=498021;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=709301;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-4577' coro=<MCPClient._main_loop() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    -  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   -  │ __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=322927;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=779032;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  task: <Task pending name='Task-4578' coro=<Event.wait() running at    -  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=937095;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=322051;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-6935' coro=<MCPClient._main_loop() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    -  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   -  │ __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=712365;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=907769;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  task: <Task pending name='Task-6936' coro=<Event.wait() running at    -  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   -  ERROR  default_exception_handler() - Task exception was never retrieved ]8;id=87390;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=528830;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  future: <Task finished name='Task-9248' coro=<MCPClient._main_loop() done, defined at    -  /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:41> exception=ExceptionGroup('unhandled    -  errors in a TaskGroup', [ConnectError('All connection attempts failed')])>   -  ╭───────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────╮   -  │ /home/zjq/euler-copilot-framework_1/apps/scheduler/pool/mcp/client.py:84 in _main_loop │   -  │ │   -  │  81 │ │ # 创建Client、Session │   -  │  82 │ │ try: │   -  │  83 │ │ │ exit_stack = AsyncExitStack() │   -  │ ❱  84 │ │ │ read, write = await exit_stack.enter_async_context(client) │   -  │  85 │ │ │ self.client = ClientSession(read, write) │   -  │  86 │ │ │ session = await exit_stack.enter_async_context(self.client) │   -  │  87 │ │ │ # 初始化Client │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:650 in enter_async_context │   -  │ │   -  │ 647 │ │ │ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does " │   -  │ 648 │ │ │ │ │ │ │ f"not support the asynchronous context manager protocol" │   -  │ 649 │ │ │ │ │ │ ) from None │   -  │ ❱ 650 │ │ result = await _enter(cm) │   -  │ 651 │ │ self._push_async_cm_exit(cm, _exit) │   -  │ 652 │ │ return result │   -  │ 653  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:210 in __aenter__ │   -  │ │   -  │ 207 │ │ # they are only needed for recreation, which is not possible anymore │   -  │ 208 │ │ del self.args, self.kwds, self.func │   -  │ 209 │ │ try: │   -  │ ❱ 210 │ │ │ return await anext(self.gen) │   -  │ 211 │ │ except StopAsyncIteration: │   -  │ 212 │ │ │ raise RuntimeError("generator didn't yield") from None │   -  │ 213  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/mcp/client/sse.py:43 in sse_client │   -  │ │   -  │  40 │ read_stream_writer, read_stream = anyio.create_memory_object_stream(0) │   -  │  41 │ write_stream, write_stream_reader = anyio.create_memory_object_stream(0) │   -  │  42 │  │   -  │ ❱  43 │ async with anyio.create_task_group() as tg: │   -  │  44 │ │ try: │   -  │  45 │ │ │ logger.info(f"Connecting to SSE endpoint: {remove_request_params(url)}") │   -  │  46 │ │ │ async with httpx.AsyncClient(headers=headers) as client: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:772 in │   -  │ __aexit__ │   -  │ │   -  │  769 │ │ │ │ │ # added to self._exceptions so it's ok to break exception │   -  │  770 │ │ │ │ │ # chaining and avoid adding a "During handling of above..." │   -  │  771 │ │ │ │ │ # for each nesting level. │   -  │ ❱  772 │ │ │ │ │ raise BaseExceptionGroup( │   -  │  773 │ │ │ │ │ │ "unhandled errors in a TaskGroup", self._exceptions │   -  │  774 │ │ │ │ │ ) from None │   -  │  775 │ │ │ │ elif exc_val: │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)   -  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=697550;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=933544;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  task: <Task pending name='Task-9249' coro=<Event.wait() running at    -  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   -  ERROR  default_exception_handler() - Task was destroyed but it is pending! ]8;id=938522;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py\base_events.py]8;;\:]8;id=375977;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/base_events.py#1785\1785]8;;\ -  task: <Task pending name='Task-12134' coro=<Event.wait() running at    -  /root/miniconda3/envs/framework_test_env/lib/python3.11/asyncio/locks.py:213> wait_for=>   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=831420;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=59960;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:346 in app │   -  │ │   -  │  343 │ │ │ │ validation_error = RequestValidationError( │   -  │  344 │ │ │ │ │ _normalize_errors(errors), body=body │   -  │  345 │ │ │ │ ) │   -  │ ❱  346 │ │ │ │ raise validation_error │   -  │  347 │ │ if response is None: │   -  │  348 │ │ │ raise FastAPIError( │   -  │  349 │ │ │ │ "No response object was returned. There's a high chance that the " │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  RequestValidationError: [{'type': 'model_attributes_type', 'loc': ('body',), 'msg': 'Input should be a valid    -  dictionary or object to extract fields from', 'input':   -  b'------WebKitFormBoundaryAIGBXkBO7yWnYuGc\r\nContent-Disposition: form-data; name="icon";    -  filename="openEuler.png"\r\nContent-Type:    -  image/png\r\n\r\n\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe2\x01\xd8ICC_PROFILE\x00   -  \x01\x01\x00\x00\x01\xc8\x00\x00\x00\x00\x040\x00\x00mntrRGB XYZ    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00acsp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tdesc\x00\x00\x00\xf0\x00\x00\x00$rXYZ\x00\x00\x01   -  \x14\x00\x00\x00\x14gXYZ\x00\x00\x01(\x00\x00\x00\x14bXYZ\x00\x00\x01<\x00\x00\x00\x14wtpt\x00\x00\x01P\x00\x00\x00\   -  x14rTRC\x00\x00\x01d\x00\x00\x00(gTRC\x00\x00\x01d\x00\x00\x00(bTRC\x00\x00\x01d\x00\x00\x00(cprt\x00\x00\x01\x8c\x0   -  0\x00\x00!\x8a\x   -  d9\xab\x1fl\xad\xb5\xdbk\xa6hV\xf3w\xb7\x1c\x12]\x17\xcek\xe6\xda\xefn\xebU\xab:\x16\xb3J\xdb\xa7\x14^\x19\x8e5Mj\xf   -  f\x00U\xb8\x95K\xcb\x9a\x93\x8b\xf8\xb2y:\xb7\xfaN.\x1e^\x07\xa7\xe0\xf4\xca\xc7\x9b4\xb2g\xdb\x9ds\xa8WugQ\xd5\x9dn   -  7\x9f\xceI\xbc}\xa5\x9e/)\x89\xbe\xbe\x1d\xc5\xbaX\x9byX\x19\xc4\xda]\x0e\xcdp\xd6\x9e\x9a\xb6\xbe\xd7*\xcb\x8dtH\xb   -  6\x91[(}L\x93,3\x1a\x18\x00\x85v    -  \xc19D\xa5\x18+\x8c\xb1\x1c`\xa5`\x95\xd4\xa4\xd7r\x10\xf3^q\x9fYEX\xb9I5\xcb\xd4\\\x06X\xad{u)\x89\xd3\xb0\xd15\xcb   -  \xed"\xe25m\xaa\xcf\x93\xce8\x9e\x0c\xdb\xb0\xdb\xe8\x8bt\xed\xf5\x99\xc2\x9b\xe9\xcb\x99\x80Y0\x92R\xe4\xb1%\xcf\'#   -  \x97\xc2\xae_P\xd9\xc5\x97M\xf4\xd9\xfdn\xcfU\xb5\x8dkJ\xbcqh\xed\xdc\xdb\xe8h\xde\xcb\xed\xc6\xa9\xa1\xdd\xc2P\xadV   -  t\xa3\xf13\xc8\xcf\xbb\r\xbd\x9bMEB\x95\xe5HR\x9c\xb9sg\x9b\xe4t\xebb\x99\x98o\xd34i\x99\xd3e|G_c}B\xea\x84jQ\xa8\xa   -  7\x17\xd1\xa3\x95\xc6\x97Vr2c\x9a\xcb,e\xda\xf2eI\x96\xa3$\xfa\x15\xa7\x82\xb1:^\'j\xf2IG\x12%4^%e@\x8c\x92XH\x00\x8   -  4\x80\x01\x00\x00$0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x0   -  0\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00dd\x01\x19\'$"\x92!\x96\xd9q\xf4-K)\x8f+D\xe9L\xde9\xf5-y\x   -  cf\x9f\x17\x9b\xe0U^\xb5:t\xa5)\xca1\xc7\x8b\xc1\x8e6\xc7y\x9af\x84\xa7M\xd4\xcdn\x8b\x85\xe5d\xcf\x8f\x05\xb2N\xa1\   -  x83.X\x87\xbd\xbc\xd4m\xech\xca\xa5z\xb0\x82K\xa3x1.\xdco\x87O\xd3\x1dJv\xb0u*\xae\\Py0\xee\xdao\'T\xd6\xee*B\x15\xb   -  f\xab\xbe\x98\xe4c\xca\xeeUf\xe596\xdf\x8b;\xbcn\x95:\x8bY\xa3\x97\x93\xb8\xd4=V\xd7\xed\x9e\xa1\xaf\xd4\x94\xe5q/#.   -  |\x0c\xf2I\xe5e\x94\xc6\x1c/(\xb9\x9c\x9d\xee?\x1f\xf1\xfd9\xf3(    -  \x91\x83z#F\xc8\xf2\xe8U\x8e\xf21\x80\x11\xb4\xe4\x13\x82\tD\xce\xc0\xc0!\x08\x03\xbc\x92\x12\x13\x82\tD\tD\x90\x89\   -  x02\x08}J\x8aq\xcci0\xa2M\xae\x85\xea\x15\xbc\x9e%o\xf9\xba\xab\xe3\x14\xf2)q\xf01d\xc3\x19!\x922L2\x1e\xc4o;S\xd1\x   -  ebB\x85\xedy\xd5\xa3\x17\x8c#b\xb6?o\xf4\xcdr\xde\x1cuaNmt\x94\xb9\x9aa\xc2\xa2\xf33\x97\xa6j\x17\x1671\xa9B\xa4\x92   -  O+\x99\xc8\xe4\xf4\xa8\xbcxe\xaef\xfe\xd1\xadN\xad>*RN>)\x97a\x9e\xf7\x93Wv;{\xf7\x96J\x9d\x1dN\xaeh.\\\x973=\xec\xe   -  6\xd5\xd8\xeb\x16t\xaaZ\xd5\x8f\x9c\xb3\x87%\x93\xce\xf2x\x16\xc7\xee\x1b\xf8\xb2\xc4\xbdQT;\xce\x1d\n\x95%.&\xd3\x8   -  3\xe9\x83\x97\x13N)\xdb\xe1\xb5\x13\xb5h\xa9\x14&U\x91+*\x059%\x15\x12\xd9\x19\x00@\x90\x01    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x19)\x93\x0c\xa5\xb2$3\x828\x88\x93\xe4Q\x92;\xa3\xec\xdc/E\xe49$q\xf3%\xcd?\xd8uZ\xce\xb   -  9e\xa7R\x95K\xab\x88SqY\xc4\x9fS%)\xdf>\x14\xb5\xe2\x1d\xd3\xab\x1f\x13\xc8m^\xd9\xe9\x9a\rY~Sp\xa3U/E\x98\xafo\xb7\   -  xcdN\x959\xda\xe9\xf4\xd3\x93\xe5\xe5    -  \xff\x00\xe4\xc0\x9a\xee\xd0\xdf\xeaWrw5\xeaUr\xe7\x96\xfa\x1dn\'L\x9b\xce\xed\xe9\xa7\x97\x931\xf1d\xfd\xe2o\x92\xe   -  e\xfeU-t\xde\x17M\xf2\xe2\x8b\xc31%\xe5\xed\xcd\xf4\xddK\x8a\xb3\x94\xa5\xe3,\x9cO&\xf8\xb8\xa5\xd5\x97\x0e\xf6\x1e\   -  x1dq\xfa\x86\x95\xf3\xcd\x88.\x1eY\xc9,&\x0e\xbe9\x88\x8di\xaf1\xb9\xda\x02$\x94[\xd8\x0f\xd82TU\x1bR\xc1$\x81\x19    -  \x96A(\x00\x00C\' \x15J2J`\r\x1bNFH\x19\x1a6\x91\x92224\x84\x93\x9c\x14\xe4\r\n\x9e\'\xe9\x14\xc9pz<\xc0&    -  \x85\xb9Jr\xe4\xf9\x1d\xe6\xce\xed.\xa3\xa3V\x8c\xa8\xd5\x9b\x8c_$\xe4\xf0t\xf8\x1d\xc6\xb6n-s{e\xaeY\xaf\xa6\xc8\xe   -  e\xf7|6\xd7\x0e\x145\xda\xb0\xa1\xdd\x16\xbb\xd9\x9b4\x9d^\xd7R\xb6\x8dkZ\x8at\xdfFh\x04\xa37\x89S\x93\x8c\xa3\xcd4z   -  \xed\x90\xde\x16\xb1\xa0W\x84[\xadqI|\\\xf2<\xf73\xa5\xc5\'uob\xe4\xcc\xb7\x92-4R\xe6\xb3\x8c\x98\x9baw\xb5\xa7\xea\   -  xb4\xa1J\xf2T\xed\xea\xf4\xc4\x9f3\'\xda\xdd\xd1\xbc\xa5\x1a\x94\'\x19E\xf3M\x1c\x0c\x98\xedI\xd4\xba\x18\xef\x16\xf   -  6\xe5\xa9s+\xe2H\xb1\xdc\x13q\xee\xe2(\xc9i\x8f\xa7\'9\x05\xaak\x0b9.\xa2\x15\x89H\x00$\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\   -  xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08r#bAG\x11*Dw\n\x88c$9`\x98\x9d\x   -  a2F[\x93\xc1\n\xb4d\xf0\xb2[\xadV0\x8b\x94\xa4\x92^,\x99\xac\xcf\xa6+^!2\x97\x89\xc5\xba\xbd\xa1kI\xd4\xadR0\x8a\xf1   -  x\x87Y.|+<_\xff\x00\x87\x7f\x87\xd3#\xba;\xdc\   -  xdc\x99\x9c\x8b\xeb\xeb\xdb\xdb\x89U\xb8\xab:\x9c\\\xf1)d\xe299zK\x87\xd4\\\x92qK\x85\xf1|\xc8\x86\xd2\xe5>O\xe7=\x1   -  6<\x14\xc5\xf1`\x9c\xbbYqI\xf2\x93c\x05R\x8bO\x9a    -  \xb4\xfbc\x9bl!\xf5*\xc1\x1d\xe2\x15B\x0c\x90N\xc4`\x12C%;\x02\x04\xa2\xc8\x18\xef\x0c\x8e\xf0$\x94\x10DJFGqS)k\x91\   -  x00\x08\xef$    -  \x00\x00\x00\x00\x00\x00\x00\x00d\x90\xc9\x00\x00\x00\x00\x00\x00\x00R\xca\x88\xc6J\xc8\xa5\xac\x95E\xf0<\xc6M\xb2\x   -  1a\x18\xc31[\x0fz\xd0\xef4=\xa4\xd54\xdb\x98T\xb7\xabS\x86/\xd1R\xe4\xcc\xe7\xb0\x9b\xdf\xa1_\xc9\xda\xea\xf5!E\xf4\   -  xcey\x9a\xe5\x1a\x93\x8fD\xc2^w\x1a\x9f\x0c\xd74\xceg/\xa6\xc4\xc6\xf4\xdd\xc5\x9b\xb64\xdfm/R\xb5\xd4-\xa3+:\xbeV2]   -  N\xce\x85?&\xb9\xb7\xcc\xd2\xbd\x8c\xdb\xcdOC\xad\x0e+\x8a\xb5)\'\xe8\xe4\xd8}\x8a\xde\x85\x86\xb3\nq\xb8\xa9\n5zp\x   -  c9\xf3g\x9a\xcd\xc2\xbd\'\xd3k\x1eX\xb4\xb2\x9a*G\x12\x85\xe5+\x8aq\x9d\t\xa9&\xb3\x94rb\xf2\x8d\x1bW^\xdb1\xe1^I)*"   -  \x16\x81\x01\xde\x18H\x08\x00\xda\xa4\x08\x89!    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i   -  \xbe\xab\xf8\xaa@v\xa3\xf8\t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C`Ce.X\r\x96\xdc\x8aM\xa7j\xcd\xb4\xb9\x1a\x89\xbcd\x8a\x92\x   -  e1Y8\x93\xa9Iq9K\x18\xf9\xcf\x15\xb6;\xc4\xd34\n2\x8dj\xdez\xe4\xb1\xcf\x99\xb1\x8b\x15\xaf:\x88W\xf2C\xd9\xd6\xd4h\   -  xd2M\xd5\x92\x82]\xf2x1\x9e\xde\xeff\xc7C\x84\xe8\xdb\xb9N\xab\xe4\x9d7\x9c}\x86\x18\xdb}\xeak\x1a\xadI\xd3\xa0\xe0\   -  xad\x1fF\xb93\x1dN\xeaW^R\xac\xe7)\xcf\xab\xe2y;U*\x8a\x0f\xcc\xe4\xc7\x14f\xf3Q7/\x12\xdb\x05\xf5\xa4B\xb77\'\x87\xd1t    -  \x81\x96\x04\xb6Gx\x00\x00\x00\x08d\x82E%H\x02v\x0c\x00H\x9c\x8c\x84IT\x8c\xa5\xe4\xa8\x80mN\x19$\x80\x84\x02@\x10\t   -  d\x00\x00\x00\x00\x00\'$\x00\'#$\x00\'#$\x00\'#$\x01\x02r@\x19b`\x00\x05\xab\xe1;Jmt!\xc1>o\xa91%\x91o\xdb\xda{\xa5J   -  n=\x19z\xd2\xb5Kj\xca\xbd\xbc\xd4+\xc7\xa4\x99d\xa2t\x94\xfa7\xc4k_\x8bKG\x96|Y;gl\xb3\xb1\x1b\xdc\xd44y\xc2\x8e\xa7   -  V\xa5j]<\xc4\xfa\x1b\x0b\xb2[w\xa7k\xb6\xb0\x9d)\xa8I\xae\x92\x973I\xa8\xd5t\xa0\xe9\xcd.}\xe7c\xa3kw\xda=\xd2\xabmR   -  X\xcf%\xc4\xce\x1f/\xa6\xd2\xde\x9b\x7f\xc8o\xbd\x1b\x88UY\x8b\xca\xf5\x97<\xaa5\x9fb\xf7\xcd:\x15)\xd1\xd6\xa6\xa3G   -  \xa6b\xb9\x99\xd3g\xf6\x9a\xcb^\xb7\x8dk\x1a\xaaT\xf1\xde\xce\x16n\x1d\xf1{\x8f\x0c\xf4\xcb\xdc\xf4\xaa\xa6I\xe3,A\x   -  a6\xb9\x15\xa3B\xdb\x89l\xc4\xf8]\xe2\t\xe5\x94\xa2\xa4<\xa5Rx*L\xa3%H\x91    -  \x02R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\   -  x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef"O\x11l\xa1TMe\xf5    -  VNKq\x9e{\xb0O\x11*\xef\xca\xa6\xcbre5*\xa8\xe1`\xeb\xb5\x1d^\xd6\xc6\x12\x95\xcdXS\xc2\xefe\xabY\xbf\xa2m\x10\xe6\x   -  d5\x97\x0cr\xfa\x1eo^\xda\xbd3I\xa5\'qs\x18I.\x8c\xc6\xdb\xc6\xde\xed\xb5\xa5\x1a\x96\x9a\x7f\x9dS\xfb\xc83\x01\xeb\   -  x9bQ{\xabV\x94\xae*\xceQ}\xcc\xea\xf1z^L\x9f\xb5\xa1\xa3\x9f\xe2\xecd\xd2\xc7q\xe9\xb8\xdd?\x1d#\xcb\x04\x   -  e7^m\xb5\x86\xf9\x14%\xc3\x94\xb9d\x85"M\xc8\xc5Z\xfaj\xe4\xc9\xb4\xe0`d\x93$0\xed\x0f\xa1K*l\x86JT\xb2\t\x04J@\x00@   -  \x00\x00\x00$\x00\x00\x02\x01\x018C\x081\xcc%\x08\x9c"\x9c\x95\xacx\x90\x00ex\x8c\x8d\xa7@\xe4:\x81\xb5NC\x91\x12\xf   -  9\x87>\xf1\x1e@\x86K \x99\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x01    -  \x00\x02bTS\x12\xa2\x042;\xc9\x04Jv\xa6Q\xcf6R\xf2\xber\xe0\xc7#\x1c\xe3\x89\xf6E\xa4\x8c!%\xc5)b^\x07}\xb3\xdba\xa9   -  \xe87\x10\x9d\xbdJ\x92\xa7\x1f\x8b\xc5\xc8\xf3\xcda\x86\xfc\xdc\x1a\xf9\xb0V\xf5\xd6\x99\xa9\x92b[=\xbb\xfd\xefP\xbe   -  \x84i\xea2\x85)t\xe6\xcc\xc1\xa6\xea\xb6\xda\x8d\x15V\xd6\xa2\x9c_L\x1a\x05J\xa5J3\x8c\xa9I\xc5\xa3\xdelN\xf1\xf5\x1   -  d\x12\xea1\xa9V\xa5J+\x0b\x87=\x0f=\xcc\xe9\x9a\xfd\xa9\x0e\x86<\xde4\xdc\xf5R_$\xae-\xb3\x19\xec^\xf2\xf4\xedf0\x85   -  z\xd0\xa3Q\xf7J\\\xcc\x87kwJ\xe2\x1a\x8dw\x18\xb3{[p\xf4m>\xad\xb5\x94\xa2\xee$\xb9&l\xe2\xc79   -  &+\rk[\xcb\x9d\xb6\xdb\xce\xd3vuN\x9dI9\xd5|\xa3\xc0\xf3\x86k\x8e\xddo+U\xd7.\xaa*u\xa4\xad\x9b\xe4\x9ay<\x9e\xaf\xa   -  8\xcfR\xbd\x95\xc5\xd5Y\xba\xed\xe5\xc7\x89\xb4q%/(\xf8\x9aG\xa4\xe2t\xce\xcf-\\\x99US\x94\xabA\xd4\xaa\xf3&\xc9e+\x   -  97"N\xfe*vWN}\xed\xdd*pN\x03$\xc8\xa6\xc4T\x88D\xa0\x84\x92S\x92r \x19ISd2E \x02%    -  \x040$\x11\x81\xde\x12\x90\x01(\x00\x00\x02\x00\x03\t\xe0\x02\x16\x88\x1c\x93X!A.r\xe80S<,d\xc394\x98\x85\xc4\xa2\xf   -  a&9"\x98T\x92\xe5\x18\xe7\xf6\x1c\xaa67wo\x14\xe97\x9f\x98\xc5~LS\xdb$Q\xc7!\xac\xf7\x9d\xd5-\x94\xd5\xea,\xc6\xdf+\   -  xf6\x95Oeu(E\xba\x94Z\xc7\xac\xc7\xfc\xda\x7f\xab~\'D\xa3\xc1\xcd\xbc\x95J\xa2}\x0eM[\n\xb6\xef\xf3\x91\x92\xc1\xc3\   -  xad5\xc4\x94\x11\x9f\x1f&\x8aN9O0\\\x82\xab\xc0\xdf\n\xc1h\xda\x9b\xc5\xfd1\xcdt\xa8\x10I\x08\x00\x01\x00\x00\x00\x0   -  0\x01\x01\x84\x13\x01$ud\x93\x04\x80w\x01\x08\x00\x04\x89\x89QLJ\x88\x02\t\x04H\x00\x08\x14\xb4R\xca\xc8eS\n\x19W\x0   -  2\x8cx\xa3\xe90\\\x8d4\x96rR\xd5\x8bx\x96H\xbe\x91m}\xf9%UR\x82\x9ck\xa7\xe9w\x19s`\xb7\xb3}\xa6J\x9d-N\xac\xa7o\xd1   -  \xa8\xe4\xc4.|\xf9\xc5\x15q>\xe3G?\x06\x99#\xcb%s7\x8bfv\x9a\xcf^\xb6\x85{i\xa4\x9a\xce\x1b\xe6zH\xc9I\xf1.\x8c\xd2\   -  x8d\x80\xdb\x8b\x9d\x07Q\x82\xabQ\xaa\x1c\\\xf2\xfb\x8d\xb8\xd9\x1dr\xdf]\xd1h\xdd\xdb\xcf\x8a3\\\x8f-\xcc\xe2\xfe)\   -  xf0\xe8\xe1\xcc\xf4\x89\xa4T\x8e\x1cd\xf3\xe7z^\x076\x9f\xa2\xb2r\xab\xefM\xd8\xb6\xd2\x91Q\x08\x93"\x12\x80@\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\xa3\xf8\   -  t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18   -  \x0c\x8c\x90\x02\x06P\xd1[(l\xc7oi\xfauz\xe5\xcc,\xac\xea\xd7\x9b\xc6"\xcd+\xdeF\xd0\xd6\xd6\xb5\xea\xf9\x93\x84i\xc   -  d\xa5\xcf\xa9\xb3\xbb\xf3\xd5e\xa6l\x8dZ\x94\xb3\xc6\xde9\x1aus\'sq:\xd2y\x94\x9eY\xe8\xfaO\x1e/=\xd2\xe6\xf2-1>\x11   -  \x07\x14\xb9\xc57\xe2C\xc3yK\x01\x12z\xda\xc4G\xa7:o2\x84H\x05\xb6\xa0\x00 2J\xcb \x01<\xc9)\x02\x04\xb1\x92\x07y    -  \t\x0b\xa0\x0c\x11\x86H#B0\xc6\t\x04\xa4\xc3\x18`\x04\x18c\x0c\x00    -  \x98\xa4\xb2\xd9\x1d\xe4\xfajH\xac\xcaajS\xc2\xe2\xee+R\x8b\x86s\xcc\xa3\x19\xa4\xa0\xd6p\xce\xcfJ\xd2\xaakW\xf4m\xa   -  c\xa2\xd4\xa5\xc9\xb4\x8cW\xc9\x14\x8d\xcb5+\xb7\x1e\xda\xd6\xa5\xd4\xe3\x0bh\xba\x95\x1fr26\xc9n\xa7P\xd5\xf8*^S\xa   -  9F\x1dy\xa3.n\xe3u\xd6ZM\xad\x1b\x9b\xfaP\xabZI<\xe3\x9a2\xbd\xbc)[\xc1B\x95Q0\xfek\xaf8\xa2   -  =W\x7f\x81\x9b\xf7\x01\xb4\xb5hj2\xd3\xebM\xba1\x8f\x9b\x96a\x1f\x8a\xdb\xee=\x0e\xc1\xeas\   -  xd3\xf5\xcbi\xc1\xb4\xe75\x16ry\xfch\xb5&[Xg\xcbyh\xf9\xd0\x8c\xfcN]>\x87]\xa2\xcdV\xd3\xa8O9\xcc\x13\xff\x00C\xb0H\   -  xf1\x13^\xdb\xcb\xab\x8f\xd2\xe1=J\x17R\xa4Y\x99$\x90H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    -  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x06\x04\x00\x02\x14\xc   -  8\xb7.E\xd6[\x911\t\xfaa\xde\xd0\xf2\xe1\xd9*\x8d\xf8\x9a\x9dO\xcd\xe2\xf9\xcd\xb1\xed\x17\x1c\xec\x85Oh\xd5\'\x1eH\   -  xf5\x9d\x1a?G\'\x93\xed\x08\x92\x11\'\xa1s\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xde\x07x\x12\x00\x00\x00\x00\x00\x00\   -  x03    -  \t\x0c\x82{\x80\x80\xb9>@\xa6S\x8cZM\xf5)x\xff\x00\x13\x11\xb9SVn\x1e\x8f\x7f#g#\xaa\xe4\xed\xc7\xa8oa\xa3:\xd2q\x8d5\x95\xe6\xf   -  7"\xec\x13\xeb\xf1J\xe9\xd3\xc2\xe6K\x8f\x81\xe3\xad\xe5\xd4\xc7\x8e\x10\xa2\xb3\x92\xe4y\x14\xa4\xc9\xc3K,\xc7\xdb\   -  x10\xcf\xa8\x85dL\x88\xce$\xe52{UP\xf0\xc8\xc7"\xbe\x1c\xf4!\xc4\xa5\xad\xda\x8f\x0e\x9fht{mcO\xabmu\x0e(N8f\xb5m\xe   -  6\xe8\xabi\xf5jW\xd1i\xa5K9\xc3\xe6\xcd\xab\xc1b\xad\xb5:\x99\xe3\x84d\xbeu\x93w\x85\xce\xb6?Ml\xf8{\xfd4\n\xff\x00I   -  \xba\xb4\xb8t\xee-\xeb:\xab\xbdA\xe0\xb7\x1byF\x0f\x8e\x95O\xddf\xf4\xea{1\xa6\xdf\xc1\xc6\xa5\xa5\x14\xdf\xc6T\xd6O   -  /[u:5Y\xc9\xbc\xac\xf8D\xecS\xabx\xf2\xd4\x9c\x1et\xd3\x97C\xc2\x9dO\xddd\xd3\xb5\xad9b\x9d\x1a\x8f\xff\x00\x16n\n\x   -  dd\x06\x89\xf2\xa5\xfb\xbf\xf2v:~\xec\xb4k)\'\x18\xa9c\xc6%g\xaa\xaf\xfcYj\x05\xa6\xcf\xeaW\r([\xd5\xe7\xff\x00c;J;\   -  x0b\xacW~m&\xbdqf\xeaYhZ}\xb4\x14aiA\xe3\xbd\xd3G*Z]\x9c\x97+zK\xd5\x04a\x9e\xadm\x9f\xc5\x96\x95\xcfw:\xd4)q8/\xb0\   -  xe9/\xf6SU\xb3NS\xa36\x97\x84\x19\xbd\xbf\xc9\xb6\xc9c\xc8\xd3k\xe7\x8a,\xdch\xd65\xe9\xb8N\xd6\x8e\x1f\xff\x00\xad\   -  x11\xff\x00Zw\xe5Y\xe2\xd9\xa11\x84\xa8>\x1b\x8as\x8b\xf9\xe2\xd1fm96\xba\x1b\x85\xaf\xee\x8fE\xd5\xa7*\x93\x94\xa9\   -  xb7\xdd\x08\xe3\xff\x00\xf4\xc0[w\xbb=CB\xb8\xafV\xde\x8c\xa5g\x16\xda\x94\xb3\xd0\xeb\xf0\xba\x96<\x93\xad\xb0_\x04   -  \xd7\xdb\x1c\xa2s\x82\x1ajmx\x15c=N\xdcZ/\xe6\x1a\xd7\x8d#    -  \x9c\x13\x82\xd1\n\xa0\x13\x82\x1a-\x10i(\x04\x80\xd0\x00\x08\xdc\xc2\x0e\xe2\x19$H\x8e\xe9\x10A$`\xb4X\x11$"H\x94!\   -  x82C!*N\xcbg\x17\xfdb\xd3\xe9#\xf7\x9dn\x0e\xc7g\xbd\xd9\xb4\xfaX\xfd\xe6\x0edG\xe3g\xc3>[\xcf\xb2\x9e\xe3\xdb\xfb\x   -  0b\xee;\x94t\xbb+\xeeM\xba\xff\x00\xb1}\xc7w\x86|\xfb<\x7f\xe4\x99v1\xfaLz\x95"\x12\xc1(\xc4\xcc\x92H$\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\xa3\xf8\t\xdao\   -  xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x03\x02\x0   -  0\x01\x08}\n\x1a.2\x86L\'\xe9\x87{E\xbcl\x8dOh\xd5\x07,\xa3k;F\xfb\xd2\xa9\xed\x1a\xa0\xba\x1e\xb7\xa3|\x1c\x9eO\xb5   -  H\x92\x17RN\xfe\xdc\xf0\x00\x00\x00H\x00\x00\x00\x00\x0e\xf0;\xc0\x90\x08`H\x18\x03@\x06F@\x0c\x00\xc8\xd8\x82y\x90\   -  nM\xc1\x919E\xf0\xb7\x15\xe6\xf3$\xe7\xd8\xe97Z\x85ZT\xedhT\xa9\xc6\xf0\xdcVpV\xdc\xaab\x8d\xd9\x97\x1cyN\x8bm=_S\xa   -  7J\xd6\x8f\x1c\xa4\xd2j>\x06\xe0n\xb3e\xe9\xec\xbe\x85\x18\xac9\xd4JMc\xa1\xe2\xf7I\xbb\xaa\x1aLi\xdd\\\xd1^]\xae\xa   -  d\x19\x92\x9a\xc4U/\xb0\xf2]K\x99\xf9\xed\xaa\xfat\xf0\xc6\x9c\xd8IJ)\xf4%\xb4\x8e,\xe9UIp\xcd$\x8e\x16\xa7\xabZ\xe9   -  \xb6\xfcw5`\x9a\xf1\x96\x0e-)kKfrv\xbbg\xd3=\x0b\x15.iQM\xd5\xaa\x92^&\x1f\xda\xfd\xf1\xd9Xq\xd1\xb5\x8c\xa7>\x89\xc   -  1\xe4\xc3\xbbE\xbc\xedr\xed\xcf\xc8^\xca\x11\x97D\xfb\x8e\x86.\x9d{\xfbb\xb7#M\xaa\xd46\xafG\xb3\xfd=\xe5*~\xb6us\xd   -  e\x1e\xceC)\xea\x96\xf9]\xd94\xd2\xf3_\xd4\xef\x9bw\xb7\x0e\xa9\xc0s\x84\xa5\xc5(>/\x13\xa1\x8f\xa4Z}\xb0\xdb\x96\xd   -  d\x15\xbc\xfd\t\x7f\xf7(\xfd\xa7.\xc7x\xda\r\xd4\xf8]\xfd\x04\xdfvM%\xeb\xd3\x90\x84\xea\xd1\x9a\x95)bK\xbc\xc9~\x8d   -  \x1ab\x9ed\xb7\xf6\xcfW\xb1\xbd\x8av\xf5\xe1<\xf8\x1c\xde\\9\xcf#Ft]\xbb\xd7t\xba\xb4\xfc\x9d\xdc\x958\xbei\x19\xe3w   -  \xbb\xd7\xa7\xa8:t/\xe4\xddG\xcb\xceg77M\xb6/5la\xe4w\xb3dd\xa5\xd1\xe4\xa8\xe3Z\xd4\xa7V\x94gK\x1c2Y9\x08\xe6\xda\x   -  b3\x12\xd9\x8a\xef\xca\xa4N\x08Ei\x06X\x8d&+\x91(\x95\xd0r+"\x99.e%M\x94\xe0\xc7h\x99\x14\xb3\xa4\xd5\xb4\xdaZ\xbd\x   -  bdZ\x17\x14\xa2\xa2\xd62\xce\xf1\xa2\xdd\\p\xbf\x136\t\xb5\x1a\xb9a\xa6\x9b\xd7\xd9\xc5\xa1\xeb\x95\xa3J\tQ\xe2\xe4\   -  xd7C\xc1\x19\xcf\xb45j\x12\x9a\xa7\x1cyU>|\xcc\x18\x8fy\xd3/7\xc3\x13.F_gp\x083~gJD!\xbc!\x19\'\xd1\x89`\x9a6W\x15\x   -  a5\x8bzso\xe6F)\xcd\xa5\xe2\xa3Mu!\xc9.\xac\xe7\xd3\xd0\xf5Yc6\xb5\xe5\x9f\x083\x99Ke\xb5J\x91\xcf\xe4W\x1f\xb8\xcd{   -  \xf3\xebY\xd4\xca\xdf\x8d\xd1\xf1\xc7\xc4\xa9sGkq\xb2\xfa\xa5/\xfe\x95\xc7\xee3\x85SI\xd4\xa8\xa6\xe7i]%\xde\xe0\xcb   -  c\xe7R\xf3\xa5f\x9aq\xfa\x11\xd4\x89)\xc1\xb58I?\x9d\x04\xcd\x8f\xcdU41\x94\x19\x06H\x98\x9fJ\xa7    -  \x84H\x94\x00\x00!\x9d\x86\xcf\xfb\xb5g\xf4\xb1\xfb\xce\xbc\xec6{\xdd\xab?\xa5\x8f\xdek\xf3?\xad\x9f\x07\xb6\xf3\xec   -  \xc7\xb9\x96\xde\xc2\xfb\x8e\xed\x1d&\xcc{\x99m\xecG\xee;\xd4|\xff\x007\xce]\xac~\x80\x89\xc012\x84\x84\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\   -  x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  `0    -  \x00\x10\x87\xd0\xa5\xf4*}\x0bl\x98O\xd3\x0e\xf6\x8c\xf7\xa5S\xda5C\xb8\xdb\x0e\xd1k\xfb#S\xda5C\x1c\x8fY\xd1\xbe\x0   -  eO\'\xd8\x10\x08\xef\xc3\x9e\x90\x01    -  \x00$\x00\x00\x00\x00\x07x\x1d\xe0H`0%4\xba\xf4"i\xc99C\xd1]CI\xfaO\x08:\x9eE.\x1eqeo~\xd4\xc4nV<\xae_.\x85m\xcaX\xe   -  0\xe6s\xf4M\x16\xef[\xbf\x8d\x1bZNI\xbe\xe3:\xec~\xe4\xe9\xbaT\xee/\xe5R59>\x1e\xe3\x99\xc8\xea\x15\xc5\xf6\xd9\xa6\   -  x1e\xefM~\xa7\n\xce/4j7\xdd\x88\xb3\x91o\xa6_\xdc\xbf\xcdP\xa9\xfb`\xcd\xcd\xd2w\x7f\xa5YS\x8av\xf4\xa6\xd2\xf8\xd0G   -  yGf\xb4\xca},\xad\xd7\xfe\x08\xe7[\xadk\xd3   -  \xd0\x89\xbcs\xefE\xfd&\xe6v\xda\x85\x1a\xf0\x93RRY\xc3,Ie\x14P\x92\x8d\\M\xe1w\x1a\xbc\x9c1j\xf8\x86\xce\x0bv\xb7Sv   -  z\xc4\xb5]\x02\x94\x94\xb3$\x92=\xbcs$\xb0\xfdf\xac\xeeko\xe9\xe8\x97\x10\xb1\xbe\xa8\xa1m\'\x9e6\xcd\x94\xd2\xb5;}Z   -  \x9ckZTR\xa7\x8c\xe5\x1e\x1f\x9d\x82\xd5\xbc\xba\xd8\xb2\xf8v\xc8\xb9\x06[\x89W\x12]\xe7?\xcb7\xe4]!\xf4(RD:\x89ub"v   -  w\xc2d\xcbnO\xb8JI\xf48\xd7\x93\x8c)fR\xe1H\xc9\xd9\xbf\x08\x9c\x90\xb9:\xd2Q\xcfr<\xee\xd2m\x15\x1d\x1a\xc6\xad\xc5   -  \xd5D\xb8Vb\xb2u[W\xbc\x1d\'D\xb7\x9cgq\x1f,\x97(\xbe\xf3Y7\x83\xb7\xf7{A{,I\xc6\x8c_\x9a\xa2\xf94t8]>\xf9\'\xcbS6G\   -  x13x;A=\xa2\xda\x0b\x8b\x8ar\xcd&\xf9d\xf2\xae\\\x1dJ\xb8<\xb4|\xaep\xdfTS\tc\x92\\O\xe7=\x7f\x1f\x1cq1\xea\\\xdbGt\   -  x94\xdb\x94\xb8>3\xe8w{9\xb3z\x86\xb7s*6\xf4\x9eS\xc6Zx=N\xeb\xb6\x02\xe3ikyk\xa8J\x9d\x08\xcb\x9c\x91\xb4\x1b3\xb26   -  \x1a=\xa5*tiA\xb8\xafM\xc7\x9b9\x1c\xce\xaf\x15\x9dU\xb3\x8f\x0e\xd8[dw)V\xb7\rM^\x0b\xc9\xfc\xcc\xc9\xdaN\xeb4\x1d?   -  \x85\xd2\xa5.%\xe2d\'\x04\xa0\xa3\x15\x84\xbc\x02\\\x8e&N\xa1\x96\xf3\xf2\xd3n0\xc4:Km\x9b\xd3\xe8$\xa3F<\xbcb\x8e\x   -  c6\x8e\x9bk\x05\x85F\x9f\xee\xa3\x96\x93\xc9Z\\\xcd[f\xb5\xbd\xca\xd1\x8a\x1c\x1a\xbaM\xa5X\xf9\xd4i\xfe\xea:\x8dGd\   -  xec.\xe9\xca\x9c\xa8G\x85\xf5\xc4Q\xea;\x8a$\x85s^\xbebSl5\x98\xf4\xc4\xba\xb6\xe6\xb4;\xaau%N\x94\x95g\xd3\x9f#\x10   -  m\xa6\xe9u=-\xca\xa5\x9d4\xe8\xae~<\x8d\xb7\x92}\xc7\x1e\xb5\nu\xa2\xe1^\x9ce\x17\xe2\xb2l\xd3\x9b\x92\xbe\xe5\x8f\x   -  f8\xf5\xff\x00\x1a\x03\x7fesg6\xaa\xc2Q\xc3\xc74qr\xd3J]Y\xb6\x1b\xcd\xdd\xd5\rJ\x85[\x8bJ*2I\xbcE`\xd5\xddkN\xaf\xa   -  6\xea3\xa1u\x0e\t&\xd2G\xa5\xe0\xf3c$G\x97?.)\xac\xfaqP%$0wfbk\xb8`0C$3\x19\xa5\'a\xb3\xde\xedY\xfd,~\xf3\xafga\xb3\   -  xde\xedY\xfd,~\xf3\x073\xfa\xd9\xb0\xfbo>\xcc{\x99m\xec/\xb8\xefbt;1\xeee\xbf\xb0\xbe\xe3\xbe\x89\xf3\xec\xdf9v1zH\x   -  00\xc4\xcc\x94\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;   -  M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x000\x18\x10\x00\x08C\xe8[e\xc6Q!\x1e\xc9\x9f\x0c;\xda/\xde\x8dOh\xd5\x05\xd0\xda\xfe\xd1~\xf4*{F\xa8.\   -  x87\xac\xe8\xdf\x07#\x93>@\x81\'\xa0\x86\x88\x00$\x00\x04\x80\x00\x00\x00\x00\xef\x03\xbc\t\x0c\x00!\xf9\xdc\x8b\x96   -  \xb6\xf2\xbc\xb8\x85\xbc3\xc4\xde\x16\x0e<\x9c\xbc\xaa\x8c\x1e$zm\xdf\xd2\xa7[j\xac!%\x97\xe5\x17\x11\xcf\xe6\xe4\xe   -  d\xac\xcbc\x156\xd8\xcd\xcdle\xb6\x99\xa2\xd1\xba\xba\xa3\x19Wk\xe3.fX\xb6\x97\x1c=\x0e\x04\xb9`\xe3iV\xf4\xe9\xda\x   -  d3\x84#\x88\xa4\x8e\xcb\x87\x1d\x0f\x0f\xc8\xcd7\xbc\xed\xd9\xc3\x8e+\n\tL\xab\x84`\xc1\xe5\x9f\xf5R\xf9\x04N\x06\x0   -  6\x94\x98\x80\x87\xcc\xa8\x8c\x16\xf0F\x90\xde\x11\xe1\xf7\xa3\x7f[O\xd9\xbb\x8a\xf4\xf3\xc9w\x1e\xe5\xc7\'\x8c\xde\   -  xa5\x95]Cf.-\xa8\xf3mt\xc1zO\x98b\xc8\xd2\xddZ\xb4\xae\xb5*\xf5\xe7\xceS\x96K*/\x07#\\\xb3\xafc\xaaN\x9c\xe1$\xa3,>E   -  \x89\xcf\x97#\xdbpiX\xa499be\x1d\x01C\x99\x1c|\xba3\xa7Jy\xdc\xb5\xbb%Y%\x11\xa9\x97\xd1\xa2\xac\x97\x9dA\xdb#\x00\x   -  14\x9b\xc4#R\x896\xba,\x92\xaaAG\xce\xa6\x9c\x82\xcey<\x13(\xe3\x9b\xe7\xea+7\x89\x8d-\x111\xe4\xa3\tK\xf3\xaa\\\rtG   -  \xb5\xd9\r\xe2\xea;;QE\xd4\xa9^\x9a~\x8eO\x12\xeag\xa2\xc1o\x81g\'7?\x162\xb3W7ket\x1d\xf7R\xad\x8f\xcam\xd4=o\xfeOk   -  g\xbd\r\x1a\xe6\x92\x95K\x9a\x14\xdb\xeel\xd3g\xcd\x11\x84h\xcfG\xac\xf9f\x8eCt\xe3\xbc=\t>\'\xa9\xdb\xbf\x9b,\xe0\x   -  df\xefKG\xa5\x9f\'^\x8c\xfdL\xd3w\x08\xf5h\xaa).\x82:\x1c\xcd\xac]2\x94\xfaD\xf2\\\xdb\xdb\xeb\xcdZR\xa9wu7\'\xd1H\xe2   -  \xd3\xa8\xa3\xe6T\xa3\x9c|g\xdeB\x8f\x9c\x9f\x81rM\xcb\xa9\xbfN?g\xc5\xaf|\xdbZ\x93\x92\x9ec\xca\x1e\x07q\xb2\xda\x1   -  c\xb5\xedb\x8d*5x^SqK\xa9\xd5\xf9HRX\x9a\xca|\x8c\x83\xb8\xbat\xe9m\xbd:\x95q\xe4\xdc{\xcc<\xfb\xcdqN\xd9\xb0F\xfc\x   -  b6\x87d\xb4:\x1a~\x93kJ\xde\x9a\xa4\xd4\x12\x9e;\xd9\xe9a\x17\x0eM\xe7\x05\xabg\x1f\'\x19C\xa69\x17\xe3\x96\xf9\x9e\   -  x1e\xfa\x9byuqR!R\xe6JA"LV\x88e\xd4%"\xa4\x8aQRe"UOB\x19QK/\x12\x98Q(\xe7\xbf\x05\x18q\xe7\xe9\x17Z(\xc6\r|\xb6\x98\   -  xf4\xbf\x85\x9a\xb0W\x14\xdc%\x1c&\x8dh\xdf\xfe\xca\xabk\xef\xcbhS\xf3\x12\xcbi\x1b1Zj\x0f+\x9b0\xfe\xff\x00u\n\x14\   -  xf4*\xb6\xf3k\xca\xcdrY:\x9d2\xf6\xef\x86\xb7#\x1cv\xed\xab\x08\x94\x01\xefqO\xe8\xe1_\xc5\x92C\x19)e\xd1\xb43\xb0\x   -  d9\xdfv\xac\xfe\x96?y\xd7\x9d\x86\xcf{\xb5g\xf4\xb1\xfb\xcc\x1c\xcf\xeblb\xf6\xdem\x99\xf72\xdb\xd8\x8f\xdcw\xd1\xe8   -  t;1\xeee\xb7\xb0\xbe\xe3\xbe\x89\xf3\xfc\xff\x009u\xf0\xfaH\x00\xc2\xcc\x94\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x18\x10\x00\x08D\xba\x14H\xae]\n\x18\   -  xfbV\xde\x98w\xb4_\xbd\n\x9e\xd1\xaa\x1d\xc6\xd7\xf6\x8b\xf7\xa3S\xda5A\x1e\xaf\xa3|\\~G\xb1\x12\x01\xe8\xb4\xd4\x00   -  \x00\x00\x04\x80\x00\x00\x00\x00\xef\x00\t\x04dd\x08\x8c%\xe5\x95E\xd1\x1e\x83w\x95\xe1Gl\xac\\\xf3\xe7UG\x9f\x9c\xf   -  c\xc7\x15\xd5\x9e\xbbv\x9az\xbc\xda;\x19%\x99S\xa8\xb2rz\x84\xc7l\xb78\xfe\xdb\xa5\xa6\xd4R\xa1NK\xa3H\xec\xd7DuV\xb   -  0t\xad)/\x99\x1d\x959\xe5#\xc3d\x98\xfc\x8e\xddc\xf5V\xcaJ\xdb!\x92\x89P\xc1,\x05%\x18 \xab    -  +\xb5%\x9a\xd4#Y8\xcd&\x9f\x89\xc8    -  \x88\x9d\x13\x1ba\r\xe5\xee\xb5\xea.\xad\xc6\x99I:\x92\xcby5\xff\x00^\xd8\xfd[G\xa9(\xdcQ|\xbc\x13f\xf6\xb4\xa5\xc9\   -  xa3\xaa\xd4\xb4{\x1b\xa5\xf9\xdbZSo\xabq:\x98:\x95\xe9\x1d\xb2\xc1l[hD(\xd6s\xe1\xf2s\xca\xf1\x8b*\xc5X\xbcy9}\x86\x   -  ea\xea;\xbf\xd2n\x17\x15;jPo\xc2\'V\xf7]\xa5\xbe|\x10\xcf\xb2t+\xd5\xa5\x8ap\xb4\xf9F\xac\x9e\x159~\xe9\xcf\xb5\xd1\   -  xef.Z\xf2te\xcf\xe6f\xdb\xda\xee\xdfK\xb7\x9e|\x8d9z\xe2z\x1b\x1d\x98\xd3\xad\xe9\xe26T\x1f\xcf\xc2V\xddV~\x91\x186\   -  xd4+}\x83\xd6\xab\xa5\xc1G\xa9z\xb6\xee\xf5\xda0\xe2\x9d\x15\x83p\xa8h\xd6\x94\x9e|\x94\x17\xec9\x8e\xca\xcd\xc7\x0e   -  \x8d9z\xd1\x82\xddZ\xcc\xd1\xc5\x86\x89\xdfh7\xd6\x92j\xb5\x19\xf2\xf0\x8b:\xe5\tS\x9f\x0f\x0c\x93\xf9\xd1\xbew:\x06   -  \x9bq\t)XPy\xef\xe0<\x1e\xd4n\x9bJ\xd5\xa17I\xaa\x15z\xa5\x08\xe0\xcd\x83\xab\x7f\xf4\xad\xb8\xda\x86\xa5\\R\xa9N\xac\x94{\xac7\x8b\xd5\xc9\x9fi*\xc1J+#H\x94\x12\x18A\x12\x0c\x82\x19(2%\xcd   -  s\x081\xaf+B\x9cbI\xf7\xa3\xbb\xd0u\xcb\xfd2\xa3\x95\xa5\xd4\xa8\xae\xf4\xbb\xce\x95\xa2\x1a}\xc6,\xb8\xa3$jYk\x92a\   -  x99\xf6c|\xd5\xb4\xf7\x1aWt\xe7Y\xae\xb2l\xc9\x9a&\xf8\xb4\xeb\xb7\x15Z0\xa5\x9e\xf93R\x1d\x19qg(\xe4\xc5A%\xc5\x9f\   -  xd8\xce\x1f#\xa6V\xde\x99\xa3<\xb7\x82\xcfot:\xf0M\xdf\xdb\xc5\xf89\x1c\xd5\xb5\xda\x1b\x8eV\xa7o\xfb\xc6\x8a:\xb1\x   -  82\xfc\xdf\x12d;\xdb\x95\xca5\x1e=f\x9f\xfcy\x9fL\x91\xc8\x96\xf0\\\xed\xde\x85E<\xea6\xef\xff\x00#\xcc\xeb{\xdd\xd2   -  \xac\x1bt\'N\xba_&F\x9f\xd4\x94\xea\xaf>M\xfe\xd2\xca\xa3%/5\xf9\xbe\xb3%:<}\x93\x9d\x9ev\x9f~\x95o8\xe8\xd9\xdbT\xa   -  3\xdd\xc4\x9f\xfc\x98\xc7_\xda\xbdGYN5\xee\xe6\xe0\xfb\x9b<\xd2XXqe^J/\xb8\xeb\xf1zu1\xc7\xa6\t\xcfi\xfbS\x18F\x1d\x   -  1a*\x8c\x9cSQ|\x88\xe0K\xa07?\x15k>!\x8am\xb3\x1c\xf3\xdeU\x9c\xf5    -  w\x19!IJ\xc1\x0c~\xc0\xcbB\x03\xb0\xd9\xefv\xac\xfe\x96?y\xd7\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb\xcd~g\xf5\xcbc\x0by\xb6c   -  \xdc\xcboa}\xc7}\x13\xa1\xd9\x8fs-\xbd\x85\xf7\x1d\xf4O\x9f\xe7\xf9\xcb\xaf\x87\xd2@\x06\x16d\xa0\x10\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\   -  x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00    -  \x00\x10\x87\xdeS"\xa6R\xc6\xfc\x93\xe9\x87{E{\xd1\xa9\xed\x1a\xa3\xdcm\x7fh\xafz5=\xa3T\x17C\xd6ti\xfd\\~Dy\x10\x00   -  \xf4-    -  \x02:\xb0$dr#\x8b\x02$NFDc\xe5;\xf0[\xa9\xf9\xa9\xa8\xc5\xf17\xdca\xcb\x9e1\xadZ\xcd\x95\xe4\x1d\xc6\x99\xb3\x1a\xbe   -  \xb0\xa1\xf9\r\x9c\xea.\xfc\x19\x1bf\xf73}\xa8(\xca\xf7\xca\xd0\xf9\xb0sr\xf3\xeb\x1ev\xd8\xaf\x1ae\x88Ro\xa2l\xbbom   -  V\xb5h\xc6\x9c$\xe6\xfa,r6gF\xdc\x9d\x9d\x94\xa3*\xd5\xddLwI\x1e\xfbE\xd8\x8d\x1bO\x8f;J\x15%\xdc\xdcN~~\xa9\xfa\xfe   -  \xac\xb5\xe2\xccN\xda\xd5\xb3;\xad\xd56\x81\xd2\x9d\xd5\x07\n-\xe71m\x19\xfba\xf7a\xa7\xec\xf5(5\x0e9\xa5\x9f=d\xf7\   -  xb6\xd6t-\xe2\x95\nQ\x82]\xc9\x1c\xa8\xe5.\xa7#/2\xf7\xfbn\xe3\xa4C\x8bF\x94i\xc7\x821Q\x8a\xf0X.\xa8\xe7\x94\xbd\x1   -  e\xe6V\xd2\xc9\xc7\xbf\xb9\x85\xa5\xb4\xea\xd4iF+&\xa5m7\xb6\x99\xed\xa8\x85\x9dJ\xfe\xdfM\xb4\xa9V\xac\xf0\xa1\x17\   -  '\x93\\\xb7\x87\xbd\xaa\xba\x8dj\xb6zt\xe3\xf9*n.K\x93\xc9\xc5\xdf&\xf0*\xea\xb7\x95t\xcb\n\xae\x9ci\xber\x83\xea\x8   -  c2\xa5\x96\xf9\xe5\xe7\x99\xe8\xb8\x1d7z\xbd\xdc\xec\xd7\x98\xf4\xe6j\x17\x95.\xa79:\xf5g9<\xe2Rl\xe0\xc2U\xa9\xfaqE   -  is\xcfyS\xe7\xd4\xefS\x8dJ\xfd5\'$\xa3\xcbN]b\xb1\xf3\x10\xe9\xd2|\xe4\xdeI\xc7\x81\x0e&~\xd8\x88\xf0\xa4\xdeTz<\xa9   -  \xf3\xf5\x97a\x18\xd4Xy\xe2]\xc5)a\x93\x1eO+\xa9Y\x89Gr*Fu\x17\x92K\x92/Y\xb8\xdbT\x8b\x95I\xd3i\xe70x(\xcb\xce{\xc8   -  \x92\xcf^f\x0c\xb8"\xd1;g\xc7\x93M\xaf\xdcf\xd5S\xd6\xb4\xb7m\x1a\x8en\x82Qm\xf52\xef\xc4F\xa9v|\xd5!a\xa8\xd5\xa1)(   -  \xca\xb4\xb0\x97\x89\xb54\x9bt\xa3\x9e\xa7\x89\xe4\xe3\xec\xbc\xbaX\xaf\xb8W\x12\xb4Q\x12\xa3Z[\x11\xe1^y\x04B\xf9\x   -  c9+&\xd2Gx\x05$D\xb9\xa6Y\x97\x9c\x92]Qu\x96\xe4\xb9\xe4\xaf~\xbc\'~\x14\xd4\x8ec\x95\xd4\xc3\x1b\xfc\xd5i\xd9\xe9r\   -  xb5\x93\\Uc\xc8\xca\xfa\xde\xa3GL\xb0\xa9qqQB\x11]Y\xa7\xfb\xe0\xdb\x19\xed\x16\xb4\xa0\xb9S\xa4\xdcSO\xaa;\x1d7\r\x   -  b2\xda%\xa5\x9e\xde\x1e\x03\xabeH\x84I\xec\xf8\xf8\xad\x8a<\xb9R\x15\x10\x91&\xce\x95\x999\x92B$\x84\x042@\x11\xe0K\   -  xeaAV\x02\xcaB*\xc2\t\x11$\x98]\xe4a.q\'\x19\x18\xe6SJ\xa8r\x93\xea\x81[)h\xb4j\x16\xdc\xa9\xc1TV9\xae\xa0\x94\xb0D\   -  xca&W<\xadlp\xf0\xc7\x87\xc7\x05=:\x92\x99\x12\x1f\xb1\xedK    -  \x96A:\x90\x1f\xb4\x02}\x00$\x86;\x90\x1d\x86\xcf{\xb5g\xf4\xb1\xfb\xce\xbf\xbc\xec6{\xdd\xab?\xa5\x8f\xde`\xe6\x7f[   -  g\x0by\xb6c\xdc\xcboa}\xc7}\x13\xa1\xd9\x8fs-\xbd\x85\xf7\x1d\xf4O\x9f\xe7\xf9\xcb\xaf\x87\xd2@\x06\x16d\xa0\x10\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa   -  8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00    -  \x00\x10\x89\x14\xb2\xa6R\xc7\xdag\xd3\x0fv\x8b\xf7\xa3S\xda5At6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa\x0b\xa1\xea\xfa7\xc5\x   -  c8\xe4\xfb\x00@\xf4M\x042H\x05fD\x94\xceJ\x0b-d\x9c\x9d\xe6\xcal\xc5\xee\xd2_\xc6\x85\xa4\x1e3\x96\xda\xe5\x83_>X\xa   -  5&v\xc9\x8e\xbd\xd6\xd3\x87\xa2i\x17Z\xc5eN\xd2\x12\xcb\xe5\xc9\x19\xbfw\xbb\x97\xe0\x94.u\x8a\xb0\xac\xa5\xe7(It2\x   -  16\xed\xf7{\xa7\xe8\x16\x90\xabZ\x8f\xf5\x85\xd5\x99\x066\xe9\xb5\xe4\x96\x12<\xa7+\xa8M\xa6b\x1dl\\h\x87O\xa4l\xa5\   -  x96\x90\x97\xe4T\xe3M|\xc7\xa0\xa5\x05\x08a!\t\xe7\xcc}Qq,\x1ck\xf2-y\xf2\xda\xfcq\n\x14y\xf9\xdc\xc9p\x8fr*$\xbcL\x   -  a3\xb5m"\xa4\xb9\x15p\x8c\x04kN=\xc5GN\x98v\x80O\xed\x01Y\x95=\xe4\xa1\xde0\x08H`\x89<\x111\xb8\   -  xd2\xf1.\xefb\xf5\x85\xa3m%\x9d\xd5^P\x84\xf2\xd3\xef7?e\xb6\x92\xd7\\\xd3i\\P\x94s%\xe8\xa6h}u\xe5\xda\xe2\xf8\xbd\   -  x0c\x83\xbb\x8d\xe0\\\xec\xe5x\xd2\x9dG\xf9\x19d\xd6\xfd\xc3\xedE*UU\xa5\xc4\xf8q\   -  x85\x1c\xbc\x1b#J\xacjSR\x8bM5\xdcx\x9e\xa3[~I\x97W\x0c\xc4\xc2\xe1Re9\'\'9\xb5\x1a\x1b\x19\x00\xb6\x93\xe0\x19\x0c\   -  xa1\x89\x84\xf8V\x999-\xe4\xa9>EM\xc2*\xf4\xcfy\xd6\xea4iW\xa5\xe4\xae)\xf9HO\x93Gc.da\x13[LJ\xb6\x88\x96\x16\xdb\xa   -  d\xd1Zj\xb2\x95{\np\xa37\xcf\xa1\x876\x8bu\xfa\xa6\x9fRT\x94%W\xe7\x8cM\xccqMsE\xa9[R\x9b\xf3\xa1\x16\xfett0\xf3\xef   -  \x89\xad|\x11-\x0c\x9e\xc9\xeb4$\xe3\xf9\r\xc3K\xc2\x0c\xb6\xf6sW\xff\x00.\xb9\xfd\xc6o\x9c\xacm\xfb\xe8\xd3\xfd\xd4   -  [\xfc\x82\xdb\xfb\x9a\x7f\xba\x8d\x9f\xfa\xf7b\xfe44\x97I\xd8=kPq\xcd\xbdZi\xfc\xa8\x1e\xca\xcbq\xba\xa5\xcd%7^1o\xb   -  9\xa3k\xe8\xdaP\x87\xa3J\x0b\xff\x00\x14_T\xe2\xba%\xf6\x18\xe7\xaa\xe4^8\x90\xd5\x1f\xe8\x17U\xff\x00\x17O\xec8z\x8   -  6\xe5\xf5K*N^YT\xc7tQ\xb7N\x11\xf0E\xb9\xd1\x83\xeb\x14\xff\x00`\xafV\xbcO\x95g\x8b\x10\xd1M_d\xb5-;\xa3\x06\xc7s\x0e\xd1\xfbA)\x12;\xb6\x9d\xa9\xc0eDr\x1a\x996\xa5\x82\xa7\x82\x9c\x13\xa0\xef$\x80I\xa4\x80\x   -  02\x02\t\x01(\x04\x80l\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x042Hb\x04\x1d\x8e\xc   -  f{\xb5g\xf4\xb1\xfb\xce\xb8\xecv{\xdd\xab?\xa5\x8f\xdek\xf3\x7f\xae[8[\xcd\xb3>\xe5\xdb{\x0b\xee;\xe8\x9d\x0e\xcc\xf   -  b\x97m\xec/\xb8\xef\xa2|\xf7\x91?\xbc\xba\xf8\xbd$\x00`\xdb2P\x08\x12\x00\x02@\x00\x00\x00H\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x04"]\n\x19[\xe8P\xc4{V\xde   -  \x98{\xb4W\xbd\n\x9e\xd1\xaaK\xa26\xb7\xb4W\xbd\n\x9e\xd1\xaaK\xa1\xea\xfa7\xc5\xc7\xe4{I\x03#\'\xa2j)\x96q\xe6\xac\   -  xb2\xba\x91T\xe7MK\x92\x97R\x14\xb8I\x9e+4\xe4\xf1\x82\x93^\xe9LN\xa5\xca\xb4\xd5+i\x97\x94k[I\xae\x19g\x93\xc6M\x83   -  \xdd\xf6\xf7hy8Q\xd5\xaa\xc2\x9aK\xaeMp\xa9\x15\xe6\xac\xe4\xa5\xd4\x95\x1a\xbcPm\xa3\x97\xcd\xe0FF\xc6<\xb3\r\xe6\x   -  d2v\xd3L\xd4\x92\xfc\x9e\xba\x96N\xe3\xf9R\x9aYrX4N\xdf_\xd4m\x9av\xf7Ui\xfc\xc9\x9c\xaf\xe7^\xbd\x9c\xff\x00*\xdc5\   -  xe1\x94r\xbf\xe4L\xb3\x7f&[\xbf=r\xd2\x11nU\x12\xc1\xd0\xea{\xc3\xd1l\x1bU\xae\xa3\x1cz\x8d@{U\xac\xcdbZ\x85o\xb5\x1   -  d}\xd6\xa9w]\xbf-^u=l\xb4tr92\xdb9o\x93f\x93k\xf2\xe8r\xf9\x97\xfb\x97m\xb7\xbd\xb35\xa5\x87\x7f\x1f\xb1\x7f\xb9\xa7   -  .Ym\xb1\x07(\xcdJ2k\x05\xe7\xa4C$r\x1b\xd7\xa5\xed~\x95\xaa%\xf9\x15\xc2\xa8\xdfC\xbbUk[U\xbft$\x00U\x92P\xfa\x14\x95\xa2xB\x8abVBXD\x85\xe1\x01\xa09\x94\x9   -  a\xed:\xda\xdc\xe3\x94\xd1\xc5\x95\xbaP\x92k\x8b>\';\x048\x99+\xba\xb0d\xc7\xb6\xb6o\xe3a\xe4\xa4\xb5\x1b*]<\xe9\xe1   -  \x18\x0e\xe5(B-\xf2\xa9\x9eh\xde=\xbc\xb4W\x1a\r\xdd9\xc7\x8b\x8a\x1d\xfd\xc6\x96mE\x05k\xaa\xd6\xa2\x92\xe4\xcfO\xd   -  33M\xe2"Z9i\x10\xebT\xb8\xe5\x92\xb2\x8a+\x0b\x99p\xf4\xb3\x1e\x1c\xfbB\t\xe6\x03!P\x86\xb22R\xd9x\x13\x82\x18M\x06\   -  xc2\xd0\x80\x01 \x89 \x9c\xa2\x11    -  \x19\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x0c\x92\x18\x81\x07c\xb   -  3\xde\xedY\xfd,~\xf3\xae;\x1d\x9e\xf7j\xcf\xe9c\xf7\x9a\xfc\xdf\xeb\x96\xce\x16\xf3l\xc7\xb9v\xde\xc4~\xe3\xbe\x8fq\   -  xd0\xec\xc7\xb9v\xde\xc4~\xe3\xbe\x8fq\xf3\xceG\xce]|^\x92\x0003%\x00\x81h\x00\x01    -  \x00\x00\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}   -  W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x02\   -  x06[\x97B\xb6S"a\x16\xf4\xc3\xbd\xa2\xbd\xe8T\xf6\x8dQ\xf8\xa6\xd7v\x8a\xf7\xa3S\xda5G\xb8\xf5}\x1b\xe2\xe3\xf2=\xa1   -  \x12\xc0=\x0bQ\x03\x04\x80\x18)\x92+)\x91:J\x06\x00\xee\'P    -  \x9c\x02J\xcc\x08\xc0A\x84A\x12\x94\xd2y}\x0b\xaa\xa3U\x15Z\x0f\x12E\x96\xb3\x1c\n\x19\xa3\xe8\xff\x00\xa9\x83\x91\x   -  87\xbe\xabm\xb1\xbb\x86\xda\xc9\xd6\xa0\xec\xaef\xdc\xdb\xc2\xc9\x9f\xe8\xbcE<\xf54\xc3s\xf75^\xdaY\xc1\xcbi\xd4\xe3O\xea\xe5\x82"V\x91\xce\x8fM\xff\x00\xa1t%\x04\x8a\xb0B\x9aS\x80\x91V\x08ad\   -  x10N\x18\xc10D\xa00\xf9\x16\xe4\xc4\x92\xe8\xf6\xbaq\xa3\xa3\xdcJ~\x87\x0f3Kv\xf6tj\xebu\xe7G\x0f2\xeef\xd3\xef{\\Z~   -  \x81sBrJU`\xd4M9\xba\x9b\x9d\xe5I\xd5m\xe5\x9e\x87\xa4SS\xb7\'\x91>QO\xa1Se+/\xd1\x1c\xfb\xcfY\xdd\xb8\xd3BUd\x890\x   -  84\x86\xd3\xa5\x19\x19\x18\x04wTH\x00\x9e\xfa\xa4\x00\x0e\xfa\x80\x00D\xa2B\xae\xe2\x92\xae\xe2v\xaa\x11$"B\x00\x01\   -  x02\x18\x0c\x12\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86I\x0c@\x83\xb1\xd9\xefv\xac\xfe\x96?y   -  \xd7\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb\xcd~o\xf5\xcbg\x0by\xb6c\xdc\xbbob?q\xdfG\xb8\xe8vc\xdc\xbbob?q\xdfG\xa1\xf3\xdeG   -  \xce]|^\x92\x000C2P\x08\x16\x00\x00\x00\x00\x00\x01    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x   -  8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00    -  \x00\x10\x86R\xca\x99K\x1b\xf2O\xa6\x1d\xed\x15\xefF\xa7\xb4j\x8a6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa\x08\xf5}\x1b\xe2\xe3   -  \xf2#\xc8\x00=\x1e\x9ac    -  \x12\x89\xd1\xb4\x10\xc9\xef\x0cm\x1bA\x05D"6\x91\x12\x01\x02;\xc9\x04"\x04\x80\x83/\xbd\xc2^\xf3s\x0e+m\xec\xb8\xbe   -  Q\xba\x14\x9c]\x18\xe3\xc0\xd1M\x84\xbf\xfeM\xda\x0b{\x9f\x92\xcd\xd0\xd9\x8b\xcf\xe5\x1d"\xda\xe1O\xd2\x8epx\xae\xb   -  1I\x8c\x93gO\x8d}F\x9d\xe7\x17\n\xcb.\xc7\x9f3\x8d\x1fI\xf1t\xee/R|\x8e\x15f}K\xa1\x13\x1a^H2\x10,\x93#%\r\xf3##HW\x   -  94C\x91A\r\x91\xe4\xde\x959d\xe2^\xddR\xb6\x84\xa5VX\xc2\xc8\xbb\xbc\xa5iM\xd4\xad5\x18\xa5\xd5\x98\x0b|\xfb\xcc\xa7   -  \x1a5,4\xd9\xf9\xf2\xe5\xe5`\xfa\x1bx0NY\xd3\r\xf2D\x93K\xa1\x9f\x1fS\xdc\xeeI\xe2CP2\xb8\x9a}Q9X2F\xden\xc3P\xd1j\xb9\xda\xc2\xa5\xc4S\xe6\x   -  e2\x8f\x01:3\xa3Q\xc2\xbd7NK\xb9\x9d\xbe?6\xb9>\xda\xb90\xf6\xaca\xae\xa1\x15s\xe1|_\xb0\xa4\xe8D\xc5\xbd5\xe64\x902   -  \tT\x00\x10!\x80\xc1)\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x0c\x92\x18\x81\x07c\xb3\xde\xedY\   -  xfd,~\xf3\xae;\x1d\x9e\xf7j\xcf\xe9c\xf7\x9a\xfc\xdf\xeb\x96\xce\x16\xf3l\xcf\xb9v\xde\xc2\xfb\x8e\xfa=\x0e\x87f}\xc   -  b\xb6\xf6\x17\xdcw\xd1>{\xc8\xf9\xcb\xaf\x8b\xd2@\x06\x16d\xa0\x10\'`\x00\x00\x00\x00\x00$\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00b\xae\xd4\x7f\x01;M\xf5_\xc5R\x03\xb5\x1f\xc0N\xd3}W\xf1T\x80\x19T\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x02\x11"\x96T\xca\x1b\x1fi\xfaa\xfe\xd1~\xf   -  4j{F\xa8.\x86\xd7v\x8b\x7f\xd9\x1a\x9e\xd1\xaa\t\xf2=_F\xf8\xb9\x1c\x9ff@\x07\xa4\x86\x80I\x04\xe4\x91\x00\x06T\x08D   -  \x90\x99\tH\x19\x19\x00;\xc6Gx\x13\x802C`]\xb6\xa8\xe9\xd6\x8c\x97s\xe8lV\xe6v\xfe\x12\x84l/*4\xa3\x88\xc7\x89\xe0\x   -  d6\xfao\x86\xb4g\xdc\x8eU\xb6\xa5^\xd6\xee5\xa8\xc9\xc5\xc5\xe5a\xe0\xe6s8u\xcdY\xdb>;\xf6\xb7\xde5\xbc\xa2\x8c\xe3%   -  *o\xa6\x1eNu\'\x98\xa3Y6\x07|_\x91\xd2\x85\xbe\xb1Q*1]R\xcb3\x1e\x83\xbc\x9d\x9f\xd4\xe8\xa9Z\xdc7\x9f\x1c\x1e;?\x0f   -  %/\xe9\xd1\xc5\x9a\'\xdb\xde\xae\x80\xeb\xeduk[\x88qS\xab\x16\x9f\xce\x8b\xff\x00\x96Q\xfe\xf2?i\x83\xb2\xd1>a\xb3\x   -  19+\xfe\xb9\x0c\xa2Y\xee8wZ\x95\xb5\xbd7:\x95b\x92\xf9\xd1\xe5\xf5=\xe3\xe8Zz\x97\x95\xae\xf2\xbc0d\xae+\xdb\xd4"r\x   -  d6=\xcb\xd8\xf3\x8f\xa4tz\xde\xd0\xd9\xe9T\xeaT\xb8\xab\x08\xa8,\xe1\xc9,\x98wk\xb7\xdb\xe4\xdc\x96\x938K\xc3\x89\x1   -  8_j\xf6\xdbS\xdaj\xaf\xf2\xd9\xb8G9\\\x12\xc1\xbd\xc5\xe0\xdb%\xbfhb\xc9\x9e\xb1\xeaY\'z\x1b\xd6\x96\xa3\x19\xdbi5%\   -  x08g\x1c\xf9\x98N\xea\xac\xee\xa7)\xd6|R\x93\xcbe\n\x10K\x8b\x8aN\x7f;\x07\xa4\xe2\xf0\xabH\xd3\x9b\x97,\xcc\x9d#\xc   -  2\xba\x14I\xf0\xac\xb2\xb8\xae\'\x85\xd4\xa9R\xe3\xad\x1aM7)\x88\xb5qK\xcb\xc2t\xea\xc585\x8e   -  h\xd9\xe3\xf2\xaf\x8ew\x0cy1D\xb4\x02\xfe\xda\xb5\xa5\xcc\xa9WX\x94^9\xa2\xc1\x9aw\xe7\xb1\x15,n\xe7\xa8\xdbS\xc5\xb   -  a\xe6\xda0\xac^Y\xec\xfao"2\xe3\xf2\xe5g\xc7\xdb)$\x82Q\xd2\xee\x89j\xca;\xc9D\x12\x88\x11    -  $\x0b\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x92C\x10    -  \xecv{\xdd\xab?\xa5\x8f\xdeu\xc7c\xb3\xde\xedY\xfd,~\xf3_\x9b\xfdr\xd9\xc2\xdem\x99\xf7.\xdb\xd8_q\xdfD\xe8vc\xdc\xc   -  boa}\xc7|\x8f\x9fg\xf9\xcb\xaf\x8b\xd2@\x06&d\xa0\x10    -  \x00\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cU\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@v\x   -  a3\xf8\t\xdao\xaa\xfe*\x90\x03*\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x06\x03\x02\x00\x01\x08}\n\x19q\xf4-\xb2c\xd9\xf4\xc3\xbd\xa2\xfd\xe8\xd4\xf6\x8dP\xee6\xbf\xb4_\xbd\x1a\x9e\xd1\xaa   -  \x1d\xc7\xab\xe8\xdf\x17\'\x93\xed    -  \x84I\xe8\x9a\x00\x00\x80\x04\x00\x94\x80\x02\x00\x00\x00\x00\xd0\x00C\x1a\x02\t\x05\xa7\x1e\xe10\x82\xed\x0b\x9b\x9   -  a\x12N\x85\xcdJK\xc2,\xb6F\x11\xa5\x93\x8f\x16\xf6\xbc_N\xfe\xd3j\xb5kT\xb8o\xee\x1a_\xf7\x1c\xcf\xe7\xe6\xad\xfe2\x   -  b7\xef\x1eT\xa7\x85x\x18\xa3\x83O\xf1x\xc8\xf4W\x1bQ\xaa\xddI\xcaZ\x8d\xc2\x8b\xee\xe2:\xdb\x8b\xfa\xd5\xf3\xe5n\xa7   -  ,\xf8\xb3\x80\xb9,"\x97\x1ey2W\x85H\xfaD\xdbi\xa9\x0e\'\x9e6\xc8\x8cx{\xc9H\x94d\xa7\x1e\xb8\xfc\xc2\xb3)D\xbe\x9c\x   -  82\x0c\xc9\xa5HK\xc9\xc2y\xf4\xbb\x8c\x87\xb9\xcd\x96\x9e\xbd\xacF\xa5x7\nmK\x9a1\xed\x08\xab\x86\xe0\xbd.\xe3lw%\xa   -  2\xc2\xc7f\xad\xae\x14\x12\xabR8l\xe3\xf5\x1c\xfd\xb5na\xab\'\xe8\xd6\xb4,\xec\xe9\xd2\xb7\x8cTb\xb1\xc9\x1d\x91\xc6   -  \xb4\xa7\xc1\x13\x90y\x1b\xce\xe5\xd5\xc7\xe8h\x8c\x15\x02\xac\xaap0TIUv\xa1\xaeE8.`\x86\xb2B\x14\x00\xd70\x972\x04c   -  \x998\xca%\xa2W"\xd0<\x9e\xf0\xf4xj\xfb?^\x84\xe2\xb2\xd6s\x83J\xb5\xdaQ\xd3\xb5\xda\xf6\xcdaFn&\xfcj1U-\xaa&\xbb\x9   -  9\xa5\x9b\xd6\xd1\xfc\x86\xb9yYrnm\xa3\xd0tl\xba\x9e\xd7?\x95\x11\xb7\x8d\xac\xd3\xa8\xf8z\x14\xa2\xdd\xb6|\x9f\x9f\   -  xd4\xae=\x0fW\x82\x9d\xd12\xe5\xda<\xa4    -  \x87"P\x89\x00\xc1`\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x042Hb\x04\x1d\x8e\xcf{\xb5g\xf4\xb1\xfb   -  \xce\xb8\xecv{\xdd\xab?\xa5\x8f\xdek\xf3\x7f\xae[8[\xcd\xb3\x1e\xe6[{\x0b\xee;\xe8\x9d\x0e\xcc{\x97m\xec/\xb8\xef\x9   -  1\xf3\xfc\xff\x009u\xf0\xfaH\x00\xc2\xcc\x94\x02\x04\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0`@\x00!\x0f\xa1m\x97\x1a(do\xca&|0\xefh\xbfz5=\xa3T;\x8d\xa   -  f\xed\x17\xefF\xa7\xb4j\x87q\xeb:4\xfe\xae?"|\x99\x19\x18\x18=\x1bM \x02\x00\x00\r\x80\x00\x00\x0e\xe0##    -  \x16\xd0dd\x01\xa0\x04\x90O|\xeb@\x16\x001\xcf\x918    -  e\x82\x00\x86H-\xb4\xed\x18\'\xb8\x9e\xe29\x84\x88\x92;\xca\x99\x13\x08\xfbv[1m\n\xfa\xe5\xb5&\xb9\xceF\xe8\xec5\xa2   -  \xb6\xd0\xad\xa8\xae\x91]\xc6\x9blb\xfe\xd0Z\xc9\xfcY\x9b\xab\xb1\xdev\x8fB^(\xf2\xdd^t\xe8\xe0\x87\xa0\x8f$TB%\x1en   -  \xce\x85\x120\x06Y]\xb2l$\x02\xd0\x81\x90H\x02\x86\xb9\x90\xf9\x15\x90\xda\xef+"\x9c\xe5d\xa2U\x141\x91\x87\x9c\xae\   -  x852\xf3\x99Z\xee}\x8an\xe6\xbc\x8c\xb3\xf2Y\xa6\xdb\xda\xbew;E^\x8d7\x84\xa6\xd3\xc9\xb6{G~\xac\xb4\xaa\xd5\xa4\xd2   -  QM\x1aQ\xb6\xb7\x9f\x97m%\xd4\xe0\xff\x00\xf9\x19\xe8\xbaF)\x9bw49N\x92\xb4<\x9c\xa3\x1f\x9c\x9a\xab\x12\xc2\xe8%\x1   -  97\xe7uDg\x8b\x9b=\x87\x1eu\x13\x0e]\x91\x81\x82\xa0\xfa\x16\xadbfHRFJ\x88*\x80\x04\t@\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00C$\x86    -  A\xd8\xec\xf7\xbbV\x7fK\x1f\xbc\xeb\xce\xc3g\xbd\xda\xb3\xfaX\xfd\xe6\xbf7\xfa\xe5\xb3\x87\xdby\xb6g\xdc\xbboa}\xc7}   -  \x13\xa1\xd9\x9fs-\xbd\x88\xfd\xc7}\x13\xe7\xbc\x8f\x9c\xba\xf8\xbd$\x00`fJ\x01\x02@\x00H\x00\x00\x00\t\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    -  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00    -  \x13\x81\x80\x85/\xa1C+|\x8a\x19\x1fj\xdb\xd3\x0fv\x8a\xf7\xa3S\xda5?\xb8\xda\xbe\xd1U\x17\xf3^\xa5>\xfe#U\x1e1\xd4\   -  xf5\x9d\x1e?W+\x91\x1b\x94"JQQ\xe8\xe2Zr\x94\x08D\x90\xac\x80\x00\x80\x00\x12\x0e\xe0\x00\x80\x01m\x80\x00\x91$`\x90   -  PF\x06\t\x00F\x06\t\x00F\x06\t\x00F\t\x00\x00\x00\x94\xc2\xf5\x84\xe7m\xa8Q\xaf\t4\xa0\xf2\xf0n\x86\xe9\xf5*z\x86\xc   -  b\xda\xca3N|<\xd1\xa5\xb0\x9a\xf2SO\xbc\xcd\xbd\x9f\xb6\xb9Y\xdd\xbb;\xba\x89S\xc6"\x9b\xef<\xd7V\xe3\xde\xd1\xb8\x8   -  7K\x04\xb6\x81\x15\x1cZ7*\xa55(\xac\xa6\xb2^\x8c\xfcO+\x925\xed\xd0\xaa\xe1\x01I\x15u)\x13\xb5\xb4    -  \x10\xc9h\x022\x01a\x0f\xe6\x1dHl\xb79\xb4D\xa7K\xb8X8\xf5\xe7\xc0\x9bH\x8f/\x87\x86\xb2yM\xba\xda\x8a\x1a\x15\x85Z\   -  x95$\xb8\x9cZK&\\8\xa6\xf3\xa8R\xd7\x8a\xfbc\xfd\xfam\x95;=.\xae\x9bBIU\x9a\xea\x9f3X\xae\xaa\xb9U\x8c\xdb\xf3\xa5\x   -  cd\xb3\xbc\xdb]z\xa6\xb9\xab\xd4\xadRN\\\xde\x0f=U98\xbf\x03\xda\xf4\x9e4c\xa7\xec\xe6\xf2r\xd6\xd3\xe1q\xb7&\x9f\xd   -  aU&\xb3\xe6\xa2\x9arQO(\x88\xbeGV\xb1\x112\xe7\xca\xa4\xc3|\x88\x05\xab\xe2e1>\x12Gx\xe2\x19\xe6PF\t!\xf3$\x94\x00\x   -  00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86I\x0c\x01\xd8l\xef\xbb6\x7fK\x1f\xbc\xeby\x9d\x9e\xcfc\xf9f\xcf\x9   -  a\xfd,~\xf3S\x9bh\xec\x96\xc6\x1fm\xe6\xd9\x9fs-\xbd\x85\xf7\x1d\xec{\x8e\x8bf=\xcc\xb6\xf6#\xf7\x1d\xea<\x07#\xe7.\   -  xce(\xf0\x90\x01\x81\x95(\x04\t\x80\x00\x12\x00\x00\x00\x02@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xe   -  dG\xf0\x13\xb4\xdfU\xfcU    -  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00D\x8br.2\xdb#\xed[zb\x0e\xd0\xb6n{)R\xaaY\xf3\xb0j]\xcd\xbc\xad\xea\xac\xfcnf\xf6m\xee\x8e\xb5\x9d\   -  n\xb5\xbb\x8ey6i>\xd2XJ\xcbV\xb9\xa5W)\xc2m$z.\x93\x9f_\xab\x9d\x9e\x1dX\x08\x94z\xb8\x97>\xde\xc4TRT\x14\x00\x04\x9   -  a\x00\x00\x00\x00\x08d\x8c\x12 \x0c\x0c\x13\xb1    -  \x02\xa0\x00\x1a\x00\x00\xd0\x00\x00\x00\t\x00\xfa\x80\xfa\x81)6\xd3\x8f\xa0\xbd"\xfd\x85\xfc\xec/\xa9\\P\x93\x8a\x8   -  c\x93E\x8au\x9d\x1c\xac&\x9f\x89[\xa5\x18\xc1\xd5o\xd3]\r^E{\xe3M\xacY4\xdb\r\xd5\xef\x0e\x86\xad\xa7R\xa1uU~P\x962\   -  xde\x0c\xa3F\xe2\x15\x92qi\x9a\x07\xa5\xea\x17z<\xa3^\xd6\xa4\xf2\xa5\xf2\xb0g\x9d\x80\xdf\x05%J\x95\x1dr\xa4(\xb4\x   -  92Mw\x9eW\x99\xd3\xa7\xdd]\x0cy\x9b\x14\xa4\xb3\x84\xd1Z\x9e:\x9eoA\xd6\xac\xb5x*\xf65\xbc\xa4\x1f3\xbb\xab%8\xac7\x   -  c8\xe2\xdf\x8fj\xce\x99\xe3$9\x89\xe4\x96qiU\xe8\x99\xc8O(v\xe9m\xa7!\xb2\x8a\x99\xc7#\x8f\x99E\x91\xdb3(\x9bi~R]\xe   -  5\x12\x9aK\x9f$tZ\xee\xb9g\xa6E\xca\xf2\xb7\x93H\xc4\xdbm\xbe\x9b;[z\x944\xaa\xb4\xea\xd5K\x0b8\xeama\xe2_$\xc6\x94\   -  xb6^\xd8d\x8d\xb2\xda\xfb\r\x9f\xb3\xa9:\xb5\x13\xac\xd3\xe1Qi\xf35sx\x1bm}\xb4\x15\xaayZ\x99\xa0\xdf%\xdey\xfdw_\xb   -  e\xd6\xae\xa5wV\xac\xdc\xa4\xf2\xe1\xc4\xf0\x8e\xaaugY\xe5\xa5\x9e\xf4z>\x17N\xfcs\xb9s\xf3g\xefY\x8c    -  \xe2\xe5\x1c\xfe\xd0W,(\xf9\x9c\xd7yGS\xbd\x8e\x9d\xb0\xd2\x99\xf2    -  I\x0c\xc8\xa8\x86B\x02\x00!\x82p\x12\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00$\x03x\x04d\x81.I\xacw\x   -  9c\xad\x02\x94\xff\x00\x97,Z\xcbN\xaczz\xce<    -  \xb8\\\xbb\xd1\x90\xb7)\xb3\xf5\xb5\xad\xa3R\xabK4\xa9\xe2I\x9cn\xa1\x97U\x96|\x1el\xdb]\n\x9f\x93\xd1\xed\x9a\xeb\x   -  e4\xe3\xf7\x1d\xc5?E\x1c\x0be\xe4U*)r\x8cR;\x18\xf4(\xc6\xbbs\xbb\x1d3\\U+N\x   -  96+\xbek\x87\x91\x95\\<9\x16%Eq6\xf9\x99\xf0\xe7\xb5\'lY1\xc4\xb4\xc7l7{\xa8\xe8s\x9do$\xdd\x08\xf4\xc2\xcb<,\xa3\x9   -  9\xb8\xce./\xe7X7\xf6\xf7L\xb5\xba\xa3(V\xa1Ni\xfc\xa5\x93\x0cm\xfe\xe8\xad\xaf\xbc\xa5{\x15(\xd4|\xd4`\xb0w\xb8}N\x   -  bf\x1b9\xf9x\xf3\xbf\re\x9c8\x1f.\x84\'\x93\xd1\xed\x1e\xcaj:\rW\x0b\x9a2T\xd3\xc7\x13<\xef\x93\x93\x9f\x98\xb3\x13\   -  xb1\x87<^|KVqL$!\x8cz]Ix\xee:\x15\xf2\xc5h\xd2\x18%\x91\x83$B\xa0*\xc3\xc1KD$\x08\x12\x91\x12\x80\x13\x81\x82\x04\x0   -  2p@\x00\x00\x00\x00\x00\x00\x02H\x19\x02\xa42B\x00T\xc8\xc8\xc9\x19f;\xcd\xbf\xf5L\'$I\x8c\x90\xcbR\xd3\xf6mHC\x03\x   -  06n\xe8N\xd5\xae\x84\xe4\xa5\x13\x82\xb3dm#\xbc\x8c1\xcc\xae\xf6m#$s\x00\xd9\x92\x1fRp0\x10\x82\x19V\x08\xc0\x01\x81   -  \xcc%\x90\x93\xa1\x03\x1c\xc9\xc1h\x81\x03$\x91\x810\x84\x80\x90(\x00\x0c\x04\x800\x00\x86H+3\xa4    -  d\xa9S\x94\xa3\x98\xac\x95*q\x94xb\xf3U\xf4\x89K^+\x1b\x96J\xe3\x9bz[g&\xce\xd6\xbd\xd5HS\x8d9K\x89\xe28M\xf3=\xbe\x   -  c5n\xd3S\xd7e\t\xdcP\x9c(\xcb\xe3/\x03`\xb6#v\x96:\x14    -  \xeaRU\xa4\xbe\\rr\xb9\x9dB\x94\x8dD\xf9lc\xe2\xd9\x87\xf6\x13sw\xda\x8dZw\x1a\xd4\x17\xe4\xaf\x9f\x9a\xf9\x9b\x03\x   -  b2[\x1b\xa5l\xe5\xba\xa7eK\xaf^$\x99\xe9i\xda\xc2\x9c\x14i\xc5F+\xb9r.\xa8._1\xe5\xf9<\xbb\xe4\xfboS\x0e\x91\x18\xa8   -  \xfa)%\xf3\x15c\x1c\xca\xd4CY4\xbb\xa6[T\xacB\x94T\x87\t)\x08\x86]\xaaD\x91\xccs,\xa2\xa4\x02\xe8\x00\x00\x08\x00\x0   -  0\x00\x01    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x   -  8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x18!\xa2@\x14\xb2\x96\x8b\x8c\xa1\x89\x14\xa4\x9fR\xcd\xc5$\xd7B\xebx)\xcey2\x9d\xf6\xaf\xa2i\xb8y\xddsf4\xed   -  V\xdaj\xe6\xde\x9c\xe4\xd7,\x98\x1bo\xf7A^\x9a\x9d\xde\x97&\x96s\xe4\xa0\x8d\x9b\xe0E\x15    -  \xb8Zx\xe6m\xe0\xe7_\x1c\xb5o\x87m\x08\xd4\xf4\xbb\xdb\t\xca\x95\xdd\x9dJx\xf8\xd2GV\xe5\x18\xf2\xc9\xbb{S\xb1:f\xbf   -  Jj\xb5\xba\x95F\xba\xb3]\xf6\xdbu\x17\x9aUj\xd5\xa8\xc5J\x8e[Q\x8a\xcb\xc1\xe8\xf8}O\xbf\xc4\xcbO.\x16-\xceRh\x17\xa   -  e\xecn,\xaa5Z\x9c\xe1\x1e\xe5%\x82\xc9\xdc\xa6~\xe8i\xda\xba\x94\xfe\xd2\x00\xef2E\xf6\xac\xa4\x062Z\'j\x80d"@\x82H\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x0c\x90\x00\x00\x1d\xe0   -  \x0f\xd86\x94\x0c\x93\x81\x81\xde\x84\x00\xf9\x01\xdc%\x10\xc0\xee    -  ;\xc9D\x0c\x91\xb4\xc2_B\x96\xf0\xb2IC\xcf\x7f4"\xd1\x1ee\x92\xb5\xeeJ\x9a}\xe4\xd3~R|\x10\xf3\xa5\xe0\x8e^\x99\xa2\   -  xdej\x170\x85\xad\n\x8f\x89\xf5Ql\xcd\xbb\x03\xb9\xc9IB\xf3P\x8c\x1ey\xe1\xf2g7\x99\xce\xa6?\xb6Z\xe1b\xbd\x0bd5mj\x   -  a4)\xd2\xa1Z\x9d6\xfd4\xb9\x19\xff\x00w{\xa3\xb4\xb0\xa7N\xbe\xa6\xa1^}q4d\xad\x9f\xd9\xfb]2\xd64\xe8R\xe1H\xee\x94\   -  xf8ZXx<\xcf#\xa8\xde\xfb\x88\x96\xee\x1c?\xea\xd5\x8e\x9dmiMB\xda\x8ciF+\t#\x9b\x1eE\xbf;\x1cY\xf3|\n\xe3\x86\xb2\x8   -  et\xdeg\xdb~+\xa8V\xc8@\x98\xf5)2\x8d*D\x90\x89*\x94\x13\x80\t\x84\xa4\x022H\xa9t\x01t\x04    -  \x00\x00\x00\r\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0   -  e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x06R\xd1Q\x00[\x91F\x0b\xad"\x9c\x110\x98\x95\x1c\xcag\x0e%\xcc\xb8\xc8#\xb6\x15\x9f$V\x   -  160q\xae\xec\xa8\xdd,U\x84e\xebG(\x17\xad\xa6\xbe\x98\xe6\xbbb\xdd\xbf\xddu\x86\xb9G\x8e\x84\x1a\xaa\xb9\xf9\xbc\x8d   -  x\xdbM\x81\xd4v~\xb4\xa7*O\xc8.\xf5\x96n\xbc\x92k\x99\xd4j\x9ae\xb5\xfd)S\xb8\xb6\xa7Q>\xf9,\x9d>7?%}\xc8\xf7[\x13\xb0Z\xa6\xbd8\xaa\x96\xf3\x85\x19u\x92\xeeF\xaf#\x95JW{e\xa6=   -  \xbc=\x1bK\x9b\x9a\xaa\x16\xf0ro\xe62f\xc2\xee\xb6\xff\x00Xp\xabyE\xaa\x19\xe6f\xed\x88\xddn\x9f\xa1\xc2\x12\xab\x8a   -  \xd2\xef\xe3FB\x85\xa5+jJ\x9d\xb5\x18B?\xf6\xa3\xccr\xba\x9d\xa6uItp`\x88\x9f//\xb2;\r\xa7h4)\xf9*Q\x94\xb1\xcf\x89&   -  {\x0f#\x07\x14\x94TR\xf0X"\x87\x12X\x92/\xa3\x93|\x96\xc9;\xb4\xb7?\x1dH\xc5Ea\x10\xe0\xba\xe0\xab\x91/\xa1\x8fI\x88   -  \xd2\xdf\x02*H\x90VS2\x8c\x15$A(\x81RC\x01\x12L\x06\x060J H \x01\x08H \x94J@\x01    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x0   -  2v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x94\xf0\xb2\xb6\x88\x02\xde\x06\n\xf0F0\x10\x8c\x11\x8eED\x10\x85\r\x14?Qy\x   -  a28H\xf3\xf4\xbf\x8d8\x93\x87\x1eq\xe6\x9d\x16\xbd\xb2\xfan\xb3o8]Z\xc2u1\x857\xdcz\x87M0\xe0\xb1\x84_\x1d\xefY\xf6\   -  xc1l{j\xc6\xf17Swc)\xdci\xed\xd4\x8fU\x08#\x10\xdd\xd8\xdd\xdaT\x94/\xad\xaaS\x92\xf9H\xdf\xea\xb6\xf1\x94Z\xc6rxm\x   -  ae\xdd\xd6\x95\xae\xa9\xce\xad\xbau_\x7f#\xb1\xc7\xea\x13O\x93Z\xfcY\x9fM,mg\x902\x9e\xdf\xee\xb6\xebAs\xadkO\x8a\x9   -  2\xe7\x88,\xbf\xf41L\xa9WU\xa7\tBt\xb8~\\Z\xfb\xcfA\xc7\xea4\xbcD4\xef\xc6\xb5WS$\xb5\x19\xe1\xf0\xcb-\xf8\x97\x94\x   -  1e3\x95\x83\xa9Y\x8bF\xe1\xadj\xf6\xa1\x90\x1c\x92\xee!<\x97\x88\x84D$\x92\tDJd\x00\x10\xa8\x00\x00\x00\x00\x00@\x01   -  8\x18\x02\x018\x18\x02\x00h\x00\x00\x00\x00\x00d\x90\xc9\x00\xfa\x05\xd0\x80LF\xd3\x06I\xc8    -  Z4\xb4\x03\xd6C\x0f\x93\xe1|\xdf\x89\x8f\xba\x0e\xd4\x8c,6\xdf5\xdcQJ\xaas\xe0q\x96|N\xcbN\xd2\xae5\x1b\x88\xd2\xa1F   -  \xa3\x93xO\x85\xb4b\xcb\x9e\xb5\xae\xf6\xcb\x8f\x1c\xcc\xe9\xd7Sn\xb3\xe1qq\xf0;\xfd\x9c\xd9}GS\xba\x8d*V\xf5\\%\xf1   -  \xd2\xe4em\x84\xdc\xf5{\xa9S\xaf\xab\xc6\x13\xa5\xc9\xe3\xa33\xde\x81\xb2\xdan\x8dJ\x11\xb3\xa2\xa2\xd2<\xf7/\xa9\xd   -  60\xb9\xd4\x1c+\xb7\xe7p5\xd0\xcb\xbav\x97icN1\xb3\xa7\x1aIuH\xeda\x04\xb9$\x15\x18\xa9g   -  \x1c\xce\x16^U\xf2O\x99g\xa6\r\t$\x89\xc1V\tH\xd7\xde\xdbU\xae\x94\xe0a\x95a\x13\x82R\xa5&N\t\'\x04\nR\x18*\xc0\xc1\   -  x08S\x82R\'\x03\x04hJ\x01\x13\x82a" \x90\xc9B\x00\x18    -  2J\x18\x00\x00\x04\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5   -  \x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00`\x86H`A\x04\xe0`\x1aF\x06\t\xc0\xc0\x102\xbc\t\xc0#b\x1e   -  \n\\Wy^\x08\xc1\x1d\xfa\x1c+\xbb*\x17Pp\xadN\x12\x8b\xf1\x8af)\xde\x1e\xe8\xf4\xedj\x94\xaa\xd9\xc6Q\xae\xb9\xa5\x05   -  \x84\xdf\xec2\xfc\x91nk\x933b\xe4Z\x93\xb8\x96;\xd3p\xd1\xfd\xa8\xd8-cg\xeaIW\xb7\xc54\xfa\xf3\xf3`\xb6\x0fu\xd6:\x1d8J\xea\x11\xad%\xcf3\x89\xc8\xe4\xf5\x18\xc7\xb8l\xd3\x17w\x98a\xad\x81\   -  xdd\x8e\xa1\xab\xd5\x84\xb5*\x1c\x14\x1b\xea\xba\xe0\xcf\xfb+\xb0zf\x89\x18\xaa4\xd4\xa4\xba\xb9G\'\xaf\xb7\xb6\xb7\   -  xa3\x15\x1bZQ\x8a\\\xb9#\x98\xa1\x88\xa7\x8eg\x0b?:\xf7lS\x17l\xedE:q\xa5MF\x9cRK\xc1\x17c\xd0\xa7\x05i\x1c\xdb[\xb9   -  \xb5\x1eS\x1e\xa5e1Ei\x15\x85\xe1\x18a\x12\xc1+\x0f\x01\x0c\x13\xd0 H<\x04\xc0\x00\tA\x08\xc0\xc1    -  i"\x00\x12\x01\x80\x04w\x92\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x18\xab\xb5\x1f\xc0N\xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    -  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x8d\x08\xc0$\x11\xda-\xc9\x14\xb8\xe4\xba\xd1\x0cD\x12\xb2\xa0   -  \xa2\xf9"\x8a\xb1RM9,\x17\xe4q\xea\xd3\xcb\xca,\xa4\xc3\xccm&\xcbi\xda\xcd\xb4\xe9\xdc[FR\x92\xe5&k\xfe\xde\xee\x86\   -  xf2\xc6S\xafaQJ\x97U\x08#i\xd48\xbc\xd7\x8c\x14\xd6\xb5\xa5R\x9b\x8b\x8a~\xb3\xa1\xc6\xe7_\x04\xf8\x96\xbd\xf0\xf7\x   -  b4\x06\xfbM\xba\xb3\xab*U\xe8N\x94\xa3\xdf%\x83\xae\x83\x9b\xa9\x87\x9c\x1b\x9d\xb6{\xbb\xd3\xb5\xbaS\x94\xe8\xfe}\x   -  f7\xa3_6\xd3vz\xae\x8dVuh\xc1J\xd9wEe\x9e\x83\x8f\xd5#\'\x89j\xdf\x8f\xa6;%"\xaa\xf4\xeaP\x93\x8dXN-|\xa8\xb4[S\xca\   -  xe4u\xb1\xe6\x8b\xfai\xda\x9a\x95x    -  \xa3\x8c\xad34Z\x15\x93\x18\'\x04\x12\x89\xda\xa6\x10\x00\x94!\x82z\x90L\x00\x00\x90d\x12\xc8\x00\x89!\x12T\x00\x00\   -  x19-y\xb9\xe2\xe7\xe0    -  \x9b\x96#\xd4\xaa4x\xa7\x8c\xa5/\x9c\xc5\x93,R\x16\xacmz\xde\x84j\xc3.J/\xc1\x96\'(\xd1\xaf\xc3\xc3\xe5\x17\x82/\xdb   -  i\xf7w\x97q\xa1mNr\x93x\xca\x8bh\xcc\xfb\xbd\xdc\xf5[\xa9\xd3\xb9\xd5a\x19A\xf3\xc7y\xcb\xcf\xd4\xabF\xd50\xcc\xb1V\   -  x89\xb3z\x86\xbbUF\xda\xda\xac"\xdf\xa5\xc2gM\xdcn\x86\x8d\x93\x85\xc6\xad\x18Vo\x0f\x12]\x0c\xb9\xb3\xfb+c\xa2\xd0P   -  \xb5\xa2\xa2\xd7\xccw\xdeM8\xe1\xa3\x87\xc9\xeaV\xc9\xe2\xad\x8aa\xd4\xf9u\xfa^\x97cb\xd5;J\n\x9cW\x81\xdba8\xe1\xae   -  E\x9aPq\x9b\xf09\x11\xe8q\xef\x92m;n\xd2"!M:Q\x87\xa2\xb0L\xd1Zd>effW\xd2\xde>b\xb4\x89EEt\x9d#\x04\xa4H%&\x08\xc1$\   -  x12#\x03\x04\x80\x80\x00\x80\x9c\x002JF@\x00J\x04"r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\xfcU    -  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\r\x12\x00\xa1\x96\xa4\   -  xe7\x9e\x9c\x8b\xed\x10\xd0D\xc6\xdc~\x18\xbe\xf7\x92\xa4]\xe0^\x03\x84\x9f\x0bWP\xb3(\xa9uG\x0e\xe6\xc2\x8dd\xd5JP\   -  x9a}\xd2\x8agd\xa2O\th\xbe\xbd+z\xc5\x98_x\x1b\xa9\xb1\xd6\xd4\xabZ\xc6Q\xaa\xb9\xf0\xc1a\x7f\xa1\xaf\xdbW\xb1\x17\x   -  9b=ZJ\xa59(\'\xd5\xb3y\xdd(\xe1\xf2\\\xcf9\xafhV:\xb4gJ\xe6\xd6\x9e\x1f\xc6h\xe9\xf0\xfa\x8c\xe2\x9f\xdb\xcc4\xb2q\x   -  bb\x9a \xe7\x0c\xf0\xfca\xcd3`v\xfbs1JwZl\xdb}x`\x8c/\xaa\xe8:\x86\x9b]\xd2\xb9\xb5\x9c    -  \xbe;G\xa0\xc1\xce\xa6_R\xd3\xbe\x19\xaf\x87O\x90\x993\x84!&\x9c\xc8j+\xa4\xb2uk1\xad\xed\xafjL\x1c\xc0L\x17\x8d)\t    -  \x02\x93m$D\xf7\x90\x892\xc4\xaa\x86A<\xbcBQ\xf9DL\xa6!\x08\x92p\xbb\x9eJ\x963\xcc\xa4\xdbQ\xb4-\xb6@t\xe5R\xae!\x97   -  \xe0\xbcOU\xb2{\r\xabm\x15\xdc#+Z\xb4h\x7fx\x97#G/>\xb8\xd9\xa9\x8el\xf3v\x94\xddZ\xca1\xea\xcc\x97\xb1\xfb\xad\xbc\   -  xda\x0e\x19\xdc\xc2p\xb7\x7f\x1a-\xf43\x16\xc0\xee\xa2\xc3J\xf2u\xaf8.$\xbe,\xd1\x95\xad,-\xad    -  \xa1mF\x14\xe3\xe1\x13\x85\xcc\xea\xdd\xf3\xaa\xc3{\x17\x17\xed\xe0v7w\xda~\xce[\xc2\x14)\xaa\xd3K\r\xd5\x8eY\xefm-\   -  xd5\x18$\xa1\x18\xfc\xc9\x1c\x95\x04\xbb\x8a\xb0p\xb2\xe4\xb5\xe7{oS\x1cUN\x08\xc1^\x08\xc72\xabZ\xb0\x84\x8a\xd1\x1   -  8%\x14\x98Ea8\x18$\x05\xc4\x02\'\x00\x00\x00\x08$\x01\x00\x01\xa4\x01u%\x00\x04\x120JP\t\xc0\xc0\x10\t\xc0\xc0\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\xab\xb5\x1f\xc0N\   -  xd3}W\xf1T\x80\xedG\xf0\x13\xb4\xdfU\xfcU    -  \x06U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01L\xbar,J\x1cO\xce\xe6\x   -  8eC)hyVVeN..-r<\xb6\xd2\xecn\x9b\xacP\x9cj[\xc5\xcd\xae\xac\xf5\x92E\xb9\x19)\x92\xd4\x9d\xc1\x18\xa2\xde\xda\x9b\xb   -  7\x9b\xa4\xbc\xd3*\xd6\xb9\xb6\xfc\xe5<\xb6\xa3\x05\x9c\x18\xae\xe2\xce\xad\xb5WN\xe2\x94\xe95\xf2\x96\r\xff\x00\xaf   -  o\xe5b\xd7\x0cZ}r\xb2c\xcd\xb3\xddV\x95\xafS\xa9W\xc95r\xd6V9,\x9d\x8c\x1dN\xd1\xe2\xd2\xd3\xcb\x82>\x9ayS\xf3r\xc7U   -  \xe2\x13\xca=\xfe\xd8n\xd3W\xd0\xaaO\x8a\x9a\x95\x05\xcdp\xac\xb3\xc1U\xa5:2q\x9cd\x9a\xe5\xcd\x1d\xee?./\x1e\xdc\xe   -  b\xe3\xed\x94&2R\x89\xc9\xd0\xa6\xad\xe5\x8eaR%\x91\x90\x99\x9b\xc4+\xa9CE\r\xc6=Qv/\x99\xca\xb6\xb0\xad\xa8VT\xad\x   -  a9\xceS}\xea-\xa3_7"\xb8\xfd\xca\xd4\xac\xcb\x81\t\xc78\xe8w\x9a.\xcf\xdfj\xb7\xb4h\xdb\xdb\xd5\x94\'\xf1\xd4r\x91\x   -  92v\x0fs7z\x9f\x05}b\x0b\xc8u\xc2\xe4\xcd\x82\xd9\x1d\x95\xd3t\x0buF\xca\x8a\xc2XnI3\x85\xcb\xea\xb1\x111V\xdd8\xdb\   -  xf3,[\xb0{\xa2\xa3NQ\xab\xa9\xd2\x8dLs\xc3Fd\xd3t[m:\xde4\xac\xe9\xaaq]\xc7i4\xa1\x1f\xcd\xa4\x85)I\xfaG\x9e\xcb\xca   -  \xb6I\xdc\xcbw\x16\x18\xaa\xbat\xd4R.\xa2\x11TQ\xaf3\xb6\xd4F\x92\x06\x06\x08H\x06\x06\x00\x12\x88\xc1Q\x00\x00\x00\   -  x00\x00\x00\x00\x00\x01\x81\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\   -  xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x08h\x90\r-   -  \xc9\x10\xa2\\k%8\t\xda00T@Va\xc3\xbe\xb0\xb6\xba\xa5(\xd7\xa3\t\xa6\xb1\xe7G&\x17\xdb\x9d\xd3[_\xba\xb54\xe8\xb79e\   -  xe2+\x06p\x92e\x97K\x1d\x0c\xf8\xb3\xdb\x1c\xf8\x96\xb6lqf\x92\xed\x06\xc1\xebZ\x15Y\xf9{F\xa8\xfc\xa7\xe0x\xfb\x98\   -  xc6\x15\x1c\x13\xf3\xfb\xd1\xbf\xb7zM\x9d\xec\\o(B\xaa\x7f(\xf3\xd7\xfb\xbc\xd9\xfb\x85.\r2\xde\x13\x7f\x1b\x0c\xeb\   -  xe0\xea\xb3O\x12\xd6\xfc\r!\x8d\xbc\xbe3i\x1c\xcb+J\xb5\xea\xaav\xf1\xe3l\xdb\x8b]\xd4\xe9\x94\xaa9T\xa5J\xa2\xcfF\x   -  8fA\xa7\xec.\x89i%(\xe9\xf42\xbb\xf0\xcc\xf9:\xbe\xe3\xc2k\x85\xad;+\xba\xbdKW\x9ce^\x8c\xe1F}d\xb3\xc9\x19\xff\x00a   -  ww\xa5l\xdd\xbc\x14\xa2\xaa\xd4K\xadH\xe5\x9e\xe6\x8d\x95\n\x10P\xb7\xa6\xa9\xa5\xdc\x8b\xf4\xe9\xa5\xe9sg\x1f\x93\x   -  cd\xb6i\xde\xd9\xeb\x8e!n\x95:t\xe3\x8aQ\x8cc\xe0\x96\x0b\xd0ItE\\\tt*K\x91\xa5\xdd2\xcdZ\x8a9\x1c(\xad\x10\xd1\x0b\   -  xc4h]\n\x91\t\x15"V\x01 \x08\x04\x80    -  \x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d   -  \xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x03 \x91\x80    -  \x82\xac\x06\x05\xb6\x8a\x1a.\xb4R\xd10\xafj\xde\tH\xab\x04\xa4N\xd1\xda\x84\xbeb\x1a.`\x86\x88\x99\xd9\xda\xb5\x82\   -  xa4\x8a\xb0JE;S\xda\x84\x8a\x92\x18*\'I\xd2\x9c\x0c\x15`\x80    -  \x94J\x04\x80\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5   -  \x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06A#\x00F\x06\t\xc0\xc0\x10\t\xc0\xc0\x10H\xc0\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8   -  \xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8   -  \xaa@\x0c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x02\x1bK\xa9\x1ck\xc4\xa2\xb6_4\xfa\x16s\xc4\xd2K\x84\x0eWR:\x11\x17\xc8\xa2\xac\xbc\xdc.\xa0\\SNXO\x98\x95H\x   -  c5\xe1\xb3\xcek\x9bO\xa6h6\xd3\xa9wsJ5\x12\xcf\x0bxl\xc3Z\xb7h\xbd:\xcbU\x95/\xe4\xf9T\x86q\xc4\x9f    -  6!M>\xf2x\x91\x8ev\x1bz\x1a.\xd3\xd1O\xca\xd2\xb6\xa8\xfaBR\xe6{\xeau\xa1Y)R\x92\x94_z\x03\x90\x89)]\t@H\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00o\x00\xb7]f\x9b\xc3\   -  xc7\xce\x02\xa5hS\xc7\x13\xc6J\xa1R3Y\x8b\xca<~\xad\xb6Z6\x9bU\xdb\xdf]\xd0U"\xf1\x89H\xe1Gx\xbb?\x15\x88\xea6\xd1^\   -  x1c`{\xec\xa1\xc4\xbcO\x03\xfd$\xe8\x0b\xff\x00\xc9[?\xfc\xc7\xf4\x95\xb3\xff\x00\xe66\xdf\xbe\x07\xbe\xe2^#\x89x\x9   -  e\x0b\xfaK\xd9\xef\xf3\x0bo\xdf\x1f\xd2^\xcf\x7f\x98[~\xf8\x1e\xf7\x89x\x8e%\xe2x/\xe9/g\xbf\xcc-\xbf|\x7fI{=\xfeam\   -  xfb\xe0{\xde%\xe28\x97\x89\xe0\xbf\xa4\xbd\x9e\xff\x000\xb6\xfd\xf1\xfd%\xec\xf7\xf9\x85\xb7\xef\x81\xefx\x97\x88\xe   -  2G\x82\xfe\x92\xf6{\xfc\xc2\xdb\xf7\xc8\xfe\x926}\xf4\xd4\xad\x97\xfe`{\xd74\xbb\xc9R^\'\x82\x86\xf2t\tT\x8d5}o)I\xe   -  3\x94\xcfQmq\x0b\xeaq\xabi^2\xa6\xd6|\xd0;\\\xe4\x16\xe94\xd68\xb2\xd1p\t\xc8    -  \x94\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\xd2Yd\xb7\x85\xcc\xf3:\xde\xd6iZEeN\xf2\xf6\x8c\x1b\xee\x94\xb0   -  \x07\xa4\x8c\xd3\xe8TxW\xbc}\x9d\x8f\xa3\xa8\xdb~\xf8\xfe\x92v\x7f\xfc\xc2\xdb\xf7\xc0\xf7\x0e\xa4T\xb8[\xe6Kh\xf16\   -  xfb\xc2\xd0.k(\xd3\xbe\xb7\x94\xdfLL\xf5v\x95\xe3^\x94j\xc2JP\x92\xcah\x0eX)L\x9c\x81P!\x12\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\xfcU    -  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00o\x08\xa1TM<\x01X)R\xca\'    -  H!\xbc\x10\xa6\x80\xa2x\xc9i\xa9\xb7\xd5`_W\x8d\nnRiEuf/\xdb\xbd\xebh\xdb3J\xa7\x05\xd2w\x0b\xa4^:\x81\x91\xf5\rJ\xd   -  6\xc2\x84\xa7qV\x9d\x7f\xef\xea\xe2\xaa\xdb\xddB\nrQ\x8dNK&2\x9dj\xb2\x96]   -  I}\xa6H\xdf\xd7\xc2\x0e\xa7\xed\x98\xd0\n\xbc\xa5O\x97/\xb4yI\xfc\xb9}\xa5\x00\n\xfc\xa4\xfe\\\xbe\xd1\xe5\'\xf2\xe5   -  \xf6\x94\x00+\xf2\x93\xf9r\xfbG\x94\x9f\xcb\x97\xdaP\x00\xaf\xcaO\xe5\xcb\xed\x1eR\x7f._i@\x02\xbf)?\x97/\xb4yJ\x9f.   -  _i@\x03\x97\xa7\xd6\xab\x0b\xea\rT\x96T\xd7y\xbe\xfb\x84\xb8\xa9u\xb2\x14\xe5Y\xf15\x84h%\x97\xebt}\xa4o\x9fg\xa9\x7   -  fca\xeb@eZtcM\xb7\x1e\xf2\xe6\x02\xe8\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x15\xbfE?Q\xa4\xdd\xa6\xa   -  aN\x9e\xbf\x08\xc2m\'\x9e\xf3vk~\x8a~\xa3H\xbbO?\xed\x15?\xda\x06\x12UjG\x9a\xa9/\xb5\x87qW\x1f\xa4\x97\xdaZO\x90o\x   -  90\x1d\x9e\x83wZ\x86\xa7Bt\xeaIK\x89w\xfc\xe7\xd1m\x80\x9c\xaal\x9e\x979\xbc\xc9\xd1\x8eO\x9c:G\xeb\xf4}\xb5\xf7\x9f   -  Gwx\x9b\xd8\xbd/\x1d|\x84~\xe0=\x14d\xfc\xa3O\xa1x\xb5\x86\xa2\xb3\xd4\xae=\x00\xa9u$\x84H\x12\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x15v\xa3\xf8\t\xdao\xaa\xfe*\x90\x1d\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x00\xca   -  \xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\xac\xfc\xdeE\x8f\x8c\xb8zw   -  \x97\xaat-\xa4\xa2\x9e\x00\xba\xb1\x8eD\x9cg6\xb9\'\xcc\xea\xf5\x9d\xa2\xb0\xd1m\xe7;\xdb\x9aPqY\xc4\xa5\x8c\x81\xde   -  \xc9\xa5\x16\xdfDx\xad\xae\xdb\xed#gm\xaaJ\xad\xd5/+\x15\xe86aM\xe3\xef\xf6\x14\xa5V\xd7JS\x84\xf9\xa58\xbeF\xb8\xed   -  \x16\xd3\xea:\xed\xcdJ\x97\xb7\x12\xa8\xa4\xf3\x86\x06\\\xden\xfc/5\xb9\xce\xdbNn\x84"\xdaR\xa7.\xa6\x16\xbc\xd4\xae   -  \xb5\x1a\xd2\x9d\xfd\xc4\xe7\x9e~s:\xe5\x14\xba\x13<\xc9a\x81\x15\xe5\xe7at-\xa6\x92\xe8K\\\xc4p\xa5\xcc\x02I\xf5x\x   -  08\xbb\xc2\xaa\xc9B\x94\x1b\x93\xf0=6\x99\xb1Z\xbd\xe5\x8b\xafN\xc2\xbb\x8e3\x95\x00<\xa9\'*\xf2\xca\xbd\x8dYS\xb9\x   -  a3:rO\xe3,\x1c&\xf2\xc0\xb9\xc8\xae\x95YS\xa8\xa5\t\xb8I|dX\xc8|\xc0\xc8\xfb\x19\xbd\x1d[f+\xd3j\xbd[\x9aI\xfa\x0e\\   -  \x8d\x9d\xdd\xde\xf8\xb4\xcdv\x84?/\xb8\xa5m_\x1c\xa0\xdfVh\xd6\x0eE\xa5\xddkJ\xb1\xa9o7\t\xc5\xe54\x07\xd3\xad>\xf2   -  \x95\xf5\x18\xd7\xa7%*R\xe8\xd1\xc9\xff\x00\xe4\xf3}\x13Hw{\xbe\xcdOF\xf26\xda\x85Z\xb5\xa8&\x96<\r\xa5\xd8\xad\xe2i   -  \x1bAeNq\xb9\xa5J\xab\xf8\x92\x9f0=\xf1(\xe2\xaa\xaar\x84\xa9\xc98>\xf4rS\xe4\x05D\x94\x92\x04\x80\x80\x00\x00\x00\x   -  08\x93\xc0\x12\x0bnm\xf4L\x98\xbf\x16\x05`\xb76\xfb\x99\x11\x93]@\xba\nS\xc9    -  H\x00\x00\x00\x00\x00\x00\x19\x00\x00\x0f\xa0\x00Q\x17\xe2R\xa7\xc6\xdaO\xa0\x17A\xc7\x94jqr|\x8b\x8f-u\xc3\x02\xe0\   -  xc9\xc7P\xa8\xfe1qFX\xe6\x05\xc0B%\x00\x00\x00\x00d\x00\x03    -  \x03\x19\x0f\xa0\x14\x02@\x04T\x8a\x1c\x92\xea\xc9R\xf0\x02\xa0[r\nO\xbc\x0b\x80\xa1>ey\x00\x00\x00SS\xd0~\xa2\xa2\x   -  9a\x9e\x83\xf5\x01\xf3\xeb\x7f_\x08:\x9f\xb6cS%o\xeb\xe1\x07S\xf6\xccj\x00\x0c|\xe5\xf8Q\x8c\xa7\x08\xa9.`X\x06j\xd9   -  \x1d\xc6\xea\x1bI\xa4\xd1\xbe\xa1u\x08B\xaa\xcaM\x1d\xbc\xbb5k\x1cxW\xf4\xf1\xea\x03_\x81\xb0\x7f\xfai\xd5\xff\x00\x   -  cc)}\x83\xff\x00M:\xbf\xf9\x85/\xb0\r|\x06\xc1\xff\x00\xe9\xa7W\xff\x000\xa5\xf6\x0f\xfd4\xea\xff\x00\xe6\x14\xbe\xc   -  05\xf0\x1b\x07\xff\x00\xa6\x9d_\xfc\xc2\x97\xd8\x1ff\xbdZ1\x7f\xd7\xe9\xb7\xea\x03\x01Y\xfe\xb7G\xdaF\xf7\xf6{\xf7\x   -  9d\x0fY\x84,;7\xea\xd4\xee\xe9\xce\xad\xf57\x15$\xfa\x1b7\xbb\xcd\x98{/\xa0\xc6\xcau#9u\xca\x03\xd7A\xf2*8p\x94\xe3.   -  yh\xbe\xaa\xe7\xb9\x81t\x14\'\x90\xe5\x80+\x05\xbf)\xf3\x15\'\x90*\x04"@\x00q\xddf\xaa8\xf0\xbfX\x1c\x80q\x93\x93\xa   -  d\x9e/7\xc0\xbe\xe4\xb1\xd4\n\x81b\x9b\x92\x9br|\xbb\x8a\xa5\'\x90*\xac\xff\x005?S4\x7f\xb4\xf3\xfe\xd1S\xfd\xa6\xed   -  \xd5\x93\xf2R\xf53H\xfbN\xaf\xed\x15?\xda\x06\x10A\x84\x18\x1c\xbd\'\xf5\xfa>\xda\xfb\xcf\xa4;\xb7\xf7\x9b\xa5}\x04~   -  \xe3\xe6\xf6\x93\xfa\xfd\x1fm}\xe7\xd2\x1d\xdb\xfb\xcd\xd2\xbe\x82?p\x1e\x9d\xa4A#\x00@\'\x03\x00\x00\x00\x00o\x1dKS   -  \x9f\x83\x02\xe88\xf1\xe2\x7f\x18\xaeJN>l\xb9\x81t\x16#\x19\xafJY.\xc4\n\x81\x04\x80\x03#    -  \x00\xc8\x00\x0b\x15\xe7(\xce8\xce\n\xdc\xf2\xb90.\x02\xde%\xe2D\xb8\x94^:\x81td\xb1Jo\xe3d\xb9\x9c\xf4\x02\xbc\x82\   -  x85\x92\xa0$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\x   -  b4\xdfU\xfcU    -  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  3\x00\nd\xb2P\xd1q\x90\xda\x03\x1c\xef_m\xe8lf\x9e\xea6\xd5j\x8b\xcd\xf5\x9ag\xbc-\xe2j\xdbSu5q]\xf9\x1c\xe5a\xb4g^\   -  xd7u$\xa8Y(7\xcf\xa9\xa9\xd2o8\x97P"s\x9dIfM\xb7\xf3\x95E\xf8\x94\xa6J`W\xc5\xcf\x05S\x8bK%\xb8\xc3\x8a]y\x1d\x8e\x9   -  f\xa6\\j\x15\xa1J\xc6.\xac\xe4\xf0\x90\x1dn[|\x93;\xcd\x9c\xd9mKh.#J\xca\x8c\xf2\xde2\xe2\xf0f\xbd\xdc\xee&\xee\xfet   -  \xae6\x82\x8dKx\xbc?7=\r\x93\xd9=\x8f\xd1\xf6z\xde4\xad\xe8\xd3\x94\xa2\xb1\xc5(,\x81\x847e\xb8Jv\xea\x8d\xd6\xd0\xd   -  2R\x97&\xb8Y\xb0\xdaf\x87i\xa6\xd8+;Z0Tq\x8eqGc.\x19(\xacp\xa5\xd1"\xfa\xe8\x06%\xdb\xfd\xcch\xbbAmV\xb5\n\x18\xbc|\   -  xd3\xe4\x91\xab\x9b}\xba=gf\xa7R\xab\xa6\xa5Ae\xae\x05\x9eF\xfc\xce\xa3R\xe1}\x19\xc4\xd4t\xbb[\xebi\xd3\xadF\x9dE5\   -  x87\xc5\x14\xc0\xf9\x8b:u)\xb6\xa7\tE\xae\xe6\xb0S\x14\xe4\xf0\x8d\xc6\xde>\xe2\xacu\x05R\xebLS\xfc\xa2\\\xf8"\xb0\x   -  8dj\xda\xfd\x84\xd4\xf6Z\xeaq\xd4\xe8J\x95%\xd1\xe4\x0f%\x1a2\x94\x1c\x97DP^\xabQ/6\x1e\x8b,\xb0+\x85N\x15\x87\xd0\x   -  ectMr\xebH\xbb\x8d\xcd\xadY\xc6\xa4zsx:\xa6\x88`m\x8e\xe37\xc3u\xab^Q\xd2\xb5\x9a\x8eu\xa6\xf8i\xe1w\x1b9FJPM\x1fv\xbdGP\xcf;\xcb\x8f\xe22\x97\xaaj\x0b\xff\x00\xb9q\xfcF\x07\xd1z[}\xa3T\x9ca\x1b\x88e\xbczh\xf5\x14n\xa9\xd6\x8   -  4eNI\xc6K)\xa6|\xc6\xb3\xd6o\xe9]R\x9b\xbc\xaf\x88\xc9?\xd23d\xf6s}\xd6zN\xca\xaar\xb9\x8c\xefc\x14\x94f\xf3\xdc\x06   -  \xd0_\xeav\xb6T\'V\xbdzqQYi\xcd#\x1a\xed.\xfb\xf6kE\xe2\x85iT\x94\xd7/1\xe4\xd4\xed\xb0\xden\xab\xb45k\xba\x95\xe7J\   -  r\xbe\x15\t\xb5\x93\xc0\xd7\xba\xb9\x9cx\xabT\x9dL\xf7\xcaY\x03lo\xbbHi|\xff\x00\'\x95U\xe1\x94t\xb5\xbbF\xc5\xcf\xf   -  3u&\xa3\xea5m\xb6\xd8\x03k-;G[\xaa\x91\xf2\xf3\x9b\x8f~\x11\xect>\xd0\xdb5{UR\xaa\xeb)\xbeYk\xfe\r"+\xa7)FY\x84\x9ce   -  \xe2\x98\x1fJt\x1d\xb0\xd2\xb5\x9aQ\x9d\xb5zi>\xe9Md\xf4Tj\xc2\xa2\xcd9)/\x14\xf2|\xd0\xd16\x93S\xd2.\xa3R\x95\xdd~_   -  \x17\xca<\x19\xefw{\xfa\xb9\xb3\x9d+MM\xd3\x8d\'\xc9\xc9\xbc\xb06\xd6\xa5X\xc3\x19&5\x14\x8f\'\xb2\xdbOc\xb54\xa3Z\x   -  d2\xb2\x9f\n\xcf#\xd4z\\\xba    -  /e\x12\x8b0\xca\x96\x174^\x00\xca[%\x94I\x81-\xe0B\xa2\x93h\xb7\'\xc8\xe3Qu*NNK\x1c/\x96;\xc0\xe7JI\x16\xae.\xa8\xd0   -  \xa6\xe5V\xa4"\x97\x8bH\xf1\xfbm\xb7\xdaN\xca\xdaJW\xf7*\x9dly\xa9\xf8\x9a\xb5\xbc\x8d\xf4\xea:\xc5j\xb4l\xa4\xa3A\x   -  f4\x94%\x86\x06\xcd\xed>\xf4t\x1d\x06\x13\xfc\xa6\xb7\x13\x8f\xc8\x92f-\xd6{Fh\xb4\xa5%\xa7:\xca_:52\xf7S\xbd\xbc\xa   -  b)W\xb9\xad>\'\x9c9\xb6q%\x17\x9e}@\xd8\x8dW\xb4v\xb0\xe6\xff\x00!\xac\x94{\xb2\x8bZ\x7fh\xbdo\x8f\xfa\xddd\xd7\xcc\   -  x8d|I\x15r\xc0\x1ba\xa3v\x8e\xb4\x84s\xa8J\xa3\xf5#!l\xe6\xfcvwZq\x85)\xce2}x\xb9\x1a\x1c\x94\xa5\x16\xf1\xe6\x95\xd   -  1\xba\xabl\xf3B\xb4\xe2\xff\x00\xed\x96\x00\xfas\xa6\xeb\x16z\x85\xbcj\xdb\xd7\xa7%.\xee5\x93\x9f\xc6\xb1\x9c\xf2>w\   -  xecV\xf2u]\x02\xe6-\xdcT\xa9\x08\xf4S\x9bh\xd9\xbd\xd9\xef\xaa\xcbh\xdd+=N\xb4)\\>\x8a8\x03;9\xa4\xb2G\x94X82\xadNj\   -  x94\xe9\xc9\xb5%\x98\xfc\xe5\xde\x14\xd7\x13o\x8b\xc0\x0eG\x1aee\x8am\xb5\x96\x8b\xb9x\x02rFH\xc9N@\xad>d\xf1\xac\xe   -  0\xe3Wu1\xf9\xb5\x96yM\xb6\xdb]7dt\xf9\xd4\xbd\xb8P\xac\x96R`z\xda\xf7Th&\xea\xd4\x84\x12\xf9O\x07\x85\xda\xcd\xeah;   -  9\x95sW\x8eK\x97\x99$\xcdc\xde.\xfbu\x1d\xa0\xa9R\x85\x94\xa3\n+*2\xa6\xf0\xda\xfd\x86\x1c\xbf\xd4o\xee\xaaJw5\xea\x   -  cf?*m\x81\xb6z\xafh\xbd\x13\xcaJ6\xee\xb2}\xdc\x8e\x86]\xa4"\xa4\xd4\'>\x1e\xeeF\xae(\xb9so\x99C\xea\x06\xda\xe9\x1d   -  \xa3\xac\xa7S\x17\xb3\xa8\xd7\xcc\x8fw\xa4o\xd7f\xaf|\x9c8\xaa)\xc9\xe3\x99\xa2\x11\xeb\xd7\x05\xfau\xebSy\xa7RK\x1d   -  \xe9\x81\xf4\xcfJ\xd6\xecu*\x11\xabm^\x9c\x93\xff\x00\xbdd\xedT\xe2\xe3\x94\xf2\x8f\x9d\xdb!\xbc=Sg\xa9\xc6t\xae*U\x   -  92~\x8c\xe6\xda6\x97t\x9b\xdd\xb2\xda\x1a\x10\xb4\xd4\xebB\x9d\xe4\xf9F\x11\xef\x035yU\x8fYZ\x91\xc6\xa0\xe1(\xe6\x0   -  f(\xbc\x9a\xc8\x172EOB^\xa22D\xdf\x99/P\x1f>\xf7\xf7\xf0\x85\xa9}!\x8d\x97#$\xef\xef\xe1\x0bR\xfaC\x1b\x01TR\x94\xb0   -  \xcb\x96\x91N\xea+\xbb%\xa8r\x91z\xcf\x9d\xc2\xf5\x81\xbf\xfb\x96Q\xa5\xbb\xad1\xd3\\\xdcL\x85E9\xd3\xf3\xd2\xc9\x8e   -  \xb7\x1f\x99\xee\xff\x00LO\xa2\x89\x92\xa2\xb0\xb9\x01O\x92\x88\xf2Q\xf0.\x00-\xf9(\xf8\x0f%\x1f\x02\xe0\x02\xdf\x92   -  \x8f\x81D\xa1\x89.\x14\x8b\xe5\x0f\xa8\x14\xd4YK\x85$U\xe4\xd2\x8eHo\x05M\xe6\x00a\xfd\xefoR\x9e\xc4\xde\xd0\xa0\xe5   -  $\xea,\xf2F3\x9fh\xee~mI~\xe9\xd3v\xbb\x7f\xf5\xdb\x1fd\xd7v\x06\xd0.\xd2\x13\xfe\xf2_a~\xcb\xb4l*\\\xc1W\xa9>\x06\x   -  d2\xe4\x8dU/\xda~\x9e\x9f\xb4\xbe\xf0>\x96l\xae\xb1\xfc\xb3\xa5[\xdeA\xbe\n\xb0RY;\xe5\xd0\xf0\xdb\xa6\xf7\x9b\xa6}\   -  x0cOp\x98\x15"\xac\x94\x92\x04\x98\xdb{[}Kb,!qq\x95\x1a\x8f\x0b\x85\x19$\xd6\xbe\xd8~\xf7l\xbe\x90\x0f?>\xd1x\xa8\xf   -  8jO\x87\xd4U\xff\x00\xa8\xcf\xff\x00d\xbe\xc3W\x99\x00m\x05\x0e\xd1\xd2\xf2\xeb\xcbT\x97\x93\xcfr3\xf6\xee\xb6\xae\x   -  1bW\xa3R\xbe\xa4\xdb\x84\xd7y\xf3\x84\xde\xbe\xcc\xfe\xf1l\xfd@f\x1a\xbf\xa2\x97\xa8\xd2^\xd3\x9e\xf8i\xfe\xd3w+/\xc   -  dK\xd4\xcd$\xed:\xb1\xb44\xff\x00h\x185\x06J\x0f\xa0\x1c\xad\'\xf5\xfa>\xda\xfb\xcf\xa4;\xb7\xf7\x9b\xa5}\x0cO\x9b\x   -  faG\xeb\xf4}\xb5\xf7\x9fH7o\xef;K\xfa\x18\x81\xe9\xa5\xc9\x14yL,\xb2\xb7\xd0\xe3\xbeS\xcb\xe8\x05\xe7Q(\xe4F\xa2\x91   -  k\x83/\x8b,\xa2\xe2Q\x857VO\n    -  re4\xba\xb3\xad\xd5\xf5\xcb\x1d.\xdeUnn)$\xba\xae5\x93\r\xef3}\x1av\x83:\xd6zu\xc4*_G*P\x969\x1a\xb5\xb6\x9b{\xab\xe   -  d\x15\xf4\xea\xd4\xb9\xabI?\x8b\n\x8d    -  6\xd7h\xb7\xfb\xb3\x16\x0e\xa5\x04\xea\xba\xab\x96W4c\x9dk\xb4M4\xdf\xf2t\xe6\x9fvQ\xacu\xaej\xd4\x8f\x9d)I\xf7\xb6\   -  xf2q\xd4[\xea\x06z\x97h\x8d\xa0\xfc\xa1\xb8\xd7\x8f\x93\xf5\x1d\xc5\x87h\xddB2_\x95U\xca\xef\xc25\xc1@\xa2k\x98\x1b\   -  x89\xa0\xf6\x8d\xd1\xea\xce1\xbfu\x9b~\x08\xcb[-\xbc-\x17h)\xc6V\x95\xe3\x1c\xf7NI\x1f9\xe9f\x97\x9e\x8e\xcfO\xd6\xa   -  f\xackF\xb5\xad\xd5h\xf0\xbc\xb8\xa9\xb4\x80\xfaeJ\xe2\x95W\xf9\xba\x91\x97\xa9\xe4\xb9R\\1\xc9\xa5{\xbd\xdf\xa6\xa1   -  \xa5\xd7\xa3J\xf1\xc2T\xb2\x94\xa57\x9eF\xd5l\x9e\xdb\xe8\xfbOiNz}\xca\xab6\x97\x12X\xe4\xc0\xf51\x96VJ\x8bI\xa2\xa4   -  \xc0\xb8;\x8aS\xc9=\xc0b\xed\xf2o\x11lL(,\xb5*\x8b+\x08\xc1\xd5\xbbD\xdf\xf9f\xe9\xd5j>\xa3\xd1\xf6\xc2Yz\x7f\xb2\xc   -  dNK\x9b\x03d\xd7h\xdb\xfc~\x95\xfe\xe9\xdal\xff\x00hj\xd77\xf4\xe9]T\x93\x8c\x9e9#V\x0e\xdbe\xe9\xd4\xab\xacP\x85(\x   -  f1I\xc9\x01\xf4\x87C\xd5\xa3\xa9i6\xf7qM\xc6\xacT\x91\xd8*\xb1Q\xe2\x94\xe3\x15\xff\x00s\xc1\x8f\xf4\x9d\xa7\xb0\xd9   -  m\x83\xb0\xa9\xaa\xd4\x8d)*)\xa4\xcc\x15\xbcm\xfa\\\xdf:\x96\xfa,\xa1*K\xe3E\xe1\x81\xb5:\x8e\xbba\xa7\xd1u+\xdc\xd1   -  \xc2\xeeSG\x91\xb8\xde\xde\xce\xd0\xad\xe4\xe5U\xb9g\x1c\x9a4_S\xda\xfd[P\x94\x9d[\xdb\x85\x97\xd1Tx:\xab[\xcb\xba\x   -  97p\xcd\xc5V\xdc\x97Y0>\x99\xe9Z\xa5\rJ\xc6\x8d\xd5\xbe]:\xab19\xe7\x83\xdd\x07\x13\xd8=1\xc9\xb9K\xc9.\xa7\xb9\xa6\   -  xdb^wP+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7   -  f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\xc0`Q&P\xdbe\xc6P\xd0\x1a\xbf\xdb!\xf0P\xd3\\yg\xc0\xd5\x1c\xf8\x9b_\xdb/\xf5}0\xd5\x00\x19\x08\x82\xe7\x0f8\x8   -  1\x93\xb7_\xba\xeb\xad\xaf\xaa\xa7\xe5gN\x9a\xe7\x9ce3k6\x07uZV\xcd\xd0\xa7*\xd4)\\U]\xee<\xce\x8b\xb3M*+giJ\x11\xc4   -  \xdc\x16Y\x9b\x1c$\xc0\xb5J\x8d8AF\x10Q\x8aXI\x15\xaap\xcf\xa2\x8a\xd4pH\x14\xb8/\x02pU\x81\x80(pO\xaa\rar+\xc1\rd\x   -  0bN)\xf5<\xfe\xd4\xec\x8e\x99\xb4V\x93\xa5ykJS\x97\xc7\x92=\'\x01O\x93\x9b\x97\'\xc8\rF\xde\x8e\xe2\xe5\xa5S\xad\x7f   -  \xa6\xd5u\xe3\x1e~N\x11\xff\x00\x83^/-j\xdb\xdeN\x8dx\xbar\x8b\xc3O\xb8\xfaO\xb5\xf4\xf8tZ\xef\xbb\x85\xe4\xf9\xeb\x   -  bc)\xaf\xe7^\xa1\x95\xff\x00\xc8\xf0\x07\x9b\x94xe\x8c\xe4\xa1\xaeeI\xe4\x890=\xb6\xe6\x97\xf6\xfbN\xf6\x8f\xa1ZO\xe   -  a4\xbdG\xcfm\xccs\xdb\xfd;\xda>\x86iQ\xfe\xa3K\xd4\x07!\xb3V\xfbW6\xabK\x1f$\xday#U{X\xc9+\x89G\xbf\x84\rZ\xcb\xf1\x   -  04dd\t\xc1<\xdfVB*\xe1~\x0c\tJ]q\x94\x8a\xaaNU#\x85\x17\x84B\x94\xe1\xc9g\x0c\x99NQ\\\x93Y\x02\xce\x02*\xa7\tTx\x8am   -  \x9c\xa8\xe9\xd7nm\x9d\xce\xf0\xb6\xae\x8e\xccl\x   -  c5\xcd\xe5y\xaf)\x1c\xa5\x14\xf9\x9a)\xb6\xdbMy\xb4\xba\xd5K\x9b\x9a\x8et\x94\xdb\x82}\xc8\t\xdb\r\xab\xd46\x92\xfe\   -  xa5\xc5\xddz\x8e\x12yT\xe4\xfa\x1enM\xbe\xac\x99\xbe)\xb7\xdcC\x02\xde\x12e3y.\xd2\x83\xab"\xe3\   -  xf4_\xa8\x0f\x9f\xbb\xfa\xf8B\xd4\xbe\x90\xc6\xe8\xc9[\xfa_\xfb\x83\xa9{f4o\x0c\x03\xe4\xf9\x17\xad\xb9M2\xc6J\xe9\x   -  d4\xe0\xee\x03\xe8.\xe2%O\xfa8\xd3\x1b\x92\xcf\x01\x91UZ\x7f)\x1f;4}\xe9\xedN\x8faN\xcfO\xd4\'J\xde\x9a\xc4b\xb3\xcb   -  \xfdNz\xdf>\xda\x7f\x9bO\xfd\x7f\xdc\x0f\xa0\xdeV\x9f\xca\x1eV\x9f\x89\xf3\xf1o\xa7m\x17\xff\x00\x96\x9f\xfa\xff\x00   -  \xb9?\xd3V\xda\x7f\x9bO\xfd\x7f\xdc\x0f\xa0^V\x9f\x88\xf2\xb4\xfcO\x9f\xbf\xd3V\xda\x7f\x9bO\xfd\x7f\xdc\x7fM[i\xfem   -  ?\xf5\xff\x00p>\x81yZ~%\xaa\xf8\x9c[\x8c\xb1\x83@\xbf\xa6\xad\xb4\xff\x006\x9f\xfa\xff\x00\xb90\xdff\xdaF\xa4s\xaa\x   -  d4p\xef\\\xf9\xff\x00\xa8\x1b\xf5E\xa9R^vYs>c1\x0e\xe36\xb6\xf3it\x9au/jJsk-\xb3/\xa5\xf9\xb6\x06\x9c\xf6\xba\x7f\xf   -  5\xcb\x1fd\xd7\x8c\x9b\x11\xda\xed\x7f\xd7l}\x93]\xc0\x82\xfd\xa7\xe9\xe9\xfbK\xef,\x97\xed?OK\xdb_x\x1fD7O\xef3L\xf   -  a\x18\x9e\xdd\x1e\'t\xfe\xf3t\xcf\xa1\x89\xee\x17@\x08\x90\x00\x9e\xe3Z\xfba\xfb\xde\xb2\xfaCe;\x8dk\xed\x87\xefv\xc   -  b\xe9\x00\xd4\x16A,\x80\x06\xf5\xf6g\xf7\x8bg\xea4P\xde\xbe\xcc\xfe\xf1l\xfd@fJ\xdf\xa2\x97\xa9\x9aI\xda{\xdf\r?\xda   -  n\xddo\xd1K\xd4\xcd$\xed=\xef\x86\x9f\xed\x03\x07    -  \xd7!\x12_@9ZB\xfe\xbdG\xdb_y\xf4\x7fw\\\xb6;J\xfa\x08\x9f8t\x7f\xd7h\xfbk\xef>\x8e\xee\xed\xe3ct\xaf\xa0\x8f\xdc\x0   -  7\xa5m\xe0\xb7\xc3\xcb\x99[e\xa9TQ\xe2\xcfD\xb3\x908\xfa\x85zV\x94\xa5^\xbdUN\x9cW<\x9a\xc5\xbf-\xefJS\x9d\x86\x8d]\   -  xc1\xac\xc5\xce\x9c\x8e\xd3\xb4^\xf3\xff\x00\x93\xb8\xf4\x8d>\xab\xe3\x9a\xf4\xa2\xf2\x91\xa9\xd7U\xea]\\J\xbdifryl\   -  x0b\xf7\x97U\xefngquVUj\xcb\xac\xa5\xd5\x9cf\xb8\xa5\xe1\xf3\x85.E2\x92\xef\x02q\x8e\xbc\x89E\x11|r\xc390\xb6\xadRIS   -  \x84\xa7\x9f\x04\x05\x92$\xb2sg\xa5\xdf\xa7\x85g]\xfc\xea\x0c\xa6Z}\xe4#\xc5;j\xb1_\xe9\x92[\r\xa6c\xfb\xb4{X\xf4<6\xe9\xaaI\xec^\x9b\x19BPj\x9a\xe4\xd   -  1\xeec\xd0\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\x   -  d5\x7f\x15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\xc0\x02\x92\x1a\xe6T\xc6\x00\xd5\xde\xd9k\xfa\xbe\x9aj~\r\xb2\xed\x95\xfa\r4\xd4\xfc\x01Iw>\x89o\x04\xfcd\   -  x06\xef\xf6h\xe7\xb3\xb4\xbd\x84g\x14\xb9s0ofo{\xf4\xfd\x84g\x16\xf2\x044\x12\xc1    -  \x00\x00\x00\x04\xa0\x18\t\x02r\x07G\xb6~\xe1\\{,\xf9\xd9\xbc/}W\xff\x00H\xcf\xa2[d\xff\x00\xe8W\x1e\xcb>v\xef\x0b\x   -  dfU\xff\x00\xd20<\xe2\x12!\x06\x07\xba\xdc\xaf\xc2\x06\x9d\xed\x1fC\xb4\xa5\xfdJ\x9f\xa8\xf9\xe7\xb95\x9d\xe0i\xde\x   -  d1\xf47K\xfdN\x9f\xa8\x0eQ\xaa\x1d\xad?]~\xc9\xb5\xe6\xa8v\xb5\xfdu\xfb    -  j\xd0\x00\t\xef\xe4_\x8dJ\x98\xe5\x82\xc1v\x94\x1bY\xcb\x02\xed>)T\x8eb\xdc\xbb\x92FH\xd8\xad\xd6k{]*u(QJ\xdda\xcb\x   -  89c\x91\xe97\x11\xbbYm\x15\xeco\xef!/%FI\xa5\x8c\xa6\x8d\xc1\xd14\xcb]2\xda4-\xe8S\xa4\xa2\xb1\x98\xc7\x19\x03\x0bl\   -  xa7g\xfd\x06\x95(\xd4\xbd\xa7S\xca\xa5\xcf\x0f\xbc\xf6\x96{\xa6\xd9\xca\x14\xdd5FO\xd6\x8c\x8f\x18\xe3\xa2\xe4\x14V@   -  \xc5\xfa\x8e\xe4vb\xfa\x94\xbc\xa5)\xa6\xfa`\xc5;q\xd9\xe9\xd1\xa39\xe8\x14\xfas\xf3\x99\xb5\x04J*K\x12Y^\x0c\x0f\x9   -  a\x9bO\xb3z\x86\xcd\xdf\xca\xd7P\xa5%5\xde\x93\xc1\xd3\x1b\xf3\xbdm\x80\xb3\xda\xbd6\xb5\x1f!\nuRrU!\x1ef\x8f\xedn\x   -  87q\xa2j\xb5\xadn)\xb8F\x9c\x9cb\xdfz\x03\xa5\xee+\xa5W\x9a\x8c\xb9c\xa3-t\r\xe5au\x03d;7m\xd4\xed/\xe9h\xd7u_\x0c\x   -  b9\xac\xb3m\xed\xaa\xaa\x90\x8c\xd78\xc9e\x1f4\xf6KU\xad\xa4\xeb\x14+\xd2o\x8dI.\xbf9\xf4\x1fwz\xcc5m\x9c\xb3\xa8\xe   -  4\x9c\xd55\xc4\x07\xacG\x1e\xf6\xb4h[\xd4\xab7\xe6\xc192\xf6O\x1d\xbd\r\xa0\x86\x81\xb3W5j4\xb8\xe0\xe2\xb3\xea\x03U   -  \xfbFm\xd3\xd6\xb5\xd9Y\xd8Tn\xde+\x86K=\xe6\x10M\xae\xa7+[\xba\x9d\xd6\xadu^RrR\xa8\xda\xcb\xf9\xce\x0f\x16@\xbb\x9   -  4\x1f4Z\xe2\xe6\x8fK\xb1;1{\xb5\x1a\xdd+-:\x94\xaa\xbc\xa7,w    -  *\xd8\xfd\x90\xd4\xf6\xa2\xf2\x16\xdae&\xe7\'\xd5\xa7\x83cv3\xb3\xcd\xbciR\xa9\xaf\xd3~U/\x8a\xcc\xb5\xbb]\x88\xd3\x   -  b6_E\xa5N\x9d8J\xe5\xc59I\xc7\x9ag\xb7M\xa5\x80<&\x97\xba\xbd\x9d\xd3\xe9ES\xa2\xde\x876\xa3\xc8\xf1\x1b\xc8\xd9\x1b]\xa1\xd1\xae<\xb5(\xba\x8a\r\xc5\xe3\xbc\x0f\x9d\xde%,\xef6\xb7G\x   -  a9\xa0\xeb\x95\xad\xab\xc5\xc7\xcexO\xc3\'B\xde[\x02s\x87\x93`{/\xedD\xed5\xf9Z\xd7\x9e(p\xe1,\x9a\xf8z\x9d\x80\xd5\   -  xe7\xa6\xeb\xf6n\x9b\xe1\xe2\xa9\x14\xf1\xeb\x03\xe9\r\x19\xc6\xa58\xca=\x1a\xc9\\\xbd\x17\xea:\xdd\x9f\xac\xab\xe8\   -  xf6\x93\x8b\xcei\xc5\xbf\xb0\xec\xdf\xa2\xfd@|\xff\x00\xdf\xd7\xc2\x0e\xa5\xf4\x8c\xc6R\xf4\x8c\x9b\xbf\x9c\x7fH:\x9   -  7\xd2\x18\xca^\x90\x14\x82Y\x00\n\xd1J$\t\x00\x00\x00\x00)\x97R\xa2\x99u\x03r{,\xf3\xd1\xa9\xfb&\xc2\xa5\xe63^\xbb,{   -  \x8dO\xd96\x19z\x0c\r:\xedv\xbf\xeb\xb6>\xc9\xae\xed\x1b\x13\xda\xef\xdd\xdb\x1fd\xd7v\x058/\xda/\xcf\xd2\xf6\xd7\xd   -  eY/\xd9\xfe\x9e\x97\xb6\xbe\xf0>\x88\xee\x9d\x7fct\xcf\xa1\x89\xed\xd2\xe4x\x9d\xd3\xfb\xcd\xd3>\x86\'\xb7\x020H\x00   -  \rk\xed\x87\xefv\xcb\xe9\r\x945\xaf\xb6\x1f\xbd\xdb/\xa4\x03PY\x04\xb2\x00\x1b\xd7\xd9\x9f\xde-\x9f\xa8\xd1Cz\xfb3\x   -  fb\xc5\xb3\xf5\x01\x99+~\x8a^\xa6i\'i\xef|4\xff\x00i\xbbu\xbfE/S4\x93\xb4\xf7\xbe\x1a\x7f\xb4\x0c\x1d\x12_B"K\xe8\x0   -  7/G\xfdv\x8f\xb6\xbe\xf3\xe8\xe6\xef=\xe6\xe9_C\x1f\xb8\xf9\xc7\xa3\xfe\xbbG\xdb_y\xf4sw\x9e\xf3t\xaf\xa1\x8f\xdc\x0   -  7\xa4|\xd1\xe2\xb7\xa5\xb4\x90\xd9\x8d\x9c\xadr\xe6\x93\x9aqG\xb5}\rO\xedC\xb5R\xafySD\x8c\xf0\xe1\xe7a05\xf7kuk\x8d   -  cY\xafqq.,\xcd\xb5\xcf\xb8\xe9\x912\x93ry\t6\xf0\xba\x80.\xc2\x87\x94\x8aT\xe3)To\x1c\x96Kq\xa7\x99(\xb7\x89x\x19\xe   -  fp\xfb\xb9\xad\xaaN\x9d\xfd\xe5\xbems\xe95\x94\x07\x9d\xdd\x9e\xe6\xb5]\xa5\xabN\xe2\xe2\x9aV\x7f\x1b<\x99\xb0\xfb5\   -  xb8\xcd\x13N\x8a\x9dzRr\x8f\xed2~\x8b\xa6Z\xe9\xd4)\xd3\xb5\x8ca\x18\xac5\x15\x83\xb9N8\xea\x07\x85\xa5\xbb\xfd\n+\x   -  86\x9d\x0e\x7f\x86,\xabQ\xd6\xab)\xcb\xbd\xe4\xb5\xc8g\xe7\x0   -  2\xb1\x92\x8c\x93\x902F\xe3uu\xa4ml*5\x9e6\xa2o\xb6\x97u\xf9M\x85\x19\xb8\xf0\xf1E3\xe6\xe6\xc7\xdcJ\x8e\xd0\xd98ef\   -  xacW\xfa\x9fF\xf6\x7f\xcf\xd1l\xa4\x9f\xff\x00\x14~\xe0;\x19z/\xd4hWhJ\xbc[u\x7f\x1ct\x99\xbe\xb2~k\xf5\x1a\t\xda\t\   -  xff\x00o\xb5\x0fl\x0ca\xdeTR\xfa\x86\xc0\xef\xb62\x9cn\xb6\x9a\xc6\x8dH\xa7\x07<4\xcf\xa1\x1b\x01e\x1b=\x9c\xb5\xa7I   -  %\x05\x1eI\x1f>\xb7}\xef\xbbO\xfaD}\x13\xd8\xd5\xff\x00@\xb6\xf6@\xee\x11RD\xe1\x00"Q\xcf\xac\xa6T\xd4\xa2\xe3>q}Qp\   -  x01\xa4]\xab,h[m\xbbt)\xa8\'\x0e\xe3\x05\x1b\x01\xda\xd7\xdf\xa7\xfe\x06\xbf\x809\xda\x1c\xb8u{F\xba\xaa\x8b\xef8\'3   -  G\xf7V\xd7\xe9\x10\x1fDwU^w\x1b1o*\x8d\xb6\xa2\x97\xfa\x1e\xce^\x8b\xf5\x1e#t+\xfb+C\xd9_q\xeejz\x0f\xd4\x07\xcf\xbd   -  \xfd?\xfd\xc1\xd4\xbd\xb3\x19\xb7\x93%o\xef\xe1\x0bS\xf6\xd9\x8d@\x98G\x89\xe1\x15\xf9\x1c\xbc\'\xcf\xc0\xa6\x9c\xb8   -  %\x93\x91c\x0f)r\xa4\xfad\x0e\xd2\xd7c\xf5\xdb\xcbx\xd6\xb4\xd3n+S\x97IEu9\x11\xd8=\xa7\x7f\xfe\x1a\xef\xf7W\xfb\x9b   -  \xbb\xb9;+\x7f\xe6\x06\x9dQ\xc32q=\xed+5\xe5x\xb9p\xf8\x01\xf3\xa3\xf9\x81\xb4\xff\x00\xe4\xb7\x7f\xba\xbf\xdc\x7f06   -  \x9f\xfc\x96\xef\xf7W\xfb\x9fH\xbf&\xa5\xe0?&\xa5\xe0\x07\xcd\xdf\xe6\x06\xd3\xff\x00\x92\xdd\xfe\xea\xff\x00q\xfc\x   -  c0\xda\x7f\xf2[\xbf\xdd_\xee}"\xfc\x9a\x97\x80\xfc\x9a\x9f\x80\x1f7\x7f\x98\x1bO\xfeKw\xfb\xab\xfd\xc9\x8e\xef\xb6\x   -  9eRI\xe8\xd7i{+\xfd\xcf\xa4?\x93S\xf0-V\xa1Ma(\xf5\x03\n\xf6r\xd0\xaf\xf4}*\x9c/\xad\xeaQ|?\x19\x19\xc5z\x0c\xa2\x85   -  ?\'\x1cg\x91>w\x0b\xe6\x06\x9e\xf6\xbb\xf7v\xc7\xd95\xdc\xd8~\xd7|K\\\xb1\xf6Mw\xe6\x04\x97\xec\xff\x00OK\xdb_y\xc7\   -  xe6r,\xff\x00OK\xdb_x\x1fD\xb7O\xef7L\xfa\x18\x9e\xdc\xf1\x1b\xa7\xf7\x9b\xa6}\x0cOn\x00\x00\x00\xd6\xbe\xd8~\xf7l\x   -  be\x90\xd9CZ\xfba\xfb\xdd\xb2\xfa@5\x05\x90K    -  \x01\xbd}\x99\xfd\xe2\xd9\xfa\x8d\x147\xaf\xb3?\xbc[?P\x19\x92\xb7\xe8\xa5\xeaf\x92v\x9e\xf7\xc3O\xf6\x9b\xb7[\xf4R\   -  xf53I;O{\xe1\xa7\xfb@\xc1\xd1%\xf4"$\xbe\x80r\xf4\x7f\xd7h\xfbk\xef>\x8en\xf3\xden\x95\xf41\xfb\x8f\x9cz?\xeb\xb4}\x   -  b5\xf7\x9fG7y\xef7J\xfa\x18\xfd\xc0w:\xadwma^\xb2\xf8\x91l\xd0]\xf8j\x92\xd46\xe2\xe2\xbfG\xd0\xde\xfd\xaa\x97\x06\x   -  cf\xde\xcb\xc2\x9b>w\xef\x0e\xb3\xb8\xda[\x89g>s\xfb\xc0\xf3\xf5\xb1\xc4\xb0\xba\x94G\x93L\xa6rm\xa0\x98\x17\xa9MB\x   -  ba\xa9%\x9c3,l\xa6\xf8n6{F\x8d\x85\x0bi\xe1w\xa7\xff\x00&#]\n\xba\x81\x9b\xe1\xbf\xeb\xfaI\xaf!U\xe7\xe7\xff\x00\x91   -  \xff\x00\xa8-C\xfb\x8a\xbfo\xfc\x982\xa2\xc7R\xd8\x19\xde]\xa0\xb5\'\xd2\x8dU\xff\x00\x97\xfc\x94\xff\x00\xea\x07R\x   -  fe\xee\xb7\xef\x7f\xc9\x82\x80\x19\xd7\xff\x00P:\x96?E[\xf7\xbf\xe4K\xb4\x06\xa2\xf8qF\xaa\xc7\xfd\xdd\x7f\xd4\xc1@\   -  x0fY\xb7\x1b[Sj\xb5)\xdd\xd6\xa6\xe39x\x9ei?\x02\xca*\x8b\x02\xe6Y\x0er\x8bN/\x0c"b\x93\xfd\x80nOf-^W;7F\xc2^\x94y\x   -  f1\x19\xfb\x1c\x91\xaa\xdd\x95\xae\x9f\xe5\x8a\x8a\xee\x89\xb5+\x9a\x03X\xfb^\xf5\xb0\xf6MP^\x936\xc3\xb5\xe2\xe7a\x   -  ec\x9a\xa1\xf1\xd8\x14\xa6^\xa5O\x8e\x9e\x13\xe6\xde\x0b\'e\xa0Q\xf2\xf7\xf4\xa0\xfd\x17$\x06\xd5\xf6h\xd8Jzu\x8b\xd   -  4.\xe9\xaa\xd3\xac\x94\xa0\xe4\xbd\x13ch\xd2\xe0\x97\x17y\xe5wYmN\xdfc\xb4\xe5Ma\xf9%\x93\xd8\x00k$`\xa9u%\xa0(H\x94   -  0J@J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x   -  15H\x0e\xd4\x7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x03\x002S&Q\xc4\x06\xb2v\xc9\xfd_M5A\xf56\xb7\xb6D\xbf3\xa6\x1a\xa7>\x80RW\x18\xe1\xaf\x06\xca\n\x9c\x9f\x0e\x00\x   -  dd\x0e\xcd\xfa\x85\xac\xf4Z4T\xd2\x9cb\xb9d\xce\xd5+F\x9a\\]\x19\xf3\x97a\xf6\xe6\xff\x00en\xe1V\xdeR\x9cS\xcf\x0b|\   -  x8d\xa4\xdd\xee\xfc\xb4\xfdj\x9d:Z\xc4\xe9[O\xa7\xed\x03h#\x83\xa5jV\xba\x95\x18\xd4\xb4\xaa\xaaA\xf7\xa3\x9a\x9f   -  <\x01QR)*\xee\x02AO\x1a\xf1#8\xe8\x05}\xc5\x8a\x93\x8e\\~0\xa9s\ni\xba\x92I#\xc1m\xd6\xf34}\x9c\xa3?\xeb\x14\xa5r\xb   -  e#\x03\xb8\xda\xda\x94\xec\xf4K\x99U\x9aM\xa7\xd5\x9a\x03\xb7\x9c56\x9e\xfe\xa2i\xa9Tx2\x0e\xf4w\xc9\xa8m7\x94\xa1l\   -  xbc\x8d.\x99\x84\x8c5Z\xadJ\xd3s\xab7)>\xad\xb0(k\x0c\x82F\x00\xf7\xbb\x92x\xde\x06\x9d\xed\x9fB\xf4\xcf\xd4\xe9\xfa   -  \x8f\x9e{\x96\xe5\xb7\xfaw\xb4}\n\xd2\xdf\xf5:^\xa09\x8c\xd5\x0e\xd6\x9f\xae\xbfd\xda\xf6\xcdO\xedi\xfa\xeb\xf6@\xd5   -  \xc0\x00\x035\xf6d\x94!\xb7V\x89\xbef\x142>\xe2\xb5%\xa6m\xcd\xad\xc5ip\xd2\\\x9b`}\x08\xe1]QR:\xed\x1a\xf27\x96t\xa   -  bA\xe62YL\xec\x1b}\xc0TIo\x89\xf8\x15$\xc0\x96\x88\xc18\x18`P\xcf\x0b\xbez\x8a\x8e\xc1j\x13}\x14Ou7\xc2\xb2\xcc\'\xd   -  a+jiYl\xb5\xd6\x9b7\x15:\xd1\xe5\xe2\x06\x96\xea\xf5U[\xf9\xcdt\xc9\xc5|\xdeH\xa8\xf8\xa6\xdb\xf1\x11\x02\x99\xf46{\   -  xb2O\x9fJ\xe1\xf7)\x9a\xc94\xe4\xb0\xba\x9bU\xd9\x0e\xc6Q\xd2\xef\xeaTMK\x8b\x92\xf1\x03f\xe3\xe7L\xd4\xde\xd5\xb6\x   -  cd\\\xce\xafsf\xd7\xd2m7\xc5\xc9\x9a\xe1\xda\xc6\xc5GC\x8d\xc3\xef\x98\x1a\x8c\x89!\xfc\xc4\x810%\xa9I\xf2\x8b\x7f\x   -  b0S\xf4\xd1\xb1\xdb\x94\xdd\xe6\x87\xb5:U:\xb7\x17\t\\\xbe\xb0\xc0\x1a\xe2\xa9\xd4\x7f\x12_a>F\x7f&_a\xbc\xf1\xdcV\x   -  8b\x8f\xd2/\xdd\'\xfa\n\xd1\x7f\xbc_\xba\x06\x8b\xf9\x19\xfc\x99}\x83\xc8\xcf\xe4\xcb\xec7\xa3\xfa\n\xd1\x7f\xbc_\xb   -  a?\xa0\xad\x17\xfb\xc5\xfb\xa0h\xbf\x91\x9f\xc9\x97\xd8<\x8c\xfeL\xbe\xc3z?\xa0\xad\x17\xfb\xc5\xfb\xa4\x7fAZ/\xcb_\   -  xba\x06\x8cy\x19\xfc\x99}\x83\xc8\xcf\xe4\xcb\xec7\x96[\x8c\xd1\xba)\xac\xfb$\xff\x00Az\'\xf7\x8b\xf7@\xd1\x9f#?\x93   -  /\xb0y\x19\xfc\x99}\x86\xf3-\xc5\xe8\xad\xfak\xf7J\xd6\xe24_\x96\xbft\r0\xd9\x18Vz\xf5\x8ccM\xfe\x96=\xdf9\xf4_gZ\x8   -  6\x8fe\x1ey\xf2Q\xfb\x8f\x19\xa1\xeewF\xd2\xaecZ1\x84\xe5\x17\x95\x98\x99&\x95\xbc)S\x84"\x92QX@S&\xf8_\xa8\xd0^\xd0   -  \x1e\xff\x00\xb5\x1fl\xdf\xe9G\xcd~\xa3@{@\xacm\xfe\xa3\xed\x81\x8c\x1b\xe62\x1fQ\x80=\x16\xefW\xf6\xbbO\xfaD}\x14\x   -  d8\xefp-\xbd\x93\xe7n\xef\x17\xf6\xb7O\xfaD}\x14\xd8\xdfpm\xbd\x90;\x91\x82\xa1\x80)\xc0\xc1V\x08\xc0\x1aY\xda\xd7\x   -  df\xa3\xf6\r\x7f6\x07\xb5\xb2\xfe\xda?`\xd7\xf0    -  \xe6h\xfe\xea\xda\xfd"8\x989\x9a?\xba\xb6\xbfH\x80\xfa\x19\xba\x0fz\xb4=\x95\xf7\x1e\xe6\xa7\xa0\xfdG\x86\xdd\x07\xb   -  dZ\x1e\xca\xfb\x8fsS\xd0~\xa0>|\xef\xef\xe1\x0bS\xf6\xd9\x8dL\x95\xbf\xbf\x84-O\xdbf5\x02i\xfag&\xd3\x95u\xeb8\xd0\x   -  f4\x8eM\xb7+\x88z\xc0\xdf\xfd\xc6\xc7\xff\x00o4\xd6\xfeA\x90\x8f\x03\xb8\xe5\xff\x00\xb7:g\xb0{\xf4\x80\x95\x92\xa5\   -  xd0$N\x18\x02H\xc1    -  \x0br\xea\\(\x92\x02\x87\xd0\x84\xff\x006\xca\x9fB\x8cy\xad\x01\xa8\x1d\xaf_\xfdn\xc3\xd95\xd8\xd8\xfe\xd7\xb4[\xd6t   -  \xfcu\xe15\xd2\x14\xf3\xc5\xc4\xf0\xd0\x16\xcb\xf6\x7f\xa7\xa5\xed\xaf\xbc\xe3\xe4\xbbl\xdf\xe5\x14\xbd\xa5\xf7\x81\   -  xf4Wt\xfe\xf3t\xcf\xa1\x89\xed\xcf\x0b\xbaJ\x91\x96\xc5\xe9\xdc\xf9\xaa1=\xa7\x94\xf1\xe8\x05\xe0ZRy\xe6\xb9\x13\xc4   -  \xf3\xcb\xa0\x17\rk\xed\x87\xefz\xcb\xe9\r\x93\xcf#[;_5W@\xb4\x8cy\xc9O\x9a\x03PY\x04\xb4\xd3\xc3\'\x0c\nM\xeb\xec\x   -  cf\xef\x16\xcf\xd4h\xba\x83\x97N\xe3z\xbb5E\xc7`\xec\xdfv\x00\xccU\xbfE/S4\x93\xb4\xf7\xbe\x1a\x7f\xb4\xdd\x9a\xaf\x   -  f3R\xf5\x1aK\xdau\xff\x00hi\xfe\xd00|I}\nb\xca\x9f@9z?\xeb\xb4}\xb5\xf7\x9fG7y\xef7J\xfa\x18\xfd\xc7\xce=\x1f\xf5\xd   -  a>\xda\xfb\xcf\xa3\x9b\xbc\xf7\x9b\xa5}\x0c~\xe09[b\xb8\xb6kPK\xfb\xa9\x1f;\xb6\xb9y\x1d~\xe5K\xaf\x13\xeb\xeb>\x8c\   -  xed\x15\'_E\xbb\xa6\xba\xca\x9bG\xcfm\xeb\xd8\xca\xc3j\xee)\xc9a\xe5\xbc\x01\xe3d\xf3&B\xeb\xcf\xa0\x00r8\xe3\xc1\xc   -  3\x1c\xe4\xa2\x9a\xa9Ny\xe0\x97\xd8w\x9b\x19iF\xf3Y\xb7\xa1]\xae\n\x93Qo\xc0\xdb\xdd#r\xba%\xd6\x9dJt\xea)\xa9E6\xf8   -  @\xd2z\xdcu%\x9e\t}\x85\xaf\'?\x91/\xb0\xde\xd8\xee+D\xf2n.q\xe7\xdf\xc2[{\x86\xd1?\xbd_\xba\x06\x8by9\xfc\x89}\x83\   -  xc9\xcf\xe4K\xec7\x9d\xee#E\xcf\xe9\x17\xee\x90\xf7\x13\xa1\xae\xb5W\xee\x81\xa3>N\x7f"_`\xf2s\xf9\x12\xfb\r\xe5\xfe   -  \x824W\xe8\xd4O\xff\x00\x12?\xa0\x8d\x1f\xe5\xaf\xdd\x03G8%\xf2%\xf6\x15F\x94\xbeL\xbe\xc3x\xe3\xb8\xad\x0f8\xf2\xab   -  >\x1c%kq:/\xf7\x8b\xf7@\xd1\xc5J_&_a\x12\xa7%\xf1e\xf6\x1b\xcb\x1d\xc5h\xbf\xde/\xdd&[\x87\xd1e\xff\x00\xc8\xbft\x0c   -  e\xd9R\x8b\xa7|\xaa\xca2I\xc7\xbd\x1b^\xb9\xa3\xcb\xecf\xc4\xd8l\xbd\xba\xa7i\x18\xb6\xbe60z\xbc`\ra\xedy\xd6\xc3\xd   -  95?\xe3\xc8\xdb\x0e\xd8\x1c\x9e\x9f\xec\xb3S\x97\xa4\xc0\x8c\x1d\xc6\xcc{\xa9F+\xbeH\xe9\xf2v\xfb,\xff\x00\xeb4=\xa4   -  \x07\xd0\xdd\xda\xae\r\x91\xd3\xf3\xfd\xda=b<\xae\xef^vOM\xc7\xf7h\xf5h\x01(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8\   -  xaa@\x0c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x0c\n\x1a\xc9C.\x14   -  \xc905\x93\xb6\r\xbdj\xf6\xfat\xa9S\x94\xa3\x1e\xadw\x1a\xa5Qr\xe5\xd4\xfa=\xb6\xfb)e\xb5z]kk\x8a\\UxZ\x83}\x134\xf3   -  x\xfb\x9b\xd5\xf6r\xbdZ\xf4b\xa7C/\n\x9a\xe2k\xec\x03\x0f\xe4\x9c\x95\xdd[V\xb6\xa8\xe1Z\x9c\xe2\xd3\xef\x8bE\x94\x0   -  5x\xe2\xef\xc1\xc8\xb4\xba\x95\xb5E(da    -  *\xac\xb89\'\x9c\x96pW"\x90!&\xfa"R\xe7\x86_\xb5\x84\xa7)*~\x96\x0fE\xb2;\x13\xabm6\xa1\n\x16\xb4g\x0c\xbfJpi}\xa0v\   -  xfb\x95\xb6\xabWot\xf9R\xa7)EK\x9bG\xd0]2.6t\x94\x96\x1aF\x1d\xdc\xde\xea-\xb6V\x9d;\x9b\xfaQ\x95\xe7&\xa5\x1c\x19\x   -  b2+\x92\xc0\x07\xd4\xd5\x0e\xd6\x9f\xaf?e\x1b`\xd1\xaa\x1d\xad?^~\xc8\x1a\xb6\x00\x00s,k\xd6\xb4\xa9\x1a\xb4j8\xca->   -  G\x0c\xb9\x16\x06\xf1n\x03x6z\xee\x89N\xca\xe2\xa4i\\P\x8a\x82R|\xe6\xcc\xd2\xf9\xac\xa6|\xd4\xd9]\xa0\xbb\xd9\xfdB\   -  x9d\xcd\x95G\n\x90yL\xdc]\xd1\xef~\xc7h\xec)Y\xdf\xd5\xe1\xbf\x82\xf3\xe7R\\)\xfd\xa0f>\x19g\xd3+\xc3K.E\x8a\x176\x9   -  5\x92t\xee(\xcf\xd9\xa8\x99u\xd4\x8c\x96"\xd0\x17#%\x8e\xa4\xf1/\x13\x8a\xe7\ny\xe3\xabN+\xe7\x92GC\xb4\x9bW\xa6l\xf   -  5\xac\xae.\xae)N\x18\xf4aQ6\x07k\xac\xea\xb6z}\xa5J\xd7u\xe9\xd3\x8cSy\x934o\x7f\x1b}\x1d\xab\xd7\xe5\x0bzN\x9d*\r\x   -  c39\xe5/\x9c\xf4\x1b\xe9\xde\xd2\xda\n\xd5-t\x99\xd4\x85\x9fG\x19g\xa9\x83\xeb\xcaW\x12\xf2\x8f\xfd@\xb2\xb9\x95&\x8   -  8\xc7!J9\x9b\xc8\x17\xad\xa2\xe7qJ)e\xb9%\xfe\xa6\xfbn?f\xe3\xa3\xec\xcd\xbdh\xc5E\xd6\xa6\xa4\xcdJ\xdc\xb6\xc8\xcfi   -  \xf6\xb2\x85*\x90\xe2\xa1\xd7\x9a\xe4o\x8e\x93h\xf4\xdb\x1b[Jk\x10\xa5\x05\x109\x93\x8e%\x93\x15v\x85\xd0^\xb7\xb2\x   -  0e\x10\x87\x14\xa1\x99rFY\x92\xcb:\xfdn\xce\x17\x9a]\xcd\x19\xa4\xf8\xa9\xb4\xbe\xc0>e][\xba7uh\xb5\x87\x194Xk\x0f\x   -  06@\xde\xa6\xcfOg\xf6\x8e\xe23\xa6\xd2\x9c\x9c\x97/\x9c\xf0\x13y\x93~    -  Bx2\xa6\xe2\xb6\xe6[/\xb4\xb4\xdd\xcbr\xb6\x97\x9b\xc3\x9eH\xc5e\xcaM\xc2\xa4d\xba\xa7\x90>\x9c\xe8z\xa5\xbe\xadaJ\x   -  e6\xd6\xa4g\x19\xc57\xc2\xfa\x1d\x81\xa5\x9b\x9e\xdf\x1d]\x9d\xb8\xa3i\xa8\xd4\xa9+>\x8e+&\xd8\xec\xee\xd9iZ\xf5\xa4   -  +\xda\xdc\xd1\x82\x92\xce%Qd\x0fDCh\xb1\xf9]\x16\xb3\x1b\x8aM?\t\xa1:\xb4\xb8\x7fMMz\xe4\x80\xbc\xe7\x15\xd5\xa4D\xa   -  a\xc21rrX]Y\xd6\xdc\xdfX\xd1M\xd7\xba\xb7O\xe7\xaa\x91\x82\xf7\xbd\xbek]&\x9d[\x1d\x1a\xabU\xf9\xc6R\x8b\xcao\xf6\x0   -  1\x9e\xe8\xea\x16\xb5\xab8\xd1\xaf\t\xcf\xbe)\xf49\x91K\xaeO\x9f:v\xf6\xb6\xa6\xcbR\x9d\xcd\xad\xea\x8b\x93\xe7\x94\   -  xfa}\xa6f\xdd\xee\xff\x00\xe3p\xe9\xdb\xebu*N\xbb~\x974\x80\xdaX\xa5\xdcU\xd0\xf3{;\xb5\x9af\xb1o\t\xdb\xdc\xd2M\xae   -  \x8e\xa2\xc9\xdeN\xe2)f-I|\xcf    -  _\xc8-Q\x9f\x1cs\x86\x8b\x80\'\x8e\x16|\xff\x00\xed\x07\xf0\x81\xa8\xfbg\xd0\tz/\xd4|\xfe\xed\x05\xf0\x81\xa8\xfb`b\   -  xf7\xd4d2\x00\xf4\xdb\xbb\x7f\xda\xdd?\xe9\x11\xf4Oc\xbd\xc1\xb6\xf6O\x9d{\xbc\xf7\xdb\xa7\xfd">\x8alo\xb86\xde\xc8\   -  x1d\xd8\x00\x00\x00\r-\xedk\xef\xcf\xff\x00\x03_\xbb\xcd\x81\xedi\xef\xcd\xfb\x06\xbf.\xa0I\xca\xd1\xfd\xd5\xb5\xfaD   -  qY\xcb\xd1\xfd\xd5\xb5\xfaD\x07\xd0\xcd\xd0{\xd5\xa1\xec\xaf\xb8\xf75=\x07\xea<6\xe8=\xea\xd0\xf6W\xdc{\x9a\x9e\x83\   -  xf5\x01\xf3\xe7\x7f\x7f\x08Z\x9f\xb6\xccjd\xad\xfd\xfc!j~\xdb1\xa8\x13\x1fI\x1c\xba\x14\xe4\xee)\xb5\x16\xd6N%8\xb9\   -  xcb\t\xe0\xe6\xdaV\xa9J\xe6\x9c\\\x962\x07\xd0\r\xc8\xb5\r\xdc\xe9\x9c\\\xbc\xde\xf3\xdf\xc6Qk)\x98\xd7r\xb7\xb6\x95   -  v\x07N\xa7V\xe2\x8aj=\x1c\xd22\x14n,\xa1\x0cF\xe6\x86>\x91\x01\xcaR^#\x8e>\'\x13\xf2\xab?\xf14?\x88\x88\xfc\xaa\xcd\   -  x7f\xf6\xa8\x7f\x11\x01\xcc\xe2^$\xa6\x8e\x17\xe5\x96k\xff\x00\xb5C\xf8\x88\x95\x7ff\xbf\xfb4?\x88\x80\xe6\xe5\x14\x   -  c9\xa5\xd4\xe2\xff\x00(\xd9\xff\x00\x8a\xa1\xfcDQR\xfa\xd2o\n\xea\x87\xf1\x10\x1c\xae(>I\xa6D\xa2\xf2q]\xc5\x9c0\xe1   -  sC/\xc2\xa2/?)S\x0e\x9c\xe2\xe3\xf3<\x81\xac\x9d\xad,jN\xee\xce\xea4\xdb\x8d8sf\xaeW\x96s4\xb1\xc4o\x86\xfe4\x17\xaa   -  \xec\xa5\xcc\x92R\xa9\x08r4WQ\xa5\xf9%y\xdb\xd5^t\x1e\x00\xeb\xcb\xb4e\xc1\xc3/\x06\x99A]$\x9b\xc3\xe8\x06\xe5vf\xdb   -  \x1aZ\x9e\x91;;\xba\xd1\xa7:IF\x11\x93\xe7/Q\x9e%\x88\xf3\x97G\xd0\xf9\xc7\xb1\x1bOq\xb3z\xc5\x1b\xbaSq\x859e\xa4nf\   -  xef7\xa1\xa6\xedM\x8d\x08\xd5\xaf\x1au\xf1\xe7:\x93Q\xcf\xda\x06T\x8b\xe3\x8e\x17\xdaT\xbc\xc7\x86q(_\xd9\xe5F\x17T\   -  x1a\xc7uD\xcb:\x86\xb9\xa7Y\xc1\xba\xb7T0\x96\x7fJ\x80\xeckV\xa7J\x9b\x9dI(\xc1ul\xd2\xce\xd2\x1b\\\xaf\xf6\x82\xbe\   -  x9fJ~R\x959ri\xf22\x0e\xf87\xd7ooJ\xb6\x9d\xa4T\x92\xa9$\xe3\xc4\x9eQ\xaa\xba\xc6\xa1q\xa9_T\xb8\xba\x9f\x1dY<\xb6\x   -  07\n\xae\x1dND\xe1`\x84\xb9\xe4\xa8\x0b\xb6Q\xe3\xa9\xe4\x92\xcb\x97$o\xb7g\xeb_\xc9wyc\t\xacO\x1d\r(\xdd\xf6\x93-Si   -  \xec\xa9B9\x8b\xa8\x93\xca>\x82\xecf\x95\x1d+D\xb7\xa1\x14\x96"\x80\xef*\xbf\xcdK\xd4i/i\xdf|4\xff\x00i\xbb5\x7fE/S4   -  \x97\xb4\xef\xbe*\x7f\xb4\x0c!\x12[\xe4R\xba\x95>\x80r\xf4w\xfdz\x8f\xb6\xbe\xf3\xe8\xee\xef=\xe6\xe9_C\x1f\xb8\xf9\   -  xc3\xa4{\xa1G\xdb_y\xf4{w~\xf3\xb4\xaf\xa0\x8f\xdc\x07\xa2\xa9\x0588\xcb\x9a}M\'\xed=\xa0\xca\xd7k+^\xd3\xa6\xd5\'\x   -  cb8\xe4n\xd3\xe8\xcc5\xda\x1bd\x96\xb9\xb2\xf3\x9d\xad?\xcfE\xf17\x804g\xd2\x0b\x0b\xafB\xfd\xed\xbc\xad\xae\xaaQ\x9   -  7XI\xa6Y\xc0\x1c\x9b[\xc9ZV\xa7Z\x83\xe1\x9c^y\x1b\x89\xd9\xefx\xb4\xb5M\x1e\x96\x9d{]+\x95\xdf\'\xcc\xd3\x17\x13\xb   -  6\xd9\xbdn\xf7A\xd4awaW\xc9\xd5\x8b\xeb\xf3\x01\xf4\xc7\x8b\x94\\^S]J\xb3\x93\x02n\x8b|\xf6\xfa\xbd\xbd+MV\xab\xf2\x   -  cb\x11\xe2\x93\xc2\xff\x00S5[kz}j|t\xae(\xc9|\xd5\x13\x03\xb0o\x1dH|=\xeb%\xbaW\x14k\xc7\x8dT\x86=\xa4U;\x9bh,J\xbd%   -  \xeb\x9a\x02p\xe5\xe8\xf2E\x8a\xf7\x94(.\x1a\xf5\xa1M\xf8\xb6y\xdd\xa7\xdb}+g(J\xad\xcd\xcd\x1a\x89,\xe2\x9dD\xd9\xa   -  a\xfb\xd1\xdfU\xce\xa7\xa8N\x1a-Y\xd3\xa5\x19|d\xc0\xdc\xcbj\xd6\xf5\xa2\xa7F\xacj|\xe8\xbe\xe7\x14\xf0\xdaF\x89l\x9   -  e\xfb\xb6\x8bI\xb8\x8f\xe5\x17nV\xcb\xacRy6#w\xfb\xe8\xd0\xf6\x924\xe9\xdcq\xc2\xe1\xf2r\x9b\xe1_\xea\x06fR\x8a\xea\   -  xf1\x92\xec^y\xa3\xa7\xb6\xbf\xb4\xbbQ\x95:\xf4\xaa\'\xd1Bi\x9d\xa5\x06\x9a\xe5\xd0\x0b\xc1\xa0\x00\xd5\xfe\xd8>\x96   -  \x9f\xec\xb3SW\xa4\xcd\xb3\xed\x81\xd6\xc3\xd9f\xa6\xafI\x81\x07m\xb2\xfe\xecP\xf6\x91\xd5\x1d\xb6\xcb\xfb\xb1C\xda@   -  }\x0e\xdd\xd7\xbd=7\xe8\xd1\xebQ\xe4\xf7v\xbf\xb2:w\xd1\xa3\xd5    -  *\x04\x12\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x   -  02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x002\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x   -  00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xc0%\x90\x04F)<\x9cmB\xce\x85\xdd\t\xd3\xadJ\x9c\xe3%\x87\xc5\x14\xceYEX\xe5r   -  \x03\x03o\x0fq\xfa^\xb3\x1a\xb5\xac#?\xca\x1eZ\x8cV\x17\xfa\x1a\xbb\xb6[\xbc\xd6vf\xf2\xa4n\xed\xdch\xa6\xf8_>\x87\x   -  d1g\x1c\xacc\x07M\xadl\xf6\x9f\xab\xdb\xce\x9d\xe5\xa5*\x92|\xb8\xa4\xb2\x07\xcdem%\x9e5\x8c\x16%\xc9\xb4m\x86\xf37\   -  t\n\x8a\xa5\xe6\x95VnO2\xf2P\\\x8ds\xda]\x94\xd4t:\xd2\x85\xed\xb4\xe9\xa8\xbfJ@y\xa4\xca\x94\x9aM.\xf2#\tJ\\1Ya\xc5   -  \xc5\xe2K\x0c\t\x84\xe5\x07\x98\xb6\x8e]=V\xfa\x9c8auq\x18\xf8*\x8d#\x86\xca@\xbdZ\xe2\xadw\x9a\x93\x94\x9f\x8c\x9eK   -  qmd\x84JY\xe4\x80\xa92\xb4\xe1\xc3\xcd\xf3-\xf4x}NV\x9fcq{p\xa9[Ru*?\x8a\x80\xe2\xf3\x93\xe5\xcc\xed4M\n\xff\x00Z\xb   -  8Tl)9\xd4o\x08\xca\xbb\xbb\xdc\xbe\xa9\xad^\xd1\xa9\xa9P\xabkA\xf3\xce\r\xa0\xd8\xfd\xddi[9B0\xa7oJ\xadD\xb1\xc6\xe3   -  \xcc\x0c\x15\xbb\x8d\xc2;\x98\xd0\xb8\xd7!R\x95D\xd4\x9a\x8bx6gg\xb6SM\xd1,\xe1F\xd6\x85?5/9\xc1d\xed)[\xc6\x8d4\xa9   -  \xacz\x8eE$\xf1\xe7\x01>M$\xb0\xba\x17#\xd0\x82P\x06j\x87kO\xd7\x9f\xb2m{5C\xb5\xa7\xeb\xcf\xd9@j\xe0\x00\t*\x8fR\x8   -  2\xa8\'\'\xc9d\x0b\xa9\xe1\xe7\xbd\x17\xa8]\xdc[\xd5U(V\xa9NK\xe4I\xaf\xb8\xe3\xf4|\xc9l\x0c\x81\xb3\xbb\xd7\xda\r\r   -  E[\xd4\xf2\x98\xfe\xf2m\x9e\xb6\x87h\xed\xab\xa5\x1e\x15B\xd9\xafR\xff\x00c\x08\xf1\x0e    -  2\xe6\xa9\xbfm\xa6\xd4b\xd5H\xd2\x86~K\xff\x00\x83\xc1k{S\xa9\xeb\x15\x1c\xaen*\xf3\xee\xe3x:\x1c\x8c\xa0*\x93r\xea\   -  xdb\xf5\x8a\xb5\x1c\xd2\xca\xc6<\n[&1\x94\x97%\x90)I\xe3\xce9z}\xad{\xbb\x9aT(\xc3\x8aS\x92\x8a\xc1j\x85\n\xb5\xebF\   -  x8d(\xb9\xd4\x9b\xc2F\xcdn\x03u\xb3\x85Jz\x96\xadA\xe1\xac\xa8\xcdt\x03    -  vz\xd8\x1f\xe4\r\x16\x9d\xdd\xf57\x0b\xb7\xcdz\x8c\xdb\x84Y\xb5\xa5J\x8d\x18S\xa5\x14\x94V0\x8b\xe0[}J*AIa\x97\xb0\x   -  88|8\x03\x07\xef\xf7v\xf4\xb5\xed\x1e\xb6\xa3gM\xcbQ\x82\xf3b\xba`\xd2\xfdSO\xadeuR\x85X\xf0\xd5\xa6\xf1%\xf3\x9fL\x   -  eb\xd2U3\n\x91S\x83]\xe6\xb2\xef\xebur\xa8\xea\xeaZe&\xb1\x99\xc9A\x01\xab1\x8e:\x95\xa4r/(N\xd6n\x95x\xf0\xce=S,&\x   -  9f@\x12\x9c\xb8p\xb9|\xe8\xec\xb4}\xa3\xd4\xb4\x99\xf1[\\\xd6\xe5\xdc\xea<\x1d[e\xb6\x06I\xb4\xdf\x16\xd1Z\xc21\x8c\   -  x94\x94|dr\xae\xf7\xdf\xb4\xb71\xe1\x97\x93\x8a\xf9\x9f\xfc\x18\xad\x90\x07\xb0\xd6v\xff\x00Z\xd5`\xe3Z\xe2\xa4\x13\   -  xf95\x1a<\xadj\xb5kI\xca\xadI\xcd\xbe\xf9I\xb2\xd9    -  F\x19r\nq\xf3\xd4\x9cW\x8ax(\xc9S\x8b\xe1\xc6y\xf8\x01\xe8\xb6kiu\x8d\x16\xe25\xac\xab\xd5\x97\x0b\xcaR\xa8\xf0m\xbf   -  g\x9d\xb7\xd6\xb6\xae5\xa9\xea\xf4\xa1\x18R\x8f\x9a\xd7\x7f\xfa\x1a\xe5\xba}\x82\xbf\xda\xab\xfaO\xc9N6\xaa^t\xd2\xe   -  4\x8d\xd8\xd8\xdd\x97\xb4\xd9\xbd*\x8d\x0bZpU#\x1cJia\xb0=B\x8e:\x13\x82!,\xaeeY\x02%\xe8\xbfQ\xf3\xfb\xb4\x17\xc2\x   -  06\xa3\xed\x9f@e\xe8\xbfQ\xf3\xfb\xb4\x17\xc2\x06\xa3\xed\x81\x8b\xd9\x04\xb2\x00\xf4\xbb\xbc\xf7\xdb\xa7\xfd">\x8al   -  o\xb86\xde\xc9\xf3\xafw\x9e\xfbt\xff\x00\xa4G\xd1M\x8d\xf7\x06\xdb\xd9\x03\xbb\x00\x00\x00\x01\xa5\xbd\xad=\xfa?`\xd   -  7\xee\xf3`{Z{\xf4~\xc1\xaf\xdd\xe0\x19\xcb\xd1\xfd\xd4\xb5\xfaE\xf7\x9cC\x99\xa3\xfb\xabk\xf4\x88\x0f\xa1{\xa1\xf7\x   -  abC\xd9_q\xeej?\xcd\xbfQ\xe1\xb7C\xefV\x87\xb2\xbe\xe3\xdcT\x7f\x9b~\xa0>|\xef\xed\xff\x00\xee\x16\xa5\xf4\x8c\xc6\x   -  e6G\xdf\xd3\xff\x00\xdc-K\xe9\x0cn\x00\x96\xdb\xc7\x8a\x00\x0fS\xa4m\xc6\xad\xa5[B\x85\xb5Y(G\xa2\xe3gh\xf7\xa5\xaf\   -  xb8\xf0\xf9g\x8fm\x9e\x08\x01\xee\xbf\xa4\xfd{\xfb\xe9~\xfb!\xef7]\x7f\xfc\xd2\xfd\xf6x`\x07\xb8\xfe\x92\xf5\xdf\xef   -  \xa5\xfb\xec\x8f\xe9+]\x7f\xfc\xd2\xfd\xf6x\x80\x07\xb7\xfe\x92\xb5\xcf\xef\xe5\xfb\xec\x98\xef3]\x8ax\xad.\x7f\xf7\   -  xb3\xc3\x802\x06\x9f\xbc\xcdu^\xd1\xfc\xf4\x9ar\\\xb8\xd9\xba\x1b\x9c\xd6\xaeu\xad\x99\x85k\xacq\xf2\\\x8f\x9e\xd6?\   -  xaeP\xf6\xd1\xbe\xbd\x9f\xbd\xe8S\xf5\xaf\xb8\x0f}\xac\xe9\xd4\xb5\r>\xbd\xad\\\xb5Q`\xd1\r\xf6lm\xd6\xce\xed%\xc5YS   -  \xc5\xb5I\xbe\x07\xe2o\xfc\xa5\x89\xe3\x1dLo\xbem\x86\xa3\xb5z\x1dGN\x0b\xf2\x9aQn).m\x81\xa0<1\\\xa4\xdeH\x9aq\xe4w   -  \x1bE\xa4\xddhZ\x9d[+\xfa\x0e\x9dX\xb7\xca]N\x9e\xa2i\xe79@\x1c\x9bX.\xda\xde\xddZ\xcdJ\x85\xc5Zm|\x99\xb4X\xc8\x03\   -  xdaXo#\\\xb2\xa2\xa9\xc2\xbc\xe4\x97|\xa6\xce\xbfX\xdb]_S\x8bU\xaej\xc5?\x93Q\x9ei\xa2\x90+\xa9V\xa5YqT\xa99\xcb\xc6   -  O"\t\xcb\xa1Az\x8c%<\xf0\xa7\xc8\x08\x8ce7\xe6\xa2\xe5.\x0c\xf0\xcd\xbc\x94\xa6\xd4\xb3\xd1\x19\x03t\xbb\ry\xb5\xfa\   -  xfd\x08\xc6\x84\x9d\x97\x17\x9fU.H\x0c\xad\xd9\xbfb%Z\xab\xd4/\xe98\xd3X\x959%\xd4\xda{~8\xe21_\x9aK\x93:\xdd\x97\xd   -  9\xebm\x03G\xa3eB1\xf3#\xc3\xc4\x97S\xb9\xa7\x1e\x18$\x04V\xfd\x14\xbdL\xd2N\xd3\x9e\xf8i\xfe\xd3v\xeb~\x8a^\xa6i\'i   -  \xcf|T\xbfh\x18E\x06\x10`s4\x9f\xd7\xe8\xfbk\xef>\x8en\xef\xdev\x95\xf4\x11\xfb\x8f\x9cZO\xeb\xf4}\xb5\xf7\x9fGww\xe   -  f;J\xfa\x08\xfd\xc0ztq5\x1bX\xdd\xdaV\xa38\xa6\xa7\x17\x1eh\xe5\xc7\xa1\x0f\xa8\x1a)\xbfM\xdc\xd7\xd9\xadf\xb5\xdd\x   -  a59;Z\x8d\xceR}\xcd\x98\x87\x9e9\x9fH\xb6\xebem6\xa3G\xadgq\x08\xc5\xc9r\xa9\x8eh\xd1\xdd\xeb\xec%\xee\xca\xea\x93\x   -  8b\xa35n\xe4\xf8f\xd7T\x06>\xc9\x1c\xd3\xc9\x19D\x81v\x95\xe5z2N\x8dI\xd3k\xbe2h\xf5:6\xf0\xb5\xad*)Q\xaf9\xa5\xf2\x   -  a6\xd9\xe3\x99\x00e\x9a;\xf3\xdajT\xf8"\xa9c\xd7\xff\x00\x07\x0bQ\xdf\x1e\xd1_Sp\xa9(\xc5?\x93,\x18\xcc\x01\xdajZ\xd   -  5\xfe\xa3VS\xb8\xba\xae\xf3\xdc\xea6\x8e\xb5\xe5\xbc\xb7\x96\x00\x15)4\xb0_\xb7\xba\xadC\x9d\x1a\x93\xa6\xff\x00\xed   -  \x93G\x1d,\xb4\xbb\xcem\xa5\x85\xc5\xcd\xcc(R\xa6\xe5R]\x12\x03!\xee\xd3y:\xf6\x91\xaaP\xb7\xb5\x93\xac\xa5$\xb1RNF\   -  xf2lv\xa1s\xaahV\xd7w\xb0\x8ckN9\x92\x8fC]\xf7\x13\xb9\xff\x00$\xe9\xea\x9a\xbc\x1ce\x1cJ0\x9a\xeal\xf5\xa5*v\xf4cN\   -  x94Tc\x15\x84\x90\x17\xc0\xc8\x03X;`u\xb0\xf6Y\xa9\xab\xd2f\xd9v\xc1xz\x7f\xb2\xcdM^\x93\x00v\x9b1\xee\xcd\x0fi\x1dV   -  N\xd3f}\xd8\xa1\xed    -  >\x8a\xee\xe1gdt\xef\xa3G\xa8<\xc6\xed\xfd\xe8i\xdfF\x8fQ\x80\x18\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001Wj?\x80\x9d\xa6\xfa\xaf\xe2\xa9\x01\xda\x8f\xe0\'i\xbe\xab\xf8\xaa@\x0   -  c\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f@\x00\xa5\x   -  94\xb4V\xc8\x02\xcdNqk\xb8\xf1[Y\xb0\xda^\xd0\xd2\x9cn\xada9\xb5\xc9\xb3\xdb\xca<\xc8Q\x03L\xf7\x99\xb9[\xdd\x1eu.\x   -  f4\xc4\xe5Ms\xe0\x84L\x1f\xaa\xe9\xd7z}g\x0b\xdaS\xa7,\xf2\xe2X>\x9c\xdcP\xa5qM\xc2\xacT\xa2\xfec\x19m\xee\xe7t-\xa5   -  \xa5:\xae\x87\xf5\xa4\xbc\xc7\x94\xb9\x81\xa0\xa0\xcb\x1b\xc1\xdc\xf6\xad\xb3U\xaa\xd6PR\xb6O\xcdPY\x7f\xe8c\tZU\x8c   -  \x9ceF\xaak\xb9\xc5\x81\xc6+\xa3\t\xce\xaccN.R}\x12=\x06\xcdlv\xa9\xb47P\xa3gB\xa4x\x9e3(<\x1b-\xbb=\xc1P\xb3To5\xea   -  Q\x9dU\x89G\x85\x81\x836\x1fvZ\xb6\xd2]\xc1\xca\x85Z4\xdf\xc6\x94y\x1bG\xbb\xcd\xcc\xe9\x9a\r\nuo)R\xadr\xb9\xf1\x99   -  ?I\xd2\xadt\xcbx\xd1\xb5\xa7\x18\xc2+\x0b\x92;\x18Ec\x00q\xe8\xdbS\xb5\xa5\x1atR\x8c\x12\xc6\x11z(\xba\xe0\x92)H\t\x   -  89q\x14"\xb4\x04\xe0\x00\x043T;Z~\xbc\xfd\x94m{5C\xb5\xa7\xeb\xcf\xd9@j\xe0\x00\n\xe9A\xd4\xa9\x18.\xb2x=t\xb6\x1bV\   -  xa7\xa7\xab\xcat*\xbax\xceTO/\xa76\xaf\xed\xda\xeb\xc6\x8d\xed\xdd]\x95\r_c!CR\xa6\xa7\x17\x14\xb9/\x98\r\x14\xba\xa   -  5:3p\xa9\x17\x19\xae\xb98\xf27?n7\x0b\xa6jj\xa5m&\x8a\x8dis\xf3\x9a\xea`\x9d\xa4\xdc\x86\xd1i\x93\xab5\x18J\x9cy\xe2   -  <\xc0\xc4\x81\x1d\xd5\xce\xcc\xea\x94%%;J\xef\x0f\x1c\xa9\xc8\xe0\xd4\xd3/\xa9\xcb\x12\xb3\xb8\xcf\xd1K\xfd\x80\xe2\   -  xf7\x13\xdcs\xe8\xe8\xd7\xf5zY\xdc\x7f\n_\xecz\x8d\x9e\xdd\x96\xbd\xaeJ*\xd6\x8b\x86~\\Z\x03\xc3\xe1\xfa\xce\xdfE\xd   -  1\xb5\x1dR\xe6\x14l\xed\xea\xcb\x89\xe31\x8eL\xf5\xb1\xbd\x9d\xf5\x178K\\\x8d)S\xea\xd4Y\x9f6Cw:\x0e\xcd\xce\x8b\xb4   -  \xb6j\xb4{\xdf>`a\xed\xce\xeeeY\xd4\xa7\x7f\xaeS\x8dY)e,#\x94R\xa0\x97B\xa4\x05,\xa1\xa2\xebE-    -  ,\xb4q\xaf\xac\xe8\xde\xd0\x95\x1b\x84\xa5NK\x12O\xbc\xe64D\xa8\xc6k\xce\x03Z\xb7\xbb\xb8\xf8\xeaUj\xde\xe9\x1c\x14\   -  x96\\\xb8b\xba\x9a\xcf\xb4{7\xa8h\x972\xa3^\xda\xacT^8\x9cy\x1fK*Q\xcd>\x14\x93G\x87\xdb=\xdfi\x1bEBQ\xbb\xa0\x9c\x9   -  f\x86\x00\xf9\xdd\xcf<\xc86Sm\xfb>]S\x94\xa7\xa2\xc2\x11\x8fU\x96c-ct\x9a\xfe\x92\x97\xe5\x10So\xe4E\xb01\xbb    -  \xf4\x17\x9b+\xaa[I\xa9Z\xd6~\xaal\xb3Kg5*\xaf\x10\xb3\xb8^\xbaR\x03\xa6$\xf6zN\xee\xf5\xadE\xa8\xd3\xa18\xc9\xf4\xe   -  2\x83FF\xd9^\xcf\x1a\xf5\xddHU\xbf\xf2>E\xf3k8x\xfb@\xc1\xd6\x96U\xee\xea([R\x95I\xf8E\x19\x83u\xdb\x9e\xd46\x82\xbd   -  *\xd7\xd0\x95\ny\xe9R86\x13bw%\xa2h\x95!Z\xbd\xbej\xaf\x9d>fW\xb5\xd3\xed\xed`\xa3F\n),,    -  :\r\x8e\xd9[-\x9a\xb0\xa5oaJ4\xdaIM\xc7\xe33\xd4`F\x9a\x8fB\xac\x01\x11*!\x12\x02^\x83\xf5\x1f?\xbbA|    -  j>\xd9\xf4\x06^\x8b\xf5\x1aC\xbe\xdd\x8b\xd65\r\xb7\xd4nh\xd2r\xa5)\xe5b-\x81\x83\x19\x07\xa6\x96\xc5\xeb\n|?\x93U\x   -  cf\xd1\xb2\x7f\x99Z\xbf\xf8j\xbf\xc3`S\xbb\xcf}\xba\x7f\xd2#\xe8\xa6\xc6\xfb\x83m\xec\x9a)\xbb\xed\x86\xd5\xe7\xb4\x   -  b6U#FpP\x9f7(4on\xcb[\xd4\xb4\xd1\xa8Q\xad\x8e8\xae`w    -  \xa52r\x04\x80D\xb3\xc2\xf1\xd4\r.\xedi\xef\xd1\xfb\x06\xbe\x9b9\xdage\xb5MWj]\xc5\xbd7*|=\xd1l\xc1\xafb5e4\xbf\'\xa   -  b\xfb\x8c\x0f*s\xf4U\xff\x00V\xb5\xfaDw\x0fb\xf5|\xbf\xea\xd5y\x7f\xfa\xd9\xdb\xec\xe6\xc1k\x15u\x1bj\xae\x84\xd4\x1   -  4\xd7X07gt\x9c\xb6b\x87\xb2\xbe\xe3\xdcT\xf4\x1f\xa8\xf2\x9b\xbd\xb0\x9e\x9f\xa0P\xa3QbJ+\xee=5V\xfc\x9c\xb8z\xe0\x0   -  f\x9f\xdb\xfa\xf8B\xd4\xbe\x90\xc6\xe8\xcd[\xee\xd8\xfdR\xe7l\xef\xaeiQ\x9c\xa19\xe5b\r\x98\xf6\x8e\xc5j\xd3\xcbv\xd   -  5q\xf4l\x0f0\x0fO\xfc\xc9\xd5\xf0\xff\x00\xabU\xcf\xd1\xb2\x9f\xe6N\xb1\xfe\x1a\xaf\xf0\xd8\x1eh\x1e\x97\xf9\x93\xac   -  \x7f\x86\xab\xfc6?\x99:\xc7\xf8j\xbf\xc3`y\xa0z_\xe6N\xb1\xfe\x1a\xaf\xf0\xd8\xfed\xeb\x1f\xe1\xaa\xff\x00\r\x81\xe6   -  \x81\xe9\x7f\x99:\xc7\xf8j\xbf\xc3c\xf9\x93\xac\x7f\x86\xab\xfc6\x07\x9a\x07\xa5\xfed\xeb\x1f\xe1\xaa\xff\x00\r\x94\   -  xbd\x8c\xd5\xd3\xfdV\xaf\xf0\xd8\x1d\x1d\x8f\xeb\x94}\xb4o\xafg\xefz\x14\xfdk\xee4\xc3N\xd8\x8dbw\x94\x7f\xab\xd4^r\   -  xeb\x06n\xde\xe5\xb4\xbb\xad\'f)\xd2\xbb\xc2|\x9e\x00\xc83k\x8f\x18\xe7\xe2[I\xc6\xa4\xb8\xbc\xe5\xe0rb\x94\x9eQ\x1e   -  J)\xb7\xe2\x06\'\xde\xd6\xea\xb4\xed\xaf\xb4\xa9skF\x9d\x1b\xf5\xcd\xd5}Y\xa7{m\xb1\x9a\x9e\xcfj\x13\xa3R\xd6\xac\xa   -  9E\xfaj<\x8f\xa3\x9c\tG\x1d\xc7\x9e\xda]\x95\xd2\xf6\x82\xdeT\xaf\xe8)&\xbb\x92\x03\xe6\xd5Jj\x18\xca\xc3\xf0-\xc8\x   -  db\r\xb8\xec\xf3\x1b\x99\xce\xa6\x85\x08A\xbek\x8d\xa3\x12k{\x8f\xdam)9\xd6T\xe7\x15\xf2\x16@\xc5\x0c\xa5\x9e\xbe\xb   -  6\xc4j\x91\x9b\x82\xb6\xab\xc5\xec3\x95a\xbb-z\xf6\xacaN\x8bM\xf8\xc5\x81\xe1NM\x92\xadR\xa2\xa7B2\x94\xa5\xcb\x08\x   -  cc\xfa\x1e\xe0u\xfb\xbcyo%\x87\xe3\xff\x00\xfd3&\xc3n\x1fJ\xd3#J\xa6\xa3AJ\xea8m\xa7\xc8\x0c\x19\xbb\xad\xd3\xea;IqM   -  V\xa5:4\x9b\xcb\x94\xe3\xc9\x9bu\xbb\xbd\x92\xb1\xd9M:6\xb6\x94#Nx\xf3\x9a\xefg\xa8\xd2\xb4\xcb}2\xda4m\xa9\xa8\xc1/   -  \x03\x98\xe9\xa75.\xf0    -  \x82\xe3\x8f2\x1cP\x16k/\xcdK\xd4\xcd$\xed9\xef\x8a\x97\xed7z\xacsNIx\x1a\x8d\xda\x1bdu\rOY\x8d[jr\x92Y\xe9\x16\xc0\   -  xd6\xc0\xcfL\xf67T\x84\xb8em[+\xff\x00\xd6\xca\x96\xc5j\xd3Y\x8d\xbdE\xff\x00\x83\x03\xa2\xd2\x7f_\xa3\xed\xaf\xbc\x   -  fa;\xbb\xbfy\xdaW\xd0G\xee4K@\xdd\xfe\xb3swI\xc2\x84\xe2\xd4\xd7X?\x13}v&\xd2v{-\xa6\xd0\xab\xfaHRI\x81\xdf\xc3\xa0h   -  \x98t\'\x00X\xa9NNY\xcf\x9b\xe0y\r\xb4\xd9+\x1d\xae\xb0\xadB\xf2\x84]D\xb1\tK\xb8\xf6\xb2Y\xe4R\xe0\x80\xd1\x8d\xe5n   -  \x92\xf7D\xadQ\xdaP\x9c\xe1\x17\xd6\x11\xe4b\x1b\xabZ\xf6\x95\x1c.)\xca\r|\xa4};\xd4,(_Q\x95+\x88FQk\x0f\x91\x87\xb6   -  \xebr:F\xb1)\xd5\xb5\xa0\x95W\xd1\xe5\x01\xa3\xb2    -  \xcd\xfbK\xb8\x1d\xa0\xb1\xab:\x94<\x93\xa2\xba%\xcd\xfd\xe7\x81\xd5\xb7}\xadi\xcd\xf9Ky\xcb\x1f&\r\x81\xe3I;\x95\xb   -  3Z\xa7\xf8:\xff\x00\xc3\x91z\xd7d\xb5k\x9a\xaa\x9c-k&\xfci\xb0:\x12T[i.\xac\xc9z>\xe6\xb6\x93S\xc3\xa5\x08\xc5?\x94\   -  xb0e}\x89\xec\xf8\xe1R\x94\xb5\xc8Bx\xeb\xc2\xc0\xc0Z\x06\xc7\xea:\xcdJj\xd6\x95I6\xfb\xa3\x9c\x1bC\xb9\xfd\xd0R\xd2   -  \xe8\xd3\xbf\xd6\xe1\x1a\xf5\xa3\xd15\xcd\x19cd\xf6\x07E\xd9\xacKO\xa1\xc3\x12\xe5en\xfdt\xd1\xce\x93J\xa7\x13\x   -  97"\xa4\xb3\xcf<\x80\xeb\xe3\xa5X9K66\xd8\x7f\xfe\xb4Lt\xbb*mpZP^\xaah\xe7\xb4\x00\xa21\x8cc\x88\xa4\x97\xcc&\xe4\xa   -  0\xdc\x16dW\x82Ty\x01\xc1\xab\xa7[\\\xc5J\xe2\xd6\x84\xaaw\xf1A2\x9f\xe4\x9b\x08A(\xd8\xdbg\xe8\xd1\xd9\xa5\xc8`\x0e   -  \xbf\xf9.\xc7\x96,m\xbf\x85\x12\xaf\xe4\xab\x0f\xf06\xdf\xc2G=\x05\xd4\x0e\x07\xf2U\x87\xf8\x1bo\xe1D\x7f%X\x7f\x81\   -  xb6\xfe\x14N\xc0\x01\xd7\xff\x00%X\x7f\x81\xb6\xfe\x14G\xf2U\x87\xf8\x1bo\xe1D\xec\x00\x1d\x7f\xf2U\x87\xf8\x1bo\xe1   -  D\x7f%X\x7f\x81\xb6\xfe\x14\x7f\xd8\xec00\x07_\xfc\x95a\xfe\x06\xdb\xf8Q\xff\x00b\x97\xa5X\x7f\x81\xb5\xfe\x12\xff\x   -  00c\xb2\xc1n\xa4r\xf9K\x00pV\x95\xa7\xe7?\x91\xdb\xa6\xbc)\xa2\xf3\xa3\x184\xa9EF>\x0b\x91{-r\xc6J\xa3\xcdt\xc0\x13O   -  \n(\xa9\x91\x82@\xa5\x96g9\'\xc9"\xfb\xe8[\x92\xc0\x16\x1d77\x99e\x15J\xda\x8c\xe3\xc3R\x94&\xbf\xee\x8ae\xd4\xb9\x1   -  5\xc5\x01\xd6\xcfH\xb0\xce\x7f"\xb7\xcf\xd1\xa1KN\xb5\x84\xd3\x8d\xad\x08\xfa\xa0\x8e\xc7\x03\x84\x0bq\xb7\xa5\x1fF\   -  x11\x8f\xa9\n\x8ePK\x81&^\xc1L\x96@\x8aO1\xcb.d\xa1G\x1d\n\x80\x90\x10\x02\x1a8u\xf4\xfbk\x8a\x8aU\xa8R\x9b_*)\x9c\x   -  d6F\x00\xeb\'\xa3\xe9\xeeM\xfeCm\xfc(\x94\xbd\x0bN\x93\xcf\xe4v\xeb\xd5M\x1d\xae\x06\x00\xeb\xe9\xe9VT\xda\x94m(E\xa   -  f\nh\xe5\xc6<+\t$\xbc\x11w\x044\x02<\x91Q\x18%\x01\x0c\x12\x00\x82\xdc\xb3\x9e\x85\xd1\x808\xb3\xa6\xaaK\x15i\xc1\xc   -  7\xe7Y-\xd4\xd3l\'\xe9\xd9\xdb\xcb\xd7M3\x9b\x8c\x91$\xb0\x07U-\x1fM\xe2\xe5\xa7\xda\x7f\n?\xecL4k\x08\xbc\xab\x0bU\   -  xf3\xaaQ;\x1c\xff\x00\xda8[\xf8\xc0X\xa7mB\x92\xfc\xdd\nQ\xf5E"\xe4i\xc5<\xf4\xf9\x8b\xaa\x1f9*\x00S\xc5\xf3\x15E\xe   -  4p\x92\x96\x00\x94N\x08$\x00\x00\x0e\x0e\xa1gF\xeb\n\xbd\nuR\xf9qL\xe1\xc7@\xd2\xf3\x97aj\xdf\xcfJ\'o%\x92\x89\xa6\x   -  97    -  :\xef\xe4=.?\xfe>\xd3\xf8Q\xff\x00b#\xa2\xe9\xbcI\xc2\xca\xda/\xe6\xa6\x91\xd8\xc3?\x1f\xa1_\x99\xdc\x05\x14a\x1aqQ\   -  x84Tb\xba$\x8b\xc9\xf2#\x04\x81    -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06*\xedG\xf0\x13\xb4\xdfU\   -  xfcU    -  ;Q\xfc\x04\xed7\xd5\x7f\x15H\x01\x95@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x0000\x00\x10\t\xc0\xc0\x10F\n\xb00\x04\x02@\x14\xe0\x92p0\x04\x02F\x00\x82p\x00\x0c\x0c\x   -  00\x05\xba\x9c\xb0j\x9fk?\xd7\x1f\xb2\x8d\xad\xaa\x9bK\x06\xa9v\xb1\xfdu\xae\xfe\x105l\x15`\x8c\x01\xc8\xd3\xbf^\xa1   -  \xed\xa3\xe8\x06\xe3W\xf6R\x97\xa9\x1f?\xf4\xfeW\xd4=\xb4o\xee\xe2\xe6\xa5\xb2\xb4\xb1\xe0\x80\xc94\xfd&\\(\xa6\xb0\   -  xd9s\x00S\x81\x82\xac\x0c\x01N\x06\n\xb00\x04"P\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x020\t\x18\x02\x9c\x0c\x15``\np0   -  U\x81\x80(h(\xac\x95\xe0`\n\\\x13\n)t*\x00\x00\x0000\x00\x0c\x10H\xc0\x14\xb4G\t^\x06\x00\xa3\x85\x0e\x04V\x00\xa5,\   -  x12N\x06\x00`>`\x01C\xa5\x16\xb0\xd7"p\x97$T0\x05\x18\xe48pU\x82@\xa7\x03\x05X\x18\x02\x01    -  \x06\x06\x00\x00\x00\x00\x00\x00\x00\x00F2H\x02\x12\xc0\xc1 \x08\'\x00\x01\rr)h\xac`\n\x12*D\xe0`\np0U\x81\x80    -  2p0\x058$\x9c\x0c\x01\x04\xe0\x00\x18 \x91\x80 \x13\x81\x80 \x13\x81\x80    -  `\x9c\x00\x18\x18\x00\x06\x06\x00\x01\x81\x80\x00`\xa7\x85\x15\x00    -  \x94\x00\x11\x80H\x01\x80\x00\x00\x00\x10\xc8H\xa8\x01\x0e)\xaee<\x11L\xac\x01\x04\xe0`\x00\x00\x00\x00\x00\x00\x00\   -  x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x8a\xbbQ\xfc\x04\xed7\xd5\x7f\x15H\x0e\xd4\x   -  7f\x01;M\xf5_\xc5R\x00eP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00   -  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\xab\xb6\xa3\xc8\xd5\x1e\xd54jU\   -  xd4_/\x8am\x9bI\xf5:\x8d[f\xf4\x9d^\\Z\x95\x8d\x1b\x87\xe34\x07\xcc\xcf\xc9*x2?$\xa9\xe0}!\xfe\x8fvW\xfc\x92\xd3\xec   -  \x7f\xee?\xa3\xdd\x95\xff\x00$\xb4\xfb\x1f\xfb\x81\xf3\x9bN\xb4\xa9\xf9}\xba\xe1\xf8\xe8\xdf\x8d\xccR\xfc\x9be\xe8\x   -  a7\xf2Q\xe8c\xbb\xed\x96\x8c\x94\xa3\xa2\xda\xa6\xb9\xa7\x86w\xf6z}\xb5\x9d%N\xda\x94i\xd3_\x16 r    -  \xf2\x93+!$\x97"@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0   -  0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5]\xa8\xfe\x02v\x9b\xea\xbf\x8a\xa4\x07j?\x80\x9d\xa6\xf   -  a\xaf\xe2\xa9\x00?\xff\xd9\r\n------WebKitFormBoundaryAIGBXkBO7yWnYuGc--\r\n'}]   -    -  During handling of the above exception, another exception occurred:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:93 in │   -  │ __call__ │   -  │ │   -  │  90 │ │ │ await response(scope, receive, send) │   -  │  91 │ │ │ return │   -  │  92 │ │  │   -  │ ❱  93 │ │ await self.simple_response(scope, receive, send, request_headers=headers) │   -  │  94 │  │   -  │  95 │ def is_allowed_origin(self, origin: str) -> bool: │   -  │  96 │ │ if self.allow_all_origins: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:144 in │   -  │ simple_response │   -  │ │   -  │ 141 │  │   -  │ 142 │ async def simple_response(self, scope: Scope, receive: Receive, send: Send, │   -  │ request_headers: Headers) -> None: │   -  │ 143 │ │ send = functools.partial(self.send, send=send, request_headers=request_headers) │   -  │ ❱ 144 │ │ await self.app(scope, receive, send) │   -  │ 145 │  │   -  │ 146 │ async def send(self, message: Message, send: Send, request_headers: Headers) -> │   -  │ None: │   -  │ 147 │ │ if message["type"] != "http.response.start": │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:59 in │   -  │ wrapped_app │   -  │ │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ 57 │ │ │  │   -  │ 58 │ │ │ if is_async_callable(handler): │   -  │ ❱ 59 │ │ │ │ response = await handler(conn, exc) │   -  │ 60 │ │ │ else: │   -  │ 61 │ │ │ │ response = await run_in_threadpool(handler, conn, exc) # type: ignore │   -  │ 62 │ │ │ if response is not None: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/exception_handlers.py:25 in │   -  │ request_validation_exception_handler │   -  │ │   -  │ 22 ) -> JSONResponse: │   -  │ 23 │ return JSONResponse( │   -  │ 24 │ │ status_code=HTTP_422_UNPROCESSABLE_ENTITY, │   -  │ ❱ 25 │ │ content={"detail": jsonable_encoder(exc.errors())}, │   -  │ 26 │ ) │   -  │ 27  │   -  │ 28  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:303 in │   -  │ jsonable_encoder │   -  │ │   -  │ 300 │ │ encoded_list = [] │   -  │ 301 │ │ for item in obj: │   -  │ 302 │ │ │ encoded_list.append( │   -  │ ❱ 303 │ │ │ │ jsonable_encoder( │   -  │ 304 │ │ │ │ │ item, │   -  │ 305 │ │ │ │ │ include=include, │   -  │ 306 │ │ │ │ │ exclude=exclude, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:289 in │   -  │ jsonable_encoder │   -  │ │   -  │ 286 │ │ │ │ │ custom_encoder=custom_encoder, │   -  │ 287 │ │ │ │ │ sqlalchemy_safe=sqlalchemy_safe, │   -  │ 288 │ │ │ │ ) │   -  │ ❱ 289 │ │ │ │ encoded_value = jsonable_encoder( │   -  │ 290 │ │ │ │ │ value, │   -  │ 291 │ │ │ │ │ by_alias=by_alias, │   -  │ 292 │ │ │ │ │ exclude_unset=exclude_unset, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:318 in │   -  │ jsonable_encoder │   -  │ │   -  │ 315 │ │ return encoded_list │   -  │ 316 │  │   -  │ 317 │ if type(obj) in ENCODERS_BY_TYPE: │   -  │ ❱ 318 │ │ return ENCODERS_BY_TYPE[type(obj)](obj) │   -  │ 319 │ for encoder, classes_tuple in encoders_by_class_tuples.items(): │   -  │ 320 │ │ if isinstance(obj, classes_tuple): │   -  │ 321 │ │ │ return encoder(obj) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/encoders.py:59 in  │   -  │ │   -  │  56  │   -  │  57  │   -  │  58 ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { │   -  │ ❱  59 │ bytes: lambda o: o.decode(), │   -  │  60 │ Color: str, │   -  │  61 │ datetime.date: isoformat, │   -  │  62 │ datetime.datetime: isoformat, │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 140: invalid start byte   -25-Aug-12 20:18:05 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=86609;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=648296;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=458907;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=222483;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=350635;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=689697;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=271170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=634748;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48212 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=984017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=346992;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:08 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=280289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=401479;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=111468;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=340078;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=634020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=61193;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=750499;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=85754;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48213 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=806073;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=342863;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:11 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=816927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=775280;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=343687;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=866951;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=607324;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=299883;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=775811;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=334784;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48214 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=569906;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=609404;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:14 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=33236;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=274409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=924845;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=509306;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:18:15 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=595086;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=733238;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=660778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=55056;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48215 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=681553;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=718623;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:18 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=712132;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=619079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=379660;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=536503;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=637731;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=394501;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=356449;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=843910;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48216 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=649952;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=848693;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:21 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=408677;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=51146;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=680438;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=305395;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=447981;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=903477;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=592350;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=520497;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48217 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=510539;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=257793;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=219518;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=91676;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=447767;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=176528;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=372672;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=330251;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=614288;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602735;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48218 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=287866;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=394835;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:27 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=956675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=320155;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:18:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=627289;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=738978;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=326573;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=754286;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=876329;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=548104;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48219 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=405344;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=478061;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=583970;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=650746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=361043;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=375203;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=968800;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=712718;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=509055;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=37930;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48220 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=837625;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=321076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:34 INFO  send() - 124.70.231.45:20909 - "GET /api/conversation HTTP/1.1" 200 ]8;id=367126;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=615135;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=771057;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=880356;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=613508;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995794;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=520260;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=49670;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=398612;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=61854;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48221 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=590412;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=89813;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:36 INFO  send() - 124.70.231.34:48222 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=701254;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=536824;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:37 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=270786;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=684000;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=910492;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=353379;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=378541;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=228071;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=625693;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=666715;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48223 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=180472;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=286248;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:40 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=498129;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=15034;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=498726;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=172669;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=459877;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=230632;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=164069;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=603543;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48224 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=987842;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=41209;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:43 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=195903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=430093;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=468468;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=331514;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=593966;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995243;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:18:44 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=236319;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=606247;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48225 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=669007;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=952699;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:47 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=746929;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831823;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=124505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=92564;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=566615;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=81874;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=409382;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=244922;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48226 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=162304;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=17278;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=535444;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=161691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=772495;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21787;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=989409;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=875114;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=889689;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=108041;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48227 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=837263;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=405655;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=817906;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=211643;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=534368;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=427198;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=76949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=631446;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=976018;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=729543;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48228 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=283711;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=470976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:18:57 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=66643;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=985764;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=90554;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=588472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=530038;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=540472;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=496170;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=727768;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48229 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=387987;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=282778;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:00 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=419414;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=24673;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=931130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=978746;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=790739;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=414668;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=676622;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=3812;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48230 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=460634;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=436011;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:03 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=205136;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=21733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=449386;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=397050;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=744067;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=831541;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=910773;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=543001;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48231 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=151903;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=77410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=206364;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=179601;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=831600;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=812604;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=842580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=580969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=898356;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=604787;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48232 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=422462;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=207748;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:08 INFO  send() - 124.70.231.34:48234 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=527182;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=809936;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48233 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=754313;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=985669;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48235 - "POST /api/stop HTTP/1.1" 200 ]8;id=492950;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=630481;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:09 INFO  send() - 124.70.231.34:48734 - "GET /api/llm HTTP/1.1" 200 ]8;id=163;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=779505;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=61285;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=98867;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:48237 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=535687;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=700363;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48735 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=252040;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=208398;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48736 - "POST /api/stop HTTP/1.1" 200 ]8;id=437147;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=514030;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48737 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=363592;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=181825;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:10 INFO  send() - 124.70.231.34:48740 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=747220;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=340945;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=987293;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=947747;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:48738 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=217919;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=666643;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48739 - "GET /api/llm HTTP/1.1" 200 ]8;id=231921;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=905147;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48742 - "POST /api/stop HTTP/1.1" 200 ]8;id=868976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=148094;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48741 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=530487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=406446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=786484;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=534027;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=394020;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=200438;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:19:11 INFO  send() - 124.70.231.34:48236 - "GET /api/conversation HTTP/1.1" 200 ]8;id=18126;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=752245;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=34462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=995171;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=116450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=796547;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48743 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=135017;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=378040;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:12 INFO  send() - 124.70.231.34:48745 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=960520;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=292898;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:13 INFO  send() - 124.70.231.34:48744 - "GET /api/conversation HTTP/1.1" 200 ]8;id=406872;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=325331;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:14 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=78664;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=670040;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:48749 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=340334;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=740131;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  INFO  send() - 124.70.231.34:48748 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=384689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=393991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=843523;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=810508;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:19:16 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=118668;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=762723;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48747 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=541683;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=388446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10633;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=903663;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=458278;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=36767;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=168334;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=206293;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48750 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=65599;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=253665;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:17 INFO  send() - 124.70.231.34:48746 - "GET /api/conversation HTTP/1.1" 200 ]8;id=461940;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=326548;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48752 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=284409;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=29725;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:19 INFO  send() - 124.70.231.34:48751 - "GET /api/conversation HTTP/1.1" 200 ]8;id=773152;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=873667;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=511288;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=78197;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:48756 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=983931;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=296797;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=38733;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=765189;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48755 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=873861;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851199;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=2076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=720814;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:19:21 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=786628;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=555143;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48754 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=182213;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=308418;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=649993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=227834;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=698516;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=645960;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48757 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=863206;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=582195;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:22 INFO  send() - 124.70.231.34:48753 - "GET /api/conversation HTTP/1.1" 200 ]8;id=309338;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=116381;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:23 INFO  send() - 124.70.231.34:48759 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=223446;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=902826;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=995345;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=875257;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=750212;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=922665;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48758 - "GET /api/conversation HTTP/1.1" 200 ]8;id=338854;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=344243;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=131043;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=82209;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=216082;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=639525;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:19:25 INFO  send() - 124.70.231.34:48760 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=843951;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=297132;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48762 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=754760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=311487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:26 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=763251;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=212524;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48763 - "GET /api/mcp/xDhQ7o?edit=true HTTP/1.1" 200 ]8;id=811302;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=929895;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48761 - "GET /api/conversation HTTP/1.1" 200 ]8;id=638733;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=297289;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:27 INFO  send() - 124.70.231.34:48764 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=978225;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=311743;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=446471;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=432180;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=811188;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=629974;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=173916;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=757063;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=996464;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48765 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=481605;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=412322;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=764753;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=213903;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=547729;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=793742;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=40734;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=732342;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=638103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=480264;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48766 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=22810;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=862332;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:34 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=876283;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=323303;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=297539;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=918533;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=272936;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=90070;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=998942;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=778562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48767 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=670739;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=33647;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=499872;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=665223;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=780131;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=853897;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=550511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=773762;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=668220;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=230019;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48768 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=94636;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=101941;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=29103;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=844257;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=269061;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=427839;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=401450;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=189288;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=297141;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=373949;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48769 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=886006;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=477087;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:46 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=695702;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=744042;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=222342;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=641700;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=861875;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=827083;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=373716;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=454124;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48770 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=913316;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=579487;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:50 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=769230;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=874880;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=825235;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=772504;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=204182;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=886612;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=516218;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=309879;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48771 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=640491;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=449629;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:54 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=30987;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=605901;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=738617;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=137829;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=236927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=739725;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=18435;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=113474;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48772 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=45356;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=176336;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:19:58 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=353952;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=10943;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=336553;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=703512;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=761555;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=495383;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=472580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=238433;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48773 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=718038;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=766153;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:02 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=417332;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=694933;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=907004;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=258580;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=265065;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=748525;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=339562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=719870;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48774 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=580793;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=545936;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:06 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=608868;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=964779;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=717963;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=964476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=81551;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=154051;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=749445;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=90147;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:48775 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=951426;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=861779;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:10 INFO  send() - 124.70.231.34:48776 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=780447;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=259264;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48777 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=588180;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=45740;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:44 INFO  send() - 124.70.231.34:48778 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=299923;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=428323;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48779 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=946106;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=849193;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:50 INFO  send() - 124.70.231.34:48781 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=714847;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=169464;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48780 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=488238;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=580400;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48782 - "POST /api/stop HTTP/1.1" 200 ]8;id=706435;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=161070;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:51 INFO  send() - 124.70.231.34:48785 - "GET /api/llm HTTP/1.1" 200 ]8;id=364073;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=743285;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48784 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=652689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=853910;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=41787;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=252610;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:48786 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=64189;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=11210;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48788 - "POST /api/stop HTTP/1.1" 200 ]8;id=526980;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=368355;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48787 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=259737;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=875239;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=768102;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=948592;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:48789 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=996723;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=707159;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48790 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=314101;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=46320;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48791 - "GET /api/llm HTTP/1.1" 200 ]8;id=221398;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=73991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48793 - "POST /api/stop HTTP/1.1" 200 ]8;id=159226;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=773939;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:48792 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=622080;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=970817;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:52 INFO  send() - 124.70.231.34:48783 - "GET /api/conversation HTTP/1.1" 200 ]8;id=585006;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=867379;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:53 INFO  send() - 124.70.231.34:48795 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=634567;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=36150;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:54 INFO  send() - 124.70.231.34:48794 - "GET /api/conversation HTTP/1.1" 200 ]8;id=760745;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=216352;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:55 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=797077;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=153628;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:49295 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=698379;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=606732;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  INFO  send() - 124.70.231.34:49294 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=652444;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=186518;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=543308;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=184789;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:20:57 INFO  send() - 124.70.231.34:49293 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=281408;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=470566;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:58 INFO  send() - 124.70.231.34:49292 - "GET /api/conversation HTTP/1.1" 200 ]8;id=438891;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=286837;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:20:59 INFO  send() - 124.70.231.34:49297 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=932234;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=562962;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:00 INFO  send() - 124.70.231.34:49296 - "GET /api/conversation HTTP/1.1" 200 ]8;id=621482;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=12454;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:01 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=381136;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=918606;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:49301 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=933937;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=484333;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  INFO  send() - 124.70.231.34:49300 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=690814;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=643886;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=713261;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=594737;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:21:04 INFO  send() - 124.70.231.34:49299 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=477092;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=989480;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:05 INFO  send() - 124.70.231.34:49298 - "GET /api/conversation HTTP/1.1" 200 ]8;id=726842;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=771456;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:06 INFO  send() - 124.70.231.34:49303 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=859495;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=12864;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:08 INFO  send() - 124.70.231.34:49302 - "GET /api/conversation HTTP/1.1" 200 ]8;id=228843;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=56992;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49305 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=726502;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=40071;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:10 INFO  send() - 124.70.231.34:49304 - "GET /api/conversation HTTP/1.1" 200 ]8;id=368745;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=819107;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49307 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=374290;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=505213;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49306 - "GET /api/service?page=1&searchType=all&my=true HTTP/1.1" 200 ]8;id=10403;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=184682;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49308 - "POST /api/stop HTTP/1.1" 200 ]8;id=266235;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=587071;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=117000;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=446945;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:49311 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=621976;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=978080;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49310 - "GET /api/llm HTTP/1.1" 200 ]8;id=651076;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=933151;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49312 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=175656;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=149159;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:11 INFO  send() - 124.70.231.34:49313 - "POST /api/stop HTTP/1.1" 200 ]8;id=335083;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=695096;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49314 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=874624;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=564764;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:12 INFO  send() - 124.70.231.34:49315 - "GET /api/auth/user HTTP/1.1" 200 ]8;id=349727;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=465395;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取知识库ID失败,未找到对话 ]8;id=814376;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=636982;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#88\88]8;;\ -  INFO  send() - 124.70.231.34:49316 - "GET /api/knowledge?conversationId=&kbName= HTTP/1.1" 200 ]8;id=525430;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851628;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49317 - "GET /api/llm HTTP/1.1" 200 ]8;id=430838;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=829634;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=798476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=349045;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49320 - "POST /api/stop HTTP/1.1" 200 ]8;id=253773;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=149060;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49319 - "GET /api/app/recent?count=5 HTTP/1.1" 200 ]8;id=213964;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=940494;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=608462;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=204744;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=343046;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=602446;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=175017;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=403323;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49318 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=119802;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=249593;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:13 INFO  send() - 124.70.231.34:49309 - "GET /api/conversation HTTP/1.1" 200 ]8;id=911552;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=97453;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49322 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=762930;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=767513;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:14 INFO  send() - 124.70.231.34:49321 - "GET /api/conversation HTTP/1.1" 200 ]8;id=972959;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=296053;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:15 ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=405416;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=701978;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:49324 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=878300;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=819907;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  INFO  send() - 124.70.231.34:49325 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=606111;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=257782;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=166016;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=123468;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:21:17 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=124240;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=556135;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49326 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=182426;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=987519;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=295778;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=464640;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=42941;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=408926;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=407483;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=648098;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49327 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=474645;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=785529;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:18 INFO  send() - 124.70.231.34:49323 - "GET /api/conversation HTTP/1.1" 200 ]8;id=965194;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=712338;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:19 INFO  send() - 124.70.231.34:49329 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=497644;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=851104;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:21 INFO  send() - 124.70.231.34:49328 - "GET /api/conversation HTTP/1.1" 200 ]8;id=879529;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=737580;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=113744;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=841295;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=63766;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=404592;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=131526;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=232511;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=824927;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=743748;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49330 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=323047;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=245103;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  ERROR  list_team_kb() - [KnowledgeBaseManager] 获取团队知识库列表失败: All connection attempts failed ]8;id=229006;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py\knowledge.py]8;;\:]8;id=666828;file:///home/zjq/euler-copilot-framework_1/apps/services/knowledge.py#98\98]8;;\ -  INFO  send() - 124.70.231.34:49334 - "GET /api/knowledge?conversationId=5e728684-a6f3-4827-805e-9652630ac1cb&kbName=  ]8;id=443727;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=694192;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 200   -  INFO  send() - 124.70.231.34:49333 - "GET /api/document/5e728684-a6f3-4827-805e-9652630ac1cb?used=true&unused=true  ]8;id=432971;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=391979;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  HTTP/1.1" 500   -  ERROR  run_asgi() - Exception in ASGI application ]8;id=60569;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=110663;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#408\408]8;;\ -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:101 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │  98 │ if len(HTTPCORE_EXC_MAP) == 0: │   -  │  99 │ │ HTTPCORE_EXC_MAP = _load_httpcore_exceptions() │   -  │ 100 │ try: │   -  │ ❱ 101 │ │ yield │   -  │ 102 │ except Exception as exc: │   -  │ 103 │ │ mapped_exc = None │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:394 in │   -  │ handle_async_request │   -  │ │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ 393 │ │ with map_httpcore_exceptions(): │   -  │ ❱ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ 397  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:256 in │   -  │ handle_async_request │   -  │ │   -  │ 253 │ │ │ │ closing = self._assign_requests_to_connections() │   -  │ 254 │ │ │  │   -  │ 255 │ │ │ await self._close_connections(closing) │   -  │ ❱ 256 │ │ │ raise exc from None │   -  │ 257 │ │  │   -  │ 258 │ │ # Return the response. Note that in this case we still have to manage │   -  │ 259 │ │ # the point at which the response is closed. │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection_pool.py:236 in │   -  │ handle_async_request │   -  │ │   -  │ 233 │ │ │ │  │   -  │ 234 │ │ │ │ try: │   -  │ 235 │ │ │ │ │ # Send the request on the assigned connection. │   -  │ ❱ 236 │ │ │ │ │ response = await connection.handle_async_request( │   -  │ 237 │ │ │ │ │ │ pool_request.request │   -  │ 238 │ │ │ │ │ ) │   -  │ 239 │ │ │ │ except ConnectionNotAvailable: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:101 in │   -  │ handle_async_request │   -  │ │   -  │  98 │ │ │ │ │ │ ) │   -  │  99 │ │ except BaseException as exc: │   -  │ 100 │ │ │ self._connect_failed = True │   -  │ ❱ 101 │ │ │ raise exc │   -  │ 102 │ │  │   -  │ 103 │ │ return await self._connection.handle_async_request(request) │   -  │ 104  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:78 in │   -  │ handle_async_request │   -  │ │   -  │  75 │ │ try: │   -  │  76 │ │ │ async with self._request_lock: │   -  │  77 │ │ │ │ if self._connection is None: │   -  │ ❱  78 │ │ │ │ │ stream = await self._connect(request) │   -  │  79 │ │ │ │ │  │   -  │  80 │ │ │ │ │ ssl_object = stream.get_extra_info("ssl_object") │   -  │  81 │ │ │ │ │ http2_negotiated = ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_async/connection.py:124 in │   -  │ _connect │   -  │ │   -  │ 121 │ │ │ │ │ │ "socket_options": self._socket_options, │   -  │ 122 │ │ │ │ │ } │   -  │ 123 │ │ │ │ │ async with Trace("connect_tcp", logger, request, kwargs) as trace: │   -  │ ❱ 124 │ │ │ │ │ │ stream = await self._network_backend.connect_tcp(**kwargs) │   -  │ 125 │ │ │ │ │ │ trace.return_value = stream │   -  │ 126 │ │ │ │ else: │   -  │ 127 │ │ │ │ │ kwargs = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/auto.py:31 in │   -  │ connect_tcp │   -  │ │   -  │ 28 │ │ socket_options: typing.Iterable[SOCKET_OPTION] | None = None, │   -  │ 29 │ ) -> AsyncNetworkStream: │   -  │ 30 │ │ await self._init_backend() │   -  │ ❱ 31 │ │ return await self._backend.connect_tcp( │   -  │ 32 │ │ │ host, │   -  │ 33 │ │ │ port, │   -  │ 34 │ │ │ timeout=timeout, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_backends/anyio.py:113 in │   -  │ connect_tcp │   -  │ │   -  │ 110 │ │ │ OSError: ConnectError, │   -  │ 111 │ │ │ anyio.BrokenResourceError: ConnectError, │   -  │ 112 │ │ } │   -  │ ❱ 113 │ │ with map_exceptions(exc_map): │   -  │ 114 │ │ │ with anyio.fail_after(timeout): │   -  │ 115 │ │ │ │ stream: anyio.abc.ByteStream = await anyio.connect_tcp( │   -  │ 116 │ │ │ │ │ remote_host=host, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpcore/_exceptions.py:14 in │   -  │ map_exceptions │   -  │ │   -  │ 11 │ except Exception as exc: # noqa: PIE786 │   -  │ 12 │ │ for from_exc, to_exc in map.items(): │   -  │ 13 │ │ │ if isinstance(exc, from_exc): │   -  │ ❱ 14 │ │ │ │ raise to_exc(exc) from exc │   -  │ 15 │ │ raise # pragma: nocover │   -  │ 16  │   -  │ 17  │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -    -  The above exception was the direct cause of the following exception:   -    -  ╭─────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────╮   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py:403 in │   -  │ run_asgi │   -  │ │   -  │ 400 │ # ASGI exception wrapper │   -  │ 401 │ async def run_asgi(self, app: ASGI3Application) -> None: │   -  │ 402 │ │ try: │   -  │ ❱ 403 │ │ │ result = await app( # type: ignore[func-returns-value] │   -  │ 404 │ │ │ │ self.scope, self.receive, self.send │   -  │ 405 │ │ │ ) │   -  │ 406 │ │ except BaseException as exc: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py:60 in │   -  │ __call__ │   -  │ │   -  │  57 │ │ │ │ │ port = 0 │   -  │  58 │ │ │ │ │ scope["client"] = (host, port) │   -  │  59 │ │  │   -  │ ❱  60 │ │ return await self.app(scope, receive, send) │   -  │  61  │   -  │  62  │   -  │  63 def _parse_raw_hosts(value: str) -> list[str]: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/applications.py:1054 in __call__ │   -  │ │   -  │ 1051 │ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 1052 │ │ if self.root_path: │   -  │ 1053 │ │ │ scope["root_path"] = self.root_path │   -  │ ❱ 1054 │ │ await super().__call__(scope, receive, send) │   -  │ 1055 │  │   -  │ 1056 │ def add_api_route( │   -  │ 1057 │ │ self, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/applications.py:112 in __call__ │   -  │ │   -  │ 109 │ │ scope["app"] = self │   -  │ 110 │ │ if self.middleware_stack is None: │   -  │ 111 │ │ │ self.middleware_stack = self.build_middleware_stack() │   -  │ ❱ 112 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 113 │  │   -  │ 114 │ def on_event(self, event_type: str) -> typing.Callable: # type: ignore[type-arg] │   -  │ 115 │ │ return self.router.on_event(event_type) # pragma: no cover │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:187 in │   -  │ __call__ │   -  │ │   -  │ 184 │ │ │ # We always continue to raise the exception. │   -  │ 185 │ │ │ # This allows servers to log the error, or allows test clients │   -  │ 186 │ │ │ # to optionally raise the error within the test case. │   -  │ ❱ 187 │ │ │ raise exc │   -  │ 188 │  │   -  │ 189 │ def format_line(self, index: int, line: str, frame_lineno: int, frame_index: int) -> │   -  │ str: │   -  │ 190 │ │ values = { │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/errors.py:165 in │   -  │ __call__ │   -  │ │   -  │ 162 │ │ │ await send(message) │   -  │ 163 │ │  │   -  │ 164 │ │ try: │   -  │ ❱ 165 │ │ │ await self.app(scope, receive, _send) │   -  │ 166 │ │ except Exception as exc: │   -  │ 167 │ │ │ request = Request(scope) │   -  │ 168 │ │ │ if self.debug: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/cors.py:85 in │   -  │ __call__ │   -  │ │   -  │  82 │ │ origin = headers.get("origin") │   -  │  83 │ │  │   -  │  84 │ │ if origin is None: │   -  │ ❱  85 │ │ │ await self.app(scope, receive, send) │   -  │  86 │ │ │ return │   -  │  87 │ │  │   -  │  88 │ │ if method == "OPTIONS" and "access-control-request-method" in headers: │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/middleware/exceptions.py:62 in │   -  │ __call__ │   -  │ │   -  │ 59 │ │ else: │   -  │ 60 │ │ │ conn = WebSocket(scope, receive, send) │   -  │ 61 │ │  │   -  │ ❱ 62 │ │ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) │   -  │ 63 │  │   -  │ 64 │ def http_exception(self, request: Request, exc: Exception) -> Response: │   -  │ 65 │ │ assert isinstance(exc, HTTPException) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:714 in __call__ │   -  │ │   -  │ 711 │ │ """ │   -  │ 712 │ │ The main entry point to the Router class. │   -  │ 713 │ │ """ │   -  │ ❱ 714 │ │ await self.middleware_stack(scope, receive, send) │   -  │ 715 │  │   -  │ 716 │ async def app(self, scope: Scope, receive: Receive, send: Send) -> None: │   -  │ 717 │ │ assert scope["type"] in ("http", "websocket", "lifespan") │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:734 in app │   -  │ │   -  │ 731 │ │ │ match, child_scope = route.matches(scope) │   -  │ 732 │ │ │ if match == Match.FULL: │   -  │ 733 │ │ │ │ scope.update(child_scope) │   -  │ ❱ 734 │ │ │ │ await route.handle(scope, receive, send) │   -  │ 735 │ │ │ │ return │   -  │ 736 │ │ │ elif match == Match.PARTIAL and partial is None: │   -  │ 737 │ │ │ │ partial = route │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:288 in handle │   -  │ │   -  │ 285 │ │ │ │ response = PlainTextResponse("Method Not Allowed", status_code=405, │   -  │ headers=headers) │   -  │ 286 │ │ │ await response(scope, receive, send) │   -  │ 287 │ │ else: │   -  │ ❱ 288 │ │ │ await self.app(scope, receive, send) │   -  │ 289 │  │   -  │ 290 │ def __eq__(self, other: typing.Any) -> bool: │   -  │ 291 │ │ return ( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:76 in app │   -  │ │   -  │  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │ ❱  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │  77 │  │   -  │  78 │ return app │   -  │  79  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:53 in │   -  │ wrapped_app │   -  │ │   -  │ 50 │ │ │ │ handler = _lookup_exception_handler(exception_handlers, exc) │   -  │ 51 │ │ │  │   -  │ 52 │ │ │ if handler is None: │   -  │ ❱ 53 │ │ │ │ raise exc │   -  │ 54 │ │ │  │   -  │ 55 │ │ │ if response_started: │   -  │ 56 │ │ │ │ raise RuntimeError("Caught handled exception, but response already  │   -  │ started.") from exc │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/_exception_handler.py:42 in │   -  │ wrapped_app │   -  │ │   -  │ 39 │ │ │ await send(message) │   -  │ 40 │ │  │   -  │ 41 │ │ try: │   -  │ ❱ 42 │ │ │ await app(scope, receive, sender) │   -  │ 43 │ │ except Exception as exc: │   -  │ 44 │ │ │ handler = None │   -  │ 45  │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/starlette/routing.py:73 in app │   -  │ │   -  │  70 │ │ request = Request(scope, receive, send) │   -  │  71 │ │  │   -  │  72 │ │ async def app(scope: Scope, receive: Receive, send: Send) -> None: │   -  │ ❱  73 │ │ │ response = await f(request) │   -  │  74 │ │ │ await response(scope, receive, send) │   -  │  75 │ │  │   -  │  76 │ │ await wrap_app_handling_exceptions(app, request)(scope, receive, send) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:301 in app │   -  │ │   -  │  298 │ │ │ │ ) │   -  │  299 │ │ │ │ errors = solved_result.errors │   -  │  300 │ │ │ │ if not errors: │   -  │ ❱  301 │ │ │ │ │ raw_response = await run_endpoint_function( │   -  │  302 │ │ │ │ │ │ dependant=dependant, │   -  │  303 │ │ │ │ │ │ values=solved_result.values, │   -  │  304 │ │ │ │ │ │ is_coroutine=is_coroutine, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/fastapi/routing.py:212 in │   -  │ run_endpoint_function │   -  │ │   -  │  209 │ assert dependant.call is not None, "dependant.call must be a function" │   -  │  210 │  │   -  │  211 │ if is_coroutine: │   -  │ ❱  212 │ │ return await dependant.call(**values) │   -  │  213 │ else: │   -  │  214 │ │ return await run_in_threadpool(dependant.call, **values) │   -  │  215  │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/routers/document.py:96 in get_document_list │   -  │ │   -  │  93 │ if unused: │   -  │  94 │ │ # 拿到所有未使用的文档 │   -  │  95 │ │ unused_docs = await DocumentManager.get_unused_docs(user_sub, conversation_id) │   -  │ ❱  96 │ │ doc_status = await KnowledgeBaseService.get_doc_status_from_rag(session_id,  │   -  │ [item.id for item in unused_docs]) │   -  │  97 │ │ for current_doc in unused_docs: │   -  │  98 │ │ │ for status_item in doc_status: │   -  │  99 │ │ │ │ if current_doc.id != status_item.id: │   -  │ │   -  │ /home/zjq/euler-copilot-framework_1/apps/services/knowledge_base.py:76 in get_doc_status_from_rag │   -  │ │   -  │ 73 │ │ } │   -  │ 74 │ │ post_data = {"ids": doc_ids} │   -  │ 75 │ │ async with httpx.AsyncClient() as client: │   -  │ ❱ 76 │ │ │ resp = await client.post(_RAG_DOC_STATUS_URI, headers=headers,  │   -  │ json=post_data, timeout=30.0) │   -  │ 77 │ │ │ resp_data = resp.json() │   -  │ 78 │ │ │ if resp.status_code != status.HTTP_200_OK: │   -  │ 79 │ │ │ │ return [] │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1859 in post │   -  │ │   -  │ 1856 │ │  │   -  │ 1857 │ │ **Parameters**: See `httpx.request`. │   -  │ 1858 │ │ """ │   -  │ ❱ 1859 │ │ return await self.request( │   -  │ 1860 │ │ │ "POST", │   -  │ 1861 │ │ │ url, │   -  │ 1862 │ │ │ content=content, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1540 in request │   -  │ │   -  │ 1537 │ │ │ timeout=timeout, │   -  │ 1538 │ │ │ extensions=extensions, │   -  │ 1539 │ │ ) │   -  │ ❱ 1540 │ │ return await self.send(request, auth=auth, follow_redirects=follow_redirects) │   -  │ 1541 │  │   -  │ 1542 │ @asynccontextmanager │   -  │ 1543 │ async def stream( │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1629 in send │   -  │ │   -  │ 1626 │ │  │   -  │ 1627 │ │ auth = self._build_request_auth(request, auth) │   -  │ 1628 │ │  │   -  │ ❱ 1629 │ │ response = await self._send_handling_auth( │   -  │ 1630 │ │ │ request, │   -  │ 1631 │ │ │ auth=auth, │   -  │ 1632 │ │ │ follow_redirects=follow_redirects, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1657 in │   -  │ _send_handling_auth │   -  │ │   -  │ 1654 │ │ │ request = await auth_flow.__anext__() │   -  │ 1655 │ │ │  │   -  │ 1656 │ │ │ while True: │   -  │ ❱ 1657 │ │ │ │ response = await self._send_handling_redirects( │   -  │ 1658 │ │ │ │ │ request, │   -  │ 1659 │ │ │ │ │ follow_redirects=follow_redirects, │   -  │ 1660 │ │ │ │ │ history=history, │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1694 in │   -  │ _send_handling_redirects │   -  │ │   -  │ 1691 │ │ │ for hook in self._event_hooks["request"]: │   -  │ 1692 │ │ │ │ await hook(request) │   -  │ 1693 │ │ │  │   -  │ ❱ 1694 │ │ │ response = await self._send_single_request(request) │   -  │ 1695 │ │ │ try: │   -  │ 1696 │ │ │ │ for hook in self._event_hooks["response"]: │   -  │ 1697 │ │ │ │ │ await hook(response) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_client.py:1730 in │   -  │ _send_single_request │   -  │ │   -  │ 1727 │ │ │ ) │   -  │ 1728 │ │  │   -  │ 1729 │ │ with request_context(request=request): │   -  │ ❱ 1730 │ │ │ response = await transport.handle_async_request(request) │   -  │ 1731 │ │  │   -  │ 1732 │ │ assert isinstance(response.stream, AsyncByteStream) │   -  │ 1733 │ │ response.request = request │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:393 in │   -  │ handle_async_request │   -  │ │   -  │ 390 │ │ │ content=request.stream, │   -  │ 391 │ │ │ extensions=request.extensions, │   -  │ 392 │ │ ) │   -  │ ❱ 393 │ │ with map_httpcore_exceptions(): │   -  │ 394 │ │ │ resp = await self._pool.handle_async_request(req) │   -  │ 395 │ │  │   -  │ 396 │ │ assert isinstance(resp.stream, typing.AsyncIterable) │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/contextlib.py:158 in __exit__ │   -  │ │   -  │ 155 │ │ │ │ # tell if we get the same exception back │   -  │ 156 │ │ │ │ value = typ() │   -  │ 157 │ │ │ try: │   -  │ ❱ 158 │ │ │ │ self.gen.throw(typ, value, traceback) │   -  │ 159 │ │ │ except StopIteration as exc: │   -  │ 160 │ │ │ │ # Suppress StopIteration *unless* it's the same exception that │   -  │ 161 │ │ │ │ # was passed to throw(). This prevents a StopIteration │   -  │ │   -  │ /root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/httpx/_transports/default.py:118 in │   -  │ map_httpcore_exceptions │   -  │ │   -  │ 115 │ │ │ raise │   -  │ 116 │ │  │   -  │ 117 │ │ message = str(exc) │   -  │ ❱ 118 │ │ raise mapped_exc(message) from exc │   -  │ 119  │   -  │ 120  │   -  │ 121 class ResponseStream(SyncByteStream): │   -  ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   -  ConnectError: All connection attempts failed   -25-Aug-12 20:21:23 INFO  send() - 124.70.231.34:49332 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=965528;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=728341;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:24 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=862805;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=920109;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=956002;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=223299;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=402572;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=558679;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=215339;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=120022;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49335 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=197827;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=334689;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:25 INFO  send() - 124.70.231.34:49331 - "GET /api/conversation HTTP/1.1" 200 ]8;id=668330;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=101957;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49337 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=387684;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=663568;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:26 INFO  send() - 124.70.231.34:49336 - "GET /api/conversation HTTP/1.1" 200 ]8;id=321373;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=135896;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:27 INFO  send() - 124.70.231.34:49339 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=62709;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=139932;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:28 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=64678;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=769884;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=120465;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=366336;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=52914;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=500386;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=743476;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=810424;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49340 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=213221;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=559760;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -  INFO  send() - 124.70.231.34:49338 - "GET /api/conversation HTTP/1.1" 200 ]8;id=308878;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=104305;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:29 INFO  send() - 124.70.231.34:49341 - "GET /api/record/5e728684-a6f3-4827-805e-9652630ac1cb HTTP/1.1" 200 ]8;id=476360;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=499021;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:31 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=998929;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=399486;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=10214;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=272279;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=308654;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=697314;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=335121;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=193852;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49342 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=123709;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=515022;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:35 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=660969;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=769415;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=536505;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=353060;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=977970;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=495195;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=549799;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=836861;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49343 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=213023;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=512435;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:38 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=551836;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=869305;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=624478;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=577130;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -25-Aug-12 20:21:39 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=466195;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=895732;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=987595;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=242923;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49344 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=408991;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=103151;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:42 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=733562;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=169691;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=400302;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=854310;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=76653;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=976850;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=815076;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=856404;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49345 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=114580;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=982410;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:45 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=922040;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=548675;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=287291;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=997707;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=593810;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=181919;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=472132;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=436316;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49346 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=822625;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=992628;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:49 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=848528;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=788025;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=9526;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=24552;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=81785;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=722376;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=139079;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=576866;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49347 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=296964;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=165145;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -25-Aug-12 20:21:53 WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: xDhQ7o ]8;id=269564;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=252993;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: CxaGNS ]8;id=666040;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=998984;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: tCn5Fy ]8;id=762824;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=497623;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  WARNING  get_icon() - [MCPLoader] MCP模板图标不存在: 6Zn8Gg ]8;id=888593;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py\mcp.py]8;;\:]8;id=195181;file:///home/zjq/euler-copilot-framework_1/apps/scheduler/pool/loader/mcp.py#353\353]8;;\ -  INFO  send() - 124.70.231.34:49348 - "GET /api/mcp?page=1&searchType=all&isActive=true HTTP/1.1" 200 ]8;id=251138;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py\h11_impl.py]8;;\:]8;id=677327;file:///root/miniconda3/envs/framework_test_env/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py#473\473]8;;\ -- Gitee From e3ecc6bb05b8a1b8cb44cc30038359f5296bc1fe Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 23:15:53 +0800 Subject: [PATCH 77/78] =?UTF-8?q?=E5=AE=9E=E6=97=B6=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=AE=A1=E5=88=92=E5=B9=B6=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 13 +++++++-- apps/scheduler/mcp_agent/plan.py | 8 ++++-- apps/scheduler/mcp_agent/prompt.py | 45 +++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 3c6ef8e5..d2cfce15 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -93,6 +93,15 @@ class MCPAgentExecutor(BaseExecutor): for tool in mcp_service.tools: self.tools[tool.id] = tool self.tool_list.extend(mcp_service.tools) + self.tools[FINAL_TOOL_ID] = MCPTool( + id=FINAL_TOOL_ID, + name="Final Tool", + description="结束流程的工具", + mcp_id="", + input_schema={} + ) + self.tool_list.append(MCPTool(id=FINAL_TOOL_ID, name="Final Tool", + description="结束流程的工具", mcp_id="", input_schema={})) async def get_tool_input_param(self, is_first: bool) -> None: if is_first: @@ -260,7 +269,7 @@ class MCPAgentExecutor(BaseExecutor): if step is None or step.tool_id not in self.tools.keys(): step = Step( tool_id=FINAL_TOOL_ID, - step_description=FINAL_TOOL_ID + description=FINAL_TOOL_ID ) tool_id = step.tool_id if tool_id == FINAL_TOOL_ID: @@ -399,7 +408,6 @@ class MCPAgentExecutor(BaseExecutor): async def summarize(self) -> None: async for chunk in MCPPlanner.generate_answer( self.task.runtime.question, - self.task.runtime.temporary_plans, (await MCPHost.assemble_memory(self.task)), self.resoning_llm ): @@ -420,6 +428,7 @@ class MCPAgentExecutor(BaseExecutor): self.task.state.flow_id = str(uuid.uuid4()) self.task.state.flow_name = await MCPPlanner.get_flow_name(self.task.runtime.question, self.resoning_llm) await TaskManager.save_task(self.task.id, self.task) + await self.get_next_step() except Exception as e: import traceback logger.error("[MCPAgentExecutor] 初始化失败: %s", traceback.format_exc()) diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 9fee0b78..84c08d60 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -181,6 +181,10 @@ class MCPPlanner(McpBase): # 解析为结构化数据 schema = Step.model_json_schema() + if "enum" not in schema["properties"]["tool_id"]: + schema["properties"]["tool_id"]["enum"] = [] + for tool in tools: + schema["properties"]["tool_id"]["enum"].append(tool.id) step = await MCPPlanner._parse_result(result, schema) # 使用Step模型解析结果 return Step.model_validate(step) @@ -296,7 +300,6 @@ class MCPPlanner(McpBase): prompt = tmplate.render( goal=goal, history=history, - error_message=error_message, step_id=tool.id, step_name=tool.name, step_description=step_description, @@ -349,12 +352,11 @@ class MCPPlanner(McpBase): @staticmethod async def generate_answer( - user_goal: str, plan: MCPPlan, memory: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> AsyncGenerator[ + user_goal: str, memory: str, resoning_llm: ReasoningLLM = ReasoningLLM()) -> AsyncGenerator[ str, None]: """生成最终回答""" template = _env.from_string(FINAL_ANSWER) prompt = template.render( - plan=plan.model_dump(exclude_none=True, by_alias=True), memory=memory, goal=user_goal, ) diff --git a/apps/scheduler/mcp_agent/prompt.py b/apps/scheduler/mcp_agent/prompt.py index b7cf10e8..31e8ce54 100644 --- a/apps/scheduler/mcp_agent/prompt.py +++ b/apps/scheduler/mcp_agent/prompt.py @@ -512,9 +512,9 @@ GEN_STEP = dedent(r""" 3.不要选择不存在的工具。 4.如果你认为当前已经达成了用户的目标,可以直接返回Final工具,表示计划执行结束。 - # 样例 + # 样例 1 # 目标 - 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优 + 我需要扫描当前mysql数据库,分析性能瓶颈, 并调优,我的ip是192.168.1.1,数据库端口是3306,用户名是root,密码是password # 历史记录 第1步:生成端口扫描命令 - 调用工具 `command_generator`,并提供参数 `帮我生成一个mysql端口扫描命令` @@ -534,8 +534,42 @@ GEN_STEP = dedent(r""" # 输出 ```json { - "tool_id": "mcp_tool", // 选择的工具ID - "step_description": "分析MySQL数据库性能" // 对当前步骤的描述 + "tool_id": "mcp_tool_1", // 选择的工具ID + "description": "扫描ip为192.168.1.1的MySQL数据库,端口为3306,用户名为root,密码为password的数据库性能", + } + ``` + # 样例二 + # 目标 + 计划从杭州到北京的旅游计划 + # 历史记录 + 第1步:将杭州转换为经纬度坐标 + - 调用工具 `maps_geo_planner`,并提供参数 `{"city_from": "杭州", "address": "西湖"}` + - 执行状态:成功 + - 得到数据:`{"location": "123.456, 78.901"}` + 第2步:查询杭州的天气 + - 调用工具 `weather_query`,并提供参数 `{"location": "123.456, 78.901"}` + - 执行状态:成功 + - 得到数据:`{"weather": "晴", "temperature": "25°C"}` + 第3步:将北京转换为经纬度坐标 + - 调用工具 `maps_geo_planner`,并提供参数 `{"city_from": "北京", "address": "天安门"}` + - 执行状态:成功 + - 得到数据:`{"location": "123.456, 78.901"}` + 第4步:查询北京的天气 + - 调用工具 `weather_query`,并提供参数 `{"location": "123.456, 78.901"}` + - 执行状态:成功 + - 得到数据:`{"weather": "晴", "temperature": "25°C"}` + # 工具 + + - mcp_tool_4 maps_geo_planner;将详细的结构化地址转换为经纬度坐标。支持对地标性名胜景区、建筑物名称解析为经纬度坐标 + - mcp_tool_5 weather_query;天气查询,用于查询天气信息 + - mcp_tool_6 maps_direction_transit_integrated;根据用户起终点经纬度坐标规划综合各类公共(火车、公交、地铁)交通方式的通勤方案,并且返回通勤方案的数据,跨城场景下必须传起点城市与终点城市 + - Final Final;结束步骤,当执行到这一步时,表示计划执行结束,所得到的结果将作为最终结果。 + + # 输出 + ```json + { + "tool_id": "mcp_tool_6", // 选择的工具ID + "description": "规划从杭州到北京的综合公共交通方式的通勤方案" } ``` # 现在开始生成步骤: @@ -1035,9 +1069,6 @@ FINAL_ANSWER = dedent(r""" {{memory}} - # 其他背景信息: - - {{status}} # 现在,请根据以上信息,向用户报告目标的完成情况: -- Gitee From a493ac1a7699dc99ad1f192a6c35165dfde552d0 Mon Sep 17 00:00:00 2001 From: zxstty Date: Tue, 12 Aug 2025 23:21:01 +0800 Subject: [PATCH 78/78] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E7=94=9F=E6=88=90=E8=AE=A1=E5=88=92=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/scheduler/executor/agent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index d2cfce15..3997d89a 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -455,7 +455,7 @@ class MCPAgentExecutor(BaseExecutor): await self.summarize() return try: - while 1: + while self.task.state.flow_status == FlowStatus.RUNNING: if self.task.state.tool_id == FINAL_TOOL_ID: break await self.work() -- Gitee