@menghuan1918/dsh-apollo 0.5.0 → 0.5.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/README.md +8 -6
- package/docs/DEVELOPMENT.md +9 -7
- package/package.json +1 -1
- package/src/migrate.js +68 -8
package/README.md
CHANGED
|
@@ -86,13 +86,13 @@ flowchart TB
|
|
|
86
86
|
|
|
87
87
|
```sh
|
|
88
88
|
# npm 安装(发布后)
|
|
89
|
-
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.
|
|
89
|
+
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.1
|
|
90
90
|
|
|
91
91
|
# 或从 GitHub main 源码安装(备选)
|
|
92
92
|
dsh plugin --profile <profile> add github:Menghuan1918/dsh-apollo
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
> **发布状态(诚实说明)**:Apollo `0.5.0`
|
|
95
|
+
> **发布状态(诚实说明)**:Apollo `0.5.0` 已发布,`dsh-better-subagent@0.1.0` / `dsh-better-compact@0.1.0` 作为其精确依赖已可从 npm 取得。当前版本 `0.5.1` 是旧 profile `name` guard 的迁移修复版;本仓库 0.5.1 的验证使用本地 tarball `npm install --no-save`,提交的 manifest 中**没有** `file:` / `link:` / Git 说明符。
|
|
96
96
|
|
|
97
97
|
安装、升级或换包都会改变运行的代码,必须重启对应 profile 的 DSH 进程;只刷新网页不够。目标行、子代理行与压缩行由 Apollo 的 bundle patch 插入,不需要再单独 `add` 三个子包。
|
|
98
98
|
|
|
@@ -102,14 +102,16 @@ dsh plugin --profile <profile> add github:Menghuan1918/dsh-apollo
|
|
|
102
102
|
|
|
103
103
|
```sh
|
|
104
104
|
dsh plugin --profile <profile> remove dsh-apollo
|
|
105
|
-
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.
|
|
105
|
+
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.1
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
> `dsh-apollo` 只是旧入口名;unscoped 的 `dsh-apollo` 已被其他项目占用,不要从 npm 安装它。
|
|
109
109
|
|
|
110
110
|
## 从 0.4.x 升级
|
|
111
111
|
|
|
112
|
-
0.5.0 把子代理与压缩能力移出 Apollo
|
|
112
|
+
0.5.0 把子代理与压缩能力移出 Apollo,0.5.1 修复旧 profile 行的 `name` guard 迁移缺口。旧 profile 不需要手工重填配置:Apollo 启动后在 settings/loader 可用时运行一次**幂等迁移**([src/migrate.js](src/migrate.js))。
|
|
113
|
+
|
|
114
|
+
> **0.5.1 迁移修复**:如果旧 profile patch 的 `apollo-skills` 覆盖还带历史名称 `name: dsh-apollo`,DSH 会把 `name` 当 guard 并跳过该覆盖,导致有效配置看起来仍是默认值。0.5.1 从 `configEditor.configuration().override` 恢复这些显式值(含 `false` / `0` / `""` / `[]`),再合并到迁移来源;被跳过的旧预设覆盖(`preset-eng` / `preset-eng-ptc`)同样处理。无需手工修改旧行;升级后重启 profile 即可。
|
|
113
115
|
|
|
114
116
|
```mermaid
|
|
115
117
|
flowchart LR
|
|
@@ -204,7 +206,7 @@ dsh plugin --profile <profile> remove dsh-better-compact
|
|
|
204
206
|
- 彻底移除压缩增强:从 Apollo 组合中移除 Apollo,或把预设/组合改回原生压缩。**只禁用独立 compact bundle 不会恢复 Apollo 预设内的 engine 行**,因为该 engine 由 Apollo 自己的预设 patch 声明;需要移除 Apollo,或恢复一份使用原生 `compaction-basic` 的预设覆盖。
|
|
205
207
|
- 彻底移除子代理增强:移除 Apollo(或至少禁用其 `dsh-better-subagent` 行)。原生 create/fork/message/interrupt 仍可用;CLI-only 旧会话需要重新安装 better-subagent 才能续接,其它原生会话不受影响。
|
|
206
208
|
- 卸载不删除原生压缩事件、goal 日志或 CLI 身份 KV;handoff 临时文件不是必需依赖,删除后已压缩会话仍可从原生 checkpoint 恢复。
|
|
207
|
-
- 回退到 0.4.x 前先备份 profile 的 `cordis.patch.yml`;旧字段仍能装载,但 0.5.
|
|
209
|
+
- 回退到 0.4.x 前先备份 profile 的 `cordis.patch.yml`;旧字段仍能装载,但 0.5.x 写入的新行配置不会被 0.4.x 读取。
|
|
208
210
|
|
|
209
211
|
## 提示词归属
|
|
210
212
|
|
|
@@ -224,7 +226,7 @@ dsh plugin --profile <profile> remove dsh-better-compact
|
|
|
224
226
|
- `package.json` 的 `files` 只列入 `docs/DEVELOPMENT.md`,并额外用 [.npmignore](.npmignore) 排除 `docs/specs/`;
|
|
225
227
|
- `tests/packaging.test.mjs` 直接运行 `npm pack --dry-run --json`,断言发布清单没有 Specs、测试、脚本、快照或 tarball。
|
|
226
228
|
|
|
227
|
-
发布顺序:**先发布并验证两个独立包(`@menghuan1918/dsh-better-subagent@0.1.0`、`dsh-better-compact@0.1.0`),再发布 Apollo 0.5.0
|
|
229
|
+
发布顺序:**先发布并验证两个独立包(`@menghuan1918/dsh-better-subagent@0.1.0`、`dsh-better-compact@0.1.0`),再发布 Apollo 0.5.1**。两个 0.1.0 已随 0.5.0 发布;0.5.1 可只发布本包。Apollo 的精确依赖指向尚不存在的版本时,`npm install` 会失败;不要用开发 `file:`/`link:` 依赖发布。两个子仓各自有 trusted publishing workflow;Apollo 的 [release workflow](.github/workflows/release.yml) 只发布本包。
|
|
228
230
|
|
|
229
231
|
## 验证状态(诚实记录)
|
|
230
232
|
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
面向维护者、集成者和需要排查装配问题的用户。用户安装与配置请看 [README](../README.md);本文保留 DSH 插件的实现细节、旧配置迁移、组合安装边界与验证方法。
|
|
4
4
|
|
|
5
|
-
当前实现版本:`0.5.
|
|
5
|
+
当前实现版本:`0.5.1`;npm 包名是 `@menghuan1918/dsh-apollo`。纯 ESM,无构建步骤;宿主浏览器半边是直接加载的闭包工厂。
|
|
6
6
|
|
|
7
7
|
## 目录
|
|
8
8
|
|
|
@@ -203,6 +203,8 @@ npm install --no-save /path/to/menghuan1918-dsh-better-subagent-0.1.0.tgz /path/
|
|
|
203
203
|
|
|
204
204
|
来源:`apollo-skills` 的**有效配置**。volatile 字段来自 `describe().value`;非 volatile 的 `trustedHosts` 来自旧行 raw config(`describe().value` 只投影 volatile 表单,不能用来判断 trustedHosts)。
|
|
205
205
|
|
|
206
|
+
**0.5.1 修复**:DSH 把 profile 覆盖行的 `name` 当 guard。旧 profile 若保留历史 `name: dsh-apollo`,Loader 会跳过该覆盖,`describe().value` 只剩默认值(例如用户显式 `subagents.eng: false` 会被看成默认 `true`)。迁移现在额外读取 `configEditor.configuration()` 中该行的 `override`,递归合并到有效配置之上:普通对象逐键合并,数组与所有标量(含 `false`/`0`/`""`/`[]`)整体覆盖。这样被跳过的显式值仍会迁移。`preset-eng` / `preset-eng-ptc` 的预设覆盖也按同样方式合并(`plugins` 数组整体替换),再读取原生 `compaction-basic`。
|
|
207
|
+
|
|
206
208
|
目标:`dsh-better-subagent` 的 `settings.describe()`:
|
|
207
209
|
|
|
208
210
|
- `target.user` 的存在性表示显式值(含 false/0/""/[]);
|
|
@@ -306,10 +308,10 @@ DSH_PACKAGE_ROOT="/…/node_modules/@deepseek-ai/dsh" npm run prompts
|
|
|
306
308
|
### npm 安装
|
|
307
309
|
|
|
308
310
|
```sh
|
|
309
|
-
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.
|
|
311
|
+
dsh plugin --profile <profile> add @menghuan1918/dsh-apollo@0.5.1
|
|
310
312
|
```
|
|
311
313
|
|
|
312
|
-
包发布后即可用此命令安装,并带入三个精确依赖、应用三份 bundle patch。安装后需要重启对应 profile 的 DSH
|
|
314
|
+
包发布后即可用此命令安装,并带入三个精确依赖、应用三份 bundle patch。安装后需要重启对应 profile 的 DSH 进程。0.5.0 已发布;0.5.1 是迁移修复版本,可只发布本包。
|
|
313
315
|
|
|
314
316
|
### GitHub 源码安装
|
|
315
317
|
|
|
@@ -344,7 +346,7 @@ dsh --profile <profile> --dump-config
|
|
|
344
346
|
|
|
345
347
|
### 升级
|
|
346
348
|
|
|
347
|
-
- 升级包后重启 profile;0.4.x → 0.5.
|
|
349
|
+
- 升级包后重启 profile;0.4.x → 0.5.x 的迁移见 [旧配置迁移](#旧配置迁移);
|
|
348
350
|
- 迁移写入的 compact 设置需要再重载一次才会被运行中引擎采用;
|
|
349
351
|
- 升级 DSH 后先跑 `npm test`,漂移测试会按目标 DSH 安装比较预设;
|
|
350
352
|
- 版本范围声明:Node `^22.19.0 || >=24.0.0`,DSH `>=0.2.1-rc.2 <0.3.0`;声明范围接受预发布版,不等于逐版验证保证。
|
|
@@ -363,7 +365,7 @@ dsh plugin --profile <profile> remove @menghuan1918/dsh-apollo
|
|
|
363
365
|
|
|
364
366
|
1. 先发布 `@menghuan1918/dsh-better-subagent@0.1.0` 与 `dsh-better-compact@0.1.0`(各自仓库的 Release);
|
|
365
367
|
2. 在官方 registry(`https://registry.npmjs.org/`)确认两个版本可取得、可安装;
|
|
366
|
-
3. 再把 Apollo 的精确依赖指向已发布版本,推 main 并发布 Apollo Release
|
|
368
|
+
3. 再把 Apollo 的精确依赖指向已发布版本,推 main 并发布 Apollo Release(0.5.0 已发布;本轮为 `v0.5.1`);
|
|
367
369
|
4. 子包版本可取得前,不要把指向它们的精确依赖推到 Apollo main,否则 `npm install` / GitHub 源码安装会 404。
|
|
368
370
|
|
|
369
371
|
## 测试与冒烟
|
|
@@ -390,7 +392,7 @@ DSH_PACKAGE_ROOT=/path/to/node_modules/@deepseek-ai/dsh npm test
|
|
|
390
392
|
| [tests/dsh-home.test.mjs](../tests/dsh-home.test.mjs) | `DSH_HOME` 的默认、绝对、`~`、相对与空白处理 |
|
|
391
393
|
| [tests/exit-guard.test.mjs](../tests/exit-guard.test.mjs) | job-only 判断、终态过滤、source kind、SessionId 参数、fail-open、用户中断、无豁免 |
|
|
392
394
|
| [tests/migrate.test.mjs](../tests/migrate.test.mjs) | 迁移纯函数与 fake host 编排(见上) |
|
|
393
|
-
| [tests/migration.runtime.test.mjs](../tests/migration.runtime.test.mjs) | 真实 temp-profile
|
|
395
|
+
| [tests/migration.runtime.test.mjs](../tests/migration.runtime.test.mjs) | 真实 temp-profile 迁移;含旧 `name: dsh-apollo` 被 Loader 跳过时从 `configuration().override` 恢复显式值的回归(无宿主时跳过) |
|
|
394
396
|
| [tests/mode-instructions.test.mjs](../tests/mode-instructions.test.mjs) | 只含通用纪律 + job 守卫;无委派/分档/CLI/PTC 文本;不依赖 tiers |
|
|
395
397
|
| [tests/owns-host.test.mjs](../tests/owns-host.test.mjs) | `declareOwnsHost` tap 注入位置、开关、去重、零路由 |
|
|
396
398
|
| [tests/packaging.test.mjs](../tests/packaging.test.mjs) | 真实 `npm pack --dry-run`:Specs/tests/scripts/prompts/tarball 不在清单 |
|
|
@@ -479,7 +481,7 @@ DSH_PACKAGE_ROOT=/path/to/node_modules/@deepseek-ai/dsh node scripts/runtime-smo
|
|
|
479
481
|
|
|
480
482
|
### 发布
|
|
481
483
|
|
|
482
|
-
release workflow 使用 npm trusted publishing:tag 必须等于 `package.json` 版本,先 `npm install` / `npm test` 再 `npm publish --provenance`。Apollo 0.5.
|
|
484
|
+
release workflow 使用 npm trusted publishing:tag 必须等于 `package.json` 版本,先 `npm install` / `npm test` 再 `npm publish --provenance`。Apollo 0.5.x 的 release job 只有在两个子包 0.1.0 可取得后才可能成功;不要硬编码 token、假发布或用开发 link 代替正式依赖。
|
|
483
485
|
|
|
484
486
|
## 许可与致谢
|
|
485
487
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@menghuan1918/dsh-apollo",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "DSH plugin bundle: workflow skills, engineering presets, independent better-goal / better-subagent / better-compact integration, and a minimal job exit guard. Pure ESM, no build step.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": {
|
package/src/migrate.js
CHANGED
|
@@ -70,6 +70,35 @@ function clone(value) {
|
|
|
70
70
|
return value === undefined ? undefined : structuredClone(value)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Deep-merge an explicit profile override over an effective config.
|
|
75
|
+
*
|
|
76
|
+
* DSH applies a profile row's `name` as a guard: an old row whose name no
|
|
77
|
+
* longer matches the active row (for example the historical
|
|
78
|
+
* `name: dsh-apollo` on `apollo-skills`) is skipped by the Loader, yet
|
|
79
|
+
* `configEditor.configuration().override` still exposes its explicit config.
|
|
80
|
+
* Merging that override back over the effective config recovers the user's
|
|
81
|
+
* explicit values during migration.
|
|
82
|
+
*
|
|
83
|
+
* Plain objects merge recursively; arrays and every scalar - including
|
|
84
|
+
* explicit `false`, `0`, `""` and `[]` - replace the base value.
|
|
85
|
+
*
|
|
86
|
+
* @param base - effective config (defaults + applied layers).
|
|
87
|
+
* @param override - raw explicit profile override; undefined means "no override".
|
|
88
|
+
* @returns a detached merged value.
|
|
89
|
+
*/
|
|
90
|
+
export function mergeConfigOverride(base, override) {
|
|
91
|
+
if (override === undefined) return clone(base)
|
|
92
|
+
if (!isRecord(base) || !isRecord(override)) return clone(override)
|
|
93
|
+
const result = clone(base)
|
|
94
|
+
for (const [key, value] of Object.entries(override)) {
|
|
95
|
+
result[key] = isRecord(value) && isRecord(result[key])
|
|
96
|
+
? mergeConfigOverride(result[key], value)
|
|
97
|
+
: clone(value)
|
|
98
|
+
}
|
|
99
|
+
return result
|
|
100
|
+
}
|
|
101
|
+
|
|
73
102
|
/** Assign a nested path into a patch object. */
|
|
74
103
|
function setPatch(patch, keys, value) {
|
|
75
104
|
let node = patch
|
|
@@ -383,7 +412,26 @@ function defaultPresetOf(agentPresets) {
|
|
|
383
412
|
}
|
|
384
413
|
}
|
|
385
414
|
|
|
386
|
-
/**
|
|
415
|
+
/** Read one row's raw profile override from configEditor.configuration(). */
|
|
416
|
+
function configurationOverrideOf(configEditor, id) {
|
|
417
|
+
try {
|
|
418
|
+
const rows = configEditor?.configuration?.()
|
|
419
|
+
if (!Array.isArray(rows)) return undefined
|
|
420
|
+
const row = rows.find((candidate) => candidate?.entry?.options?.id === id)
|
|
421
|
+
return isRecord(row?.override) ? row.override : undefined
|
|
422
|
+
} catch {
|
|
423
|
+
return undefined
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Top-level preset declarations visible to configEditor.entries().
|
|
429
|
+
*
|
|
430
|
+
* A preset override whose `name` guard no longer matches is skipped by the
|
|
431
|
+
* Loader, so merge the configuration override back before reading its native
|
|
432
|
+
* `compaction-basic` config. Array values (the child `plugins` list) replace
|
|
433
|
+
* wholesale, matching DSH's preset-override semantics.
|
|
434
|
+
*/
|
|
387
435
|
function presetRowsOf(configEditor) {
|
|
388
436
|
let entries
|
|
389
437
|
try {
|
|
@@ -394,11 +442,16 @@ function presetRowsOf(configEditor) {
|
|
|
394
442
|
if (!Array.isArray(entries)) return []
|
|
395
443
|
return entries
|
|
396
444
|
.filter((entry) => entry?.options?.name === '@deepseek-ai/dsh-agent-preset')
|
|
397
|
-
.map((entry) =>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
config:
|
|
401
|
-
|
|
445
|
+
.map((entry) => {
|
|
446
|
+
const base = isRecord(entry.options.config) ? entry.options.config : {}
|
|
447
|
+
const override = configurationOverrideOf(configEditor, entry.options.id)
|
|
448
|
+
const config = override === undefined ? base : mergeConfigOverride(base, override)
|
|
449
|
+
return {
|
|
450
|
+
rowId: entry.options.id,
|
|
451
|
+
presetId: config.id,
|
|
452
|
+
config,
|
|
453
|
+
}
|
|
454
|
+
})
|
|
402
455
|
}
|
|
403
456
|
|
|
404
457
|
/** Find the target row entry (needed for the non-volatile trustedHosts write). */
|
|
@@ -550,13 +603,20 @@ export async function runMigration(ctx, options = {}) {
|
|
|
550
603
|
const agentPresets = options.agentPresets ?? serviceOf(ctx, 'agentPresets')
|
|
551
604
|
// describe().value only projects the *volatile* form, so read the Apollo
|
|
552
605
|
// row's raw config for non-volatile fields (trustedHosts) and overlay the
|
|
553
|
-
// live volatile values on top.
|
|
606
|
+
// live volatile values on top. Finally merge the raw profile override:
|
|
607
|
+
// DSH skips a row whose old `name` guard no longer matches (historical
|
|
608
|
+
// `name: dsh-apollo`), and only configuration().override still carries the
|
|
609
|
+
// user's explicit values.
|
|
554
610
|
const rawSource = targetEntryOf(configEditor, APOLLO_NS)?.options?.config
|
|
555
611
|
const sourceBase = {
|
|
556
612
|
...(isRecord(options.config) ? options.config : {}),
|
|
557
613
|
...(isRecord(rawSource) ? rawSource : {}),
|
|
558
614
|
}
|
|
559
|
-
const
|
|
615
|
+
const effectiveSource = { ...sourceBase, ...(sourceDescriptor?.value ?? {}) }
|
|
616
|
+
const source = normalizeConfig(mergeConfigOverride(
|
|
617
|
+
effectiveSource,
|
|
618
|
+
configurationOverrideOf(configEditor, APOLLO_NS),
|
|
619
|
+
))
|
|
560
620
|
const subagent = await migrateSubagent({ settings, configEditor, descriptors, source, log })
|
|
561
621
|
const compact = await migrateCompact({ settings, configEditor, descriptors, agentPresets, log })
|
|
562
622
|
const status = [subagent.status, compact.status].some((value) => value === 'error')
|