@luchenglong/cli-bridge 0.2.7 → 0.2.8
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 +48 -0
- package/docs/HANDOVER.md +9 -0
- package/docs/audits/2026-10-18-preset-0.2.1-contract-fix.md +160 -0
- package/docs/audits/README.md +15 -0
- package/home-plugin/cli-bridge-indicator/lib/preset-declarations.mjs +85 -6
- package/mcp/cli-bridge-mcp.mjs +2 -2
- package/package.json +5 -5
- package/preset/agy-first/agent.cordis.yml +0 -5
- package/preset/agy-first/plugin-list.mjs +4 -1
- package/preset/codebuddy-first/agent.cordis.yml +0 -5
- package/preset/mimo-first/agent.cordis.yml +1 -7
- package/preset/mimo-first/plugin-list.mjs +18 -12
- package/preset/mimo-member/plugin-list.mjs +49 -0
- package/preset/opencode-first/agent.cordis.yml +0 -5
- package/preset/opencode-first/plugin-list.mjs +4 -2
- package/preset/standard-base.mjs +18 -6
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,54 @@ GitHub Release(`scripts/verify.mjs` 在 CI 与 prepack 双重锁一致)。
|
|
|
9
9
|
> - CodeBuddy 线:[docs/history/codebuddy/CHANGELOG.md](docs/history/codebuddy/CHANGELOG.md)(终版 1.6.2)
|
|
10
10
|
> - MiMo 线:[docs/history/mimo/CHANGELOG.md](docs/history/mimo/CHANGELOG.md)(终版 1.2.9)
|
|
11
11
|
|
|
12
|
+
## [0.2.8] - 2026-10-18
|
|
13
|
+
|
|
14
|
+
> 用户使用 agy 优先模式时整轮失败:
|
|
15
|
+
> `unknown prompt variable "{{cwd}}" in section "deployment:persona-suffix"; registered variables: provider, model`。
|
|
16
|
+
> 根因是**预设从旧版上游模板转录**,继承了上游在实装 `0.2.1-alpha.5` 已删除的三类写法。
|
|
17
|
+
> 完整方案与逐项取证:[docs/audits/2026-10-18-preset-0.2.1-contract-fix.md](docs/audits/2026-10-18-preset-0.2.1-contract-fix.md)。
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **预设整体不可用:persona `suffix` 里的 `{{cwd}}` 不是注册变量**。`dsh-system-prompt` 的
|
|
22
|
+
`interpolate()` 对 `{{name}}` 严格解析(须匹配 `/^[a-z][a-z0-9_]*$/` 且**已注册**),
|
|
23
|
+
未注册引用会在**任何模型请求之前**抛错 ⇒ 该预设完全不可用。当前循环只注册 `provider` 与
|
|
24
|
+
`model`(`dsh-agent-loop`),工作目录已改由 working-directory 服务以「不插值的用户上下文」
|
|
25
|
+
提供 —— 官方预设的 persona 因此**只有 `prefix`**。已在 `standard-base.mjs` 与
|
|
26
|
+
agy/mimo/opencode 三个单源里删除 `suffix`,并重新生成四个 `agent.cordis.yml`。
|
|
27
|
+
- **`cordis-mimo` 整个预设挂载失败:`tool-subagent.config.persona`**。`dsh-tool-subagent`
|
|
28
|
+
0.2.1 起在 `apply()` 里对 `persona`/`toolFilter` **显式 throw**
|
|
29
|
+
("…no longer supported; configure persona and tool plugins in an Agent Preset and select it
|
|
30
|
+
with agentPreset (spawn only)")。原委派人格已**迁移**为成员预设(见 Added),能力未丢失。
|
|
31
|
+
- **死配置 `backgroundMode`**(四行委派行都有)。该字段已从 DSH 全部包移除,且实装 schema
|
|
32
|
+
**会放行并保留**它(`Config['~standard'].validate` 无 issues;schemastery 没有 strict 开关),
|
|
33
|
+
只是**无人读取** ⇒ 静默**忽略**而非丢弃:表面声明 `continuable`/`one-shot` 却毫无效果,
|
|
34
|
+
且**运行时不报错**。已删除。
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **成员预设 `cordis-mimo-member`**(`preset/mimo-member/plugin-list.mjs`):人格 = 旧委派指令
|
|
39
|
+
verbatim;工具面 = mimo 桥接行(子 agent 必须能调 `mimo_run` 才能"派活")+ 只读文件面
|
|
40
|
+
(旧 `toolFilter` 白名单的新表达:`write`/`edit` 直接不存在)。`cordis-mimo` 的 **spawn**
|
|
41
|
+
行以 `agentPreset` 引用它;**fork 行不设**(`agentPreset` 仅 in-process spawn 支持,
|
|
42
|
+
fork/外部后端会 reject)。成员预设**先于**主预设注册(委派行 `validate()` 会经
|
|
43
|
+
`presets.readDocument(id)` 校验引用存在)。
|
|
44
|
+
- **防回归闸门 `tests/keystone/persona-prompt-vars.test.mjs`**:persona 的 `{{var}}` 必须在注册
|
|
45
|
+
白名单内且不设 `suffix`;`tool-subagent` 行不得带已删字段;委派行的 `agentPreset` 必须等于
|
|
46
|
+
成员预设 `meta.id` 且只出现在 `spawn` 行。内存单源 + 磁盘生成物双层。三道闸门均已实测
|
|
47
|
+
**按正确原因变红**后再保留。
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- `tests/keystone/scheduling-gate.test.mjs` 的注册顺序期望改为从成员表派生
|
|
52
|
+
(`[...memberPresetIds(ids), ...provider presets]`),不硬编码。
|
|
53
|
+
|
|
54
|
+
### 未跟进(能力面差异,非缺陷)
|
|
55
|
+
|
|
56
|
+
- 相对实装 `dsh-web-app@0.2.1-alpha.5` 的官方 standard 预设(35 行),本包基线(对齐官方
|
|
57
|
+
`0.1.7-rc.1`,33 行)缺 `time-context`、`tool-schedule`、`tool-plugin-market`。属能力面差异,
|
|
58
|
+
是否跟进待定。
|
|
59
|
+
|
|
12
60
|
## [0.2.7] - 2026-10-18
|
|
13
61
|
|
|
14
62
|
> 0.2.6 发布后立即发现两件事必须纠正,故 0.2.7 紧随其后。
|
package/docs/HANDOVER.md
CHANGED
|
@@ -317,6 +317,15 @@ npm whoami # 应输出 luchenglong
|
|
|
317
317
|
已收敛到 `mcp/version.mjs` 单一来源(红线 §5.8)。
|
|
318
318
|
- **测试里硬编码 id 列表**:4 个 keystone 测试钉死三家 id,新增 provider 即红 → 违反单一 id 轴。
|
|
319
319
|
已全部改为从 `PROVIDER_IDS` 派生(红线 §5.4)。
|
|
320
|
+
- **预设契约随 DSH 版本漂移**(2026-10-18):预设从**旧版上游模板**转录,继承了上游已删除的写法 →
|
|
321
|
+
① persona `suffix` 里的 `{{cwd}}` 不再是注册变量(DSH 只注册 `provider`/`model`),
|
|
322
|
+
组装期直接 throw,**整个预设不可用**;② `dsh-tool-subagent` 0.2.1 起 `persona`/`toolFilter`
|
|
323
|
+
在 `apply()` 里显式 throw、`backgroundMode` 被静默**忽略**(注意:不是"被 schema 丢弃" ——
|
|
324
|
+
实测实装 schema 会**放行并保留**该键,只是无人读取;所以运行时不报错,只能靠静态闸门拦)。
|
|
325
|
+
已修 + 立三层闸门(`tests/keystone/persona-prompt-vars.test.mjs`)。
|
|
326
|
+
**完整方案与取证:`docs/audits/2026-10-18-preset-0.2.1-contract-fix.md`**(索引 `docs/audits/README.md`)。
|
|
327
|
+
教训:上游预设模板是**会过期**的参考物,升级 DSH 后必须重新对照已实装包的
|
|
328
|
+
`presets/*.patch.yml` 与 `lib/index.js` 的 schema,不能沿用旧转录。
|
|
320
329
|
|
|
321
330
|
## 13. OpenCode provider(0.2.3 新增)
|
|
322
331
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# 审计:DSH 0.2.1 预设契约漂移修复(2026-10-18)
|
|
2
|
+
|
|
3
|
+
> 起因:用户使用 **agy 优先模式**时整轮失败 ——
|
|
4
|
+
> `unknown prompt variable "{{cwd}}" in section "deployment:persona-suffix"; registered variables: provider, model`
|
|
5
|
+
>
|
|
6
|
+
> 修复范围:本仓(`@luchenglong/cli-bridge`)+ 姊妹仓 `agy-first-bridge`。
|
|
7
|
+
> 本文是**修复方案 + 结果审计**存档(用户规则 #29),并与 `docs/HANDOVER.md` §12 速查表互相索引。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. 根因
|
|
12
|
+
|
|
13
|
+
DSH 的提示词组装器 `interpolate()`(`dsh-system-prompt/lib/index.js:158-182`)对 `{{name}}` 做**严格解析**:
|
|
14
|
+
|
|
15
|
+
| 判据 | 源码 | 违反后果 |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| 完整 `{{…}}` 组 | `GROUP_AT = /^\{\{([^{}]*)\}\}/`(:65) | 有 `}}` 却不成组 → `malformed prompt variable reference` |
|
|
18
|
+
| 名字形态 | `VARIABLE_NAME = /^[a-z][a-z0-9_]*$/`(:63) | `{{cwd }}`(含空格)也算 malformed |
|
|
19
|
+
| **必须已注册** | `if (!Object.hasOwn(variables, name)) throw`(:172-174) | `unknown prompt variable` |
|
|
20
|
+
|
|
21
|
+
关键:它在**任何模型请求之前**、组装系统提示词时抛错 ⇒ 整个回合失败,且该预设**完全不可用**(不是降级、不是警告)。
|
|
22
|
+
|
|
23
|
+
**当前只注册两个变量**(已全量取证):
|
|
24
|
+
|
|
25
|
+
- `dsh-agent-loop/lib/index.js:1591-1592` —— `provider` / `model`,全仓无第二个注册点。
|
|
26
|
+
- 官方 `dsh-system-prompt/README.zh.md:72` —— 工作目录改由 working-directory 服务以
|
|
27
|
+
**不执行插值的用户上下文**提供;`:78` 明确要求从 preset 的 `suffix` 字段移除该句。
|
|
28
|
+
- 实装 `dsh-web-app@0.2.1-alpha.5` 的 `presets/{standard,ptc,cordis,minimal}.patch.yml`
|
|
29
|
+
的 persona **只有 `prefix`**,没有 `suffix`。
|
|
30
|
+
|
|
31
|
+
**为什么现在才炸(漂移性质)**:上游预设在 `0.1.5-rc.2` ~ `0.1.7-rc.1` 期间**确实带**这句
|
|
32
|
+
(`agy-first-bridge/.probe/wa-*` 逐版留证 16 处),到 `0.2.1-alpha.5` 才移除。
|
|
33
|
+
本仓预设从**旧版上游模板转录**而来 ⇒ 继承了被上游删除的 suffix。
|
|
34
|
+
属"上游改版、下游转录物陈旧"型漂移,**不是**当初写错。
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. 第二类缺陷(同一主题,独立成因)
|
|
39
|
+
|
|
40
|
+
排查"还有没有同类问题"时又查出两类 **dsh-tool-subagent 契约漂移**:
|
|
41
|
+
|
|
42
|
+
| 字段 | 0.2.1 行为 | 证据 | 影响 |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| `persona` | **显式 throw** | `dsh-tool-subagent/lib/index.js:355`:`for (const field of ["persona","toolFilter"]) if (Object.hasOwn(config, field)) throw new Error("tool-subagent: … is no longer supported; configure persona and tool plugins in an Agent Preset and select it with agentPreset (spawn only)")` | **mimo 预设整个挂载失败** |
|
|
45
|
+
| `toolFilter` | 同上 | 同上 | 同上 |
|
|
46
|
+
| `backgroundMode` | **静默忽略(非丢弃)** | 该字段已从 DSH 全部包消失(实测全仓 0 命中);且实装 schema **会放行**它 —— 见下方更正 | 声明 `continuable`/`one-shot` 却毫无效果,**运行时不报错** |
|
|
47
|
+
|
|
48
|
+
> **⚠ 机制更正(2026-10-18 独立验证查出)**:初稿写"`Config` 不是 strict ⇒ 被静默丢弃"是**错的**。
|
|
49
|
+
> 用实装包双路径实测:`Config({provider, backgroundMode})` 与 cordis 真正走的
|
|
50
|
+
> `Config['~standard'].validate(...)`(`cordis/lib/index.js:958`)**都无 issues 且把该键原样保留**;
|
|
51
|
+
> `Config.strict` 为 `undefined` —— schemastery **根本没有 strict 开关**。
|
|
52
|
+
> 正确表述:未知/已删键**通过校验并被保留**,随后**无人读取** ⇒ 静默**忽略**。
|
|
53
|
+
> 这条更正很关键:正因为校验放行,**运行时永远抓不到这类死字段**,静态闸门是唯一防线;
|
|
54
|
+
> 而"schema 会丢"的错误表述会让人误以为 schema 层已兜住。
|
|
55
|
+
> 附带影响:键被保留 ⇒ 任何对 config 的反射/对比/序列化都可能把它当**幽灵设置**暴露出来。
|
|
56
|
+
|
|
57
|
+
当前 `Config` 接受:`provider` / `toolName` / `modelSelectionSettings` / `agentOptions` /
|
|
58
|
+
`agentPreset` / `allowedAgentPresets` / `maxDepth`。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. 修复方案
|
|
63
|
+
|
|
64
|
+
### 3.1 变量契约(`{{cwd}}`)
|
|
65
|
+
|
|
66
|
+
删除所有 preset 的 persona `suffix`,保留 `prefix` 的 `{{model}}`。与官方预设形态一致。
|
|
67
|
+
|
|
68
|
+
| 文件 | 性质 |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `preset/standard-base.mjs` | **源头**(共享基座;codebuddy 经它继承) |
|
|
71
|
+
| `preset/agy-first/plugin-list.mjs`、`preset/mimo-first/plugin-list.mjs`、`preset/opencode-first/plugin-list.mjs` | **源头**(各自 persona 覆盖) |
|
|
72
|
+
| `preset/{agy,codebuddy,mimo,opencode}-first/agent.cordis.yml` | **生成物** —— 由 `node scripts/build.mjs` 从上述源头重新生成 |
|
|
73
|
+
|
|
74
|
+
> ⚠️ 只改生成物无效:`npm test` 里的 `build --check` 会判漂移失败。
|
|
75
|
+
|
|
76
|
+
### 3.2 死字段(`backgroundMode`)
|
|
77
|
+
|
|
78
|
+
从 `preset/standard-base.mjs` 的委派组四行中删除。
|
|
79
|
+
|
|
80
|
+
### 3.3 mimo 委派人设 → 成员预设(迁移,不删能力)
|
|
81
|
+
|
|
82
|
+
0.2.1 的契约是"人格与工具面放进独立 Agent Preset,由委派行经 `agentPreset` 选择"。
|
|
83
|
+
新增成员预设 + 让 spawn 行引用它,**保留**"子 agent 优先把活派给 mimo_run"这一能力。
|
|
84
|
+
|
|
85
|
+
| 新增/改动 | 内容 |
|
|
86
|
+
|---|---|
|
|
87
|
+
| **新增** `preset/mimo-member/plugin-list.mjs` | 成员预设单源:人格(旧委派指令 verbatim)+ mimo 桥接工具面(子 agent 必须能调 `mimo_run`)+ 只读文件面(旧 `toolFilter` 白名单的新表达:`write/edit: false`) |
|
|
88
|
+
| `preset/mimo-first/plugin-list.mjs` | 删 `persona`/`toolFilter`;**仅 spawn 行**加 `agentPreset: cordis-mimo-member`(`fork` 与外部后端会 reject 该字段) |
|
|
89
|
+
| `home-plugin/…/lib/preset-declarations.mjs` | 新增 `declareMemberPresets()` 并在主预设**之前**注册;导出 `memberPresetIds()` 供测试派生 |
|
|
90
|
+
|
|
91
|
+
**可行性取证(关键,避免了错误的实现路径)**:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
// dsh-agent-preset-registry/lib/index.js
|
|
95
|
+
async register(definition) { … this.definitions.set(definition.id, record) } // :470-479 写
|
|
96
|
+
readDocument(agentPreset) { const record = this.definitions.get(agentPreset) … } // :613 读**同一个 Map**
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
而委派行 `validate()` 正是用 `presets.readDocument(id)` 校验引用
|
|
100
|
+
(`dsh-tool-subagent/lib/index.js:228-232`,未注册即 `agent-preset/not-found`)。
|
|
101
|
+
⇒ **动态 `register()` 与 bundle 行声明互通**,无需改用 bundle 行,
|
|
102
|
+
因而不破坏本包"旧 DSH 上不因行 import 失败而整包拒挂"的既有设计(见 `cordis.patch.yml` 头注)。
|
|
103
|
+
|
|
104
|
+
顺序要求:成员预设**先于**主预设注册(kexi-crypto v1.9.21 同款结论)。
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. 防回归闸门
|
|
109
|
+
|
|
110
|
+
新增 `tests/keystone/persona-prompt-vars.test.mjs`(15 项),三层同时覆盖:
|
|
111
|
+
|
|
112
|
+
1. **内存单源层** —— 对 5 个 preset 目录(4 provider + 1 成员)的 `buildPlugins()` 输出断言:
|
|
113
|
+
- persona 的 `prefix`/`suffix` 里每个 `{{var}}` ∈ `['provider','model']`;
|
|
114
|
+
- `suffix` 必须缺席;
|
|
115
|
+
- `tool-subagent` 行不含 `persona`/`toolFilter`/`backgroundMode`。
|
|
116
|
+
2. **磁盘生成物层** —— 对 4 个 `agent.cordis.yml` 全文同样断言(防只手改生成物)。
|
|
117
|
+
字段用**键正则** `(^|\n)[ \t]*<field>[ \t]*:` 匹配,而非子串 —— 否则
|
|
118
|
+
`name: '@deepseek-ai/dsh-persona'` 与 `- id: persona` 会误报。
|
|
119
|
+
3. **跨文件一致性层** —— 委派行引用的 `agentPreset` 必须等于成员预设的 `meta.id`,
|
|
120
|
+
且只允许出现在 `provider: spawn` 行上(fork/外部后端会 reject)。
|
|
121
|
+
|
|
122
|
+
`tests/keystone/scheduling-gate.test.mjs` 与 `tests/mimo/plugin-list.test.mjs` 同步改造:
|
|
123
|
+
注册顺序期望改为 `[...memberPresetIds(ids), ...provider presets]`(从单一源派生,不硬编码)。
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 5. 验证结果(本机实测)
|
|
128
|
+
|
|
129
|
+
| 命令 | 结果 |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `node scripts/build.mjs --check` | `[build] up to date`,exit 0 |
|
|
132
|
+
| `node --test` | **373 tests / 372 pass / 0 fail / 1 skipped**,exit 0(20.5s) |
|
|
133
|
+
| `node scripts/verify.mjs` | `verify: OK`(含导出目标、四 provider 描述符、凭据扫描 201 文件) |
|
|
134
|
+
| `node mcp/cli-bridge-mcp.mjs --check` | `"errors": []`,exit 0 |
|
|
135
|
+
| 静态复核 | mimo 生成物含 `agentPreset: cordis-mimo-member`、**无** `persona:` 字段、无 `backgroundMode`、4 个 yml 均无 `{{cwd}}` |
|
|
136
|
+
|
|
137
|
+
**闸门"确实会红"取证**(临时注入缺陷 → 跑闸门 → 还原,三次均按**正确原因**变红):
|
|
138
|
+
|
|
139
|
+
| 注入的缺陷 | 闸门报错 |
|
|
140
|
+
|---|---|
|
|
141
|
+
| 删掉 spawn 行的 `agentPreset` | `本 provider 应至少有一行经 agentPreset 选择成员预设` |
|
|
142
|
+
| 把 `persona` 写回 spawn 行 | `tool-subagent 行 'tool-subagent' 仍带已删除字段 persona` |
|
|
143
|
+
| 成员预设 `id` 改成 `cordis-mimo-member-TYPO` | `tool-subagent 行 'tool-subagent' 的 agentPreset 与成员预设 id 不一致` |
|
|
144
|
+
|
|
145
|
+
另:`{{cwd}}` 的闸门在修复过程中亦已实测会红(写回后 `agent.cordis.yml 引用了未注册变量 {{cwd}}`)。
|
|
146
|
+
全部场景还原后复跑均恢复绿。
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 6. 未做 / 遗留
|
|
151
|
+
|
|
152
|
+
- **未发版**:未 bump `package.json` 版本、未加 `CHANGELOG.md` 条目、未 `npm publish`、未 commit。
|
|
153
|
+
- **姊妹仓**:`agy-first-bridge` 的同类修复由并行同伴完成并独立复跑验证,同样未发版。
|
|
154
|
+
- **历史留证未动**:`docs/history/**/CHANGELOG.md` 与 `agy-first-bridge/.probe/**` 里的 `{{cwd}}`
|
|
155
|
+
字面量是"上游旧版确有该 suffix"的原始证据,**故意保留**。
|
|
156
|
+
- **面未覆盖**:本次只治理 preset 内的人格模板;宿主层 `personaSuffix`、
|
|
157
|
+
家级/profile `cordis.patch.yml` 若也有未注册引用,需另行排查(本闸门不覆盖)。
|
|
158
|
+
- **成员预设工具面偏窄**(刻意):只给只读文件面 + 桥接行。若希望子 agent 能自己跑构建做验证,
|
|
159
|
+
需在 `preset/mimo-member/plugin-list.mjs` 里补平台门控 shell —— 属产品取舍,未擅自加。
|
|
160
|
+
- **`.probe/` 留证已过期**(只到 `0.1.7-rc.1`,实装已 `0.2.1-alpha.5`):若要复算上游轨迹需重取该版本 tarball。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# docs/audits — 修复方案与结果审计存档
|
|
2
|
+
|
|
3
|
+
本目录按"一事一档"存放**修复方案 + 验证结果 + 取证**,供后来者追溯"当时为什么这么改、
|
|
4
|
+
验证到什么程度、还有什么没做"。索引如下(新档请追加一行)。
|
|
5
|
+
|
|
6
|
+
| 日期 | 主题 | 档 |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| 2026-10-18 | DSH 0.2.1 预设契约漂移:`{{cwd}}` 未注册变量、`tool-subagent` 已删字段、mimo 委派人设迁移为成员预设 | [2026-10-18-preset-0.2.1-contract-fix.md](./2026-10-18-preset-0.2.1-contract-fix.md) |
|
|
9
|
+
|
|
10
|
+
相关索引:
|
|
11
|
+
|
|
12
|
+
- 事故速查表:`docs/HANDOVER.md` §12
|
|
13
|
+
- 排障手册(症状 → 原因 → 处置):`docs/HANDOVER.md` §10
|
|
14
|
+
- 不可动的契约(红线):`docs/HANDOVER.md` §5
|
|
15
|
+
- 发布流程:`docs/RELEASE-SOP.md`
|
|
@@ -27,6 +27,23 @@ export const PKG_NAME = '@luchenglong/cli-bridge'
|
|
|
27
27
|
// 三个旧包时代的遗留布局,provider id 不带 —— 这里不映射就永远找不到 plugin-list)。
|
|
28
28
|
const PRESET_DIRS = { agy: 'agy-first', codebuddy: 'codebuddy-first', mimo: 'mimo-first', opencode: 'opencode-first' }
|
|
29
29
|
|
|
30
|
+
// 【成员预设】0.2.1 起 dsh-tool-subagent 的 config 不再接受 persona/toolFilter(apply()
|
|
31
|
+
// 里显式 throw),角色人格只能作为独立 Agent Preset 存在、由委派行经 agentPreset 选择。
|
|
32
|
+
// key = provider id(决定它是否随该 provider 的启用面注册,与主预设的启用语义一致);
|
|
33
|
+
// value = { id: 预设身份(委派行按它选择), dir: preset/<dir>/plugin-list.mjs }。
|
|
34
|
+
// ⚠ 必须**先于**对应 provider 的主预设注册:主预设委派行的 validate() 会对每个
|
|
35
|
+
// agentPreset id 调 presets.readDocument(id),未注册即抛 agent-preset/not-found,
|
|
36
|
+
// 而 apply() 一抛就拖垮整组预设挂载(这正是 mimo 在 0.2.1 上挂载失败的根因链)。
|
|
37
|
+
const MEMBER_PRESETS = { mimo: { id: 'cordis-mimo-member', dir: 'mimo-member' } }
|
|
38
|
+
|
|
39
|
+
/** 只读视图:provider id → 成员预设 id(测试与诊断从它派生,避免第二处硬编码)。 */
|
|
40
|
+
export function memberPresetIds(ids) {
|
|
41
|
+
const list = ids || []
|
|
42
|
+
return Object.entries(MEMBER_PRESETS)
|
|
43
|
+
.filter(([providerId]) => list.includes(providerId))
|
|
44
|
+
.map(([, member]) => member.id)
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
31
48
|
const ROOT = join(HERE, '..', '..', '..')
|
|
32
49
|
|
|
@@ -46,26 +63,85 @@ function realize(v, seen) {
|
|
|
46
63
|
return out
|
|
47
64
|
}
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
/** 按 preset 目录名加载单源 plugin-list(provider 预设与成员预设共用)。 */
|
|
67
|
+
async function loadPluginListDir(dir) {
|
|
68
|
+
const abs = join(ROOT, 'preset', dir, 'plugin-list.mjs')
|
|
51
69
|
if (!existsSync(abs)) return null
|
|
52
70
|
const mod = await import(pathToFileURL(abs).href)
|
|
53
71
|
if (!mod || typeof mod.buildPlugins !== 'function' || !mod.meta) return null
|
|
54
72
|
return mod
|
|
55
73
|
}
|
|
56
74
|
|
|
75
|
+
async function loadPluginList(id) {
|
|
76
|
+
return loadPluginListDir(PRESET_DIRS[id] || id)
|
|
77
|
+
}
|
|
78
|
+
|
|
57
79
|
/**
|
|
58
|
-
*
|
|
80
|
+
* 按【目录名】生成 agentPresets 定义(真函数已落地;不含任何 DSH 活对象)。
|
|
81
|
+
* bridgeName 决定桥接行的入口子路径:provider 预设用 '/preset-<id>',成员预设用
|
|
82
|
+
* 其所属 provider 的同一入口(子 agent 要能调到该 provider 的 run 工具)。
|
|
59
83
|
* @returns {Promise<{id,name,description,order,plugins}|null>}
|
|
60
84
|
*/
|
|
61
|
-
|
|
62
|
-
const mod = await
|
|
85
|
+
async function buildDefinitionFromDir(dir, bridgeName) {
|
|
86
|
+
const mod = await loadPluginListDir(dir)
|
|
63
87
|
if (!mod) return null
|
|
64
88
|
const meta = mod.meta
|
|
65
|
-
const plugins = realize(mod.buildPlugins({ bridgeName
|
|
89
|
+
const plugins = realize(mod.buildPlugins({ bridgeName }) || [], [])
|
|
66
90
|
return { id: meta.id, name: meta.name || meta.id, description: meta.description || '', order: meta.order != null ? meta.order : 10, plugins }
|
|
67
91
|
}
|
|
68
92
|
|
|
93
|
+
/**
|
|
94
|
+
* 生成某 provider 的 agentPresets 定义。
|
|
95
|
+
* @returns {Promise<{id,name,description,order,plugins}|null>}
|
|
96
|
+
*/
|
|
97
|
+
export async function buildPresetDefinition(id) {
|
|
98
|
+
return buildDefinitionFromDir(PRESET_DIRS[id] || id, PKG_NAME + '/preset-' + id)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 注册某 provider 的成员预设(先行注册)。只注册启用面里的 provider,与主预设一致。
|
|
103
|
+
* @param ctx - 指示灯插件的 context。
|
|
104
|
+
* @param out - 与主预设共用的诊断数组。
|
|
105
|
+
* @param ids - 已启用(按调度顺序)的 provider id 列表。
|
|
106
|
+
*/
|
|
107
|
+
function declareMemberPresets(ctx, out, ids) {
|
|
108
|
+
if (typeof ctx.inject !== 'function') return
|
|
109
|
+
for (const [providerId, member] of Object.entries(MEMBER_PRESETS)) {
|
|
110
|
+
if (!ids.includes(providerId)) continue
|
|
111
|
+
try {
|
|
112
|
+
ctx.inject(['agentPresets'], (child) => {
|
|
113
|
+
child.effect(() => {
|
|
114
|
+
let disposer = null
|
|
115
|
+
const registering = (async () => {
|
|
116
|
+
try {
|
|
117
|
+
const def = await buildDefinitionFromDir(member.dir, PKG_NAME + '/preset-' + providerId)
|
|
118
|
+
if (!def) { out.push({ id: member.id, ok: false, error: 'plugin-list missing' }); return }
|
|
119
|
+
disposer = await child.agentPresets.register(def)
|
|
120
|
+
out.push({ id: member.id, ok: true, member: true })
|
|
121
|
+
} catch (e) {
|
|
122
|
+
out.push({ id: member.id, ok: false, error: String(e && e.message || e) })
|
|
123
|
+
try {
|
|
124
|
+
if (child.logger && typeof child.logger.warn === 'function') {
|
|
125
|
+
child.logger.warn('cli-bridge: member preset ' + member.id + ' registration skipped: ' + (e && e.message || e))
|
|
126
|
+
}
|
|
127
|
+
} catch (_) { }
|
|
128
|
+
}
|
|
129
|
+
})()
|
|
130
|
+
return async () => {
|
|
131
|
+
try { await registering } catch (_) { }
|
|
132
|
+
if (typeof disposer === 'function') {
|
|
133
|
+
try { await disposer() } catch (_) { }
|
|
134
|
+
}
|
|
135
|
+
disposer = null
|
|
136
|
+
}
|
|
137
|
+
}, 'cli-bridge: member preset declaration ' + member.id)
|
|
138
|
+
})
|
|
139
|
+
} catch (e) {
|
|
140
|
+
out.push({ id: member.id, ok: false, error: String(e && e.message || e) })
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
69
145
|
/**
|
|
70
146
|
* 在 indicator 的 ctx 上挂「agentPresets 就绪 → 注册启用面的 preset」等待器。
|
|
71
147
|
* 返回每个 provider 的注册状态数组(诊断用);任何异常都不外抛。
|
|
@@ -89,6 +165,9 @@ export function declareBridgePresets(ctx, opts) {
|
|
|
89
165
|
}
|
|
90
166
|
const out = []
|
|
91
167
|
if (typeof ctx.inject !== 'function') return out
|
|
168
|
+
// 成员预设先注册:主预设委派行的 validate() 会经 presets.readDocument(id) 校验
|
|
169
|
+
// agentPreset 引用存在,未注册即抛 agent-preset/not-found。
|
|
170
|
+
declareMemberPresets(ctx, out, ids)
|
|
92
171
|
for (const id of ids) {
|
|
93
172
|
try {
|
|
94
173
|
ctx.inject(['agentPresets'], (child) => {
|
package/mcp/cli-bridge-mcp.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import * as mimoMcp from './providers/mimo.mjs'
|
|
|
31
31
|
import * as opencodeMcp from './providers/opencode.mjs'
|
|
32
32
|
|
|
33
33
|
const SERVER_NAME = 'cli-bridge-mcp'
|
|
34
|
-
const SERVER_VERSION = '0.2.
|
|
34
|
+
const SERVER_VERSION = '0.2.8'
|
|
35
35
|
const PROTOCOL = '2024-11-05'
|
|
36
36
|
|
|
37
37
|
const PROVIDERS = [agyMcp, codebuddyMcp, mimoMcp, opencodeMcp]
|
|
@@ -183,4 +183,4 @@ process.stdin.on('data', (d) => {
|
|
|
183
183
|
process.stdin.on('end', () => { stdinClosed = true; maybeExit() })
|
|
184
184
|
process.on('SIGINT', () => process.exit(0))
|
|
185
185
|
process.on('SIGTERM', () => process.exit(0))
|
|
186
|
-
|
|
186
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luchenglong/cli-bridge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "CLI Bridge for DeepSeek Harness (DSH): one package bridging four local coding-CLI agents — agy (Google Antigravity CLI), Tencent CodeBuddy Code, Xiaomi MiMo (MiMoCode / MiMo Desktop), and OpenCode. Each provider keeps its own agent preset (cordis-agy / codebuddy-first / cordis-mimo / opencode-first), tools (agy_run / codebuddy_run / mimo_run / opencode_run + continue + status), rate-limit/network fallback dialog, and zero-dependency MCP server, unified under a single home-level status light, one settings file, and one bundle patch. Merges agy-first-bridge, codebuddy-first-bridge and mimo-first-bridge.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"url": "https://github.com/new-256/cli-bridge/issues"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
- id: persona
|
|
5
5
|
name: '@deepseek-ai/dsh-persona'
|
|
6
6
|
config:
|
|
7
|
-
suffix: 'Your working directory is {{cwd}}.'
|
|
8
7
|
prefix: 'You are a coding agent powered by the {{model}} model.'
|
|
9
8
|
- id: agent-instructions
|
|
10
9
|
name: '@deepseek-ai/dsh-agent-instructions'
|
|
@@ -86,20 +85,17 @@
|
|
|
86
85
|
provider: spawn
|
|
87
86
|
toolName: subagent
|
|
88
87
|
modelSelectionSettings: true
|
|
89
|
-
backgroundMode: continuable
|
|
90
88
|
- id: tool-subagent-fork
|
|
91
89
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
92
90
|
config:
|
|
93
91
|
provider: fork
|
|
94
92
|
toolName: subagent_fork
|
|
95
|
-
backgroundMode: continuable
|
|
96
93
|
- id: tool-subagent-codex
|
|
97
94
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
98
95
|
disabled: true
|
|
99
96
|
config:
|
|
100
97
|
provider: codex
|
|
101
98
|
toolName: subagent_codex
|
|
102
|
-
backgroundMode: one-shot
|
|
103
99
|
maxDepth: provider-managed
|
|
104
100
|
- id: tool-subagent-claude-code
|
|
105
101
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
@@ -107,7 +103,6 @@
|
|
|
107
103
|
config:
|
|
108
104
|
provider: claude-code
|
|
109
105
|
toolName: subagent_claude_code
|
|
110
|
-
backgroundMode: one-shot
|
|
111
106
|
maxDepth: provider-managed
|
|
112
107
|
- id: workflow-ptc
|
|
113
108
|
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
@@ -16,10 +16,13 @@ export function buildPlugins(deps) {
|
|
|
16
16
|
const rows = standardPluginRows()
|
|
17
17
|
// 旧仓 agent.cordis.yml persona 段 verbatim(v1.5.15:dsh-persona 要求
|
|
18
18
|
// prefix 必填 + suffix 可选;旧单 text: 字段被 schema 拒绝)。
|
|
19
|
+
// 2026-10-18:不再设置 suffix —— 当前 DSH 只注册 provider/model 两个提示词变量,
|
|
20
|
+
// 工作目录由 working-directory 服务作为不插值的用户上下文提供,写 {{cwd}} 会让
|
|
21
|
+
// 本预设整轮组装失败(unknown prompt variable)。delete 兼防基座再引入 suffix。
|
|
19
22
|
const persona = rows.find((r) => r.id === 'persona')
|
|
20
23
|
if (persona && persona.config) {
|
|
21
24
|
persona.config.prefix = 'You are a coding agent powered by the {{model}} model.'
|
|
22
|
-
persona.config.suffix
|
|
25
|
+
delete persona.config.suffix
|
|
23
26
|
}
|
|
24
27
|
rows.push(bridgeRow('agy', deps && deps.bridgeName))
|
|
25
28
|
return rows
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
- id: persona
|
|
5
5
|
name: '@deepseek-ai/dsh-persona'
|
|
6
6
|
config:
|
|
7
|
-
suffix: 'Your working directory is {{cwd}}.'
|
|
8
7
|
prefix: 'You are a coding agent powered by the {{model}} model.'
|
|
9
8
|
- id: agent-instructions
|
|
10
9
|
name: '@deepseek-ai/dsh-agent-instructions'
|
|
@@ -86,20 +85,17 @@
|
|
|
86
85
|
provider: spawn
|
|
87
86
|
toolName: subagent
|
|
88
87
|
modelSelectionSettings: true
|
|
89
|
-
backgroundMode: continuable
|
|
90
88
|
- id: tool-subagent-fork
|
|
91
89
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
92
90
|
config:
|
|
93
91
|
provider: fork
|
|
94
92
|
toolName: subagent_fork
|
|
95
|
-
backgroundMode: continuable
|
|
96
93
|
- id: tool-subagent-codex
|
|
97
94
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
98
95
|
disabled: true
|
|
99
96
|
config:
|
|
100
97
|
provider: codex
|
|
101
98
|
toolName: subagent_codex
|
|
102
|
-
backgroundMode: one-shot
|
|
103
99
|
maxDepth: provider-managed
|
|
104
100
|
- id: tool-subagent-claude-code
|
|
105
101
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
@@ -107,7 +103,6 @@
|
|
|
107
103
|
config:
|
|
108
104
|
provider: claude-code
|
|
109
105
|
toolName: subagent_claude_code
|
|
110
|
-
backgroundMode: one-shot
|
|
111
106
|
maxDepth: provider-managed
|
|
112
107
|
- id: workflow-ptc
|
|
113
108
|
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
- id: persona
|
|
5
5
|
name: '@deepseek-ai/dsh-persona'
|
|
6
6
|
config:
|
|
7
|
-
suffix: 'Your working directory is {{cwd}}.'
|
|
8
7
|
prefix: 'You are a coding agent powered by the {{model}} model.'
|
|
9
8
|
- id: agent-instructions
|
|
10
9
|
name: '@deepseek-ai/dsh-agent-instructions'
|
|
@@ -86,22 +85,18 @@
|
|
|
86
85
|
provider: spawn
|
|
87
86
|
toolName: subagent
|
|
88
87
|
modelSelectionSettings: true
|
|
89
|
-
|
|
90
|
-
persona: 'Delegation directive: you are a child agent in a MiMo-first session. Before doing any coding, building, debugging, or multi-file investigation work yourself, check whether the mimo_run tool (or the MCP form mcp__mimo__mimo_run) is available to you; if it is, dispatch that work to mimo first per the MiMo-first policy, then verify its output with your own read-only tools. Reserve your own direct work for quick read-only lookups and final verification.'
|
|
88
|
+
agentPreset: cordis-mimo-member
|
|
91
89
|
- id: tool-subagent-fork
|
|
92
90
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
93
91
|
config:
|
|
94
92
|
provider: fork
|
|
95
93
|
toolName: subagent_fork
|
|
96
|
-
backgroundMode: continuable
|
|
97
|
-
persona: 'Delegation directive: you are a child agent in a MiMo-first session. Before doing any coding, building, debugging, or multi-file investigation work yourself, check whether the mimo_run tool (or the MCP form mcp__mimo__mimo_run) is available to you; if it is, dispatch that work to mimo first per the MiMo-first policy, then verify its output with your own read-only tools. Reserve your own direct work for quick read-only lookups and final verification.'
|
|
98
94
|
- id: tool-subagent-codex
|
|
99
95
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
100
96
|
disabled: true
|
|
101
97
|
config:
|
|
102
98
|
provider: codex
|
|
103
99
|
toolName: subagent_codex
|
|
104
|
-
backgroundMode: one-shot
|
|
105
100
|
maxDepth: provider-managed
|
|
106
101
|
- id: tool-subagent-claude-code
|
|
107
102
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
@@ -109,7 +104,6 @@
|
|
|
109
104
|
config:
|
|
110
105
|
provider: claude-code
|
|
111
106
|
toolName: subagent_claude_code
|
|
112
|
-
backgroundMode: one-shot
|
|
113
107
|
maxDepth: provider-managed
|
|
114
108
|
- id: workflow-ptc
|
|
115
109
|
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// preset/mimo-first/plugin-list.mjs — cordis-mimo 预设的单源插件清单(PROVIDER-CONTRACT §5)。
|
|
2
2
|
//
|
|
3
|
-
// = 官方 standard 基线(standard-base.mjs)+ mimo 桥接行 +
|
|
4
|
-
// preset/mimo-first/agent.cordis.yml 的 persona 与 tool-subagent 委派文案 verbatim)。
|
|
3
|
+
// = 官方 standard 基线(standard-base.mjs)+ mimo 桥接行 + 委派差异。
|
|
5
4
|
// preset id 'cordis-mimo' 是旧会话头引用,不可变。
|
|
6
5
|
import { standardPluginRows, bridgeRow } from '../standard-base.mjs'
|
|
7
6
|
|
|
@@ -12,26 +11,33 @@ export const meta = {
|
|
|
12
11
|
order: 10
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 子 agent 所用的成员预设 id(人格与工具面在 preset/mimo-member/plugin-list.mjs)。
|
|
16
|
+
* 0.2.1 起角色人格不能再写在 dsh-tool-subagent 行上,只能由 agentPreset 指向独立预设。
|
|
17
|
+
*/
|
|
18
|
+
export const MEMBER_PRESET_ID = 'cordis-mimo-member'
|
|
18
19
|
|
|
19
20
|
export function buildPlugins(deps) {
|
|
20
21
|
const rows = standardPluginRows()
|
|
21
|
-
// persona
|
|
22
|
-
//
|
|
22
|
+
// persona 行:prefix 与官方 standard 逐字一致({{model}})。
|
|
23
|
+
// 2026-10-18:不再设置 suffix —— DSH 只注册 provider/model 两个变量,工作目录由
|
|
24
|
+
// working-directory 服务以不插值的用户上下文提供,{{cwd}} 会让本预设整轮组装失败。
|
|
23
25
|
const persona = rows.find((r) => r.id === 'persona')
|
|
24
26
|
if (persona && persona.config) {
|
|
25
27
|
persona.config.prefix = 'You are a coding agent powered by the {{model}} model.'
|
|
26
|
-
persona.config.suffix
|
|
28
|
+
delete persona.config.suffix
|
|
27
29
|
}
|
|
28
|
-
//
|
|
30
|
+
// 委派组:0.2.1 起人格与工具面属于【独立成员预设】,委派行只用 agentPreset 选择它。
|
|
29
31
|
const delegation = rows.find((r) => r.id === 'delegation')
|
|
30
32
|
if (delegation && Array.isArray(delegation.config)) {
|
|
31
33
|
for (const child of delegation.config) {
|
|
32
|
-
if (child
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
if (!child || child.name !== '@deepseek-ai/dsh-tool-subagent' || !child.config) continue
|
|
35
|
+
// persona/toolFilter 会被 dsh-tool-subagent 的 apply() 直接 throw,写进去就是
|
|
36
|
+
// 整个预设挂载失败 —— 一律删除(人格已迁到成员预设)。
|
|
37
|
+
delete child.config.persona
|
|
38
|
+
delete child.config.toolFilter
|
|
39
|
+
// agentPreset 只有 in-process spawn 支持;fork 与外部后端会拒绝它,故只给 spawn。
|
|
40
|
+
if (child.config.provider === 'spawn') child.config.agentPreset = MEMBER_PRESET_ID
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
rows.push(bridgeRow('mimo', deps && deps.bridgeName))
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// preset/mimo-member/plugin-list.mjs — cordis-mimo 的【成员预设】单源清单(PROVIDER-CONTRACT §5)。
|
|
2
|
+
//
|
|
3
|
+
// 为什么需要它(2026-10-18 实测结论):
|
|
4
|
+
// dsh-tool-subagent 0.2.1 起,config 里的 `persona` / `toolFilter` 会在 apply() 里
|
|
5
|
+
// **显式 throw**("tool-subagent: persona is no longer supported; configure persona
|
|
6
|
+
// and tool plugins in an Agent Preset and select it with agentPreset (spawn only)")。
|
|
7
|
+
// mimo 预设此前把委派指令写在 tool-subagent.config.persona 上 ⇒ 整个 preset 挂载失败
|
|
8
|
+
// (与 dsh-kexi-crypto v1.9.21 踩的是同一个坑)。
|
|
9
|
+
// 新契约:角色人格只能是**独立的 Agent Preset**,由委派行经 `agentPreset` 选择。
|
|
10
|
+
//
|
|
11
|
+
// 本预设就是那个成员预设:人格(旧委派指令 verbatim)+ mimo 桥接工具面(子 agent 必须
|
|
12
|
+
// 能调 mimo_run,否则"派活"无从谈起)+ 只读文件面(够做只读查询与最终验证)。
|
|
13
|
+
// 由 preset-declarations.mjs 在**主预设之前**注册 —— 委派行的 validate() 会对每个
|
|
14
|
+
// agentPreset id 调 presets.readDocument(id),未注册即抛 agent-preset/not-found。
|
|
15
|
+
//
|
|
16
|
+
// 它不是独立会话入口:直接选择它只会得到一个只能派活、不能自己改文件的子代理。
|
|
17
|
+
import { bridgeRow } from '../standard-base.mjs'
|
|
18
|
+
|
|
19
|
+
/** Preset identity —— 旧会话头不可引用它(成员预设是本次新增),但委派行按此 id 选择。 */
|
|
20
|
+
export const meta = {
|
|
21
|
+
id: 'cordis-mimo-member',
|
|
22
|
+
name: 'MiMo 子代理(内部预设·勿直接选择)',
|
|
23
|
+
description: 'MiMo-first 会话里被委派的子 agent 所用成员预设:只挂 mimo 桥接工具与只读文件面,人格要求把编码工作派给 mimo_run。仅供 cordis-mimo 的委派行经 agentPreset 选择,不是独立会话入口;直接选择它只会得到一个只能派活、不能自己改文件的子代理。',
|
|
24
|
+
order: 501
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 旧 agent.cordis.yml 的 spawn/fork 委派指令文案 verbatim(0.2.1 起只能放进 persona)。 */
|
|
28
|
+
export const MIMO_DELEGATION_PERSONA = 'Delegation directive: you are a child agent in a MiMo-first session. Before doing any coding, building, debugging, or multi-file investigation work yourself, check whether the mimo_run tool (or the MCP form mcp__mimo__mimo_run) is available to you; if it is, dispatch that work to mimo first per the MiMo-first policy, then verify its output with your own read-only tools. Reserve your own direct work for quick read-only lookups and final verification.'
|
|
29
|
+
|
|
30
|
+
export function buildPlugins(deps) {
|
|
31
|
+
return [
|
|
32
|
+
// 人格:委派指令。prefix 必填;suffix 不设(DSH 只注册 provider/model 两个提示词变量,
|
|
33
|
+
// 工作目录由 working-directory 服务以不插值的用户上下文提供)。
|
|
34
|
+
{ id: 'persona', name: '@deepseek-ai/dsh-persona', config: {
|
|
35
|
+
prefix: MIMO_DELEGATION_PERSONA,
|
|
36
|
+
includeRuntimeContext: true,
|
|
37
|
+
} },
|
|
38
|
+
// 只读文件面:旧 toolFilter 白名单的新表达 —— 写/改工具直接不存在,比黑名单更严格
|
|
39
|
+
// (成员纪律:改文件一律经 mimo_run)。
|
|
40
|
+
{ id: 'tool-fs', name: '@deepseek-ai/dsh-tool-fs', config: {
|
|
41
|
+
read: true, readImage: true, write: false, edit: false,
|
|
42
|
+
} },
|
|
43
|
+
{ id: 'tool-fs-search', name: '@deepseek-ai/dsh-tool-fs-search', config: {
|
|
44
|
+
sampleOverCapGlobResults: false,
|
|
45
|
+
} },
|
|
46
|
+
// 桥接工具面:子 agent 必须能调 mimo_run/mimo_continue/ mimo_status。
|
|
47
|
+
bridgeRow('mimo', deps && deps.bridgeName),
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
- id: persona
|
|
5
5
|
name: '@deepseek-ai/dsh-persona'
|
|
6
6
|
config:
|
|
7
|
-
suffix: 'Your working directory is {{cwd}}.'
|
|
8
7
|
prefix: 'You are a coding agent powered by the {{model}} model.'
|
|
9
8
|
- id: agent-instructions
|
|
10
9
|
name: '@deepseek-ai/dsh-agent-instructions'
|
|
@@ -86,20 +85,17 @@
|
|
|
86
85
|
provider: spawn
|
|
87
86
|
toolName: subagent
|
|
88
87
|
modelSelectionSettings: true
|
|
89
|
-
backgroundMode: continuable
|
|
90
88
|
- id: tool-subagent-fork
|
|
91
89
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
92
90
|
config:
|
|
93
91
|
provider: fork
|
|
94
92
|
toolName: subagent_fork
|
|
95
|
-
backgroundMode: continuable
|
|
96
93
|
- id: tool-subagent-codex
|
|
97
94
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
98
95
|
disabled: true
|
|
99
96
|
config:
|
|
100
97
|
provider: codex
|
|
101
98
|
toolName: subagent_codex
|
|
102
|
-
backgroundMode: one-shot
|
|
103
99
|
maxDepth: provider-managed
|
|
104
100
|
- id: tool-subagent-claude-code
|
|
105
101
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
@@ -107,7 +103,6 @@
|
|
|
107
103
|
config:
|
|
108
104
|
provider: claude-code
|
|
109
105
|
toolName: subagent_claude_code
|
|
110
|
-
backgroundMode: one-shot
|
|
111
106
|
maxDepth: provider-managed
|
|
112
107
|
- id: workflow-ptc
|
|
113
108
|
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
@@ -15,11 +15,13 @@ export const meta = {
|
|
|
15
15
|
|
|
16
16
|
export function buildPlugins(deps) {
|
|
17
17
|
const rows = standardPluginRows()
|
|
18
|
-
// persona
|
|
18
|
+
// persona 段:prefix 与三家旧 preset 同构(dsh-persona 要求 prefix 必填)。
|
|
19
|
+
// 2026-10-18:不再设置 suffix —— DSH 只注册 provider/model 两个变量,工作目录由
|
|
20
|
+
// working-directory 服务以不插值的用户上下文提供,{{cwd}} 会让本预设整轮组装失败。
|
|
19
21
|
const persona = rows.find((r) => r.id === 'persona')
|
|
20
22
|
if (persona && persona.config) {
|
|
21
23
|
persona.config.prefix = 'You are a coding agent powered by the {{model}} model.'
|
|
22
|
-
persona.config.suffix
|
|
24
|
+
delete persona.config.suffix
|
|
23
25
|
}
|
|
24
26
|
rows.push(bridgeRow('opencode', deps && deps.bridgeName))
|
|
25
27
|
return rows
|
package/preset/standard-base.mjs
CHANGED
|
@@ -26,13 +26,16 @@ export const PLAN_MODE_SECTION = [
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* 官方 standard preset 的插件行表(不含 persona 差异与桥接行)。
|
|
29
|
-
* persona 行返回【副本】供 provider 修改 prefix
|
|
29
|
+
* persona 行返回【副本】供 provider 修改 prefix;其余行按原样返回。
|
|
30
30
|
* @returns {object[]}
|
|
31
31
|
*/
|
|
32
32
|
export function standardPluginRows() {
|
|
33
33
|
return [
|
|
34
|
+
// persona 只留 prefix。DSH 的提示词循环只注册 provider/model 两个变量
|
|
35
|
+
// (dsh-agent-loop),工作目录由 working-directory 服务以「不执行插值的用户
|
|
36
|
+
// 上下文」提供。写 {{cwd}} 会在组装期抛 unknown prompt variable,导致整个
|
|
37
|
+
// 预设不可用(2026-10-18 实测)。官方 presets 全部不带 suffix。
|
|
34
38
|
{ id: 'persona', name: '@deepseek-ai/dsh-persona', config: {
|
|
35
|
-
suffix: 'Your working directory is {{cwd}}.',
|
|
36
39
|
prefix: 'You are a coding agent powered by the {{model}} model.',
|
|
37
40
|
} },
|
|
38
41
|
{ id: 'agent-instructions', name: '@deepseek-ai/dsh-agent-instructions', config: { maxBytes: 65536 } },
|
|
@@ -66,20 +69,29 @@ export function standardPluginRows() {
|
|
|
66
69
|
{
|
|
67
70
|
id: 'delegation', name: 'cordis:group', group: true,
|
|
68
71
|
isolate: { workflowEngine: true },
|
|
72
|
+
// 2026-10-18:移除 backgroundMode —— dsh-tool-subagent 0.2.1(当前 0.2.1-alpha.5)
|
|
73
|
+
// 已删除该字段。机制经实装包双路径实测更正:未知/已删键会**通过 schema 校验并被
|
|
74
|
+
// 原样保留**(`Config['~standard'].validate({provider,backgroundMode})` 无 issues,
|
|
75
|
+
// 值幸存;schemastery 根本没有 strict 开关),只是**无人读取**该键
|
|
76
|
+
// (全 DSH 树对 backgroundMode 0 命中)⇒ 属「静默**忽略**」,不是「静默丢弃」。
|
|
77
|
+
// 危害:表面声明 continuable/one-shot 却毫无效果,且**运行时不报错**,
|
|
78
|
+
// 只能靠静态闸门(tests/keystone/persona-prompt-vars.test.mjs)拦。
|
|
79
|
+
// 当前 schema 接受:provider / toolName / modelSelectionSettings /
|
|
80
|
+
// agentOptions / agentPreset / allowedAgentPresets / maxDepth。
|
|
69
81
|
config: [
|
|
70
82
|
{ id: 'tool-subagent-control', name: '@deepseek-ai/dsh-tool-subagent-control' },
|
|
71
83
|
{ id: 'tool-subagent-list-agents', name: '@deepseek-ai/dsh-tool-subagent-control/list-agents' },
|
|
72
84
|
{ id: 'tool-subagent', name: '@deepseek-ai/dsh-tool-subagent', config: {
|
|
73
|
-
provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true,
|
|
85
|
+
provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true,
|
|
74
86
|
} },
|
|
75
87
|
{ id: 'tool-subagent-fork', name: '@deepseek-ai/dsh-tool-subagent', config: {
|
|
76
|
-
provider: 'fork', toolName: 'subagent_fork',
|
|
88
|
+
provider: 'fork', toolName: 'subagent_fork',
|
|
77
89
|
} },
|
|
78
90
|
{ id: 'tool-subagent-codex', name: '@deepseek-ai/dsh-tool-subagent', disabled: true, config: {
|
|
79
|
-
provider: 'codex', toolName: 'subagent_codex',
|
|
91
|
+
provider: 'codex', toolName: 'subagent_codex', maxDepth: 'provider-managed',
|
|
80
92
|
} },
|
|
81
93
|
{ id: 'tool-subagent-claude-code', name: '@deepseek-ai/dsh-tool-subagent', disabled: true, config: {
|
|
82
|
-
provider: 'claude-code', toolName: 'subagent_claude_code',
|
|
94
|
+
provider: 'claude-code', toolName: 'subagent_claude_code', maxDepth: 'provider-managed',
|
|
83
95
|
} },
|
|
84
96
|
{ id: 'workflow-ptc', name: '@deepseek-ai/dsh-workflow-ptc', config: { provider: 'spawn' } },
|
|
85
97
|
{ id: 'tool-workflow', name: '@deepseek-ai/dsh-tool-workflow' },
|