@hueyexe/opencode-ensemble 0.13.3 → 0.14.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 +101 -64
- package/dist/index.js +2196 -796
- package/package.json +3 -3
- package/src/index.ts +35 -5
- package/src/state.ts +107 -0
- package/src/system-prompt.ts +5 -0
- package/src/tools/shared.ts +35 -0
- package/src/tools/team-cleanup.ts +422 -2
- package/src/types.ts +2 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@hueyexe/opencode-ensemble)
|
|
8
8
|
[](https://www.npmjs.com/package/@hueyexe/opencode-ensemble)
|
|
9
|
-
[]()
|
|
10
10
|
[]()
|
|
11
11
|
[]()
|
|
12
12
|
[](./LICENSE)
|
|
@@ -19,7 +19,7 @@ Plugin built on the public OpenCode SDK. No internal dependencies.
|
|
|
19
19
|
|
|
20
20
|
```json
|
|
21
21
|
{
|
|
22
|
-
"plugin": ["@hueyexe/opencode-ensemble@0.
|
|
22
|
+
"plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -29,79 +29,114 @@ Add to your `opencode.json`, restart OpenCode, and ask it to do something that b
|
|
|
29
29
|
|
|
30
30
|
You ask the agent to do something complex. It creates a team, spawns teammates, and they work in parallel. Each teammate runs in its own OpenCode session with a fresh context window.
|
|
31
31
|
|
|
32
|
-
A
|
|
32
|
+
A realistic development-team interaction:
|
|
33
33
|
|
|
34
34
|
```
|
|
35
|
-
You: "
|
|
35
|
+
You: "Fix checkout idempotency so duplicate Stripe webhooks cannot create
|
|
36
|
+
duplicate orders. Add regression tests and review the final diff for risk."
|
|
36
37
|
|
|
37
38
|
The lead agent:
|
|
38
|
-
1. Creates a team called "
|
|
39
|
-
2. Adds tasks
|
|
40
|
-
3.
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
|
|
39
|
+
1. Creates a team called "checkout-idempotency".
|
|
40
|
+
2. Adds independent tasks first and records the generated task IDs.
|
|
41
|
+
3. Adds dependent QA and review tasks with `depends_on` using real returned IDs.
|
|
42
|
+
4. Spawns a small team with explicit roles:
|
|
43
|
+
- scout: explore agent, worktree disabled, model openai/gpt-5.3-codex-spark
|
|
44
|
+
- api-dev: build agent, own worktree, model anthropic/claude-opus-4-7, plan_approval: true
|
|
45
|
+
- qa: build agent, own worktree, model anthropic/claude-sonnet-4-6
|
|
46
|
+
- reviewer: explore agent, worktree disabled, model openai/gpt-5.3-codex-spark
|
|
45
47
|
```
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
[
|
|
52
|
-
|
|
49
|
+
The lead uses the task board to make sequencing visible. Record the returned task IDs before creating dependent tasks:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
team_tasks_add({
|
|
53
|
+
tasks: [
|
|
54
|
+
{ content: "Map checkout webhook flow and identify idempotency risks", priority: "high" },
|
|
55
|
+
{ content: "Implement duplicate-webhook idempotency guard", priority: "high" },
|
|
56
|
+
],
|
|
57
|
+
})
|
|
58
|
+
// -> Added 2 tasks: task_abc123, task_def456
|
|
59
|
+
|
|
60
|
+
team_tasks_add({
|
|
61
|
+
tasks: [
|
|
62
|
+
{ content: "Add regression tests for duplicate webhook delivery", priority: "high", depends_on: ["task_def456"] },
|
|
63
|
+
],
|
|
64
|
+
})
|
|
65
|
+
// -> Added 1 task: task_ghi789
|
|
66
|
+
|
|
67
|
+
team_tasks_add({
|
|
68
|
+
tasks: [
|
|
69
|
+
{ content: "Review final diff for order, payment, and retry risks", priority: "medium", depends_on: ["task_def456", "task_ghi789"] },
|
|
70
|
+
],
|
|
71
|
+
})
|
|
72
|
+
// -> Added 1 task: task_jkl012
|
|
53
73
|
```
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
Then it spawns teammates one at a time:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
team_spawn({
|
|
79
|
+
name: "scout",
|
|
80
|
+
agent: "explore",
|
|
81
|
+
worktree: false,
|
|
82
|
+
model: "openai/gpt-5.3-codex-spark",
|
|
83
|
+
claim_task: "task_abc123",
|
|
84
|
+
prompt: "Trace the checkout webhook flow. Report the files, data model, existing tests, and the smallest safe implementation plan. Do not edit files.",
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
team_spawn({
|
|
88
|
+
name: "api-dev",
|
|
89
|
+
agent: "build",
|
|
90
|
+
model: "anthropic/claude-opus-4-7",
|
|
91
|
+
plan_approval: true,
|
|
92
|
+
claim_task: "task_def456",
|
|
93
|
+
prompt: "After scout reports, implement the idempotency guard. Keep the change narrow. Commit your work and send a task-result message.",
|
|
94
|
+
})
|
|
62
95
|
```
|
|
63
96
|
|
|
64
|
-
|
|
97
|
+
The same pattern assigns `qa` to regression tests and `reviewer` to final review. The reviewer stays read-only (`worktree: false`) so it can inspect merged changes without producing another branch.
|
|
65
98
|
|
|
66
|
-
|
|
99
|
+
Teammates coordinate without the lead polling:
|
|
67
100
|
|
|
68
101
|
```
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
alice [idle 2m, last msg: 1m ago] agent: build branch: ensemble-validation-alice
|
|
75
|
-
bob [idle 1m, last msg: 30s ago] agent: build branch: ensemble-validation-bob
|
|
76
|
-
carol [working 5m, last msg: 3m ago] agent: build branch: ensemble-validation-carol
|
|
77
|
-
task: Write integration tests for validated endpoints
|
|
78
|
-
Tasks: 5 total (3 completed, 1 in_progress, 1 pending)
|
|
102
|
+
scout -> lead: "Checkout flow is src/webhooks/stripe.ts -> createOrderFromPayment(). Existing tests are in test/checkout-webhook.test.ts. Risk: retries race before order insert commits."
|
|
103
|
+
api-dev -> lead: "Plan ready: add unique event_id insert before order creation, treat duplicate insert as success, add a transaction around order creation."
|
|
104
|
+
lead -> api-dev: approves plan
|
|
105
|
+
qa -> api-dev: "Which duplicate signal should tests assert: event_id conflict or existing order lookup?"
|
|
106
|
+
api-dev -> qa: "Assert duplicate event_id returns success and creates one order. See src/webhooks/stripe.ts."
|
|
79
107
|
```
|
|
80
108
|
|
|
81
|
-
|
|
109
|
+
When work is done, the lead reviews and integrates deliberately:
|
|
82
110
|
|
|
83
111
|
```
|
|
84
|
-
|
|
112
|
+
team_results({ from: "api-dev" })
|
|
113
|
+
team_shutdown({ member: "api-dev" })
|
|
114
|
+
team_merge({ member: "api-dev" })
|
|
115
|
+
|
|
116
|
+
team_results({ from: "qa" })
|
|
117
|
+
team_shutdown({ member: "qa" })
|
|
118
|
+
team_merge({ member: "qa" })
|
|
85
119
|
|
|
86
|
-
|
|
87
|
-
-> TUI switches to carol's session, showing her full chat log
|
|
88
|
-
-> Use the session picker (ctrl+p) to go back to the lead
|
|
120
|
+
team_spawn({ name: "reviewer", agent: "explore", worktree: false, claim_task: "task_jkl012", prompt: "Review the merged diff for correctness, missed tests, and risky behavior. Do not edit files." })
|
|
89
121
|
```
|
|
90
122
|
|
|
91
|
-
|
|
123
|
+
The lead runs the repository verification commands, summarizes the result, and only then cleans up the team. All merged teammate changes remain in your working directory as unstaged changes for review with `git diff`.
|
|
92
124
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
12 test cases added. Team cleaned up.
|
|
100
|
-
Merged 3 branch(es) into working directory (unstaged).
|
|
101
|
-
Review changes with: git diff"
|
|
125
|
+
## Agent Skill
|
|
126
|
+
|
|
127
|
+
Install the companion skill to teach your AI how to form useful Ensemble teams, write better teammate prompts, choose models, and avoid common coordination failures:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx skills@latest add hueyexe/opencode-ensemble --skill opencode-ensemble
|
|
102
131
|
```
|
|
103
132
|
|
|
104
|
-
|
|
133
|
+
The skill is useful when you want the agent to decide whether parallel work is appropriate, split work into independent slices, use `depends_on` correctly, or pick a safe mix of `explore` and `build` teammates.
|
|
134
|
+
|
|
135
|
+
Good team shapes:
|
|
136
|
+
|
|
137
|
+
- **Scout, builder, reviewer**: one read-only `explore` agent maps the code, one `build` agent changes it, one read-only `explore` agent reviews the diff.
|
|
138
|
+
- **Parallel slices**: two or three `build` agents own independent files or vertical slices, then one reviewer checks the combined result.
|
|
139
|
+
- **Risky change**: use `plan_approval: true` on the implementing teammate, then approve or reject the plan through `team_message` before edits begin.
|
|
105
140
|
|
|
106
141
|
## Dashboard
|
|
107
142
|
|
|
@@ -140,7 +175,7 @@ Add to your OpenCode config with a pinned version. Project-level or global.
|
|
|
140
175
|
|
|
141
176
|
```json
|
|
142
177
|
{
|
|
143
|
-
"plugin": ["@hueyexe/opencode-ensemble@0.
|
|
178
|
+
"plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
|
|
144
179
|
}
|
|
145
180
|
```
|
|
146
181
|
|
|
@@ -148,7 +183,7 @@ Add to your OpenCode config with a pinned version. Project-level or global.
|
|
|
148
183
|
|
|
149
184
|
```json
|
|
150
185
|
{
|
|
151
|
-
"plugin": ["@hueyexe/opencode-ensemble@0.
|
|
186
|
+
"plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
|
|
152
187
|
}
|
|
153
188
|
```
|
|
154
189
|
|
|
@@ -198,7 +233,7 @@ Build with `bun run build`, then restart OpenCode to pick up changes.
|
|
|
198
233
|
|
|
199
234
|
14 tools. The lead has all of them. Teammates get 6 (messaging + tasks).
|
|
200
235
|
|
|
201
|
-
**Team lifecycle** (lead only)
|
|
236
|
+
**Team lifecycle** (lead only, except archived-team purge may also be run from the main session)
|
|
202
237
|
|
|
203
238
|
| Tool | What it does |
|
|
204
239
|
|------|-------------|
|
|
@@ -206,10 +241,12 @@ Build with `bun run build`, then restart OpenCode to pick up changes.
|
|
|
206
241
|
| `team_spawn` | Start a new teammate with a task. Supports `plan_approval` mode. |
|
|
207
242
|
| `team_shutdown` | Ask a teammate to stop. Preserves their branch before aborting. Supports `force` flag. |
|
|
208
243
|
| `team_merge` | Merge a shutdown teammate's branch into working directory (unstaged). Blocks if you have local changes to overlapping files. |
|
|
209
|
-
| `team_cleanup` | Remove the team when done. Safety-net merges
|
|
244
|
+
| `team_cleanup` | Remove the current team when done. Safety-net merges forgotten branches. With `purge`, previews archived-team deletion and returns exact approval labels plus a confirmation token. |
|
|
210
245
|
| `team_status` | See all members, their status, and a task summary. |
|
|
211
246
|
| `team_view` | Switch the TUI to a teammate's session. |
|
|
212
247
|
|
|
248
|
+
Archived-team purge is intentionally two-step. First call `team_cleanup` with `purge` to get a preview, exact approval and denial option labels, and `confirm_token`; no data is deleted. Stale archived worktree/workspace references and stale Ensemble-owned branches are counted in the preview and cleaned during confirmed purge. Arbitrary non-Ensemble branches still block purge for safety. The lead must then use the question tool with those exact options. Only after the user selects the exact approval option should it call `team_cleanup` again with the same `purge`, `confirm_purge: true`, and the preview token.
|
|
249
|
+
|
|
213
250
|
**Communication** (everyone)
|
|
214
251
|
|
|
215
252
|
| Tool | What it does |
|
|
@@ -276,8 +313,8 @@ Control which AI models your agents use. By default, agents use whatever model O
|
|
|
276
313
|
```json
|
|
277
314
|
{
|
|
278
315
|
"modelsByAgent": {
|
|
279
|
-
"build": "anthropic/claude-opus-4-
|
|
280
|
-
"explore": "
|
|
316
|
+
"build": "anthropic/claude-opus-4-7",
|
|
317
|
+
"explore": "openai/gpt-5.3-codex-spark"
|
|
281
318
|
}
|
|
282
319
|
}
|
|
283
320
|
```
|
|
@@ -285,7 +322,7 @@ Control which AI models your agents use. By default, agents use whatever model O
|
|
|
285
322
|
**Rotate through a pool for diverse perspectives:**
|
|
286
323
|
```json
|
|
287
324
|
{
|
|
288
|
-
"modelPool": ["anthropic/claude-opus-4-
|
|
325
|
+
"modelPool": ["anthropic/claude-opus-4-7", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
|
|
289
326
|
"modelAssignment": "rotate"
|
|
290
327
|
}
|
|
291
328
|
```
|
|
@@ -294,7 +331,7 @@ Control which AI models your agents use. By default, agents use whatever model O
|
|
|
294
331
|
```json
|
|
295
332
|
{
|
|
296
333
|
"promptForModels": true,
|
|
297
|
-
"modelPool": ["anthropic/claude-opus-4-
|
|
334
|
+
"modelPool": ["anthropic/claude-opus-4-7", "opencode/big-pickle", "openai/gpt-5.3-codex-spark"]
|
|
298
335
|
}
|
|
299
336
|
```
|
|
300
337
|
|
|
@@ -309,7 +346,7 @@ When `promptForModels` is true, the lead uses the question tool to ask which mod
|
|
|
309
346
|
|
|
310
347
|
The lead can always override by passing `model` directly on `team_spawn`, regardless of config.
|
|
311
348
|
|
|
312
|
-
Model IDs use the `provider/model` format from [models.dev](https://models.dev) (e.g. `anthropic/claude-opus-4-
|
|
349
|
+
Model IDs use the `provider/model` format from [models.dev](https://models.dev) (e.g. `anthropic/claude-opus-4-7`, `openai/gpt-5.4`). For OpenCode Zen models, use the `opencode/` prefix (e.g. `opencode/big-pickle`).
|
|
313
350
|
|
|
314
351
|
## Configuration
|
|
315
352
|
|
|
@@ -329,7 +366,7 @@ Configure via JSON files, environment variables, or both. Project config overrid
|
|
|
329
366
|
"rateLimitCapacity": 10,
|
|
330
367
|
"dashboardPort": 4747,
|
|
331
368
|
"defaultModel": "anthropic/claude-sonnet-4-6",
|
|
332
|
-
"modelPool": ["anthropic/claude-opus-4-
|
|
369
|
+
"modelPool": ["anthropic/claude-opus-4-7", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
|
|
333
370
|
"modelsByAgent": {},
|
|
334
371
|
"modelAssignment": "default",
|
|
335
372
|
"promptForModels": false
|
|
@@ -351,7 +388,7 @@ All fields are optional. Missing fields use defaults.
|
|
|
351
388
|
| `dashboardPort` | `4747` | Dashboard server port. `0` disables. |
|
|
352
389
|
| `defaultModel` | `""` | Default model for all agents (e.g. `"anthropic/claude-sonnet-4-6"`). Empty = OpenCode's default. |
|
|
353
390
|
| `modelPool` | `[]` | List of models for rotation/random assignment. |
|
|
354
|
-
| `modelsByAgent` | `{}` | Map agent type to model (e.g. `{"build": "anthropic/claude-opus-4-
|
|
391
|
+
| `modelsByAgent` | `{}` | Map agent type to model (e.g. `{"build": "anthropic/claude-opus-4-7"}`). |
|
|
355
392
|
| `modelAssignment` | `"default"` | How to assign models: `"default"`, `"rotate"`, or `"random"`. |
|
|
356
393
|
| `promptForModels` | `false` | Lead asks user about model preferences before spawning. |
|
|
357
394
|
|
|
@@ -410,7 +447,7 @@ Same coordination model (shared tasks, peer messaging, lead coordination) with s
|
|
|
410
447
|
```bash
|
|
411
448
|
bun install
|
|
412
449
|
bun run typecheck
|
|
413
|
-
bun test #
|
|
450
|
+
bun test # 561 tests
|
|
414
451
|
bun run build
|
|
415
452
|
```
|
|
416
453
|
|