Windows 下选择工作区因后台启动与目录权限受阻 #256
Replies: 1 comment
|
这份报告里三个阻塞实际上是互相独立的三件事,各自的判据不同,分开说。 一、原生选择器为什么「不可见」——这是判据不足,不是对话框坏了自动后端是一个纯函数 + 启动期一次性采样,四条提前返回,全部输入有五个:
源码 你的情形命中第三行: 这一点包文档已经把它列为已知限制( 所以你第 3 步做的 profile patch( 二、应用内浏览器读不到主目录——EPERM 来自外部的文件系统沙箱两点先确认:
而那个 你能用的恢复入口已经存在:路径编辑按钮在「首屏 home listing 失败、 当前版本的可用绕过:别在受限上下文里起服务。在普通 PowerShell 里、从仓库根目录起,一次设好 Set-Location 'D:\deepseek-harness-master'
$env:DSH_HOME = 'D:\deepseek-harness-master\.dsh-runtime'
pnpm dsh web( 三、端口被占用——报错里没有 PID,但有现成命令
换端口现在有 flag 了: pnpm dsh web --port 8080 # 换端口(全局安装的 dsh 则用 dsh web --port 8080)
pnpm dsh web --port 0 # 让 OS 分配一个空闲端口
pnpm dsh web --help # 看这个 app 自己的 flag 列表( 关于「原生选择器」这一条官方可以怎么改按性价比,我会把这两条排在最前:
如果这条解释解决了你的问题,可以把它标为 answer,方便后面从类似 IDE/桌面环境后台启动 dsh 的人找到。 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
在 Windows 上从 Codex 桌面环境启动
dsh web后,“选择工作区”流程先后遇到原生目录选择器不可见、应用内目录浏览器无法读取用户主目录,以及重启时端口被旧实例占用的问题。最终在普通 PowerShell 中启动服务后恢复。希望项目改进自动后端选择、失败后的恢复入口和 Windows 启动诊断。环境、复现、源码核对与建议
环境
D:\deepseek-harness-master(示例路径)@deepseek-ai/dsh-root 0.1.0-rc.5^22.19.0 || >=24.0.0v24.19.011.19.0;仓库package.json声明pnpm@11.7.0http://127.0.0.1:3080用户影响
用户看到“选择工作区目录”弹窗,但目录区域为空,底部显示:
此时“新建文件夹”和“打开”按钮不可用。标题栏右侧虽然有铅笔图标,可以在首次主目录加载失败时输入绝对路径,但界面没有文字说明这是恢复入口,容易被理解为整个弹窗无法交互。
本次流程因此无法通过常规的逐级浏览完成工作区选择。目标目录本身
D:\deepseek-harness-master可用,问题发生在目录选择器首先尝试读取C:\Users\<用户名>时。发布时请使用脱敏后的占位符,不要公开真实 Windows 用户名。完整复现与排障时间线
1. 构建和 Web 页面本身正常
依赖安装和构建成功:
Web UI 可以从
http://127.0.0.1:3080打开,页面返回 HTTP 200。工作区D:\deepseek-harness-master后来也能注册并创建空白会话,因此问题不在静态页面构建或工作区数据格式。2. 默认自动后端选择了原生 Windows 目录选择器
Web bundle 默认组合
@deepseek-ai/dsh-host-directory-picker-auto。当前实现只要同时满足以下条件,就会在 Windows 上选择native:127.0.0.1;SSH_CONNECTION或SSH_TTY;process.platform === 'win32'。对应源码:
packages/bundle/web-app/cordis.patch.ymlpackages/host/directory-picker-auto/src/resolve.ts这次 Web 服务由 Codex 桌面环境以隐藏后台进程方式启动。点击“选择工作区”后,浏览器需要等待宿主 Windows 原生对话框,但用户无法在当前交互界面中看到或操作该对话框。
这里可以确认的是:自动选择逻辑在该启动上下文中选中了
native,而用户没有可操作的选择器。仅凭这次现象不能断言 Windows COMIFileOpenDialog实现本身失败;更可能的问题是启动侧的win32 + loopback + 非 SSH信号不足以证明操作者能看到并控制宿主桌面。directory-picker-auto的 README 也已将“启动侧信号无法证明操作者位置”列为已知限制。3. 强制切换到应用内 browse 后端
为使目录选择发生在网页内,profile patch 改为禁用自动选择器,并同时组合 browse 的 Host 与 Client 两侧:
配置文件位于:
切换后应用内弹窗可以正常打开,但首次目录列表请求立即失败。
4. browse 后端固定从宿主账户主目录开始
packages/host/directory-picker-browse/src/index.ts的list(path?)在没有传入路径时执行:在本机,
os.homedir()为C:\Users\<用户名>。服务继承了 Codex 文件系统沙箱权限,不能枚举该目录,因此opendir返回EPERM。使用最小 Node.js 命令可以复现同一错误:browse 后端当前
Config只有maxEntries,没有defaultPath、initialPath或browseRoot。因此部署方无法仅通过插件配置把首次列表改为已授权的目录,例如D:\deepseek-harness-master。5. 错误传到 UI,但恢复入口不明显
Host 将此失败映射为
directory-unreadable;Client runtime 使用DirectoryBrowseError保留 Host 的消息;DirectoryBrowser的failureText()再把消息原样显示在弹窗中。相关源码:packages/host/directory-picker-browse/src/index.tspackages/host/apiproxy/src/api/host.tspackages/client/runtime/src/client/workspaces/service.tspackages/client/ui-directory-picker-browse/src/client/DirectoryBrowser.tsx客户端其实实现了一个重要的恢复路径:即使首次 home listing 失败、
parent === null,右上角的路径编辑按钮仍保持可用;点击铅笔后可以输入完整绝对路径并按 Enter。源码注释也明确称它是“failed home listing”的 remaining way forward。但是截图中的弹窗只有一个铅笔图标,没有“输入路径”文字、错误恢复按钮或针对
EPERM的说明。用户首先看到的是空白目录区、红色底层错误和两个禁用按钮,因此很难发现必须点击铅笔继续。6. 改为普通 PowerShell 启动时,
pnpm不在 PATH为避免服务继承 Codex 沙箱权限,尝试在普通 PowerShell 中启动:
普通 PowerShell 报错:
Codex 使用的 pnpm 位于其私有运行时目录,没有加入普通 PowerShell 的
PATH。本机最终使用:该
pnpm.cmd会使用同一 Codex runtime 中的 Node.js,因此不依赖普通 PowerShell 的 pnpm 命令解析。项目开发文档已说明需要启用 Corepack,并建议
pnpm --version无法解析时运行corepack enable。不过对于从 Codex 桌面环境切换到普通 Windows 终端这一实际恢复场景,用户仍需要明确知道:Codex 内可用的pnpm不一定存在于系统PATH。7. 第一次用绝对 pnpm 路径启动时工作目录错误
在新 PowerShell 窗口中直接运行绝对 pnpm 路径时,当前目录仍是
C:\Users\<用户名>,因此 pnpm 报错:切换到仓库根目录并在同一个 PowerShell 会话中设置
DSH_HOME后解决:8. 旧的受限实例仍占用 3080
从普通 PowerShell 启动的新实例随后两次失败:
连续
netstat -ano -p tcp采样确认旧实例 PID36516一直监听127.0.0.1:3080,且存在多个已建立连接。停止确切的旧进程树:输出确认终止了 PID
36516及其子进程 PID38632。当前
EADDRINUSE错误包含地址和端口,但没有显示占用 PID、没有提示已有dsh web实例,也没有给出选择其他端口或停止旧实例的下一步操作。对于不熟悉端口诊断的用户,这会形成第二个启动阻塞。9. 最终恢复与验证
在普通 PowerShell 的仓库根目录中,使用同一个
.dsh-runtime重新启动:成功输出:
验证结果:
46668GET http://127.0.0.1:3080:HTTP 200text/html; charset=utf-8.dsh-runtime配置、工作区和会话数据保留D:\deepseek-harness-master可继续使用这说明主要故障来自服务启动上下文继承的文件权限,而不是目标工作区不可用或 Web 页面构建失败。
根因与相关问题的划分
已验证的直接原因
os.homedir()开始。C:\Users\<用户名>执行opendir返回EPERM。36516持续占用127.0.0.1:3080,导致普通 PowerShell 中的新实例报EADDRINUSE。有源码支持的产品可用性问题
directory-picker-auto在 Windows 上把win32 + loopback + 非 SSH直接视为原生选择器可供当前操作者使用,无法识别隐藏后台进程或受限桌面启动上下文。EADDRINUSE诊断没有提供占用进程或明确恢复动作。不应过度归因的部分
EPERM本身符合宿主进程的文件系统权限,不建议通过放宽产品文件系统策略来修复。IFileOpenDialog的 COM 实现出错;已证明的是自动选择出的原生交互在当前启动方式下不可供用户操作。期望行为
至少满足以下一种恢复方式:
native/browse。directory-unreadable时,弹窗明确显示“输入绝对路径”操作,并把焦点或按钮引导到路径编辑器。defaultPath;如果增加browseRoot,应明确它只是 UX 范围还是安全限制。建议改进
A. 提升自动后端选择的可控性
--directory-picker=native|browse|auto,或在公开 profile 配置文档中给出一段官方覆盖示例。directory-picker-auto判断。directory picker: browse (forced by profile),便于直接诊断。B. 改善 browse 首屏失败后的恢复体验
directory-unreadable时显示本地化说明,例如“无法读取默认主目录。请输入一个可访问的绝对路径,或在宿主终端重新启动服务”。EPERM详情供展开查看或复制,不要丢失诊断证据。BrowseDirectoryPicker.Config增加defaultPath。该字段应在插件加载或第一次可解析时验证为完全限定路径,并明确读取失败行为。C. 改善 Windows 启动文档
DSH_HOME需要在启动命令所在的同一个 PowerShell 会话设置。pnpm不可用时给出 Corepack 检查步骤:corepack enable、pnpm --version。D. 改善端口占用诊断
dsh web的 PID,避免给出宽泛的 Node 进程清理命令。建议验收条件
opendir返回EPERM,应用内弹窗仍提供清晰、可键盘操作的绝对路径恢复流程。directory-unreadable的 UI 同时包含面向用户的恢复动作和可复制的底层错误详情。3080已被旧实例占用时,启动错误能引导用户识别旧实例或使用其他端口。可提供的附件
EPERM截图EADDRINUSE堆栈netstat连续采样结果This attachment is redacted for public sharing.
Environment
Command:
Result:
The directory picker uses os.homedir() when no path is supplied, so the first
browse request targets the same home directory.
Command was first run from C:\Users<username>:
Result:
Recovery:
Result while the restricted old service was still running:
Read-only netstat sampling identified the listener:
The old process tree was stopped only after confirming that it was the old
dsh web instance:
The service was then started from a normal Windows PowerShell session, from
the repository root, with the existing DSH_HOME:
Output:
Validation:
The existing .dsh-runtime configuration, workspace registration, and session
data remained available after the restart.
Source references
All reactions