GitHub Issue #976 · 标签:路径映射
分析方法:人工排查 + Codex 交叉验证,两者结论一致。结论给出根因、扩散隐患点、可减免的 if/else 与确定性修复方案。
SessionManager.sandbox_workspace_for_session() 的返回值依赖进程内、不落库、注册时机不确定的内存字典 self._user_home_paths(manager.py:72)。同一个持久会话在「未注册 / 注册 local fallback / 注册 Blade OS home」三种状态间切换,于是对同一会话给出不同目录,读写路径天然会漂。
sandbox_workspace_for_session() 本应是纯确定性函数(同样的 session metadata 永远返回同一目录),现在却成了依赖可变全局状态的函数。这是问题的本质。
create_session 只试 _resolve_user_home_host_path(),Blade OS 失败就不注册 → 初始化文件写进 fallback 目录(_engine_session_create.py:95-99)。ensure_session_user_home(),若此刻 Blade OS 可解析就注册真实 user_home(sessions_helpers.py:303)。_create_sandbox_provider() 解析 Blade OS 失败时会注册 local_user_home()(_engine_runtime.py:136-140)——同进程内把 local fallback 钉住;但后端重启后 dict 清空,文件 API 又可能重新解析到 Blade OS home,目录再次漂移。
| 位置 | 隐患 |
|---|---|
execution/session_runtime.py:95 | runtime 按 session_id 缓存,root 固定在创建那一刻。之后 dict 变了,文件 API 读新目录、已起容器仍写旧目录。 |
sessions_helpers.py:331-334 | /root fallback 用 sandbox/.root;但 sandbox provider 把 local_user_home 挂到容器 /root。"文件 API 先访问" vs "容器先启动" 得到两个不同 /root。 |
services/app_publish.py:438 | 直接调 workspace,无 ensure。重启后容易发布空目录/旧 fallback 目录。 |
routes/software_factory.py:409/462/496/660/841 | 多处直接读写 workspace,无 ensure,时机不一致。 |
routes/factory_v2.py:40 | 自己实现第三套 _resolve_user_home():Blade OS 失败 fallback 到 local,但不注册回 SessionManager。注释写着"和 _engine_runtime.py 一样"——典型复制粘贴。 |
routes/prod_agents.py:504/540 | 仍写 user_workspace() 而非 sandbox workspace,未来持久化会和容器可见 workspace 分叉。 |
_session_file_helpers.py:112 | 用 sandbox.parent.name 反推 workspace_root。持久会话 parent 是「智能助手工作空间」而非 session_id,路径拼错。 |
sandbox/docker_container_create.py:109 | 持久容器存在第三种 /root 存储(named volume fallback)。产品目标是"用户文件可见",静默落到不可见 named volume 是错误兜底。 |
最该删sandbox_workspace_for_session() 的"registered vs local fallback"动态分支(manager.py:131-141)。两个内层分支只差 user_home 来源,函数却因此变成非确定性。正确做法:让"有效 user_home"在建会话时确定一次并持久化,之后只读结果。分支消失,确定性恢复。
合并四处 resolver 合并成一条路径。 _resolve_user_home_host_path()、ensure_session_user_home()、factory_v2._resolve_user_home()、_create_sandbox_provider() 各有"只查 Blade OS / 查不到 local fallback / 查到才注册 / 不注册"差异,是重复且矛盾的 4 套语义。
收敛register_user_home() 不该是任意时刻可改路径的公共 cache。收敛成内部 ensure_effective_user_home(session),只初始化一次,已有路径不允许悄悄切换。
降级报错多余 fallback 直接报错。Blade OS 已配置(BLADE_OS_BASE_URL 非空)但解析失败 → 直接报错,不静默落 local;只有明确本地开发无 Blade OS 时才用 local_user_home()。少一层 fallback 就少一条漂移路径。
workspace/{session_id}/workspace,/root → sandbox/.rooteffective_user_home/智能助手工作空间/{session_id},/root → 同一个 effective_user_homeeffective_user_home 一旦为某 session/user 确定,不因后续注册时机变化而改变分两步落地
sandbox_workspace_for_session() 始终返回同一目录。这比"注册后路径正确"更能覆盖 #976。