@wrongstack/tui 0.7.0 → 0.7.2
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 +1940 -1613
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -313,1671 +313,1861 @@ function FleetPanel({ entries, totalCost, roster }) {
|
|
|
313
313
|
}
|
|
314
314
|
);
|
|
315
315
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (start + 1 >= lines.length) return start;
|
|
339
|
-
if (!ROW_RE.test(lines[start] ?? "")) return start;
|
|
340
|
-
const sep2 = lines[start + 1] ?? "";
|
|
341
|
-
if (!SEP_RE.test(sep2) || !/-/.test(sep2)) return start;
|
|
342
|
-
let end = start + 2;
|
|
343
|
-
while (end < lines.length && ROW_RE.test(lines[end] ?? "")) end++;
|
|
344
|
-
return end;
|
|
345
|
-
}
|
|
346
|
-
function parseCells(line) {
|
|
347
|
-
const inner = line.trim().replace(/^\||\|$/g, "");
|
|
348
|
-
const parts = [];
|
|
349
|
-
let buf = "";
|
|
350
|
-
for (let i = 0; i < inner.length; i++) {
|
|
351
|
-
const ch = inner[i];
|
|
352
|
-
if (ch === "\\" && inner[i + 1] === "|") {
|
|
353
|
-
buf += "|";
|
|
354
|
-
i++;
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
if (ch === "|") {
|
|
358
|
-
parts.push(buf);
|
|
359
|
-
buf = "";
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
buf += ch;
|
|
363
|
-
}
|
|
364
|
-
parts.push(buf);
|
|
365
|
-
return parts.map((c) => c.trim());
|
|
366
|
-
}
|
|
367
|
-
function parseAlign(sep2) {
|
|
368
|
-
const t = sep2.trim();
|
|
369
|
-
const left = t.startsWith(":");
|
|
370
|
-
const right = t.endsWith(":");
|
|
371
|
-
if (left && right) return "center";
|
|
372
|
-
if (right) return "right";
|
|
373
|
-
return "left";
|
|
374
|
-
}
|
|
375
|
-
function renderTable(tableLines, maxWidth) {
|
|
376
|
-
const header = parseCells(tableLines[0] ?? "");
|
|
377
|
-
const sepCells = parseCells(tableLines[1] ?? "");
|
|
378
|
-
const cols = header.length;
|
|
379
|
-
const aligns = [];
|
|
380
|
-
for (let c = 0; c < cols; c++) {
|
|
381
|
-
aligns.push(parseAlign(sepCells[c] ?? ""));
|
|
382
|
-
}
|
|
383
|
-
const dataRows = tableLines.slice(2).map(parseCells);
|
|
384
|
-
for (const row of dataRows) {
|
|
385
|
-
while (row.length < cols) row.push("");
|
|
386
|
-
row.length = cols;
|
|
387
|
-
}
|
|
388
|
-
const widths = computeWidths([header, ...dataRows], cols, maxWidth);
|
|
389
|
-
const lines = [];
|
|
390
|
-
lines.push(border("\u250C", "\u252C", "\u2510", widths));
|
|
391
|
-
lines.push(...renderRow(header, widths, aligns));
|
|
392
|
-
lines.push(border("\u251C", "\u253C", "\u2524", widths));
|
|
393
|
-
for (const row of dataRows) {
|
|
394
|
-
lines.push(...renderRow(row, widths, aligns));
|
|
395
|
-
}
|
|
396
|
-
lines.push(border("\u2514", "\u2534", "\u2518", widths));
|
|
397
|
-
return lines.join("\n");
|
|
398
|
-
}
|
|
399
|
-
function computeWidths(allRows, cols, maxWidth) {
|
|
400
|
-
const overhead = 3 * cols + 1;
|
|
401
|
-
const avail = Math.max(cols * MIN_COL_WIDTH, maxWidth - overhead);
|
|
402
|
-
const natural = new Array(cols).fill(0);
|
|
403
|
-
for (const row of allRows) {
|
|
404
|
-
for (let c = 0; c < cols; c++) {
|
|
405
|
-
const cell = row[c] ?? "";
|
|
406
|
-
const w = longestWord(cell);
|
|
407
|
-
const total = cell.length;
|
|
408
|
-
natural[c] = Math.max(natural[c], total);
|
|
409
|
-
if (w > natural[c]) natural[c] = Math.min(total + 1, w);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
const sumNatural = natural.reduce((s, n) => s + n, 0);
|
|
413
|
-
if (sumNatural <= avail) return natural;
|
|
414
|
-
const widths = natural.slice();
|
|
415
|
-
let sum = sumNatural;
|
|
416
|
-
while (sum > avail) {
|
|
417
|
-
let maxIdx = -1;
|
|
418
|
-
let maxVal = MIN_COL_WIDTH;
|
|
419
|
-
for (let i = 0; i < cols; i++) {
|
|
420
|
-
const w = widths[i];
|
|
421
|
-
if (w > maxVal) {
|
|
422
|
-
maxVal = w;
|
|
423
|
-
maxIdx = i;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
if (maxIdx < 0) break;
|
|
427
|
-
widths[maxIdx]--;
|
|
428
|
-
sum--;
|
|
429
|
-
}
|
|
430
|
-
return widths;
|
|
431
|
-
}
|
|
432
|
-
var MIN_COL_WIDTH = 4;
|
|
433
|
-
function longestWord(s) {
|
|
434
|
-
let max = 0;
|
|
435
|
-
for (const w of s.split(/\s+/)) if (w.length > max) max = w.length;
|
|
436
|
-
return max;
|
|
437
|
-
}
|
|
438
|
-
function border(left, mid, right, widths) {
|
|
439
|
-
return left + widths.map((w) => "\u2500".repeat(w + 2)).join(mid) + right;
|
|
440
|
-
}
|
|
441
|
-
function renderRow(cells, widths, aligns) {
|
|
442
|
-
const wrapped = cells.map((c, i) => wrapCell(c, widths[i] ?? MIN_COL_WIDTH));
|
|
443
|
-
const height = Math.max(1, ...wrapped.map((w) => w.length));
|
|
444
|
-
const out = [];
|
|
445
|
-
for (let line = 0; line < height; line++) {
|
|
446
|
-
const parts = [];
|
|
447
|
-
for (let c = 0; c < widths.length; c++) {
|
|
448
|
-
const w = widths[c] ?? MIN_COL_WIDTH;
|
|
449
|
-
const text = wrapped[c]?.[line] ?? "";
|
|
450
|
-
parts.push(padCell(text, w, aligns[c] ?? "left"));
|
|
451
|
-
}
|
|
452
|
-
out.push("\u2502 " + parts.join(" \u2502 ") + " \u2502");
|
|
453
|
-
}
|
|
454
|
-
return out;
|
|
455
|
-
}
|
|
456
|
-
function wrapCell(text, width) {
|
|
457
|
-
if (text.length <= width) return [text];
|
|
458
|
-
const out = [];
|
|
459
|
-
const words = text.split(/(\s+)/);
|
|
460
|
-
let cur = "";
|
|
461
|
-
for (const word of words) {
|
|
462
|
-
if (!word) continue;
|
|
463
|
-
if (cur.length + word.length <= width) {
|
|
464
|
-
cur += word;
|
|
465
|
-
continue;
|
|
466
|
-
}
|
|
467
|
-
if (cur) {
|
|
468
|
-
out.push(cur.trimEnd());
|
|
469
|
-
cur = "";
|
|
470
|
-
}
|
|
471
|
-
if (word.length > width) {
|
|
472
|
-
let rest = word;
|
|
473
|
-
while (rest.length > width) {
|
|
474
|
-
out.push(rest.slice(0, width));
|
|
475
|
-
rest = rest.slice(width);
|
|
476
|
-
}
|
|
477
|
-
cur = rest;
|
|
478
|
-
} else if (!/^\s+$/.test(word)) {
|
|
479
|
-
cur = word;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
if (cur) out.push(cur.trimEnd());
|
|
483
|
-
return out.length === 0 ? [""] : out;
|
|
484
|
-
}
|
|
485
|
-
function padCell(text, width, align) {
|
|
486
|
-
if (text.length >= width) return text.slice(0, width);
|
|
487
|
-
const pad = width - text.length;
|
|
488
|
-
if (align === "right") return " ".repeat(pad) + text;
|
|
489
|
-
if (align === "center") {
|
|
490
|
-
const l = Math.floor(pad / 2);
|
|
491
|
-
return " ".repeat(l) + text + " ".repeat(pad - l);
|
|
492
|
-
}
|
|
493
|
-
return text + " ".repeat(pad);
|
|
494
|
-
}
|
|
495
|
-
function History({ entries, streamingText, toolStream }) {
|
|
496
|
-
const { stdout } = useStdout();
|
|
497
|
-
const termWidth = stdout?.columns ?? 80;
|
|
498
|
-
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
499
|
-
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
500
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
501
|
-
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id) }),
|
|
502
|
-
tail ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
503
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
504
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "ASSISTANT: " }),
|
|
505
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "(streaming...)" })
|
|
506
|
-
] }),
|
|
507
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: tail })
|
|
508
|
-
] }) : null,
|
|
509
|
-
toolTail ? /* @__PURE__ */ jsx(
|
|
510
|
-
ToolStreamBox,
|
|
511
|
-
{
|
|
512
|
-
name: toolStream.name,
|
|
513
|
-
text: toolTail,
|
|
514
|
-
startedAt: toolStream.startedAt,
|
|
515
|
-
termWidth
|
|
516
|
-
}
|
|
517
|
-
) : null
|
|
518
|
-
] });
|
|
519
|
-
}
|
|
520
|
-
var MAX_STREAM_DISPLAY_CHARS = 480;
|
|
521
|
-
var MAX_STREAM_LINES = 8;
|
|
522
|
-
function ToolStreamBox({
|
|
523
|
-
name,
|
|
524
|
-
text,
|
|
525
|
-
startedAt,
|
|
526
|
-
termWidth
|
|
316
|
+
function StatusBar({
|
|
317
|
+
model,
|
|
318
|
+
version,
|
|
319
|
+
state,
|
|
320
|
+
tokenCounter,
|
|
321
|
+
hint,
|
|
322
|
+
queueCount = 0,
|
|
323
|
+
yolo = false,
|
|
324
|
+
autonomy,
|
|
325
|
+
elapsedMs,
|
|
326
|
+
todos,
|
|
327
|
+
plan,
|
|
328
|
+
fleet,
|
|
329
|
+
fleetAgents,
|
|
330
|
+
git,
|
|
331
|
+
subagentCount = 0,
|
|
332
|
+
context,
|
|
333
|
+
projectName,
|
|
334
|
+
processCount,
|
|
335
|
+
hiddenItems,
|
|
336
|
+
eternalStage,
|
|
337
|
+
goalSummary
|
|
527
338
|
}) {
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
},
|
|
533
|
-
const
|
|
534
|
-
const
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
if (text.length <= maxChars) return text;
|
|
558
|
-
const cut = text.length - maxChars;
|
|
559
|
-
const nl = text.indexOf("\n", cut);
|
|
560
|
-
if (nl !== -1 && nl < cut + 80) {
|
|
561
|
-
return `\u2026 ${text.slice(nl + 1)}`;
|
|
562
|
-
}
|
|
563
|
-
return `\u2026 ${text.slice(cut)}`;
|
|
564
|
-
}
|
|
565
|
-
function DiffBlock({ rows, hidden }) {
|
|
566
|
-
let gutterWidth = 1;
|
|
567
|
-
for (const r of rows) {
|
|
568
|
-
const n = r.kind === "del" ? r.oldLine : r.newLine;
|
|
569
|
-
if (typeof n === "number") {
|
|
570
|
-
const w = String(n).length;
|
|
571
|
-
if (w > gutterWidth) gutterWidth = w;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
const blank = " ".repeat(gutterWidth);
|
|
575
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, marginTop: 0, children: [
|
|
576
|
-
rows.map((row, i) => {
|
|
577
|
-
const key = i;
|
|
578
|
-
if (row.kind === "hunk") {
|
|
579
|
-
return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: row.text }, key);
|
|
580
|
-
}
|
|
581
|
-
if (row.kind === "meta") {
|
|
582
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${blank} ${row.text}` }, key);
|
|
583
|
-
}
|
|
584
|
-
const lnNumber = row.kind === "del" ? row.oldLine : row.newLine;
|
|
585
|
-
const lnText = typeof lnNumber === "number" ? String(lnNumber).padStart(gutterWidth, " ") : blank;
|
|
586
|
-
if (row.kind === "ctx") {
|
|
587
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ${row.text}` }, key);
|
|
588
|
-
}
|
|
589
|
-
const bg = row.kind === "add" ? "greenBright" : "redBright";
|
|
590
|
-
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
591
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ` }),
|
|
592
|
-
/* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: "black", children: row.text })
|
|
593
|
-
] }, key);
|
|
594
|
-
}),
|
|
595
|
-
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${blank} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
|
|
596
|
-
] });
|
|
597
|
-
}
|
|
598
|
-
function Entry({
|
|
599
|
-
entry,
|
|
600
|
-
termWidth
|
|
601
|
-
}) {
|
|
602
|
-
switch (entry.kind) {
|
|
603
|
-
case "user":
|
|
604
|
-
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
605
|
-
/* @__PURE__ */ jsx(Text, { color: entry.queued ? "yellow" : "cyan", children: entry.queued ? "\u231B" : "\u203A" }),
|
|
606
|
-
" ",
|
|
607
|
-
/* @__PURE__ */ jsx(Text, { dimColor: entry.queued ?? false, children: entry.text }),
|
|
608
|
-
entry.queued ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (queued)" }) : null
|
|
609
|
-
] });
|
|
610
|
-
case "assistant":
|
|
611
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
612
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "ASSISTANT: " }) }),
|
|
613
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: renderMarkdownTables(entry.text, termWidth) })
|
|
614
|
-
] });
|
|
615
|
-
case "tool": {
|
|
616
|
-
const argSummary = formatToolArgs(entry.name, entry.input);
|
|
617
|
-
const outLines = formatToolOutput(
|
|
618
|
-
entry.name,
|
|
619
|
-
entry.output,
|
|
620
|
-
entry.ok,
|
|
621
|
-
entry.outputBytes,
|
|
622
|
-
entry.outputLines
|
|
623
|
-
);
|
|
624
|
-
const diff = entry.ok ? extractDiffPreview(entry.name, entry.output) : void 0;
|
|
625
|
-
const sizeChip = (() => {
|
|
626
|
-
if (!entry.ok) return "";
|
|
627
|
-
const parts = [];
|
|
628
|
-
if (entry.outputLines !== void 0 && entry.outputLines > 0) {
|
|
629
|
-
parts.push(`${entry.outputLines} L`);
|
|
630
|
-
}
|
|
631
|
-
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
632
|
-
parts.push(fmtBytes2(entry.outputBytes));
|
|
633
|
-
}
|
|
634
|
-
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
635
|
-
parts.push(`\u2248${fmtTok(entry.outputTokens)} tok`);
|
|
636
|
-
}
|
|
637
|
-
return parts.join(" \xB7 ");
|
|
638
|
-
})();
|
|
639
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
640
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
641
|
-
/* @__PURE__ */ jsx(Text, { color: entry.ok ? "green" : "red", children: entry.ok ? "\u25CF" : "\u2717" }),
|
|
642
|
-
" ",
|
|
643
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: entry.name }),
|
|
644
|
-
argSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
645
|
-
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
646
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: argSummary })
|
|
339
|
+
const hiddenSet = new Set(hiddenItems);
|
|
340
|
+
const usage = tokenCounter?.total();
|
|
341
|
+
const cost = tokenCounter?.estimateCost();
|
|
342
|
+
const cache2 = tokenCounter?.cacheStats();
|
|
343
|
+
const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
|
|
344
|
+
const hasSecondLine = yolo || autonomy && autonomy !== "off" || elapsedMs !== void 0 || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0;
|
|
345
|
+
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
346
|
+
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity;
|
|
347
|
+
return /* @__PURE__ */ jsxs(
|
|
348
|
+
Box,
|
|
349
|
+
{
|
|
350
|
+
flexDirection: "column",
|
|
351
|
+
paddingX: 1,
|
|
352
|
+
borderStyle: "single",
|
|
353
|
+
borderTop: true,
|
|
354
|
+
borderBottom: false,
|
|
355
|
+
borderLeft: false,
|
|
356
|
+
borderRight: false,
|
|
357
|
+
children: [
|
|
358
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
359
|
+
version ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
360
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
361
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
|
|
362
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
363
|
+
" v",
|
|
364
|
+
version
|
|
365
|
+
] })
|
|
366
|
+
] }),
|
|
367
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
|
|
647
368
|
] }) : null,
|
|
648
|
-
/* @__PURE__ */
|
|
649
|
-
|
|
369
|
+
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
370
|
+
"\u25CF ",
|
|
371
|
+
stateLabel
|
|
372
|
+
] }),
|
|
373
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
374
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
|
|
375
|
+
context && context.max > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
376
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
377
|
+
/* @__PURE__ */ jsx(ContextChip, { ctx: context })
|
|
378
|
+
] }) : null,
|
|
379
|
+
usage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
380
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
381
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
382
|
+
"\u2191",
|
|
383
|
+
" ",
|
|
384
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)) }),
|
|
385
|
+
" ",
|
|
386
|
+
"\u2193 ",
|
|
387
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.output) })
|
|
388
|
+
] })
|
|
389
|
+
] }) : null,
|
|
390
|
+
cache2 && cache2.hitRatio > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
391
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
392
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
393
|
+
"cache ",
|
|
394
|
+
(cache2.hitRatio * 100).toFixed(0),
|
|
395
|
+
"%"
|
|
396
|
+
] })
|
|
397
|
+
] }) : null,
|
|
398
|
+
cost && cost.total > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
399
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
400
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
401
|
+
"$",
|
|
402
|
+
cost.total.toFixed(4)
|
|
403
|
+
] })
|
|
404
|
+
] }) : null,
|
|
405
|
+
queueCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
406
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
407
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
408
|
+
"\u231B queued: ",
|
|
409
|
+
queueCount
|
|
410
|
+
] })
|
|
411
|
+
] }) : null,
|
|
412
|
+
typeof processCount === "number" && processCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
413
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
414
|
+
/* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
415
|
+
"\u26A1 ",
|
|
416
|
+
processCount,
|
|
417
|
+
" process",
|
|
418
|
+
processCount === 1 ? "" : "es"
|
|
419
|
+
] })
|
|
420
|
+
] }) : null,
|
|
421
|
+
hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
422
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
423
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
|
|
424
|
+
] }) : null
|
|
650
425
|
] }),
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
/* @__PURE__ */ jsxs(
|
|
654
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children:
|
|
655
|
-
/* @__PURE__ */
|
|
426
|
+
hasSecondLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
427
|
+
yolo ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
|
|
428
|
+
autonomy && autonomy !== "off" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
429
|
+
yolo ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
430
|
+
/* @__PURE__ */ jsxs(
|
|
656
431
|
Text,
|
|
657
432
|
{
|
|
658
|
-
color:
|
|
659
|
-
|
|
660
|
-
children:
|
|
433
|
+
color: autonomy === "eternal" ? "red" : autonomy === "auto" ? "yellow" : "cyan",
|
|
434
|
+
bold: true,
|
|
435
|
+
children: [
|
|
436
|
+
"\u221E ",
|
|
437
|
+
autonomy.toUpperCase()
|
|
438
|
+
]
|
|
661
439
|
}
|
|
662
440
|
)
|
|
663
|
-
] },
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
/* @__PURE__ */
|
|
695
|
-
|
|
696
|
-
/* @__PURE__ */
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
})
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
441
|
+
] }) : null,
|
|
442
|
+
eternalStage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
443
|
+
yolo || autonomy && autonomy !== "off" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
444
|
+
/* @__PURE__ */ jsx(EternalStageChip, { stage: eternalStage })
|
|
445
|
+
] }) : null,
|
|
446
|
+
elapsedMs !== void 0 && !hiddenSet.has("elapsed") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
447
|
+
yolo || autonomy && autonomy !== "off" || eternalStage ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
448
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
449
|
+
"\u23F1 ",
|
|
450
|
+
fmtElapsed(elapsedMs)
|
|
451
|
+
] })
|
|
452
|
+
] }) : null,
|
|
453
|
+
projectName ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
454
|
+
yolo || elapsedMs !== void 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
455
|
+
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
456
|
+
"\u{1F4C1} ",
|
|
457
|
+
projectName
|
|
458
|
+
] })
|
|
459
|
+
] }) : null,
|
|
460
|
+
goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
461
|
+
yolo || elapsedMs !== void 0 || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
462
|
+
/* @__PURE__ */ jsxs(Text, { color: goalSummary.goalState === "active" ? "green" : goalSummary.goalState === "paused" ? "yellow" : goalSummary.goalState === "completed" ? "green" : "dim", children: [
|
|
463
|
+
"\u{1F3AF} ",
|
|
464
|
+
goalSummary.goal.length > 40 ? `${goalSummary.goal.slice(0, 37)}\u2026` : goalSummary.goal,
|
|
465
|
+
" [",
|
|
466
|
+
goalSummary.goalState,
|
|
467
|
+
"] (iter ",
|
|
468
|
+
goalSummary.iterations,
|
|
469
|
+
")"
|
|
470
|
+
] })
|
|
471
|
+
] }) : null,
|
|
472
|
+
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
473
|
+
yolo || elapsedMs !== void 0 || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
474
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
475
|
+
/* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
476
|
+
"\u2387 ",
|
|
477
|
+
git.branch
|
|
478
|
+
] }),
|
|
479
|
+
git.added > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
480
|
+
" +",
|
|
481
|
+
git.added
|
|
482
|
+
] }) : null,
|
|
483
|
+
git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
484
|
+
" -",
|
|
485
|
+
git.deleted
|
|
486
|
+
] }) : null,
|
|
487
|
+
git.untracked > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
488
|
+
" ?",
|
|
489
|
+
git.untracked
|
|
490
|
+
] }) : null
|
|
491
|
+
] })
|
|
492
|
+
] }) : null
|
|
493
|
+
] }) : null,
|
|
494
|
+
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
495
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
496
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
|
|
497
|
+
todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
498
|
+
"\u231B",
|
|
499
|
+
todos.inProgress
|
|
500
|
+
] }) : null,
|
|
501
|
+
todos.inProgress > 0 && (todos.pending > 0 || todos.completed > 0) ? " " : "",
|
|
502
|
+
todos.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
503
|
+
"\u2610",
|
|
504
|
+
todos.pending
|
|
505
|
+
] }) : null,
|
|
506
|
+
todos.pending > 0 && todos.completed > 0 ? " " : "",
|
|
507
|
+
todos.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
508
|
+
"\u2713",
|
|
509
|
+
todos.completed
|
|
510
|
+
] }) : null
|
|
511
|
+
] }) : null,
|
|
512
|
+
plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
513
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
514
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
515
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
|
|
516
|
+
plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
517
|
+
"\u231B",
|
|
518
|
+
plan.inProgress
|
|
519
|
+
] }) : null,
|
|
520
|
+
plan.inProgress > 0 && (plan.open > 0 || plan.done > 0) ? " " : "",
|
|
521
|
+
plan.open > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
522
|
+
"\u2610",
|
|
523
|
+
plan.open
|
|
524
|
+
] }) : null,
|
|
525
|
+
plan.open > 0 && plan.done > 0 ? " " : "",
|
|
526
|
+
plan.done > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
527
|
+
"\u2713",
|
|
528
|
+
plan.done
|
|
529
|
+
] }) : null
|
|
530
|
+
] })
|
|
531
|
+
] }) : null,
|
|
532
|
+
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
533
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
534
|
+
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
535
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
|
|
536
|
+
fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
537
|
+
"\u25B6",
|
|
538
|
+
fleet.running
|
|
539
|
+
] }) : null,
|
|
540
|
+
fleet.running > 0 && (fleet.pending > 0 || fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
541
|
+
fleet.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
542
|
+
"\u2610",
|
|
543
|
+
fleet.pending
|
|
544
|
+
] }) : null,
|
|
545
|
+
fleet.pending > 0 && (fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
546
|
+
fleet.idle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
547
|
+
"\xB7",
|
|
548
|
+
fleet.idle,
|
|
549
|
+
"idle"
|
|
550
|
+
] }) : null,
|
|
551
|
+
fleet.idle > 0 && fleet.completed > 0 ? " " : "",
|
|
552
|
+
fleet.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
553
|
+
"\u2713",
|
|
554
|
+
fleet.completed
|
|
555
|
+
] }) : null
|
|
556
|
+
] }) : /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
557
|
+
"\u{1F310} ",
|
|
558
|
+
subagentCount,
|
|
559
|
+
" agent",
|
|
560
|
+
subagentCount === 1 ? "" : "s"
|
|
561
|
+
] })
|
|
562
|
+
] }) : null
|
|
563
|
+
] }) : null,
|
|
564
|
+
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
565
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
566
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
567
|
+
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
568
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
569
|
+
/* @__PURE__ */ jsx(Text, { color: a.running ? "yellow" : void 0, dimColor: !a.running, children: a.running ? "\u25B6" : "\xB7" }),
|
|
570
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
571
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
572
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
573
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
574
|
+
a.toolCalls,
|
|
575
|
+
"t"
|
|
576
|
+
] }),
|
|
577
|
+
a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
578
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
579
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
|
|
580
|
+
] }) : null,
|
|
581
|
+
a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
582
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
583
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
584
|
+
"\u26A1\xD7",
|
|
585
|
+
a.extensions
|
|
586
|
+
] })
|
|
587
|
+
] }) : null
|
|
588
|
+
] }, i)
|
|
589
|
+
)) }) : null
|
|
590
|
+
]
|
|
591
|
+
}
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
function EternalStageChip({
|
|
595
|
+
stage
|
|
596
|
+
}) {
|
|
597
|
+
switch (stage.phase) {
|
|
598
|
+
case "idle":
|
|
599
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2B1C idle" });
|
|
600
|
+
case "decide":
|
|
601
|
+
return /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
602
|
+
"\u2B07 decide: ",
|
|
603
|
+
stage.reason
|
|
604
|
+
] });
|
|
605
|
+
case "execute":
|
|
606
|
+
return /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
607
|
+
"\u25B6 ",
|
|
608
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "execute" }),
|
|
609
|
+
stage.task ? `(${stage.task})` : ""
|
|
610
|
+
] });
|
|
611
|
+
case "reflect":
|
|
612
|
+
return /* @__PURE__ */ jsxs(Text, { color: stage.status === "success" ? "green" : stage.status === "failure" ? "red" : "yellow", children: [
|
|
613
|
+
"\u21A9 reflect: ",
|
|
614
|
+
stage.status
|
|
615
|
+
] });
|
|
616
|
+
case "sleep":
|
|
617
|
+
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
618
|
+
"\u{1F4A4} sleep ",
|
|
619
|
+
Math.round(stage.ms / 1e3),
|
|
620
|
+
"s"
|
|
621
|
+
] });
|
|
622
|
+
case "paused":
|
|
623
|
+
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u23F8 paused" });
|
|
624
|
+
case "stopped":
|
|
625
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25A0 stopped" });
|
|
626
|
+
case "error":
|
|
627
|
+
return /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
628
|
+
"\u26A0 error: ",
|
|
629
|
+
stage.message
|
|
630
|
+
] });
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function ContextChip({ ctx }) {
|
|
634
|
+
const ratio = Math.max(0, Math.min(1, ctx.used / ctx.max));
|
|
635
|
+
const pct = Math.round(ratio * 100);
|
|
636
|
+
const color = ratio >= 0.85 ? "red" : ratio >= 0.65 ? "yellow" : "cyan";
|
|
637
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
638
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx " }),
|
|
639
|
+
/* @__PURE__ */ jsx(Text, { color, children: renderProgress(ratio, 10) }),
|
|
640
|
+
/* @__PURE__ */ jsxs(Text, { color, children: [
|
|
641
|
+
" ",
|
|
642
|
+
pct,
|
|
643
|
+
"%"
|
|
743
644
|
] }),
|
|
744
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
745
|
-
|
|
746
|
-
|
|
645
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
646
|
+
" ",
|
|
647
|
+
"(",
|
|
648
|
+
fmtTok(ctx.used),
|
|
649
|
+
"/",
|
|
650
|
+
fmtTok(ctx.max),
|
|
651
|
+
")"
|
|
747
652
|
] })
|
|
748
653
|
] });
|
|
749
654
|
}
|
|
750
|
-
function
|
|
751
|
-
if (
|
|
752
|
-
|
|
655
|
+
function stateChip(state, fleetRunning) {
|
|
656
|
+
if (state === "idle" && fleetRunning > 0) {
|
|
657
|
+
return { label: `agents \u25B6${fleetRunning}`, color: "magenta" };
|
|
658
|
+
}
|
|
659
|
+
if (state === "idle") return { label: "idle", color: "cyan" };
|
|
660
|
+
if (state === "aborting") return { label: "aborting\u2026", color: "yellow" };
|
|
661
|
+
return { label: "thinking\u2026", color: "green" };
|
|
662
|
+
}
|
|
663
|
+
var FILLED = "\u2588";
|
|
664
|
+
var EMPTY = "\u2591";
|
|
665
|
+
function renderProgress(ratio, width) {
|
|
666
|
+
const clamped = Math.max(0, Math.min(1, ratio));
|
|
667
|
+
const filled = clamped === 0 ? 0 : Math.max(1, Math.round(clamped * width));
|
|
668
|
+
const capped = Math.min(width, filled);
|
|
669
|
+
return FILLED.repeat(capped) + EMPTY.repeat(width - capped);
|
|
753
670
|
}
|
|
754
671
|
function fmtTok(n) {
|
|
755
|
-
if (
|
|
756
|
-
if (n
|
|
757
|
-
|
|
758
|
-
return String(n);
|
|
672
|
+
if (n < 1e3) return String(n);
|
|
673
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(n < 1e4 ? 1 : 0)}k`;
|
|
674
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
759
675
|
}
|
|
760
|
-
function
|
|
761
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
762
|
-
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
676
|
+
function fmtElapsed(ms) {
|
|
763
677
|
const totalSec = Math.floor(ms / 1e3);
|
|
764
|
-
|
|
678
|
+
const h = Math.floor(totalSec / 3600);
|
|
679
|
+
const m = Math.floor(totalSec % 3600 / 60);
|
|
680
|
+
const s = totalSec % 60;
|
|
681
|
+
if (h > 0) {
|
|
682
|
+
return `${h}:${pad2(m)}:${pad2(s)}`;
|
|
683
|
+
}
|
|
684
|
+
return `${pad2(m)}:${pad2(s)}`;
|
|
765
685
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
return first ? `${shortenPath(first, 50)}${more}` : `${files.length} files`;
|
|
836
|
-
}
|
|
837
|
-
const filter = stringOf(obj["filter"]) ?? stringOf(obj["pattern"]);
|
|
838
|
-
return filter ? `"${truncMid(filter, ARG_BUDGET - 2)}"` : "";
|
|
839
|
-
}
|
|
840
|
-
case "json": {
|
|
841
|
-
const file = stringOf(obj["file"]);
|
|
842
|
-
const q = stringOf(obj["query"]);
|
|
843
|
-
if (file) return q ? `${shortenPath(file, 40)} ${q}` : shortenPath(file, ARG_BUDGET);
|
|
844
|
-
return q ? truncMid(q, ARG_BUDGET) : "";
|
|
686
|
+
function pad2(n) {
|
|
687
|
+
return n < 10 ? `0${n}` : String(n);
|
|
688
|
+
}
|
|
689
|
+
var STATUS = {
|
|
690
|
+
idle: { icon: "\u25CB", color: "gray" },
|
|
691
|
+
running: { icon: "\u25B6", color: "yellow" },
|
|
692
|
+
success: { icon: "\u2713", color: "green" },
|
|
693
|
+
failed: { icon: "\u2717", color: "red" },
|
|
694
|
+
timeout: { icon: "\u23F1", color: "yellow" },
|
|
695
|
+
stopped: { icon: "\u2298", color: "gray" }
|
|
696
|
+
};
|
|
697
|
+
var SPARK = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
698
|
+
function bucketActivity(recentTools, now, bins = 12, binMs = 2e3) {
|
|
699
|
+
const out = new Array(bins).fill(0);
|
|
700
|
+
const windowStart = now - bins * binMs;
|
|
701
|
+
for (const t of recentTools) {
|
|
702
|
+
if (t.at < windowStart || t.at > now) continue;
|
|
703
|
+
let idx = Math.floor((t.at - windowStart) / binMs);
|
|
704
|
+
if (idx < 0) idx = 0;
|
|
705
|
+
if (idx >= bins) idx = bins - 1;
|
|
706
|
+
out[idx]++;
|
|
707
|
+
}
|
|
708
|
+
return out;
|
|
709
|
+
}
|
|
710
|
+
function sparkline(values) {
|
|
711
|
+
if (values.length === 0) return "";
|
|
712
|
+
const max = Math.max(1, ...values);
|
|
713
|
+
return values.map((v) => {
|
|
714
|
+
if (v <= 0) return SPARK[0];
|
|
715
|
+
const idx = Math.min(SPARK.length - 1, Math.ceil(v / max * (SPARK.length - 1)));
|
|
716
|
+
return SPARK[idx];
|
|
717
|
+
}).join("");
|
|
718
|
+
}
|
|
719
|
+
function fmtTokens(n) {
|
|
720
|
+
if (n < 1e3) return String(n);
|
|
721
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
722
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
723
|
+
}
|
|
724
|
+
function FleetMonitor({
|
|
725
|
+
entries,
|
|
726
|
+
totalCost,
|
|
727
|
+
totalTokens,
|
|
728
|
+
maxConcurrent = 4,
|
|
729
|
+
nowTick
|
|
730
|
+
}) {
|
|
731
|
+
const all = Object.values(entries);
|
|
732
|
+
const running = all.filter((e) => e.status === "running");
|
|
733
|
+
const done = all.filter((e) => e.status === "success").length;
|
|
734
|
+
const failed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
735
|
+
const concurrencyRatio = maxConcurrent > 0 ? running.length / maxConcurrent : 0;
|
|
736
|
+
const maxTools = Math.max(1, ...all.map((e) => e.toolCalls));
|
|
737
|
+
const ordered = [...all].sort((a, b) => {
|
|
738
|
+
const ra = a.status === "running" ? 0 : a.status === "idle" ? 1 : 2;
|
|
739
|
+
const rb = b.status === "running" ? 0 : b.status === "idle" ? 1 : 2;
|
|
740
|
+
if (ra !== rb) return ra - rb;
|
|
741
|
+
return a.startedAt - b.startedAt;
|
|
742
|
+
});
|
|
743
|
+
const shown = ordered.slice(0, 8);
|
|
744
|
+
const events = [];
|
|
745
|
+
for (const e of all) {
|
|
746
|
+
events.push({ at: e.startedAt, icon: "\u25CF", color: "cyan", text: `${e.name} spawned` });
|
|
747
|
+
if (e.status !== "running" && e.status !== "idle") {
|
|
748
|
+
const s = STATUS[e.status];
|
|
749
|
+
events.push({
|
|
750
|
+
at: e.lastEventAt,
|
|
751
|
+
icon: s.icon,
|
|
752
|
+
color: s.color,
|
|
753
|
+
text: `${e.name} ${e.status} (${e.toolCalls}t)`
|
|
754
|
+
});
|
|
845
755
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
756
|
+
if (e.budgetWarning) {
|
|
757
|
+
events.push({
|
|
758
|
+
at: e.budgetWarning.at,
|
|
759
|
+
icon: "\u26A1",
|
|
760
|
+
color: "yellow",
|
|
761
|
+
text: `${e.name} ${e.budgetWarning.kind} ${e.budgetWarning.used}/${e.budgetWarning.limit} \u2014 extending`
|
|
762
|
+
});
|
|
851
763
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
764
|
+
}
|
|
765
|
+
events.sort((a, b) => b.at - a.at);
|
|
766
|
+
const timeline = events.slice(0, 6);
|
|
767
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
768
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
769
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "FLEET MONITOR" }),
|
|
770
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
771
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
772
|
+
"\u25B6",
|
|
773
|
+
running.length
|
|
774
|
+
] }),
|
|
775
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
776
|
+
"\u2713",
|
|
777
|
+
done
|
|
778
|
+
] }),
|
|
779
|
+
failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
780
|
+
"\u2717",
|
|
781
|
+
failed
|
|
782
|
+
] }) : null,
|
|
783
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Ctrl+F to close" })
|
|
784
|
+
] }),
|
|
785
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
786
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "concurrency" }),
|
|
787
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
788
|
+
"[",
|
|
789
|
+
renderProgress(concurrencyRatio, 10),
|
|
790
|
+
"]"
|
|
791
|
+
] }),
|
|
792
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
793
|
+
running.length,
|
|
794
|
+
"/",
|
|
795
|
+
maxConcurrent
|
|
796
|
+
] }),
|
|
797
|
+
totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
798
|
+
" ",
|
|
799
|
+
fmtTokens(totalTokens.input),
|
|
800
|
+
"\u2191 ",
|
|
801
|
+
fmtTokens(totalTokens.output),
|
|
802
|
+
"\u2193"
|
|
803
|
+
] }) : null,
|
|
804
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: ` $${totalCost.toFixed(3)}` })
|
|
805
|
+
] }),
|
|
806
|
+
shown.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No subagents yet \u2014 spawn with /fleet spawn or /fleet dispatch." }) : null,
|
|
807
|
+
shown.map((e) => {
|
|
808
|
+
const s = STATUS[e.status];
|
|
809
|
+
const elapsed = e.status === "running" ? fmtElapsed(Math.max(0, nowTick - e.startedAt)) : e.status;
|
|
810
|
+
const spark = sparkline(bucketActivity(e.recentTools, nowTick));
|
|
811
|
+
const tool = e.currentTool?.name ?? e.recentTools[e.recentTools.length - 1]?.name ?? "";
|
|
812
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
813
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
814
|
+
/* @__PURE__ */ jsx(Text, { color: s.color, bold: true, children: s.icon }),
|
|
815
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: e.name.padEnd(12).slice(0, 12) }),
|
|
816
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed.padEnd(7).slice(0, 7) }),
|
|
817
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: renderProgress(e.toolCalls / maxTools, 10) }),
|
|
818
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
819
|
+
"L",
|
|
820
|
+
e.iterations,
|
|
821
|
+
" ",
|
|
822
|
+
e.toolCalls,
|
|
823
|
+
"t"
|
|
824
|
+
] }),
|
|
825
|
+
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
826
|
+
"\u26A1\xD7",
|
|
827
|
+
e.extensions
|
|
828
|
+
] }) : null
|
|
829
|
+
] }),
|
|
830
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
831
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
832
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: spark }),
|
|
833
|
+
tool ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: tool }) : null
|
|
834
|
+
] })
|
|
835
|
+
] }, e.id);
|
|
836
|
+
}),
|
|
837
|
+
timeline.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
838
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "timeline" }),
|
|
839
|
+
timeline.map((ev, i) => (
|
|
840
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
|
|
841
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
842
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
843
|
+
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
844
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
845
|
+
] }, i)
|
|
846
|
+
))
|
|
847
|
+
] }) : null
|
|
848
|
+
] });
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// src/markdown-table.ts
|
|
852
|
+
function renderMarkdownTables(text, maxWidth) {
|
|
853
|
+
if (!text.includes("|")) return text;
|
|
854
|
+
const lines = text.split("\n");
|
|
855
|
+
const out = [];
|
|
856
|
+
let i = 0;
|
|
857
|
+
while (i < lines.length) {
|
|
858
|
+
const end = detectTable(lines, i);
|
|
859
|
+
if (end > i) {
|
|
860
|
+
out.push(renderTable(lines.slice(i, end), Math.max(20, maxWidth)));
|
|
861
|
+
i = end;
|
|
862
|
+
} else {
|
|
863
|
+
out.push(lines[i] ?? "");
|
|
864
|
+
i++;
|
|
857
865
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
866
|
+
}
|
|
867
|
+
return out.join("\n");
|
|
868
|
+
}
|
|
869
|
+
var ROW_RE = /^\s*\|.*\|\s*$/;
|
|
870
|
+
var SEP_RE = /^\s*\|[\s\-:|]+\|\s*$/;
|
|
871
|
+
function detectTable(lines, start) {
|
|
872
|
+
if (start + 1 >= lines.length) return start;
|
|
873
|
+
if (!ROW_RE.test(lines[start] ?? "")) return start;
|
|
874
|
+
const sep2 = lines[start + 1] ?? "";
|
|
875
|
+
if (!SEP_RE.test(sep2) || !/-/.test(sep2)) return start;
|
|
876
|
+
let end = start + 2;
|
|
877
|
+
while (end < lines.length && ROW_RE.test(lines[end] ?? "")) end++;
|
|
878
|
+
return end;
|
|
879
|
+
}
|
|
880
|
+
function parseCells(line) {
|
|
881
|
+
const inner = line.trim().replace(/^\||\|$/g, "");
|
|
882
|
+
const parts = [];
|
|
883
|
+
let buf = "";
|
|
884
|
+
for (let i = 0; i < inner.length; i++) {
|
|
885
|
+
const ch = inner[i];
|
|
886
|
+
if (ch === "\\" && inner[i + 1] === "|") {
|
|
887
|
+
buf += "|";
|
|
888
|
+
i++;
|
|
889
|
+
continue;
|
|
861
890
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
891
|
+
if (ch === "|") {
|
|
892
|
+
parts.push(buf);
|
|
893
|
+
buf = "";
|
|
894
|
+
continue;
|
|
865
895
|
}
|
|
896
|
+
buf += ch;
|
|
866
897
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
898
|
+
parts.push(buf);
|
|
899
|
+
return parts.map((c) => c.trim());
|
|
900
|
+
}
|
|
901
|
+
function parseAlign(sep2) {
|
|
902
|
+
const t = sep2.trim();
|
|
903
|
+
const left = t.startsWith(":");
|
|
904
|
+
const right = t.endsWith(":");
|
|
905
|
+
if (left && right) return "center";
|
|
906
|
+
if (right) return "right";
|
|
907
|
+
return "left";
|
|
908
|
+
}
|
|
909
|
+
function renderTable(tableLines, maxWidth) {
|
|
910
|
+
const header = parseCells(tableLines[0] ?? "");
|
|
911
|
+
const sepCells = parseCells(tableLines[1] ?? "");
|
|
912
|
+
const cols = header.length;
|
|
913
|
+
const aligns = [];
|
|
914
|
+
for (let c = 0; c < cols; c++) {
|
|
915
|
+
aligns.push(parseAlign(sepCells[c] ?? ""));
|
|
870
916
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
917
|
+
const dataRows = tableLines.slice(2).map(parseCells);
|
|
918
|
+
for (const row of dataRows) {
|
|
919
|
+
while (row.length < cols) row.push("");
|
|
920
|
+
row.length = cols;
|
|
921
|
+
}
|
|
922
|
+
const widths = computeWidths([header, ...dataRows], cols, maxWidth);
|
|
923
|
+
const lines = [];
|
|
924
|
+
lines.push(border("\u250C", "\u252C", "\u2510", widths));
|
|
925
|
+
lines.push(...renderRow(header, widths, aligns));
|
|
926
|
+
lines.push(border("\u251C", "\u253C", "\u2524", widths));
|
|
927
|
+
for (const row of dataRows) {
|
|
928
|
+
lines.push(...renderRow(row, widths, aligns));
|
|
875
929
|
}
|
|
930
|
+
lines.push(border("\u2514", "\u2534", "\u2518", widths));
|
|
931
|
+
return lines.join("\n");
|
|
876
932
|
}
|
|
877
|
-
function
|
|
878
|
-
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
const
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (bytes !== void 0) return [`${tag} \xB7 ${fmtBytes2(bytes)}`];
|
|
889
|
-
return [tag];
|
|
933
|
+
function computeWidths(allRows, cols, maxWidth) {
|
|
934
|
+
const overhead = 3 * cols + 1;
|
|
935
|
+
const avail = Math.max(cols * MIN_COL_WIDTH, maxWidth - overhead);
|
|
936
|
+
const natural = new Array(cols).fill(0);
|
|
937
|
+
for (const row of allRows) {
|
|
938
|
+
for (let c = 0; c < cols; c++) {
|
|
939
|
+
const cell = row[c] ?? "";
|
|
940
|
+
const w = longestWord(cell);
|
|
941
|
+
const total = cell.length;
|
|
942
|
+
natural[c] = Math.max(natural[c], total);
|
|
943
|
+
if (w > natural[c]) natural[c] = Math.min(total + 1, w);
|
|
890
944
|
}
|
|
891
945
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
946
|
+
const sumNatural = natural.reduce((s, n) => s + n, 0);
|
|
947
|
+
if (sumNatural <= avail) return natural;
|
|
948
|
+
const widths = natural.slice();
|
|
949
|
+
let sum = sumNatural;
|
|
950
|
+
while (sum > avail) {
|
|
951
|
+
let maxIdx = -1;
|
|
952
|
+
let maxVal = MIN_COL_WIDTH;
|
|
953
|
+
for (let i = 0; i < cols; i++) {
|
|
954
|
+
const w = widths[i];
|
|
955
|
+
if (w > maxVal) {
|
|
956
|
+
maxVal = w;
|
|
957
|
+
maxIdx = i;
|
|
958
|
+
}
|
|
897
959
|
}
|
|
960
|
+
if (maxIdx < 0) break;
|
|
961
|
+
widths[maxIdx]--;
|
|
962
|
+
sum--;
|
|
898
963
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
if (toolName === "replace") {
|
|
921
|
-
if (json && typeof json === "object") {
|
|
922
|
-
const o = json;
|
|
923
|
-
const files = numOf(o["files_modified"]);
|
|
924
|
-
const reps = numOf(o["total_replacements"]);
|
|
925
|
-
if (files !== void 0 && reps !== void 0) {
|
|
926
|
-
return [
|
|
927
|
-
`${reps} replacement${reps === 1 ? "" : "s"} in ${files} file${files === 1 ? "" : "s"}`
|
|
928
|
-
];
|
|
929
|
-
}
|
|
964
|
+
return widths;
|
|
965
|
+
}
|
|
966
|
+
var MIN_COL_WIDTH = 4;
|
|
967
|
+
function longestWord(s) {
|
|
968
|
+
let max = 0;
|
|
969
|
+
for (const w of s.split(/\s+/)) if (w.length > max) max = w.length;
|
|
970
|
+
return max;
|
|
971
|
+
}
|
|
972
|
+
function border(left, mid, right, widths) {
|
|
973
|
+
return left + widths.map((w) => "\u2500".repeat(w + 2)).join(mid) + right;
|
|
974
|
+
}
|
|
975
|
+
function renderRow(cells, widths, aligns) {
|
|
976
|
+
const wrapped = cells.map((c, i) => wrapCell(c, widths[i] ?? MIN_COL_WIDTH));
|
|
977
|
+
const height = Math.max(1, ...wrapped.map((w) => w.length));
|
|
978
|
+
const out = [];
|
|
979
|
+
for (let line = 0; line < height; line++) {
|
|
980
|
+
const parts = [];
|
|
981
|
+
for (let c = 0; c < widths.length; c++) {
|
|
982
|
+
const w = widths[c] ?? MIN_COL_WIDTH;
|
|
983
|
+
const text = wrapped[c]?.[line] ?? "";
|
|
984
|
+
parts.push(padCell(text, w, aligns[c] ?? "left"));
|
|
930
985
|
}
|
|
986
|
+
out.push("\u2502 " + parts.join(" \u2502 ") + " \u2502");
|
|
931
987
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
if (truncated) head.push("truncated");
|
|
945
|
-
return head.length > 0 ? [head.join(" \xB7 ")] : [];
|
|
988
|
+
return out;
|
|
989
|
+
}
|
|
990
|
+
function wrapCell(text, width) {
|
|
991
|
+
if (text.length <= width) return [text];
|
|
992
|
+
const out = [];
|
|
993
|
+
const words = text.split(/(\s+)/);
|
|
994
|
+
let cur = "";
|
|
995
|
+
for (const word of words) {
|
|
996
|
+
if (!word) continue;
|
|
997
|
+
if (cur.length + word.length <= width) {
|
|
998
|
+
cur += word;
|
|
999
|
+
continue;
|
|
946
1000
|
}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
if (json && typeof json === "object") {
|
|
951
|
-
const o = json;
|
|
952
|
-
const bytes = numOf(o["bytes"]);
|
|
953
|
-
if (bytes !== void 0) return [`${fmtBytes2(bytes)} read`];
|
|
1001
|
+
if (cur) {
|
|
1002
|
+
out.push(cur.trimEnd());
|
|
1003
|
+
cur = "";
|
|
954
1004
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1005
|
+
if (word.length > width) {
|
|
1006
|
+
let rest = word;
|
|
1007
|
+
while (rest.length > width) {
|
|
1008
|
+
out.push(rest.slice(0, width));
|
|
1009
|
+
rest = rest.slice(width);
|
|
959
1010
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
return [`${head} \xB7 ${tail} \xB7 ${fmtBytes2(text.length)}`];
|
|
1011
|
+
cur = rest;
|
|
1012
|
+
} else if (!/^\s+$/.test(word)) {
|
|
1013
|
+
cur = word;
|
|
964
1014
|
}
|
|
965
1015
|
}
|
|
966
|
-
if (
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
];
|
|
977
|
-
const firstHit = matches && matches.length > 0 ? formatMatchHit(matches[0]) : void 0;
|
|
978
|
-
if (firstHit) lines.push(firstHit);
|
|
979
|
-
return lines;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
1016
|
+
if (cur) out.push(cur.trimEnd());
|
|
1017
|
+
return out.length === 0 ? [""] : out;
|
|
1018
|
+
}
|
|
1019
|
+
function padCell(text, width, align) {
|
|
1020
|
+
if (text.length >= width) return text.slice(0, width);
|
|
1021
|
+
const pad = width - text.length;
|
|
1022
|
+
if (align === "right") return " ".repeat(pad) + text;
|
|
1023
|
+
if (align === "center") {
|
|
1024
|
+
const l = Math.floor(pad / 2);
|
|
1025
|
+
return " ".repeat(l) + text + " ".repeat(pad - l);
|
|
982
1026
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1027
|
+
return text + " ".repeat(pad);
|
|
1028
|
+
}
|
|
1029
|
+
function History({ entries, streamingText, toolStream }) {
|
|
1030
|
+
const { stdout } = useStdout();
|
|
1031
|
+
const termWidth = stdout?.columns ?? 80;
|
|
1032
|
+
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
1033
|
+
const toolTail = toolStream?.text ? tailForDisplay(toolStream.text, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
1034
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1035
|
+
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth }) }, entry.id) }),
|
|
1036
|
+
tail ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
1037
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1038
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "ASSISTANT: " }),
|
|
1039
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "(streaming...)" })
|
|
1040
|
+
] }),
|
|
1041
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: tail })
|
|
1042
|
+
] }) : null,
|
|
1043
|
+
toolTail ? /* @__PURE__ */ jsx(
|
|
1044
|
+
ToolStreamBox,
|
|
1045
|
+
{
|
|
1046
|
+
name: toolStream.name,
|
|
1047
|
+
text: toolTail,
|
|
1048
|
+
startedAt: toolStream.startedAt,
|
|
1049
|
+
termWidth
|
|
1004
1050
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1051
|
+
) : null
|
|
1052
|
+
] });
|
|
1053
|
+
}
|
|
1054
|
+
var MAX_STREAM_DISPLAY_CHARS = 480;
|
|
1055
|
+
var MAX_STREAM_LINES = 8;
|
|
1056
|
+
function ToolStreamBox({
|
|
1057
|
+
name,
|
|
1058
|
+
text,
|
|
1059
|
+
startedAt,
|
|
1060
|
+
termWidth
|
|
1061
|
+
}) {
|
|
1062
|
+
const [tick, setTick] = useState(0);
|
|
1063
|
+
useEffect(() => {
|
|
1064
|
+
const t = setInterval(() => setTick((n) => n + 1), 500);
|
|
1065
|
+
return () => clearInterval(t);
|
|
1066
|
+
}, []);
|
|
1067
|
+
const elapsedMs = Date.now() - startedAt;
|
|
1068
|
+
const lines = text.split("\n");
|
|
1069
|
+
const totalLines = lines.length;
|
|
1070
|
+
const hidden = Math.max(0, totalLines - MAX_STREAM_LINES);
|
|
1071
|
+
const visible = hidden > 0 ? lines.slice(hidden) : lines;
|
|
1072
|
+
const contentWidth = Math.max(20, Math.min(termWidth - 4, 100));
|
|
1073
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 0, children: [
|
|
1074
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1075
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25C6 " }),
|
|
1076
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: name }),
|
|
1077
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration2(elapsedMs)}` }),
|
|
1078
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
1079
|
+
] }),
|
|
1080
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
1081
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: ` \u2026 ${hidden} more line${hidden === 1 ? "" : "s"} above` }) : null,
|
|
1082
|
+
visible.map((line, i) => {
|
|
1083
|
+
const key = i;
|
|
1084
|
+
const trimmed = line.length > contentWidth ? `${line.slice(0, contentWidth - 1)}\u2026` : line;
|
|
1085
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: trimmed || " " }, key);
|
|
1086
|
+
})
|
|
1087
|
+
] })
|
|
1088
|
+
] });
|
|
1089
|
+
}
|
|
1090
|
+
function tailForDisplay(text, maxChars) {
|
|
1091
|
+
if (text.length <= maxChars) return text;
|
|
1092
|
+
const cut = text.length - maxChars;
|
|
1093
|
+
const nl = text.indexOf("\n", cut);
|
|
1094
|
+
if (nl !== -1 && nl < cut + 80) {
|
|
1095
|
+
return `\u2026 ${text.slice(nl + 1)}`;
|
|
1010
1096
|
}
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
const
|
|
1019
|
-
if (
|
|
1020
|
-
if (ct) head.push(ct.split(";")[0] ?? ct);
|
|
1021
|
-
if (content) head.push(fmtBytes2(Buffer.byteLength(content, "utf8")));
|
|
1022
|
-
const lines = [];
|
|
1023
|
-
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1024
|
-
if (url && status !== void 0 && (status < 200 || status >= 400)) {
|
|
1025
|
-
lines.push(shortenPath(url, 70));
|
|
1026
|
-
}
|
|
1027
|
-
if (lines.length > 0) return lines;
|
|
1097
|
+
return `\u2026 ${text.slice(cut)}`;
|
|
1098
|
+
}
|
|
1099
|
+
function DiffBlock({ rows, hidden }) {
|
|
1100
|
+
let gutterWidth = 1;
|
|
1101
|
+
for (const r of rows) {
|
|
1102
|
+
const n = r.kind === "del" ? r.oldLine : r.newLine;
|
|
1103
|
+
if (typeof n === "number") {
|
|
1104
|
+
const w = String(n).length;
|
|
1105
|
+
if (w > gutterWidth) gutterWidth = w;
|
|
1028
1106
|
}
|
|
1029
1107
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
const head = [];
|
|
1037
|
-
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1038
|
-
const stdoutLines = countLines(stdout);
|
|
1039
|
-
const stderrLines = countLines(stderr);
|
|
1040
|
-
const lparts = [];
|
|
1041
|
-
if (stdoutLines > 0) lparts.push(`${stdoutLines} out`);
|
|
1042
|
-
if (stderrLines > 0) lparts.push(`${stderrLines} err`);
|
|
1043
|
-
if (lparts.length > 0) head.push(lparts.join(" \xB7 "));
|
|
1044
|
-
const lines = [];
|
|
1045
|
-
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1046
|
-
const preview = firstNonEmpty(stdout) ?? firstNonEmpty(stderr);
|
|
1047
|
-
if (preview) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1048
|
-
if (lines.length > 0) return lines;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
if (toolName === "lint") {
|
|
1052
|
-
if (json && typeof json === "object") {
|
|
1053
|
-
const o = json;
|
|
1054
|
-
const linter = stringOf(o["linter"]);
|
|
1055
|
-
const files = numOf(o["files_checked"]);
|
|
1056
|
-
const errors = numOf(o["errors"]) ?? 0;
|
|
1057
|
-
const warnings = numOf(o["warnings"]) ?? 0;
|
|
1058
|
-
const fix = o["fix_applied"] === true;
|
|
1059
|
-
const head = [];
|
|
1060
|
-
if (linter && linter !== "none") head.push(linter);
|
|
1061
|
-
head.push(`${errors} error${errors === 1 ? "" : "s"}`);
|
|
1062
|
-
head.push(`${warnings} warning${warnings === 1 ? "" : "s"}`);
|
|
1063
|
-
if (files !== void 0) head.push(`${files} file${files === 1 ? "" : "s"}`);
|
|
1064
|
-
if (fix) head.push("fixed");
|
|
1065
|
-
return [head.join(" \xB7 ")];
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
if (toolName === "format") {
|
|
1069
|
-
if (json && typeof json === "object") {
|
|
1070
|
-
const o = json;
|
|
1071
|
-
const fixer = stringOf(o["fixer"]);
|
|
1072
|
-
const checked = numOf(o["files_checked"]);
|
|
1073
|
-
const changed = numOf(o["files_changed"]);
|
|
1074
|
-
const head = [];
|
|
1075
|
-
if (fixer && fixer !== "none") head.push(fixer);
|
|
1076
|
-
if (changed !== void 0 && checked !== void 0) {
|
|
1077
|
-
head.push(`${changed}/${checked} changed`);
|
|
1078
|
-
} else if (changed !== void 0) {
|
|
1079
|
-
head.push(`${changed} changed`);
|
|
1108
|
+
const blank = " ".repeat(gutterWidth);
|
|
1109
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, marginTop: 0, children: [
|
|
1110
|
+
rows.map((row, i) => {
|
|
1111
|
+
const key = i;
|
|
1112
|
+
if (row.kind === "hunk") {
|
|
1113
|
+
return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: row.text }, key);
|
|
1080
1114
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
}
|
|
1084
|
-
if (toolName === "typecheck") {
|
|
1085
|
-
if (json && typeof json === "object") {
|
|
1086
|
-
const o = json;
|
|
1087
|
-
const exit = numOf(o["exit_code"]) ?? numOf(o["exitCode"]);
|
|
1088
|
-
const errors = numOf(o["errors"]);
|
|
1089
|
-
const head = [];
|
|
1090
|
-
if (errors !== void 0) head.push(`${errors} error${errors === 1 ? "" : "s"}`);
|
|
1091
|
-
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1092
|
-
const stdout = stringOf(o["output"]) ?? stringOf(o["stdout"]) ?? "";
|
|
1093
|
-
const lines = [];
|
|
1094
|
-
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1095
|
-
const preview = firstNonEmpty(stdout);
|
|
1096
|
-
if (preview && (!errors || errors > 0)) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1097
|
-
if (lines.length > 0) return lines;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
if (toolName === "test") {
|
|
1101
|
-
if (json && typeof json === "object") {
|
|
1102
|
-
const o = json;
|
|
1103
|
-
const runner = stringOf(o["runner"]);
|
|
1104
|
-
const total = numOf(o["tests_run"]) ?? 0;
|
|
1105
|
-
const passed = numOf(o["passed"]) ?? 0;
|
|
1106
|
-
const failed = numOf(o["failed"]) ?? 0;
|
|
1107
|
-
const duration = numOf(o["duration_ms"]);
|
|
1108
|
-
const head = [];
|
|
1109
|
-
if (runner && runner !== "none") head.push(runner);
|
|
1110
|
-
head.push(`${passed}/${total} passed`);
|
|
1111
|
-
if (failed > 0) head.push(`${failed} failed`);
|
|
1112
|
-
if (duration !== void 0) head.push(fmtDuration2(duration));
|
|
1113
|
-
return [head.join(" \xB7 ")];
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
if (toolName === "audit") {
|
|
1117
|
-
if (json && typeof json === "object") {
|
|
1118
|
-
const o = json;
|
|
1119
|
-
const total = numOf(o["total"]) ?? 0;
|
|
1120
|
-
const summary = stringOf(o["summary"]);
|
|
1121
|
-
if (total === 0) return ["no vulnerabilities"];
|
|
1122
|
-
const head = `${total} vulnerabilit${total === 1 ? "y" : "ies"}`;
|
|
1123
|
-
return summary && summary.toLowerCase() !== head.toLowerCase() ? [head, truncMid(summary, OUT_BUDGET)] : [head];
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
if (toolName === "outdated") {
|
|
1127
|
-
if (json && typeof json === "object") {
|
|
1128
|
-
const o = json;
|
|
1129
|
-
const total = numOf(o["total"]) ?? 0;
|
|
1130
|
-
const pkgs = Array.isArray(o["packages"]) ? o["packages"] : void 0;
|
|
1131
|
-
if (total === 0) return ["all up to date"];
|
|
1132
|
-
const lines = [`${total} outdated`];
|
|
1133
|
-
if (pkgs && pkgs.length > 0) {
|
|
1134
|
-
const first = pkgs[0];
|
|
1135
|
-
if (first && typeof first === "object") {
|
|
1136
|
-
const p = first;
|
|
1137
|
-
const name = stringOf(p["name"]) ?? stringOf(p["package"]);
|
|
1138
|
-
const cur = stringOf(p["current"]);
|
|
1139
|
-
const wanted = stringOf(p["wanted"]) ?? stringOf(p["latest"]);
|
|
1140
|
-
if (name && cur && wanted) lines.push(`${name}: ${cur} \u2192 ${wanted}`);
|
|
1141
|
-
else if (name) lines.push(name);
|
|
1142
|
-
}
|
|
1115
|
+
if (row.kind === "meta") {
|
|
1116
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${blank} ${row.text}` }, key);
|
|
1143
1117
|
}
|
|
1144
|
-
|
|
1118
|
+
const lnNumber = row.kind === "del" ? row.oldLine : row.newLine;
|
|
1119
|
+
const lnText = typeof lnNumber === "number" ? String(lnNumber).padStart(gutterWidth, " ") : blank;
|
|
1120
|
+
if (row.kind === "ctx") {
|
|
1121
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ${row.text}` }, key);
|
|
1122
|
+
}
|
|
1123
|
+
const bg = row.kind === "add" ? "greenBright" : "redBright";
|
|
1124
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
1125
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${lnText} ` }),
|
|
1126
|
+
/* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: "black", children: row.text })
|
|
1127
|
+
] }, key);
|
|
1128
|
+
}),
|
|
1129
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${blank} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
|
|
1130
|
+
] });
|
|
1131
|
+
}
|
|
1132
|
+
function Entry({
|
|
1133
|
+
entry,
|
|
1134
|
+
termWidth
|
|
1135
|
+
}) {
|
|
1136
|
+
switch (entry.kind) {
|
|
1137
|
+
case "user":
|
|
1138
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
1139
|
+
/* @__PURE__ */ jsx(Text, { color: entry.queued ? "yellow" : "cyan", children: entry.queued ? "\u231B" : "\u203A" }),
|
|
1140
|
+
" ",
|
|
1141
|
+
/* @__PURE__ */ jsx(Text, { dimColor: entry.queued ?? false, children: entry.text }),
|
|
1142
|
+
entry.queued ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (queued)" }) : null
|
|
1143
|
+
] });
|
|
1144
|
+
case "assistant":
|
|
1145
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
1146
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "ASSISTANT: " }) }),
|
|
1147
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: renderMarkdownTables(entry.text, termWidth) })
|
|
1148
|
+
] });
|
|
1149
|
+
case "tool": {
|
|
1150
|
+
const argSummary = formatToolArgs(entry.name, entry.input);
|
|
1151
|
+
const outLines = formatToolOutput(
|
|
1152
|
+
entry.name,
|
|
1153
|
+
entry.output,
|
|
1154
|
+
entry.ok,
|
|
1155
|
+
entry.outputBytes,
|
|
1156
|
+
entry.outputLines
|
|
1157
|
+
);
|
|
1158
|
+
const diff = entry.ok ? extractDiffPreview(entry.name, entry.output) : void 0;
|
|
1159
|
+
const sizeChip = (() => {
|
|
1160
|
+
if (!entry.ok) return "";
|
|
1161
|
+
const parts = [];
|
|
1162
|
+
if (entry.outputLines !== void 0 && entry.outputLines > 0) {
|
|
1163
|
+
parts.push(`${entry.outputLines} L`);
|
|
1164
|
+
}
|
|
1165
|
+
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
1166
|
+
parts.push(fmtBytes2(entry.outputBytes));
|
|
1167
|
+
}
|
|
1168
|
+
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
1169
|
+
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
1170
|
+
}
|
|
1171
|
+
return parts.join(" \xB7 ");
|
|
1172
|
+
})();
|
|
1173
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1174
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1175
|
+
/* @__PURE__ */ jsx(Text, { color: entry.ok ? "green" : "red", children: entry.ok ? "\u25CF" : "\u2717" }),
|
|
1176
|
+
" ",
|
|
1177
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: entry.name }),
|
|
1178
|
+
argSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1179
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1180
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: argSummary })
|
|
1181
|
+
] }) : null,
|
|
1182
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration2(entry.durationMs)}` }),
|
|
1183
|
+
sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
|
|
1184
|
+
] }),
|
|
1185
|
+
outLines.map((line, i) => (
|
|
1186
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: tool output lines are static, index is stable
|
|
1187
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1188
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
|
|
1189
|
+
/* @__PURE__ */ jsx(
|
|
1190
|
+
Text,
|
|
1191
|
+
{
|
|
1192
|
+
color: !entry.ok || line.startsWith("!") ? "red" : void 0,
|
|
1193
|
+
dimColor: entry.ok && !line.startsWith("!"),
|
|
1194
|
+
children: line
|
|
1195
|
+
}
|
|
1196
|
+
)
|
|
1197
|
+
] }, i)
|
|
1198
|
+
)),
|
|
1199
|
+
diff ? /* @__PURE__ */ jsx(DiffBlock, { rows: diff.rows, hidden: diff.hidden }) : null
|
|
1200
|
+
] });
|
|
1145
1201
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1202
|
+
case "info":
|
|
1203
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.text });
|
|
1204
|
+
case "warn":
|
|
1205
|
+
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: entry.text });
|
|
1206
|
+
case "error":
|
|
1207
|
+
return /* @__PURE__ */ jsx(Text, { color: "red", children: entry.text });
|
|
1208
|
+
case "turn-summary":
|
|
1209
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.text });
|
|
1210
|
+
case "confirm":
|
|
1211
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1, children: [
|
|
1212
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", children: [
|
|
1213
|
+
"\u26A0 Confirm: ",
|
|
1214
|
+
entry.toolName
|
|
1215
|
+
] }),
|
|
1216
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Waiting for y / n / a / d..." })
|
|
1217
|
+
] });
|
|
1218
|
+
case "banner":
|
|
1219
|
+
return /* @__PURE__ */ jsx(Banner, { entry });
|
|
1220
|
+
case "subagent": {
|
|
1221
|
+
const lines = entry.text.split("\n");
|
|
1222
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1223
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1224
|
+
/* @__PURE__ */ jsx(Text, { color: entry.agentColor, bold: true, children: `[${entry.agentLabel}]` }),
|
|
1225
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1226
|
+
/* @__PURE__ */ jsx(Text, { color: entry.agentColor, children: entry.icon }),
|
|
1227
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1228
|
+
/* @__PURE__ */ jsx(Text, { children: lines[0] ?? "" }),
|
|
1229
|
+
entry.detail ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1230
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
1231
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.detail })
|
|
1232
|
+
] }) : null
|
|
1233
|
+
] }),
|
|
1234
|
+
lines.slice(1).map((line, i) => (
|
|
1235
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: stable line index
|
|
1236
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1237
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
1238
|
+
/* @__PURE__ */ jsx(Text, { children: line })
|
|
1239
|
+
] }, i)
|
|
1240
|
+
))
|
|
1241
|
+
] });
|
|
1158
1242
|
}
|
|
1159
1243
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1244
|
+
}
|
|
1245
|
+
function Banner({
|
|
1246
|
+
entry
|
|
1247
|
+
}) {
|
|
1248
|
+
const cwdShort = shortenPath(entry.cwd, 48);
|
|
1249
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
1250
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1251
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
1252
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "WrongStack" }),
|
|
1253
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " v" }),
|
|
1254
|
+
/* @__PURE__ */ jsx(Text, { children: entry.version })
|
|
1255
|
+
] }),
|
|
1256
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: " Built on the wrong stack. Shipped anyway." }),
|
|
1257
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1258
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " provider " }),
|
|
1259
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1260
|
+
entry.provider,
|
|
1261
|
+
"/",
|
|
1262
|
+
entry.model
|
|
1263
|
+
] })
|
|
1264
|
+
] }),
|
|
1265
|
+
entry.family ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1266
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " family " }),
|
|
1267
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.family })
|
|
1268
|
+
] }) : null,
|
|
1269
|
+
entry.keyTail ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1270
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " key " }),
|
|
1271
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25CF\u25CF\u25CF\u2026" }),
|
|
1272
|
+
/* @__PURE__ */ jsx(Text, { children: entry.keyTail })
|
|
1273
|
+
] }) : null,
|
|
1274
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1275
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " cwd " }),
|
|
1276
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: cwdShort })
|
|
1277
|
+
] }),
|
|
1278
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1279
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: " hints " }),
|
|
1280
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/help \xB7 /init \xB7 /memory \xB7 /queue \xB7 /exit" })
|
|
1281
|
+
] })
|
|
1282
|
+
] });
|
|
1283
|
+
}
|
|
1284
|
+
function shortenPath(p, max) {
|
|
1285
|
+
if (p.length <= max) return p;
|
|
1286
|
+
return `\u2026${p.slice(p.length - (max - 1))}`;
|
|
1287
|
+
}
|
|
1288
|
+
function fmtTok2(n) {
|
|
1289
|
+
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
1290
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
1291
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
1292
|
+
return String(n);
|
|
1293
|
+
}
|
|
1294
|
+
function fmtDuration2(ms) {
|
|
1295
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1296
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1297
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
1298
|
+
return `${Math.floor(totalSec / 60)}m${totalSec % 60}s`;
|
|
1299
|
+
}
|
|
1300
|
+
var ARG_BUDGET = 60;
|
|
1301
|
+
var OUT_BUDGET = 80;
|
|
1302
|
+
function formatToolArgs(toolName, input) {
|
|
1303
|
+
if (!input || typeof input !== "object") return "";
|
|
1304
|
+
const obj = input;
|
|
1305
|
+
switch (toolName) {
|
|
1306
|
+
case "read":
|
|
1307
|
+
case "write":
|
|
1308
|
+
case "edit":
|
|
1309
|
+
case "patch":
|
|
1310
|
+
case "document":
|
|
1311
|
+
case "list_dir":
|
|
1312
|
+
case "ls":
|
|
1313
|
+
case "tree": {
|
|
1314
|
+
const p = stringOf(obj["path"]) ?? stringOf(obj["file"]);
|
|
1315
|
+
return p ? shortenPath(p, ARG_BUDGET) : "";
|
|
1316
|
+
}
|
|
1317
|
+
case "grep":
|
|
1318
|
+
case "search":
|
|
1319
|
+
case "replace": {
|
|
1320
|
+
const pat = stringOf(obj["pattern"]) ?? stringOf(obj["query"]);
|
|
1321
|
+
const scope = stringOf(obj["path"]) ?? stringOf(obj["glob"]);
|
|
1322
|
+
const head = pat ? `"${truncMid(pat, 36)}"` : "";
|
|
1323
|
+
const tail = scope ? ` in ${shortenPath(scope, 28)}` : "";
|
|
1324
|
+
return `${head}${tail}` || (stringOf(obj["command"]) ?? "");
|
|
1325
|
+
}
|
|
1326
|
+
case "glob": {
|
|
1327
|
+
const pat = stringOf(obj["pattern"]) ?? stringOf(obj["glob"]);
|
|
1328
|
+
return pat ? `"${truncMid(pat, ARG_BUDGET - 2)}"` : "";
|
|
1329
|
+
}
|
|
1330
|
+
case "bash":
|
|
1331
|
+
case "shell":
|
|
1332
|
+
case "exec":
|
|
1333
|
+
case "install":
|
|
1334
|
+
case "git": {
|
|
1335
|
+
const cmd = stringOf(obj["command"]) ?? stringOf(obj["args"]);
|
|
1336
|
+
return cmd ? truncMid(cmd, ARG_BUDGET) : "";
|
|
1337
|
+
}
|
|
1338
|
+
case "diff": {
|
|
1339
|
+
const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
|
|
1340
|
+
if (files && files.length > 0) {
|
|
1341
|
+
const head = stringOf(files[0]) ?? "";
|
|
1342
|
+
const rest = files.length > 1 ? ` (+${files.length - 1})` : "";
|
|
1343
|
+
return head ? `${shortenPath(head, 50)}${rest}` : "";
|
|
1344
|
+
}
|
|
1345
|
+
const mode = stringOf(obj["mode"]);
|
|
1346
|
+
return mode ? `mode: ${mode}` : "";
|
|
1347
|
+
}
|
|
1348
|
+
case "fetch":
|
|
1349
|
+
case "webfetch":
|
|
1350
|
+
case "web_fetch": {
|
|
1351
|
+
const u = stringOf(obj["url"]);
|
|
1352
|
+
return u ? truncMid(u, ARG_BUDGET) : "";
|
|
1353
|
+
}
|
|
1354
|
+
case "todo": {
|
|
1355
|
+
const list = obj["todos"];
|
|
1356
|
+
if (Array.isArray(list)) return `${list.length} item${list.length === 1 ? "" : "s"}`;
|
|
1357
|
+
return "";
|
|
1358
|
+
}
|
|
1359
|
+
case "lint":
|
|
1360
|
+
case "format":
|
|
1361
|
+
case "typecheck":
|
|
1362
|
+
case "test":
|
|
1363
|
+
case "audit":
|
|
1364
|
+
case "outdated": {
|
|
1365
|
+
const files = obj["files"];
|
|
1366
|
+
if (Array.isArray(files) && files.length > 0) {
|
|
1367
|
+
const first = stringOf(files[0]);
|
|
1368
|
+
const more = files.length > 1 ? ` (+${files.length - 1})` : "";
|
|
1369
|
+
return first ? `${shortenPath(first, 50)}${more}` : `${files.length} files`;
|
|
1370
|
+
}
|
|
1371
|
+
const filter = stringOf(obj["filter"]) ?? stringOf(obj["pattern"]);
|
|
1372
|
+
return filter ? `"${truncMid(filter, ARG_BUDGET - 2)}"` : "";
|
|
1373
|
+
}
|
|
1374
|
+
case "json": {
|
|
1375
|
+
const file = stringOf(obj["file"]);
|
|
1376
|
+
const q = stringOf(obj["query"]);
|
|
1377
|
+
if (file) return q ? `${shortenPath(file, 40)} ${q}` : shortenPath(file, ARG_BUDGET);
|
|
1378
|
+
return q ? truncMid(q, ARG_BUDGET) : "";
|
|
1379
|
+
}
|
|
1380
|
+
case "scaffold": {
|
|
1381
|
+
const tmpl = stringOf(obj["template"]) ?? stringOf(obj["type"]);
|
|
1382
|
+
const name = stringOf(obj["name"]);
|
|
1383
|
+
if (tmpl && name) return `${tmpl} \u2192 ${truncMid(name, ARG_BUDGET - tmpl.length - 4)}`;
|
|
1384
|
+
return name ?? tmpl ?? "";
|
|
1385
|
+
}
|
|
1386
|
+
case "remember":
|
|
1387
|
+
case "forget":
|
|
1388
|
+
case "memory": {
|
|
1389
|
+
const key = stringOf(obj["key"]) ?? stringOf(obj["name"]);
|
|
1390
|
+
return key ? truncMid(key, ARG_BUDGET) : "";
|
|
1391
|
+
}
|
|
1392
|
+
case "mode": {
|
|
1393
|
+
const m = stringOf(obj["mode"]) ?? stringOf(obj["name"]);
|
|
1394
|
+
return m ? truncMid(m, ARG_BUDGET) : "";
|
|
1395
|
+
}
|
|
1396
|
+
case "logs": {
|
|
1397
|
+
const target = stringOf(obj["target"]) ?? stringOf(obj["service"]) ?? stringOf(obj["path"]);
|
|
1398
|
+
return target ? truncMid(target, ARG_BUDGET) : "";
|
|
1171
1399
|
}
|
|
1172
1400
|
}
|
|
1173
|
-
|
|
1401
|
+
for (const key of ["path", "file", "url", "name", "query", "pattern", "command"]) {
|
|
1402
|
+
const v = stringOf(obj[key]);
|
|
1403
|
+
if (v) return truncMid(v, ARG_BUDGET);
|
|
1404
|
+
}
|
|
1405
|
+
try {
|
|
1406
|
+
return truncMid(JSON.stringify(obj), ARG_BUDGET);
|
|
1407
|
+
} catch {
|
|
1408
|
+
return "";
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
1412
|
+
if (!output) return ok ? [] : ["failed"];
|
|
1413
|
+
const text = output.trim();
|
|
1414
|
+
if (!text) return ok ? [] : ["failed"];
|
|
1415
|
+
const json = tryParseJson(text);
|
|
1416
|
+
if (toolName === "write") {
|
|
1174
1417
|
if (json && typeof json === "object") {
|
|
1175
1418
|
const o = json;
|
|
1176
|
-
const
|
|
1177
|
-
const
|
|
1178
|
-
const
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
if (added !== void 0) head.push(`+${added}`);
|
|
1182
|
-
if (removed !== void 0) head.push(`-${removed}`);
|
|
1183
|
-
const stdout = stringOf(o["stdout"]) ?? stringOf(o["output"]) ?? "";
|
|
1184
|
-
const lines = [];
|
|
1185
|
-
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1186
|
-
const preview = firstNonEmpty(stdout);
|
|
1187
|
-
if (preview) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1188
|
-
if (lines.length > 0) return lines;
|
|
1419
|
+
const bytes = numOf(o["bytes_written"]) ?? numOf(o["bytes"]);
|
|
1420
|
+
const created = o["created"] === true;
|
|
1421
|
+
const tag = created ? "created" : "updated";
|
|
1422
|
+
if (bytes !== void 0) return [`${tag} \xB7 ${fmtBytes2(bytes)}`];
|
|
1423
|
+
return [tag];
|
|
1189
1424
|
}
|
|
1190
1425
|
}
|
|
1191
|
-
if (toolName === "
|
|
1426
|
+
if (toolName === "edit") {
|
|
1192
1427
|
if (json && typeof json === "object") {
|
|
1193
1428
|
const o = json;
|
|
1194
|
-
const
|
|
1195
|
-
|
|
1196
|
-
const parts = [];
|
|
1197
|
-
if (created !== void 0) parts.push(`${created.length} created`);
|
|
1198
|
-
if (skipped !== void 0 && skipped.length > 0) parts.push(`${skipped.length} skipped`);
|
|
1199
|
-
if (parts.length > 0) return [parts.join(" \xB7 ")];
|
|
1429
|
+
const reps = numOf(o["replacements"]);
|
|
1430
|
+
if (reps !== void 0) return [`${reps} replacement${reps === 1 ? "" : "s"}`];
|
|
1200
1431
|
}
|
|
1201
1432
|
}
|
|
1202
|
-
if (toolName === "
|
|
1203
|
-
return ok ? [toolName === "forget" ? "removed" : "saved"] : [text.split("\n")[0] ?? ""];
|
|
1204
|
-
}
|
|
1205
|
-
if (toolName === "mode") {
|
|
1433
|
+
if (toolName === "patch") {
|
|
1206
1434
|
if (json && typeof json === "object") {
|
|
1207
1435
|
const o = json;
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1436
|
+
const applied = numOf(o["applied"]);
|
|
1437
|
+
const rejected = numOf(o["rejected"]);
|
|
1438
|
+
const files = Array.isArray(o["files"]) ? o["files"] : void 0;
|
|
1439
|
+
const lines = [];
|
|
1440
|
+
if (applied !== void 0 || rejected !== void 0) {
|
|
1441
|
+
const parts = [];
|
|
1442
|
+
if (applied !== void 0) parts.push(`${applied} applied`);
|
|
1443
|
+
if (rejected !== void 0 && rejected > 0) parts.push(`${rejected} rejected`);
|
|
1444
|
+
lines.push(parts.join(" \xB7 "));
|
|
1445
|
+
}
|
|
1446
|
+
if (files && files.length > 0) {
|
|
1447
|
+
const first = stringOf(files[0]) ?? "";
|
|
1448
|
+
const more = files.length > 1 ? ` (+${files.length - 1})` : "";
|
|
1449
|
+
lines.push(`${shortenPath(first, 60)}${more}`);
|
|
1450
|
+
}
|
|
1451
|
+
if (lines.length > 0) return lines;
|
|
1210
1452
|
}
|
|
1211
1453
|
}
|
|
1212
|
-
if (toolName === "
|
|
1454
|
+
if (toolName === "replace") {
|
|
1213
1455
|
if (json && typeof json === "object") {
|
|
1214
1456
|
const o = json;
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1217
|
-
if (
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
if (firstHit) lines.push(firstHit);
|
|
1222
|
-
return lines;
|
|
1457
|
+
const files = numOf(o["files_modified"]);
|
|
1458
|
+
const reps = numOf(o["total_replacements"]);
|
|
1459
|
+
if (files !== void 0 && reps !== void 0) {
|
|
1460
|
+
return [
|
|
1461
|
+
`${reps} replacement${reps === 1 ? "" : "s"} in ${files} file${files === 1 ? "" : "s"}`
|
|
1462
|
+
];
|
|
1223
1463
|
}
|
|
1224
1464
|
}
|
|
1225
1465
|
}
|
|
1226
|
-
if (toolName === "
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
var GENERIC_BUDGET = 240;
|
|
1241
|
-
function summarizeJsonObject(obj) {
|
|
1242
|
-
const keys = Object.keys(obj);
|
|
1243
|
-
if (keys.length === 0) return null;
|
|
1244
|
-
const priority = [
|
|
1245
|
-
"ok",
|
|
1246
|
-
"status",
|
|
1247
|
-
"timedOut",
|
|
1248
|
-
"stopReason",
|
|
1249
|
-
"reason",
|
|
1250
|
-
"error",
|
|
1251
|
-
"message",
|
|
1252
|
-
"result",
|
|
1253
|
-
"summary",
|
|
1254
|
-
"iterations",
|
|
1255
|
-
"toolCalls",
|
|
1256
|
-
"durationMs",
|
|
1257
|
-
"subagentId",
|
|
1258
|
-
"taskId"
|
|
1259
|
-
];
|
|
1260
|
-
const ordered = [
|
|
1261
|
-
...priority.filter((k) => keys.includes(k)),
|
|
1262
|
-
...keys.filter((k) => !priority.includes(k))
|
|
1263
|
-
];
|
|
1264
|
-
const parts = [];
|
|
1265
|
-
let used = 0;
|
|
1266
|
-
for (const key of ordered) {
|
|
1267
|
-
const v = obj[key];
|
|
1268
|
-
if (v === void 0 || v === null) continue;
|
|
1269
|
-
const rendered = typeof v === "string" ? `${key}="${truncMid(v.replace(/\s+/g, " "), 80)}"` : typeof v === "number" || typeof v === "boolean" ? `${key}=${v}` : Array.isArray(v) ? `${key}=[${v.length}]` : `${key}={\u2026}`;
|
|
1270
|
-
if (used + rendered.length > GENERIC_BUDGET) {
|
|
1271
|
-
parts.push("\u2026");
|
|
1272
|
-
break;
|
|
1273
|
-
}
|
|
1274
|
-
parts.push(rendered);
|
|
1275
|
-
used += rendered.length + 3;
|
|
1276
|
-
}
|
|
1277
|
-
return parts.length > 0 ? parts.join(" \xB7 ") : null;
|
|
1278
|
-
}
|
|
1279
|
-
function firstNonEmpty(text) {
|
|
1280
|
-
if (!text) return void 0;
|
|
1281
|
-
const line = text.split("\n").find((l) => l.trim());
|
|
1282
|
-
return line ? line.replace(/\s+/g, " ").trim() : void 0;
|
|
1283
|
-
}
|
|
1284
|
-
function formatMatchHit(hit) {
|
|
1285
|
-
if (typeof hit === "string") return truncMid(hit, 70);
|
|
1286
|
-
if (hit && typeof hit === "object") {
|
|
1287
|
-
const o = hit;
|
|
1288
|
-
const file = stringOf(o["file"]) ?? stringOf(o["path"]);
|
|
1289
|
-
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
1290
|
-
const snippet = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]);
|
|
1291
|
-
if (file) {
|
|
1292
|
-
const head = line !== void 0 ? `${shortenPath(file, 40)}:${line}` : shortenPath(file, 50);
|
|
1293
|
-
return snippet ? `${head} ${truncMid(snippet.replace(/\s+/g, " "), 40)}` : head;
|
|
1466
|
+
if (toolName === "diff") {
|
|
1467
|
+
if (json && typeof json === "object") {
|
|
1468
|
+
const o = json;
|
|
1469
|
+
const files = Array.isArray(o["files"]) ? o["files"] : void 0;
|
|
1470
|
+
const truncated = o["truncated"] === true;
|
|
1471
|
+
const mode = stringOf(o["mode"]);
|
|
1472
|
+
const diff = stringOf(o["diff"]);
|
|
1473
|
+
if (!diff) return [files && files.length === 0 ? "no changes" : "empty diff"];
|
|
1474
|
+
const head = [];
|
|
1475
|
+
if (mode) head.push(mode);
|
|
1476
|
+
if (files && files.length > 0)
|
|
1477
|
+
head.push(`${files.length} file${files.length === 1 ? "" : "s"}`);
|
|
1478
|
+
if (truncated) head.push("truncated");
|
|
1479
|
+
return head.length > 0 ? [head.join(" \xB7 ")] : [];
|
|
1294
1480
|
}
|
|
1295
|
-
if (snippet) return truncMid(snippet, 70);
|
|
1296
1481
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
if (!text) return void 0;
|
|
1304
|
-
let diff;
|
|
1305
|
-
if (toolName === "edit" || toolName === "diff") {
|
|
1306
|
-
const parsed = tryParseJson(text);
|
|
1307
|
-
if (parsed && typeof parsed === "object") {
|
|
1308
|
-
diff = stringOf(parsed["diff"]);
|
|
1482
|
+
if (toolName === "read") {
|
|
1483
|
+
if (outputLines !== void 0) return [];
|
|
1484
|
+
if (json && typeof json === "object") {
|
|
1485
|
+
const o = json;
|
|
1486
|
+
const bytes = numOf(o["bytes"]);
|
|
1487
|
+
if (bytes !== void 0) return [`${fmtBytes2(bytes)} read`];
|
|
1309
1488
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1489
|
+
const range = scanNumberedRange(text);
|
|
1490
|
+
if (range.count > 0 && range.first !== void 0 && range.last !== void 0) {
|
|
1491
|
+
if (range.first === range.last) {
|
|
1492
|
+
return [`L${range.first} \xB7 ${fmtBytes2(text.length)}`];
|
|
1493
|
+
}
|
|
1494
|
+
const contiguous = range.count === range.last - range.first + 1;
|
|
1495
|
+
const head = `L${range.first}\u2013${range.last}`;
|
|
1496
|
+
const tail = contiguous ? `${range.count} line${range.count === 1 ? "" : "s"}` : `${range.count} lines (gaps)`;
|
|
1497
|
+
return [`${head} \xB7 ${tail} \xB7 ${fmtBytes2(text.length)}`];
|
|
1316
1498
|
}
|
|
1317
1499
|
}
|
|
1318
|
-
if (
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
oldLn = Number.parseInt(m[1] ?? "0", 10) || 0;
|
|
1333
|
-
newLn = Number.parseInt(m[2] ?? "0", 10) || 0;
|
|
1500
|
+
if (toolName === "grep" || toolName === "glob") {
|
|
1501
|
+
if (json && typeof json === "object") {
|
|
1502
|
+
const o = json;
|
|
1503
|
+
const matches = Array.isArray(o["matches"]) ? o["matches"] : void 0;
|
|
1504
|
+
const count = numOf(o["count"]) ?? matches?.length;
|
|
1505
|
+
const truncated = o["truncated"] === true;
|
|
1506
|
+
if (count !== void 0) {
|
|
1507
|
+
if (count === 0) return ["no matches"];
|
|
1508
|
+
const lines = [
|
|
1509
|
+
`${count} match${count === 1 ? "" : "es"}${truncated ? " (truncated)" : ""}`
|
|
1510
|
+
];
|
|
1511
|
+
const firstHit = matches && matches.length > 0 ? formatMatchHit(matches[0]) : void 0;
|
|
1512
|
+
if (firstHit) lines.push(firstHit);
|
|
1513
|
+
return lines;
|
|
1334
1514
|
}
|
|
1335
|
-
all.push({ kind: "hunk", text: truncMid(line, 60) });
|
|
1336
|
-
continue;
|
|
1337
|
-
}
|
|
1338
|
-
if (line.startsWith("+")) {
|
|
1339
|
-
all.push({ kind: "add", text: truncMid(line, 100), newLine: newLn });
|
|
1340
|
-
newLn++;
|
|
1341
|
-
continue;
|
|
1342
|
-
}
|
|
1343
|
-
if (line.startsWith("-")) {
|
|
1344
|
-
all.push({ kind: "del", text: truncMid(line, 100), oldLine: oldLn });
|
|
1345
|
-
oldLn++;
|
|
1346
|
-
continue;
|
|
1347
1515
|
}
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1516
|
+
}
|
|
1517
|
+
if (toolName === "bash" || toolName === "shell") {
|
|
1518
|
+
if (json && typeof json === "object") {
|
|
1519
|
+
const o = json;
|
|
1520
|
+
const exit = numOf(o["exit_code"]) ?? numOf(o["exitCode"]);
|
|
1521
|
+
const stdout = stringOf(o["stdout"]) ?? "";
|
|
1522
|
+
const stderr = stringOf(o["stderr"]) ?? "";
|
|
1523
|
+
const stdoutLines = countLines(stdout);
|
|
1524
|
+
const stderrLines = countLines(stderr);
|
|
1525
|
+
const head = [];
|
|
1526
|
+
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1527
|
+
const lineParts = [];
|
|
1528
|
+
if (stdoutLines > 0) lineParts.push(`${stdoutLines} out`);
|
|
1529
|
+
if (stderrLines > 0) lineParts.push(`${stderrLines} err`);
|
|
1530
|
+
if (lineParts.length > 0) head.push(lineParts.join(" \xB7 "));
|
|
1531
|
+
const lines = [];
|
|
1532
|
+
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1533
|
+
const stdoutPreview = firstNonEmpty(stdout);
|
|
1534
|
+
const stderrPreview = firstNonEmpty(stderr);
|
|
1535
|
+
if (stdoutPreview) lines.push(`"${truncMid(stdoutPreview, 70)}"`);
|
|
1536
|
+
if (stderrPreview && stderrPreview !== stdoutPreview) {
|
|
1537
|
+
lines.push(`! "${truncMid(stderrPreview, 70)}"`);
|
|
1538
|
+
}
|
|
1539
|
+
if (lines.length > 0) return lines;
|
|
1351
1540
|
}
|
|
1352
|
-
if (line.length === 0) continue;
|
|
1353
|
-
all.push({ kind: "ctx", text: truncMid(line, 100), oldLine: oldLn, newLine: newLn });
|
|
1354
|
-
oldLn++;
|
|
1355
|
-
newLn++;
|
|
1356
1541
|
}
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
return { rows: all.slice(0, maxLines), hidden: all.length - maxLines };
|
|
1360
|
-
}
|
|
1361
|
-
function stringOf(v) {
|
|
1362
|
-
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
1363
|
-
}
|
|
1364
|
-
function numOf(v) {
|
|
1365
|
-
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
1366
|
-
}
|
|
1367
|
-
function tryParseJson(s) {
|
|
1368
|
-
const t = s.trimStart();
|
|
1369
|
-
if (!t.startsWith("{") && !t.startsWith("[")) return void 0;
|
|
1370
|
-
try {
|
|
1371
|
-
return JSON.parse(s);
|
|
1372
|
-
} catch {
|
|
1373
|
-
return void 0;
|
|
1542
|
+
if (toolName === "todo") {
|
|
1543
|
+
return ok ? [] : [text.split("\n")[0] ?? ""];
|
|
1374
1544
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
if (
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1545
|
+
if (toolName === "fetch" || toolName === "webfetch" || toolName === "web_fetch") {
|
|
1546
|
+
if (json && typeof json === "object") {
|
|
1547
|
+
const o = json;
|
|
1548
|
+
const status = numOf(o["status"]);
|
|
1549
|
+
const ct = stringOf(o["content_type"]);
|
|
1550
|
+
const url = stringOf(o["url"]);
|
|
1551
|
+
const content = stringOf(o["content"]);
|
|
1552
|
+
const head = [];
|
|
1553
|
+
if (status !== void 0) head.push(`HTTP ${status}`);
|
|
1554
|
+
if (ct) head.push(ct.split(";")[0] ?? ct);
|
|
1555
|
+
if (content) head.push(fmtBytes2(Buffer.byteLength(content, "utf8")));
|
|
1556
|
+
const lines = [];
|
|
1557
|
+
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1558
|
+
if (url && status !== void 0 && (status < 200 || status >= 400)) {
|
|
1559
|
+
lines.push(shortenPath(url, 70));
|
|
1388
1560
|
}
|
|
1561
|
+
if (lines.length > 0) return lines;
|
|
1389
1562
|
}
|
|
1390
1563
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
return null;
|
|
1412
|
-
}
|
|
1413
|
-
var EMPTY_KEY = {
|
|
1414
|
-
upArrow: false,
|
|
1415
|
-
downArrow: false,
|
|
1416
|
-
leftArrow: false,
|
|
1417
|
-
rightArrow: false,
|
|
1418
|
-
return: false,
|
|
1419
|
-
escape: false,
|
|
1420
|
-
ctrl: false,
|
|
1421
|
-
meta: false,
|
|
1422
|
-
shift: false,
|
|
1423
|
-
tab: false,
|
|
1424
|
-
backspace: false,
|
|
1425
|
-
delete: false,
|
|
1426
|
-
pageUp: false,
|
|
1427
|
-
pageDown: false,
|
|
1428
|
-
home: false,
|
|
1429
|
-
end: false
|
|
1430
|
-
};
|
|
1431
|
-
function Input({
|
|
1432
|
-
prompt = "\u203A ",
|
|
1433
|
-
value,
|
|
1434
|
-
cursor,
|
|
1435
|
-
placeholders,
|
|
1436
|
-
disabled,
|
|
1437
|
-
hint,
|
|
1438
|
-
onKey
|
|
1439
|
-
}) {
|
|
1440
|
-
useInput((input, key) => {
|
|
1441
|
-
if (disabled) return;
|
|
1442
|
-
onKey(input, key);
|
|
1443
|
-
});
|
|
1444
|
-
const { stdin } = useStdin();
|
|
1445
|
-
useEffect(() => {
|
|
1446
|
-
if (!stdin || disabled) return;
|
|
1447
|
-
const handleData = (data) => {
|
|
1448
|
-
const kind = isHomeEnd(data.toString());
|
|
1449
|
-
if (kind === "home") onKey("", { ...EMPTY_KEY, home: true });
|
|
1450
|
-
else if (kind === "end") onKey("", { ...EMPTY_KEY, end: true });
|
|
1451
|
-
};
|
|
1452
|
-
stdin.on("data", handleData);
|
|
1453
|
-
return () => {
|
|
1454
|
-
stdin.off("data", handleData);
|
|
1455
|
-
};
|
|
1456
|
-
}, [stdin, disabled, onKey]);
|
|
1457
|
-
const before = value.slice(0, cursor);
|
|
1458
|
-
const at = value.slice(cursor, cursor + 1) || " ";
|
|
1459
|
-
const after = value.slice(cursor + 1);
|
|
1460
|
-
const promptColor = disabled ? "red" : "cyan";
|
|
1461
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1462
|
-
placeholders.map((p, i) => (
|
|
1463
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: placeholders are append-only, index is stable
|
|
1464
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1465
|
-
" \u21B3 ",
|
|
1466
|
-
p
|
|
1467
|
-
] }, i)
|
|
1468
|
-
)),
|
|
1469
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1470
|
-
/* @__PURE__ */ jsx(Text, { color: promptColor, children: prompt }),
|
|
1471
|
-
before,
|
|
1472
|
-
/* @__PURE__ */ jsx(Text, { inverse: true, children: at }),
|
|
1473
|
-
after
|
|
1474
|
-
] }),
|
|
1475
|
-
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
1476
|
-
] });
|
|
1477
|
-
}
|
|
1478
|
-
function fmtElapsed(ms) {
|
|
1479
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
1480
|
-
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1481
|
-
const m = Math.floor(ms / 6e4);
|
|
1482
|
-
const s = Math.floor(ms % 6e4 / 1e3);
|
|
1483
|
-
return `${m}m${s.toString().padStart(2, "0")}s`;
|
|
1484
|
-
}
|
|
1485
|
-
function fmtBytes3(n) {
|
|
1486
|
-
if (n < 1024) return `${n}B`;
|
|
1487
|
-
return `${(n / 1024).toFixed(1)}KB`;
|
|
1488
|
-
}
|
|
1489
|
-
function fmtRecentTool2(tool) {
|
|
1490
|
-
const status = tool.ok === false ? "fail" : "ok";
|
|
1491
|
-
const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
|
|
1492
|
-
const parts = [status, name];
|
|
1493
|
-
if (typeof tool.durationMs === "number") parts.push(fmtElapsed(tool.durationMs));
|
|
1494
|
-
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes3(tool.outputBytes));
|
|
1495
|
-
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
1496
|
-
return parts.join(" ");
|
|
1497
|
-
}
|
|
1498
|
-
function fmtRecentMessage2(message) {
|
|
1499
|
-
const text = message.text.replace(/\s+/g, " ");
|
|
1500
|
-
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
1501
|
-
}
|
|
1502
|
-
function LiveActivityStrip({
|
|
1503
|
-
entries,
|
|
1504
|
-
nowTick,
|
|
1505
|
-
maxRows = 4
|
|
1506
|
-
}) {
|
|
1507
|
-
const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt).slice(0, maxRows);
|
|
1508
|
-
if (running.length === 0) return null;
|
|
1509
|
-
const now = Date.now();
|
|
1510
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1511
|
-
running.map((e) => {
|
|
1512
|
-
const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
|
|
1513
|
-
const taskElapsed = now - e.startedAt;
|
|
1514
|
-
const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed(toolElapsed)})` : "idle between tools";
|
|
1515
|
-
const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool2).join(" | ");
|
|
1516
|
-
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage2).join("");
|
|
1517
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1518
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25CF" }),
|
|
1519
|
-
/* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
|
|
1520
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
1521
|
-
/* @__PURE__ */ jsx(Text, { color: e.currentTool ? "green" : "yellow", children: toolSeg }),
|
|
1522
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
1523
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1524
|
-
e.iterations,
|
|
1525
|
-
"it ",
|
|
1526
|
-
e.toolCalls,
|
|
1527
|
-
"tc \xB7 ",
|
|
1528
|
-
fmtElapsed(taskElapsed)
|
|
1529
|
-
] }),
|
|
1530
|
-
recentTools ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1531
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
1532
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1533
|
-
"last: ",
|
|
1534
|
-
recentTools
|
|
1535
|
-
] })
|
|
1536
|
-
] }) : null,
|
|
1537
|
-
messageText ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1538
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
1539
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1540
|
-
"msg: ",
|
|
1541
|
-
fmtRecentMessage2({ text: messageText})
|
|
1542
|
-
] })
|
|
1543
|
-
] }) : null
|
|
1544
|
-
] }, e.id);
|
|
1545
|
-
}),
|
|
1546
|
-
Object.values(entries).filter((e) => e.status === "running").length > maxRows ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1547
|
-
"\u2026+",
|
|
1548
|
-
Object.values(entries).filter((e) => e.status === "running").length - maxRows,
|
|
1549
|
-
" more"
|
|
1550
|
-
] }) }) : null
|
|
1551
|
-
] });
|
|
1552
|
-
}
|
|
1553
|
-
var AUTONOMY_OPTIONS = [
|
|
1554
|
-
{ mode: "off", label: "OFF", description: "Agent stops after each turn (normal interactive mode)", color: "green" },
|
|
1555
|
-
{ mode: "suggest", label: "SUGGEST", description: "Shows next-step suggestions after each turn", color: "cyan" },
|
|
1556
|
-
{ mode: "auto", label: "AUTO", description: "Self-driving \u2014 agent picks next step and continues", color: "yellow" },
|
|
1557
|
-
{ mode: "eternal", label: "ETERNAL", description: "Goal-driven loop \u2014 requires /goal set first", color: "red" },
|
|
1558
|
-
{ mode: "eternal-parallel", label: "PARALLEL", description: "Fan-out 4\u20138 subagents per tick \u2014 requires /goal", color: "magenta" }
|
|
1559
|
-
];
|
|
1560
|
-
function AutonomyPicker({ options, selected, hint }) {
|
|
1561
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1562
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Autonomy Mode \u2501\u2501" }),
|
|
1563
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
1564
|
-
options.map((opt, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? opt.color : void 0, inverse: i === selected, children: [
|
|
1565
|
-
i === selected ? "\u203A " : " ",
|
|
1566
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.label.padEnd(12) }),
|
|
1567
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: opt.description })
|
|
1568
|
-
] }, opt.mode)),
|
|
1569
|
-
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
1570
|
-
] });
|
|
1571
|
-
}
|
|
1572
|
-
function ModelPicker({
|
|
1573
|
-
step,
|
|
1574
|
-
providerOptions,
|
|
1575
|
-
modelOptions,
|
|
1576
|
-
selected,
|
|
1577
|
-
pickedProviderId,
|
|
1578
|
-
hint
|
|
1579
|
-
}) {
|
|
1580
|
-
if (step === "provider") {
|
|
1581
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1582
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch model \u2014 Step 1/2: Pick provider \u2501\u2501" }),
|
|
1583
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
1584
|
-
providerOptions.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(no providers with keys \u2014 add one via `wstack auth`)" }) : providerOptions.map((p, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
1585
|
-
i === selected ? "\u203A " : " ",
|
|
1586
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: p.id.padEnd(28) }),
|
|
1587
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1588
|
-
" [",
|
|
1589
|
-
p.family,
|
|
1590
|
-
"]"
|
|
1591
|
-
] }),
|
|
1592
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1593
|
-
" ",
|
|
1594
|
-
p.models.length,
|
|
1595
|
-
" model",
|
|
1596
|
-
p.models.length === 1 ? "" : "s"
|
|
1597
|
-
] })
|
|
1598
|
-
] }, p.id)),
|
|
1599
|
-
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
1600
|
-
] });
|
|
1564
|
+
if (toolName === "git") {
|
|
1565
|
+
if (json && typeof json === "object") {
|
|
1566
|
+
const o = json;
|
|
1567
|
+
const exit = numOf(o["exitCode"]) ?? numOf(o["exit_code"]);
|
|
1568
|
+
const stdout = stringOf(o["stdout"]) ?? "";
|
|
1569
|
+
const stderr = stringOf(o["stderr"]) ?? "";
|
|
1570
|
+
const head = [];
|
|
1571
|
+
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1572
|
+
const stdoutLines = countLines(stdout);
|
|
1573
|
+
const stderrLines = countLines(stderr);
|
|
1574
|
+
const lparts = [];
|
|
1575
|
+
if (stdoutLines > 0) lparts.push(`${stdoutLines} out`);
|
|
1576
|
+
if (stderrLines > 0) lparts.push(`${stderrLines} err`);
|
|
1577
|
+
if (lparts.length > 0) head.push(lparts.join(" \xB7 "));
|
|
1578
|
+
const lines = [];
|
|
1579
|
+
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1580
|
+
const preview = firstNonEmpty(stdout) ?? firstNonEmpty(stderr);
|
|
1581
|
+
if (preview) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1582
|
+
if (lines.length > 0) return lines;
|
|
1583
|
+
}
|
|
1601
1584
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
")
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
]
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1825
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1826
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1827
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
|
|
1828
|
-
plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1829
|
-
"\u231B",
|
|
1830
|
-
plan.inProgress
|
|
1831
|
-
] }) : null,
|
|
1832
|
-
plan.inProgress > 0 && (plan.open > 0 || plan.done > 0) ? " " : "",
|
|
1833
|
-
plan.open > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1834
|
-
"\u2610",
|
|
1835
|
-
plan.open
|
|
1836
|
-
] }) : null,
|
|
1837
|
-
plan.open > 0 && plan.done > 0 ? " " : "",
|
|
1838
|
-
plan.done > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1839
|
-
"\u2713",
|
|
1840
|
-
plan.done
|
|
1841
|
-
] }) : null
|
|
1842
|
-
] })
|
|
1843
|
-
] }) : null,
|
|
1844
|
-
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1845
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1846
|
-
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1847
|
-
/* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
|
|
1848
|
-
fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1849
|
-
"\u25B6",
|
|
1850
|
-
fleet.running
|
|
1851
|
-
] }) : null,
|
|
1852
|
-
fleet.running > 0 && (fleet.pending > 0 || fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1853
|
-
fleet.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1854
|
-
"\u2610",
|
|
1855
|
-
fleet.pending
|
|
1856
|
-
] }) : null,
|
|
1857
|
-
fleet.pending > 0 && (fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1858
|
-
fleet.idle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1859
|
-
"\xB7",
|
|
1860
|
-
fleet.idle,
|
|
1861
|
-
"idle"
|
|
1862
|
-
] }) : null,
|
|
1863
|
-
fleet.idle > 0 && fleet.completed > 0 ? " " : "",
|
|
1864
|
-
fleet.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1865
|
-
"\u2713",
|
|
1866
|
-
fleet.completed
|
|
1867
|
-
] }) : null
|
|
1868
|
-
] }) : /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
1869
|
-
"\u{1F310} ",
|
|
1870
|
-
subagentCount,
|
|
1871
|
-
" agent",
|
|
1872
|
-
subagentCount === 1 ? "" : "s"
|
|
1873
|
-
] })
|
|
1874
|
-
] }) : null
|
|
1875
|
-
] }) : null,
|
|
1876
|
-
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
1877
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
1878
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1879
|
-
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
1880
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
1881
|
-
/* @__PURE__ */ jsx(Text, { color: a.running ? "yellow" : void 0, dimColor: !a.running, children: a.running ? "\u25B6" : "\xB7" }),
|
|
1882
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
1883
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed2(a.elapsedMs) }),
|
|
1884
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
1885
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1886
|
-
a.toolCalls,
|
|
1887
|
-
"t"
|
|
1888
|
-
] })
|
|
1889
|
-
] }, i)
|
|
1890
|
-
)) }) : null
|
|
1891
|
-
]
|
|
1585
|
+
if (toolName === "lint") {
|
|
1586
|
+
if (json && typeof json === "object") {
|
|
1587
|
+
const o = json;
|
|
1588
|
+
const linter = stringOf(o["linter"]);
|
|
1589
|
+
const files = numOf(o["files_checked"]);
|
|
1590
|
+
const errors = numOf(o["errors"]) ?? 0;
|
|
1591
|
+
const warnings = numOf(o["warnings"]) ?? 0;
|
|
1592
|
+
const fix = o["fix_applied"] === true;
|
|
1593
|
+
const head = [];
|
|
1594
|
+
if (linter && linter !== "none") head.push(linter);
|
|
1595
|
+
head.push(`${errors} error${errors === 1 ? "" : "s"}`);
|
|
1596
|
+
head.push(`${warnings} warning${warnings === 1 ? "" : "s"}`);
|
|
1597
|
+
if (files !== void 0) head.push(`${files} file${files === 1 ? "" : "s"}`);
|
|
1598
|
+
if (fix) head.push("fixed");
|
|
1599
|
+
return [head.join(" \xB7 ")];
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
if (toolName === "format") {
|
|
1603
|
+
if (json && typeof json === "object") {
|
|
1604
|
+
const o = json;
|
|
1605
|
+
const fixer = stringOf(o["fixer"]);
|
|
1606
|
+
const checked = numOf(o["files_checked"]);
|
|
1607
|
+
const changed = numOf(o["files_changed"]);
|
|
1608
|
+
const head = [];
|
|
1609
|
+
if (fixer && fixer !== "none") head.push(fixer);
|
|
1610
|
+
if (changed !== void 0 && checked !== void 0) {
|
|
1611
|
+
head.push(`${changed}/${checked} changed`);
|
|
1612
|
+
} else if (changed !== void 0) {
|
|
1613
|
+
head.push(`${changed} changed`);
|
|
1614
|
+
}
|
|
1615
|
+
return head.length > 0 ? [head.join(" \xB7 ")] : [];
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
if (toolName === "typecheck") {
|
|
1619
|
+
if (json && typeof json === "object") {
|
|
1620
|
+
const o = json;
|
|
1621
|
+
const exit = numOf(o["exit_code"]) ?? numOf(o["exitCode"]);
|
|
1622
|
+
const errors = numOf(o["errors"]);
|
|
1623
|
+
const head = [];
|
|
1624
|
+
if (errors !== void 0) head.push(`${errors} error${errors === 1 ? "" : "s"}`);
|
|
1625
|
+
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1626
|
+
const stdout = stringOf(o["output"]) ?? stringOf(o["stdout"]) ?? "";
|
|
1627
|
+
const lines = [];
|
|
1628
|
+
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1629
|
+
const preview = firstNonEmpty(stdout);
|
|
1630
|
+
if (preview && (!errors || errors > 0)) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1631
|
+
if (lines.length > 0) return lines;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
if (toolName === "test") {
|
|
1635
|
+
if (json && typeof json === "object") {
|
|
1636
|
+
const o = json;
|
|
1637
|
+
const runner = stringOf(o["runner"]);
|
|
1638
|
+
const total = numOf(o["tests_run"]) ?? 0;
|
|
1639
|
+
const passed = numOf(o["passed"]) ?? 0;
|
|
1640
|
+
const failed = numOf(o["failed"]) ?? 0;
|
|
1641
|
+
const duration = numOf(o["duration_ms"]);
|
|
1642
|
+
const head = [];
|
|
1643
|
+
if (runner && runner !== "none") head.push(runner);
|
|
1644
|
+
head.push(`${passed}/${total} passed`);
|
|
1645
|
+
if (failed > 0) head.push(`${failed} failed`);
|
|
1646
|
+
if (duration !== void 0) head.push(fmtDuration2(duration));
|
|
1647
|
+
return [head.join(" \xB7 ")];
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
if (toolName === "audit") {
|
|
1651
|
+
if (json && typeof json === "object") {
|
|
1652
|
+
const o = json;
|
|
1653
|
+
const total = numOf(o["total"]) ?? 0;
|
|
1654
|
+
const summary = stringOf(o["summary"]);
|
|
1655
|
+
if (total === 0) return ["no vulnerabilities"];
|
|
1656
|
+
const head = `${total} vulnerabilit${total === 1 ? "y" : "ies"}`;
|
|
1657
|
+
return summary && summary.toLowerCase() !== head.toLowerCase() ? [head, truncMid(summary, OUT_BUDGET)] : [head];
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
if (toolName === "outdated") {
|
|
1661
|
+
if (json && typeof json === "object") {
|
|
1662
|
+
const o = json;
|
|
1663
|
+
const total = numOf(o["total"]) ?? 0;
|
|
1664
|
+
const pkgs = Array.isArray(o["packages"]) ? o["packages"] : void 0;
|
|
1665
|
+
if (total === 0) return ["all up to date"];
|
|
1666
|
+
const lines = [`${total} outdated`];
|
|
1667
|
+
if (pkgs && pkgs.length > 0) {
|
|
1668
|
+
const first = pkgs[0];
|
|
1669
|
+
if (first && typeof first === "object") {
|
|
1670
|
+
const p = first;
|
|
1671
|
+
const name = stringOf(p["name"]) ?? stringOf(p["package"]);
|
|
1672
|
+
const cur = stringOf(p["current"]);
|
|
1673
|
+
const wanted = stringOf(p["wanted"]) ?? stringOf(p["latest"]);
|
|
1674
|
+
if (name && cur && wanted) lines.push(`${name}: ${cur} \u2192 ${wanted}`);
|
|
1675
|
+
else if (name) lines.push(name);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return lines;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
if (toolName === "tree") {
|
|
1682
|
+
if (json && typeof json === "object") {
|
|
1683
|
+
const o = json;
|
|
1684
|
+
const files = numOf(o["total_files"]);
|
|
1685
|
+
const dirs = numOf(o["total_dirs"]);
|
|
1686
|
+
const truncated = o["truncated"] === true;
|
|
1687
|
+
const parts = [];
|
|
1688
|
+
if (files !== void 0) parts.push(`${files} file${files === 1 ? "" : "s"}`);
|
|
1689
|
+
if (dirs !== void 0) parts.push(`${dirs} dir${dirs === 1 ? "" : "s"}`);
|
|
1690
|
+
if (truncated) parts.push("truncated");
|
|
1691
|
+
return parts.length > 0 ? [parts.join(" \xB7 ")] : [];
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
if (toolName === "json") {
|
|
1695
|
+
if (json && typeof json === "object") {
|
|
1696
|
+
const o = json;
|
|
1697
|
+
const err = stringOf(o["error"]);
|
|
1698
|
+
if (err) return [truncMid(err, OUT_BUDGET)];
|
|
1699
|
+
const type = stringOf(o["type"]);
|
|
1700
|
+
const keys = Array.isArray(o["keys"]) ? o["keys"] : void 0;
|
|
1701
|
+
const parts = [];
|
|
1702
|
+
if (type) parts.push(type);
|
|
1703
|
+
if (keys) parts.push(`${keys.length} key${keys.length === 1 ? "" : "s"}`);
|
|
1704
|
+
return parts.length > 0 ? [parts.join(" \xB7 ")] : [];
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
if (toolName === "install") {
|
|
1708
|
+
if (json && typeof json === "object") {
|
|
1709
|
+
const o = json;
|
|
1710
|
+
const exit = numOf(o["exit_code"]) ?? numOf(o["exitCode"]);
|
|
1711
|
+
const added = numOf(o["added"]);
|
|
1712
|
+
const removed = numOf(o["removed"]);
|
|
1713
|
+
const head = [];
|
|
1714
|
+
if (exit !== void 0) head.push(`exit ${exit}`);
|
|
1715
|
+
if (added !== void 0) head.push(`+${added}`);
|
|
1716
|
+
if (removed !== void 0) head.push(`-${removed}`);
|
|
1717
|
+
const stdout = stringOf(o["stdout"]) ?? stringOf(o["output"]) ?? "";
|
|
1718
|
+
const lines = [];
|
|
1719
|
+
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
1720
|
+
const preview = firstNonEmpty(stdout);
|
|
1721
|
+
if (preview) lines.push(`"${truncMid(preview, 70)}"`);
|
|
1722
|
+
if (lines.length > 0) return lines;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (toolName === "scaffold") {
|
|
1726
|
+
if (json && typeof json === "object") {
|
|
1727
|
+
const o = json;
|
|
1728
|
+
const created = Array.isArray(o["created"]) ? o["created"] : void 0;
|
|
1729
|
+
const skipped = Array.isArray(o["skipped"]) ? o["skipped"] : void 0;
|
|
1730
|
+
const parts = [];
|
|
1731
|
+
if (created !== void 0) parts.push(`${created.length} created`);
|
|
1732
|
+
if (skipped !== void 0 && skipped.length > 0) parts.push(`${skipped.length} skipped`);
|
|
1733
|
+
if (parts.length > 0) return [parts.join(" \xB7 ")];
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
if (toolName === "remember" || toolName === "forget" || toolName === "memory") {
|
|
1737
|
+
return ok ? [toolName === "forget" ? "removed" : "saved"] : [text.split("\n")[0] ?? ""];
|
|
1738
|
+
}
|
|
1739
|
+
if (toolName === "mode") {
|
|
1740
|
+
if (json && typeof json === "object") {
|
|
1741
|
+
const o = json;
|
|
1742
|
+
const mode = stringOf(o["mode"]) ?? stringOf(o["active"]) ?? stringOf(o["name"]);
|
|
1743
|
+
if (mode) return [`mode: ${mode}`];
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
if (toolName === "search") {
|
|
1747
|
+
if (json && typeof json === "object") {
|
|
1748
|
+
const o = json;
|
|
1749
|
+
const matches = Array.isArray(o["matches"]) ? o["matches"] : Array.isArray(o["results"]) ? o["results"] : void 0;
|
|
1750
|
+
const count = numOf(o["count"]) ?? matches?.length;
|
|
1751
|
+
if (count !== void 0) {
|
|
1752
|
+
if (count === 0) return ["no results"];
|
|
1753
|
+
const lines = [`${count} result${count === 1 ? "" : "s"}`];
|
|
1754
|
+
const firstHit = matches && matches.length > 0 ? formatMatchHit(matches[0]) : void 0;
|
|
1755
|
+
if (firstHit) lines.push(firstHit);
|
|
1756
|
+
return lines;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (toolName === "logs") {
|
|
1761
|
+
const lines = text.split("\n").filter((l) => l.trim());
|
|
1762
|
+
if (lines.length === 0) return [];
|
|
1763
|
+
const head = `${lines.length} line${lines.length === 1 ? "" : "s"}`;
|
|
1764
|
+
const lastLine = lines[lines.length - 1];
|
|
1765
|
+
return lastLine ? [head, `"${truncMid(lastLine.trim(), 70)}"`] : [head];
|
|
1766
|
+
}
|
|
1767
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
1768
|
+
const summary = summarizeJsonObject(json);
|
|
1769
|
+
if (summary) return [summary];
|
|
1770
|
+
}
|
|
1771
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
1772
|
+
return [truncMid(collapsed, GENERIC_BUDGET)];
|
|
1773
|
+
}
|
|
1774
|
+
var GENERIC_BUDGET = 240;
|
|
1775
|
+
function summarizeJsonObject(obj) {
|
|
1776
|
+
const keys = Object.keys(obj);
|
|
1777
|
+
if (keys.length === 0) return null;
|
|
1778
|
+
const priority = [
|
|
1779
|
+
"ok",
|
|
1780
|
+
"status",
|
|
1781
|
+
"timedOut",
|
|
1782
|
+
"stopReason",
|
|
1783
|
+
"reason",
|
|
1784
|
+
"error",
|
|
1785
|
+
"message",
|
|
1786
|
+
"result",
|
|
1787
|
+
"summary",
|
|
1788
|
+
"iterations",
|
|
1789
|
+
"toolCalls",
|
|
1790
|
+
"durationMs",
|
|
1791
|
+
"subagentId",
|
|
1792
|
+
"taskId"
|
|
1793
|
+
];
|
|
1794
|
+
const ordered = [
|
|
1795
|
+
...priority.filter((k) => keys.includes(k)),
|
|
1796
|
+
...keys.filter((k) => !priority.includes(k))
|
|
1797
|
+
];
|
|
1798
|
+
const parts = [];
|
|
1799
|
+
let used = 0;
|
|
1800
|
+
for (const key of ordered) {
|
|
1801
|
+
const v = obj[key];
|
|
1802
|
+
if (v === void 0 || v === null) continue;
|
|
1803
|
+
const rendered = typeof v === "string" ? `${key}="${truncMid(v.replace(/\s+/g, " "), 80)}"` : typeof v === "number" || typeof v === "boolean" ? `${key}=${v}` : Array.isArray(v) ? `${key}=[${v.length}]` : `${key}={\u2026}`;
|
|
1804
|
+
if (used + rendered.length > GENERIC_BUDGET) {
|
|
1805
|
+
parts.push("\u2026");
|
|
1806
|
+
break;
|
|
1892
1807
|
}
|
|
1893
|
-
|
|
1808
|
+
parts.push(rendered);
|
|
1809
|
+
used += rendered.length + 3;
|
|
1810
|
+
}
|
|
1811
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : null;
|
|
1894
1812
|
}
|
|
1895
|
-
function
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
case "reflect":
|
|
1913
|
-
return /* @__PURE__ */ jsxs(Text, { color: stage.status === "success" ? "green" : stage.status === "failure" ? "red" : "yellow", children: [
|
|
1914
|
-
"\u21A9 reflect: ",
|
|
1915
|
-
stage.status
|
|
1916
|
-
] });
|
|
1917
|
-
case "sleep":
|
|
1918
|
-
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1919
|
-
"\u{1F4A4} sleep ",
|
|
1920
|
-
Math.round(stage.ms / 1e3),
|
|
1921
|
-
"s"
|
|
1922
|
-
] });
|
|
1923
|
-
case "paused":
|
|
1924
|
-
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u23F8 paused" });
|
|
1925
|
-
case "stopped":
|
|
1926
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25A0 stopped" });
|
|
1927
|
-
case "error":
|
|
1928
|
-
return /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
1929
|
-
"\u26A0 error: ",
|
|
1930
|
-
stage.message
|
|
1931
|
-
] });
|
|
1813
|
+
function firstNonEmpty(text) {
|
|
1814
|
+
if (!text) return void 0;
|
|
1815
|
+
const line = text.split("\n").find((l) => l.trim());
|
|
1816
|
+
return line ? line.replace(/\s+/g, " ").trim() : void 0;
|
|
1817
|
+
}
|
|
1818
|
+
function formatMatchHit(hit) {
|
|
1819
|
+
if (typeof hit === "string") return truncMid(hit, 70);
|
|
1820
|
+
if (hit && typeof hit === "object") {
|
|
1821
|
+
const o = hit;
|
|
1822
|
+
const file = stringOf(o["file"]) ?? stringOf(o["path"]);
|
|
1823
|
+
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
1824
|
+
const snippet = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]);
|
|
1825
|
+
if (file) {
|
|
1826
|
+
const head = line !== void 0 ? `${shortenPath(file, 40)}:${line}` : shortenPath(file, 50);
|
|
1827
|
+
return snippet ? `${head} ${truncMid(snippet.replace(/\s+/g, " "), 40)}` : head;
|
|
1828
|
+
}
|
|
1829
|
+
if (snippet) return truncMid(snippet, 70);
|
|
1932
1830
|
}
|
|
1831
|
+
return void 0;
|
|
1933
1832
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
const
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1833
|
+
var DIFF_MAX_LINES = 8;
|
|
1834
|
+
function extractDiffPreview(toolName, output) {
|
|
1835
|
+
if (!output) return void 0;
|
|
1836
|
+
const text = output.trim();
|
|
1837
|
+
if (!text) return void 0;
|
|
1838
|
+
let diff;
|
|
1839
|
+
if (toolName === "edit" || toolName === "diff") {
|
|
1840
|
+
const parsed = tryParseJson(text);
|
|
1841
|
+
if (parsed && typeof parsed === "object") {
|
|
1842
|
+
diff = stringOf(parsed["diff"]);
|
|
1843
|
+
}
|
|
1844
|
+
} else if (toolName === "patch") {
|
|
1845
|
+
const parsed = tryParseJson(text);
|
|
1846
|
+
if (parsed && typeof parsed === "object") {
|
|
1847
|
+
diff = stringOf(parsed["diff"]) ?? stringOf(parsed["stdout"]);
|
|
1848
|
+
} else if (text.includes("@@") || text.startsWith("---")) {
|
|
1849
|
+
diff = text;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
if (!diff || !diff.trim() || diff.startsWith("(no-op")) return void 0;
|
|
1853
|
+
return parseUnifiedDiff(diff, DIFF_MAX_LINES);
|
|
1854
|
+
}
|
|
1855
|
+
function parseUnifiedDiff(diff, maxLines) {
|
|
1856
|
+
const all = [];
|
|
1857
|
+
let oldLn = 0;
|
|
1858
|
+
let newLn = 0;
|
|
1859
|
+
for (const raw of diff.split("\n")) {
|
|
1860
|
+
const line = raw.replace(/\r$/, "");
|
|
1861
|
+
if (line.startsWith("+++") || line.startsWith("---")) continue;
|
|
1862
|
+
if (line.startsWith("diff --git") || line.startsWith("index ")) continue;
|
|
1863
|
+
if (line.startsWith("@@")) {
|
|
1864
|
+
const m = line.match(/^@@\s+-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s+@@/);
|
|
1865
|
+
if (m) {
|
|
1866
|
+
oldLn = Number.parseInt(m[1] ?? "0", 10) || 0;
|
|
1867
|
+
newLn = Number.parseInt(m[2] ?? "0", 10) || 0;
|
|
1868
|
+
}
|
|
1869
|
+
all.push({ kind: "hunk", text: truncMid(line, 60) });
|
|
1870
|
+
continue;
|
|
1871
|
+
}
|
|
1872
|
+
if (line.startsWith("+")) {
|
|
1873
|
+
all.push({ kind: "add", text: truncMid(line, 100), newLine: newLn });
|
|
1874
|
+
newLn++;
|
|
1875
|
+
continue;
|
|
1876
|
+
}
|
|
1877
|
+
if (line.startsWith("-")) {
|
|
1878
|
+
all.push({ kind: "del", text: truncMid(line, 100), oldLine: oldLn });
|
|
1879
|
+
oldLn++;
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1882
|
+
if (line.startsWith("\\ No newline")) {
|
|
1883
|
+
all.push({ kind: "meta", text: line });
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
if (line.length === 0) continue;
|
|
1887
|
+
all.push({ kind: "ctx", text: truncMid(line, 100), oldLine: oldLn, newLine: newLn });
|
|
1888
|
+
oldLn++;
|
|
1889
|
+
newLn++;
|
|
1890
|
+
}
|
|
1891
|
+
if (all.length === 0) return { rows: [], hidden: 0 };
|
|
1892
|
+
if (all.length <= maxLines) return { rows: all, hidden: 0 };
|
|
1893
|
+
return { rows: all.slice(0, maxLines), hidden: all.length - maxLines };
|
|
1894
|
+
}
|
|
1895
|
+
function stringOf(v) {
|
|
1896
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
1897
|
+
}
|
|
1898
|
+
function numOf(v) {
|
|
1899
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
1900
|
+
}
|
|
1901
|
+
function tryParseJson(s) {
|
|
1902
|
+
const t = s.trimStart();
|
|
1903
|
+
if (!t.startsWith("{") && !t.startsWith("[")) return void 0;
|
|
1904
|
+
try {
|
|
1905
|
+
return JSON.parse(s);
|
|
1906
|
+
} catch {
|
|
1907
|
+
return void 0;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function scanNumberedRange(text) {
|
|
1911
|
+
let first;
|
|
1912
|
+
let last;
|
|
1913
|
+
let count = 0;
|
|
1914
|
+
for (const line of text.split("\n")) {
|
|
1915
|
+
const m = line.match(/^\s*(\d+)→/);
|
|
1916
|
+
if (m?.[1]) {
|
|
1917
|
+
const n = Number.parseInt(m[1], 10);
|
|
1918
|
+
if (Number.isFinite(n)) {
|
|
1919
|
+
if (first === void 0) first = n;
|
|
1920
|
+
last = n;
|
|
1921
|
+
count++;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
return { first, last, count };
|
|
1926
|
+
}
|
|
1927
|
+
function countLines(text) {
|
|
1928
|
+
if (!text) return 0;
|
|
1929
|
+
return text.replace(/\n$/, "").split("\n").length;
|
|
1930
|
+
}
|
|
1931
|
+
function fmtBytes2(n) {
|
|
1932
|
+
if (n < 1024) return `${n}B`;
|
|
1933
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
1934
|
+
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
1935
|
+
}
|
|
1936
|
+
function truncMid(s, max) {
|
|
1937
|
+
if (s.length <= max) return s;
|
|
1938
|
+
return `${s.slice(0, max - 1)}\u2026`;
|
|
1939
|
+
}
|
|
1940
|
+
function isHomeEnd(data) {
|
|
1941
|
+
if (data === "\x1B[H" || data === "\x1B[1~" || data === "\x1BOH" || data === "\x1B[7~")
|
|
1942
|
+
return "home";
|
|
1943
|
+
if (data === "\x1B[F" || data === "\x1B[4~" || data === "\x1BOF" || data === "\x1B[8~")
|
|
1944
|
+
return "end";
|
|
1945
|
+
return null;
|
|
1946
|
+
}
|
|
1947
|
+
var EMPTY_KEY = {
|
|
1948
|
+
upArrow: false,
|
|
1949
|
+
downArrow: false,
|
|
1950
|
+
leftArrow: false,
|
|
1951
|
+
rightArrow: false,
|
|
1952
|
+
return: false,
|
|
1953
|
+
escape: false,
|
|
1954
|
+
ctrl: false,
|
|
1955
|
+
meta: false,
|
|
1956
|
+
shift: false,
|
|
1957
|
+
tab: false,
|
|
1958
|
+
backspace: false,
|
|
1959
|
+
delete: false,
|
|
1960
|
+
pageUp: false,
|
|
1961
|
+
pageDown: false,
|
|
1962
|
+
home: false,
|
|
1963
|
+
end: false
|
|
1964
|
+
};
|
|
1965
|
+
function Input({
|
|
1966
|
+
prompt = "\u203A ",
|
|
1967
|
+
value,
|
|
1968
|
+
cursor,
|
|
1969
|
+
placeholders,
|
|
1970
|
+
disabled,
|
|
1971
|
+
hint,
|
|
1972
|
+
onKey
|
|
1973
|
+
}) {
|
|
1974
|
+
useInput((input, key) => {
|
|
1975
|
+
if (disabled) return;
|
|
1976
|
+
onKey(input, key);
|
|
1977
|
+
});
|
|
1978
|
+
const { stdin } = useStdin();
|
|
1979
|
+
useEffect(() => {
|
|
1980
|
+
if (!stdin || disabled) return;
|
|
1981
|
+
const handleData = (data) => {
|
|
1982
|
+
const kind = isHomeEnd(data.toString());
|
|
1983
|
+
if (kind === "home") onKey("", { ...EMPTY_KEY, home: true });
|
|
1984
|
+
else if (kind === "end") onKey("", { ...EMPTY_KEY, end: true });
|
|
1985
|
+
};
|
|
1986
|
+
stdin.on("data", handleData);
|
|
1987
|
+
return () => {
|
|
1988
|
+
stdin.off("data", handleData);
|
|
1989
|
+
};
|
|
1990
|
+
}, [stdin, disabled, onKey]);
|
|
1991
|
+
const before = value.slice(0, cursor);
|
|
1992
|
+
const at = value.slice(cursor, cursor + 1) || " ";
|
|
1993
|
+
const after = value.slice(cursor + 1);
|
|
1994
|
+
const promptColor = disabled ? "red" : "cyan";
|
|
1995
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1996
|
+
placeholders.map((p, i) => (
|
|
1997
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: placeholders are append-only, index is stable
|
|
1998
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1999
|
+
" \u21B3 ",
|
|
2000
|
+
p
|
|
2001
|
+
] }, i)
|
|
2002
|
+
)),
|
|
2003
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2004
|
+
/* @__PURE__ */ jsx(Text, { color: promptColor, children: prompt }),
|
|
2005
|
+
before,
|
|
2006
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: at }),
|
|
2007
|
+
after
|
|
1945
2008
|
] }),
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
" ",
|
|
1948
|
-
"(",
|
|
1949
|
-
fmtTok2(ctx.used),
|
|
1950
|
-
"/",
|
|
1951
|
-
fmtTok2(ctx.max),
|
|
1952
|
-
")"
|
|
1953
|
-
] })
|
|
2009
|
+
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
1954
2010
|
] });
|
|
1955
2011
|
}
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
const
|
|
1960
|
-
const
|
|
1961
|
-
|
|
1962
|
-
return FILLED.repeat(capped) + EMPTY.repeat(width - capped);
|
|
2012
|
+
function fmtElapsed2(ms) {
|
|
2013
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
2014
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
2015
|
+
const m = Math.floor(ms / 6e4);
|
|
2016
|
+
const s = Math.floor(ms % 6e4 / 1e3);
|
|
2017
|
+
return `${m}m${s.toString().padStart(2, "0")}s`;
|
|
1963
2018
|
}
|
|
1964
|
-
function
|
|
1965
|
-
if (n <
|
|
1966
|
-
|
|
1967
|
-
return `${(n / 1e6).toFixed(1)}M`;
|
|
2019
|
+
function fmtBytes3(n) {
|
|
2020
|
+
if (n < 1024) return `${n}B`;
|
|
2021
|
+
return `${(n / 1024).toFixed(1)}KB`;
|
|
1968
2022
|
}
|
|
1969
|
-
function
|
|
1970
|
-
const
|
|
1971
|
-
const
|
|
1972
|
-
const
|
|
1973
|
-
|
|
1974
|
-
if (
|
|
1975
|
-
|
|
2023
|
+
function fmtRecentTool2(tool) {
|
|
2024
|
+
const status = tool.ok === false ? "fail" : "ok";
|
|
2025
|
+
const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
|
|
2026
|
+
const parts = [status, name];
|
|
2027
|
+
if (typeof tool.durationMs === "number") parts.push(fmtElapsed2(tool.durationMs));
|
|
2028
|
+
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes3(tool.outputBytes));
|
|
2029
|
+
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
2030
|
+
return parts.join(" ");
|
|
2031
|
+
}
|
|
2032
|
+
function fmtRecentMessage2(message) {
|
|
2033
|
+
const text = message.text.replace(/\s+/g, " ");
|
|
2034
|
+
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
2035
|
+
}
|
|
2036
|
+
function LiveActivityStrip({
|
|
2037
|
+
entries,
|
|
2038
|
+
nowTick,
|
|
2039
|
+
maxRows = 4
|
|
2040
|
+
}) {
|
|
2041
|
+
const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt).slice(0, maxRows);
|
|
2042
|
+
if (running.length === 0) return null;
|
|
2043
|
+
const now = Date.now();
|
|
2044
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2045
|
+
running.map((e) => {
|
|
2046
|
+
const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
|
|
2047
|
+
const taskElapsed = now - e.startedAt;
|
|
2048
|
+
const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed2(toolElapsed)})` : "idle between tools";
|
|
2049
|
+
const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool2).join(" | ");
|
|
2050
|
+
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage2).join("");
|
|
2051
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2052
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25CF" }),
|
|
2053
|
+
/* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
|
|
2054
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2055
|
+
/* @__PURE__ */ jsx(Text, { color: e.currentTool ? "green" : "yellow", children: toolSeg }),
|
|
2056
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2057
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2058
|
+
e.iterations,
|
|
2059
|
+
"it ",
|
|
2060
|
+
e.toolCalls,
|
|
2061
|
+
"tc \xB7 ",
|
|
2062
|
+
fmtElapsed2(taskElapsed)
|
|
2063
|
+
] }),
|
|
2064
|
+
recentTools ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2065
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2066
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2067
|
+
"last: ",
|
|
2068
|
+
recentTools
|
|
2069
|
+
] })
|
|
2070
|
+
] }) : null,
|
|
2071
|
+
messageText ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2072
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2073
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2074
|
+
"msg: ",
|
|
2075
|
+
fmtRecentMessage2({ text: messageText})
|
|
2076
|
+
] })
|
|
2077
|
+
] }) : null
|
|
2078
|
+
] }, e.id);
|
|
2079
|
+
}),
|
|
2080
|
+
Object.values(entries).filter((e) => e.status === "running").length > maxRows ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2081
|
+
"\u2026+",
|
|
2082
|
+
Object.values(entries).filter((e) => e.status === "running").length - maxRows,
|
|
2083
|
+
" more"
|
|
2084
|
+
] }) }) : null
|
|
2085
|
+
] });
|
|
2086
|
+
}
|
|
2087
|
+
var AUTONOMY_OPTIONS = [
|
|
2088
|
+
{ mode: "off", label: "OFF", description: "Agent stops after each turn (normal interactive mode)", color: "green" },
|
|
2089
|
+
{ mode: "suggest", label: "SUGGEST", description: "Shows next-step suggestions after each turn", color: "cyan" },
|
|
2090
|
+
{ mode: "auto", label: "AUTO", description: "Self-driving \u2014 agent picks next step and continues", color: "yellow" },
|
|
2091
|
+
{ mode: "eternal", label: "ETERNAL", description: "Goal-driven loop \u2014 requires /goal set first", color: "red" },
|
|
2092
|
+
{ mode: "eternal-parallel", label: "PARALLEL", description: "Fan-out 4\u20138 subagents per tick \u2014 requires /goal", color: "magenta" }
|
|
2093
|
+
];
|
|
2094
|
+
function AutonomyPicker({ options, selected, hint }) {
|
|
2095
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2096
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Autonomy Mode \u2501\u2501" }),
|
|
2097
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
2098
|
+
options.map((opt, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? opt.color : void 0, inverse: i === selected, children: [
|
|
2099
|
+
i === selected ? "\u203A " : " ",
|
|
2100
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.label.padEnd(12) }),
|
|
2101
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: opt.description })
|
|
2102
|
+
] }, opt.mode)),
|
|
2103
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
2104
|
+
] });
|
|
2105
|
+
}
|
|
2106
|
+
function ModelPicker({
|
|
2107
|
+
step,
|
|
2108
|
+
providerOptions,
|
|
2109
|
+
modelOptions,
|
|
2110
|
+
selected,
|
|
2111
|
+
pickedProviderId,
|
|
2112
|
+
hint
|
|
2113
|
+
}) {
|
|
2114
|
+
if (step === "provider") {
|
|
2115
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2116
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch model \u2014 Step 1/2: Pick provider \u2501\u2501" }),
|
|
2117
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
2118
|
+
providerOptions.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(no providers with keys \u2014 add one via `wstack auth`)" }) : providerOptions.map((p, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
2119
|
+
i === selected ? "\u203A " : " ",
|
|
2120
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: p.id.padEnd(28) }),
|
|
2121
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2122
|
+
" [",
|
|
2123
|
+
p.family,
|
|
2124
|
+
"]"
|
|
2125
|
+
] }),
|
|
2126
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2127
|
+
" ",
|
|
2128
|
+
p.models.length,
|
|
2129
|
+
" model",
|
|
2130
|
+
p.models.length === 1 ? "" : "s"
|
|
2131
|
+
] })
|
|
2132
|
+
] }, p.id)),
|
|
2133
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
2134
|
+
] });
|
|
1976
2135
|
}
|
|
1977
|
-
return
|
|
2136
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2137
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
2138
|
+
"\u2501\u2501 Switch model \u2014 Step 2/2: Pick model (",
|
|
2139
|
+
pickedProviderId,
|
|
2140
|
+
") \u2501\u2501"
|
|
2141
|
+
] }),
|
|
2142
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc back \xB7 Ctrl+C exit" }),
|
|
2143
|
+
modelOptions.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(no models known for this provider)" }) : modelOptions.map((id, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
2144
|
+
i === selected ? "\u203A " : " ",
|
|
2145
|
+
id
|
|
2146
|
+
] }, id)),
|
|
2147
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
2148
|
+
] });
|
|
1978
2149
|
}
|
|
1979
|
-
function
|
|
1980
|
-
|
|
2150
|
+
function SlashMenu({ query, matches, selected }) {
|
|
2151
|
+
const placeholder = query ? `/${query}` : "/";
|
|
2152
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2153
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2154
|
+
placeholder || "/",
|
|
2155
|
+
" \u2014 \u2191/\u2193 select, Enter dispatch, Tab autocomplete, Esc close"
|
|
2156
|
+
] }),
|
|
2157
|
+
matches.map((m, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
2158
|
+
i === selected ? "\u203A " : " ",
|
|
2159
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: m.name }),
|
|
2160
|
+
m.argsHint ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2161
|
+
" ",
|
|
2162
|
+
m.argsHint
|
|
2163
|
+
] }) : null,
|
|
2164
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2165
|
+
" \u2014 ",
|
|
2166
|
+
m.description
|
|
2167
|
+
] })
|
|
2168
|
+
] }, m.name)),
|
|
2169
|
+
matches.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No matching commands" })
|
|
2170
|
+
] });
|
|
1981
2171
|
}
|
|
1982
2172
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
1983
2173
|
"node_modules",
|
|
@@ -2057,6 +2247,19 @@ async function searchFiles(root, query, limit = 8) {
|
|
|
2057
2247
|
scored.sort((a, b) => a.score - b.score);
|
|
2058
2248
|
return scored.slice(0, limit).map((x) => x.path);
|
|
2059
2249
|
}
|
|
2250
|
+
|
|
2251
|
+
// src/paste-accumulator.ts
|
|
2252
|
+
var BEGIN = "[200~";
|
|
2253
|
+
var END = "[201~";
|
|
2254
|
+
var BEGIN_RE = /\x1b?\[200~/g;
|
|
2255
|
+
var END_RE = /\x1b?\[201~/g;
|
|
2256
|
+
function feedPaste(accum, input) {
|
|
2257
|
+
if (accum === null && !input.includes(BEGIN)) return null;
|
|
2258
|
+
const piece = input.replace(BEGIN_RE, "").replace(END_RE, "");
|
|
2259
|
+
const next = (accum ?? "") + piece;
|
|
2260
|
+
if (input.includes(END)) return { accum: null, complete: next };
|
|
2261
|
+
return { accum: next, complete: null };
|
|
2262
|
+
}
|
|
2060
2263
|
async function readGitInfo(cwd) {
|
|
2061
2264
|
const [branchRes, numstatRes, statusRes] = await Promise.all([
|
|
2062
2265
|
runGit(cwd, ["branch", "--show-current"]),
|
|
@@ -2732,12 +2935,36 @@ function reducer(state, action) {
|
|
|
2732
2935
|
}
|
|
2733
2936
|
};
|
|
2734
2937
|
}
|
|
2938
|
+
case "fleetBudgetExtended": {
|
|
2939
|
+
const cur = state.fleet[action.id];
|
|
2940
|
+
if (!cur) return state;
|
|
2941
|
+
return {
|
|
2942
|
+
...state,
|
|
2943
|
+
fleet: {
|
|
2944
|
+
...state.fleet,
|
|
2945
|
+
[action.id]: {
|
|
2946
|
+
...cur,
|
|
2947
|
+
// The director sends the authoritative cumulative count; trust it
|
|
2948
|
+
// over a local increment so a dropped event can't desync the badge.
|
|
2949
|
+
extensions: action.totalExtensions,
|
|
2950
|
+
lastEventAt: Date.now()
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2735
2955
|
case "fleetCost": {
|
|
2736
|
-
return {
|
|
2956
|
+
return {
|
|
2957
|
+
...state,
|
|
2958
|
+
fleetCost: action.cost,
|
|
2959
|
+
fleetTokens: action.input !== void 0 || action.output !== void 0 ? { input: action.input ?? state.fleetTokens.input, output: action.output ?? state.fleetTokens.output } : state.fleetTokens
|
|
2960
|
+
};
|
|
2737
2961
|
}
|
|
2738
2962
|
case "setStreamFleet": {
|
|
2739
2963
|
return { ...state, streamFleet: action.enabled };
|
|
2740
2964
|
}
|
|
2965
|
+
case "toggleMonitor": {
|
|
2966
|
+
return { ...state, monitorOpen: !state.monitorOpen };
|
|
2967
|
+
}
|
|
2741
2968
|
case "checkpointReceived": {
|
|
2742
2969
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
2743
2970
|
if (existing) return state;
|
|
@@ -2859,7 +3086,7 @@ function App({
|
|
|
2859
3086
|
}, [statuslineHiddenItems]);
|
|
2860
3087
|
useEffect(() => {
|
|
2861
3088
|
setStatuslineHiddenItems(hiddenItems);
|
|
2862
|
-
}, [setStatuslineHiddenItems]);
|
|
3089
|
+
}, [setStatuslineHiddenItems, hiddenItems]);
|
|
2863
3090
|
const projectRoot = agent.ctx.projectRoot;
|
|
2864
3091
|
useEffect(() => {
|
|
2865
3092
|
if (!projectRoot) return;
|
|
@@ -2925,7 +3152,9 @@ function App({
|
|
|
2925
3152
|
contextChipVersion: 0,
|
|
2926
3153
|
fleet: {},
|
|
2927
3154
|
fleetCost: 0,
|
|
3155
|
+
fleetTokens: { input: 0, output: 0 },
|
|
2928
3156
|
streamFleet: true,
|
|
3157
|
+
monitorOpen: false,
|
|
2929
3158
|
checkpoints: [],
|
|
2930
3159
|
rewindOverlay: null,
|
|
2931
3160
|
eternalStage: null,
|
|
@@ -2935,7 +3164,10 @@ function App({
|
|
|
2935
3164
|
if (builderRef.current === null) {
|
|
2936
3165
|
builderRef.current = new InputBuilder({ store: attachments });
|
|
2937
3166
|
}
|
|
3167
|
+
const pasteAccumRef = useRef(null);
|
|
3168
|
+
const pasteFlushTimerRef = useRef(null);
|
|
2938
3169
|
const activeCtrlRef = useRef(null);
|
|
3170
|
+
const exitRequestedRef = useRef(false);
|
|
2939
3171
|
const inputGateRef = useRef(false);
|
|
2940
3172
|
const lastEnterAtRef = useRef(0);
|
|
2941
3173
|
const projectName = React2.useMemo(() => {
|
|
@@ -3048,7 +3280,11 @@ function App({
|
|
|
3048
3280
|
color: lbl.color,
|
|
3049
3281
|
elapsedMs: Math.max(0, nowTick - e.startedAt),
|
|
3050
3282
|
toolCalls: e.toolCalls,
|
|
3051
|
-
running: e.status === "running"
|
|
3283
|
+
running: e.status === "running",
|
|
3284
|
+
// Last/current action, so the 4th line shows what each agent is
|
|
3285
|
+
// doing right now (e.g. "▶ 12s · 8t · bash") rather than just counts.
|
|
3286
|
+
tool: e.currentTool?.name,
|
|
3287
|
+
extensions: e.extensions
|
|
3052
3288
|
};
|
|
3053
3289
|
});
|
|
3054
3290
|
}, [state.fleet, nowTick]);
|
|
@@ -3441,7 +3677,7 @@ function App({
|
|
|
3441
3677
|
flushTimerRef.current = null;
|
|
3442
3678
|
};
|
|
3443
3679
|
const offDelta = events.on("provider.text_delta", (e) => {
|
|
3444
|
-
const text = e.text.replace(/\x1b
|
|
3680
|
+
const text = e.text.replace(/\x1b?\[200~|\x1b?\[201~/g, "");
|
|
3445
3681
|
streamingTextRef.current += text;
|
|
3446
3682
|
pendingDeltaRef.current += text;
|
|
3447
3683
|
if (!flushTimerRef.current) flushTimerRef.current = setTimeout(flush, FLUSH_MS);
|
|
@@ -3632,6 +3868,20 @@ function App({
|
|
|
3632
3868
|
}
|
|
3633
3869
|
});
|
|
3634
3870
|
});
|
|
3871
|
+
const offBudgetExtended = events.on("subagent.budget_extended", (e) => {
|
|
3872
|
+
const lbl = labelFor(e.subagentId);
|
|
3873
|
+
dispatch({ type: "fleetBudgetExtended", id: e.subagentId, totalExtensions: e.totalExtensions });
|
|
3874
|
+
dispatch({
|
|
3875
|
+
type: "addEntry",
|
|
3876
|
+
entry: {
|
|
3877
|
+
kind: "subagent",
|
|
3878
|
+
agentLabel: lbl.label,
|
|
3879
|
+
agentColor: lbl.color,
|
|
3880
|
+
icon: "\u26A1",
|
|
3881
|
+
text: `extended ${e.kind} \u2192 ${e.newLimit} (\xD7${e.totalExtensions})`
|
|
3882
|
+
}
|
|
3883
|
+
});
|
|
3884
|
+
});
|
|
3635
3885
|
const offIterationSummary = events.on("subagent.iteration_summary", (e) => {
|
|
3636
3886
|
const lbl = labelFor(e.subagentId);
|
|
3637
3887
|
const costStr = e.costUsd > 0 ? ` \xB7 ${e.costUsd.toFixed(3)}` : "";
|
|
@@ -3664,6 +3914,7 @@ function App({
|
|
|
3664
3914
|
offStarted();
|
|
3665
3915
|
offCompleted();
|
|
3666
3916
|
offBudgetWarning();
|
|
3917
|
+
offBudgetExtended();
|
|
3667
3918
|
offIterationSummary();
|
|
3668
3919
|
offTool();
|
|
3669
3920
|
};
|
|
@@ -3735,6 +3986,8 @@ function App({
|
|
|
3735
3986
|
useEffect(() => {
|
|
3736
3987
|
if (fleetStreamController) fleetStreamController.enabled = state.streamFleet;
|
|
3737
3988
|
}, [state.streamFleet, fleetStreamController]);
|
|
3989
|
+
const lastEscAtRef = useRef(0);
|
|
3990
|
+
const ESC_DOUBLE_PRESS_MS = 1e3;
|
|
3738
3991
|
useEffect(() => {
|
|
3739
3992
|
const d = director;
|
|
3740
3993
|
if (!d) return;
|
|
@@ -3775,7 +4028,7 @@ function App({
|
|
|
3775
4028
|
});
|
|
3776
4029
|
labelFor(s.id, meta?.name ?? s.name);
|
|
3777
4030
|
}
|
|
3778
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4031
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3779
4032
|
const seen = new Set(Object.keys(status.subagents));
|
|
3780
4033
|
const pending = /* @__PURE__ */ new Map();
|
|
3781
4034
|
let flushTimer = null;
|
|
@@ -3885,7 +4138,7 @@ function App({
|
|
|
3885
4138
|
break;
|
|
3886
4139
|
}
|
|
3887
4140
|
case "provider.response": {
|
|
3888
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4141
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3889
4142
|
break;
|
|
3890
4143
|
}
|
|
3891
4144
|
case "session.ended":
|
|
@@ -3929,7 +4182,7 @@ function App({
|
|
|
3929
4182
|
iterations: payload.result.iterations,
|
|
3930
4183
|
toolCalls: payload.result.toolCalls
|
|
3931
4184
|
});
|
|
3932
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4185
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3933
4186
|
if (streamFlushTimer) {
|
|
3934
4187
|
clearTimeout(streamFlushTimer);
|
|
3935
4188
|
flushStreamBufs();
|
|
@@ -3949,14 +4202,16 @@ function App({
|
|
|
3949
4202
|
const current = stateRef.current;
|
|
3950
4203
|
if (current.interrupts >= 1) {
|
|
3951
4204
|
getProcessRegistry().killAll({ force: true });
|
|
3952
|
-
if (current
|
|
3953
|
-
process.exit(130);
|
|
3954
|
-
}
|
|
3955
|
-
try {
|
|
4205
|
+
if (exitRequestedRef.current) {
|
|
3956
4206
|
process.exit(130);
|
|
3957
|
-
} catch {
|
|
3958
4207
|
}
|
|
4208
|
+
exitRequestedRef.current = true;
|
|
3959
4209
|
dispatch({ type: "interrupt" });
|
|
4210
|
+
if (director) void director.terminateAll().catch(() => void 0);
|
|
4211
|
+
onExit(130);
|
|
4212
|
+
exit();
|
|
4213
|
+
const hardExit = setTimeout(() => process.exit(130), 400);
|
|
4214
|
+
hardExit.unref?.();
|
|
3960
4215
|
return;
|
|
3961
4216
|
}
|
|
3962
4217
|
dispatch({ type: "interrupt" });
|
|
@@ -4008,6 +4263,37 @@ function App({
|
|
|
4008
4263
|
});
|
|
4009
4264
|
}
|
|
4010
4265
|
} else {
|
|
4266
|
+
const fleetRunning = Object.values(current.fleet).filter(
|
|
4267
|
+
(e) => e.status === "running"
|
|
4268
|
+
).length;
|
|
4269
|
+
const autonomyRunning = eternalLoopRunningRef.current || parallelLoopRunningRef.current || getEternalEngine?.()?.currentState === "running" || getParallelEngine?.()?.currentState === "running";
|
|
4270
|
+
if (autonomyRunning || fleetRunning > 0) {
|
|
4271
|
+
getEternalEngine?.()?.stop();
|
|
4272
|
+
getParallelEngine?.()?.stop();
|
|
4273
|
+
if (autonomyRunning) switchAutonomy?.("off");
|
|
4274
|
+
if (director) {
|
|
4275
|
+
const cap = new Promise((resolve) => {
|
|
4276
|
+
const t = setTimeout(resolve, 1500);
|
|
4277
|
+
t.unref?.();
|
|
4278
|
+
});
|
|
4279
|
+
void Promise.race([director.terminateAll().catch(() => void 0), cap]);
|
|
4280
|
+
}
|
|
4281
|
+
const killed2 = getProcessRegistry().killAll();
|
|
4282
|
+
const bits = [];
|
|
4283
|
+
if (autonomyRunning) bits.push("autonomy stopped");
|
|
4284
|
+
if (fleetRunning > 0)
|
|
4285
|
+
bits.push(`${fleetRunning} agent${fleetRunning === 1 ? "" : "s"} terminated`);
|
|
4286
|
+
if (killed2.length > 0)
|
|
4287
|
+
bits.push(`${killed2.length} process${killed2.length === 1 ? "" : "es"} killed`);
|
|
4288
|
+
dispatch({
|
|
4289
|
+
type: "addEntry",
|
|
4290
|
+
entry: {
|
|
4291
|
+
kind: "warn",
|
|
4292
|
+
text: `${bits.join(" + ") || "Background work stopped"}. Press Ctrl+C again to exit.`
|
|
4293
|
+
}
|
|
4294
|
+
});
|
|
4295
|
+
return;
|
|
4296
|
+
}
|
|
4011
4297
|
const killed = getProcessRegistry().killAll();
|
|
4012
4298
|
const procTag = killed.length > 0 ? ` Killed ${killed.length} process${killed.length === 1 ? "" : "es"}.` : "";
|
|
4013
4299
|
dispatch({
|
|
@@ -4020,11 +4306,52 @@ function App({
|
|
|
4020
4306
|
return () => {
|
|
4021
4307
|
process.off("SIGINT", onSigint);
|
|
4022
4308
|
};
|
|
4023
|
-
}, [director]);
|
|
4309
|
+
}, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
|
|
4310
|
+
const commitPaste = async (full) => {
|
|
4311
|
+
const builder = builderRef.current;
|
|
4312
|
+
if (!builder || !full) return;
|
|
4313
|
+
if (builder.wouldCollapse(full) || full.includes("\n")) {
|
|
4314
|
+
const lineCount = full.split("\n").length;
|
|
4315
|
+
const ph = await builder.appendPaste(full);
|
|
4316
|
+
dispatch({ type: "addPlaceholder", ph: `${ph ?? "[pasted]"} (${lineCount} lines)` });
|
|
4317
|
+
return;
|
|
4318
|
+
}
|
|
4319
|
+
const { buffer, cursor } = draftRef.current;
|
|
4320
|
+
const next = buffer.slice(0, cursor) + full + buffer.slice(cursor);
|
|
4321
|
+
setDraft(next, cursor + full.length);
|
|
4322
|
+
};
|
|
4024
4323
|
const handleKey = async (input, key) => {
|
|
4025
4324
|
if (state.status === "aborting" && state.interrupts === 0) return;
|
|
4026
4325
|
if (state.confirmQueue.length > 0) return;
|
|
4027
4326
|
if (inputGateRef.current) return;
|
|
4327
|
+
if (key.escape) {
|
|
4328
|
+
const now = Date.now();
|
|
4329
|
+
if (state.buffer.length > 0 && now - lastEscAtRef.current < ESC_DOUBLE_PRESS_MS) {
|
|
4330
|
+
dispatch({ type: "clearInput" });
|
|
4331
|
+
lastEscAtRef.current = 0;
|
|
4332
|
+
return;
|
|
4333
|
+
}
|
|
4334
|
+
lastEscAtRef.current = now;
|
|
4335
|
+
}
|
|
4336
|
+
if (input) {
|
|
4337
|
+
const paste = feedPaste(pasteAccumRef.current, input);
|
|
4338
|
+
if (paste) {
|
|
4339
|
+
pasteAccumRef.current = paste.accum;
|
|
4340
|
+
if (pasteFlushTimerRef.current) clearTimeout(pasteFlushTimerRef.current);
|
|
4341
|
+
if (paste.complete !== null) {
|
|
4342
|
+
pasteFlushTimerRef.current = null;
|
|
4343
|
+
await commitPaste(paste.complete);
|
|
4344
|
+
return;
|
|
4345
|
+
}
|
|
4346
|
+
pasteFlushTimerRef.current = setTimeout(() => {
|
|
4347
|
+
pasteFlushTimerRef.current = null;
|
|
4348
|
+
const full = pasteAccumRef.current;
|
|
4349
|
+
pasteAccumRef.current = null;
|
|
4350
|
+
if (full) void commitPaste(full);
|
|
4351
|
+
}, 250);
|
|
4352
|
+
return;
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4028
4355
|
const isEnter = key.return || input === "\r" || input === "\n";
|
|
4029
4356
|
if (state.modelPicker.open) {
|
|
4030
4357
|
if (key.escape) {
|
|
@@ -4203,6 +4530,14 @@ function App({
|
|
|
4203
4530
|
});
|
|
4204
4531
|
return;
|
|
4205
4532
|
}
|
|
4533
|
+
if (key.ctrl && input === "f") {
|
|
4534
|
+
dispatch({ type: "toggleMonitor" });
|
|
4535
|
+
return;
|
|
4536
|
+
}
|
|
4537
|
+
if (key.escape && state.monitorOpen) {
|
|
4538
|
+
dispatch({ type: "toggleMonitor" });
|
|
4539
|
+
return;
|
|
4540
|
+
}
|
|
4206
4541
|
if (isEnter) {
|
|
4207
4542
|
const now = Date.now();
|
|
4208
4543
|
if (now - lastEnterAtRef.current < 50) return;
|
|
@@ -4320,40 +4655,23 @@ function App({
|
|
|
4320
4655
|
return;
|
|
4321
4656
|
}
|
|
4322
4657
|
if (!input || key.ctrl || key.meta) return;
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
if (input.includes("\x1B[200~") || input.includes("\x1B[201~")) {
|
|
4326
|
-
cleanInput = input.replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "");
|
|
4327
|
-
bracketedPaste = true;
|
|
4328
|
-
}
|
|
4329
|
-
if (bracketedPaste || cleanInput.length > PASTE_THRESHOLD_CHARS) {
|
|
4330
|
-
const builder = builderRef.current;
|
|
4331
|
-
if (!builder) return;
|
|
4332
|
-
const ph = await builder.appendPaste(cleanInput);
|
|
4333
|
-
if (ph) {
|
|
4334
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4335
|
-
dispatch({ type: "addPlaceholder", ph: `${ph} (${lineCount} lines)` });
|
|
4336
|
-
} else if (cleanInput.includes("\n")) {
|
|
4337
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4338
|
-
dispatch({ type: "addPlaceholder", ph: `[pasted] (${lineCount} lines)` });
|
|
4339
|
-
} else {
|
|
4340
|
-
const next2 = buffer.slice(0, cursor) + cleanInput + buffer.slice(cursor);
|
|
4341
|
-
setDraft(next2, cursor + cleanInput.length);
|
|
4342
|
-
}
|
|
4658
|
+
if (input.length > PASTE_THRESHOLD_CHARS) {
|
|
4659
|
+
await commitPaste(input);
|
|
4343
4660
|
return;
|
|
4344
4661
|
}
|
|
4345
|
-
if (
|
|
4346
|
-
const normalized =
|
|
4662
|
+
if (input.includes("\n")) {
|
|
4663
|
+
const normalized = input.replace(/\r?\n/g, " ");
|
|
4347
4664
|
const next2 = buffer.slice(0, cursor) + normalized + buffer.slice(cursor);
|
|
4348
4665
|
setDraft(next2, cursor + normalized.length);
|
|
4349
4666
|
return;
|
|
4350
4667
|
}
|
|
4351
|
-
const next = buffer.slice(0, cursor) +
|
|
4352
|
-
setDraft(next, cursor +
|
|
4668
|
+
const next = buffer.slice(0, cursor) + input + buffer.slice(cursor);
|
|
4669
|
+
setDraft(next, cursor + input.length);
|
|
4353
4670
|
};
|
|
4354
4671
|
const runBlocks = async (blocks) => {
|
|
4355
4672
|
const ctrl = new AbortController();
|
|
4356
4673
|
activeCtrlRef.current = ctrl;
|
|
4674
|
+
dispatch({ type: "resetInterrupts" });
|
|
4357
4675
|
dispatch({ type: "status", status: "running" });
|
|
4358
4676
|
try {
|
|
4359
4677
|
const startedAt = Date.now();
|
|
@@ -4749,6 +5067,7 @@ User message:
|
|
|
4749
5067
|
StatusBar,
|
|
4750
5068
|
{
|
|
4751
5069
|
model: `${liveProvider}/${liveModel}`,
|
|
5070
|
+
version: appVersion,
|
|
4752
5071
|
state: state.status,
|
|
4753
5072
|
tokenCounter,
|
|
4754
5073
|
hint: renderRunningTools(state.runningTools) || state.hint,
|
|
@@ -4770,7 +5089,15 @@ User message:
|
|
|
4770
5089
|
goalSummary: state.goalSummary
|
|
4771
5090
|
}
|
|
4772
5091
|
),
|
|
4773
|
-
|
|
5092
|
+
state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
5093
|
+
FleetMonitor,
|
|
5094
|
+
{
|
|
5095
|
+
entries: state.fleet,
|
|
5096
|
+
totalCost: state.fleetCost,
|
|
5097
|
+
totalTokens: state.fleetTokens,
|
|
5098
|
+
nowTick
|
|
5099
|
+
}
|
|
5100
|
+
) : director ? /* @__PURE__ */ jsx(FleetPanel, { entries: state.fleet, totalCost: state.fleetCost, roster: fleetRoster }) : null
|
|
4774
5101
|
] });
|
|
4775
5102
|
}
|
|
4776
5103
|
function renderRunningTools(running) {
|