Cherry Studio 中 DeepSeek Harness 无头运行指南:dsh 有界仓库任务委托与安全实践
【免费下载链接】cherry-studio🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio
本文对应仓库技能文档 SKILL.md,讲解 Cherry Studio 的 Code Mate 在把仓库级分析与实现任务委托给 DeepSeek Harness(dsh)时,应如何以无头(headless)模式安全、有界地执行。读完本文,你将掌握 dsh 无头任务的完整运行流程、退出码与输出语义、认证与权限的边界处理,以及如何结合仓库内服务层实现理解其底层机制。
一、技能定位:Code Mate 中的 DeepSeek Harness 委托
在 Cherry Studio 仓库中,resources/code-cli-skills/目录下按code-mate-<工具名>/SKILL.md的组织方式存放着一组“Code Mate 技能”文档,code-mate-deepseek-harness/SKILL.md 是其中之一,负责约束智能体在用户要求“把分析或实现委托给 DeepSeek Harness”时如何行事。
该文档的 frontmatter 给出了技能的触发语义:
name: code-mate-deepseek-harness description: Runs DeepSeek Harness headlessly for bounded repository tasks. Use when the user asks to delegate analysis or implementation to DeepSeek Harness.关键词有两个:headlessly(无头)与bounded repository tasks(有界的仓库任务)。也就是说,这份技能约束的不是 Cherry Studio 的图形界面操作,而是智能体侧应当执行的命令行动作与边界纪律;它与仓库内src/main/services/deepSeekHarness/的受管运行实现相互呼应(后者负责安装、配置下发与进程生命周期管理),两者共同构成 DeepSeek Harness 在 Cherry Studio 中的完整接入。
二、无头运行三步流程(Run)
SKILL.md 把一次合法的 dsh 委托运行收敛为严格的三步:
1. 定位工作目录并设置有限超时
Set the Bash working directory to the exact project the user named and set a finite timeout, normally 10 minutes.
- 必须把 Bash 工作目录切换到用户明确指定的那个项目,而不是当前任意目录——这是“有界(bounded)”的第一层含义;
- 必须设置有限的超时时间,默认按 10 分钟计。无头任务不应无限挂起,超时机制是防止 dsh 进程失控的前提。
2. 检查可用性
Check availability with
command -v dsh. If it is missing, stop and ask the user to install DeepSeek Harness in Code Mate.
command -v dsh- 若命令找不到,立即停止,转而请用户在 Code Mate 中安装 DeepSeek Harness,而不是尝试自行下载、猜测路径或绕过检查继续执行。
- 这一检查也与仓库中的二进制管理逻辑对应:
DeepSeekHarnessService通过BinaryManager.getToolSnapshots(['dsh'])查询 dsh 二进制的可用性(DeepSeekHarnessService.ts),source为'none'时即视为未安装,启动会直接报错“DeepSeek Harness is not installed”。
3. 执行单个无头任务
Run one headless task:
dsh --profile headless "<prompt>"执行时须遵守以下输出与退出约定:
| 约定 | 含义 |
|---|---|
| Prompt 作为一个整体 | 必须以一个被引号包裹的参数传入,避免被 shell 拆分 |
| stdout 语义 | 把stdout 当作最终文本,不要按 JSON 解析 |
| 退出码 0 | 任务成功完成 |
| 退出码 1 | 任务失败或未完成 |
| 交互限制 | 绝不启动交互式 UI,绝不触发登录流程 |
也就是说,无头模式是纯一次性调用:一次 prompt、一个最终文本结果、一个明确的成败判定,全程无人值守、无交互界面。
三、认证与权限边界(Authentication And Permissions)
1. 配置缺失时:停止并提示用户
If DSH reports a missing provider, model, or API configuration, stop and ask the user to configure DeepSeek Harness in Code Mate.
当 dsh 报告缺少 provider、模型或 API 配置时,技能要求智能体停止并引导用户在 Code Mate 中完成配置。注意这里的职责边界:配置由用户在应用内完成,智能体只负责消费。
2. 凭据红线:绝不接触密钥
Never request, read, print, or copy credentials.
这条“红线”在仓库实现中得到了系统性贯彻:
- 环境变量注入而非文本传递:受管启动时,配置以环境变量形式注入子进程(如
DSH_HOME、DSH_PERMISSION_MODE),见 DeepSeekHarnessService.ts; - 受管凭据被清理:子进程环境中所有匹配
CHERRY_STUDIO_CODEMATE_<12位十六进制>_API_KEY/CHERRY_STUDIO_CODEMATE_GATEWAY_API_KEY的变量会在启动前被删除(DeepSeekHarnessService.ts),避免旧的受管密钥泄露进新进程; - 错误信息脱敏:诊断输出经过
redactLiteral与redactSecretText双重脱敏,且截断到 2KB(DIAGNOSTIC_LIMIT)以内(DeepSeekHarnessService.ts); - 凭据文件最小权限:
.credentials.yaml以0o600权限写入(config.ts),仅当前用户可读写。
3. 写权限与持久会话:只读优先
Headless DSH can write to the workspace and creates a persistent session. For read-only work, explicitly tell it not to modify files and inspect the repository diff afterward. Allow modifications only when the user explicitly requested workspace changes, and restrict the working directory to the intended project.
三点纪律需要同时执行:
- 默认假设可写:无头 dsh 具备写工作区的能力,并且会创建持久会话(后续可复用上下文),因此不能默认它“只读”;
- 只读任务显式声明:当任务是只读性质(如诊断、分析)时,必须在 prompt 中明确告知 dsh 不要修改文件,并在运行结束后检查仓库 diff,确认没有意外改动;
- 修改需用户授权:仅当用户明确要求改动工作区时才允许写操作,且工作目录必须限制在用户指定的目标项目内。
这与仓库中受管运行的权限模式设计一脉相承。受管模式下,dsh 子进程会通过DSH_PERMISSION_MODE环境变量接收权限模式,取值包括default、acceptEdits、plan、bypassPermissions(见 protocol.ts)。其中plan 模式是纯只读的:决策管线在 plan 模式下只放行planSafeTools中的工具与工作区内的读操作,其余一律拒绝(policy.ts);而acceptEdits模式下,编辑类工具只有在目标路径位于allowedRoots(工作区与代理数据目录)内时才会自动放行。
路径判定还做了防绕过处理:isToolPathInsideAllowedRoots会先对目标做realpath规范化再与根目录比较,符号链接无法把外部路径伪装成工作区内路径;任何解析歧义(非字符串路径、file://链接、解析失败)都按“外部”处理,从而强制走人工确认(policy.ts)。
4. 全局安装防护:防止跨会话污染
虽然 SKILL.md 未逐条列举,但受管运行时对命令执行还有一道硬性防护:dsh 子进程内的bash/pwsh工具在执行前会经过全局安装检测,npm/pnpm/yarn/bun -g、yarn global add、uv tool install、pipx install、pip --user/--system、uv pip install --system、直接修改 mise 状态、cargo/go/gem install、brew/apt/dnf/yum install、dotnet tool install --global等会写入全局/共享位置的命令都会被拦截,理由是“避免跨 agent 会话的依赖污染”(policy.ts)。该防护在所有权限模式下生效(包括bypassPermissions),且作为硬守卫排在普通策略之前。在无头场景下委托仓库任务时,理解这道防线有助于解释“为什么某些安装命令会被拒绝”。
四、实战示例:只读诊断一个测试失败
SKILL.md 给出的示例完整描述了“只读委托”的闭环:
Example: ask DSH to diagnose a test failure without editing, run it in the repository, confirm exit zero and a clean diff, then summarize its final text.
按该示例展开为可操作的检查清单:
- 切换目录:
cd到用户指定的仓库目录; - 设置超时:如 10 分钟;
- 检查可用性:
command -v dsh,缺失则停止并请用户在 Code Mate 中安装; - 构造只读 prompt:在提示词中明确“请诊断测试失败原因,不要修改任何文件”;
- 执行:
dsh --profile headless "诊断……不要修改文件"; - 校验退出码:
echo $?必须为 0; - 校验无副作用:
git status/git diff确认仓库 diff 干净; - 汇报:把 stdout 中的最终文本整理后交给用户。
如果用户确实要求修改,则步骤 4 的 prompt 改为明确授权写操作,并始终把工作目录限制在目标项目内。
五、补充:受管运行背后的实现线索
无头技能是“轻量入口”,而在 Cherry Studio 内部,DeepSeek Harness 还有一条完整的受管运行链路,理解它能帮助你把握技能文档之外的全貌:
- 生命周期服务:
DeepSeekHarnessService负责启动(dsh web --host 127.0.0.1 --port 0 --no-open,端口 0 表示随机可用端口、--no-open禁止弹出浏览器)、就绪探测(解析 stdout 中的dsh web: <url>并做 HTTP 探活,超时 30 秒)、以及分级停止(先优雅终止,3 秒内未退出再强制结束进程树),状态机在stopped / starting / running / error间流转(DeepSeekHarnessService.ts); - 配置投影与事务:启动前会把当前选中的模型、provider 与网关配置“投影”写入
settings.yaml与.credentials.yaml(分别对应DSH_HOME指向的配置目录),路由命名形如cherry-studio-codemate-<12位哈希>,凭据引用形如CHERRY_STUDIO_CODEMATE_<HASH>_API_KEY;写入过程使用.lock锁文件、支持孤儿锁回收、原子写入与失败回滚,避免多进程并发破坏配置(config.ts); - 控制面侧信道:
packages/dsh-bridge是 Cherry 与 dsh 运行时之间的控制面插件,通过 Unix socket/命名管道走 JSON-RPC,承载会话打开、提示、取消、策略下发、命令执行、子代理生命周期与工具审批等“Cherry 自有”方法(protocol.ts、link.ts)。其中策略由宿主在打开会话时一次性下发(BridgePolicy),工具调用的裁决则全部在 dsh 子进程内本地完成。
六、小结:三条不可妥协的纪律
综合技能文档与仓库实现,使用code-mate-deepseek-harness技能时始终守住三条纪律:
- 有界执行:工作目录限定在用户指定的项目,超时有限(默认 10 分钟),一次只跑一个无头任务;
- 凭据零接触:配置缺失即停止并交由用户在 Code Mate 中处理,智能体不请求、不读取、不打印、不复制任何密钥;
- 写操作最小化:只读任务显式声明不修改文件并事后检查 diff;写操作仅在用户明确授权时发生。
按此执行,dsh --profile headless "<prompt>"就能在 Cherry Studio 中成为既可委派分析、又可执行实现,同时风险可控的仓库级工具。
【免费下载链接】cherry-studio🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考