@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
@@ -0,0 +1,476 @@
1
+ /**
2
+ * tm_dispatch / tm_join — ASYNC sub-agent dispatch (issue #7 of 2026-09-18).
3
+ *
4
+ * Why this exists: the host's built-in `task` tool blocks the CALLING
5
+ * session until the child agent returns, so "the team runs in parallel" was
6
+ * only half true — the lead stood still for the sum of every dispatch, and
7
+ * each child's full reply landed in the lead's context whether it needed it
8
+ * there or not. OpenCode hands plugins its own client (`input.client`), and
9
+ * the official session API has `create` + `promptAsync` — "start if needed
10
+ * and return IMMEDIATELY" — so a plugin-owned dispatcher gets real overlap
11
+ * without touching a line of host code. If a future host ever removes that
12
+ * surface, both tools degrade with an explicit instruction to fall back to
13
+ * `task`, rather than failing the round.
14
+ *
15
+ * Contract kept from T3 (no sub-agent spawns a sub-agent):
16
+ * - `tm_dispatch` executes ONLY for the team lead (ctx.agent check here,
17
+ * plus an explicit deny for the five specialists in agents.ts — the
18
+ * tm_* wildcard would otherwise hand it to everyone);
19
+ * - children are the five named specialists, never "team";
20
+ * - the child session is parented to the lead session (parentID), so the
21
+ * host's own session tree, cancellation and UI still make sense.
22
+ *
23
+ * Context economy (design goal #4): tm_join renders each child's reply
24
+ * through the SAME governance pipeline as every other tm_* tool, so five
25
+ * long sub-agent reports become five handles + 80-token previews that the
26
+ * lead can page through with tm_fetch — not 5×N kilotokens dumped inline.
27
+ */
28
+ import { tmError, toToolResult } from "./result.js";
29
+ import { unwrapClientResult } from "./client-unwrap.js";
30
+ import { detectContentType } from "./preview.js";
31
+ import { shorten } from "./config.js";
32
+ /** The five dispatchable specialists — "team" is deliberately NOT in the
33
+ * list: a lead spawning a lead is the nesting T3 closed. */
34
+ export const DISPATCH_TARGETS = ["architect", "implementer", "reviewer", "tester", "researcher"];
35
+ /** Resolve the host session API defensively — a missing namespace means the
36
+ * host does not speak this protocol, and the caller must degrade. */
37
+ export function sessionApiOf(client) {
38
+ const session = client?.session;
39
+ if (!session || typeof session !== "object")
40
+ return null;
41
+ const api = session;
42
+ if (typeof api.create !== "function" || typeof api.promptAsync !== "function")
43
+ return null;
44
+ return api;
45
+ }
46
+ /** The title `tm_dispatch` gives every child session. `parseDispatchTitle`
47
+ * is the discriminator on the way back: a child the host lists but this
48
+ * process never created is OURS only if this shape (and a known agent)
49
+ * matches — otherwise it belongs to the built-in `task` tool and we must
50
+ * not claim its reply. */
51
+ export function dispatchTitle(agent, label) {
52
+ return `tm:${agent}:${label}`;
53
+ }
54
+ export function parseDispatchTitle(title, targets) {
55
+ const t = typeof title === "string" ? title.trim() : "";
56
+ if (!t.startsWith("tm:"))
57
+ return null;
58
+ const rest = t.slice(3);
59
+ const colon = rest.indexOf(":");
60
+ const agent = (colon < 0 ? rest : rest.slice(0, colon)).trim().toLowerCase();
61
+ if (!agent || !targets.includes(agent))
62
+ return null;
63
+ return { agent, label: (colon < 0 ? "" : rest.slice(colon + 1)).trim().slice(0, 40) };
64
+ }
65
+ /**
66
+ * Pull the assistant reply text (and, when the host records it, the moment
67
+ * that reply completed) out of a `session.messages` payload.
68
+ * Shapes accepted (host has renamed things before): {info,parts} pairs or a
69
+ * bare Part[] — the LAST assistant message is the answer, everything earlier
70
+ * is that agent's own working transcript.
71
+ *
72
+ * `completedAt` is what lets a rebuilt registry tell "still running" from
73
+ * "finished while we were not listening": AssistantMessage.time.completed is
74
+ * only set once the message is done.
75
+ */
76
+ export function lastAssistantMessage(messages) {
77
+ const list = Array.isArray(messages) ? messages : [];
78
+ for (let i = list.length - 1; i >= 0; i--) {
79
+ const entry = list[i];
80
+ const info = entry?.info;
81
+ const role = typeof info?.role === "string" ? String(info.role).toLowerCase() : "";
82
+ if (role && role !== "assistant")
83
+ continue;
84
+ const completed = Number(info?.time?.completed);
85
+ const completedAt = Number.isFinite(completed) && completed > 0 ? completed : undefined;
86
+ const parts = entry?.parts;
87
+ if (!Array.isArray(parts)) {
88
+ // a bare message list (no {info,parts} envelope) — take any text part
89
+ const one = entry ?? {};
90
+ if (one.type === "text" && typeof one.text === "string")
91
+ return { text: one.text, completedAt };
92
+ continue;
93
+ }
94
+ const texts = parts
95
+ .filter((p) => {
96
+ const pp = p;
97
+ return pp && pp.type === "text" && typeof pp.text === "string" && pp.text.trim() !== "";
98
+ })
99
+ .map((p) => String(p.text));
100
+ if (texts.length)
101
+ return { text: texts.join("\n"), completedAt };
102
+ }
103
+ return { text: "" };
104
+ }
105
+ /** Back-compat seam: the reply text alone. */
106
+ export function lastAssistantText(messages) {
107
+ return lastAssistantMessage(messages).text;
108
+ }
109
+ /** One child's status line — the lead reads these, so keep them terse. */
110
+ export function renderChildLine(c, elapsedMs) {
111
+ const secs = Math.round(elapsedMs / 1000);
112
+ const tag = c.state === "running" ? `运行中 ${secs}s` : c.state === "error" ? `失败:${shorten(c.error ?? "", 80)}` : `已完成 ${secs}s`;
113
+ return `${c.sessionID} · ${c.agent} · "${c.label}" · ${tag}${c.adopted ? " ·(本进程重启后由宿主会话树接管)" : ""}`;
114
+ }
115
+ /** Verdicts tm_join can actually observe (issue #7's "leader keeps control"). */
116
+ export function summarizeStates(children) {
117
+ let running = 0;
118
+ let idle = 0;
119
+ let error = 0;
120
+ for (const c of children) {
121
+ if (c.state === "running")
122
+ running++;
123
+ else if (c.state === "error")
124
+ error++;
125
+ else
126
+ idle++;
127
+ }
128
+ return { running, idle, error };
129
+ }
130
+ /**
131
+ * Sleep used only by tm_join's bounded wait. Deliberately a plain timer:
132
+ * it never holds the event loop (the wait is awaited, not spun) and it is
133
+ * capped by `maxWaitMs` so a hung child cannot hang the lead.
134
+ */
135
+ function sleep(ms) {
136
+ return new Promise((res) => {
137
+ const t = setTimeout(res, ms);
138
+ t.unref?.();
139
+ });
140
+ }
141
+ export function buildDispatchTools(deps) {
142
+ const leadAgent = deps.leadAgent ?? "team";
143
+ const targets = deps.targets ?? DISPATCH_TARGETS;
144
+ const maxWaitMs = deps.maxWaitMs ?? 300_000;
145
+ const now = deps.now ?? (() => Date.now());
146
+ const store = deps.pipelines.store;
147
+ const log = (e) => store.appendTrajectory({ tool: "tm_dispatch", ...e });
148
+ const children = new Map();
149
+ const api = sessionApiOf(deps.client);
150
+ /** Refresh a child's state from the host's own status map (the event bus
151
+ * is the fast path; this is the belt when an event was missed — a child
152
+ * dispatched before a plugin restart, or a session.idle that never
153
+ * arrived). */
154
+ async function refreshFromStatus(directory) {
155
+ if (typeof api?.status !== "function")
156
+ return;
157
+ let un;
158
+ try {
159
+ // PROPERTY-ACCESS CALL — the SDK's endpoints need their receiver (see
160
+ // approval-gate.ts's replyCapableFn note); `const f = api.status` then
161
+ // `f(...)` threw "Cannot read properties of undefined (reading
162
+ // 'client')" on the live host and killed every dispatch.
163
+ un = unwrapClientResult(await api.status(directory ? { query: { directory } } : {}));
164
+ }
165
+ catch {
166
+ return;
167
+ }
168
+ if (!un.ok || !un.data || typeof un.data !== "object")
169
+ return;
170
+ const map = un.data;
171
+ for (const [sid, st] of Object.entries(map)) {
172
+ const rec = children.get(sid);
173
+ if (!rec || rec.state !== "running")
174
+ continue;
175
+ const type = String(st?.type ?? "").toLowerCase();
176
+ if (type === "idle") {
177
+ rec.state = "idle";
178
+ rec.finishedAt = now();
179
+ }
180
+ else if (type === "busy" || type === "retry") {
181
+ rec.state = "running";
182
+ }
183
+ }
184
+ }
185
+ function fetchReply(sid, directory) {
186
+ return (async () => {
187
+ if (typeof api?.messages !== "function")
188
+ return { text: "" };
189
+ try {
190
+ const un = unwrapClientResult(await api.messages({ path: { id: sid }, ...(directory ? { query: { directory } } : {}) }));
191
+ return un.ok ? lastAssistantMessage(un.data) : { text: "" };
192
+ }
193
+ catch {
194
+ return { text: "" };
195
+ }
196
+ })();
197
+ }
198
+ /**
199
+ * Adopt the children the HOST lists under this parent but this process never
200
+ * dispatched: the plugin instance restarted (or the lead resumed a session
201
+ * an earlier instance created) while a specialist was still working — or had
202
+ * already answered into a registry that no longer exists. Without this,
203
+ * tm_join's honest answer would be "没有待收集的派发" while a finished report
204
+ * sits in the host, which is exactly the silent loss issue #7 was about.
205
+ *
206
+ * The discriminator is the title tm_dispatch itself writes (`dispatchTitle`
207
+ * + a known agent), so a child spawned by the built-in `task` tool is never
208
+ * claimed as ours.
209
+ */
210
+ async function adoptFromHost(parent, directory, only) {
211
+ if (typeof api?.children !== "function" || !parent)
212
+ return 0;
213
+ let un;
214
+ try {
215
+ un = unwrapClientResult(await api.children({ path: { id: parent }, ...(directory ? { query: { directory } } : {}) }));
216
+ }
217
+ catch {
218
+ return 0;
219
+ }
220
+ if (!un.ok || !Array.isArray(un.data))
221
+ return 0;
222
+ let adopted = 0;
223
+ for (const raw of un.data) {
224
+ const sid = String(raw?.id ?? "").trim();
225
+ if (!sid || children.has(sid))
226
+ continue;
227
+ if (only && !only.has(sid))
228
+ continue;
229
+ const parsed = parseDispatchTitle(raw?.title, targets);
230
+ if (!parsed)
231
+ continue;
232
+ const created = Number(raw?.time?.created);
233
+ const rec = {
234
+ sessionID: sid,
235
+ agent: parsed.agent,
236
+ label: parsed.label || parsed.agent,
237
+ parentSessionID: parent,
238
+ startedAt: Number.isFinite(created) && created > 0 ? created : now(),
239
+ state: "running",
240
+ adopted: true,
241
+ };
242
+ children.set(sid, rec);
243
+ // the child's own protected reads must still open the official dialog
244
+ deps.onChildSession?.(sid, parsed.agent);
245
+ adopted++;
246
+ log({ step_id: "join", event: "adopt", child: sid, agent: parsed.agent, label: rec.label });
247
+ }
248
+ return adopted;
249
+ }
250
+ /** Settle verdict for adopted rows: `AssistantMessage.time.completed` is
251
+ * only set once the reply is done, so it answers "finished while nobody
252
+ * was listening?" without waiting for an event that already fired. */
253
+ async function settleAdopted(records, directory) {
254
+ for (const rec of records) {
255
+ if (!rec.adopted || rec.state !== "running")
256
+ continue;
257
+ const reply = await fetchReply(rec.sessionID, directory);
258
+ if (typeof reply.completedAt === "number") {
259
+ rec.state = "idle";
260
+ rec.finishedAt = reply.completedAt;
261
+ }
262
+ }
263
+ }
264
+ const dispatch = {
265
+ description: `Fire-and-continue sub-agent dispatch — the lead's parallelism lever (the built-in task tool BLOCKS you until the child finishes; this one does not).
266
+ - { agent: ${targets.join("|")} , task: "<self-contained brief>", label: "<short slug>" } → starts the specialist in its OWN child session (parented to yours) and returns the child session id IMMEDIATELY. You keep working the same round: plan the next step, do a cheap read of your own, or fire more dispatches — independent work runs concurrently instead of serially.
267
+ - The brief must stand alone: the child has not seen this conversation, does not know what you tried, and cannot ask you mid-run. Say what to do, WHY it matters, which files/paths are its territory, what "done" looks like, and how much thoroughness you expect — the child still answers the mandatory STATUS/CHANGES/FINDINGS/EVIDENCE/HANDOFF skeleton.
268
+ - Collect with tm_join (no wait = status snapshot, waitMs = bounded wait). Collected replies ride the offload pipeline: a long report arrives as a handle + preview, not a context flood.
269
+ - Division of labour: bulk reading / searching / aggregation burns the CHILD's context and comes back as a skeleton; your own context is the scarce resource — keep it for routing, decisions and the final merge.
270
+ - Only the team lead may call this; a child never dispatches (no nested teams). If the host exposes no async session API the call fails with an explicit "use the built-in task tool" directive.`,
271
+ args: {
272
+ agent: { descriptor: `agent: ${targets.join("|")} (required)` },
273
+ task: { descriptor: "task: string (required — the full self-contained brief the child works from)" },
274
+ label: { descriptor: "label: string (optional short slug for this dispatch, ≤40 chars)" },
275
+ },
276
+ execute: async (rawArgs, ctx) => {
277
+ const tool = "tm_dispatch";
278
+ try {
279
+ const args = (rawArgs ?? {});
280
+ const c = (ctx ?? {});
281
+ const caller = String(c.agent ?? "").trim();
282
+ if (caller && caller !== leadAgent) {
283
+ return toToolResult(tmError(tool, "governance", `只有 ${leadAgent} 可以派发子代理(当前 agent="${shorten(caller, 24)}")。T3 规则:子代理不再派子代理——把需要并行的工作交给 lead 编排。`));
284
+ }
285
+ const agent = String(args.agent ?? "").trim().toLowerCase();
286
+ if (!targets.includes(agent)) {
287
+ return toToolResult(tmError(tool, "args", `未知派发目标 "${shorten(agent, 30)}"——可用: ${targets.join(", ")}`));
288
+ }
289
+ const task = typeof args.task === "string" ? args.task.trim() : "";
290
+ if (task.length < 20) {
291
+ return toToolResult(tmError(tool, "args", "task 太短:子代理看不到本会话,派发说明必须自包含(目标、涉及文件、完成判据、期望深度)。"));
292
+ }
293
+ const parent = String(c.sessionID ?? "").trim();
294
+ if (!parent) {
295
+ return toToolResult(tmError(tool, "client", "缺少 sessionID(宿主未把会话上下文传给插件),无法建立父子会话。"));
296
+ }
297
+ if (!api) {
298
+ return toToolResult(tmError(tool, "client", `此宿主未暴露异步会话 API(client.session.create/promptAsync),tm_dispatch 不可用——改用内置 task 工具(会阻塞你,但功能等价)。`));
299
+ }
300
+ const label = (typeof args.label === "string" && args.label.trim() ? args.label.trim() : task.split(/\s+/).slice(0, 4).join(" ")).slice(0, 40);
301
+ if (typeof api?.create !== "function" || typeof api?.promptAsync !== "function") {
302
+ return toToolResult(tmError(tool, "client", "此宿主的 client.session 缺少 create/promptAsync——改用内置 task 工具。"));
303
+ }
304
+ // PROPERTY-ACCESS CALLS (api.create / api.promptAsync), never a
305
+ // captured function reference — see refreshFromStatus above.
306
+ const created = unwrapClientResult(await api.create({ body: { parentID: parent, title: dispatchTitle(agent, label) } }));
307
+ if (!created.ok)
308
+ return toToolResult(tmError(tool, "client", `创建子会话失败:${shorten(created.message ?? "", 120)}`));
309
+ const sid = String(created.data?.id ?? "").trim();
310
+ if (!sid)
311
+ return toToolResult(tmError(tool, "client", "子会话创建后未返回 id"));
312
+ const promptBody = {
313
+ agent,
314
+ noReply: false,
315
+ parts: [{ type: "text", text: task }],
316
+ };
317
+ const directory = typeof c.directory === "string" && c.directory ? c.directory : undefined;
318
+ const sent = unwrapClientResult(await api.promptAsync({ path: { id: sid }, ...(directory ? { query: { directory } } : {}), body: promptBody }));
319
+ if (!sent.ok) {
320
+ return toToolResult(tmError(tool, "client", `子会话 ${sid} 已创建但提示未能启动:${shorten(sent.message ?? "", 120)}——可对该 id 直接用内置 task,或本次改用 task 工具。`));
321
+ }
322
+ const rec = { sessionID: sid, agent, label, parentSessionID: parent, startedAt: now(), state: "running" };
323
+ children.set(sid, rec);
324
+ deps.onChildSession?.(sid, agent);
325
+ log({ step_id: "dispatch", event: "start", child: sid, parent: parent, agent, label });
326
+ return toToolResult([
327
+ `已派发(非阻塞):${agent} · "${label}" · 子会话 ${sid}`,
328
+ `你现在可以继续:编排下一步、做廉价检查、或继续派发其它独立任务。`,
329
+ `收集结果:tm_join(立即看状态)或 tm_join { waitMs: 60000 }。所有派发完成前不要提交结论。`,
330
+ ].join("\n"));
331
+ }
332
+ catch (err) {
333
+ const e = err;
334
+ return toToolResult(tmError(tool, "execute", `tm_dispatch 失败:${shorten(e?.message ?? err, 160)}`));
335
+ }
336
+ },
337
+ };
338
+ const join = {
339
+ description: `Collect what the async dispatches (tm_dispatch) have produced.
340
+ - No args: status snapshot of every open child of THIS session — running / idle(done) / error, with elapsed seconds. Cheap and non-blocking: use it to decide whether to keep working or start merging.
341
+ - { waitMs: 30000 }: bounded wait (capped at ${Math.round(maxWaitMs / 1000)}s) until every child settles, then returns each one's reply skeleton. Never wait for a child whose result you do not need — abort it instead ({ cancel: true }).
342
+ - { ids: [...] }: restrict to those child sessions; { cancel: true }: abort still-running ones (a runaway child is yours to stop, not the user's problem).
343
+ - A plugin/host restart does NOT orphan a dispatch: children the host still lists under your session are re-adopted automatically (their rows are marked 接管), and one that answered while nobody was listening is reported 已完成, not lost.
344
+ - Replies come back through the offload pipeline: a long sub-agent report arrives as a handle + ≤80-token preview (page it with tm_fetch), so five parallel dispatches do not multiply your context. STATUS: blocked/failed children are surfaced first, always.`,
345
+ args: {
346
+ ids: { descriptor: "ids: string[] (optional — only these child sessions)" },
347
+ waitMs: { descriptor: "waitMs: number (optional 0..300000 — bounded wait before collecting)" },
348
+ cancel: { descriptor: "cancel: true (abort the still-running children in this set)" },
349
+ includeText: { descriptor: "includeText: false to get only the status table (default true)" },
350
+ },
351
+ execute: async (rawArgs, ctx) => {
352
+ const tool = "tm_join";
353
+ try {
354
+ const args = (rawArgs ?? {});
355
+ const c = (ctx ?? {});
356
+ const caller = String(c.agent ?? "").trim();
357
+ if (caller && caller !== leadAgent) {
358
+ return toToolResult(tmError(tool, "governance", `只有 ${leadAgent} 能收集派发结果。`));
359
+ }
360
+ const parent = String(c.sessionID ?? "").trim();
361
+ const directory = typeof c.directory === "string" && c.directory ? c.directory : undefined;
362
+ const idFilter = Array.isArray(args.ids)
363
+ ? new Set(args.ids.map((x) => String(x ?? "").trim()).filter(Boolean))
364
+ : null;
365
+ const owned = () => [...children.values()].filter((r) => (!parent || r.parentSessionID === parent) && (!idFilter || idFilter.has(r.sessionID)));
366
+ let mine = owned();
367
+ // This process has never seen some (or all) of what the lead is asking
368
+ // for — the host's session tree, not our memory, is the authority.
369
+ if (mine.length < (idFilter ? idFilter.size : 1)) {
370
+ if (await adoptFromHost(parent, directory, idFilter))
371
+ mine = owned();
372
+ }
373
+ if (!mine.length) {
374
+ return toToolResult(`没有待收集的派发${idFilter ? "(ids 未匹配到本会话的子代理,宿主会话树里也没有 tm: 标题的子会话)" : ""}。刚派发过却看不到?说明那次派发没成功——回到 tm_dispatch 的返回值检查。`);
375
+ }
376
+ await settleAdopted(mine, directory);
377
+ const waitMs = Math.max(0, Math.min(maxWaitMs, Number(args.waitMs) || 0));
378
+ const deadline = now() + waitMs;
379
+ let settled = false;
380
+ for (;;) {
381
+ await refreshFromStatus(directory);
382
+ const open = mine.filter((r) => r.state === "running");
383
+ if (!open.length || now() >= deadline) {
384
+ settled = !open.length;
385
+ break;
386
+ }
387
+ await sleep(Math.min(1000, Math.max(100, deadline - now())));
388
+ }
389
+ const stillRunning = mine.filter((r) => r.state === "running");
390
+ if (args.cancel === true || args.cancel === "true") {
391
+ for (const r of stillRunning) {
392
+ if (typeof api?.abort === "function") {
393
+ const un = unwrapClientResult(await api.abort({ path: { id: r.sessionID } }));
394
+ r.error = un.ok ? "aborted on request" : `abort failed: ${shorten(un.message ?? "", 60)}`;
395
+ }
396
+ else {
397
+ r.error = "宿主无 abort 接口,未取消";
398
+ }
399
+ r.state = "error";
400
+ r.finishedAt = now();
401
+ log({ step_id: "join", event: "cancel", child: r.sessionID, agent: r.agent, ok: r.error.startsWith("aborted") });
402
+ }
403
+ }
404
+ const sums = summarizeStates(mine);
405
+ const header = [
406
+ `派发汇总:${sums.idle} 完成 / ${sums.running} 运行中 / ${sums.error} 失败${settled ? "(全部已结算)" : "(未等到全部结算,可再次 tm_join)"}`,
407
+ ...mine.map((r) => renderChildLine(r, (r.finishedAt ?? now()) - r.startedAt)),
408
+ ];
409
+ const wantText = !(args.includeText === false || args.includeText === "false");
410
+ const collectible = mine.filter((r) => r.state !== "running");
411
+ const blocks = [];
412
+ if (wantText) {
413
+ for (const r of collectible) {
414
+ const reply = await fetchReply(r.sessionID, directory);
415
+ const text = reply.text;
416
+ blocks.push(`--- ${r.agent} "${r.label}" (${r.sessionID}) ---\n${text.trim() || "(该子会话没有可读的助手回复——用内置 read/tm_read 检查其会话,或重新派发)"}`);
417
+ }
418
+ }
419
+ const body = [...header, ...(blocks.length ? ["", blocks.join("\n")] : [])].join("\n");
420
+ const stepId = deps.pipelines.nextStepId();
421
+ return toToolResult(await deps.pipelines.govern(stepId, tool, body, {
422
+ contentType: detectContentType(body),
423
+ clue: `join parent=${shorten(parent, 24)} idle=${sums.idle} running=${sums.running} error=${sums.error}`,
424
+ }));
425
+ }
426
+ catch (err) {
427
+ const e = err;
428
+ return toToolResult(tmError(tool, "execute", `tm_join 失败:${shorten(e?.message ?? err, 160)}`));
429
+ }
430
+ },
431
+ };
432
+ const observeEvent = (event) => {
433
+ const type = String(event?.type ?? "");
434
+ if (!type.startsWith("session."))
435
+ return;
436
+ const props = event?.properties;
437
+ const sid = String(props?.sessionID ?? "").trim();
438
+ if (!sid)
439
+ return;
440
+ const rec = children.get(sid);
441
+ if (!rec)
442
+ return;
443
+ if (type === "session.idle") {
444
+ if (rec.state === "running") {
445
+ rec.state = "idle";
446
+ rec.finishedAt = now();
447
+ log({ step_id: "events", event: "idle", child: sid, agent: rec.agent, ms: (rec.finishedAt ?? 0) - rec.startedAt });
448
+ }
449
+ return;
450
+ }
451
+ if (type === "session.error") {
452
+ rec.state = "error";
453
+ rec.finishedAt = now();
454
+ rec.error = shorten(props?.error?.message ?? props?.error ?? "session.error", 120);
455
+ log({ step_id: "events", event: "error", child: sid, agent: rec.agent, reason: rec.error });
456
+ return;
457
+ }
458
+ if (type === "session.status") {
459
+ const st = String(props?.status?.type ?? "").toLowerCase();
460
+ if (st === "idle" && rec.state === "running") {
461
+ rec.state = "idle";
462
+ rec.finishedAt = now();
463
+ }
464
+ else if (st === "busy") {
465
+ rec.state = "running";
466
+ }
467
+ }
468
+ };
469
+ return {
470
+ tm_dispatch: dispatch,
471
+ tm_join: join,
472
+ observeEvent,
473
+ children: () => [...children.values()],
474
+ };
475
+ }
476
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/tm/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The "the engine ignored you" detector (2026-09-19, from a live session).
3
+ *
4
+ * Evidence: one `team` session spent 66 tool calls / 25 LLM steps / 2.8 M
5
+ * input tokens on a three-term lookup. Calls #5 and #6 asked bing for
6
+ * `"舞萌DX" "你好世界"` and `"舞萌DX" "我的世界"` — two different queries — and
7
+ * got byte-identical 10-hit lists about the Chinese character 舞 (dictionary
8
+ * entries, dance videos). Nothing in the reply said so, so the agent kept
9
+ * paying for the collapse: 20 more calls hand-building SERP URLs, then a
10
+ * browser session, to work out what one honest signal would have told it in
11
+ * the first minute — that the engine had dropped its qualifiers.
12
+ *
13
+ * Two independent signals, both cheap and deterministic:
14
+ * - IDENTICAL hit set under a DIFFERENT query → the engine ignored the
15
+ * query (a collapse), not "the topic is thin";
16
+ * - ZERO query-token overlap across every hit → the answer is unrelated to
17
+ * what was asked.
18
+ *
19
+ * Either one is reported as a DIRECTIVE (what to do next: split the concept,
20
+ * switch engine, or hand the whole lookups to a dispatched researcher), not
21
+ * as a shrug. The repetition counter is the circuit-breaker the failing
22
+ * session never had.
23
+ */
24
+ /** Stable fingerprint of a result set: the hosts+paths that came back, not
25
+ * their order (a re-rank of the same pages is the same answer). */
26
+ export declare function hitSignature(hits: ReadonlyArray<{
27
+ url?: string;
28
+ }>): string;
29
+ /** Does ANY hit actually mention the query? CJK is bigram-indexed (the same
30
+ * 口径 as the RRF relevance score) so "舞萌DX" matches a hit about 舞萌DX,
31
+ * while a page about the single character 舞 does not match. */
32
+ export declare function hitsShareAnyQueryTerm(hits: ReadonlyArray<{
33
+ title?: string;
34
+ snippet?: string;
35
+ url?: string;
36
+ }>, terms: readonly string[]): boolean;
37
+ export interface DupeVerdict {
38
+ /** how many times this SHAPE has now come back in this process */
39
+ repeats: number;
40
+ collapse: boolean;
41
+ irrelevant: boolean;
42
+ /** the directive appended to the tool output, "" when nothing is wrong */
43
+ note: string;
44
+ }
45
+ /**
46
+ * Per-process ledger of (engine → last signature + query). Deliberately
47
+ * in-memory: it is a conversation-level observation, and a restart of the
48
+ * plugin legitimately starts a fresh judgement (the agent is asking afresh).
49
+ */
50
+ export declare function createDupeGuard(limit?: number): {
51
+ observe: (engine: string, query: string, hits: ReadonlyArray<{
52
+ url?: string;
53
+ title?: string;
54
+ snippet?: string;
55
+ }>, terms: readonly string[]) => DupeVerdict;
56
+ seen: () => number;
57
+ };
58
+ //# sourceMappingURL=dupe-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dupe-guard.d.ts","sourceRoot":"","sources":["../../src/tm/dupe-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;oEACoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAa1E;AAED;;gEAEgE;AAChE,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,aAAa,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACvE,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAWT;AAED,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,SAAK,GAAG;IAC3C,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,WAAW,CAAA;IAC1J,IAAI,EAAE,MAAM,MAAM,CAAA;CACnB,CA2CA"}