diff --git a/core/main_terminal.py b/core/main_terminal.py index e08bc4cb..a81a951a 100644 --- a/core/main_terminal.py +++ b/core/main_terminal.py @@ -259,6 +259,8 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi self.terminal_manager.set_host_execution_mode(mode) if getattr(self, "sub_agent_manager", None): self.sub_agent_manager.set_host_execution_mode(mode) + if getattr(self, "file_manager", None): + self.file_manager.set_host_execution_mode(mode) def _init_host_network_permission(self): default_permission = str(HOST_SANDBOX_NETWORK_PERMISSION or "restricted").strip().lower() diff --git a/modules/file_manager/base.py b/modules/file_manager/base.py index 85ad3484..9d20015a 100644 --- a/modules/file_manager/base.py +++ b/modules/file_manager/base.py @@ -54,8 +54,15 @@ class FileManagerBase: self.container_session: Optional["ContainerHandle"] = None self._container_proxy: Optional[ContainerFileProxy] = None self._data_dir: Optional[str] = data_dir + # 宿主机执行环境(sandbox / direct),由主终端同步; + # direct 时与 run_command 对齐:不走路径授权检查(不套沙箱语义)。 + self.host_execution_mode: str = "sandbox" self.set_container_session(container_session) + def set_host_execution_mode(self, mode: str) -> None: + normalized = str(mode or "").strip().lower() + self.host_execution_mode = "direct" if normalized == "direct" else "sandbox" + def _load_personalization_config(self) -> Optional[Dict]: """加载个性化配置""" if not self._data_dir: diff --git a/modules/file_manager/path_mixin.py b/modules/file_manager/path_mixin.py index b45341f2..a40d3d5b 100644 --- a/modules/file_manager/path_mixin.py +++ b/modules/file_manager/path_mixin.py @@ -175,6 +175,11 @@ class PathMixin: def _ensure_host_access(self, full_path: Path, access: str) -> Tuple[bool, str]: if not self._is_host_mode(): return True, "" + # 执行环境为 direct(完全访问权限)时,run_command 不套沙箱、可读写任意路径; + # read_file/write_file/edit_file 为进程内文件操作,本就不走 OS 沙箱,此处与 + # run_command 语义对齐,直接放行。sandbox 模式下保持授权范围检查不变。 + if getattr(self, "host_execution_mode", "sandbox") == "direct": + return True, "" check_target = full_path if access == "write" and not full_path.exists(): check_target = full_path.parent.resolve()