DeepSeek Harness Plugin Hub

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

探索

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

社区

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

相关链接

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

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

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

dsh-plugin-forge-cnb

Plugin Forge Cnb

用于 DSH forge registry 的 CNB(cnb.cool)提供程序:通过主机上的 CNB OpenAPI 读取合并请求、检查、差异、评审并执行合并。

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

npx -y @deepseek-ai/dsh plugin --profile web add github:genius-alray/dsh-plugin-forge-cnb#38117d1b18edee43042cb09cec6d616f0c2f5e50
README兼容性版本

兼容性与来源证明

Plugin Forge Cnb 以 dsh-plugin-forge-cnb 发布,当前版本为 0.1.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
any
发布来源
github
Registry 更新时间
2026/11/4

版本

0.1.0stable
2026/11/4

相关插件

正在加载相关插件…

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

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

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

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

认领这个 Plugin →
报告问题

相关插件

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

Web App@deepseek-ai/dsh-web-appdsh 浏览器界面捆绑包:位于 dsh-base 之上的 Web 补丁层,加上运行时粘合插件(提供前端 dist、Web 界面提示符、bash 运行时变量和 URL 行)Sdk Minimal@deepseek-ai/dsh-sdk-minimal独立的最小 SDK 配置包:JSON-RPC、一个 DeepSeek 适配器、持久化 Shell 和 JSONL 会话Sdk App@deepseek-ai/dsh-sdk-appdsh SDK 配置包:基于 dsh-base 提供 stdio JSON-RPC 服务和进程生命周期管理Experimental Inspector@deepseek-ai/dsh-experimental-inspector用于 Host 调试和 Client Runtime 检查的实验性跨 realm CDP hub

README

dsh-plugin-forge-cnb

GitHub: https://github.com/genius-alray/dsh-plugin-forge-cnb

CNB (cnb.cool) provider for the DSH forge registry. It registers a ForgeProvider with ctx.forge, so the “变更请求与工作树” (change request and working tree) panel can show CNB merge requests: state, additions/deletions, mergeability, checks, reviewers, diff, file contents, review publication, and merge.

This is a host-side bundle with zero runtime dependencies: global fetch and Node built-ins only, Node.js >= 22. No client or DSH package change is needed — registering the provider is enough.

What it adds

contract methodCNB source
repositoryFromRemote / changeRequestFromUrl / changeRequestUrlremote-URL and MR-URL parsing for https, ssh://, and scp-like remotes, nested groups (a/b/c), .git suffixes, ports; the two URL functions are exact inverses
fetchGET /{repo}/-/pulls/{n} + GET /{repo}/-/pulls/{n}/commit-statuses, plus per-head-commit totals (…/files), head commit date (…/git/commits/{sha}), and cached repository merge settings
fetchChecksthe same reads, always with the complete check list (no 50-row polling cap)
findByHeadGET /{repo}/-/pulls?state=open&page_size=100&page=N, filtered client-side (CNB has no head-branch filter)
diffGET /{repo}/-/pulls/{n}/files, assembled into one Git-style unified patch
fileText / fileUrlGET /{repo}/-/git/raw/{commit}/{path} (falls back to the base64 contents endpoint on HTTP 413), and the /-/blob/{commit}/{path} web URL
mergere-reads the MR, compares head.sha with the confirmed commit, then PUT /{repo}/-/pulls/{n}/merge with merge_style; never sends force
markReadyno API exists; returns a clear failure telling the user to edit the WIP title in the web UI
submitReviewPOST /{repo}/-/pulls/{n}/reviews with event and inline comments
readinessGET /user; an expired or missing token reads as unauthenticated and tells the user to run cnb login

Install

This is a DSH bundle distributed from GitHub rather than npm. Clone it, then install the checked-out directory as a bundle in your profile (for example with the Plugin Manager's install-bundle flow, or the plugin_manager tool with action: install_bundle):

git clone https://github.com/genius-alray/dsh-plugin-forge-cnb

The bundle ships its own cordis.patch.yml, which inserts the provider row; you pick the bundle, not the row. It needs Node.js >= 22 on the host and a valid cnb login session (~/.cnb/token, re-read whenever the CLI refreshes it).

Enable it

The bundle ships a Cordis patch, so enabling it in the profile is one entry:

- insert:
    - id: forge-cnb
      name: 'dsh-plugin-forge-cnb'
      config:
        hosts: ['cnb.cool']
        tokenFile: '~/.cnb/token'
        timeoutMs: 10000
        maxPages: 3
config fielddefaultmeaning
hosts['cnb.cool']web hosts this provider serves; repositories on other hosts are ignored
tokenFile~/.cnb/tokenCNB CLI credential file; CNB_TOKEN in the environment overrides it
timeoutMs10000deadline of one HTTP request, combined with the caller's cancellation
maxPages3pages of 100 open MRs findByHead reads per lookup

Nothing is written to any repository unless you explicitly merge or submit a review.

How a merge request binds to a session

The forge session layer discovers a session's change request by running git in the session checkout: it maps the checkout's remote to a repository (repositoryFromRemote) and then asks findByHead(repository, branch) for open MRs whose head is the current branch. Pasting a CNB MR URL into the session binds it directly (changeRequestFromUrl), and bindings are re-resolved through changeRequestUrl → changeRequestFromUrl, which is why those two are exact inverses.

gh command output parsing does not apply here — that is GitHub-CLI specific. For CNB the only binding paths are the git remote/branch discovery and a pasted MR URL.

Credentials

The provider reads ~/.cnb/token (written by the official cnb CLI) and takes .auths["cnb.cool"].access_token. The token is never printed or logged. A token lives ~8 hours:

  • the file is re-read when its mtime/size changes, so a cnb login refresh is picked up without a restart;
  • a 401 / errcode: 16 response is reported as unauthenticated with a message telling the user to run cnb login;
  • CNB_TOKEN can supply a token for one process instead of the file.

Scopes used: repo-pr:r (MRs, statuses, files), repo-code:r (commit, raw file), repo-manage:r (merge settings), repo-pr:rw (merge), repo-notes:rw (review). Missing scopes surface as HTTP 403 (errcode 10023) and are reported as unavailable/failed rather than crashing the panel.

Mapping decisions

  • updatedAt: CNB's MR detail carries no timestamps. It is the head commit's committer date (GET /{repo}/-/git/commits/{headSha}), cached per commit; when that read fails it is the first time this head commit was observed (stable across polls, not the time of every poll).
  • closedAt: always null. CNB exposes no closed_at/merged_at on merge requests at all.
  • unresolvedThreads: always 0. CNB has no resolved/unresolved flag on review comments anywhere in the API.
  • additions/deletions: sum of the MR's changed files. CNB caps that list (see limitations), so a very large MR's totals can read low; there is no MR-level statistics endpoint.
  • mergeability: conflict/no-merge-base (or blocked_on = code_conflict/no_merge_base) is conflicting; mergeable/merging/merged is mergeable; everything else is unknown.
  • mergeReady: state == open && !is_wip && !is_merged && mergeable_state == mergeable && blocked_on == unblocked — mergeable_state alone is not enough (a mergeable MR can still wait for review or CI).
  • reviewDecision: changes_requested on any reviewer wins, then all-approved is approved, otherwise review-required; no reviewers is none.
  • checksRollup: CNB's aggregate state of commit-statuses is used directly (success/failure/ error/pending); individual success|pending|failure|error|skipped items become check rows with created_at/updated_at as start/completion times, capped at 50 in polling snapshots (checksTruncated) and complete in fetchChecks.
  • mergeMethods: from GET /{repo}/-/settings/pull-request (allow_merge_commit_merge, allow_squash_merge, allow_rebase_merge), cached per repository for 5 minutes; if it cannot be read (for example a token without repo-manage:r), the default set [merge, squash, rebase] is offered so the merge button does not disappear.

Diff format

The panel parses diff() with jsdiff 9.0.0 (parsePatch), which resolves a file's path from diff --git / --- / +++ headers and silently drops a section that has only hunks. CNB's /pulls/{n}/files returns hunks only and reports the file basename in filename, so this provider:

  1. recovers the full repository-relative path from blob_url/raw_url/contents_url (…/-/blob/{sha}/{path}), never from filename;
  2. emits per file: diff --git a/<path> b/<path>, new file mode 100644/deleted file mode 100644, --- a/<path> + +++ b/<path> (or /dev/null on the missing side), then the recorded hunks byte-for-byte, with LF line endings and a trailing newline;
  3. renders an empty patch (add/delete/modify) as Binary files … differ, which jsdiff records as isBinary, instead of an empty change;
  4. keeps rename origins when a payload exposes previous_filename; a CNB rename otherwise renders as a change of the new path.

This is covered by an offline unit test that parses the assembled patch with the real jsdiff copy when it is discoverable and skips otherwise.

Known limitations

  • WIP cannot be cleared through the API: is_wip is read-only on CNB, so markReady always fails with a message asking the user to edit the title in the web UI. The provider never PATCHes the title.
  • The changed-file list is hard-capped at 300 entries even though CNB documents it as unpaginated (a verified 490-file MR returns 300). additions/deletions and diff() therefore cover at most 300 files for a very large MR; there is no truncation flag to expose and no workaround endpoint.
  • Rename origin is not recoverable from the MR file list; a rename renders as a change of the new path (no rename from header) unless the payload happens to carry previous_filename. Only GET /{repo}/-/git/compare/{base}...{head} exposes it, and that endpoint shares the 300-file cap.
  • No close/merge timestamp (see closedAt), so the panel cannot show when an MR was merged or closed.
  • Resolve state of review threads is unavailable (see unresolvedThreads).
  • Merge refusal shape is unverified: CNB documents 403 (die.WebError) but may answer 200 with merged:false; both are handled as failed with the host message. fast_forward is a valid CNB merge_style but not part of the forge contract's method set, so it is not offered.
  • Fork merge requests: CNB bakes the base repository path plus the head commit into the file URLs, and the base repository refuses a raw read of a foreign commit (HTTP 400 errcode 3). The provider detects a fork via head.repo.id !== base.repo.id (or differing paths), caches the head repository per change request, and reads fileText/fileUrl from head.repo.path. Before the first poll it learns the head repository from one MR detail read when the base read fails.
  • The diff/hunks are whatever the host returns: this provider does not re-number hunks or trim lines, because a count mismatch would make the panel's parser throw.
  • Custom hosts: only cnb.cool is tested; for another host the API base is derived as https://api.<host> and the token must exist under that host key in the token file.
  • No rate-limit headers are exposed by CNB; the provider does no adaptive throttling.

Development

npm install        # dev dependency: jsdiff, the same parser the panel host uses
npm test           # 85 offline unit tests (fixtures + fake fetch); live test skipped
npm run check      # node --check on every source and test file

The unit tests never touch the network: they load the synthetic responses under tests/fixtures/ and inject a fake fetch. Two format tests parse the assembled patch with the panel's own jsdiff copy; they skip when the dev dependency is not installed. Write paths (merge, review) are covered only by fake-fetch tests; this package was never used to write to a real repository.

An optional read-only smoke test runs against any repository and merge request you can read:

CNB_LIVE=1 CNB_LIVE_REPO=owner/repo CNB_LIVE_MR=12 node --test tests/live.test.js

  • review body: POST /pulls/{n}/reviews takes event + inline comments; an empty review body is omitted instead of sent as "". Inline comments use the same full repository paths as diff().