🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

双模型协作 aa2246740/dsh-model-fusion

DeepSeek Harnessv0.2.8
aa22467405 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness 融合模式:前沿 Lead 负责规划与审查,便宜得多的 Sidekick 负责写代码——用折扣价拿到前沿效果。

54.4/100
综合分
69
GitHub 星标
320
npm 周下载
—/5
用户评分

数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-model-fusion
npm 源 · dsh-model-fusion 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · market
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-model-fusion @ 0.2.8
✓Node 引擎要求 >=22.14.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/28 06:40:26

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 98 处,展示前 67 条)
  • 读取本地文件
    lib/dsh-model-fusion.js:1165
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    lib/dsh-model-fusion.js:1174
    lead: readFileSync(join(dir, "lead.md"), "utf8"),
  • 读取本地文件
    lib/dsh-model-fusion.js:1175
    worker: readFileSync(join(dir, "worker.md"), "utf8"),
  • 读取本地文件
    lib/dsh-model-fusion.js:1176
    compact: readFileSync(join(dir, "compact.md"), "utf8")
  • 读取本地文件
    lib/dsh-model-fusion.js:1181
    lead: readFileSync(join(dir, "model-lead.md"), "utf8"),
  • 读取本地文件
    lib/dsh-model-fusion.js:1182
    worker: readFileSync(join(dir, "model-worker.md"), "utf8"),
  • 写入本地文件
    lib/dsh-model-fusion.js:2342
    mkdirSync: (path) => mkdirSync(path, { recursive: true }),
  • 写入本地文件
    lib/dsh-model-fusion.js:2344
    writeFileSync: (path, data) => writeFileSync(path, data),
  • 删除本地文件
    lib/dsh-model-fusion.js:2346
    rmSync: (path) => rmSync(path, { force: true })
  • 写入本地文件
    lib/dsh-model-fusion.js:2571
    renameSync(from, to) {
  • 写入本地文件
    lib/dsh-model-fusion.js:2592
    if (filename !== ":memory:") mkdirSync(dirname(filename), { recursive: true });
  • 写入本地文件
    lib/dsh-model-fusion.js:3145
    fs.mkdirSync(path.dirname(legacy), {
  • 执行外部命令固定命令
    lib/dsh-model-fusion.js:3549
    const out = execFileSync("git", [
  • 写入本地文件
    lib/dsh-model-fusion.js:11178
    mkdirSync(options.output, { mode: 448 });
  • 发起网络请求
    lib/client.js:67
    fetch(`/api/model-fusion?view=history&cursor=${encodeURIComponent(cursor)}`, {
  • 发起网络请求
    lib/client.js:260
    const response = await fetch("/api/model-fusion", {
  • 发起网络请求
    lib/client.js:418
    fetch("/api/model-fusion?view=cache", {
  • 发起网络请求
    lib/client.js:567
    fetch("/api/model-fusion?view=settings", {
  • 发起网络请求
    lib/client.js:594
    const response = await fetch("/api/model-fusion", {
  • 发起网络请求
    lib/client.js:606
    const current = await fetch("/api/model-fusion?view=settings", {
  • 写入本地文件
    src/benchmark/native-run.ts:86
    mkdirSync(options.output, { mode: 0o700 })
  • 写入本地文件
    src/benchmark/native-run.ts:156
    writeFileSync(join(options.output, 'manifest.json'), JSON.stringify(frozen, null, 2), { mode: 0o600, flag: 'wx' })
  • 写入本地文件
    src/benchmark/native-run.ts:207
    writeFileSync(join(options.output, 'parent-events.json'), JSON.stringify(events, null, 2), { mode: 0o600, flag: 'wx' })
  • 写入本地文件
    src/benchmark/native-run.ts:208
    workers.forEach((session, index) => writeFileSync(join(options.output, workerSessions[index]!.eventsFile),
  • 写入本地文件
    src/benchmark/native-run.ts:210
    writeFileSync(join(options.output, 'result.json'), JSON.stringify(result, null, 2), { mode: 0o600, flag: 'wx' })
  • 发起网络请求
    src/client/status-polling.ts:39
    const response = await fetch(`/api/model-fusion?view=status&sessionId=${encodeURIComponent(sessionId)}`,
  • 写入本地文件
    src/execution/write-lease.ts:110
    fs.mkdirSync(path.dirname(legacy), { recursive: true, mode: 0o700 })
  • 读取本地文件
    src/execution/write-lease.ts:111
    const oldTemporary = leasePath(workspaceId, path.join(fs.existsSync('/tmp') ? '/tmp' : os.tmpdir(), 'dsh-model-fusion-leases'))
  • 读取本地文件
    src/execution/write-lease.ts:114
    fs.lstatSync(lock)
  • 读取本地文件
    src/host/change-evidence.ts:20
    const before = lstatSync(path)
  • 读取本地文件
    src/host/change-evidence.ts:43
    const after = lstatSync(path)
  • 读取本地文件
    src/host/coordinator.ts:196
    try { current = readFileSync(workspacePath(root, path), 'utf8') } catch { return [{ path, removedLines: original.split('\n').filter(line => line.trim(
  • 读取本地文件
    src/host/coordinator.ts:1572
    const texts = changes.flatMap(path => { try { return [readFileSync(workspacePath(root, path), 'utf8')] } catch { return [] } })
  • 读取本地文件
    src/host/native-budget.ts:75
    const raw = this.authorizationFile ? JSON.parse(readFileSync(this.authorizationFile, 'utf8'))
  • 读取本地文件
    src/host/native-checks.ts:59
    return digestOf({ definition, files: definition.definitionPaths.map(path => ({ path, digest: sha256Hex(readFileSync(workspacePath(root, path))) })) })
  • 读取本地文件
    src/host/native-checks.ts:84
    if (!lstatSync(workspacePath(root, path), { throwIfNoEntry: false })?.isFile()) {
  • 读取本地文件
    src/host/native-checks.ts:342
    try { accessSync(path, windows ? constants.F_OK : constants.X_OK); return true } catch { return false }
  • 读取本地文件
    src/host/native-exploration.ts:29
    try { stat = lstatSync(path) }
  • 读取本地文件
    src/host/native-exploration.ts:36
    const bytes = readFileSync(path)
  • 读取本地文件
    src/host/native-exploration.ts:108
    if (!lstatSync(path).isFile()) return source.path
  • 读取本地文件
    src/host/native-exploration.ts:109
    const bytes = readFileSync(path)
  • 读取本地文件
    src/host/workspace.ts:33
    try { if (lstatSync(current).isSymbolicLink()) throw new Error('Workspace path traverses a symlink') }
  • 执行外部命令固定命令
    src/host/workspace.ts:68
    const out = execFileSync('git', ['-C', root, 'ls-files', '-z', '--cached', '--others', '--exclude-standard'],
  • 读取本地文件
    src/host/workspace.ts:84
    const contents = large ? undefined : readFileSync(full)
  • 读取本地文件
    src/host/workspace.ts:85
    const after = lstatSync(full)
  • 读取本地文件
    src/host/workspace.ts:92
    for (const name of readdirSync(directory).sort()) {
  • 读取本地文件
    src/host/workspace.ts:94
    const stat = lstatSync(full)
  • 读取本地文件
    src/host/workspace.ts:105
    try { stat = lstatSync(full) } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue; throw error }
  • 读取本地文件
    src/profile/resolve.ts:130
    return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>
  • 读取本地文件
    src/prompts.ts:15
    lead: readFileSync(join(dir, 'lead.md'), 'utf8'),
  • 读取本地文件
    src/prompts.ts:16
    worker: readFileSync(join(dir, 'worker.md'), 'utf8'),
  • 读取本地文件
    src/prompts.ts:17
    compact: readFileSync(join(dir, 'compact.md'), 'utf8'),
  • 读取本地文件
    src/prompts.ts:23
    lead: readFileSync(join(dir, 'model-lead.md'), 'utf8'),
  • 读取本地文件
    src/prompts.ts:24
    worker: readFileSync(join(dir, 'model-worker.md'), 'utf8'),
  • 读取本地文件
    src/prompts.ts:25
    compact: readFileSync(join(dir, 'compact.md'), 'utf8'),
  • 写入本地文件
    src/task/sqlite-store.ts:22
    if (filename !== ':memory:') mkdirSync(dirname(filename), { recursive: true })
  • 读取本地文件
    src/task/store.ts:11
    existsSync(path: string): boolean
  • 写入本地文件
    src/task/store.ts:12
    mkdirSync(path: string): void
  • 读取本地文件
    src/task/store.ts:13
    readFileSync(path: string): string
  • 写入本地文件
    src/task/store.ts:14
    writeFileSync(path: string, data: string | Uint8Array): void
  • 写入本地文件
    src/task/store.ts:15
    renameSync(from: string, to: string): void
  • 删除本地文件
    src/task/store.ts:16
    rmSync(path: string): void
  • 写入本地文件
    src/task/store.ts:21
    mkdirSync: path => mkdirSync(path, { recursive: true }),
  • 读取本地文件
    src/task/store.ts:22
    readFileSync: path => readFileSync(path, 'utf8'),
  • 写入本地文件
    src/task/store.ts:23
    writeFileSync: (path, data) => writeFileSync(path, data),
  • 删除本地文件
    src/task/store.ts:25
    rmSync: path => rmSync(path, { force: true }),
  • 写入本地文件
    src/task/store.ts:275
    renameSync(from, to) {
扫描于 2026/10/31(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/schemastery@deepseek-ai/dsh-agent@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-session-query@deepseek-ai/dsh-subagent@deepseek-ai/dsh-tools@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-commands@deepseek-ai/dsh-host-webserver
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 前沿模型规划审查
  • 低成本模型编写代码
  • 折扣价获前沿效果
v0.2.92026-10-30
· dsh-model-fusion 0.2.9 Fusion 现在一个包同时支持 DeepSeek Harness 0.2.0-rc.2 和 0.2.1-rc.2。 · 变更 · 模型菜单使用 Host 的主题配色,深色模式下标签依然清晰可读。 · Fusion 接受所配置 Lead 支持的输入模态,Lead 支持图片时也能处理图片。 · 缺失或为 null 的用量计数器保持未知状态,不再以 USAGE_MERGE_CONFLICT 中止本轮。 · 其他插件替换组装好的工具表后,Fusion 会恢复自己获准使用的工具。缺少必需的 Fusion 工具时,请求以 FUSION_TOOL_TABLE_INCOMPLETE 停止。 · 工作区写入租约只作用于 Fusion 拥有的智能体。同一文件夹里的普通会话不再被另一个 Fusion 任务的租约阻塞。 · 只读报告会校验其引用的文件。无关的文件改动或不受支持的文件类型,不再妨碍原本有效的回答完成。 · Sidekick 已结束却没有报告时返回 WORKFLOW_INCOMPLETE。恢复控制会说明模型切换在何时被拒绝,用户的沙箱模式会传递给常驻 Sidekick。 · Sidekick 的工具允许列表在工具执行时强制执行,包括其他插件直接注册到 Sidekick 上的工具。 这些变更包含 PR #16、#17 和 #18,并纳入了 PR #2、#7 和 #14 的贡献。 · 验证 发布准备通过类型检查、全部 326 个单元测试、一次全新构建和 DSHX 静态插件检查。重新构建的 lib/ 与合并候选逐字节一致。 合并候选此前在每个受支持的 Host 版本上通过 256 个原生 Host 测试,其中一个 Windows 专属测试在 macOS 上跳过。真实模型的实现任务在两个版本上都已完成,只读问题在 0.2.1-rc.2 上完成。本次发布准备没有发起新的模型调用,也没有在你正在运行的 Host 中安装或激活插件。 · 未关闭的报告 · #15:配额显示不正确,等待复现细节。 · #19:对空文件夹的调查可能在等待反馈时一直阻塞。 · #20:首轮缺少 Fusion 工具,报告于 0.2.8,尚未针对本版本验证。 · #21:更改模型或推理强度后缓存保活;PR #22 仍在审查中。 · 安装 使用 dsh-model-fusion@0.2.9。参见英文说明或中文安装说明。 · 已发布产物验证 · npm:dsh-model-fusion@0.2.9,同时打上 latest 标签。 · 源码提交:8192f845387f9f7d588cbee6302979d8b93c6976。 · 标签发布工作流成功。 · 注册表 tarball 的 SHA-256:e6b35f52edc247174dfa34b802a57070e1d13f88b1ecae9707b859c6d89508a4。 · 附件中的 tarball 从公共 npm 注册表下载,其完整性和 shasum 一致。全新注册表安装、服务端入口导入和客户端懒注册均通过。npm audit signatures 通过,没有无效或缺失的签名。来源主体摘要、仓库、标签、提交和工作流运行均匹配。 · 打包的源文件和声明与发布检出一致。npm 运行时 bundle 仅在注释、字面量渲染、常量折叠、拆分声明和三个即用临时变量上不同。经过附件比较脚本中的显式归一化后,两个 bundle 一致;客户端 source map 内容完全一致。以上均为产物检查;没有额外运行实际 Host 激活或模型任务。 · SHA256SUMS.txt 覆盖 tarball、来源、验证报告和比较脚本。
v0.2.82026-10-14
· dsh-model-fusion 0.2.8 使用记录很大时,每次查询状态不再需要扫描整个文档。增量式 SQLite 索引保留原有状态统计,支持可取消的异步回填,并在后续请求中继续未完成的回填。同一会话的状态组件在同一页面内共用轮询,折叠时退避,隐藏或卸载时暂停。 Fusion 还通过可选的 compactionRoutes v1 服务,把冻结的会话路由提供给 Compact Saviour。配合 Compact Saviour 0.2.8,容量规划和摘要生成使用同一物理模型、effort 和输出上限。模型变更、取消和所有者卸载会在旧计划提交摘要前将其作废。 这些改动已在 macOS 上用合成记录和真实 Desktop Host 验证。原报告者约 4 GB 的 OOM 和完整的异常压缩链未能复现。本版本解决了已确认的状态扫描瓶颈和压缩路由不匹配问题,但不声称 issue #11 的所有症状都已解决。原生 Electron 交互和数小时的生产负载仍未验证。 · 验证 在 macOS 上,发布源码通过 287 个单元测试、241 个原生 Host 测试和 10 个跨插件 Host 测试;跳过 1 个 Windows 专用测试。类型检查、构建、DSHX 检查和归档校验均通过。本地构建的运行时与先前通过真实 Desktop Host 验证过的 v9 安装一致。npm 构建仅有编译器输出差异:PURE 注释、精确常量折叠、声明拆分,以及三处等价的临时变量内联变换。经这些显式归一化后,两个运行时文件一致,source-map 的源码内容完全一致。10 个跨插件测试使用合成适配器,未发起任何网络调用。在验证 registry 产物期间,未进行额外的真实模型调用或生产 Host 安装。 · 已发布产物验证 · npm:dsh-model-fusion@0.2.8 · 源码提交:1af018f9db834761dde188af638ed1886cb67abd · 标签发布工作流成功 · Registry tarball SHA-256:55fbc36acbb0c181988944cf6c68d7fb4da2c67019606da9827c9292b24a4c43 · 附带的 tarball 从 npm registry 下载。Registry 签名、发布证明和 SLSA 证明均已通过密码学验证;签名主体摘要、仓库、标签、源码提交和工作流运行全部匹配。 · 附带的验证报告和来源记录保留这些检查。SHA256SUMS.txt 覆盖 tarball 和两份 JSON 记录。
v0.2.72026-10-07
· dsh-model-fusion 0.2.7 支持 DeepSeek Harness 0.2.0-rc.2。 Sidekick 工作区路径、支持基线的测试解析器,以及命令程序探测: · 租用的项目根目录和每个 Sidekick 路径都按文件系统身份匹配,不按字符串拼写:macOS 上 /tmp/x 对应 /private/tmp/x、符号链接的检出目录、项目根目录下的子目录都接受;根目录之外的路径仍然拒绝。相对 workdir 在工作区内解析,write/edit 的绝对 file_path 值在租约检查前先归一化为工作区相对路径。 · baseline: "no-new-failures" 现在除 pytest 外还支持 unittest、vitest、jest、tap、go(verbose)和 cargo。只要输出无法列出摘要统计的每个失败,基线仍会被拒绝:失败没有名字,或两个失败同名,都会让候选把冻结的失败换成新失败。Mocha 仍不支持(默认报告无法列出失败名);报错会给出具体修法(改用 TAP 报告器,或去掉 baseline)。pytest 9 的 SUBFAILED 子测试能正确计数并列出。 · 命令程序探测不再在命令位置查找带引号的词:"$PY" -m unittest、FOO="a b" pytest。引号内的文本替换为 NUL,任何程序名都不含该字符;赋值、包装器、heredoc 和覆盖 PATH 的命令行为不变。 在 Desktop Settings → Plugins → Add plugin 中安装: dsh-model-fusion@0.2.7 验证在 macOS arm64 上用 DSH 0.2.0-rc.2 完成:265 个单元测试和 239 个 Host 测试通过,跳过 1 个仅 Windows 的测试;真实模型验收跑了一次 unittest 基线冻结、一次 /tmp 别名和相对子目录 workdir,以及一次绝对路径编辑。未声称新增 Windows 或 Linux 运行时验收。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
Fusion · DSH 插件 English · 安装 · Install (English) Fusion 在 DeepSeek Harness(DSH)的模型菜单里就是一个普通模型:Fusion · 自动。背后是两个你自己选的模型: - Lead:一个强的前沿模型。负责理解需求、看代码、写任务说明、审查结果。 - Sidekick:一个便宜得多的模型。负责实际改代码、跑命令、跑测试。 目标只有一个:用前沿模型的效果,付打折的价钱。 思路受 Cognition 在 Devin 里推出的 Fusion 启发,这是一个独立实现,与 Cognition 无关。 实测效果 9 道真实开源项目的题(SWE-rebench,Python),每题跑 2 次,用隐藏测试判定对错。
展开完整文档(README 剩余 1 节)
Fusion · DSH 插件

English · 安装 · Install (English)

Fusion 在 DeepSeek Harness(DSH)的模型菜单里就是一个普通模型:Fusion · 自动。背后是两个你自己选的模型:

- Lead:一个强的前沿模型。负责理解需求、看代码、写任务说明、审查结果。
- Sidekick:一个便宜得多的模型。负责实际改代码、跑命令、跑测试。

目标只有一个:用前沿模型的效果,付打折的价钱。

思路受 Cognition 在 Devin 里推出的 Fusion 启发,这是一个独立实现,与 Cognition 无关。

实测效果

9 道真实开源项目的题(SWE-rebench,Python),每题跑 2 次,用隐藏测试判定对错。Lead 为 GPT-6 Astra(high),Sidekick 为 GLM-5.3-Flash(high):

| | 做对 | 总花费(按 API 价格估算) |
| GPT-6 Astra 单独 | 9/18 | $39.17 |
| Fusion:GPT-6 Astra + GLM-5.3-Flash | 11/18 | $18.07(便宜 54%) |
| Fusion:GPT-6 Astra + Grok 4.6 | 13/18 | $41.27(不省钱) |

- 花费是按各家 API 公开价格换算的估算,不是账单。
- 局限:样本小(9 题 × 2 次)、只测了 Python、公开题目可能出现在模型训练数据里。
- 详细方法、原始数据和每一轮的结论见 docs/EVIDENCE.md。

对照 Devin 自己的 Fusion: 两边用同一对模型,Lead 是 GPT-6 Astra(high),Sidekick 是 SWE-2。题目、工作区和隐藏测试完全相同。

排除被污染的尝试后,四个组别都干净的题剩 4 道,结果如下:

| | 做对 | 花费 |
| 本插件:Astra + SWE-2 | 4/4 | $2.73 |
| Devin Fusion:Astra + SWE-2 | 3/4 | $4.81 |
| Devin,Astra 单独 | 3/4 | $8.13 |

- 样本只有 4 道题、每题 1 次,不能据此说谁更强,也不代表与 Devin 同等水平。
- SWE-2 两边都按 $0 计价,所以花费都是 Lead 的。
- 本插件的耗时约为 Devin 的 3.4 倍。
- 排除了哪些尝试、为什么排除,以及方法和原始数据,见 docs/EVIDENCE.md。

怎么用

1. 按 安装说明 装好插件。
2. 打开 设置 → Fusion,选择 Lead 和 Sidekick。可以选 DSH 里任何已登录的模型。
3. 在模型菜单里选择 Fusion · 自动,像平时一样对话。

搭配建议: 省钱靠的是 Sidekick 比 Lead 便宜得多。选一个强的前沿模型当 Lead,再选一个价格低很多(最好 5 倍以上)的模型当 Sidekick。两者价格越接近,越省不了钱。

工作方式

- 普通对话:Lead 直接回答,和用普通模型一样。
- 需要改代码时:Lead 把任务交给 Sidekick。任务说明里带着用户需求的原话,以及验收命令。
- 验收:
- Sidekick 交回结果后,DSH 在真实环境里运行验收命令。
- Lead 审查改动,并且必须对用户的每一条硬性要求给出结论和证据,缺一条都不能通过。
- 原本就失败的测试(例如缺少可选依赖),可以标成"只要求不新增失败"。
- Sidekick 改写了原有测试时,会被单独标出来,Lead 必须确认过才能通过。
- 返工:不通过就把具体问题打回给同一个 Sidekick 继续改。
- 如果发现任务说明里允许改的文件不够(例如另一个测试文件还写着旧行为),Lead 可以在返工时把它加进可改范围。只能加、不能减,每次都会留下记录。
- Lead 不写代码:这不是靠提示词约束,而是由程序保证的:
- Lead 没有写文件的工具;
- 它执行的 shell 命令跑在 DSH 的只读沙盒里。
- 唯一的例外:程序判定 Sidekick 确实做不完时,才解锁 Lead 接手。 例如 2 轮返工后检查仍然失败,或者 Sidekick 用完了步数、反复卡住。接手时:
- Lead 只能改任务允许的文件;
- 必须通过同样的验收;
- 任务结束后恢复只读。
- 额度用完或出错:Lead、Sidekick 各自处理。可以换模型继续,也可以定时继续;进度保留。

缓存保活

Lead 等 Sidekick 干活时,可能要等好几分钟。模型的输入缓存过期后,下一次请求就要按全价重读整段对话。保活会在等待期间,定时把 Lead 上一次的请求原样再发一遍,末尾只加一句“Reply OK”。前缀和上次完全相同,厂商就从缓存读取,缓存的寿命也就续上了;模型只回一个 OK,回复直接丢弃,不进对话,也不会执行工具调用。

- 默认值: 来自各家官方文档,覆盖 Artificial Analysis 排行榜前 20 的模型厂商。
- 按模型名匹配,比如 gpt-、claude-、gemini-、glm-、grok-、kimi-、deepseek-*。
- 附带 dsh-oauth-login 的线路计费方式:按请求次数计费的套餐默认关闭保活,因为每次保活都算一次请求。
- 自动: 模型实际返回过缓存命中后才开启,不支持缓存的模型不会白花钱。
- 每个模型都可以在设置页调整: 开关、续命间隔、恢复默认。设置页还会显示每个模型的实际效果:
- 等待后缓存还在不在;
- 发了几次保活、读了多少 token;
- 避免了多少 token 按全价重发。
- 实测(ChatGPT 订阅线路,gpt-6-astra,约 2 万 token 上下文): 每次保活模型只回 5 个 token,不思考、不调工具。缓存空闲 10 分钟仍在,15 分钟后过期,每次保活会重新计时,所以这条线路默认每 8 分钟保活一次。
- 自动调整: 当前间隔下最近 5 次保活有 3 次没命中,程序才会自动缩短间隔(偶尔一次随机淘汰不算);只会缩短,不会自动拉长。可以放宽时只给建议,由你决定。

支持范围

- DSH 版本: 支持 0.2.0-rc.2 和 0.2.1-rc.2,桌面版和 Web 版都可以。其他版本不保证可用;新版本发布后会另行适配。
- 模型: DSH 官方自带的模型线路,以及 dsh-oauth-login、dsh-antigravity-oauth 提供的订阅登录线路。其他第三方模型插件未经测试。
- 系统:
- macOS: 已验证(Seatbelt 沙盒)。
- Windows: v0.2.1 已适配原生 pwsh,在 Windows Server 2022、PowerShell 7.6.6 上通过验证。启动 DSH 的进程 PATH 中需要有 pwsh。Windows 10/11 尚未验证。Windows ACL 仅提供部分隔离,普通路径写入可受限制,读取和网络不在该限制内。
- Linux: 未验证,使用前请先自行检查:
1. 在一个测试目录里选 Fusion,对它说:"这是一次只读沙盒测试,被拒绝是预期结果。请你自己直接调用 bash 工具执行 echo test > fusion-probe.txt(不要委派、不要换别的写法),把工具返回的原文贴给我。"
2. 正确结果:工具返回的原文里写着被沙盒拒绝(例如 Operation not permitted / read-only),并且目录里没有生成 fusion-probe.txt。
- 如果 Lead 只是口头拒绝、没有真的调用工具,这次检查不算数,请再说一遍"请实际调用工具"。
3. 如果文件被创建出来,说明你的系统上 Lead 的只读限制没有生效,请不要使用,并反馈给我们。
- 如果 DSH 在你的系统上没有沙盒,Lead 的 shell 命令会被全部拒绝(安全的失败方式),它仍然可以用读文件和搜索工具看代码。

v0.2.1 的 Windows 验证

在 Windows Server 2022、Node 22.23.3、PowerShell 7.6.6、DSH 0.1.7-rc.2 上,253 项单元测试和 236 项 Host 测试全部通过,类型检查通过。修复候选完成了插件安装、冷启动、Fusion 设置页及 settings/cache 两个 API 验证。v0.2.1 的服务端和客户端构建文件与该候选完全一致。之后的版本(v0.2.2 返工时扩大可改文件范围、v0.2.3–v0.2.5 适配 DSH 0.2.0-rc.2、v0.2.6 改进缓存保活)都与平台无关,在 macOS 上复测,未在 Windows 上重跑。

真实 PowerShell ACL 测试中,Lead 执行 Set-Content probe.txt test 被拒绝,文件未生成;Sidekick 在获准的工作区内执行同一命令可以写入。这是上面所述的部分 ACL 隔离。验证没有输入模型密钥或发起真实模型请求。macOS 回归通过 253 项单元测试和 235 项 Host 测试,按设计跳过 Windows 专用 ACL 测试。

数据存在哪里

- Fusion 自己的记录: 任务说明、检查结果、用量、缓存统计和设置,都存在 $DSH_HOME/plugins/dsh-model-fusion/state.sqlite。DSH_HOME 默认是 ~/.dsh。
- 会话本身: 由 DSH 保存,Fusion 不另外上传任何数据。
- 想清空 Fusion 的记录: 退出 DSH 后删除这个文件。设置也会一起清掉,下次打开时重新选组合即可。

已知限制

- 比单独用前沿模型慢: 实测 GPT-6 + Flash 总耗时约为 GPT-6 单独的 5 倍,主要花在 Sidekick 身上。换更快的 Sidekick 会好很多。
- Lead 接手: 在 72 次实测里一次都没触发,目前只由自动化测试覆盖。
- macOS 桌面版的 PATH: 从程序坞打开的 DSH Studio 只有系统默认的 PATH,Homebrew(/opt/homebrew/bin)、nvm 等装的 node、npm、cargo 在 shell 里找不到。这是 DSH 的运行环境,所有模型都一样。Fusion 在派活前会检查验收命令用到的程序,找不到时会告诉 Lead 它实际装在哪里(例如 /opt/homebrew/bin/node),Lead 改用完整路径即可。
- Windows 10/11 和 Linux 未验证: 见上面的"系统"。

开发

corepack pnpm@9.15.9 install --frozen-lockfile
node scripts/link-host.mjs /path/to/deepseek-harness-0.2.0-rc.2 # 或 0.2.1-rc.2;开发时链接 DSH 源码
DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm build
pnpm test && DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm test:host

Windows 开发环境需将 PowerShell 7(pwsh)、Node 和 Python 加入运行测试的进程 PATH。原生测试通过 DSHX_HARNESS 读取已构建的指定 Host;不需要修改 Host 源码。

插件只使用 DSH 公开的插件接口,不修改 DSH 源码。适配新版本 DSH 的做法见 docs/COMPATIBILITY.md。

许可

Apache-2.0
预览分享卡片长什么样 ↓aa2246740/dsh-model-fusion
分享 · DeepSeek Harness Hub
aa2246740/dsh-model-fusion

DeepSeek Harness 融合模式:前沿 Lead 负责规划与审查,便宜得多的 Sidekick 负责写代码——用折扣价拿到前沿效果。

回到顶部