deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:dubeno/dsh-agent-plugin-bridge
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
A generic Agent Plugins 1.0 → DeepSeek Harness bridge. Drop it into any
DSH profile and it will scan a list of plugin roots and plugin directories,
pick up every package that has a plugin.json, and wire its skills/ and
mcp.json into the host. No per-business branching — same code path works
for tm-dagu-adapt, agenthandoff, or any future agent-plugins.org
package.
Forked from zoahdev/dsh-plugin-template: carries the template's runtime peer-version guard, the bundled
cordis.patch.yml, the unit + packaged integration + DSH-boot smoke posture, and the bilingual README.Tested with:
dsh0.1.0-rc.6 · Node 24 · pnpm 11
├── package.json # dsh.bundle manifest + build scripts (prepare = git-install build)
├── cordis.patch.yml # plugin row: id, package name, default config
├── src/
│ ├── index.ts # plugin entry: name / inject / Config / apply + bridge_summary tool + peer guard
│ ├── version.ts # dependency-free caret-range matcher used by the runtime guard
│ ├── discover.ts # plugin.json + skills/ + mcp.json discovery
│ ├── expand.ts # ${VAR} placeholder expansion
│ ├── mcp.ts # Agent Plugin MCP + standalone mcp.json registration
│ ├── skills.ts # SKILL.md discovery and host-skills registration
│ └── types.ts # shared wire types
├── tests/
│ ├── index.spec.ts # plugin registration, runBridge end-to-end (mocked ctx)
│ ├── version.spec.ts # prerelease range behavior matrix
│ ├── discover.spec.ts # plugin.json scanning, dedup
│ ├── expand.spec.ts # ${VAR} expansion rules
│ └── skills.spec.ts # SKILL.md → host skills service mapping
├── scripts/
│ ├── integration-test.mjs # installs the PACKED tarball → real apply() → real tool execution
│ ├── local-skill.mjs # loads the packed plugin into a real cordis context, registers a real Agent Plugin (default: tm-dagu-adapt), asserts bridge_summary
│ └── dsh-smoke.sh # fresh DSH profile install + config check + web boot (bounded retry)
├── .github/workflows/ci.yml # doctor → test → pack → integration → DSH boot smoke (windows-latest)
└── README.md # bilingual
apply() runs assertPeerCompatible() and refuses to load if
the resolved @deepseek-ai/dsh-tools does not satisfy ^0.1.0-rc.6. This
turns pnpm's silent older-RC linking into a loud, actionable error.discoverPlugins(pluginRoots, pluginsDirs). Each
candidate directory must contain a plugin.json with a name field;
optional skills/ and mcp.json are picked up if present.skills/<folder>/SKILL.md
into the host skills service (frontmatter is parsed with a tiny
dependency-free parser). If loadPluginMcp is on it also registers the
plugin's mcp.json against the host MCP client.mcpJsonPaths and registers every standalone mcp.json
(typical: ~/.cursor/mcp.json) the same way — same wire format, same
${VAR} expansion semantics.bridge_summary tool so the agent can introspect what was
actually loaded.mcp.jsonAgent Plugins 1.0 bundles an mcp.json per package. Those often use
${SOME_ENV} placeholders that only resolve when the host has the right
secrets — until then they fail with empty command after env expansion.
The bridge exposes two knobs:
loadPluginMcp (default true) — load the per-plugin mcp.json.mcpJsonPaths — extra standalone mcp.json files outside any package.
Typical: ~/.cursor/mcp.json, which is the user-level MCP config and
does not depend on plugin env vars.Set loadPluginMcp: false while the env vars are missing and the bridge
will still pick up the standalone file.
cordis.patch.yml ships these defaults — override them in your profile
config:
- id: dsh-agent-plugin-bridge
name: dsh-agent-plugin-bridge
config:
pluginRoots: [] # explicit Agent Plugin package roots
pluginsDirs: # directories whose children are scanned
- '~/.cursor/plugins/local'
mcpJsonPaths: # extra standalone mcp.json files
- '~/.cursor/mcp.json'
loadPluginMcp: false # load each plugin's own mcp.json (default off, plugin mcp.json usually needs host env vars)
failOnMcpError: false # keep going when an MCP server fails to start
skillProviderLabel: agent-plugin
Use ~ in paths; the bridge expands it against homedir().
@deepseek-ai/dsh-tools 0.1.0-rc.6 and @deepseek-ai/cordis ^4.0.1.peerDependencies declares "@deepseek-ai/dsh-tools": "^0.1.0-rc.6". This is a caret range, not a pin:0.1.0-rc.6, later RCs of 0.1.x (rc.7, rc.10, ...), and 0.1.0 stable once published.0.1.0-rc.5/older RCs, nor the 0.0.1-rc.* train.devDependencies uses the same range; the committed pnpm-lock.yaml pins the exact tested version for development and CI.0.1.0-rc.3), pnpm's default config links that older version into the plugin's peer slot with only a generic warning — no error, no auto-upgrade. npm fails loudly with ERESOLVE instead. Neither tool auto-upgrades the host.The plugin refuses to load when the resolved @deepseek-ai/dsh-tools does
not satisfy ^0.1.0-rc.6 (runtime guard in apply(), backed by
src/version.ts). A silent mismatch becomes a clear, actionable error.
The bridge is bundled for the standard dsh plugin add flow:
pnpm install
pnpm build
pnpm test
pnpm pack
dsh plugin --profile web add ./dsh-agent-plugin-bridge-0.1.0.tgz
dsh web --port 4099
Then ask the agent: "Use the bridge_summary tool to tell me what was loaded."
.github/workflows/ci.yml mirrors the template pipeline:
pnpm install --frozen-lockfilepnpm typecheckpnpm run buildpnpm test (unit)pnpm packscripts/integration-test.mjs installs the actual tarball into a fresh project, loads the installed bundle, registers bridge_summary through the real apply() / ctx.tools.register path, executes the real handler, and asserts the canonical result.dsh-smoke job (windows-latest): scripts/dsh-smoke.sh installs the tarball into a brand-new DSH_HOME, verifies the plugin row in --dump-config, boots dsh web with a 30s bounded retry, and cleans up the background process.For local end-to-end without dsh web (when C: is full or you cannot install @deepseek-ai/dsh):
pnpm pack
node scripts/local-skill.mjs D:/AgentRepo/GitRepo/GitRepo/tm-dagu-adapt
This loads the packed tarball into a real cordis Context, registers the first plugin.json it finds, registers its SKILL.md into the host skills service, and asserts bridge_summary.execute() returns the right counts.
pnpm typecheck and pnpm build passpnpm test passespnpm pack produces a tarballbridge_summary runtime invocation passes with an asserted result (integration script)dsh-pluginv0.1.0) with the packed tarballpnpm publish to npmERESOLVE peer dependency conflictThe host already has an older RC that does not satisfy ^0.1.0-rc.6.
Upgrade the host to the tested version or newer:
pnpm dlx @deepseek-ai/dsh --version # must print 0.1.0-rc.6 or later
Reinstall the plugin so it links against the upgraded host:
pnpm dlx @deepseek-ai/dsh plugin --profile web add <this-plugin>
Do not reach for --legacy-peer-deps to silence the error — the plugin's runtime guard will refuse to load if an incompatible version is linked anyway.
pnpm's default config can silently link an older RC into the plugin's peer slot. The plugin then refuses to load with:
dsh-agent-plugin-bridge: resolved @deepseek-ai/dsh-tools 0.1.0-rc.3, but this plugin is tested with ^0.1.0-rc.6. ...
0.1.0-rc.6 or later and reinstall.strict-peer-dependencies=true in your project/profile .npmrc.mcp ${server}: empty command after env expansionA plugin's mcp.json uses a ${SOME_ENV} placeholder that the host does not have. Two options:
loadPluginMcp: false in cordis.patch.yml and rely on a standalone mcp.json (e.g. ~/.cursor/mcp.json) instead.plugin.json with a name field — the bridge silently skips invalid manifests.pluginsDirs and pluginRoots; paths starting with ~ are expanded against homedir().skills service (this plugin declares inject = ['skills']).Bump TESTED_PEER_RANGE in src/index.ts, update package.json (peer + dev), regenerate pnpm-lock.yaml (pnpm install), and update the "Tested with" line in this README — all four together.
MIT
dsh-agent-plugin-bridge 是通用 Agent Plugins 1.0 → DeepSeek Harness 桥接插件:把它装进任何 DSH profile,
它就会扫描一组 plugin 根目录与 plugin 目录,挑出所有带 plugin.json 的包,把 skills/ 和 mcp.json
挂到宿主上。不按业务分叉——tm-dagu-adapt、agenthandoff 或任何未来符合 agent-plugins.org 规范的包都走同一条代码路径。
Fork 自 zoahdev/dsh-plugin-template: 沿用了模板的运行时 peer 版本守卫、捆绑的
cordis.patch.yml、单元 + 打包集成 + DSH 启动冒烟流程、双语 README。已验证版本:
dsh0.1.0-rc.6 · Node 24 · pnpm 11
├── package.json # dsh.bundle 清单 + 构建脚本(prepare 支持 git 安装)
├── cordis.patch.yml # 插件行:id、包名、默认 config
├── src/
│ ├── index.ts # 插件入口 + bridge_summary 工具 + 运行时版本守卫
│ ├── version.ts # 无依赖的 caret 范围匹配器(守卫使用)
│ ├── discover.ts # plugin.json + skills/ + mcp.json 发现
│ ├── expand.ts # ${VAR} 占位符展开
│ ├── mcp.ts # Agent Plugin MCP 与独立 mcp.json 注册
│ ├── skills.ts # SKILL.md 发现并写入宿主 skills 服务
│ └── types.ts # 共享线协议类型
├── tests/ # vitest:注册、行为、取消、解析
├── scripts/
│ ├── integration-test.mjs # 安装打包产物 → apply() → 执行真实 bridge_summary → 断言
│ ├── local-skill.mjs # 真 cordis 上下文里加载打包插件,加载真实 Agent Plugin(默认 tm-dagu-adapt),断言 bridge_summary
│ └── dsh-smoke.sh # 全新 DSH profile 安装 + 配置校验 + web 启动(限时重试)
├── .github/workflows/ci.yml # doctor → test → pack → integration → DSH 启动冒烟(windows-latest)
└── README.md # 双语
apply() 先跑 assertPeerCompatible(),解析到的 @deepseek-ai/dsh-tools
不满足 ^0.1.0-rc.6 就直接拒绝加载。把 pnpm 静默链接老 RC 变成响亮、可操作的报错。discoverPlugins(pluginRoots, pluginsDirs)。每个候选目录必须含 plugin.json 与 name 字段;
有 skills/ 与 mcp.json 就一并收下。skills/<folder>/SKILL.md 注册进宿主 skills 服务
(frontmatter 用一个免依赖的小解析器处理)。loadPluginMcp 为开时再把它自己的 mcp.json 注册到宿主 MCP 客户端。mcpJsonPaths,把每个独立的 mcp.json(典型:~/.cursor/mcp.json)也按同样规则注册——同样的线协议、同样的 ${VAR} 展开语义。bridge_summary 工具,agent 可以随时回头查"这一轮到底加载了什么"。mcp.jsonAgent Plugins 1.0 的包内 mcp.json 经常使用 ${SOME_ENV} 占位符,需要宿主里准备好对应变量;
在变量到位之前,启动时会报 empty command after env expansion。桥接给了两个旋钮:
loadPluginMcp(默认 true)——加载每个插件自己的 mcp.json。mcpJsonPaths——额外、独立于任何包的 mcp.json 文件。典型:~/.cursor/mcp.json,是用户级 MCP 配置,不依赖插件环境变量。环境变量没到位的时候,把 loadPluginMcp: false,桥接仍然能加载独立的那份。
cordis.patch.yml 自带默认值,需要在 profile config 里覆盖就覆盖:
- id: dsh-agent-plugin-bridge
name: dsh-agent-plugin-bridge
config:
pluginRoots: [] # 显式 Agent Plugin 包根
pluginsDirs: # 子目录会被扫描
- '~/.cursor/plugins/local'
mcpJsonPaths: # 额外的独立 mcp.json 文件
- '~/.cursor/mcp.json'
loadPluginMcp: false # 是否加载插件自己的 mcp.json(默认关:插件 mcp.json 经常依赖宿主环境变量)
failOnMcpError: false # MCP 启动失败时是否中止整桥
skillProviderLabel: agent-plugin
路径里的 ~ 会按 homedir() 展开。
@deepseek-ai/dsh-tools 0.1.0-rc.6、@deepseek-ai/cordis ^4.0.1。peerDependencies 声明 "@deepseek-ai/dsh-tools": "^0.1.0-rc.6"。这是 caret 范围,不是 pin:0.1.0-rc.6、后续 0.1.x 的 RC(rc.7、rc.10…),以及未来发布的 0.1.0 稳定版。0.1.0-rc.5 及更早 RC,也不匹配 0.0.1-rc.* 版本线。devDependencies 使用同一范围;提交的 pnpm-lock.yaml 把开发与 CI 固定到已验证的确切版本。0.1.0-rc.3)时,pnpm 默认配置会把旧版本链进插件的 peer 槽,只给一条泛泛的警告。
npm 则会以 ERESOLVE 响亮失败。两个工具都不会自动帮你升级宿主。插件在 apply() 里加了运行时版本守卫(src/version.ts 支撑),把静默不兼容变成清晰、可操作的报错。
按 dsh plugin add 标准流程安装:
pnpm install
pnpm build
pnpm test
pnpm pack
dsh plugin --profile web add ./dsh-agent-plugin-bridge-0.1.0.tgz
dsh web --port 4099
然后让 agent:"用 bridge_summary 工具告诉我加载了什么。"
.github/workflows/ci.yml 复刻模板流水线:
pnpm install --frozen-lockfilepnpm typecheckpnpm run buildpnpm test(单元)pnpm packscripts/integration-test.mjs 把实际 tarball 装进全新项目,加载已安装产物,
通过真实的 apply() / ctx.tools.register 注册 bridge_summary,执行真实 handler,断言返回结果。dsh-smoke job(windows-latest):scripts/dsh-smoke.sh 在全新 DSH_HOME 安装 tarball,
校验 --dump-config 里的插件行,30 秒限时重试启动 dsh web,并清理后台进程。本地端到端(不需要 dsh web、C: 盘满或者装不了 @deepseek-ai/dsh 时用):
pnpm pack
node scripts/local-skill.mjs D:/AgentRepo/GitRepo/GitRepo/tm-dagu-adapt
——把打包好的 tarball 装进一个真 cordis Context,加载第一个 plugin.json,把 SKILL.md 写入宿主 skills 服务,断言 bridge_summary.execute() 返回的计数。
pnpm typecheck 与 pnpm build 通过pnpm test 通过pnpm pack 产出 tarballbridge_summary 运行时调用通过并有明确断言(集成脚本)dsh-pluginv0.1.0)并附 tarballpnpm publish 发 npmERESOLVE peer 依赖冲突宿主已有不满足 ^0.1.0-rc.6 的旧 RC。
把宿主升到已验证版本或更新:
pnpm dlx @deepseek-ai/dsh --version # 必须打印 0.1.0-rc.6 或更新
重新安装插件,让它链接到升级后的宿主:
pnpm dlx @deepseek-ai/dsh plugin --profile web add <本插件>
不要用 --legacy-peer-deps 压掉错误——压掉以后运行时守卫照样会在版本不对时拒绝加载。
pnpm 默认配置可能把旧 RC 静默链进插件的 peer 槽。插件随后拒绝加载,报错形如:
dsh-agent-plugin-bridge: resolved @deepseek-ai/dsh-tools 0.1.0-rc.3, but this plugin is tested with ^0.1.0-rc.6. ...
0.1.0-rc.6 或更新,然后重装。.npmrc 里加 strict-peer-dependencies=true,让 pnpm 响亮失败。mcp ${server}: empty command after env expansion插件 mcp.json 用了 ${SOME_ENV} 占位符,宿主里没设环境变量。两种修法:
cordis.patch.yml 里把 loadPluginMcp: false,并依赖独立的 mcp.json(如 ~/.cursor/mcp.json)。plugin.json 且带 name 字段——桥接对非法清单会静默跳过。pluginsDirs 与 pluginRoots;以 ~ 开头的路径会按 homedir() 展开。skills 服务(本插件声明 inject = ['skills'])。同步改四处:src/index.ts 的 TESTED_PEER_RANGE、package.json(peer + dev)、
pnpm-lock.yaml(重新 pnpm install)、README 的"已验证版本"行。
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。