dsh-custom-mode 1.11.6 → 1.12.0
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/README.i18n.yaml +2 -2
- package/README.md +17 -13
- package/README.zh.md +17 -12
- package/atomic.mjs +31 -1
- package/client.js +223 -88
- package/composition.mjs +39 -5
- package/index.mjs +38 -10
- package/locales.mjs +39 -11
- package/package.json +3 -3
- package/preset/prompt-tool.mjs +4 -4
- package/preset-backend/declarative.mjs +24 -5
package/README.i18n.yaml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# 双语配对一致性记录:两侧在「上次确认一致」时的 git blob 哈希。
|
|
2
2
|
# 两份文档权威相同——改完任意一侧,请把另一侧也改掉,然后重新记录:
|
|
3
3
|
# node tools/verify-translation-pairing.mjs --write
|
|
4
|
-
README.md:
|
|
5
|
-
README.zh.md:
|
|
4
|
+
README.md: 242356173df2a98b55e929f18ffa0d2505c51d3e
|
|
5
|
+
README.zh.md: 0bae340a594f7de448cbafe5c583a58fcebeb5f8
|
package/README.md
CHANGED
|
@@ -27,15 +27,13 @@ modes ("assistants") can live side by side, each with its own prompt.
|
|
|
27
27
|
Also searched for as: custom mode · custom prompt · system-prompt editor · multi-mode / several assistants ·
|
|
28
28
|
multi-agent · roleplay (RP) / chat personas.
|
|
29
29
|
|
|
30
|
-
**
|
|
31
|
-
neither merely claimed. npm's `latest` and `next` have both pointed at `0.2.0-rc.2` since 2026-09-29, so
|
|
32
|
-
"latest stable" and "latest preview" are one release now; the second leg stays because most installs in
|
|
33
|
-
the field are still on `0.1.7-rc.2`:
|
|
30
|
+
**Unit tests cover three lines. The render gate runs only on `0.2.0-rc.2`.** npm's `latest` and `next` have both pointed at `0.2.0-rc.2` since 2026-09-29:
|
|
34
31
|
|
|
35
32
|
| dsh | role | status |
|
|
36
33
|
| --- | --- | --- |
|
|
37
34
|
| `0.2.0-rc.2` | **newest line** — npm's `latest` *and* `next`, and the line the official desktop app ships (it is version-locked to dsh) | ✅ CI (ubuntu node 20/24 + **windows**) + a real instance: install, composition and the seeded preset verified on this line (the full render gate runs here) |
|
|
38
|
-
| `0.1
|
|
35
|
+
| `0.2.1-alpha.1` | preview line — npm `alpha`. Covered by unit tests; the render gate does not run here | ✅ CI |
|
|
36
|
+
| `0.1.7-rc.2` | previous stable — still inside the declared range, and what most existing installs run | ✅ CI. On this line the page falls back where the shell does not provide atoms; the render gate does not run here |
|
|
39
37
|
|
|
40
38
|
Older builds (`0.1.5-rc.3`, `0.1.6-alpha.*`) use the same mechanisms and remain inside the declared peer
|
|
41
39
|
range, but they no longer get a CI leg of their own.
|
|
@@ -59,7 +57,7 @@ One command installs everything — the settings-page plugin, and the preset it
|
|
|
59
57
|
activation:
|
|
60
58
|
|
|
61
59
|
```sh
|
|
62
|
-
dsh plugin --profile web add dsh-custom-mode@1.
|
|
60
|
+
dsh plugin --profile web add dsh-custom-mode@1.12.0 # pin the version to get this one for sure
|
|
63
61
|
# A bare `add dsh-custom-mode` is subject to pnpm's release cooldown (`minimumReleaseAge`, 1 day by
|
|
64
62
|
# default): for hours after a release it can silently install an OLDER version — measured: a bare
|
|
65
63
|
# install 38 minutes after 1.3.0 shipped landed on 1.0.3. Check what you got with `npm ls
|
|
@@ -118,7 +116,7 @@ Electron shell**, so this plugin's page renders there unchanged. One install pat
|
|
|
118
116
|
too and points you at the app, so the two agree instead of one silently working around the other.
|
|
119
117
|
(A lab simulation of the profile shape can override it with `DSH_ALLOW_DESKTOP_PROFILE=1`.)
|
|
120
118
|
**The app's own bundled CLI is the exception** — `<install>\resources\runtime\cli\bin\dsh.cmd` is allowed
|
|
121
|
-
to operate on that profile (
|
|
119
|
+
to operate on that profile (an older note claimed a pin installed a different version; that note is withdrawn).
|
|
122
120
|
It is a launcher, not a dsh feature: it starts Electron with `ELECTRON_RUN_AS_NODE=1` and runs the
|
|
123
121
|
desktop-host CLI, so it is the app talking to its own profile rather than something driving from outside.
|
|
124
122
|
- **Nothing else to do on the preset side**: `$DSH_HOME/.agent-presets/` is product data shared by the
|
|
@@ -315,13 +313,19 @@ What this plugin supports is declared in `engines.dsh` and the `@deepseek-ai/dsh
|
|
|
315
313
|
`package.json`, and `tools/verify-version-consistency.mjs` (run in CI) asserts that the DSH
|
|
316
314
|
version CI installs and tests falls inside those ranges.
|
|
317
315
|
|
|
318
|
-
**
|
|
319
|
-
since 2026-09-29, and the line the desktop app ships)
|
|
316
|
+
**Three lines are supported: the newest stable line (`0.2.0-rc.2`, which npm's `latest` and `next` both
|
|
317
|
+
point at since 2026-09-29, and the line the desktop app ships), the newest preview line
|
|
318
|
+
(`0.2.1-alpha.1`, which npm's `alpha` points at) and the previous stable (`0.1.7-rc.2` — still inside
|
|
320
319
|
the declared range, and what most existing installs run)** — declared as
|
|
321
|
-
`>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0` (the extra clauses exist because
|
|
322
|
-
semver only matches a pre-release inside a range that names its own `major.minor.patch`), and CI installs
|
|
320
|
+
`>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0 || >=0.2.1-alpha.1 <0.3.0-0` (the extra clauses exist because
|
|
321
|
+
semver only matches a pre-release inside a range that names its own `major.minor.patch`), and CI installs all three
|
|
323
322
|
and runs the whole suite against each — the rendered gate runs on the **newest** line, because that is
|
|
324
323
|
where the shell's own UI changes land first.
|
|
324
|
+
**The newest preview line needs its own leg because the stable line's clause does *not* cover it**:
|
|
325
|
+
`>=0.2.0-0 <0.3.0-0` reads like it covers all of `0.2.x`, but the pre-release gate only opens when some
|
|
326
|
+
comparator in the set names the same `major.minor.patch`, and that comparator's tuple is `0.2.0` — so
|
|
327
|
+
`0.2.1-alpha.1` is refused. A range that *looks* wide is therefore neither coverage of the preview line
|
|
328
|
+
nor evidence that it was ever run.
|
|
325
329
|
**The official desktop app (DeepSeek Harness Desktop) is covered too**: it is version-locked to dsh and now
|
|
326
330
|
ships `0.2.0-rc.2`, i.e. the same combination this matrix pins. Install it from inside the app (sidebar →
|
|
327
331
|
Plugins); the CLI is refused for that profile by dsh itself. On `0.2.0-rc.2` measured (2026-09-30, clean
|
|
@@ -400,7 +404,7 @@ MIT
|
|
|
400
404
|
| | |
|
|
401
405
|
| --- | --- |
|
|
402
406
|
| Model | DeepSeek V4.1 Flash (`deepseek-v4-flash`, provider `deepseek-official`) |
|
|
403
|
-
| Runtime |
|
|
407
|
+
| Runtime | Unit tests: `0.2.0-rc.2`, `0.2.1-alpha.1`, `0.1.7-rc.2`. The render gate runs only on `0.2.0-rc.2`. The token figures below are from an earlier `0.1.6-alpha.2` session |
|
|
404
408
|
| Uncached input | 224,058 tok |
|
|
405
409
|
| Cache reads | 125,638,016 tok |
|
|
406
410
|
| Output | 425,539 tok |
|
|
@@ -430,7 +434,7 @@ installing again — your data is not touched:
|
|
|
430
434
|
|
|
431
435
|
```sh
|
|
432
436
|
# the pinned form: what you ask for is what you get
|
|
433
|
-
dsh plugin --profile web add dsh-custom-mode@1.
|
|
437
|
+
dsh plugin --profile web add dsh-custom-mode@1.12.0
|
|
434
438
|
# then restart the DSH process that serves the web profile
|
|
435
439
|
```
|
|
436
440
|
|
package/README.zh.md
CHANGED
|
@@ -22,12 +22,13 @@ base mode / plugin switches / multi-assistant / multi-persona。
|
|
|
22
22
|
常见的叫法:自定义模式 · 自定义提示词 · 系统提示词编辑 · 多助手/多模式 · 多个 Agent 模式 ·
|
|
23
23
|
角色扮演/聊天人格(RP)。
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
**单元测试覆盖三条线,渲染闸门只跑 `0.2.0-rc.2`。** npm 的 `latest` 与 `next` 自 2026-09-29 起都指向 `0.2.0-rc.2`:
|
|
26
26
|
|
|
27
27
|
| dsh | 定位 | 状态 |
|
|
28
28
|
| --- | --- | --- |
|
|
29
29
|
| `0.2.0-rc.2` | **最新线** —— npm 的 `latest` 与 `next` 都指向它,官方桌面端也在这一条线上(与 dsh 同版本号) | ✅ CI(ubuntu node 20/24 + **windows**)+ 真机:这条线上安装、组合树与播种都验过(整道渲染闸门跑在这里)|
|
|
30
|
-
| `0.1
|
|
30
|
+
| `0.2.1-alpha.1` | 预览线 —— npm 的 `alpha` 指向它。单元测试覆盖;渲染闸门不在这条线上 | ✅ CI |
|
|
31
|
+
| `0.1.7-rc.2` | 上一个正式版 —— 仍在声明范围内,现役安装大多在它上面 | ✅ CI。设置页在这条线上会退回壳没提供的控件;渲染闸门不在这里 |
|
|
31
32
|
|
|
32
33
|
更早的线(`0.1.5-rc.3`、`0.1.6-alpha.*`)共用同一套机制,peer 范围仍然接纳,但不再单独占 CI 腿。
|
|
33
34
|
|
|
@@ -48,7 +49,7 @@ base mode / plugin switches / multi-assistant / multi-persona。
|
|
|
48
49
|
一条命令装完——设置页插件,以及它在首次激活时自动播种的 preset:
|
|
49
50
|
|
|
50
51
|
```sh
|
|
51
|
-
dsh plugin --profile web add dsh-custom-mode@1.
|
|
52
|
+
dsh plugin --profile web add dsh-custom-mode@1.12.0 # 钉版本才能确定拿到这一版
|
|
52
53
|
# 不带版本号会受 pnpm 的发布冷却期影响(`minimumReleaseAge`,默认一天):发布后数小时内按名安装
|
|
53
54
|
# 可能**静默装到旧版** —— 实测 1.3.0 发布 38 分钟后按名安装装到了 1.0.3。用 profile 里的
|
|
54
55
|
# `npm ls dsh-custom-mode` 核对实际装到的版本,或像上面那样钉版本。
|
|
@@ -67,7 +68,7 @@ dsh `0.1.6-alpha.2` 起有插件管理页:**侧边栏 → 插件 → 添加插
|
|
|
67
68
|
|
|
68
69
|
| 输入 | 填什么 | 说明 |
|
|
69
70
|
| --- | --- | --- |
|
|
70
|
-
| **包名** | `dsh-custom-mode` |
|
|
71
|
+
| **包名** | `dsh-custom-mode` | 受 pnpm 发布冷却期影响,可能装到旧版。要这一版请钉 `@1.12.0` |
|
|
71
72
|
| **GitHub 仓库地址** | `https://github.com/BOWLUNA/dsh-custom-mode` | 指向**仓库根**即可 |
|
|
72
73
|
| **本地插件目录** | `<你 clone 的路径>` | 就是仓库根 —— 仓库根**本身**就是发布包 |
|
|
73
74
|
|
|
@@ -98,7 +99,7 @@ dsh `0.1.6-alpha.2` 起有插件管理页:**侧边栏 → 插件 → 添加插
|
|
|
98
99
|
`cordis.patch.yml`。所以 `install.sh` 也**拒绝** `--profile desktop` 并指向应用内安装 —— 两边一致,
|
|
99
100
|
而不是某一方偷偷绕过去。(只想在本机模拟 profile 形状时可设 `DSH_ALLOW_DESKTOP_PROFILE=1`。)
|
|
100
101
|
**应用自带的捆绑 CLI 是例外**:`<安装目录>\resources\runtime\cli\bin\dsh.cmd` 可以操作那个 profile
|
|
101
|
-
(1.11.1
|
|
102
|
+
(1.11.1 实测时,命令写的版本和装上的版本对不上,这次记录作废)。它是启动器而不是 dsh 的
|
|
102
103
|
新功能 —— 它用 `ELECTRON_RUN_AS_NODE=1` 起 Electron 去跑 desktop-host 的 CLI,所以那是**应用在跟自己的
|
|
103
104
|
profile 说话**,不是从外面驱动它。
|
|
104
105
|
- **预设那一侧不用做任何事**:`$DSH_HOME/.agent-presets/` 是桌面端与 CLI 共享的产品数据,
|
|
@@ -222,12 +223,16 @@ dsh 的系统提示词通常来自 preset 的 YAML,而官方 `@deepseek-ai/dsh
|
|
|
222
223
|
|
|
223
224
|
## 版本
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
**支持三条线:最新正式线(`0.2.0-rc.2`,npm 的 `latest` 与 `next` 自 2026-09-29 起都指向它,也是桌面端
|
|
227
|
+
所在的那条线)、最新预览线(`0.2.1-alpha.1`,npm 的 `alpha` 指向它)与上一个正式版(`0.1.7-rc.2`,
|
|
228
|
+
仍在声明范围内,现役安装大多在它上面)** —— 声明为
|
|
229
|
+
`>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0 || >=0.2.1-alpha.1 <0.3.0-0`(多出来的三段是因为
|
|
230
|
+
semver 只允许范围里**点名了** `major.minor.patch` 的预发布版本被匹配到),CI 会三条线各装一次并各跑一遍
|
|
229
231
|
完整测试 —— 其中**渲染闸门跑在最新线**上,因为壳自己的 UI 改动最先落在那里。
|
|
230
|
-
这里的策略是"
|
|
232
|
+
这里的策略是"只跟最新的几条":更早的线(`0.1.5-rc.3`、`0.1.6-alpha.*`)仍在 peer 范围内,但不单独占 CI 腿。
|
|
233
|
+
★ 最新**预览**线必须单独占一条腿,因为它**不会**被正式线的范围顺带覆盖:`>=0.2.0-0 <0.3.0-0` 读起来
|
|
234
|
+
覆盖整个 `0.2.x`,但预发布门只在**某个比较符点名了同 `major.minor.patch`** 时才放行,而那个比较符的
|
|
235
|
+
元组是 `0.2.0` ⇒ `0.2.1-alpha.1` 被拒。所以"声明看着宽"既不等于"预览线被覆盖",更不等于"跑过"。
|
|
231
236
|
**官方桌面端(DeepSeek Harness Desktop)也在覆盖范围内**:它与 dsh 同版本号,当前即为 `0.2.0-rc.2`,
|
|
232
237
|
正是这条矩阵钉住的组合;在应用内(侧栏 → Plugins)安装即可,CLI 那条路 dsh 自己会拒。
|
|
233
238
|
`0.2.0-rc.2` 实测(2026-09-30,干净的一次性 `DSH_HOME`):`dsh plugin --profile web add dsh-custom-mode`
|
|
@@ -301,7 +306,7 @@ MIT
|
|
|
301
306
|
| | |
|
|
302
307
|
| --- | --- |
|
|
303
308
|
| 模型 | DeepSeek V4.1 Flash(`deepseek-v4-flash`,provider `deepseek-official`) |
|
|
304
|
-
| 运行时 |
|
|
309
|
+
| 运行时 | 单元测试:`0.2.0-rc.2`、`0.2.1-alpha.1`、`0.1.7-rc.2`。渲染闸门只跑 `0.2.0-rc.2`。下面的用量数字来自更早的 `0.1.6-alpha.2` 那一轮 |
|
|
305
310
|
| 未缓存输入 | 224,058 tok |
|
|
306
311
|
| 缓存读取 | 125,638,016 tok |
|
|
307
312
|
| 输出 | 425,539 tok |
|
|
@@ -330,7 +335,7 @@ MIT
|
|
|
330
335
|
|
|
331
336
|
```sh
|
|
332
337
|
# 钉版本的写法:要哪版就是哪版
|
|
333
|
-
dsh plugin --profile web add dsh-custom-mode@1.
|
|
338
|
+
dsh plugin --profile web add dsh-custom-mode@1.12.0
|
|
334
339
|
# 然后重启为该 profile 提供服务的 DSH 进程
|
|
335
340
|
```
|
|
336
341
|
|
package/atomic.mjs
CHANGED
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
* random temporary name does not help with *that* collision, only with temp-vs-temp ones.
|
|
15
15
|
*/
|
|
16
16
|
import { randomBytes } from 'node:crypto'
|
|
17
|
-
import { existsSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
17
|
+
import { existsSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
18
|
+
import { join } from 'node:path'
|
|
18
19
|
|
|
19
20
|
/** Synchronous backoff: these write paths are synchronous, so waiting is simpler than async plumbing. */
|
|
20
21
|
function sleepSync(ms) {
|
|
@@ -195,6 +196,35 @@ export function writeAtomicPair(entries) {
|
|
|
195
196
|
* @param {string} text - content to write.
|
|
196
197
|
* @returns {void}
|
|
197
198
|
*/
|
|
199
|
+
/**
|
|
200
|
+
* 掉电落在「旧文件已改名为 .bak、新文件还没装上」时,把唯一的备份移回原名。
|
|
201
|
+
*
|
|
202
|
+
* 多于一份备份时不动:无法判断哪一份是最后的好内容。
|
|
203
|
+
*
|
|
204
|
+
* @param {string} directory - one assistant directory.
|
|
205
|
+
* @returns {void}
|
|
206
|
+
*/
|
|
207
|
+
export function restoreBackups(directory) {
|
|
208
|
+
const names = ['prompt.md', 'agent.cordis.yml', 'preset.yml']
|
|
209
|
+
let entries
|
|
210
|
+
try {
|
|
211
|
+
entries = readdirSync(directory)
|
|
212
|
+
} catch {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
for (const name of names) {
|
|
216
|
+
const file = join(directory, name)
|
|
217
|
+
if (existsSync(file)) continue
|
|
218
|
+
const backups = entries.filter((entry) => entry.startsWith(name + '.bak-'))
|
|
219
|
+
if (backups.length !== 1) continue
|
|
220
|
+
try {
|
|
221
|
+
renameSync(join(directory, backups[0]), file)
|
|
222
|
+
} catch {
|
|
223
|
+
/* 恢复失败就留着备份,下一次读取再试 */
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
198
228
|
export function writeAtomic(file, text) {
|
|
199
229
|
const temporary = `${file}.tmp-${String(process.pid)}-${randomBytes(4).toString('hex')}`
|
|
200
230
|
try {
|