dsh-subagent-control 1.0.6 → 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 +9 -0
- package/README.en.md +97 -0
- package/README.md +47 -168
- package/docs/implementation.en.md +65 -0
- package/docs/implementation.md +67 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
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
|
+
|
|
3
12
|
## 1.0.6
|
|
4
13
|
|
|
5
14
|
- Declares the harness versions this bundle supports: `engines.dsh` is now
|
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
|
-
|
|
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
|
-
|
|
9
|
+
## 什么时候用得上
|
|
18
10
|
|
|
19
|
-
|
|
11
|
+
- 派了几个子代理分头干活,想知道还有谁在跑、跑到哪一步
|
|
12
|
+
- 想给某个正在跑的子代理补一句话
|
|
13
|
+
- 想叫停跑偏的那个,把回合收回来
|
|
14
|
+
- 团队里,组长派出去的孙代子代理也要从上往下管得住
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
## 三个工具
|
|
22
17
|
|
|
23
|
-
|
|
|
18
|
+
| 工具 | 做什么 | 参数 |
|
|
24
19
|
| --- | --- | --- |
|
|
25
|
-
| `list_subagents` | `scope
|
|
26
|
-
| `send_subagent_message` |
|
|
27
|
-
| `interrupt_subagent` |
|
|
20
|
+
| `list_subagents` | 列出自己派出的子代理 | `scope`:`children`(默认,直接子代理)/ `descendants`(整棵子树);`include_teammates`:默认 `true` |
|
|
21
|
+
| `send_subagent_message` | 给一个直接子代理补一句话 | `subagent_id`、`message` |
|
|
22
|
+
| `interrupt_subagent` | 叫停某个子代理当前这一轮 | `subagent_id` |
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
长这样:
|
|
30
25
|
|
|
31
26
|
```
|
|
32
27
|
list_subagents
|
|
@@ -36,183 +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="
|
|
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
|
-
|
|
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
|
-
A sibling UI plugin, [`dsh-find-session`](https://github.com/SpaceRelay/dsh-subagent-control/tree/main/dsh-find-session),
|
|
112
|
-
adds conversation keyword search: `Ctrl+F` searches the conversation you are in, `Ctrl+Shift+F`
|
|
113
|
-
searches every stored session and lists the hits in the right sidebar. It installs separately — it
|
|
114
|
-
is a browser-side panel rather than part of the subagent tooling, and the Host half only reads
|
|
115
|
-
session logs.
|
|
116
|
-
|
|
117
|
-
### License
|
|
41
|
+
每行是 `id 状态 "标签" depth=`。`running` 表示正在跑;`inactive` 只表示当前没有回合在执行——**不是子代理没了**,发条消息就能唤醒。
|
|
118
42
|
|
|
119
|
-
|
|
120
|
-
[github.com/SpaceRelay/dsh-subagent-control](https://github.com/SpaceRelay/dsh-subagent-control).
|
|
43
|
+
团队里的队友本身也是可续子代理,所以也会出现在列表里,标着 `team=teammate`。只想要自己派的普通子代理,传 `include_teammates: false`。
|
|
121
44
|
|
|
122
|
-
|
|
45
|
+
## 安装
|
|
123
46
|
|
|
124
|
-
|
|
47
|
+
1. 打开 设置 → 插件 → 市场,搜索 `dsh-subagent-control`
|
|
48
|
+
2. 点安装
|
|
49
|
+
3. **不用重启**——这是纯宿主侧插件,装完三个工具立刻可用
|
|
125
50
|
|
|
126
|
-
|
|
51
|
+
带界面页的插件才需要完全退出 DSH 再打开,这个不是。
|
|
127
52
|
|
|
128
|
-
|
|
53
|
+
## 可选功能(四个,默认关闭)
|
|
129
54
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
本插件不去抢那三个被占用的名字,而是全局注册三个**新名字**,组长和每个组员立刻都能用。
|
|
133
|
-
|
|
134
|
-
### 工具
|
|
135
|
-
|
|
136
|
-
| 工具 | 参数 | 底层调用 |
|
|
55
|
+
| 面板里显示的名字 | 工具 | 作用 |
|
|
137
56
|
| --- | --- | --- |
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
142
|
-
### 用法
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
list_subagents
|
|
146
|
-
→ 3b0f9c1e running "review the patch" depth=1
|
|
57
|
+
| 跨层补话 | `relay_subagent_message` | 给够不着的深层后代发消息:投给第一跳并请它继续往下转 |
|
|
58
|
+
| 等待子代理 | `wait_subagents` | 在当前回合等子代理跑完,而不是先结束回合 |
|
|
59
|
+
| 释放子代理 | `drain_subagents` | 停掉并释放直接子代理,真正把实例腾出来 |
|
|
60
|
+
| 委派预算 | `subagent_budget` | 只读报告:深度上限、各层人数、运行 / 已停数量 |
|
|
147
61
|
|
|
148
|
-
|
|
149
|
-
→ 3b0f9c1e running "review the patch" depth=1
|
|
150
|
-
7d2a44b0 inactive "check the tests" depth=2
|
|
151
|
-
|
|
152
|
-
send_subagent_message subagent_id=3b0f9c1e message="顺手看一下 locale/zh.json"
|
|
153
|
-
→ messageId=...
|
|
154
|
-
|
|
155
|
-
interrupt_subagent subagent_id=3b0f9c1e
|
|
156
|
-
→ accepted=true
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
每行格式是 `id status "label" depth=`。`status` 为 `running` 或 `inactive`——**inactive 表示当前没有在跑,不代表子代理已经消失**;用 `send_subagent_message` 可以把它叫醒。
|
|
160
|
-
|
|
161
|
-
团队成员本身也是可续子代理,所以同样会出现在列表里,并带 `team=teammate`(或 `team=lead`)标记;只想看自己派的普通子代理时,传 `include_teammates: false`。
|
|
162
|
-
|
|
163
|
-
### 行为与边界
|
|
164
|
-
|
|
165
|
-
- **一次性子代理不会被列出。** 它们无法接收后续消息,列出来只会诱导一次注定失败的调用。
|
|
166
|
-
- **记录损坏时报告,而不是抛错。** 某个子代理状态读不出来,会作为诊断条目(`corrupt` / `unsupported` / `unavailable`)返回,而不是让整个列表失败。
|
|
167
|
-
- **`send_subagent_message` 只能发给直接子代理。** 这是服务本身的规则,插件没有放宽。
|
|
168
|
-
- **`interrupt_subagent` 覆盖所有后代**,所以组长也能打断孙代。
|
|
169
|
-
- **任何失败都说明原因**:没有调用者、id 不存在、或者不是你的子代理。
|
|
170
|
-
- **不写配置、不落存储。** 除了这三个服务,插件不读写任何东西。
|
|
171
|
-
|
|
172
|
-
### 安装
|
|
173
|
-
|
|
174
|
-
在插件面板 / 市场中安装,或者让智能体执行:
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
plugin_manager install_bundle target "dsh-subagent-control@1.0.0"
|
|
178
|
-
```
|
|
62
|
+
在 设置 → 插件 → 已安装 → `dsh-subagent-control` 下面逐个打开,打开一个只注册一个工具。
|
|
179
63
|
|
|
180
|
-
|
|
64
|
+
## 相关插件
|
|
181
65
|
|
|
182
|
-
|
|
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) —— 会话内 / 跨会话关键词查找
|
|
183
69
|
|
|
184
|
-
|
|
185
|
-
- Node `^22.19.0 || >=24.0.0`。
|
|
186
|
-
- **零依赖**:没有运行时依赖、没有 peer 依赖,模块里一行 `import` 都没有。工具是带显式 JSON Schema 的普通定义对象,所以 npm 安装与软链安装行为完全一致。
|
|
70
|
+
三个都是单独安装的:它们改的是宿主自带的行或别的插件的行为,不该跟着这个包一起悄悄生效。
|
|
187
71
|
|
|
188
|
-
|
|
72
|
+
## 常见问题
|
|
189
73
|
|
|
190
|
-
|
|
74
|
+
**装完怎么确认能用?** 让智能体调一次 `list_subagents`。这些工具是给智能体用的,界面上不会多出按钮。
|
|
191
75
|
|
|
192
|
-
|
|
76
|
+
**为什么只列出一两个?** 默认只列直接子代理。要看整棵树,`scope=descendants`。
|
|
193
77
|
|
|
194
|
-
|
|
78
|
+
**inactive 的还能用吗?** 能。它只是当前没有回合在跑,发消息会唤醒。
|
|
195
79
|
|
|
196
|
-
|
|
80
|
+
**和 `dsh-subagent-library` 冲突吗?** 两者都注册 `list_subagents`,同时装只有一个生效,选一个。
|
|
197
81
|
|
|
198
|
-
|
|
82
|
+
## 隐私与开销
|
|
199
83
|
|
|
200
|
-
|
|
84
|
+
- 只读子代理注册表,不写文件、不联网、没有配置项
|
|
85
|
+
- 零依赖,不引入任何运行时包
|
|
201
86
|
|
|
202
|
-
|
|
203
|
-
| --- | --- | --- | --- |
|
|
204
|
-
| 跨层补话 | `relay_subagent_message` | 把消息投给第一跳并请它继续向下转发 | 中间层可能改写,**不保证送达** |
|
|
205
|
-
| 等待子代理 | `wait_subagents` | 等后代结束再收工(受 `timeout_seconds` 限制) | 会阻塞到超时 |
|
|
206
|
-
| 释放子代理 | `drain_subagents` | 停止**并释放**直接子级;`interrupt_subagent` 只停当前回合 | 被释放的子级不能再靠消息唤醒 |
|
|
207
|
-
| 委派预算 | `subagent_budget` | 只读报告:深度上限、树有多深、运行/空闲数量 | 无 |
|
|
87
|
+
## 卸载
|
|
208
88
|
|
|
209
|
-
|
|
89
|
+
在插件面板里停用或卸载,不会留下任何残留。
|
|
210
90
|
|
|
211
|
-
|
|
91
|
+
## 技术细节
|
|
212
92
|
|
|
213
|
-
|
|
93
|
+
实现、与内置工具的边界、四个组件的细节、测试:[docs/implementation.md](https://github.com/SpaceRelay/dsh-subagent-control/blob/main/docs/implementation.md)
|
|
214
94
|
|
|
215
|
-
|
|
95
|
+
## 许可
|
|
216
96
|
|
|
217
|
-
MIT,见 [LICENSE](./LICENSE)。源码与问题反馈:
|
|
218
|
-
[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.
|
|
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
|
],
|