@te-river/opencode-team-mode 1.5.12 → 1.5.14

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.
Files changed (88) hide show
  1. package/README.md +30 -6
  2. package/README.zh-CN.md +28 -4
  3. package/dist/agents.d.ts +5 -1
  4. package/dist/agents.d.ts.map +1 -1
  5. package/dist/agents.js +24 -2
  6. package/dist/agents.js.map +1 -1
  7. package/dist/capabilities.d.ts +66 -0
  8. package/dist/capabilities.d.ts.map +1 -0
  9. package/dist/capabilities.js +165 -0
  10. package/dist/capabilities.js.map +1 -0
  11. package/dist/host-hooks.d.ts +115 -0
  12. package/dist/host-hooks.d.ts.map +1 -0
  13. package/dist/host-hooks.js +270 -0
  14. package/dist/host-hooks.js.map +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +103 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/prompts/lead.d.ts +1 -1
  19. package/dist/prompts/lead.d.ts.map +1 -1
  20. package/dist/prompts/lead.js +71 -8
  21. package/dist/prompts/lead.js.map +1 -1
  22. package/dist/prompts/shared.d.ts +1 -1
  23. package/dist/prompts/shared.d.ts.map +1 -1
  24. package/dist/prompts/shared.js +51 -2
  25. package/dist/prompts/shared.js.map +1 -1
  26. package/dist/prompts/specialists.d.ts +1 -1
  27. package/dist/prompts/specialists.d.ts.map +1 -1
  28. package/dist/prompts/specialists.js +38 -17
  29. package/dist/prompts/specialists.js.map +1 -1
  30. package/dist/tm/args-schema.d.ts +7 -1
  31. package/dist/tm/args-schema.d.ts.map +1 -1
  32. package/dist/tm/args-schema.js +9 -3
  33. package/dist/tm/args-schema.js.map +1 -1
  34. package/dist/tm/bash-timeout.d.ts +72 -0
  35. package/dist/tm/bash-timeout.d.ts.map +1 -0
  36. package/dist/tm/bash-timeout.js +100 -0
  37. package/dist/tm/bash-timeout.js.map +1 -0
  38. package/dist/tm/browser.d.ts +91 -5
  39. package/dist/tm/browser.d.ts.map +1 -1
  40. package/dist/tm/browser.js +564 -89
  41. package/dist/tm/browser.js.map +1 -1
  42. package/dist/tm/cache.d.ts +68 -0
  43. package/dist/tm/cache.d.ts.map +1 -0
  44. package/dist/tm/cache.js +157 -0
  45. package/dist/tm/cache.js.map +1 -0
  46. package/dist/tm/config.d.ts +87 -0
  47. package/dist/tm/config.d.ts.map +1 -1
  48. package/dist/tm/config.js +66 -0
  49. package/dist/tm/config.js.map +1 -1
  50. package/dist/tm/dispatch.d.ts +123 -0
  51. package/dist/tm/dispatch.d.ts.map +1 -0
  52. package/dist/tm/dispatch.js +476 -0
  53. package/dist/tm/dispatch.js.map +1 -0
  54. package/dist/tm/dupe-guard.d.ts +58 -0
  55. package/dist/tm/dupe-guard.d.ts.map +1 -0
  56. package/dist/tm/dupe-guard.js +105 -0
  57. package/dist/tm/dupe-guard.js.map +1 -0
  58. package/dist/tm/index.d.ts +32 -4
  59. package/dist/tm/index.d.ts.map +1 -1
  60. package/dist/tm/index.js +58 -5
  61. package/dist/tm/index.js.map +1 -1
  62. package/dist/tm/perm-ask.d.ts +1 -0
  63. package/dist/tm/perm-ask.d.ts.map +1 -1
  64. package/dist/tm/perm-ask.js +15 -1
  65. package/dist/tm/perm-ask.js.map +1 -1
  66. package/dist/tm/pipelines.d.ts.map +1 -1
  67. package/dist/tm/pipelines.js +11 -0
  68. package/dist/tm/pipelines.js.map +1 -1
  69. package/dist/tm/pty.d.ts +70 -0
  70. package/dist/tm/pty.d.ts.map +1 -0
  71. package/dist/tm/pty.js +242 -0
  72. package/dist/tm/pty.js.map +1 -0
  73. package/dist/tm/search.d.ts +56 -7
  74. package/dist/tm/search.d.ts.map +1 -1
  75. package/dist/tm/search.js +195 -41
  76. package/dist/tm/search.js.map +1 -1
  77. package/dist/tm/stats.d.ts +117 -0
  78. package/dist/tm/stats.d.ts.map +1 -0
  79. package/dist/tm/stats.js +296 -0
  80. package/dist/tm/stats.js.map +1 -0
  81. package/dist/tm/webfetch.d.ts +23 -0
  82. package/dist/tm/webfetch.d.ts.map +1 -1
  83. package/dist/tm/webfetch.js +97 -8
  84. package/dist/tm/webfetch.js.map +1 -1
  85. package/dist/types.d.ts +16 -0
  86. package/dist/types.d.ts.map +1 -1
  87. package/docs/installation.md +216 -17
  88. package/package.json +2 -2
package/README.md CHANGED
@@ -46,8 +46,9 @@ TeamMode's answer to each:
46
46
  |---|---|
47
47
  | 🔥 **Context flooding** | Every governed tool output over its content-class offload threshold (prose 4000 / data 2000 tokens, CJK-aware) is offloaded to a local run store and replaced by an 80-token preview + an HMAC handle. The agent pages through what it needs — the window never drowns. |
48
48
  | 🐌 **Round-trip overhead** | `tm_ptc_run`: the agent writes ONE program that makes N governed calls in a single turn. Zero LLM round-trips during the run. |
49
- | 🕳️ **Silent side effects** | R6/R2 approval gate: env-var reads and dangerous ops route through OpenCode's official confirmation dialog, auto-rejected after 10 unanswered minutes. The plugin never approves on its own — it only ever rejects. |
49
+ | 🕳️ **Silent side effects** | R6/R2 approval gate: env-var reads and dangerous ops route through OpenCode's official confirmation dialog, auto-rejected after 1 unanswered minute (default). The plugin never approves on its own — it only ever rejects. |
50
50
  | 🌫️ **Hallucinated research** | Web access is a two-role grant with an allowlisted, governed tool chain. A fact that couldn't be fetched is reported as a gap — never fabricated. |
51
+ | 🧭 **Walls of text** | Replies are steered into the shape the host renders fastest: a markdown table for per-file / per-case / per-finding results, fenced code for diffs and configs, a browser screenshot attached as an inline image only when you ask for one. The host does not draw mermaid, so no agent pretends it does. |
51
52
 
52
53
  And the workflow discipline underneath: deterministic routing, a ≤30-line plan
53
54
  you approve before ≥2 dispatches execute, structured `STATUS/CHANGES/FINDINGS/
@@ -127,10 +128,12 @@ OpenCode installs the plugin on next startup.
127
128
  - **Restart to activate.** After touching `opencode.json`, fully quit and restart OpenCode (Desktop: quit from tray, not just the window).
128
129
  - **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:
129
130
 
130
- | OS | Cache location |
131
+ | OS | Purge command — recursive, covers BOTH cache layouts |
131
132
  |---|---|
132
- | macOS / Linux | `rm -rf ~/.cache/opencode/packages/@te_river+opencode-team-mode@latest` |
133
- | Windows | `Remove-Item -Recurse -Force "$env:LOCALAPPDATA\opencode\cache\packages\@te_river+opencode-team-mode@latest"` |
133
+ | macOS / Linux | `find ~/.cache/opencode/packages -type d -name '*opencode-team-mode*' -prune -exec rm -rf {} +` |
134
+ | Windows (PowerShell) | `foreach ($r in "$HOME\.cache\opencode\packages", "$env:LOCALAPPDATA\opencode\cache\packages") { if (Test-Path $r) { Get-ChildItem $r -Directory -Recurse -Filter '*opencode-team-mode*' -EA SilentlyContinue | Sort-Object { $_.FullName.Length } | Remove-Item -Recurse -Force -EA SilentlyContinue } }` |
135
+
136
+ ⚠️ OpenCode loads the plugin from `~/.cache/opencode/packages/` — possibly nested inside the scoped `@te-river/` directory — **not** from `~/.config/opencode/node_modules`, which is why the delete must recurse (a top-level-only `rm -rf` silently misses the scoped copy).
134
137
 
135
138
  If you also npm-installed the plugin into `~/.config/opencode`, its package-lock pins the version — run `npm install @te-river/opencode-team-mode@latest` there too. Full recipe (including an agent-driven update prompt): [installation guide, Updating](./docs/installation.md).
136
139
  - **Prerequisites:** [OpenCode](https://opencode.ai) (Desktop or CLI) and Node ≥ 18.
@@ -216,7 +219,10 @@ through with `tm_fetch` when it genuinely needs the payload.
216
219
  | `tm_ptc_run` | Batch orchestration: one program, N governed calls, zero LLM round-trips; web roles also get `tm.search` / `tm.webfetch` inside the program | all six agents |
217
220
  | `tm_search` | Multi-engine web search with extracted, deduplicated, RRF-fused hit lists | Lead + Researcher |
218
221
  | `tm_webfetch` | Single governed GET of an allowlisted page (search pages auto-extracted) | Lead + Researcher |
219
- | `tm_browser` | Interactive browser session (**your default browser**): 16 Playwright verbs (snapshot-first `take_snapshot` → uid-addressed `click`/`fill`/`drag`/…) + 5 legacy compat verbs (open/navigate/read/screenshot/close); Playwright engine needs Node ≥ 20, below that (or on any import failure) it auto-degrades to the legacy CDP engine | Lead + Researcher + Tester (UI verification) |
222
+ | `tm_dispatch` / `tm_join` | **Async sub-agent dispatch**: `tm_dispatch` starts a specialist in its own child session and returns the id immediately (the built-in `task` tool blocks you until it finishes), `tm_join` collects — status snapshot, bounded `waitMs`, `cancel:true` to abort a runaway child; collected replies ride the offload pipeline, so five fat reports arrive as handles + previews instead of multiplying your context. Lead-only, and a child never dispatches | Lead only |
223
+ | `tm_pty` | **Non-blocking command execution** on the host's own terminal sessions (`start`/`status`/`list`/`kill`) — independent builds and test suites overlap instead of queueing behind one 120 s bash call. Captures no output (the command tees its own log; read it with `tm_read`), and every start passes the R6 classifier, the R2 danger-face globs **and** the official confirmation dialog before a process exists | Lead only |
224
+ | `tm_stats` | **The plugin reads its own trajectory back**: tokens kept out of the context window by offloading (net of the preview that arrived), seconds saved by dispatch overlap (serial cost minus the wall window the children actually used), PTC internals, governance counts (blocked subresources, refused `tm_pty` starts, clamped bash timeouts, cache hits, redactions) — plus the **host capability matrix** (`已验证/存在未用/待观察/缺失/需人眼` per host surface). Read-only over files this plugin wrote; run it first after an OpenCode upgrade | All agents |
225
+ | `tm_browser` | Interactive browser session (**your default browser**): 16 Playwright verbs (snapshot-first `take_snapshot` → uid-addressed `click`/`fill`/`drag`/…) + 5 legacy compat verbs (open/navigate/read/screenshot/close); Playwright engine needs Node ≥ 20, below that (or on any import failure) it auto-degrades to the legacy CDP engine. It drives YOUR default browser channel (an Edge Beta default opens Edge Beta), stays headful unless the operator sets `TM_BROWSER_HEADLESS`, loads a page's own images/CSS/JS via the `same-site` subresource policy, and `take_screenshot { image:true }` attaches a JPEG so the model can actually see the screen | Lead + Researcher + Tester (UI verification) |
220
226
 
221
227
  > **Fixed tool priority ladder (every task): ① TeamMode governed tools
222
228
  > (`tm_*`) → ② user MCP/plugin tools → ③ the model's own reasoning.**
@@ -283,7 +289,7 @@ sees raw SERP chrome.
283
289
 
284
290
  | Engine | Notes |
285
291
  |---|---|
286
- | `auto` (default) | Classifies the query, fans out to 2–3 engines **in parallel**, dedupes by host+path and fuses with weighted RRF (stackoverflow/bing 0.4, others 0.2) into a top-10 list tagged with each hit's source engine(s). Routing: errors / camelCase APIs → `stackoverflow`+`github`+`bing`; dev-ecosystem (releases, frameworks, open source) → `hn`+`github`+`npm`; Chinese / general → `bing`. Pin another default via `TM_SEARCH_DEFAULT_ENGINE` |
292
+ | `auto` (default) | Classifies the query, fans the matching engines out **in parallel** (every route has ≥2 legs), dedupes by host+path and fuses them with weighted RRF into a top-10 list tagged with each hit's source engine(s). Ranking is scaled by real query-token overlap (floor `TM_SEARCH_RELEVANCE_FLOOR`), so a trusted engine's off-topic junk no longer outranks another engine's best hit. Routing: errors / camelCase APIs → `stackoverflow`+`github`+`bing`; dev-ecosystem (releases, frameworks, open source) → `hn`+`github`+`npm`; Chinese → `bing`+`moegirl`+`stackoverflow`+`hn`; other → `bing`+`stackoverflow`+`hn`+`github`. Pin another default via `TM_SEARCH_DEFAULT_ENGINE` |
287
293
  | `bing` | cn.bing.com — the only live CN HTML SERP; multi-word CJK queries get their phrase boundary protected (quoted) so markup shuffle can't split the result list |
288
294
  | `stackoverflow` | api.stackexchange.com question search (no key, 300/day/IP) → numbered questions with composite snippets; `auto` tracks the quota and swaps in `bing` once spent |
289
295
  | `hn` | Hacker News via Algolia API (no key) → story titles + snippets with direct article URLs |
@@ -467,6 +473,24 @@ for overrides, extra agents and disabling roles.
467
473
  | `TM_BROWSER_HEADLESS` | `auto` | `1` headless (CI) / `0` headful / `auto` (headless only on display-less Linux) |
468
474
  | `TM_BROWSER_ENGINE` | `playwright` | `playwright` (needs Node ≥ 20; any import failure auto-degrades) / `cdp-legacy` (zero-dep CDP pipe, core verbs only) |
469
475
  | `TM_BROWSER_SNAPSHOT_MAX_TOKENS` | `1200` | hard cap on `take_snapshot` payloads |
476
+ | `TM_BROWSER_SUBRESOURCE` | `same-site` | what a page may load after its navigation was allowed: `same-site` = images/media/fonts/stylesheets always, scripts/XHR only for a site this session actually opened; `passive` = only the passive types; `off` = the legacy every-request gate. Blocked requests surface as a "N 个子资源请求被拦截" note on the next snapshot |
477
+ | `TM_BROWSER_IDLE_MS` | `180000` | an untouched browser session closes itself after this many ms (0 disables) and tells the user — a window nobody owns is a user-facing bug |
478
+ | `TM_BROWSER_ASK_EVAL` | `on` | `evaluate_script` runs arbitrary JS in YOUR browser — the one verb the domain allowlist can't cover (it limits where we navigate, not what a loaded page hands back). One official-dialog consent per browser session; no ask bridge ⇒ refused. `off` restores the old behaviour; the result redaction (JWT/bearer/cookie/api-key shapes) is NOT switchable |
479
+ | `TM_WEB_CACHE_TTL_SEC` | `300` | how long a governed fetch may re-serve the same URL (0 = off). One store shared by tm_webfetch / tm_search / the PTC bridge; entries are hash-named (a token-bearing query never hits disk) and are only read or written for hops the STATIC allowlist admitted — dialog consent stays per-request, and a re-served page says 缓存命中 |
480
+ | `TM_BROWSER_IMAGE_MAX_BYTES` | `400000` | ceiling on the JPEG `take_screenshot { image:true }` inlines into the model's context (above it the reply stays path-only and says why) |
481
+ | `TM_SEARCH_WEIGHTS` | unset | per-engine fusion weight overrides, e.g. `bing=0.3,hn=0.25`; anything unset keeps the built-in table |
482
+ | `TM_SEARCH_RELEVANCE_FLOOR` | `0.35` | weight fraction kept by a hit that shares no query token with its title/snippet/host (demotes junk without deleting an engine) |
483
+ | `TM_SEARCH_MAX_HITS` | `10` | hits kept per engine leg and in the fused list |
484
+ | `TM_SEARCH_DISABLED_ENGINES` | unset | engines removed from the roster AND from every `auto` route (`sogou,baidu` style) |
485
+ | `TM_BASH_TIMEOUT_PROBE_MS` | `60000` | ceiling forced onto a `timeout` the model set for a read-only probe command (0 disables) |
486
+ | `TM_BASH_TIMEOUT_MAX_MS` | `0` | optional global ceiling for every other bash command — off by default so a real build keeps the timeout it asked for |
487
+ | `TM_PTY_MAX` | `4` | concurrent `tm_pty` terminal sessions this plugin may keep running at once |
488
+ | `TM_TOOL_HINTS` | `on` | append TeamMode's call-site discipline to the built-in `bash` / `task` tool DESCRIPTIONS via `tool.definition` (append-only, idempotent — the host text is never replaced) |
489
+ | `TM_AGENT_TEMPERATURE` | `off` | `on` applies a per-role sampling table (architect 0.35 / researcher 0.3 / reviewer 0.1 / rest 0.2) via `chat.params`; or give it `reviewer=0.05;team=0.4`. Off = the documented "all agents at 0.2" invariant stands |
490
+ | `TM_COMPACTION_CONTEXT` | `on` | on the host's pre-compaction hook, add the must-survive list (reply skeleton, offload handles, dispatched child session ids, provenance, board paths). Additive — the host's own summarizer prompt is never replaced |
491
+ | `TM_COMPACTION_AUTOCONTINUE` | `on` | `off` stops the host from silently resuming the turn after a compaction, so a human re-reads state first |
492
+ | `TM_SHELL_NO_COLOR` | `on` | inject `NO_COLOR`/`TERM=dumb` into every child shell via `shell.env` (ANSI progress bars are pure context tax). Never overwrites a value the host already set |
493
+ | `TM_SHELL_ENV` | — | explicit `KEY=VALUE;KEY2=VALUE2` passthrough into child shells — deliberately allowlisted, so this hook can't become a side channel for the parent environment |
470
494
  | `TM_BROWSER_USER_DATA_DIR` | — (isolated temp profile) | explicit persistent profile dir — the ONLY way logins survive between sessions |
471
495
  | `TM_MEMORY_GLOBAL_DIR` | `~/.opencode-team/memories/global/` | tm_memory GLOBAL tier store |
472
496
  | `TM_MEMORY_SESSION_TTL_MIN` | `240` | session-tier entry TTL (lazy + boot sweep) |
package/README.zh-CN.md CHANGED
@@ -47,6 +47,7 @@ TeamMode 对每一个的回应:
47
47
  | 🐌 **回合开销** | `tm_ptc_run`:agent 写**一个程序**,单回合内发起 N 次受治理调用。运行期间零 LLM 回合。 |
48
48
  | 🕳️ **静默副作用** | R6/R2 审批门禁:环境变量读取和危险操作走 OpenCode 官方确认弹窗,1 分钟没人理自动拒绝。插件从不代替你批准——它只会拒绝。 |
49
49
  | 🌫️ **幻觉式调研** | 联网是双角色的授权 + 白名单受治理工具链。抓不到的事实就报告为缺口——绝不编造。 |
50
+ | 🧭 **纯文本墙** | 回复被引导成宿主渲染得最快的形状:逐文件 / 逐用例 / 逐条发现用 markdown 表格,diff 和配置用围栏代码块,浏览器截图只在你明确要求时才内联附上。宿主不画 mermaid,所以没有 agent 会假装它在画。 |
50
51
 
51
52
  底下还有流程纪律:确定性路由表、≥2 次派工先出 ≤30 行计划等你批、agent
52
53
  之间用 `STATUS/CHANGES/FINDINGS/EVIDENCE/HANDOFF` 结构化交接、以及静态
@@ -126,8 +127,10 @@ OpenCode 下次启动时装好。
126
127
 
127
128
  | 系统 | 缓存位置 |
128
129
  |---|---|
129
- | macOS / Linux | `rm -rf ~/.cache/opencode/packages/@te_river+opencode-team-mode@latest` |
130
- | Windows | `Remove-Item -Recurse -Force "$env:LOCALAPPDATA\opencode\cache\packages\@te_river+opencode-team-mode@latest"` |
130
+ | macOS / Linux | `find ~/.cache/opencode/packages -type d -name '*opencode-team-mode*' -prune -exec rm -rf {} +` |
131
+ | Windows (PowerShell) | `foreach ($r in "$HOME\.cache\opencode\packages", "$env:LOCALAPPDATA\opencode\cache\packages") { if (Test-Path $r) { Get-ChildItem $r -Directory -Recurse -Filter '*opencode-team-mode*' -EA SilentlyContinue | Sort-Object { $_.FullName.Length } | Remove-Item -Recurse -Force -EA SilentlyContinue } }` |
132
+
133
+ ⚠️ OpenCode 是从 `~/.cache/opencode/packages/` 加载插件的(可能嵌套在 `@te-river/` 作用域目录里),**不是** `~/.config/opencode/node_modules`——所以删除必须递归:只删顶层会静默漏掉作用域式的缓存副本。
131
134
 
132
135
  如果插件还被 npm 装进了 `~/.config/opencode`,package-lock 会钉住版本——在那里再跑一次 `npm install @te-river/opencode-team-mode@latest`。完整配方(含 agent 更新提示词)见[安装指南·更新](./docs/installation.md)。
133
136
  - **前置条件:** [OpenCode](https://opencode.ai)(桌面版或 CLI)+ Node ≥ 18。
@@ -210,7 +213,10 @@ HMAC 句柄,agent 真需要 payload 时用 `tm_fetch` 分页取。
210
213
  | `tm_ptc_run` | 批量编排:一个程序、N 次受治理调用、零 LLM 回合;联网角色还能在程序里调 `tm.search` / `tm.webfetch` | 全部六个 agent |
211
214
  | `tm_search` | 多引擎网络搜索,返回提取、去重、RRF 融合后的命中列表 | Lead + Researcher |
212
215
  | `tm_webfetch` | 白名单页面的单次受治理 GET(搜索页自动提取) | Lead + Researcher |
213
- | `tm_browser` | 交互式浏览器会话(**驱动你的默认浏览器**):16 个 Playwright 动词(快照优先:`take_snapshot` → 按 uid 寻址的 `click`/`fill`/`drag`…)+ 5 个旧版兼容动词(open/navigate/read/screenshot/close);Playwright 引擎需 Node ≥ 20,不满足或导入失败时自动降级到旧版 CDP 引擎 | Lead + Researcher + Tester(仅 UI 验证) |
216
+ | `tm_dispatch` / `tm_join` | **异步子代理派发**:`tm_dispatch` 在独立子会话里启动某个专员并立刻返回其 id(内置 `task` 会把你阻塞到子代理结束),`tm_join` 负责回收——不带参数=状态快照,`waitMs`=有界等待,`cancel:true` 取消跑飞的子任务;回收到的回复同样走卸载管线,五份长报告变成句柄+预览而不是压垮你的上下文 | 仅 Lead(子代理不得再派发) |
217
+ | `tm_pty` | 在宿主自己的终端会话上**非阻塞执行命令**(`start`/`status`/`list`/`kill`):独立的构建与测试各自一个会话并行跑,不再串成一条 120 秒的 bash 调用。它不抓输出(命令自己 tee 日志,用 `tm_read` 读),且每次启动都先过 R6 分类器、R2 危险面 glob,再走官方确认窗,才真的建进程 | 仅 Lead |
218
+ | `tm_stats` | **插件把自己的 trajectory 读回来**:卸载挡在上下文之外的 token(扣掉确实回来的预览)、派发重叠省下的秒数(串行代价减去子代理实际占用的墙钟)、PTC 内部量、治理计数(被拦子资源、`tm_pty` 拒绝、bash 超时夹顶、缓存命中、脱敏次数)——外加**宿主能力矩阵**(每个宿主接口标 `已验证/存在未用/待观察/缺失/需人眼`)。只读本插件自己写的文件;OpenCode 升级后第一个跑它 | 全角色 |
219
+ | `tm_browser` | 交互式浏览器会话(**驱动你的默认浏览器**):16 个 Playwright 动词(快照优先:`take_snapshot` → 按 uid 寻址的 `click`/`fill`/`drag`…)+ 5 个旧版兼容动词(open/navigate/read/screenshot/close);Playwright 引擎需 Node ≥ 20,不满足或导入失败时自动降级到旧版 CDP 引擎。它开的是**你自己的默认浏览器渠道**(默认装 Edge Beta 就开 Beta),除操作者设 `TM_BROWSER_HEADLESS` 外保持有头;页面自家图片/CSS/JS 靠 `same-site` 子资源策略正常加载;`take_screenshot { image:true }` 会附一张 JPEG,让模型真能看见画面 | Lead + Researcher + Tester(仅 UI 验证) |
214
220
 
215
221
  > **固定工具优先级阶梯(每个任务都适用):① TeamMode 受治理工具(`tm_*`)
216
222
  > → ② 用户 MCP/插件工具 → ③ 模型自己的推理。** 它同时是回退链:某个受治理
@@ -264,7 +270,7 @@ agent 永远看不到原始搜索页的噪音。
264
270
 
265
271
  | 引擎 | 说明 |
266
272
  |---|---|
267
- | `auto`(默认) | 给查询分类,**并行**扇出 2–3 个引擎,按 host+path 去重后做加权 RRF 融合(stackoverflow/bing 0.4,其余 0.2),产出标有来源引擎的 top-10 列表。路由:报错/camelCase API → `stackoverflow`+`github`+`bing`;开发生态(发布、框架、开源)→ `hn`+`github`+`npm`;中文/通用 → `bing`。用 `TM_SEARCH_DEFAULT_ENGINE` 钉别的默认 |
273
+ | `auto`(默认) | 给查询分类,**并行**扇出匹配的引擎(每条路由至少 2 条腿),按 host+path 去重后做加权 RRF 融合,产出标有来源引擎的 top-10 列表。排序按命中与查询词的真实重叠度打折(地板 `TM_SEARCH_RELEVANCE_FLOOR`),高权重引擎的无关结果不再压过别的引擎最好的一条。路由:报错/camelCase API → `stackoverflow`+`github`+`bing`;开发生态(发布、框架、开源)→ `hn`+`github`+`npm`;中文 → `bing`+`moegirl`+`stackoverflow`+`hn`;其它 → `bing`+`stackoverflow`+`hn`+`github`。用 `TM_SEARCH_DEFAULT_ENGINE` 钉别的默认 |
268
274
  | `bing` | cn.bing.com——唯一活着的中文 HTML SERP;多词 CJK 查询自动保护短语边界(加引号),markup 洗牌拆不散结果列表 |
269
275
  | `stackoverflow` | api.stackexchange.com 问题搜索(免 Key,300 次/天/IP)→ 带复合摘要的编号问题列表;`auto` 跟踪配额,耗尽自动换 `bing` 顶上 |
270
276
  | `hn` | Hacker News(Algolia API,免 Key)→ 帖子标题 + 摘要与原文链接 |
@@ -418,6 +424,24 @@ Team Lead 自己从不删黑板,你可以随时审计任何一次运行。
418
424
  | `TM_BLACKBOARD_TTL` | `7` | 存储保留天数 |
419
425
  | `TM_BASH_READONLY_ALLOWED` | 内置表 | tm_bash 白名单 |
420
426
  | `TM_SEARCH_DEFAULT_ENGINE` | `auto` | tm_search 未显式给 `engine` 时的默认引擎(`auto` = 分类 + 并行扇出 + RRF 融合;也可钉表中任一引擎) |
427
+ | `TM_SEARCH_WEIGHTS` | 未设 | 按引擎覆盖融合权重,如 `bing=0.3,hn=0.25`;未列出的沿用内置表 |
428
+ | `TM_SEARCH_RELEVANCE_FLOOR` | `0.35` | 与查询词零重叠的命中只保留该比例的权重(压垃圾,不删引擎) |
429
+ | `TM_SEARCH_MAX_HITS` | `10` | 每引擎腿与融合列表保留的命中数 |
430
+ | `TM_SEARCH_DISABLED_ENGINES` | 未设 | 从引擎表与所有 `auto` 路由中移除的引擎(`sogou,baidu` 写法) |
431
+ | `TM_BROWSER_SUBRESOURCE` | `same-site` | 顶层导航过白名单后,页面子资源的策略:`same-site` = 图/媒体/字体/样式表一律放行,脚本/XHR 仅当属于本次会话真正打开过的站点;`passive` = 只放被动资源;`off` = 旧行为(逐请求过白名单)。被拦掉的请求会在下一次快照以"N 个子资源请求被拦截"告知 |
432
+ | `TM_BROWSER_IDLE_MS` | `180000` | 无人触碰的浏览器会话超过该毫秒数自动关闭并提示用户(0 关闭该回收)——没人负责的窗口是打扰用户的 bug |
433
+ | `TM_BROWSER_ASK_EVAL` | `on` | `evaluate_script` 在**你的**浏览器里跑任意 JS——这是域白名单管不住的唯一动词(白名单限制我们去哪儿导航,管不了已加载的页面交回什么)。每个浏览器会话走一次官方确认窗;没有 ask 桥就拒绝。`off` 恢复旧行为;结果脱敏(JWT/bearer/cookie/api-key 形状)不可关闭 |
434
+ | `TM_WEB_CACHE_TTL_SEC` | `300` | 受治理抓取在同一 URL 上可复用多久(0 = 关)。tm_webfetch / tm_search / PTC 桥共用一份缓存;条目以哈希命名(带令牌的查询串不落盘),且只在**静态白名单**放行的那一跳读写——弹窗授权仍是逐请求的,复用命中会标注 缓存命中 |
435
+ | `TM_BROWSER_IMAGE_MAX_BYTES` | `400000` | `take_screenshot { image:true }` 内联给模型的 JPEG 上限;超过则只回路径并说明原因 |
436
+ | `TM_BASH_TIMEOUT_PROBE_MS` | `60000` | 对只读探针命令(P3 白名单内)强制夹顶模型自设的 `timeout`(0 关闭) |
437
+ | `TM_BASH_TIMEOUT_MAX_MS` | `0` | 其它 bash 命令的可选全局上限——默认关闭,真实构建保留它要的超时 |
438
+ | `TM_PTY_MAX` | `4` | 本插件同时最多保持多少个 `tm_pty` 终端会话 |
439
+ | `TM_TOOL_HINTS` | `on` | 通过 `tool.definition` 把本插件的调用点纪律追加到内置 `bash` / `task` 的**描述**后面(只追加、幂等,绝不替换宿主原文) |
440
+ | `TM_AGENT_TEMPERATURE` | `off` | `on` 时按角色分档采样(architect 0.35 / researcher 0.3 / reviewer 0.1 / 其余 0.2)经 `chat.params` 生效;也可写 `reviewer=0.05;team=0.4`。默认关闭=守住"所有 agent 0.2"这条既定原则 |
441
+ | `TM_COMPACTION_CONTEXT` | `on` | 在宿主压缩前追加"必须存活清单"(回复骨架、offload 句柄、未回收的子会话 id、出处、板上路径)。只做追加——宿主自己的压缩提示词不被替换 |
442
+ | `TM_COMPACTION_AUTOCONTINUE` | `on` | 设 `off` 则压缩后不让宿主静默续跑,先由人复核状态 |
443
+ | `TM_SHELL_NO_COLOR` | `on` | 经 `shell.env` 给每个子 shell 注入 `NO_COLOR`/`TERM=dumb`(ANSI 进度条纯属上下文税)。绝不覆盖宿主已设的值 |
444
+ | `TM_SHELL_ENV` | — | 显式 `KEY=VALUE;KEY2=VALUE2` 透传进子 shell——刻意用白名单,避免这个钩子变成父环境泄露通道 |
421
445
  | `TM_WEBFETCH_ALLOWED_DOMAINS` | 23 个种子主机 | tm_webfetch / tm_search / tm_browser 白名单(`"*"` 全开;空 = 全拒;自定义值**替换**种子——保留引擎主机) |
422
446
  | `TM_BROWSER_PATH` | 自动探测 | tm_browser 可执行文件覆盖(默认用你的默认浏览器——Chromium 系时;否则回退 Edge/Chrome 探测) |
423
447
  | `TM_BROWSER_HEADLESS` | `auto` | `1` 无头(CI)/ `0` 有头 / `auto`(仅无显示的 Linux 用无头) |
package/dist/agents.d.ts CHANGED
@@ -27,6 +27,10 @@
27
27
  * high-risk profiles.
28
28
  * - All agents run at temperature 0.2 for format discipline.
29
29
  */
30
- import type { AgentConfig } from "./types.js";
30
+ import type { AgentConfig, AgentPermission } from "./types.js";
31
+ /** Grant the async levers to the lead only (issue #6 + #7). A child cannot
32
+ * dispatch or spawn processes: these matrix entries and the tools' own
33
+ * runtime `ctx.agent` checks are two independent locks. */
34
+ export declare function applyDispatcherPermission(permission: AgentPermission, isTeamLead: boolean): void;
31
35
  export declare const agents: Record<string, AgentConfig>;
32
36
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAA;AAqR9D,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAO9C,CAAA"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoH9D;;4DAE4D;AAC5D,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAIhG;AAiLD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAO9C,CAAA"}
package/dist/agents.js CHANGED
@@ -89,8 +89,10 @@ const PER_AGENT_TOOLS = ["edit", "write", "task", "bash", "todowrite", "question
89
89
  /** The governed tools, named explicitly next to the "tm_*" wildcard
90
90
  * (belt-and-braces: the explicit allows survive even if a host ever
91
91
  * stops expanding the wildcard). tm_memory is the project memory store —
92
- * not a network channel, available to all six agents. */
93
- const TM_TOOLS = ["tm_read", "tm_grep", "tm_bash", "tm_fetch", "tm_memory"];
92
+ * not a network channel, available to all six agents. tm_stats reads this
93
+ * plugin's own trajectory (no network, no shell, no secrets) so any role can
94
+ * answer "what did we spend" — and after a host upgrade, "what broke". */
95
+ const TM_TOOLS = ["tm_read", "tm_grep", "tm_bash", "tm_fetch", "tm_memory", "tm_stats"];
94
96
  /** M3: tm_ptc_run — explicit per-agent grant. v1.5.4 revised the original
95
97
  * M3 ruling (five specialists = allow, team = deny): ALL SIX agents now
96
98
  * get `allow` (per user request, CHANGELOG 1.5.4), overriding the tm_*
@@ -116,8 +118,26 @@ const whitelist = (...granted) => {
116
118
  permission["tm_webfetch"] = "deny";
117
119
  permission["tm_search"] = "deny";
118
120
  permission["tm_browser"] = "deny";
121
+ // Async dispatch (tm_dispatch / tm_join) is the LEAD's lever — the tm_*
122
+ // wildcard would otherwise hand every specialist the ability to spawn
123
+ // sub-agents, which is exactly the nesting T3 closed.
124
+ permission["tm_dispatch"] = "deny";
125
+ permission["tm_join"] = "deny";
126
+ // tm_pty starts a real process, so it must pop the OFFICIAL dialog on
127
+ // every use: the WEB_ASK_MAP shape is what makes PermissionV2's findLast
128
+ // resolve to `ask` instead of swallowing the ask under the tm_* allow.
129
+ // Default deny; the lead gets the ask-map (applyDispatcherPermission).
130
+ permission["tm_pty"] = "deny";
119
131
  return permission;
120
132
  };
133
+ /** Grant the async levers to the lead only (issue #6 + #7). A child cannot
134
+ * dispatch or spawn processes: these matrix entries and the tools' own
135
+ * runtime `ctx.agent` checks are two independent locks. */
136
+ export function applyDispatcherPermission(permission, isTeamLead) {
137
+ permission["tm_dispatch"] = isTeamLead ? "allow" : "deny";
138
+ permission["tm_join"] = isTeamLead ? "allow" : "deny";
139
+ permission["tm_pty"] = isTeamLead ? { ...WEB_ASK_MAP } : "deny";
140
+ }
121
141
  /** Apply the tm_ptc_run grant to an agent's permission block. All six
122
142
  * agents get `allow` (overrides the tm_* wildcard for explicit key priority). */
123
143
  function applyPtcPermission(permission, _isTeamLead) {
@@ -261,12 +281,14 @@ for (const a of [architect, implementer, reviewer, tester, researcher]) {
261
281
  if (teamLead.permission) {
262
282
  applyPtcPermission(teamLead.permission, true);
263
283
  applyNetworkPermission(teamLead.permission, true);
284
+ applyDispatcherPermission(teamLead.permission, true);
264
285
  }
265
286
  for (const a of [architect, implementer, reviewer, tester, researcher]) {
266
287
  if (a.permission) {
267
288
  applyPtcPermission(a.permission, false);
268
289
  // tester: tm_browser only (UI verification); researcher: full web grant
269
290
  applyNetworkPermission(a.permission, a === researcher, a === tester);
291
+ applyDispatcherPermission(a.permission, false);
270
292
  }
271
293
  }
272
294
  /* ------------------------------------------------------------------ */
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Host-capability probe — the "fail loud, not silent" seam (2026-09-19).
3
+ *
4
+ * Everything this plugin does interesting leans on a host surface that is NOT
5
+ * part of a stability promise: `ctx.ask`, the `permission.asked` event,
6
+ * `client.session.create/promptAsync/children`, `client.pty.*`, `tui.showToast`,
7
+ * and the handful of hooks the host agrees to call (`tool.definition`,
8
+ * `chat.params`, `shell.env`, the compaction pair). Each of our features
9
+ * already degrades gracefully when one of those disappears — which is exactly
10
+ * the problem: an OpenCode upgrade can quietly take `tm_pty` and every web
11
+ * dialog out of the build, and the only symptom is the agent working around
12
+ * something the user never agreed to lose.
13
+ *
14
+ * So the plugin records what it ACTUALLY sees and says it out loud once:
15
+ * - `missing` — the surface is gone; the named feature is off.
16
+ * - `declared` — the surface exists but nothing has exercised it yet.
17
+ * - `ok` — observed working in this process (a hook fired, an event
18
+ * arrived, an ask bridge was handed to a tool).
19
+ * - `not-seen` — the host has not called/fired it since startup; the
20
+ * feature is armed and waiting (NOT evidence of a break).
21
+ * - `unverified`— we emit the contract; only a human can see the result
22
+ * (the `attachments` screenshot — the host either paints it
23
+ * or ignores it, and we cannot observe which).
24
+ *
25
+ * `tm_stats` renders the live matrix; a missing REQUIRED surface also raises
26
+ * one toast at startup, so a host upgrade is reported instead of discovered
27
+ * mid-task. Nothing here ever throws and nothing probes the network.
28
+ */
29
+ /** How each row was decided — kept as data so a test can pin the reasoning. */
30
+ export type CapState = "ok" | "declared" | "missing" | "not-seen" | "unverified";
31
+ export type CapEvidence = "static" | "hook" | "event" | "runtime" | "human";
32
+ export interface CapabilityRow {
33
+ /** The host surface, spelled the way the user reads it in a toast. */
34
+ seam: string;
35
+ /** What we lose if it is gone. */
36
+ feature: string;
37
+ state: CapState;
38
+ evidence: CapEvidence;
39
+ note?: string;
40
+ }
41
+ export interface CapabilityProbe {
42
+ observeAskBridge(present: boolean): void;
43
+ observeEvent(type: string): void;
44
+ observeHook(name: string): void;
45
+ /** Live matrix for tm_stats. */
46
+ snapshot(): CapabilityRow[];
47
+ /** Rows the plugin considers load-bearing and did NOT find. */
48
+ missingRequired(): CapabilityRow[];
49
+ /** One trajectory line + (when something required is gone) one toast. */
50
+ report(): {
51
+ rows: CapabilityRow[];
52
+ missing: string[];
53
+ };
54
+ }
55
+ export declare function createCapabilityProbe(deps: {
56
+ client: unknown;
57
+ /** `input.$` — the host shell bridge, handed outside the client object. */
58
+ hasShellBridge?: boolean;
59
+ /** Already-resolved R6 reply capability (index.ts owns that decision). */
60
+ hasPermissionReply?: boolean;
61
+ trajectory?: (event: Record<string, unknown>) => void;
62
+ notify?: (message: string) => void;
63
+ }): CapabilityProbe;
64
+ /** Markdown table for tm_stats — the shape the host renders fastest. */
65
+ export declare function renderCapabilityMatrix(rows: readonly CapabilityRow[]): string;
66
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAA;AAEhF,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAA;AAE3E,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,QAAQ,CAAA;IACf,QAAQ,EAAE,WAAW,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAmED,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACxC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gCAAgC;IAChC,QAAQ,IAAI,aAAa,EAAE,CAAA;IAC3B,+DAA+D;IAC/D,eAAe,IAAI,aAAa,EAAE,CAAA;IAClC,yEAAyE;IACzE,MAAM,IAAI;QAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CACvD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,OAAO,CAAA;IACf,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACrD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC,GAAG,eAAe,CAoElB;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAQ7E"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Host-capability probe — the "fail loud, not silent" seam (2026-09-19).
3
+ *
4
+ * Everything this plugin does interesting leans on a host surface that is NOT
5
+ * part of a stability promise: `ctx.ask`, the `permission.asked` event,
6
+ * `client.session.create/promptAsync/children`, `client.pty.*`, `tui.showToast`,
7
+ * and the handful of hooks the host agrees to call (`tool.definition`,
8
+ * `chat.params`, `shell.env`, the compaction pair). Each of our features
9
+ * already degrades gracefully when one of those disappears — which is exactly
10
+ * the problem: an OpenCode upgrade can quietly take `tm_pty` and every web
11
+ * dialog out of the build, and the only symptom is the agent working around
12
+ * something the user never agreed to lose.
13
+ *
14
+ * So the plugin records what it ACTUALLY sees and says it out loud once:
15
+ * - `missing` — the surface is gone; the named feature is off.
16
+ * - `declared` — the surface exists but nothing has exercised it yet.
17
+ * - `ok` — observed working in this process (a hook fired, an event
18
+ * arrived, an ask bridge was handed to a tool).
19
+ * - `not-seen` — the host has not called/fired it since startup; the
20
+ * feature is armed and waiting (NOT evidence of a break).
21
+ * - `unverified`— we emit the contract; only a human can see the result
22
+ * (the `attachments` screenshot — the host either paints it
23
+ * or ignores it, and we cannot observe which).
24
+ *
25
+ * `tm_stats` renders the live matrix; a missing REQUIRED surface also raises
26
+ * one toast at startup, so a host upgrade is reported instead of discovered
27
+ * mid-task. Nothing here ever throws and nothing probes the network.
28
+ */
29
+ const SEAMS = [
30
+ {
31
+ seam: "ToolContext.ask",
32
+ feature: "out-of-allowlist web fetch/search/browser + every tm_pty start",
33
+ evidence: "runtime",
34
+ observed: ["ask-bridge"],
35
+ required: true,
36
+ note: "first observed by whichever tm_* tool runs",
37
+ },
38
+ { seam: "client.session.create+promptAsync", feature: "tm_dispatch (non-blocking lead)", evidence: "static", path: "session.promptAsync", required: true },
39
+ { seam: "client.session.children", feature: "tm_join recovery after a restart", evidence: "static", path: "session.children" },
40
+ { seam: "client.session.status", feature: "tm_join bounded wait", evidence: "static", path: "session.status" },
41
+ { seam: "client.session.abort", feature: "tm_join cancel:true", evidence: "static", path: "session.abort" },
42
+ { seam: "client.pty.create", feature: "tm_pty (non-blocking commands)", evidence: "static", path: "pty.create", required: true },
43
+ { seam: "client.permission.reply", feature: "the approval gate's auto-reject timer", evidence: "static", path: "permission.reply", required: true },
44
+ { seam: "tui.showToast", feature: "a toast when a dialog is waiting", evidence: "static", path: "tui.showToast" },
45
+ { seam: "input.$ (shell bridge)", feature: "tm_bash via the host shell (else spawn fallback)", evidence: "static", path: "$" },
46
+ {
47
+ seam: "event permission.asked",
48
+ feature: "R6/R2 dialog observation + the unanswered-ask timer",
49
+ evidence: "event",
50
+ observed: ["permission.asked"],
51
+ note: "only arrives once something asks — absence so far is not a break",
52
+ },
53
+ { seam: "hook tool.execute.before", feature: "bash timeout clamp + R6 deferral", evidence: "hook", observed: ["hook:tool.execute.before"], required: true },
54
+ { seam: "hook tool.definition", feature: "TM_TOOL_HINTS on built-in bash/task", evidence: "hook", observed: ["hook:tool.definition"] },
55
+ { seam: "hook chat.params", feature: "TM_AGENT_TEMPERATURE", evidence: "hook", observed: ["hook:chat.params"] },
56
+ { seam: "hook shell.env", feature: "NO_COLOR / TM_SHELL_ENV passthrough", evidence: "hook", observed: ["hook:shell.env"] },
57
+ { seam: "hook experimental.session.compacting", feature: "the must-survive compaction context", evidence: "hook", observed: ["hook:session.compacting"] },
58
+ {
59
+ seam: "ToolResult.attachments",
60
+ feature: "tm_browser take_screenshot { image:true }",
61
+ evidence: "human",
62
+ state: "unverified",
63
+ note: "we emit the official shape; whether the desktop paints it is only visible to you",
64
+ },
65
+ ];
66
+ /** Read a dot path off the live client without assuming any of it exists. */
67
+ function pathPresent(client, dotted) {
68
+ if (dotted === "$")
69
+ return false; // resolved by the caller — not a client path
70
+ let cur = client;
71
+ for (const seg of dotted.split(".")) {
72
+ if (!cur || typeof cur !== "object")
73
+ return false;
74
+ cur = cur[seg];
75
+ }
76
+ return typeof cur === "function";
77
+ }
78
+ export function createCapabilityProbe(deps) {
79
+ const ok = new Set();
80
+ if (deps.hasShellBridge)
81
+ ok.add("$");
82
+ if (deps.hasPermissionReply)
83
+ ok.add("permission.reply");
84
+ const presentOf = (spec) => {
85
+ if (!spec.path)
86
+ return null;
87
+ if (spec.path === "$")
88
+ return !!deps.hasShellBridge;
89
+ if (spec.path === "permission.reply")
90
+ return !!deps.hasPermissionReply;
91
+ return pathPresent(deps.client, spec.path);
92
+ };
93
+ const rowFor = (spec) => {
94
+ const observed = (spec.observed ?? []).some((name) => ok.has(name));
95
+ const present = presentOf(spec);
96
+ const row = { seam: spec.seam, feature: spec.feature, evidence: spec.evidence, state: "not-seen" };
97
+ if (spec.state === "unverified")
98
+ row.state = "unverified";
99
+ else if (observed)
100
+ row.state = "ok";
101
+ else if (present === false)
102
+ row.state = "missing";
103
+ else if (spec.evidence === "static")
104
+ row.state = "declared";
105
+ else
106
+ row.state = "not-seen";
107
+ if (spec.note)
108
+ row.note = spec.note;
109
+ return row;
110
+ };
111
+ let reported = false;
112
+ const report = () => {
113
+ const rows = SEAMS.map(rowFor);
114
+ const missing = rows.filter((r) => r.state === "missing").map((r) => r.seam);
115
+ if (reported)
116
+ return { rows, missing };
117
+ reported = true;
118
+ try {
119
+ deps.trajectory?.({ tool: "capabilities", step_id: "boot", event: "probe", rows: rows.map((r) => `${r.seam}=${r.state}`) });
120
+ }
121
+ catch {
122
+ /* observability only */
123
+ }
124
+ const required = SEAMS.filter((s, i) => s.required && rows[i].state === "missing").map((s) => s.feature);
125
+ if (required.length) {
126
+ try {
127
+ deps.notify?.(`检测到宿主接口缺失,本进程已降级:${required.join(";")}。` +
128
+ `(OpenCode 升级后常见。用 tm_stats 看完整能力矩阵。)`);
129
+ }
130
+ catch {
131
+ /* notification is best-effort */
132
+ }
133
+ }
134
+ return { rows, missing };
135
+ };
136
+ return {
137
+ observeAskBridge(present) {
138
+ if (present)
139
+ ok.add("ask-bridge");
140
+ },
141
+ observeEvent(type) {
142
+ const t = String(type ?? "");
143
+ if (t === "permission.asked" || t === "permission.updated")
144
+ ok.add("permission.asked");
145
+ },
146
+ observeHook(name) {
147
+ const n = String(name ?? "");
148
+ if (n)
149
+ ok.add(`hook:${n}`);
150
+ },
151
+ snapshot: () => SEAMS.map(rowFor),
152
+ missingRequired: () => SEAMS.map(rowFor).filter((r, i) => SEAMS[i].required && r.state === "missing"),
153
+ report,
154
+ };
155
+ }
156
+ /** Markdown table for tm_stats — the shape the host renders fastest. */
157
+ export function renderCapabilityMatrix(rows) {
158
+ const badge = (s) => s === "ok" ? "✓ 已验证" : s === "declared" ? "◦ 存在未用" : s === "missing" ? "✗ 缺失" : s === "not-seen" ? "… 待观察" : "? 需人眼";
159
+ const lines = ["| 宿主接口 | 影响的能力 | 状态 |", "|---|---|---|"];
160
+ for (const r of rows) {
161
+ lines.push(`| \`${r.seam}\` | ${r.feature} | ${badge(r.state)}${r.note ? ` — ${r.note}` : ""} |`);
162
+ }
163
+ return lines.join("\n");
164
+ }
165
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}