@nanmicoder/dsh-agent-teams 0.1.16-rc.1 → 0.1.17-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -58
- package/README_ZH.md +22 -57
- package/compatibility.json +17 -4
- package/lib/capabilities.js +106 -0
- package/lib/client/ActivityPanel.js +4 -4
- package/lib/client/index.js +9 -3
- package/lib/client/session-navigation.js +8 -2
- package/lib/client.js +24 -14
- package/lib/client.js.map +1 -1
- package/lib/command.js +3 -3
- package/lib/harness-compat.js +24 -4
- package/lib/index.js +40 -36
- package/lib/members.js +9 -13
- package/lib/profiles.js +1 -1
- package/lib/state.js +34 -6
- package/lib/tool-names.js +11 -0
- package/lib/tools.js +16 -3
- package/lib/types/capabilities.d.ts +14 -0
- package/lib/types/client/ActivityPanel.d.ts +2 -1
- package/lib/types/client/session-navigation.d.ts +8 -2
- package/lib/types/harness-compat.d.ts +4 -3
- package/lib/types/index.d.ts +3 -1
- package/lib/types/members.d.ts +2 -0
- package/lib/types/state.d.ts +7 -1
- package/lib/types/tool-names.d.ts +4 -0
- package/lib/types/tools.d.ts +3 -0
- package/package.json +52 -49
- package/release-notes/v0.1.16-rc.2.md +33 -0
- package/release-notes/v0.1.16-rc.3.md +33 -0
- package/release-notes/v0.1.17-rc.1.md +20 -0
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
`dsh-agent-teams` turns the current DeepSeek Harness session into a captain that can assemble durable sub-agents, split a goal into dependency-aware tasks, and coordinate work through direct messages.
|
|
24
24
|
|
|
25
|
-
Ask in natural language. The plugin provides the team protocol,
|
|
25
|
+
Ask in natural language. The plugin provides the team protocol, 13 coordination tools, persistent state, an automatic shared-task scheduler, and a live Web UI—without requiring a separate workflow engine.
|
|
26
26
|
|
|
27
27
|
<p align="center">
|
|
28
28
|
<img src="./assets/ui.png" width="100%" alt="DeepSeek Harness conversation with the AgentTeams live activity panel, members, tasks, dependencies, and reports">
|
|
@@ -30,7 +30,7 @@ Ask in natural language. The plugin provides the team protocol, eleven coordinat
|
|
|
30
30
|
|
|
31
31
|
## Releases
|
|
32
32
|
|
|
33
|
-
[v0.1.
|
|
33
|
+
[v0.1.17-rc.1](./release-notes/v0.1.17-rc.1.md) supports DeepSeek Harness `0.1.5-rc.1` on the npm `next` channel. It adapts subagent delivery, explicit member initialization, and Web panel navigation while retaining three older host targets.
|
|
34
34
|
|
|
35
35
|
## Why AgentTeams?
|
|
36
36
|
|
|
@@ -49,77 +49,39 @@ The conversation card and activity panel use Harness's official locale service.
|
|
|
49
49
|
|
|
50
50
|
## Install and choose versions
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
> **0.1.16-rc.1 is a prerelease on the `next` track.** Use the exact version below for the supported 0.1.2 hosts. Plugin 0.1.15 targets Alpha.2; do not use a mutable `latest` tag as a compatibility guarantee. Check the actual running host and profile before updating either side.
|
|
52
|
+
**Recommended pair: DeepSeek Harness `0.1.5-rc.1` + AgentTeams `0.1.17-rc.1`. Both are prereleases.**
|
|
54
53
|
|
|
55
|
-
|
|
|
54
|
+
| Use case | DeepSeek Harness | AgentTeams plugin |
|
|
56
55
|
| --- | --- | --- |
|
|
57
|
-
| **0.1.
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
56
|
+
| **Recommended installation** | **`0.1.5-rc.1`** | **`0.1.17-rc.1`** |
|
|
57
|
+
| Retaining an older RC | `0.1.2-rc.1` | `0.1.17-rc.1` |
|
|
58
|
+
| Developer Alpha testing | `0.1.2-alpha.5` | `0.1.17-rc.1` |
|
|
59
|
+
| Retaining an older Alpha | `0.1.2-alpha.2` | `0.1.17-rc.1` |
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
### Ordinary users: keep a matching host and plugin
|
|
65
|
-
|
|
66
|
-
The recommended host installation target is:
|
|
61
|
+
### 1. Install DeepSeek Harness
|
|
67
62
|
|
|
68
63
|
```sh
|
|
69
|
-
npm install --global @deepseek-ai/dsh@0.1.
|
|
64
|
+
npm install --global @deepseek-ai/dsh@0.1.5-rc.1
|
|
70
65
|
dsh --version
|
|
71
66
|
```
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```sh
|
|
76
|
-
dsh plugin --profile web add --save-exact @nanmicoder/dsh-agent-teams@0.1.16-rc.1
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Restart the actual Harness process after changing either side and refresh the browser. Updating a global CLI does not replace an embedded Desktop core or another source checkout. For an unpublished checkout, use the source build below.
|
|
80
|
-
|
|
81
|
-
An exact npm CLI version can still contain broad transitive dependencies. Preserve a verified lockfile and inspect the actual installation. Do not delete credentials or `.agent-teams` data to address a version mismatch.
|
|
82
|
-
|
|
83
|
-
### Build and verify this candidate
|
|
68
|
+
Skip this if you already run this version. Alpha is opt-in: select an exact Alpha version from the table and lock all host dependencies as described in the [maintenance guide](./docs/maintenance-workflow.md).
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```sh
|
|
88
|
-
pnpm install --frozen-lockfile
|
|
89
|
-
pnpm typecheck
|
|
90
|
-
pnpm build
|
|
91
|
-
pnpm verify
|
|
92
|
-
pnpm pack --out ./agent-teams-candidate.tgz
|
|
93
|
-
```
|
|
70
|
+
### 2. Install the AgentTeams plugin
|
|
94
71
|
|
|
95
|
-
|
|
72
|
+
Install into the `web` profile. Replace the profile name if needed:
|
|
96
73
|
|
|
97
74
|
```sh
|
|
98
|
-
|
|
99
|
-
dsh plugin --profile agent-teams-preview add --save-exact /absolute/path/agent-teams-candidate.tgz
|
|
100
|
-
node scripts/doctor.mjs --host-root "/actual/host/package/directory" --profile-root "/actual/test/profile/directory" --json
|
|
101
|
-
dsh --profile agent-teams-preview --dump-config
|
|
102
|
-
dsh web --profile agent-teams-preview
|
|
75
|
+
dsh plugin --profile web add --save-exact @nanmicoder/dsh-agent-teams@0.1.17-rc.1
|
|
103
76
|
```
|
|
104
77
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
### Developers: explicitly test Alpha
|
|
108
|
-
|
|
109
|
-
Choose an exact Alpha version; `^0.1.2-alpha.2` does not mean “Alpha.2 only.” Development uses exact rc.1 packages, cohort-wide `pnpm.overrides` and a frozen lockfile. The runtime runner creates separate dependency cohorts, profiles and workspaces for Alpha.2, Alpha.5 and rc.1, installs the same candidate tgz, and checks actual resolution.
|
|
78
|
+
**After installation, stop and restart Harness for that profile, then refresh the browser.**
|
|
110
79
|
|
|
111
|
-
|
|
112
|
-
node scripts/harness-runtime-verify.mjs \
|
|
113
|
-
--host-version 0.1.2-alpha.2 \
|
|
114
|
-
--artifact ./agent-teams-candidate.tgz \
|
|
115
|
-
--report-dir /tmp/agent-teams-alpha2-check
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
This developer command downloads the host into temporary directories without modifying existing user profiles. It uses deterministic model responses with the real CLI, plugin, sessions, tools and subagents. See the [maintenance workflow](./docs/maintenance-workflow.md) for coverage and release requirements.
|
|
80
|
+
Plugin prereleases use npm `next`; use the exact-version command above. `latest` is not the recommended entry for this host pair. See the [source installation guide](./docs/maintenance-workflow.md) and [release verification](./docs/releases/v0.1.17-rc.1/README.md).
|
|
119
81
|
|
|
120
|
-
|
|
82
|
+
> Desktop users must check the app's embedded Harness core; upgrading the global CLI does not upgrade it. For older `0.1.0-*` / `0.1.1-*` or unlisted hosts, keep a working pair and follow the [older-version and diagnostic guide](./docs/maintenance-workflow.md).
|
|
121
83
|
|
|
122
|
-
|
|
84
|
+
See the full [compatibility matrix](./compatibility.json), [source installation and Alpha testing guide](./docs/maintenance-workflow.md), and [verification coverage and platform limits](./docs/maintenance-2026-09-06/release/README.md).
|
|
123
85
|
|
|
124
86
|
Then ask for a team directly:
|
|
125
87
|
|
|
@@ -127,7 +89,7 @@ Then ask for a team directly:
|
|
|
127
89
|
|
|
128
90
|
## How it works
|
|
129
91
|
|
|
130
|
-
1.
|
|
92
|
+
1. For a request to use AgentTeams, the captain follows the core protocol already in its system instructions. It continues an existing team and uses `agent_teams_status` when current state needs checking. When no team exists, the goal becomes a staged plan for review.
|
|
131
93
|
2. The captain adds role-specific members backed by continuable sub-agents.
|
|
132
94
|
3. The goal becomes tasks with owners and explicit dependencies.
|
|
133
95
|
4. The shared scheduler uses real `running / idle / ready` state to atomically claim one ready task per idle member and wake it. An interrupted resident attempt stays parked and can resume through a direct message without losing its capability; after a cold process restart, the scheduler retries stranded open work with a fresh attempt.
|
|
@@ -138,6 +100,8 @@ Team state is stored under `<workspace>/.agent-teams/`; the Web panel reads that
|
|
|
138
100
|
|
|
139
101
|
Member creation is zero-interaction by default: a member on the captain's current LLM route snapshots that provider, model, and reasoning effort, while a member on a requested alternative route snapshots the target model's default effort; later continuations restore the resolved snapshot. Only an explicit heterogeneous-team request (for example, “backend on provider A/model X, frontend on provider B/model Y”) supplies a member-specific `provider` + `model`; there is no per-member model or reasoning prompt.
|
|
140
102
|
|
|
103
|
+
Captain sessions keep the concise core protocol and the original 13 native team tools from their first request. All business tools are directly available; no loading tool or extra activation call is needed. Configured profiles retain their bounded directory in the fixed system prompt. Creating, approving, continuing or ending a team does not rewrite the system prompt or tool schemas. Core rules remain available after history compaction or discarded code-mode tool results. Members receive four team tools, fixed member instructions, and their ordinary coding/research tools. Web approval wakes the captain with a control message; later member reports wake it again. See the [fixed protocol and benchmark contract](./docs/progressive-loading.md).
|
|
104
|
+
|
|
141
105
|
## Slash command
|
|
142
106
|
|
|
143
107
|
No “use AgentTeams” phrasing required. The plugin registers the
|
|
@@ -152,7 +116,7 @@ command), describe the goal, and press Enter.
|
|
|
152
116
|
The command pipeline claims the line, then preserves that exact input as an
|
|
153
117
|
ordinary user follow-up so it remains visible in the main chat. The gesture
|
|
154
118
|
boundary adds the deterministic activation directive at pre-step, so the
|
|
155
|
-
|
|
119
|
+
first model request follows the staged planning protocol without a mandatory helper call. The invocation is also durably
|
|
156
120
|
logged (`command/run` / `command/done`).
|
|
157
121
|
|
|
158
122
|
Surfaces without command adjudication (for example the headless CLI) get the
|
|
@@ -160,6 +124,8 @@ same deterministic activation through a gesture boundary: any genuine user
|
|
|
160
124
|
message starting with `/agent-teams` activates the protocol for the rest of
|
|
161
125
|
the text. Mid-sentence mentions stay ordinary prose.
|
|
162
126
|
|
|
127
|
+
Historical panels require saved team state or archives. Sessions from early versions that deleted teams without retaining archives do not yet support reconstructing the full panel from logs.
|
|
128
|
+
|
|
163
129
|
## Configuration
|
|
164
130
|
|
|
165
131
|
Defaults work without extra setup. A trusted profile can override member behavior:
|
package/README_ZH.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
`dsh-agent-teams` 让当前 DeepSeek Harness 会话成为队长:创建可续聊的子 Agent、把目标拆成有依赖的任务,并通过直达消息协调成员工作。
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
你只需用自然语言提出目标。插件会提供精简的固定团队协议、13 个业务工具、持久化状态、自动共享任务调度和实时 Web UI,不需要额外的 Workflow 引擎。
|
|
26
26
|
|
|
27
27
|
<p align="center">
|
|
28
28
|
<img src="./assets/ui.png" width="100%" alt="DeepSeek Harness 对话与 AgentTeams 实时活动面板,展示成员、任务依赖和回报">
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
## 版本更新
|
|
32
32
|
|
|
33
|
-
[v0.1.
|
|
33
|
+
[v0.1.17-rc.1](./release-notes/v0.1.17-rc.1.md) 适配 DeepSeek Harness `0.1.5-rc.1`,发布到 npm `next` 渠道。新增子代理投递、成员初始化和 Web 面板导航适配,保留三个旧宿主目标。
|
|
34
34
|
|
|
35
35
|
## 为什么需要 AgentTeams?
|
|
36
36
|
|
|
@@ -48,82 +48,46 @@
|
|
|
48
48
|
|
|
49
49
|
## 安装与版本选择
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
> **0.1.16-rc.1 是 `next` 渠道的预发布版本。** 对当前支持的 0.1.2 宿主,请使用下方精确插件版本。0.1.15 面向 Alpha.2,不能把可变的 `latest` 标签当作兼容保证。请先核对实际运行的宿主和 profile,再更新两端。
|
|
51
|
+
**推荐组合:DeepSeek Harness `0.1.5-rc.1` + AgentTeams `0.1.17-rc.1`。两者均为预发布版本。**
|
|
53
52
|
|
|
54
|
-
|
|
|
53
|
+
| 使用场景 | DeepSeek Harness | AgentTeams 插件 |
|
|
55
54
|
| --- | --- | --- |
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
55
|
+
| **推荐安装** | **`0.1.5-rc.1`** | **`0.1.17-rc.1`** |
|
|
56
|
+
| 保留旧 RC | `0.1.2-rc.1` | `0.1.17-rc.1` |
|
|
57
|
+
| 开发者测试 Alpha | `0.1.2-alpha.5` | `0.1.17-rc.1` |
|
|
58
|
+
| 保留旧 Alpha | `0.1.2-alpha.2` | `0.1.17-rc.1` |
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
### 普通用户:固定匹配的宿主与插件
|
|
64
|
-
|
|
65
|
-
推荐宿主安装目标为:
|
|
60
|
+
### 1. 安装 DeepSeek Harness
|
|
66
61
|
|
|
67
62
|
```sh
|
|
68
|
-
npm install --global @deepseek-ai/dsh@0.1.
|
|
63
|
+
npm install --global @deepseek-ai/dsh@0.1.5-rc.1
|
|
69
64
|
dsh --version
|
|
70
65
|
```
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```sh
|
|
75
|
-
dsh plugin --profile web add --save-exact @nanmicoder/dsh-agent-teams@0.1.16-rc.1
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
宿主或插件更新后,停止并重启实际运行的 Harness,再刷新浏览器。全局 CLI 升级不会更换 Desktop 内置核心,也不会更新另一个源码工作区。尚未发布的 checkout 可使用下方源码构建方式。
|
|
79
|
-
|
|
80
|
-
npm 的精确 CLI 版本仍可能包含宽范围间接依赖。升级时保留已验证的锁文件,对实际安装路径运行诊断;不要通过删除凭据或 `.agent-teams` 来处理版本错配。
|
|
67
|
+
已有该版本可跳过。Alpha 仅供主动测试:手动指定表中的 Alpha 版本,并按[维护指南](./docs/maintenance-workflow.md)锁定整组宿主依赖。
|
|
81
68
|
|
|
82
|
-
###
|
|
69
|
+
### 2. 安装 AgentTeams 插件
|
|
83
70
|
|
|
84
|
-
|
|
71
|
+
安装到 `web` profile;使用其他 profile 时替换名称:
|
|
85
72
|
|
|
86
73
|
```sh
|
|
87
|
-
|
|
88
|
-
pnpm typecheck
|
|
89
|
-
pnpm build
|
|
90
|
-
pnpm verify
|
|
91
|
-
pnpm pack --out ./agent-teams-candidate.tgz
|
|
74
|
+
dsh plugin --profile web add --save-exact @nanmicoder/dsh-agent-teams@0.1.17-rc.1
|
|
92
75
|
```
|
|
93
76
|
|
|
94
|
-
|
|
77
|
+
**安装后,停止并重新启动该 profile 的 Harness 进程,再刷新浏览器。**
|
|
95
78
|
|
|
96
|
-
|
|
97
|
-
node scripts/doctor.mjs --host-root "/实际运行的宿主包目录" --json
|
|
98
|
-
dsh plugin --profile agent-teams-preview add --save-exact /完整路径/agent-teams-candidate.tgz
|
|
99
|
-
node scripts/doctor.mjs --host-root "/实际运行的宿主包目录" --profile-root "/实际测试profile目录" --json
|
|
100
|
-
dsh --profile agent-teams-preview --dump-config
|
|
101
|
-
dsh web --profile agent-teams-preview
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
`doctor` 检查整组 DSH 包版本、重复运行时身份以及 profile 中的插件版本。它只读文件,不读取凭据、不修改配置;检查通过不替代实际建队、任务执行和 UI 验收。源码更改后需要重新构建、打包和重启。
|
|
105
|
-
|
|
106
|
-
### 开发者:显式测试 Alpha
|
|
79
|
+
插件预发布使用 npm `next`,请使用上面的精确版本命令;`latest` 不是这组宿主的推荐安装入口。源码安装见[维护指南](./docs/maintenance-workflow.md),验证范围见[本版验收记录](./docs/releases/v0.1.17-rc.1/README.md)。
|
|
107
80
|
|
|
108
|
-
|
|
81
|
+
> Desktop 用户需核对应用内置的 Harness 核心;全局 CLI 升级不会升级桌面内核。旧 `0.1.0-*` / `0.1.1-*` 或其他未列出的宿主,请先保留已工作的组合,参考[旧版本与诊断指引](./docs/maintenance-workflow.md)。
|
|
109
82
|
|
|
110
|
-
|
|
111
|
-
node scripts/harness-runtime-verify.mjs \
|
|
112
|
-
--host-version 0.1.2-alpha.2 \
|
|
113
|
-
--artifact ./agent-teams-candidate.tgz \
|
|
114
|
-
--report-dir /tmp/agent-teams-alpha2-check
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
这是会创建临时目录并下载宿主的开发验收命令,不会修改已有用户 profile。模型适配器使用固定测试响应;CLI、插件、会话、工具与子代理使用真实宿主实现。完整范围和发布流程见[维护流程](./docs/maintenance-workflow.md)。
|
|
118
|
-
|
|
119
|
-
### 保留旧宿主 / 回退
|
|
120
|
-
|
|
121
|
-
对于历史组合 Harness `0.1.0-rc.8` + 插件 `0.1.14`,应固定两端版本;不能据此推断所有旧 RC 都兼容。已使用其他已验证旧组合的用户先保留该组合。历史 [Alpha.2 兼容记录](./docs/alpha2-compatibility.md)和[验收报告](./docs/alpha2-release-acceptance.md)只描述当时版本,不覆盖当前清单。
|
|
83
|
+
完整[兼容清单](./compatibility.json)、[源码安装与 Alpha 验证](./docs/maintenance-workflow.md)、[已验证范围与平台限制](./docs/maintenance-2026-09-06/release/README.md)。
|
|
122
84
|
|
|
123
85
|
接着直接用自然语言拉团队:
|
|
124
86
|
|
|
125
87
|
> 使用 AgentTeams 审查 v0.5.3 之后的提交,分别从性能、安全和产品角度分工,最后输出一份汇总报告。
|
|
126
88
|
|
|
89
|
+
队长会话从第一轮起保留精简的固定核心协议和原有 13 个业务工具,直接调用,无需额外的加载工具或激活调用。已配置模板的精简目录固定保留。创建、批准、继续或结束团队都不会改写系统提示词和工具 schema,会话压缩或代码模式丢弃工具结果也不会丢失核心规则。成员保留四个团队工具、固定成员说明及普通编程/研究工具。Web 批准后会通知并唤醒队长,后续成员报告会再次唤醒它,无需忙轮询。详见[固定协议与 benchmark 标准](./docs/progressive-loading.md)。
|
|
90
|
+
|
|
127
91
|
## 工作方式
|
|
128
92
|
|
|
129
93
|
1. 当前会话创建团队并成为队长。
|
|
@@ -172,6 +136,7 @@ node scripts/harness-runtime-verify.mjs \
|
|
|
172
136
|
- 一个队长同一时间只能带一个活动团队。
|
|
173
137
|
- 没有开放任务的空闲成员会自动续领就绪任务;仍持有开放 attempt 的空闲成员会停驻,队长可发消息让其沿用原 attempt 继续,或显式转派;冷重启遗留的开放任务才会生成新 attempt。暂时无法实时投递的消息会持久保存在邮箱中并在后续状态边界重投。
|
|
174
138
|
- 状态使用文件持久化,并在单个 DSH 进程内串行操作;多个进程同时修改同一团队不保证一致。
|
|
139
|
+
- 历史面板依赖保存的团队状态或归档;早期版本删除团队时未保留归档的会话,暂不支持从日志重建完整面板。
|
|
175
140
|
- 活动面板如实展示持久化状态;模型偶尔可能完成工作却没有按协议更新任务状态。
|
|
176
141
|
|
|
177
142
|
完整工具列表、状态模型、Web UI 行为、配置与已知限制见 [docs/usage.md](./docs/usage.md)。
|
|
@@ -207,7 +172,7 @@ pnpm verify
|
|
|
207
172
|
|
|
208
173
|
在 `cordis.patch.yml` 的 `profiles` 中配置完整团队模板。每个 profile 都提供成员阵容,可独立指定 provider、model、role、reasoning_effort。`taskPlanning: captain` 表示只提供阵容和约束,由 Captain 根据用户目标设计 DAG;省略该字段或设为 `seed` 时,展开模板中的固定任务图。使用 `/agent-teams --profile <名称> <目标>` 显式激活;不会把首个普通 token 隐式识别为 profile。
|
|
209
174
|
|
|
210
|
-
普通 `/agent-teams`
|
|
175
|
+
普通 `/agent-teams` 流程继续已有团队,按需调用 `agent_teams_status` 确认状态;仅在没有当前团队时调用 `agent_teams_create({ profile, approval: "required" })`:只落盘可编辑的成员占位和 DAG,不创建子会话、不领取任务。成员模型和推理等级直接读取 Harness 的模型目录。「返回对话修改」会终止仍在运行的规划轮次,让队长先追问修改方向,再用一次原子操作更新同一份草案;「放弃本次计划」经二次确认后会归档草案、中止轮次,并向模型注入不得自动重建团队的控制上下文。只有点击「确认并启动团队」才会按最终配置原子创建成员并启动就绪任务。运行中团队的停止入口位于该团队的面板标题,点击后需要二次确认,不再占用输入区域。直接工具调用方可显式传 `approval: "automatic"` 保留旧的立即执行路径。审查或测试失败不会解锁下游;自动 repair/review 不依赖 failed review。
|
|
211
176
|
|
|
212
177
|
## 许可证
|
|
213
178
|
|
package/compatibility.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"recommendedHost": "0.1.
|
|
3
|
+
"recommendedHost": "0.1.5-rc.1",
|
|
4
4
|
"previewTag": "next",
|
|
5
5
|
"supportedHosts": [
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
{
|
|
7
|
+
"version": "0.1.5-rc.1",
|
|
8
|
+
"track": "recommended"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.2-rc.1",
|
|
12
|
+
"track": "legacy"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.1.2-alpha.5",
|
|
16
|
+
"track": "preview"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"version": "0.1.2-alpha.2",
|
|
20
|
+
"track": "legacy"
|
|
21
|
+
}
|
|
9
22
|
]
|
|
10
23
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readTeamSync, readRetiredMemberIdsSync } from "./state.js";
|
|
4
|
+
import { MEMBER_TOOL_NAMES, TEAM_TOOL_NAMES } from "./tool-names.js";
|
|
5
|
+
export const TEAM_ACTIVATION_PROMPT = 'AgentTeams (Agent Teams) provides multi-agent team collaboration. Apply these rules when the user requests it (including /agent-teams) or when continuing an existing team. Mentioning, quoting, discussing, or declining AgentTeams alone is not a request to start work.';
|
|
6
|
+
export const TEAM_MEMBER_PROMPT = 'You are an AgentTeams member. Follow your assigned member persona and task contract. Use agent_teams_claim_task, agent_teams_update_task, agent_teams_send_message and agent_teams_status for your own work. Include the current attempt_id in updates; report completion or failure to the captain. Do not create, approve, edit or resume a team. If your durable membership is unavailable, report that to the parent instead of creating a replacement.';
|
|
7
|
+
function stateRoot(agent, config) {
|
|
8
|
+
return join(agent.session.header.cwd ?? process.cwd(), config.stateDir);
|
|
9
|
+
}
|
|
10
|
+
/** Synchronous startup/HMR hydration must finish before the first assembly. */
|
|
11
|
+
function currentTeam(agent, config) {
|
|
12
|
+
const root = stateRoot(agent, config);
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error.code === 'ENOENT')
|
|
19
|
+
return undefined;
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
let found;
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (!entry.isDirectory() || entry.name === 'archive')
|
|
25
|
+
continue;
|
|
26
|
+
const team = readTeamSync(root, entry.name);
|
|
27
|
+
if (team === undefined || (team.captainSessionId !== agent.id
|
|
28
|
+
&& !team.members.some(member => member.id === agent.id)))
|
|
29
|
+
continue;
|
|
30
|
+
if (found !== undefined)
|
|
31
|
+
throw new Error('ambiguous AgentTeams membership');
|
|
32
|
+
found = team;
|
|
33
|
+
}
|
|
34
|
+
return found;
|
|
35
|
+
}
|
|
36
|
+
/** Call once, after all business definitions have registered. Never per member. */
|
|
37
|
+
export function installTeamCapabilities(ctx, config) {
|
|
38
|
+
const states = new WeakMap();
|
|
39
|
+
const active = new Set();
|
|
40
|
+
let mounted = true;
|
|
41
|
+
// Snapshot policy once: profiles, team state, and tool results must never
|
|
42
|
+
// rewrite this prefix or control whether core instructions are available.
|
|
43
|
+
const captainPrompt = `${TEAM_ACTIVATION_PROMPT}\n\n${config.captainPrompt()}`;
|
|
44
|
+
function attach(agent) {
|
|
45
|
+
const prior = states.get(agent);
|
|
46
|
+
if (prior !== undefined)
|
|
47
|
+
return prior;
|
|
48
|
+
if (!mounted)
|
|
49
|
+
throw new Error('AgentTeams capability provider is disposed');
|
|
50
|
+
// Determine a member's role before its first request and retain it for the
|
|
51
|
+
// lifetime of this scope. Team creation/archive must never rewrite the
|
|
52
|
+
// captain's system/tools prefix, even after a long ordinary conversation.
|
|
53
|
+
let member = config.isPendingMember(agent);
|
|
54
|
+
try {
|
|
55
|
+
member ||= readRetiredMemberIdsSync(stateRoot(agent, config)).has(agent.id);
|
|
56
|
+
const team = currentTeam(agent, config);
|
|
57
|
+
member ||= team !== undefined && team.captainSessionId !== agent.id;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// Unrelated damaged state must not disable ordinary conversation.
|
|
61
|
+
// Business tools still validate durable team state before acting.
|
|
62
|
+
ctx.logger.warn(`agent-teams: capability hydration failed: ${String(error)}`);
|
|
63
|
+
}
|
|
64
|
+
const state = { member, dispose: () => undefined };
|
|
65
|
+
let revoke;
|
|
66
|
+
let disposed = false;
|
|
67
|
+
let releaseLifetime;
|
|
68
|
+
state.dispose = () => {
|
|
69
|
+
if (disposed)
|
|
70
|
+
return;
|
|
71
|
+
disposed = true;
|
|
72
|
+
revoke?.();
|
|
73
|
+
releaseLifetime?.();
|
|
74
|
+
states.delete(agent);
|
|
75
|
+
active.delete(state);
|
|
76
|
+
};
|
|
77
|
+
states.set(agent, state);
|
|
78
|
+
active.add(state);
|
|
79
|
+
try {
|
|
80
|
+
if (member)
|
|
81
|
+
revoke = agent.ctx.tools.restrict({
|
|
82
|
+
deny: TEAM_TOOL_NAMES.filter(name => !MEMBER_TOOL_NAMES.includes(name)),
|
|
83
|
+
});
|
|
84
|
+
releaseLifetime = agent.ctx.effect(() => state.dispose, 'agent-teams: capability lifetime');
|
|
85
|
+
return state;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
state.dispose();
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
ctx.systemPrompt.section({
|
|
93
|
+
name: 'agent-teams:usage', order: config.order ?? 117,
|
|
94
|
+
text: ({ agent }) => {
|
|
95
|
+
return agent !== undefined && states.get(agent)?.member ? TEAM_MEMBER_PROMPT : captainPrompt;
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
ctx.on('agent/session-start', ({ agent }) => { attach(agent); });
|
|
99
|
+
ctx.effect(() => () => {
|
|
100
|
+
mounted = false;
|
|
101
|
+
for (const state of [...active])
|
|
102
|
+
state.dispose();
|
|
103
|
+
}, 'agent-teams: capability scopes');
|
|
104
|
+
for (const agent of ctx.agents.list())
|
|
105
|
+
attach(agent);
|
|
106
|
+
}
|
|
@@ -410,7 +410,7 @@ function historicCardTeam(data, owner) {
|
|
|
410
410
|
captainInbox: [],
|
|
411
411
|
};
|
|
412
412
|
}
|
|
413
|
-
export function ActivityPanel({ sessionsList, modelDirectories, openMember, t }) {
|
|
413
|
+
export function ActivityPanel({ sessionsList, modelDirectories, openMember, t, conversationVisible = true }) {
|
|
414
414
|
// Navigating to a member's subagent transcript is an explicit departure:
|
|
415
415
|
// hide the floater immediately instead of waiting out the autocollapse
|
|
416
416
|
// grace, so the panel never lingers over the member session.
|
|
@@ -439,7 +439,7 @@ export function ActivityPanel({ sessionsList, modelDirectories, openMember, t })
|
|
|
439
439
|
setOpen(false);
|
|
440
440
|
setOpenOwner(undefined);
|
|
441
441
|
window.requestAnimationFrame(() => {
|
|
442
|
-
document.querySelector('[data-composer-card] textarea')?.focus();
|
|
442
|
+
document.querySelector('[data-composer-card] [contenteditable="true"][role="textbox"], [data-composer-card] textarea')?.focus();
|
|
443
443
|
});
|
|
444
444
|
};
|
|
445
445
|
const { teams, archivedTeams } = useSyncExternalStore(subscribeActivitySnapshots, getActivitySnapshotsSnapshot);
|
|
@@ -447,7 +447,7 @@ export function ActivityPanel({ sessionsList, modelDirectories, openMember, t })
|
|
|
447
447
|
const currentRef = useRef(current);
|
|
448
448
|
useEffect(() => { currentRef.current = current; }, [current]);
|
|
449
449
|
const mountedAtRef = useRef(performance.now());
|
|
450
|
-
const expanded = activityPanelExpandedForSession(open, openOwner, current);
|
|
450
|
+
const expanded = conversationVisible && activityPanelExpandedForSession(open, openOwner, current);
|
|
451
451
|
const geometry = useMemo(() => resolvePanelGeometry(layout, bounds), [layout, bounds]);
|
|
452
452
|
const compact = compactPanelForBounds(bounds);
|
|
453
453
|
const commitLayout = useCallback((next) => {
|
|
@@ -754,7 +754,7 @@ export function ActivityPanel({ sessionsList, modelDirectories, openMember, t })
|
|
|
754
754
|
maxHeight: panelMaximumHeight(geometry, bounds),
|
|
755
755
|
transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`,
|
|
756
756
|
};
|
|
757
|
-
if (!hasTeams && !expanded)
|
|
757
|
+
if (!conversationVisible || (!hasTeams && !expanded))
|
|
758
758
|
return null;
|
|
759
759
|
return (_jsxs(_Fragment, { children: [!expanded && (_jsx(CollapsedBadge, { count: visibleCount, busy: busy, t: t, onClick: () => {
|
|
760
760
|
if (current === undefined)
|
package/lib/client/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import { agentTeamsCardDefinition } from "./agent-teams-card-definition.js";
|
|
|
5
5
|
import { AGENT_TEAMS_LOCALE_NAMESPACE, en, zh, } from "./locales.js";
|
|
6
6
|
import { openAgentTeamMember } from "./session-navigation.js";
|
|
7
7
|
/** Required services: conversation nodes, slots, sessions navigation, and locale. */
|
|
8
|
-
export const inject = ['uiConversation', 'slots', 'sessions', 'locale', 'modelDirectories'];
|
|
8
|
+
export const inject = ['uiConversation', 'slots', 'sessions', 'locale', 'modelDirectories', 'layout'];
|
|
9
|
+
const useLegacyPanelInfo = select => select({ activePanelId: null });
|
|
9
10
|
/** The replayed user message is the canonical transcript entry. */
|
|
10
11
|
function HiddenAgentTeamsCommand() {
|
|
11
12
|
return null;
|
|
@@ -18,11 +19,16 @@ function HiddenAgentTeamsCommand() {
|
|
|
18
19
|
export function apply(ctx) {
|
|
19
20
|
ctx.effect(() => ctx.locale.register(AGENT_TEAMS_LOCALE_NAMESPACE, { zh, en }), 'agent-teams: dictionaries');
|
|
20
21
|
const openMember = (parentId, childId) => {
|
|
21
|
-
void openAgentTeamMember(ctx.sessions, parentId, childId).catch((error) => {
|
|
22
|
+
void openAgentTeamMember(ctx.sessions, parentId, childId, ctx.layout).catch((error) => {
|
|
22
23
|
console.warn(`agent-teams: failed to open member transcript ${childId}: ${String(error)}`);
|
|
23
24
|
});
|
|
24
25
|
};
|
|
25
|
-
const Panel = ({ t }) =>
|
|
26
|
+
const Panel = ({ t, usePanelInfo }) => {
|
|
27
|
+
// A host's standard hook set is fixed for this mounted plugin instance.
|
|
28
|
+
const usePanel = usePanelInfo ?? useLegacyPanelInfo;
|
|
29
|
+
const conversationVisible = usePanel(panel => panel.activePanelId === null);
|
|
30
|
+
return (_jsx(ActivityPanel, { conversationVisible: conversationVisible, sessionsList: ctx.sessions.list, modelDirectories: ctx.modelDirectories, openMember: openMember, t: t }));
|
|
31
|
+
};
|
|
26
32
|
ctx.slots.inject('shell.overlay', () => ctx.slots.register({
|
|
27
33
|
name: 'shell.overlay',
|
|
28
34
|
id: 'agent-teams-activity',
|
|
@@ -5,17 +5,23 @@
|
|
|
5
5
|
* Harness rc.8 intentionally removed cold subagents from the ordinary session
|
|
6
6
|
* list. They must first be rediscovered in their parent's catalog, then opened
|
|
7
7
|
* with the exact parent/child/mode address. Older runtimes have only `open()`;
|
|
8
|
-
* the fallback preserves
|
|
8
|
+
* the fallback preserves ordinary-session navigation. New layouts also select
|
|
9
|
+
* the Conversation panel and cancel catalog refreshes superseded by navigation.
|
|
9
10
|
*/
|
|
10
|
-
export async function openAgentTeamMember(sessions, parentSessionId, childSessionId) {
|
|
11
|
+
export async function openAgentTeamMember(sessions, parentSessionId, childSessionId, layout) {
|
|
12
|
+
const navigation = layout?.beginNavigation?.();
|
|
11
13
|
if (sessions.openSubagent === undefined || sessions.refreshSubagents === undefined) {
|
|
12
14
|
sessions.open(childSessionId);
|
|
15
|
+
layout?.selectPanel?.(null);
|
|
13
16
|
return 'session';
|
|
14
17
|
}
|
|
15
18
|
await sessions.refreshSubagents(parentSessionId);
|
|
19
|
+
if (navigation?.aborted)
|
|
20
|
+
return 'cancelled';
|
|
16
21
|
const retained = sessions.subagentAddress?.(childSessionId);
|
|
17
22
|
sessions.openSubagent(retained?.parentSessionId === parentSessionId
|
|
18
23
|
? retained
|
|
19
24
|
: { parentSessionId, childSessionId, mode: 'continuable' });
|
|
25
|
+
layout?.selectPanel?.(null);
|
|
20
26
|
return 'subagent';
|
|
21
27
|
}
|
package/lib/client.js
CHANGED
|
@@ -2692,7 +2692,7 @@ window.__ModuleLoader__.load({
|
|
|
2692
2692
|
captainInbox: []
|
|
2693
2693
|
};
|
|
2694
2694
|
}
|
|
2695
|
-
function ActivityPanel({ sessionsList, modelDirectories, openMember, t }) {
|
|
2695
|
+
function ActivityPanel({ sessionsList, modelDirectories, openMember, t, conversationVisible = true }) {
|
|
2696
2696
|
const navigateToSession = (parentId, childId) => {
|
|
2697
2697
|
setOpen(false);
|
|
2698
2698
|
setWasActive(false);
|
|
@@ -2722,7 +2722,7 @@ window.__ModuleLoader__.load({
|
|
|
2722
2722
|
setOpen(false);
|
|
2723
2723
|
setOpenOwner(void 0);
|
|
2724
2724
|
window.requestAnimationFrame(() => {
|
|
2725
|
-
document.querySelector("[data-composer-card] textarea")?.focus();
|
|
2725
|
+
document.querySelector("[data-composer-card] [contenteditable=\"true\"][role=\"textbox\"], [data-composer-card] textarea")?.focus();
|
|
2726
2726
|
});
|
|
2727
2727
|
};
|
|
2728
2728
|
const { teams, archivedTeams } = (0, react.useSyncExternalStore)(subscribeActivitySnapshots, getActivitySnapshotsSnapshot);
|
|
@@ -2732,7 +2732,7 @@ window.__ModuleLoader__.load({
|
|
|
2732
2732
|
currentRef.current = current;
|
|
2733
2733
|
}, [current]);
|
|
2734
2734
|
const mountedAtRef = (0, react.useRef)(performance.now());
|
|
2735
|
-
const expanded = activityPanelExpandedForSession(open, openOwner, current);
|
|
2735
|
+
const expanded = conversationVisible && activityPanelExpandedForSession(open, openOwner, current);
|
|
2736
2736
|
const geometry = (0, react.useMemo)(() => resolvePanelGeometry(layout, bounds), [layout, bounds]);
|
|
2737
2737
|
const compact = compactPanelForBounds(bounds);
|
|
2738
2738
|
const commitLayout = (0, react.useCallback)((next) => {
|
|
@@ -3006,7 +3006,7 @@ window.__ModuleLoader__.load({
|
|
|
3006
3006
|
maxHeight: panelMaximumHeight(geometry, bounds),
|
|
3007
3007
|
transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`
|
|
3008
3008
|
};
|
|
3009
|
-
if (!hasTeams && !expanded) return null;
|
|
3009
|
+
if (!conversationVisible || !hasTeams && !expanded) return null;
|
|
3010
3010
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!expanded && (0, react_jsx_runtime.jsx)(CollapsedBadge, {
|
|
3011
3011
|
count: visibleCount,
|
|
3012
3012
|
busy,
|
|
@@ -3620,20 +3620,25 @@ window.__ModuleLoader__.load({
|
|
|
3620
3620
|
* Harness rc.8 intentionally removed cold subagents from the ordinary session
|
|
3621
3621
|
* list. They must first be rediscovered in their parent's catalog, then opened
|
|
3622
3622
|
* with the exact parent/child/mode address. Older runtimes have only `open()`;
|
|
3623
|
-
* the fallback preserves
|
|
3623
|
+
* the fallback preserves ordinary-session navigation. New layouts also select
|
|
3624
|
+
* the Conversation panel and cancel catalog refreshes superseded by navigation.
|
|
3624
3625
|
*/
|
|
3625
|
-
async function openAgentTeamMember(sessions, parentSessionId, childSessionId) {
|
|
3626
|
+
async function openAgentTeamMember(sessions, parentSessionId, childSessionId, layout) {
|
|
3627
|
+
const navigation = layout?.beginNavigation?.();
|
|
3626
3628
|
if (sessions.openSubagent === void 0 || sessions.refreshSubagents === void 0) {
|
|
3627
3629
|
sessions.open(childSessionId);
|
|
3630
|
+
layout?.selectPanel?.(null);
|
|
3628
3631
|
return "session";
|
|
3629
3632
|
}
|
|
3630
3633
|
await sessions.refreshSubagents(parentSessionId);
|
|
3634
|
+
if (navigation?.aborted) return "cancelled";
|
|
3631
3635
|
const retained = sessions.subagentAddress?.(childSessionId);
|
|
3632
3636
|
sessions.openSubagent(retained?.parentSessionId === parentSessionId ? retained : {
|
|
3633
3637
|
parentSessionId,
|
|
3634
3638
|
childSessionId,
|
|
3635
3639
|
mode: "continuable"
|
|
3636
3640
|
});
|
|
3641
|
+
layout?.selectPanel?.(null);
|
|
3637
3642
|
return "subagent";
|
|
3638
3643
|
}
|
|
3639
3644
|
//#endregion
|
|
@@ -3644,8 +3649,10 @@ window.__ModuleLoader__.load({
|
|
|
3644
3649
|
"slots",
|
|
3645
3650
|
"sessions",
|
|
3646
3651
|
"locale",
|
|
3647
|
-
"modelDirectories"
|
|
3652
|
+
"modelDirectories",
|
|
3653
|
+
"layout"
|
|
3648
3654
|
];
|
|
3655
|
+
const useLegacyPanelInfo = (select) => select({ activePanelId: null });
|
|
3649
3656
|
/** The replayed user message is the canonical transcript entry. */
|
|
3650
3657
|
function HiddenAgentTeamsCommand() {
|
|
3651
3658
|
return null;
|
|
@@ -3661,16 +3668,19 @@ window.__ModuleLoader__.load({
|
|
|
3661
3668
|
en
|
|
3662
3669
|
}), "agent-teams: dictionaries");
|
|
3663
3670
|
const openMember = (parentId, childId) => {
|
|
3664
|
-
openAgentTeamMember(ctx.sessions, parentId, childId).catch((error) => {
|
|
3671
|
+
openAgentTeamMember(ctx.sessions, parentId, childId, ctx.layout).catch((error) => {
|
|
3665
3672
|
console.warn(`agent-teams: failed to open member transcript ${childId}: ${String(error)}`);
|
|
3666
3673
|
});
|
|
3667
3674
|
};
|
|
3668
|
-
const Panel = ({ t }) =>
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3675
|
+
const Panel = ({ t, usePanelInfo }) => {
|
|
3676
|
+
return (0, react_jsx_runtime.jsx)(ActivityPanel, {
|
|
3677
|
+
conversationVisible: (usePanelInfo ?? useLegacyPanelInfo)((panel) => panel.activePanelId === null),
|
|
3678
|
+
sessionsList: ctx.sessions.list,
|
|
3679
|
+
modelDirectories: ctx.modelDirectories,
|
|
3680
|
+
openMember,
|
|
3681
|
+
t
|
|
3682
|
+
});
|
|
3683
|
+
};
|
|
3674
3684
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
3675
3685
|
name: "shell.overlay",
|
|
3676
3686
|
id: "agent-teams-activity",
|