npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ding-harness

v0.6.0

Published

Ding Harness 的命令行宿主:本机优先的桌面 Agent 工作台(同一内核、同一套闸门)

Readme

Ding Harness

CI

AI 工作台 + 无限画布 —— 一个本机优先的桌面 Agent 工作台

A local-first desktop agent workbench: AI workspace + infinite canvas.

English: README.en.md

Ding Harness 是一个 Electron 桌面应用,把「对话式 Agent」和「无限画布」放在同一个工作台里。 它本机运行、本机存数据,模型走你自己配置的通道(OpenAI 兼容 / Anthropic / Google 三种协议)——不依赖任何后端服务。

状态:v0.5.1。目前仅提供 Windows 构建。


功能

  • Agent 工具面:文件与命令(list_files / read_file / write_file / list_dir / search_files / edit_file / run_command)、记忆(memory_save / memory_list)、定时任务(schedule_create / schedule_list)、画布(canvas_add_node)、本地知识库(knowledge_search)、浏览器与电脑操作,以及子智能体(spawn_agent / 小队)。权威清单以 shared/agentTools.ts 的注册表为准(这里不写死数量,免得又旧了)。
  • 连接器(MCP):以 stdio 子进程接入 MCP server(最多 8 个),工具以 mcp__<server>__<tool> 暴露给模型。
  • 审批闸门:三档模式(全部允许 / 按需确认 / 每步确认);每个工具按读/写分级,MCP 工具默认按写对待;被拦下的调用可就地允许或拒绝,决策写入会话日志。
  • 子智能体:独立上下文、只回要点报告、token 成本上卷父级;共用同一张闸门表,不穿透审批。
  • 上下文管理:唯一的切分点,只在消息边界切、保留段以 user 开头、最后一条必留;用 provider 返回的真实 usage 校准估算系数。
  • 会话日志:界面状态由事件投影(applyEvent)生成,与日志同源——历史从日志恢复。
  • 工作区授权:经系统对话框授权真实目录(渲染进程无法注入路径),最多 8 个、可随时撤销;文件类工具与 run_command 全部收敛到白名单。
  • 产物:对话里的 <artifact> 会被提取成卡片并落盘;支持真 Office 格式(docx / pptx / xlsx,真 ZIP 容器)。
  • 工作台:任务、检查点、长期记忆、定时任务、技能/插件面板、AI 文档、主题系统;无限画布节点支持 markdown / code / image / whiteboard。

技术栈

Electron 44 · React 19 · zustand · Vite 7 · React Flow v12 · Vercel AI SDK v7 · zod · TypeScript 5.9 · pnpm

五分钟上手

# ① 装(三选一)
#    a. 有 Node:从 npm 装(已发布 [email protected])
npm i -g ding-harness
#    b. 不想装 Node:用单文件可执行(目标机器什么都不用装)
pnpm cli:bin && node scripts/install-cli.mjs --bin
#    c. 从源码装成全局命令
node scripts/install-cli.mjs --link

# ② 配(交互式向导:配 key → 选模型 → 选工作目录,全程四问)
ding init

# ③ 自检(它会告诉你这台机器上缺什么、下一步做什么)
ding doctor

# ④ 跑一句
ding run "把这个目录里的文件列一遍,说清哪个最可能是配置"

装完不放心就先看看它到底会动什么:ding recipe list(内置几个常用模板, ding recipe show <id> 看它要发什么提示词、用哪些工具)。

桌面端:pnpm dev(一条命令同时起 Vite 与 Electron),或者直接跑安装包。 第一次打开会带你走同样的向导。

文档

快速开始

环境要求:Node ≥ 20(实测 v24)、pnpm ≥ 10、Windows。

pnpm install

开发(一条命令:同时起 Vite 与 Electron):

pnpm dev

只想跑其中一半:

pnpm dev:web                      # Vite 开发服务器 → http://localhost:5173
pnpm electron:build && pnpm start # 用已构建产物启动桌面端(会先查产物是否过期)

打包(含 typecheck / lint / test 全门禁):

pnpm build   # → release/ding-harness-<package.json 的 version>-setup.exe

交付前自检(门禁 + 产物新鲜度 + CLI 产物 + 开箱冒烟):

pnpm verify

配置模型

模型走三种协议(OpenAI 兼容 / Anthropic / Google),内置十个 provider:DeepSeek 官方、tokenrhythm / apiKeyFan / API_HUB 中转、通义千问、Anthropic、Google、OpenAI、OpenRouter、strata。 密钥按以下优先级读取:

  1. 环境变量
  2. ~/.dsh/.credentials.yaml

设置页有连通性探测,用来区分「配了密钥」和「密钥真的可用」。

架构

内核 + 双宿主:agent 逻辑住在 engine/,桌面与命令行都只是它的宿主。

engine/                       内核(不 import electron —— 有守卫盯着)
├─ core/       纯逻辑,零 IO、零 Electron —— 可整包单测
│   ├─ events.ts     ★ 事件溯源:state = fold(events);日志即真相
│   ├─ context.ts    上下文规划器(唯一切分 + 用量校准)
│   ├─ policy.ts     审批闸门判定(run / ask / hide)
│   ├─ assembly.ts   系统提示词装配
│   ├─ notices.ts    错误回注三件套(未知工具 / 闸门拦截 / 执行失败,单一来源)
│   ├─ ledger.ts     成本账本(从事件流现算,不另存统计)
│   └─ snapshot.ts   快照:重放 diff(重构零漂移的验收器)
├─ runtime/    编排层
│   ├─ loop.ts       ★ 唯一的主循环(streamText + stepCountIs)
│   ├─ subagent.ts   子智能体(独立上下文、成本上卷、审批穿透)
│   ├─ registry.ts   工具注册表(builtin / MCP / 插件三来源)
│   ├─ providers.ts  provider 表(baseURL 惰性读环境变量)
│   └─ tools/        与宿主无关的文件工具(read/write/edit/exec/search)
├─ ports/      宿主适配接口:store / health / executor
├─ adapters/   SQLite 事件存储(node:sqlite:CLI 与桌面**同一份实现**)
└─ index.ts    createEngine(ports) → { run, resume, replay, record }

hosts/
├─ cli/ding.ts     命令行宿主:run / sessions / record / replay / models
├─ server/         HTTP 宿主(`ding serve`):会话/空间/中继/渠道
└─ mcp/            画布 MCP server:把画布工具族交给**外部 MCP 客户端**(见 hosts/mcp/README.md)

packages/          SDK:engine-core(事件 + 主循环,无 IO)/ engine(完整能力面)
examples/sdk-turn/ 10 分钟跑通一轮的两个示例(完整面 / 最小面)

electron/      桌面宿主:窗口、IPC、各 store(JSON 落盘)、MCP 连接器
               ├─ 会话事件 → engine 的 SQLite 库(userData/sessions.db)
               └─ 启动时把旧 sessions/*.jsonl 一次性迁进来(只读旧、写新、不删旧)
shared/        跨宿主契约:ipc.ts(含档位词表)/ agentTools.ts(工具声明)/ mcp.ts
src/           渲染进程(React 19 + zustand + Vite)

几条刻意的设计约束(写进 code review 口径):

  • 状态 = fold(events):会话、待办、用量全部由事件流折叠得出 —— 可重放、可恢复。
  • 日志即真相:界面是事件流的投影,不是第二个真相。
  • 错误即结果:工具失败 / 未知工具 / 闸门拦截,统一作为 tool result 回注,不中断循环。
  • 单一事实来源:主循环、上下文切分、提示词装配、工具注册、闸门判定各只有一处实现。
  • 不编:拿不到 usage 就留空;不知道模型上下文上限就不硬编。

命令行

ding 是正式的命令行宿主,不是"桌面的附属开关":它跟桌面跑同一个内核、同一套闸门。

pnpm ding                                      # 不给参数 = 进交互模式(上下文接着上一句)
pnpm ding run "把 demo 里的 md 整理成一份纪要" --dir ./demo
pnpm ding sessions [--json|--export <id>]      # 列会话 / 导出 JSONL
pnpm ding sessions --cost [--by session|day|model]   # 成本账本(数字只来自 provider 上报)
pnpm ding models [--json]                      # provider 与模型(逐条标出数据来源与是否过期)
pnpm ding providers list|add|remove …          # 自定义 provider(端点/协议/密钥引用,进 config.json)
pnpm ding schedule add "每天 9 点" --title <名> --prompt <任务>  # 定时任务(与桌面共用 schedules.json)
pnpm ding schedule run-due --every 1           # 常驻执行(关掉终端才停)
pnpm ding im serve [--port 8790]               # 飞书/Slack bot 身份桥(webhook 验签 + 去重 + 回复)
pnpm ding memory export|import --git <目录>    # 记忆镜像到 Git(一条一个 .md,可 diff/可推拉)
pnpm ding workflow run <定义.json>              # 多 agent 工作流(依赖泳道 + 断点续跑)
pnpm ding agents                               # 内置专家(AgentSpec)
pnpm ding eval [类别] [--json] [--repeat <k>]  # 离线评测集(不烧 token;--repeat = pass@k)
pnpm ding eval --update-baseline               # 落一份通过率基线(进版本库)
pnpm ding bench list|run [suite]               # 任务级公开基准(判产物;见 BENCHMARKS.md)
pnpm ding fork <会话 id> [--at-turn N|--at-seq N] [--into <新id>] [--list]  # 从任一时点分叉
pnpm ding worktree start|list|merge|remove <名字>   # git 工作树隔离改动,改完合回主树
pnpm ding knowledge add <文件|目录> [--domain private|team]  # 本地知识库(FTS,带引用)
pnpm ding knowledge search <词> [--limit n]        # 检索并给出「标题 + 路径 + 第几段」
pnpm ding knowledge ask <问题>                     # 真模型 + 引用(会花钱)
pnpm ding doctor [--json]                      # 一键自检(每项失败都给下一步)
pnpm ding init                                 # 首次配置向导(配 key / 选模型 / 选目录)
pnpm ding resume [<会话 id>] [--continue]      # 崩溃恢复(看被打断的回合 / 接着跑完)
pnpm ding sessions --search <词>               # 本地全文检索(FTS + 子串)
pnpm ding backup [--out <文件>]                # 全量备份(会话 + 配置,单个 JSON,不含密钥)
pnpm ding restore <文件> [--list]              # 从备份恢复(只补不覆盖)
pnpm ding recipe list|show|run|export|import   # 任务模板(可分享)
pnpm ding serve [--port 8787]                  # Agent Server(REST + SSE;默认只绑回环)
pnpm ding acp                                  # 作为 ACP agent 跑在 stdio 上(被外部宿主驱动)
pnpm ding acp-drive --cmd <可执行> --prompt "…"  # 反过来:Ding 驱动外部 ACP agent
pnpm ding plugins list|install|enable|disable|remove|doctor
pnpm ding config [show|set <键> <值>|unset <键>] # 默认 provider / 模型 / 档位 / 目录

交互模式里的斜杠命令:/model /mode /provider /agents /sessions /help /exit。

配置与优先级(~/.ding/config.json,也读无扩展名的 ~/.ding/config):

命令行显式参数  >  环境变量(DH_PROVIDER / DH_MODEL / DH_MODE / DH_DIRS)  >  配置文件  >  内置默认

数据目录默认 ~/.ding(DH_DATA_DIR 可覆盖);--dir 可重复给(就是桌面的"工作区授权")。 --json 给脚本/CI 用;--dev 会多出两个工程模式命令(record / replay,验收驱动器)。

装成全局命令:node scripts/install-cli.mjs(默认只构建并打印怎么装;加 --link 才真装)。

当 SDK 用(把引擎嵌进你自己的程序)

npm i ding-engine        # 完整能力面(SQLite + 工具 + 凭据 + 插件)
npm i ding-engine-core   # 最小嵌入面(只有事件 + 主循环,不碰 IO)

十分钟那条路在 examples/sdk-turn/README.md; 它有两个真能跑的示例(完整面走 SQLite、最小面走内存 store),CI 里每次 push 都会 把两个包打成 tarball、装进干净工程、原样跑一遍(pnpm verify:sdk)。

公开面冻结在 packages/api.frozen.json(加名字要补清单、删或改签名要 ADR + major), 版本与发布口径见 RELEASE.md。

开发与验收

pnpm typecheck   # tsc --noEmit
pnpm lint        # oxlint
pnpm test        # vitest(内核测试在 engine/**/*.test.ts,与渲染层共跑一个 node 环境)

scripts/accept/ 下是浏览器端验收脚本,scripts/verify-*.mjs 是产物与打包校验。

pnpm eval            # 离线评测集(63 条,六类;不烧 token)
pnpm perf:budget     # perf-budget 实测(数字落 engine/eval/perf-baseline.md)
pnpm cli:bin         # 编单文件可执行(四个平台;Windows 那个可验)
pnpm sandbox:build   # 编命令沙箱(Rust;零外部依赖)
node scripts/verify-acceptances.mjs   # 免模型验收批跑(68 条)

改完东西请顺手跑一次 pnpm eval:它是"行为有没有变"的最快信号。 pnpm test 的门是任何一条产品失败或装置不可达都红;基线(engine/eval/baseline.json) 另外锁住两件事:用例只增不减,且基线本身必须记的是 100%(拿半绿的运行去 --update-baseline 等于把及格线调低)。

写插件

插件是一个目录(manifest + 入口),能力分两类:tools:register / hooks:register 真的生效, fs:read / fs:write / net / exec 只是声明(v1 拦不住)。 写之前先读 PLUGIN.md(含最小可用示例、四个钩子、装/试/卸与两条易忽略的规矩)。

平台覆盖(如实标注)

CLI 有两种装法,验过的程度不一样 —— 分开说,别混成一句"CLI 跑过":

| 跑法 | 是什么 | 谁在验它 | |---|---|---| | npm 那条路(npm i -g ding-harness → dist-cli/) | 发布包在 packages/cli(pnpm cli:pkg 生成),bin.ding 指向 dist-cli/hosts/cli/ding.js,要目标机器有 Node;包名 ding-harness(@ding 作用域属于别人,发不了;与 2FA 无关) | pnpm cli:build + pnpm cli:pkg:check + node scripts/verify-cli-npm.mjs(在 pnpm build 链里,也在 CI 的 gates 里) | | 单二进制那条路(dist-bin/ding-<平台>) | Bun 编出来的单文件,不需要目标机器装 Node | pnpm cli:release(= cli:bin + verify-cli-bin.mjs),CI 里是独立一个 cli-bin job | | 开发态 | pnpm ding(tsx 直接跑源码) | pnpm test 里的引擎/宿主测试 |

| 平台 | 桌面 | CLI(npm 那条路) | CLI(单二进制) | 命令的资源上限 | 密钥加密存储 | |---|---|---|---|---|---| | Windows x64 | ✅ 打包 + 启动验过(pnpm package:win) | ✅ 验过:--help / sessions / models / doctor / eval 63/63,且与源树逐条对照(node scripts/verify-cli-npm.mjs) | ✅ 编出来且跑过(pnpm cli:release:剥掉 PATH 只剩系统目录再跑,eval 63/63) | ✅ 作业对象(内存 / 子进程数 / 不留孤儿);安装包带着 ding-sandbox.exe(落在 resources/,应用自己找得到) | ✅ 桌面走 DPAPI;CLI 无 | | macOS(x64 / arm64) | ⚠️ 目标配置就位,没在真机上跑过 | ⚠️ 这条路只验过 Windows(纯 Node,理论上哪都一样,但没在 macOS 上执行过) | ⚠️ 编得出来,没跑过 | ⚠️ 没打进去(只有 Windows 那份进了 extraResources) | ⚠️ 桌面可走 Keychain;未验证 | | Linux x64 | ⚠️ 同上(AppImage / deb),桌面版没在 Linux 上跑过 | ⚠️ 同上(没在 Linux 上执行过) | ✅ 跑过:WSL Ubuntu 24.04 里 --help / doctor / eval 63/63(2026-10-16)—— 走的是单二进制那条路 | ⚠️ 同上(没打进去;实现只有 Windows 那份) | ⚠️ 桌面可走 libsecret;未验证 |

这张表就是"我们验过什么"的清单:⚠️ 的那些是能编出来但没在对应系统上执行过, 不是"已支持"。ding doctor 会把当前这台机器上缺的能力逐条列出来。

自动更新未做:它需要代码签名证书与一个更新 feed(见 SAFETY.md 第五节)。 现在装新版本是手动下载安装包。

排错(先跑 ding doctor)

| 现象 | 多半是什么 | 怎么弄 | |---|---|---| | 没有可用的模型凭据 | 还没配 key | ding init,或设环境变量(DEEPSEEK_API_KEY 等) | | 连不上 provider | 网络 / 本地服务没起 | 本地 provider 要先起服务;远程看代理设置 | | 密钥无效或已过期 | key 过期 / 抄漏了 | 重新写一次;ding doctor 的「模型凭据」会告诉你读到几条 | | 工具一律报「不在可写范围内」 | 工作目录没配 / 配的目录不存在 | ding config set dirs <目录>;ding doctor 的「工作目录」那一格会红 | | 界面上按钮点不动 | 旧构建 | 重新 pnpm build:web && pnpm electron:build(验收脚本也会报同一个原因) | | 上次关窗口时它还在跑,现在那个任务躺着 | 回合被打断(正常现象) | ding resume 看有哪些,ding resume <id> --continue 接着跑;桌面上那颗「继续」按钮同理 | | 想找三个月前聊过的内容 | —— | ding sessions --search <词>(检索会话正文,不只是标题) | | 沙箱报「不受限地跑」 | 没编 ding-sandbox | pnpm sandbox:build(需要 Rust);不编也能用,只是命令没有资源上限 |

多机同步与 E2EE

ding serve --port 8787 --token <口令> --member bob:<bob 的口令>   # 中继那一台
ding sync <会话 id> --to http://<中继>:8787 --token <口令> --key <房间密钥>
ding sync <会话 id> --to … --every 60                            # 常驻对账
pnpm e2ee:demo                                                   # 现场演示:中继只见密文

内容类记录(提示词/回复/工具结果)在客户端用 AES-256-GCM 封好再上传; 控制类(审批/接管)明文 —— 零知识与"让云端帮你路由审批"天生不相容(ADR-0014)。 pnpm e2ee:demo 会真起一个服务、真推一段会话、把中继出站数据抓下来,验证 搜不到明文 / 没密钥解不开 / 持钥两端一致。

已知边界

安全边界逐条写在 SAFETY.md(包括"没做的"那一节)—— 这里只列最要紧的:

  • run_command 不是安全边界:Windows 上它有内存与子进程数上限(作业对象), 但命令仍以你的身份运行,能读能写能联网。唯一拦着 rm -rf 的是闸门(你点的那一下)。
  • 插件跑在独立 Worker(G18):死循环/崩溃只毁它自己;读插件目录外、写文件、起子进程 默认拒绝(批准 fs:write 只能写插件目录、批准 exec 才能起子进程); net 仍拦不住(Node 权限模型没有网络那一格)。宿主不支持权限模型时降级为 "只隔离崩溃"并在界面与 ding plugins list 标注 worker。
  • 密钥:桌面端「设置 → 密钥」里填的 key 走 safeStorage(DPAPI / Keychain / libsecret), 拿不到系统加密能力时拒绝写并说清原因(不退化成明文); CLI 向导(ding init)写的是明文 —— 原因是 CLI 没有系统钥匙串入口 (secretsEncrypted() 恒为 false),不是因为"CLI 不落盘";它写的是 ~/.dsh/.credentials.yaml 里 refs: 段自己那一个键(那个文件桌面与 CLI 共用, 别人的键与注释原样保留);mode: 0o600 只在 POSIX 成立,Windows 上没有这层保护。 「旧明文配置一次性迁移并提示」没做(列在 SAFETY.md 第五节)。 备份里不含密钥,而且加密是本机绑定的(换机器解不开,要重填一次)。

连到远端的 agent(Phase 17 的另一半)

ding serve 把 agent 挂到 HTTP 上;ding connect 是客户端:

ding connect 192.168.1.9:8787                                       # 看看那台机器上是谁、什么档位、工作目录
ding connect 192.168.1.9:8787 "把 D:/报表 里那三个 csv 合成一张表"   # 跑一轮,正文边收边打(SSE)
ding connect 192.168.1.9:8787 --sessions                            # 那边的会话列表
ding connect 192.168.1.9:8787 "..." --token <口令>                    # 远端带 token 时(对外绑定必然要)

退出码跟着远端那一轮走(成功 0 / 失败 1),所以它能直接写进脚本。

  • 多平台:见上面那张表 —— 桌面只有 Windows x64 验过;CLI 单二进制多了一个 Linux (WSL Ubuntu 24.04 上真跑过 eval 63/63);npm 那条路(dist-cli)只在 Windows 上执行过; macOS 仍然只有编得出来,没在真机上跑过。
  • 模型目录表只登记了少数模型;未登记的走保守默认并在账本上标「未登记模型」。
  • 旧 JSONL 数据在启动时自动迁移,迁移不删旧文件; 配置型数据从 Phase 12.1 起默认存 SQLite(DSH_STORE_BACKEND=file 可退回文件)。

治理、隐私与支持

| 文件 | 内容 | |---|---| | PRIVACY.md | 默认零遥测:本机存什么、什么时候联网、怎么删 | | SECURITY.md | 漏洞披露(私密渠道)、AI 生成报告政策、已知安全边界 | | GOVERNANCE.md | 谁定什么、ADR 流程、不可协商的四条 | | SUPPORT.md | 去哪问、提问带什么、响应预期 | | AGENTS.md | 给 agent 协作者的项目说明书(架构地图与规矩) | | BENCHMARKS.md | 公开评测/基准成绩、方法论与失败分类 | | CONTRIBUTING.md | 提 PR 的路(四道门、六条规矩) |

许可

Apache-2.0(含明确的专利授权;package.json 的 license 与它是同一件事)