nexrall-code 0.5.127 → 0.5.129
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/index.js +193 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -146428,47 +146428,44 @@ function formatToolUse(name, input) {
|
|
|
146428
146428
|
const argDisplay = primaryArg ? source_default.dim(" ") + source_default.white(String(primaryArg).replace(/\n/g, "\u21B5").slice(0, 80)) : "";
|
|
146429
146429
|
return source_default.yellow(icons.tool) + " " + source_default.bold(name) + argDisplay;
|
|
146430
146430
|
}
|
|
146431
|
-
var ToolStreamPrinter = class
|
|
146431
|
+
var ToolStreamPrinter = class {
|
|
146432
|
+
// Only the first PREVIEW lines are printed live; the rest are COUNTED, not printed, and the
|
|
146433
|
+
// full text stays in the ToolOutputStore for Ctrl+O / /expand. A build log used to bury the
|
|
146434
|
+
// conversation under 200 lines of scrollback that nobody re-reads.
|
|
146435
|
+
constructor(preview = 8) {
|
|
146436
|
+
this.preview = preview;
|
|
146437
|
+
}
|
|
146432
146438
|
carry = "";
|
|
146433
146439
|
linesShown = 0;
|
|
146434
|
-
|
|
146435
|
-
// build tool re-printing a progress bar thousands of times) doesn't flood
|
|
146436
|
-
// the terminal — the full output is still available afterward via
|
|
146437
|
-
// formatToolResult's summary and, for large output, the spill file.
|
|
146438
|
-
static MAX_LINES = 200;
|
|
146439
|
-
capped = false;
|
|
146440
|
+
hidden = 0;
|
|
146440
146441
|
feed(chunk) {
|
|
146441
|
-
if (this.capped)
|
|
146442
|
-
return;
|
|
146443
146442
|
this.carry += chunk;
|
|
146444
146443
|
const lines = this.carry.split("\n");
|
|
146445
146444
|
this.carry = lines.pop() ?? "";
|
|
146446
|
-
for (const line of lines)
|
|
146447
|
-
|
|
146448
|
-
return;
|
|
146449
|
-
}
|
|
146445
|
+
for (const line of lines)
|
|
146446
|
+
this.printLine(line);
|
|
146450
146447
|
}
|
|
146451
146448
|
printLine(line) {
|
|
146452
|
-
if (this.linesShown >=
|
|
146453
|
-
|
|
146454
|
-
|
|
146455
|
-
console.log(source_default.dim(" \u2502 \u2026 output continues (full log in the result above once finished)"));
|
|
146456
|
-
}
|
|
146457
|
-
return false;
|
|
146449
|
+
if (this.linesShown >= this.preview) {
|
|
146450
|
+
this.hidden++;
|
|
146451
|
+
return;
|
|
146458
146452
|
}
|
|
146459
146453
|
this.linesShown++;
|
|
146460
146454
|
console.log(source_default.dim(" \u2502 ") + source_default.gray(line.slice(0, 300)));
|
|
146461
|
-
|
|
146455
|
+
}
|
|
146456
|
+
/** Lines counted but not printed so far (the trailing partial line is not included). */
|
|
146457
|
+
get hiddenLines() {
|
|
146458
|
+
return this.hidden;
|
|
146462
146459
|
}
|
|
146463
146460
|
flush() {
|
|
146464
|
-
if (
|
|
146461
|
+
if (this.carry)
|
|
146465
146462
|
this.printLine(this.carry);
|
|
146466
146463
|
this.carry = "";
|
|
146467
146464
|
}
|
|
146468
146465
|
reset() {
|
|
146469
146466
|
this.carry = "";
|
|
146470
146467
|
this.linesShown = 0;
|
|
146471
|
-
this.
|
|
146468
|
+
this.hidden = 0;
|
|
146472
146469
|
}
|
|
146473
146470
|
};
|
|
146474
146471
|
function formatToolResult(name, result, durationMs) {
|
|
@@ -155005,9 +155002,9 @@ function ErrorOverview({ error }) {
|
|
|
155005
155002
|
))) : null,
|
|
155006
155003
|
error.stack ? import_react13.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, error.stack.split("\n").slice(1).map((line) => {
|
|
155007
155004
|
const parsedLine = stackUtils.parseLine(line);
|
|
155008
|
-
const
|
|
155009
|
-
stackLineCounts.set(line,
|
|
155010
|
-
const key = `${line}-${
|
|
155005
|
+
const lineCount2 = stackLineCounts.get(line) ?? 0;
|
|
155006
|
+
stackLineCounts.set(line, lineCount2 + 1);
|
|
155007
|
+
const key = `${line}-${lineCount2}`;
|
|
155011
155008
|
if (!parsedLine?.file || !parsedLine.line || !parsedLine.column) {
|
|
155012
155009
|
return import_react13.default.createElement(
|
|
155013
155010
|
Box_default,
|
|
@@ -157583,6 +157580,7 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
157583
157580
|
{ name: "cost", description: "Tokens and cost of this conversation", kind: "builtin" },
|
|
157584
157581
|
{ name: "status", description: "Version, model, mode, directory and session at a glance", kind: "builtin" },
|
|
157585
157582
|
{ name: "copy", description: "Copy the last reply to the clipboard", kind: "builtin" },
|
|
157583
|
+
{ name: "expand", description: "Show the full output of a folded tool call (Ctrl+O)", argHint: "[n]", kind: "builtin" },
|
|
157586
157584
|
{ name: "export", description: "Write this conversation to a Markdown file", argHint: "[file]", kind: "builtin" },
|
|
157587
157585
|
{ name: "rename", description: "Rename this session", argHint: "<title>", requiresArg: true, kind: "builtin" },
|
|
157588
157586
|
{ name: "diff", description: "Show uncommitted changes in the working directory", kind: "builtin" },
|
|
@@ -157696,6 +157694,9 @@ function windowStart(selected, total, size) {
|
|
|
157696
157694
|
const start = selected - Math.floor(size / 2);
|
|
157697
157695
|
return Math.max(0, Math.min(start, total - size));
|
|
157698
157696
|
}
|
|
157697
|
+
function reserveMenuRows(previous, showing) {
|
|
157698
|
+
return Math.max(0, previous, showing);
|
|
157699
|
+
}
|
|
157699
157700
|
|
|
157700
157701
|
// src/commands/bangShell.ts
|
|
157701
157702
|
import { spawn } from "child_process";
|
|
@@ -158394,6 +158395,7 @@ var App2 = ({ onReady }) => {
|
|
|
158394
158395
|
const slashEntriesRef = (0, import_react35.useRef)(BUILTIN_SLASH_COMMANDS);
|
|
158395
158396
|
const menuSelRef = (0, import_react35.useRef)({ query: "", idx: 0 });
|
|
158396
158397
|
const menuDismissedRef = (0, import_react35.useRef)(null);
|
|
158398
|
+
const menuReserveRef = (0, import_react35.useRef)(0);
|
|
158397
158399
|
const [, bumpMenu] = (0, import_react35.useState)(0);
|
|
158398
158400
|
const searchRef = (0, import_react35.useRef)(null);
|
|
158399
158401
|
const draftBeforeSearchRef = (0, import_react35.useRef)("");
|
|
@@ -158405,6 +158407,10 @@ var App2 = ({ onReady }) => {
|
|
|
158405
158407
|
const onHelp = (0, import_react35.useCallback)((cb) => {
|
|
158406
158408
|
onHelpRef.current = cb;
|
|
158407
158409
|
}, []);
|
|
158410
|
+
const onExpandRef = (0, import_react35.useRef)(null);
|
|
158411
|
+
const onExpand = (0, import_react35.useCallback)((cb) => {
|
|
158412
|
+
onExpandRef.current = cb;
|
|
158413
|
+
}, []);
|
|
158408
158414
|
const mentionSelRef = (0, import_react35.useRef)({ query: "", idx: 0 });
|
|
158409
158415
|
const mentionDismissedRef = (0, import_react35.useRef)(null);
|
|
158410
158416
|
const mentionRootRef = (0, import_react35.useRef)(process.cwd());
|
|
@@ -158602,6 +158608,12 @@ var App2 = ({ onReady }) => {
|
|
|
158602
158608
|
onCycleModeRef.current?.();
|
|
158603
158609
|
return;
|
|
158604
158610
|
}
|
|
158611
|
+
if (key.ctrl && char === "o") {
|
|
158612
|
+
if (askResolverRef.current)
|
|
158613
|
+
return;
|
|
158614
|
+
onExpandRef.current?.();
|
|
158615
|
+
return;
|
|
158616
|
+
}
|
|
158605
158617
|
const menu = askResolverRef.current || searchRef.current || historyRef.current.browsing ? null : computeMenu(lineRef.current, cursorRef.current, slashEntriesRef.current, menuDismissedRef.current);
|
|
158606
158618
|
if (menu) {
|
|
158607
158619
|
const sel = menuSelRef.current.query === menu.query ? menuSelRef.current.idx : 0;
|
|
@@ -158846,6 +158858,7 @@ var App2 = ({ onReady }) => {
|
|
|
158846
158858
|
const submitted = lineRef.current.slice(0, pos) + before + lineRef.current.slice(pos);
|
|
158847
158859
|
setLine(after);
|
|
158848
158860
|
setCursorPos(0);
|
|
158861
|
+
menuReserveRef.current = 0;
|
|
158849
158862
|
print(prompt2 + submitted);
|
|
158850
158863
|
const askResolve = askResolverRef.current;
|
|
158851
158864
|
if (!askResolve && submitted.trim()) {
|
|
@@ -158971,7 +158984,8 @@ var App2 = ({ onReady }) => {
|
|
|
158971
158984
|
onBusyCommand,
|
|
158972
158985
|
onCycleMode,
|
|
158973
158986
|
onRewind,
|
|
158974
|
-
onHelp
|
|
158987
|
+
onHelp,
|
|
158988
|
+
onExpand
|
|
158975
158989
|
});
|
|
158976
158990
|
}, []);
|
|
158977
158991
|
const slices = renderInputSlices(line, cursorPos);
|
|
@@ -159035,9 +159049,13 @@ var App2 = ({ onReady }) => {
|
|
|
159035
159049
|
hint: ` ${sel + 1}/${m2.items.length} \xB7 \u2191\u2193 select \xB7 Tab/Enter insert \xB7 Esc close`
|
|
159036
159050
|
};
|
|
159037
159051
|
})();
|
|
159052
|
+
menuReserveRef.current = reserveMenuRows(
|
|
159053
|
+
menuReserveRef.current,
|
|
159054
|
+
slashMenu ? slashMenu.rows.length + 1 : mentionMenu ? mentionMenu.rows.length + 1 : 0
|
|
159055
|
+
);
|
|
159038
159056
|
const choiceVm = choiceRef.current ? choiceView(choiceRef.current.spec, choiceRef.current.sel) : null;
|
|
159039
159057
|
const riskColor = choiceVm?.risk === "high" ? "red" : choiceVm?.risk === "medium" ? "yellow" : "green";
|
|
159040
|
-
return /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Static, { items, key: staticKey }, (item) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: item.id }, item.content)), live ? /* @__PURE__ */ import_react35.default.createElement(Text, null, live) : null, choiceVm ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Text, { bold: true, wrap: "truncate-end" }, choiceVm.title), choiceVm.detail ? /* @__PURE__ */ import_react35.default.createElement(Text, { wrap: "truncate-end", color: choiceVm.risk ? riskColor : void 0, dimColor: !choiceVm.risk }, choiceVm.risk ? `${choiceVm.risk.toUpperCase()} RISK \xB7 ` : "", choiceVm.detail) : null, choiceVm.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.text, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, choiceVm.hint)) : null, searchVm ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Text, { color: searchVm.failed ? "red" : "cyan", wrap: "truncate-end" }, " " + searchVm.label), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, SEARCH_HINT)) : null, mentionMenu ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, mentionMenu.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.key, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, mentionMenu.hint)) : null, slashMenu ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, slashMenu.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.key, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, slashMenu.hint)) : null, /* @__PURE__ */ import_react35.default.createElement(
|
|
159058
|
+
return /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Static, { items, key: staticKey }, (item) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: item.id }, item.content)), live ? /* @__PURE__ */ import_react35.default.createElement(Text, null, live) : null, choiceVm ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Text, { bold: true, wrap: "truncate-end" }, choiceVm.title), choiceVm.detail ? /* @__PURE__ */ import_react35.default.createElement(Text, { wrap: "truncate-end", color: choiceVm.risk ? riskColor : void 0, dimColor: !choiceVm.risk }, choiceVm.risk ? `${choiceVm.risk.toUpperCase()} RISK \xB7 ` : "", choiceVm.detail) : null, choiceVm.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.text, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, choiceVm.hint)) : null, searchVm ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react35.default.createElement(Text, { color: searchVm.failed ? "red" : "cyan", wrap: "truncate-end" }, " " + searchVm.label), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, SEARCH_HINT)) : null, menuReserveRef.current > 0 ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column", justifyContent: "flex-end", minHeight: menuReserveRef.current }, mentionMenu ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, mentionMenu.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.key, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, mentionMenu.hint)) : null, slashMenu ? /* @__PURE__ */ import_react35.default.createElement(Box_default, { flexDirection: "column" }, slashMenu.rows.map((r2) => /* @__PURE__ */ import_react35.default.createElement(Text, { key: r2.key, wrap: "truncate-end", inverse: r2.selected }, r2.text)), /* @__PURE__ */ import_react35.default.createElement(Text, { dimColor: true, wrap: "truncate-end" }, slashMenu.hint)) : null) : null, /* @__PURE__ */ import_react35.default.createElement(
|
|
159041
159059
|
Box_default,
|
|
159042
159060
|
{
|
|
159043
159061
|
borderStyle: "single",
|
|
@@ -159255,6 +159273,99 @@ function rewindChoices(cps) {
|
|
|
159255
159273
|
return { options, ids: newest.map((c) => c.id) };
|
|
159256
159274
|
}
|
|
159257
159275
|
|
|
159276
|
+
// src/ui/toolOutputStore.ts
|
|
159277
|
+
var MAX_ENTRIES = 20;
|
|
159278
|
+
var MAX_ENTRY_CHARS = 4e5;
|
|
159279
|
+
var MAX_EXPAND_LINES = 1500;
|
|
159280
|
+
var PREVIEW_LINES = 8;
|
|
159281
|
+
function toolLabel(name, input) {
|
|
159282
|
+
const rec = input && typeof input === "object" ? input : {};
|
|
159283
|
+
const pick = ["command", "file_path", "path", "pattern", "url", "query", "description"].map((k) => rec[k]).find((v) => typeof v === "string" && v.length > 0);
|
|
159284
|
+
const flat = (pick ?? "").replace(/\s+/g, " ").trim();
|
|
159285
|
+
const clipped = flat.length > 100 ? flat.slice(0, 99) + "\u2026" : flat;
|
|
159286
|
+
return clipped ? `${name}: ${clipped}` : name;
|
|
159287
|
+
}
|
|
159288
|
+
function capOutput(text, max = MAX_ENTRY_CHARS) {
|
|
159289
|
+
if (text.length <= max)
|
|
159290
|
+
return text;
|
|
159291
|
+
const head = Math.floor(max * 0.6);
|
|
159292
|
+
const tail = max - head;
|
|
159293
|
+
const dropped = text.length - max;
|
|
159294
|
+
return text.slice(0, head) + `
|
|
159295
|
+
\u2026 ${dropped.toLocaleString()} characters omitted \u2026
|
|
159296
|
+
` + text.slice(text.length - tail);
|
|
159297
|
+
}
|
|
159298
|
+
var ToolOutputStore = class {
|
|
159299
|
+
entries = [];
|
|
159300
|
+
nextId = 1;
|
|
159301
|
+
add(e2) {
|
|
159302
|
+
const entry = { ...e2, id: this.nextId++, output: capOutput(e2.output) };
|
|
159303
|
+
this.entries.push(entry);
|
|
159304
|
+
if (this.entries.length > MAX_ENTRIES)
|
|
159305
|
+
this.entries.shift();
|
|
159306
|
+
return entry;
|
|
159307
|
+
}
|
|
159308
|
+
/** Newest first; `n` = 1 is the latest. */
|
|
159309
|
+
fromEnd(n) {
|
|
159310
|
+
if (!Number.isInteger(n) || n < 1)
|
|
159311
|
+
return void 0;
|
|
159312
|
+
return this.entries[this.entries.length - n];
|
|
159313
|
+
}
|
|
159314
|
+
byId(id) {
|
|
159315
|
+
return this.entries.find((e2) => e2.id === id);
|
|
159316
|
+
}
|
|
159317
|
+
/** The newest entry that actually has something worth expanding. */
|
|
159318
|
+
latestFoldable() {
|
|
159319
|
+
for (let i2 = this.entries.length - 1; i2 >= 0; i2--) {
|
|
159320
|
+
const e2 = this.entries[i2];
|
|
159321
|
+
if (lineCount(e2.output) > PREVIEW_LINES)
|
|
159322
|
+
return e2;
|
|
159323
|
+
}
|
|
159324
|
+
return void 0;
|
|
159325
|
+
}
|
|
159326
|
+
list() {
|
|
159327
|
+
return this.entries.slice();
|
|
159328
|
+
}
|
|
159329
|
+
clear() {
|
|
159330
|
+
this.entries = [];
|
|
159331
|
+
}
|
|
159332
|
+
};
|
|
159333
|
+
function lineCount(text) {
|
|
159334
|
+
if (!text)
|
|
159335
|
+
return 0;
|
|
159336
|
+
const t2 = text.endsWith("\n") ? text.slice(0, -1) : text;
|
|
159337
|
+
return t2.split("\n").length;
|
|
159338
|
+
}
|
|
159339
|
+
function expansionOf(e2, maxLines = MAX_EXPAND_LINES) {
|
|
159340
|
+
const all = (e2.output.endsWith("\n") ? e2.output.slice(0, -1) : e2.output).split("\n");
|
|
159341
|
+
const total = all.length;
|
|
159342
|
+
let lines = all;
|
|
159343
|
+
let omitted = 0;
|
|
159344
|
+
if (total > maxLines) {
|
|
159345
|
+
const head = Math.floor(maxLines * 0.4);
|
|
159346
|
+
const tail = maxLines - head;
|
|
159347
|
+
lines = [...all.slice(0, head), ...all.slice(total - tail)];
|
|
159348
|
+
omitted = total - maxLines;
|
|
159349
|
+
}
|
|
159350
|
+
return {
|
|
159351
|
+
header: `#${e2.id} ${e2.label}${e2.isError ? " (failed)" : ""} \u2014 ${total} line${total === 1 ? "" : "s"}`,
|
|
159352
|
+
lines,
|
|
159353
|
+
omitted
|
|
159354
|
+
};
|
|
159355
|
+
}
|
|
159356
|
+
function resolveExpand(store, arg) {
|
|
159357
|
+
const a = arg.trim();
|
|
159358
|
+
if (a === "") {
|
|
159359
|
+
const e3 = store.latestFoldable() ?? store.fromEnd(1);
|
|
159360
|
+
return e3 ? { entry: e3 } : { error: "No tool output yet." };
|
|
159361
|
+
}
|
|
159362
|
+
const n = Number(a.replace(/^#/, ""));
|
|
159363
|
+
if (!Number.isInteger(n) || n < 1)
|
|
159364
|
+
return { error: `Usage: /expand [n] (n = 1 is the latest tool call, 2 the one before \u2026)` };
|
|
159365
|
+
const e2 = store.fromEnd(n);
|
|
159366
|
+
return e2 ? { entry: e2 } : { error: `Only the last ${Math.min(MAX_ENTRIES, store.list().length)} tool call(s) are kept.` };
|
|
159367
|
+
}
|
|
159368
|
+
|
|
159258
159369
|
// src/commands/chat.ts
|
|
159259
159370
|
var require2 = createRequire(import.meta.url);
|
|
159260
159371
|
var CLI_VERSION = (() => {
|
|
@@ -159277,6 +159388,23 @@ var CLI_VERSION = (() => {
|
|
|
159277
159388
|
return "unknown";
|
|
159278
159389
|
})();
|
|
159279
159390
|
var sessionUsage = new UsageTotals();
|
|
159391
|
+
var toolOutputs = new ToolOutputStore();
|
|
159392
|
+
function printExpansion(arg) {
|
|
159393
|
+
const r2 = resolveExpand(toolOutputs, arg);
|
|
159394
|
+
if (!r2.entry) {
|
|
159395
|
+
console.log(source_default.dim(" " + (r2.error ?? "Nothing to expand.")));
|
|
159396
|
+
return;
|
|
159397
|
+
}
|
|
159398
|
+
const x2 = expansionOf(r2.entry);
|
|
159399
|
+
console.log();
|
|
159400
|
+
console.log(source_default.cyan(" \u25BE " + x2.header));
|
|
159401
|
+
for (const l2 of x2.lines)
|
|
159402
|
+
console.log(source_default.dim(" \u2502 ") + source_default.gray(l2.slice(0, 300)));
|
|
159403
|
+
if (x2.omitted > 0)
|
|
159404
|
+
console.log(source_default.dim(` \u2514 \u2026 ${x2.omitted} line(s) omitted \u2014 /export writes the whole conversation to a file`));
|
|
159405
|
+
else
|
|
159406
|
+
console.log(source_default.dim(" \u2514 end"));
|
|
159407
|
+
}
|
|
159280
159408
|
var MODEL_LABELS = {
|
|
159281
159409
|
"claude-sonnet-5-5": "Claude Sonnet 5.5",
|
|
159282
159410
|
"claude-opus-5-5": "Claude Opus 5.5",
|
|
@@ -159836,9 +159964,10 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
159836
159964
|
let lastUsage;
|
|
159837
159965
|
const spinner = new Spinner();
|
|
159838
159966
|
const mdRender = new MarkdownStreamRenderer();
|
|
159839
|
-
const toolStream = new ToolStreamPrinter();
|
|
159967
|
+
const toolStream = new ToolStreamPrinter(PREVIEW_LINES);
|
|
159840
159968
|
let toolStartTime = 0;
|
|
159841
159969
|
let lastToolName = "";
|
|
159970
|
+
let lastToolLabel = "";
|
|
159842
159971
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
159843
159972
|
const subPrefix = (meta) => source_default.dim(` \u21B3 ${meta?.agentName ?? "sub-agent"} `);
|
|
159844
159973
|
let thinkingTokens = 0;
|
|
@@ -159944,7 +160073,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
159944
160073
|
mdRender.flush();
|
|
159945
160074
|
spinner.stop();
|
|
159946
160075
|
if (meta?.id)
|
|
159947
|
-
toolCalls.set(meta.id, { name, start: Date.now() });
|
|
160076
|
+
toolCalls.set(meta.id, { name, start: Date.now(), label: toolLabel(name, input) });
|
|
159948
160077
|
if (isSubTask) {
|
|
159949
160078
|
console.log(subPrefix(meta) + formatToolUse(name, input).trim());
|
|
159950
160079
|
spinner.start(`${meta?.agentName ?? "sub-agent"}: ${name}\u2026`);
|
|
@@ -159954,6 +160083,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
159954
160083
|
console.log();
|
|
159955
160084
|
console.log(formatToolUse(name, input));
|
|
159956
160085
|
lastToolName = name;
|
|
160086
|
+
lastToolLabel = toolLabel(name, input);
|
|
159957
160087
|
toolStartTime = Date.now();
|
|
159958
160088
|
spinner.start(`running ${name}\u2026`);
|
|
159959
160089
|
},
|
|
@@ -159984,6 +160114,26 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
159984
160114
|
toolStream.flush();
|
|
159985
160115
|
const durationMs = Date.now() - (tracked?.start ?? toolStartTime);
|
|
159986
160116
|
console.log(formatToolResult(tracked?.name ?? lastToolName, res, durationMs));
|
|
160117
|
+
const text = res.error ? `${res.output ? res.output + "\n" : ""}${res.error}` : res.output ?? "";
|
|
160118
|
+
if (text) {
|
|
160119
|
+
const entry = toolOutputs.add({
|
|
160120
|
+
name: tracked?.name ?? lastToolName,
|
|
160121
|
+
label: tracked?.label ?? lastToolLabel,
|
|
160122
|
+
output: text,
|
|
160123
|
+
isError: !!res.error,
|
|
160124
|
+
durationMs
|
|
160125
|
+
});
|
|
160126
|
+
const total = lineCount(text);
|
|
160127
|
+
if (total > PREVIEW_LINES) {
|
|
160128
|
+
if (res.error) {
|
|
160129
|
+
const tail = text.replace(/\n$/, "").split("\n").slice(-3);
|
|
160130
|
+
for (const l2 of tail)
|
|
160131
|
+
console.log(source_default.dim(" \u2502 ") + source_default.red(l2.slice(0, 300)));
|
|
160132
|
+
}
|
|
160133
|
+
const more = Math.max(0, total - PREVIEW_LINES - (res.error ? 3 : 0));
|
|
160134
|
+
console.log(source_default.dim(` \u2514 \u2026 +${more} more line${more === 1 ? "" : "s"} \xB7 Ctrl+O or /expand to see all (#${entry.id})`));
|
|
160135
|
+
}
|
|
160136
|
+
}
|
|
159987
160137
|
toolStartTime = 0;
|
|
159988
160138
|
resumeWorking();
|
|
159989
160139
|
},
|
|
@@ -160215,6 +160365,7 @@ function printHelp() {
|
|
|
160215
160365
|
["/team [use <id|personal>]", "List your teams, or switch what usage is billed to"],
|
|
160216
160366
|
["/cost", "Tokens and cost of this conversation so far"],
|
|
160217
160367
|
["/status", "Version, model, mode, directory, session and cost at a glance"],
|
|
160368
|
+
["/expand [n]", "Show the full output of a folded tool call (newest by default; Ctrl+O does the same)"],
|
|
160218
160369
|
["/copy", "Copy the last reply to the clipboard"],
|
|
160219
160370
|
["/export [file]", "Write this conversation to a Markdown file"],
|
|
160220
160371
|
["/rename <title>", "Rename this session"],
|
|
@@ -160257,6 +160408,7 @@ function printHelp() {
|
|
|
160257
160408
|
["Ctrl+G", "Edit the draft in $VISUAL / $EDITOR"],
|
|
160258
160409
|
["Esc Esc", "At an empty prompt: pick a checkpoint to rewind to (same as /rewind)"],
|
|
160259
160410
|
["?", "At an empty prompt: show this list"],
|
|
160411
|
+
["Ctrl+O", "Expand the last folded tool output (also works while it is running; /expand [n] picks an older one)"],
|
|
160260
160412
|
["Ctrl+L", "Redraw the screen"],
|
|
160261
160413
|
["Ctrl+D", "Delete the character under the cursor; press twice on an empty line to exit"],
|
|
160262
160414
|
["(paste)", "Multi-line paste goes into the input box \u2014 it does not send until you press Enter"]
|
|
@@ -160674,6 +160826,9 @@ ${text}` : "");
|
|
|
160674
160826
|
getInkTerminal().onHelp(() => {
|
|
160675
160827
|
printHelp();
|
|
160676
160828
|
});
|
|
160829
|
+
getInkTerminal().onExpand(() => {
|
|
160830
|
+
printExpansion("");
|
|
160831
|
+
});
|
|
160677
160832
|
getInkTerminal().onRewind(() => {
|
|
160678
160833
|
void (async () => {
|
|
160679
160834
|
const opts = rewindChoices(checkpoints.list());
|
|
@@ -160742,6 +160897,7 @@ ${text}` : "");
|
|
|
160742
160897
|
sessionTitle = "";
|
|
160743
160898
|
(0, import_code_core8.resetSessionSubAgentBudget)();
|
|
160744
160899
|
sessionUsage.reset();
|
|
160900
|
+
toolOutputs.clear();
|
|
160745
160901
|
cliBackgroundAgents.stopAll({ dropPending: true });
|
|
160746
160902
|
inputBuffer = "";
|
|
160747
160903
|
if (interactive)
|
|
@@ -161198,6 +161354,10 @@ ${dirList}`;
|
|
|
161198
161354
|
rl.prompt();
|
|
161199
161355
|
return;
|
|
161200
161356
|
}
|
|
161357
|
+
case "/expand":
|
|
161358
|
+
printExpansion(arg);
|
|
161359
|
+
rl.prompt();
|
|
161360
|
+
return;
|
|
161201
161361
|
case "/copy": {
|
|
161202
161362
|
const text = lastAssistantText(messages);
|
|
161203
161363
|
if (!text) {
|
|
@@ -161633,7 +161793,7 @@ ${text}
|
|
|
161633
161793
|
if (shown < MAX_SHOWN_LINES)
|
|
161634
161794
|
console.log(" " + clean);
|
|
161635
161795
|
else if (shown === MAX_SHOWN_LINES)
|
|
161636
|
-
console.log(source_default.dim(" \u2026 output continues (the model still gets the start and the end)"));
|
|
161796
|
+
console.log(source_default.dim(" \u2026 output continues (the model still gets the start and the end; /expand shows it all)"));
|
|
161637
161797
|
shown++;
|
|
161638
161798
|
};
|
|
161639
161799
|
let result;
|
|
@@ -161655,6 +161815,9 @@ ${text}
|
|
|
161655
161815
|
}
|
|
161656
161816
|
const tag = result.aborted ? source_default.yellow(" interrupted") : result.timedOut ? source_default.yellow(" timed out") : result.code === 0 ? source_default.dim(" exit 0") : source_default.red(` exit ${result.code ?? result.signal}`);
|
|
161657
161817
|
console.log(tag);
|
|
161818
|
+
if (result.output) {
|
|
161819
|
+
toolOutputs.add({ name: "bash", label: `!${bang}`, output: result.output, isError: result.code !== 0, durationMs: 0 });
|
|
161820
|
+
}
|
|
161658
161821
|
messages.push(
|
|
161659
161822
|
{ role: "user", content: [{ type: "text", text: bangTranscript(bang, result) }] },
|
|
161660
161823
|
{ role: "assistant", content: [{ type: "text", text: "Noted the command output." }] }
|