From 42bf89c0c116ead227281dabbd3905f352c85246 Mon Sep 17 00:00:00 2001 From: ymq Date: Mon, 17 Aug 2026 15:15:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20workspace=20fallback=20=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=88=B0=20WORKSPACE=5FBASE(/d/pipeline/workspaces)?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E9=80=9A=E7=94=A8=E5=8A=A9=E6=89=8B?= =?UTF-8?q?(=E6=97=A0=E9=A1=B9=E7=9B=AE)=E4=BB=8D=E7=94=A8=E6=97=A7=20/tmp?= =?UTF-8?q?/pipeline=5Fws=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_service/agent_loop.py | 10 ++++++---- pipeline_service/agent_loop_v2.py | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index 50ba5a3..8ef1082 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -19,6 +19,8 @@ import logging logger = logging.getLogger("pipeline.agent_loop") +from .workspace import WORKSPACE_BASE + ROLE_ALIASES = { 'developer': 'agent.develop', 'dev': 'agent.develop', 'development': 'agent.develop', 'coding': 'agent.develop', 'requirement': 'agent.requirement', 'requirements': 'agent.requirement', 'requirement_analysis': 'agent.requirement', @@ -156,14 +158,14 @@ def _get_db(): def _resolve_workspace(workspace_dir): if not workspace_dir: - workspace_dir = os.path.expanduser('~/pipeline_ws/default') + workspace_dir = os.path.join(WORKSPACE_BASE, 'default') try: parent = os.path.dirname(workspace_dir) if parent and not os.access(parent, os.W_OK): proj_name = os.path.basename(workspace_dir) - workspace_dir = os.path.expanduser(f'~/pipeline_ws/{proj_name}') + workspace_dir = os.path.join(WORKSPACE_BASE, proj_name) except Exception: - workspace_dir = os.path.expanduser(f'~/pipeline_ws/{os.path.basename(workspace_dir) or "default"}') + workspace_dir = os.path.join(WORKSPACE_BASE, os.path.basename(workspace_dir) or "default") os.makedirs(workspace_dir, exist_ok=True) return workspace_dir @@ -219,7 +221,7 @@ async def _is_safe_workdir_async(workdir): async def _run_shell(command, workdir, timeout=120): """安全执行 shell 命令。返回 {"rc": int, "stdout": str, "stderr": str}""" - cwd = os.path.abspath(workdir) if workdir else os.path.expanduser('~/pipeline_ws') + cwd = os.path.abspath(workdir) if workdir else WORKSPACE_BASE if not await _is_safe_workdir_async(cwd): return {"rc": -1, "stdout": "", "stderr": f"安全限制:目录 {cwd} 不在允许范围"} if not os.path.isdir(cwd): diff --git a/pipeline_service/agent_loop_v2.py b/pipeline_service/agent_loop_v2.py index e0905f0..76405a8 100644 --- a/pipeline_service/agent_loop_v2.py +++ b/pipeline_service/agent_loop_v2.py @@ -26,6 +26,8 @@ from typing import AsyncGenerator, Dict, List, Optional logger = logging.getLogger("pipeline.agent_executor") +from .workspace import WORKSPACE_BASE + # ── 默认工具定义(在 pipeline-core 未加载时使用)── @@ -67,7 +69,7 @@ class AgentExecutor: self.org_id = "" # loaded from project context self.pipeline_id = "" # loaded from project context(产线能力包 key) self.role = role # 产线内角色(技能/工具/prompt 按角色加载) - self.workspace_dir = workspace_dir or "/tmp/pipeline_ws" + self.workspace_dir = workspace_dir or WORKSPACE_BASE self.model_name = model_name or config.model_name # 运行状态 @@ -800,7 +802,7 @@ class AgentExecutor: org_id = getattr(_u[0], "orgid", "0") or "0" # 项目专属工作空间目录(workspace_base 从 appbase params 表读,可动态配置) - # 不设置 workspace_dir 会导致 _resolve_workspace 回退到 ~/pipeline_ws/default, + # 不设置 workspace_dir 会导致 _resolve_workspace 回退到 WORKSPACE_BASE/default, # 所有项目共用同一目录,设计文档/代码互相覆盖。 from .workspace import get_workspace_base workspace_base = await get_workspace_base(sor) @@ -837,7 +839,7 @@ class AgentExecutor: def _resolve_ws_path(self, path: str) -> str: """解析相对路径为工作空间内绝对路径(越界返回 '')。""" import os - ws = self.workspace_dir or "/tmp/pipeline_ws" + ws = self.workspace_dir or WORKSPACE_BASE full = os.path.abspath(os.path.join(ws, path or ".")) # 限制在 workspace 内 if full != ws and not full.startswith(ws.rstrip("/") + "/"):