dsh-subagent-control 1.0.5 → 1.0.7

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.7
4
+
5
+ - Rewrote the README for users instead of maintainers: what the three tools are for, how to install
6
+ from the market, when to use each optional component, FAQ, privacy and uninstall. The Chinese
7
+ README is now the primary one and `README.en.md` is the English translation.
8
+ - The install example no longer pins a version, so it cannot go stale.
9
+ - Implementation notes, the boundary with the built-in tools and the test coverage moved to
10
+ `docs/implementation.md` and `docs/implementation.en.md`.
11
+
12
+ ## 1.0.6
13
+
14
+ - Declares the harness versions this bundle supports: `engines.dsh` is now
15
+ `>=0.2.1-rc.1 <0.3.0-0`. The field was absent, so the installer had nothing to check against
16
+ the running harness before installing.
17
+
3
18
  ## 1.0.5
4
19
 
5
20
  - The `subagent_budget` tool says "not running" instead of "inactive", and its line now lists how
package/README.en.md ADDED
@@ -0,0 +1,97 @@
1
+ # dsh-subagent-control
2
+
3
+ **Lets any agent — including a team member — list, steer and stop the subagents it started.**
4
+
5
+ `list_subagents` · `send_subagent_message` · `interrupt_subagent`
6
+
7
+ > English | [中文](README.md)
8
+
9
+ ## When you need it
10
+
11
+ - You started a few subagents to work in parallel and want to know who is still running
12
+ - You want to add one sentence to a subagent that is already working
13
+ - You want to stop the one that went off track
14
+ - Inside a team, a Lead's grandchildren should still be manageable top-down
15
+
16
+ ## The three tools
17
+
18
+ | Tool | What it does | Parameters |
19
+ | --- | --- | --- |
20
+ | `list_subagents` | List the subagents you started | `scope`: `children` (default, direct children) / `descendants` (the whole subtree); `include_teammates`: `true` by default |
21
+ | `send_subagent_message` | Send one more message to a direct child | `subagent_id`, `message` |
22
+ | `interrupt_subagent` | Stop a subagent's current turn | `subagent_id` |
23
+
24
+ It looks like this:
25
+
26
+ ```
27
+ list_subagents
28
+ → 3b0f9c1e running "review the patch" depth=1
29
+
30
+ list_subagents scope=descendants
31
+ → 3b0f9c1e running "review the patch" depth=1
32
+ 7d2a44b0 inactive "check the tests" depth=2
33
+
34
+ send_subagent_message subagent_id=3b0f9c1e message="also look at locale/zh.json"
35
+ → messageId=...
36
+
37
+ interrupt_subagent subagent_id=3b0f9c1e
38
+ → accepted=true
39
+ ```
40
+
41
+ Each line is `id status "label" depth=`. `running` means a turn is executing; `inactive` only means no turn is running right now — **the subagent is still there**, and a message wakes it.
42
+
43
+ Team members are continuable subagents too, so they show up in the list marked `team=teammate`. Pass `include_teammates: false` when you only want the plain subagents you started.
44
+
45
+ ## Install
46
+
47
+ 1. Open **Settings → Plugins → Market** and search for `dsh-subagent-control`
48
+ 2. Install it
49
+ 3. **No restart needed** — this is a host-side plugin, and the three tools are available immediately
50
+
51
+ Plugins with a settings page need a full quit and relaunch; this one does not.
52
+
53
+ ## Optional features (four, off by default)
54
+
55
+ | Row in the panel | Tool | What it does |
56
+ | --- | --- | --- |
57
+ | Cross-layer relay | `relay_subagent_message` | Message a deeper descendant: delivered to the first hop with a request to forward it down |
58
+ | Wait for subagents | `wait_subagents` | Wait for subagents in this turn instead of ending it first |
59
+ | Release subagents | `drain_subagents` | Stop and release direct children, freeing the run they occupy |
60
+ | Delegation budget | `subagent_budget` | Read-only report: depth limit, how many sit on each level, running / stopped |
61
+
62
+ Turn them on one by one under **Settings → Plugins → Installed → `dsh-subagent-control`**; each one registers exactly one tool.
63
+
64
+ ## Related plugins
65
+
66
+ - [dsh-team-limits](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/team-limits) — make the Agent Team limits editable fields on the plugin page
67
+ - [dsh-human-wait](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/human-wait) — keep PTC mode from burning its budget while you answer
68
+ - [dsh-find-session](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/dsh-find-session) — find text in the conversation or across every session
69
+
70
+ All three install separately: they override a shipped row or another plugin's behaviour, and that should never happen implicitly.
71
+
72
+ ## FAQ
73
+
74
+ **How do I confirm it works?** Ask the agent to call `list_subagents` once. These tools are for the agent — no new button appears in the UI.
75
+
76
+ **Why does it list only one or two?** It lists direct children by default. Use `scope=descendants` for the whole tree.
77
+
78
+ **Can an `inactive` subagent still be used?** Yes. It just has no turn running; a message wakes it.
79
+
80
+ **Does it clash with `dsh-subagent-library`?** Both register `list_subagents`, and only one global registration can win — pick one.
81
+
82
+ ## Privacy and cost
83
+
84
+ - Reads the subagent registry only; writes no files, opens no network connections, ships no config
85
+ - Zero dependencies
86
+
87
+ ## Uninstall
88
+
89
+ Disable or remove it in the plugin panel. Nothing is left behind.
90
+
91
+ ## Technical notes
92
+
93
+ Implementation, the boundary with the built-in tools, the four components and the tests: [docs/implementation.en.md](https://github.com/SpaceRelay/dsh-subagent-control/blob/main/docs/implementation.en.md)
94
+
95
+ ## License
96
+
97
+ MIT — see [LICENSE](./LICENSE). Source and issues: [github.com/SpaceRelay/dsh-subagent-control](https://github.com/SpaceRelay/dsh-subagent-control).
package/README.md CHANGED
@@ -1,32 +1,27 @@
1
1
  # dsh-subagent-control
2
2
 
3
- **English** · [简体中文](#简体中文)
4
-
5
- Three tools that let any DSH agent — **including a team member** — list, steer and stop the subagents it started.
3
+ **让任意智能体——包括团队成员——能列出、追问、中止自己派出的子代理。**
6
4
 
7
5
  `list_subagents` · `send_subagent_message` · `interrupt_subagent`
8
6
 
9
- ---
10
-
11
- ## English
12
-
13
- ### The problem
14
-
15
- The Harness ships `list_agents`, `send_message` and `interrupt_agent`. When the Agent Team bundle is active, it registers tools with **those same three names** in every team member's exact Agent scope, and the more specific registration wins. Inside a teammate scope the team versions take over: they resolve `target` against the team roster only, and interrupting is a Lead-only operation.
7
+ > [English](README.en.md) | 中文
16
8
 
17
- The result: a teammate can start a subagent with `subagent`, but cannot list it, follow up with it, or stop it — even though the subagent service (`ctx.subagents`) has supported all three for any live agent all along, and its authority rules already allow an ancestor to manage its own descendants.
9
+ ## 什么时候用得上
18
10
 
19
- This bundle does not fight over the taken names. It registers three **new** names, globally, so the Lead and every teammate get them at once.
11
+ - 派了几个子代理分头干活,想知道还有谁在跑、跑到哪一步
12
+ - 想给某个正在跑的子代理补一句话
13
+ - 想叫停跑偏的那个,把回合收回来
14
+ - 团队里,组长派出去的孙代子代理也要从上往下管得住
20
15
 
21
- ### Tools
16
+ ## 三个工具
22
17
 
23
- | Tool | Parameters | Underlying call |
18
+ | 工具 | 做什么 | 参数 |
24
19
  | --- | --- | --- |
25
- | `list_subagents` | `scope?`: `"children"` \| `"descendants"` (default `children`) | `ctx.subagents.listChildren()` / `listDescendants()` |
26
- | `send_subagent_message` | `subagent_id`, `message` (both required) | `ctx.subagents.sendMessage()` |
27
- | `interrupt_subagent` | `subagent_id` (required) | `ctx.subagents.interrupt()` with ancestor authority |
20
+ | `list_subagents` | 列出自己派出的子代理 | `scope`:`children`(默认,直接子代理)/ `descendants`(整棵子树);`include_teammates`:默认 `true` |
21
+ | `send_subagent_message` | 给一个直接子代理补一句话 | `subagent_id`、`message` |
22
+ | `interrupt_subagent` | 叫停某个子代理当前这一轮 | `subagent_id` |
28
23
 
29
- ### Usage
24
+ 长这样:
30
25
 
31
26
  ```
32
27
  list_subagents
@@ -36,175 +31,67 @@ list_subagents scope=descendants
36
31
  → 3b0f9c1e running "review the patch" depth=1
37
32
  7d2a44b0 inactive "check the tests" depth=2
38
33
 
39
- send_subagent_message subagent_id=3b0f9c1e message="also look at locale/zh.json"
34
+ send_subagent_message subagent_id=3b0f9c1e message="顺手看一下 locale/zh.json"
40
35
  → messageId=...
41
36
 
42
37
  interrupt_subagent subagent_id=3b0f9c1e
43
38
  → accepted=true
44
39
  ```
45
40
 
46
- Each listing line is `id status "label" depth=`. `status` is `running` or `inactive` — **inactive means no turn is executing, not that the subagent is gone**. Use `send_subagent_message` to wake it.
47
-
48
- Team members are continuable subagents too, so they also appear in this list, marked `team=teammate` (or `team=lead`). Pass `include_teammates: false` when you want only the plain subagents you started.
49
-
50
- ### Behaviour and limits
51
-
52
- - **One-shot subagents are hidden.** They cannot accept a follow-up message, so listing them would only invite a call that is guaranteed to fail.
53
- - **A broken record is reported, not thrown.** A child whose state cannot be read comes back as a diagnostic entry (`corrupt` / `unsupported` / `unavailable`) instead of turning the whole listing into an error.
54
- - **`send_subagent_message` reaches direct children only.** That is the service's own rule; the plugin does not widen it.
55
- - **`interrupt_subagent` reaches descendants**, so a team Lead can also stop a grandchild.
56
- - **Every failure names its cause**: no calling agent, unknown id, or an id that is not yours.
57
- - **No config, no storage.** The bundle writes nothing and reads nothing outside the three services.
58
-
59
- ### Install
60
-
61
- Through the plugin panel / market, or by asking the agent:
62
-
63
- ```
64
- plugin_manager install_bundle target "dsh-subagent-control@1.0.0"
65
- ```
66
-
67
- From a checkout, pass the **directory path** instead of the npm spec. The bundle applies immediately — no restart needed. Afterwards the three tool names are visible and the plugin row is enabled.
68
-
69
- ### Compatibility
70
-
71
- - DSH with the `tools`, `subagents` and `agents` services (0.2.x and later).
72
- - Node `^22.19.0 || >=24.0.0`.
73
- - **Zero dependencies** — no runtime dependency, no peer dependency, not a single `import`. The tools are plain tool-table objects with explicit JSON Schemas, so they install and behave identically from npm or from a linked checkout.
74
-
75
- ### Name collisions
76
-
77
- `dsh-subagent-library` also registers a global `list_subagents` tool. Two global registrations of one name cannot both win: install one of them, or remember that the other may shadow this one.
78
-
79
- The three new names were chosen precisely because they do **not** collide with the built-in `list_agents` / `send_message` / `interrupt_agent`.
80
-
81
- ### Uninstall
82
-
83
- Remove or disable the bundle in the plugin panel. Nothing is left behind.
84
-
85
- ### Optional components (each off by default)
86
-
87
- Four extra tools ship as **separate components**, each with its own row and switch in the plugin
88
- panel (`Cross-layer relay`, `Wait for subagents`, `Release subagents`, `Delegation budget`).
89
- All four start disabled; turning one on registers exactly one tool, so you can enable only what
90
- you need.
91
-
92
- | Component | Tool | What it does | Risk |
93
- | --- | --- | --- | --- |
94
- | Cross-layer relay | `relay_subagent_message` | Best-effort message to a deeper descendant: delivered to the first hop with a request to forward it down | intermediate agents may summarize; not guaranteed |
95
- | Wait for subagents | `wait_subagents` | Wait for descendants (bounded by `timeout_seconds`) instead of ending your turn first | blocks up to the timeout |
96
- | Release subagents | `drain_subagents` | Stop **and release** direct children, unlike `interrupt_subagent`, which only stops the current turn | a released child cannot be woken by a message |
97
- | Delegation budget | `subagent_budget` | Read-only report: depth limit, how deep the tree goes, running/inactive counts | none |
98
-
99
- A separate companion bundle, [`dsh-team-limits`](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/team-limits),
100
- raises the Agent Team limits (members, tasks, message bytes). It is a separate install on
101
- purpose: it overrides the shipped `agent-team` row, and that should never happen implicitly.
102
-
103
- A second companion bundle, [`dsh-human-wait`](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/human-wait),
104
- stops the PTC `run_code` deadline from counting the time you spend answering a question, reviewing
105
- a plan or approving a request. PTC mode wraps the whole program — nested tool and approval waits
106
- included — in one 120 s wall clock, so a slow answer used to surface as
107
- `Error: code run failed (timeout): execution deadline reached (120000ms)`. With the bundle
108
- installed that wait no longer burns the budget (default cap 24 h, `-1` = unlimited) while a plain
109
- runaway program is still stopped at the normal budget.
110
-
111
- ### License
41
+ 每行是 `id 状态 "标签" depth=`。`running` 表示正在跑;`inactive` 只表示当前没有回合在执行——**不是子代理没了**,发条消息就能唤醒。
112
42
 
113
- MIT — see [LICENSE](./LICENSE). Issues and source live at
114
- [github.com/SpaceRelay/dsh-subagent-control](https://github.com/SpaceRelay/dsh-subagent-control).
43
+ 团队里的队友本身也是可续子代理,所以也会出现在列表里,标着 `team=teammate`。只想要自己派的普通子代理,传 `include_teammates: false`。
115
44
 
116
- ---
45
+ ## 安装
117
46
 
118
- ## 简体中文
47
+ 1. 打开 设置 → 插件 → 市场,搜索 `dsh-subagent-control`
48
+ 2. 点安装
49
+ 3. **不用重启**——这是纯宿主侧插件,装完三个工具立刻可用
119
50
 
120
- ### 它解决什么问题
51
+ 带界面页的插件才需要完全退出 DSH 再打开,这个不是。
121
52
 
122
- Harness 自带 `list_agents`、`send_message`、`interrupt_agent`。开启 Agent Team 后,团队插件会把**同名的三个工具**注册进每个团队成员的精确作用域,而更具体的作用域优先。于是在成员作用域里生效的是团队版:`target` 只认队友名,打断只有组长能做。
53
+ ## 可选功能(四个,默认关闭)
123
54
 
124
- 结果是:团队成员能用 `subagent` 派出子代理,却列不出、追问不了、也打断不了它。而底层的子代理服务(`ctx.subagents`)本来就支持这三件事,权限规则也允许祖先管理自己的后代。
125
-
126
- 本插件不去抢那三个被占用的名字,而是全局注册三个**新名字**,组长和每个组员立刻都能用。
127
-
128
- ### 工具
129
-
130
- | 工具 | 参数 | 底层调用 |
55
+ | 面板里显示的名字 | 工具 | 作用 |
131
56
  | --- | --- | --- |
132
- | `list_subagents` | `scope?`:`"children"` 或 `"descendants"`,默认 `children` | `ctx.subagents.listChildren()` / `listDescendants()` |
133
- | `send_subagent_message` | `subagent_id`、`message`(均必填) | `ctx.subagents.sendMessage()` |
134
- | `interrupt_subagent` | `subagent_id`(必填) | `ctx.subagents.interrupt()`(祖先权限) |
135
-
136
- ### 用法
137
-
138
- ```
139
- list_subagents
140
- → 3b0f9c1e running "review the patch" depth=1
141
-
142
- list_subagents scope=descendants
143
- → 3b0f9c1e running "review the patch" depth=1
144
- 7d2a44b0 inactive "check the tests" depth=2
145
-
146
- send_subagent_message subagent_id=3b0f9c1e message="顺手看一下 locale/zh.json"
147
- → messageId=...
148
-
149
- interrupt_subagent subagent_id=3b0f9c1e
150
- → accepted=true
151
- ```
152
-
153
- 每行格式是 `id status "label" depth=`。`status` 为 `running` 或 `inactive`——**inactive 表示当前没有在跑,不代表子代理已经消失**;用 `send_subagent_message` 可以把它叫醒。
57
+ | 跨层补话 | `relay_subagent_message` | 给够不着的深层后代发消息:投给第一跳并请它继续往下转 |
58
+ | 等待子代理 | `wait_subagents` | 在当前回合等子代理跑完,而不是先结束回合 |
59
+ | 释放子代理 | `drain_subagents` | 停掉并释放直接子代理,真正把实例腾出来 |
60
+ | 委派预算 | `subagent_budget` | 只读报告:深度上限、各层人数、运行 / 已停数量 |
154
61
 
155
- 团队成员本身也是可续子代理,所以同样会出现在列表里,并带 `team=teammate`(或 `team=lead`)标记;只想看自己派的普通子代理时,传 `include_teammates: false`。
62
+ 在 设置 → 插件 → 已安装 → `dsh-subagent-control` 下面逐个打开,打开一个只注册一个工具。
156
63
 
157
- ### 行为与边界
158
-
159
- - **一次性子代理不会被列出。** 它们无法接收后续消息,列出来只会诱导一次注定失败的调用。
160
- - **记录损坏时报告,而不是抛错。** 某个子代理状态读不出来,会作为诊断条目(`corrupt` / `unsupported` / `unavailable`)返回,而不是让整个列表失败。
161
- - **`send_subagent_message` 只能发给直接子代理。** 这是服务本身的规则,插件没有放宽。
162
- - **`interrupt_subagent` 覆盖所有后代**,所以组长也能打断孙代。
163
- - **任何失败都说明原因**:没有调用者、id 不存在、或者不是你的子代理。
164
- - **不写配置、不落存储。** 除了这三个服务,插件不读写任何东西。
165
-
166
- ### 安装
167
-
168
- 在插件面板 / 市场中安装,或者让智能体执行:
169
-
170
- ```
171
- plugin_manager install_bundle target "dsh-subagent-control@1.0.0"
172
- ```
64
+ ## 相关插件
173
65
 
174
- 从本地目录安装时,把 npm 规格换成**目录路径**。安装即时生效,无需重启;装完后三个工具名可见、插件行为已启用。
66
+ - [dsh-team-limits](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/team-limits) —— 把 Agent Team 的人数、任务数、消息大小改成插件页里能填的数字
67
+ - [dsh-human-wait](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/human-wait) —— PTC 模式下等你回答问题时不烧掉执行预算
68
+ - [dsh-find-session](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/dsh-find-session) —— 会话内 / 跨会话关键词查找
175
69
 
176
- ### 兼容性
70
+ 三个都是单独安装的:它们改的是宿主自带的行或别的插件的行为,不该跟着这个包一起悄悄生效。
177
71
 
178
- - 具备 `tools`、`subagents`、`agents` 三个服务的 DSH(0.2.x 及以上)。
179
- - Node `^22.19.0 || >=24.0.0`。
180
- - **零依赖**:没有运行时依赖、没有 peer 依赖,模块里一行 `import` 都没有。工具是带显式 JSON Schema 的普通定义对象,所以 npm 安装与软链安装行为完全一致。
72
+ ## 常见问题
181
73
 
182
- ### 撞名
74
+ **装完怎么确认能用?** 让智能体调一次 `list_subagents`。这些工具是给智能体用的,界面上不会多出按钮。
183
75
 
184
- `dsh-subagent-library` 也注册了全局的 `list_subagents`。同一个名字的两个全局注册不可能同时生效——二选一安装,或记住其中一个可能被另一个覆盖。
76
+ **为什么只列出一两个?** 默认只列直接子代理。要看整棵树,`scope=descendants`。
185
77
 
186
- 这三个新名字是特意挑的,**不会**和内置的 `list_agents` / `send_message` / `interrupt_agent` 冲突。
78
+ **inactive 的还能用吗?** 能。它只是当前没有回合在跑,发消息会唤醒。
187
79
 
188
- ### 卸载
80
+ **和 `dsh-subagent-library` 冲突吗?** 两者都注册 `list_subagents`,同时装只有一个生效,选一个。
189
81
 
190
- 在插件面板里移除或停用即可,不会留下任何残留。
82
+ ## 隐私与开销
191
83
 
192
- ### 可选组件(各自默认关闭)
84
+ - 只读子代理注册表,不写文件、不联网、没有配置项
85
+ - 零依赖,不引入任何运行时包
193
86
 
194
- 另外四个工具是**四个独立组件**,在插件面板里各有自己的一行和一个开关(中文界面显示:跨层补话 / 等待子代理 / 释放子代理 / 委派预算)。四个都默认关闭,打开哪一个就只注册那一个工具——只开你需要的。
87
+ ## 卸载
195
88
 
196
- | 组件 | 工具 | 作用 | 风险 |
197
- | --- | --- | --- | --- |
198
- | 跨层补话 | `relay_subagent_message` | 把消息投给第一跳并请它继续向下转发 | 中间层可能改写,**不保证送达** |
199
- | 等待子代理 | `wait_subagents` | 等后代结束再收工(受 `timeout_seconds` 限制) | 会阻塞到超时 |
200
- | 释放子代理 | `drain_subagents` | 停止**并释放**直接子级;`interrupt_subagent` 只停当前回合 | 被释放的子级不能再靠消息唤醒 |
201
- | 委派预算 | `subagent_budget` | 只读报告:深度上限、树有多深、运行/空闲数量 | 无 |
89
+ 在插件面板里停用或卸载,不会留下任何残留。
202
90
 
203
- 另有一个独立的同伴包 [`dsh-team-limits`](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/team-limits),用来提高 Agent Team 的成员数、任务数与消息字节上限。**它刻意做成单独安装**:它覆盖的是宿主自带的 `agent-team` 行,这种事不该偷偷发生。
91
+ ## 技术细节
204
92
 
205
- 还有一个独立的同伴包 [`dsh-human-wait`](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/human-wait),用来让 PTC 模式 `run_code` 的执行预算在「等你回答提问 / 审议计划 / 审批」期间暂停。PTC 会把整个程序——**包括嵌套的工具调用与审批等待**——包在一个 120 秒墙钟里,所以回答慢一点就会看到 `Error: code run failed (timeout): execution deadline reached (120000ms)`;装上之后这段等待不再计入预算(默认上限 24 小时,`-1` 表示不限),而普通的死循环程序仍会在原预算处被终止。**同样刻意做成单独安装**:它拦截的是宿主 `ptc-runtime` 的执行预算。
93
+ 实现、与内置工具的边界、四个组件的细节、测试:[docs/implementation.md](https://github.com/SpaceRelay/dsh-subagent-control/blob/main/docs/implementation.md)
206
94
 
207
- ### 许可
95
+ ## 许可
208
96
 
209
- MIT,见 [LICENSE](./LICENSE)。源码与问题反馈:
210
- [github.com/SpaceRelay/dsh-subagent-control](https://github.com/SpaceRelay/dsh-subagent-control)。
97
+ MIT,见 [LICENSE](./LICENSE)。源码与问题反馈:[github.com/SpaceRelay/dsh-subagent-control](https://github.com/SpaceRelay/dsh-subagent-control)。
@@ -0,0 +1,65 @@
1
+ # dsh-subagent-control — implementation notes
2
+
3
+ For maintainers. User-facing docs live in [../README.en.md](../README.en.md).
4
+
5
+ ## Why these three tools exist
6
+
7
+ The Harness ships `list_agents`, `send_message` and `interrupt_agent`. When the Agent Team bundle is active, it registers tools with **those same three names** in every team member's exact Agent scope, and the more specific registration wins. Inside a teammate scope the team versions take over: they resolve `target` against the team roster only, and interrupting is a Lead-only operation.
8
+
9
+ The result: a teammate can start a subagent with `subagent`, but cannot list it, follow up with it, or stop it — even though the subagent service (`ctx.subagents`) has supported all three for any live agent all along, and its authority rules already allow an ancestor to manage its own descendants.
10
+
11
+ This bundle does not fight over the taken names. It registers three **new** names, globally, so the Lead and every teammate get them at once.
12
+
13
+ ## Tools and the calls underneath
14
+
15
+ | Tool | Parameters | Underlying call |
16
+ | --- | --- | --- |
17
+ | `list_subagents` | `scope?`: `children` \| `descendants` (default `children`); `include_teammates?` (default `true`) | `ctx.subagents.listChildren()` / `listDescendants()` |
18
+ | `send_subagent_message` | `subagent_id`, `message` (both required) | `ctx.subagents.sendMessage()` |
19
+ | `interrupt_subagent` | `subagent_id` (required) | `ctx.subagents.interrupt()` with ancestor authority |
20
+
21
+ Each listing line is `id status "label" depth=`; `status` comes from `ctx.agents.get(id)?.status === 'running'`.
22
+
23
+ ## Behaviour and limits
24
+
25
+ - **One-shot subagents are hidden.** They cannot accept a follow-up message, so listing them would only invite a call that is guaranteed to fail.
26
+ - **A broken record is reported, not thrown.** A child whose state cannot be read comes back as a diagnostic entry (`corrupt` / `unsupported` / `unavailable`) instead of turning the whole listing into an error.
27
+ - **`send_subagent_message` reaches direct children only.** That is the service's own rule; the plugin does not widen it.
28
+ - **`interrupt_subagent` reaches descendants**, so a team Lead can also stop a grandchild.
29
+ - **Every failure names its cause**: no calling agent, unknown id, or an id that is not yours.
30
+ - **No config, no storage.** The bundle writes nothing and reads nothing outside the three services.
31
+
32
+ ## Compatibility
33
+
34
+ - DSH with the `tools`, `subagents` and `agents` services (0.2.x and later).
35
+ - Node `^22.19.0 || >=24.0.0`.
36
+ - **Zero dependencies** — no runtime dependency, no peer dependency, not a single `import`. The tools are plain tool-table objects with explicit JSON Schemas, so they install and behave identically from npm or from a linked checkout.
37
+
38
+ ## Name collisions
39
+
40
+ `dsh-subagent-library` also registers a global `list_subagents` tool. Two global registrations of one name cannot both win: install one of them, or remember that the other may shadow this one.
41
+
42
+ The three new names were chosen precisely because they do **not** collide with the built-in `list_agents` / `send_message` / `interrupt_agent`.
43
+
44
+ ## Installing as a developer
45
+
46
+ Through the plugin panel / market, or with `plugin_manager install_bundle`. From a checkout, pass the **directory path** instead of the npm spec. A host-side plugin applies immediately — no restart — and the three tool names are visible right away.
47
+
48
+ ## The four optional components
49
+
50
+ Four extra tools ship as **separate components**, each with its own row and switch in the plugin panel (Cross-layer relay, Wait for subagents, Release subagents, Delegation budget). All four start disabled; turning one on registers exactly one tool.
51
+
52
+ | Component | Tool | What it does | Risk |
53
+ | --- | --- | --- | --- |
54
+ | Cross-layer relay | `relay_subagent_message` | Best-effort message to a deeper descendant: delivered to the first hop with a request to forward it down | intermediate agents may summarize; not guaranteed |
55
+ | Wait for subagents | `wait_subagents` | Wait for descendants (bounded by `timeout_seconds`) instead of ending your turn first | blocks up to the timeout |
56
+ | Release subagents | `drain_subagents` | Stop **and release** direct children, unlike `interrupt_subagent`, which only stops the current turn | a released child is not woken by a message |
57
+ | Delegation budget | `subagent_budget` | Read-only report: depth limit, how deep the tree goes, running/inactive counts | none |
58
+
59
+ ## Tests
60
+
61
+ ```powershell
62
+ npm test # node test/smoke.mjs && node test/smoke-extras.mjs
63
+ ```
64
+
65
+ Coverage: registry shape, projection and rendering, the parameters of the three service calls, the error when there is no calling agent, and that each of the four components mounts alone and registers exactly one tool.
@@ -0,0 +1,67 @@
1
+ # dsh-subagent-control 实现说明
2
+
3
+ 面向维护者。用户向说明见 [../README.md](../README.md)。
4
+
5
+ ## 为什么需要这三个工具
6
+
7
+ Harness 自带 `list_agents`、`send_message`、`interrupt_agent`。开启 Agent Team 后,团队插件会把**同名的三个工具**注册进每个团队成员的精确 Agent 作用域,而更具体的作用域优先。于是在成员作用域里生效的是团队版:`target` 只认队友名,打断只有组长能做。
8
+
9
+ 结果是:团队成员能用 `subagent` 派出子代理,却列不出、追问不了、也打断不了它。而底层的子代理服务(`ctx.subagents`)本来就支持这三件事,权限规则也允许祖先管理自己的后代。
10
+
11
+ 本包不抢名字,而是全局注册三个**新**名字,组长和每个成员同时拿到。
12
+
13
+ ## 工具与底层调用
14
+
15
+ | 工具 | 参数 | 底层调用 |
16
+ | --- | --- | --- |
17
+ | `list_subagents` | `scope?`:`children` \| `descendants`(默认 `children`);`include_teammates?`(默认 `true`) | `ctx.subagents.listChildren()` / `listDescendants()` |
18
+ | `send_subagent_message` | `subagent_id`、`message`(必填) | `ctx.subagents.sendMessage()` |
19
+ | `interrupt_subagent` | `subagent_id`(必填) | `ctx.subagents.interrupt()`,带祖先权限 |
20
+
21
+ 输出行格式 `id 状态 "标签" depth=`;状态来自 `ctx.agents.get(id)?.status === 'running'`。
22
+
23
+ ## 行为与边界
24
+
25
+ - **一次性子代理被隐藏。** 它们无法接受后续消息,列出来只会引诱一次必然失败的调用。
26
+ - **坏记录报告而不抛出。** 状态读不出来的子代理以诊断条目返回(`corrupt` / `unsupported` / `unavailable`),不会让整个列表失败。
27
+ - **`send_subagent_message` 只到直接子级。** 这是服务本身的规则,插件不越过它。
28
+ - **`interrupt_subagent` 能到后代**,所以团队组长也能叫停孙代。
29
+ - **每个失败都写明原因**:没有调用者、未知 id、或者不是你的子代理。
30
+ - **无配置、无存储。** 只读这三个服务,不写任何东西。
31
+
32
+ ## 兼容性
33
+
34
+ - 需要带 `tools`、`subagents`、`agents` 服务的 DSH(0.2.x 及以上)。
35
+ - Node `^22.19.0 || >=24.0.0`。
36
+ - **零依赖**——没有运行时依赖、没有 peer 依赖、一行 `import` 都没有。工具是带显式 JSON Schema 的普通工具表对象,所以从 npm 装和从软链装表现一致。
37
+
38
+ ## 同名冲突
39
+
40
+ `dsh-subagent-library` 也注册全局 `list_subagents`。两个全局同名注册不能同时生效:装其中一个,并记住另一个可能盖住它。
41
+
42
+ 这三个新名字是特意选的,**不**与内置的 `list_agents` / `send_message` / `interrupt_agent` 撞名。
43
+
44
+ ## 开发者安装
45
+
46
+ 通过插件面板 / 市场,或者让智能体执行 `plugin_manager install_bundle`。
47
+
48
+ 从检出目录装时传**目录路径**而不是 npm spec。宿主侧插件装完立即生效,不需要重启;三个工具立刻可见,插件行处于启用状态。
49
+
50
+ ## 四个可选组件
51
+
52
+ 四个额外工具作为**独立组件**发布,各自在插件面板里有单独一行和开关(跨层补话 / 等待子代理 / 释放子代理 / 委派预算)。四个默认都关闭;打开一个只注册一个工具。
53
+
54
+ | 组件 | 工具 | 做什么 | 风险 |
55
+ | --- | --- | --- | --- |
56
+ | 跨层补话 | `relay_subagent_message` | 给更深的后代发消息:投递给第一跳并请求它继续往下转发 | 中间层可能概括内容;不保证送达 |
57
+ | 等待子代理 | `wait_subagents` | 等后代跑完(受 `timeout_seconds` 限制)而不是先结束回合 | 最多阻塞到超时 |
58
+ | 释放子代理 | `drain_subagents` | 停止**并释放**直接子代,不同于 `interrupt_subagent` 只停当前回合 | 被释放的子代不会因消息再被唤醒 |
59
+ | 委派预算 | `subagent_budget` | 只读报告:深度上限、树有多深、运行/已停数量 | 无 |
60
+
61
+ ## 测试
62
+
63
+ ```powershell
64
+ npm test # node test/smoke.mjs && node test/smoke-extras.mjs
65
+ ```
66
+
67
+ 覆盖:注册表形状、投影与渲染、三个服务调用的参数、无调用者时报错,以及四个组件各自单独挂载时只注册一个工具。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-subagent-control",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Three tools — list_subagents, send_subagent_message, interrupt_subagent — that let any agent, including a team member, list, steer and stop the subagents it started.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -35,6 +35,8 @@
35
35
  "locale/*.json",
36
36
  "icon.svg",
37
37
  "README.md",
38
+ "README.en.md",
39
+ "docs",
38
40
  "LICENSE",
39
41
  "CHANGELOG.md"
40
42
  ],
@@ -49,7 +51,8 @@
49
51
  "orchestration"
50
52
  ],
51
53
  "engines": {
52
- "node": "^22.19.0 || >=24.0.0"
54
+ "node": "^22.19.0 || >=24.0.0",
55
+ "dsh": ">=0.2.1-rc.1 <0.3.0-0"
53
56
  },
54
57
  "scripts": {
55
58
  "test": "node test/smoke.mjs && node test/smoke-extras.mjs"