@te-river/opencode-team-mode 1.5.0 → 1.5.2
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 +157 -53
- package/README.zh-CN.md +137 -53
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +128 -26
- package/dist/agents.js.map +1 -1
- package/dist/approval-gate.d.ts +147 -0
- package/dist/approval-gate.d.ts.map +1 -0
- package/dist/approval-gate.js +471 -0
- package/dist/approval-gate.js.map +1 -0
- package/dist/commands.js +3 -3
- package/dist/commands.js.map +1 -1
- package/dist/envprotect.d.ts +234 -0
- package/dist/envprotect.d.ts.map +1 -0
- package/dist/envprotect.js +820 -0
- package/dist/envprotect.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -1
- package/dist/index.js.map +1 -1
- package/dist/tm/config.d.ts +105 -0
- package/dist/tm/config.d.ts.map +1 -0
- package/dist/tm/config.js +118 -0
- package/dist/tm/config.js.map +1 -0
- package/dist/tm/guard.d.ts +56 -0
- package/dist/tm/guard.d.ts.map +1 -0
- package/dist/tm/guard.js +249 -0
- package/dist/tm/guard.js.map +1 -0
- package/dist/tm/index.d.ts +41 -0
- package/dist/tm/index.d.ts.map +1 -0
- package/dist/tm/index.js +93 -0
- package/dist/tm/index.js.map +1 -0
- package/dist/tm/preview.d.ts +46 -0
- package/dist/tm/preview.d.ts.map +1 -0
- package/dist/tm/preview.js +354 -0
- package/dist/tm/preview.js.map +1 -0
- package/dist/tm/ptc.d.ts +279 -0
- package/dist/tm/ptc.d.ts.map +1 -0
- package/dist/tm/ptc.js +839 -0
- package/dist/tm/ptc.js.map +1 -0
- package/dist/tm/refs.d.ts +37 -0
- package/dist/tm/refs.d.ts.map +1 -0
- package/dist/tm/refs.js +58 -0
- package/dist/tm/refs.js.map +1 -0
- package/dist/tm/store.d.ts +95 -0
- package/dist/tm/store.d.ts.map +1 -0
- package/dist/tm/store.js +222 -0
- package/dist/tm/store.js.map +1 -0
- package/dist/tm/tools.d.ts +84 -0
- package/dist/tm/tools.d.ts.map +1 -0
- package/dist/tm/tools.js +710 -0
- package/dist/tm/tools.js.map +1 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -55,73 +55,40 @@ Instead of one agent trying to do everything, you get:
|
|
|
55
55
|
|
|
56
56
|
### Install TeamMode
|
|
57
57
|
|
|
58
|
-
**Option A — One-line installer
|
|
58
|
+
**Option A — One-line installer:**
|
|
59
59
|
|
|
60
60
|
macOS / Linux (bash):
|
|
61
61
|
```bash
|
|
62
|
-
curl -fsSL
|
|
62
|
+
curl -fsSL https://ghproxy.net/https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.sh | bash
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
Windows (PowerShell):
|
|
66
66
|
```powershell
|
|
67
|
-
irm
|
|
67
|
+
irm https://ghproxy.net/https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.ps1 | iex
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
# macOS / Linux — jsdelivr
|
|
73
|
-
curl -fsSL "https://cdn.jsdelivr.net/gh/Te-River/Opencode-TeamMode@main/scripts/install.sh" | bash
|
|
74
|
-
|
|
75
|
-
# Windows — jsdelivr
|
|
76
|
-
irm "https://cdn.jsdelivr.net/gh/Te-River/Opencode-TeamMode@main/scripts/install.ps1" | iex
|
|
77
|
-
|
|
78
|
-
# macOS / Linux — GitHub raw
|
|
79
|
-
curl -fsSL https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.sh | bash
|
|
80
|
-
|
|
81
|
-
# Windows — GitHub raw
|
|
82
|
-
irm https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.ps1 | iex
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
These scripts install the npm package and automatically register the plugin in your `opencode.jsonc`.
|
|
70
|
+
**Option B — Manual config:**
|
|
86
71
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
# 1. Install the plugin package
|
|
91
|
-
npm install -g @te-river/opencode-team-mode
|
|
92
|
-
|
|
93
|
-
# 2. Add the plugin to your opencode.jsonc
|
|
94
|
-
# (see "Configuration" below)
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Option C — Local dev install (from this repo):**
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
git clone https://github.com/Te-River/Opencode-TeamMode.git
|
|
101
|
-
cd Opencode-TeamMode
|
|
102
|
-
npm install
|
|
103
|
-
npm run build
|
|
104
|
-
npm link
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## ⚙️ Configuration
|
|
110
|
-
|
|
111
|
-
After installing, add the plugin to your `opencode.jsonc`:
|
|
72
|
+
Add the plugin to your `opencode.jsonc`:
|
|
112
73
|
|
|
113
74
|
```jsonc
|
|
114
75
|
{
|
|
115
76
|
"$schema": "https://opencode.ai/config.json",
|
|
116
77
|
"plugin": [
|
|
117
|
-
"@te-river/opencode-team-mode@
|
|
78
|
+
"@te-river/opencode-team-mode@latest"
|
|
118
79
|
]
|
|
119
80
|
}
|
|
120
81
|
```
|
|
121
82
|
|
|
122
|
-
|
|
83
|
+
OpenCode will automatically install the plugin on startup.
|
|
84
|
+
|
|
85
|
+
> **Tip:** After modifying `opencode.json`, **restart OpenCode Desktop** for changes to take effect.
|
|
123
86
|
|
|
124
|
-
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## ⚙️ Configuration
|
|
90
|
+
|
|
91
|
+
The plugin automatically injects all team agents and commands when OpenCode starts. **No need to manually copy agent files or command definitions.**
|
|
125
92
|
|
|
126
93
|
> ⚠️ **Model choice matters.** Every judgment in the workflow — triage,
|
|
127
94
|
> decomposition, dispatch briefs, synthesis, review-loop verdicts — flows
|
|
@@ -139,7 +106,7 @@ To enable TeamMode in every project, add the plugin to your global config:
|
|
|
139
106
|
{
|
|
140
107
|
"$schema": "https://opencode.ai/config.json",
|
|
141
108
|
"plugin": [
|
|
142
|
-
"@te-river/opencode-team-mode@
|
|
109
|
+
"@te-river/opencode-team-mode@latest"
|
|
143
110
|
]
|
|
144
111
|
}
|
|
145
112
|
```
|
|
@@ -251,6 +218,139 @@ In **OpenCode Desktop**, you get additional UX benefits:
|
|
|
251
218
|
|
|
252
219
|
---
|
|
253
220
|
|
|
221
|
+
## 🧯 Context governance (tm_* + R6 + R2) — new in v1.5.1
|
|
222
|
+
|
|
223
|
+
> ⚠️ Requires `@te-river/opencode-team-mode@1.5.1` or later (released
|
|
224
|
+
> 2026-09-08). If your config pins `@latest`, OpenCode upgrades on next start.
|
|
225
|
+
|
|
226
|
+
**JIT layer-2 tools (`tm_read` / `tm_grep` / `tm_bash` / `tm_fetch`).**
|
|
227
|
+
Large tool outputs are context cost's main driver: every step re-sends the
|
|
228
|
+
whole window. The tm_* tools run the built-in capability under governance
|
|
229
|
+
first: results above `TM_OFFLOAD_THRESHOLD` tokens never enter the window —
|
|
230
|
+
they are written to a local run store and replaced by a handle with a
|
|
231
|
+
content-aware preview (JSON keys / CSV header+shape / log ERROR×N stats /
|
|
232
|
+
code signatures / binary metadata, hard-capped at 80 tokens). When the agent
|
|
233
|
+
actually needs the payload it pages through it with `tm_fetch`, using an
|
|
234
|
+
HMAC-signed, run-scoped, expiring handle. `tm_bash` only allows read-only
|
|
235
|
+
commands (allowlist), and failures come back as structured errors instead of
|
|
236
|
+
raw dumps.
|
|
237
|
+
|
|
238
|
+
**R6 environment protection (now an approval gate).** With TeamMode active,
|
|
239
|
+
the model cannot read environment variables silently. Env-var reads
|
|
240
|
+
(`printenv`, `env`, `Get-ChildItem env:`, …) and env files (`.env`, shell rc
|
|
241
|
+
files) route through OpenCode's **official confirmation dialog**: you get a
|
|
242
|
+
native prompt to approve or deny, and an unanswered prompt is **auto-rejected
|
|
243
|
+
after `TM_ASK_TIMEOUT_MIN` (default 10 min)** — the plugin only ever rejects
|
|
244
|
+
on timeout, never approves on the model's behalf. Env reads that no wildcard
|
|
245
|
+
can express (embedded `$VAR` / `${VAR}` / `$env:` inside another command,
|
|
246
|
+
command substitution, subshell/escaped forms) and the `tm_*` wrapper channel
|
|
247
|
+
stay a **hard block** (no dialog to slip through). tm_* wrappers route through
|
|
248
|
+
the same checks (no backdoor via the wrappers). Audit lines record only tool
|
|
249
|
+
name + pattern category + the verdict (`ask` / `allowed-once` /
|
|
250
|
+
`allowed-always` / `rejected` / `timeout-rejected` / `degraded`) — never
|
|
251
|
+
command text, paths, variable names or values.
|
|
252
|
+
|
|
253
|
+
**R2 dangerous operations (same dialog).** Delete (`rm`/`del`/`Remove-Item`/
|
|
254
|
+
`rmdir`), git publishing (`git push`/`git commit`), network fetch (`curl`/
|
|
255
|
+
`wget`/`Invoke-WebRequest`/`Invoke-RestMethod`), package installs/publishes
|
|
256
|
+
(`npm install`/`npm publish`/`pip install`/`winget`/`choco`), process/system
|
|
257
|
+
(`taskkill`/`Stop-Process`/`kill`/`shutdown`/`format`) and privilege changes
|
|
258
|
+
(`chmod`/`takeown`/`icacls`) — none are silently allowed. They pop the same
|
|
259
|
+
official dialog and are auto-rejected if you don't answer within the timeout.
|
|
260
|
+
The normal verification stack (`npm test`, `tsc`, `git status`/`diff`) is NOT
|
|
261
|
+
gated, so day-to-day team work runs without interruption.
|
|
262
|
+
|
|
263
|
+
> ⚠️ **When you approve a dialog, pick "once" — not "always".** Verified on
|
|
264
|
+
> the live host, "always" records a far broader rule than the command you
|
|
265
|
+
> saw: approving `Get-ChildItem env:PATH` with "always" stores `Get-ChildItem
|
|
266
|
+
> *`, so every later `Get-ChildItem` runs with no dialog at all. Only the
|
|
267
|
+
> once-verdict keeps each gated operation individually human-checked.
|
|
268
|
+
|
|
269
|
+
> Deferral is per-session: env reads only route to the dialog in sessions
|
|
270
|
+
> running TeamMode's injected agents (or after such a session has shown one
|
|
271
|
+
> of these dialogs). In any other session (e.g. a stock `build`/`plan` chat)
|
|
272
|
+
> TeamMode's guard keeps hard-blocking env reads, since no dialog would back
|
|
273
|
+
> them there. Compound commands (`a; b`) are evaluated per segment by the
|
|
274
|
+
> host and approved through one dialog; the guard blocks them outright
|
|
275
|
+
> whenever any segment is an env read.
|
|
276
|
+
|
|
277
|
+
> The permission protocol was verified against a live `opencode serve` host
|
|
278
|
+
> (1.18.29) via SSE event capture; the Desktop dialog rendering itself is the
|
|
279
|
+
> one leg that still needs eyeballing in a real Desktop session. Headless
|
|
280
|
+
> `opencode run` auto-rejects an unanswered `ask` immediately (there is no
|
|
281
|
+
> human to prompt).
|
|
282
|
+
|
|
283
|
+
| Env var | Default | Purpose |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `TM_ENV_PROTECT` | `strict` | R6 mode: `strict` / `standard` / `off` (off also disarms the approval timer) |
|
|
286
|
+
| `TM_ASK_TIMEOUT_MIN` | `10` | minutes before an unanswered R6/R2 confirmation dialog is auto-rejected; minimum 3 minutes (the host's `permission.replied` reaches the plugin ~120 s late on the event bus — shorter values would auto-reject a just-approved request) |
|
|
287
|
+
| `TM_ENV_PROTECT_EXTRA_DENY` | — | extra block patterns (regex list; always a hard block, never dialog-governed) |
|
|
288
|
+
| `TM_OFFLOAD_THRESHOLD` | `2000` | offload threshold (tokens, chars/4 estimate) |
|
|
289
|
+
| `TM_PREVIEW_MAX_TOKENS` | `80` | preview hard cap |
|
|
290
|
+
| `TM_FETCH_MAX_LINES` | `2000` | tm_fetch page cap |
|
|
291
|
+
| `TM_BLACKBOARD_DIR` | `.blackboard/` | offloaded payload store |
|
|
292
|
+
| `TM_TRAJECTORY_DIR` | `.trajectory/` | append-only tool-call ledger |
|
|
293
|
+
| `TM_BLACKBOARD_TTL` | `7` | store retention (days) |
|
|
294
|
+
| `TM_BASH_READONLY_ALLOWED` | built-in table | tm_bash allowlist |
|
|
295
|
+
| `TM_PTC_MAX_PROGRAM_CHARS` | `4000` | PTC program source length cap (chars) |
|
|
296
|
+
| `TM_PTC_MAX_CALLS` | `20` | PTC per-run bridge-call budget (1–200) |
|
|
297
|
+
| `TM_PTC_MAX_ERRORS` | `3` | PTC per-run error budget (1–50) |
|
|
298
|
+
| `TM_PTC_TIMEOUT_MS` | `60000` | PTC per-run wall-clock timeout (5s–10min) |
|
|
299
|
+
| `TM_PTC_ENGINE` | `auto` | PTC engine: `auto` (worker→inline degrade) / `worker` / `inline` |
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## ⚡ Batch orchestration (`tm_ptc_run`) — new in v1.5.2
|
|
304
|
+
|
|
305
|
+
> Shipped in **v1.5.2** (2026-09-10). Requires `@te-river/opencode-team-mode@1.5.2`
|
|
306
|
+
> or later.
|
|
307
|
+
|
|
308
|
+
`tm_ptc_run` lets a specialist agent write **one async program** that makes N
|
|
309
|
+
governed `tm_*` calls in a single turn — zero LLM round-trips during the run,
|
|
310
|
+
only an aggregation summary returns to context. It is designed for batch
|
|
311
|
+
read-only tasks: multi-file reconnaissance, bulk grep + read aggregation,
|
|
312
|
+
cross-referencing search results.
|
|
313
|
+
|
|
314
|
+
### How it works
|
|
315
|
+
|
|
316
|
+
The agent writes a program body using `tm.read(args)`, `tm.grep(args)`,
|
|
317
|
+
`tm.bash(args)`, `tm.fetch(args)` — same args as the four governed tools.
|
|
318
|
+
Each call returns `{ok:true, data}` (governed: inline text or an offload
|
|
319
|
+
handle) or `{ok:false, error:{tool,phase,line?,message}}`. The program
|
|
320
|
+
`return`s a value; it is JSON-serialized into the aggregation summary.
|
|
321
|
+
|
|
322
|
+
Programs containing `require`, `import`, `process`, `globalThis`, `Deno`,
|
|
323
|
+
`Bun`, `fs`, `net`, or `child_process` are rejected before execution (static
|
|
324
|
+
pre-scan, auxiliary guard).
|
|
325
|
+
|
|
326
|
+
### Budgets (tighten-only)
|
|
327
|
+
|
|
328
|
+
The caller may tighten `max_calls`, `max_errors`, and `timeout_ms` — values
|
|
329
|
+
above the `TM_PTC_*` ceilings are clamped down; values below the floor are
|
|
330
|
+
clamped up. Hitting any budget stops the whole run; produced output is NOT
|
|
331
|
+
lost.
|
|
332
|
+
|
|
333
|
+
### Engine (`TM_PTC_ENGINE`)
|
|
334
|
+
|
|
335
|
+
| Mode | Behavior |
|
|
336
|
+
|---|---|
|
|
337
|
+
| `auto` (default) | Tries `worker_threads` first; on failure degrades to `node:vm` with a `degraded-engine` mark in the summary |
|
|
338
|
+
| `worker` | Forces the worker engine (engine-error on failure) |
|
|
339
|
+
| `inline` | Forces the `node:vm` engine (30s compile timeout for sync busy-loops; await-gap residual documented) |
|
|
340
|
+
|
|
341
|
+
The worker engine runs the program in a dedicated thread with `env:{}`
|
|
342
|
+
(process.env emptied), `resourceLimits`, and hard wall-clock `terminate()`.
|
|
343
|
+
All governance (P2 path scope, P3 allowlist, R6, threshold offload, TTL)
|
|
344
|
+
applies to every bridged call — PTC is not a bypass layer.
|
|
345
|
+
|
|
346
|
+
### Access
|
|
347
|
+
|
|
348
|
+
Five specialist agents (`implementer`, `tester`, `architect`, `reviewer`,
|
|
349
|
+
`researcher`) have `tm_ptc_run` in their whitelist. The `team` lead does
|
|
350
|
+
not — it orchestrates, it does not run batch programs itself.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
254
354
|
## 🏗️ Architecture
|
|
255
355
|
|
|
256
356
|
```
|
|
@@ -258,14 +358,18 @@ opencode-team-mode/
|
|
|
258
358
|
├── package.json ← npm package definition
|
|
259
359
|
├── tsconfig.json ← TypeScript config
|
|
260
360
|
├── src/
|
|
261
|
-
│ ├── index.ts ← Plugin entry (server() +
|
|
361
|
+
│ ├── index.ts ← Plugin entry (server(): config + R6 tool.execute.before + approval-gate event + tool segment)
|
|
262
362
|
│ ├── agents.ts ← Agent definitions (prompts, modes, colors)
|
|
263
363
|
│ ├── commands.ts ← Command definitions (templates, agent bindings)
|
|
264
364
|
│ ├── blackboard.ts ← Shared blackboard + TTL auto-cleanup sweeper
|
|
365
|
+
│ ├── envprotect.ts ← R6 env-var read protection + R2 ask-pattern sets (dialog vs hard-block)
|
|
366
|
+
│ ├── approval-gate.ts ← Unified approval gate: host-dialog timeout auto-reject (never self-allows)
|
|
367
|
+
│ ├── tm/ ← JIT layer-2 tools (tm_read / tm_grep / tm_bash / tm_fetch / tm_ptc_run)
|
|
265
368
|
│ └── types.ts ← Loader-contract type definitions (1.18.x)
|
|
266
369
|
├── scripts/
|
|
267
370
|
│ ├── install.sh ← One-click installer (bash)
|
|
268
371
|
│ └── install.ps1 ← One-click installer (PowerShell)
|
|
372
|
+
├── pt07/ ← PT-07 baseline suite (seeded A/B token measurement)
|
|
269
373
|
├── LICENSE ← Apache 2.0
|
|
270
374
|
├── README.md ← English documentation
|
|
271
375
|
└── README.zh-CN.md ← Chinese documentation
|
|
@@ -274,8 +378,8 @@ opencode-team-mode/
|
|
|
274
378
|
### How it works
|
|
275
379
|
|
|
276
380
|
1. OpenCode Desktop starts and loads `opencode.json(c)`.
|
|
277
|
-
2. It sees `"@te-river/opencode-team-mode@
|
|
278
|
-
3. The loader calls the plugin's `server(input, options)`, which registers a `config` hook; the hook injects 6 agents and 6 commands into the merged config.
|
|
381
|
+
2. It sees `"@te-river/opencode-team-mode@latest"` in the `plugin` array and loads the npm package.
|
|
382
|
+
3. The loader calls the plugin's `server(input, options)`, which registers a `config` hook; the hook injects 6 agents and 6 commands into the merged config. The same call installs the R6 `tool.execute.before` guard, arms the unified R6/R2 approval gate (official dialog + `TM_ASK_TIMEOUT_MIN` auto-reject, wired through an `event` hook), and registers the governed `tm_*` tools (see [Context governance](#-context-governance-tm--r6--r2--new-in-v151) below).
|
|
279
383
|
4. The plugin's `id: "team-mode"` is displayed as the plugin name in the Desktop UI.
|
|
280
384
|
5. Agents and commands are immediately available in the Desktop UI — no file copying needed. User-defined agents with the same name always win (the plugin never clobbers them).
|
|
281
385
|
|
|
@@ -381,7 +485,7 @@ Default is **5 days**. To choose your own, use the tuple plugin form in
|
|
|
381
485
|
{
|
|
382
486
|
"$schema": "https://opencode.ai/config.json",
|
|
383
487
|
"plugin": [
|
|
384
|
-
["@te-river/opencode-team-mode@
|
|
488
|
+
["@te-river/opencode-team-mode@latest", { "ttlDays": 7 }]
|
|
385
489
|
]
|
|
386
490
|
}
|
|
387
491
|
```
|
|
@@ -405,7 +509,7 @@ team**):
|
|
|
405
509
|
```jsonc
|
|
406
510
|
{
|
|
407
511
|
"plugin": [
|
|
408
|
-
["@te-river/opencode-team-mode@
|
|
512
|
+
["@te-river/opencode-team-mode@latest", { "defaultAgent": false }]
|
|
409
513
|
]
|
|
410
514
|
}
|
|
411
515
|
```
|
package/README.zh-CN.md
CHANGED
|
@@ -55,73 +55,40 @@ TeamMode 将 OpenCode 桌面版从一个单 Agent 编码助手,升级为**一
|
|
|
55
55
|
|
|
56
56
|
### 安装 TeamMode
|
|
57
57
|
|
|
58
|
-
**方式 A —
|
|
58
|
+
**方式 A — 一键安装脚本:**
|
|
59
59
|
|
|
60
60
|
macOS / Linux(bash):
|
|
61
61
|
```bash
|
|
62
|
-
curl -fsSL
|
|
62
|
+
curl -fsSL https://ghproxy.net/https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.sh | bash
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
Windows(PowerShell):
|
|
66
66
|
```powershell
|
|
67
|
-
irm
|
|
67
|
+
irm https://ghproxy.net/https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.ps1 | iex
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
# macOS / Linux — jsdelivr
|
|
73
|
-
curl -fsSL "https://cdn.jsdelivr.net/gh/Te-River/Opencode-TeamMode@main/scripts/install.sh" | bash
|
|
74
|
-
|
|
75
|
-
# Windows — jsdelivr
|
|
76
|
-
irm "https://cdn.jsdelivr.net/gh/Te-River/Opencode-TeamMode@main/scripts/install.ps1" | iex
|
|
77
|
-
|
|
78
|
-
# macOS / Linux — GitHub 原始地址
|
|
79
|
-
curl -fsSL https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.sh | bash
|
|
80
|
-
|
|
81
|
-
# Windows — GitHub 原始地址
|
|
82
|
-
irm https://raw.githubusercontent.com/Te-River/Opencode-TeamMode/main/scripts/install.ps1 | iex
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
脚本会自动安装 npm 包,并将插件注册到你的 `opencode.jsonc` 中。
|
|
70
|
+
**方式 B — 手动配置:**
|
|
86
71
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
# 1. 安装插件包
|
|
91
|
-
npm install -g @te-river/opencode-team-mode
|
|
92
|
-
|
|
93
|
-
# 2. 将插件添加到 opencode.jsonc
|
|
94
|
-
# (见下方"配置"章节)
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**方式 C — 本地开发安装(从本仓库):**
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
git clone https://github.com/Te-River/Opencode-TeamMode.git
|
|
101
|
-
cd Opencode-TeamMode
|
|
102
|
-
npm install
|
|
103
|
-
npm run build
|
|
104
|
-
npm link
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## ⚙️ 配置
|
|
110
|
-
|
|
111
|
-
安装后,将插件添加到你的 `opencode.jsonc`:
|
|
72
|
+
在你的 `opencode.jsonc` 中添加插件:
|
|
112
73
|
|
|
113
74
|
```jsonc
|
|
114
75
|
{
|
|
115
76
|
"$schema": "https://opencode.ai/config.json",
|
|
116
77
|
"plugin": [
|
|
117
|
-
"@te-river/opencode-team-mode@
|
|
78
|
+
"@te-river/opencode-team-mode@latest"
|
|
118
79
|
]
|
|
119
80
|
}
|
|
120
81
|
```
|
|
121
82
|
|
|
122
|
-
|
|
83
|
+
OpenCode 启动时会自动安装插件。
|
|
84
|
+
|
|
85
|
+
> **提示:** 修改 `opencode.json` 后,**重启 OpenCode Desktop** 使配置生效。
|
|
123
86
|
|
|
124
|
-
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## ⚙️ 配置
|
|
90
|
+
|
|
91
|
+
插件会在 OpenCode 启动时自动注入所有团队 Agent 和命令,**无需手动复制任何 Agent 文件或命令定义**。
|
|
125
92
|
|
|
126
93
|
> ⚠️ **模型选择很重要。** 工作流里的每一个判断——分诊、拆解、派单、
|
|
127
94
|
> 整合、审查/测试闭环裁决——都经过 **Team Lead**。这个位置上放弱模型,
|
|
@@ -137,7 +104,7 @@ npm link
|
|
|
137
104
|
{
|
|
138
105
|
"$schema": "https://opencode.ai/config.json",
|
|
139
106
|
"plugin": [
|
|
140
|
-
"@te-river/opencode-team-mode@
|
|
107
|
+
"@te-river/opencode-team-mode@latest"
|
|
141
108
|
]
|
|
142
109
|
}
|
|
143
110
|
```
|
|
@@ -246,6 +213,119 @@ team 完成。
|
|
|
246
213
|
|
|
247
214
|
---
|
|
248
215
|
|
|
216
|
+
## 🧯 上下文治理(tm_* + R6 + R2)—— v1.5.1 起提供
|
|
217
|
+
|
|
218
|
+
> ⚠️ 需 `@te-river/opencode-team-mode@1.5.1` 或更新(2026-09-08 发布)。
|
|
219
|
+
> 配置里钉 `@latest` 的用户,下次启动自动升级。
|
|
220
|
+
|
|
221
|
+
**JIT 层 2 工具(`tm_read` / `tm_grep` / `tm_bash` / `tm_fetch`)。**
|
|
222
|
+
大体积工具输出是上下文成本的主要来源:智能体每走一步都要重发整个窗口。
|
|
223
|
+
tm_* 工具先用受治理的管线执行内置能力:超过 `TM_OFFLOAD_THRESHOLD`
|
|
224
|
+
token 的结果**不进窗口**——全量写入本地 run 存储,模型只拿一张句柄
|
|
225
|
+
“提货单”,附内容感知预览(JSON 键结构 / CSV 表头+形状 / 日志
|
|
226
|
+
ERROR×N 统计 / 代码签名清单 / 二进制元信息,硬上限 80 token)。
|
|
227
|
+
确实需要全文时,用 HMAC 签名、限本 run、带有效期的句柄经 `tm_fetch`
|
|
228
|
+
分段取回。`tm_bash` 仅放行只读命令白名单,失败以结构化错误返回。
|
|
229
|
+
|
|
230
|
+
**R6 环境变量保护(现已升级为审批门控)。** TeamMode 激活时,模型无法
|
|
231
|
+
静默读取环境变量。env 导出命令(`printenv`、`env`、`Get-ChildItem env:`
|
|
232
|
+
等)与环境文件(`.env`、shell rc 文件)会走 OpenCode **官方确认弹窗**:
|
|
233
|
+
你会在桌面收到一次原生确认,超过 `TM_ASK_TIMEOUT_MIN`(默认 10 分钟)
|
|
234
|
+
无人响应即**自动拒绝**——插件超时只会拒绝,绝不为模型自我放行。通配符
|
|
235
|
+
表达不了的形态(命令里内嵌的 `$VAR` / `${VAR}` / `$env:`、命令替换、
|
|
236
|
+
子 shell/转义写法)以及 `tm_*` 包装通道仍维持**代码级硬拦**(没有弹窗
|
|
237
|
+
可钻)。tm_* 包装工具同样过这套检查(不给包装层留后门)。审计日志只记
|
|
238
|
+
工具名 + 模式类别 + 裁决事件(`ask` / `allowed-once` / `allowed-always` /
|
|
239
|
+
`rejected` / `timeout-rejected` / `degraded`)——绝不记录命令文本、路径、
|
|
240
|
+
变量名或值。
|
|
241
|
+
|
|
242
|
+
**R2 危险操作(同一个确认弹窗)。** 删除(`rm`/`del`/`Remove-Item`/
|
|
243
|
+
`rmdir`)、git 发布(`git push`/`git commit`)、网络(`curl`/`wget`/
|
|
244
|
+
`Invoke-WebRequest`/`Invoke-RestMethod`)、包安装与发布(`npm install`/
|
|
245
|
+
`npm publish`/`pip install`/`winget`/`choco`)、进程/系统(`taskkill`/
|
|
246
|
+
`Stop-Process`/`kill`/`shutdown`/`format`)、权限(`chmod`/`takeown`/
|
|
247
|
+
`icacls`)——都不再静默放行,而是弹同一个官方确认框,超时未响应即自动
|
|
248
|
+
拒绝。日常验证栈(`npm test`、`tsc`、`git status`/`diff`)**不在**门控
|
|
249
|
+
之列,团队协作照常无打扰运行。
|
|
250
|
+
|
|
251
|
+
> ⚠️ **批准弹窗时请选 once(仅此一次),不要选 always。** 真实宿主实测:
|
|
252
|
+
> always 记录的泛化规则远比当次命令宽——对 `Get-ChildItem env:PATH` 选
|
|
253
|
+
> always 会记下 `Get-ChildItem *`,此后所有 `Get-ChildItem` 都不再弹窗。
|
|
254
|
+
> 只有 once 能让每次危险操作继续单独过人手。
|
|
255
|
+
|
|
256
|
+
> 延后是**按会话**生效的:只有运行 TeamMode 注入角色的会话(或已弹过这类
|
|
257
|
+
> 确认框的会话)里的 env 读取才会被放行给弹窗;其他会话(如原生
|
|
258
|
+
> `build`/`plan`)里守护仍然直接硬拦——那里根本没有弹窗兜底。宿主对复合
|
|
259
|
+
> 命令(`a; b`)按段评估、单次弹窗批准整条;任一子段是 env 读取时守护整条
|
|
260
|
+
> 拦截。
|
|
261
|
+
|
|
262
|
+
> 权限协议已在真实 `opencode serve` 宿主(1.18.29)上经 SSE 事件捕获实测
|
|
263
|
+
> 核验;桌面弹窗的渲染本身仍需在真实 Desktop 会话里目视确认一次。非交互
|
|
264
|
+
> `opencode run` 下,无人应答的 `ask` 会被立即自动拒绝(没有人类可弹)。
|
|
265
|
+
|
|
266
|
+
| 环境变量 | 默认 | 作用 |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| `TM_ENV_PROTECT` | `strict` | R6 模式:`strict` / `standard` / `off`(off 同时解除审批计时器) |
|
|
269
|
+
| `TM_ASK_TIMEOUT_MIN` | `10` | R6/R2 确认弹窗无人应答后自动拒绝的分钟数;最小 3 分钟(宿主的 `permission.replied` 经事件总线到达插件约延迟 ~120 秒——更小的值会把刚获批的请求误拒) |
|
|
270
|
+
| `TM_ENV_PROTECT_EXTRA_DENY` | — | 追加拦截正则(分号分隔;始终硬拦,不走弹窗) |
|
|
271
|
+
| `TM_OFFLOAD_THRESHOLD` | `2000` | 卸载阈值(token,chars/4 估算) |
|
|
272
|
+
| `TM_PREVIEW_MAX_TOKENS` | `80` | 预览硬上限 |
|
|
273
|
+
| `TM_FETCH_MAX_LINES` | `2000` | tm_fetch 单段上限 |
|
|
274
|
+
| `TM_BLACKBOARD_DIR` | `.blackboard/` | 卸载载荷存储 |
|
|
275
|
+
| `TM_TRAJECTORY_DIR` | `.trajectory/` | 只追加工具调用账本 |
|
|
276
|
+
| `TM_BLACKBOARD_TTL` | `7` | 存储保留天数 |
|
|
277
|
+
| `TM_BASH_READONLY_ALLOWED` | 内置表 | tm_bash 只读白名单 |
|
|
278
|
+
| `TM_PTC_MAX_PROGRAM_CHARS` | `4000` | PTC 程序源码长度上限(字符) |
|
|
279
|
+
| `TM_PTC_MAX_CALLS` | `20` | PTC 单次运行桥接调用数上限(1–200) |
|
|
280
|
+
| `TM_PTC_MAX_ERRORS` | `3` | PTC 单次运行错误数上限(1–50) |
|
|
281
|
+
| `TM_PTC_TIMEOUT_MS` | `60000` | PTC 单次运行墙钟超时(5 秒–10 分钟) |
|
|
282
|
+
| `TM_PTC_ENGINE` | `auto` | PTC 引擎:`auto`(worker→inline 降级)/ `worker` / `inline` |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## ⚡ 批量编排(`tm_ptc_run`)—— v1.5.2 起提供
|
|
287
|
+
|
|
288
|
+
> 已随 **v1.5.2**(2026-09-10)发布。需 `@te-river/opencode-team-mode@1.5.2` 或更新。
|
|
289
|
+
|
|
290
|
+
`tm_ptc_run` 让专家代理编写**一个异步程序**,在单次回合中执行 N 次受治理的
|
|
291
|
+
`tm_*` 调用——运行期间零 LLM 往返,仅将聚合摘要返回上下文。设计用于批量
|
|
292
|
+
只读任务:多文件侦察、批量 grep + read 聚合、交叉引用搜索结果。
|
|
293
|
+
|
|
294
|
+
### 工作原理
|
|
295
|
+
|
|
296
|
+
代理使用 `tm.read(args)`、`tm.grep(args)`、`tm.bash(args)`、`tm.fetch(args)`
|
|
297
|
+
编写程序体——参数与四个受治理工具相同。每次调用返回 `{ok:true, data}`(已受
|
|
298
|
+
治理:内联文本或卸载句柄)或 `{ok:false, error:{tool,phase,line?,message}}`。
|
|
299
|
+
程序 `return` 一个值;它会被 JSON 序列化进聚合摘要。
|
|
300
|
+
|
|
301
|
+
包含 `require`、`import`、`process`、`globalThis`、`Deno`、`Bun`、`fs`、`net`
|
|
302
|
+
或 `child_process` 的程序会在执行前被拒绝(静态预扫描,辅助防护)。
|
|
303
|
+
|
|
304
|
+
### 预算(仅收紧)
|
|
305
|
+
|
|
306
|
+
调用方可收紧 `max_calls`、`max_errors` 和 `timeout_ms`——超过 `TM_PTC_*` 上限
|
|
307
|
+
的值会被钳制到上限;低于下限的值会被钳制到下限。触达任一预算即整体停止运行;
|
|
308
|
+
已产出的输出不会丢失。
|
|
309
|
+
|
|
310
|
+
### 引擎(`TM_PTC_ENGINE`)
|
|
311
|
+
|
|
312
|
+
| 模式 | 行为 |
|
|
313
|
+
|---|---|
|
|
314
|
+
| `auto`(默认) | 优先尝试 `worker_threads`;失败时降级为 `node:vm`,摘要标记 `degraded-engine` |
|
|
315
|
+
| `worker` | 强制使用 worker 引擎(失败时返回 engine-error) |
|
|
316
|
+
| `inline` | 强制使用 `node:vm` 引擎(30 秒编译超时斩杀同步忙等;await 间隙残余已记录) |
|
|
317
|
+
|
|
318
|
+
worker 引擎在专用线程中运行程序,`env:{}` 清空 process.env、`resourceLimits`
|
|
319
|
+
限量、硬墙钟 `terminate()`。所有治理(P2 路径范围、P3 白名单、R6、阈值卸载、
|
|
320
|
+
TTL)对每次桥接调用生效——PTC 不是绕过层。
|
|
321
|
+
|
|
322
|
+
### 访问权限
|
|
323
|
+
|
|
324
|
+
五个专家代理(`implementer`、`tester`、`architect`、`reviewer`、`researcher`)
|
|
325
|
+
的白名单中包含 `tm_ptc_run`。`team` lead 不包含——它负责编排,不运行批量程序。
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
249
329
|
## 🏗️ 架构
|
|
250
330
|
|
|
251
331
|
```
|
|
@@ -253,14 +333,18 @@ opencode-team-mode/
|
|
|
253
333
|
├── package.json ← npm 包定义
|
|
254
334
|
├── tsconfig.json ← TypeScript 配置
|
|
255
335
|
├── src/
|
|
256
|
-
│ ├── index.ts ← 插件入口(server() +
|
|
336
|
+
│ ├── index.ts ← 插件入口(server():config + R6 tool.execute.before + 审批门 event 钩子 + tool 段)
|
|
257
337
|
│ ├── agents.ts ← Agent 定义(prompts、模式、颜色)
|
|
258
338
|
│ ├── commands.ts ← 命令定义(模板、Agent 绑定)
|
|
259
339
|
│ ├── blackboard.ts ← 共享黑板 + TTL 自动清理清扫器
|
|
340
|
+
│ ├── envprotect.ts ← R6 环境变量读取保护 + R2 确认弹窗模式集(弹窗 vs 硬拦)
|
|
341
|
+
│ ├── approval-gate.ts ← 统一审批门:官方弹窗超时自动拒绝(绝不自我放行)
|
|
342
|
+
│ ├── tm/ ← JIT 层 2 工具(tm_read / tm_grep / tm_bash / tm_fetch / tm_ptc_run)
|
|
260
343
|
│ └── types.ts ← 加载器契约类型定义(1.18.x)
|
|
261
344
|
├── scripts/
|
|
262
345
|
│ ├── install.sh ← 一键安装脚本(bash)
|
|
263
346
|
│ └── install.ps1 ← 一键安装脚本(PowerShell)
|
|
347
|
+
├── pt07/ ← PT-07 基线任务集(种子化 A/B token 测量)
|
|
264
348
|
├── LICENSE ← Apache 2.0
|
|
265
349
|
└── README.md ← 英文文档
|
|
266
350
|
README.zh-CN.md ← 中文文档
|
|
@@ -269,8 +353,8 @@ opencode-team-mode/
|
|
|
269
353
|
### 工作原理
|
|
270
354
|
|
|
271
355
|
1. OpenCode 桌面版启动,加载 `opencode.json(c)`
|
|
272
|
-
2. 检测到 `plugin` 数组中的 `"@te-river/opencode-team-mode@
|
|
273
|
-
3. 加载器调用插件的 `server(input, options)`,注册 `config` hook;hook 向合并后的配置注入 6 个 Agent 和 6
|
|
356
|
+
2. 检测到 `plugin` 数组中的 `"@te-river/opencode-team-mode@latest"`,加载 npm 包
|
|
357
|
+
3. 加载器调用插件的 `server(input, options)`,注册 `config` hook;hook 向合并后的配置注入 6 个 Agent 和 6 个命令。同一次调用还会安装 R6 的 `tool.execute.before` 防护、武装 R6/R2 统一审批门(官方确认弹窗 + `TM_ASK_TIMEOUT_MIN` 超时自动拒绝,经 `event` 钩子驱动),并注册受治理的 `tm_*` 工具(见下文“上下文治理”)
|
|
274
358
|
4. 插件的 `id: "team-mode"` 作为插件名显示在桌面版 UI
|
|
275
359
|
5. Agent 和命令立即在桌面版 UI 中可用 —— 无需复制任何文件;同名 Agent 以用户自定义优先(插件绝不覆盖)
|
|
276
360
|
|
|
@@ -353,7 +437,7 @@ Team Lead 不再删除任务目录 —— 跑完的黑板原地留给你回看
|
|
|
353
437
|
{
|
|
354
438
|
"$schema": "https://opencode.ai/config.json",
|
|
355
439
|
"plugin": [
|
|
356
|
-
["@te-river/opencode-team-mode@
|
|
440
|
+
["@te-river/opencode-team-mode@latest", { "ttlDays": 7 }]
|
|
357
441
|
]
|
|
358
442
|
}
|
|
359
443
|
```
|
|
@@ -372,7 +456,7 @@ TeamMode 默认**把 Team 设为你的默认代理**——新会话直接由团
|
|
|
372
456
|
```jsonc
|
|
373
457
|
{
|
|
374
458
|
"plugin": [
|
|
375
|
-
["@te-river/opencode-team-mode@
|
|
459
|
+
["@te-river/opencode-team-mode@latest", { "defaultAgent": false }]
|
|
376
460
|
]
|
|
377
461
|
}
|
|
378
462
|
```
|
package/dist/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAA;AAqpB9D,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAO9C,CAAA"}
|