@llmist/cli 15.12.0 → 15.14.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/cli.js +256 -14
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -51,7 +51,11 @@ var OPTION_FLAGS = {
|
|
|
51
51
|
maxRetries: "--max-retries <count>",
|
|
52
52
|
retryMinTimeout: "--retry-min-timeout <ms>",
|
|
53
53
|
retryMaxTimeout: "--retry-max-timeout <ms>",
|
|
54
|
-
noRetry: "--no-retry"
|
|
54
|
+
noRetry: "--no-retry",
|
|
55
|
+
// Reasoning options
|
|
56
|
+
reasoning: "--reasoning [effort]",
|
|
57
|
+
noReasoning: "--no-reasoning",
|
|
58
|
+
reasoningBudget: "--reasoning-budget <tokens>"
|
|
55
59
|
};
|
|
56
60
|
var OPTION_DESCRIPTIONS = {
|
|
57
61
|
model: "Model identifier, e.g. openai:gpt-5-nano or anthropic:claude-sonnet-4-5.",
|
|
@@ -88,7 +92,11 @@ var OPTION_DESCRIPTIONS = {
|
|
|
88
92
|
maxRetries: "Maximum retry attempts for failed API calls.",
|
|
89
93
|
retryMinTimeout: "Initial retry delay in milliseconds.",
|
|
90
94
|
retryMaxTimeout: "Maximum retry delay in milliseconds.",
|
|
91
|
-
noRetry: "Disable retry logic for API calls."
|
|
95
|
+
noRetry: "Disable retry logic for API calls.",
|
|
96
|
+
// Reasoning descriptions
|
|
97
|
+
reasoning: "Enable reasoning mode. Optional effort: none, low, medium, high, maximum (default: medium).",
|
|
98
|
+
noReasoning: "Disable auto-enabled reasoning for reasoning-capable models.",
|
|
99
|
+
reasoningBudget: "Explicit reasoning token budget (Anthropic/Gemini 2.5). Overrides effort level."
|
|
92
100
|
};
|
|
93
101
|
var SUMMARY_PREFIX = "[llmist]";
|
|
94
102
|
|
|
@@ -98,7 +106,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
|
|
|
98
106
|
// package.json
|
|
99
107
|
var package_default = {
|
|
100
108
|
name: "@llmist/cli",
|
|
101
|
-
version: "15.
|
|
109
|
+
version: "15.14.0",
|
|
102
110
|
description: "CLI for llmist - run LLM agents from the command line",
|
|
103
111
|
type: "module",
|
|
104
112
|
main: "dist/cli.js",
|
|
@@ -154,7 +162,7 @@ var package_default = {
|
|
|
154
162
|
node: ">=22.0.0"
|
|
155
163
|
},
|
|
156
164
|
dependencies: {
|
|
157
|
-
llmist: "^15.
|
|
165
|
+
llmist: "^15.14.0",
|
|
158
166
|
"@unblessed/node": "^1.0.0-alpha.23",
|
|
159
167
|
chalk: "^5.6.2",
|
|
160
168
|
commander: "^12.1.0",
|
|
@@ -168,7 +176,7 @@ var package_default = {
|
|
|
168
176
|
zod: "^4.1.12"
|
|
169
177
|
},
|
|
170
178
|
devDependencies: {
|
|
171
|
-
"@llmist/testing": "^15.
|
|
179
|
+
"@llmist/testing": "^15.14.0",
|
|
172
180
|
"@types/diff": "^8.0.0",
|
|
173
181
|
"@types/js-yaml": "^4.0.9",
|
|
174
182
|
"@types/marked-terminal": "^6.1.1",
|
|
@@ -420,6 +428,7 @@ var COMPLETE_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
420
428
|
"log-llm-requests",
|
|
421
429
|
"rate-limits",
|
|
422
430
|
"retry",
|
|
431
|
+
"reasoning",
|
|
423
432
|
"type"
|
|
424
433
|
// Allowed for inheritance compatibility, ignored for built-in commands
|
|
425
434
|
]);
|
|
@@ -452,6 +461,7 @@ var AGENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
452
461
|
"log-llm-requests",
|
|
453
462
|
"rate-limits",
|
|
454
463
|
"retry",
|
|
464
|
+
"reasoning",
|
|
455
465
|
"type"
|
|
456
466
|
// Allowed for inheritance compatibility, ignored for built-in commands
|
|
457
467
|
]);
|
|
@@ -684,6 +694,39 @@ function validateRetryConfig(value, section) {
|
|
|
684
694
|
}
|
|
685
695
|
return result;
|
|
686
696
|
}
|
|
697
|
+
var REASONING_CONFIG_KEYS = /* @__PURE__ */ new Set(["enabled", "effort", "budget-tokens"]);
|
|
698
|
+
var VALID_REASONING_EFFORTS = /* @__PURE__ */ new Set(["none", "low", "medium", "high", "maximum"]);
|
|
699
|
+
function validateReasoningConfig(value, section) {
|
|
700
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
701
|
+
throw new ConfigError(`[${section}] must be a table`);
|
|
702
|
+
}
|
|
703
|
+
const raw = value;
|
|
704
|
+
const result = {};
|
|
705
|
+
for (const [key, val] of Object.entries(raw)) {
|
|
706
|
+
if (!REASONING_CONFIG_KEYS.has(key)) {
|
|
707
|
+
throw new ConfigError(`[${section}] has unknown key: ${key}`);
|
|
708
|
+
}
|
|
709
|
+
switch (key) {
|
|
710
|
+
case "enabled":
|
|
711
|
+
result.enabled = validateBoolean(val, key, section);
|
|
712
|
+
break;
|
|
713
|
+
case "effort": {
|
|
714
|
+
const effort = validateString(val, key, section);
|
|
715
|
+
if (!VALID_REASONING_EFFORTS.has(effort)) {
|
|
716
|
+
throw new ConfigError(
|
|
717
|
+
`[${section}].effort must be one of: none, low, medium, high, maximum (got "${effort}")`
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
result.effort = effort;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
case "budget-tokens":
|
|
724
|
+
result["budget-tokens"] = validateNumber(val, key, section, { integer: true, min: 1 });
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return result;
|
|
729
|
+
}
|
|
687
730
|
function validateGlobalSubagentConfig(value, section) {
|
|
688
731
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
689
732
|
throw new ConfigError(`[${section}] must be a table`);
|
|
@@ -850,6 +893,9 @@ function validateCompleteConfig(raw, section) {
|
|
|
850
893
|
if ("retry" in rawObj) {
|
|
851
894
|
result.retry = validateRetryConfig(rawObj.retry, `${section}.retry`);
|
|
852
895
|
}
|
|
896
|
+
if ("reasoning" in rawObj) {
|
|
897
|
+
result.reasoning = validateReasoningConfig(rawObj.reasoning, `${section}.reasoning`);
|
|
898
|
+
}
|
|
853
899
|
return result;
|
|
854
900
|
}
|
|
855
901
|
function validateAgentConfig(raw, section) {
|
|
@@ -947,6 +993,9 @@ function validateAgentConfig(raw, section) {
|
|
|
947
993
|
if ("retry" in rawObj) {
|
|
948
994
|
result.retry = validateRetryConfig(rawObj.retry, `${section}.retry`);
|
|
949
995
|
}
|
|
996
|
+
if ("reasoning" in rawObj) {
|
|
997
|
+
result.reasoning = validateReasoningConfig(rawObj.reasoning, `${section}.reasoning`);
|
|
998
|
+
}
|
|
950
999
|
return result;
|
|
951
1000
|
}
|
|
952
1001
|
function validateImageConfig(raw, section) {
|
|
@@ -3164,6 +3213,8 @@ var StreamProgress = class {
|
|
|
3164
3213
|
// Cache token tracking for live cost estimation during streaming
|
|
3165
3214
|
callCachedInputTokens = 0;
|
|
3166
3215
|
callCacheCreationInputTokens = 0;
|
|
3216
|
+
// Reasoning token tracking for live cost estimation during streaming
|
|
3217
|
+
callReasoningTokens = 0;
|
|
3167
3218
|
// Cumulative stats (cumulative mode)
|
|
3168
3219
|
totalStartTime = Date.now();
|
|
3169
3220
|
totalTokens = 0;
|
|
@@ -3282,6 +3333,7 @@ var StreamProgress = class {
|
|
|
3282
3333
|
if (info.cachedInputTokens !== void 0) agent.cachedInputTokens = info.cachedInputTokens;
|
|
3283
3334
|
if (info.cacheCreationInputTokens !== void 0)
|
|
3284
3335
|
agent.cacheCreationInputTokens = info.cacheCreationInputTokens;
|
|
3336
|
+
if (info.reasoningTokens !== void 0) agent.reasoningTokens = info.reasoningTokens;
|
|
3285
3337
|
if (info.finishReason !== void 0) agent.finishReason = info.finishReason;
|
|
3286
3338
|
if (info.cost !== void 0) {
|
|
3287
3339
|
agent.cost = info.cost;
|
|
@@ -3293,7 +3345,8 @@ var StreamProgress = class {
|
|
|
3293
3345
|
agent.inputTokens ?? 0,
|
|
3294
3346
|
agent.outputTokens,
|
|
3295
3347
|
agent.cachedInputTokens,
|
|
3296
|
-
agent.cacheCreationInputTokens
|
|
3348
|
+
agent.cacheCreationInputTokens,
|
|
3349
|
+
agent.reasoningTokens
|
|
3297
3350
|
);
|
|
3298
3351
|
agent.cost = costResult?.totalCost;
|
|
3299
3352
|
} catch {
|
|
@@ -3407,6 +3460,7 @@ var StreamProgress = class {
|
|
|
3407
3460
|
this.isStreaming = false;
|
|
3408
3461
|
this.callCachedInputTokens = 0;
|
|
3409
3462
|
this.callCacheCreationInputTokens = 0;
|
|
3463
|
+
this.callReasoningTokens = 0;
|
|
3410
3464
|
this.start();
|
|
3411
3465
|
}
|
|
3412
3466
|
/**
|
|
@@ -3425,7 +3479,8 @@ var StreamProgress = class {
|
|
|
3425
3479
|
usage.inputTokens,
|
|
3426
3480
|
usage.outputTokens,
|
|
3427
3481
|
usage.cachedInputTokens ?? 0,
|
|
3428
|
-
usage.cacheCreationInputTokens ?? 0
|
|
3482
|
+
usage.cacheCreationInputTokens ?? 0,
|
|
3483
|
+
usage.reasoningTokens ?? 0
|
|
3429
3484
|
);
|
|
3430
3485
|
if (cost) {
|
|
3431
3486
|
this.totalCost += cost.totalCost;
|
|
@@ -3484,6 +3539,14 @@ var StreamProgress = class {
|
|
|
3484
3539
|
this.callCachedInputTokens = cachedInputTokens;
|
|
3485
3540
|
this.callCacheCreationInputTokens = cacheCreationInputTokens;
|
|
3486
3541
|
}
|
|
3542
|
+
/**
|
|
3543
|
+
* Sets reasoning token count for the current call (from stream metadata).
|
|
3544
|
+
* Used for live cost estimation during streaming.
|
|
3545
|
+
* @param reasoningTokens - Number of reasoning/thinking tokens (subset of outputTokens)
|
|
3546
|
+
*/
|
|
3547
|
+
setReasoningTokens(reasoningTokens) {
|
|
3548
|
+
this.callReasoningTokens = reasoningTokens;
|
|
3549
|
+
}
|
|
3487
3550
|
/**
|
|
3488
3551
|
* Get total elapsed time in seconds since the first call started.
|
|
3489
3552
|
* @returns Elapsed time in seconds with 1 decimal place
|
|
@@ -3725,7 +3788,8 @@ var StreamProgress = class {
|
|
|
3725
3788
|
this.callInputTokens,
|
|
3726
3789
|
outputTokens,
|
|
3727
3790
|
this.callCachedInputTokens,
|
|
3728
|
-
this.callCacheCreationInputTokens
|
|
3791
|
+
this.callCacheCreationInputTokens,
|
|
3792
|
+
this.callReasoningTokens
|
|
3729
3793
|
);
|
|
3730
3794
|
return cost?.totalCost ?? 0;
|
|
3731
3795
|
} catch {
|
|
@@ -3946,7 +4010,11 @@ function addCompleteOptions(cmd, defaults) {
|
|
|
3946
4010
|
OPTION_DESCRIPTIONS.retryMaxTimeout,
|
|
3947
4011
|
createNumericParser({ label: "Max timeout", integer: true, min: 0 }),
|
|
3948
4012
|
defaults?.retry?.["max-timeout"]
|
|
3949
|
-
).option(OPTION_FLAGS.noRetry, OPTION_DESCRIPTIONS.noRetry)
|
|
4013
|
+
).option(OPTION_FLAGS.noRetry, OPTION_DESCRIPTIONS.noRetry).option(OPTION_FLAGS.reasoning, OPTION_DESCRIPTIONS.reasoning).option(OPTION_FLAGS.noReasoning, OPTION_DESCRIPTIONS.noReasoning).option(
|
|
4014
|
+
OPTION_FLAGS.reasoningBudget,
|
|
4015
|
+
OPTION_DESCRIPTIONS.reasoningBudget,
|
|
4016
|
+
createNumericParser({ label: "Reasoning budget", integer: true, min: 1 })
|
|
4017
|
+
);
|
|
3950
4018
|
}
|
|
3951
4019
|
function addAgentOptions(cmd, defaults) {
|
|
3952
4020
|
const gadgetAccumulator = (value, previous = []) => [
|
|
@@ -4009,7 +4077,11 @@ function addAgentOptions(cmd, defaults) {
|
|
|
4009
4077
|
OPTION_DESCRIPTIONS.retryMaxTimeout,
|
|
4010
4078
|
createNumericParser({ label: "Max timeout", integer: true, min: 0 }),
|
|
4011
4079
|
defaults?.retry?.["max-timeout"]
|
|
4012
|
-
).option(OPTION_FLAGS.noRetry, OPTION_DESCRIPTIONS.noRetry)
|
|
4080
|
+
).option(OPTION_FLAGS.noRetry, OPTION_DESCRIPTIONS.noRetry).option(OPTION_FLAGS.reasoning, OPTION_DESCRIPTIONS.reasoning).option(OPTION_FLAGS.noReasoning, OPTION_DESCRIPTIONS.noReasoning).option(
|
|
4081
|
+
OPTION_FLAGS.reasoningBudget,
|
|
4082
|
+
OPTION_DESCRIPTIONS.reasoningBudget,
|
|
4083
|
+
createNumericParser({ label: "Reasoning budget", integer: true, min: 1 })
|
|
4084
|
+
);
|
|
4013
4085
|
}
|
|
4014
4086
|
function configToCompleteOptions(config) {
|
|
4015
4087
|
const result = {};
|
|
@@ -4034,6 +4106,9 @@ function configToCompleteOptions(config) {
|
|
|
4034
4106
|
if (r["max-timeout"] !== void 0) result.retryMaxTimeout = r["max-timeout"];
|
|
4035
4107
|
if (r.enabled === false) result.noRetry = true;
|
|
4036
4108
|
}
|
|
4109
|
+
if (config.reasoning) {
|
|
4110
|
+
result.profileReasoning = config.reasoning;
|
|
4111
|
+
}
|
|
4037
4112
|
return result;
|
|
4038
4113
|
}
|
|
4039
4114
|
function configToAgentOptions(config) {
|
|
@@ -4073,6 +4148,9 @@ function configToAgentOptions(config) {
|
|
|
4073
4148
|
if (r["max-timeout"] !== void 0) result.retryMaxTimeout = r["max-timeout"];
|
|
4074
4149
|
if (r.enabled === false) result.noRetry = true;
|
|
4075
4150
|
}
|
|
4151
|
+
if (config.reasoning) {
|
|
4152
|
+
result.profileReasoning = config.reasoning;
|
|
4153
|
+
}
|
|
4076
4154
|
if (config["show-hints"] !== void 0) result.showHints = config["show-hints"];
|
|
4077
4155
|
return result;
|
|
4078
4156
|
}
|
|
@@ -4327,6 +4405,9 @@ function formatLLMCallCollapsed(node, selected) {
|
|
|
4327
4405
|
if (d.outputTokens && d.outputTokens > 0) {
|
|
4328
4406
|
parts.push(chalk3.dim("\u2193") + chalk3.green(` ${formatTokens(d.outputTokens)}`));
|
|
4329
4407
|
}
|
|
4408
|
+
if (d.reasoningTokens && d.reasoningTokens > 0) {
|
|
4409
|
+
parts.push(chalk3.dim("\u{1F4AD}") + chalk3.magenta(` ${formatTokens(d.reasoningTokens)}`));
|
|
4410
|
+
}
|
|
4330
4411
|
if (d.elapsedSeconds !== void 0) {
|
|
4331
4412
|
parts.push(chalk3.dim(`${d.elapsedSeconds.toFixed(1)}s`));
|
|
4332
4413
|
}
|
|
@@ -4374,6 +4455,11 @@ function formatLLMCallExpanded(node) {
|
|
|
4374
4455
|
`${indent}${chalk3.dim(BOX.vertical)} Output: ${chalk3.green(formatTokens(d.outputTokens))} tokens`
|
|
4375
4456
|
);
|
|
4376
4457
|
}
|
|
4458
|
+
if (d.reasoningTokens !== void 0 && d.reasoningTokens > 0) {
|
|
4459
|
+
lines.push(
|
|
4460
|
+
`${indent}${chalk3.dim(BOX.vertical)} Reason: ${chalk3.magenta(formatTokens(d.reasoningTokens))} tokens`
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4377
4463
|
if (d.contextPercent !== void 0) {
|
|
4378
4464
|
let contextColor = chalk3.green;
|
|
4379
4465
|
if (d.contextPercent >= 80) contextColor = chalk3.red;
|
|
@@ -4633,6 +4719,8 @@ var BlockRenderer = class _BlockRenderer {
|
|
|
4633
4719
|
nodeIdCounter = 0;
|
|
4634
4720
|
/** Current LLM call node (for adding gadget children) */
|
|
4635
4721
|
currentLLMCallId = null;
|
|
4722
|
+
/** Current thinking block (accumulates chunks during streaming) */
|
|
4723
|
+
currentThinkingId = null;
|
|
4636
4724
|
/** Persisted expanded states (survives rebuildBlocks) */
|
|
4637
4725
|
expandedStates = /* @__PURE__ */ new Map();
|
|
4638
4726
|
/** Whether to auto-scroll to bottom on new content ("follow mode") */
|
|
@@ -4868,6 +4956,66 @@ var BlockRenderer = class _BlockRenderer {
|
|
|
4868
4956
|
this.rebuildBlocks();
|
|
4869
4957
|
return id;
|
|
4870
4958
|
}
|
|
4959
|
+
/**
|
|
4960
|
+
* Add thinking content from a reasoning model.
|
|
4961
|
+
* Creates a new thinking block on first chunk, appends to existing on subsequent chunks.
|
|
4962
|
+
* The block lives as a child of the current LLM call.
|
|
4963
|
+
*
|
|
4964
|
+
* @param content - Thinking text chunk
|
|
4965
|
+
* @param thinkingType - Whether this is actual thinking or redacted content
|
|
4966
|
+
*/
|
|
4967
|
+
addThinking(content, thinkingType) {
|
|
4968
|
+
if (this.currentThinkingId) {
|
|
4969
|
+
const node2 = this.getNode(this.currentThinkingId);
|
|
4970
|
+
if (node2 && node2.type === "thinking") {
|
|
4971
|
+
node2.content += content;
|
|
4972
|
+
this.updateBlock(this.currentThinkingId);
|
|
4973
|
+
return;
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
const id = this.generateId("thinking");
|
|
4977
|
+
const parentLLMCallId = this.currentLLMCallId;
|
|
4978
|
+
let depth = 0;
|
|
4979
|
+
if (parentLLMCallId) {
|
|
4980
|
+
const parent = this.getNode(parentLLMCallId);
|
|
4981
|
+
if (parent) {
|
|
4982
|
+
depth = parent.depth + 1;
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
const node = {
|
|
4986
|
+
id,
|
|
4987
|
+
type: "thinking",
|
|
4988
|
+
depth,
|
|
4989
|
+
parentId: parentLLMCallId,
|
|
4990
|
+
sessionId: this.currentSessionId,
|
|
4991
|
+
content,
|
|
4992
|
+
thinkingType,
|
|
4993
|
+
isComplete: false,
|
|
4994
|
+
children: []
|
|
4995
|
+
};
|
|
4996
|
+
this.nodes.set(id, node);
|
|
4997
|
+
if (parentLLMCallId) {
|
|
4998
|
+
const parent = this.getNode(parentLLMCallId);
|
|
4999
|
+
parent.children.push(id);
|
|
5000
|
+
} else {
|
|
5001
|
+
this.rootIds.push(id);
|
|
5002
|
+
}
|
|
5003
|
+
this.currentThinkingId = id;
|
|
5004
|
+
this.rebuildBlocks();
|
|
5005
|
+
}
|
|
5006
|
+
/**
|
|
5007
|
+
* Complete the current thinking block.
|
|
5008
|
+
* Called when the LLM call finishes to mark thinking as complete.
|
|
5009
|
+
*/
|
|
5010
|
+
completeThinking() {
|
|
5011
|
+
if (!this.currentThinkingId) return;
|
|
5012
|
+
const node = this.getNode(this.currentThinkingId);
|
|
5013
|
+
if (node && node.type === "thinking") {
|
|
5014
|
+
node.isComplete = true;
|
|
5015
|
+
this.updateBlock(this.currentThinkingId);
|
|
5016
|
+
}
|
|
5017
|
+
this.currentThinkingId = null;
|
|
5018
|
+
}
|
|
4871
5019
|
/**
|
|
4872
5020
|
* Add a user message block (for REPL mid-session input).
|
|
4873
5021
|
*
|
|
@@ -4951,6 +5099,7 @@ var BlockRenderer = class _BlockRenderer {
|
|
|
4951
5099
|
this.selectableIds = [];
|
|
4952
5100
|
this.selectedIndex = -1;
|
|
4953
5101
|
this.currentLLMCallId = null;
|
|
5102
|
+
this.currentThinkingId = null;
|
|
4954
5103
|
for (const child of [...this.container.children]) {
|
|
4955
5104
|
child.detach();
|
|
4956
5105
|
}
|
|
@@ -5280,6 +5429,25 @@ ${fullContent}
|
|
|
5280
5429
|
}
|
|
5281
5430
|
return this.abbreviateToLines(fullContent, 2, selected);
|
|
5282
5431
|
}
|
|
5432
|
+
case "thinking": {
|
|
5433
|
+
const DIM2 = "\x1B[2m";
|
|
5434
|
+
const RED_DIM = "\x1B[2;31m";
|
|
5435
|
+
const RESET3 = "\x1B[0m";
|
|
5436
|
+
const contIndent = getContinuationIndent(node.depth);
|
|
5437
|
+
if (node.thinkingType === "redacted") {
|
|
5438
|
+
const header2 = `${indent}${RED_DIM}\u{1F512} [Redacted thinking block]${RESET3}`;
|
|
5439
|
+
return header2;
|
|
5440
|
+
}
|
|
5441
|
+
if (!expanded) {
|
|
5442
|
+
const firstLine = node.content.split("\n")[0]?.slice(0, 60) ?? "";
|
|
5443
|
+
const suffix = node.isComplete ? "" : "...";
|
|
5444
|
+
return `${indent}${DIM2}\u{1F4AD} Thinking${suffix} ${firstLine}${RESET3}`;
|
|
5445
|
+
}
|
|
5446
|
+
const tokenInfo = node.isComplete ? ` (${Math.ceil(node.content.length / 4)} tokens est.)` : "";
|
|
5447
|
+
const header = `${indent}${DIM2}\u25BC \u{1F4AD} Thinking${tokenInfo}${RESET3}`;
|
|
5448
|
+
const contentLines = node.content.split("\n").map((line) => `${contIndent}${DIM2}${line}${RESET3}`);
|
|
5449
|
+
return [header, ...contentLines].join("\n");
|
|
5450
|
+
}
|
|
5283
5451
|
case "system_message": {
|
|
5284
5452
|
const icon = this.getSystemMessageIcon(node.category);
|
|
5285
5453
|
const color = this.getSystemMessageColor(node.category);
|
|
@@ -5619,6 +5787,8 @@ ${indicator}`;
|
|
|
5619
5787
|
return true;
|
|
5620
5788
|
case "llm_call":
|
|
5621
5789
|
return false;
|
|
5790
|
+
case "thinking":
|
|
5791
|
+
return false;
|
|
5622
5792
|
case "gadget": {
|
|
5623
5793
|
const name = node.name;
|
|
5624
5794
|
return name === "TellUser" || name === "AskUser" || name === "Finish";
|
|
@@ -5680,6 +5850,7 @@ ${indicator}`;
|
|
|
5680
5850
|
handleTreeEvent(event, tree) {
|
|
5681
5851
|
switch (event.type) {
|
|
5682
5852
|
case "llm_call_start": {
|
|
5853
|
+
this.currentThinkingId = null;
|
|
5683
5854
|
let parentBlockId;
|
|
5684
5855
|
if (event.parentId) {
|
|
5685
5856
|
parentBlockId = this.treeNodeToBlockId.get(event.parentId);
|
|
@@ -5698,12 +5869,14 @@ ${indicator}`;
|
|
|
5698
5869
|
break;
|
|
5699
5870
|
}
|
|
5700
5871
|
case "llm_call_complete": {
|
|
5872
|
+
this.completeThinking();
|
|
5701
5873
|
const blockId = this.treeNodeToBlockId.get(event.nodeId);
|
|
5702
5874
|
if (blockId) {
|
|
5703
5875
|
this.completeLLMCall(blockId, {
|
|
5704
5876
|
inputTokens: event.usage?.inputTokens,
|
|
5705
5877
|
cachedInputTokens: event.usage?.cachedInputTokens,
|
|
5706
5878
|
outputTokens: event.usage?.outputTokens,
|
|
5879
|
+
reasoningTokens: event.usage?.reasoningTokens,
|
|
5707
5880
|
cost: event.cost,
|
|
5708
5881
|
finishReason: event.finishReason ?? void 0
|
|
5709
5882
|
});
|
|
@@ -5714,6 +5887,10 @@ ${indicator}`;
|
|
|
5714
5887
|
}
|
|
5715
5888
|
break;
|
|
5716
5889
|
}
|
|
5890
|
+
case "thinking": {
|
|
5891
|
+
this.addThinking(event.content, event.thinkingType);
|
|
5892
|
+
break;
|
|
5893
|
+
}
|
|
5717
5894
|
case "gadget_call": {
|
|
5718
5895
|
let parentBlockId;
|
|
5719
5896
|
if (event.parentId) {
|
|
@@ -7404,6 +7581,7 @@ var StatusBar = class {
|
|
|
7404
7581
|
inputTokens: 0,
|
|
7405
7582
|
outputTokens: 0,
|
|
7406
7583
|
cachedTokens: 0,
|
|
7584
|
+
reasoningTokens: 0,
|
|
7407
7585
|
cost: 0,
|
|
7408
7586
|
startTime: Date.now(),
|
|
7409
7587
|
iteration: 0,
|
|
@@ -7437,10 +7615,11 @@ var StatusBar = class {
|
|
|
7437
7615
|
* Called when an LLM call completes.
|
|
7438
7616
|
* Replaces streaming estimates with actual values.
|
|
7439
7617
|
*/
|
|
7440
|
-
endCall(inputTokens, outputTokens, cachedTokens, cost) {
|
|
7618
|
+
endCall(inputTokens, outputTokens, cachedTokens, cost, reasoningTokens = 0) {
|
|
7441
7619
|
this.metrics.inputTokens += inputTokens;
|
|
7442
7620
|
this.metrics.outputTokens += outputTokens;
|
|
7443
7621
|
this.metrics.cachedTokens += cachedTokens;
|
|
7622
|
+
this.metrics.reasoningTokens += reasoningTokens;
|
|
7444
7623
|
this.metrics.cost += cost;
|
|
7445
7624
|
this.streamingInputTokens = 0;
|
|
7446
7625
|
this.streamingOutputTokens = 0;
|
|
@@ -7640,7 +7819,8 @@ var StatusBar = class {
|
|
|
7640
7819
|
event.usage?.inputTokens ?? 0,
|
|
7641
7820
|
event.usage?.outputTokens ?? 0,
|
|
7642
7821
|
event.usage?.cachedInputTokens ?? 0,
|
|
7643
|
-
event.cost ?? 0
|
|
7822
|
+
event.cost ?? 0,
|
|
7823
|
+
event.usage?.reasoningTokens ?? 0
|
|
7644
7824
|
);
|
|
7645
7825
|
}
|
|
7646
7826
|
this.nodeIdToLabel.delete(event.nodeId);
|
|
@@ -7805,6 +7985,9 @@ var StatusBar = class {
|
|
|
7805
7985
|
const outputPrefix = this.isStreaming ? "~" : "";
|
|
7806
7986
|
parts.push(`${GREEN2}\u2193${outputPrefix}${formatTokens(displayOutputTokens)}${RESET3}`);
|
|
7807
7987
|
}
|
|
7988
|
+
if (this.metrics.reasoningTokens > 0) {
|
|
7989
|
+
parts.push(`${MAGENTA2}\u{1F4AD}${formatTokens(this.metrics.reasoningTokens)}${RESET3}`);
|
|
7990
|
+
}
|
|
7808
7991
|
const earliestStart = this.getEarliestLLMCallStartTime();
|
|
7809
7992
|
if (earliestStart !== null) {
|
|
7810
7993
|
const elapsedSeconds = (Date.now() - earliestStart) / 1e3;
|
|
@@ -8048,6 +8231,8 @@ var TUIApp = class _TUIApp {
|
|
|
8048
8231
|
handleEvent(event) {
|
|
8049
8232
|
if (event.type === "text") {
|
|
8050
8233
|
this.blockRenderer.addText(event.content);
|
|
8234
|
+
} else if (event.type === "thinking") {
|
|
8235
|
+
this.blockRenderer.addThinking(event.content, event.thinkingType);
|
|
8051
8236
|
}
|
|
8052
8237
|
}
|
|
8053
8238
|
/**
|
|
@@ -8698,6 +8883,27 @@ ${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`
|
|
|
8698
8883
|
if (options.temperature !== void 0) {
|
|
8699
8884
|
builder.withTemperature(options.temperature);
|
|
8700
8885
|
}
|
|
8886
|
+
if (options.reasoning === false) {
|
|
8887
|
+
builder.withoutReasoning();
|
|
8888
|
+
} else if (options.reasoning !== void 0 || options.reasoningBudget !== void 0) {
|
|
8889
|
+
const effort = typeof options.reasoning === "string" ? options.reasoning : void 0;
|
|
8890
|
+
builder.withReasoning({
|
|
8891
|
+
enabled: true,
|
|
8892
|
+
...effort && { effort },
|
|
8893
|
+
...options.reasoningBudget && { budgetTokens: options.reasoningBudget }
|
|
8894
|
+
});
|
|
8895
|
+
} else if (options.profileReasoning) {
|
|
8896
|
+
const cfg = options.profileReasoning;
|
|
8897
|
+
if (cfg.enabled === false) {
|
|
8898
|
+
builder.withoutReasoning();
|
|
8899
|
+
} else {
|
|
8900
|
+
builder.withReasoning({
|
|
8901
|
+
enabled: true,
|
|
8902
|
+
...cfg.effort && { effort: cfg.effort },
|
|
8903
|
+
...cfg["budget-tokens"] && { budgetTokens: cfg["budget-tokens"] }
|
|
8904
|
+
});
|
|
8905
|
+
}
|
|
8906
|
+
}
|
|
8701
8907
|
if (tui) {
|
|
8702
8908
|
builder.onHumanInput(async (question) => {
|
|
8703
8909
|
return tui.waitForInput(question, "AskUser");
|
|
@@ -8788,6 +8994,11 @@ ${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`
|
|
|
8788
8994
|
} else {
|
|
8789
8995
|
if (event.type === "text") {
|
|
8790
8996
|
env.stdout.write(event.content);
|
|
8997
|
+
} else if (event.type === "thinking") {
|
|
8998
|
+
const stderrTTY = env.stderr.isTTY === true;
|
|
8999
|
+
if (stderrTTY && !options.quiet) {
|
|
9000
|
+
env.stderr.write(`\x1B[2m${event.content}\x1B[0m`);
|
|
9001
|
+
}
|
|
8791
9002
|
} else if (event.type === "gadget_result" && event.result.gadgetName === "TellUser" && event.result.result) {
|
|
8792
9003
|
env.stdout.write(`${event.result.result}
|
|
8793
9004
|
`);
|
|
@@ -8854,6 +9065,7 @@ function registerAgentCommand(program, env, config, globalSubagents, globalRateL
|
|
|
8854
9065
|
globalRetry,
|
|
8855
9066
|
profileRateLimits: config?.["rate-limits"],
|
|
8856
9067
|
profileRetry: config?.retry,
|
|
9068
|
+
profileReasoning: config?.reasoning,
|
|
8857
9069
|
showHints: config?.["show-hints"]
|
|
8858
9070
|
};
|
|
8859
9071
|
return executeAgent(prompt, mergedOptions, env, "agent");
|
|
@@ -8908,11 +9120,34 @@ async function executeComplete(promptArg, options, env) {
|
|
|
8908
9120
|
const content = formatLlmRequest2(messages);
|
|
8909
9121
|
await writeLogFile(llmLogDir, filename, content);
|
|
8910
9122
|
}
|
|
9123
|
+
let reasoning;
|
|
9124
|
+
if (options.reasoning === false) {
|
|
9125
|
+
reasoning = { enabled: false };
|
|
9126
|
+
} else if (options.reasoning !== void 0 || options.reasoningBudget !== void 0) {
|
|
9127
|
+
const effort = typeof options.reasoning === "string" ? options.reasoning : void 0;
|
|
9128
|
+
reasoning = {
|
|
9129
|
+
enabled: true,
|
|
9130
|
+
...effort && { effort },
|
|
9131
|
+
...options.reasoningBudget && { budgetTokens: options.reasoningBudget }
|
|
9132
|
+
};
|
|
9133
|
+
} else if (options.profileReasoning) {
|
|
9134
|
+
const cfg = options.profileReasoning;
|
|
9135
|
+
if (cfg.enabled === false) {
|
|
9136
|
+
reasoning = { enabled: false };
|
|
9137
|
+
} else {
|
|
9138
|
+
reasoning = {
|
|
9139
|
+
enabled: true,
|
|
9140
|
+
...cfg.effort && { effort: cfg.effort },
|
|
9141
|
+
...cfg["budget-tokens"] && { budgetTokens: cfg["budget-tokens"] }
|
|
9142
|
+
};
|
|
9143
|
+
}
|
|
9144
|
+
}
|
|
8911
9145
|
const stream = client.stream({
|
|
8912
9146
|
model,
|
|
8913
9147
|
messages,
|
|
8914
9148
|
temperature: options.temperature,
|
|
8915
|
-
maxTokens: options.maxTokens
|
|
9149
|
+
maxTokens: options.maxTokens,
|
|
9150
|
+
...reasoning && { reasoning }
|
|
8916
9151
|
});
|
|
8917
9152
|
const printer = new StreamPrinter(env.stdout);
|
|
8918
9153
|
const stderrTTY = env.stderr.isTTY === true;
|
|
@@ -8932,6 +9167,12 @@ async function executeComplete(promptArg, options, env) {
|
|
|
8932
9167
|
progress.setOutputTokens(chunk.usage.outputTokens, false);
|
|
8933
9168
|
}
|
|
8934
9169
|
}
|
|
9170
|
+
if (chunk.thinking?.content) {
|
|
9171
|
+
if (stderrTTY && !options.quiet) {
|
|
9172
|
+
progress.pause();
|
|
9173
|
+
env.stderr.write(`\x1B[2m${chunk.thinking.content}\x1B[0m`);
|
|
9174
|
+
}
|
|
9175
|
+
}
|
|
8935
9176
|
if (chunk.text) {
|
|
8936
9177
|
progress.pause();
|
|
8937
9178
|
accumulatedResponse += chunk.text;
|
|
@@ -8965,7 +9206,8 @@ function registerCompleteCommand(program, env, config, globalRateLimits, globalR
|
|
|
8965
9206
|
const mergedOptions = {
|
|
8966
9207
|
...options,
|
|
8967
9208
|
globalRateLimits,
|
|
8968
|
-
globalRetry
|
|
9209
|
+
globalRetry,
|
|
9210
|
+
profileReasoning: config?.reasoning
|
|
8969
9211
|
};
|
|
8970
9212
|
return executeComplete(prompt, mergedOptions, env);
|
|
8971
9213
|
}, env)
|