llmist 5.0.0 → 6.0.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/dist/{chunk-3SZIQI45.js → chunk-EIE5VRSI.js} +72 -7
- package/dist/chunk-EIE5VRSI.js.map +1 -0
- package/dist/{chunk-UBPZUVIN.js → chunk-F62X5W2G.js} +2 -2
- package/dist/cli.cjs +360 -83
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +288 -76
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +71 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +2 -2
- package/dist/testing/index.cjs +71 -6
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3SZIQI45.js.map +0 -1
- /package/dist/{chunk-UBPZUVIN.js.map → chunk-F62X5W2G.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-F62X5W2G.js";
|
|
3
3
|
import {
|
|
4
4
|
AbstractGadget,
|
|
5
5
|
AgentBuilder,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
schemaToJSONSchema,
|
|
35
35
|
text,
|
|
36
36
|
validateGadgetSchema
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-EIE5VRSI.js";
|
|
38
38
|
|
|
39
39
|
// src/cli/constants.ts
|
|
40
40
|
var CLI_NAME = "llmist";
|
|
@@ -121,7 +121,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
|
|
|
121
121
|
// package.json
|
|
122
122
|
var package_default = {
|
|
123
123
|
name: "llmist",
|
|
124
|
-
version: "5.
|
|
124
|
+
version: "5.1.0",
|
|
125
125
|
description: "TypeScript LLM client with streaming tool execution. Tools fire mid-stream. Built-in function calling works with any model\u2014no structured outputs or native tool support required.",
|
|
126
126
|
type: "module",
|
|
127
127
|
main: "dist/index.cjs",
|
|
@@ -2941,7 +2941,8 @@ function formatCost(cost) {
|
|
|
2941
2941
|
}
|
|
2942
2942
|
function formatLLMCallLine(info) {
|
|
2943
2943
|
const parts = [];
|
|
2944
|
-
|
|
2944
|
+
const callNumber = info.parentCallNumber ? `#${info.parentCallNumber}.${info.iteration}` : `#${info.iteration}`;
|
|
2945
|
+
parts.push(`${chalk3.cyan(callNumber)} ${chalk3.magenta(info.model)}`);
|
|
2945
2946
|
if (info.contextPercent !== void 0 && info.contextPercent !== null) {
|
|
2946
2947
|
const formatted = `${Math.round(info.contextPercent)}%`;
|
|
2947
2948
|
if (info.contextPercent >= 80) {
|
|
@@ -3046,7 +3047,7 @@ function getRawValue(value) {
|
|
|
3046
3047
|
function truncateValue(str, maxLen) {
|
|
3047
3048
|
if (maxLen <= 0) return "";
|
|
3048
3049
|
if (str.length <= maxLen) return str;
|
|
3049
|
-
return `${str.slice(0, maxLen)}\u2026`;
|
|
3050
|
+
return `${str.slice(0, maxLen - 1)}\u2026`;
|
|
3050
3051
|
}
|
|
3051
3052
|
function formatParametersInline(params, maxWidth) {
|
|
3052
3053
|
if (!params || Object.keys(params).length === 0) {
|
|
@@ -3074,6 +3075,11 @@ function formatParametersInline(params, maxWidth) {
|
|
|
3074
3075
|
const proportion = v.length / totalRawLength;
|
|
3075
3076
|
return Math.max(minPerValue, Math.floor(proportion * availableForValues));
|
|
3076
3077
|
});
|
|
3078
|
+
const totalLimits = limits.reduce((sum, l) => sum + l, 0);
|
|
3079
|
+
if (totalLimits > availableForValues) {
|
|
3080
|
+
const scale = availableForValues / totalLimits;
|
|
3081
|
+
limits = limits.map((l) => Math.max(1, Math.floor(l * scale)));
|
|
3082
|
+
}
|
|
3077
3083
|
}
|
|
3078
3084
|
}
|
|
3079
3085
|
} else {
|
|
@@ -3089,8 +3095,8 @@ function formatGadgetLine(info, maxWidth) {
|
|
|
3089
3095
|
const gadgetLabel = chalk3.magenta.bold(info.name);
|
|
3090
3096
|
const timeStr = `${info.elapsedSeconds.toFixed(1)}s`;
|
|
3091
3097
|
const timeLabel = chalk3.dim(timeStr);
|
|
3092
|
-
const fixedLength =
|
|
3093
|
-
const availableForParams = Math.max(40, terminalWidth - fixedLength -
|
|
3098
|
+
const fixedLength = 3 + info.name.length + 2 + 1 + timeStr.length;
|
|
3099
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 3);
|
|
3094
3100
|
const paramsStr = formatParametersInline(info.parameters, availableForParams);
|
|
3095
3101
|
const paramsLabel = paramsStr ? `${chalk3.dim("(")}${paramsStr}${chalk3.dim(")")}` : "";
|
|
3096
3102
|
if (info.error) {
|
|
@@ -3100,17 +3106,21 @@ function formatGadgetLine(info, maxWidth) {
|
|
|
3100
3106
|
if (!info.isComplete) {
|
|
3101
3107
|
return `${chalk3.blue("\u23F5")} ${gadgetLabel}${paramsLabel} ${timeLabel}`;
|
|
3102
3108
|
}
|
|
3103
|
-
let
|
|
3109
|
+
let outputLabel;
|
|
3104
3110
|
if (info.tokenCount !== void 0 && info.tokenCount > 0) {
|
|
3105
|
-
|
|
3111
|
+
outputLabel = chalk3.dim("\u2193") + chalk3.green(` ${formatTokens(info.tokenCount)} `);
|
|
3106
3112
|
} else if (info.outputBytes !== void 0 && info.outputBytes > 0) {
|
|
3107
|
-
|
|
3113
|
+
outputLabel = chalk3.green(formatBytes(info.outputBytes)) + " ";
|
|
3108
3114
|
} else {
|
|
3109
|
-
|
|
3115
|
+
outputLabel = "";
|
|
3110
3116
|
}
|
|
3111
3117
|
const icon = info.breaksLoop ? chalk3.yellow("\u23F9") : chalk3.green("\u2713");
|
|
3112
|
-
const
|
|
3113
|
-
|
|
3118
|
+
const nameRef = chalk3.magenta(info.name);
|
|
3119
|
+
const line1 = `${icon} ${gadgetLabel}${paramsLabel}`;
|
|
3120
|
+
const line2Prefix = ` ${chalk3.dim("\u2192")} ${nameRef} ${outputLabel}`;
|
|
3121
|
+
const line2 = `${line2Prefix}${timeLabel}`;
|
|
3122
|
+
return `${line1}
|
|
3123
|
+
${line2}`;
|
|
3114
3124
|
}
|
|
3115
3125
|
function formatBytes(bytes) {
|
|
3116
3126
|
if (bytes < 1024) {
|
|
@@ -3121,6 +3131,11 @@ function formatBytes(bytes) {
|
|
|
3121
3131
|
}
|
|
3122
3132
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
3123
3133
|
}
|
|
3134
|
+
function truncateOutputPreview(output, maxWidth) {
|
|
3135
|
+
const normalized = output.replace(/\s+/g, " ").trim();
|
|
3136
|
+
if (normalized.length <= maxWidth) return normalized;
|
|
3137
|
+
return normalized.slice(0, maxWidth - 1) + "\u2026";
|
|
3138
|
+
}
|
|
3124
3139
|
function getMediaIcon(kind) {
|
|
3125
3140
|
switch (kind) {
|
|
3126
3141
|
case "image":
|
|
@@ -3148,37 +3163,99 @@ function formatGadgetSummary2(result) {
|
|
|
3148
3163
|
const gadgetLabel = chalk3.magenta.bold(result.gadgetName);
|
|
3149
3164
|
const timeStr = result.executionTimeMs >= 1e3 ? `${(result.executionTimeMs / 1e3).toFixed(1)}s` : `${Math.round(result.executionTimeMs)}ms`;
|
|
3150
3165
|
const timeLabel = chalk3.dim(timeStr);
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3166
|
+
const fixedLength = 3 + result.gadgetName.length + 2;
|
|
3167
|
+
const availableForParams = Math.max(40, terminalWidth - fixedLength - 3);
|
|
3168
|
+
const paramsStr = formatParametersInline(result.parameters, availableForParams);
|
|
3169
|
+
const paramsLabel = paramsStr ? `${chalk3.dim("(")}${paramsStr}${chalk3.dim(")")}` : "";
|
|
3170
|
+
const icon = result.breaksLoop ? chalk3.yellow("\u23F9") : result.error ? chalk3.red("\u2717") : chalk3.green("\u2713");
|
|
3171
|
+
const line1 = `${icon} ${gadgetLabel}${paramsLabel}`;
|
|
3172
|
+
const nameRef = chalk3.magenta(result.gadgetName);
|
|
3173
|
+
const hasSubagentMetrics = result.subagentMetrics && result.subagentMetrics.callCount > 0;
|
|
3174
|
+
let outputLabel;
|
|
3175
|
+
let outputStrRaw;
|
|
3176
|
+
if (!hasSubagentMetrics && result.tokenCount !== void 0 && result.tokenCount > 0) {
|
|
3177
|
+
const tokenStr = formatTokens(result.tokenCount);
|
|
3178
|
+
outputLabel = chalk3.dim("\u2193") + chalk3.green(` ${tokenStr} `);
|
|
3179
|
+
outputStrRaw = `\u2193 ${tokenStr} `;
|
|
3180
|
+
} else if (!hasSubagentMetrics && result.result) {
|
|
3155
3181
|
const outputBytes = Buffer.byteLength(result.result, "utf-8");
|
|
3156
|
-
|
|
3182
|
+
if (outputBytes > 0) {
|
|
3183
|
+
const bytesStr = formatBytes(outputBytes);
|
|
3184
|
+
outputLabel = chalk3.green(bytesStr) + " ";
|
|
3185
|
+
outputStrRaw = bytesStr + " ";
|
|
3186
|
+
} else {
|
|
3187
|
+
outputLabel = "";
|
|
3188
|
+
outputStrRaw = "";
|
|
3189
|
+
}
|
|
3157
3190
|
} else {
|
|
3158
|
-
|
|
3191
|
+
outputLabel = "";
|
|
3192
|
+
outputStrRaw = "";
|
|
3159
3193
|
}
|
|
3160
|
-
const fixedLength = 2 + result.gadgetName.length + 2 + 3 + outputStr.length + 1 + timeStr.length;
|
|
3161
|
-
const availableForParams = Math.max(40, terminalWidth - fixedLength - 2);
|
|
3162
|
-
const paramsStr = formatParametersInline(result.parameters, availableForParams);
|
|
3163
|
-
const paramsLabel = paramsStr ? `${chalk3.dim("(")}${paramsStr}${chalk3.dim(")")}` : "";
|
|
3164
3194
|
if (result.error) {
|
|
3165
3195
|
const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}\u2026` : result.error;
|
|
3166
|
-
|
|
3196
|
+
const line22 = ` ${chalk3.dim("\u2192")} ${nameRef} ${chalk3.red("error:")} ${errorMsg} ${timeLabel}`;
|
|
3197
|
+
return `${line1}
|
|
3198
|
+
${line22}`;
|
|
3199
|
+
}
|
|
3200
|
+
const previewWidth = Math.floor(terminalWidth * 0.6);
|
|
3201
|
+
const prefixLength = 4 + result.gadgetName.length + 1 + outputStrRaw.length + 1 + timeStr.length + 2;
|
|
3202
|
+
const availablePreview = Math.max(20, previewWidth - prefixLength);
|
|
3203
|
+
let customPreview;
|
|
3204
|
+
if (result.gadgetName === "TodoUpsert" && result.parameters?.content) {
|
|
3205
|
+
const statusEmoji = result.parameters.status === "done" ? "\u2705" : result.parameters.status === "in_progress" ? "\u{1F504}" : "\u2B1C";
|
|
3206
|
+
const content = String(result.parameters.content);
|
|
3207
|
+
customPreview = `${statusEmoji} ${truncateOutputPreview(content, availablePreview - 3)}`;
|
|
3208
|
+
}
|
|
3209
|
+
if (result.gadgetName === "GoogleSearch" && result.parameters?.query) {
|
|
3210
|
+
const query = String(result.parameters.query);
|
|
3211
|
+
const countMatch = result.result?.match(/\((\d+)\s+of\s+[\d,]+\s+results?\)/i) || // "(10 of 36400000 results)"
|
|
3212
|
+
result.result?.match(/(\d+)\s+results?\s+found/i) || // "10 results found"
|
|
3213
|
+
result.result?.match(/found\s+(\d+)\s+results?/i);
|
|
3214
|
+
const count = countMatch?.[1] ?? (result.parameters.maxResults ? String(result.parameters.maxResults) : null);
|
|
3215
|
+
const countStr = count ? ` \u2192 ${count} results` : "";
|
|
3216
|
+
const queryPreview = truncateOutputPreview(query, availablePreview - 5 - countStr.length);
|
|
3217
|
+
customPreview = `\u{1F50D} "${queryPreview}"${countStr}`;
|
|
3218
|
+
}
|
|
3219
|
+
let subagentMetricsStr = "";
|
|
3220
|
+
if (result.subagentMetrics && result.subagentMetrics.callCount > 0) {
|
|
3221
|
+
const parts = [];
|
|
3222
|
+
const m = result.subagentMetrics;
|
|
3223
|
+
if (m.inputTokens > 0) {
|
|
3224
|
+
parts.push(chalk3.dim("\u2191") + chalk3.yellow(` ${formatTokens(m.inputTokens)}`));
|
|
3225
|
+
}
|
|
3226
|
+
if (m.cachedInputTokens > 0) {
|
|
3227
|
+
parts.push(chalk3.dim("\u27F3") + chalk3.blue(` ${formatTokens(m.cachedInputTokens)}`));
|
|
3228
|
+
}
|
|
3229
|
+
if (m.outputTokens > 0) {
|
|
3230
|
+
parts.push(chalk3.dim("\u2193") + chalk3.green(` ${formatTokens(m.outputTokens)}`));
|
|
3231
|
+
}
|
|
3232
|
+
if (m.cost > 0) {
|
|
3233
|
+
parts.push(chalk3.cyan(`$${formatCost(m.cost)}`));
|
|
3234
|
+
}
|
|
3235
|
+
if (parts.length > 0) {
|
|
3236
|
+
subagentMetricsStr = parts.join(chalk3.dim(" | ")) + chalk3.dim(" | ");
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
let line2;
|
|
3240
|
+
const previewContent = customPreview ?? (result.result?.trim() ? truncateOutputPreview(result.result, availablePreview) : null);
|
|
3241
|
+
if (previewContent) {
|
|
3242
|
+
line2 = ` ${chalk3.dim("\u2192")} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}${chalk3.dim(":")} ${chalk3.dim(previewContent)}`;
|
|
3243
|
+
} else {
|
|
3244
|
+
line2 = ` ${chalk3.dim("\u2192")} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}`;
|
|
3167
3245
|
}
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
let summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${chalk3.dim("\u2192")} ${outputLabel} ${timeLabel}`;
|
|
3246
|
+
let output = `${line1}
|
|
3247
|
+
${line2}`;
|
|
3171
3248
|
if (result.media && result.media.length > 0) {
|
|
3172
3249
|
const mediaLines = result.media.map(formatMediaLine);
|
|
3173
|
-
|
|
3250
|
+
output += "\n" + mediaLines.join("\n");
|
|
3174
3251
|
}
|
|
3175
3252
|
if (result.gadgetName === "TellUser" && result.parameters?.message) {
|
|
3176
3253
|
const message = String(result.parameters.message);
|
|
3177
3254
|
const rendered = renderMarkdownWithSeparators(message);
|
|
3178
|
-
return `${
|
|
3255
|
+
return `${output}
|
|
3179
3256
|
${rendered}`;
|
|
3180
3257
|
}
|
|
3181
|
-
return
|
|
3258
|
+
return output;
|
|
3182
3259
|
}
|
|
3183
3260
|
|
|
3184
3261
|
// src/cli/utils.ts
|
|
@@ -3371,18 +3448,60 @@ var StreamProgress = class {
|
|
|
3371
3448
|
hasInFlightGadgets() {
|
|
3372
3449
|
return this.inFlightGadgets.size > 0;
|
|
3373
3450
|
}
|
|
3451
|
+
/**
|
|
3452
|
+
* Mark a gadget as completed (keeps it visible with ✓ indicator).
|
|
3453
|
+
* Records completion time to freeze the elapsed timer.
|
|
3454
|
+
* The gadget and its nested operations remain visible until clearCompletedGadgets() is called.
|
|
3455
|
+
*/
|
|
3456
|
+
completeGadget(invocationId) {
|
|
3457
|
+
const gadget = this.inFlightGadgets.get(invocationId);
|
|
3458
|
+
if (gadget) {
|
|
3459
|
+
gadget.completed = true;
|
|
3460
|
+
gadget.completedTime = Date.now();
|
|
3461
|
+
if (this.isRunning && this.isTTY) {
|
|
3462
|
+
this.render();
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
/**
|
|
3467
|
+
* Clear all completed gadgets from the display.
|
|
3468
|
+
* Called when new text output arrives to clean up the finished gadget section.
|
|
3469
|
+
*/
|
|
3470
|
+
clearCompletedGadgets() {
|
|
3471
|
+
for (const [id, gadget] of this.inFlightGadgets) {
|
|
3472
|
+
if (gadget.completed) {
|
|
3473
|
+
this.inFlightGadgets.delete(id);
|
|
3474
|
+
for (const [nestedId, nested] of this.nestedAgents) {
|
|
3475
|
+
if (nested.parentInvocationId === id) {
|
|
3476
|
+
this.nestedAgents.delete(nestedId);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
for (const [nestedId, nested] of this.nestedGadgets) {
|
|
3480
|
+
if (nested.parentInvocationId === id) {
|
|
3481
|
+
this.nestedGadgets.delete(nestedId);
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
if (this.isRunning && this.isTTY) {
|
|
3487
|
+
this.render();
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3374
3490
|
/**
|
|
3375
3491
|
* Add a nested agent LLM call (called when nested llm_call_start event received).
|
|
3376
3492
|
* Used to display hierarchical progress for subagent gadgets.
|
|
3493
|
+
* @param parentCallNumber - Top-level call number for hierarchical display (e.g., #1.2)
|
|
3377
3494
|
*/
|
|
3378
|
-
addNestedAgent(id, parentInvocationId, depth, model, iteration,
|
|
3495
|
+
addNestedAgent(id, parentInvocationId, depth, model, iteration, info, parentCallNumber) {
|
|
3379
3496
|
this.nestedAgents.set(id, {
|
|
3380
3497
|
parentInvocationId,
|
|
3381
3498
|
depth,
|
|
3382
3499
|
model,
|
|
3383
3500
|
iteration,
|
|
3501
|
+
parentCallNumber,
|
|
3384
3502
|
startTime: Date.now(),
|
|
3385
|
-
inputTokens
|
|
3503
|
+
inputTokens: info?.inputTokens,
|
|
3504
|
+
cachedInputTokens: info?.cachedInputTokens
|
|
3386
3505
|
});
|
|
3387
3506
|
if (this.isRunning && this.isTTY) {
|
|
3388
3507
|
this.render();
|
|
@@ -3396,22 +3515,23 @@ var StreamProgress = class {
|
|
|
3396
3515
|
updateNestedAgent(id, info) {
|
|
3397
3516
|
const agent = this.nestedAgents.get(id);
|
|
3398
3517
|
if (agent) {
|
|
3399
|
-
agent.inputTokens = info.inputTokens;
|
|
3400
|
-
agent.outputTokens = info.outputTokens;
|
|
3401
|
-
agent.cachedInputTokens = info.cachedInputTokens;
|
|
3402
|
-
|
|
3403
|
-
|
|
3518
|
+
if (info.inputTokens !== void 0) agent.inputTokens = info.inputTokens;
|
|
3519
|
+
if (info.outputTokens !== void 0) agent.outputTokens = info.outputTokens;
|
|
3520
|
+
if (info.cachedInputTokens !== void 0) agent.cachedInputTokens = info.cachedInputTokens;
|
|
3521
|
+
if (info.cacheCreationInputTokens !== void 0)
|
|
3522
|
+
agent.cacheCreationInputTokens = info.cacheCreationInputTokens;
|
|
3523
|
+
if (info.finishReason !== void 0) agent.finishReason = info.finishReason;
|
|
3404
3524
|
if (info.cost !== void 0) {
|
|
3405
3525
|
agent.cost = info.cost;
|
|
3406
|
-
} else if (this.modelRegistry && agent.model &&
|
|
3526
|
+
} else if (this.modelRegistry && agent.model && agent.outputTokens) {
|
|
3407
3527
|
try {
|
|
3408
3528
|
const modelName = agent.model.includes(":") ? agent.model.split(":")[1] : agent.model;
|
|
3409
3529
|
const costResult = this.modelRegistry.estimateCost(
|
|
3410
3530
|
modelName,
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3531
|
+
agent.inputTokens ?? 0,
|
|
3532
|
+
agent.outputTokens,
|
|
3533
|
+
agent.cachedInputTokens,
|
|
3534
|
+
agent.cacheCreationInputTokens
|
|
3415
3535
|
);
|
|
3416
3536
|
agent.cost = costResult?.totalCost;
|
|
3417
3537
|
} catch {
|
|
@@ -3433,6 +3553,27 @@ var StreamProgress = class {
|
|
|
3433
3553
|
this.render();
|
|
3434
3554
|
}
|
|
3435
3555
|
}
|
|
3556
|
+
/**
|
|
3557
|
+
* Get aggregated metrics from all nested agents for a parent gadget.
|
|
3558
|
+
* Used to show total token counts and cost for subagent gadgets like BrowseWeb.
|
|
3559
|
+
*/
|
|
3560
|
+
getAggregatedSubagentMetrics(parentInvocationId) {
|
|
3561
|
+
let inputTokens = 0;
|
|
3562
|
+
let outputTokens = 0;
|
|
3563
|
+
let cachedInputTokens = 0;
|
|
3564
|
+
let cost = 0;
|
|
3565
|
+
let callCount = 0;
|
|
3566
|
+
for (const [, nested] of this.nestedAgents) {
|
|
3567
|
+
if (nested.parentInvocationId === parentInvocationId) {
|
|
3568
|
+
inputTokens += nested.inputTokens ?? 0;
|
|
3569
|
+
outputTokens += nested.outputTokens ?? 0;
|
|
3570
|
+
cachedInputTokens += nested.cachedInputTokens ?? 0;
|
|
3571
|
+
cost += nested.cost ?? 0;
|
|
3572
|
+
callCount++;
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
return { inputTokens, outputTokens, cachedInputTokens, cost, callCount };
|
|
3576
|
+
}
|
|
3436
3577
|
/**
|
|
3437
3578
|
* Add a nested gadget call (called when nested gadget_call event received).
|
|
3438
3579
|
*/
|
|
@@ -3600,20 +3741,23 @@ var StreamProgress = class {
|
|
|
3600
3741
|
this.clearRenderedLines();
|
|
3601
3742
|
const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];
|
|
3602
3743
|
const lines = [];
|
|
3603
|
-
|
|
3604
|
-
lines.push(this.formatStreamingLine(spinner));
|
|
3605
|
-
} else {
|
|
3606
|
-
lines.push(this.formatCumulativeLine(spinner));
|
|
3607
|
-
}
|
|
3744
|
+
const activeNestedStreams = [];
|
|
3608
3745
|
if (this.isTTY) {
|
|
3609
3746
|
for (const [gadgetId, gadget] of this.inFlightGadgets) {
|
|
3610
|
-
const
|
|
3611
|
-
const
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3747
|
+
const endTime = gadget.completedTime ?? Date.now();
|
|
3748
|
+
const elapsedSeconds = (endTime - gadget.startTime) / 1e3;
|
|
3749
|
+
const termWidth = process.stdout.columns ?? 80;
|
|
3750
|
+
const gadgetIndent = " ";
|
|
3751
|
+
const line = formatGadgetLine(
|
|
3752
|
+
{
|
|
3753
|
+
name: gadget.name,
|
|
3754
|
+
parameters: gadget.params,
|
|
3755
|
+
elapsedSeconds,
|
|
3756
|
+
isComplete: gadget.completed ?? false
|
|
3757
|
+
},
|
|
3758
|
+
termWidth - gadgetIndent.length
|
|
3759
|
+
);
|
|
3760
|
+
const gadgetLine = line.split("\n").map((l) => gadgetIndent + l).join("\n");
|
|
3617
3761
|
lines.push(gadgetLine);
|
|
3618
3762
|
const nestedOps = [];
|
|
3619
3763
|
for (const [_agentId, nested] of this.nestedAgents) {
|
|
@@ -3623,6 +3767,7 @@ var StreamProgress = class {
|
|
|
3623
3767
|
startTime: nested.startTime,
|
|
3624
3768
|
depth: nested.depth,
|
|
3625
3769
|
iteration: nested.iteration,
|
|
3770
|
+
parentCallNumber: nested.parentCallNumber,
|
|
3626
3771
|
model: nested.model,
|
|
3627
3772
|
inputTokens: nested.inputTokens,
|
|
3628
3773
|
cachedInputTokens: nested.cachedInputTokens,
|
|
@@ -3632,6 +3777,19 @@ var StreamProgress = class {
|
|
|
3632
3777
|
completed: nested.completed,
|
|
3633
3778
|
completedTime: nested.completedTime
|
|
3634
3779
|
});
|
|
3780
|
+
if (!nested.completed) {
|
|
3781
|
+
activeNestedStreams.push({
|
|
3782
|
+
depth: nested.depth,
|
|
3783
|
+
iteration: nested.iteration,
|
|
3784
|
+
parentCallNumber: nested.parentCallNumber,
|
|
3785
|
+
model: nested.model,
|
|
3786
|
+
inputTokens: nested.inputTokens,
|
|
3787
|
+
cachedInputTokens: nested.cachedInputTokens,
|
|
3788
|
+
outputTokens: nested.outputTokens,
|
|
3789
|
+
cost: nested.cost,
|
|
3790
|
+
startTime: nested.startTime
|
|
3791
|
+
});
|
|
3792
|
+
}
|
|
3635
3793
|
}
|
|
3636
3794
|
}
|
|
3637
3795
|
for (const [_nestedId, nestedGadget] of this.nestedGadgets) {
|
|
@@ -3649,12 +3807,16 @@ var StreamProgress = class {
|
|
|
3649
3807
|
}
|
|
3650
3808
|
nestedOps.sort((a, b) => a.startTime - b.startTime);
|
|
3651
3809
|
for (const op of nestedOps) {
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3810
|
+
if (op.type === "agent" && !op.completed) {
|
|
3811
|
+
continue;
|
|
3812
|
+
}
|
|
3813
|
+
const indent = " ".repeat(op.depth + 2);
|
|
3814
|
+
const endTime2 = op.completedTime ?? Date.now();
|
|
3815
|
+
const elapsedSeconds2 = (endTime2 - op.startTime) / 1e3;
|
|
3655
3816
|
if (op.type === "agent") {
|
|
3656
|
-
const
|
|
3817
|
+
const line2 = formatLLMCallLine({
|
|
3657
3818
|
iteration: op.iteration ?? 0,
|
|
3819
|
+
parentCallNumber: op.parentCallNumber,
|
|
3658
3820
|
model: op.model ?? "",
|
|
3659
3821
|
inputTokens: op.inputTokens,
|
|
3660
3822
|
cachedInputTokens: op.cachedInputTokens,
|
|
@@ -3665,21 +3827,49 @@ var StreamProgress = class {
|
|
|
3665
3827
|
isStreaming: !op.completed,
|
|
3666
3828
|
spinner
|
|
3667
3829
|
});
|
|
3668
|
-
lines.push(`${indent}${
|
|
3830
|
+
lines.push(`${indent}${line2}`);
|
|
3669
3831
|
} else {
|
|
3670
|
-
const
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3832
|
+
const termWidth2 = process.stdout.columns ?? 80;
|
|
3833
|
+
const line2 = formatGadgetLine(
|
|
3834
|
+
{
|
|
3835
|
+
name: op.name ?? "",
|
|
3836
|
+
parameters: op.parameters,
|
|
3837
|
+
elapsedSeconds: elapsedSeconds2,
|
|
3838
|
+
isComplete: op.completed ?? false
|
|
3839
|
+
},
|
|
3840
|
+
termWidth2 - indent.length
|
|
3841
|
+
);
|
|
3842
|
+
const indentedLine = line2.split("\n").map((l) => indent + l).join("\n");
|
|
3843
|
+
lines.push(indentedLine);
|
|
3677
3844
|
}
|
|
3678
3845
|
}
|
|
3679
3846
|
}
|
|
3680
3847
|
}
|
|
3681
|
-
|
|
3682
|
-
|
|
3848
|
+
for (const stream of activeNestedStreams) {
|
|
3849
|
+
const indent = " ".repeat(stream.depth + 2);
|
|
3850
|
+
const elapsedSeconds = (Date.now() - stream.startTime) / 1e3;
|
|
3851
|
+
const line = formatLLMCallLine({
|
|
3852
|
+
iteration: stream.iteration,
|
|
3853
|
+
parentCallNumber: stream.parentCallNumber,
|
|
3854
|
+
model: stream.model,
|
|
3855
|
+
inputTokens: stream.inputTokens,
|
|
3856
|
+
cachedInputTokens: stream.cachedInputTokens,
|
|
3857
|
+
outputTokens: stream.outputTokens,
|
|
3858
|
+
elapsedSeconds,
|
|
3859
|
+
cost: stream.cost,
|
|
3860
|
+
isStreaming: true,
|
|
3861
|
+
spinner
|
|
3862
|
+
});
|
|
3863
|
+
lines.push(`${indent}${line}`);
|
|
3864
|
+
}
|
|
3865
|
+
if (this.mode === "streaming") {
|
|
3866
|
+
lines.push(this.formatStreamingLine(spinner));
|
|
3867
|
+
} else {
|
|
3868
|
+
lines.push(this.formatCumulativeLine(spinner));
|
|
3869
|
+
}
|
|
3870
|
+
const output = lines.join("\n");
|
|
3871
|
+
this.lastRenderLineCount = (output.match(/\n/g) || []).length + 1;
|
|
3872
|
+
this.target.write("\r" + output);
|
|
3683
3873
|
this.hasRendered = true;
|
|
3684
3874
|
}
|
|
3685
3875
|
/**
|
|
@@ -4291,6 +4481,7 @@ async function executeAgent(promptArg, options, env) {
|
|
|
4291
4481
|
env.stderr.write(`${summary}
|
|
4292
4482
|
`);
|
|
4293
4483
|
}
|
|
4484
|
+
env.stderr.write("\n");
|
|
4294
4485
|
}
|
|
4295
4486
|
if (llmSessionDir) {
|
|
4296
4487
|
const filename = `${formatCallNumber(llmCallCounter)}.response`;
|
|
@@ -4397,8 +4588,7 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
4397
4588
|
builder.withTrailingMessage(
|
|
4398
4589
|
(ctx) => [
|
|
4399
4590
|
`[Iteration ${ctx.iteration + 1}/${ctx.maxIterations}]`,
|
|
4400
|
-
"Think carefully: what gadget invocations can
|
|
4401
|
-
"Maximize efficiency by batching independent operations in a single response."
|
|
4591
|
+
"Think carefully in two steps: 1. what gadget invocations we should be making next? 2. how do they depend on one another so we can run all of them in the right order? Then respond with all the gadget invocations you are able to do now."
|
|
4402
4592
|
].join(" ")
|
|
4403
4593
|
);
|
|
4404
4594
|
if (!options.quiet) {
|
|
@@ -4411,8 +4601,14 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
4411
4601
|
subagentEvent.gadgetInvocationId,
|
|
4412
4602
|
subagentEvent.depth,
|
|
4413
4603
|
info.model,
|
|
4414
|
-
info.iteration,
|
|
4415
|
-
|
|
4604
|
+
info.iteration + 1,
|
|
4605
|
+
// Make 1-indexed like main agent
|
|
4606
|
+
{
|
|
4607
|
+
inputTokens: info.usage?.inputTokens ?? info.inputTokens,
|
|
4608
|
+
cachedInputTokens: info.usage?.cachedInputTokens
|
|
4609
|
+
},
|
|
4610
|
+
llmCallCounter
|
|
4611
|
+
// Parent call number for hierarchical display (e.g., #1.2)
|
|
4416
4612
|
);
|
|
4417
4613
|
} else if (subagentEvent.type === "llm_call_end") {
|
|
4418
4614
|
const info = subagentEvent.event;
|
|
@@ -4456,6 +4652,9 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
4456
4652
|
let textBuffer = "";
|
|
4457
4653
|
const flushTextBuffer = () => {
|
|
4458
4654
|
if (textBuffer) {
|
|
4655
|
+
if (!options.quiet) {
|
|
4656
|
+
progress.clearCompletedGadgets();
|
|
4657
|
+
}
|
|
4459
4658
|
const output = options.quiet ? textBuffer : renderMarkdownWithSeparators(textBuffer);
|
|
4460
4659
|
printer.write(output);
|
|
4461
4660
|
textBuffer = "";
|
|
@@ -4478,7 +4677,7 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
4478
4677
|
} else if (event.type === "gadget_result") {
|
|
4479
4678
|
flushTextBuffer();
|
|
4480
4679
|
if (!options.quiet) {
|
|
4481
|
-
progress.
|
|
4680
|
+
progress.completeGadget(event.result.invocationId);
|
|
4482
4681
|
}
|
|
4483
4682
|
progress.pause();
|
|
4484
4683
|
if (options.quiet) {
|
|
@@ -4489,10 +4688,23 @@ Denied: ${result.reason ?? "by user"}`
|
|
|
4489
4688
|
}
|
|
4490
4689
|
} else {
|
|
4491
4690
|
const tokenCount = await countGadgetOutputTokens(event.result.result);
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
`
|
|
4691
|
+
const subagentMetrics = progress.getAggregatedSubagentMetrics(
|
|
4692
|
+
event.result.invocationId
|
|
4495
4693
|
);
|
|
4694
|
+
const summary = formatGadgetSummary2({
|
|
4695
|
+
...event.result,
|
|
4696
|
+
tokenCount,
|
|
4697
|
+
media: event.result.storedMedia,
|
|
4698
|
+
subagentMetrics: subagentMetrics.callCount > 0 ? subagentMetrics : void 0
|
|
4699
|
+
});
|
|
4700
|
+
if (event.result.gadgetName === "TellUser") {
|
|
4701
|
+
env.stderr.write(`${summary}
|
|
4702
|
+
`);
|
|
4703
|
+
} else {
|
|
4704
|
+
const indentedSummary = summary.split("\n").map((line) => " " + line).join("\n");
|
|
4705
|
+
env.stderr.write(`${indentedSummary}
|
|
4706
|
+
`);
|
|
4707
|
+
}
|
|
4496
4708
|
}
|
|
4497
4709
|
if (progress.hasInFlightGadgets()) {
|
|
4498
4710
|
progress.start();
|