diff --git a/backend/package/yuxi/agents/backends/__init__.py b/backend/package/yuxi/agents/backends/__init__.py index b5010208..702fa5b7 100644 --- a/backend/package/yuxi/agents/backends/__init__.py +++ b/backend/package/yuxi/agents/backends/__init__.py @@ -27,9 +27,9 @@ from .sandbox import ( get_sandbox_base_port, get_sandbox_host, get_sandbox_image, + get_sandbox_provider, get_sandbox_provisioner_url, get_sandbox_security_opts, - get_sandbox_provider, ) from .skills_backend import SelectedSkillsReadonlyBackend diff --git a/backend/package/yuxi/agents/backends/composite.py b/backend/package/yuxi/agents/backends/composite.py index ec66206b..0c4da3a4 100644 --- a/backend/package/yuxi/agents/backends/composite.py +++ b/backend/package/yuxi/agents/backends/composite.py @@ -4,8 +4,8 @@ from deepagents.backends import CompositeBackend, StateBackend from yuxi.agents.middlewares.skills_middleware import normalize_selected_skills -from .skills_backend import SelectedSkillsReadonlyBackend from .sandbox import get_sandbox_provider +from .skills_backend import SelectedSkillsReadonlyBackend def _get_visible_skills_from_runtime(runtime) -> list[str]: diff --git a/backend/package/yuxi/agents/backends/sandbox/__init__.py b/backend/package/yuxi/agents/backends/sandbox/__init__.py index 694c3dc4..8688a92a 100644 --- a/backend/package/yuxi/agents/backends/sandbox/__init__.py +++ b/backend/package/yuxi/agents/backends/sandbox/__init__.py @@ -16,10 +16,7 @@ - docker_api: Docker API 调用封装 """ -from .sandbox_executor import YuxiSandboxBackend -from .sandbox_info import SandboxInfo -from .sandbox_provisioner import YuxiSandboxProvider, get_sandbox_provider -from .sandbox_provisioner_base import SandboxBackend +from .path_security import normalize_virtual_path from .sandbox_config import ( IDLE_CHECK_INTERVAL, LARGE_TOOL_RESULTS_DIR, @@ -39,9 +36,12 @@ from .sandbox_config import ( get_sandbox_provisioner_url, get_sandbox_security_opts, ) +from .sandbox_executor import YuxiSandboxBackend +from .sandbox_info import SandboxInfo from .sandbox_local_container import LocalContainerBackend +from .sandbox_provisioner import YuxiSandboxProvider, get_sandbox_provider +from .sandbox_provisioner_base import SandboxBackend from .sandbox_remote import RemoteSandboxBackend -from .path_security import normalize_virtual_path __all__ = [ # Executor diff --git a/backend/package/yuxi/agents/backends/sandbox/sandbox_local_container.py b/backend/package/yuxi/agents/backends/sandbox/sandbox_local_container.py index c7723b2f..52d6cf6f 100644 --- a/backend/package/yuxi/agents/backends/sandbox/sandbox_local_container.py +++ b/backend/package/yuxi/agents/backends/sandbox/sandbox_local_container.py @@ -9,9 +9,9 @@ import urllib.parse from yuxi.utils.logging_config import logger from .docker_api import docker_api_request -from .sandbox_provisioner_base import SandboxBackend from .sandbox_config import get_sandbox_host, get_sandbox_security_opts from .sandbox_info import SandboxInfo +from .sandbox_provisioner_base import SandboxBackend class LocalContainerBackend(SandboxBackend): diff --git a/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner.py b/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner.py index 547a22db..b3d097b3 100644 --- a/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner.py +++ b/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner.py @@ -14,10 +14,6 @@ from yuxi import config as sys_config from yuxi.services.skill_service import get_skills_root_dir from yuxi.utils.logging_config import logger -from .sandbox_local_container import LocalContainerBackend -from .sandbox_remote import RemoteSandboxBackend -from .sandbox_executor import YuxiSandboxBackend -from .sandbox_provisioner_base import SandboxBackend from .sandbox_config import ( IDLE_CHECK_INTERVAL, LARGE_TOOL_RESULTS_DIR, @@ -34,7 +30,11 @@ from .sandbox_config import ( get_sandbox_image, get_sandbox_provisioner_url, ) +from .sandbox_executor import YuxiSandboxBackend from .sandbox_info import SandboxInfo +from .sandbox_local_container import LocalContainerBackend +from .sandbox_provisioner_base import SandboxBackend +from .sandbox_remote import RemoteSandboxBackend class YuxiSandboxProvider: @@ -259,9 +259,7 @@ class YuxiSandboxProvider: self._last_activity.pop(sandbox_id, None) self._warm_pool.pop(sandbox_id, None) thread_ids = [ - thread_id - for thread_id, mapped_id in self._thread_sandboxes.items() - if mapped_id == sandbox_id + thread_id for thread_id, mapped_id in self._thread_sandboxes.items() if mapped_id == sandbox_id ] for thread_id in thread_ids: del self._thread_sandboxes[thread_id] diff --git a/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner_base.py b/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner_base.py index 921d94fb..ff2418b9 100644 --- a/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner_base.py +++ b/backend/package/yuxi/agents/backends/sandbox/sandbox_provisioner_base.py @@ -13,17 +13,13 @@ class SandboxBackend(ABC): thread_id: str, sandbox_id: str, extra_mounts: list[tuple[str, str, bool]] | None = None, - ) -> SandboxInfo: - ... + ) -> SandboxInfo: ... @abstractmethod - def destroy(self, info: SandboxInfo) -> None: - ... + def destroy(self, info: SandboxInfo) -> None: ... @abstractmethod - def is_alive(self, info: SandboxInfo) -> bool: - ... + def is_alive(self, info: SandboxInfo) -> bool: ... @abstractmethod - def discover(self, sandbox_id: str) -> SandboxInfo | None: - ... + def discover(self, sandbox_id: str) -> SandboxInfo | None: ... diff --git a/backend/package/yuxi/agents/backends/sandbox/sandbox_remote.py b/backend/package/yuxi/agents/backends/sandbox/sandbox_remote.py index 9e6e35d7..e04fcd86 100644 --- a/backend/package/yuxi/agents/backends/sandbox/sandbox_remote.py +++ b/backend/package/yuxi/agents/backends/sandbox/sandbox_remote.py @@ -6,8 +6,8 @@ import requests from yuxi.utils.logging_config import logger -from .sandbox_provisioner_base import SandboxBackend from .sandbox_info import SandboxInfo +from .sandbox_provisioner_base import SandboxBackend class RemoteSandboxBackend(SandboxBackend): diff --git a/backend/package/yuxi/agents/buildin/chatbot/graph.py b/backend/package/yuxi/agents/buildin/chatbot/graph.py index 0833768d..01b7c869 100644 --- a/backend/package/yuxi/agents/buildin/chatbot/graph.py +++ b/backend/package/yuxi/agents/buildin/chatbot/graph.py @@ -21,6 +21,7 @@ from yuxi.services.subagent_service import get_subagents_from_names from .prompt import PROMPT + def _create_fs_backend(rt): """创建文件存储后端(支持沙盒执行) diff --git a/backend/package/yuxi/agents/buildin/deep_agent/graph.py b/backend/package/yuxi/agents/buildin/deep_agent/graph.py index bec69710..ba3015ff 100644 --- a/backend/package/yuxi/agents/buildin/deep_agent/graph.py +++ b/backend/package/yuxi/agents/buildin/deep_agent/graph.py @@ -39,11 +39,7 @@ class DeepAgent(BaseAgent): description = "具备规划、深度分析和子智能体协作能力的智能体,可以处理复杂的多步骤任务" context_schema = DeepContext capabilities = ["file_upload", "files", "todo"] # 支持文件上传功能 - metadata = { - "examples": [ - "调研一下多模态 GraphRAG 的相关论文" - ] - } + metadata = {"examples": ["调研一下多模态 GraphRAG 的相关论文"]} def __init__(self, **kwargs): super().__init__(**kwargs) diff --git a/backend/package/yuxi/agents/context.py b/backend/package/yuxi/agents/context.py index d28808f2..62901df6 100644 --- a/backend/package/yuxi/agents/context.py +++ b/backend/package/yuxi/agents/context.py @@ -92,7 +92,7 @@ class BaseContext: default=sys_config.default_model, metadata={ "name": "子智能体的默认模型", - "description": "子智能体的默认模型,会被子智能体的配置覆盖。", + "description": "为所有子智能体设置默认模型,可在各子智能体配置中单独覆盖。", }, ) diff --git a/backend/package/yuxi/agents/middlewares/skills_middleware.py b/backend/package/yuxi/agents/middlewares/skills_middleware.py index efa929eb..f1d6b826 100644 --- a/backend/package/yuxi/agents/middlewares/skills_middleware.py +++ b/backend/package/yuxi/agents/middlewares/skills_middleware.py @@ -404,9 +404,8 @@ class SkillsMiddleware(AgentMiddleware): return None pure = PurePosixPath(raw if raw.startswith("/") else f"/{raw}") parts = [p for p in pure.parts if p not in ("/", "")] - if len(parts) == 3 and parts[0] == "skills" and parts[2] == "SKILL.md": - slug = parts[1] - elif len(parts) == 4 and parts[0] == "mnt" and parts[1] == "skills" and parts[3] == "SKILL.md": + # 只支持 /mnt/skills/{slug}/SKILL.md 格式 + if len(parts) == 4 and parts[0] == "mnt" and parts[1] == "skills" and parts[3] == "SKILL.md": slug = parts[2] else: return None diff --git a/backend/package/yuxi/services/filesystem_service.py b/backend/package/yuxi/services/filesystem_service.py index aff59081..f98ef10a 100644 --- a/backend/package/yuxi/services/filesystem_service.py +++ b/backend/package/yuxi/services/filesystem_service.py @@ -4,15 +4,15 @@ import asyncio from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession -from yuxi.agents.context import BaseContext from yuxi.agents.backends import ( create_agent_composite_backend, resolve_sandbox_backend_async, ) +from yuxi.agents.context import BaseContext from yuxi.repositories.agent_config_repository import AgentConfigRepository from yuxi.repositories.conversation_repository import ConversationRepository -from yuxi.storage.postgres.models_business import User from yuxi.services.conversation_service import require_user_conversation +from yuxi.storage.postgres.models_business import User async def _resolve_filesystem_context( diff --git a/backend/package/yuxi/services/viewer_filesystem_service.py b/backend/package/yuxi/services/viewer_filesystem_service.py index 8b3465a8..3439df38 100644 --- a/backend/package/yuxi/services/viewer_filesystem_service.py +++ b/backend/package/yuxi/services/viewer_filesystem_service.py @@ -9,12 +9,11 @@ from urllib.parse import quote from fastapi import HTTPException from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession - from yuxi.agents.backends.sandbox import SKILLS_PATH, USER_DATA_PATH from yuxi.agents.backends.skills_backend import SelectedSkillsReadonlyBackend from yuxi.agents.middlewares.skills_middleware import normalize_selected_skills -from yuxi.storage.postgres.models_business import User from yuxi.services.filesystem_service import _resolve_filesystem_state +from yuxi.storage.postgres.models_business import User def _normalize_path(path: str | None) -> str: @@ -117,9 +116,7 @@ async def list_viewer_filesystem_tree( ) if normalized_path == "/": - entries = [ - {"path": f"{USER_DATA_PATH}/", "name": "user-data", "is_dir": True, "size": 0, "modified_at": ""} - ] + entries = [{"path": f"{USER_DATA_PATH}/", "name": "user-data", "is_dir": True, "size": 0, "modified_at": ""}] if selected_skills: entries.append({"path": f"{SKILLS_PATH}/", "name": "skills", "is_dir": True, "size": 0, "modified_at": ""}) return {"entries": entries} diff --git a/scripts/init.ps1 b/scripts/init.ps1 index a9060e2f..6e267f79 100644 --- a/scripts/init.ps1 +++ b/scripts/init.ps1 @@ -67,7 +67,7 @@ $images = @( "ghcr.io/astral-sh/uv:0.7.2", "nginx:alpine", "quay.io/coreos/etcd:v3.5.5", - "postgres:16" + "postgres:16", "redis:7-alpine" ) diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index 8ba4565d..a9a424d6 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -476,7 +476,9 @@ const isStreaming = computed(() => { }) const isProcessing = computed(() => isStreaming.value) const isSendButtonDisabled = computed(() => { - return sendCooldownActive.value || (((!userInput.value || !currentAgent.value) && !isProcessing.value)) + return ( + sendCooldownActive.value || ((!userInput.value || !currentAgent.value) && !isProcessing.value) + ) }) const startSendCooldown = () => { diff --git a/web/src/components/AgentConfigSidebar.vue b/web/src/components/AgentConfigSidebar.vue index 9868a0bb..89bc580f 100644 --- a/web/src/components/AgentConfigSidebar.vue +++ b/web/src/components/AgentConfigSidebar.vue @@ -58,11 +58,7 @@
{{
formatContent(currentFile.content)
}}
- {{ currentFile.content }}
+ {{
+ currentFile.content
+ }}
{{ JSON.stringify(currentFile, null, 2) }}
- 添加自定义的LLM供应商,支持OpenAI兼容的API格式。 -
+添加自定义的LLM供应商,支持OpenAI兼容的API格式。
请在 .env 文件中配置对应的 APIKEY,并重新启动服务
+ 请在 .env 文件中配置对应的 APIKEY,并重新启动服务
+