# 常见问题 装不上、报错看不懂、行为不符合预期时先查这里。 --- ## 安装与载荷 ### `node_modules/@dsh-ops/` 下没有 `bash-win32-x64` **这不是安装损坏。** Windows Bash 载荷是精确钉版的**可选依赖**(`optionalDependencies`):若你的 registry 未同步该平台包的对应版本,包管理器会**静默跳过**它——安装仍以退出码 0 结束,且不打印任何指向缺包的警告。 实测(2026-10-12):`registry.npmmirror.com` 上 `@dsh-ops/bash-win32-x64` 的 `dist-tags.latest = 0.0.0-stage`、`versions` 只有 `0.0.0-stage`;官方源 `registry.npmjs.org` 为 `0.2.1`。走镜像的 `npm view @dsh-ops/bash-win32-x64 version` 因此会打印误导性的旧版本号,不能拿来判断载荷是否可用。镜像补齐后本节自然过期,下面是自证与兜底的办法。 **首选兜底**:`provision-shells` 绕过 registry,直接取上游 GitHub Release 的钉版资产,校验 sha256 后解包,并写 `.provisioned.json` receipt。 ```console npx --yes dsh-ops@latest provision-shells --bash ``` 需要代理时(`HTTPS_PROXY` 会被显式交给 curl 的 `--proxy`,同时随环境继承): ```console :: cmd set HTTPS_PROXY=http://127.0.0.1: npx --yes dsh-ops@latest provision-shells --bash ``` ```console # PowerShell $env:HTTPS_PROXY = 'http://127.0.0.1:' npx --yes dsh-ops@latest provision-shells --bash ``` **核对**请跑 profile 自己那份副本:`ladder` 只报告**执行它的那份包**的随包梯级,`npx … ladder` 检查的是 npx 缓存副本,结论与你的 profile 无关。 ```console node "%USERPROFILE%\.dsh\profiles\\node_modules\dsh-ops\bin\dsh-ops.mjs" ladder ``` provisioned 副本在 `/dsh-ops/shells`(跨 profile 共享,provision 一次对同机所有 profile 生效),解析时优先于随包副本,`ladder` 会给出 `source: provisioned`。 **不要**用 `allowSystemShellFallback: true` 绕过:那是安全姿态降级(改用未固定摘要的系统 bash),且首次升级启动的配置迁移会把它改回 `false`。 ### 缺少随包 bash 载荷时 `ops_bash` 的报错 当随包 bash 载荷在 profile 的声明/lockfile 中存在、但实际 `node_modules` 已被宿主包管理器清理时,`ops_bash` 会返回可读的 `ENOENT` 诊断,而不是把裸的 `spawn` 异常抛给模型。此时应使用 profile 的 frozen install 或官方插件管理器恢复依赖;不会静默切换到未授权的系统 bash。 --- ## 命令执行 ### 整轮因 `MALFORMED_RESPONSE` 作废 长脚本、heredoc、多层引号与反斜杠会让模型在工具调用 JSON 里做多层转义。请先用宿主的文件工具把脚本写入文件,再传给 `script_path` 执行,不要整段塞进 `command`。详见 [使用指南](使用指南.md)。 ### Bash 后台执行需要宿主 jobs 服务 只有宿主 jobs 服务已挂载时才提供 `run_in_background`;它返回宿主 job ID,通过 `job_output` / `job_kill` 收集或停止。没有该服务时,移除后台参数并使用有界前台命令。默认超时 120 秒,上限 600 秒;有 jobs 时超时会交接同一个任务,没有时停止命令。 ### 参数被判为未知键 `ops_bash` 的 schema 不声明的键会在执行前被拒绝,错误信息会同时点出未知键与可接受的键。这是刻意的——不会静默忽略。 ### 受限模式下 `ops_bash` 无法运行自定义 bashPath 或 Git for Windows 现象(只读或工作区内修改会话):`EXECUTOR_UNAVAILABLE: ops_bash cannot run the configured bashPath … in restricted modes`(0.3.0 时报 `This MSYS version has no verified DSH IPC compatibility build. Rebuild the matching proxies`)。 **这是按设计的行为。** 在 DSH 的 Windows 受限令牌下,MSYS 无法创建自己的 signal pipe(`couldn't create signal pipe, Win32 error 5` / `0xC0000142`)。dsh-ops 通过针对某一个固定摘要 `msys-2.0.dll` 校验过的 IPC 兼容代理让 Bash 在受限模式下可用;其它任何 MSYS 版本——自带 Git for Windows、自定义 `bashPath`、`allowSystemShellFallback` 找到的系统 bash——都会被拒绝,而不是裸执行。重建代理不是终端用户的补救办法:`npm run build:bash-ipc` 只会重新固定随包载荷。 处理办法: - 从 `dsh-ops/shell` 行删除 `bashPath`(以及 `allowSystemShellFallback`),改用随包的固定摘要 bash;若该载荷缺失,运行 `npx --yes dsh-ops@latest provision-shells --bash`。 - 或者把会话切换到 `danger-full-access`,此时 `bashPath` 会直接运行。 - 用 profile 自己的副本检查:`node "\node_modules\dsh-ops\bin\dsh-ops.mjs" ladder --config <文件>`,报告中的 `restricted: yes/no` 表示受限模式能否运行所选 bash。 ### Bash 审批被拒绝或不可用 `ops_bash` 通过宿主审批申请更宽的 `sandbox_permissions`,必须为当前命令提供非空 `justification`。拒绝或缺少审批服务时不执行;不要换 shell 重试。审批无法修复不兼容的受限 Bash 运行时。 ### 文件工具收到空占位参数 严格的工具调用适配器会把 schema 里每个字段都填上,于是 `ops_inspect_local_file`、`ops_grep`、`ops_glob`、`ops_replace` 未使用的可选字段会收到 `""`、`null` 或 `[]` 占位值。插件会在原生 worker 运行前丢弃这些可选字段的占位值,不再触发 `path`/`encoding`/`view` 校验报错。必填字段、`replacement: ""`、`false` 和 `0` 仍原样转发,真正非法的值依旧会报错。 --- ## 权限与沙箱 ### 用过 OPS 文件工具后,宿主 `edit` 报「has not been read」或「changed since it was read」 此改动后已修复:`ops_inspect_local_file` 与 `ops_replace` 会像宿主 `read`/`edit` 一样登记到宿主的「先读后改」观测表,之后宿主 `edit` 可直接使用。旧版本(基于 FastCtx 的 0.2.x)中 OPS 的读取不计入观测,使用宿主 `edit` 前请先用宿主 `read` 读一次。(#17) ### 文件工具是否需要命令权限 不需要。固定文件操作走 DSH fs-sandbox 同类的可信操作权限检查,**不执行模型代码**。read-only 拒绝替换,workspace-write 允许工作区与 DSH 临时区域内替换,full-access 不额外限制写路径。 ### 凭据位置是读、写、删除全部被拒 **这是有意设计。** 文件工具不会触碰凭据位置(`~/.ssh`、`~/.aws`、`~/.config/gcloud`、`.netrc`、 `.npmrc`、`.pypirc`、`id_rsa`/`id_ed25519` 形私钥、`*credentials.{json,yaml,ini}`、`.env` 以及 DSH 的 凭据存储),统一返回 `CREDENTIAL_DENIED`:读被拒,写、`copy`/`move` 的目标、`replace` 目标、`remove` 同样被拒;`glob` 与 `grep` 也不会列出它们。`danger-full-access` 下 DSH 权限模式本来允许这些写操作, 所以正是这道围栏在阻止通过文件工具新建、覆盖或删除凭据文件。 配置键仍叫 `denyCredentialReads`(为兼容保留),但它的范围包括写。**实际后果**:名为 `.env` 的文件 **无法用 ops 工具创建**,请改用宿主 `write` 工具(宿主受 DSH 权限模式约束,不受这道围栏约束)。 某一配置行写 `denyCredentialReads: false` 只关闭该行的围栏;`DSH_OPS_DENY_READ` 只能增加位置, 不能减少。 ### 目录里出现 `.dsh-ops-update-*.lock` 文件 **这是持久的协作锁,不是垃圾文件。** 写者之间在目标旁边的一个隐藏 sidecar 上串行: `.dsh-ops-update-<文件名的 sha256>.lock`。它首次使用时创建、之后从不删除,因为原子重命名前后锁必须 保持同一身份;删掉它会让两个写者在同名锁上锁到不同对象。它既不代表操作成功,也不代表失败,里面 没有数据,`glob`、`grep` 和整目录 `replace` 都会跳过它。 自本版本起,在拿锁之前就被拒的请求(`expectedRevision` 过期、`EDIT_CONFLICT`、目标已存在、凭据路径) 不再产生它。拿锁之后才失败的请求——并发写者抢赢了、或发布阶段失败——仍可能留下一个;因 `maxReplacements` 被拒的 `replace` 可能每个扫描过的文件留一个(不只是匹配到的文件)。**不要手工删除这些文件**:另一个进程可能 正在等待它,删除会让后来的写者误以为只有自己。 ### 后台工具去哪了 `dsh-ops/background` 组件及其基于 FastCtx 的工具(`ops_run`、`ops_run_background`、`ops_job_output`、`ops_job_list`、`ops_job_kill`)已移除。仍写着 `dsh-ops/background` 的 profile 行会作为空操作加载,并记录 `the dsh-ops/background component (FastCtx background jobs) was removed in this version; it publishes no tools`;删除该行即可消除提示。长时间运行的进程可在宿主 jobs 可用时使用 `ops_bash` 的 `run_in_background`,再通过宿主 `job_output` 收集结果。 ### `DSH workspace preparation failed` 在工作区内修改会话中,第一次受限 `run_code` / `pwsh` / `bash` / `ops_bash` 调用前,dsh-ops 会给工作区根目录补一条仅作用于该目录的 `WRITE_OWNER` ACE(宿主沙箱需要),并先把原 DACL 备份到 `/dsh-ops/acl-backups/`。之后的调用走很快的 `ready` 路径。 这一步用 Windows PowerShell 5.1 运行包内自带的 `bin/prepare-workspace.ps1`,**以当前用户身份、在沙箱约束生效之前执行**;只在 Windows 的工作区内修改模式下运行,且只修改工作区根目录自身的 DACL。只读与 danger-full-access 会话会跳过它。 报错会写明原因: - `PowerShell execution policy blocked dsh-ops's own preparation script …`:dsh-ops 会传 `-ExecutionPolicy Bypass`(旧版本没有传,因此 Windows 客户端默认的 `Restricted` 会让所有 shell 工具失败,#66)。现在仍被拒绝,说明是组策略(MachinePolicy/UserPolicy)在强制执行策略,`Set-ExecutionPolicy -Scope CurrentUser` 无法覆盖。请运行 `powershell.exe -NoProfile -Command Get-ExecutionPolicy -List` 检查、联系管理员,或为该会话使用 danger-full-access。 - `the workspace root … does not meet the sandbox prerequisite …`:问题出在文件夹本身——不属于当前用户、路径经过 junction 或符号链接,或 `WRITE_OWNER` 被显式拒绝或无法授予。请修正该文件夹的所有者或权限,或打开你自己拥有的工作区。这不是 DSH 的授权拒绝。 - 根目录 DACL 通过它自己的句柄写入,不触发 Windows 的继承遍历,耗时不再随文件数增长(实测 5 万文件 18.7 s → 4.3 s;10 个文件约 3.9 s,主要是 PowerShell 启动)。旧版本会遍历整棵目录树,大工作区触发 10 s 限制且冒号后为空。(#43) - `the preparation executor timed out after 120000 ms …`:触发了 120 s 兜底超时。此时 ACL 状态未知,重试前请把根目录 DACL 与 `acl-backups` 中最新的收据对比。`the preparation executor could not start …` 表示 `powershell.exe` 本身无法启动。 - `exited with code N …: <文本>`:其它失败,附脚本自己的输出。 ### 宿主 shell 被拒绝 `shellPolicy: deny-host-shell` 会拒绝 `deniedHostTools` 列表中的宿主 shell(默认 `[pwsh, bash, pwsh_persistent]`),该策略与 `allowSystemShellFallback` 独立。这也会禁用第三层 pwsh,谨慎开启。 --- ## 安装位置与 profile ### `tui` profile 是什么 `tui` 映射到 **dsh-TUI 产品的 `dsh-tui` profile**,不是旧的 `tui` 目录。 ### 桌面端为什么必须用它自带的 CLI 普通 DSH CLI 不能管理保留的 `desktop` profile;不要把它与桌面自带入口混淆。桌面端默认探测 `%LOCALAPPDATA%\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd`,装在别处时用 `--dsh-cli` 显式指定。 ### 卸载后 `~/.fastctx/` 还在 它是已移除的后台组件留下的状态,默认不删;需要时显式加 `--purge-fastctx`。 ### 旧版 provision 的文件没被清掉 旧版显式 provision 的 `/dsh-ops/` 文件需单独清理:`npx --yes dsh-ops@latest uninstall --yes`。 --- ## 进程 ### 残留的 `runtime-host` 进程是不是泄漏 不是。它是 FastCtx 的可复用共享进程,由带后台组件的早期版本启动;本版本不会启动它。无客户端且空闲约十分钟后自行退出。不要按进程名批量杀它。新版不自动清理旧版本已留下的进程。 ## macOS arm64 ### 没有自带的 bash / PowerShell 载荷 macOS 没有 `@dsh-ops/bash-darwin-arm64` 或 `@dsh-ops/pwsh-darwin-arm64`,也没有可移植的官方 macOS bash。在 `dsh-ops/shell` 行用 `bashPath` 指定要使用的 bash(例如 `/opt/homebrew/bin/bash`)。PowerShell 7 可以 provision,但宿主在非 Windows 上禁用了 `pwsh-sandbox` 与 `tool-pwsh` 两行,所以 macOS 上不会出现 pwsh 工具。 ### 文件工具拒绝 `/tmp` 下的路径 macOS 上 `/tmp` 是指向 `/private/tmp` 的软链,而原生 file worker 拒绝穿越软链,因此这类路径会返回 `POLICY_DENIED: Links, reparse points and special objects are not traversed`。改用规范路径(`/private/tmp/...`)。这是设计上的 no-follow 行为,不是缺陷。 ### 换了包之后文件工具不见了 宿主只在启动时 import 一次插件模块,所以改 profile 补丁可以重挂/卸载组件,但**换不掉已加载的代码**。换包之后要重启应用;只改配置不需要重启。 --- ## 相关文档 - [使用指南](使用指南.md) —— 完整安装与命令行接口 - [配置参考](配置参考.md) —— 配置项与归属组件 - [组件参考](组件参考.md) —— 工具与权限