dsh-team-presets 0.2.3 → 0.2.4

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.
@@ -0,0 +1,153 @@
1
+ # How this branch differs from upstream
2
+
3
+ Upstream: [bloodarea/dsh-agent-team-presets](https://github.com/bloodarea/dsh-agent-team-presets)
4
+ This branch: [jaxhu1108/dsh-agent-team-presets](https://github.com/jaxhu1108/dsh-agent-team-presets)
5
+ Package name: `dsh-team-presets` (GitHub and npm)
6
+
7
+ ---
8
+
9
+ ## 1. What this is not
10
+
11
+ This branch is **not an upgraded version of upstream**. It is an **independently maintained variant**.
12
+
13
+ It does several things upstream does not, and it omits several things upstream has. Which one you want depends on what you need — both sides are laid out below so you can decide.
14
+
15
+ Upstream is carefully maintained. This branch's `setExecutor` lifetime approach was adopted by upstream `v0.2.0` as an independent implementation (no code merged), see [upstream issue #5](https://github.com/bloodarea/dsh-agent-team-presets/issues/5).
16
+
17
+ ---
18
+
19
+ ## 2. What this branch adds
20
+
21
+ ### 2.1 A tool-policy subsystem (the main difference)
22
+
23
+ Upstream offers two `toolMode` values: all tools, or a custom allow-list. This branch splits that into three modules totalling **476 lines**:
24
+
25
+ | Module | Lines | Role |
26
+ |---|---|---|
27
+ | `src/tool-catalog.ts` | 191 | Tool catalog: presents host tools as a browsable, grouped list |
28
+ | `src/tool-policy.ts` | 261 | Policy: roles, circuit breaking, recovery tool sets, guard decisions |
29
+ | `src/tool-descriptions.ts` | 24 | Tool description injection |
30
+
31
+ **The practical difference**: configuring a read-only scout, or a reviewer that may run tests but not edit code —
32
+
33
+ - Upstream: type tool names by hand, with no list of what is available.
34
+ - This branch: the settings page lists every tool, grouped, ready to check.
35
+
36
+ ### 2.2 A per-Team personnel switch (`personnelControl`)
37
+
38
+ Each Team carries an independent switch, default `false`. When enabled, only the captain may add or remove members; when disabled, member edits are refused with a reason.
39
+
40
+ The use case: freezing a Team into a distributable template so a recipient cannot accidentally restructure it.
41
+
42
+ Upstream has no equivalent.
43
+
44
+ ### 2.3 An npm release channel
45
+
46
+ | Channel | Upstream | This branch |
47
+ |---|---|---|
48
+ | GitHub Releases | ✅ | ✅ |
49
+ | npm | ❌ | ✅ `dsh-team-presets` |
50
+
51
+ **This matters more than it looks.** Update detection admits registry sources only:
52
+
53
+ ```ts
54
+ // packages/boot/plugin-manager/src/index.ts — updateRefusal()
55
+ if (parsed.kind !== 'registry' || ...) return `${name} is not installed from a registry under its own name`
56
+ ```
57
+
58
+ A `github:` spec parses as `kind: 'git'` and is refused before any version lookup.
59
+
60
+ - Installed from upstream GitHub → **never offered an update**; reinstall by hand.
61
+ - Installed from this branch's npm package → the manager compares `latest` and offers the upgrade.
62
+
63
+ ### 2.4 Unified corner radii
64
+
65
+ Upstream's stylesheets mix twelve hard-coded radii (5–17px), bypassing the theme's six-rung ladder. This branch:
66
+
67
+ - Routes all 35 radii through `--dsw-radius-xs/sm/md/lg/xl/panel`
68
+ - Pairs the four full-round elements with `corner-shape: round` (the host applies `* { corner-shape: superellipse(1.5) }` globally; an unpaired circle becomes a squircle and a capsule gets squared ends)
69
+ - Adds `tests/corner-radius.client.spec.ts` with two static guards
70
+
71
+ ### 2.5 Typert remote-face isolation test
72
+
73
+ `tests/typert-isolation.spec.ts` (17 cases) loads both wire faces in a process that **cannot resolve zod**, proving the client face carries no zod dependency. Upstream has no such guard.
74
+
75
+ ---
76
+
77
+ ## 3. What upstream has and this branch did not
78
+
79
+ ### Now included: the built-in troubleshooting skill
80
+
81
+ Upstream's `src/builtin-skill.ts` (252 lines) registers a global runtime skill so a user hitting "the Team does not apply / members cannot be summoned / tools are refused / model routing looks wrong" can self-diagnose. It has twelve sections, an evidence-priority table, diagnostic commands, and a report template.
82
+
83
+ **This branch now includes it** (from `v0.2.4`), with two adaptations:
84
+
85
+ - Package names and paths point at `dsh-team-presets`
86
+ - Content calibrated against this branch's actual implementation
87
+
88
+ ### Still absent: per-member model selection in the client
89
+
90
+ Upstream's client lets you pick provider/model per member. This branch does not.
91
+
92
+ Why it is not chased: this branch's `personnelControl` governs *members per Team*; upstream's `selectMember` picks *a model per member*. Two different axes, and forcing both into one UI produces two mechanisms fighting each other. **This branch configures member routing in the Team preset rather than per Session.**
93
+
94
+ ---
95
+
96
+ ## 4. Where both agree
97
+
98
+ The Agent-lifetime binding for `setExecutor`. Both sides **implemented it independently and reached the same conclusion**:
99
+
100
+ ```ts
101
+ agent.ctx.tools.setExecutor(new NativeToolExecutor(agent.ctx))
102
+ ```
103
+
104
+ - The registration lands on the Agent's own scope and its disposer is never called.
105
+ - The Agent's context owns it, so it is released when the Agent is destroyed.
106
+ - The rc.1 one-way release (tombstone) is therefore never triggered.
107
+
108
+ `src/presentation.ts` here behaves the same as upstream `v0.2.0` on this point. Upstream states explicitly that no downstream code was merged.
109
+
110
+ ---
111
+
112
+ ## 5. Choosing between them
113
+
114
+ | Your situation | Recommendation |
115
+ |---|---|
116
+ | You need precise per-member tool allow-lists | **This branch** |
117
+ | You need Teams frozen into distributable templates | **This branch** |
118
+ | You want update prompts in the plugin manager | **This branch** (npm channel) |
119
+ | You need per-member model switching inside a Session | **Upstream** |
120
+ | You want to track the most active development | **Upstream** |
121
+ | You only use the nine built-in presets and never touch tool policy | Either; upstream is lighter |
122
+
123
+ **Migration cost**: settings and Team Skills live under `$DSH_HOME/agent-team-presets/`, keyed by the **plugin's internal name** rather than by package name. Both sides use the same internal name, so no data is lost. The two packages cannot be installed side by side, however — the internal name would collide — so uninstall before switching.
124
+
125
+ ---
126
+
127
+ ## 6. Maintenance commitment, and its limits
128
+
129
+ This branch is **independently maintained**. It does not promise to follow every upstream release. Concretely:
130
+
131
+ - An upstream fix for a security or correctness problem affecting this branch → followed.
132
+ - A new upstream feature with no conflict → evaluated and adopted.
133
+ - A new upstream feature that conflicts with this branch's mechanisms → not adopted, with the reason recorded here.
134
+
135
+ **Upstream is the mainline; this branch is a side branch.** If you only need upstream's full feature set, using upstream is the right call.
136
+
137
+ ---
138
+
139
+ ## 7. Version comparison
140
+
141
+ | | Upstream | This branch |
142
+ |---|---|---|
143
+ | Latest | `v0.2.0` | `v0.2.4` |
144
+ | `engines.dsh` | `>=0.2.2-rc.1 <0.3.0` | `>=0.2.2-rc.1 <0.3.0` |
145
+ | Install name | `dsh-agent-team-presets` | `dsh-team-presets` |
146
+ | npm | none | [available](https://www.npmjs.com/package/dsh-team-presets) |
147
+ | Tests | — | 772 (771 pass / 1 skipped) |
148
+
149
+ The version numbers are deliberately not aligned: two independent packages evolving separately need no version-number relationship to signal compatibility.
150
+
151
+ ---
152
+
153
+ *Last updated 2026-11-12 · corresponds to this branch's `v0.2.4`*
package/DIFFERENCES.md ADDED
@@ -0,0 +1,153 @@
1
+ # 这个分支和上游有什么不同
2
+
3
+ 上游:[bloodarea/dsh-agent-team-presets](https://github.com/bloodarea/dsh-agent-team-presets)
4
+ 本分支:[jaxhu1108/dsh-agent-team-presets](https://github.com/jaxhu1108/dsh-agent-team-presets)
5
+ 包名:`dsh-team-presets`(npm 与 GitHub 双渠道)
6
+
7
+ ---
8
+
9
+ ## 一、先说清楚:这不是「更好的版本」
10
+
11
+ 这个分支**不是上游的升级版**,是**一个独立维护的变体**。
12
+
13
+ 它多做了几件上游没做的事,也少做了几件上游有的事。选择哪个,取决于你要什么——下面把两边摆平,你自己判断。
14
+
15
+ 上游维护得很认真。本分支的 `setExecutor` 生命周期方案已被上游 `v0.2.0` 采纳(独立实现,未合并代码),见 [上游 issue #5](https://github.com/bloodarea/dsh-agent-team-presets/issues/5)。
16
+
17
+ ---
18
+
19
+ ## 二、本分支比上游多什么
20
+
21
+ ### 1. 工具策略体系(核心差异)
22
+
23
+ 上游只有「全部工具」和「自定义白名单」两种 `toolMode`。本分支把它拆成三个模块,共 **476 行**:
24
+
25
+ | 模块 | 行数 | 作用 |
26
+ |---|---|---|
27
+ | `src/tool-catalog.ts` | 191 | 工具目录:把宿主工具整理成可浏览、可分类的清单 |
28
+ | `src/tool-policy.ts` | 261 | 策略计算:角色、熔断、恢复工具集、guard 判定 |
29
+ | `src/tool-descriptions.ts` | 24 | 工具描述注入 |
30
+
31
+ **实际差别**:配一个「只能读不能写」的侦察兵,或一个「只能跑测试不能改代码」的审查员时——
32
+
33
+ - 上游:你得在设置页手打工具名,且不知道有哪些可选
34
+ - 本分支:设置页列出所有工具,按组浏览,勾选即可
35
+
36
+ ### 2. 团队级成员管理开关(`personnelControl`)
37
+
38
+ 每个团队有一个独立开关,默认 `false`。开启后,**只有队长**能增删成员;关闭时成员的增删被拒绝并给出原因。
39
+
40
+ 用途:把团队冻结成模板分发给别人时,防止对方误改成员结构。
41
+
42
+ 上游没有这个概念。
43
+
44
+ ### 3. npm 发布渠道
45
+
46
+ | 渠道 | 上游 | 本分支 |
47
+ |---|---|---|
48
+ | GitHub Releases | ✅ | ✅ |
49
+ | npm | ❌ | ✅ `dsh-team-presets` |
50
+
51
+ **这不是小事。** 插件管理器的更新检测只认可 registry 来源:
52
+
53
+ ```ts
54
+ // packages/boot/plugin-manager/src/index.ts — updateRefusal()
55
+ if (parsed.kind !== 'registry' || ...) return `${name} is not installed from a registry under its own name`
56
+ ```
57
+
58
+ `github:` 会被解析成 `kind: 'git'`,在任何版本查询之前就被拒绝。
59
+
60
+ - 从上游 GitHub 安装 → **永远不会提示更新**,只能手动重装
61
+ - 从本分支 npm 安装 → 管理器自动比对 `latest` 并提示
62
+
63
+ ### 4. 界面圆角统一
64
+
65
+ 上游的样式表混用 12 种硬编码圆角(5~17px),绕开主题的六档梯度。本分支:
66
+
67
+ - 35 处全部改走 `--dsw-radius-xs/sm/md/lg/xl/panel`
68
+ - 4 处全圆元件补 `corner-shape: round`(宿主用 `* { corner-shape: superellipse(1.5) }` 全局施加超椭圆,缺配对会让圆点变南瓜、胶囊两端削平)
69
+ - 新增 `tests/corner-radius.client.spec.ts` 两条静态守护
70
+
71
+ ### 5. Typert 远端面隔离测试
72
+
73
+ `tests/typert-isolation.spec.ts`(17 条):在**无法解析 zod** 的进程里加载两个 wire face,证明客户端面不依赖 zod。上游没有这层保护。
74
+
75
+ ---
76
+
77
+ ## 三、上游有而本分支原来没有的
78
+
79
+ ### 已补齐:内置排障 Skill
80
+
81
+ 上游 `src/builtin-skill.ts`(252 行)注册一个全局 runtime skill,用户遇到「团队不生效 / 成员召唤不了 / 工具被拒 / 模型路由不符」时能自助排查,含 12 个章节、证据优先级表、诊断命令和报告模板。
82
+
83
+ **本分支已纳入**(`v0.2.4`),并做了两处适配:
84
+
85
+ - 包名与路径指向 `dsh-team-presets`
86
+ - 内容按本分支的实际实现校准
87
+
88
+ ### 仍未纳入:客户端按成员选模型
89
+
90
+ 上游客户端有一套「按成员维度选择 provider/model」的界面。本分支没有。
91
+
92
+ 为什么不追:本分支的 `personnelControl` 是「按团队管成员」,上游的 `selectMember` 是「按成员选模型」——两个方向不同,硬追会变成两套机制互相打架。**本分支的模型路由在团队预设里配置,不依赖会话内选择。**
93
+
94
+ ---
95
+
96
+ ## 四、两者一致的实现
97
+
98
+ `setExecutor` 的 Agent 生命周期绑定。两边**独立实现,结论相同**:
99
+
100
+ ```ts
101
+ agent.ctx.tools.setExecutor(new NativeToolExecutor(agent.ctx))
102
+ ```
103
+
104
+ - 注册挂在 Agent 自己的作用域上,disposer 永不调用
105
+ - Agent 销毁时随上下文回收
106
+ - 因此不会触发 rc.1 的单向释放(tombstone)
107
+
108
+ 本分支的 `src/presentation.ts` 与上游 `v0.2.0` 在这一点的行为一致。上游明确说明「未合并下游代码」。
109
+
110
+ ---
111
+
112
+ ## 五、怎么选
113
+
114
+ | 你的情况 | 建议 |
115
+ |---|---|
116
+ | 需要精细控制成员能调哪些工具 | **本分支** |
117
+ | 需要把团队冻结成模板分发 | **本分支** |
118
+ | 希望插件能自动提示更新 | **本分支**(npm 渠道) |
119
+ | 需要会话内按成员切模型 | **上游** |
120
+ | 想紧跟最活跃的开发 | **上游** |
121
+ | 只是用内置的 9 套预设,不改工具策略 | 两边都行,上游更轻 |
122
+
123
+ **换分支的迁移成本**:设置与 Team Skill 存在 `$DSH_HOME/agent-team-presets/` 下,按**插件内部名**而非包名。两边的内部名相同,所以数据不丢。但两个包不能同时安装(同一个插件内部名会冲突),切换时先卸载再装。
124
+
125
+ ---
126
+
127
+ ## 六、维护承诺与其边界
128
+
129
+ 本分支**独立维护**,不承诺跟随上游的每个版本。具体说:
130
+
131
+ - 上游修复了会影响本分支的安全或正确性问题 → 跟进
132
+ - 上游新增功能,与本分支无冲突 → 评估后纳入
133
+ - 上游新增功能,与本分支机制冲突 → 不纳入,在本文档记录原因
134
+
135
+ **上游是主线,本分支是侧支。** 如果你只需要上游的全部能力,用上游没有错。
136
+
137
+ ---
138
+
139
+ ## 七、当前版本对照
140
+
141
+ | | 上游 | 本分支 |
142
+ |---|---|---|
143
+ | 最新版本 | `v0.2.0` | `v0.2.4` |
144
+ | `engines.dsh` | `>=0.2.2-rc.1 <0.3.0` | `>=0.2.2-rc.1 <0.3.0` |
145
+ | 安装包名 | `dsh-agent-team-presets` | `dsh-team-presets` |
146
+ | npm | 无 | [有](https://www.npmjs.com/package/dsh-team-presets) |
147
+ | 测试用例 | — | 772(771 通过 / 1 跳过) |
148
+
149
+ 版本号不对齐是**故意的**:两个独立包,各自演进,不需要用版本号暗示兼容关系。
150
+
151
+ ---
152
+
153
+ *最后更新:2026-11-12 · 对应本分支 `v0.2.4`*
package/README.en.md CHANGED
@@ -6,13 +6,17 @@
6
6
 
7
7
  English | [中文](<README.md>)
8
8
 
9
- > **Version v0.2.3** · For DeepSeek Runtime `0.2.2-rc.1` and later 0.2.x
9
+ > **Version v0.2.4** · For DeepSeek Runtime `0.2.2-rc.1` and later 0.2.x
10
10
  >
11
11
  > Requires a compatible DeepSeek Harness deployment with Agent Teams enabled. This version targets the DSH `0.2.2-rc.1` API; see [Requirements](#requirements). Prebuilt artifacts are included, so installation does not require a source build.
12
12
  >
13
13
  > **This plugin's development was inspired by the original author, [bloodarea](https://github.com/bloodarea/dsh-agent-team-presets).** The team-preset data model, the nine built-in presets, the private Team Skill subsystem and the overall plugin skeleton all originate upstream. This repository is an adaptation fork that follows newer Runtime releases — not an independent work. See [CREDITS.md](<CREDITS.md>) for the full attribution.
14
14
 
15
- > **v0.2.3 interface update**: every corner radius in the settings page and composer picker now resolves through the theme's `--dsw-radius-*` tokens, and circular elements plus capsule tags declare `corner-shape: round`. The plugin previously carried twelve distinct hard-coded radii (5–17px), which read as uneven; the surfaces now follow the host's six-rung ladder and match the rest of the settings UI.
15
+ > **This branch differs from upstream — read the comparison first**: this repository is an **independently maintained variant**, not an upgraded upstream. It adds a tool-policy subsystem, a per-Team personnel switch, an npm channel and unified radii; it omits upstream's per-member model switching inside a Session.
16
+ >
17
+ > Both sides laid out side by side, so you can decide → **[DIFFERENCES.en.md](<DIFFERENCES.en.md>)** ([中文](<DIFFERENCES.md>))
18
+ >
19
+ > **Interface**: corner radii now resolve through the theme's `--dsw-radius-*` tokens, and the four full-round elements declare `corner-shape: round`.
16
20
 
17
21
  <a id="project-introduction"></a>
18
22
  ## Overview
@@ -159,7 +163,7 @@ The screenshots illustrate the v0.2.x settings interface, Team Skill management,
159
163
  - **A Web or Desktop profile with Settings and the required client services.** Install into the profile you actually use, typically `web` for the Web GUI or `desktop` for Desktop.
160
164
  - **Durable storage and a continuable subagent backend for member execution.** Member creation is refused if the storage domain or selected execution backend is unavailable. The default backend names are `spawn` and `fork`.
161
165
 
162
- The plugin version (`0.2.3`) and the Harness version (`0.2.2-rc.1`, for example) are separate version lines.
166
+ The plugin version (`0.2.4`) and the Harness version (`0.2.2-rc.1`, for example) are separate version lines.
163
167
 
164
168
  <a id="use-this-package"></a>
165
169
  ## Install and upgrade
@@ -169,50 +173,49 @@ The plugin version (`0.2.3`) and the Harness version (`0.2.2-rc.1`, for example)
169
173
  Open **Global panels → Plugins → Add plugin**, paste the line below into **Package name or address**, and click **Install**:
170
174
 
171
175
  ```text
172
- dsh-team-presets@0.2.3
176
+ dsh-team-presets@0.2.4
173
177
  ```
174
178
 
175
179
  <!-- release-version: keep in sync with package.json version -->
176
180
 
177
181
  - **Registry** selects which npm source the download comes from. **Default registry** uses pnpm's own configuration. Pick **Official npm registry** to bypass a mirror, or **Custom address** for an internal or cloud mirror.
178
- - `@0.2.2` pins the version; omit it to install the latest published package.
182
+ - `@0.2.4` pins the version; omit it to install the latest published package.
179
183
  - The field accepts package names, `name@version`, `github:owner/repo`, tarball URLs, or absolute filesystem paths.
180
184
  - This package declares `dsh.bundle`, so the plugin manager automatically registers it as a profile bundle layer; do not add a loader entry by hand.
181
185
  - Once installed, reinstalling the same package identity is blocked. To switch sources (e.g. from GitHub to npm), uninstall first, then install the new spec.
182
186
  - After installation, reload or restart as prompted.
183
187
 
184
- ### Install from GitHub
185
-
186
- To receive repository update notifications:
188
+ ### Install from npm (recommended — update checks work)
187
189
 
188
190
  ```sh
189
- dsh plugin --profile <profile> add github:jaxhu1108/dsh-agent-team-presets
191
+ dsh plugin --profile <profile> add dsh-team-presets
190
192
  ```
191
193
 
192
- Replace `<profile>` with your active profile (e.g. `web` or `desktop`):
194
+ Replace `<profile>` with your active profile (e.g. `web` or `desktop`). To pin this release:
193
195
 
194
196
  ```sh
195
- dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets
197
+ dsh plugin --profile <profile> add dsh-team-presets@0.2.4
196
198
  ```
197
199
 
198
- To pin the v0.2.3 release tag:
200
+ > **Why npm is recommended**: only registry installs are checked for newer versions. The plugin manager admits update candidates solely when the saved source parses as a registry spec (`updateRefusal()` in `plugin-manager/src/index.ts`); a `github:` spec parses as `kind: 'git'` and is refused before any version lookup. Install from GitHub and you will never be offered an update.
201
+
202
+ ### Install from GitHub (no update notifications)
199
203
 
200
204
  ```sh
201
- dsh plugin --profile <profile> add github:jaxhu1108/dsh-agent-team-presets#v0.2.3
205
+ dsh plugin --profile <profile> add github:jaxhu1108/dsh-agent-team-presets
202
206
  ```
203
207
 
204
- ### npm release channel
205
-
206
- GitHub and [npm](https://www.npmjs.com/package/dsh-team-presets) are separate release channels. Verify the published version on npm before installing:
208
+ To pin the v0.2.4 release tag:
207
209
 
208
210
  ```sh
209
- npm view dsh-team-presets version
210
- dsh plugin --profile <profile> add dsh-team-presets
211
+ dsh plugin --profile <profile> add github:jaxhu1108/dsh-agent-team-presets#v0.2.4
211
212
  ```
212
213
 
214
+ > This channel never offers updates; reinstalling by hand is the only way to move to a newer release. Use it when you want to track repository commits, or when the npm registry is unreachable from your network.
215
+
213
216
  ### Verify and upgrade safely
214
217
 
215
- After installation, follow the plugin manager's reload/restart prompts and navigate to **Settings → Agent team presets**. Verify that details display `dsh-team-presets`, version `0.2.3`, and a running component.
218
+ After installation, follow the plugin manager's reload/restart prompts and navigate to **Settings → Agent team presets**. Verify that details display `dsh-team-presets`, version `0.2.4`, and a running component.
216
219
 
217
220
  - Back up profile settings, Team definitions, and Session selections before upgrading.
218
221
  - When migrating from a development link, remove `@deepseek-ai/dsh-experimental-agent-team-presets` first before enabling the community package.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  中文 | [English](<README.en.md>)
8
8
 
9
- > **版本 v0.2.3** · 适配 DeepSeek Runtime `0.2.2-rc.1` 及以后的 0.2.x
9
+ > **版本 v0.2.4** · 适配 DeepSeek Runtime `0.2.2-rc.1` 及以后的 0.2.x
10
10
  >
11
11
  > 这是一个 **DSH 插件**:给你的 DeepSeek Runtime 加一个可视化的「智能体团队预设」管理器。配好一套团队,从输入区一键选用,队长就能带着队员干活。
12
12
  >
@@ -14,7 +14,11 @@
14
14
  >
15
15
  > **仓库已包含预构建产物**,安装不需要编译源码。
16
16
 
17
- > **v0.2.3 界面更新**:设置页与输入区选择器的圆角全部改用主题 token(`--dsw-radius-*`),并补齐了圆形元件与胶囊标签的 `corner-shape: round` 声明。此前插件自带 12 种不同的圆角数值(5~17px),设置页看起来不够整齐;现在统一到宿主的六档梯度,与设置页其它区域一致。
17
+ > **本分支与上游不同,请先看对照**:这个仓库是**独立维护的变体**,不是上游的升级版。多做了工具策略体系、团队级成员管理开关、npm 发布渠道与圆角统一;上游有而这里没有的是「会话内按成员切模型」。
18
+ >
19
+ > 两者摆平对照,自己判断用哪个 → **[DIFFERENCES.md](<DIFFERENCES.md>)**([English](<DIFFERENCES.en.md>))
20
+ >
21
+ > **界面**:设置页与输入区圆角已统一到主题 token(`--dsw-radius-*`),4 处全圆元件补齐 `corner-shape: round`。
18
22
 
19
23
  ---
20
24
 
@@ -71,30 +75,46 @@ dsh --version
71
75
 
72
76
  ### 版本号别搞混
73
77
 
74
- - **插件版本**:本版 `0.2.3`
78
+ - **插件版本**:本版 `0.2.4`
75
79
  - **Runtime 版本**:例如 `0.2.2-rc.1`
76
80
 
77
- 两条完全独立的版本线。插件 `0.2.3` 跑在 Runtime `0.2.2-rc.1` 上是**正常组合**,不是版本不匹配。
81
+ 两条完全独立的版本线。插件 `0.2.4` 跑在 Runtime `0.2.2-rc.1` 上是**正常组合**,不是版本不匹配。
78
82
 
79
83
  ---
80
84
 
81
85
  ## 安装
82
86
 
83
- ### 方式一:从 GitHub 安装(推荐,能收到更新)
87
+ ### 方式一:从 npm 安装(推荐,能收到更新提示)
84
88
 
85
89
  ```sh
86
- dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets
90
+ dsh plugin --profile web add dsh-team-presets
87
91
  ```
88
92
 
89
93
  把 `web` 换成你实际的 profile 名。要固定本版:
90
94
 
91
95
  ```sh
92
- dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets#v0.2.3
96
+ dsh plugin --profile web add dsh-team-presets@0.2.4
97
+ ```
98
+
99
+ > **为什么推荐 npm**:只有从 registry 安装的插件才会被插件管理器**自动检测新版本**。管理器只放行 `kind === 'registry'` 的来源(见 `plugin-manager/src/index.ts` 的 `updateRefusal()`),`github:` 会被判定成 `kind: 'git'`,永远不会提示更新。想有更新提示,就用这条。
100
+
101
+ ### 方式二:从 GitHub 安装(不会提示更新)
102
+
103
+ ```sh
104
+ dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets
93
105
  ```
94
106
 
107
+ 要固定某个发布 tag:
108
+
109
+ ```sh
110
+ dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets#v0.2.4
111
+ ```
112
+
113
+ > 这条路径**不会**收到更新提示,新版本要手动重装。适合想跟仓库最新提交、或 npm 不可达的场景。
114
+ >
95
115
  > 仓库是**私有**的。拉取前你本机得有 GitHub 凭据(`gh auth login`、SSH key 或 `.netrc` 任选其一),否则会拉取失败。
96
116
 
97
- ### 方式二:在 GUI 里点(装本地包)
117
+ ### 方式三:在 GUI 里点(装本地包)
98
118
 
99
119
  打开 **全局面板 → 插件 → 添加插件**,在「包名或地址」里粘贴本地绝对路径:
100
120
 
@@ -111,7 +131,7 @@ dsh plugin --profile web add github:jaxhu1108/dsh-agent-team-presets#v0.2.3
111
131
  按插件管理器的提示重新加载(或重启 DSH),然后:
112
132
 
113
133
  1. 打开 **设置 → 智能体团队预设**
114
- 2. 确认插件详情显示名称 `dsh-team-presets`、版本 `0.2.3`
134
+ 2. 确认插件详情显示名称 `dsh-team-presets`、版本 `0.2.4`
115
135
  3. 确认组件状态是「运行中」
116
136
 
117
137
  ### 注意事项
package/lib/index.js CHANGED
@@ -7090,6 +7090,249 @@ function teamSettingsReconcile(ctx, config, namespace) {
7090
7090
  }
7091
7091
 
7092
7092
 
7093
+ /**
7094
+ * The plugin's own global troubleshooting skill.
7095
+ *
7096
+ * Unlike a Team Skill, this is a host-level runtime skill: it is registered on
7097
+ * the plugin's own context as soon as the deployment composes the skill
7098
+ * service, so every Session can see it without a Team, a role assignment, or
7099
+ * any per-Agent scope. It documents the failure modes this plugin can produce
7100
+ * and the evidence that distinguishes them from host, provider, and user
7101
+ * configuration problems.
7102
+ *
7103
+ * @module dsh-team-presets/builtin-skill
7104
+ */
7105
+ /** Stable name the host `skill` tool addresses this guide by. */
7106
+ const BUILTIN_SKILL_NAME = "team-presets-troubleshooting";
7107
+ /** Routing description shown in the session skill catalog. */
7108
+ const BUILTIN_SKILL_DESCRIPTION = "当使用 dsh-team-presets 出现团队不生效、成员无法召唤、工具被拒、成员模型路由不符、Team Skill 不可见、安装/升级异常或行为与预期不一致时使用;按证据定位,区分插件、宿主与用户配置。";
7109
+ /** Extra routing guidance; kept separate from the body so discovery stays short. */
7110
+ const BUILTIN_SKILL_WHEN_TO_USE = "用户报告本插件的 Team 选择、成员创建、工具策略、模型路由、Team Skill、安装升级或运行时行为异常时。";
7111
+ /** The full instruction body loaded by the host skill tool. */
7112
+ const BUILTIN_SKILL_CONTENT = `# Agent Team Presets 使用问题排查
7113
+
7114
+ ## 适用范围
7115
+
7116
+ 本 Skill 只处理 **dsh-team-presets** 插件自身的配置与运行问题。Agent Teams 子系统、模型供应商、宿主 UI 或浏览器本身的问题要分开判断;不要把所有异常都归因于本插件。
7117
+
7118
+ 排查原则:先确认事实,再改配置;只读诊断优先;修改、重装、重启前先确认影响和回滚方式。
7119
+
7120
+ ## 证据优先级(重要)
7121
+
7122
+ 按以下顺序采信证据,不要用低优先级的值推翻高优先级的值:
7123
+
7124
+ 1. **运行事实**:成员子会话日志里的 model/selection、首条 request/header 的 header.config;spawn_team_member 返回的 configuredRoute;成员快照里的 route。
7125
+ 2. **配置事实**:Team 预设中该成员的 provider/model/reasoningEffort;当前会话的 Team selection;Agent preset。
7126
+ 3. **展示值**:subagent/descriptor 的 agentModel、list_agents/成员名册里的 model、UI 卡片上的模型名。
7127
+
7128
+ 展示值可能是从父会话继承的 fallback 元数据,**不能作为模型路由证据**。已知 list_agents 的 model 可能返回错误或继承值,而成员实际请求已经使用自己的路由;这属于展示问题,不代表路由注入失败。同理,路由恰好等于队长模型时,也不能证明“注入生效”;要验证注入,应选一个与队长路由不同的成员做对照。
7129
+
7130
+ ## 快速分诊
7131
+
7132
+ | 现象 | 先查 | 常见原因 | 处理 |
7133
+ |---|---|---|---|
7134
+ | 选中团队但不生效 | 当前会话 Team selection、应用状态、报错文本 | Team 无效、被 quarantine、任务运行中冻结、Agent preset 不兼容 | 修复预设或换 Team;等队长/成员 idle;必要时换 Agent preset |
7135
+ | 自定义工具策略被拒 | 报错是否提到 native executor / run_code 仍暴露 | 挂载 native 执行器失败,或挂载后工具面仍含 PTC 传输 | 改用 all-tools,或在会话开始前换 standard/cordis 预设;两种情况都不会留下残留 |
7136
+ | 成员无法召唤 | 报错文本、成员快照、subagent provider、存储 | 无 member runtime、无存储、无 spawn/fork 后端、深度/配额、快照损坏、技能目录无法发布 | 按报错逐项修复;不要绕过标记或隔离 |
7137
+ | 成员模型与配置不符 | configuredRoute、model/selection、request/header、成员快照 route;list_agents 的 model 仅作展示 | 展示值 fallback(list_agents 可能返回错误/继承模型);预设未保存;provider 不支持该模型/effort;成员路由在召唤时读取 | 以运行证据为准;三处运行证据一致而 list_agents 不同时,判定为展示问题,实际路由正确 |
7138
+ | Team Skill 不可见 | 是否已分配给正确 roleId、skill 工具是否可见、库是否打开 | 分配错角色、成员创建早于目录发布、宿主隐藏 skill 工具、存储未打开 | 重新分配/重建成员;检查库与绑定 |
7139
+ | 成员没有技能 / 创建被拒 | 该角色是否已有分配、目录能否发布 | 有分配但目录发布失败,插件拒绝创建以避免空目录 | 修复 Team Skill 存储/绑定后再召唤 |
7140
+ | 运行中改配置不生效 | 队长/成员是否 running、任务边界 | 运行中的 Team 任务冻结定义 | 等任务结束或换 Team;不要强改运行中定义 |
7141
+ | Agent preset 切换失败 | 会话是否已开始、报错是否 locked | 只能在首轮前切换;切换后 Team 会重新校验 | 新建会话;PTC 下改用 all-tools 或原生 preset |
7142
+ | 安装/升级异常 | 保存的依赖、已安装版本、engines、安装日志 | 版本范围不符、包管理器策略、安装未完成、未重启 | 按官方管理器重试;核对版本/哈希/重启要求 |
7143
+ | 重挂载后工具被拒 | quarantine 状态、任务边界 | 运行中重挂载会隔离到任务边界 | 等 idle;选择其他 Team 或 No team |
7144
+
7145
+ ## 1. 选中团队但不生效
7146
+
7147
+ - 先确认当前会话的 Team selection:输入区 Team 控件、设置页,或 profile 的 cordis.patch.yml 中 selections。当前会话没有选中 Team 时,工具不受 Team 策略约束,这是预期行为。
7148
+ - 如果 Team 被拒绝,页面/日志会给出原因:能力缺失、PTC 自定义策略、恢复失败、定义无效等。按原因修预设,不要反复重选同一个无效 Team。
7149
+ - 如果队长或任一成员正在 running/provisioning,当前 Team 任务会冻结它启动时的定义;新保存的修改要等任务边界才采用。不要用重挂载强行刷新。
7150
+ - 恢复通道:在输入区选择另一个有效 Team 或 No team;变更在队长和成员都 idle 后生效。
7151
+ - 如果报错提到配置被 home patch / 命令行覆盖,检查 profile patch、$DSH_HOME/cordis.patch.yml 和 --patch 是否有重复的 agent-team-presets 声明。
7152
+
7153
+ ## 2. 自定义工具策略被拒 / PTC
7154
+
7155
+ PTC 预设 + 自定义白名单现在可以应用,但会改变该会话的工具面:
7156
+
7157
+ - 应用时插件把宿主自带的 native 工具执行器挂到**该会话的 Agent 作用域**(方法「agent.ctx.tools.setExecutor」),部署级 PTC 执行器和其他会话都不受影响。
7158
+ - 该注册的 effect 归 Agent ctx 所有,插件**从不主动释放** —— 这正是 DSH 0.2.2-rc.1 单向释放(tombstone)不会咬到的原因;Agent 销毁时随上下文回收。
7159
+ - 代价:这个会话此后不再使用「run_code」,直到它的 Agent 结束。
7160
+ - 报错时只有两种可能:挂载失败,或挂载后工具面仍暴露 PTC 传输;两种情况都不会留下残留(从未释放过执行器),处理方式是该 Team 改用 all-tools 模式,或在会话开始前选 native 预设。
7161
+ - 不要绕过 guard、不要关闭隔离、也不要手工「presentAs」:策略必须与实际执行面一致。
7162
+ - 检查点:会话当前 Agent preset、Team 队长/成员的 toolMode、报错是否来自应用阶段还是 spawn_team_member。
7163
+
7164
+ ## 3. 成员无法召唤
7165
+
7166
+ 先读完整报错,再对照:
7167
+
7168
+ - **没有 member runtime**:Session 不是在插件激活范围内组合的,无法给成员安装冻结配置。检查 profile 是否加载了本插件与 Agent Teams。
7169
+ - **没有持久存储 / member store 打不开**:成员快照无法落盘,创建会被拒绝。检查 storage domain 与 $DSH_HOME 可写性。
7170
+ - **没有执行后端**:spawn/fork provider 未注册、不可用或不能创建 continuable child。检查 subagents provider 注册与配置的 freshProvider/forkProvider。
7171
+ - **深度/并发/生命周期配额**:检查 delegation depth、并发 subagent 上限、Team lifetime member quota。成员名不会被复用;已完成的成员仍占 roster 槽位,下一次会得到 executor-2 之类的新名字;lifetime quota 用完后不能再召唤。
7172
+ - **标记为 preset-managed 但 roster 找不到 / 快照丢失或损坏**:插件会拒绝而不是用默认配置恢复。检查成员快照与 Team roster,不要手工伪造标记。
7173
+ - **技能目录无法发布**:该角色已有 Team Skill 分配,但目录没有成功发布;插件拒绝创建,避免成员首轮看到空目录。先修 Team Skill 存储/绑定。
7174
+
7175
+ 检查位置:$DSH_HOME/storages/agent_team_presets_members.json、profile 的 subagents 配置、Team Skill 库与 bindings.json、当前 Team 的成员 roster。
7176
+
7177
+ ## 4. 成员模型路由不符 / 验证路由
7178
+
7179
+ 按证据优先级取证:
7180
+
7181
+ 1. spawn_team_member 结果里的 configuredRoute:插件实际安装的路由。
7182
+ 2. 成员子会话日志的 model/selection:会话级持久选择。
7183
+ 3. 同一日志首条 request/header 的 header.config:真实请求使用的 provider/model/reasoningEffort。
7184
+ 4. 成员快照的 route:冻结在成员记录里的路由。
7185
+
7186
+ 不要用 subagent/descriptor 的 agentModel、list_agents/成员名册的 model、UI 卡片上的模型名作为路由证据;它们可能是父会话继承的展示值。
7187
+
7188
+ **已知展示差异:** list_agents 的 model 字段可能返回父会话的 fallback 模型(例如队长模型),而成员实际请求已经使用自己的路由。只要 configuredRoute、model/selection、首条 request/header.config、成员快照 route 一致,就应判定为“展示值错误、实际运行正确”,不要据此修改 Team 或报告路由故障。
7189
+
7190
+ 如果实际请求与配置不一致:
7191
+
7192
+ - 确认 Team 预设中该成员的 provider/model/reasoningEffort 已保存;
7193
+ - 确认 provider registry 支持该模型和 reasoning effort;
7194
+ - 成员路由在召唤时读取;已存在成员保留冻结路由。修改 Team 后请召唤新成员(名字不会复用);
7195
+ - 冷恢复成员会重放其记录路由;要换路由,创建新成员。
7196
+ - 如果配置路由恰好等于队长模型,选一个不同路由的成员做对照,才能证明注入生效。
7197
+
7198
+ ## 5. Team Skill 不可见 / 成员没有技能
7199
+
7200
+ 先区分两类技能:
7201
+
7202
+ - **Team Skill**:本插件的私有库,按 Team 角色分配,只在被召唤成员自己的 Agent 作用域注册;默认路径 $DSH_HOME/agent-team-presets/team-skills。
7203
+ - **宿主/插件级 skill**:注册在全局层,所有会话可见;例如本排查 Skill。它不需要 Team,也不按角色隔离。
7204
+
7205
+ Team Skill 排查:
7206
+
7207
+ - 库是否成功打开;资产是否存在于私有库;
7208
+ - 是否分配给正确的 roleId(不是显示名);成员的角色身份是否匹配;
7209
+ - 该 Agent 是否能看到 skill 工具(宿主隐藏它时,分配存在但目录不可用);
7210
+ - 成员创建时目录是否已发布;有分配但发布失败时,插件会拒绝创建。
7211
+
7212
+ 检查 bindings.json、库页面与成员快照中的 roleId;不要手工编辑存储文件。
7213
+
7214
+ ## 6. 内置技能更新 / 本地覆盖
7215
+
7216
+ - 插件内置的 Team Skill 是只读的;需要修改时创建本地副本(override),不要直接改内置目录。
7217
+ - 内置版本升级后,本地副本可能显示 updateAvailable;用“恢复为插件内置版本”重置。
7218
+ - 如果日志出现 shipped skill changed without bumping its version,说明包内文件变了但版本号没变;保留已审核副本并修正发布版本,不要强行覆盖。
7219
+
7220
+ ## 7. 任务运行中改配置不生效
7221
+
7222
+ - 运行中的 Team 任务会冻结它启动时的定义:persona、briefing、成员 roster、工具策略都来自冻结定义。
7223
+ - 新保存的 Team 修改只在任务边界采用;不要在队长/成员 running 时期待热更新。
7224
+ - 需要立即切换时,先结束/等待任务,或在输入区选择其他 Team / No team;不要用重挂载绕过冻结。
7225
+
7226
+ ## 8. Agent preset 切换失败 / Team 重新校验
7227
+
7228
+ - Agent preset 只能在会话首轮开始前切换;已有轮次后会报 agent-preset/locked。需要换 preset 时新建会话。
7229
+ - 切换 preset 后,插件会释放旧 Team 应用并按新能力重新校验选中的 Team。新 preset 是 PTC 且 Team 使用自定义策略时,会被拒绝或隔离;改用 all-tools 或原生 preset。
7230
+ - 切换后如果工具暂时被拒,检查是否在重新校验窗口;等应用完成,不要连续重试。
7231
+
7232
+ ## 9. 安装 / 升级 / 版本
7233
+
7234
+ - 本版本要求 DSH >=0.2.2-rc.1 <0.3.0;旧宿主请保留 0.1.8。安装前核对 engines.dsh。
7235
+ - 通过官方插件管理器安装/升级;仓库包含预构建产物,通常无需构建。
7236
+ - 安装失败时不要只看版本号:核对 application 结果、warnings、保存的 package source、已安装文件哈希、是否需要重启。
7237
+ - 失败的安装可能让 node_modules 比保存的依赖规格更新;这是未完成状态,不要据此宣称升级成功。解决包管理器策略后重试,并再次核对保存的 source 与运行版本。
7238
+ - 不要为了强制使用被拒绝的包文件而反复切换插件激活状态。
7239
+
7240
+ ## 10. HMR / 重挂载 / quarantine
7241
+
7242
+ - 运行中重挂载可能让 Session 进入 quarantine,直到任务边界;这是保护措施,不是配置错误。
7243
+ - 等队长/成员 idle 后再操作;用输入区选择另一个 Team 或 No team 恢复。
7244
+ - quarantine 下队长只有恢复工具可用,成员没有豁免;不要尝试关闭 guard 或伪造状态。
7245
+
7246
+ ## 11. 诊断命令与证据位置
7247
+
7248
+ 当前会话/Team:
7249
+
7250
+ ~~~bash
7251
+ # profile 中的 Team 定义与 selections(按实际 profile 调整)
7252
+ sed -n '1,200p' "$DSH_HOME/profiles/web/cordis.patch.yml"
7253
+ ~~~
7254
+
7255
+ 成员快照:
7256
+
7257
+ ~~~bash
7258
+ python3 - <<'PY'
7259
+ import json, os
7260
+ from pathlib import Path
7261
+ home = Path(os.environ.get('DSH_HOME') or (Path.home() / '.dsh'))
7262
+ p = home / 'storages/agent_team_presets_members.json'
7263
+ d = json.loads(p.read_text())
7264
+ for k, v in d['tables']['members'].items():
7265
+ if v.get('rootSessionId') == '<root-session-id>':
7266
+ print(k, v.get('memberName'), v.get('route'), v.get('childSessionId'), v.get('lifecycle'))
7267
+ PY
7268
+ ~~~
7269
+
7270
+ 成员子会话日志:
7271
+
7272
+ ~~~bash
7273
+ # 先按 DSH_SESSION_ID 找到目录;日志文件名以实际为准
7274
+ SID='<child-session-id>'
7275
+ DIR=$(find "$DSH_HOME/sessions" -maxdepth 2 -type d -name "$SID")
7276
+ zstdcat "$DIR/session.v4.jsonl.zstd" | python3 -c '
7277
+ import json, sys
7278
+ sel = []; hdr = None
7279
+ for line in sys.stdin:
7280
+ e = json.loads(line)
7281
+ if e.get("type") == "model/selection": sel.append(e.get("data"))
7282
+ elif e.get("type") == "request/header" and hdr is None:
7283
+ hdr = e["data"]["header"]["config"]
7284
+ print("selection", sel)
7285
+ print("request", hdr)
7286
+ '
7287
+ ~~~
7288
+
7289
+ 注意:request/header 行内嵌完整 tools schema,不要直接 grep 原文,使用 JSON 投影只取 header.config。
7290
+
7291
+ Team Skill 私有库:
7292
+
7293
+ ~~~bash
7294
+ ls -la "$DSH_HOME/agent-team-presets/team-skills"
7295
+ cat "$DSH_HOME/agent-team-presets/team-skills/bindings.json"
7296
+ ~~~
7297
+
7298
+ 插件版本/范围:profile 的 package.json、已安装包的 package.json、engines.dsh。
7299
+
7300
+ ## 12. 报告模板
7301
+
7302
+ 报告时请给出:
7303
+
7304
+ - 现象与预期;
7305
+ - 复现步骤(Session、Team、成员、Agent preset);
7306
+ - 插件版本与 DSH 版本;
7307
+ - 证据:configuredRoute、model/selection、request/header.config、成员快照 route、相关日志路径;
7308
+ - 已确认 / 未确认的边界;
7309
+ - 建议的修复与影响。
7310
+
7311
+ 不要在没有运行证据时宣称“已修复”;不要把展示值当作运行事实;不要在未授权时提交、推送或发布。
7312
+ `;
7313
+ /**
7314
+ * Register the global troubleshooting skill when the deployment composes the
7315
+ * skill service.
7316
+ *
7317
+ * The registration is intentionally not scoped to an Agent: it belongs to the
7318
+ * plugin installation, so a Session with no Team, no selected preset, and no
7319
+ * Team Skill assignment can still load it. The injection fiber is owned by the
7320
+ * plugin, so unload removes the skill with the rest of this activation.
7321
+ * @param ctx - the plugin context whose lifetime owns the registration.
7322
+ */
7323
+ function registerBuiltinSkill(ctx) {
7324
+ ctx.inject(["skills"], (injected) => {
7325
+ injected.effect(() => injected.skills.register({
7326
+ name: BUILTIN_SKILL_NAME,
7327
+ description: BUILTIN_SKILL_DESCRIPTION,
7328
+ whenToUse: BUILTIN_SKILL_WHEN_TO_USE,
7329
+ source: "runtime",
7330
+ content: BUILTIN_SKILL_CONTENT
7331
+ }), "team-presets: built-in troubleshooting skill");
7332
+ });
7333
+ }
7334
+
7335
+
7093
7336
  /**
7094
7337
  * Live Team execution state for the settings page.
7095
7338
  *
@@ -19294,6 +19537,7 @@ function apply(ctx, config) {
19294
19537
  clearTimeout(reconcileTimer);
19295
19538
  settingsReconcile.dispose();
19296
19539
  }, "agent-team-presets: settings reconcile readiness");
19540
+ registerBuiltinSkill(ctx);
19297
19541
  for (const agent of ctx.agents.list()) if (isSessionRoot(agent)) reconcile(agent);
19298
19542
  else initializeChild(agent, true);
19299
19543
  members.whenReady().then(() => {
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The plugin's own global troubleshooting skill.
3
+ *
4
+ * Unlike a Team Skill, this is a host-level runtime skill: it is registered on
5
+ * the plugin's own context as soon as the deployment composes the skill
6
+ * service, so every Session can see it without a Team, a role assignment, or
7
+ * any per-Agent scope. It documents the failure modes this plugin can produce
8
+ * and the evidence that distinguishes them from host, provider, and user
9
+ * configuration problems.
10
+ *
11
+ * @module dsh-team-presets/builtin-skill
12
+ */
13
+ import type { Context } from '@deepseek-ai/cordis';
14
+ /** Stable name the host `skill` tool addresses this guide by. */
15
+ export declare const BUILTIN_SKILL_NAME = "team-presets-troubleshooting";
16
+ /** Routing description shown in the session skill catalog. */
17
+ export declare const BUILTIN_SKILL_DESCRIPTION = "\u5F53\u4F7F\u7528 dsh-team-presets \u51FA\u73B0\u56E2\u961F\u4E0D\u751F\u6548\u3001\u6210\u5458\u65E0\u6CD5\u53EC\u5524\u3001\u5DE5\u5177\u88AB\u62D2\u3001\u6210\u5458\u6A21\u578B\u8DEF\u7531\u4E0D\u7B26\u3001Team Skill \u4E0D\u53EF\u89C1\u3001\u5B89\u88C5/\u5347\u7EA7\u5F02\u5E38\u6216\u884C\u4E3A\u4E0E\u9884\u671F\u4E0D\u4E00\u81F4\u65F6\u4F7F\u7528\uFF1B\u6309\u8BC1\u636E\u5B9A\u4F4D\uFF0C\u533A\u5206\u63D2\u4EF6\u3001\u5BBF\u4E3B\u4E0E\u7528\u6237\u914D\u7F6E\u3002";
18
+ /** Extra routing guidance; kept separate from the body so discovery stays short. */
19
+ export declare const BUILTIN_SKILL_WHEN_TO_USE = "\u7528\u6237\u62A5\u544A\u672C\u63D2\u4EF6\u7684 Team \u9009\u62E9\u3001\u6210\u5458\u521B\u5EFA\u3001\u5DE5\u5177\u7B56\u7565\u3001\u6A21\u578B\u8DEF\u7531\u3001Team Skill\u3001\u5B89\u88C5\u5347\u7EA7\u6216\u8FD0\u884C\u65F6\u884C\u4E3A\u5F02\u5E38\u65F6\u3002";
20
+ /** The full instruction body loaded by the host skill tool. */
21
+ export declare const BUILTIN_SKILL_CONTENT: string;
22
+ /**
23
+ * Register the global troubleshooting skill when the deployment composes the
24
+ * skill service.
25
+ *
26
+ * The registration is intentionally not scoped to an Agent: it belongs to the
27
+ * plugin installation, so a Session with no Team, no selected preset, and no
28
+ * Team Skill assignment can still load it. The injection fiber is owned by the
29
+ * plugin, so unload removes the skill with the rest of this activation.
30
+ * @param ctx - the plugin context whose lifetime owns the registration.
31
+ */
32
+ export declare function registerBuiltinSkill(ctx: Context): void;
@@ -0,0 +1,241 @@
1
+ /**
2
+ * The plugin's own global troubleshooting skill.
3
+ *
4
+ * Unlike a Team Skill, this is a host-level runtime skill: it is registered on
5
+ * the plugin's own context as soon as the deployment composes the skill
6
+ * service, so every Session can see it without a Team, a role assignment, or
7
+ * any per-Agent scope. It documents the failure modes this plugin can produce
8
+ * and the evidence that distinguishes them from host, provider, and user
9
+ * configuration problems.
10
+ *
11
+ * @module dsh-team-presets/builtin-skill
12
+ */
13
+ /** Stable name the host `skill` tool addresses this guide by. */
14
+ export const BUILTIN_SKILL_NAME = 'team-presets-troubleshooting';
15
+ /** Routing description shown in the session skill catalog. */
16
+ export const BUILTIN_SKILL_DESCRIPTION = '当使用 dsh-team-presets 出现团队不生效、成员无法召唤、工具被拒、成员模型路由不符、Team Skill 不可见、安装/升级异常或行为与预期不一致时使用;按证据定位,区分插件、宿主与用户配置。';
17
+ /** Extra routing guidance; kept separate from the body so discovery stays short. */
18
+ export const BUILTIN_SKILL_WHEN_TO_USE = '用户报告本插件的 Team 选择、成员创建、工具策略、模型路由、Team Skill、安装升级或运行时行为异常时。';
19
+ /** The full instruction body loaded by the host skill tool. */
20
+ export const BUILTIN_SKILL_CONTENT = `# Agent Team Presets 使用问题排查
21
+
22
+ ## 适用范围
23
+
24
+ 本 Skill 只处理 **dsh-team-presets** 插件自身的配置与运行问题。Agent Teams 子系统、模型供应商、宿主 UI 或浏览器本身的问题要分开判断;不要把所有异常都归因于本插件。
25
+
26
+ 排查原则:先确认事实,再改配置;只读诊断优先;修改、重装、重启前先确认影响和回滚方式。
27
+
28
+ ## 证据优先级(重要)
29
+
30
+ 按以下顺序采信证据,不要用低优先级的值推翻高优先级的值:
31
+
32
+ 1. **运行事实**:成员子会话日志里的 model/selection、首条 request/header 的 header.config;spawn_team_member 返回的 configuredRoute;成员快照里的 route。
33
+ 2. **配置事实**:Team 预设中该成员的 provider/model/reasoningEffort;当前会话的 Team selection;Agent preset。
34
+ 3. **展示值**:subagent/descriptor 的 agentModel、list_agents/成员名册里的 model、UI 卡片上的模型名。
35
+
36
+ 展示值可能是从父会话继承的 fallback 元数据,**不能作为模型路由证据**。已知 list_agents 的 model 可能返回错误或继承值,而成员实际请求已经使用自己的路由;这属于展示问题,不代表路由注入失败。同理,路由恰好等于队长模型时,也不能证明“注入生效”;要验证注入,应选一个与队长路由不同的成员做对照。
37
+
38
+ ## 快速分诊
39
+
40
+ | 现象 | 先查 | 常见原因 | 处理 |
41
+ |---|---|---|---|
42
+ | 选中团队但不生效 | 当前会话 Team selection、应用状态、报错文本 | Team 无效、被 quarantine、任务运行中冻结、Agent preset 不兼容 | 修复预设或换 Team;等队长/成员 idle;必要时换 Agent preset |
43
+ | 自定义工具策略被拒 | 报错是否提到 native executor / run_code 仍暴露 | 挂载 native 执行器失败,或挂载后工具面仍含 PTC 传输 | 改用 all-tools,或在会话开始前换 standard/cordis 预设;两种情况都不会留下残留 |
44
+ | 成员无法召唤 | 报错文本、成员快照、subagent provider、存储 | 无 member runtime、无存储、无 spawn/fork 后端、深度/配额、快照损坏、技能目录无法发布 | 按报错逐项修复;不要绕过标记或隔离 |
45
+ | 成员模型与配置不符 | configuredRoute、model/selection、request/header、成员快照 route;list_agents 的 model 仅作展示 | 展示值 fallback(list_agents 可能返回错误/继承模型);预设未保存;provider 不支持该模型/effort;成员路由在召唤时读取 | 以运行证据为准;三处运行证据一致而 list_agents 不同时,判定为展示问题,实际路由正确 |
46
+ | Team Skill 不可见 | 是否已分配给正确 roleId、skill 工具是否可见、库是否打开 | 分配错角色、成员创建早于目录发布、宿主隐藏 skill 工具、存储未打开 | 重新分配/重建成员;检查库与绑定 |
47
+ | 成员没有技能 / 创建被拒 | 该角色是否已有分配、目录能否发布 | 有分配但目录发布失败,插件拒绝创建以避免空目录 | 修复 Team Skill 存储/绑定后再召唤 |
48
+ | 运行中改配置不生效 | 队长/成员是否 running、任务边界 | 运行中的 Team 任务冻结定义 | 等任务结束或换 Team;不要强改运行中定义 |
49
+ | Agent preset 切换失败 | 会话是否已开始、报错是否 locked | 只能在首轮前切换;切换后 Team 会重新校验 | 新建会话;PTC 下改用 all-tools 或原生 preset |
50
+ | 安装/升级异常 | 保存的依赖、已安装版本、engines、安装日志 | 版本范围不符、包管理器策略、安装未完成、未重启 | 按官方管理器重试;核对版本/哈希/重启要求 |
51
+ | 重挂载后工具被拒 | quarantine 状态、任务边界 | 运行中重挂载会隔离到任务边界 | 等 idle;选择其他 Team 或 No team |
52
+
53
+ ## 1. 选中团队但不生效
54
+
55
+ - 先确认当前会话的 Team selection:输入区 Team 控件、设置页,或 profile 的 cordis.patch.yml 中 selections。当前会话没有选中 Team 时,工具不受 Team 策略约束,这是预期行为。
56
+ - 如果 Team 被拒绝,页面/日志会给出原因:能力缺失、PTC 自定义策略、恢复失败、定义无效等。按原因修预设,不要反复重选同一个无效 Team。
57
+ - 如果队长或任一成员正在 running/provisioning,当前 Team 任务会冻结它启动时的定义;新保存的修改要等任务边界才采用。不要用重挂载强行刷新。
58
+ - 恢复通道:在输入区选择另一个有效 Team 或 No team;变更在队长和成员都 idle 后生效。
59
+ - 如果报错提到配置被 home patch / 命令行覆盖,检查 profile patch、$DSH_HOME/cordis.patch.yml 和 --patch 是否有重复的 agent-team-presets 声明。
60
+
61
+ ## 2. 自定义工具策略被拒 / PTC
62
+
63
+ PTC 预设 + 自定义白名单现在可以应用,但会改变该会话的工具面:
64
+
65
+ - 应用时插件把宿主自带的 native 工具执行器挂到**该会话的 Agent 作用域**(方法「agent.ctx.tools.setExecutor」),部署级 PTC 执行器和其他会话都不受影响。
66
+ - 该注册的 effect 归 Agent ctx 所有,插件**从不主动释放** —— 这正是 DSH 0.2.2-rc.1 单向释放(tombstone)不会咬到的原因;Agent 销毁时随上下文回收。
67
+ - 代价:这个会话此后不再使用「run_code」,直到它的 Agent 结束。
68
+ - 报错时只有两种可能:挂载失败,或挂载后工具面仍暴露 PTC 传输;两种情况都不会留下残留(从未释放过执行器),处理方式是该 Team 改用 all-tools 模式,或在会话开始前选 native 预设。
69
+ - 不要绕过 guard、不要关闭隔离、也不要手工「presentAs」:策略必须与实际执行面一致。
70
+ - 检查点:会话当前 Agent preset、Team 队长/成员的 toolMode、报错是否来自应用阶段还是 spawn_team_member。
71
+
72
+ ## 3. 成员无法召唤
73
+
74
+ 先读完整报错,再对照:
75
+
76
+ - **没有 member runtime**:Session 不是在插件激活范围内组合的,无法给成员安装冻结配置。检查 profile 是否加载了本插件与 Agent Teams。
77
+ - **没有持久存储 / member store 打不开**:成员快照无法落盘,创建会被拒绝。检查 storage domain 与 $DSH_HOME 可写性。
78
+ - **没有执行后端**:spawn/fork provider 未注册、不可用或不能创建 continuable child。检查 subagents provider 注册与配置的 freshProvider/forkProvider。
79
+ - **深度/并发/生命周期配额**:检查 delegation depth、并发 subagent 上限、Team lifetime member quota。成员名不会被复用;已完成的成员仍占 roster 槽位,下一次会得到 executor-2 之类的新名字;lifetime quota 用完后不能再召唤。
80
+ - **标记为 preset-managed 但 roster 找不到 / 快照丢失或损坏**:插件会拒绝而不是用默认配置恢复。检查成员快照与 Team roster,不要手工伪造标记。
81
+ - **技能目录无法发布**:该角色已有 Team Skill 分配,但目录没有成功发布;插件拒绝创建,避免成员首轮看到空目录。先修 Team Skill 存储/绑定。
82
+
83
+ 检查位置:$DSH_HOME/storages/agent_team_presets_members.json、profile 的 subagents 配置、Team Skill 库与 bindings.json、当前 Team 的成员 roster。
84
+
85
+ ## 4. 成员模型路由不符 / 验证路由
86
+
87
+ 按证据优先级取证:
88
+
89
+ 1. spawn_team_member 结果里的 configuredRoute:插件实际安装的路由。
90
+ 2. 成员子会话日志的 model/selection:会话级持久选择。
91
+ 3. 同一日志首条 request/header 的 header.config:真实请求使用的 provider/model/reasoningEffort。
92
+ 4. 成员快照的 route:冻结在成员记录里的路由。
93
+
94
+ 不要用 subagent/descriptor 的 agentModel、list_agents/成员名册的 model、UI 卡片上的模型名作为路由证据;它们可能是父会话继承的展示值。
95
+
96
+ **已知展示差异:** list_agents 的 model 字段可能返回父会话的 fallback 模型(例如队长模型),而成员实际请求已经使用自己的路由。只要 configuredRoute、model/selection、首条 request/header.config、成员快照 route 一致,就应判定为“展示值错误、实际运行正确”,不要据此修改 Team 或报告路由故障。
97
+
98
+ 如果实际请求与配置不一致:
99
+
100
+ - 确认 Team 预设中该成员的 provider/model/reasoningEffort 已保存;
101
+ - 确认 provider registry 支持该模型和 reasoning effort;
102
+ - 成员路由在召唤时读取;已存在成员保留冻结路由。修改 Team 后请召唤新成员(名字不会复用);
103
+ - 冷恢复成员会重放其记录路由;要换路由,创建新成员。
104
+ - 如果配置路由恰好等于队长模型,选一个不同路由的成员做对照,才能证明注入生效。
105
+
106
+ ## 5. Team Skill 不可见 / 成员没有技能
107
+
108
+ 先区分两类技能:
109
+
110
+ - **Team Skill**:本插件的私有库,按 Team 角色分配,只在被召唤成员自己的 Agent 作用域注册;默认路径 $DSH_HOME/agent-team-presets/team-skills。
111
+ - **宿主/插件级 skill**:注册在全局层,所有会话可见;例如本排查 Skill。它不需要 Team,也不按角色隔离。
112
+
113
+ Team Skill 排查:
114
+
115
+ - 库是否成功打开;资产是否存在于私有库;
116
+ - 是否分配给正确的 roleId(不是显示名);成员的角色身份是否匹配;
117
+ - 该 Agent 是否能看到 skill 工具(宿主隐藏它时,分配存在但目录不可用);
118
+ - 成员创建时目录是否已发布;有分配但发布失败时,插件会拒绝创建。
119
+
120
+ 检查 bindings.json、库页面与成员快照中的 roleId;不要手工编辑存储文件。
121
+
122
+ ## 6. 内置技能更新 / 本地覆盖
123
+
124
+ - 插件内置的 Team Skill 是只读的;需要修改时创建本地副本(override),不要直接改内置目录。
125
+ - 内置版本升级后,本地副本可能显示 updateAvailable;用“恢复为插件内置版本”重置。
126
+ - 如果日志出现 shipped skill changed without bumping its version,说明包内文件变了但版本号没变;保留已审核副本并修正发布版本,不要强行覆盖。
127
+
128
+ ## 7. 任务运行中改配置不生效
129
+
130
+ - 运行中的 Team 任务会冻结它启动时的定义:persona、briefing、成员 roster、工具策略都来自冻结定义。
131
+ - 新保存的 Team 修改只在任务边界采用;不要在队长/成员 running 时期待热更新。
132
+ - 需要立即切换时,先结束/等待任务,或在输入区选择其他 Team / No team;不要用重挂载绕过冻结。
133
+
134
+ ## 8. Agent preset 切换失败 / Team 重新校验
135
+
136
+ - Agent preset 只能在会话首轮开始前切换;已有轮次后会报 agent-preset/locked。需要换 preset 时新建会话。
137
+ - 切换 preset 后,插件会释放旧 Team 应用并按新能力重新校验选中的 Team。新 preset 是 PTC 且 Team 使用自定义策略时,会被拒绝或隔离;改用 all-tools 或原生 preset。
138
+ - 切换后如果工具暂时被拒,检查是否在重新校验窗口;等应用完成,不要连续重试。
139
+
140
+ ## 9. 安装 / 升级 / 版本
141
+
142
+ - 本版本要求 DSH >=0.2.2-rc.1 <0.3.0;旧宿主请保留 0.1.8。安装前核对 engines.dsh。
143
+ - 通过官方插件管理器安装/升级;仓库包含预构建产物,通常无需构建。
144
+ - 安装失败时不要只看版本号:核对 application 结果、warnings、保存的 package source、已安装文件哈希、是否需要重启。
145
+ - 失败的安装可能让 node_modules 比保存的依赖规格更新;这是未完成状态,不要据此宣称升级成功。解决包管理器策略后重试,并再次核对保存的 source 与运行版本。
146
+ - 不要为了强制使用被拒绝的包文件而反复切换插件激活状态。
147
+
148
+ ## 10. HMR / 重挂载 / quarantine
149
+
150
+ - 运行中重挂载可能让 Session 进入 quarantine,直到任务边界;这是保护措施,不是配置错误。
151
+ - 等队长/成员 idle 后再操作;用输入区选择另一个 Team 或 No team 恢复。
152
+ - quarantine 下队长只有恢复工具可用,成员没有豁免;不要尝试关闭 guard 或伪造状态。
153
+
154
+ ## 11. 诊断命令与证据位置
155
+
156
+ 当前会话/Team:
157
+
158
+ ~~~bash
159
+ # profile 中的 Team 定义与 selections(按实际 profile 调整)
160
+ sed -n '1,200p' "$DSH_HOME/profiles/web/cordis.patch.yml"
161
+ ~~~
162
+
163
+ 成员快照:
164
+
165
+ ~~~bash
166
+ python3 - <<'PY'
167
+ import json, os
168
+ from pathlib import Path
169
+ home = Path(os.environ.get('DSH_HOME') or (Path.home() / '.dsh'))
170
+ p = home / 'storages/agent_team_presets_members.json'
171
+ d = json.loads(p.read_text())
172
+ for k, v in d['tables']['members'].items():
173
+ if v.get('rootSessionId') == '<root-session-id>':
174
+ print(k, v.get('memberName'), v.get('route'), v.get('childSessionId'), v.get('lifecycle'))
175
+ PY
176
+ ~~~
177
+
178
+ 成员子会话日志:
179
+
180
+ ~~~bash
181
+ # 先按 DSH_SESSION_ID 找到目录;日志文件名以实际为准
182
+ SID='<child-session-id>'
183
+ DIR=$(find "$DSH_HOME/sessions" -maxdepth 2 -type d -name "$SID")
184
+ zstdcat "$DIR/session.v4.jsonl.zstd" | python3 -c '
185
+ import json, sys
186
+ sel = []; hdr = None
187
+ for line in sys.stdin:
188
+ e = json.loads(line)
189
+ if e.get("type") == "model/selection": sel.append(e.get("data"))
190
+ elif e.get("type") == "request/header" and hdr is None:
191
+ hdr = e["data"]["header"]["config"]
192
+ print("selection", sel)
193
+ print("request", hdr)
194
+ '
195
+ ~~~
196
+
197
+ 注意:request/header 行内嵌完整 tools schema,不要直接 grep 原文,使用 JSON 投影只取 header.config。
198
+
199
+ Team Skill 私有库:
200
+
201
+ ~~~bash
202
+ ls -la "$DSH_HOME/agent-team-presets/team-skills"
203
+ cat "$DSH_HOME/agent-team-presets/team-skills/bindings.json"
204
+ ~~~
205
+
206
+ 插件版本/范围:profile 的 package.json、已安装包的 package.json、engines.dsh。
207
+
208
+ ## 12. 报告模板
209
+
210
+ 报告时请给出:
211
+
212
+ - 现象与预期;
213
+ - 复现步骤(Session、Team、成员、Agent preset);
214
+ - 插件版本与 DSH 版本;
215
+ - 证据:configuredRoute、model/selection、request/header.config、成员快照 route、相关日志路径;
216
+ - 已确认 / 未确认的边界;
217
+ - 建议的修复与影响。
218
+
219
+ 不要在没有运行证据时宣称“已修复”;不要把展示值当作运行事实;不要在未授权时提交、推送或发布。
220
+ `;
221
+ /**
222
+ * Register the global troubleshooting skill when the deployment composes the
223
+ * skill service.
224
+ *
225
+ * The registration is intentionally not scoped to an Agent: it belongs to the
226
+ * plugin installation, so a Session with no Team, no selected preset, and no
227
+ * Team Skill assignment can still load it. The injection fiber is owned by the
228
+ * plugin, so unload removes the skill with the rest of this activation.
229
+ * @param ctx - the plugin context whose lifetime owns the registration.
230
+ */
231
+ export function registerBuiltinSkill(ctx) {
232
+ ctx.inject(['skills'], (injected) => {
233
+ injected.effect(() => injected.skills.register({
234
+ name: BUILTIN_SKILL_NAME,
235
+ description: BUILTIN_SKILL_DESCRIPTION,
236
+ whenToUse: BUILTIN_SKILL_WHEN_TO_USE,
237
+ source: 'runtime',
238
+ content: BUILTIN_SKILL_CONTENT,
239
+ }), 'team-presets: built-in troubleshooting skill');
240
+ });
241
+ }
@@ -22,6 +22,7 @@ import { createdDepthRefusal } from "./delegation.js";
22
22
  import { isPresetMemberProvider, memberProviderMarker, registerMemberProviders } from "./member-identity.js";
23
23
  import { installNativePresentation, personaBaseline, prepareNativePresentation, readWire } from "./presentation.js";
24
24
  import { teamSettingsReconcile } from "./settings-reconcile.js";
25
+ import { registerBuiltinSkill } from "./builtin-skill.js";
25
26
  import { hasTeamApplicationMarker, isSessionRoot, TeamExecutionMonitor, teammatesBusy } from "./execution.js";
26
27
  import { RUN_CODE_NAME } from '@deepseek-ai/dsh-tools';
27
28
  import { registerPresetTools } from "./preset-tools.js";
@@ -1038,6 +1039,11 @@ export function apply(ctx, config) {
1038
1039
  const reconcileTimer = setTimeout(() => { if (!disposed)
1039
1040
  void settingsReconcile.request(); }, 0);
1040
1041
  ctx.effect(() => () => { clearTimeout(reconcileTimer); settingsReconcile.dispose(); }, 'agent-team-presets: settings reconcile readiness');
1042
+ // The troubleshooting guide ships with the installation, not with a Team: a
1043
+ // Session that selected no Team, or whose Team failed to apply, is exactly the
1044
+ // Session that needs it. Registration is owned by this activation's context,
1045
+ // so an unload removes the skill with the rest of the plugin.
1046
+ registerBuiltinSkill(ctx);
1041
1047
  for (const agent of ctx.agents.list()) {
1042
1048
  if (isSessionRoot(agent))
1043
1049
  reconcile(agent);
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "bugs": {
17
17
  "url": "https://github.com/jaxhu1108/dsh-agent-team-presets/issues"
18
18
  },
19
- "version": "0.2.3",
19
+ "version": "0.2.4",
20
20
  "keywords": [
21
21
  "agent-presets",
22
22
  "agent-teams",
@@ -173,6 +173,8 @@
173
173
  "NOTES.en.md",
174
174
  "NOTES.md",
175
175
  "ADAPTATION.md",
176
- "examples"
176
+ "examples",
177
+ "DIFFERENCES.md",
178
+ "DIFFERENCES.en.md"
177
179
  ]
178
180
  }