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

可视化编排画布 taltara/mddl-harness

DeepSeek Harness
taltara65 天前有提交已提供中文文档扫描:含敏感能力

拖拽模型与工具连线,导出可用的补丁覆盖文件

29/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

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

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add taltara/mddl-harness
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · vision
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 65 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

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

✗npm 包mddl-harness(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.19.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/23 11:36:13

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

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

读写/删除本地文件写入剪贴板(不计风险)
查看扫描证据(共 87 处,展示前 62 条)
  • 写入剪贴板
    apps/studio/src/lib/downloadText.ts:12
    await navigator.clipboard.writeText(text)
  • 读取本地文件
    packages/blueprint/src/index.ts:217
    return await readFile(path, 'utf8')
  • 读取本地文件
    packages/blueprint/src/index.ts:237
    names = await readdir(dir)
  • 读取本地文件
    packages/blueprint/src/index.ts:245
    const info = await stat(join(dir, name))
  • 写入本地文件
    packages/blueprint/src/index.ts:259
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    packages/blueprint/src/index.ts:261
    await copyFile(path, file).catch(() => undefined)
  • 读取本地文件
    packages/blueprint/src/index.ts:262
    const kept = (await readdir(dir)).sort()
  • 删除本地文件
    packages/blueprint/src/index.ts:264
    await unlink(join(dir, stale)).catch(() => undefined)
  • 写入本地文件
    packages/blueprint/src/index.ts:285
    await writeFile(temp, next, { encoding: 'utf8', mode: 0o600, flag: 'wx' })
  • 写入本地文件
    packages/blueprint/src/index.ts:286
    await rename(temp, path)
  • 读取本地文件
    packages/blueprint/src/index.ts:494
    const snapshot = await readFile(file, 'utf8')
  • 写入本地文件
    packages/blueprint/src/index.ts:540
    await mkdir(dir, { recursive: true })
  • 写入本地文件
    packages/blueprint/src/index.ts:541
    await writeFile(composition, compileGraphToPreset(graph), 'utf8')
  • 删除本地文件递归
    packages/blueprint/src/index.ts:555
    await rm(dir, { recursive: true, force: true })
  • 写入本地文件
    packages/blueprint/src/reviewRows.test.ts:12
    mkdirSync(pkgDir, { recursive: true })
  • 写入本地文件
    packages/blueprint/src/reviewRows.test.ts:13
    writeFileSync(join(pkgDir, 'package.json'), JSON.stringify({ name }))
  • 写入本地文件
    packages/blueprint/src/reviewRows.test.ts:14
    if (manifest !== null) writeFileSync(join(pkgDir, 'CAP.md'), manifest)
  • 读取本地文件
    packages/compiler/src/example.test.ts:15
    expect(readFileSync(exampleFile, 'utf8')).toEqual(
  • 读取本地文件
    packages/overlay-check/lib/index.js:217
    await access(join(dir, "node_modules", name, "package.json"));
  • 读取本地文件
    packages/overlay-check/lib/index.js:321
    return await realpath(current);
  • 读取本地文件
    packages/overlay-check/lib/index.js:342
    return await readFile(path);
  • 写入本地文件
    packages/overlay-check/lib/index.js:381
    await mkdir(snapDir, { recursive: true });
  • 写入本地文件
    packages/overlay-check/lib/index.js:385
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    packages/overlay-check/lib/index.js:386
    await writeFile(target, content);
  • 写入本地文件
    packages/overlay-check/lib/index.js:388
    await writeFile(join(snapDir, MANIFEST), `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
  • 读取本地文件
    packages/overlay-check/lib/index.js:395
    ids = await readdir(store.dir);
  • 读取本地文件
    packages/overlay-check/lib/index.js:401
    const raw = await readFile(join(store.dir, id, MANIFEST), "utf8");
  • 删除本地文件
    packages/overlay-check/lib/index.js:435
    await rm(livePath, { force: true });
  • 读取本地文件
    packages/overlay-check/lib/index.js:439
    const saved = await readFile(join(store.dir, manifest.id, "files", entry.path));
  • 写入本地文件
    packages/overlay-check/lib/index.js:440
    await mkdir(dirname(livePath), { recursive: true });
  • 写入本地文件
    packages/overlay-check/lib/index.js:442
    await writeFile(temp, saved, { flag: "wx" });
  • 删除本地文件
    packages/overlay-check/lib/index.js:468
    for (const manifest of stale) await rm(join(store.dir, manifest.id), {
  • 写入本地文件
    packages/overlay-check/src/preflight.test.ts:17
    await mkdir(installed, { recursive: true })
  • 写入本地文件
    packages/overlay-check/src/preflight.test.ts:18
    await writeFile(join(installed, 'package.json'), '{"name":"@scope/present"}')
  • 读取本地文件
    packages/overlay-check/src/preflight.ts:65
    await access(join(dir, 'node_modules', name, 'package.json'))
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:30
    await writeFile(
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:37
    await writeFile(join(root, 'pnpm-lock.yaml'), 'lockfileVersion: 9\n')
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:38
    await writeFile(
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:46
    await writeFile(
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:54
    await writeFile(
  • 写入本地文件
    packages/overlay-check/src/snapshot.test.ts:58
    await writeFile(
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:74
    const before = await readFile(join(root, 'package.json'), 'utf8')
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:76
    expect(await readFile(join(root, 'package.json'), 'utf8')).toBe(before)
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:111
    originals.set(file, await readFile(join(root, file), 'utf8'))
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:120
    expect(await readFile(join(root, file), 'utf8')).toBe(originals.get(file))
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:136
    readFile(join(root, 'created-by-install.yml'), 'utf8'),
  • 读取本地文件
    packages/overlay-check/src/snapshot.test.ts:145
    const failedManifest = await readFile(join(root, 'package.json'), 'utf8')
  • 删除本地文件
    packages/overlay-check/src/snapshot.test.ts:199
    await rm(join(root, 'cordis.patch.yml'))
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:85
    return await realpath(current)
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:121
    return await readFile(path)
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:170
    await mkdir(snapDir, { recursive: true })
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:176
    await mkdir(dirname(target), { recursive: true })
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:177
    await writeFile(target, content)
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:179
    await writeFile(
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:193
    ids = await readdir(store.dir)
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:200
    const raw = await readFile(join(store.dir, id, MANIFEST), 'utf8')
  • 删除本地文件
    packages/overlay-check/src/snapshot.ts:264
    await rm(livePath, { force: true })
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:268
    const saved = await readFile(
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:271
    await mkdir(dirname(livePath), { recursive: true })
  • 写入本地文件
    packages/overlay-check/src/snapshot.ts:276
    await writeFile(temp, saved, { flag: 'wx' })
  • 删除本地文件递归
    packages/overlay-check/src/snapshot.ts:316
    await rm(join(store.dir, manifest.id), { recursive: true, force: true })
  • 读取本地文件
    packages/overlay-check/src/snapshot.ts:332
    const info = await stat(join(store.dir, manifest.id, 'files', entry.path))
扫描于 2026/11/2(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 拖拽模型与工具连线
  • 导出补丁覆盖文件

DeepSeek Harness 可视化编排器——把模型和工具拖到画布上,导出真正的 cordis.patch.yml 覆盖层。

README

由 DeepSeek 最新模型翻译生成
mddl harness DeepSeek Harness 的可视化编排器。将模型和工具拖到画布上,然后导出一个真实的 cordis.patch.yml 覆盖文件。 这不是 dsh 的分支,也不是围绕 npx @deepseek-ai/dsh 的子进程封装。上游已经提供了 web profile、Cordis 补丁和 session/event 遥测。我们将图编译成那种覆盖格式,以便这些工作日后可以作为 dsh-plugin 挂载。 工作室:Bash、DeepSeek V4 Flash、Web Search 和 Filesystem 接入一个 agent 循环,检查器显示 agent-default-model 行 将模型和工具拖到画布上,将它们接入 agent 循环,然后导出覆盖文件。pnpm dev 会在 打开它。 为什么选择这套技术栈 | PDF 方案 | 我们实际的做法 | | Next.js App Router | Vite + React SPA。DSH 提供静态 dist;RSC 是累赘。
展开完整文档(README 剩余 1 节)
mddl harness

DeepSeek Harness 的可视化编排器。将模型和工具拖到画布上,然后导出一个真实的 cordis.patch.yml 覆盖文件。

这不是 dsh 的分支,也不是围绕 npx @deepseek-ai/dsh 的子进程封装。上游已经提供了 web profile、Cordis 补丁和 session/event 遥测。我们将图编译成那种覆盖格式,以便这些工作日后可以作为 dsh-plugin 挂载。

工作室:Bash、DeepSeek V4 Flash、Web Search 和 Filesystem 接入一个 agent 循环,检查器显示 agent-default-model 行

将模型和工具拖到画布上,将它们接入 agent 循环,然后导出覆盖文件。pnpm dev 会在 打开它。

为什么选择这套技术栈

| PDF 方案 | 我们实际的做法 |
| Next.js App Router | Vite + React SPA。DSH 提供静态 dist;RSC 是累赘。 |
| 虚构的 dsh.yaml | cordis.patch.yml(id 替换 + insert) |
| 通过 Socket.io 启动 dsh run | 后续:监听 session/event / agent/* 的 Cordis 插件 |
| 配置放在展开的节点内 | 哑节点 + 检查器(让 XYFlow 保持 60fps) |
| 节点内嵌 xterm.js | 仅停靠式预览。终端属于后续的宿主插件。 |

包

- @mddl/graph-schema — 图 IR 以及随附的 DSH 行目录
- @mddl/compiler — 图 → Cordis 补丁 YAML,外加覆盖文件 lint
- @mddl/studio — 可视化编辑器
- dsh-blueprint — DSH web 客户端内的 Blueprint 标签页(readme)
- dsh-overlay-check — 独立的覆盖文件安全检查,无依赖,适用于任何写入配置的场景(readme)

运行

pnpm install
pnpm dev

工作室:http://localhost:5173

pnpm lint # biome check
pnpm format # biome check --write
pnpm test
pnpm typecheck

CI 在每次推送时运行 lint、typecheck、test 和 build。

画布在你编辑时会保存到 localStorage,因此重新加载会保留你的图。
标题栏中的 Reset 会恢复初始图。

在面板中按名称、行 id、包或描述查找模块。按 / 跳转到搜索,Not on canvas 会隐藏你已经放置的内容。

应用导出的覆盖文件。--patch 是从你的终端 cwd 解析的,而不是工作室。从 ~ 运行 ./cordis.patch.yml 会查找 /Users//cordis.patch.yml。

在 Export 之后(典型的 macOS 下载):

npx @deepseek-ai/dsh web --patch "$HOME/Downloads/cordis.patch.yml"

或者使用本仓库中的初始覆盖文件(从仓库根目录):

npx @deepseek-ai/dsh web --patch "$PWD/examples/cordis.patch.yml"

第一阶段不做什么

实时 harness 执行、profile 安装或 DSH 客户端槽位。“Preview telemetry” 是一个本地动画,用于验证发光/边路径。真实的运行状态来自后续阶段的 session/event。

能力披露在写入 overlay 行之前,预检会报告每个被插入的包声明它可能做什么,如果该包附带 capmark 清单,则使用该清单:

warning capability-high-risk "build-helper" declares fs:read, proc:spawn.
proc:spawn hands over broad control — read its manifest before applying.

这是运行时门控无法做出的唯一决定。插件的 apply() 在其行加载的那一刻就以完整的 Node 权限在进程内运行,此时任何工具调用都还不存在,因此写入是安装它仍然是一个选择的最后时机。它只报告,从不阻止:如今几乎没有插件带有清单,拒绝它们会使这项检查对真实配置毫无用处。

dsh-overlay-check 保持零依赖;这部分位于 dsh-blueprint 中。

路线图

已在 dsh-blueprint 0.5.0 中发布:读取实时加载器树、对实际启动的配置进行 lint、将 overlay 写回标记分隔块之后、拒绝写入会导致 harness 无法启动的行、带一键恢复的快照、将运行中的配置导入画布,以及编译为 agent 预设,使画布更改会话实际获得的内容。接下来,按顺序:

1. 将 session/event 映射到画布遥测,取代本地动画。
2. 英文和中文同等优先。
3. 超越已发布的 DeepSeek 适配器的模型行。

如果 harness 无法启动

一行指定了配置无法加载的包会直接导致 harness 无法启动,而不是禁用某个条目。dsh-blueprint 拒绝写入这样的行,但如果你通过其他途径到达这一步,有两件事会有帮助:

- dsh --profile --dump-default-config 在跳过配置和主目录用户层的同时读取 bundle,因此当问题出在 overlay 上时它仍能给出答案。已在 rc.7 上确认:写入配置的 cordis.patch.yml 中的一行会出现在 --dump-config 中,而在 --dump-default-config 中缺失。
- sandbaseai 团队的 DSH 手册的恢复运行手册 是关于如何从中恢复的最详尽论述,包括哪个用户层拥有哪个文件。

状态

早期阶段。DSH 本身是一个开发者预览版,在发布候选版本之间存在破坏性变更,因此这里的行 id 和补丁形态都在追随一个移动的目标。已针对 @deepseek-ai/dsh 0.1.0-rc.7 和 0.1.1-rc.2 验证。

0.1.1-rc.2 未修复的一件事:在 overlay 中设置的 agent-presets.roots 会在启动时被替换为已发布的根,而 --dump-config 仍会打印你的值,因为覆盖是在它所打印的组合之后应用的。参见 deepseek-harness#403。dsh-overlay-check 会对此发出警告,而不是让 overlay 静默地声称拥有它。

许可证

MIT。参见 LICENSE。
预览分享卡片长什么样 ↓taltara/mddl-harness
分享 · DeepSeek Harness Hub
taltara/mddl-harness

拖拽模型与工具连线,导出可用的补丁覆盖文件

这是你的仓库?认领条目

回到顶部