@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.
- package/README.md +30 -6
- package/README.zh-CN.md +28 -4
- package/dist/agents.d.ts +5 -1
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +24 -2
- package/dist/agents.js.map +1 -1
- package/dist/capabilities.d.ts +66 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +165 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/host-hooks.d.ts +115 -0
- package/dist/host-hooks.d.ts.map +1 -0
- package/dist/host-hooks.js +270 -0
- package/dist/host-hooks.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +103 -4
- package/dist/index.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 +71 -8
- 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 +51 -2
- package/dist/prompts/shared.js.map +1 -1
- package/dist/prompts/specialists.d.ts +1 -1
- package/dist/prompts/specialists.d.ts.map +1 -1
- package/dist/prompts/specialists.js +38 -17
- package/dist/prompts/specialists.js.map +1 -1
- package/dist/tm/args-schema.d.ts +7 -1
- package/dist/tm/args-schema.d.ts.map +1 -1
- package/dist/tm/args-schema.js +9 -3
- package/dist/tm/args-schema.js.map +1 -1
- package/dist/tm/bash-timeout.d.ts +72 -0
- package/dist/tm/bash-timeout.d.ts.map +1 -0
- package/dist/tm/bash-timeout.js +100 -0
- package/dist/tm/bash-timeout.js.map +1 -0
- package/dist/tm/browser.d.ts +91 -5
- package/dist/tm/browser.d.ts.map +1 -1
- package/dist/tm/browser.js +564 -89
- package/dist/tm/browser.js.map +1 -1
- package/dist/tm/cache.d.ts +68 -0
- package/dist/tm/cache.d.ts.map +1 -0
- package/dist/tm/cache.js +157 -0
- package/dist/tm/cache.js.map +1 -0
- package/dist/tm/config.d.ts +87 -0
- package/dist/tm/config.d.ts.map +1 -1
- package/dist/tm/config.js +66 -0
- package/dist/tm/config.js.map +1 -1
- package/dist/tm/dispatch.d.ts +123 -0
- package/dist/tm/dispatch.d.ts.map +1 -0
- package/dist/tm/dispatch.js +476 -0
- package/dist/tm/dispatch.js.map +1 -0
- package/dist/tm/dupe-guard.d.ts +58 -0
- package/dist/tm/dupe-guard.d.ts.map +1 -0
- package/dist/tm/dupe-guard.js +105 -0
- package/dist/tm/dupe-guard.js.map +1 -0
- package/dist/tm/index.d.ts +32 -4
- package/dist/tm/index.d.ts.map +1 -1
- package/dist/tm/index.js +58 -5
- package/dist/tm/index.js.map +1 -1
- package/dist/tm/perm-ask.d.ts +1 -0
- package/dist/tm/perm-ask.d.ts.map +1 -1
- package/dist/tm/perm-ask.js +15 -1
- package/dist/tm/perm-ask.js.map +1 -1
- package/dist/tm/pipelines.d.ts.map +1 -1
- package/dist/tm/pipelines.js +11 -0
- package/dist/tm/pipelines.js.map +1 -1
- package/dist/tm/pty.d.ts +70 -0
- package/dist/tm/pty.d.ts.map +1 -0
- package/dist/tm/pty.js +242 -0
- package/dist/tm/pty.js.map +1 -0
- package/dist/tm/search.d.ts +56 -7
- package/dist/tm/search.d.ts.map +1 -1
- package/dist/tm/search.js +195 -41
- package/dist/tm/search.js.map +1 -1
- package/dist/tm/stats.d.ts +117 -0
- package/dist/tm/stats.d.ts.map +1 -0
- package/dist/tm/stats.js +296 -0
- package/dist/tm/stats.js.map +1 -0
- package/dist/tm/webfetch.d.ts +23 -0
- package/dist/tm/webfetch.d.ts.map +1 -1
- package/dist/tm/webfetch.js +97 -8
- package/dist/tm/webfetch.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/installation.md +216 -17
- 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"}
|