dsh-molbio-tools 0.21.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/README.md +7 -7
- package/benchmark/README.md +1 -1
- package/benchmark/profile.mjs +2 -1
- package/build/preset-patch.mjs +101 -41
- package/cordis.patch.yml +187 -25
- package/docs/history.md +24 -0
- package/docs/maintainer.md +6 -5
- package/docs/roadmap.md +6 -1
- package/docs/store-evidence.md +152 -0
- package/docs/store-preset-exemption-issue.md +46 -0
- package/docs/store-preset-exemption.md +231 -0
- package/docs/workflow.md +3 -3
- package/package.json +11 -7
- package/preset/install.mjs +4 -4
- package/preset/molbio-lab/agent.cordis.yml +7 -7
- package/test/contract.mjs +18 -4
- package/test/drift-probe.mjs +1 -1
- package/test/preset-health.mjs +1 -1
- package/test/preset-rows.mjs +4 -3
- package/packages/molbio-panel/README.md +0 -63
- package/packages/molbio-panel/cordis.patch.yml +0 -7
- package/packages/molbio-panel/index.mjs +0 -33
- package/packages/molbio-panel/lib/client.js +0 -9113
- package/packages/molbio-panel/package.json +0 -57
- package/preset/molbio-lab/preset.patch.yml +0 -170
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,97 @@
|
|
|
10
10
|
改为按**包名**引用后模块缓存问题随之消失——没有拷贝,也就没有需要保持同步的版本目录。
|
|
11
11
|
下文历史条目里出现的 `vN` 目录保持原样,作为当时的记录。
|
|
12
12
|
|
|
13
|
+
## [0.21.1] — 2026-10-25(DSH STORE 提交前置:一个 patch、逐版本兼容声明、一个 tarball 一个清单)
|
|
14
|
+
|
|
15
|
+
**工具数不变(60),插件运行时行为零改动。** 这一版不加任何计算能力,只把"这个包以什么形状提交"
|
|
16
|
+
改成 DSH STORE 的提交预检与 DSH 自身的清单契约**都能接受、且不再互相矛盾**的那一种。三处改动都
|
|
17
|
+
来自同一次上架提交:预检里能靠改包解决的两条已经解决,剩下两条的原理与请求另写在
|
|
18
|
+
[docs/store-preset-exemption.md](docs/store-preset-exemption.md)。
|
|
19
|
+
|
|
20
|
+
### 1. 两层 patch 合并成单个 `cordis.patch.yml`
|
|
21
|
+
|
|
22
|
+
0.21.0 的 `dsh.bundle.patch` 是**有序数组**:`["./cordis.patch.yml", "./preset/molbio-lab/preset.patch.yml"]`。
|
|
23
|
+
DSH 运行时接受这种写法(`@deepseek-ai/dsh-app-boot` 的 `bundlePatchPaths`:one file, or an
|
|
24
|
+
ordered list of files),官方 `@deepseek-ai/dsh-web-app` 自己就列了 5 个文件;但 DSH STORE 的提交
|
|
25
|
+
预检(`scripts/check-plugin-submission.mjs` 的 `safePatchPath`)只接受字符串,数组直接判
|
|
26
|
+
`SUBMISSION_BUNDLE_PATCH_INVALID`。两边都自称官方契约,解法不必等预检放宽:
|
|
27
|
+
|
|
28
|
+
- `build/preset-patch.mjs` 现在直接产出**根目录的 `cordis.patch.yml`**,内容是**两个 insert**:
|
|
29
|
+
`molbio-client → ./host.mjs`(惰性宿主锚点)在前,`preset-molbio-lab`(由
|
|
30
|
+
`preset/molbio-lab/agent.cordis.yml` 生成的 preset 行)在后;顺序即应用顺序。
|
|
31
|
+
- 不再生成 `preset/molbio-lab/preset.patch.yml`(文件已删);`package.json` 的
|
|
32
|
+
`dsh.bundle.patch` 是**单字符串**。
|
|
33
|
+
- 四个读者改为跟单文件走:`test/preset-health.mjs`、`test/drift-probe.mjs`、
|
|
34
|
+
`preset/install.mjs`、`test/preset-rows.mjs`(后者在同一个文件的两个 insert 里找 preset 段,
|
|
35
|
+
不假设"preset.patch.yml 才是 preset")。
|
|
36
|
+
|
|
37
|
+
> 这一条同时守住一条更早的教训:**锚点行不能因为"文件变少了"而消失**。0.15.2 的两个侧栏 tab
|
|
38
|
+
> 就是锚点丢失后静默消失的;`test/client-mount.mjs` 仍然逐包断言"被选中的包必须有一个宿主行
|
|
39
|
+
> 能解析到它",`test/contract.mjs` 仍然断言"产物里的每一处 `register` 都在 `inject` 里"。
|
|
40
|
+
|
|
41
|
+
### 2. `engines.dsh` 与逐版本 `dshReleases`
|
|
42
|
+
|
|
43
|
+
两个 manifest 各声明一份:
|
|
44
|
+
|
|
45
|
+
```jsonc
|
|
46
|
+
"engines": { "node": ">=26", "dsh": ">=0.2.1-rc.2 <0.3.0-0" },
|
|
47
|
+
"dsh": { "compatibility": { "dshReleases": {
|
|
48
|
+
"0.2.1-rc.1": "unknown", "0.2.1-rc.2": "compatible", "0.2.1-rc.3": "unknown" } } }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
上界写 `<0.3.0-0` 而不是 `<0.3.0`:DSH 用 `semver.satisfies(..., { includePrerelease: true })`
|
|
52
|
+
判定(`@deepseek-ai/dsh-app-boot` 的 `unmetRequirements`),带 prerelease 选项时 `<0.3.0`
|
|
53
|
+
会放行 `0.3.0-alpha.1`,`-0` 不会。`rc.1` 早于本包基线、`rc.3` 未取得也未验证,两者都只能
|
|
54
|
+
标 `unknown`——**范围不等于验收**:`engines` 是安装时的粗筛,商城的 `dshReleases` 记录才是
|
|
55
|
+
逐版本的验收结论。
|
|
56
|
+
|
|
57
|
+
面板包随之 `0.1.3 → 0.1.4`:它的版本线独立于根包,但清单变了,不发这个版本号就没有能承载新
|
|
58
|
+
声明的发布物。
|
|
59
|
+
|
|
60
|
+
### 3. 根 tarball 不再内嵌面板包
|
|
61
|
+
|
|
62
|
+
`files` 白名单去掉 `packages`。此前根 tarball 里同时躺着 `package.json` 与
|
|
63
|
+
`packages/molbio-panel/package.json` 两个 DSH 插件清单,还重复携带 427 KB 相同的 `lib/client.js`;
|
|
64
|
+
商城把"一个包里出现第二个插件清单"视为提交歧义是对的。现在根 tarball **只有一个插件清单**:
|
|
65
|
+
**118 → 115 个文件、约 1.1 MB → 约 999 kB**(多出的 1 个文件是本次提交的
|
|
66
|
+
`docs/store-preset-exemption-issue.md`)。面板没有因此消失——根包的 `lib/client.js` 本来就带着它
|
|
67
|
+
(第 4 节的启动回读可以作证);面板包继续按自己的地址单独发布。
|
|
68
|
+
|
|
69
|
+
`test/contract.mjs` 的打包断言随之改向:不再要求 `files` 必须包含 `packages/`,而是断言
|
|
70
|
+
**一个 tarball 里恰好只有一个 DSH 清单**(把 `packages` 加回白名单会立刻 FAIL)。
|
|
71
|
+
|
|
72
|
+
### 4. 一次性 profile 证据(tarball 就是发布物)
|
|
73
|
+
|
|
74
|
+
证据记录在 [docs/store-evidence.md](docs/store-evidence.md),用临时 `DSH_HOME` 重跑,不碰真实
|
|
75
|
+
`~/.dsh`:`npm pack` → `--from-default-profile web` 建 profile → `plugin add` tarball →
|
|
76
|
+
`--dump-config`(`molbio-client` 解析到已安装包内,preset 行带 `tool-molbio`)→
|
|
77
|
+
`--no-open --port 0` 启动 → 带 token 回读页面(**HTTP 200**,`__DSH_BOOT__` 图里有
|
|
78
|
+
`dsh-molbio-tools/client.js`)→ `plugin remove` → 再 `--dump-config`(`molbio` 引用 **0** 处)。
|
|
79
|
+
装 tarball 而不是目录,是因为 tarball 同时证明 `files` 白名单带全了运行文件。
|
|
80
|
+
|
|
81
|
+
### 5. 未做 / 边界
|
|
82
|
+
|
|
83
|
+
- **`0.2.1-rc.3` 没有验证**,因此标 `unknown`。拿到该版本后按
|
|
84
|
+
[docs/workflow.md](docs/workflow.md) 第 4 节的升级流程重跑 `preset-health` / `drift-probe` /
|
|
85
|
+
一次性 profile,再把它改成 `compatible`。
|
|
86
|
+
- **预检的另外两条(保护命名空间、身份一致)不是改包能解决的**:本包已自行消掉
|
|
87
|
+
`SUBMISSION_BUNDLE_PATCH_INVALID`;剩下两条的证据、代码位置与三个可执行请求写在
|
|
88
|
+
[docs/store-preset-exemption.md](docs/store-preset-exemption.md),可直接贴到 issue 的短版在
|
|
89
|
+
[docs/store-preset-exemption-issue.md](docs/store-preset-exemption-issue.md)。
|
|
90
|
+
- **工具行为与 benchmark 一律不动**:60 个工具的输出与 0.21.0 相同,按规则 6 的"没变就不必跑
|
|
91
|
+
模型";`bench --offline` 仍在 `npm test` 里,期望值照样逐条校验。
|
|
92
|
+
|
|
93
|
+
### 6. 版本与验证
|
|
94
|
+
|
|
95
|
+
- 根包 `0.21.0 → 0.21.1`;面板 `0.1.4`(见 §2)。
|
|
96
|
+
- `npm test` 全绿:smoke、画面四套、客户端四套、contract 16 项、drift-probe 14 条突变、
|
|
97
|
+
preset-health 30 行、release 13 项、benchmark 四道守卫 + `bench --offline` 61 题。
|
|
98
|
+
- `node build/preset-patch.mjs --check` 与 `node build/client-bundle.mjs --check` 均报告与源一致。
|
|
99
|
+
- `node build/release-preflight.mjs --tag v0.21.1`:本地不变量全过;npm 上 `dsh-molbio-tools`
|
|
100
|
+
已有 0.21.0、本版按 `publish` 处理;面板 0.1.4 尚未发布。
|
|
101
|
+
- 文档同步:maintainer 的版本号、roadmap 的当前状态、history 的版本一览与本段、store-evidence
|
|
102
|
+
的 tarball 名与文件数。
|
|
103
|
+
|
|
13
104
|
## [0.21.0] — 2026-10-23(DSH 0.2.1-rc.2 适配;两条 benchmark 欠账清零)
|
|
14
105
|
|
|
15
106
|
**工具数不变(60),插件行为零改动。** 这是一次"只跟上游走"的版本:0.20.1 之后本机 harness
|
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ dsh plugin --profile web update dsh-molbio-tools
|
|
|
79
79
|
> **0.7.1 起不再需要"注册 preset 根目录"这一步。**
|
|
80
80
|
> DSH 0.1.7-alpha.1 移除了 `@deepseek-ai/dsh-agent-presets` 及其目录发现机制:preset 现在是
|
|
81
81
|
> bundle patch 里的一个 `@deepseek-ai/dsh-agent-preset` **行**(本包的是
|
|
82
|
-
> `
|
|
82
|
+
> `cordis.patch.yml` 里的第二个 insert,由 `dsh.bundle.patch` 声明)。
|
|
83
83
|
> 因此 preset 随 bundle 一起安装,**装完即出现**。
|
|
84
84
|
>
|
|
85
85
|
> 老版本遗留的两样东西可以清理(`node preset\install.mjs --profile web` 会替你查出来):
|
|
@@ -95,12 +95,12 @@ dsh plugin --profile web update dsh-molbio-tools
|
|
|
95
95
|
|
|
96
96
|
### 工具只在专属模式里出现(设计如此)
|
|
97
97
|
|
|
98
|
-
本包的 bundle patch
|
|
98
|
+
本包的 bundle patch 是**一个文件、两层 insert**,分工是固定的:
|
|
99
99
|
|
|
100
|
-
|
|
|
100
|
+
| 层(同一个 `cordis.patch.yml` 里的两段) | 作用 |
|
|
101
101
|
| --- | --- |
|
|
102
|
-
| `
|
|
103
|
-
| `preset
|
|
102
|
+
| `molbio-client` → `./host.mjs` | 只插一行**惰性宿主锚点**,不注册任何工具 |
|
|
103
|
+
| `preset-molbio-lab` → `@deepseek-ai/dsh-agent-preset` | 声明 **Molecular Biology Lab** 模式,60 个工具在这一层里 |
|
|
104
104
|
|
|
105
105
|
所以 60 个工具**只在选中该模式的会话里加载**,其它模式(standard / ptc / minimal / cordis)
|
|
106
106
|
不带它们,不占提示预算。bundle 安装 ≠ 工具全局可见:bundle 只是把"模式"和"面板"一起装进来。
|
|
@@ -741,11 +741,11 @@ dsh-molbio-tools/
|
|
|
741
741
|
├── lib/client.js # 客户端产物(exports["./client"],由 npm run build:client 生成)
|
|
742
742
|
├── packages/molbio-panel/ # 面板专用包(只面板、不带工具)
|
|
743
743
|
├── preset/molbio-lab/ # 专属模式 preset:agent.cordis.yml 是行清单(手改这里)
|
|
744
|
-
│ # preset.
|
|
744
|
+
│ # preset.yml 是选择器文案;两者由生成器写进下面的 cordis.patch.yml
|
|
745
745
|
├── benchmark/ # 可用性评估:tasks/*.json + 判分器 + headless profile 推导(见其 README)
|
|
746
746
|
├── test/ # 冒烟 + 光栅化器 + 客户端/组合检查(含 preset 漂移与 benchmark profile 守卫)
|
|
747
747
|
├── docs/ # 维护者与实现文档(rules / workflow / roadmap / history 是本目录的骨架)
|
|
748
|
-
└── cordis.patch.yml # bundle
|
|
748
|
+
└── cordis.patch.yml # 唯一 bundle patch(生成物):锚点 insert + preset insert
|
|
749
749
|
```
|
|
750
750
|
|
|
751
751
|
---
|
package/benchmark/README.md
CHANGED
|
@@ -222,7 +222,7 @@ session "…" runs under agent preset "molbio-lab", which the one-shot runner do
|
|
|
222
222
|
Presets are an agent-plane feature the Web surface composes; the one-shot runner
|
|
223
223
|
drives `agents.create()` directly and never joins one. So the tools must be
|
|
224
224
|
mounted as **host rows**, which is the one shape this package otherwise refuses
|
|
225
|
-
to ship (`cordis.patch.yml`
|
|
225
|
+
to ship (`cordis.patch.yml` only inserts the inert client anchor).
|
|
226
226
|
|
|
227
227
|
`benchmark/profile.mjs` therefore generates a dedicated profile
|
|
228
228
|
(`$DSH_HOME/profiles/molbio-bench`) whose patch layer is **derived** from
|
package/benchmark/profile.mjs
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
* agent-plane feature the Web surface composes; the one-shot runner drives
|
|
18
18
|
* `agents.create()` directly and never joins one. So the tools have to be
|
|
19
19
|
* mounted as HOST rows, which is the one shape this package otherwise refuses
|
|
20
|
-
* to ship (`cordis.patch.yml`
|
|
20
|
+
* to ship (`cordis.patch.yml` only inserts the inert client anchor — see the
|
|
21
|
+
* preset's header).
|
|
21
22
|
*
|
|
22
23
|
* ── What keeps the reconstruction honest ────────────────────────────────────
|
|
23
24
|
*
|
package/build/preset-patch.mjs
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dsh-molbio-tools/build/preset-patch.mjs
|
|
3
3
|
*
|
|
4
|
-
* Generate the
|
|
4
|
+
* Generate the ONE bundle patch this package ships: the client anchor plus the
|
|
5
|
+
* "Molecular Biology Lab" agent preset.
|
|
5
6
|
*
|
|
6
|
-
* WHY
|
|
7
|
-
*
|
|
8
|
-
* DSH
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* WHY ONE FILE
|
|
8
|
+
* ------------
|
|
9
|
+
* DSH's runtime accepts `dsh.bundle.patch` as a file path or an ordered list of
|
|
10
|
+
* file paths (`@deepseek-ai/dsh-app-boot` → `bundlePatchPaths`), and the shipped
|
|
11
|
+
* `@deepseek-ai/dsh-web-app` uses the list form. DSH STORE's submission precheck
|
|
12
|
+
* only accepts a single string (`safePatchPath`), so the two layers this package
|
|
13
|
+
* used to ship as a list are emitted as one file with two top-level `insert`
|
|
14
|
+
* operations, in the same order they were applied:
|
|
14
15
|
*
|
|
15
|
-
* -
|
|
16
|
-
*
|
|
17
|
-
* name: '@deepseek-ai/dsh-agent-preset'
|
|
18
|
-
* config:
|
|
19
|
-
* id: molbio-lab
|
|
20
|
-
* name: Molecular Biology Lab
|
|
21
|
-
* description: ...
|
|
22
|
-
* plugins: [ ...the rows that used to be the composition... ]
|
|
16
|
+
* 1. molbio-client → './host.mjs' (inert host anchor; see below)
|
|
17
|
+
* 2. preset-molbio-lab → '@deepseek-ai/dsh-agent-preset'
|
|
23
18
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* Nothing about either layer changes: a patch file is an ordered list of
|
|
20
|
+
* operations, and DSH applies them in file order exactly as it applied the two
|
|
21
|
+
* files in list order.
|
|
22
|
+
*
|
|
23
|
+
* WHY THE ANCHOR EXISTS
|
|
24
|
+
* ---------------------
|
|
25
|
+
* DSH's client-module scan walks the HOST Loader tree only. It reads each live
|
|
26
|
+
* host row's package manifest, takes `dsh.client` and `exports["./client"]` from
|
|
27
|
+
* it, and composes the browser graph that becomes `window.__DSH_BOOT__`. A
|
|
28
|
+
* preset's rows live in an isolated subtree that scan never visits.
|
|
29
|
+
*
|
|
30
|
+
* So when the tools moved into the preset, this package lost its only host-plane
|
|
31
|
+
* row, its bundle stopped reaching the page, and the two right-sidebar tabs
|
|
32
|
+
* (Molbio / Papers) silently disappeared. `host.mjs` restores exactly one inert
|
|
33
|
+
* row so the browser half is discoverable again — without putting any tool into
|
|
34
|
+
* a session that did not choose the molbio-lab mode.
|
|
35
|
+
*
|
|
36
|
+
* WHY THE PRESET IS GENERATED
|
|
37
|
+
* ---------------------------
|
|
38
|
+
* DSH 0.1.7-alpha.1 removed the `<dshHome>/.agent-presets` directory scan: a
|
|
39
|
+
* preset is now a `@deepseek-ai/dsh-agent-preset` ROW in a bundle patch, which
|
|
40
|
+
* is what the second insert below declares. Because the BUNDLE registers it,
|
|
41
|
+
* `dsh plugin --profile <p> add dsh-molbio-tools` puts the mode in the picker
|
|
42
|
+
* with no copy step and no preset-root patch — see README「安装」.
|
|
43
|
+
*
|
|
44
|
+
* Keeping the rows in ONE place and generating the container from them is what
|
|
45
|
+
* stops the two from drifting, because `test/preset-health.mjs` validates every
|
|
46
|
+
* row against the INSTALLED harness's own schemas.
|
|
28
47
|
*
|
|
29
48
|
* source : preset/molbio-lab/agent.cordis.yml (top-level row list, comments intact)
|
|
30
|
-
*
|
|
49
|
+
* source : preset/molbio-lab/preset.yml (picker name + description)
|
|
50
|
+
* output : cordis.patch.yml (GENERATED; anchor + preset)
|
|
31
51
|
*
|
|
32
|
-
* The
|
|
52
|
+
* The rows are emitted as-is: no re-serialization, so the comments that explain
|
|
33
53
|
* each row survive and the file stays diffable against the shipped `standard`
|
|
34
54
|
* patch it descends from.
|
|
35
55
|
*
|
|
@@ -55,20 +75,56 @@ export function rowBlockOf(source) {
|
|
|
55
75
|
/** Indent every line of a block by `width` spaces. */
|
|
56
76
|
const indent = (block, width) => block.split('\n').map((line) => (line === '' ? line : ' '.repeat(width) + line)).join('\n');
|
|
57
77
|
|
|
78
|
+
const HEADER = [
|
|
79
|
+
'# dsh-molbio-tools bundle patch — the one file `dsh.bundle.patch` names.',
|
|
80
|
+
'#',
|
|
81
|
+
'# GENERATED by build/preset-patch.mjs. Edit the row list in',
|
|
82
|
+
'# preset/molbio-lab/agent.cordis.yml (and the picker strings in preset.yml), then',
|
|
83
|
+
'# re-run `node build/preset-patch.mjs`; hand edits here are reverted by the next',
|
|
84
|
+
'# run, and `node build/preset-patch.mjs --check` fails while the two disagree.',
|
|
85
|
+
'#',
|
|
86
|
+
'# Two top-level inserts, applied in this order:',
|
|
87
|
+
'# 1. molbio-client — inert host anchor for the browser half (see below)',
|
|
88
|
+
'# 2. preset-molbio-lab — the "Molecular Biology Lab" agent preset',
|
|
89
|
+
].join('\n');
|
|
90
|
+
|
|
91
|
+
const ANCHOR = [
|
|
92
|
+
'# ── 1. the CLIENT-BUNDLE ANCHOR ────────────────────────────────────────────',
|
|
93
|
+
'#',
|
|
94
|
+
'# `host.mjs` registers no tool and publishes no service. Its only job is to be a',
|
|
95
|
+
"# loader row DSH's client-module scan can see: that scan walks the HOST Loader",
|
|
96
|
+
"# tree, reads the row's package manifest, and takes `dsh.client` +",
|
|
97
|
+
'# `exports["./client"]` from it to compose `window.__DSH_BOOT__`. A preset\'s rows',
|
|
98
|
+
'# live in an isolated subtree the scan never visits, so a `dsh.client` package',
|
|
99
|
+
'# referenced only from inside a preset loses its only discoverable row and its',
|
|
100
|
+
'# right-sidebar tabs silently disappear.',
|
|
101
|
+
'#',
|
|
102
|
+
'# Keep the tool in the PRESET and only the anchor here. An earlier version of',
|
|
103
|
+
"# this file inserted a host row for the tool itself (`name: dsh-molbio-tools`),",
|
|
104
|
+
"# which both registered all 60 tools globally and collided with the preset's own",
|
|
105
|
+
'# copy of that row:',
|
|
106
|
+
'#',
|
|
107
|
+
'# broken: "tool-molbio (...): never started"',
|
|
108
|
+
'- insert:',
|
|
109
|
+
' - id: molbio-client',
|
|
110
|
+
" name: './host.mjs'",
|
|
111
|
+
].join('\n');
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Build the bundle patch: anchor first, preset second.
|
|
115
|
+
*
|
|
116
|
+
* @param {{rows: string, description: string, displayName?: string}} input
|
|
117
|
+
* @returns {string} the complete `cordis.patch.yml` text (single trailing newline)
|
|
118
|
+
*/
|
|
58
119
|
export function buildPatch({ rows, description, displayName = 'Molecular Biology Lab' }) {
|
|
59
|
-
const
|
|
60
|
-
'#
|
|
120
|
+
const presetHeader = [
|
|
121
|
+
'# ── 2. the MOLECULAR BIOLOGY LAB PRESET ───────────────────────────────────',
|
|
61
122
|
'#',
|
|
62
|
-
'#
|
|
63
|
-
'#
|
|
64
|
-
|
|
65
|
-
'# `
|
|
66
|
-
'#',
|
|
67
|
-
'# DSH 0.1.7-alpha.1 removed the `<dshHome>/.agent-presets` directory scan: a preset is',
|
|
68
|
-
'# now a `@deepseek-ai/dsh-agent-preset` ROW in a bundle patch, which is what this',
|
|
69
|
-
'# layer inserts. Because the BUNDLE registers it, `dsh plugin --profile <p> add',
|
|
70
|
-
'# dsh-molbio-tools` puts the mode in the picker with no copy step and no',
|
|
71
|
-
'# preset-root patch — see README「安装」.',
|
|
123
|
+
'# DSH 0.1.7-alpha.1 removed the `<dshHome>/.agent-presets` directory scan: a',
|
|
124
|
+
'# preset is now a `@deepseek-ai/dsh-agent-preset` ROW in a bundle patch, which',
|
|
125
|
+
'# is what this insert declares. Because the BUNDLE registers it,',
|
|
126
|
+
'# `dsh plugin --profile <p> add dsh-molbio-tools` puts the mode in the picker',
|
|
127
|
+
'# with no copy step and no preset-root patch — see README「安装」.',
|
|
72
128
|
'#',
|
|
73
129
|
'# `order: 5` is deliberate: the shipped presets occupy 1..4 (standard, ptc,',
|
|
74
130
|
'# minimal, cordis) and the registry sorts by `order` with an id tie-break, so a',
|
|
@@ -76,7 +132,11 @@ export function buildPatch({ rows, description, displayName = 'Molecular Biology
|
|
|
76
132
|
].join('\n');
|
|
77
133
|
|
|
78
134
|
return [
|
|
79
|
-
|
|
135
|
+
HEADER,
|
|
136
|
+
'',
|
|
137
|
+
ANCHOR,
|
|
138
|
+
'',
|
|
139
|
+
presetHeader,
|
|
80
140
|
'- insert:',
|
|
81
141
|
' - id: preset-molbio-lab',
|
|
82
142
|
" name: '@deepseek-ai/dsh-agent-preset'",
|
|
@@ -95,7 +155,7 @@ function main() {
|
|
|
95
155
|
const check = process.argv.includes('--check');
|
|
96
156
|
const sourcePath = join(repoRoot, 'preset', 'molbio-lab', 'agent.cordis.yml');
|
|
97
157
|
const metaPath = join(repoRoot, 'preset', 'molbio-lab', 'preset.yml');
|
|
98
|
-
const outPath = join(repoRoot, '
|
|
158
|
+
const outPath = join(repoRoot, 'cordis.patch.yml');
|
|
99
159
|
|
|
100
160
|
const rows = rowBlockOf(readFileSync(sourcePath, 'utf8'));
|
|
101
161
|
if (rows === undefined || !rows.includes('- id:')) {
|
|
@@ -124,16 +184,16 @@ function main() {
|
|
|
124
184
|
process.exit(1);
|
|
125
185
|
}
|
|
126
186
|
if (current !== text) {
|
|
127
|
-
console.error('preset-patch: the committed
|
|
187
|
+
console.error('preset-patch: the committed bundle patch is STALE — run `node build/preset-patch.mjs`');
|
|
128
188
|
process.exit(1);
|
|
129
189
|
}
|
|
130
|
-
console.log('
|
|
190
|
+
console.log('bundle patch is current');
|
|
131
191
|
return;
|
|
132
192
|
}
|
|
133
193
|
|
|
134
194
|
writeFileSync(outPath, text, 'utf8');
|
|
135
|
-
const
|
|
136
|
-
console.log(`
|
|
195
|
+
const rowCount = rows.split('\n').filter((line) => /^\s*- id:/.test(line)).length;
|
|
196
|
+
console.log(`bundle patch written: ${outPath} (${rowCount} preset rows + anchor)`);
|
|
137
197
|
}
|
|
138
198
|
|
|
139
199
|
if (process.argv[1] !== undefined && import.meta.url === pathToFileURLSafe(process.argv[1])) main();
|
package/cordis.patch.yml
CHANGED
|
@@ -1,34 +1,196 @@
|
|
|
1
|
-
# dsh-molbio-tools bundle
|
|
1
|
+
# dsh-molbio-tools bundle patch — the one file `dsh.bundle.patch` names.
|
|
2
2
|
#
|
|
3
|
-
#
|
|
3
|
+
# GENERATED by build/preset-patch.mjs. Edit the row list in
|
|
4
|
+
# preset/molbio-lab/agent.cordis.yml (and the picker strings in preset.yml), then
|
|
5
|
+
# re-run `node build/preset-patch.mjs`; hand edits here are reverted by the next
|
|
6
|
+
# run, and `node build/preset-patch.mjs --check` fails while the two disagree.
|
|
4
7
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
8
|
+
# Two top-level inserts, applied in this order:
|
|
9
|
+
# 1. molbio-client — inert host anchor for the browser half (see below)
|
|
10
|
+
# 2. preset-molbio-lab — the "Molecular Biology Lab" agent preset
|
|
11
|
+
|
|
12
|
+
# ── 1. the CLIENT-BUNDLE ANCHOR ────────────────────────────────────────────
|
|
7
13
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
14
|
+
# `host.mjs` registers no tool and publishes no service. Its only job is to be a
|
|
15
|
+
# loader row DSH's client-module scan can see: that scan walks the HOST Loader
|
|
16
|
+
# tree, reads the row's package manifest, and takes `dsh.client` +
|
|
17
|
+
# `exports["./client"]` from it to compose `window.__DSH_BOOT__`. A preset's rows
|
|
18
|
+
# live in an isolated subtree the scan never visits, so a `dsh.client` package
|
|
19
|
+
# referenced only from inside a preset loses its only discoverable row and its
|
|
20
|
+
# right-sidebar tabs silently disappear.
|
|
11
21
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# never visits.
|
|
17
|
-
#
|
|
18
|
-
# So when the tools moved into the preset, this package lost its only host-plane
|
|
19
|
-
# row, its bundle stopped reaching the page, and the two right-sidebar tabs
|
|
20
|
-
# (Molbio / Papers) silently disappeared: the panel code was still in the
|
|
21
|
-
# artifact, nothing ever loaded it. `host.mjs` restores exactly one inert row so
|
|
22
|
-
# the browser half is discoverable again — without putting any tool into a
|
|
23
|
-
# session that did not choose the molbio-lab mode.
|
|
24
|
-
#
|
|
25
|
-
# An earlier version of this file inserted a host row for the tool itself
|
|
26
|
-
# (`name: dsh-molbio-tools`), which both registered all 57 tools globally and
|
|
27
|
-
# collided with the preset's own copy of that row:
|
|
22
|
+
# Keep the tool in the PRESET and only the anchor here. An earlier version of
|
|
23
|
+
# this file inserted a host row for the tool itself (`name: dsh-molbio-tools`),
|
|
24
|
+
# which both registered all 60 tools globally and collided with the preset's own
|
|
25
|
+
# copy of that row:
|
|
28
26
|
#
|
|
29
27
|
# broken: "tool-molbio (...): never started"
|
|
30
|
-
#
|
|
31
|
-
# Keep the tool in the PRESET and only the anchor here.
|
|
32
28
|
- insert:
|
|
33
29
|
- id: molbio-client
|
|
34
30
|
name: './host.mjs'
|
|
31
|
+
|
|
32
|
+
# ── 2. the MOLECULAR BIOLOGY LAB PRESET ───────────────────────────────────
|
|
33
|
+
#
|
|
34
|
+
# DSH 0.1.7-alpha.1 removed the `<dshHome>/.agent-presets` directory scan: a
|
|
35
|
+
# preset is now a `@deepseek-ai/dsh-agent-preset` ROW in a bundle patch, which
|
|
36
|
+
# is what this insert declares. Because the BUNDLE registers it,
|
|
37
|
+
# `dsh plugin --profile <p> add dsh-molbio-tools` puts the mode in the picker
|
|
38
|
+
# with no copy step and no preset-root patch — see README「安装」.
|
|
39
|
+
#
|
|
40
|
+
# `order: 5` is deliberate: the shipped presets occupy 1..4 (standard, ptc,
|
|
41
|
+
# minimal, cordis) and the registry sorts by `order` with an id tie-break, so a
|
|
42
|
+
# shared number would let the picker order depend on alphabetical accident.
|
|
43
|
+
- insert:
|
|
44
|
+
- id: preset-molbio-lab
|
|
45
|
+
name: '@deepseek-ai/dsh-agent-preset'
|
|
46
|
+
config:
|
|
47
|
+
id: molbio-lab
|
|
48
|
+
order: 5
|
|
49
|
+
name: Molecular Biology Lab
|
|
50
|
+
description: "分子生物学专属模式:标准编码能力 + 60 个 molbio_* 工具(序列分析、引物设计(含跨内含子 qPCR、盐/浓度旋钮与目标位置偏好)、TaqMan 水解探针(含 MGB 与订购 CSV)与多重 PCR 互扰/退火温度/浓度建议、克隆模拟与选酶(含 Golden Gate)、酶目录查询、甲基化敏感位点与双酶切 buffer 兼容检查、多序列比对(每个输入残基都会进比对结果)、保守性分析与比对后处理(共识/缺口修剪/同一性矩阵/逐列覆盖度,含 sequence logo 图)、CRISPR gRNA 设计(SpCas9/SaCas9/Cas12a/Cas13,家族特定 PAM/PFS/种子)与脱靶搜索、SnapGene/GenBank 解析与质粒图谱、Sanger 测序验证、蛋白性质/密码子优化/螺旋轮投影与疏水性图、qPCR 与绘图、虚拟凝胶、实验台分析(FASTQ 质控、密码子使用、系统发生树(长叶名自动折行)、in-silico PCR、CpG/GC 组成、批量文件分析/CSV)、静默酶切位点突变设计——生成的 SVG 图片自动用系统默认应用打开,文献/协议/实验记录)。"
|
|
51
|
+
plugins:
|
|
52
|
+
- id: persona
|
|
53
|
+
name: '@deepseek-ai/dsh-persona'
|
|
54
|
+
config:
|
|
55
|
+
prefix: You are a coding agent powered by the {{model}} model.
|
|
56
|
+
- id: agent-instructions
|
|
57
|
+
name: '@deepseek-ai/dsh-agent-instructions'
|
|
58
|
+
config:
|
|
59
|
+
maxBytes: 65536
|
|
60
|
+
- id: time-context
|
|
61
|
+
name: '@deepseek-ai/dsh-time-context'
|
|
62
|
+
- id: tool-bash
|
|
63
|
+
name: '@deepseek-ai/dsh-tool-bash'
|
|
64
|
+
disabled: !!js process.platform === 'win32'
|
|
65
|
+
- id: tool-pwsh
|
|
66
|
+
name: '@deepseek-ai/dsh-tool-pwsh'
|
|
67
|
+
disabled: !!js process.platform !== 'win32'
|
|
68
|
+
- id: tool-fs
|
|
69
|
+
name: '@deepseek-ai/dsh-tool-fs'
|
|
70
|
+
- id: tool-fs-search
|
|
71
|
+
name: '@deepseek-ai/dsh-tool-fs-search'
|
|
72
|
+
config:
|
|
73
|
+
sampleOverCapGlobResults: false
|
|
74
|
+
- id: tool-jobs
|
|
75
|
+
name: '@deepseek-ai/dsh-tool-jobs'
|
|
76
|
+
- id: tool-schedule
|
|
77
|
+
name: '@deepseek-ai/dsh-tool-schedule'
|
|
78
|
+
- id: skill-filesystem
|
|
79
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
80
|
+
- id: tool-skill
|
|
81
|
+
name: '@deepseek-ai/dsh-tool-skill'
|
|
82
|
+
- id: command-goal
|
|
83
|
+
name: '@deepseek-ai/dsh-command-goal'
|
|
84
|
+
- id: tool-goal
|
|
85
|
+
name: '@deepseek-ai/dsh-tool-goal'
|
|
86
|
+
- id: planning
|
|
87
|
+
name: cordis:group
|
|
88
|
+
group: true
|
|
89
|
+
isolate:
|
|
90
|
+
planMode: true
|
|
91
|
+
config:
|
|
92
|
+
- id: plan-mode
|
|
93
|
+
name: '@deepseek-ai/dsh-plan-mode'
|
|
94
|
+
config:
|
|
95
|
+
section: |
|
|
96
|
+
You are in plan mode. Stay in plan mode until the user approves your plan through exit_plan_mode or switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
|
|
97
|
+
|
|
98
|
+
Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
|
|
99
|
+
|
|
100
|
+
The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
|
|
101
|
+
|
|
102
|
+
Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
|
|
103
|
+
|
|
104
|
+
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
105
|
+
|
|
106
|
+
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
107
|
+
- id: compaction
|
|
108
|
+
name: cordis:group
|
|
109
|
+
group: true
|
|
110
|
+
isolate:
|
|
111
|
+
compaction: true
|
|
112
|
+
toolResultPruner: true
|
|
113
|
+
config:
|
|
114
|
+
- id: compaction-basic
|
|
115
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
116
|
+
- id: command-compact
|
|
117
|
+
name: '@deepseek-ai/dsh-command-compact'
|
|
118
|
+
- id: tool-result-pruner
|
|
119
|
+
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
|
120
|
+
config:
|
|
121
|
+
thresholdChars: 8192
|
|
122
|
+
headChars: 4096
|
|
123
|
+
tailChars: 1024
|
|
124
|
+
- id: delegation
|
|
125
|
+
name: cordis:group
|
|
126
|
+
group: true
|
|
127
|
+
isolate:
|
|
128
|
+
workflowEngine: true
|
|
129
|
+
config:
|
|
130
|
+
- id: tool-subagent-control
|
|
131
|
+
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
132
|
+
- id: tool-subagent-list-agents
|
|
133
|
+
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
134
|
+
- id: tool-subagent
|
|
135
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
136
|
+
config:
|
|
137
|
+
provider: spawn
|
|
138
|
+
toolName: subagent
|
|
139
|
+
modelSelectionSettings: true
|
|
140
|
+
- id: tool-subagent-fork
|
|
141
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
142
|
+
config:
|
|
143
|
+
provider: fork
|
|
144
|
+
toolName: subagent_fork
|
|
145
|
+
- id: workflow-ptc
|
|
146
|
+
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
147
|
+
config:
|
|
148
|
+
provider: spawn
|
|
149
|
+
- id: tool-workflow
|
|
150
|
+
name: '@deepseek-ai/dsh-tool-workflow'
|
|
151
|
+
- id: tool-ask-user
|
|
152
|
+
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
153
|
+
- id: tool-todo
|
|
154
|
+
name: '@deepseek-ai/dsh-tool-todo'
|
|
155
|
+
config:
|
|
156
|
+
allowParallelInProgress: true
|
|
157
|
+
- id: tool-web
|
|
158
|
+
name: '@deepseek-ai/dsh-tool-web'
|
|
159
|
+
config:
|
|
160
|
+
fetch: true
|
|
161
|
+
searchTimeoutMs: 60000
|
|
162
|
+
- id: present
|
|
163
|
+
name: '@deepseek-ai/dsh-tool-present'
|
|
164
|
+
- id: tool-plugin-manager
|
|
165
|
+
name: '@deepseek-ai/dsh-plugin-manager/tools'
|
|
166
|
+
disabled: true
|
|
167
|
+
- id: tool-plugin-market
|
|
168
|
+
name: '@deepseek-ai/dsh-plugin-market/tools'
|
|
169
|
+
disabled: true
|
|
170
|
+
|
|
171
|
+
# dsh-molbio-tools: molecular-biology toolset (60 tools across sequence
|
|
172
|
+
# analysis, primers (incl. TaqMan probes and multiplex compatibility),
|
|
173
|
+
# in-silico PCR, cloning (incl. Golden Gate), enzyme catalog, methylation-aware
|
|
174
|
+
# and double digests, plasmids, Sanger verification, proteins (incl. helical
|
|
175
|
+
# wheel/hydropathy plots), qPCR, virtual gels, multiple sequence
|
|
176
|
+
# alignment/conservation (every supplied residue is conserved), sequence logos,
|
|
177
|
+
# codon-usage analysis, phylogenetic trees (bootstrap + Newick, long labels
|
|
178
|
+
# wrapped), CpG-island/GC-skew composition, read-level FASTQ QC, CRISPR gRNA
|
|
179
|
+
# design, and literature/protocol/experiment records).
|
|
180
|
+
# Registers into the host `tools` registry and publishes no service, so it
|
|
181
|
+
# needs no isolate realm.
|
|
182
|
+
#
|
|
183
|
+
# The specifier is the PACKAGE NAME, resolved by Node from the profile's
|
|
184
|
+
# node_modules — not a `./plugins/…` path. A relative specifier here does NOT
|
|
185
|
+
# work on DSH 0.1.7-alpha.1: the preset mounts, but the entry is created without
|
|
186
|
+
# ever being imported, so the roster reports the mode as broken and it loads
|
|
187
|
+
# zero tools:
|
|
188
|
+
#
|
|
189
|
+
# tool-molbio (./plugins/dsh-molbio-tools-v20/index.mjs): never started
|
|
190
|
+
#
|
|
191
|
+
# A bare name is also what makes upgrades automatic: `dsh plugin update` moves
|
|
192
|
+
# the package and this row follows it. The per-release `plugins/dsh-molbio-
|
|
193
|
+
# tools-vN/` copies existed only to work around ESM module-cache reuse of a
|
|
194
|
+
# relative file URL, which a resolved package name does not have.
|
|
195
|
+
- id: tool-molbio
|
|
196
|
+
name: 'dsh-molbio-tools'
|
package/docs/history.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
| 包版本 | preset 版本 | 内容 | 工具数 |
|
|
18
18
|
| --- | --- | --- | --- |
|
|
19
|
+
| 0.21.1 | — | **DSH STORE 提交前置**:单文件 bundle patch、逐版本兼容声明;根 tarball 只带一个插件清单(工具行为零变化) | 60 |
|
|
19
20
|
| 0.21.0 | — | **DSH 0.2.1-rc.2 适配**:preset 行清单逐行重抄;contract 两条断言重锚到行为;两条 suspended 记录用真实模型重录 | 60 |
|
|
20
21
|
| 0.20.1 | — | 插件专属图标(透明底双螺旋 SVG),运行时零改动 | 60 |
|
|
21
22
|
| 0.20.0 | — | **Cas 家族几何**(SpCas9/SaCas9/Cas12a/Cas13a/b/d)+ 反向链脱靶定位修复;TaqMan MGB/订购 CSV;multiplex 退火温度/浓度;批量分析 CSV;静默位点突变;并入 0.19.1 硬化 | 60 |
|
|
@@ -43,6 +44,29 @@
|
|
|
43
44
|
|
|
44
45
|
---
|
|
45
46
|
|
|
47
|
+
## v0.21.1(2026-10-25,包 0.21.1)
|
|
48
|
+
|
|
49
|
+
上架前置版:一个工具都没改,只改「提交的形状」。三条教训都关于**契约不止一份**。
|
|
50
|
+
|
|
51
|
+
**(1) 当两个官方契约互相矛盾时,先让包同时满足两边,而不是等其中一个放宽。**
|
|
52
|
+
`dsh.bundle.patch` 在 DSH 运行时是有序数组(官方 `dsh-web-app` 自己就列了 5 个文件),但 DSH STORE
|
|
53
|
+
的提交预检只接受字符串。我们选了不依赖对方先改的解法:合并成一个 `cordis.patch.yml`,两个 insert
|
|
54
|
+
(锚点 + preset)放在同一个文件里,生成器直接产出它。代价是四个读者要跟着换路径——真正危险的不是
|
|
55
|
+
改路径,而是**锚点行可能在合并时被当成重复内容删掉**:0.15.2 的两个侧栏 tab 就是这么消失的。所以
|
|
56
|
+
`client-mount` 的「每个被选中的包必须有一个可解析的宿主行」没有随合并松动。
|
|
57
|
+
|
|
58
|
+
**(2) 兼容性声明是两件事:安装范围与逐版本验收。**
|
|
59
|
+
`engines.dsh` 的 `>=0.2.1-rc.2 <0.3.0-0` 是粗筛(`-0` 是必要的:带 prerelease 的比较里
|
|
60
|
+
`<0.3.0` 会放行 `0.3.0-alpha.1`);`dsh.compatibility.dshReleases` 才是逐版本的结论。没有跑过的
|
|
61
|
+
版本只能写 `unknown`,不能因为「补丁号在范围内」就写成 `compatible`——这正是把「范围」误读成
|
|
62
|
+
「验收」时会发生的事。
|
|
63
|
+
|
|
64
|
+
**(3) 一个 tarball 只能有一个插件清单。**
|
|
65
|
+
根包曾把 `packages/molbio-panel` 一起打包,于是同一个 tarball 里有两个 `dsh` 清单、两份相同的
|
|
66
|
+
427 KB `lib/client.js`。删掉 `packages` 不改变任何用户可见行为(面板照样由根包的 `lib/client.js`
|
|
67
|
+
提供),但「不改变行为」必须能被观察到:一次性 profile 的启动回读里,`window.__DSH_BOOT__` 仍然
|
|
68
|
+
包含 `dsh-molbio-tools/client.js`,这才是证据;tarball 此时是 115 个文件、约 999 kB。
|
|
69
|
+
|
|
46
70
|
## v0.21.0(2026-10-23,包 0.21.0)
|
|
47
71
|
|
|
48
72
|
纯适配版:DSH 0.2.0-rc.2 → 0.2.1-rc.2。工具行为零变化,但上游动了三样本仓库**以为不会动**的东西,
|