@wrongstack/tui 0.7.0 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1199 -651
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -313,6 +313,667 @@ function FleetPanel({ entries, totalCost, roster }) {
|
|
|
313
313
|
}
|
|
314
314
|
);
|
|
315
315
|
}
|
|
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
|
|
338
|
+
}) {
|
|
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" })
|
|
368
|
+
] }) : null,
|
|
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
|
|
425
|
+
] }),
|
|
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(
|
|
431
|
+
Text,
|
|
432
|
+
{
|
|
433
|
+
color: autonomy === "eternal" ? "red" : autonomy === "auto" ? "yellow" : "cyan",
|
|
434
|
+
bold: true,
|
|
435
|
+
children: [
|
|
436
|
+
"\u221E ",
|
|
437
|
+
autonomy.toUpperCase()
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
)
|
|
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
|
+
"%"
|
|
644
|
+
] }),
|
|
645
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
646
|
+
" ",
|
|
647
|
+
"(",
|
|
648
|
+
fmtTok(ctx.used),
|
|
649
|
+
"/",
|
|
650
|
+
fmtTok(ctx.max),
|
|
651
|
+
")"
|
|
652
|
+
] })
|
|
653
|
+
] });
|
|
654
|
+
}
|
|
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);
|
|
670
|
+
}
|
|
671
|
+
function fmtTok(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`;
|
|
675
|
+
}
|
|
676
|
+
function fmtElapsed(ms) {
|
|
677
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
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)}`;
|
|
685
|
+
}
|
|
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
|
+
});
|
|
755
|
+
}
|
|
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
|
+
});
|
|
763
|
+
}
|
|
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
|
+
var STATUS2 = {
|
|
851
|
+
idle: { icon: "\u25CB", color: "gray" },
|
|
852
|
+
running: { icon: "\u25B6", color: "yellow" },
|
|
853
|
+
success: { icon: "\u2713", color: "green" },
|
|
854
|
+
failed: { icon: "\u2717", color: "red" },
|
|
855
|
+
timeout: { icon: "\u23F1", color: "yellow" },
|
|
856
|
+
stopped: { icon: "\u2298", color: "gray" }
|
|
857
|
+
};
|
|
858
|
+
function fmtTokens2(n) {
|
|
859
|
+
if (n < 1e3) return String(n);
|
|
860
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
861
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
862
|
+
}
|
|
863
|
+
function AgentsMonitor({
|
|
864
|
+
entries,
|
|
865
|
+
totalCost,
|
|
866
|
+
totalTokens,
|
|
867
|
+
nowTick
|
|
868
|
+
}) {
|
|
869
|
+
const all = Object.values(entries);
|
|
870
|
+
const running = all.filter((e) => e.status === "running");
|
|
871
|
+
const done = all.filter((e) => e.status === "success").length;
|
|
872
|
+
const failed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
873
|
+
const maxTools = Math.max(1, ...all.map((e) => e.toolCalls));
|
|
874
|
+
const ordered = [...all].sort((a, b) => {
|
|
875
|
+
const ra = a.status === "running" ? 0 : a.status === "idle" ? 1 : 2;
|
|
876
|
+
const rb = b.status === "running" ? 0 : b.status === "idle" ? 1 : 2;
|
|
877
|
+
if (ra !== rb) return ra - rb;
|
|
878
|
+
return a.startedAt - b.startedAt;
|
|
879
|
+
});
|
|
880
|
+
const shown = ordered.slice(0, 20);
|
|
881
|
+
const events = [];
|
|
882
|
+
for (const e of all) {
|
|
883
|
+
events.push({ at: e.startedAt, icon: "\u25CF", color: "cyan", text: `${e.name} spawned` });
|
|
884
|
+
if (e.status !== "running" && e.status !== "idle") {
|
|
885
|
+
const s = STATUS2[e.status];
|
|
886
|
+
events.push({
|
|
887
|
+
at: e.lastEventAt,
|
|
888
|
+
icon: s.icon,
|
|
889
|
+
color: s.color,
|
|
890
|
+
text: `${e.name} ${e.status} (${e.toolCalls}t)`
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
if (e.budgetWarning) {
|
|
894
|
+
events.push({
|
|
895
|
+
at: e.budgetWarning.at,
|
|
896
|
+
icon: "\u26A1",
|
|
897
|
+
color: "yellow",
|
|
898
|
+
text: `${e.name} ${e.budgetWarning.kind} ${e.budgetWarning.used}/${e.budgetWarning.limit} \u2014 extending`
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
events.sort((a, b) => b.at - a.at);
|
|
903
|
+
const timeline = events.slice(0, 6);
|
|
904
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
905
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
906
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS MONITOR" }),
|
|
907
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
908
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
909
|
+
"\u25B6",
|
|
910
|
+
running.length
|
|
911
|
+
] }),
|
|
912
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
913
|
+
"\u2713",
|
|
914
|
+
done
|
|
915
|
+
] }),
|
|
916
|
+
failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
917
|
+
"\u2717",
|
|
918
|
+
failed
|
|
919
|
+
] }) : null,
|
|
920
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Ctrl+Shift+M to close" })
|
|
921
|
+
] }),
|
|
922
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
923
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "agents" }),
|
|
924
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: all.length }),
|
|
925
|
+
totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
926
|
+
fmtTokens2(totalTokens.input),
|
|
927
|
+
"\u2191 ",
|
|
928
|
+
fmtTokens2(totalTokens.output),
|
|
929
|
+
"\u2193"
|
|
930
|
+
] }) : null,
|
|
931
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: ` $${totalCost.toFixed(3)}` })
|
|
932
|
+
] }),
|
|
933
|
+
shown.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No subagents yet \u2014 spawn with /spawn or /fleet dispatch." }) : null,
|
|
934
|
+
shown.map((e) => {
|
|
935
|
+
const s = STATUS2[e.status];
|
|
936
|
+
const elapsed = e.status === "running" ? fmtElapsed(Math.max(0, nowTick - e.startedAt)) : e.status;
|
|
937
|
+
const spark = sparkline(bucketActivity(e.recentTools, nowTick));
|
|
938
|
+
const tool = e.currentTool?.name ?? e.recentTools[e.recentTools.length - 1]?.name ?? "";
|
|
939
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
940
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
941
|
+
/* @__PURE__ */ jsx(Text, { color: s.color, bold: true, children: s.icon }),
|
|
942
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: e.name.padEnd(14).slice(0, 14) }),
|
|
943
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed.padEnd(8).slice(0, 8) }),
|
|
944
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: renderProgress(e.toolCalls / maxTools, 10) }),
|
|
945
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
946
|
+
"L",
|
|
947
|
+
e.iterations,
|
|
948
|
+
" ",
|
|
949
|
+
e.toolCalls,
|
|
950
|
+
"t"
|
|
951
|
+
] }),
|
|
952
|
+
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
953
|
+
"\u26A1\xD7",
|
|
954
|
+
e.extensions
|
|
955
|
+
] }) : null
|
|
956
|
+
] }),
|
|
957
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
958
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
959
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: spark }),
|
|
960
|
+
tool ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: tool }) : null
|
|
961
|
+
] })
|
|
962
|
+
] }, e.id);
|
|
963
|
+
}),
|
|
964
|
+
timeline.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
965
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "timeline" }),
|
|
966
|
+
timeline.map((ev, i) => (
|
|
967
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
|
|
968
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
969
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
970
|
+
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
971
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
972
|
+
] }, i)
|
|
973
|
+
))
|
|
974
|
+
] }) : null
|
|
975
|
+
] });
|
|
976
|
+
}
|
|
316
977
|
|
|
317
978
|
// src/markdown-table.ts
|
|
318
979
|
function renderMarkdownTables(text, maxWidth) {
|
|
@@ -602,10 +1263,16 @@ function Entry({
|
|
|
602
1263
|
switch (entry.kind) {
|
|
603
1264
|
case "user":
|
|
604
1265
|
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
605
|
-
/* @__PURE__ */ jsx(Text, {
|
|
606
|
-
|
|
607
|
-
/* @__PURE__ */ jsx(Text, { dimColor:
|
|
608
|
-
entry.
|
|
1266
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "USER: " }),
|
|
1267
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: entry.text }),
|
|
1268
|
+
entry.queued ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (queued)" }) : null,
|
|
1269
|
+
entry.pasteContent ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1270
|
+
entry.text ? "\n" : null,
|
|
1271
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1272
|
+
" \u21B3 ",
|
|
1273
|
+
entry.pasteContent
|
|
1274
|
+
] })
|
|
1275
|
+
] }) : null
|
|
609
1276
|
] });
|
|
610
1277
|
case "assistant":
|
|
611
1278
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
@@ -632,7 +1299,7 @@ function Entry({
|
|
|
632
1299
|
parts.push(fmtBytes2(entry.outputBytes));
|
|
633
1300
|
}
|
|
634
1301
|
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
635
|
-
parts.push(`\u2248${
|
|
1302
|
+
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
636
1303
|
}
|
|
637
1304
|
return parts.join(" \xB7 ");
|
|
638
1305
|
})();
|
|
@@ -751,7 +1418,7 @@ function shortenPath(p, max) {
|
|
|
751
1418
|
if (p.length <= max) return p;
|
|
752
1419
|
return `\u2026${p.slice(p.length - (max - 1))}`;
|
|
753
1420
|
}
|
|
754
|
-
function
|
|
1421
|
+
function fmtTok2(n) {
|
|
755
1422
|
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
756
1423
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
757
1424
|
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
@@ -1361,623 +2028,279 @@ function parseUnifiedDiff(diff, maxLines) {
|
|
|
1361
2028
|
function stringOf(v) {
|
|
1362
2029
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
1363
2030
|
}
|
|
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;
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
function scanNumberedRange(text) {
|
|
1377
|
-
let first;
|
|
1378
|
-
let last;
|
|
1379
|
-
let count = 0;
|
|
1380
|
-
for (const line of text.split("\n")) {
|
|
1381
|
-
const m = line.match(/^\s*(\d+)→/);
|
|
1382
|
-
if (m?.[1]) {
|
|
1383
|
-
const n = Number.parseInt(m[1], 10);
|
|
1384
|
-
if (Number.isFinite(n)) {
|
|
1385
|
-
if (first === void 0) first = n;
|
|
1386
|
-
last = n;
|
|
1387
|
-
count++;
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
return { first, last, count };
|
|
1392
|
-
}
|
|
1393
|
-
function countLines(text) {
|
|
1394
|
-
if (!text) return 0;
|
|
1395
|
-
return text.replace(/\n$/, "").split("\n").length;
|
|
1396
|
-
}
|
|
1397
|
-
function fmtBytes2(n) {
|
|
1398
|
-
if (n < 1024) return `${n}B`;
|
|
1399
|
-
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
1400
|
-
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
1401
|
-
}
|
|
1402
|
-
function truncMid(s, max) {
|
|
1403
|
-
if (s.length <= max) return s;
|
|
1404
|
-
return `${s.slice(0, max - 1)}\u2026`;
|
|
1405
|
-
}
|
|
1406
|
-
function isHomeEnd(data) {
|
|
1407
|
-
if (data === "\x1B[H" || data === "\x1B[1~" || data === "\x1BOH" || data === "\x1B[7~")
|
|
1408
|
-
return "home";
|
|
1409
|
-
if (data === "\x1B[F" || data === "\x1B[4~" || data === "\x1BOF" || data === "\x1B[8~")
|
|
1410
|
-
return "end";
|
|
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
|
-
] });
|
|
2031
|
+
function numOf(v) {
|
|
2032
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
1552
2033
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
{
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
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
|
-
] });
|
|
2034
|
+
function tryParseJson(s) {
|
|
2035
|
+
const t = s.trimStart();
|
|
2036
|
+
if (!t.startsWith("{") && !t.startsWith("[")) return void 0;
|
|
2037
|
+
try {
|
|
2038
|
+
return JSON.parse(s);
|
|
2039
|
+
} catch {
|
|
2040
|
+
return void 0;
|
|
2041
|
+
}
|
|
1571
2042
|
}
|
|
1572
|
-
function
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
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
|
-
] });
|
|
2043
|
+
function scanNumberedRange(text) {
|
|
2044
|
+
let first;
|
|
2045
|
+
let last;
|
|
2046
|
+
let count = 0;
|
|
2047
|
+
for (const line of text.split("\n")) {
|
|
2048
|
+
const m = line.match(/^\s*(\d+)→/);
|
|
2049
|
+
if (m?.[1]) {
|
|
2050
|
+
const n = Number.parseInt(m[1], 10);
|
|
2051
|
+
if (Number.isFinite(n)) {
|
|
2052
|
+
if (first === void 0) first = n;
|
|
2053
|
+
last = n;
|
|
2054
|
+
count++;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
1601
2057
|
}
|
|
1602
|
-
return
|
|
1603
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
1604
|
-
"\u2501\u2501 Switch model \u2014 Step 2/2: Pick model (",
|
|
1605
|
-
pickedProviderId,
|
|
1606
|
-
") \u2501\u2501"
|
|
1607
|
-
] }),
|
|
1608
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc back \xB7 Ctrl+C exit" }),
|
|
1609
|
-
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: [
|
|
1610
|
-
i === selected ? "\u203A " : " ",
|
|
1611
|
-
id
|
|
1612
|
-
] }, id)),
|
|
1613
|
-
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
1614
|
-
] });
|
|
2058
|
+
return { first, last, count };
|
|
1615
2059
|
}
|
|
1616
|
-
function
|
|
1617
|
-
|
|
1618
|
-
return
|
|
1619
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1620
|
-
placeholder || "/",
|
|
1621
|
-
" \u2014 \u2191/\u2193 select, Enter dispatch, Tab autocomplete, Esc close"
|
|
1622
|
-
] }),
|
|
1623
|
-
matches.map((m, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
1624
|
-
i === selected ? "\u203A " : " ",
|
|
1625
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: m.name }),
|
|
1626
|
-
m.argsHint ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1627
|
-
" ",
|
|
1628
|
-
m.argsHint
|
|
1629
|
-
] }) : null,
|
|
1630
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1631
|
-
" \u2014 ",
|
|
1632
|
-
m.description
|
|
1633
|
-
] })
|
|
1634
|
-
] }, m.name)),
|
|
1635
|
-
matches.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No matching commands" })
|
|
1636
|
-
] });
|
|
2060
|
+
function countLines(text) {
|
|
2061
|
+
if (!text) return 0;
|
|
2062
|
+
return text.replace(/\n$/, "").split("\n").length;
|
|
1637
2063
|
}
|
|
1638
|
-
function
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
2064
|
+
function fmtBytes2(n) {
|
|
2065
|
+
if (n < 1024) return `${n}B`;
|
|
2066
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
2067
|
+
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
2068
|
+
}
|
|
2069
|
+
function truncMid(s, max) {
|
|
2070
|
+
if (s.length <= max) return s;
|
|
2071
|
+
return `${s.slice(0, max - 1)}\u2026`;
|
|
2072
|
+
}
|
|
2073
|
+
function isHomeEnd(data) {
|
|
2074
|
+
if (data === "\x1B[H" || data === "\x1B[1~" || data === "\x1BOH" || data === "\x1B[7~")
|
|
2075
|
+
return "home";
|
|
2076
|
+
if (data === "\x1B[F" || data === "\x1B[4~" || data === "\x1BOF" || data === "\x1B[8~")
|
|
2077
|
+
return "end";
|
|
2078
|
+
return null;
|
|
2079
|
+
}
|
|
2080
|
+
var EMPTY_KEY = {
|
|
2081
|
+
upArrow: false,
|
|
2082
|
+
downArrow: false,
|
|
2083
|
+
leftArrow: false,
|
|
2084
|
+
rightArrow: false,
|
|
2085
|
+
return: false,
|
|
2086
|
+
escape: false,
|
|
2087
|
+
ctrl: false,
|
|
2088
|
+
meta: false,
|
|
2089
|
+
shift: false,
|
|
2090
|
+
tab: false,
|
|
2091
|
+
backspace: false,
|
|
2092
|
+
delete: false,
|
|
2093
|
+
pageUp: false,
|
|
2094
|
+
pageDown: false,
|
|
2095
|
+
home: false,
|
|
2096
|
+
end: false
|
|
2097
|
+
};
|
|
2098
|
+
function Input({
|
|
2099
|
+
prompt = "\u203A ",
|
|
2100
|
+
value,
|
|
2101
|
+
cursor,
|
|
2102
|
+
placeholders,
|
|
2103
|
+
disabled,
|
|
1642
2104
|
hint,
|
|
1643
|
-
|
|
1644
|
-
yolo = false,
|
|
1645
|
-
autonomy,
|
|
1646
|
-
elapsedMs,
|
|
1647
|
-
todos,
|
|
1648
|
-
plan,
|
|
1649
|
-
fleet,
|
|
1650
|
-
fleetAgents,
|
|
1651
|
-
git,
|
|
1652
|
-
subagentCount = 0,
|
|
1653
|
-
context,
|
|
1654
|
-
projectName,
|
|
1655
|
-
processCount,
|
|
1656
|
-
hiddenItems,
|
|
1657
|
-
eternalStage,
|
|
1658
|
-
goalSummary
|
|
2105
|
+
onKey
|
|
1659
2106
|
}) {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
const
|
|
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
|
-
|
|
2107
|
+
useInput((input, key) => {
|
|
2108
|
+
if (disabled) return;
|
|
2109
|
+
onKey(input, key);
|
|
2110
|
+
});
|
|
2111
|
+
const { stdin } = useStdin();
|
|
2112
|
+
useEffect(() => {
|
|
2113
|
+
if (!stdin || disabled) return;
|
|
2114
|
+
const handleData = (data) => {
|
|
2115
|
+
const kind = isHomeEnd(data.toString());
|
|
2116
|
+
if (kind === "home") onKey("", { ...EMPTY_KEY, home: true });
|
|
2117
|
+
else if (kind === "end") onKey("", { ...EMPTY_KEY, end: true });
|
|
2118
|
+
};
|
|
2119
|
+
stdin.on("data", handleData);
|
|
2120
|
+
return () => {
|
|
2121
|
+
stdin.off("data", handleData);
|
|
2122
|
+
};
|
|
2123
|
+
}, [stdin, disabled, onKey]);
|
|
2124
|
+
const before = value.slice(0, cursor);
|
|
2125
|
+
const at = value.slice(cursor, cursor + 1) || " ";
|
|
2126
|
+
const after = value.slice(cursor + 1);
|
|
2127
|
+
const promptColor = disabled ? "red" : "cyan";
|
|
2128
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2129
|
+
placeholders.map((p, i) => (
|
|
2130
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: placeholders are append-only, index is stable
|
|
2131
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2132
|
+
" \u21B3 ",
|
|
2133
|
+
p
|
|
2134
|
+
] }, i)
|
|
2135
|
+
)),
|
|
2136
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2137
|
+
/* @__PURE__ */ jsx(Text, { color: promptColor, children: prompt }),
|
|
2138
|
+
before,
|
|
2139
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: at }),
|
|
2140
|
+
after
|
|
2141
|
+
] }),
|
|
2142
|
+
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
2143
|
+
] });
|
|
2144
|
+
}
|
|
2145
|
+
function fmtElapsed2(ms) {
|
|
2146
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
2147
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
2148
|
+
const m = Math.floor(ms / 6e4);
|
|
2149
|
+
const s = Math.floor(ms % 6e4 / 1e3);
|
|
2150
|
+
return `${m}m${s.toString().padStart(2, "0")}s`;
|
|
2151
|
+
}
|
|
2152
|
+
function fmtBytes3(n) {
|
|
2153
|
+
if (n < 1024) return `${n}B`;
|
|
2154
|
+
return `${(n / 1024).toFixed(1)}KB`;
|
|
2155
|
+
}
|
|
2156
|
+
function fmtRecentTool2(tool) {
|
|
2157
|
+
const status = tool.ok === false ? "fail" : "ok";
|
|
2158
|
+
const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
|
|
2159
|
+
const parts = [status, name];
|
|
2160
|
+
if (typeof tool.durationMs === "number") parts.push(fmtElapsed2(tool.durationMs));
|
|
2161
|
+
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes3(tool.outputBytes));
|
|
2162
|
+
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
2163
|
+
return parts.join(" ");
|
|
2164
|
+
}
|
|
2165
|
+
function fmtRecentMessage2(message) {
|
|
2166
|
+
const text = message.text.replace(/\s+/g, " ");
|
|
2167
|
+
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
2168
|
+
}
|
|
2169
|
+
function LiveActivityStrip({
|
|
2170
|
+
entries,
|
|
2171
|
+
nowTick,
|
|
2172
|
+
maxRows = 4
|
|
2173
|
+
}) {
|
|
2174
|
+
const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt).slice(0, maxRows);
|
|
2175
|
+
if (running.length === 0) return null;
|
|
2176
|
+
const now = Date.now();
|
|
2177
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2178
|
+
running.map((e) => {
|
|
2179
|
+
const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
|
|
2180
|
+
const taskElapsed = now - e.startedAt;
|
|
2181
|
+
const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed2(toolElapsed)})` : "idle between tools";
|
|
2182
|
+
const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool2).join(" | ");
|
|
2183
|
+
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage2).join("");
|
|
2184
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2185
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25CF" }),
|
|
2186
|
+
/* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
|
|
2187
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2188
|
+
/* @__PURE__ */ jsx(Text, { color: e.currentTool ? "green" : "yellow", children: toolSeg }),
|
|
2189
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
2190
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2191
|
+
e.iterations,
|
|
2192
|
+
"it ",
|
|
2193
|
+
e.toolCalls,
|
|
2194
|
+
"tc \xB7 ",
|
|
2195
|
+
fmtElapsed2(taskElapsed)
|
|
1737
2196
|
] }),
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
{
|
|
1745
|
-
color: autonomy === "eternal" ? "red" : autonomy === "auto" ? "yellow" : "cyan",
|
|
1746
|
-
bold: true,
|
|
1747
|
-
children: [
|
|
1748
|
-
"\u221E ",
|
|
1749
|
-
autonomy.toUpperCase()
|
|
1750
|
-
]
|
|
1751
|
-
}
|
|
1752
|
-
)
|
|
1753
|
-
] }) : null,
|
|
1754
|
-
eternalStage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1755
|
-
yolo || autonomy && autonomy !== "off" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1756
|
-
/* @__PURE__ */ jsx(EternalStageChip, { stage: eternalStage })
|
|
1757
|
-
] }) : null,
|
|
1758
|
-
elapsedMs !== void 0 && !hiddenSet.has("elapsed") ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1759
|
-
yolo || autonomy && autonomy !== "off" || eternalStage ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1760
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1761
|
-
"\u23F1 ",
|
|
1762
|
-
fmtElapsed2(elapsedMs)
|
|
1763
|
-
] })
|
|
1764
|
-
] }) : null,
|
|
1765
|
-
projectName ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1766
|
-
yolo || elapsedMs !== void 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1767
|
-
/* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
1768
|
-
"\u{1F4C1} ",
|
|
1769
|
-
projectName
|
|
1770
|
-
] })
|
|
1771
|
-
] }) : null,
|
|
1772
|
-
goalSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1773
|
-
yolo || elapsedMs !== void 0 || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1774
|
-
/* @__PURE__ */ jsxs(Text, { color: goalSummary.goalState === "active" ? "green" : goalSummary.goalState === "paused" ? "yellow" : goalSummary.goalState === "completed" ? "green" : "dim", children: [
|
|
1775
|
-
"\u{1F3AF} ",
|
|
1776
|
-
goalSummary.goal.length > 40 ? `${goalSummary.goal.slice(0, 37)}\u2026` : goalSummary.goal,
|
|
1777
|
-
" [",
|
|
1778
|
-
goalSummary.goalState,
|
|
1779
|
-
"] (iter ",
|
|
1780
|
-
goalSummary.iterations,
|
|
1781
|
-
")"
|
|
1782
|
-
] })
|
|
1783
|
-
] }) : null,
|
|
1784
|
-
git ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1785
|
-
yolo || elapsedMs !== void 0 || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1786
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1787
|
-
/* @__PURE__ */ jsxs(Text, { color: "magenta", children: [
|
|
1788
|
-
"\u2387 ",
|
|
1789
|
-
git.branch
|
|
1790
|
-
] }),
|
|
1791
|
-
git.added > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1792
|
-
" +",
|
|
1793
|
-
git.added
|
|
1794
|
-
] }) : null,
|
|
1795
|
-
git.deleted > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
1796
|
-
" -",
|
|
1797
|
-
git.deleted
|
|
1798
|
-
] }) : null,
|
|
1799
|
-
git.untracked > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1800
|
-
" ?",
|
|
1801
|
-
git.untracked
|
|
1802
|
-
] }) : null
|
|
1803
|
-
] })
|
|
1804
|
-
] }) : null
|
|
1805
|
-
] }) : null,
|
|
1806
|
-
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
1807
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1808
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
|
|
1809
|
-
todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1810
|
-
"\u231B",
|
|
1811
|
-
todos.inProgress
|
|
1812
|
-
] }) : null,
|
|
1813
|
-
todos.inProgress > 0 && (todos.pending > 0 || todos.completed > 0) ? " " : "",
|
|
1814
|
-
todos.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1815
|
-
"\u2610",
|
|
1816
|
-
todos.pending
|
|
1817
|
-
] }) : null,
|
|
1818
|
-
todos.pending > 0 && todos.completed > 0 ? " " : "",
|
|
1819
|
-
todos.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1820
|
-
"\u2713",
|
|
1821
|
-
todos.completed
|
|
1822
|
-
] }) : null
|
|
1823
|
-
] }) : null,
|
|
1824
|
-
plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1825
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1826
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1827
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u{1F4CB} " }),
|
|
1828
|
-
plan.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1829
|
-
"\u231B",
|
|
1830
|
-
plan.inProgress
|
|
1831
|
-
] }) : null,
|
|
1832
|
-
plan.inProgress > 0 && (plan.open > 0 || plan.done > 0) ? " " : "",
|
|
1833
|
-
plan.open > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1834
|
-
"\u2610",
|
|
1835
|
-
plan.open
|
|
1836
|
-
] }) : null,
|
|
1837
|
-
plan.open > 0 && plan.done > 0 ? " " : "",
|
|
1838
|
-
plan.done > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1839
|
-
"\u2713",
|
|
1840
|
-
plan.done
|
|
1841
|
-
] }) : null
|
|
1842
|
-
] })
|
|
1843
|
-
] }) : null,
|
|
1844
|
-
fleetHasActivity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1845
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
1846
|
-
fleet ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
1847
|
-
/* @__PURE__ */ jsx(Text, { color: "blue", children: "\u{1F310} " }),
|
|
1848
|
-
fleet.running > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
1849
|
-
"\u25B6",
|
|
1850
|
-
fleet.running
|
|
1851
|
-
] }) : null,
|
|
1852
|
-
fleet.running > 0 && (fleet.pending > 0 || fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1853
|
-
fleet.pending > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1854
|
-
"\u2610",
|
|
1855
|
-
fleet.pending
|
|
1856
|
-
] }) : null,
|
|
1857
|
-
fleet.pending > 0 && (fleet.idle > 0 || fleet.completed > 0) ? " " : "",
|
|
1858
|
-
fleet.idle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1859
|
-
"\xB7",
|
|
1860
|
-
fleet.idle,
|
|
1861
|
-
"idle"
|
|
1862
|
-
] }) : null,
|
|
1863
|
-
fleet.idle > 0 && fleet.completed > 0 ? " " : "",
|
|
1864
|
-
fleet.completed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
1865
|
-
"\u2713",
|
|
1866
|
-
fleet.completed
|
|
1867
|
-
] }) : null
|
|
1868
|
-
] }) : /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
|
|
1869
|
-
"\u{1F310} ",
|
|
1870
|
-
subagentCount,
|
|
1871
|
-
" agent",
|
|
1872
|
-
subagentCount === 1 ? "" : "s"
|
|
1873
|
-
] })
|
|
1874
|
-
] }) : null
|
|
2197
|
+
recentTools ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2198
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2199
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2200
|
+
"last: ",
|
|
2201
|
+
recentTools
|
|
2202
|
+
] })
|
|
1875
2203
|
] }) : null,
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
)
|
|
2204
|
+
messageText ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2205
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2206
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2207
|
+
"msg: ",
|
|
2208
|
+
fmtRecentMessage2({ text: messageText})
|
|
2209
|
+
] })
|
|
2210
|
+
] }) : null
|
|
2211
|
+
] }, e.id);
|
|
2212
|
+
}),
|
|
2213
|
+
Object.values(entries).filter((e) => e.status === "running").length > maxRows ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2214
|
+
"\u2026+",
|
|
2215
|
+
Object.values(entries).filter((e) => e.status === "running").length - maxRows,
|
|
2216
|
+
" more"
|
|
2217
|
+
] }) }) : null
|
|
2218
|
+
] });
|
|
2219
|
+
}
|
|
2220
|
+
var AUTONOMY_OPTIONS = [
|
|
2221
|
+
{ mode: "off", label: "OFF", description: "Agent stops after each turn (normal interactive mode)", color: "green" },
|
|
2222
|
+
{ mode: "suggest", label: "SUGGEST", description: "Shows next-step suggestions after each turn", color: "cyan" },
|
|
2223
|
+
{ mode: "auto", label: "AUTO", description: "Self-driving \u2014 agent picks next step and continues", color: "yellow" },
|
|
2224
|
+
{ mode: "eternal", label: "ETERNAL", description: "Goal-driven loop \u2014 requires /goal set first", color: "red" },
|
|
2225
|
+
{ mode: "eternal-parallel", label: "PARALLEL", description: "Fan-out 4\u20138 subagents per tick \u2014 requires /goal", color: "magenta" }
|
|
2226
|
+
];
|
|
2227
|
+
function AutonomyPicker({ options, selected, hint }) {
|
|
2228
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2229
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Autonomy Mode \u2501\u2501" }),
|
|
2230
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
2231
|
+
options.map((opt, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? opt.color : void 0, inverse: i === selected, children: [
|
|
2232
|
+
i === selected ? "\u203A " : " ",
|
|
2233
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.label.padEnd(12) }),
|
|
2234
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: opt.description })
|
|
2235
|
+
] }, opt.mode)),
|
|
2236
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
2237
|
+
] });
|
|
1894
2238
|
}
|
|
1895
|
-
function
|
|
1896
|
-
|
|
2239
|
+
function ModelPicker({
|
|
2240
|
+
step,
|
|
2241
|
+
providerOptions,
|
|
2242
|
+
modelOptions,
|
|
2243
|
+
selected,
|
|
2244
|
+
pickedProviderId,
|
|
2245
|
+
hint
|
|
1897
2246
|
}) {
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
"\
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
] })
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
"\u{1F4A4} sleep ",
|
|
1920
|
-
Math.round(stage.ms / 1e3),
|
|
1921
|
-
"s"
|
|
1922
|
-
] });
|
|
1923
|
-
case "paused":
|
|
1924
|
-
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u23F8 paused" });
|
|
1925
|
-
case "stopped":
|
|
1926
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25A0 stopped" });
|
|
1927
|
-
case "error":
|
|
1928
|
-
return /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
1929
|
-
"\u26A0 error: ",
|
|
1930
|
-
stage.message
|
|
1931
|
-
] });
|
|
2247
|
+
if (step === "provider") {
|
|
2248
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2249
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Switch model \u2014 Step 1/2: Pick provider \u2501\u2501" }),
|
|
2250
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel \xB7 Ctrl+C exit" }),
|
|
2251
|
+
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: [
|
|
2252
|
+
i === selected ? "\u203A " : " ",
|
|
2253
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: p.id.padEnd(28) }),
|
|
2254
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2255
|
+
" [",
|
|
2256
|
+
p.family,
|
|
2257
|
+
"]"
|
|
2258
|
+
] }),
|
|
2259
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2260
|
+
" ",
|
|
2261
|
+
p.models.length,
|
|
2262
|
+
" model",
|
|
2263
|
+
p.models.length === 1 ? "" : "s"
|
|
2264
|
+
] })
|
|
2265
|
+
] }, p.id)),
|
|
2266
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
2267
|
+
] });
|
|
1932
2268
|
}
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
1939
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "ctx " }),
|
|
1940
|
-
/* @__PURE__ */ jsx(Text, { color, children: renderProgress(ratio, 10) }),
|
|
1941
|
-
/* @__PURE__ */ jsxs(Text, { color, children: [
|
|
1942
|
-
" ",
|
|
1943
|
-
pct,
|
|
1944
|
-
"%"
|
|
2269
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2270
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
2271
|
+
"\u2501\u2501 Switch model \u2014 Step 2/2: Pick model (",
|
|
2272
|
+
pickedProviderId,
|
|
2273
|
+
") \u2501\u2501"
|
|
1945
2274
|
] }),
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
|
|
1948
|
-
"
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
")"
|
|
1953
|
-
] })
|
|
2275
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate \xB7 Enter select \xB7 Esc back \xB7 Ctrl+C exit" }),
|
|
2276
|
+
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: [
|
|
2277
|
+
i === selected ? "\u203A " : " ",
|
|
2278
|
+
id
|
|
2279
|
+
] }, id)),
|
|
2280
|
+
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
1954
2281
|
] });
|
|
1955
2282
|
}
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
}
|
|
1977
|
-
return `${pad2(m)}:${pad2(s)}`;
|
|
1978
|
-
}
|
|
1979
|
-
function pad2(n) {
|
|
1980
|
-
return n < 10 ? `0${n}` : String(n);
|
|
2283
|
+
function SlashMenu({ query, matches, selected }) {
|
|
2284
|
+
const placeholder = query ? `/${query}` : "/";
|
|
2285
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2286
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2287
|
+
placeholder || "/",
|
|
2288
|
+
" \u2014 \u2191/\u2193 select, Enter dispatch, Tab autocomplete, Esc close"
|
|
2289
|
+
] }),
|
|
2290
|
+
matches.map((m, i) => /* @__PURE__ */ jsxs(Text, { color: i === selected ? "cyan" : void 0, inverse: i === selected, children: [
|
|
2291
|
+
i === selected ? "\u203A " : " ",
|
|
2292
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: m.name }),
|
|
2293
|
+
m.argsHint ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2294
|
+
" ",
|
|
2295
|
+
m.argsHint
|
|
2296
|
+
] }) : null,
|
|
2297
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2298
|
+
" \u2014 ",
|
|
2299
|
+
m.description
|
|
2300
|
+
] })
|
|
2301
|
+
] }, m.name)),
|
|
2302
|
+
matches.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No matching commands" })
|
|
2303
|
+
] });
|
|
1981
2304
|
}
|
|
1982
2305
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
1983
2306
|
"node_modules",
|
|
@@ -2057,6 +2380,19 @@ async function searchFiles(root, query, limit = 8) {
|
|
|
2057
2380
|
scored.sort((a, b) => a.score - b.score);
|
|
2058
2381
|
return scored.slice(0, limit).map((x) => x.path);
|
|
2059
2382
|
}
|
|
2383
|
+
|
|
2384
|
+
// src/paste-accumulator.ts
|
|
2385
|
+
var BEGIN = "[200~";
|
|
2386
|
+
var END = "[201~";
|
|
2387
|
+
var BEGIN_RE = /\x1b?\[200~/g;
|
|
2388
|
+
var END_RE = /\x1b?\[201~/g;
|
|
2389
|
+
function feedPaste(accum, input) {
|
|
2390
|
+
if (accum === null && !input.includes(BEGIN)) return null;
|
|
2391
|
+
const piece = input.replace(BEGIN_RE, "").replace(END_RE, "");
|
|
2392
|
+
const next = (accum ?? "") + piece;
|
|
2393
|
+
if (input.includes(END)) return { accum: null, complete: next };
|
|
2394
|
+
return { accum: next, complete: null };
|
|
2395
|
+
}
|
|
2060
2396
|
async function readGitInfo(cwd) {
|
|
2061
2397
|
const [branchRes, numstatRes, statusRes] = await Promise.all([
|
|
2062
2398
|
runGit(cwd, ["branch", "--show-current"]),
|
|
@@ -2298,20 +2634,31 @@ function reducer(state, action) {
|
|
|
2298
2634
|
case "setBuffer":
|
|
2299
2635
|
return { ...state, buffer: action.buffer, cursor: action.cursor };
|
|
2300
2636
|
case "addPlaceholder":
|
|
2301
|
-
return {
|
|
2637
|
+
return {
|
|
2638
|
+
...state,
|
|
2639
|
+
placeholders: [...state.placeholders, action.ph],
|
|
2640
|
+
placeholderContents: [...state.placeholderContents, action.content ?? ""]
|
|
2641
|
+
};
|
|
2302
2642
|
case "removeLastPlaceholder":
|
|
2303
2643
|
if (state.placeholders.length === 0) return state;
|
|
2304
|
-
return {
|
|
2644
|
+
return {
|
|
2645
|
+
...state,
|
|
2646
|
+
placeholders: state.placeholders.slice(0, -1),
|
|
2647
|
+
placeholderContents: state.placeholderContents.slice(0, -1)
|
|
2648
|
+
};
|
|
2305
2649
|
case "clearInput":
|
|
2306
2650
|
return {
|
|
2307
2651
|
...state,
|
|
2308
2652
|
buffer: "",
|
|
2309
2653
|
cursor: 0,
|
|
2310
2654
|
placeholders: [],
|
|
2655
|
+
placeholderContents: [],
|
|
2311
2656
|
historyIndex: 0,
|
|
2312
2657
|
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
2313
2658
|
slashPicker: { open: false, query: "", matches: [], selected: 0 }
|
|
2314
2659
|
};
|
|
2660
|
+
case "clearPlaceholdersOnly":
|
|
2661
|
+
return { ...state, placeholders: [], placeholderContents: [] };
|
|
2315
2662
|
case "clearHistory": {
|
|
2316
2663
|
const last = state.entries[state.entries.length - 1];
|
|
2317
2664
|
return {
|
|
@@ -2732,12 +3079,39 @@ function reducer(state, action) {
|
|
|
2732
3079
|
}
|
|
2733
3080
|
};
|
|
2734
3081
|
}
|
|
3082
|
+
case "fleetBudgetExtended": {
|
|
3083
|
+
const cur = state.fleet[action.id];
|
|
3084
|
+
if (!cur) return state;
|
|
3085
|
+
return {
|
|
3086
|
+
...state,
|
|
3087
|
+
fleet: {
|
|
3088
|
+
...state.fleet,
|
|
3089
|
+
[action.id]: {
|
|
3090
|
+
...cur,
|
|
3091
|
+
// The director sends the authoritative cumulative count; trust it
|
|
3092
|
+
// over a local increment so a dropped event can't desync the badge.
|
|
3093
|
+
extensions: action.totalExtensions,
|
|
3094
|
+
lastEventAt: Date.now()
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
2735
3099
|
case "fleetCost": {
|
|
2736
|
-
return {
|
|
3100
|
+
return {
|
|
3101
|
+
...state,
|
|
3102
|
+
fleetCost: action.cost,
|
|
3103
|
+
fleetTokens: action.input !== void 0 || action.output !== void 0 ? { input: action.input ?? state.fleetTokens.input, output: action.output ?? state.fleetTokens.output } : state.fleetTokens
|
|
3104
|
+
};
|
|
2737
3105
|
}
|
|
2738
3106
|
case "setStreamFleet": {
|
|
2739
3107
|
return { ...state, streamFleet: action.enabled };
|
|
2740
3108
|
}
|
|
3109
|
+
case "toggleMonitor": {
|
|
3110
|
+
return { ...state, monitorOpen: !state.monitorOpen };
|
|
3111
|
+
}
|
|
3112
|
+
case "toggleAgentsMonitor": {
|
|
3113
|
+
return { ...state, agentsMonitorOpen: !state.agentsMonitorOpen };
|
|
3114
|
+
}
|
|
2741
3115
|
case "checkpointReceived": {
|
|
2742
3116
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
2743
3117
|
if (existing) return state;
|
|
@@ -2859,7 +3233,7 @@ function App({
|
|
|
2859
3233
|
}, [statuslineHiddenItems]);
|
|
2860
3234
|
useEffect(() => {
|
|
2861
3235
|
setStatuslineHiddenItems(hiddenItems);
|
|
2862
|
-
}, [setStatuslineHiddenItems]);
|
|
3236
|
+
}, [setStatuslineHiddenItems, hiddenItems]);
|
|
2863
3237
|
const projectRoot = agent.ctx.projectRoot;
|
|
2864
3238
|
useEffect(() => {
|
|
2865
3239
|
if (!projectRoot) return;
|
|
@@ -2898,6 +3272,7 @@ function App({
|
|
|
2898
3272
|
buffer: "",
|
|
2899
3273
|
cursor: 0,
|
|
2900
3274
|
placeholders: [],
|
|
3275
|
+
placeholderContents: [],
|
|
2901
3276
|
streamingText: "",
|
|
2902
3277
|
toolStream: null,
|
|
2903
3278
|
status: "idle",
|
|
@@ -2925,7 +3300,10 @@ function App({
|
|
|
2925
3300
|
contextChipVersion: 0,
|
|
2926
3301
|
fleet: {},
|
|
2927
3302
|
fleetCost: 0,
|
|
3303
|
+
fleetTokens: { input: 0, output: 0 },
|
|
2928
3304
|
streamFleet: true,
|
|
3305
|
+
monitorOpen: false,
|
|
3306
|
+
agentsMonitorOpen: false,
|
|
2929
3307
|
checkpoints: [],
|
|
2930
3308
|
rewindOverlay: null,
|
|
2931
3309
|
eternalStage: null,
|
|
@@ -2935,7 +3313,10 @@ function App({
|
|
|
2935
3313
|
if (builderRef.current === null) {
|
|
2936
3314
|
builderRef.current = new InputBuilder({ store: attachments });
|
|
2937
3315
|
}
|
|
3316
|
+
const pasteAccumRef = useRef(null);
|
|
3317
|
+
const pasteFlushTimerRef = useRef(null);
|
|
2938
3318
|
const activeCtrlRef = useRef(null);
|
|
3319
|
+
const exitRequestedRef = useRef(false);
|
|
2939
3320
|
const inputGateRef = useRef(false);
|
|
2940
3321
|
const lastEnterAtRef = useRef(0);
|
|
2941
3322
|
const projectName = React2.useMemo(() => {
|
|
@@ -2964,6 +3345,10 @@ function App({
|
|
|
2964
3345
|
draftRef.current = { buffer: "", cursor: 0 };
|
|
2965
3346
|
dispatch({ type: "clearInput" });
|
|
2966
3347
|
};
|
|
3348
|
+
const clearPlaceholdersOnly = () => {
|
|
3349
|
+
draftRef.current = { buffer: "", cursor: 0 };
|
|
3350
|
+
dispatch({ type: "clearPlaceholdersOnly" });
|
|
3351
|
+
};
|
|
2967
3352
|
const startedAtRef = useRef(Date.now());
|
|
2968
3353
|
const [nowTick, setNowTick] = React2.useState(Date.now());
|
|
2969
3354
|
useEffect(() => {
|
|
@@ -3048,7 +3433,11 @@ function App({
|
|
|
3048
3433
|
color: lbl.color,
|
|
3049
3434
|
elapsedMs: Math.max(0, nowTick - e.startedAt),
|
|
3050
3435
|
toolCalls: e.toolCalls,
|
|
3051
|
-
running: e.status === "running"
|
|
3436
|
+
running: e.status === "running",
|
|
3437
|
+
// Last/current action, so the 4th line shows what each agent is
|
|
3438
|
+
// doing right now (e.g. "▶ 12s · 8t · bash") rather than just counts.
|
|
3439
|
+
tool: e.currentTool?.name,
|
|
3440
|
+
extensions: e.extensions
|
|
3052
3441
|
};
|
|
3053
3442
|
});
|
|
3054
3443
|
}, [state.fleet, nowTick]);
|
|
@@ -3398,6 +3787,20 @@ function App({
|
|
|
3398
3787
|
slashRegistry.unregister("rewind");
|
|
3399
3788
|
};
|
|
3400
3789
|
}, [slashRegistry, handleRewindTo]);
|
|
3790
|
+
useEffect(() => {
|
|
3791
|
+
const cmd = {
|
|
3792
|
+
name: "agents",
|
|
3793
|
+
description: "Toggle the agents monitor overlay.",
|
|
3794
|
+
async run() {
|
|
3795
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3796
|
+
return { message: void 0 };
|
|
3797
|
+
}
|
|
3798
|
+
};
|
|
3799
|
+
slashRegistry.register(cmd);
|
|
3800
|
+
return () => {
|
|
3801
|
+
slashRegistry.unregister("agents");
|
|
3802
|
+
};
|
|
3803
|
+
}, [slashRegistry]);
|
|
3401
3804
|
useEffect(() => {
|
|
3402
3805
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
3403
3806
|
const cmd = {
|
|
@@ -3415,6 +3818,23 @@ function App({
|
|
|
3415
3818
|
slashRegistry.unregister("model");
|
|
3416
3819
|
};
|
|
3417
3820
|
}, [slashRegistry, getPickableProviders, switchProviderAndModel]);
|
|
3821
|
+
useEffect(() => {
|
|
3822
|
+
const cmd = {
|
|
3823
|
+
name: "agents",
|
|
3824
|
+
description: "Open or close the agents monitor overlay.",
|
|
3825
|
+
async run(args) {
|
|
3826
|
+
if (args.trim().toLowerCase() === "monitor") {
|
|
3827
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3828
|
+
return { message: "Agents monitor toggled." };
|
|
3829
|
+
}
|
|
3830
|
+
return { message: "Usage: /agents monitor" };
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
slashRegistry.register(cmd);
|
|
3834
|
+
return () => {
|
|
3835
|
+
slashRegistry.unregister("agents");
|
|
3836
|
+
};
|
|
3837
|
+
}, [slashRegistry]);
|
|
3418
3838
|
useEffect(() => {
|
|
3419
3839
|
if (!switchAutonomy) return;
|
|
3420
3840
|
const cmd = {
|
|
@@ -3441,7 +3861,7 @@ function App({
|
|
|
3441
3861
|
flushTimerRef.current = null;
|
|
3442
3862
|
};
|
|
3443
3863
|
const offDelta = events.on("provider.text_delta", (e) => {
|
|
3444
|
-
const text = e.text.replace(/\x1b
|
|
3864
|
+
const text = e.text.replace(/\x1b?\[200~|\x1b?\[201~/g, "");
|
|
3445
3865
|
streamingTextRef.current += text;
|
|
3446
3866
|
pendingDeltaRef.current += text;
|
|
3447
3867
|
if (!flushTimerRef.current) flushTimerRef.current = setTimeout(flush, FLUSH_MS);
|
|
@@ -3632,6 +4052,20 @@ function App({
|
|
|
3632
4052
|
}
|
|
3633
4053
|
});
|
|
3634
4054
|
});
|
|
4055
|
+
const offBudgetExtended = events.on("subagent.budget_extended", (e) => {
|
|
4056
|
+
const lbl = labelFor(e.subagentId);
|
|
4057
|
+
dispatch({ type: "fleetBudgetExtended", id: e.subagentId, totalExtensions: e.totalExtensions });
|
|
4058
|
+
dispatch({
|
|
4059
|
+
type: "addEntry",
|
|
4060
|
+
entry: {
|
|
4061
|
+
kind: "subagent",
|
|
4062
|
+
agentLabel: lbl.label,
|
|
4063
|
+
agentColor: lbl.color,
|
|
4064
|
+
icon: "\u26A1",
|
|
4065
|
+
text: `extended ${e.kind} \u2192 ${e.newLimit} (\xD7${e.totalExtensions})`
|
|
4066
|
+
}
|
|
4067
|
+
});
|
|
4068
|
+
});
|
|
3635
4069
|
const offIterationSummary = events.on("subagent.iteration_summary", (e) => {
|
|
3636
4070
|
const lbl = labelFor(e.subagentId);
|
|
3637
4071
|
const costStr = e.costUsd > 0 ? ` \xB7 ${e.costUsd.toFixed(3)}` : "";
|
|
@@ -3664,6 +4098,7 @@ function App({
|
|
|
3664
4098
|
offStarted();
|
|
3665
4099
|
offCompleted();
|
|
3666
4100
|
offBudgetWarning();
|
|
4101
|
+
offBudgetExtended();
|
|
3667
4102
|
offIterationSummary();
|
|
3668
4103
|
offTool();
|
|
3669
4104
|
};
|
|
@@ -3735,6 +4170,8 @@ function App({
|
|
|
3735
4170
|
useEffect(() => {
|
|
3736
4171
|
if (fleetStreamController) fleetStreamController.enabled = state.streamFleet;
|
|
3737
4172
|
}, [state.streamFleet, fleetStreamController]);
|
|
4173
|
+
const lastEscAtRef = useRef(0);
|
|
4174
|
+
const ESC_DOUBLE_PRESS_MS = 1e3;
|
|
3738
4175
|
useEffect(() => {
|
|
3739
4176
|
const d = director;
|
|
3740
4177
|
if (!d) return;
|
|
@@ -3775,7 +4212,7 @@ function App({
|
|
|
3775
4212
|
});
|
|
3776
4213
|
labelFor(s.id, meta?.name ?? s.name);
|
|
3777
4214
|
}
|
|
3778
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4215
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3779
4216
|
const seen = new Set(Object.keys(status.subagents));
|
|
3780
4217
|
const pending = /* @__PURE__ */ new Map();
|
|
3781
4218
|
let flushTimer = null;
|
|
@@ -3885,7 +4322,7 @@ function App({
|
|
|
3885
4322
|
break;
|
|
3886
4323
|
}
|
|
3887
4324
|
case "provider.response": {
|
|
3888
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4325
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3889
4326
|
break;
|
|
3890
4327
|
}
|
|
3891
4328
|
case "session.ended":
|
|
@@ -3929,7 +4366,7 @@ function App({
|
|
|
3929
4366
|
iterations: payload.result.iterations,
|
|
3930
4367
|
toolCalls: payload.result.toolCalls
|
|
3931
4368
|
});
|
|
3932
|
-
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost });
|
|
4369
|
+
dispatch({ type: "fleetCost", cost: d.snapshot().total.cost, input: d.snapshot().total.input, output: d.snapshot().total.output });
|
|
3933
4370
|
if (streamFlushTimer) {
|
|
3934
4371
|
clearTimeout(streamFlushTimer);
|
|
3935
4372
|
flushStreamBufs();
|
|
@@ -3949,14 +4386,16 @@ function App({
|
|
|
3949
4386
|
const current = stateRef.current;
|
|
3950
4387
|
if (current.interrupts >= 1) {
|
|
3951
4388
|
getProcessRegistry().killAll({ force: true });
|
|
3952
|
-
if (current
|
|
4389
|
+
if (exitRequestedRef.current) {
|
|
3953
4390
|
process.exit(130);
|
|
3954
4391
|
}
|
|
3955
|
-
|
|
3956
|
-
process.exit(130);
|
|
3957
|
-
} catch {
|
|
3958
|
-
}
|
|
4392
|
+
exitRequestedRef.current = true;
|
|
3959
4393
|
dispatch({ type: "interrupt" });
|
|
4394
|
+
if (director) void director.terminateAll().catch(() => void 0);
|
|
4395
|
+
onExit(130);
|
|
4396
|
+
exit();
|
|
4397
|
+
const hardExit = setTimeout(() => process.exit(130), 400);
|
|
4398
|
+
hardExit.unref?.();
|
|
3960
4399
|
return;
|
|
3961
4400
|
}
|
|
3962
4401
|
dispatch({ type: "interrupt" });
|
|
@@ -4008,6 +4447,37 @@ function App({
|
|
|
4008
4447
|
});
|
|
4009
4448
|
}
|
|
4010
4449
|
} else {
|
|
4450
|
+
const fleetRunning = Object.values(current.fleet).filter(
|
|
4451
|
+
(e) => e.status === "running"
|
|
4452
|
+
).length;
|
|
4453
|
+
const autonomyRunning = eternalLoopRunningRef.current || parallelLoopRunningRef.current || getEternalEngine?.()?.currentState === "running" || getParallelEngine?.()?.currentState === "running";
|
|
4454
|
+
if (autonomyRunning || fleetRunning > 0) {
|
|
4455
|
+
getEternalEngine?.()?.stop();
|
|
4456
|
+
getParallelEngine?.()?.stop();
|
|
4457
|
+
if (autonomyRunning) switchAutonomy?.("off");
|
|
4458
|
+
if (director) {
|
|
4459
|
+
const cap = new Promise((resolve) => {
|
|
4460
|
+
const t = setTimeout(resolve, 1500);
|
|
4461
|
+
t.unref?.();
|
|
4462
|
+
});
|
|
4463
|
+
void Promise.race([director.terminateAll().catch(() => void 0), cap]);
|
|
4464
|
+
}
|
|
4465
|
+
const killed2 = getProcessRegistry().killAll();
|
|
4466
|
+
const bits = [];
|
|
4467
|
+
if (autonomyRunning) bits.push("autonomy stopped");
|
|
4468
|
+
if (fleetRunning > 0)
|
|
4469
|
+
bits.push(`${fleetRunning} agent${fleetRunning === 1 ? "" : "s"} terminated`);
|
|
4470
|
+
if (killed2.length > 0)
|
|
4471
|
+
bits.push(`${killed2.length} process${killed2.length === 1 ? "" : "es"} killed`);
|
|
4472
|
+
dispatch({
|
|
4473
|
+
type: "addEntry",
|
|
4474
|
+
entry: {
|
|
4475
|
+
kind: "warn",
|
|
4476
|
+
text: `${bits.join(" + ") || "Background work stopped"}. Press Ctrl+C again to exit.`
|
|
4477
|
+
}
|
|
4478
|
+
});
|
|
4479
|
+
return;
|
|
4480
|
+
}
|
|
4011
4481
|
const killed = getProcessRegistry().killAll();
|
|
4012
4482
|
const procTag = killed.length > 0 ? ` Killed ${killed.length} process${killed.length === 1 ? "" : "es"}.` : "";
|
|
4013
4483
|
dispatch({
|
|
@@ -4020,11 +4490,64 @@ function App({
|
|
|
4020
4490
|
return () => {
|
|
4021
4491
|
process.off("SIGINT", onSigint);
|
|
4022
4492
|
};
|
|
4023
|
-
}, [director]);
|
|
4493
|
+
}, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
|
|
4494
|
+
const truncatePastePreview = (text, lines) => {
|
|
4495
|
+
const all = text.split("\n");
|
|
4496
|
+
if (all.length <= lines) return text;
|
|
4497
|
+
const head = all.slice(0, lines).join("\n");
|
|
4498
|
+
return `${head}
|
|
4499
|
+
... (${all.length - lines} more lines)`;
|
|
4500
|
+
};
|
|
4501
|
+
const commitPaste = async (full) => {
|
|
4502
|
+
const builder = builderRef.current;
|
|
4503
|
+
if (!builder || !full) return;
|
|
4504
|
+
if (builder.wouldCollapse(full) || full.includes("\n")) {
|
|
4505
|
+
const lineCount = full.split("\n").length;
|
|
4506
|
+
const ph = await builder.appendPaste(full);
|
|
4507
|
+
const preview = truncatePastePreview(full, 6);
|
|
4508
|
+
dispatch({
|
|
4509
|
+
type: "addPlaceholder",
|
|
4510
|
+
ph: `${ph ?? "[pasted]"} (${lineCount} lines)`,
|
|
4511
|
+
content: preview
|
|
4512
|
+
});
|
|
4513
|
+
return;
|
|
4514
|
+
}
|
|
4515
|
+
const { buffer, cursor } = draftRef.current;
|
|
4516
|
+
const next = buffer.slice(0, cursor) + full + buffer.slice(cursor);
|
|
4517
|
+
setDraft(next, cursor + full.length);
|
|
4518
|
+
};
|
|
4024
4519
|
const handleKey = async (input, key) => {
|
|
4025
4520
|
if (state.status === "aborting" && state.interrupts === 0) return;
|
|
4026
4521
|
if (state.confirmQueue.length > 0) return;
|
|
4027
4522
|
if (inputGateRef.current) return;
|
|
4523
|
+
if (key.escape) {
|
|
4524
|
+
const now = Date.now();
|
|
4525
|
+
if (state.buffer.length > 0 && now - lastEscAtRef.current < ESC_DOUBLE_PRESS_MS) {
|
|
4526
|
+
dispatch({ type: "clearInput" });
|
|
4527
|
+
lastEscAtRef.current = 0;
|
|
4528
|
+
return;
|
|
4529
|
+
}
|
|
4530
|
+
lastEscAtRef.current = now;
|
|
4531
|
+
}
|
|
4532
|
+
if (input) {
|
|
4533
|
+
const paste = feedPaste(pasteAccumRef.current, input);
|
|
4534
|
+
if (paste) {
|
|
4535
|
+
pasteAccumRef.current = paste.accum;
|
|
4536
|
+
if (pasteFlushTimerRef.current) clearTimeout(pasteFlushTimerRef.current);
|
|
4537
|
+
if (paste.complete !== null) {
|
|
4538
|
+
pasteFlushTimerRef.current = null;
|
|
4539
|
+
await commitPaste(paste.complete);
|
|
4540
|
+
return;
|
|
4541
|
+
}
|
|
4542
|
+
pasteFlushTimerRef.current = setTimeout(() => {
|
|
4543
|
+
pasteFlushTimerRef.current = null;
|
|
4544
|
+
const full = pasteAccumRef.current;
|
|
4545
|
+
pasteAccumRef.current = null;
|
|
4546
|
+
if (full) void commitPaste(full);
|
|
4547
|
+
}, 250);
|
|
4548
|
+
return;
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4028
4551
|
const isEnter = key.return || input === "\r" || input === "\n";
|
|
4029
4552
|
if (state.modelPicker.open) {
|
|
4030
4553
|
if (key.escape) {
|
|
@@ -4203,6 +4726,22 @@ function App({
|
|
|
4203
4726
|
});
|
|
4204
4727
|
return;
|
|
4205
4728
|
}
|
|
4729
|
+
if (key.ctrl && input === "f") {
|
|
4730
|
+
dispatch({ type: "toggleMonitor" });
|
|
4731
|
+
return;
|
|
4732
|
+
}
|
|
4733
|
+
if (key.ctrl && key.shift && input === "M") {
|
|
4734
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4735
|
+
return;
|
|
4736
|
+
}
|
|
4737
|
+
if (key.escape && state.monitorOpen) {
|
|
4738
|
+
dispatch({ type: "toggleMonitor" });
|
|
4739
|
+
return;
|
|
4740
|
+
}
|
|
4741
|
+
if (key.escape && state.agentsMonitorOpen) {
|
|
4742
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4743
|
+
return;
|
|
4744
|
+
}
|
|
4206
4745
|
if (isEnter) {
|
|
4207
4746
|
const now = Date.now();
|
|
4208
4747
|
if (now - lastEnterAtRef.current < 50) return;
|
|
@@ -4320,40 +4859,23 @@ function App({
|
|
|
4320
4859
|
return;
|
|
4321
4860
|
}
|
|
4322
4861
|
if (!input || key.ctrl || key.meta) return;
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
if (input.includes("\x1B[200~") || input.includes("\x1B[201~")) {
|
|
4326
|
-
cleanInput = input.replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "");
|
|
4327
|
-
bracketedPaste = true;
|
|
4328
|
-
}
|
|
4329
|
-
if (bracketedPaste || cleanInput.length > PASTE_THRESHOLD_CHARS) {
|
|
4330
|
-
const builder = builderRef.current;
|
|
4331
|
-
if (!builder) return;
|
|
4332
|
-
const ph = await builder.appendPaste(cleanInput);
|
|
4333
|
-
if (ph) {
|
|
4334
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4335
|
-
dispatch({ type: "addPlaceholder", ph: `${ph} (${lineCount} lines)` });
|
|
4336
|
-
} else if (cleanInput.includes("\n")) {
|
|
4337
|
-
const lineCount = cleanInput.split("\n").length;
|
|
4338
|
-
dispatch({ type: "addPlaceholder", ph: `[pasted] (${lineCount} lines)` });
|
|
4339
|
-
} else {
|
|
4340
|
-
const next2 = buffer.slice(0, cursor) + cleanInput + buffer.slice(cursor);
|
|
4341
|
-
setDraft(next2, cursor + cleanInput.length);
|
|
4342
|
-
}
|
|
4862
|
+
if (input.length > PASTE_THRESHOLD_CHARS) {
|
|
4863
|
+
await commitPaste(input);
|
|
4343
4864
|
return;
|
|
4344
4865
|
}
|
|
4345
|
-
if (
|
|
4346
|
-
const normalized =
|
|
4866
|
+
if (input.includes("\n")) {
|
|
4867
|
+
const normalized = input.replace(/\r?\n/g, " ");
|
|
4347
4868
|
const next2 = buffer.slice(0, cursor) + normalized + buffer.slice(cursor);
|
|
4348
4869
|
setDraft(next2, cursor + normalized.length);
|
|
4349
4870
|
return;
|
|
4350
4871
|
}
|
|
4351
|
-
const next = buffer.slice(0, cursor) +
|
|
4352
|
-
setDraft(next, cursor +
|
|
4872
|
+
const next = buffer.slice(0, cursor) + input + buffer.slice(cursor);
|
|
4873
|
+
setDraft(next, cursor + input.length);
|
|
4353
4874
|
};
|
|
4354
4875
|
const runBlocks = async (blocks) => {
|
|
4355
4876
|
const ctrl = new AbortController();
|
|
4356
4877
|
activeCtrlRef.current = ctrl;
|
|
4878
|
+
dispatch({ type: "resetInterrupts" });
|
|
4357
4879
|
dispatch({ type: "status", status: "running" });
|
|
4358
4880
|
try {
|
|
4359
4881
|
const startedAt = Date.now();
|
|
@@ -4611,18 +5133,26 @@ User message:
|
|
|
4611
5133
|
}
|
|
4612
5134
|
if (steering) dispatch({ type: "steerConsume" });
|
|
4613
5135
|
const displayText = trimmed ? steering ? `\u21AF ${trimmed}` : trimmed : "(attachments only)";
|
|
5136
|
+
const pasteParts = [];
|
|
5137
|
+
for (let i = 0; i < state.placeholders.length; i++) {
|
|
5138
|
+
const label = state.placeholders[i];
|
|
5139
|
+
const content = state.placeholderContents[i] ?? "";
|
|
5140
|
+
pasteParts.push(label);
|
|
5141
|
+
if (content) pasteParts.push(` ${content.split("\n").slice(0, 6).join("\n ")}`);
|
|
5142
|
+
}
|
|
5143
|
+
const pasteContent = pasteParts.length > 0 ? pasteParts.join("\n") : void 0;
|
|
4614
5144
|
pushSubmittedHistory();
|
|
4615
|
-
|
|
5145
|
+
clearPlaceholdersOnly();
|
|
4616
5146
|
const blocks = await builder.submit();
|
|
4617
5147
|
if (state.status !== "idle") {
|
|
4618
5148
|
dispatch({
|
|
4619
5149
|
type: "addEntry",
|
|
4620
|
-
entry: { kind: "user", text: displayText, queued: true }
|
|
5150
|
+
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
4621
5151
|
});
|
|
4622
5152
|
dispatch({ type: "enqueue", item: { displayText, blocks } });
|
|
4623
5153
|
return;
|
|
4624
5154
|
}
|
|
4625
|
-
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText } });
|
|
5155
|
+
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
|
|
4626
5156
|
await runBlocks(blocks);
|
|
4627
5157
|
};
|
|
4628
5158
|
const bootInjectedRef = useRef(false);
|
|
@@ -4749,6 +5279,7 @@ User message:
|
|
|
4749
5279
|
StatusBar,
|
|
4750
5280
|
{
|
|
4751
5281
|
model: `${liveProvider}/${liveModel}`,
|
|
5282
|
+
version: appVersion,
|
|
4752
5283
|
state: state.status,
|
|
4753
5284
|
tokenCounter,
|
|
4754
5285
|
hint: renderRunningTools(state.runningTools) || state.hint,
|
|
@@ -4770,7 +5301,24 @@ User message:
|
|
|
4770
5301
|
goalSummary: state.goalSummary
|
|
4771
5302
|
}
|
|
4772
5303
|
),
|
|
4773
|
-
|
|
5304
|
+
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
5305
|
+
AgentsMonitor,
|
|
5306
|
+
{
|
|
5307
|
+
entries: state.fleet,
|
|
5308
|
+
totalCost: state.fleetCost,
|
|
5309
|
+
totalTokens: state.fleetTokens,
|
|
5310
|
+
nowTick
|
|
5311
|
+
}
|
|
5312
|
+
) : null,
|
|
5313
|
+
state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
5314
|
+
FleetMonitor,
|
|
5315
|
+
{
|
|
5316
|
+
entries: state.fleet,
|
|
5317
|
+
totalCost: state.fleetCost,
|
|
5318
|
+
totalTokens: state.fleetTokens,
|
|
5319
|
+
nowTick
|
|
5320
|
+
}
|
|
5321
|
+
) : director ? /* @__PURE__ */ jsx(FleetPanel, { entries: state.fleet, totalCost: state.fleetCost, roster: fleetRoster }) : null
|
|
4774
5322
|
] });
|
|
4775
5323
|
}
|
|
4776
5324
|
function renderRunningTools(running) {
|