deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
DeepSeek Harness(DSH)插件:一个插件包、多个小工具。当前包含:
- 任务 1 · 编辑消息——在用户消息的复制按钮旁新增「编辑」按钮,把误发送的未完成消息 在原消息位置覆盖一条与官方输入框同款的内联编辑卡继续编辑,编辑后作为一条新消息正常发送;
- 任务 2 · web_fetch 内网放行(web-fetch-policy)——给官方
web_fetch换一个带 「内网放行开关」的 fetch provider:默认与官方完全一致(只允许公网目标),在 设置 → 插件配置 打开开关后放行解析到私网/回环等内网地址的目标(TUN / 代理用户 的 DNS 常回 fake-ip/内网地址,不开会全部被拒);- 任务 3 · 提醒通知(turn-notify)——agent 回合完成、弹出提问或需要审批时, 页面不在前台则弹浏览器系统通知(标题带场景前缀,需先授权一次);开关在 cajita 设置卡里。
npm:@hpyperry/dsh-cajita · 仓库:https://github.com/hpyperry/dsh-cajita
安装(推荐锁版本):
dsh plugin --profile web add @hpyperry/dsh-cajita@0.1.5
| 工具 | 能力 | 说明 |
|---|---|---|
| 📝 | 编辑消息 | 用户消息复制按钮旁新增「编辑」:内联覆盖编辑卡带出原消息文本,继续编写后发送新消息(与正常发送完全同管线) |
| 🌐 | web_fetch 内网放行 | 为官方 web_fetch 换上带开关的 provider:默认与官方一致(仅公网);设置里打开开关后放行私网/回环/内网目标(TUN / 代理用户必开) |
| 🔔 | 提醒通知 | agent 回合完成 / 提问等待回答 / 需要审批时(页面不在前台)弹浏览器系统通知,标题带场景前缀;可开关 + 授权按钮,默认开 |
插件已发布到 npm(@hpyperry/dsh-cajita),直接按包名安装即可:
包名
@hpyperry/dsh-cajita是 npm 安装/卸载身份;插件注册进 dsh 的 layer id 为cajita(不带dsh-前缀,与 ref-lib 同模式:@hpyperry/dsh-ref-lib↔ layer idref-lib)。
# 从 npm 安装(推荐锁版本)
dsh plugin --profile web add @hpyperry/dsh-cajita@0.1.5
# 或装最新标签
dsh plugin --profile web add @hpyperry/dsh-cajita@latest
npm 包自带构建产物(lib/),无需源码构建/授权;想要最新开发版或未发布改动时, 可用本地 link 形态安装源码目录(见下)。
升级插件的小坑:pnpm 在“已装版本仍满足当前声明范围”(如声明 ^0.1.4、新出
0.1.5)时,add <包>@latest 会被判定为无需改动(no-op)。要真正升级请显式指定
新版本(…add @hpyperry/dsh-cajita@0.1.5),或在 profile 里跑
pnpm update @hpyperry/dsh-cajita --latest。
安装后重启生效:dsh --profile web。
dsh plugin --profile web add /path/to/dsh-cajitadsh plugin --profile web remove @hpyperry/dsh-cajitacd /path/to/dsh-cajita
# 升版本(npm version patch 等)→ 构建并发布
npm publish # prepare 自动跑 tsc + tsdown 产出 lib/
scoped 公开包所需配置(publishConfig.access: public)已在 package.json 内;
发布前请确认 npm whoami 已登录(账号需与 @hpyperry scope 一致)。
编辑框为简单文本编辑(与 ChatGPT 一致,不含
/命令与@引用补全——官方 未提供第三方输入框的可插拔补全 API;需要完整/@能力时,可把编辑文本setDraft进主输入框继续编辑,见下「边界」)。
| 边界 | 处理 |
|---|---|
| 长文本(几万字) | 内联编辑框文本域是纯本地 state,不进输入机器、不跑装饰扫描,一次性回填/持续输入无 hang 风险;仅发送那一刻一次性 setDraft(O(n) 对账,毫秒级) |
原消息含 / |
已发送文本是序列化后的文本;重新发送走同一判定:/未知命令 仍按普通消息发送(行为一致);若编辑后以已知命令开头,发送会执行命令——与输入框手动输入完全一致(官方行为),编辑卡内以提示明示 |
原消息含 @ |
@引用 发送时已序列化为模型形态,回填后按字面文本发送(内容与气泡显示一致);编辑框为简单文本,无补全菜单(与 ChatGPT 一致) |
| 输入框已有未发送草稿 | 发送将替换输入框内容(发送成功后被清空),编辑卡内以提示明示 |
| 忙碌/会话移除 | adjudicating/submitting 或会话已移除时禁用发送 |
| UI 规范 | 全部使用官方 primitives 与 --dsw-* 设计令牌,编辑卡视觉与官方输入框一致(同款背景/圆角/阴影/宽度上限) |
插件级设置收成一张与官方插件配置同风格的可展开卡片,三个即写开关
(写 $DSH_HOME/settings.yaml 的 cajita: 节,改完即时生效,无需重启):
官方 web_fetch 只允许访问公网目标:解析结果里出现私网/回环/fake-ip(如 TUN
代理常见的 198.18.0.0/15 或内网 DNS 回包)会整组拒绝。TUN / 代理模式下 DNS 常被
劫持成非公网地址,导致 web_fetch 全部失败。官方没有关闭这项检查的开关。
web_fetch 用法完全不变。| 边界 | 处理 |
|---|---|
| 开关默认值 | 默认关(与官方一致,仅公网);TUN/内网用户到设置里打开一次即持久化 |
| 关闭语义 | 关闭 = 官方等价行为;没有"真卸载式"的运行时开关——彻底回滚官方行为需卸载插件并重启 |
| 装卸 | 卸载插件即恢复官方行为(回滚干净);装卸后需重启 dsh web |
| 设置迁移 | v0.1.2 的 cajita-web-fetch: 节已并入 cajita: 节(v0.1.3);旧节残留无害,可手工删除 |
| 其它 profile | 本插件面向 --profile web;装进没有相关组件的 profile 时开关卡片不展示、无副作用 |
| 设置不可写 | 命名空间未提供 / 宿主只读时卡片整体隐藏或禁用(与官方卡片一致) |
pnpm typecheck # tsc --noEmit
pnpm lint # eslint(typescript-eslint recommended)+ prettier
pnpm test # vitest(L0 纯函数 / L1 装载)
pnpm build # tsc(node half)+ tsdown(client bundle)→ lib/
src/(node half:插件身份 + web-fetch-policy 行)+ src/client/
(web half:index.ts 编排「绑定设置 → TOOLS 动态注册 → 注册设置卡片」+
locales.ts 汇总;每个功能独立目录 src/client/<tool>/,自带 register/组件/
纯逻辑/字典片段/样式标签;插件级设置表面在 src/client/settings/)+ tests/
(按功能子目录);cajita 文案/设置命名空间;新功能 =
新目录 + 在 src/client/index.ts 的 TOOLS 注册表登记(见 AGENTS.md §6.2);src/client/* 改动 pnpm build:client 后浏览器 ≤0.5s 自动热更新;
node half 改动需重启 dsh web。所有开发/联调一律在独立 DSH_HOME(默认 ~/.dsh-dev)进行,真实 ~/.dsh
零接触(2026-08-17 事故教训:直接在真实 profile 联调可能污染真实会话日志);
rm -rf ~/.dsh-dev 即完全重置。
| 命令 | 说明 |
|---|---|
./scripts/dev-isolate.sh |
首次运行自动把本插件装入隔离 profile(默认 ~/.dsh-dev)并启动 web |
DEV_HOME=/tmp/dsh-dev ./scripts/dev-isolate.sh |
自定义隔离 home |
PLUGIN=/path/to/other-plugin ./scripts/dev-isolate.sh |
隔离其他插件 |
DEV_HOME=/tmp/dsh-dev ./scripts/dev-isolate.sh --port 3090 |
透传任意 dsh 参数(如 --port) |
DSH_BIN=<绝对路径> ./scripts/dev-isolate.sh |
用指定版本的 dsh 可执行文件启动(多版本矩阵,见下) |
DSH_HOME=$HOME/.dsh-dev dsh plugin --profile web add <插件路径> |
手动安装/重装插件(本地路径 = link 开发形态) |
DSH_HOME=$HOME/.dsh-dev dsh --profile web --port 3090 --no-open |
手动启动隔离 web(--port 指定端口,--no-open 不自动开浏览器) |
DSH_HOME=$HOME/.dsh-dev dsh plugin --profile web remove @hpyperry/dsh-cajita |
卸载插件 |
rm -rf $HOME/.dsh-dev |
完全重置开发环境 |
插件的依赖基线需要与宿主 dsh 版本族配对。默认 dev-isolate.sh 用 PATH 上的全局
dsh;要验证「本插件实现在 dsh 0.1.2-rc.1(当前 latest/next)上是否兼容」,
用 scripts/dsh-local.sh 取一个版本化本地安装(装进 ~/.dsh-tools/<版本>/,
与 npm 全局安装完全无关),再经 DSH_BIN 指给隔离环境:
# 例:在隔离环境用 dsh 0.1.2-rc.1 验证本插件(首次自动安装该版本 CLI)
DSH_BIN="$(DSH_VERSION=0.1.2-rc.1 ./scripts/dsh-local.sh)" \
DEV_HOME="$HOME/.dsh-dev-rc1" \
./scripts/dev-isolate.sh --port 3091
宿主 @deepseek-ai/dsh 的 npm dist-tag latest/next 均已是 0.1.2-rc.1:
任何无 pin 的全局安装都会升级生产宿主,安装脚本/验证一律显式 pin 版本;
不同版本用独立 DEV_HOME(如 ~/.dsh-dev-rc1)与 profile,互不干扰;
依赖基线升级的破坏面/迁移结论记录在 docs/upgrade-dsh-*.md。
提示:若全局 npm 缓存目录(~/.npm)存在 root 属主文件导致 npm install 报
EPERM,可先 npm cache verify 修复,或为 dsh-local.sh 指定可写的
npm_config_cache 环境变量。
常用端口:--port 3090,浏览器访问 http://127.0.0.1:3090;
验证加载:启动日志(stdout)会列出装载的插件与 client bundle;也可
curl -s http://127.0.0.1:3090/ | head 确认 web 在服务;client 注册是否生效
以浏览器 UI 为准(编辑按钮出现在用户消息复制按钮旁);
user/steering
气泡渲染器(priority -1,数值最低者渲染)。官方气泡视觉升级时需手动同步(快照结构变化由 typecheck
兜底);同 key 的第三方接管者按 shadow 链数值低者渲染;接管条目随「编辑消息」
开关运行时增删——关闭即 dispose、官方气泡即时恢复;dsh plugin remove 并重启;cajita-web-fetch: 设置节已并入 cajita: 节;
旧节残留无害,可手工从 settings.yaml 删除;http://127.0.0.1 这类本地地址是安全上下文可用,局域网
IP / 0.0.0.0 / 非 https 部署不可用;同 origin 多标签页会各自弹通知(官方无跨
标签协调)。/ 命令与 @ 引用补全(官方未提供第三方输入框
的可插拔补全 API;官方输入框的补全落地硬接线到 composer 机器)。需要完整 / @
能力时,可把编辑文本 setDraft 进主输入框继续编辑后发送;MIT,与 DeepSeek Harness 一致。
AGENTS.mdCLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。