DeepSeek Harness Plugin Hub

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

探索

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

社区

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

相关链接

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

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

Bulk Scrna Concordance — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
B

@local/dsh-bulk-scrna-concordance

Bulk Scrna Concordance

作为代理工具提供的 Bulk RNA-seq 与 scRNA-seq 伪批量一致性分析。

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

npx -y @deepseek-ai/dsh plugin --profile web add github:Wanner122333/dsh-bulk-scrna-concordance#22bbce8c2a20038ec97164ee43687241bd20adb8
README兼容性版本

兼容性与来源证明

Bulk Scrna Concordance 以 @local/dsh-bulk-scrna-concordance 发布,当前版本为 1.0.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

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

版本

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

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

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

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

认领这个 Plugin →
报告问题

README

Bulk–scRNA Concordance — DSH Host plugin

Turns the TBtools Transcriptome Integration — Bulk & scRNA Correlation plugin into an agent-callable analysis tool in the DeepSeek Harness.

The original .plugin package contained a 118 MB PyInstaller-encrypted EXE plus a TBtools Java GUI shell. This bundle replaces both: the numerics live in a readable Python script inside the package, and the Harness registers a tool the agent can call directly.

  • Full parameter reference, input formats and interpretation: docs/usage.md
  • Runnable input fixtures: examples/synthetic/ (600 genes × 6 cells, disjoint group markers)
  • Survey of the neighbouring DSH plugin ecosystem: docs/github-survey.md
  • CI runs the analysis on those fixtures on Linux and Windows: .github/workflows/checks.yml

What it adds

One tool: bulk_scrna_concordance.

For each group (L1/L2/L3 …) it sums single-cell counts into a pseudo-bulk profile, CPM-normalizes both sides over the shared genes, applies log2(x+1), and reports Pearson r, Spearman rho, and a linear fit.

With discriminability: true it also correlates every pseudo-bulk group against every bulk group and reports:

  • matched vs mismatched mean r and their gap
  • whether each pseudo-bulk group best-matches its own bulk group

Do this whenever the correlation is meant as evidence. A single high r cannot show that a correlation is meaningful, because any two transcriptomes from the same experiment correlate strongly; the discriminability block can.

Files

FileRole
package.jsonbundle manifest (dsh.bundle.patch), display metadata, dependency declarations
cordis.patch.ymlinserts the Host plugin row and its config
index.jsregisters the tool, validates arguments, launches the analysis, reads the result JSON
python/bulk_scrna_concordance.pythe analysis itself
locale/{en,zh}.jsonPlugin Manager card text

This bundle declares no npm dependencies and imports nothing outside node:. A Host-only bundle needs none, and a dependency would make installation require the npm registry. The tool definition is therefore a plain registry-ready object with JSON Schema parameters, plus the local argument check that defineTool would otherwise supply. Config is declared as JSON Schema for the same reason.

Prerequisite: a Python interpreter with the scientific stack

The analysis needs anndata, h5py, scipy, pandas, numpy, matplotlib. The interpreter that ships inside DSH has only numpy and pandas, so it is not sufficient for .h5ad input.

Check a candidate interpreter:

python -c "import anndata, h5py, scipy, pandas, numpy, matplotlib; print('ok')"

Then point the plugin at it. The shipped cordis.patch.yml assumes python on PATH; override it in your profile's own cordis.patch.yml:

- id: bulk-scrna-concordance
  name: "@local/dsh-bulk-scrna-concordance"
  config:
    pythonPath: /usr/bin/python3        # or C:/Python313/python.exe
    defaultTimeoutMs: 1800000
    maxLogLines: 40

An absolute pythonPath is recommended: the Host's PATH is not guaranteed to match your shell's.

If the interpreter is wrong the tool returns a clean failure naming the path and listing the packages it needs — it does not throw.

Install

git clone https://github.com/<you>/dsh-bulk-scrna-concordance

Then install the checkout into a profile. In the Harness Web UI:

  1. Open Settings → Plugins.
  2. Install a bundle, with the absolute path of the directory containing package.json as the target (e.g. /home/me/dsh-bulk-scrna-concordance or C:\src\dsh-bulk-scrna-concordance).
  3. Read the returned application field. applied means it is live; restart-required means it is not yet.

From a shell, where a dsh CLI is available:

dsh plugin --profile <profile> add /abs/path/to/dsh-bulk-scrna-concordance

That installs the package, links it into node_modules and adds it to dsh.profile.bundles. It writes no row into the profile's cordis.patch.yml, so add the config row yourself if you need a non-default pythonPath (see above).

Notes:

  • @local/... is a deliberate scope: this package is meant to be installed from a path or a git checkout, not published to npm.
  • The installer performs package installation and bundle selection. Do not hand-edit the profile's package.json or cordis.patch.yml to select a bundle, and do not run pnpm in the profile directory.
  • A fresh bundle can activate through HMR. Replacing an already-installed package requires a restart to load the new JavaScript generation.
  • The Desktop app owns the desktop profile and the dsh CLI refuses to write it; install from inside the app there.

Verify

  1. The tool row exists and is enabled (Plugin Manager, or cordis_inspect_query).

  2. Run it on real data and confirm the tool result, not just the log:

    bulk_scrna_concordance with
      sc_h5ad        /path/to/scRNA_with_celltype.h5ad
      bulk_csv       /path/to/bulk_FPKM.csv
      group_col      Group
      discriminability true
      out_dir        <somewhere writable>
    

    Expected on the dataset this was developed against (verified — see below):

    groupPearson rSpearman rhon_genes
    L10.87260.860621843
    L20.88440.878222206
    L30.87720.874822104

    and discriminability: matched 0.8781, mismatched 0.8213, gap 0.0568, correct=2/3, misassigned: ["L1->L2"].

What was fixed relative to the original

  1. --strip_version was a dead switch. It was action="store_true" with default=True, so it could never be turned off. It is now --strip-version / --no-strip-version, default off.
  2. Duplicate gene IDs after version stripping crashed the analysis. The original truncated at the first . with no dedup, then pseudo_df.loc[common_genes, g] returned a DataFrame for a duplicated label and died with ValueError: operands could not be broadcast together with shapes (n,) (m,). Duplicate IDs are now collapsed explicitly (values summed) and the count is reported.
  3. Bulk sample-to-group matching was ambiguous. startswith/endswith /substring tests silently mis-assigned groups that are prefixes of one another (L1 vs L10). Matching now uses exact delimited tokens, and unmatched samples are reported instead of dropped quietly.
  4. The nan group was treated as a real group. In the original dataset 3440 cells have no group label, and the original built a pseudo-bulk column for them. They are now excluded and reported.
  5. Added the discriminability assessment described above.
  6. Added --results-json so a caller reads one structured object instead of scraping stdout (stdout is a log file here, for the sandbox reason below).
  7. Run parameters are recorded in the result JSON for reproducibility.
  8. The figure no longer emits a tight_layout warning.

One deliberate numeric change

CPM normalization is computed over the genes actually used in the correlation (the shared, informative set), not over the whole shared gene list as in the original. Pearson r and Spearman rho are identical to the original for this reason — they are invariant to a linear rescaling of either axis. The fitted slope/intercept are on a different scale: e.g. L1 slope is 0.901 here vs 0.845 in the original. Scale-free reporting should quote r, not the slope.

Normalization is now explicit

--normalize {cpm,tpm,none} (tool argument normalize), default cpm:

  • cpm — the historical behaviour, and what every published number above used.
  • tpm — also divides by gene length. Needs --sc-lengths-col (an .h5ad var column) and --bulk-lengths-col (a bulk column, excluded from the expression matrix). Lengths must be present on both sides or the run stops, rather than silently falling back.
  • none — inputs already on a common scale.

The choice is recorded in the results JSON and the manifest, because it changes the fitted slope even though it barely moves r.

Why stdout is a file rather than a pipe

Under the Harness file sandbox, child processes may not use piped stdio (spawnSync ... EPERM); stdio: 'inherit' and raw file-descriptor redirection both work. The plugin opens a descriptor on <out_dir>/<prefix>_run.log, gives the child a duplicate of it, then reads the tail back for diagnostics. The machine-readable result does not travel over stdout at all — it is read from the JSON file the script writes.

Outputs

Everything lands in out_dir:

FileContent
<prefix>_manifest.jsonprovenance: script hash, input/output SHA-256, params, seed, environment lock
<prefix>_results.jsonschema dsh.bulk-scrna-concordance/1: parameters, per-group stats, discriminability matrix, warnings, environment
<prefix>_bulk_scrna_correlation_stats.csvone row per group
<prefix>_discriminability.csvthe pseudo × bulk Pearson matrix
<prefix>_bulk_scrna_correlation.{png,pdf,svg}density scatter with regression and y=x lines
<prefix>_run.logfull analysis log

Provenance

Every run writes a manifest answering "this figure = which code + which inputs + which parameters + which environment":

  • script hash — the analysis script's own SHA-256, so a figure produced by a modified script is detectable;
  • input hashes — SHA-256, byte size and mtime for the .h5ad and bulk matrix. An input that changed silently between runs is otherwise invisible;
  • environment lock — python, numpy, pandas, scipy, anndata, h5py, matplotlib and the seed. anndata decides how .X/.raw are read and scipy computes every statistic here, so those two are the versions that can actually move a reported r; recording only numpy/pandas would miss them;
  • output hashes — every produced file, so a figure can be checked against the run that claims to have made it;
  • command line and timestamps.

Nothing in this analysis is stochastic. The manifest records seed: 42 anyway, so that is a checkable claim rather than an assumption.

This follows the provenance model of poplarity/dsh-science-workbench (see docs/github-survey.md), minus the project/cell/feedback machinery that belongs to a workbench rather than to one analysis.

Pass --no-manifest to skip it.

The figure does not appear in the conversation, by platform design

A tool result cannot carry a picture. The Harness attachment documentation is explicit that the role-neutral ImageBlock leaves assistant-side image output as forward compatibility, and that current production adapters declare text-only output, so only user content carries images. An ImageBlock also needs an attachmentId minted by the attachments service, and that service is not mounted in every profile.

The render therefore emits the path plus a Markdown image reference, and states that surfacing the figure as a card in the Web UI needs a separate present call with the file path. Without that second call a user sees only a path and may reasonably conclude no figure was produced at all.

Verification status

Performed, and reproducible:

  • Python layer — full run on the real 720 MB .h5ad and the real bulk matrix; per-group r reproduced to 1e-9 against an independent recomputation; discriminability matrix matches an independent 3×3 computation exactly.
  • Node layer — the registered tool was exercised through a stub ctx.tools in five cases: invalid input combinations rejected; a bad pythonPath returned a clean failed object; a real analysis returned status: ok with the expected statistics; render() produced the expected model-facing text for both success and failure; and disposing the registration removes the tool.
  • Manifest — package.json parses, all exports targets exist, every file in the bundle validates as UTF-8, node --check passes on index.js, py_compile passes on the script.
  • Composition against the real Loader — the bundle's patch was applied to a scratch profile through dsh --profile <name> --patch … --dump-config; the row appears in the composed tree with its id, resolved module URL and full config, and the tree composes without error.
  • Installed into the desktop profile with dsh plugin --profile desktop add <bundle dir> (pnpm link:, no registry access needed). Confirmed afterwards: the bundle name is in dsh.profile.bundles, the dependency is in package.json, and node_modules/@local/dsh-bulk-scrna-concordance resolves to this directory. The profile patch carries a matching bulk-scrna-concordance row whose row id overrides the bundle's default config, so pythonPath points at D:/Python/python.exe.
  • API contract read from the installed Harness, not assumed: ctx.tools.register() was read at dsh-tools/lib/index.js:2878 and requires output.{schema,render} plus a schema accepted by assertSupportedJsonSchema — it does not require a defineTool() result, which is what makes the dependency-free form valid. The supported keyword set is type/oneOf/properties/required/additionalProperties/items/enum/const plus description/title/default/examples; this bundle uses only those.
  • Live activation and a live tool call, through a real Harness agent. A scratch headless profile ( + + this bundle) was booted with . The agent called once on the real and bulk matrix and reported with r = 0.873 / 0.884 / 0.877 and gap 0.0568 ( misassigned) — matching the independently computed values exactly. All six output files were written to the requested directory.

Two traps worth knowing, both hit while installing this

  1. Do not export Config unless its schema library resolvable from the plugin. Cordis resolves an exported Config through schemastery (resolveConfig calls Config.validate). @deepseek-ai/schemastery is not resolvable from a bundle installed by path, so an exported Config makes the plugin fail to activate with:

    bulk-scrna-concordance (@local/dsh-bulk-scrna-concordance):
    TypeError: Cannot read properties of undefined (reading 'validate')
    

    Config is optional, so it is omitted here and the row's config is read defensively in apply(). The symptom is a silent missing tool: the row composes, but only a boot-time warning says 1 entry did not activate.

  2. A newly installed bundle needs a restart. dsh plugin --profile desktop add <path> installs and selects the bundle, but writes no row into the profile's cordis.patch.yml (unlike install_bundle), and the running app does not pick up the new JavaScript generation. Both were needed here: the install, then a restart.

Scratch profile used for verification

~/.dsh/profiles/concordlive — dsh-base + the shipped dsh-headless bundle + this bundle, with a patch row supplying pythonPath. It is what produced the live verification above, and is safe to delete:

dsh plugin --profile concordlive remove @local/dsh-bulk-scrna-concordance

Note dsh plugin … add @deepseek-ai/dsh-headless installs the registry copy, which is 0.0.1-rc.1 and is rejected as incompatible with dsh 0.2.0-rc.2; the shipped bundle inside the installation is 0.2.0-rc.2 and is selected by name from dsh.profile.bundles, which is what this profile does.

exec.agent.session.cwd is read defensively for relative-path resolution; if that field is absent in the installed version, paths fall back to the Host's working directory, so passing absolute paths always works.

base
dsh-headless
dsh --profile <name> "<task>"
bulk_scrna_concordance
.h5ad
status: ok
L1→L2