@stablekernel/opencode-cursor 0.7.1 → 0.8.0
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/CHANGELOG.md +33 -0
- package/dist/{chunk-RDY3H2LE.js → chunk-YIEC27VB.js} +436 -12
- package/dist/chunk-YIEC27VB.js.map +1 -0
- package/dist/plugin/index.js +55 -11
- package/dist/plugin/index.js.map +1 -1
- package/dist/provider/index.js +264 -32
- package/dist/provider/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-RDY3H2LE.js.map +0 -1
package/dist/provider/index.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
acquireAgent,
|
|
3
|
+
activityLine,
|
|
3
4
|
addUsage,
|
|
4
5
|
classifyError,
|
|
5
6
|
dropSessionRecord,
|
|
6
7
|
extractSystemText,
|
|
7
8
|
getSessionRecord,
|
|
8
9
|
linkSubagentSession,
|
|
10
|
+
linkSubagentSessionLive,
|
|
9
11
|
pluginLog,
|
|
12
|
+
registerSubagentCall,
|
|
13
|
+
renderConversationSteps,
|
|
10
14
|
resolveControls,
|
|
11
15
|
resolveCursorApiKey,
|
|
12
16
|
resolveSystemDelivery,
|
|
17
|
+
resultText,
|
|
13
18
|
sendAgentTurnSilently,
|
|
14
19
|
setPreferredTransport,
|
|
15
20
|
streamAgentTurn,
|
|
21
|
+
unregisterSubagentCall,
|
|
16
22
|
withSessionLock
|
|
17
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-YIEC27VB.js";
|
|
18
24
|
|
|
19
25
|
// src/provider/index.ts
|
|
20
26
|
import { NoSuchModelError } from "@ai-sdk/provider";
|
|
@@ -134,6 +140,203 @@ function trailingUserMessages(prompt, count) {
|
|
|
134
140
|
return collected.reverse();
|
|
135
141
|
}
|
|
136
142
|
|
|
143
|
+
// src/provider/subagent-stream.ts
|
|
144
|
+
var TITLE_KEYS = ["path", "command", "pattern", "query", "server"];
|
|
145
|
+
function toolTitle(input) {
|
|
146
|
+
if (typeof input !== "object" || input === null) return void 0;
|
|
147
|
+
const record = input;
|
|
148
|
+
for (const key of TITLE_KEYS) {
|
|
149
|
+
const value = record[key];
|
|
150
|
+
if (typeof value === "string" && value) return value;
|
|
151
|
+
}
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
var SubagentTranscriptSink = class _SubagentTranscriptSink {
|
|
155
|
+
/** Flush when this much time has elapsed since the last flush. */
|
|
156
|
+
static FLUSH_INTERVAL_MS = 1500;
|
|
157
|
+
session;
|
|
158
|
+
text = "";
|
|
159
|
+
reasoning = "";
|
|
160
|
+
tools = [];
|
|
161
|
+
pending = false;
|
|
162
|
+
lastFlush = 0;
|
|
163
|
+
timer;
|
|
164
|
+
done = false;
|
|
165
|
+
/** Nested call id → the running tool part written for it. */
|
|
166
|
+
partHandles = /* @__PURE__ */ new Map();
|
|
167
|
+
/** Serialises tool-part writes so a result never overtakes its start. */
|
|
168
|
+
partChain = Promise.resolve();
|
|
169
|
+
anonSeq = 0;
|
|
170
|
+
/** Correlation key for a nested event that arrived without a call id. */
|
|
171
|
+
nestedKey(id) {
|
|
172
|
+
return id || `anon-${++this.anonSeq}`;
|
|
173
|
+
}
|
|
174
|
+
/** Enqueue a tool-part write; fire-and-forget, never throws. */
|
|
175
|
+
enqueuePart(write) {
|
|
176
|
+
this.partChain = this.partChain.then(async () => {
|
|
177
|
+
await write();
|
|
178
|
+
}).catch(() => void 0);
|
|
179
|
+
}
|
|
180
|
+
constructor(session) {
|
|
181
|
+
this.session = session;
|
|
182
|
+
}
|
|
183
|
+
/** The linked child session id (for stamping the task card's sessionId). */
|
|
184
|
+
get childId() {
|
|
185
|
+
return this.session.childId;
|
|
186
|
+
}
|
|
187
|
+
/** Feed a normalized nested subagent event into the sink. */
|
|
188
|
+
push(event) {
|
|
189
|
+
if (this.done) return;
|
|
190
|
+
switch (event.type) {
|
|
191
|
+
case "text":
|
|
192
|
+
this.text += event.text;
|
|
193
|
+
this.pending = true;
|
|
194
|
+
break;
|
|
195
|
+
case "reasoning":
|
|
196
|
+
this.reasoning += event.text;
|
|
197
|
+
this.pending = true;
|
|
198
|
+
break;
|
|
199
|
+
case "tool-start": {
|
|
200
|
+
this.tools.push(`**\`${event.name}\`** ${formatArgs(event.input)}`);
|
|
201
|
+
this.pending = true;
|
|
202
|
+
const key = this.nestedKey(event.id);
|
|
203
|
+
const start = Date.now();
|
|
204
|
+
this.enqueuePart(async () => {
|
|
205
|
+
const partID = await this.session.toolPart({
|
|
206
|
+
callID: key,
|
|
207
|
+
tool: event.name,
|
|
208
|
+
status: "running",
|
|
209
|
+
title: toolTitle(event.input),
|
|
210
|
+
input: event.input,
|
|
211
|
+
start
|
|
212
|
+
});
|
|
213
|
+
if (partID) {
|
|
214
|
+
this.partHandles.set(key, {
|
|
215
|
+
partID,
|
|
216
|
+
callID: key,
|
|
217
|
+
tool: event.name,
|
|
218
|
+
title: toolTitle(event.input),
|
|
219
|
+
input: event.input,
|
|
220
|
+
start
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case "tool-result": {
|
|
227
|
+
this.tools.push(formatResult(event.name, event.result, event.isError));
|
|
228
|
+
this.pending = true;
|
|
229
|
+
const key = event.id || `result-${++this.anonSeq}`;
|
|
230
|
+
this.enqueuePart(async () => {
|
|
231
|
+
const handle = this.partHandles.get(key);
|
|
232
|
+
this.partHandles.delete(key);
|
|
233
|
+
await this.session.toolPart({
|
|
234
|
+
callID: handle?.callID ?? key,
|
|
235
|
+
tool: event.name,
|
|
236
|
+
status: "completed",
|
|
237
|
+
title: handle?.title,
|
|
238
|
+
input: handle?.input,
|
|
239
|
+
partID: handle?.partID,
|
|
240
|
+
start: handle?.start ?? Date.now(),
|
|
241
|
+
end: Date.now()
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
this.flushNow();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.armTimer();
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Flush any buffered content, then append the subagent's final answer
|
|
252
|
+
* (`resultSuffix`), a render of its `conversationSteps` (its own
|
|
253
|
+
* text/thinking/tool activity), and the optional activity line, and mark
|
|
254
|
+
* the sink done. Further pushes and flushes become no-ops.
|
|
255
|
+
*/
|
|
256
|
+
async finalize(resultValue, activity) {
|
|
257
|
+
if (this.done) return;
|
|
258
|
+
this.done = true;
|
|
259
|
+
if (this.timer) clearTimeout(this.timer);
|
|
260
|
+
this.timer = void 0;
|
|
261
|
+
const body = this.render();
|
|
262
|
+
if (body) await this.session.flush(body);
|
|
263
|
+
const suffix = typeof resultValue === "object" && resultValue !== null ? resultValue["resultSuffix"] : void 0;
|
|
264
|
+
if (typeof suffix === "string" && suffix) await this.session.flush(suffix);
|
|
265
|
+
const steps = renderConversationSteps(resultValue);
|
|
266
|
+
if (steps) await this.session.flush(steps);
|
|
267
|
+
await this.partChain;
|
|
268
|
+
for (const [, handle] of this.partHandles) {
|
|
269
|
+
await this.session.toolPart({
|
|
270
|
+
callID: handle.callID,
|
|
271
|
+
tool: handle.tool,
|
|
272
|
+
status: "completed",
|
|
273
|
+
title: handle.title,
|
|
274
|
+
input: handle.input,
|
|
275
|
+
partID: handle.partID,
|
|
276
|
+
start: handle.start,
|
|
277
|
+
end: Date.now()
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
this.partHandles.clear();
|
|
281
|
+
if (activity) await this.session.finalize(activity);
|
|
282
|
+
else await this.session.finalize();
|
|
283
|
+
}
|
|
284
|
+
armTimer() {
|
|
285
|
+
if (this.done || this.timer) return;
|
|
286
|
+
const elapsed = Date.now() - this.lastFlush;
|
|
287
|
+
const delay = Math.max(0, _SubagentTranscriptSink.FLUSH_INTERVAL_MS - elapsed);
|
|
288
|
+
this.timer = setTimeout(() => {
|
|
289
|
+
this.timer = void 0;
|
|
290
|
+
this.flushNow();
|
|
291
|
+
}, delay);
|
|
292
|
+
this.timer.unref?.();
|
|
293
|
+
}
|
|
294
|
+
flushNow() {
|
|
295
|
+
if (this.done) return;
|
|
296
|
+
if (this.timer) {
|
|
297
|
+
clearTimeout(this.timer);
|
|
298
|
+
this.timer = void 0;
|
|
299
|
+
}
|
|
300
|
+
if (!this.pending) return;
|
|
301
|
+
const body = this.render();
|
|
302
|
+
this.pending = false;
|
|
303
|
+
this.lastFlush = Date.now();
|
|
304
|
+
if (body) void this.session.flush(body);
|
|
305
|
+
}
|
|
306
|
+
/** Render the accumulated activity into a single markdown message. */
|
|
307
|
+
render() {
|
|
308
|
+
const parts = [];
|
|
309
|
+
if (this.text.trim()) parts.push(this.text.trim());
|
|
310
|
+
if (this.reasoning.trim()) parts.push(`> ${this.reasoning.trim()}`);
|
|
311
|
+
if (this.tools.length > 0) parts.push(this.tools.join("\n\n"));
|
|
312
|
+
const body = parts.join("\n\n").trim();
|
|
313
|
+
this.text = "";
|
|
314
|
+
this.reasoning = "";
|
|
315
|
+
this.tools.length = 0;
|
|
316
|
+
return body;
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
function formatArgs(input) {
|
|
320
|
+
let s = "";
|
|
321
|
+
try {
|
|
322
|
+
s = typeof input === "string" ? input : JSON.stringify(input);
|
|
323
|
+
} catch {
|
|
324
|
+
return "";
|
|
325
|
+
}
|
|
326
|
+
if (!s || s === "{}" || s === '""') return "";
|
|
327
|
+
return s;
|
|
328
|
+
}
|
|
329
|
+
function formatResult(name, result, isError) {
|
|
330
|
+
if (isError) return `**\`${name}\`** \u2014 _failed_`;
|
|
331
|
+
const text = resultText(result);
|
|
332
|
+
if (!text) return `**\`${name}\`** \u2014 _done_`;
|
|
333
|
+
return `**\`${name}\`**
|
|
334
|
+
|
|
335
|
+
\`\`\`
|
|
336
|
+
${text}
|
|
337
|
+
\`\`\``;
|
|
338
|
+
}
|
|
339
|
+
|
|
137
340
|
// src/provider/stream-map.ts
|
|
138
341
|
var TASK_TOOL_NAME = "task";
|
|
139
342
|
function injectSubagentSessionId(parts, sessionId) {
|
|
@@ -213,7 +416,10 @@ function numField(v, key) {
|
|
|
213
416
|
return isRecord(v) && typeof v[key] === "number" ? v[key] : void 0;
|
|
214
417
|
}
|
|
215
418
|
function successValue(result) {
|
|
216
|
-
|
|
419
|
+
if (!isRecord(result) || result["status"] !== "success") return void 0;
|
|
420
|
+
const value = result["value"];
|
|
421
|
+
if (value === void 0) return void 0;
|
|
422
|
+
return value;
|
|
217
423
|
}
|
|
218
424
|
function subagentTypeField(args) {
|
|
219
425
|
const sub = isRecord(args) ? args["subagentType"] : void 0;
|
|
@@ -238,7 +444,7 @@ function mcpFold(result) {
|
|
|
238
444
|
return { title: "", metadata: {}, output: text };
|
|
239
445
|
}
|
|
240
446
|
function mcpInputArgs(args) {
|
|
241
|
-
return isRecord(args) ? args["args"] : void 0;
|
|
447
|
+
return isRecord(args) && isRecord(args["args"]) ? args["args"] : void 0;
|
|
242
448
|
}
|
|
243
449
|
function webSearchProvider(args) {
|
|
244
450
|
const id = (strField(args, "providerIdentifier") ?? "").toLowerCase();
|
|
@@ -253,7 +459,7 @@ var WEBSEARCH_ADAPTER = {
|
|
|
253
459
|
tool: "websearch",
|
|
254
460
|
input: (args) => {
|
|
255
461
|
const query = strField(mcpInputArgs(args), "query");
|
|
256
|
-
return query
|
|
462
|
+
return query === void 0 ? {} : { query };
|
|
257
463
|
},
|
|
258
464
|
result: (value, args) => {
|
|
259
465
|
const provider = webSearchProvider(args);
|
|
@@ -325,15 +531,15 @@ var NATIVE_ADAPTERS = {
|
|
|
325
531
|
const totalLines = numField(value, "totalLines");
|
|
326
532
|
const fileSize = numField(value, "fileSize");
|
|
327
533
|
const linesReturned = content.split("\n").length;
|
|
328
|
-
const lineLabel = totalLines
|
|
534
|
+
const lineLabel = totalLines === void 0 ? `${linesReturned} lines` : `${linesReturned}/${totalLines} lines`;
|
|
329
535
|
return {
|
|
330
536
|
title: `${filePath} (${lineLabel})`,
|
|
331
537
|
metadata: {
|
|
332
538
|
preview: content.split("\n").slice(0, 20).join("\n"),
|
|
333
539
|
loaded: [],
|
|
334
540
|
linesReturned,
|
|
335
|
-
...totalLines
|
|
336
|
-
...fileSize
|
|
541
|
+
...totalLines === void 0 ? {} : { totalLines },
|
|
542
|
+
...fileSize === void 0 ? {} : { fileSize }
|
|
337
543
|
},
|
|
338
544
|
output: content
|
|
339
545
|
};
|
|
@@ -349,7 +555,7 @@ var NATIVE_ADAPTERS = {
|
|
|
349
555
|
result: (value, args) => {
|
|
350
556
|
const filePath = strField(args, "path") ?? "";
|
|
351
557
|
const lines = numField(value, "linesCreated");
|
|
352
|
-
const output = lines
|
|
558
|
+
const output = lines === void 0 ? "Wrote file successfully." : `Wrote ${lines} line${lines === 1 ? "" : "s"}.`;
|
|
353
559
|
return {
|
|
354
560
|
title: filePath,
|
|
355
561
|
metadata: { diagnostics: {}, filepath: filePath, exists: false },
|
|
@@ -417,9 +623,7 @@ var NATIVE_ADAPTERS = {
|
|
|
417
623
|
current = file;
|
|
418
624
|
lines.push(`${file}:`);
|
|
419
625
|
}
|
|
420
|
-
lines.push(
|
|
421
|
-
line !== void 0 ? ` Line ${line}: ${text}` : ` ${text}`
|
|
422
|
-
);
|
|
626
|
+
lines.push(line === void 0 ? ` ${text}` : ` Line ${line}: ${text}`);
|
|
423
627
|
total++;
|
|
424
628
|
}
|
|
425
629
|
} else if (u["type"] === "files" && isRecord(output) && Array.isArray(output["files"])) {
|
|
@@ -440,11 +644,9 @@ var NATIVE_ADAPTERS = {
|
|
|
440
644
|
return {
|
|
441
645
|
title,
|
|
442
646
|
metadata: { matches: total, truncated: false },
|
|
443
|
-
output: total > 0 ? [
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
...lines
|
|
447
|
-
].join("\n") : "No matches found"
|
|
647
|
+
output: total > 0 ? [`Found ${total} match${total === 1 ? "" : "es"}`, "", ...lines].join(
|
|
648
|
+
"\n"
|
|
649
|
+
) : "No matches found"
|
|
448
650
|
};
|
|
449
651
|
}
|
|
450
652
|
},
|
|
@@ -452,7 +654,9 @@ var NATIVE_ADAPTERS = {
|
|
|
452
654
|
// + results body instead of the raw `{results}` JSON.
|
|
453
655
|
semSearch: {
|
|
454
656
|
input: (args) => {
|
|
455
|
-
const out = {
|
|
657
|
+
const out = {
|
|
658
|
+
query: strField(args, "query") ?? ""
|
|
659
|
+
};
|
|
456
660
|
const dirs = isRecord(args) && Array.isArray(args["targetDirectories"]) ? args["targetDirectories"] : void 0;
|
|
457
661
|
if (dirs && dirs.length > 0) out["targetDirectories"] = dirs;
|
|
458
662
|
return out;
|
|
@@ -557,7 +761,7 @@ var NATIVE_ADAPTERS = {
|
|
|
557
761
|
const start = isRecord(d["range"]) ? d["range"]["start"] : void 0;
|
|
558
762
|
const line = numField(start, "line");
|
|
559
763
|
const char = numField(start, "character");
|
|
560
|
-
const loc = line
|
|
764
|
+
const loc = line === void 0 ? "" : ` L${line + 1}${char === void 0 ? "" : `:${char + 1}`}`;
|
|
561
765
|
lines.push(` ${severity}${loc}: ${strField(d, "message") ?? ""}`);
|
|
562
766
|
total++;
|
|
563
767
|
}
|
|
@@ -579,7 +783,7 @@ var NATIVE_ADAPTERS = {
|
|
|
579
783
|
return {
|
|
580
784
|
title: path,
|
|
581
785
|
metadata: {},
|
|
582
|
-
output: size
|
|
786
|
+
output: size === void 0 ? `Deleted ${path}.` : `Deleted ${path} (${size} bytes).`
|
|
583
787
|
};
|
|
584
788
|
}
|
|
585
789
|
}
|
|
@@ -668,7 +872,8 @@ function blockToolInputPartialParts(id, name, input, state) {
|
|
|
668
872
|
dynamic: true
|
|
669
873
|
});
|
|
670
874
|
const delta = prev && serialized.startsWith(prev.serialized) ? serialized.slice(prev.serialized.length) : serialized;
|
|
671
|
-
if (delta)
|
|
875
|
+
if (delta)
|
|
876
|
+
parts.push({ type: "tool-input-delta", id, delta });
|
|
672
877
|
return parts;
|
|
673
878
|
}
|
|
674
879
|
function blockToolCallParts(id, name, input, state) {
|
|
@@ -796,6 +1001,7 @@ function cursorEventsToStream(events, toolDisplay = "blocks", ctx = {}) {
|
|
|
796
1001
|
let thinkingMs = 0;
|
|
797
1002
|
let compactions = 0;
|
|
798
1003
|
const toolState = newBlockToolState();
|
|
1004
|
+
const subagentSinks = /* @__PURE__ */ new Map();
|
|
799
1005
|
const closeDanglingToolCalls = () => {
|
|
800
1006
|
for (const part of blockDanglingParts(toolState)) {
|
|
801
1007
|
controller.enqueue(part);
|
|
@@ -898,6 +1104,16 @@ function cursorEventsToStream(events, toolDisplay = "blocks", ctx = {}) {
|
|
|
898
1104
|
toolState.dropped.add(event.id);
|
|
899
1105
|
break;
|
|
900
1106
|
}
|
|
1107
|
+
if (toolDisplay === "blocks" && event.name === TASK_TOOL_NAME && !subagentSinks.has(event.id) && ctx.sessionID) {
|
|
1108
|
+
const live = await linkSubagentSessionLive({
|
|
1109
|
+
parentSessionID: ctx.sessionID,
|
|
1110
|
+
args: event.input
|
|
1111
|
+
});
|
|
1112
|
+
if (live) {
|
|
1113
|
+
subagentSinks.set(event.id, new SubagentTranscriptSink(live));
|
|
1114
|
+
registerSubagentCall(event.id, live.childId);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
901
1117
|
if (toolDisplay === "blocks") {
|
|
902
1118
|
if (toolState.partials.delete(event.id)) {
|
|
903
1119
|
controller.enqueue({
|
|
@@ -915,9 +1131,7 @@ function cursorEventsToStream(events, toolDisplay = "blocks", ctx = {}) {
|
|
|
915
1131
|
closeText();
|
|
916
1132
|
closeReasoning();
|
|
917
1133
|
}
|
|
918
|
-
for (const part of parts)
|
|
919
|
-
controller.enqueue(part);
|
|
920
|
-
}
|
|
1134
|
+
for (const part of parts) controller.enqueue(part);
|
|
921
1135
|
} else {
|
|
922
1136
|
reasoningLine(`
|
|
923
1137
|
${formatToolCall(event.name, event.input)}
|
|
@@ -939,13 +1153,25 @@ ${formatToolCall(event.name, event.input)}
|
|
|
939
1153
|
closeText();
|
|
940
1154
|
closeReasoning();
|
|
941
1155
|
}
|
|
942
|
-
if (event.name === TASK_TOOL_NAME && !event.isError
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1156
|
+
if (event.name === TASK_TOOL_NAME && !event.isError) {
|
|
1157
|
+
const sink = subagentSinks.get(event.id);
|
|
1158
|
+
if (sink) {
|
|
1159
|
+
const value = isRecord(event.result) && event.result["status"] === "success" ? event.result["value"] : void 0;
|
|
1160
|
+
await sink.finalize(value, activityLine(value));
|
|
1161
|
+
injectSubagentSessionId(parts, sink.childId);
|
|
1162
|
+
subagentSinks.delete(event.id);
|
|
1163
|
+
unregisterSubagentCall(event.id);
|
|
1164
|
+
} else if (ctx.sessionID) {
|
|
1165
|
+
const childId = await linkSubagentSession({
|
|
1166
|
+
parentSessionID: ctx.sessionID,
|
|
1167
|
+
args: taskArgs,
|
|
1168
|
+
result: event.result
|
|
1169
|
+
});
|
|
1170
|
+
if (childId) injectSubagentSessionId(parts, childId);
|
|
1171
|
+
}
|
|
1172
|
+
} else if (event.name === TASK_TOOL_NAME) {
|
|
1173
|
+
subagentSinks.delete(event.id);
|
|
1174
|
+
unregisterSubagentCall(event.id);
|
|
949
1175
|
}
|
|
950
1176
|
for (const part of parts) {
|
|
951
1177
|
controller.enqueue(part);
|
|
@@ -955,13 +1181,17 @@ ${formatToolCall(event.name, event.input)}
|
|
|
955
1181
|
`);
|
|
956
1182
|
}
|
|
957
1183
|
break;
|
|
1184
|
+
case "subagent-event": {
|
|
1185
|
+
const sink = subagentSinks.get(event.callId);
|
|
1186
|
+
if (sink) sink.push(event.event);
|
|
1187
|
+
break;
|
|
1188
|
+
}
|
|
958
1189
|
case "usage":
|
|
959
1190
|
usage = mapUsage(event.usage);
|
|
960
1191
|
break;
|
|
961
1192
|
case "reasoning-complete":
|
|
962
1193
|
closeReasoning();
|
|
963
|
-
if (typeof event.durationMs === "number")
|
|
964
|
-
thinkingMs += event.durationMs;
|
|
1194
|
+
if (typeof event.durationMs === "number") thinkingMs += event.durationMs;
|
|
965
1195
|
break;
|
|
966
1196
|
case "compaction":
|
|
967
1197
|
compactions++;
|
|
@@ -1078,6 +1308,8 @@ ${formatToolCall(event.name, event.input)}
|
|
|
1078
1308
|
break;
|
|
1079
1309
|
case "compaction":
|
|
1080
1310
|
break;
|
|
1311
|
+
case "subagent-event":
|
|
1312
|
+
break;
|
|
1081
1313
|
case "finish":
|
|
1082
1314
|
if (!text && event.text) text = event.text;
|
|
1083
1315
|
break;
|