@wrongstack/tui 0.6.7 → 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.d.ts +3 -2
- package/dist/index.js +1975 -1608
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -313,1658 +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
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
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
|
+
] });
|
|
1158
1201
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
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
|
+
] });
|
|
1171
1242
|
}
|
|
1172
1243
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
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) : "";
|
|
1189
1399
|
}
|
|
1190
1400
|
}
|
|
1191
|
-
|
|
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") {
|
|
1192
1417
|
if (json && typeof json === "object") {
|
|
1193
1418
|
const o = json;
|
|
1194
|
-
const
|
|
1195
|
-
const
|
|
1196
|
-
const
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1199
|
-
if (parts.length > 0) return [parts.join(" \xB7 ")];
|
|
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];
|
|
1200
1424
|
}
|
|
1201
1425
|
}
|
|
1202
|
-
if (toolName === "
|
|
1203
|
-
return ok ? [toolName === "forget" ? "removed" : "saved"] : [text.split("\n")[0] ?? ""];
|
|
1204
|
-
}
|
|
1205
|
-
if (toolName === "mode") {
|
|
1426
|
+
if (toolName === "edit") {
|
|
1206
1427
|
if (json && typeof json === "object") {
|
|
1207
1428
|
const o = json;
|
|
1208
|
-
const
|
|
1209
|
-
if (
|
|
1429
|
+
const reps = numOf(o["replacements"]);
|
|
1430
|
+
if (reps !== void 0) return [`${reps} replacement${reps === 1 ? "" : "s"}`];
|
|
1210
1431
|
}
|
|
1211
1432
|
}
|
|
1212
|
-
if (toolName === "
|
|
1433
|
+
if (toolName === "patch") {
|
|
1213
1434
|
if (json && typeof json === "object") {
|
|
1214
1435
|
const o = json;
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
const
|
|
1221
|
-
if (
|
|
1222
|
-
|
|
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}`);
|
|
1223
1450
|
}
|
|
1451
|
+
if (lines.length > 0) return lines;
|
|
1224
1452
|
}
|
|
1225
1453
|
}
|
|
1226
|
-
if (toolName === "
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1454
|
+
if (toolName === "replace") {
|
|
1455
|
+
if (json && typeof json === "object") {
|
|
1456
|
+
const o = json;
|
|
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
|
+
];
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1236
1465
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
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.open > 0 && plan.done > 0 ? " " : "",
|
|
1825
|
-
plan.done > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1826
|
-
"\u2713",
|
|
1827
|
-
plan.done
|
|
1828
|
-
] }) : null
|
|
1829
|
-
] })
|
|
1830
|
-
] }) : null,
|
|
1831
|
-
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1832
|
-
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,
|
|
1833
|
-
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1834
|
-
/* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
|
|
1835
|
-
fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1836
|
-
"\u25B6",
|
|
1837
|
-
fleet.running
|
|
1838
|
-
] }) : null,
|
|
1839
|
-
fleet.running > 0 && (fleet.pending > 0 || fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1840
|
-
fleet.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1841
|
-
"\u2610",
|
|
1842
|
-
fleet.pending
|
|
1843
|
-
] }) : null,
|
|
1844
|
-
fleet.pending > 0 && (fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1845
|
-
fleet.idle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1846
|
-
"\xB7",
|
|
1847
|
-
fleet.idle,
|
|
1848
|
-
"idle"
|
|
1849
|
-
] }) : null,
|
|
1850
|
-
fleet.idle > 0 && fleet.completed > 0 ? " " : "",
|
|
1851
|
-
fleet.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1852
|
-
"\u2713",
|
|
1853
|
-
fleet.completed
|
|
1854
|
-
] }) : null
|
|
1855
|
-
] }) : /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
1856
|
-
"\u{1F310} ",
|
|
1857
|
-
subagentCount,
|
|
1858
|
-
" agent",
|
|
1859
|
-
subagentCount === 1 ? "" : "s"
|
|
1860
|
-
] })
|
|
1861
|
-
] }) : null
|
|
1862
|
-
] }) : null,
|
|
1863
|
-
fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
1864
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
1865
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1866
|
-
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
1867
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
1868
|
-
/* @__PURE__ */ jsx(Text, { color: a.running ? "yellow" : void 0, dimColor: !a.running, children: a.running ? "\u25B6" : "\xB7" }),
|
|
1869
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
1870
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed2(a.elapsedMs) }),
|
|
1871
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
1872
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1873
|
-
a.toolCalls,
|
|
1874
|
-
"t"
|
|
1875
|
-
] })
|
|
1876
|
-
] }, i)
|
|
1877
|
-
)) }) : null
|
|
1878
|
-
]
|
|
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;
|
|
1879
1807
|
}
|
|
1880
|
-
|
|
1808
|
+
parts.push(rendered);
|
|
1809
|
+
used += rendered.length + 3;
|
|
1810
|
+
}
|
|
1811
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : null;
|
|
1881
1812
|
}
|
|
1882
|
-
function
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
case "reflect":
|
|
1900
|
-
return /* @__PURE__ */ jsxs(Text, { color: stage.status === "success" ? "green" : stage.status === "failure" ? "red" : "yellow", children: [
|
|
1901
|
-
"\u21A9 reflect: ",
|
|
1902
|
-
stage.status
|
|
1903
|
-
] });
|
|
1904
|
-
case "sleep":
|
|
1905
|
-
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1906
|
-
"\u{1F4A4} sleep ",
|
|
1907
|
-
Math.round(stage.ms / 1e3),
|
|
1908
|
-
"s"
|
|
1909
|
-
] });
|
|
1910
|
-
case "paused":
|
|
1911
|
-
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u23F8 paused" });
|
|
1912
|
-
case "stopped":
|
|
1913
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25A0 stopped" });
|
|
1914
|
-
case "error":
|
|
1915
|
-
return /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
1916
|
-
"\u26A0 error: ",
|
|
1917
|
-
stage.message
|
|
1918
|
-
] });
|
|
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);
|
|
1919
1830
|
}
|
|
1831
|
+
return void 0;
|
|
1920
1832
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
"("
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
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
|
|
2008
|
+
] }),
|
|
2009
|
+
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
1941
2010
|
] });
|
|
1942
2011
|
}
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
const
|
|
1947
|
-
const
|
|
1948
|
-
|
|
1949
|
-
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`;
|
|
1950
2018
|
}
|
|
1951
|
-
function
|
|
1952
|
-
if (n <
|
|
1953
|
-
|
|
1954
|
-
return `${(n / 1e6).toFixed(1)}M`;
|
|
2019
|
+
function fmtBytes3(n) {
|
|
2020
|
+
if (n < 1024) return `${n}B`;
|
|
2021
|
+
return `${(n / 1024).toFixed(1)}KB`;
|
|
1955
2022
|
}
|
|
1956
|
-
function
|
|
1957
|
-
const
|
|
1958
|
-
const
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
if (
|
|
1962
|
-
|
|
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
|
+
] });
|
|
1963
2135
|
}
|
|
1964
|
-
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
|
+
] });
|
|
1965
2149
|
}
|
|
1966
|
-
function
|
|
1967
|
-
|
|
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
|
+
] });
|
|
1968
2171
|
}
|
|
1969
2172
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
1970
2173
|
"node_modules",
|
|
@@ -2044,6 +2247,19 @@ async function searchFiles(root, query, limit = 8) {
|
|
|
2044
2247
|
scored.sort((a, b) => a.score - b.score);
|
|
2045
2248
|
return scored.slice(0, limit).map((x) => x.path);
|
|
2046
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
|
+
}
|
|
2047
2263
|
async function readGitInfo(cwd) {
|
|
2048
2264
|
const [branchRes, numstatRes, statusRes] = await Promise.all([
|
|
2049
2265
|
runGit(cwd, ["branch", "--show-current"]),
|
|
@@ -2719,12 +2935,36 @@ function reducer(state, action) {
|
|
|
2719
2935
|
}
|
|
2720
2936
|
};
|
|
2721
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
|
+
}
|
|
2722
2955
|
case "fleetCost": {
|
|
2723
|
-
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
|
+
};
|
|
2724
2961
|
}
|
|
2725
2962
|
case "setStreamFleet": {
|
|
2726
2963
|
return { ...state, streamFleet: action.enabled };
|
|
2727
2964
|
}
|
|
2965
|
+
case "toggleMonitor": {
|
|
2966
|
+
return { ...state, monitorOpen: !state.monitorOpen };
|
|
2967
|
+
}
|
|
2728
2968
|
case "checkpointReceived": {
|
|
2729
2969
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
2730
2970
|
if (existing) return state;
|
|
@@ -2756,6 +2996,9 @@ function reducer(state, action) {
|
|
|
2756
2996
|
case "eternalStage": {
|
|
2757
2997
|
return { ...state, eternalStage: action.stage };
|
|
2758
2998
|
}
|
|
2999
|
+
case "goalSummary": {
|
|
3000
|
+
return { ...state, goalSummary: action.summary };
|
|
3001
|
+
}
|
|
2759
3002
|
}
|
|
2760
3003
|
}
|
|
2761
3004
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
@@ -2843,7 +3086,29 @@ function App({
|
|
|
2843
3086
|
}, [statuslineHiddenItems]);
|
|
2844
3087
|
useEffect(() => {
|
|
2845
3088
|
setStatuslineHiddenItems(hiddenItems);
|
|
2846
|
-
}, [setStatuslineHiddenItems]);
|
|
3089
|
+
}, [setStatuslineHiddenItems, hiddenItems]);
|
|
3090
|
+
const projectRoot = agent.ctx.projectRoot;
|
|
3091
|
+
useEffect(() => {
|
|
3092
|
+
if (!projectRoot) return;
|
|
3093
|
+
const goalPath = path2.join(projectRoot, ".wrongstack", "goal.json");
|
|
3094
|
+
fs2.readFile(goalPath, "utf8").then((raw) => {
|
|
3095
|
+
const goal = JSON.parse(raw);
|
|
3096
|
+
if (goal?.goal && typeof goal.iterations === "number") {
|
|
3097
|
+
const lastEntry = goal.journal?.[goal.journal.length - 1];
|
|
3098
|
+
dispatch({
|
|
3099
|
+
type: "goalSummary",
|
|
3100
|
+
summary: {
|
|
3101
|
+
goal: goal.goal,
|
|
3102
|
+
goalState: goal.goalState ?? "active",
|
|
3103
|
+
iterations: goal.iterations,
|
|
3104
|
+
lastTask: lastEntry?.task,
|
|
3105
|
+
lastStatus: lastEntry?.status
|
|
3106
|
+
}
|
|
3107
|
+
});
|
|
3108
|
+
}
|
|
3109
|
+
}).catch(() => {
|
|
3110
|
+
});
|
|
3111
|
+
}, [projectRoot]);
|
|
2847
3112
|
const [state, dispatch] = useReducer(reducer, {
|
|
2848
3113
|
entries: banner ? [
|
|
2849
3114
|
{
|
|
@@ -2887,19 +3152,24 @@ function App({
|
|
|
2887
3152
|
contextChipVersion: 0,
|
|
2888
3153
|
fleet: {},
|
|
2889
3154
|
fleetCost: 0,
|
|
3155
|
+
fleetTokens: { input: 0, output: 0 },
|
|
2890
3156
|
streamFleet: true,
|
|
3157
|
+
monitorOpen: false,
|
|
2891
3158
|
checkpoints: [],
|
|
2892
3159
|
rewindOverlay: null,
|
|
2893
|
-
eternalStage: null
|
|
3160
|
+
eternalStage: null,
|
|
3161
|
+
goalSummary: null
|
|
2894
3162
|
});
|
|
2895
3163
|
const builderRef = useRef(null);
|
|
2896
3164
|
if (builderRef.current === null) {
|
|
2897
3165
|
builderRef.current = new InputBuilder({ store: attachments });
|
|
2898
3166
|
}
|
|
3167
|
+
const pasteAccumRef = useRef(null);
|
|
3168
|
+
const pasteFlushTimerRef = useRef(null);
|
|
2899
3169
|
const activeCtrlRef = useRef(null);
|
|
3170
|
+
const exitRequestedRef = useRef(false);
|
|
2900
3171
|
const inputGateRef = useRef(false);
|
|
2901
3172
|
const lastEnterAtRef = useRef(0);
|
|
2902
|
-
const projectRoot = agent.ctx.projectRoot;
|
|
2903
3173
|
const projectName = React2.useMemo(() => {
|
|
2904
3174
|
const base = path2.basename(projectRoot);
|
|
2905
3175
|
return base && base !== path2.sep ? base : void 0;
|
|
@@ -3010,7 +3280,11 @@ function App({
|
|
|
3010
3280
|
color: lbl.color,
|
|
3011
3281
|
elapsedMs: Math.max(0, nowTick - e.startedAt),
|
|
3012
3282
|
toolCalls: e.toolCalls,
|
|
3013
|
-
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
|
|
3014
3288
|
};
|
|
3015
3289
|
});
|
|
3016
3290
|
}, [state.fleet, nowTick]);
|
|
@@ -3403,7 +3677,7 @@ function App({
|
|
|
3403
3677
|
flushTimerRef.current = null;
|
|
3404
3678
|
};
|
|
3405
3679
|
const offDelta = events.on("provider.text_delta", (e) => {
|
|
3406
|
-
const text = e.text.replace(/\x1b
|
|
3680
|
+
const text = e.text.replace(/\x1b?\[200~|\x1b?\[201~/g, "");
|
|
3407
3681
|
streamingTextRef.current += text;
|
|
3408
3682
|
pendingDeltaRef.current += text;
|
|
3409
3683
|
if (!flushTimerRef.current) flushTimerRef.current = setTimeout(flush, FLUSH_MS);
|
|
@@ -3594,6 +3868,20 @@ function App({
|
|
|
3594
3868
|
}
|
|
3595
3869
|
});
|
|
3596
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
|
+
});
|
|
3597
3885
|
const offIterationSummary = events.on("subagent.iteration_summary", (e) => {
|
|
3598
3886
|
const lbl = labelFor(e.subagentId);
|
|
3599
3887
|
const costStr = e.costUsd > 0 ? ` \xB7 ${e.costUsd.toFixed(3)}` : "";
|
|
@@ -3626,6 +3914,7 @@ function App({
|
|
|
3626
3914
|
offStarted();
|
|
3627
3915
|
offCompleted();
|
|
3628
3916
|
offBudgetWarning();
|
|
3917
|
+
offBudgetExtended();
|
|
3629
3918
|
offIterationSummary();
|
|
3630
3919
|
offTool();
|
|
3631
3920
|
};
|
|
@@ -3697,6 +3986,8 @@ function App({
|
|
|
3697
3986
|
useEffect(() => {
|
|
3698
3987
|
if (fleetStreamController) fleetStreamController.enabled = state.streamFleet;
|
|
3699
3988
|
}, [state.streamFleet, fleetStreamController]);
|
|
3989
|
+
const lastEscAtRef = useRef(0);
|
|
3990
|
+
const ESC_DOUBLE_PRESS_MS = 1e3;
|
|
3700
3991
|
useEffect(() => {
|
|
3701
3992
|
const d = director;
|
|
3702
3993
|
if (!d) return;
|
|
@@ -3737,7 +4028,7 @@ function App({
|
|
|
3737
4028
|
});
|
|
3738
4029
|
labelFor(s.id, meta?.name ?? s.name);
|
|
3739
4030
|
}
|
|
3740
|
-
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 });
|
|
3741
4032
|
const seen = new Set(Object.keys(status.subagents));
|
|
3742
4033
|
const pending = /* @__PURE__ */ new Map();
|
|
3743
4034
|
let flushTimer = null;
|
|
@@ -3847,7 +4138,7 @@ function App({
|
|
|
3847
4138
|
break;
|
|
3848
4139
|
}
|
|
3849
4140
|
case "provider.response": {
|
|
3850
|
-
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 });
|
|
3851
4142
|
break;
|
|
3852
4143
|
}
|
|
3853
4144
|
case "session.ended":
|
|
@@ -3891,7 +4182,7 @@ function App({
|
|
|
3891
4182
|
iterations: payload.result.iterations,
|
|
3892
4183
|
toolCalls: payload.result.toolCalls
|
|
3893
4184
|
});
|
|
3894
|
-
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 });
|
|
3895
4186
|
if (streamFlushTimer) {
|
|
3896
4187
|
clearTimeout(streamFlushTimer);
|
|
3897
4188
|
flushStreamBufs();
|
|
@@ -3911,14 +4202,16 @@ function App({
|
|
|
3911
4202
|
const current = stateRef.current;
|
|
3912
4203
|
if (current.interrupts >= 1) {
|
|
3913
4204
|
getProcessRegistry().killAll({ force: true });
|
|
3914
|
-
if (current
|
|
3915
|
-
process.exit(130);
|
|
3916
|
-
}
|
|
3917
|
-
try {
|
|
4205
|
+
if (exitRequestedRef.current) {
|
|
3918
4206
|
process.exit(130);
|
|
3919
|
-
} catch {
|
|
3920
4207
|
}
|
|
4208
|
+
exitRequestedRef.current = true;
|
|
3921
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?.();
|
|
3922
4215
|
return;
|
|
3923
4216
|
}
|
|
3924
4217
|
dispatch({ type: "interrupt" });
|
|
@@ -3970,6 +4263,37 @@ function App({
|
|
|
3970
4263
|
});
|
|
3971
4264
|
}
|
|
3972
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
|
+
}
|
|
3973
4297
|
const killed = getProcessRegistry().killAll();
|
|
3974
4298
|
const procTag = killed.length > 0 ? ` Killed ${killed.length} process${killed.length === 1 ? "" : "es"}.` : "";
|
|
3975
4299
|
dispatch({
|
|
@@ -3982,11 +4306,52 @@ function App({
|
|
|
3982
4306
|
return () => {
|
|
3983
4307
|
process.off("SIGINT", onSigint);
|
|
3984
4308
|
};
|
|
3985
|
-
}, [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
|
+
};
|
|
3986
4323
|
const handleKey = async (input, key) => {
|
|
3987
4324
|
if (state.status === "aborting" && state.interrupts === 0) return;
|
|
3988
4325
|
if (state.confirmQueue.length > 0) return;
|
|
3989
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
|
+
}
|
|
3990
4355
|
const isEnter = key.return || input === "\r" || input === "\n";
|
|
3991
4356
|
if (state.modelPicker.open) {
|
|
3992
4357
|
if (key.escape) {
|
|
@@ -4165,6 +4530,14 @@ function App({
|
|
|
4165
4530
|
});
|
|
4166
4531
|
return;
|
|
4167
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
|
+
}
|
|
4168
4541
|
if (isEnter) {
|
|
4169
4542
|
const now = Date.now();
|
|
4170
4543
|
if (now - lastEnterAtRef.current < 50) return;
|
|
@@ -4282,40 +4655,23 @@ function App({
|
|
|
4282
4655
|
return;
|
|
4283
4656
|
}
|
|
4284
4657
|
if (!input || key.ctrl || key.meta) return;
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
if (input.includes("\x1B[200~") || input.includes("\x1B[201~")) {
|
|
4288
|
-
cleanInput = input.replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "");
|
|
4289
|
-
bracketedPaste = true;
|
|
4290
|
-
}
|
|
4291
|
-
if (bracketedPaste || cleanInput.length > PASTE_THRESHOLD_CHARS) {
|
|
4292
|
-
const builder = builderRef.current;
|
|
4293
|
-
if (!builder) return;
|
|
4294
|
-
const ph = await builder.appendPaste(cleanInput);
|
|
4295
|
-
if (ph) {
|
|
4296
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4297
|
-
dispatch({ type: "addPlaceholder", ph: `${ph} (${lineCount} lines)` });
|
|
4298
|
-
} else if (cleanInput.includes("\n")) {
|
|
4299
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4300
|
-
dispatch({ type: "addPlaceholder", ph: `[pasted] (${lineCount} lines)` });
|
|
4301
|
-
} else {
|
|
4302
|
-
const next2 = buffer.slice(0, cursor) + cleanInput + buffer.slice(cursor);
|
|
4303
|
-
setDraft(next2, cursor + cleanInput.length);
|
|
4304
|
-
}
|
|
4658
|
+
if (input.length > PASTE_THRESHOLD_CHARS) {
|
|
4659
|
+
await commitPaste(input);
|
|
4305
4660
|
return;
|
|
4306
4661
|
}
|
|
4307
|
-
if (
|
|
4308
|
-
const normalized =
|
|
4662
|
+
if (input.includes("\n")) {
|
|
4663
|
+
const normalized = input.replace(/\r?\n/g, " ");
|
|
4309
4664
|
const next2 = buffer.slice(0, cursor) + normalized + buffer.slice(cursor);
|
|
4310
4665
|
setDraft(next2, cursor + normalized.length);
|
|
4311
4666
|
return;
|
|
4312
4667
|
}
|
|
4313
|
-
const next = buffer.slice(0, cursor) +
|
|
4314
|
-
setDraft(next, cursor +
|
|
4668
|
+
const next = buffer.slice(0, cursor) + input + buffer.slice(cursor);
|
|
4669
|
+
setDraft(next, cursor + input.length);
|
|
4315
4670
|
};
|
|
4316
4671
|
const runBlocks = async (blocks) => {
|
|
4317
4672
|
const ctrl = new AbortController();
|
|
4318
4673
|
activeCtrlRef.current = ctrl;
|
|
4674
|
+
dispatch({ type: "resetInterrupts" });
|
|
4319
4675
|
dispatch({ type: "status", status: "running" });
|
|
4320
4676
|
try {
|
|
4321
4677
|
const startedAt = Date.now();
|
|
@@ -4711,6 +5067,7 @@ User message:
|
|
|
4711
5067
|
StatusBar,
|
|
4712
5068
|
{
|
|
4713
5069
|
model: `${liveProvider}/${liveModel}`,
|
|
5070
|
+
version: appVersion,
|
|
4714
5071
|
state: state.status,
|
|
4715
5072
|
tokenCounter,
|
|
4716
5073
|
hint: renderRunningTools(state.runningTools) || state.hint,
|
|
@@ -4728,10 +5085,19 @@ User message:
|
|
|
4728
5085
|
subagentCount: Object.keys(state.fleet).length,
|
|
4729
5086
|
processCount: getProcessRegistry().activeCount,
|
|
4730
5087
|
hiddenItems,
|
|
4731
|
-
eternalStage: state.eternalStage
|
|
5088
|
+
eternalStage: state.eternalStage,
|
|
5089
|
+
goalSummary: state.goalSummary
|
|
4732
5090
|
}
|
|
4733
5091
|
),
|
|
4734
|
-
|
|
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
|
|
4735
5101
|
] });
|
|
4736
5102
|
}
|
|
4737
5103
|
function renderRunningTools(running) {
|
|
@@ -4879,7 +5245,8 @@ async function runTui(opts) {
|
|
|
4879
5245
|
initialAsk: opts.initialAsk,
|
|
4880
5246
|
getSDDContext: opts.getSDDContext,
|
|
4881
5247
|
onSDDOutput: opts.onSDDOutput,
|
|
4882
|
-
sessionsDir: opts.sessionsDir
|
|
5248
|
+
sessionsDir: opts.sessionsDir,
|
|
5249
|
+
projectRoot: opts.projectRoot
|
|
4883
5250
|
}),
|
|
4884
5251
|
{ exitOnCtrlC: false }
|
|
4885
5252
|
);
|