@te-river/opencode-team-mode 1.8.1 → 1.8.3
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 +47 -38
- package/README.zh-CN.md +47 -36
- package/dist/host/v2-prune.d.ts +81 -1
- package/dist/host/v2-prune.d.ts.map +1 -1
- package/dist/host/v2-prune.js +303 -18
- package/dist/host/v2-prune.js.map +1 -1
- package/dist/host/v2-retry.d.ts +14 -4
- package/dist/host/v2-retry.d.ts.map +1 -1
- package/dist/host/v2-retry.js +22 -10
- package/dist/host/v2-retry.js.map +1 -1
- package/dist/host/v2-session.d.ts +8 -0
- package/dist/host/v2-session.d.ts.map +1 -1
- package/dist/host/v2-session.js +18 -5
- package/dist/host/v2-session.js.map +1 -1
- package/dist/host/v2-state.d.ts +165 -0
- package/dist/host/v2-state.d.ts.map +1 -0
- package/dist/host/v2-state.js +448 -0
- package/dist/host/v2-state.js.map +1 -0
- package/dist/host/v2-tail.d.ts +98 -0
- package/dist/host/v2-tail.d.ts.map +1 -0
- package/dist/host/v2-tail.js +191 -0
- package/dist/host/v2-tail.js.map +1 -0
- package/dist/host/v2-types.d.ts +2 -0
- package/dist/host/v2-types.d.ts.map +1 -1
- package/dist/host/v2-usage.d.ts +72 -2
- package/dist/host/v2-usage.d.ts.map +1 -1
- package/dist/host/v2-usage.js +142 -9
- package/dist/host/v2-usage.js.map +1 -1
- package/dist/host/v2.d.ts.map +1 -1
- package/dist/host/v2.js +187 -3
- package/dist/host/v2.js.map +1 -1
- package/dist/prompts/lead.d.ts +1 -1
- package/dist/prompts/lead.d.ts.map +1 -1
- package/dist/prompts/lead.js +12 -0
- package/dist/prompts/lead.js.map +1 -1
- package/dist/prompts/shared.d.ts +1 -1
- package/dist/prompts/shared.d.ts.map +1 -1
- package/dist/prompts/shared.js +5 -0
- package/dist/prompts/shared.js.map +1 -1
- package/dist/tm/config-layers.d.ts.map +1 -1
- package/dist/tm/config-layers.js +4 -0
- package/dist/tm/config-layers.js.map +1 -1
- package/dist/tm/config.d.ts +8 -0
- package/dist/tm/config.d.ts.map +1 -1
- package/dist/tm/config.js.map +1 -1
- package/dist/tm/pipelines.d.ts +9 -0
- package/dist/tm/pipelines.d.ts.map +1 -1
- package/dist/tm/pipelines.js +1 -1
- package/dist/tm/pipelines.js.map +1 -1
- package/dist/tm/stats.d.ts +11 -0
- package/dist/tm/stats.d.ts.map +1 -1
- package/dist/tm/stats.js +34 -1
- package/dist/tm/stats.js.map +1 -1
- package/docs/v2-port-notes.md +7 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## 📑 Contents
|
|
18
|
+
|
|
19
|
+
- [Why TeamMode](#-why-teammode)
|
|
20
|
+
- [The team](#-the-team)
|
|
21
|
+
- [Install](#-install)
|
|
22
|
+
- [Usage](#-usage)
|
|
23
|
+
- [JIT context and retry](#-jit-context-and-retry)
|
|
24
|
+
- [Governed tools & security](#-governed-tools--security)
|
|
25
|
+
- [Configuration](#️-configuration)
|
|
26
|
+
- [How the team works](#-how-the-team-works)
|
|
27
|
+
- [Customization](#-customization)
|
|
28
|
+
- [Troubleshooting](#-troubleshooting)
|
|
29
|
+
- [Uninstall](#️-uninstall)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
17
33
|
## TL;DR — skip the docs
|
|
18
34
|
|
|
19
35
|
> **The lazy path:** paste this to any coding agent and let it do the work:
|
|
@@ -30,7 +46,7 @@
|
|
|
30
46
|
> **The one command to remember afterwards:** `/team-run <task>` — the Team Lead
|
|
31
47
|
> plans it, shows you the plan, waits for your approval, then runs the whole team.
|
|
32
48
|
|
|
33
|
-
Everything else below is detail. When you're ready for it,
|
|
49
|
+
Everything else below is detail. When you're ready for it, the short version:
|
|
34
50
|
|
|
35
51
|
**[Why](#-why-teammode) · [The team](#-the-team) · [Install](#-install) · [Usage](#-usage) · [Tools & security](#-governed-tools--security) · [Configuration](#️-configuration) · [How it works](#-how-the-team-works) · [Troubleshooting](#-troubleshooting) · [Uninstall](#-uninstall)**
|
|
36
52
|
|
|
@@ -147,7 +163,7 @@ OpenCode installs the plugin on next startup.
|
|
|
147
163
|
|
|
148
164
|
### ⚠️ Read this once, save yourself an hour later
|
|
149
165
|
|
|
150
|
-
- **Restart to activate.** After touching the OpenCode config,
|
|
166
|
+
- **Restart to activate.** After touching the OpenCode config, restart OpenCode — `opencode service restart` is the official command, and on Desktop quitting from the tray (not just closing the window) also works. A restart is safe mid-session: the conversation survives, and only an in-flight tool call is aborted and has to be re-issued.
|
|
151
167
|
- **Plugin updates: re-run the installer.** It is idempotent — a re-run re-patches the config (no-op when present), purges the stale plugin cache, and re-resolves any npm-installed copy. This exists because OpenCode caches plugins by spec string and does NOT re-resolve `@latest` when a new version publishes (upstream limitation). Manual recipe, if you prefer:
|
|
152
168
|
|
|
153
169
|
| OS | Purge command — recursive, covers BOTH cache layouts |
|
|
@@ -268,6 +284,20 @@ as a structured skeleton — nothing landed in your repo, nothing was guessed.
|
|
|
268
284
|
|
|
269
285
|
---
|
|
270
286
|
|
|
287
|
+
## 🧠 JIT context and retry
|
|
288
|
+
|
|
289
|
+
*New in this release:* layered request-side context keeps a long session inside the window without deleting evidence, plus a retry ladder that says what it cannot do.
|
|
290
|
+
|
|
291
|
+
- **State card (lead only).** ≤300 tokens of ledger doing/blocked/todo items, running sub-agents and the board root, injected once per request. Hash-gated: an unchanged state re-emits the same bytes, so the prefix stays cacheable (`stateCard: "off"` removes the layer).
|
|
292
|
+
- **Lossless pruning.** Past 70% of the window (`pruneAtPercent`) a settled body becomes a one-line pointer — but only after it was offloaded and deduplicated against the run store, so the stub carries a real `tm_fetch` handle (`pruneOffload`). Reply skeleton, GOAL/ACCEPTANCE, provenance, system messages and the board note are never cut; `pruneProtectPatterns` lets your regexes outrank the budget.
|
|
293
|
+
- **Window entry.** A separate `[Team 窗口占用]` line reports `<bucket>% · model <id>`, bucketed to the nearest 5% so one bucket stays byte-identical. An unreadable window means the line is absent — never "0%".
|
|
294
|
+
- **Dynamic tail.** State card, window entry, retry directive and split advice merge into ONE message at the request's end, so `system` stops changing and prefix caching survives; `dynamicTail: "off"` restores the previous system injection.
|
|
295
|
+
- **Cache metering.** Each request that reports usage writes one `v2-cache` row (read / write / input / rate); `tm_stats` renders the **缓存命中** section with its denominator. No row means usage was never read — not a 0% hit.
|
|
296
|
+
- **Retry.** A throttle is classified by name and text, then answered by a per-request ladder — 5s / 10s / 20s / 40s / 60s, five rungs, never shared across requests; the host's own countdown wins when it has one. A sub-agent that spends its budget hands the work back; the main agent stops, reports and offers options. A hard quota is the billing family only and names no wait. When nothing continues by itself, one `session.synthetic` re-drive is admitted per rung.
|
|
297
|
+
- **A user stop is a scope change.** Land in-flight work first, skip verification, then hand over in four sections: 已落盘 / 未开始 / 验证 / 提交与发布.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
271
301
|
## 🧰 Governed tools & security
|
|
272
302
|
|
|
273
303
|
Every tool TeamMode adds runs under ONE governance pipeline: outputs above
|
|
@@ -605,7 +635,7 @@ the auto-create state.
|
|
|
605
635
|
|
|
606
636
|
When the global file is **absent**, the plugin creates it at boot — atomically,
|
|
607
637
|
idempotently, and **never overwriting an existing file**. What it writes is an
|
|
608
|
-
**inert** template: all **
|
|
638
|
+
**inert** template: all **64** registry keys, each as a *comment* under a
|
|
609
639
|
one-line description, so the file parses to `{}` and sets nothing until you
|
|
610
640
|
uncomment what you want.
|
|
611
641
|
|
|
@@ -614,7 +644,7 @@ uncomment what you want.
|
|
|
614
644
|
{
|
|
615
645
|
// "offloadThreshold": 2000, // 卸载阈值(估算 token;等于阈值也卸载)。
|
|
616
646
|
// "envProtect": "strict", // R6 环境防护模式(strict/standard/off)。(红线:仅全局)
|
|
617
|
-
// …共
|
|
647
|
+
// …共 64 个键,每个都带一行说明
|
|
618
648
|
}
|
|
619
649
|
```
|
|
620
650
|
|
|
@@ -676,7 +706,10 @@ Your own agents named `team` / `architect` / … always take precedence; the
|
|
|
676
706
|
plugin never clobbers user definitions. See [Customization](#-customization)
|
|
677
707
|
for overrides, extra agents and disabling roles.
|
|
678
708
|
|
|
679
|
-
### Key reference (all
|
|
709
|
+
### Key reference (all 64)
|
|
710
|
+
|
|
711
|
+
<details>
|
|
712
|
+
<summary>All 64 keys — click to expand</summary>
|
|
680
713
|
|
|
681
714
|
**Offload, previews and the store**
|
|
682
715
|
|
|
@@ -729,10 +762,14 @@ for overrides, extra agents and disabling roles.
|
|
|
729
762
|
| `prune` | `on`/`off` | `on` | Context pruning: replace a SETTLED message body with a self-explaining pointer (an offload handle, a child id, a note). Evidence is never destroyed — the reply skeleton, GOAL/ACCEPTANCE, provenance, system messages, a still-running child and an uncollected child id are protected whole, and the untouched messages stay byte-exact. `off` disables. |
|
|
730
763
|
| `pruneAtPercent` | number | `70` | Prune once the request reaches this share of the model's window, derived from `limit.context` — never a hard-coded token count. **Clamped to 40–90.** |
|
|
731
764
|
| `pruneKeepTailPercent` | number | `40` | Share of the window kept verbatim at the tail; the newest message is always kept. |
|
|
765
|
+
| `pruneOffload` | `on`/`off` | `on` | Offload a message body to the run store BEFORE its text is replaced, so the stub carries a full `tm_fetch { ref, access_token, expire_at }` handle — otherwise "prune" is permanent deletion of the body. A body an earlier request already stored reuses that handle (one payload, not one per request); a failed offload falls back to the echo note and is counted (`prune_offload_failed`), never thrown. `off` = today's behaviour: pointer only, the body is not kept. |
|
|
766
|
+
| `pruneProtectPatterns` | regex list (comma separated) | `""` | Protection regexes for pruning: a message whose text matches ANY entry is never pruned, and the hits are counted (`prune_protect_matched`). An invalid entry is ignored (it never disables the ones next to it and never throws); an empty string = off, which is byte-identical to the behaviour without this key. Patterns containing a comma cannot be expressed — split on `,` is the parser. |
|
|
767
|
+
| `stateCard` | `on`/`off` | `on` | 任务状态卡 — ONE ≤300-token system entry on the LEAD's request: ledger counts plus open items (oldest trimmed first), the running children that belong to THIS session (an empty session id renders no children row at all), a shortened board root, and last round's offloaded-message count. Unchanged bytes write nothing (the card is compared byte-for-byte; the `hash:` line is a visible marker). `off` does not register the layer. |
|
|
768
|
+
| `dynamicTail` | `on`/`off` | `on` | Volatile context (state card / window entry / retry directive / split advice) is merged into ONE message at the END of the request (first line `[Team 动态上下文]`, each section headed by `### <name>`, fixed order state → window → retry → advice), so `system` carries only stable content and the provider's prefix cache can hit. A message array reused across requests has its old tail stripped before the rebuild (nothing accumulates); an empty sink writes not a single byte. `off` = the old behaviour: each producer injects its own `system` entry, byte-identical. |
|
|
732
769
|
| `splitAdvice` | `on`/`off` | `on` | Inject a split suggestion when a dispatch brief carries too many acceptance criteria. `off` stops the hint (the prompt discipline stays). |
|
|
733
770
|
| `splitBriefTokens` | number | `4000` | The brief token threshold that triggers it. **Clamped to ≥200.** |
|
|
734
771
|
| `splitMaxCriteria` | number | `3` | More acceptance criteria than this is a signal to split. |
|
|
735
|
-
| `retry` | `on`/`off` | `on` | Retry governance on BOTH request-failure surfaces. **(1) The provider-error governor — a PER-REQUEST retry chain:** each session's own failing request earns `retryMaxRetries` (5) retries waiting **5s/10s/20s/40s/60s** (base doubling to `retryMaxMs`, `retryJitter` default `0`), cumulative WITHIN that request — never across a session's lifetime. Chains are isolated per session (a child's failures never advance the lead's ladder), directives are delivered only to the session that earned them, and a chain ends on `session.idle`, `retryChainGapMs` of quiet, or budget exhaustion (a later error starts a fresh chain). **Sub-agent vs main agent:** a child whose budget is spent is told to hand the work back, and the LEAD receives a notice to run that step itself; the main agent is told to stop and report with options. Injected text names the retry index. A **hard quota** (
|
|
772
|
+
| `retry` | `on`/`off` | `on` | Retry governance on BOTH request-failure surfaces. **(1) The provider-error governor — a PER-REQUEST retry chain:** each session's own failing request earns `retryMaxRetries` (5) retries waiting **5s/10s/20s/40s/60s** (base doubling to `retryMaxMs`, `retryJitter` default `0`), cumulative WITHIN that request — never across a session's lifetime. Chains are isolated per session (a child's failures never advance the lead's ladder), directives are delivered only to the session that earned them, and a chain ends on `session.idle`, `retryChainGapMs` of quiet, or budget exhaustion (a later error starts a fresh chain). **Sub-agent vs main agent:** a child whose budget is spent is told to hand the work back, and the LEAD receives a notice to run that step itself; the main agent is told to stop and report with options. Injected text names the retry index. A **hard quota** (the BILLING family only: `insufficient balance` / 余额不足 / 欠费 / `insufficient_quota` / billing texts) names NO wait — stop and raise-or-reset — and trips the breaker on the SECOND consecutive error; **alibaba's `Allocated quota exceeded … error-code#token-limit` is a TRANSIENT per-minute throttle (user correction 2026-10-21) and rides the ladder and the re-drive**, while a structured `retryAfterMs` is honoured as the wait floor. **(2) The HTTP layer:** a failed request inside `tm_webfetch` / every `tm_search` engine leg (network throw, per-request timeout, HTTP 429 or 5xx) is re-asked up to 3 times on the same 5s/10s/20s rungs, and the reply labels it (`第N次重试后成功` / `重试3次…仍失败`). A policy refusal (off-allowlist, red line, env-file URL, 403/418, other 4xx) is never re-asked. **The host's own retries win:** `session.retry.scheduled` — the desktop's 「尝试 N - 在 X 秒内重试」 countdown — stands our ladder directive down while the host is retrying, and our guidance speaks only when it does not (hard quota / spent budget). **③ The plugin re-drives dead sessions itself:** when a rung's wait is over and nobody continued, the layer admits a synthetic continuation via `ctx.session.synthetic` (verified callable on 2.1.2: "admit synthetic session input and schedule execution") — one per rung within `retryMaxRetries`, never for a session the scope has not seen, cancelled the moment the host retries or the session assembles a request on its own; hard quota re-drives only at a provider-stated retry time. Honest boundary: a plugin cannot intercept the model's own retry — but it can re-drive execution. |
|
|
736
773
|
| `retryBaseMs` | number | `5000` | First rung of the ladder: retry #1 waits 5s, then doubling. |
|
|
737
774
|
| `retryMaxMs` | number | `60000` | Ceiling for that backoff (rungs 4/5 rest on 40s/60s with the defaults). |
|
|
738
775
|
| `retryMaxRetries` | number | `5` | How many retries ONE request earns before its chain stops (5 → 5s/10s/20s/40s/60s). |
|
|
@@ -769,6 +806,8 @@ for overrides, extra agents and disabling roles.
|
|
|
769
806
|
| `shellEnv` | `""` | v1-only |
|
|
770
807
|
| `ptcWebBridge` | `on` | v1-only |
|
|
771
808
|
|
|
809
|
+
</details>
|
|
810
|
+
|
|
772
811
|
> **Compaction timing belongs to the host, not to this plugin.** An earlier
|
|
773
812
|
> release triggered its own summarization at 75% of the window; that was removed
|
|
774
813
|
> by user decision — a plugin that summarizes a live conversation by itself
|
|
@@ -951,39 +990,9 @@ No DLLs were harmed. Nothing was written to your working tree.
|
|
|
951
990
|
|
|
952
991
|
## 🏛️ Architecture (for the curious)
|
|
953
992
|
|
|
954
|
-
|
|
955
|
-
opencode-team-mode/
|
|
956
|
-
├── src/
|
|
957
|
-
│ ├── index.ts ← Plugin entry ({id, setup} — v2 only)
|
|
958
|
-
│ ├── agents.ts ← Agent structure (modes, colors, temperatures, whitelist matrix)
|
|
959
|
-
│ ├── prompts/ ← Agent prompts (lead / specialists / shared) — pinned by tests
|
|
960
|
-
│ ├── commands.ts ← Slash command definitions
|
|
961
|
-
│ ├── blackboard.ts ← Shared blackboard + TTL sweeper
|
|
962
|
-
│ ├── envprotect.ts ← R6 facade (patterns / classifiers / gate predicates / hook)
|
|
963
|
-
│ ├── identity.ts ← Agent-name identity (case-insensitive lead match)
|
|
964
|
-
│ ├── tm/ ← Governed tools: pipelines / store / preview / guard / refs /
|
|
965
|
-
│ │ config-layers (the 58-key registry) / config-files (the two
|
|
966
|
-
│ │ layers) / config-template (the inert auto-created file) /
|
|
967
|
-
│ │ webfetch / search / memory / board / ledger / dispatch
|
|
968
|
-
│ ├── host/ ← v2 personality (setup / guard / offload / session / events / …)
|
|
969
|
-
│ └── types.ts ← Loader-contract types
|
|
970
|
-
├── docs/installation.md ← Historical 1.18.x guide (no longer supported)
|
|
971
|
-
├── docs/installation-v2.md ← The 2.x install guide (roles arrive as generated config files)
|
|
972
|
-
├── scripts/ ← One-line installers (bash / PowerShell)
|
|
973
|
-
├── pt07/ ← PT-07 baseline suite (seeded A/B token measurement)
|
|
974
|
-
└── README.*.md ← You are here (twice)
|
|
975
|
-
```
|
|
976
|
-
|
|
977
|
-
The loader calls `setup(ctx)` once: it registers the `tm_*` tools, resolves the
|
|
978
|
-
two config layers, installs the R6/address guard on `permission.evaluate`, attaches
|
|
979
|
-
the JIT offload on `tool.execute.after`, and publishes the blackboard note. User-defined
|
|
980
|
-
agents with the same name always win — the plugin never clobbers.
|
|
993
|
+
The package exports `{id, setup}` and nothing else. The loader calls `setup(ctx)` once: it registers the `tm_*` tools, resolves the two config layers, arms the R6 / address guard on `permission.evaluate`, attaches JIT governance on `tool.execute.after`, and publishes the blackboard note — and user-defined agents with the same name always win. One rule keeps the config layer honest: **`CONFIG_KEYS` is the registry and the single source of truth**, so a key absent from it is reported as unknown and never applied, and the red-line set is derived from that registry rather than hand-listed.
|
|
981
994
|
|
|
982
|
-
The
|
|
983
|
-
registry and the single source of truth.** A key absent from it is reported as
|
|
984
|
-
unknown and never applied; the red-line set is derived from that registry rather
|
|
985
|
-
than hand-listed; and the auto-created global file is rendered *from* the
|
|
986
|
-
registry, so it cannot drift from what the code actually reads.
|
|
995
|
+
The module map, the per-layer seams and every measured host fact are in [AGENTS.md](./AGENTS.md); the dated evidence behind each v2 claim is in [docs/v2-port-notes.md](./docs/v2-port-notes.md). `pt07/` holds the PT-07 baseline suite (seeded A/B token measurement); `scripts/` the one-line installers.
|
|
987
996
|
|
|
988
997
|
---
|
|
989
998
|
|
package/README.zh-CN.md
CHANGED
|
@@ -14,6 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## 📑 目录
|
|
18
|
+
|
|
19
|
+
- [为什么是 TeamMode](#-为什么是-teammode)
|
|
20
|
+
- [团队阵容](#-团队阵容)
|
|
21
|
+
- [安装](#-安装)
|
|
22
|
+
- [使用](#-使用)
|
|
23
|
+
- [JIT 上下文与重试](#-jit-上下文与重试)
|
|
24
|
+
- [受治理的工具与安全](#-受治理的工具与安全)
|
|
25
|
+
- [配置](#️-配置)
|
|
26
|
+
- [团队怎么运作](#-团队怎么运作)
|
|
27
|
+
- [自定义](#-自定义)
|
|
28
|
+
- [故障排查](#-故障排查)
|
|
29
|
+
- [卸载](#️-卸载)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
17
33
|
## 太长不看
|
|
18
34
|
|
|
19
35
|
> **懒人路径:** 把下面这段话粘给任意编码 agent,让它替你装:
|
|
@@ -28,7 +44,7 @@
|
|
|
28
44
|
> **装好后只需要记住一条命令:** `/team-run <任务>` —— Team Lead 会先出计划、
|
|
29
45
|
> 等你批准、然后调度整个团队干活。
|
|
30
46
|
|
|
31
|
-
|
|
47
|
+
剩下的都是细节。想看的时候,简短版:
|
|
32
48
|
|
|
33
49
|
**[为什么](#-为什么是-teammode) · [团队阵容](#-团队阵容) · [安装](#-安装) · [使用](#-使用) · [工具与安全](#-受治理的工具与安全) · [配置](#️-配置) · [运作方式](#-团队怎么运作) · [故障排查](#-故障排查) · [卸载](#️-卸载)**
|
|
34
50
|
|
|
@@ -138,7 +154,7 @@ OpenCode 会在下次启动时自己安装这个插件。
|
|
|
138
154
|
|
|
139
155
|
### ⚠️ 现在读一遍,以后省一小时
|
|
140
156
|
|
|
141
|
-
- **重启才生效。** 改完 OpenCode
|
|
157
|
+
- **重启才生效。** 改完 OpenCode 配置后重启 OpenCode——官方命令是 `opencode service restart`;桌面版从托盘退出(而不是只关窗口)也行。中途重启是安全的:会话会活下来,只有正在飞的那个工具调用会被中断、需要重发。
|
|
142
158
|
- **插件更新:重跑安装脚本。** 它是幂等的——重跑会重新改配置(已存在则不动)、
|
|
143
159
|
清掉过期插件缓存、并重新解析任何 npm 安装的副本。之所以要这样做,是因为
|
|
144
160
|
OpenCode 按 spec 字符串缓存插件,新版本发布后**不会**重新解析 `@latest`(上游限制)。
|
|
@@ -263,6 +279,20 @@ team 完成。rateLimit.ts(新增)· app.ts(+3)· 14 个测试全绿
|
|
|
263
279
|
|
|
264
280
|
---
|
|
265
281
|
|
|
282
|
+
## 🧠 JIT 上下文与重试
|
|
283
|
+
|
|
284
|
+
*本次新增:* 请求侧的分层上下文让长会话留在窗口里而不删掉证据,外加一条把边界说清楚的重试阶梯。
|
|
285
|
+
|
|
286
|
+
- **状态卡(仅领队)。** 每次请求注入 ≤300 token 的当前状态:账本的进行/阻塞/待办、运行中的子代理、看板根。hash 门控——状态没变就一个字节都不变,前缀因此仍然可缓存(`stateCard: "off"` 不注册该层)。
|
|
287
|
+
- **无损修剪。** 超过窗口 70%(`pruneAtPercent`)后,已结算的消息正文换成一行指针——但先离载并与 run 存储去重,所以 stub 带着真正的 `tm_fetch` 句柄(`pruneOffload`)。回复骨架、GOAL/ACCEPTANCE、来源说明、system 消息和黑板注记永不裁剪;`pruneProtectPatterns` 让你的正则优先于预算。
|
|
288
|
+
- **窗口占用条目。** 独立的 `[Team 窗口占用]` 条报出 `<bucket>% · 模型 <id>`,按最近 5% 分桶,同一档位逐字节稳定。读不到窗口 = 整条不显示,绝不说成 "0%"。
|
|
289
|
+
- **动态尾层。** 状态卡、窗口条目、重试指令、拆分建议合并成请求末尾的一条消息,`system` 不再变化,前缀缓存得以命中;`dynamicTail: "off"` 恢复此前的 system 注入。
|
|
290
|
+
- **缓存命中计量。** 每个读到 usage 的请求写一行 `v2-cache`(read / write / input / 命中率),`tm_stats` 以**缓存命中**一节渲染并写明分母。没有这一行 = 没读到 usage,不是 0% 命中。
|
|
291
|
+
- **重试。** 限流按名字和文本分类后,用同请求内的阶梯回答:5s / 10s / 20s / 40s / 60s 共五档,跨请求不累计;宿主自己排了倒计时就以宿主为准。子代理耗尽预算时把活交回来,主代理停下、报告、给选项;hard quota 只认账单族、不给等待。没人继续时,每档允许一次 `session.synthetic` 重驱动。
|
|
292
|
+
- **用户急停是范围变更。** 先落盘在飞的工作、跳过验证,按四段交接:已落盘 / 未开始 / 验证 / 提交与发布。
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
266
296
|
## 🧰 受治理的工具与安全
|
|
267
297
|
|
|
268
298
|
TeamMode 加的每个工具都跑在**同一条治理管线**下:超过卸载阈值的输出永不
|
|
@@ -527,7 +557,7 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
|
|
|
527
557
|
### 它会自己写一份
|
|
528
558
|
|
|
529
559
|
全局文件**不存在**时,插件在启动时创建它——原子、幂等,且**绝不覆盖已存在的
|
|
530
|
-
文件**。写进去的是一份**惰性**模板:全部 **
|
|
560
|
+
文件**。写进去的是一份**惰性**模板:全部 **64** 个注册表键,每个都以*注释*
|
|
531
561
|
形式出现在一行说明下面,所以这个文件解析出来是 `{}`,在你取消注释之前什么
|
|
532
562
|
都不设置。
|
|
533
563
|
|
|
@@ -536,7 +566,7 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
|
|
|
536
566
|
{
|
|
537
567
|
// "offloadThreshold": 2000, // 卸载阈值(估算 token;等于阈值也卸载)。
|
|
538
568
|
// "envProtect": "strict", // R6 环境防护模式(strict/standard/off)。(红线:仅全局)
|
|
539
|
-
// …共
|
|
569
|
+
// …共 64 个键,每个都带一行说明
|
|
540
570
|
}
|
|
541
571
|
```
|
|
542
572
|
|
|
@@ -594,7 +624,10 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
|
|
|
594
624
|
你自己叫 `team` / `architect` / … 的 agent 永远优先——插件从不覆盖用户定义。
|
|
595
625
|
覆盖、加自己的 agent、停用角色见[自定义](#-自定义)。
|
|
596
626
|
|
|
597
|
-
### 键参考(共
|
|
627
|
+
### 键参考(共 64 个)
|
|
628
|
+
|
|
629
|
+
<details>
|
|
630
|
+
<summary>全部 64 个键 — 点击展开</summary>
|
|
598
631
|
|
|
599
632
|
**卸载、预览与存储**
|
|
600
633
|
|
|
@@ -647,10 +680,14 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
|
|
|
647
680
|
| `prune` | `on`/`off` | `on` | 上下文裁剪:把**已结算**的消息正文替换成一个自解释的指针(卸载句柄、子代理 id、说明)。证据绝不被销毁——回复骨架、GOAL/ACCEPTANCE、来源说明、系统消息、仍在跑的子代理、尚未收集的子代理 id 全部完整保留,被动的消息逐字节不变。`off` 关闭。 |
|
|
648
681
|
| `pruneAtPercent` | number | `70` | 请求达到模型窗口的这份占比时开始裁剪,由 `limit.context` 推导——绝不是写死的 token 数。**夹在 40–90。** |
|
|
649
682
|
| `pruneKeepTailPercent` | number | `40` | 尾部逐字保留的窗口占比;最新一条消息永远保留。 |
|
|
683
|
+
| `pruneOffload` | `on`/`off` | `on` | 修剪**前**先把消息体离载到 run store,stub 里带完整的 `tm_fetch { ref, access_token, expire_at }` 句柄——否则「裁剪」就是永久删正文。同一段正文若已被上一次请求存过,直接复用那个句柄(一份载荷,不是一请求一份);离载失败退回纯注记并计数(`prune_offload_failed` 轨迹行),绝不外抛。`off` = 今日行为:只留指针,原文不保留。 |
|
|
684
|
+
| `pruneProtectPatterns` | 正则列表(逗号分隔) | `""` | 修剪保护正则:命中任一条的消息**永不修剪**,命中条数计入 `prune_protect_matched`。无效正则被忽略(不连累邻居、不抛错);空串 = 关闭,与不带此键的行为逐字节一致。正则本身若含逗号无法表达——解析就是按 `,` 切分。 |
|
|
685
|
+
| `stateCard` | `on`/`off` | `on` | 任务状态卡——lead 的请求上带**一条 ≤300 token** 的 system 条目:账本计数 + 未收口项(最旧先裁)、**本会话**运行中的子代理(空 sessionID 时整行省略)、缩短过的看板根、上轮离载条数。内容逐字节不变时一个字节都不写(比较用整串,`hash:` 行只是可见标记)。`off` = 该层不注册。 |
|
|
686
|
+
| `dynamicTail` | `on`/`off` | `on` | 易变上下文(状态卡 / 窗口占用 / 重试指令 / 拆分建议)合并成**请求末尾的一条消息**(首行 `[Team 动态上下文]`,各段前一行 `### <段名>`,顺序固定 state → window → retry → advice),`system` 只留稳定内容——provider 的前缀缓存因此能命中。宿主跨请求复用消息数组时先剥掉旧尾部再重建(不累积);sink 为空时一个字节都不动。`off` = 旧行为:四个生产者各自注入 `system`,逐字节与改动前一致。 |
|
|
650
687
|
| `splitAdvice` | `on`/`off` | `on` | 派工简报的验收标准过多时注入拆分建议。`off` 停掉这条提示(提示词纪律仍在)。 |
|
|
651
688
|
| `splitBriefTokens` | number | `4000` | 触发拆分建议的简报 token 阈值。**夹在 ≥200。** |
|
|
652
689
|
| `splitMaxCriteria` | number | `3` | 验收标准多于这个数就是该拆的信号。 |
|
|
653
|
-
| `retry` | `on`/`off` | `on` | 两个「请求失败」表面上的重试治理。**(1) provider 错误治理器——按请求重试链:** 每个会话自己那条失败请求,累计获得 `retryMaxRetries`(5)次重试,依次等 **5s/10s/20s/40s/60s**(基数翻倍、`retryMaxMs` 封顶、`retryJitter` 默认 0)——**同一次请求内**累计,绝不跨会话生命周期。链按会话隔离(子代理的失败不会推进主代理的阶梯),指令只投递给挣得它的会话;链在 `session.idle`、`retryChainGapMs` 静默、或预算耗尽时结束(之后再来的错误开新链)。**子代理 vs 主代理:** 子代理预算耗尽 → 收到「把工作交回主代理」,同时**主代理收到「自己执行这一步」的通知**;主代理耗尽 → 停止重试并向用户如实报告并给选项。注入文本写明重试序号。**hard quota
|
|
690
|
+
| `retry` | `on`/`off` | `on` | 两个「请求失败」表面上的重试治理。**(1) provider 错误治理器——按请求重试链:** 每个会话自己那条失败请求,累计获得 `retryMaxRetries`(5)次重试,依次等 **5s/10s/20s/40s/60s**(基数翻倍、`retryMaxMs` 封顶、`retryJitter` 默认 0)——**同一次请求内**累计,绝不跨会话生命周期。链按会话隔离(子代理的失败不会推进主代理的阶梯),指令只投递给挣得它的会话;链在 `session.idle`、`retryChainGapMs` 静默、或预算耗尽时结束(之后再来的错误开新链)。**子代理 vs 主代理:** 子代理预算耗尽 → 收到「把工作交回主代理」,同时**主代理收到「自己执行这一步」的通知**;主代理耗尽 → 停止重试并向用户如实报告并给选项。注入文本写明重试序号。**hard quota**(仅账单族:`insufficient balance` / 余额不足 / 欠费 / `insufficient_quota` / billing 类文案)不命名等待——停止并等充值/提额——连续第 2 次即触发断路器;**alibaba 的 `Allocated quota exceeded … error-code#token-limit` 是瞬时限流(分钟窗口会滚回,用户更正 2026-10-21),走阶梯与 ③ 重驱动**;宿主 2.1.2 的结构化 `retryAfterMs` 作为等待下限。**(2) HTTP 层:** `tm_webfetch` 与每条 `tm_search` 引擎腿里失败的请求(网络抛出、单次超时、HTTP 429/5xx)按同一 5s/10s/20s 阶梯最多重问 3 次,回复如实标注(`第N次重试后成功` / `重试3次…仍失败`)。政策性拒绝(白名单外、红线地址、env-file URL、403/418、其它 4xx)绝不重问。**宿主自己的重试优先:** `session.retry.scheduled`(桌面的「尝试 N - 在 X 秒内重试」)存在时我们的等待指令让位,只在宿主不重试的场景(hard quota/预算耗尽)说话。**③ 插件自己复活死掉的会话:** 某一档等待结束而无人继续时,层通过 `ctx.session.synthetic` 注入一条合成续跑(2.1.2 实测可调用:"admit synthetic session input and schedule execution")——每档一次、上限 `retryMaxRetries`、作用域没见过的会话绝不注入、宿主自己重试或会话自己发起请求时立即取消;hard quota 只有在服务端给出重试时间时才重驱动。老实的边界:插件拦不住模型自己的重试——但它能重新驱动执行。 |
|
|
654
691
|
| `retryBaseMs` | number | `5000` | 阶梯第一级:第 1 次重试等 5s,之后翻倍。 |
|
|
655
692
|
| `retryMaxMs` | number | `60000` | 退避上限(默认下第 4/5 级落在 40s/60s)。 |
|
|
656
693
|
| `retryMaxRetries` | number | `5` | 一条请求最多重试几次(5 → 5s/10s/20s/40s/60s);耗尽即停。 |
|
|
@@ -687,6 +724,8 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
|
|
|
687
724
|
| `shellEnv` | `""` | 仅 v1 |
|
|
688
725
|
| `ptcWebBridge` | `on` | 仅 v1 |
|
|
689
726
|
|
|
727
|
+
</details>
|
|
728
|
+
|
|
690
729
|
> **压缩时机归宿主,不归本插件。** 早先某个版本在窗口 75% 时自己触发摘要;
|
|
691
730
|
> 那已按用户决定移除——一个自己给活跃对话做摘要的插件,是在执行一个你没要求的
|
|
692
731
|
> 丢上下文动作。留下的是纯增量的部分,且只在**宿主**压缩时运行:必须存活的
|
|
@@ -851,37 +890,9 @@ OpenCode 按 spec 字符串缓存插件,从不重新解析 `@latest`(上游
|
|
|
851
890
|
|
|
852
891
|
## 🏛️ 架构(给好奇的人)
|
|
853
892
|
|
|
854
|
-
|
|
855
|
-
opencode-team-mode/
|
|
856
|
-
├── src/
|
|
857
|
-
│ ├── index.ts ← 插件入口({id, setup}——仅 v2)
|
|
858
|
-
│ ├── agents.ts ← Agent 结构(mode、颜色、温度、白名单矩阵)
|
|
859
|
-
│ ├── prompts/ ← Agent 提示词(lead / specialists / shared)——测试钉死
|
|
860
|
-
│ ├── commands.ts ← 斜杠命令定义
|
|
861
|
-
│ ├── blackboard.ts ← 共享黑板 + TTL 清扫
|
|
862
|
-
│ ├── envprotect.ts ← R6 门面(patterns / 分类器 / 门禁谓词 / hook)
|
|
863
|
-
│ ├── identity.ts ← Agent 名身份(大小写不敏感的 lead 判定)
|
|
864
|
-
│ ├── tm/ ← 受治理工具:pipelines / store / preview / guard / refs /
|
|
865
|
-
│ │ config-layers(58 键注册表)/ config-files(那两层)/
|
|
866
|
-
│ │ config-template(自动创建的那份惰性文件)/
|
|
867
|
-
│ │ webfetch / search / memory / board / ledger / dispatch
|
|
868
|
-
│ ├── host/ ← v2 人格(setup / guard / offload / session / events / …)
|
|
869
|
-
│ └── types.ts ← 加载器契约类型
|
|
870
|
-
├── docs/installation.md ← 历史 1.18.x 指南(已不再支持)
|
|
871
|
-
├── docs/installation-v2.md ← 2.x 安装指南(角色以生成的配置文件形式落地)
|
|
872
|
-
├── scripts/ ← 一行安装脚本(bash / PowerShell)
|
|
873
|
-
├── pt07/ ← PT-07 基线套件(种子化 A/B token 测量)
|
|
874
|
-
└── README.*.md ← 你在这里(有两个版本)
|
|
875
|
-
```
|
|
876
|
-
|
|
877
|
-
加载器只调一次 `setup(ctx)`:注册 `tm_*` 工具、解析那两层配置、在
|
|
878
|
-
`permission.evaluate` 上装 R6/地址守卫、在 `tool.execute.after` 上挂
|
|
879
|
-
JIT 卸载、并发布黑板注记。用户自定义的同名 agent 永远赢——插件从不覆盖。
|
|
893
|
+
包只导出 `{id, setup}`。加载器调一次 `setup(ctx)`:注册 `tm_*` 工具、解析那两层配置、在 `permission.evaluate` 上装 R6/地址守卫、在 `tool.execute.after` 上挂 JIT 治理、并发布黑板注记——你自定义的同名 agent 永远优先。让这层配置值得信任的规则只有一条:**`CONFIG_KEYS` 就是注册表,也是唯一事实来源**,不在里面的键会被报成未知且永不应用,红线集合由这个注册表推导而不是手工列一遍。
|
|
880
894
|
|
|
881
|
-
|
|
882
|
-
事实来源。** 不在它里面的键会被报成未知且永不应用;红线集合由这个注册表
|
|
883
|
-
推导而不是手工列一遍;自动创建的全局文件也是**从**它渲染出来的,所以不可能
|
|
884
|
-
与代码真正读取的东西产生漂移。
|
|
895
|
+
模块地图(每个文件的接缝、它回答的问题)、实测到的宿主事实,都在 [AGENTS.md](./AGENTS.md);每条 v2 论断背后的带日期证据在 [docs/v2-port-notes.md](./docs/v2-port-notes.md)。`pt07/` 是 PT-07 基线套件(种子化 A/B token 测量),`scripts/` 是一行安装脚本。
|
|
885
896
|
|
|
886
897
|
---
|
|
887
898
|
|
package/dist/host/v2-prune.d.ts
CHANGED
|
@@ -21,6 +21,19 @@
|
|
|
21
21
|
* protected STRING: the message may be pruned, but the stub must carry the
|
|
22
22
|
* handle verbatim, which is exactly the "keep the pointer, drop the body"
|
|
23
23
|
* contract.
|
|
24
|
+
* - **Nothing leaves that cannot be recovered.** A message carrying no handle
|
|
25
|
+
* of its own is offloaded to the run store BEFORE its body is replaced, so
|
|
26
|
+
* the stub carries a full `tm_fetch` handle (`pruneOffload`, default on). A
|
|
27
|
+
* failed offload falls back to today's echo note, one message at a time —
|
|
28
|
+
* losing a body is data loss, losing an offload is a counter. A stub with no
|
|
29
|
+
* handle to offer still carries the ADDRESSES the body named (board paths,
|
|
30
|
+
* `file:line`, URLs; at most three, deduplicated, in document order), because a
|
|
31
|
+
* pointer the reader can act on is the whole point of keeping one — and that
|
|
32
|
+
* scan is SINGLE-PASS and linear in the body length, not three global regexes
|
|
33
|
+
* over the whole text (which went quadratic on a long word run).
|
|
34
|
+
* - **A user pattern outranks the budget** (`pruneProtectPatterns`): a message
|
|
35
|
+
* whose text matches any compiled entry is never pruned, and the matches are
|
|
36
|
+
* counted (`protectMatched`) instead of silently changing the saving figure.
|
|
24
37
|
* - **The threshold is derived, never hard-coded.** `TM_PRUNE_AT_PERCENT`
|
|
25
38
|
* (default 70) of `limit.context`, the same denominator the desktop's own
|
|
26
39
|
* usage meter reads. No `limit.context` → no prune, counted `no_limit`.
|
|
@@ -40,11 +53,24 @@ export interface PruneConfig {
|
|
|
40
53
|
atPercent: number;
|
|
41
54
|
/** Percent of `limit.context` kept verbatim at the tail (clamped 0–90). */
|
|
42
55
|
keepTailPercent: number;
|
|
56
|
+
/**
|
|
57
|
+
* User-supplied protection regexes (`pruneProtectPatterns`, comma separated).
|
|
58
|
+
* A message whose text matches ANY of them is never pruned. Empty = off, and
|
|
59
|
+
* that is the byte-identical path: the list is consulted only when non-empty.
|
|
60
|
+
*/
|
|
61
|
+
protectPatterns: RegExp[];
|
|
43
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Compile the comma-separated pattern list. One invalid pattern loses only
|
|
65
|
+
* itself (a typo must not disable the ones next to it, and must never throw into
|
|
66
|
+
* the request path); an empty / absent value compiles to `[]` = off.
|
|
67
|
+
*/
|
|
68
|
+
export declare function parseProtectPatterns(raw: unknown): RegExp[];
|
|
44
69
|
export declare function resolvePruneConfig(config?: {
|
|
45
70
|
prune: string;
|
|
46
71
|
pruneAtPercent: number;
|
|
47
72
|
pruneKeepTailPercent: number;
|
|
73
|
+
pruneProtectPatterns?: string;
|
|
48
74
|
}): PruneConfig;
|
|
49
75
|
interface TextSlot {
|
|
50
76
|
container: Record<string, unknown>;
|
|
@@ -86,13 +112,43 @@ export interface PruneHandle {
|
|
|
86
112
|
ref: string;
|
|
87
113
|
accessToken: string;
|
|
88
114
|
expireAt: number;
|
|
115
|
+
/** Set when the wiring recognised this body and handed back an EXISTING handle. */
|
|
116
|
+
reused?: boolean;
|
|
89
117
|
}
|
|
118
|
+
/** 地址行最多留几条——再多就不是「地址」,而是正文摘抄。 */
|
|
119
|
+
export declare const PRUNE_ADDRESS_MAX = 3;
|
|
120
|
+
/** 地址行的前缀;整行只在真的抽到地址时出现。 */
|
|
121
|
+
export declare const PRUNE_ADDRESS_PREFIX = "\u5730\u5740\uFF1A";
|
|
122
|
+
/**
|
|
123
|
+
* 单个 token 的字符上限。 超过它的不是地址,是正文——这条上限也是性能闸门:
|
|
124
|
+
* 长词串整段跳过,永远不会进到正则里。
|
|
125
|
+
*/
|
|
126
|
+
export declare const PRUNE_ADDRESS_TOKEN_MAX = 2048;
|
|
127
|
+
/**
|
|
128
|
+
* The addresses a pruned body carried, in DOCUMENT ORDER, deduplicated, at most
|
|
129
|
+
* `PRUNE_ADDRESS_MAX`. Pure, and it only ever yields the address itself — never a
|
|
130
|
+
* fragment of the body around it, because the stub is a pointer, not a summary.
|
|
131
|
+
*
|
|
132
|
+
* LINEAR BY CONSTRUCTION (this is a performance contract, not a style note): the
|
|
133
|
+
* text is walked ONCE, token by token, and every pattern is anchored to a single
|
|
134
|
+
* token. The previous version ran three GLOBAL regexes over the whole body and
|
|
135
|
+
* blanked each URL match by rebuilding the string — quadratic on a long word run
|
|
136
|
+
* (`"a".repeat(200000)` was hundreds of seconds) and O(k·n) with many URLs. A
|
|
137
|
+
* token longer than `PRUNE_ADDRESS_TOKEN_MAX` is skipped without touching a regex.
|
|
138
|
+
*
|
|
139
|
+
* A longer address that CONTAINS a shorter one wins: `…/v2-prune.ts:120` is the
|
|
140
|
+
* pointer a reader can use, while `…/v2-prune.ts` would send them hunting for the
|
|
141
|
+
* line the message was about.
|
|
142
|
+
*/
|
|
143
|
+
export declare function extractAddresses(text: string): string[];
|
|
90
144
|
export interface PruneStubInput {
|
|
91
|
-
kind: "handle" | "child" | "echo";
|
|
145
|
+
kind: "handle" | "child" | "echo" | "offload";
|
|
92
146
|
originalTokens: number;
|
|
93
147
|
handle?: PruneHandle;
|
|
94
148
|
childId?: string;
|
|
95
149
|
childState?: string;
|
|
150
|
+
/** Addresses found in the body — rendered as one `地址:` line, or omitted whole. */
|
|
151
|
+
addresses?: string[];
|
|
96
152
|
}
|
|
97
153
|
/**
|
|
98
154
|
* The replacement text. It must be self-explanatory: a reader has to know what
|
|
@@ -109,6 +165,8 @@ export interface PrunePlanEntry {
|
|
|
109
165
|
export interface PrunePlan {
|
|
110
166
|
prune: PrunePlanEntry[];
|
|
111
167
|
protectedCount: number;
|
|
168
|
+
/** Messages a user-supplied `pruneProtectPatterns` entry kept (a subset of the kept ones). */
|
|
169
|
+
protectMatched: number;
|
|
112
170
|
keptCount: number;
|
|
113
171
|
savedTokens: number;
|
|
114
172
|
}
|
|
@@ -117,6 +175,8 @@ export interface PrunePlanOptions {
|
|
|
117
175
|
budgetTokens?: number;
|
|
118
176
|
/** Newest messages whose cumulative tokens fit here are kept verbatim. */
|
|
119
177
|
keepTailTokens?: number;
|
|
178
|
+
/** User patterns: any hit keeps that message, whatever the budget says. */
|
|
179
|
+
protectPatterns?: RegExp[];
|
|
120
180
|
}
|
|
121
181
|
/**
|
|
122
182
|
* Decide which messages to prune, oldest first, until the request fits the
|
|
@@ -138,8 +198,22 @@ export interface PruneReport {
|
|
|
138
198
|
noMessages: number;
|
|
139
199
|
foreignSkipped: number;
|
|
140
200
|
threw: number;
|
|
201
|
+
/** Bodies stored in the run store before their message was replaced. */
|
|
202
|
+
offloaded: number;
|
|
203
|
+
/** Handle reused for a body an earlier request already stored (no second write). */
|
|
204
|
+
reused: number;
|
|
205
|
+
/** Messages whose offload failed (or returned no handle) → echo stub. */
|
|
206
|
+
offloadFailed: number;
|
|
207
|
+
/** Requests whose post-prune size still exceeds the budget (counted, never re-pruned). */
|
|
208
|
+
overBudget: number;
|
|
209
|
+
/** Bodies stored for a request whose plan never landed — payloads with no pointer. */
|
|
210
|
+
orphans: number;
|
|
141
211
|
/** Parts whose `type` we did not recognise — a renamed shape shows up here. */
|
|
142
212
|
unknownParts: number;
|
|
213
|
+
/** Compiled `pruneProtectPatterns` entries (a value that failed to parse is not counted here). */
|
|
214
|
+
protectPatterns: number;
|
|
215
|
+
/** Messages a protect pattern kept out of the plan this process. */
|
|
216
|
+
protectMatched: number;
|
|
143
217
|
lastPercent: number;
|
|
144
218
|
lastUsed: number;
|
|
145
219
|
lastLimit: number;
|
|
@@ -151,6 +225,12 @@ export interface PruneInput {
|
|
|
151
225
|
modelLimitOf?: (sessionID: string, messages: unknown[]) => Promise<number | null> | number | null;
|
|
152
226
|
/** Per-decision trajectory line (counters alone are invisible in a CLI run). */
|
|
153
227
|
onEvent?: (row: Record<string, unknown>) => void;
|
|
228
|
+
/**
|
|
229
|
+
* Store one message body and hand back its handle. Absent = today's
|
|
230
|
+
* behaviour (echo stub, body not kept) — the wiring passes it only while
|
|
231
|
+
* `pruneOffload` is on.
|
|
232
|
+
*/
|
|
233
|
+
offload?: (text: string) => Promise<PruneHandle | null>;
|
|
154
234
|
}
|
|
155
235
|
export interface PruneLayer {
|
|
156
236
|
registrations: V2Registration[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2-prune.d.ts","sourceRoot":"","sources":["../../src/host/v2-prune.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"v2-prune.d.ts","sourceRoot":"","sources":["../../src/host/v2-prune.ts"],"names":[],"mappings":"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"}
|