31 KiB
GoodBuddy 自维护 DeepSeek Harness Runtime 设计
1. 文档信息
| 项目 | 内容 |
|---|---|
| 文档状态 | 实现与发布验收基线 |
| 设计目标 | 将 DeepSeek Harness 作为 GoodBuddy 的第三个 Agent Runtime |
| Runtime 标识 | deepseek-harness |
| 首版依赖基线 | 实际使用的 @deepseek-ai/dsh-* 底层库,精确锁定 0.1.0-rc.6 |
| 上游状态 | Developer Preview,允许出现破坏性变更 |
| 上游许可证 | MIT |
| GoodBuddy 目标平台 | Windows、macOS、Linux,x64 与 arm64 |
| 本文性质 | 设计与发布验收约定 |
本文定义 DeepSeek Harness 在 GoodBuddy 中的架构边界、协议、安全策略、界面、打包和验收要求。实现必须继续遵守 GoodBuddy 已有的 Main 进程安全边界、Ask/Execute 语义、授权、取消、超时、有界输出和资源回收约定。
2. 摘要
DeepSeek Harness 的底层库使用 Cordis 组合服务。GoodBuddy 不采用官方产品 profile、插件安装或市场机制,也不让用户配置覆盖安全服务,而是增加一个实验性的第三 Runtime,并完全自行维护 Host、控制协议、生命周期和兼容层。上游 DSH 包只是精确锁定并逐次审查的实现依赖,不构成 GoodBuddy 对 DSH 插件 ABI、插件目录或产品路线的承诺。
GoodBuddy 并不迫切于把该能力做成 DSH 插件或进入插件市场。当前优先级是向用户提供稳定、可靠、可审计且可完整回收的 Runtime;只有未来真实用户需求和成熟度证明插件化确有价值时,才重新评估该形态。
整体分成两个互相约束的部分:
-
GoodBuddy Main Control Plane
- 运行在 Electron Main 进程。
- 持有加密设置、模型连接选择、Ask 拒绝与 Execute 自动授权策略、Runtime 生命周期和审计归属。
- 通过 Electron
utilityProcess启动受控 Harness 子进程。 - 对环境、输入、输出、超时、取消和进程树执行强制限制。
-
GoodBuddy Harness Control Plane
- 运行在 Harness 子进程内,是 Host 私有的内部控制组件,不导出 Cordis 插件入口。
- 使用 ACP 兼容的 JSON-RPC stdio 作为基础控制面。
- 增加 GoodBuddy 所需的能力握手、每轮权限准备、会话释放、工具事件、推理、用量和安全凭据请求扩展。
- 与 GoodBuddy Host 一起维护、构建和发布,不设计为独立 npm 包、
dsh.bundle或市场插件。
DeepSeek Harness 不替换 OpenCode、Continue 或直连模型 Runtime。用户可以按全局、项目、会话或消息通道继续选择现有 Runtime。
3. 背景与上游能力
3.1 已确认的官方能力
@deepseek-ai/dsh是官方 profile 启动器。- Harness 插件是导出
apply(ctx, config)的 Cordis 模块。 - npm 包可通过
dsh.bundle声明配置补丁,再通过dsh plugin --profile <name> add <package>安装。 - ACP 支持:
- 初始化。
- 创建多个会话。
- 发送 Prompt。
- 按会话取消。
- 一次性权限选择。
- 已提交的助手文本。
- 官方本地沙箱支持:
- Linux:Bubblewrap,或 Landlock 降级。
- macOS:Seatbelt。
- Windows:ACL 受限令牌,官方明确标记为部分强制执行。
3.2 官方通道的缺口
官方 ACP 插件有意只输出已提交文本,不输出推理、工具进度、计划、标题和用量。它也没有标准的会话关闭方法。SDK JSON-RPC 的展示事件更完整,但缺少 GoodBuddy 需要的单轮取消和权限回传。
因此,首版不单独选用其中一个官方通道作为完整实现。GoodBuddy Harness Control Plane 以 ACP 语义为基础,补充有命名空间的扩展方法和事件。
3.3 自维护边界
GoodBuddy 不急于把该 Runtime 包装成标准 DSH 插件,也不以进入官方或第三方插件市场为近期目标。所有入口都随 GoodBuddy 发布,只有 GoodBuddy Main 可以启动并使用内部 Host。是否采用上游新版本或未来重新评估插件形态,只由真实用户价值、安全审查和六平台稳定性决定,不跟随市场机制或上游发布节奏。
4. 目标与非目标
4.1 首版目标
- 增加
deepseek-harnessRuntime,并在设置、聊天和消息通道中可选择。 - 使用 GoodBuddy 管理的模型连接,不在 Renderer 或持久化 Harness 配置中写入 API Key。
- Ask 模式在 Runtime 边界强制只读,并禁止任何权限升级。
- Execute 模式下的工具权限请求由 Main 自动给予单次授权,不弹出交互审批;默认文件模式仍为
workspace-write,越界仅允许在真实沙箱拒绝后对完全相同操作单次重试。 - 支持多会话、同会话串行、跨会话并行。
- 支持按请求取消、超时、会话释放和应用退出时完整回收。
- 输出文本、推理、工具参数、工具结果、stderr 和协议队列全部有界。
- 使用真实 DeepSeek 模型验证调用,而不在日志、测试产物或提交中暴露凭据。
- 保留 Windows、macOS、Linux 的 x64 和 arm64 发布能力。
4.2 首版非目标
- 不替换 OpenCode、Continue 或直连模型 Runtime。
- 不开放用户 Cordis profile、cordis.patch.yml 或 $DSH_HOME 全局补丁覆盖。
- 不提供外部 Host、自定义 Harness Control Plane、DSH 插件安装或市场入口。
- 不加载 Harness Web UI、HMR、遥测、自动更新或目录选择器。
- 不支持
danger-full-access作为会话默认值或持久设置。 - 不向 Utility 暴露 MCP 凭据或建立直连 MCP Client。只有用户明确分配给 Harness 的 MCP 工具可以通过 Main 代理调用。
- 不在首版向 Harness 暴露 GoodBuddy 浏览器控制、知识库或 Magic Notes。
- 不在首版支持图像输入、会话恢复、Harness Subagent、后台 Job、Hook、Web Search 或 Workflow。
- 不发布独立 npm 包,也不创建上游 PR。
5. 核心设计决策
5.1 第三个独立 Runtime
deepseek-harness 是明确的 Runtime 类型,不伪装成 model、opencode 或 continue。共享契约、设置迁移、Runtime 选择、检测、聊天标签、消息通道和模型用量都使用同一个稳定标识。
5.2 受控组合,不启动用户 profile
GoodBuddy 使用自己固定的 Harness Host 入口和只读组合模板,不调用 dsh web,也不启动用户已有 profile。运行时禁止以下来源参与组合:
- 当前工作目录的
.env。 - 用户 Harness Home 的
.env。 $DSH_HOME/cordis.patch.yml。- 用户 profile 的
cordis.patch.yml。 - 任意
--patch。 - HMR 和动态插件安装。
模型名称、服务地址、工作区和非秘密策略通过严格校验的 Main 配置传给 Host。API Key 只通过受控凭据通道按需提供,不写入 YAML、命令行、Renderer 或日志。
5.3 双层内部控制面
Harness 子进程内控制面不能取代 Main 控制面,Main 控制面也不能代替进程内的 Session/Tool 适配层:
- Harness Control Plane 最接近 Session、Agent、Tool、Usage 和权限 seam,适合做内部协议转换。
- Main 控制面是可信安全边界,适合持有模式授权策略、加密设置、进程控制和 IPC。
任何一侧缺失能力握手时,Runtime 必须报告不可用,不能降级为不受控执行。
5.4 GoodBuddy 继续拥有持久会话
首版不启用 Harness JSONL 会话持久化和 SQLite 会话索引。原因如下:
- GoodBuddy 已经持久化对话、消息、活动、工具事件和用量。
- 再写一份 Harness 日志会扩大敏感数据副本和清理范围。
- GoodBuddy 在 Runtime 重启后可以用现有的有界历史创建新 Harness Session。
Harness Session 只在当前 Runtime 进程生命周期内存在。释放 GoodBuddy 会话时必须同步释放对应 Harness Agent。
6. 总体架构
Renderer
│ 显式、经 schema 验证的 preload API
▼
Electron Main
├─ RuntimeSettingsStore
├─ AgentRuntimeController
├─ RuntimeAuthorizer(Ask 拒绝 / Execute 自动单次授权)
└─ DeepSeekHarnessRuntime / Main Control Plane
│ ACP + goodbuddy/* 扩展,stdin/stdout
▼
Electron utilityProcess
└─ GoodBuddy Harness Host
├─ 固定 Cordis 组合
├─ GoodBuddy Harness Control Plane(内部组件)
├─ DSH Agent 与 LLM seam
├─ DSH Sandbox Policy
├─ 沙箱 Shell / Filesystem
└─ 最小工具集
│ HTTPS
▼
用户选择的 DeepSeek 兼容模型连接
6.1 信任边界
| 区域 | 信任级别 | 允许持有的内容 |
|---|---|---|
| Renderer | 不可信展示层 | 脱敏设置、状态、用户可见事件 |
| Preload | 窄桥 | 明确方法和共享 schema |
| Electron Main | 可信控制面 | 加密设置、模式授权策略、Runtime 生命周期 |
| Harness utilityProcess | 不可信执行面 | 当前请求、临时凭据、受控工具和工作区权限 |
| Harness 工具子进程 | 最低信任 | 单次命令所需的最小环境和沙箱能力 |
Harness 子进程崩溃、输出异常、拒绝协议、加载错误或沙箱不可用时,Main 必须失败关闭。
7. GoodBuddy Harness Control Plane
7.1 内部组件职责
控制面负责:
- 启动 ACP 兼容的 JSON-RPC stdio 服务。
- 创建、查找和释放 Harness Agent。
- 在 Prompt 前应用 GoodBuddy 指定的 Ask/Execute 权限。
- 将 DSH Session 事件转换为有界的 GoodBuddy 事件。
- 将权限请求转发到 Main,并只接受一次性结果。
- 将 LLM 用量转换为稳定的模型用量事件。
- 在 dispose 时先取消 Agent,再等待子 Agent 和工具清理。
- 保证 stdout 只包含协议帧,诊断只写 stderr。
控制面不负责:
- 保存 GoodBuddy 设置。
- 持久保存 API Key。
- 决定 Main 的模式授权结果。
- 直接访问 Renderer 或 Electron API。
- 接受用户提供的插件、Host 或 profile 覆盖。
- 自行上传遥测。
7.2 非插件约束
控制面不导出 apply(ctx, config),不提供默认 stdin/stdout 入口,不包含 dsh.bundle、cordis.patch.yml 或可安装 manifest,也不接受 Host 之外创建的 transport。它可以保留清晰的内部模块边界以便测试和维护,但该边界不是公开扩展点。
若未来确有来自 GoodBuddy 真实用户、经过研究验证的扩展需求,应先重新完成产品需求、威胁模型和兼容策略评审;不得因为上游已经提供插件或市场机制而默认开放。
8. 协议设计
8.1 传输
- stdin/stdout 使用换行分隔 JSON-RPC。
- stdout 不得出现日志、Banner、进度条或调试输出。
- stderr 只允许有界诊断,不得包含 Prompt、工具完整输出或凭据。
- 每一帧、每一字段和每个请求累计输出都必须在解析前或接收时限流。
8.2 标准 ACP 方法
首版保留 ACP 的初始化、session/new、session/prompt 和 session/cancel 语义。标准 ACP 客户端可以使用只读默认行为,但只有完成 GoodBuddy 能力握手的客户端才能启用 Execute。
8.3 GoodBuddy 扩展
扩展统一使用 goodbuddy/ 命名空间:
| 方法或事件 | 方向 | 用途 |
|---|---|---|
goodbuddy/handshake |
Main → Control Plane | 交换控制协议、Harness、ACP 版本和能力 |
goodbuddy/session/prepare |
Main → Control Plane | 在下一次 Prompt 前设置工作模式和请求标识 |
goodbuddy/session/release |
Main → Control Plane | 取消并释放指定 Session |
goodbuddy/session/event |
Control Plane → Main | 文本、推理、工具、状态和用量事件 |
goodbuddy/credential/resolve |
Control Plane → Main | 按已登记引用请求当前 Runtime 的临时凭据 |
goodbuddy/tools/list |
Control Plane → Main | 取得用户分配给 Harness 的有界 MCP 工具 schema |
goodbuddy/tools/call |
Control Plane → Main | 通过当前 Execute 请求、schema 校验和自动单次授权调用 MCP |
goodbuddy/shutdown |
Main → Control Plane | 停止接收新请求并有序清理 |
扩展版本独立于 ACP 版本。握手响应至少包含:
type GoodBuddyHarnessCapabilities = {
controlProtocolVersion: 1
harnessVersion: string
acpProtocolVersion: number
supports: {
cancellation: true
sessionRelease: true
oneShotApproval: true
reasoningEvents: boolean
toolEvents: boolean
usageEvents: boolean
}
sandbox: {
provider: string
enforcement: 'full' | 'partial'
}
}
版本不兼容、必需能力缺失或 sandbox.enforcement 不满足设置要求时,Main 不得开始模型请求。
8.4 每轮权限准备
GoodBuddy 的工作模式属于每个请求,不属于 Runtime 进程全局状态。同一对话可以在 Ask 和 Execute 之间切换。因此:
session/new后默认是read-only + never。- 每个 Prompt 前,Main 发送一次
goodbuddy/session/prepare。 - Harness Control Plane 将准备状态绑定到
sessionId + requestId。 session/prompt只能消费匹配且尚未使用的准备状态。- 缺少准备状态、重复使用、请求标识不匹配时,Control Plane 使用只读且禁止授权的安全默认值,或直接拒绝请求。
- 同一 Session 只允许一个 Prompt 在途。
8.5 事件模型
Harness Control Plane 只发送 GoodBuddy 能稳定解释的字段:
status:简短运行状态。text:已提交的助手文本分片。reasoning:可选的有界推理摘要分片。tool:工具 ID、名称、状态和有界输入/输出摘要。model-usage:模型、提供方、输入、输出和缓存 Token。done:停止原因和 Session ID。
禁止发送原始 Cordis Context、完整环境、内部对象、堆栈中的凭据或无界 Session 日志。
9. Runtime 生命周期
9.1 进程模型
- 每个活动的 DeepSeek Harness Runtime 实例拥有一个
utilityProcess。 - 一个进程可以承载多个 Harness Session。
- 同一 GoodBuddy 对话的 Prompt 串行执行。
- 不同对话可以并行,但受全局并发上限控制。
- Runtime 设置变化时创建新实例,旧实例等待在途请求结束或在宽限期后被取消。
9.2 会话映射
Main 保存内存映射:
GoodBuddy conversationId -> Harness sessionId + process generation
- 首次请求创建 Session。
- 已有 Session 只发送当前 Prompt。
- 进程重启或映射失效时,创建新 Session,并只在这一次加入 GoodBuddy 提供的有界历史。
- 历史以明确的“不可信会话数据”结构传入,不能拼接成系统指令。
- 用户分配的 Skill 只通过 Main 校验的包路径进入 Host,并在 Agent scope 注册;不得把 Skill 内容伪装成用户 Prompt。
9.3 取消与超时
- 用户取消时立即发送
session/cancel。 - 取消等待有界,超时后关闭连接并终止整个 Harness 进程。
- 初始化、握手、Session 创建、Prompt、权限回传和关闭分别使用独立超时。
- Prompt 超时与用户取消使用不同错误类型,不能被宽泛 catch 抹平。
- 取消后仍可接收并丢弃该请求的最终协议结算帧,但不得写入下一请求。
9.4 释放与退出
- 删除或释放对话时调用
goodbuddy/session/release。 - Runtime dispose 时先拒绝新请求,再取消所有 Session。
- Harness Control Plane 完成 Agent、工具和会话清理,Host 完成 Cordis Fiber 与子进程的反向清理。
- Main 在宽限期内等待正常退出。
- 超时后终止 utilityProcess,并在平台允许时清理完整进程树。
- 应用退出不得因 Harness 清理无限阻塞。
10. 权限与沙箱
10.1 模式映射
| GoodBuddy 模式 | DSH 文件模式 | DSH 权限策略 | 行为 |
|---|---|---|---|
| Ask | read-only |
never |
允许受控读取,不允许写入,不允许升级 |
| Execute | workspace-write |
ask |
允许工作区与受控临时目录写入;权限请求由 Main 自动单次授权,不弹出交互审批 |
danger-full-access 只能作为某个已被沙箱拒绝的完全相同操作的一次性、更宽重试。Main 仅对该次重试自动返回 allow-once;它不能保存为默认值、复用于后续操作,或通过“始终允许”返回。
10.2 Ask 模式
- Main 即使收到权限请求也固定拒绝。
- Harness Control Plane 禁止
sandbox_permissions升级。 - 文件写入和 Shell 写入都由 DSH 共享 Sandbox Policy 强制拒绝。
- 只读不等于无限输出,读取仍受路径、字节和工具结果上限控制。
- 首版不向 Ask 暴露 GoodBuddy 的可变数据工具。
10.3 Execute 模式
- 工作区根来自 Session 创建时的规范化绝对路径。
- 工具不能自行更换工作区根。
- 工作区内操作按 DSH
workspace-write执行。 - 只有真实沙箱拒绝后的同一操作,才可请求一次升级。
- Main 不调用
ToolApprovalBroker,而是对当前 Execute 请求自动返回allow-once;界面不进入等待审批状态,也不弹出审批对话框。 - 所有工具调用仍作为活动事件记录;Ask 和 delegation 路径继续固定拒绝。
- Harness Control Plane 不接受
allow_always,也不把未知结果解释为允许。
10.4 沙箱可用性
strict:要求完整强制执行。仅有partial或无 Runner 时 Runtime 不可用。auto:允许官方报告的full或partial,但必须在状态卡显示实际强制程度。off:不允许 Harness 退化到无限制工具执行。首版将 Execute 标记为不可用,Ask 仍只能在可强制只读时运行。
Windows ACL 和旧 Linux Landlock 可能只报告 partial。界面和诊断必须如实显示,不能写成“完全隔离”。
10.5 环境与凭据
- 使用环境变量白名单构造 utilityProcess 环境。
- 不继承
NODE_OPTIONS、调试端口、任意 npm 配置、用户DSH_*覆盖或白名单之外的凭据。 DSH_TELEMETRY_DISABLED=1必须固定设置。- Harness Home 指向 GoodBuddy 管理的隔离目录。
- 不调用官方
loadEnv或loadLayeredEnv。 - API Key 由 Main 从加密设置中解析。
- Harness Control Plane 只能用已握手登记的引用通过
goodbuddy/credential/resolve请求当前 Runtime 的凭据。 - 凭据只在模型请求所需的子进程内存中短暂存在,不写磁盘、不进入工具环境、不打印。
11. 受控 Harness 组合
首版只加载完成文本对话、受控代码操作和用户明确分配能力所需的固定服务:
- Agent、Session、LLM 和 Tool Registry 基础服务。
- GoodBuddy Harness Control Plane。
- DeepSeek 兼容 LLM 适配器。
- Sandbox Policy 与平台 Sandbox Provider。
- 平台对应的受沙箱 Shell。
- 受沙箱 Filesystem。
- 一次性权限请求服务。
- Token Meter 和必要的上下文压缩。
- 有界的读取、写入、编辑和 Shell 工具。
- Agent scope 的 Skill Registry 与
skill工具。Skill 目录由 Main 选择并在 Launcher 和 Host 两次规范化、校验。 - Main 代理的 MCP schema 工具。Utility 不持有 MCP URL 凭据或 Transport。
首版明确不加载:
- Web UI、HMR、Host API 和目录选择器。
- Harness 遥测。
- Settings File 和 Local Credentials。
- 用户 profile 与全局补丁。
- Web Search、Fetch、Utility 直连 MCP、Hooks。
- Subagent、Workflow、Ralph、后台 Job。
- JSONL Session Persistence 和 SQLite Session Query。
- 自动技能发现和市场技能加载。
如果某个首版工具依赖被排除服务,启动审计必须失败,而不是自动加载更大的默认 bundle。
12. 模型配置
12.1 配置来源
DeepSeek Harness 首版只使用 GoodBuddy 模型连接:
- 协议必须是
openai-chat-completions。 - 认证必须是 API Key。
- 服务地址必须是
https://api.deepseek.com,且不得包含用户信息。 - 模型名称和服务地址由 Main 传入受控 Host。
- API Key 继续保存在 GoodBuddy 加密设置中。
不允许选择 Harness 自有的用户配置文件或自定义 Host。Runtime 始终使用随当前 GoodBuddy 版本发布的内置 Host,并通过完整内部能力握手。
12.2 设置变化
模型、凭据、沙箱、Skill 或 MCP 分配变化时,GoodBuddy 创建新 Runtime 实例。Harness Host 路径始终由当前 GoodBuddy 构建提供,不能由设置或环境变量替换。旧实例按现有 Runtime Controller 语义退役,不在一个活动进程内热替换安全配置。
12.3 输入限制
- 首版只支持文本。
- 图片输入应在发起网络调用前返回明确错误。
- GoodBuddy 历史、Prompt、系统指令分别保持不同信任层。
- 任何用户文本都不能进入 Cordis 配置表达式或模块名。
13. 输出和资源边界
建议首版默认限制:
| 项目 | 默认上限 |
|---|---|
| 单个 JSON-RPC 帧 | 1 MiB |
| 单个文本或推理事件 | 64 KiB |
| 单次请求累计协议输出 | 4 MiB |
| 工具输入摘要 | 4,000 字符 |
| 工具输出摘要 | 4,000 字符 |
| 待处理事件数 | 1,000 |
| stderr 累计 | 64 KiB |
| 初始化 | 10 秒 |
| 单次 Prompt | 10 分钟 |
| 有序关闭宽限期 | 2 秒 |
超过限制时应取消当前请求。协议帧、队列或 stderr 持续异常时,应终止 Runtime 进程,避免继续信任已失控的通道。
14. Runtime 检测与状态
14.1 检测
检测只验证:
- 内置 Host 路径是规范化文件。
- 版本可读取且在支持范围内。
- 内部控制面能力握手成功。
- 必需 Sandbox Provider 可用并报告强制程度。
检测不得调用付费模型,也不得读取或输出 API Key。真实模型测试是单独的显式操作。
14.2 设置界面
Agent Runtime 使用共享 SegmentedControl 展示 OpenCode、Continue 和 DeepSeek Harness。DeepSeek Harness 必须标记为“开发者预览”,并说明上游 RC 可能发生破坏性变更。
Runtime 的概览、模型配置和检测信息放在同一张详情卡中。当前单独显示的一行“已就绪”应移入卡片,与路径、版本号归为同一组:
Runtime: GoodBuddy 内置 DeepSeek Harness
模型配置: 跟随 GoodBuddy · dsv4flash(deepseek-v4-flash)
状态: 已就绪
路径: <受控 Host 路径>
版本: 0.1.0-rc.6
安全强制: 完整 / 部分
Host 始终由当前 GoodBuddy 版本提供,不存在自定义 Host 入口。
界面要求:
- 不再在卡片外重复一行检测结果。
- 使用语义化键值结构,路径允许换行,不截断关键信息。
- 状态不能只依靠绿色表达,必须同时有文字。
- 检测中、不可用和部分强制分别显示明确文案。
- 高级设置默认收起。
聊天顶栏只显示简短 Runtime 状态,不显示文件路径和版本。完整诊断只在设置页展示。
15. IPC 与共享契约
共享 schema 需要覆盖:
deepseek-harnessprovider 和 Runtime ID。- Runtime 选择中的
deepseekHarness分支。 - 检测结果中的路径、版本、详情和沙箱强制程度。
- GoodBuddy 模型连接选择。
- DeepSeek Harness 模型用量归属。
- Skill 与 MCP 对
deepseek-harness的显式分配。
Renderer 只接收脱敏状态。任何凭据、完整环境、启动参数或内部 Cordis 配置都不能进入共享契约。
已有设置迁移必须:
- 对没有新字段的用户使用安全默认值。
- 保留 OpenCode、Continue 和模型连接选择。
- 修复失效的 DeepSeek Harness 模型引用时给出可报告的迁移警告。
- 不把旧 Runtime 自动迁移为 DeepSeek Harness。
16. 打包与供应链
16.1 版本策略
- 官方 RC 包全部精确锁定,不使用
^或~。 - 同一 Harness 核心包族必须保持同一 RC 版本。
- 升级前检查 release diff、协议 diff、沙箱 diff和依赖闭包。
- 内部握手同时检查锁定的 Harness 基线和 GoodBuddy 控制协议版本。
16.2 原生依赖
受控组合可能需要:
node-pty,用于受管理的工具子进程。koffi,用于 Windows ACL 或相关本地能力。@deepseek-ai/node-addon-landlock-run的平台包。
不得广泛批准所有安装脚本。只允许生产组合实际需要、来源已审查、版本已锁定的脚本。六个平台的构建必须验证:
- 对应架构的原生文件存在。
- Electron Utility Process 可加载原生模块。
- Runner 或 spawn helper 的权限正确。
- 包中没有混入其他平台不需要的可执行内容,除非上游包无法拆分且已记录。
16.3 生产闭包
发布包只包含受控 Host 需要的插件和许可证。应尽量避免把 Harness Web profile、HMR 和其他未加载产品面带入生产闭包。若 npm 依赖结构无法拆分,必须:
- 确认这些模块不会被加载。
- 评估它们带来的 audit 和体积风险。
- 在后续上游版本允许时改为最小包族。
16.4 漏洞门禁
当前安装后的 npm audit 报告不能直接用 npm audit fix --force 处理。每项漏洞需要区分:
- GoodBuddy 既有依赖。
- Harness 新增生产依赖。
- 仅开发或打包依赖。
- 未加载但被带入的 Web 依赖。
进入 Harness 执行路径且有可利用条件的高危问题必须在发布前修复、替换或移出生产闭包。
16.5 发布验证
build/build-release.cjs 需要验证:
- Harness Host 和受控配置存在。
- GoodBuddy Host、内部控制协议与 Harness 依赖版本清单存在。
- 平台原生 Sandbox/PTY 依赖架构正确。
- Harness、ACP SDK 和其他新增第三方许可证已打包。
app.asar外需要执行或动态加载的资源位于预期目录。
17. 测试策略
17.1 单元测试
- Runtime 选择、设置迁移和失效引用修复。
- 二进制检测、版本解析和路径规范化。
- ACP 握手、事件转换和请求关联。
- 每个会话单请求、跨会话并行。
- Ask 固定拒绝升级。
- Execute 权限请求由 Main 自动返回单次授权,Ask 与 delegation 固定拒绝。
- 未分配 Skill/MCP 不可见;分配后的 Skill catalog 可调用
skill加载。 - Ask 不注册 MCP 工具;Execute 每轮刷新有界 schema,并在调用前再次校验活动请求、模式、参数和自动单次授权。
- MCP URL、启动命令和凭据不进入 Utility 启动配置或协议结果。
- 未知授权结果失败关闭。
- 超时、取消、迟到帧和进程意外退出。
- 协议帧、事件队列、工具摘要和 stderr 上限。
- release 和 dispose 的幂等性。
- 状态卡中的状态、路径、版本和强制程度。
17.2 本地集成测试
使用无网络的假控制面/模型验证:
- utilityProcess 管道。
- 多 Session。
- Session 释放。
- Runtime 替换。
- 进程树回收。
- 受控配置不会读取工作区
.env和用户 DSH 配置。
17.3 真实模型测试
真实测试已经获得用户授权,但必须由显式环境门禁启用。至少验证:
- 文本问答成功,并记录正确 Runtime 和模型用量。
- Ask 可以读取工作区,但写入被拒绝,且不会弹出权限对话框。
- Execute 可以在工作区创建测试文件。
- Execute 越界操作先被拒绝,再对完全相同的重试自动给予单次授权,全程不弹出审批。
- 不匹配的重试、Ask 和 delegation 不能换路径或重复绕过。
- 取消长请求后不再产生文本,并可继续使用其他 Session。
- 两个 Session 可并行,事件不会串线。
- 释放会话和关闭应用后没有残留 Harness 或工具进程。
- 从全新用户设置流程启用一个 3D 游戏 Skill 和实际本地或开放 MCP,工具事件能够证明二者确实被调用。
- Harness 生成的 3D 游戏项目可以安装、启动和实际游玩,包含 3D 渲染、玩家控制、目标和反馈,浏览器无关键错误。
测试不得打印、快照或提交 API Key。测试创建的文件只能位于专用临时工作区,并在确认可再现后清理。
17.4 项目验证
源码完成后必须运行:
npm test
npm run typecheck
npm run lint
npm run build
涉及发布资源后,还要按可用原生平台运行聚焦的 release:package 验证。无法在当前主机执行的目标必须由六平台 CI 验证。
18. 验收标准
功能只有同时满足以下条件才算完成:
deepseek-harness可被保存、选择、检测和显示。- Runtime 详情卡内显示状态、路径、版本和沙箱强制程度。
- Skills 与 MCP 设置页可把能力分配给 DeepSeek Harness,布局、键盘语义、文案和保存回显通过真机检查。
- Ask 写入测试在 Runtime 边界失败。
- Execute 工作区内写入成功。
- 越界写入只有同一操作获得自动单次授权后才能执行一次,且不弹出审批。
- 取消、超时、切换 Runtime 和退出应用均能回收进程。
- 多会话不串流、不串权限请求、不串用量。
- 用户 DSH 配置、
.env、遥测和 Web UI 未被加载。 - API Key 不进入 Renderer、配置文件、日志、错误文本或测试产物。
- 全量测试、类型检查、Lint 和生产构建通过。
- 真实 DeepSeek 请求成功。
- 真实请求调用已分配 Skill 和 MCP,并生成、启动和实际游玩一个可用的 3D 游戏项目。
- 新增第三方许可证和发布校验完整。
19. 已知限制
- DeepSeek Harness 底层库当前是 RC,但 GoodBuddy 不自动跟随升级;每次升级都可能要求同步修改内部控制面。
- Windows ACL 和部分 Linux Landlock 环境只能提供部分强制执行。
- 首版不恢复 Harness 原生 Session,Runtime 重启后由 GoodBuddy 历史重建。
- 首版不支持图片、知识库、浏览器工具和 Harness Subagent;MCP 仅支持用户分配、Main 代理和 Execute 自动单次授权路径。
- 推理、工具和用量扩展属于 GoodBuddy 协议,不是标准 ACP 保证。
- 不支持 DSH 插件、市场包、用户 profile 或自定义 Host。
20. 自维护与升级策略
GoodBuddy 对该 Runtime 采用内部维护策略:
- 当前通过验证的 Host、控制协议和依赖锁定随 GoodBuddy 一起版本化。
- 不自动跟随 DSH RC、插件 ABI、profile 格式或市场元数据变化。
- 升级前审查实际用户收益、上游 diff、沙箱与工具语义、协议行为、依赖闭包和许可证。
- 六个平台的单元、假模型、UtilityProcess、沙箱和真实模型门禁全部通过后才能更新基线。
- 若上游方向不再满足 GoodBuddy 用户需求或安全边界,允许维护兼容补丁、替换单个底层包,或逐步移除 DSH 依赖;
goodbuddy/*内部协议保持由 GoodBuddy 控制。 - 不以进入官方插件目录、适配市场机制或服务非 GoodBuddy 客户端作为目标。
21. 备选方案记录
21.1 每次调用 dsh --profile headless
未采用。它适合一次性任务,但不能满足流式事件、多会话、细粒度取消、权限回传和低延迟复用。
21.2 只使用官方 ACP 插件
未采用。取消和一次性权限选择符合需求,但缺少工具、推理、用量和会话释放事件。
21.3 只使用官方 SDK JSON-RPC
未采用。事件更完整,但单轮取消和权限回传能力不足。
21.4 把全部安全逻辑放进 Harness 子进程
未采用。Harness 子进程属于不可信执行面,不能拥有最终模式授权策略、加密设置和进程回收权限。
21.5 把全部控制适配放在 Main
未采用。Main 无法可靠观察 Cordis 内部 Session、Tool、Usage 和权限 seam,只能得到不完整的外部进程行为。
当前选择的双层内部控制面放弃标准 DSH 插件形态,只复用锁定的底层库,并维持 GoodBuddy 的可信 Main 控制权。