只放我的 DSH 插件——DeepSeek Harness 插件包的 monorepo
30.2/100
综合分
1
GitHub 星标
181
npm 周下载
—/5
用户评分
数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @omdp/dsh-connectornpm 源 · @omdp/dsh-connector 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包@omdp/dsh-connector @ 0.3.8
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 09:40:56
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 19 处,展示前 18 条)
- 读取本地文件index.js:154
text = await readFile(join(resolveHome(), 'settings.yaml.imported'), 'utf8') - 读取本地文件index.js:525
raw = await readFile(path, 'utf8') - 读取本地文件index.js:549
entries = await readdir(root, { withFileTypes: true }) - 写入本地文件index.js:589
await mkdir(dir, { recursive: true }) - 写入本地文件index.js:590
await writeFile(file, serialized, 'utf8') - 删除本地文件递归index.js:596
await rm(join(skillsRoot(), name), { recursive: true, force: true }) - 发起网络请求index.js:616
const res = await fetch(MARKET_BASE + path, { - 发起网络请求index.js:693
const res = await fetch(DOLPHIN_URL, { - 读取本地文件index.js:814
const text = await readFile(patchPath(), 'utf8') - 读取本地文件index.js:962
return existsSync(command) - 执行外部命令固定命令index.js:965
const r = spawnSync('where', [command], { stdio: 'ignore' }) - 执行外部命令固定命令index.js:968
const r = spawnSync('which', [command], { stdio: 'ignore' }) - 读取本地文件index.js:1134
text = await readFile(patchPath(), 'utf8') - 写入本地文件index.js:1187
await mkdir(dirname(patchPath()), { recursive: true }) - 写入本地文件index.js:1192
await writeFile(tmp, next, 'utf8') - 写入本地文件index.js:1193
await rename(tmp, target) - 发起网络请求client.js:119
return fetch('/connector/api' + path, { - 写入剪贴板client.js:147
navigator.clipboard.writeText(text).then(function () { done(true) }, fallback)
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- DSH插件包集合
- monorepo仓库
README
由 DeepSeek 最新模型翻译生成omdp — only my DSH plugins
🌐 语言 / Language: 中文 · English
一个 GitHub 仓库,用 monorepo 的形式收集我全部的 DeepSeek Harness(DSH)插件。每个插件各占一个子目录,都是可以独立安装的 DSH bundle,每次打 v tag 都会发布到 npm。
目录结构
omdp/
├── README.md # this file
├── package.json # root manifest — keeps bare-git installs functional (see below) ├── dsh-connector/ # unified MCP + Skills manager (Web UI settings tab) │ ├── index.js # host half │ ├── client.js # client half (Web UI) │ ├── cordis.patch.yml # bundle activation row │ ├── package.json │ └── README.md ├── dsh-key-fallback/ # multi-key API key pool with automatic rotation │ ├── lib/index.
展开完整文档(README 剩余 1 节)
omdp — only my DSH plugins
🌐 语言 / Language: 中文 · English
一个 GitHub 仓库,用 monorepo 的形式收集我全部的 DeepSeek Harness(DSH)插件。每个插件各占一个子目录,都是可以独立安装的 DSH bundle,每次打 v tag 都会发布到 npm。
目录结构
omdp/
├── README.md # this file
├── package.json # root manifest — keeps bare-git installs functional (see below) ├── dsh-connector/ # unified MCP + Skills manager (Web UI settings tab) │ ├── index.js # host half │ ├── client.js # client half (Web UI) │ ├── cordis.patch.yml # bundle activation row │ ├── package.json │ └── README.md ├── dsh-key-fallback/ # multi-key API key pool with automatic rotation │ ├── lib/index.js # host half (ESM) │ ├── lib/client.js # client half (Web UI settings tab) │ ├── cordis.patch.yml # bundle activation row │ ├── package.json │ └── README.md ├── dsh-archived-sessions/ # archived-session manager (fork of @muwinds, DSH 0.2.0-rc.1 / 0.2.0-rc.2) │ ├── lib/index.js # host half (ESM) │ ├── lib/client.js # client half (Web UI settings tab) │ ├── cordis.patch.yml # bundle activation row │ ├── package.json │ └── README.md ├── archive/ # archived plugins retained for historical reference │ ├── dsh-gitbash-win/ │ ├── resume-stream/ │ ├── key-fallback-/ # dsh-key-fallback version snapshots & design drafts │ ├── dsh-vision-bridge-/ # archived 2026-10-18 (was an active vision plugin) │ └── README.md ├── notes/ # development lessons & notes (三层:notes/<date>/<category>/) ├── docs/ # research notes, compatibility matrix, publish guide └── <future plugins>/ # each its own subdirectory + package.json
插件
@omdp/dsh-connector — MCP + Skills 管理器(v0.3.10)
一个设置标签页(Connector),在 DSH Web UI 里管理三样东西:
- MCP 服务器 — 编辑 cordis.patch.yml 里的 MCP 配置块(stdio / streamable-http),带完整校验,坏配置绝不会留到下次启动。旧式 SSE 服务器(比如知乎)保留为 mcp-remote --transport sse-only 的 stdio 桥接;插件只负责管理这段配置文本。
- 用户技能 — 读写、删除 ~/.dsh/skills/<name>/SKILL.md 下的技能(保留 frontmatter)。
- 市场浏览器(v0.2.0+) — 通过匿名 OpenAPI 只读浏览 ModelScope Skills hub 和 MCP plaza;一键复制安装命令 / mcpServers 配置片段,借助 source/sourceUpdated frontmatter 检查技能更新。市场数据只存在进程内存里(30 分钟 TTL),从不落盘。
- 工具过滤器(v0.3.0+) — 按服务器配置 MCP 工具白名单(DSH 0.1.7+:connector 配置档条目的 config.toolFilters;更早的 rc.x:settings.yaml 的 connector.toolFilters),提示词隐藏 + 执行拦截;不设置 = 全部放行。
- 支持 DSH 0.1.7(v0.3.3) — jsdom 不再在模块顶层导入(DSH 包解析器里 punycode/ 的解析缺陷会让整个插件导入失败);工具过滤器迁到易变的 Config / settings.replace() 后端,同时保留 rc.x 的 settings.yaml 后端。
- 声明 DSH 支持 + 抢救滞留的过滤器(v0.3.4) — 新增 @deepseek-ai/dsh peer(0.1.7-rc.1,当时按版本逐个枚举;v0.3.8 改为三段范围,见下文),由 DSH 自带的 evaluatePluginCompatibility() 强制执行:未测试的更新运行时会让插件包被平稳跳过,而不是以未定义的方式失败;而 ≤0.1.6 的运行时只会看到一个不认识的 peer(0.1.7 之前还没有这道校验)。同时修复工具过滤器悄悄退回全部放行的问题:0.1.7 的一次性导入器会把 settings.yaml 重命名为 settings.yaml.imported,并静默跳过没有易变 Config 的配置段,于是 connector.toolFilters 留在了 .imported 里;ensureLegacyFiltersMigration() 现在会在首次请求时把它搬回来(绝不覆盖你已有的过滤器,也绝不删除 .imported)。
- peer 枚举加入 DSH 0.1.7-rc.2(v0.3.5) — 零代码改动;验证方式:逐文件对比 tarball(shell/settings/credentials 的 lib/ 字节一致,llm 只有新增,app-boot 的改动与插件无关)、用 rc.2 的校验跑新声明、在临时 dsh@0.1.7-rc.2 配置档上做实际回归(filters 端点返回 200)。
- CRLF 补丁 + 正确的配置档文件(v0.3.6) — 两个实际 bug。(1) parseMcpServers() 的键值正则 ^\s+(\w+):\s(.)$ 在 CRLF 文件上永远匹配不上(JS 里 . 不匹配 \r,$ 也不匹配它前面的位置),于是 transport/serverName/command/url 全落进 preserve 桶:API 返回 transport:"" serverName:"",导致工具过滤器区块静默消失(if (!props.serverName) return null),传输方式徽标也退化成 stdio。现在解析前先统一换行符(toLf()),写入时输出 LF。(2) patchPath() 硬编码了 profiles/web/cordis.patch.yml,所以在桌面应用下(运行的是 profiles/desktop)MCP 编辑器改的是另一个配置档的文件——对自己的 MCP 配置毫无影响,UI 里还显示错误的路径。0.1.7+ 现在从 ctx.get('profileContext').patchPath 读取真实路径(dsh-app-boot 的 ProfileContext 契约),仅在该服务不存在的地方(0.1.5/0.1.6)保留旧路径;GET /api/mcp 会返回它,设置页因此能显示真实文件。
- DSH 0.2.0-rc.1 加入 peer 枚举(v0.3.7) —— 零代码改动。桌面应用升到 0.2.0-rc.1 之后,兼容性校验跳过了只声明到 0.1.7-rc.2 的包(Connector 标签页消失,/connector/api/ → 404 —— 属于优雅跳过,不是崩溃)。验证方式有三种:对两个官方 tarball 的每个 lib/ 文件逐个做 SHA1 比对(dsh-web-app/dsh-host-webserver/dsh-credentials/dsh-settings/dsh-tools/dsh-mcp-client 字节完全一致);用 0.2.0-rc.1 的 evaluatePluginCompatibility() 跑新清单(通过;旧清单被拦截);以及一次真实沙箱组装 —— 官方 @deepseek-ai/dsh@0.2.0-rc.1 + 隔离的 DSH_HOME + --dump-config → 插件出现在树里,没有触发跳过。
- peer 声明改为三段范围(v0.3.8) —— 零代码改动。@deepseek-ai/dsh 的 peer 从逐版本枚举改为 >=0.2.0-rc.1 <0.2.1-0。0.2.0-rc.2 发布后,兼容性校验第三次拦下旧声明(Connector 标签页消失,/connector/api/ → 404);根因从来不是不兼容,而是每次 rc 都会让枚举过期。验证方式:对 0.2.0-rc.1 → rc.2 全部 20 个包逐个文件做 SHA256 比对(本插件涉及的一切只在 package.json 的版本字符串上有变化;dsh 主包的变化全部是 desktop 配置档支持);再用真实校验跑完整矩阵 —— 0.2.0-rc.1/rc.2/rc.3/rc.9/稳定版 0.2.0 全部通过,0.2.1-rc.1/0.3.0-rc.1 全部拦截。⚠️ 这缩小了支持范围:0.1.7 系列不再声明 —— 如果你需要在那上面用,请安装 0.3.7。
- 支持 DSH 0.2.1(v0.3.10) —— @deepseek-ai/dsh 的 peer 增加了第二段三段范围:>=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0(schemastery 也增加了 3.18.5,由 0.2.1-rc.2 锁定)。零代码改动。 分四层验证:对整个 @deepseek-ai/ 树逐个文件做 SHA256 比对(0.2.0-rc.2 → 0.2.1-rc.2:包数 288 → 305,其中 177 个有真实的 .js 变动);对我们用到的 9 个包做真实的 ESM 导入/导出集合比对(唯一的移除项未被使用,位于 dsh-app-boot);对我们调用的全部 37 个符号做方法级存在性检查;以及一次真实的 0.2.1-rc.2 命令行组装,使用隔离的 DSH_HOME(--dump-config 组合出全部三个插件,零跳过)。
"dependencies": { "@omdp/dsh-connector": "^0.3.10" }
@omdp/dsh-key-fallback —— 多密钥 API key 池,支持轮换(v3.3.3)
挂接 DSH 的凭据接缝 credentials.resolve:适配器每次请求密钥时,如果该 ref 属于已配置的池,包装层就返回池中当前的密钥;遇到配置好的触发错误时,它把失败的密钥标记为冷却,并前进到下一个密钥 —— 重发完全交给 DSH 自己的 dsh-llm-retry。附带一个始终可见的设置页(Settings → API Key 回退),UI 经过重新设计:
- 可配置的轮换触发条件(rotateOn)—— 可点击的标签,覆盖 DSH LlmError 标准错误码全集(QUOTA/AUTH/RATE_LIMIT/TIMEOUT/TRANSPORT/SERVER/EMPTY_RESPONSE/INVALID_CREDENTIAL),外加自定义错误码(与 failure.code 精确匹配)。
- 显示实际使用的密钥(池的当前 ref —— 正是凭据接缝交给适配器的那个),而不是截断的哈希。
- 短 ref(key_fallback_<provider>_key1,……),并对遗留的长 ref 做一次性幂等迁移。
- 通过眼睛开关明文查看(GET /keys/plain,仅限池内密钥 / 环境密钥),并支持编辑环境密钥(文件支撑的密钥;由启动环境提供时只读)。
- 每个密钥的 nextRef、池锁定(「设为当前」)、冷却重置和删除。
- 支持 DSH 0.1.7(v3.2.0/v3.2.1) —— 双配置后端:0.1.7+ 上用易失的 Config / settings.replace() 配置档条目后端,旧版 rc.x 上用 settings.yaml 文件后端。v3.2.1 新增一次性救援,找回滞留在 settings.yaml.imported 里的池(0.1.7 迁移会重命名该文件,读文件的后端从此再也看不到它们)。
- 声明 DSH 支持范围(v3.2.2) —— 新增 @deepseek-ai/dsh peer(0.1.7-rc.1,当时按版本逐个枚举;v3.3.2 中四个 peer 全部改为三段范围,见下文),把支持的运行时变成显式、机器校验的契约(门禁语义见上面的连接器条目)。
- 四个 dsh peer 枚举全部加入 DSH 0.1.7-rc.2(v3.2.3) —— 零代码改动;通过 tarball diff(credentials lib/ 字节一致,llm 仅新增)、在 rc.2 上执行门禁、以及一次真实 scratch 配置档回归验证。
- 四个 dsh peer 枚举全部加入 DSH 0.2.0-rc.1(v3.2.4) —— 零代码改动;通过完整 lib/ SHA1 diff(credentials/llm/settings/shell/tools/mcp-client/web/agent 全部字节一致 —— 即本插件触及的整个表面)、在 0.2.0-rc.1 上执行门禁、以及一次真实沙箱组装验证。
- 四个 dsh peer 全部改为三段范围(v3.3.2) —— @deepseek-ai/dsh / dsh-credentials / dsh-llm / dsh-settings 现在都声明 >=0.2.0-rc.1 <0.2.1-0;零代码改动。0.2.0-rc.2 已连续第三轮让门禁拦下 3.3.1(settings 条目消失,路由 404/405)。通过完整 20 个包逐文件 SHA256 diff(六个声明的 peer 只有 package.json 版本字符串变化)以及在整个矩阵上跑真实门禁验证。⚠️ 0.1.7 线不再声明 —— 需要它请安装 3.3.1。cordis / schemastery 仍保持枚举(它们从不经过门禁)。
- v3.3.0 说明更正(v3.3.1)——下面 v3.3.0 条目原本声称密钥切换从未到达服务商。这个说法是错的。 提供密钥的 credentials.resolve 包装器从 v3.0.0 起就存在(75ea76a),已发布的 3.2.4 tarball 里也包含它(lib/index.js:298),以及它的 pool-hit 诊断(:305)——从 registry 下载 tarball 验证过。轮换本来就在工作;那些 process.env 写入只是挨着一个能用的包装器的冗余代码,并不是机制本身。下面保留 v3.3.0 条目,并更正其中的说法。
- 四个真实修复(v3.3.0)——(1) /pools 的 activeRef 不再误报当前密钥:它以前会反向查找 process.env[<pool env>],可能高亮错误的成员(实测:activeRef=SENSENOVA_API_KEY,而 currentRef=key_fallback_sensenova_key1);现在它就是 currentRef。(2) 5 处 process.env 写入已移除——验证过凭据层看不到它们(DSH 在启动时把 {...process.env} 冻结成启动环境快照),所以它们对认证毫无用处;去掉它们也避免了插件改动宿主环境。(3) agent/request-error 不再退回到归咎 keyValues[0]。(4) 卸载时通过 ctx.effect 恢复原来的 resolve,并带身份校验,这样热重载不再叠加包装器。重新发送仍是 DSH 的职责——每条轮换路径仍然调用 next()。
- 支持 DSH 0.2.1(v3.3.3)——四个 dsh peer 都加上了第二段三元版本区间 >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0;cordis 加上了 4.0.5,schemastery 加上了 3.18.5(两者都由 0.2.1-rc.2 锁定)。零代码改动——本插件触及的整个表面(credentials.resolve 包装、ctx.llm 事件、settings、webServer)在 0.2.0-rc.2 与 0.2.1-rc.2 之间逐字节相同,导出集 diff 和真实运行时组装都确认了这一点。
"dependencies": { "@omdp/dsh-key-fallback": "^3.3.3" }
@omdp/dsh-archived-sessions——归档会话管理器(v0.3.11)
fork 自 @muwinds/dsh-archived-sessions 0.2.0,适配 DSH 0.2.0-rc.1 / 0.2.0-rc.2(从 0.3.9 起用三元区间;更早的 0.1.5-rc.1 → 0.1.7-rc.2 系列在 0.3.8 及之前受支持,但已不再声明)——上游无人维护,在 0.1.5+ 上已损坏(sessionPersistence.list() 返回快照,locate() 被移除)。新增 Settings → 归档会话管理,与 DSH 0.1.6 引入的原生归档会话页共存:
- 列出归档会话,显示标题 / ID / 工作区 / 磁盘占用 / 运行状态;
- 释放:把会话移出归档集(不删除数据);
- 删除:删除会话目录 + 广播 api-session/removed + 清理归档 id + 释放工作区记账槽位(两步确认);
- 树删除:删除主会话时,一并删掉它的 parentSession 子树(修复上游 issue #2 —— 孤儿子代理);
- 孤儿清扫:扫描并清理残留的子代理目录,这些目录的父会话已经不存在(自 0.3.10 起,与 Delete 采用同样的 4 步拆除流程);
- 删除安全:只要路径的目录名不是会话目录(session-<uuid> 或裸 UUID),就拒绝删除;自 0.3.6 起,删除支持双时代 —— 在 DSH 0.1.7+ 上优先走 ctx.shell.resolve() → execute() → await result(),在 ≤0.1.6 上回退到 resolve() → run(),因此同一份构建能跨整条版本线完成删除。(0.3.5 只调用 execute() —— 这修好了 0.1.7,却悄悄弄坏了 rc.x,因为那里只有 run();0.3.4 犯的是镜像对称的 bug。已通过解包每个 @deepseek-ai/dsh-shell tarball 的 lib/types/index.d.ts 验证。)
- 0.3.10 —— 已删除的归档会话重新出现在聊天列表里:在 DSH 中,归档只是一层可见性遮罩(它从不过滤宿主列表;dsh-session-query 里没有任何 archiv 引用),所以客户端那一行仍留在 manager.summaries 里,只是被隐藏了。旧代码只移除归档 id —— 遮罩一撤,残留的行就又可见了(点它还会报 session/not-found),因为它发出的唯一一条移除通知只是顺带来自 entry.detach() 的 session/disposed → api-session/removed,而这条通知只对活跃会话触发。0.3.10 在每条删除路径上都显式发出 api-session/removed(包在 try/catch 里 —— cordis 的 emit 是同步且不设隔离的,所以第三方监听器抛错绝不能中断已完成的删除),并通过 entity.detachSession() 释放工作区的 sessionIds 记账槽位(DSH 按设计会一直为归档 id 记账,且永不遗忘),同时不再忽略 location.found === false(旧代码对猜测的路径执行 rm -rf,这总是失败,归档 id 就永远卡住)。客户端侧:组件从未拿到 ctx(它读的是自由变量,还把 ReferenceError 吞进一个静默的 try/catch 里),所以它的刷新是死代码。已在一个临时 DSH_HOME 上针对非活跃归档会话做 A/B 验证:旧版 = 0 个移除事件 + 记账泄漏;新版 = 1 个事件 + 记账释放。
- 声明支持 DSH(0.3.6),随后在 0.3.9 中改用三段式范围 —— @deepseek-ai/dsh 这个 peer 依赖现在写成 >=0.2.0-rc.1 <0.2.1-0,因此 0.2.0-rc.2、后续 rc 版本、稳定版 0.2.0 都能通过,无需重新发布。更早的改动:(0.3.7) 把 rc.2 加入枚举 —— 零代码改动,靠 dsh-shell 的逐字节一致 diff,以及在临时 dsh@0.1.7-rc.2 配置档上跑的一次真实端到端删除测试来验证;(0.3.8) 加入 0.2.0-rc.1 —— 靠完整的 lib/ SHA1 diff(dsh-shell 逐字节一致;dsh-session 的改动只有新增,新增了 ToolCallRecovery 导出,没有删除)、在 0.2.0-rc.1 上执行 gate、以及一次真实的沙箱组装来验证。⚠️ 从 0.3.9 起不再声明 0.1.7 系列 —— 如果你需要它,请安装 0.3.8。
- 支持 DSH 0.2.1(v0.3.11) —— @deepseek-ai/dsh 这个 peer 依赖新增了第二段三段式 >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0;cordis 新增 4.0.5。零代码改动。 本插件依赖的 api-session/removed 链路(0.3.10 的修复)现在走新的 dsh-api-remote-access 服务,该服务对配置档所有者直接短路为 ALLOW —— 而桌面配置档就是所有者。
"dependencies": { "@omdp/dsh-archived-sessions": "^0.3.11" }
从 npm 安装(推荐)
每次打 v 标签,GitHub Actions 都会自动把三个插件发布到 npm。这是首选安装方式 —— 它能避开 GitHub 安装带来的 git-#path: 归一化、交叉解析和 allowBuilds 摩擦(来龙去脉见 docs/npm-publish.md)。
// ~/.dsh/profiles/<name>/package.json — you can use one or mix-and-match
"dependencies": {
"@omdp/dsh-connector": "^0.3.10",
"@omdp/dsh-key-fallback": "^3.3.3",
"@omdp/dsh-archived-sessions": "^0.3.11"
}
cd ~/.dsh/profiles/<name>
pnpm install
更新就是标准的 pnpm update:
cd ~/.dsh/profiles/<name>
pnpm update @omdp/dsh-connector @omdp/dsh-key-fallback @omdp/dsh-archived-sessions
从 GitHub 远程安装(备选)
每个活跃插件都是独立 npm 包,放在各自的子目录里,所以也能直接从 GitHub 安装,不用本地检出:
dsh plugin --profile web add github:XJungit/omdp#path:dsh-connector
dsh plugin --profile web add github:XJungit/omdp#path:dsh-key-fallback
dsh plugin --profile web add github:XJungit/omdp#path:dsh-archived-sessions
命令可用性 —— 上面的 dsh plugin add 命令假定 dsh 已在你的 PATH 里。如果你按官方文档用 npx 跑 DSH(没有全局 dsh 命令),这些行会报 command not found: dsh —— 给每行加上 npx @deepseek-ai/dsh 前缀即可(不需要 dsh 在 PATH 里)。
#path:<subdir> 选择器告诉 pnpm 安装哪个工作区子目录(它会解析到该子包的 package.json,而不是仓库根目录)。
pnpm ≥10 的构建脚本限制。 用 git 安装拉取的是源码,pnpm 默认拒绝执行 git 依赖的 prepare/构建脚本,除非你显式放行——第一次 add 会失败,直到你在配置档的 pnpm-workspace.yaml 里把它加进白名单:
allowBuilds:
'@omdp/dsh-connector': true
'@omdp/dsh-key-fallback': true
'@omdp/dsh-archived-sessions': true
然后重新执行 add。(这些插件是纯 JavaScript,没有构建步骤,所以白名单是唯一的门槛——不需要 prepare 脚本。完整的「构建脚本陷阱」说明见官方 publish.md。)把这条放行当成「允许在安装时运行该包的代码」;来源不可信时,请固定到某个 commit(github:XJungit/omdp#<sha>&path:<subdir>)。
其他 DSH 插件集合也用同样的 monorepo 布局,例如 zhu1090093659/dsh-web-ui。
发布新版本(GitHub Actions)
1. 修改子目录 package.json 里的 version(只改你动过的那些)。
2. 提交,然后打 tag 并推送——tag 决定发布哪个包,所以必须是 <version>-<plugin>,版本号用你刚改的那个:
git tag v0.3.10-dsh-connector
git push origin master && git push origin v0.3.10-dsh-connector
3. .github/workflows/publish.yml 会把那一个包发布到 npm,并带上 provenance(版本已发布过则什么都不做——会打印一条跳过信息)。tag 匹配不到任何活跃包时,任务直接失败,不会去发布别的包。
4. 更新你的配置档:pnpm update @omdp/<plugin>。
完整配置(npm token、GitHub Secret、故障排查)见 docs/npm-publish.md,抗崩溃矩阵见 docs/plugin-compatibility.md。
历史记录:GitHub 安装与本地 link 安装
GitHub 安装(dsh plugin add github:XJungit/omdp#path:<plugin>)能用,但会碰上网络/TLS 问题(例如 UNABLE_TO_VERIFY_LEAF_SIGNATURE),以及 pnpm 在 update 时对 git #path: 的归一化处理(它会丢掉 #path: 说明,可能把两个包都解析到仓库根目录)。当时用一次性修复脚本(~/.dsh/profiles/web/update-omdp.ps1)处理这些问题,改用 npm 安装后这些都不需要了。
本地 link: 安装("@omdp/<plugin>": "link:<abs-path>/omdp/<plugin>")仍然可用:pnpm install 会创建 junction,运行中的插件就是仓库源码,更新 = 改代码/拉取 + 重启。活跃开发期间它依然是很好的选择。
约定
- 每个插件子目录都是独立的 npm 包,带 dsh.bundle 清单(可选带 dsh.client)。
- 包名统一放在 @omdp/ 作用域下,避免和 npm 上的上游 dsh- 包冲突。
- 本仓库的插件都是纯 JavaScript(无构建步骤),所以本地 link 安装和 GitHub 安装都不需要编译阶段。
- 开发阶段优先本地安装:在配置档的 dependencies 里加上 "@omdp/<plugin>": "link:<abs-path>/omdp/<plugin>",再跑 pnpm install —— 插件直接从仓库加载,重启即生效。
- 新插件请照着现有三个插件(connector / key-fallback / archived-sessions)来写,别照着骨架写 —— 真实插件才是活的模板。
- 文档纪律 —— 插件有任何更新(源码 / 配置 / 版本),都必须同步根 README、插件自己的 README 和 docs/ 下的文件;开发中踩到的坑写进 notes/<date>/<category>/(见 AGENTS.md 规范 2)。
文档索引
| 文档 | 内容 |
| docs/npm-publish.md | npm 发布流水线、为什么用 npm 而不是从 GitHub 安装、发布流程 |
| docs/plugin-compatibility.md | 各插件面对 DSH 更新时的抗崩溃矩阵 |
| docs/AI-DSH-plugin-quality.md | 社区研究:AI 写的 DSH 插件为什么会坏,以及防御性做法 |
| docs/DSH-plugin-quality-zh-discussion.md | 同一份研究的中文整理 + omdp 实践 |
| docs/dsh-drag-and-drop-troubleshooting.md | dsh-drag-and-drop 插件的排障记录(Windows / 中文) |
| notes/README.md | 开发教训与笔记索引(notes/<date>/<category>/)—— 见 AGENTS.md 规范 2 |
中文版
一个 monorepo,把作者全部 DeepSeek Harness(DSH)插件收进单一 GitHub 仓库。每个插件各自独立子目录,是可直接安装的 DSH bundle,每次打 v tag 时自动发布到 npm。
目录结构
omdp/
├── README.md # 本文件 ├── package.json # 根清单——保证 bare-git 安装可用(见下文) ├── dsh-connector/ # 统一 MCP + Skills 管理器(Web UI 设置页) │ ├── index.js # host 半区 │ ├── client.js # client 半区(Web UI) │ ├── cordis.patch.yml # bundle 激活行 │ ├── package.json │ └── README.md ├── dsh-key-fallback/ # 多 key API 池 + 自动轮换 │ ├── lib/index.js # host 半区(ESM) │ ├── lib/client.js # client 半区(Web UI 设置页) │ ├── cordis.patch.yml # bundle 激活行 │ ├── package.json │ └── README.md ├── dsh-archived-sessions/ # 归档会话管理(fork @muwinds,适配 DSH 0.2.0-rc.1 / 0.2.0-rc.2) │ ├── lib/index.js # host 半区(ESM) │ ├── lib/client.js # client 半区(Web UI 设置页) │ ├── cordis.patch.yml # bundle 激活行 │ ├── package.json │ └── README.md ├── archive/ # 已归档插件,留作历史参考 │ ├── dsh-gitbash-win/ │ ├── resume-stream/ │ ├── key-fallback-/ # dsh-key-fallback 各版本快照与设计草案 │ ├── dsh-vision-bridge-/ # 2026-10-18 起归档(原为活跃视觉插件) │ └── README.md ├── notes/ # 开发教训与笔记(三层:notes/<date>/<category>/) ├── docs/ # 研究笔记、兼容性矩阵、发布指南 └── <未来插件>/ # 每个插件一个子目录 + package.json
插件
@omdp/dsh-connector — MCP + Skills 管理器(v0.3.10)
设置页(Connector)里管三件事:
- MCP 服务器 —— 编辑 cordis.patch.yml 中的 MCP 块(stdio / streamable-http),带完整校验,坏配置绝不可能带到下次启动。旧版 SSE 服务器(如知乎)保留为 mcp-remote --transport sse-only 的 stdio 桥;插件只管这段配置文本。
- 用户 Skills —— 读写/删除 ~/.dsh/skills/<name>/SKILL.md 下的技能(保留 frontmatter)。
- 市场浏览器(v0.2.0+) —— 匿名 OpenAPI 只读浏览 ModelScope Skills 集市 与 MCP 广场;一键复制安装命令 / mcpServers 配置片段;通过 source/sourceUpdated frontmatter 检查技能更新。市场数据只存进程内存(30 分钟 TTL),绝不落盘。
- 工具过滤(v0.3.0+) —— 每 server 的 MCP 工具 allow 名单(DSH 0.1.7+ 存 connector profile 条目的 config.toolFilters;旧版 rc.x 存 settings.yaml 的 connector.toolFilters),提示词隐藏 + 执行期拦截;不配 = 全放行。
- DSH 0.1.7 适配(v0.3.3) —— jsdom 不再顶层静态 import(DSH 包解析器对 punycode/ 这类「内置名 + 子路径」会抛 TypeError,导致整个插件 import 失败、设置页永远停在「已安装,重启后生效」);工具过滤迁到 volatile Config / settings.replace(),同时保留 rc.x 的 settings.yaml 后端。
- 声明 DSH 版本支持 + 抢救滞留的过滤规则(v0.3.4) —— 新增 @deepseek-ai/dsh peer(0.1.7-rc.1,当时为逐版本枚举;v0.3.8 起改为三元组区间,见下),由 DSH 自己的 evaluatePluginCompatibility() 执行:未实测的新运行时会让 bundle 被优雅跳过(而不是以未定义方式崩掉),而 ≤0.1.6 的运行时只是看到一条不认识的 peer(该门禁 0.1.7 才引入)。同时修复工具过滤静默变回「全放行」:0.1.7 的一次性导入器把 settings.yaml 改名为 settings.yaml.imported,并静默跳过没有 volatile Config 的段,于是 connector.toolFilters 被留在 .imported;ensureLegacyFiltersMigration() 会在首个请求时把它搬回(不覆盖你已有的过滤规则、不删 .imported)。
- peer 枚举追加 DSH 0.1.7-rc.2(v0.3.5) —— 代码零改动;依据:tarball 逐文件 diff(shell/settings/credentials 的 lib/ 逐字节一致、llm 纯新增、app-boot 变更与插件无关)+ rc.2 门禁执行新声明放行 + scratch dsh@0.1.7-rc.2 profile 真机回归(过滤端点 200)。
- CRLF 补丁 + 改错 profile 文件(v0.3.6) —— 两个真机 bug。(1) parseMcpServers() 的键值正则 ^\s+(\w+):\s(.)$ 在 CRLF 文件上必然失配(JS 里 . 不匹配 \r、$ 也不匹配 \r 之前),transport/serverName/command/url 全落进 preserve:接口返回 transport:"" serverName:"" 导致工具过滤区静默消失(if (!props.serverName) return null)、transport 徽标退化成 stdio。现在解析前先归一化换行(toLf()),写回也统一 LF。(2) patchPath() 曾硬编码 profiles/web/cordis.patch.yml,桌面端(跑 profiles/desktop)因此在改另一个 profile 的文件——对自己的 MCP 配置毫无影响,UI 还显示错误路径。0.1.7+ 改为从 ctx.get('profileContext').patchPath 取真实路径(dsh-app-boot 的 ProfileContext 契约),仅在没有该服务的 0.1.5/0.1.6 上保留历史路径;GET /api/mcp 回传该路径供设置页显示。
- peer 枚举追加 DSH 0.2.0-rc.1(v0.3.7) —— 代码零改动。桌面端升到 0.2.0-rc.1 后,门禁把只声明到 0.1.7-rc.2 的 bundle 跳过(Connector 标签消失、/connector/api/ → 404;是优雅跳过而非崩溃)。依据:两版官方 tarball 全量 lib/ 文件 SHA1 逐文件 diff(dsh-web-app/dsh-host-webserver/dsh-credentials/dsh-settings/dsh-tools/dsh-mcp-client 逐字节一致)+ 用 0.2.0-rc.1 的 evaluatePluginCompatibility() 判定新声明放行(旧声明被拦)+ 沙箱真机装配(官方 @deepseek-ai/dsh@0.2.0-rc.1 + 独立 DSH_HOME + --dump-config → 插件入树、零拦截)。
- peer 声明改用三元组区间(v0.3.8) —— @deepseek-ai/dsh 由逐版本枚举改为 >=0.2.0-rc.1 <0.2.1-0;代码零改动。0.2.0-rc.2 发布后门禁第三次把旧声明拦下(Connector 标签消失、/connector/api/ → 404),根因不是不兼容,而是枚举在每次 rc 迭代下必然过时。依据:rc.1→rc.2 全量 20 包逐文件 SHA256(本插件依赖面只有 package.json 版本号变化)+ 真门禁全矩阵(0.2.0-rc.1/rc.2/rc.3/rc.9/正式版 0.2.0 全放行;0.2.1-rc.1/0.3.0-rc.1 全拦截)。⚠️ 同时收窄支持面:0.1.7 线不再声明,需要它请装 0.3.7。
- 支持 DSH 0.2.1(v0.3.10) —— @deepseek-ai/dsh peer 新增第二段三元组区间:>=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0(schemastery 同步追加 3.18.5,为 0.2.1-rc.2 的钉版)。代码零改动。 四层核查:全量 @deepseek-ai/ 逐文件 SHA256(0.2.0-rc.2 → 0.2.1-rc.2:288 → 305 个包,177 个有真实 .js 改动)、我们消费的 9 个包真实 ESM 导出面比对(移除项均未使用,在 dsh-app-boot)、调用到的 37 个符号逐个存在性复核、以及真实 0.2.1-rc.2 CLI 装配(隔离 DSH_HOME,--dump-config 三个插件全部进树、零跳过)。
"dependencies": { "@omdp/dsh-connector": "^0.3.10" }
@omdp/dsh-key-fallback — 多 key API 池 + 轮换(v3.3.3)
挂在 DSH 的凭证接缝 credentials.resolve 上:每次适配器取 key 时,若该 ref 属于已配置的池,就返回池的当前 key;遇配置的触发错误时,把失败 key 标记为冷却并切到下一把——重发完全交给 DSH 自带的 dsh-llm-retry。带一个常驻可见的设置页(设置 → API Key 回退)与全新 UI:
- 可配置的轮换触发码(rotateOn)——点选 chips 覆盖 DSH LlmError 标准码全集(QUOTA/AUTH/RATE_LIMIT/TIMEOUT/TRANSPORT/SERVER/EMPTY_RESPONSE/INVALID_CREDENTIAL),也支持自定义码(与 failure.code 精确匹配)。
- 显示当前实际使用的 key(池的当前 ref —— 正是凭证接缝交给适配器的那把),不是截断的哈希。
- 短 ref(key_fallback_<provider>_key1、…),旧长 ref 一次性幂等迁移。
- 眼睛开关明文揭示(GET /keys/plain,仅限池内 key / env key)与可编辑 env key(文件托管的可编辑;由启动环境注入的只读)。
- 每把 key 的 nextRef、池锁定("设为当前")、冷却重置与删除。
- DSH 0.1.7 适配(v3.2.0/v3.2.1) —— 配置双后端:0.1.7+ 用 volatile Config / settings.replace() 写本插件 profile 条目,旧版 rc.x 用 settings.yaml 文件后端。v3.2.1 追加一次性救援:把残留在 settings.yaml.imported 里的池捞回来(0.1.7 的迁移会改名该文件,文件后端从此再也看不到它们,被救池表现为「尚未启用 / 还没有任何池」且重启无效)。
- 声明 DSH 版本支持(v3.2.2) —— 新增 @deepseek-ai/dsh peer(0.1.7-rc.1,当时为逐版本枚举;v3.3.2 起改为三元组区间,见下),把「支持的运行时」变成显式且机器可校验的契约(门禁语义见上方 connector 条目)。
- 四条 dsh peer 枚举同步追加 0.1.7-rc.2(v3.2.3) —— 代码零改动;依据:tarball diff(credentials 的 lib/ 逐字节一致、llm 纯新增)+ rc.2 门禁放行 + scratch profile 真机回归。
- 四条 dsh peer 枚举同步追加 0.2.0-rc.1(v3.2.4) —— 代码零改动;依据:全量 lib/ SHA1 diff(credentials/llm/settings/shell/tools/mcp-client/web/agent 逐字节一致——本插件用到的整个调用面)+ 0.2.0-rc.1 门禁放行 + 沙箱真机装配入树。
- 四条 dsh peer 改用三元组区间(v3.3.2) —— @deepseek-ai/dsh / dsh-credentials / dsh-llm / dsh-settings 四条统一改为 >=0.2.0-rc.1 <0.2.1-0;代码零改动。0.2.0-rc.2 发布后门禁第三次拦下(设置项消失、路由 404/405)。依据:rc.1→rc.2 全量 20 包逐文件 SHA256(六条 peer 只有 package.json 版本号变化)+ 真门禁全矩阵放行/拦截符合预期。⚠️ 不再声明 0.1.7 线,需要它请装 3.3.1。
- 对 v3.3.0 说明的更正(v3.3.1) —— 下方 v3.3.0 条目原先声称「换 key 从来没到达 provider」。那是错的。 真正供 key 的 credentials.resolve 包装自 v3.0.0 就存在(75ea76a),已发布的 3.2.4 tarball 里就有它(lib/index.js:298)及配套 pool-hit 诊断(:305)——从 registry 下载 tarball 核对过。轮换一直在生效;那些 process.env 写入是与可用包装并存的冗余代码,而不是机制本身。下方 v3.3.0 条目保留,但其中错误断言已改正。
- 四项真实修复(v3.3.0) —— ① /pools 的 activeRef 不再报错当前 key:原先用 process.env[<池 env>] 反查、可能高亮错误的成员(实机测得 activeRef=SENSENOVA_API_KEY 而 currentRef=key_fallback_sensenova_key1),现在直接等于 currentRef。② 删除 5 处 process.env 写入——已证实启动快照冻结、凭证层读不到,对鉴权是死代码;删掉同时避免插件改写宿主环境。③ agent/request-error 不再退化成归咎 keyValues[0]。④ 卸载经 ctx.effect 还原原始 resolve(带身份校验),热重载不再叠加包装层。重发仍归 DSH 管——每条轮换路径都仍调用 next()。
- 支持 DSH 0.2.1(v3.3.3) —— 四条 dsh peer 均新增第二段三元组区间 >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0;cordis 追加 4.0.5、schemastery 追加 3.18.5(均为 0.2.1-rc.2 的钉版)。代码零改动 —— 本插件触及的整个面(credentials.resolve 包装、ctx.llm 事件、settings、webServer)在 0.2.0-rc.2 与 0.2.1-rc.2 之间逐字节一致,已由导出面比对 + 真机装配双重确认。
"dependencies": { "@omdp/dsh-key-fallback": "^3.3.3" }
@omdp/dsh-archived-sessions — 归档会话管理(v0.3.11)
fork 自 @muwinds/dsh-archived-sessions 0.2.0,适配 DSH 0.2.0-rc.1 / 0.2.0-rc.2(0.3.9 起用三元组区间声明;更早的 0.1.5-rc.1 → 0.1.7-rc.2 线支持到 0.3.8,现已不再声明)(上游已不维护,且在 0.1.5+ 下损坏:sessionPersistence.list() 返回快照、locate() 被移除)。新增 设置 → 归档会话管理,与 DSH 0.1.6 起内置的原生「已归档会话」页共存:
- 列表显示归档会话的标题 / ID / 工作区 / 磁盘占用 / 运行状态;
- 释放:把会话移出归档集合(不删数据);
- 删除:删会话目录 + 广播 api-session/removed + 移除归档标记 + 释放工作区记账槽(两步确认);
- 按树删除:删主会话时连同其 parentSession 子树一起删(修复上游 issue #2——孤儿子代理);
- 孤儿清理:扫描并清理「父会话已删除、自己还在盘上」的残留子会话目录(自 0.3.10 起与删除走同一套四步收尾);
- 删除安全:目录名不是会话目录(session-<uuid> 或裸 UUID)一律拒绝删除;删除自 0.3.6 起双时代自适应——DSH 0.1.7+ 走 ctx.shell.resolve() → execute() → await result(),≤0.1.6 回退 resolve() → run(),一份构建覆盖整条版本线。(0.3.5 只调 execute():修好了 0.1.7 却让 rc.x 静默失效——那里只有 run();0.3.4 则恰好相反。依据:逐版解包 @deepseek-ai/dsh-shell 的 lib/types/index.d.ts。)
- 0.3.10——「删掉的归档会话又回到对话列表」:归档在 DSH 里只是可见性遮罩(从不参与列表过滤,dsh-session-query 全库 0 处 archiv),客户端行一直留在 manager.summaries 里、只是被遮住。旧代码删除时只摘归档 id——遮罩一撤,幸存的行立刻重新可见(点进去报 session/not-found);它唯一的客户端通知来自 entry.detach() 顺带触发的 session/disposed → api-session/removed,而这条链只在会话仍 live 时存在。0.3.10 在每条删除路径上显式广播 api-session/removed(包 try/catch——cordis 的 emit 同步且不隔离,第三方监听器抛错不能把已完成的删除变成报错),并经 entity.detachSession() 释放工作区 sessionIds 记账(DSH 故意保留归档会话的记账,且从不遗忘),同时不再忽略 location.found === false(旧代码拿猜测路径去 rm -rf,必然失败且让归档 id 永久卡住)。客户端侧:组件原本拿不到 ctx(读的是自由变量,ReferenceError 被静默 try/catch 吞掉),刷新逻辑一直是死代码。验证方式是在 scratch DSH_HOME 上对非 live 的归档会话做 A/B:旧代码 0 个移除事件 + 记账泄漏;新代码 1 个事件 + 记账已释放。
- 声明 DSH 版本支持(0.3.6),0.3.9 起改用三元组区间——@deepseek-ai/dsh peer 现为 >=0.2.0-rc.1 <0.2.1-0,0.2.0-rc.2 / 后续同三元组 rc / 正式版 0.2.0 都不必重发包即可通过。(0.3.7)追加 0.1.7-rc.2——代码零改动,依据 dsh-shell 逐字节零变化 diff + scratch dsh@0.1.7-rc.2 profile 真机删除全链路实测;(0.3.8)追加 0.2.0-rc.1——依据全量 lib/ SHA1 diff(dsh-shell 逐字节一致;dsh-session 的 5 个变化文件为附加式新增 ToolCallRecovery 等导出、既有导出零删除)+ 0.2.0-rc.1 门禁放行 + 沙箱真机装配入树。⚠️ 0.1.7 线自 0.3.9 起不再声明,需要它请装 0.3.8。
- 支持 DSH 0.2.1(v0.3.11) —— @deepseek-ai/dsh peer 新增第二段三元组区间 >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-rc.1 <0.2.2-0;cordis 追加 4.0.5。代码零改动。 本插件依赖的 api-session/removed 链路(0.3.10 修复)在 0.2.1 上改由新的 dsh-api-remote-access 服务把关,而该服务对 profile owner 直接短路放行(桌面 profile 即 owner)。
"dependencies": { "@omdp/dsh-archived-sessions": "^0.3.11" }
从 npm 安装(推荐)
三个插件都会由 GitHub Actions 在每次打 v tag 时自动发布到 npm。这是首选安装路径——绕开 GitHub 安装带来的 git-#path: 规范化、交叉解析与 allowBuilds 摩擦(历史详见 docs/npm-publish.md)。
// ~/.dsh/profiles/<name>/package.json —— 可用其一或自由组合
"dependencies": {
"@omdp/dsh-connector": "^0.3.10",
"@omdp/dsh-key-fallback": "^3.3.3",
"@omdp/dsh-archived-sessions": "^0.3.11"
}
cd ~/.dsh/profiles/<name>
pnpm install
升级就是标准的 pnpm update:
cd ~/.dsh/profiles/<name>
pnpm update @omdp/dsh-connector @omdp/dsh-key-fallback @omdp/dsh-archived-sessions
从 GitHub 远程安装(备选)
每个活跃插件都是独立子目录里的独立 npm 包,因此也能不经过本地 checkout、直接从 GitHub 安装:
dsh plugin --profile web add github:XJungit/omdp#path:dsh-connector
dsh plugin --profile web add github:XJungit/omdp#path:dsh-key-fallback
dsh plugin --profile web add github:XJungit/omdp#path:dsh-archived-sessions
安装命令前提:上面的 dsh plugin add 假设 dsh 已在 PATH。若你是按官方文档用 npx 运行 dsh(没有全局 dsh 命令),这几行会报 command not found: dsh —— 每行前面加 npx @deepseek-ai/dsh 即可(不要求 dsh 在 PATH)。
#path:<子目录> 选择器告诉 pnpm 安装哪个 workspace 子目录(解析到该子包的 package.json,而不是仓库根)。
pnpm ≥10 构建脚本门禁。 git 安装拉取的是源码,pnpm 默认拒绝运行 git 依赖的 prepare/构建脚本,直到显式放行——首次 add 会失败,需要先在 profile 的 pnpm-workspace.yaml 里白名单:
allowBuilds:
'@omdp/dsh-connector': true
'@omdp/dsh-key-fallback': true
'@omdp/dsh-archived-sessions': true
然后重新执行 add。(这些插件是纯 JavaScript、无构建步骤,所以白名单是唯一障碍——不需要 prepare 脚本。官方 publish.md 有完整的"构建脚本坑"说明。)放行等于允许在安装时运行该包的代码;对不可信来源,请固定到具体 commit(github:XJungit/omdp#<sha>&path:<子目录>)。
其他 DSH 插件集合也采用同样的 monorepo 布局,例如 zhu1090093659/dsh-web-ui。
发布新版本(GitHub Actions)
1. 在子目录的 package.json 里 bump version(只 bump 你动过的)。
2. 提交,然后打 tag 并推送——tag 决定发哪个包,所以要写成 <version>-<plugin>,且 version 就是刚 bump 的那个:
git tag v0.3.10-dsh-connector
git push origin master && git push origin v0.3.10-dsh-connector
3. .github/workflows/publish.yml 只发布该 tag 指名的那个包到 npm(带 provenance;已发布的版本重复发布是 no-op,会打印 skip 信息)。tag 匹配不上任何活跃包时 job 直接失败,不会误发别的包。
4. 更新你的 profile:pnpm update @omdp/<plugin>。
完整配置(npm token、GitHub Secret、排障)见 docs/npm-publish.md;抗崩溃矩阵见 docs/plugin-compatibility.md。
历史:GitHub 与本地 link 安装
GitHub 安装(dsh plugin add github:XJungit/omdp#path:<插件>)能用,但会撞上网络/TLS 摩擦(如 UNABLE_TO_VERIFY_LEAF_SIGNATURE),以及 pnpm 在 update 时的 git-#path: 规范化问题(会丢 #path: 片段,甚至可能把两个包都交叉解析到仓库根)。当时用一次性修复脚本(~/.dsh/profiles/web/update-omdp.ps1)兜底,但 npm 安装让这一切都不再必要。
本地 link: 安装("@omdp/<插件>": "link:<绝对路径>/omdp/<插件>")依然可用:pnpm install 会创建 junction,让运行中的插件就是仓库源码,更新 = 改代码/拉取 + 重启。开发活跃期仍是好选择。
约定
- 每个插件子目录都是独立 npm 包,带 dsh.bundle(可选 dsh.client)清单。
- 包名统一挂在 @omdp/ 作用域下,避免与上游 dsh- 包在 npm 上撞名。
- 仓库里的插件都是纯 JavaScript(无构建步骤),所以本地 link 与 GitHub 安装都不需要编译环节。
- 开发期优先本地安装:把 "@omdp/<插件>": "link:<绝对路径>/omdp/<插件>" 加进 profile 的 dependencies,跑 pnpm install —— 插件直接从仓库加载,改完重启即生效。
- 新插件应以现有三个插件(connector / key-fallback / archived-sessions)为蓝本,而不是复制模板——真实插件就是活的模板。
- 文档纪律:插件有任何更新(源码/配置/版本)时,必须同步更新根 README、对应插件 README、docs/ 相关文档;开发中产生的教训/经验主动写入 notes/<date>/<category>/(详见 AGENTS.md 规范 2)。
文档索引
| 文档 | 内容 |
| docs/npm-publish.md | npm 发布管线、为什么选 npm 而非 GitHub 安装、发布流程 |
| docs/plugin-compatibility.md | 各插件对 DSH 更新的抗崩溃矩阵 |
| docs/AI-DSH-plugin-quality.md | 社区研究:为什么 AI 写的 DSH 插件会坏,以及防御性实践 |
| docs/DSH-plugin-quality-zh-discussion.md | 同一研究的中文版 + omdp 实践 |
| docs/dsh-drag-and-drop-troubleshooting.md | dsh-drag-and-drop 插件排障记录(Windows/中文) |
| notes/README.md | 开发教训与笔记索引(notes/<date>/<category>/)——见 AGENTS.md 规范 2 |预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
XJungit/omdp
只放我的 DSH 插件——DeepSeek Harness 插件包的 monorepo
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目