from __future__ import annotations import json import threading from pathlib import Path from typing import Dict, List from config import HOST_SANDBOX_MACOS_WRITABLE_PATHS, deploy_config_path _LOCK = threading.Lock() # 部署级配置(机器特定可读写路径,会被运行时写回)→ ~/.agents//config _POLICY_PATH = Path(deploy_config_path("host_sandbox_policy.json")) def _ensure_file() -> None: if _POLICY_PATH.exists(): return _POLICY_PATH.parent.mkdir(parents=True, exist_ok=True) _POLICY_PATH.write_text( json.dumps({"macos_writable_paths": [], "macos_readable_extra_paths": []}, ensure_ascii=False, indent=2), encoding="utf-8", ) def load_policy() -> Dict: with _LOCK: _ensure_file() try: data = json.loads(_POLICY_PATH.read_text(encoding="utf-8")) except Exception: data = {"macos_writable_paths": [], "macos_readable_extra_paths": []} if not isinstance(data, dict): data = {"macos_writable_paths": [], "macos_readable_extra_paths": []} writable_items = data.get("macos_writable_paths") if not isinstance(writable_items, list): writable_items = [] readable_items = data.get("macos_readable_extra_paths") if not isinstance(readable_items, list): readable_items = [] data["macos_writable_paths"] = [str(x).strip() for x in writable_items if str(x).strip()] data["macos_readable_extra_paths"] = [str(x).strip() for x in readable_items if str(x).strip()] return data def save_policy(policy: Dict) -> Dict: payload = dict(policy or {}) writable_items = payload.get("macos_writable_paths") if not isinstance(writable_items, list): writable_items = [] readable_items = payload.get("macos_readable_extra_paths") if not isinstance(readable_items, list): readable_items = [] payload["macos_writable_paths"] = [str(x).strip() for x in writable_items if str(x).strip()] payload["macos_readable_extra_paths"] = [str(x).strip() for x in readable_items if str(x).strip()] with _LOCK: _ensure_file() _POLICY_PATH.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") return payload def get_macos_writable_paths() -> List[str]: file_items = load_policy().get("macos_writable_paths", []) merged: List[str] = [] for raw in list(HOST_SANDBOX_MACOS_WRITABLE_PATHS or []) + list(file_items or []): val = str(raw).strip() if val and val not in merged: merged.append(val) return merged def get_macos_readable_paths() -> List[str]: data = load_policy() readable_extra = data.get("macos_readable_extra_paths", []) merged: List[str] = [] for raw in list(get_macos_writable_paths()) + list(readable_extra or []): val = str(raw).strip() if val and val not in merged: merged.append(val) return merged