DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Agent Bridge — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
A

dsh-agent-bridge

Agent Bridge

通过数据驱动的配方,将 DeepSeek Harness 连接到已安装的任意 coding-agent CLI(OpenCode、Claude Code、Codex、Gemini 等):自动发现、基于能力的 UI、每次运行的报告。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:mike-sl-ig/dsh-agent-bridge#38603f4365b96aa7494d0d6d6d403d760028affb
README兼容性版本

兼容性与来源证明

Agent Bridge 以 dsh-agent-bridge 发布,当前版本为 0.4.5。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/16

版本

0.4.5stable
2026/10/16
0.4.2stable
2026/10/16
0.4.1stable
2026/10/13
查看其余 2 个版本收起版本
0.4.0stable
2026/10/12
0.1.2stable
2026/9/30

相关插件

正在加载相关插件…

最新版
0.4.5
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 1
周下载
0
最近提交
2026/10/16
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 integrations-communication 分类下经过校验的插件。

Acp App@deepseek-ai/dsh-acp-appdsh ACP 配置文件包:基于 dsh-base 的仅限自动化的 JSON-RPC stdio 和进程生命周期管理Ab Publishdsh-ab-publish浏览器自动化发布工具,可登录任意网站并发布内容,整合为一个可发布的插件包Ab Wechat Scrapedsh-ab-wechat-scrape--- description: "树外 wechat_scrape 工具:获取微信公众号文章,过滤推广区块,并将每篇文章保存为 Markdown 文件,供此机器的 dsh 配置文件维护者使用。" kind: "package-reference" ---Remote Web Ui@linxin666/dsh-remote-web-ui通过扫码配对访问 dsh Web GUI,共享一个官方界面:设置按钮旁的二维码可将手机和 PC 配对到同一个 Web GUI(手机采用竖屏触控适配层,PC 使用完整桌面界面),通过一次性令牌和 r

README

dsh-agent-bridge

English | 简体中文

Bridge DeepSeek Harness to whatever coding-agent CLI your machine already has — OpenCode, Claude Code, Codex, Gemini, or anything you write a recipe for — and use it as an independent worker for cross-model verification, cheap bulk work, or a second opinion.

The plugin never hard-codes a vendor. An agent is described by a JSON recipe, so adding one — or fixing one whose CLI changed its flags — is a data change, not a code change. Recipes are data on purpose: that is what makes it safe to fetch them from a community registry later.

What it gives you

  • A button in the session header. Switch on a pool of candidate agents (each keeps its own model picker), enable any of the three role features, and see what the last run did. An unnamed call uses the first installed pool member; defaultAgent stays in the state file for 0.3.x consumers.
  • Three tools the model can call:
    • agent_list — which agents were found, where, what they cost, what they support (probe: true also runs --version).
    • agent_run — run one agent as an independent worker; returns the answer, session id, timing, tool calls and the path of a run report.
    • agent_mode — read/change the state the button shows.
  • A report per run: a Markdown file (prompt, answer, tool calls, tokens, cost, raw log paths) plus last-run.json for the panel.

Install

From npm (once published):

dsh plugin --profile <your-profile> add dsh-agent-bridge

Or straight from a release artifact, without npm:

dsh plugin --profile <your-profile> add https://github.com/mike-sl-ig/dsh-agent-bridge/releases/download/v0.1.1/dsh-agent-bridge-0.1.1.tgz

Or from a checkout:

dsh plugin --profile <your-profile> add /absolute/path/to/dsh-agent-bridge

Then reload the page (a new client plugin only appears after the page loads the client graph again). Nothing is installed beyond this package: it declares no runtime dependencies and no install-time lifecycle hooks.

Roles

modewhat the worker is told
defaultnothing extra
verifyindependent verifier from a different model family; tools forbidden, one pass
bulkcheap mechanical worker; prefer direct answers, no self-checking with tools
secondindependent second opinion; tools forbidden, one pass

The tool prohibition is not cosmetic. Measured: an open-ended verifier task with a tool belt spent 11 tool calls and never answered (180 s timeout), while the same question with tools forbidden answered correctly in 8 s.

Writing a recipe

Drop a JSON file in lib/recipes/. lib/recipes/opencode.json is the reference.

{
  "id": "my-agent",
  "label": "My Agent",
  "cost": "free",                     // free | paid | unknown
  "discover": {
    "env": ["MY_AGENT_CLI"],          // explicit override wins
    "bin": ["my-agent"],              // looked up on PATH
    "paths": { "win32": ["%LOCALAPPDATA%\\MyAgent\\my-agent.exe"],
               "darwin": ["/opt/homebrew/bin/my-agent"],
               "linux":  ["~/.local/bin/my-agent"] }   // `*` segments allowed
  },
  "version": { "args": ["--version"], "match": "my-agent" },
  "run": {
    "argv": ["exec", "--json"],
    "prompt": { "via": "positional" },   // or "stdin", or a flag name like "-p"
    "model":   { "flag": ["--model"] },
    "session": { "flag": ["--session"] },
    "resume":  { "flag": ["--continue"] },
    "files":   { "flag": ["--file"] }
  },
  "output": {
    "format": "jsonl",                   // jsonl | json | text
    "answer":  { "where": { "type": "text" }, "pick": "part.text" },
    "session": { "pick": "sessionID" },
    "tool":    { "where": { "type": "tool_use" }, "name": "part.tool",
                 "input": "part.state.input", "status": "part.state.status", "error": "part.state.error" },
    "usage":   { "where": { "type": "step_finish" }, "cost": "part.cost",
                 "input": "part.tokens.input", "output": "part.tokens.output",
                 "reasoning": "part.tokens.reasoning", "cacheRead": "part.tokens.cache.read" }
  },
  "caps": { "model": true, "session": true, "resume": true, "files": true },
  "models": ["provider/model-a", "provider/model-b"]
}

Field notes:

  • output.format: "text" treats the whole stdout as the answer — the honest fallback for a CLI you have not reverse-engineered. It is not a guess: nothing is silently discarded.
  • pick is a dotted path into the parsed object; where is a flat equality filter on the event object.
  • discover.derive: append templates (node_modules/<pkg>/<entry>) resolved next to a discovered shim. Derived entries always outrank the shim they came from, because a .ps1/.cmd cannot be spawned without a shell. This is how Claude Code works: npm installs claude.ps1/claude.cmd, while the real entry is .../@anthropic-ai/claude-code/bin/claude.exe.
  • output.errorFlag: a path that forces Ok=false when truthy, even on exit code 0. Claude Code exits 0 and sets is_error instead of failing the process.
  • output.usage covers both output shapes: with format: "json" the paths are read once from the single object (total_cost_usd, usage.input_tokens, num_turns); with jsonl they are summed over the matching events (step_finish → cost/tokens).
  • catalog: where the model list really comes from — { kind: "jsonFile", path: [ … ], pick: "models", map: { id, label, credits, vendor }, excludeTags: [ … ], ttlMs }. The first path that reads wins, the result is cached for ttlMs, and any failure (missing file, bad JSON, empty list) degrades to the recipe's own models with the reason in catalogError. models accepts the 0.1.x string[] and { id, label?, tier?, credits?, vendor? } objects.
  • balance: the account balance, read-only by construction — { kind: "http", base, loginProbe, summary, map, unit }. Exactly the two calls the recipe names are ever issued; no credential means unauthenticated without a request, and the four states (ok / unauthenticated / unsupported / error) never render a made-up number. A balance.write block is rejected by the validator: the plugin cannot describe a call that mutates an account.
  • interpreter: { "source": "self" } runs a JavaScript agent CLI through the Node that is already hosting the plugin, instead of handing a file to the OS.

Two shapes, both shipped and tested

recipetransportoutputcostgotcha the recipe encodes
opencode.jsonpositional prompt, --format jsonJSONL eventsfreethe answer is the concatenation of type=text events; cost only appears on tool-calling steps
claude.json-p + positional prompt, --output-format jsonONE json objectpaidnative binary behind an npm shim (derive); a failed run still exits 0 (errorFlag)
workbuddy.json-p + positional prompt, --output-format jsonONE json objectpaidthe CLI is a .js file, so it needs interpreter.source: "self"; two model catalogs (account-level first, install bundle second)

WorkBuddy

Tencent CodeBuddy Code. The desktop build ships only the headless bundle (dist/codebuddy-headless.js; there is no dist/codebuddy.js), so the interactive /login command does not exist in this install and the CLI has no login/auth subcommand. Authentication therefore comes from the environment (CODEBUDDY_AUTH_TOKEN); without it the CLI exits with Authentication required and the panel shows 「余额:未登录」 — the honest state, not a number. The model picker still works: it is read from the account-level catalog (%USERPROFILE%\.workbuddy\cache\acc-product-config-v3.json) with the install bundle's product.json as fallback, and each entry carries its 免费 / 付费 x0.21 badge.

Each recipe has a recorded real fixture in fixtures/ (shipped inside the package); npm test replays it, so a recipe whose CLI changed behaviour fails before it fails for a user.

Why a recipe and not code

Recipes are JSON so they can be reviewed and distributed without executing anything. Code-shaped adapters would mean "install this plugin and it will run whatever a registry hands it".

Adding an agent without a release

Both supported ways are data-only:

  1. Locally — agent_recipe with action: "draft" runs a CLI once and hands back a draft recipe plus every candidate field it found (the evidence, not just a conclusion). action: "save" validates and writes it to <DSH_HOME>/tools/agent-bridge/recipes/, where agent_list picks it up immediately. A local recipe wins over a bundled one with the same id, so a shipped recipe can be corrected without waiting for a release.
  2. From a registry — agent_recipe with action: "import" and an http(s) URL returning a recipe, an array, or {"recipes":[…]}. Every candidate is validated in strict mode (an unknown top-level key is an error, not a warning), oversized and non-JSON payloads are refused before parsing, and every import is recorded in _provenance.json. Nothing in a payload is ever executed — a recipe is JSON read by this plugin's own engine, which is precisely why distributing recipes is safer than distributing adapters.

Publishing

npm test runs fifteen suites offline (no network, no DSH, no agent CLI, nothing to install — the package has no runtime dependencies). pack-check.mjs packs the package with npm pack --dry-run and asserts that the manifest only promises files that are really inside the tarball, that no install-time lifecycle hook exists, and that tests/, node_modules/ and dotfiles stay out. Current payload: 19 files, ~50 KiB, zero runtime dependencies.

CI runs that suite on ubuntu / macos / windows × node 20 / 22, which is what backs the cross-platform claim; the runs that need a real agent CLI (and, for the paid adapter, real credits) are opt-in through LIVE_PAID=1 / LIVE_TOOLS=1 and stay out of CI.

Notes for contributors

  • Never auto-execute a discovered binary. Discovery is read-only (PATH, known install paths, --version). Running an agent requires an explicit call or an explicit default-agent choice.
  • Costs are real. A paid recipe spends the user's money; the panel warns before a paid agent is selected.
  • tests/parse-recorded.mjs replays every recorded agent stream on this machine through the parser; add a recorded fixture when you add a recipe.
  • tests/launch-smoke.mjs runs one real agent call end-to-end without DSH.
  • Paid recipes are opt-in in the tests too: LIVE_PAID=1 node tests/host-harness.mjs additionally drives a real Claude Code run. The default npm test never spends money.
  • Local-development hazard, measured twice on 2026-09-30. Reconciling a profile that link:s your working copy — for example swapping that dependency for a packed tarball — can leave the linked directory empty, because pnpm's reconciliation follows the link. The failure is silent, and a profile that links to your only copy will then fail to load the plugin on the next start. Keep the tree somewhere no profile links to (or a backup), and re-run npm test after changing a profile's dependencies.
  • Processes are started through ctx.subprocess when it is available (argv vector, no shell) and fall back to node:child_process with real file descriptors. Pipes are deliberately avoided: an agent CLI whose stdout is an inherited pipe can write its whole answer and then never exit.

License

MIT

.js
  • Unknown agents still work: point prompt.via at whatever flag the CLI takes and set format: "text".