@te-river/opencode-team-mode 1.4.3 → 1.4.5
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 +119 -17
- package/README.zh-CN.md +97 -10
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +28 -7
- package/dist/agents.js.map +1 -1
- package/dist/blackboard.d.ts +18 -5
- package/dist/blackboard.d.ts.map +1 -1
- package/dist/blackboard.js +70 -15
- package/dist/blackboard.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +5 -2
- package/dist/commands.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,6 +108,13 @@ That's it. The plugin automatically injects all team agents and commands when Op
|
|
|
108
108
|
|
|
109
109
|
> 💡 **Tip:** After modifying `opencode.json`, **restart OpenCode Desktop** for changes to take effect.
|
|
110
110
|
|
|
111
|
+
> ⚠️ **Model choice matters.** Every judgment in the workflow — triage,
|
|
112
|
+
> decomposition, dispatch briefs, synthesis, review-loop verdicts — flows
|
|
113
|
+
> through the **Team Lead**. A weak model in that seat degrades the whole
|
|
114
|
+
> pipeline no matter how strong the specialists are. Pin your best
|
|
115
|
+
> reasoning model to the `team` agent (recipe in
|
|
116
|
+
> [Customization](#customization) below).
|
|
117
|
+
|
|
111
118
|
### Global install (all projects)
|
|
112
119
|
|
|
113
120
|
To enable TeamMode in every project, add the plugin to your global config:
|
|
@@ -169,6 +176,55 @@ You can also invoke agents directly using the `@` mention in OpenCode Desktop:
|
|
|
169
176
|
- `@tester` — Write tests
|
|
170
177
|
- `@researcher` — Research a topic
|
|
171
178
|
|
|
179
|
+
### Demo
|
|
180
|
+
|
|
181
|
+
A session transcript, recreated from how the flow actually looks. Team is the
|
|
182
|
+
default agent out of the box (see Configuration to opt out), so the user just
|
|
183
|
+
types into a fresh chat:
|
|
184
|
+
|
|
185
|
+
> **User:** Add token-bucket rate limiting to our Express API — 100 requests
|
|
186
|
+
> per minute per user, return 429 when exceeded. Don't touch anything under
|
|
187
|
+
> `src/legacy/`.
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
team Breaking this down: design → implement → review → test.
|
|
191
|
+
Task board: .git/opencode-team/20260831-143012/rate-limiter/ (session folder + board inside .git/, auto-swept after idle TTL)
|
|
192
|
+
|
|
193
|
+
▸ @architect — designing (writes 01-architect-design.md)
|
|
194
|
+
✓ in-memory token bucket, per-user key, 429 + Retry-After
|
|
195
|
+
summary above, full design on the board
|
|
196
|
+
|
|
197
|
+
▸ @implementer — building (Reads: 01; writes 02-implementer-middleware.md)
|
|
198
|
+
✓ src/middleware/rateLimit.ts (new), wired into src/app.ts (+3 lines)
|
|
199
|
+
|
|
200
|
+
▸ @reviewer — auditing the diff (Reads: 01, 02; writes 03-reviewer-findings-r1.md)
|
|
201
|
+
⚠ 1 MAJOR — bucket refill does read-modify-write in two steps;
|
|
202
|
+
races under concurrent requests
|
|
203
|
+
→ converted to a fix task; dispatched to @implementer with the
|
|
204
|
+
finding text (the user was not asked to approve this step)
|
|
205
|
+
|
|
206
|
+
▸ @implementer r2 — fixing the race (Reads: 03-r1 §MAJOR; writes 04-implementer-r2.md)
|
|
207
|
+
✓ refill restructured to single atomic update
|
|
208
|
+
|
|
209
|
+
▸ @reviewer r2 — re-review of fixed scope only
|
|
210
|
+
✓ clean — r1 finding resolved, no regressions
|
|
211
|
+
|
|
212
|
+
▸ @tester — covering limiter + boundaries (writes 05-tester-report.md)
|
|
213
|
+
✓ 14/14 pass — burst edge, window expiry, concurrent refill,
|
|
214
|
+
src/legacy/** byte-identical (user boundary verified in tests)
|
|
215
|
+
|
|
216
|
+
team Done.
|
|
217
|
+
rate limiter shipped: rateLimit.ts (new) · app.ts (+3) · 14 tests green
|
|
218
|
+
review loop: 1 major found → fixed → clean
|
|
219
|
+
assumption: in-memory only — say the word if you want Redis
|
|
220
|
+
src/legacy/ untouched
|
|
221
|
+
task board left in place — TTL sweep will reclaim it
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The only message the user typed was the first one. The reviewer's finding
|
|
225
|
+
became the implementer's work order without a prompt; every artifact stayed
|
|
226
|
+
out of chat and on the board, read only by the dispatch that needed it.
|
|
227
|
+
|
|
172
228
|
### Desktop-specific features
|
|
173
229
|
|
|
174
230
|
In **OpenCode Desktop**, you get additional UX benefits:
|
|
@@ -214,10 +270,15 @@ opencode-team-mode/
|
|
|
214
270
|
|
|
215
271
|
Sub-agents cannot message each other live (platform limitation), so TeamMode coordinates them through a **file blackboard** with strict ownership:
|
|
216
272
|
|
|
217
|
-
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
273
|
+
- **Session isolation:** every conversation owns ONE timestamped session
|
|
274
|
+
folder, and each multi-agent task gets its own directory inside it:
|
|
275
|
+
`<repo>/.git/opencode-team/<session-key>/<task-slug>/` — inside `.git/`,
|
|
276
|
+
so your working tree and commits are **never polluted**. (Non-git
|
|
277
|
+
workspaces fall back to the OS temp dir.) Since boards now linger until
|
|
278
|
+
the TTL sweep, the session layer keeps a fresh conversation from bumping
|
|
279
|
+
into — or reading stale artifacts from — a not-yet-swept board (timestamps
|
|
280
|
+
are second-granular, so overlap needs two conversations starting in the
|
|
281
|
+
same second).
|
|
221
282
|
- **File ownership:** every artifact is one topic-sized file written by
|
|
222
283
|
exactly one agent (`01-architect-auth-design.md`, `03-reviewer-auth-r1.md`).
|
|
223
284
|
~100 lines max per file — split topics instead of letting files balloon.
|
|
@@ -242,15 +303,18 @@ your go-ahead); only explicit action requests enter the workflow. And whenever
|
|
|
242
303
|
you spell out what may or may not be touched, **those boundaries outrank
|
|
243
304
|
everything else** — the lead restates them in every single dispatch.
|
|
244
305
|
|
|
245
|
-
### Cleanup —
|
|
306
|
+
### Cleanup — the TTL sweeper is the only path
|
|
246
307
|
|
|
247
|
-
|
|
|
248
|
-
|
|
249
|
-
|
|
|
250
|
-
| Safety net | Plugin code (in-process sweeper) | At startup + every hour: removes task directories idle **beyond the TTL** |
|
|
308
|
+
| Who | When |
|
|
309
|
+
|---|---|
|
|
310
|
+
| Plugin code (in-process sweeper) | At startup + every hour: removes task directories idle **beyond the TTL** |
|
|
251
311
|
|
|
252
|
-
The
|
|
253
|
-
|
|
312
|
+
The Team Lead never deletes task directories — finished boards stay
|
|
313
|
+
readable so you can audit how a run went, and reclamation is pure code
|
|
314
|
+
that never relies on the model remembering to do anything (crashes and
|
|
315
|
+
force-kills leave nothing behind either). The sweeper prunes stale task
|
|
316
|
+
dirs individually under a still-live session, and reclaims an entirely
|
|
317
|
+
idle session folder in one pass. Set `ttlDays` to taste.
|
|
254
318
|
|
|
255
319
|
### Configure the TTL
|
|
256
320
|
|
|
@@ -271,10 +335,16 @@ fall back to 5.
|
|
|
271
335
|
|
|
272
336
|
### Default agent
|
|
273
337
|
|
|
274
|
-
TeamMode makes
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
338
|
+
By default TeamMode **makes Team your default agent** — new chats open
|
|
339
|
+
directly in the team orchestrator. One side effect comes with the default
|
|
340
|
+
slot: the switcher pins the default agent to the **first position** and
|
|
341
|
+
sorts everything else alphabetically, so the picker order is
|
|
342
|
+
**team, build, plan**. (Want Team below Plan instead? That requires
|
|
343
|
+
giving up the default slot — see the opt-out below; the two are
|
|
344
|
+
mutually exclusive by the server's sort.)
|
|
345
|
+
|
|
346
|
+
To opt out (`build` stays the default, picker order **build, plan,
|
|
347
|
+
team**):
|
|
278
348
|
|
|
279
349
|
```jsonc
|
|
280
350
|
{
|
|
@@ -284,13 +354,45 @@ as the default, or pin a different one:
|
|
|
284
354
|
}
|
|
285
355
|
```
|
|
286
356
|
|
|
287
|
-
An explicitly configured non-`build` `default_agent`
|
|
288
|
-
untouched.
|
|
357
|
+
An explicitly configured non-`build` `default_agent` in your own config is
|
|
358
|
+
always respected untouched — the plugin never clobbers it.
|
|
359
|
+
|
|
360
|
+
**Upgrade note:** v1.4.4 briefly made this promotion opt-in; v1.4.5 restores
|
|
361
|
+
Team-as-default as the shipped behavior. If you pinned `{ "defaultAgent":
|
|
362
|
+
true }` during v1.4.4, you can drop that option (or switch it to `false` to
|
|
363
|
+
opt out).
|
|
289
364
|
|
|
290
365
|
---
|
|
291
366
|
|
|
292
367
|
## 🔧 Customization
|
|
293
368
|
|
|
369
|
+
### The Team Lead's model matters most
|
|
370
|
+
|
|
371
|
+
The Lead is the orchestrating brain: it classifies every message, cuts the
|
|
372
|
+
work into packages, writes each dispatch manifest, judges reviewer/tester
|
|
373
|
+
findings, and synthesizes the final deliverable. Quality failures there
|
|
374
|
+
**multiply down the pipeline** — a mediocre Lead mis-decomposes, briefs the
|
|
375
|
+
experts vaguely, and waves weak work through; no specialist can rescue an
|
|
376
|
+
assignment it was never correctly given.
|
|
377
|
+
|
|
378
|
+
So run the strongest model you can afford **in the Lead seat**. The other
|
|
379
|
+
roles tolerate cheaper models — they work from tight briefs with scoped
|
|
380
|
+
reading. Pin models per agent:
|
|
381
|
+
|
|
382
|
+
```jsonc
|
|
383
|
+
{
|
|
384
|
+
"agent": {
|
|
385
|
+
// Team Lead — orchestration earns your best model
|
|
386
|
+
"team": { "model": "anthropic/claude-opus-4-5" },
|
|
387
|
+
// specialists — cheaper models are usually fine
|
|
388
|
+
"implementer": { "model": "anthropic/claude-sonnet-4-6" }
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
(Model IDs above are placeholders — use whatever your provider exposes.
|
|
394
|
+
Your own `agent.team` definition always takes precedence over the plugin's.)
|
|
395
|
+
|
|
294
396
|
### Override an agent
|
|
295
397
|
|
|
296
398
|
Add an agent with the same name in your `opencode.json` — your definition takes precedence:
|
package/README.zh-CN.md
CHANGED
|
@@ -108,6 +108,11 @@ npm link
|
|
|
108
108
|
|
|
109
109
|
> 💡 **提示:** 修改 `opencode.json` 后,请**重启 OpenCode 桌面版**使更改生效。
|
|
110
110
|
|
|
111
|
+
> ⚠️ **模型选择很重要。** 工作流里的每一个判断——分诊、拆解、派发清单、
|
|
112
|
+
> 整合、审查/测试闭环裁决——都经过 **Team Lead**。这个位置上放弱模型,
|
|
113
|
+
> 专家再强也救不回整条流水线。请给你的 `team` agent 钉上你能负担的最强
|
|
114
|
+
> 推理模型(配方见下方「自定义」节)。
|
|
115
|
+
|
|
111
116
|
### 全局安装(所有项目生效)
|
|
112
117
|
|
|
113
118
|
要在所有项目中启用 TeamMode,将插件添加到全局配置:
|
|
@@ -169,6 +174,51 @@ TeamMode 为 OpenCode 添加了六个斜杠命令,在聊天输入框中输入
|
|
|
169
174
|
- `@tester` — 编写测试
|
|
170
175
|
- `@researcher` — 调研主题
|
|
171
176
|
|
|
177
|
+
### 演示
|
|
178
|
+
|
|
179
|
+
以下是一段会话实录的还原。Team 出厂即默认代理(退出方法见下方配置),
|
|
180
|
+
用户开新会话直接输入:
|
|
181
|
+
|
|
182
|
+
> **用户:** 给我们的 Express API 加令牌桶限流——每用户每分钟 100 请求,
|
|
183
|
+
> 超限返回 429。不要动 `src/legacy/` 下的任何东西。
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
team 拆解任务:设计 → 实现 → 审查 → 测试。
|
|
187
|
+
任务黑板:.git/opencode-team/20260831-143012/rate-limiter/(会话目录 + 任务板,都在 .git/ 内,闲置超 TTL 自动清理)
|
|
188
|
+
|
|
189
|
+
▸ @architect — 设计中(写入 01-architect-design.md)
|
|
190
|
+
✓ 内存令牌桶、按用户键控、429 + Retry-After
|
|
191
|
+
聊天里只有摘要,设计全文在黑板上
|
|
192
|
+
|
|
193
|
+
▸ @implementer — 实现中(Reads: 01;写 02-implementer-middleware.md)
|
|
194
|
+
✓ src/middleware/rateLimit.ts(新增),接入 src/app.ts(+3 行)
|
|
195
|
+
|
|
196
|
+
▸ @reviewer — 审查改动(Reads: 01、02;写 03-reviewer-findings-r1.md)
|
|
197
|
+
⚠ 1 个 MAJOR — 桶回充分两步读-改-写,并发下有竞态
|
|
198
|
+
→ 已自动转为修复任务,发现原文随任务书派给 @implementer
|
|
199
|
+
(这一步没有要求用户拍板)
|
|
200
|
+
|
|
201
|
+
▸ @implementer r2 — 修竞态(Reads: 03-r1 §MAJOR;写 04-implementer-r2.md)
|
|
202
|
+
✓ 回充重构为单次原子更新
|
|
203
|
+
|
|
204
|
+
▸ @reviewer r2 — 只复审改动范围
|
|
205
|
+
✓ 通过 — r1 发现已解决,无回归
|
|
206
|
+
|
|
207
|
+
▸ @tester — 覆盖限流器与边界(写 05-tester-report.md)
|
|
208
|
+
✓ 14/14 通过 — 突发边界、窗口过期、并发回充、
|
|
209
|
+
src/legacy/** 逐字节未变(用户边界写进了测试断言)
|
|
210
|
+
|
|
211
|
+
team 完成。
|
|
212
|
+
限流器已交付:rateLimit.ts(新增)· app.ts(+3)· 14 测试全绿
|
|
213
|
+
审查闭环:1 个 major → 已修 → 清零
|
|
214
|
+
假设:仅内存存储——要接 Redis 说一声
|
|
215
|
+
src/legacy/ 未动
|
|
216
|
+
任务黑板留在原地,TTL 到期自动回收
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
用户输入的消息只有第一条。reviewer 的发现直接变成 implementer 的下一张
|
|
220
|
+
工单;每份制品都留在黑板上而不是聊天里,只被需要它的那次派发读取。
|
|
221
|
+
|
|
172
222
|
### 桌面版专属特性
|
|
173
223
|
|
|
174
224
|
在 **OpenCode 桌面版** 中,你还能获得额外的 UX 体验:
|
|
@@ -214,8 +264,11 @@ opencode-team-mode/
|
|
|
214
264
|
|
|
215
265
|
子代理之间无法实时互发消息(平台限制),TeamMode 通过**严格所有权的文件黑板**让它们协作:
|
|
216
266
|
|
|
217
|
-
-
|
|
267
|
+
- **会话隔离:** 每个会话拥有一个时间戳会话目录,多 Agent 任务在其内再各自
|
|
268
|
+
独立建任务目录:`<repo>/.git/opencode-team/<session-key>/<task-slug>/` ——
|
|
218
269
|
位于 `.git/` 内,**绝不污染**你的工作区和 commit(非 git 工作区自动回退到系统临时目录)。
|
|
270
|
+
正因为黑板现在会留到 TTL 清扫才消失,会话层让新对话几乎不可能撞上(或误读到)
|
|
271
|
+
上一场还没被收走的旧黑板 —— 时间戳精确到秒,理论上只有同一秒开跑的两个会话才会重名。
|
|
219
272
|
- **文件所有权**:每个制品是一个"一主题一文件",只由一个 Agent 写
|
|
220
273
|
(`01-architect-auth-design.md`、`03-reviewer-auth-r1.md`)。单文件约 ≤100 行,
|
|
221
274
|
超长就拆主题文件而不是任其膨胀。
|
|
@@ -235,14 +288,16 @@ Team Lead 对每条消息先分类再行动:咨询/提问只得到回答(零
|
|
|
235
288
|
仅**提议**修复并等待你放行);只有明确的行动指令才进入工作流。并且一旦你写明
|
|
236
289
|
了哪些能碰哪些不能碰,**这些边界高于一切规则**——lead 会在每次派发中原样重申。
|
|
237
290
|
|
|
238
|
-
### 清理 ——
|
|
291
|
+
### 清理 —— 只有 TTL 清扫器一条路
|
|
239
292
|
|
|
240
|
-
|
|
|
241
|
-
|
|
242
|
-
|
|
|
243
|
-
| 安全网 | 插件代码(进程内清扫器) | 启动时 + 每小时:清除空闲超过 **TTL** 的任务目录 |
|
|
293
|
+
| 责任方 | 时机 |
|
|
294
|
+
|---|---|
|
|
295
|
+
| 插件代码(进程内清扫器) | 启动时 + 每小时:清除空闲超过 **TTL** 的任务目录 |
|
|
244
296
|
|
|
245
|
-
|
|
297
|
+
Team Lead 不再删除任务目录 —— 跑完的黑板原地留给你回看审计;回收由纯代码
|
|
298
|
+
完成,从不依赖模型"记得删",崩溃/强杀留下的残骸同样会被清扫。清扫器对活跃
|
|
299
|
+
会话内的过期任务逐个回收,对整个闲置的会话目录一次性收走。TTL 可用
|
|
300
|
+
`ttlDays` 调节。
|
|
246
301
|
|
|
247
302
|
### 自定义 TTL
|
|
248
303
|
|
|
@@ -261,8 +316,12 @@ Team Lead 对每条消息先分类再行动:咨询/提问只得到回答(零
|
|
|
261
316
|
|
|
262
317
|
### 默认代理
|
|
263
318
|
|
|
264
|
-
TeamMode
|
|
265
|
-
|
|
319
|
+
TeamMode 默认**把 Team 设为你的默认代理**——新会话直接由团队调度者接管。
|
|
320
|
+
占默认槽附带一个排序效应:选择器会把**默认代理钉在第一位**、其余按名称
|
|
321
|
+
字母升序,所以顺序为 **team, build, plan**。(想让 Team 排在 Plan 之下?
|
|
322
|
+
那必须放弃默认槽——见下方退出开关;按服务端的排序规则二者不可兼得。)
|
|
323
|
+
|
|
324
|
+
不想占用默认代理槽(`build` 保持默认,顺序 **build, plan, team**)则退出:
|
|
266
325
|
|
|
267
326
|
```jsonc
|
|
268
327
|
{
|
|
@@ -272,12 +331,40 @@ TeamMode 会将 **`team` 设为默认代理**(替代内建 `build`),新会
|
|
|
272
331
|
}
|
|
273
332
|
```
|
|
274
333
|
|
|
275
|
-
用户显式配置的非 `build`
|
|
334
|
+
用户显式配置的非 `build` 默认代理永远原样保留——插件从不覆写。
|
|
335
|
+
|
|
336
|
+
**升级提示**:v1.4.4 曾短暂改为 opt-in(默认不占用);v1.4.5 恢复
|
|
337
|
+
Team-as-default 出厂行为。若你在 v1.4.4 期间加过 `{ "defaultAgent": true }`,
|
|
338
|
+
现在可以删掉该选项(或改为 `false` 主动退出)。
|
|
276
339
|
|
|
277
340
|
---
|
|
278
341
|
|
|
279
342
|
## 🔧 自定义
|
|
280
343
|
|
|
344
|
+
### Team Lead 的模型最关键
|
|
345
|
+
|
|
346
|
+
Lead 是编排大脑:它给每条消息分类、把工作切成包、写每份派发清单、裁决
|
|
347
|
+
reviewer/tester 的发现、合成最终交付。这里的质量问题会**沿流水线放大**——
|
|
348
|
+
平庸的 Lead 拆错任务、给专家的指令含糊、放走劣质产出;没有任何专家能
|
|
349
|
+
救回一份从一开始就派错的工单。
|
|
350
|
+
|
|
351
|
+
所以:**Lead 位上请放你负担得起的最强模型**。其他角色可以用便宜模型——
|
|
352
|
+
它们拿到的指令书精确、阅读范围受限,容错更高。按 agent 钉模型:
|
|
353
|
+
|
|
354
|
+
```jsonc
|
|
355
|
+
{
|
|
356
|
+
"agent": {
|
|
357
|
+
// Team Lead —— 编排值得最好的模型
|
|
358
|
+
"team": { "model": "anthropic/claude-opus-4-5" },
|
|
359
|
+
// 专家角色 —— 便宜一档通常够用
|
|
360
|
+
"implementer": { "model": "anthropic/claude-sonnet-4-6" }
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
(以上模型 ID 仅为示例,换成你服务商实际提供的即可。你自定义的
|
|
366
|
+
`agent.team` 永远优先于插件注入的版本。)
|
|
367
|
+
|
|
281
368
|
### 覆盖某个 Agent
|
|
282
369
|
|
|
283
370
|
在 `opencode.json` 中添加同名 Agent —— 你的定义会优先生效:
|
package/dist/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAqd7C,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAO9C,CAAA"}
|
package/dist/agents.js
CHANGED
|
@@ -104,8 +104,9 @@ Rules for the list:
|
|
|
104
104
|
4. **Integrate** — collect outputs, resolve conflicts, synthesize; consult
|
|
105
105
|
blackboard files whenever a summary is not enough.
|
|
106
106
|
5. **Verify** — run the feedback loop below before declaring done.
|
|
107
|
-
6. **Report
|
|
108
|
-
|
|
107
|
+
6. **Report** — structured summary with changes, review/test verdict,
|
|
108
|
+
risks. Leave the task directory in place: the plugin's TTL sweeper is
|
|
109
|
+
the only cleanup path (never delete it yourself).
|
|
109
110
|
|
|
110
111
|
## When you may edit directly
|
|
111
112
|
Delegation is the default, not a straitjacket. You MAY make small direct
|
|
@@ -113,11 +114,31 @@ edits: config tweaks, typo/format fixes, doc updates, tiny glue code
|
|
|
113
114
|
(≲ 10 lines). Anything substantive — feature logic, multi-file changes,
|
|
114
115
|
API design — goes to \`implementer\`.
|
|
115
116
|
|
|
117
|
+
Anti-pattern — the lead's own hands (observed in production): while
|
|
118
|
+
building something, you drift into writing file after file yourself until
|
|
119
|
+
the whole deliverable is done inline. Guard rails:
|
|
120
|
+
- If the request meets the medium-or-larger bar (see TodoList rule),
|
|
121
|
+
hand-execution is NOT permitted — every work package on the list gets
|
|
122
|
+
dispatched, including "small" ones you feel like knocking out.
|
|
123
|
+
- Sunk cost is not a reason to continue: caught yourself mid-inline-build
|
|
124
|
+
on a multi-file package? STOP, dispatch the remainder (or the whole
|
|
125
|
+
package for review), and treat what you wrote as input to the specialist,
|
|
126
|
+
not as a fait accompli.
|
|
127
|
+
- A complete feature never arrives in the lead's own diffs. If your final
|
|
128
|
+
report would say "I wrote X, Y, Z" — that is a triage failure, not
|
|
129
|
+
efficiency.
|
|
130
|
+
|
|
116
131
|
## Shared blackboard (file ownership + your dispatch manifest)
|
|
117
132
|
Sub-agents cannot message each other live; the blackboard is their shared
|
|
118
133
|
memory and YOU are the router — you decide who writes what and who reads
|
|
119
134
|
what (root path is appended at the end of this prompt):
|
|
120
|
-
-
|
|
135
|
+
- SESSION ISOLATION: this conversation owns exactly ONE session folder
|
|
136
|
+
\`<root>/<session-key>/\` (compact clock timestamp, created on your first
|
|
137
|
+
board write, reused for every later task here — see the resolved-root
|
|
138
|
+
section). Never touch or reuse a session folder another conversation
|
|
139
|
+
created; boards past their TTL stay on disk until the sweeper runs, and
|
|
140
|
+
the session layer is what keeps a fresh run from bumping into them.
|
|
141
|
+
- One task directory per multi-agent task: \`<root>/<session-key>/<task-slug>/\`.
|
|
121
142
|
- FILE OWNERSHIP — every artifact is one topic-sized file written by
|
|
122
143
|
exactly one agent: \`NN-<role>-<topic>.md\` (e.g.
|
|
123
144
|
\`01-architect-auth-design.md\`, \`03-reviewer-auth-r1.md\`). Keep files
|
|
@@ -147,10 +168,10 @@ what (root path is appended at the end of this prompt):
|
|
|
147
168
|
violation — send it back to write the file itself. Only if its reply
|
|
148
169
|
contains \`BLACKBOARD WRITE FAILED\` may you write the artifact as a
|
|
149
170
|
fallback; note the failure in MANIFEST.md so it is not silently tolerated.
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
- Do NOT delete the task directory after your report — TTL sweeping owns
|
|
172
|
+
reclamation (see Auto-cleanup in the resolved-root section). Finished
|
|
173
|
+
boards stay readable so the user can audit the run; leftovers from
|
|
174
|
+
crashed sessions sweep the same way.
|
|
154
175
|
|
|
155
176
|
## Feedback loop (mandatory before "done")
|
|
156
177
|
- Triage reviewer findings: **Critical/Major → spawn fix tasks** on the todo
|
package/dist/agents.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,wEAAwE;AACxE,+DAA+D;AAC/D,wEAAwE;AACxE,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;oCAoBO,CAAA;AAEpC,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,MAAM,QAAQ,GAAgB;IAC5B,IAAI,EAAE,SAAS;IACf,WAAW,EACT,2EAA2E;QAC3E,qEAAqE;QACrE,2EAA2E;QAC3E,2EAA2E;QAC3E,4BAA4B;IAC9B,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
|
package/dist/blackboard.d.ts
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
* Shared blackboard for sub-agent coordination + automatic maintenance.
|
|
3
3
|
*
|
|
4
4
|
* Sub-agents cannot message each other live (platform limitation), so
|
|
5
|
-
* TeamMode uses a file blackboard under
|
|
5
|
+
* TeamMode uses a file blackboard under
|
|
6
|
+
* `<repo>/.git/opencode-team/<session-key>/<task>/`:
|
|
7
|
+
* - <session-key> is a compact timestamp folder, one per conversation —
|
|
8
|
+
* a fresh conversation can never collide with a not-yet-swept board
|
|
9
|
+
* from an earlier one;
|
|
6
10
|
* - each agent writes its full deliverable to a designated file;
|
|
7
11
|
* - the team lead relays summaries + file paths in every dispatch;
|
|
8
|
-
* -
|
|
12
|
+
* - nobody deletes task directories by hand; the sweeper below reclaims
|
|
13
|
+
* them once idle past the TTL (sole cleanup path, by design).
|
|
9
14
|
*
|
|
10
|
-
* This module is the code-level
|
|
15
|
+
* This module is the code-level reclamation path, independent of the model:
|
|
11
16
|
* a sweeper removes task directories whose last activity is older than
|
|
12
17
|
* the TTL, at plugin startup and hourly in-process. Placing the board
|
|
13
18
|
* inside `.git/` guarantees the user's working tree and commits are never
|
|
@@ -31,8 +36,16 @@ export declare function teamRootFor(directory: string): string;
|
|
|
31
36
|
*/
|
|
32
37
|
export declare function resolveTtlMs(options?: Record<string, unknown>): number;
|
|
33
38
|
/**
|
|
34
|
-
* Remove idle
|
|
35
|
-
*
|
|
39
|
+
* Remove idle boards under `root`. Understands both layouts:
|
|
40
|
+
* - session-partitioned `<root>/<session-key>/<task>/`: stale tasks are
|
|
41
|
+
* pruned individually under a live session; an entirely idle session
|
|
42
|
+
* folder goes as a whole;
|
|
43
|
+
* - legacy flat `<root>/<task>/`: unchanged semantics — and if such a dir
|
|
44
|
+
* unexpectedly contains sub-directories, idle ones are pruned by the
|
|
45
|
+
* same rule (harmless hygiene, though counted as task dirs).
|
|
46
|
+
* Returns the number of task directories reclaimed; a wholesale session
|
|
47
|
+
* removal counts its task dirs (min 1, so a ghost empty stale session dir
|
|
48
|
+
* also counts 1). Never throws.
|
|
36
49
|
*/
|
|
37
50
|
export declare function sweepStale(root: string, ttlMs?: number): number;
|
|
38
51
|
/**
|
package/dist/blackboard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackboard.d.ts","sourceRoot":"","sources":["../src/blackboard.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"blackboard.d.ts","sourceRoot":"","sources":["../src/blackboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,cAAc,QAAyC,CAAA;AAQpE,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQzD;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAM1E;AAuCD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAiB,GAAG,MAAM,CA6CvE;AAID;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAiB,GACrB,MAAM,CASR"}
|
package/dist/blackboard.js
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
* Shared blackboard for sub-agent coordination + automatic maintenance.
|
|
3
3
|
*
|
|
4
4
|
* Sub-agents cannot message each other live (platform limitation), so
|
|
5
|
-
* TeamMode uses a file blackboard under
|
|
5
|
+
* TeamMode uses a file blackboard under
|
|
6
|
+
* `<repo>/.git/opencode-team/<session-key>/<task>/`:
|
|
7
|
+
* - <session-key> is a compact timestamp folder, one per conversation —
|
|
8
|
+
* a fresh conversation can never collide with a not-yet-swept board
|
|
9
|
+
* from an earlier one;
|
|
6
10
|
* - each agent writes its full deliverable to a designated file;
|
|
7
11
|
* - the team lead relays summaries + file paths in every dispatch;
|
|
8
|
-
* -
|
|
12
|
+
* - nobody deletes task directories by hand; the sweeper below reclaims
|
|
13
|
+
* them once idle past the TTL (sole cleanup path, by design).
|
|
9
14
|
*
|
|
10
|
-
* This module is the code-level
|
|
15
|
+
* This module is the code-level reclamation path, independent of the model:
|
|
11
16
|
* a sweeper removes task directories whose last activity is older than
|
|
12
17
|
* the TTL, at plugin startup and hourly in-process. Placing the board
|
|
13
18
|
* inside `.git/` guarantees the user's working tree and commits are never
|
|
@@ -57,15 +62,21 @@ export function resolveTtlMs(options = {}) {
|
|
|
57
62
|
}
|
|
58
63
|
return DEFAULT_TTL_MS;
|
|
59
64
|
}
|
|
60
|
-
/**
|
|
61
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Latest mtime within `dir`, looking through up to `levels` sub-directory
|
|
67
|
+
* layers (artifacts live one level below a task dir, so 1 suffices per
|
|
68
|
+
* task and 2 from the session/root level).
|
|
69
|
+
*/
|
|
70
|
+
function lastActivity(dir, levels = 0) {
|
|
62
71
|
try {
|
|
63
72
|
let latest = fs.statSync(dir).mtimeMs;
|
|
64
73
|
for (const entry of fs.readdirSync(dir)) {
|
|
65
74
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
const child = path.join(dir, entry);
|
|
76
|
+
const st = fs.statSync(child);
|
|
77
|
+
const seen = st.isDirectory() && levels > 0 ? lastActivity(child, levels - 1) : st.mtimeMs;
|
|
78
|
+
if (seen > latest)
|
|
79
|
+
latest = seen;
|
|
69
80
|
}
|
|
70
81
|
catch {
|
|
71
82
|
/* raced deletion — ignore */
|
|
@@ -78,8 +89,27 @@ function lastActivity(dir) {
|
|
|
78
89
|
}
|
|
79
90
|
}
|
|
80
91
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
92
|
+
* True when a directory tree shows no activity within the TTL.
|
|
93
|
+
* `levels` must reach down to the artifact files: 1 for a task directory
|
|
94
|
+
* (files sit directly inside), 2 for a session directory (task dirs are
|
|
95
|
+
* one level deeper — depth 1 here would miss in-place rewrites and let a
|
|
96
|
+
* whole live session be reclaimed; regression-pinned by test fixture).
|
|
97
|
+
*/
|
|
98
|
+
function isStale(dir, now, ttlMs, levels) {
|
|
99
|
+
const seen = lastActivity(dir, levels);
|
|
100
|
+
return seen !== 0 && now - seen > ttlMs;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Remove idle boards under `root`. Understands both layouts:
|
|
104
|
+
* - session-partitioned `<root>/<session-key>/<task>/`: stale tasks are
|
|
105
|
+
* pruned individually under a live session; an entirely idle session
|
|
106
|
+
* folder goes as a whole;
|
|
107
|
+
* - legacy flat `<root>/<task>/`: unchanged semantics — and if such a dir
|
|
108
|
+
* unexpectedly contains sub-directories, idle ones are pruned by the
|
|
109
|
+
* same rule (harmless hygiene, though counted as task dirs).
|
|
110
|
+
* Returns the number of task directories reclaimed; a wholesale session
|
|
111
|
+
* removal counts its task dirs (min 1, so a ghost empty stale session dir
|
|
112
|
+
* also counts 1). Never throws.
|
|
83
113
|
*/
|
|
84
114
|
export function sweepStale(root, ttlMs = DEFAULT_TTL_MS) {
|
|
85
115
|
let entries;
|
|
@@ -96,12 +126,37 @@ export function sweepStale(root, ttlMs = DEFAULT_TTL_MS) {
|
|
|
96
126
|
try {
|
|
97
127
|
if (!fs.statSync(dir).isDirectory())
|
|
98
128
|
continue;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
129
|
+
if (isStale(dir, now, ttlMs, 2)) {
|
|
130
|
+
// Entire tree idle: legacy flat task dir, or a finished session.
|
|
131
|
+
let tasks = 0;
|
|
132
|
+
for (const child of fs.readdirSync(dir)) {
|
|
133
|
+
try {
|
|
134
|
+
if (fs.statSync(path.join(dir, child)).isDirectory())
|
|
135
|
+
tasks++;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
/* raced — ignore */
|
|
139
|
+
}
|
|
140
|
+
}
|
|
103
141
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
104
|
-
removed
|
|
142
|
+
removed += Math.max(1, tasks);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// Live tree: prune per-task dirs (session layout; legacy dirs have
|
|
146
|
+
// no directory children, so this loop is a no-op for them).
|
|
147
|
+
for (const child of fs.readdirSync(dir)) {
|
|
148
|
+
const task = path.join(dir, child);
|
|
149
|
+
try {
|
|
150
|
+
if (!fs.statSync(task).isDirectory())
|
|
151
|
+
continue;
|
|
152
|
+
if (!isStale(task, now, ttlMs, 1))
|
|
153
|
+
continue;
|
|
154
|
+
fs.rmSync(task, { recursive: true, force: true });
|
|
155
|
+
removed++;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
/* raced — skip this task */
|
|
159
|
+
}
|
|
105
160
|
}
|
|
106
161
|
}
|
|
107
162
|
catch {
|
package/dist/blackboard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackboard.js","sourceRoot":"","sources":["../src/blackboard.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"blackboard.js","sourceRoot":"","sources":["../src/blackboard.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA8I/C,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAOlD,CAAA"}
|
package/dist/commands.js
CHANGED
|
@@ -113,7 +113,9 @@ $ARGUMENTS
|
|
|
113
113
|
- Code review → reviewer
|
|
114
114
|
- Testing → tester
|
|
115
115
|
- Research → researcher
|
|
116
|
-
5. Coordinate through the shared blackboard:
|
|
116
|
+
5. Coordinate through the shared blackboard: this conversation owns one
|
|
117
|
+
session folder (<root>/<session-key>/ — compact timestamp, created on
|
|
118
|
+
first board write), one task directory per task inside it; every
|
|
117
119
|
dispatch carries a manifest (Task / Reads: only the files needed /
|
|
118
120
|
Write to: one owned artifact file); artifacts are frozen — revisions are
|
|
119
121
|
new round-suffixed files; keep MANIFEST.md's \`## Current state\` header
|
|
@@ -124,7 +126,8 @@ $ARGUMENTS
|
|
|
124
126
|
escalate).
|
|
125
127
|
7. Collect all outputs, resolve conflicts, synthesize a final result.
|
|
126
128
|
8. Present a structured summary: changes, review/test verdict, remaining
|
|
127
|
-
assumptions and risks.
|
|
129
|
+
assumptions and risks. Leave the task blackboard directory in place —
|
|
130
|
+
the plugin's TTL sweeper reclaims idle boards; never delete it yourself.`,
|
|
128
131
|
};
|
|
129
132
|
/* ------------------------------------------------------------------ */
|
|
130
133
|
/* Export all commands keyed by name */
|
package/dist/commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wEAAwE;AACxE,MAAM,QAAQ,GAAkB;IAC9B,WAAW,EACT,+FAA+F;IACjG,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE;;;;;;;;;;;;;kDAasC;CACjD,CAAA;AAED,wEAAwE;AACxE,MAAM,aAAa,GAAkB;IACnC,WAAW,EACT,0FAA0F;IAC5F,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE;;;;;;;;4DAQgD;CAC3D,CAAA;AAED,wEAAwE;AACxE,MAAM,UAAU,GAAkB;IAChC,WAAW,EACT,0EAA0E;IAC5E,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE;;;;;;;;;;;;;gEAaoD;CAC/D,CAAA;AAED,wEAAwE;AACxE,MAAM,QAAQ,GAAkB;IAC9B,WAAW,EACT,2EAA2E;IAC7E,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE;;;;;;;;;;;8BAWkB;CAC7B,CAAA;AAED,wEAAwE;AACxE,MAAM,YAAY,GAAkB;IAClC,WAAW,EACT,uEAAuE;IACzE,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE;;;;;;;;;;;0DAW8C;CACzD,CAAA;AAED,wEAAwE;AACxE,MAAM,OAAO,GAAkB;IAC7B,WAAW,EACT,mGAAmG;IACrG,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wEAAwE;AACxE,MAAM,QAAQ,GAAkB;IAC9B,WAAW,EACT,+FAA+F;IACjG,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE;;;;;;;;;;;;;kDAasC;CACjD,CAAA;AAED,wEAAwE;AACxE,MAAM,aAAa,GAAkB;IACnC,WAAW,EACT,0FAA0F;IAC5F,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE;;;;;;;;4DAQgD;CAC3D,CAAA;AAED,wEAAwE;AACxE,MAAM,UAAU,GAAkB;IAChC,WAAW,EACT,0EAA0E;IAC5E,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE;;;;;;;;;;;;;gEAaoD;CAC/D,CAAA;AAED,wEAAwE;AACxE,MAAM,QAAQ,GAAkB;IAC9B,WAAW,EACT,2EAA2E;IAC7E,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE;;;;;;;;;;;8BAWkB;CAC7B,CAAA;AAED,wEAAwE;AACxE,MAAM,YAAY,GAAkB;IAClC,WAAW,EACT,uEAAuE;IACzE,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE;;;;;;;;;;;0DAW8C;CACzD,CAAA;AAED,wEAAwE;AACxE,MAAM,OAAO,GAAkB;IAC7B,WAAW,EACT,mGAAmG;IACrG,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4EAgCgE;CAC3E,CAAA;AAED,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AAExE,MAAM,CAAC,MAAM,QAAQ,GAAkC;IACrD,WAAW,EAAE,QAAQ;IACrB,gBAAgB,EAAE,aAAa;IAC/B,aAAa,EAAE,UAAU;IACzB,WAAW,EAAE,QAAQ;IACrB,eAAe,EAAE,YAAY;IAC7B,UAAU,EAAE,OAAO;CACpB,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* Options (via the tuple plugin form):
|
|
18
18
|
* "plugin": [["@te-river/opencode-team-mode@latest", { "ttlDays": 7 }]]
|
|
19
19
|
* - `ttlDays` → blackboard auto-cleanup TTL; default 5.
|
|
20
|
-
* - `defaultAgent` →
|
|
21
|
-
*
|
|
20
|
+
* - `defaultAgent` → Team is the default agent (opt-out: set `false`).
|
|
21
|
+
* Owning the default slot means the picker pins it
|
|
22
|
+
* FIRST — order becomes team, build, plan. Set
|
|
23
|
+
* `false` for build-as-default with Team in its
|
|
24
|
+
* alphabetical slot: build, plan, team (the two are
|
|
25
|
+
* mutually exclusive by the server's sort).
|
|
22
26
|
*/
|
|
23
27
|
import type { OpenCodePlugin } from "./types.js";
|
|
24
28
|
declare const plugin: OpenCodePlugin;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,YAAY,CAAA;AA2BhE,QAAA,MAAM,MAAM,EAAE,cAyCb,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* Options (via the tuple plugin form):
|
|
18
18
|
* "plugin": [["@te-river/opencode-team-mode@latest", { "ttlDays": 7 }]]
|
|
19
19
|
* - `ttlDays` → blackboard auto-cleanup TTL; default 5.
|
|
20
|
-
* - `defaultAgent` →
|
|
21
|
-
*
|
|
20
|
+
* - `defaultAgent` → Team is the default agent (opt-out: set `false`).
|
|
21
|
+
* Owning the default slot means the picker pins it
|
|
22
|
+
* FIRST — order becomes team, build, plan. Set
|
|
23
|
+
* `false` for build-as-default with Team in its
|
|
24
|
+
* alphabetical slot: build, plan, team (the two are
|
|
25
|
+
* mutually exclusive by the server's sort).
|
|
22
26
|
*/
|
|
23
27
|
import { agents } from "./agents.js";
|
|
24
28
|
import { commands } from "./commands.js";
|
|
@@ -30,9 +34,14 @@ function blackboardNote(root, ttlDays) {
|
|
|
30
34
|
"",
|
|
31
35
|
"## Team Blackboard — resolved for this workspace",
|
|
32
36
|
`Root directory: \`${root}\``,
|
|
33
|
-
`-
|
|
34
|
-
|
|
35
|
-
`
|
|
37
|
+
`- Session isolation: on the FIRST board write of this conversation create a session`,
|
|
38
|
+
` folder \`<root>/<session-key>/\` where <session-key> is a compact clock timestamp`,
|
|
39
|
+
` (PowerShell: \`Get-Date -Format yyyyMMdd-HHmmss\`; POSIX: \`date +%Y%m%d-%H%M%S\`).`,
|
|
40
|
+
` Reuse that folder for every later task in the same conversation; never write into`,
|
|
41
|
+
` a session folder created by a different conversation.`,
|
|
42
|
+
`- Create exactly ONE task sub-directory per multi-agent task: \`<root>/<session-key>/<task-slug>/\`.`,
|
|
43
|
+
`- Auto-cleanup: the plugin sweeps task directories idle for more than ${ttlDays} days (at startup and hourly).`,
|
|
44
|
+
` This is the ONLY cleanup path — never delete task or session directories yourself.`,
|
|
36
45
|
].join("\n");
|
|
37
46
|
}
|
|
38
47
|
const plugin = {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAExB,iEAAiE;AACjE,SAAS,cAAc,CAAC,IAAY,EAAE,OAAe;IACnD,OAAO;QACL,EAAE;QACF,EAAE;QACF,kDAAkD;QAClD,qBAAqB,IAAI,IAAI;QAC7B,qFAAqF;QACrF,qFAAqF;QACrF,uFAAuF;QACvF,qFAAqF;QACrF,yDAAyD;QACzD,sGAAsG;QACtG,yEAAyE,OAAO,gCAAgC;QAChH,sFAAsF;KACvF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,MAAM,MAAM,GAAmB;IAC7B,EAAE,EAAE,WAAW;IAEf,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC/B,wEAAwE;QACxE,MAAM,SAAS,GACb,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAChE,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;QACnB,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,gBAAgB,CAAA;QAC7E,MAAM,SAAS,GAAG,0BAA0B,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC9D,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAE/C,OAAO;YACL,iEAAiE;YACjE,MAAM,CAAC,GAAmB;gBACxB,IAAI,CAAC,GAAG,CAAC,KAAK;oBAAE,GAAG,CAAC,KAAK,GAAG,EAAE,CAAA;gBAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBACjD,mEAAmE;oBACnE,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;wBAAE,SAAQ;oBAC7B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;wBAChB,GAAG,GAAG;wBACN,MAAM,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM;qBACjE,CAAA;gBACH,CAAC;gBAED,IAAI,CAAC,GAAG,CAAC,OAAO;oBAAE,GAAG,CAAC,OAAO,GAAG,EAAE,CAAA;gBAClC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnD,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;wBAAE,SAAQ;oBAC/B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAA;gBACzB,CAAC;gBAED,uEAAuE;gBACvE,MAAM,OAAO,GAAG,OAAO,EAAE,YAAY,KAAK,KAAK,CAAA;gBAC/C,IAAI,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,aAAa,KAAK,OAAO,CAAC,EAAE,CAAC;oBACrE,GAAG,CAAC,aAAa,GAAG,MAAM,CAAA;gBAC5B,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@te-river/opencode-team-mode",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "Team collaboration mode plugin for OpenCode Desktop — injects specialized agents (architect, reviewer, implementer, tester, researcher) and team workflow commands into your OpenCode workspace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|