@bojackduy/opencode-loopd 1.8.3 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tui.js CHANGED
@@ -322,13 +322,15 @@ function tokenize(input) {
322
322
  function commandHelp() {
323
323
  return [
324
324
  "Modes: : insert \u2192 send/commands | Ctrl+N \u2192 normal | ? toggle help | Shift+B bug report",
325
- "Nav: j/k move | g/G top/bottom | o open child | c toggle done | p/r/R/x pause/resume/retry/clear | L logs | q close",
325
+ "Nav: j/k move | g/G top/bottom | o open child | c toggle done | p/r/R/x pause/resume/retry/clear | A abort worker | N nudge | L logs | q close",
326
326
  "Commands (insert mode, : prefix):",
327
- " :send <message> Send instruction to selected goal",
327
+ " :send <message> Send bare words now as their own turn (no steering)",
328
328
  " :open Open child session (same as o)",
329
329
  " :force <summary> --evidence <text> Force-complete (bypass checks)",
330
330
  " :block <reason> --needed <text> Force-block the selected goal",
331
331
  " :pause / :resume / :retry / :clear Quick controls (also p/r/R/x)",
332
+ " :abort Abort worker session now (status unchanged; A)",
333
+ " :nudge Force re-prompt now with full steering (N)",
332
334
  " :bug / :report Open prefilled GitHub bug report",
333
335
  " :logs / :help / :q Toggle logs / help / close",
334
336
  " Tip: create goals via /goal in the parent chat (agent clarifies first)."
@@ -427,6 +429,29 @@ function prevent(evt) {
427
429
  e.preventDefault?.();
428
430
  e.stopPropagation?.();
429
431
  }
432
+ function keyName(evt) {
433
+ return (evt.name || "").toLowerCase();
434
+ }
435
+ function keySeq(evt) {
436
+ const e = evt;
437
+ return e.sequence || e.raw || "";
438
+ }
439
+ function isEnterKey(evt) {
440
+ const name = keyName(evt);
441
+ if (name === "return" || name === "enter" || name === "kp_enter")
442
+ return true;
443
+ const seq = keySeq(evt);
444
+ return seq === "\r" || seq === `
445
+ `;
446
+ }
447
+ function isEscapeKey(evt) {
448
+ if (keyName(evt) === "escape" || keyName(evt) === "esc")
449
+ return true;
450
+ return keySeq(evt) === "\x1B";
451
+ }
452
+ function isCtrlN(evt) {
453
+ return Boolean(evt.ctrl) && keyName(evt) === "n";
454
+ }
430
455
  function statusColor(status, theme) {
431
456
  switch (status) {
432
457
  case "active":
@@ -543,6 +568,66 @@ function countdownLabel(targetIso, now) {
543
568
  return `${minutes}m ${diff % 60}s`;
544
569
  return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;
545
570
  }
571
+ function formatTokens(n) {
572
+ if (!n)
573
+ return "0";
574
+ if (n < 1000)
575
+ return String(Math.round(n));
576
+ if (n < 1e6)
577
+ return `${(n / 1000).toFixed(1)}k`;
578
+ return `${(n / 1e6).toFixed(2)}M`;
579
+ }
580
+ function formatCost(c) {
581
+ if (!c)
582
+ return "$0.00";
583
+ if (c < 0.01)
584
+ return `$${c.toFixed(4)}`;
585
+ return `$${c.toFixed(2)}`;
586
+ }
587
+ function formatDuration(seconds) {
588
+ if (!seconds || seconds <= 0)
589
+ return "0s";
590
+ if (seconds < 60)
591
+ return `${Math.round(seconds)}s`;
592
+ const minutes = Math.floor(seconds / 60);
593
+ if (minutes < 60)
594
+ return `${minutes}m`;
595
+ return `${(seconds / 3600).toFixed(1)}h`;
596
+ }
597
+ function agentColor(color, theme) {
598
+ if (!color)
599
+ return theme.text;
600
+ const named = {
601
+ primary: theme.primary,
602
+ secondary: theme.secondary,
603
+ accent: theme.accent,
604
+ success: theme.success,
605
+ warning: theme.warning,
606
+ error: theme.error,
607
+ info: theme.info
608
+ };
609
+ if (named[color])
610
+ return named[color];
611
+ if (/^#[0-9a-fA-F]{3,8}$/.test(color))
612
+ return color;
613
+ return theme.text;
614
+ }
615
+ function indexAgents(list) {
616
+ const map = {};
617
+ for (const a of list) {
618
+ if (!a?.name)
619
+ continue;
620
+ map[a.name] = {
621
+ color: a.color,
622
+ mode: a.mode
623
+ };
624
+ map[a.name.toLowerCase()] = {
625
+ color: a.color,
626
+ mode: a.mode
627
+ };
628
+ }
629
+ return map;
630
+ }
546
631
  function LoopDashboard(props) {
547
632
  const theme = () => props.api.theme.current;
548
633
  const [mode, setMode] = createSignal("normal");
@@ -556,6 +641,7 @@ function LoopDashboard(props) {
556
641
  const [showHelp, setShowHelp] = createSignal(false);
557
642
  const [showCompleted, setShowCompleted] = createSignal(false);
558
643
  const [clock, setClock] = createSignal(Date.now());
644
+ const [agentIndex, setAgentIndex] = createSignal({});
559
645
  let inputEl;
560
646
  let focusTimer;
561
647
  const client = createControlClient(props.directory);
@@ -584,6 +670,15 @@ function LoopDashboard(props) {
584
670
  }
585
671
  }
586
672
  refresh();
673
+ async function refreshAgents() {
674
+ try {
675
+ const res = await props.api.client?.app?.agents?.();
676
+ const list = res?.data ?? res ?? [];
677
+ if (Array.isArray(list))
678
+ setAgentIndex(indexAgents(list));
679
+ } catch {}
680
+ }
681
+ refreshAgents();
587
682
  const unsubs = [props.api.event.on("session.idle", () => refresh()), props.api.event.on("session.status", () => refresh()), props.api.event.on("session.error", () => refresh()), props.api.event.on("session.compacted", () => refresh()), setInterval(refresh, 1e4), setInterval(() => setClock(Date.now()), 500)];
588
683
  onCleanup(() => {
589
684
  popMode();
@@ -595,9 +690,9 @@ function LoopDashboard(props) {
595
690
  onMount(() => {
596
691
  try {
597
692
  const {
598
- writeFileSync
693
+ appendFileSync
599
694
  } = __require("fs");
600
- writeFileSync(LOG_FILE, `[${new Date().toISOString()}] dashboard mounted dir=${props.directory} mode=${mode()} dialogOpen=${props.api.ui.dialog.open}
695
+ appendFileSync(LOG_FILE, `[${new Date().toISOString()}] dashboard mounted dir=${props.directory} mode=${mode()} dialogOpen=${props.api.ui.dialog.open}
601
696
  `);
602
697
  } catch {}
603
698
  debugLog("mounted", "dialogOpen", props.api.ui.dialog.open, "directory", props.directory);
@@ -633,10 +728,17 @@ function LoopDashboard(props) {
633
728
  const isQuestion = name === "?" || seq === "?" || raw === "?" || seq.includes("?") || raw.includes("?");
634
729
  debugLog("isColon", isColon, "isQuestion", isQuestion, "modeBefore", mode());
635
730
  if (mode() === "insert") {
636
- if (evt.ctrl && name.toLowerCase() === "n") {
731
+ if (isEnterKey(evt)) {
732
+ prevent(evt);
733
+ debugLog("insert enter -> execute");
734
+ executeCommand(commandInput());
735
+ return;
736
+ }
737
+ if (isEscapeKey(evt) || isCtrlN(evt)) {
637
738
  prevent(evt);
638
739
  returnToNormalMode();
639
- debugLog("insert -> normal via ctrl+n");
740
+ debugLog("insert -> normal via esc/ctrl+n");
741
+ return;
640
742
  }
641
743
  return;
642
744
  }
@@ -700,6 +802,16 @@ function LoopDashboard(props) {
700
802
  executeCommand("clear");
701
803
  return;
702
804
  }
805
+ if (key === "A") {
806
+ prevent(evt);
807
+ executeCommand("abort");
808
+ return;
809
+ }
810
+ if (key === "N") {
811
+ prevent(evt);
812
+ executeCommand("nudge");
813
+ return;
814
+ }
703
815
  if (key === "L") {
704
816
  prevent(evt);
705
817
  setShowLogs((value) => !value);
@@ -737,6 +849,9 @@ function LoopDashboard(props) {
737
849
  debugLog("empty command");
738
850
  return;
739
851
  }
852
+ if (!["help", "logs", "q", "close"].includes(parsed.command)) {
853
+ setStatusText(`sending ${parsed.command}\u2026`);
854
+ }
740
855
  try {
741
856
  switch (parsed.command) {
742
857
  case "send": {
@@ -890,6 +1005,40 @@ function LoopDashboard(props) {
890
1005
  await refresh();
891
1006
  break;
892
1007
  }
1008
+ case "abort": {
1009
+ if (!selectedGoal()) {
1010
+ setStatusText("No goal");
1011
+ break;
1012
+ }
1013
+ const r = await client.execute({
1014
+ version: 1,
1015
+ requestID: randomUUID(),
1016
+ requestedAt: new Date().toISOString(),
1017
+ command: "abort_worker",
1018
+ goalID: selectedGoal().id
1019
+ });
1020
+ setStatusText(r.ok ? r.message : `Error: ${r.message}`);
1021
+ if (r.ok)
1022
+ await refresh();
1023
+ break;
1024
+ }
1025
+ case "nudge": {
1026
+ if (!selectedGoal()) {
1027
+ setStatusText("No goal");
1028
+ break;
1029
+ }
1030
+ const r = await client.execute({
1031
+ version: 1,
1032
+ requestID: randomUUID(),
1033
+ requestedAt: new Date().toISOString(),
1034
+ command: "nudge",
1035
+ goalID: selectedGoal().id
1036
+ });
1037
+ setStatusText(r.ok ? r.message : `Error: ${r.message}`);
1038
+ if (r.ok)
1039
+ await refresh();
1040
+ break;
1041
+ }
893
1042
  case "goal": {
894
1043
  setStatusText("Create goals via /goal in the parent chat (agent clarifies first). Dashboard: :send to steer the worker.");
895
1044
  break;
@@ -1041,7 +1190,7 @@ function LoopDashboard(props) {
1041
1190
  _$setProp(_el$32, "maxHeight", 14);
1042
1191
  _$setProp(_el$32, "overflow", "hidden");
1043
1192
  _$insertNode(_el$33, _el$34);
1044
- _$insertNode(_el$34, _$createTextNode(`\u2501\u2501\u2501 Keys: ? toggle help c toggle done : insert Ctrl+N normal o open Bug report q close \u2501\u2501\u2501`));
1193
+ _$insertNode(_el$34, _$createTextNode(`\u2501\u2501\u2501 Keys: ? toggle help c toggle done : insert Ctrl+N normal o open A abort worker N nudge q close \u2501\u2501\u2501`));
1045
1194
  _$setProp(_el$34, "style", {
1046
1195
  fg: "yellow",
1047
1196
  bold: true
@@ -1484,7 +1633,7 @@ function LoopDashboard(props) {
1484
1633
  _$setProp(_el$121, "border", true);
1485
1634
  _$setProp(_el$121, "padding", 1);
1486
1635
  _$setProp(_el$121, "flexShrink", 0);
1487
- _$setProp(_el$121, "maxHeight", 10);
1636
+ _$setProp(_el$121, "maxHeight", 13);
1488
1637
  _$insertNode(_el$122, _el$123);
1489
1638
  _$insertNode(_el$122, _el$125);
1490
1639
  _$insertNode(_el$122, _el$127);
@@ -1526,212 +1675,339 @@ function LoopDashboard(props) {
1526
1675
  return _el$133;
1527
1676
  })()];
1528
1677
  })(), _el$127);
1529
- _$insert(_el$128, () => goal().objective.slice(0, 160));
1530
1678
  _$insert(_el$122, (() => {
1531
- var _c$11 = _$memo(() => !!lp());
1679
+ var _c$11 = _$memo(() => !!rt()?.workerAbortedAt);
1532
1680
  return () => _c$11() && [(() => {
1533
- var _el$137 = _$createElement("span"), _el$138 = _$createTextNode(`
1534
- \u2714 `);
1535
- _$insertNode(_el$137, _el$138);
1681
+ var _el$137 = _$createElement("span");
1682
+ _$insertNode(_el$137, _$createTextNode(` \u2502 \u26A0 worker aborted `));
1536
1683
  _$effect((_$p) => _$setProp(_el$137, "style", {
1537
- fg: theme().success
1684
+ fg: theme().warning,
1685
+ bold: true
1538
1686
  }, _$p));
1539
1687
  return _el$137;
1540
1688
  })(), (() => {
1541
- var _el$140 = _$createElement("span");
1542
- _$insert(_el$140, () => lp().summary.slice(0, 100));
1543
- _$effect((_$p) => _$setProp(_el$140, "style", {
1544
- fg: theme().text
1689
+ var _el$139 = _$createElement("span"), _el$140 = _$createTextNode(` \u2014 session kept, next turn reuses it`);
1690
+ _$insertNode(_el$139, _el$140);
1691
+ _$insert(_el$139, () => ageLabel(rt().workerAbortedAt, clock()), _el$140);
1692
+ _$effect((_$p) => _$setProp(_el$139, "style", {
1693
+ fg: theme().textMuted
1545
1694
  }, _$p));
1546
- return _el$140;
1547
- })(), (() => {
1548
- var _el$141 = _$createElement("span"), _el$142 = _$createTextNode(` \u2192 `);
1549
- _$insertNode(_el$141, _el$142);
1550
- _$insert(_el$141, () => lp().next?.slice(0, 60) || "", null);
1695
+ return _el$139;
1696
+ })()];
1697
+ })(), _el$127);
1698
+ _$insert(_el$122, () => {
1699
+ const agentName = goal().config.agent;
1700
+ const meta = agentName ? agentIndex()[agentName] ?? agentIndex()[agentName.toLowerCase()] : undefined;
1701
+ const model = goal().config.model;
1702
+ const slash = model?.indexOf("/") ?? -1;
1703
+ return [`
1704
+ `, (() => {
1705
+ var _el$141 = _$createElement("span");
1706
+ _$insertNode(_el$141, _$createTextNode(`\uD83E\uDD16 `));
1551
1707
  _$effect((_$p) => _$setProp(_el$141, "style", {
1552
1708
  fg: theme().textMuted
1553
1709
  }, _$p));
1554
1710
  return _el$141;
1711
+ })(), agentName ? [(() => {
1712
+ var _el$153 = _$createElement("span");
1713
+ _$insert(_el$153, agentName);
1714
+ _$effect((_$p) => _$setProp(_el$153, "style", {
1715
+ fg: agentColor(meta?.color, theme()),
1716
+ bold: true
1717
+ }, _$p));
1718
+ return _el$153;
1719
+ })(), _$memo(() => _$memo(() => !!meta?.mode)() && (() => {
1720
+ var _el$154 = _$createElement("span"), _el$155 = _$createTextNode(` (`), _el$156 = _$createTextNode(`)`);
1721
+ _$insertNode(_el$154, _el$155);
1722
+ _$insertNode(_el$154, _el$156);
1723
+ _$insert(_el$154, () => meta.mode, _el$156);
1724
+ _$effect((_$p) => _$setProp(_el$154, "style", {
1725
+ fg: theme().textMuted
1726
+ }, _$p));
1727
+ return _el$154;
1728
+ })())] : (() => {
1729
+ var _el$157 = _$createElement("span");
1730
+ _$insertNode(_el$157, _$createTextNode(`parent default`));
1731
+ _$effect((_$p) => _$setProp(_el$157, "style", {
1732
+ fg: theme().textMuted
1733
+ }, _$p));
1734
+ return _el$157;
1735
+ })(), (() => {
1736
+ var _el$143 = _$createElement("span");
1737
+ _$insertNode(_el$143, _$createTextNode(` \u2502 \uD83E\uDDE0 `));
1738
+ _$effect((_$p) => _$setProp(_el$143, "style", {
1739
+ fg: theme().textMuted
1740
+ }, _$p));
1741
+ return _el$143;
1742
+ })(), model && slash > 0 ? [(() => {
1743
+ var _el$159 = _$createElement("span"), _el$160 = _$createTextNode(`/`);
1744
+ _$insertNode(_el$159, _el$160);
1745
+ _$insert(_el$159, () => model.slice(0, slash), _el$160);
1746
+ _$effect((_$p) => _$setProp(_el$159, "style", {
1747
+ fg: theme().textMuted
1748
+ }, _$p));
1749
+ return _el$159;
1750
+ })(), (() => {
1751
+ var _el$161 = _$createElement("span");
1752
+ _$insert(_el$161, () => model.slice(slash + 1));
1753
+ _$effect((_$p) => _$setProp(_el$161, "style", {
1754
+ fg: theme().info,
1755
+ bold: true
1756
+ }, _$p));
1757
+ return _el$161;
1758
+ })()] : (() => {
1759
+ var _el$162 = _$createElement("span");
1760
+ _$insertNode(_el$162, _$createTextNode(`session default`));
1761
+ _$effect((_$p) => _$setProp(_el$162, "style", {
1762
+ fg: theme().textMuted
1763
+ }, _$p));
1764
+ return _el$162;
1765
+ })(), (() => {
1766
+ var _el$145 = _$createElement("span");
1767
+ _$insertNode(_el$145, _$createTextNode(` \u2502 \uD83D\uDCB0 `));
1768
+ _$effect((_$p) => _$setProp(_el$145, "style", {
1769
+ fg: theme().textMuted
1770
+ }, _$p));
1771
+ return _el$145;
1772
+ })(), (() => {
1773
+ var _el$147 = _$createElement("span");
1774
+ _$insert(_el$147, () => formatTokens(goal().tokensUsed));
1775
+ _$effect((_$p) => _$setProp(_el$147, "style", {
1776
+ fg: theme().warning,
1777
+ bold: true
1778
+ }, _$p));
1779
+ return _el$147;
1780
+ })(), (() => {
1781
+ var _el$148 = _$createElement("span");
1782
+ _$insertNode(_el$148, _$createTextNode(` tokens \xB7 `));
1783
+ _$effect((_$p) => _$setProp(_el$148, "style", {
1784
+ fg: theme().textMuted
1785
+ }, _$p));
1786
+ return _el$148;
1787
+ })(), (() => {
1788
+ var _el$150 = _$createElement("span");
1789
+ _$insert(_el$150, () => formatCost(goal().costUsed));
1790
+ _$effect((_$p) => _$setProp(_el$150, "style", {
1791
+ fg: theme().success,
1792
+ bold: true
1793
+ }, _$p));
1794
+ return _el$150;
1795
+ })(), (() => {
1796
+ var _el$151 = _$createElement("span"), _el$152 = _$createTextNode(` \xB7 `);
1797
+ _$insertNode(_el$151, _el$152);
1798
+ _$insert(_el$151, () => formatDuration(goal().timeUsedSeconds), null);
1799
+ _$effect((_$p) => _$setProp(_el$151, "style", {
1800
+ fg: theme().textMuted
1801
+ }, _$p));
1802
+ return _el$151;
1555
1803
  })()];
1556
- })(), null);
1804
+ }, _el$127);
1805
+ _$insert(_el$128, () => goal().objective.slice(0, 160));
1557
1806
  _$insert(_el$122, (() => {
1558
- var _c$12 = _$memo(() => !!blk());
1807
+ var _c$12 = _$memo(() => !!lp());
1559
1808
  return () => _c$12() && [(() => {
1560
- var _el$143 = _$createElement("span"), _el$144 = _$createTextNode(`
1809
+ var _el$164 = _$createElement("span"), _el$165 = _$createTextNode(`
1810
+ \u2714 `);
1811
+ _$insertNode(_el$164, _el$165);
1812
+ _$effect((_$p) => _$setProp(_el$164, "style", {
1813
+ fg: theme().success
1814
+ }, _$p));
1815
+ return _el$164;
1816
+ })(), (() => {
1817
+ var _el$167 = _$createElement("span");
1818
+ _$insert(_el$167, () => lp().summary.slice(0, 100));
1819
+ _$effect((_$p) => _$setProp(_el$167, "style", {
1820
+ fg: theme().text
1821
+ }, _$p));
1822
+ return _el$167;
1823
+ })(), (() => {
1824
+ var _el$168 = _$createElement("span"), _el$169 = _$createTextNode(` \u2192 `);
1825
+ _$insertNode(_el$168, _el$169);
1826
+ _$insert(_el$168, () => lp().next?.slice(0, 60) || "", null);
1827
+ _$effect((_$p) => _$setProp(_el$168, "style", {
1828
+ fg: theme().textMuted
1829
+ }, _$p));
1830
+ return _el$168;
1831
+ })()];
1832
+ })(), null);
1833
+ _$insert(_el$122, (() => {
1834
+ var _c$13 = _$memo(() => !!blk());
1835
+ return () => _c$13() && [(() => {
1836
+ var _el$170 = _$createElement("span"), _el$171 = _$createTextNode(`
1561
1837
  \u2716 blocked: `);
1562
- _$insertNode(_el$143, _el$144);
1563
- _$effect((_$p) => _$setProp(_el$143, "style", {
1838
+ _$insertNode(_el$170, _el$171);
1839
+ _$effect((_$p) => _$setProp(_el$170, "style", {
1564
1840
  fg: theme().error,
1565
1841
  bold: true
1566
1842
  }, _$p));
1567
- return _el$143;
1843
+ return _el$170;
1568
1844
  })(), (() => {
1569
- var _el$146 = _$createElement("span");
1570
- _$insert(_el$146, () => blk().reason.slice(0, 140));
1571
- _$effect((_$p) => _$setProp(_el$146, "style", {
1845
+ var _el$173 = _$createElement("span");
1846
+ _$insert(_el$173, () => blk().reason.slice(0, 140));
1847
+ _$effect((_$p) => _$setProp(_el$173, "style", {
1572
1848
  fg: theme().error
1573
1849
  }, _$p));
1574
- return _el$146;
1850
+ return _el$173;
1575
1851
  })(), (() => {
1576
- var _el$147 = _$createElement("span"), _el$148 = _$createTextNode(` \u2014 `);
1577
- _$insertNode(_el$147, _el$148);
1578
- _$insert(_el$147, () => blk().needed.slice(0, 60), null);
1579
- _$effect((_$p) => _$setProp(_el$147, "style", {
1852
+ var _el$174 = _$createElement("span"), _el$175 = _$createTextNode(` \u2014 `);
1853
+ _$insertNode(_el$174, _el$175);
1854
+ _$insert(_el$174, () => blk().needed.slice(0, 60), null);
1855
+ _$effect((_$p) => _$setProp(_el$174, "style", {
1580
1856
  fg: theme().textMuted
1581
1857
  }, _$p));
1582
- return _el$147;
1858
+ return _el$174;
1583
1859
  })()];
1584
1860
  })(), null);
1585
1861
  _$insert(_el$122, (() => {
1586
- var _c$13 = _$memo(() => !!goal().config.artifactDir);
1587
- return () => _c$13() && [(() => {
1588
- var _el$149 = _$createElement("span"), _el$150 = _$createTextNode(`
1862
+ var _c$14 = _$memo(() => !!goal().config.artifactDir);
1863
+ return () => _c$14() && [(() => {
1864
+ var _el$176 = _$createElement("span"), _el$177 = _$createTextNode(`
1589
1865
  \uD83D\uDCC1 `);
1590
- _$insertNode(_el$149, _el$150);
1591
- _$effect((_$p) => _$setProp(_el$149, "style", {
1866
+ _$insertNode(_el$176, _el$177);
1867
+ _$effect((_$p) => _$setProp(_el$176, "style", {
1592
1868
  fg: theme().accent
1593
1869
  }, _$p));
1594
- return _el$149;
1870
+ return _el$176;
1595
1871
  })(), (() => {
1596
- var _el$152 = _$createElement("span");
1597
- _$insert(_el$152, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1598
- _$effect((_$p) => _$setProp(_el$152, "style", {
1872
+ var _el$179 = _$createElement("span");
1873
+ _$insert(_el$179, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1874
+ _$effect((_$p) => _$setProp(_el$179, "style", {
1599
1875
  fg: theme().textMuted
1600
1876
  }, _$p));
1601
- return _el$152;
1877
+ return _el$179;
1602
1878
  })()];
1603
1879
  })(), null);
1604
1880
  _$insert(_el$122, (() => {
1605
- var _c$14 = _$memo(() => (goal().config.checks?.length ?? 0) > 0);
1606
- return () => _c$14() ? [(() => {
1607
- var _el$153 = _$createElement("span"), _el$154 = _$createTextNode(`
1881
+ var _c$15 = _$memo(() => (goal().config.checks?.length ?? 0) > 0);
1882
+ return () => _c$15() ? [(() => {
1883
+ var _el$180 = _$createElement("span"), _el$181 = _$createTextNode(`
1608
1884
  \u25A3 checks: `);
1609
- _$insertNode(_el$153, _el$154);
1610
- _$effect((_$p) => _$setProp(_el$153, "style", {
1885
+ _$insertNode(_el$180, _el$181);
1886
+ _$effect((_$p) => _$setProp(_el$180, "style", {
1611
1887
  fg: theme().warning
1612
1888
  }, _$p));
1613
- return _el$153;
1889
+ return _el$180;
1614
1890
  })(), (() => {
1615
- var _el$156 = _$createElement("span");
1616
- _$insert(_el$156, () => goal().config.checks.join(", ").slice(0, 100));
1617
- _$effect((_$p) => _$setProp(_el$156, "style", {
1891
+ var _el$183 = _$createElement("span");
1892
+ _$insert(_el$183, () => goal().config.checks.join(", ").slice(0, 100));
1893
+ _$effect((_$p) => _$setProp(_el$183, "style", {
1618
1894
  fg: theme().textMuted
1619
1895
  }, _$p));
1620
- return _el$156;
1896
+ return _el$183;
1621
1897
  })()] : null;
1622
1898
  })(), null);
1623
1899
  _$insert(_el$122, (() => {
1624
- var _c$15 = _$memo(() => rt()?.evaluatorRejectionCount > 0);
1625
- return () => _c$15() && [(() => {
1626
- var _el$157 = _$createElement("span"), _el$158 = _$createTextNode(`
1900
+ var _c$16 = _$memo(() => rt()?.evaluatorRejectionCount > 0);
1901
+ return () => _c$16() && [(() => {
1902
+ var _el$184 = _$createElement("span"), _el$185 = _$createTextNode(`
1627
1903
  \u26A0 rejections: `);
1628
- _$insertNode(_el$157, _el$158);
1629
- _$effect((_$p) => _$setProp(_el$157, "style", {
1904
+ _$insertNode(_el$184, _el$185);
1905
+ _$effect((_$p) => _$setProp(_el$184, "style", {
1630
1906
  fg: theme().warning
1631
1907
  }, _$p));
1632
- return _el$157;
1908
+ return _el$184;
1633
1909
  })(), (() => {
1634
- var _el$160 = _$createElement("span"), _el$161 = _$createTextNode(` \u2014 `);
1635
- _$insertNode(_el$160, _el$161);
1636
- _$insert(_el$160, () => String(rt().evaluatorRejectionCount), _el$161);
1637
- _$insert(_el$160, () => String(rt().lastRejectionDetails || "").slice(0, 80), null);
1638
- _$effect((_$p) => _$setProp(_el$160, "style", {
1910
+ var _el$187 = _$createElement("span"), _el$188 = _$createTextNode(` \u2014 `);
1911
+ _$insertNode(_el$187, _el$188);
1912
+ _$insert(_el$187, () => String(rt().evaluatorRejectionCount), _el$188);
1913
+ _$insert(_el$187, () => String(rt().lastRejectionDetails || "").slice(0, 80), null);
1914
+ _$effect((_$p) => _$setProp(_el$187, "style", {
1639
1915
  fg: theme().warning
1640
1916
  }, _$p));
1641
- return _el$160;
1917
+ return _el$187;
1642
1918
  })()];
1643
1919
  })(), null);
1644
1920
  _$insert(_el$122, (() => {
1645
- var _c$16 = _$memo(() => rt()?.unknownStatusCount > 0);
1646
- return () => _c$16() && [(() => {
1647
- var _el$162 = _$createElement("span"), _el$163 = _$createTextNode(`
1921
+ var _c$17 = _$memo(() => rt()?.unknownStatusCount > 0);
1922
+ return () => _c$17() && [(() => {
1923
+ var _el$189 = _$createElement("span"), _el$190 = _$createTextNode(`
1648
1924
  \u26A0\uFE0F unreachable: `);
1649
- _$insertNode(_el$162, _el$163);
1650
- _$effect((_$p) => _$setProp(_el$162, "style", {
1925
+ _$insertNode(_el$189, _el$190);
1926
+ _$effect((_$p) => _$setProp(_el$189, "style", {
1651
1927
  fg: theme().error
1652
1928
  }, _$p));
1653
- return _el$162;
1929
+ return _el$189;
1654
1930
  })(), (() => {
1655
- var _el$165 = _$createElement("span"), _el$166 = _$createTextNode(`/3`);
1656
- _$insertNode(_el$165, _el$166);
1657
- _$insert(_el$165, () => String(rt().unknownStatusCount), _el$166);
1658
- _$effect((_$p) => _$setProp(_el$165, "style", {
1931
+ var _el$192 = _$createElement("span"), _el$193 = _$createTextNode(`/3`);
1932
+ _$insertNode(_el$192, _el$193);
1933
+ _$insert(_el$192, () => String(rt().unknownStatusCount), _el$193);
1934
+ _$effect((_$p) => _$setProp(_el$192, "style", {
1659
1935
  fg: theme().error
1660
1936
  }, _$p));
1661
- return _el$165;
1937
+ return _el$192;
1662
1938
  })(), (() => {
1663
- var _el$167 = _$createElement("span");
1664
- _$insertNode(_el$167, _$createTextNode(` \u2014 nudge to recover`));
1665
- _$effect((_$p) => _$setProp(_el$167, "style", {
1939
+ var _el$194 = _$createElement("span");
1940
+ _$insertNode(_el$194, _$createTextNode(` \u2014 nudge to recover`));
1941
+ _$effect((_$p) => _$setProp(_el$194, "style", {
1666
1942
  fg: theme().textMuted
1667
1943
  }, _$p));
1668
- return _el$167;
1944
+ return _el$194;
1669
1945
  })()];
1670
1946
  })(), null);
1671
1947
  _$insert(_el$122, (() => {
1672
- var _c$17 = _$memo(() => !!rt()?.retryAfter);
1673
- return () => _c$17() && [(() => {
1674
- var _el$169 = _$createElement("span"), _el$170 = _$createTextNode(`
1948
+ var _c$18 = _$memo(() => !!rt()?.retryAfter);
1949
+ return () => _c$18() && [(() => {
1950
+ var _el$196 = _$createElement("span"), _el$197 = _$createTextNode(`
1675
1951
  \u21BB retry in: `);
1676
- _$insertNode(_el$169, _el$170);
1677
- _$effect((_$p) => _$setProp(_el$169, "style", {
1952
+ _$insertNode(_el$196, _el$197);
1953
+ _$effect((_$p) => _$setProp(_el$196, "style", {
1678
1954
  fg: theme().accent
1679
1955
  }, _$p));
1680
- return _el$169;
1956
+ return _el$196;
1681
1957
  })(), (() => {
1682
- var _el$172 = _$createElement("span");
1683
- _$insert(_el$172, () => countdownLabel(rt().retryAfter, clock()));
1684
- _$effect((_$p) => _$setProp(_el$172, "style", {
1958
+ var _el$199 = _$createElement("span");
1959
+ _$insert(_el$199, () => countdownLabel(rt().retryAfter, clock()));
1960
+ _$effect((_$p) => _$setProp(_el$199, "style", {
1685
1961
  fg: theme().accent
1686
1962
  }, _$p));
1687
- return _el$172;
1963
+ return _el$199;
1688
1964
  })()];
1689
1965
  })(), null);
1690
1966
  _$insert(_el$122, (() => {
1691
- var _c$18 = _$memo(() => !!rt()?.nextRunAt);
1692
- return () => _c$18() && [(() => {
1693
- var _el$173 = _$createElement("span"), _el$174 = _$createTextNode(`
1967
+ var _c$19 = _$memo(() => !!rt()?.nextRunAt);
1968
+ return () => _c$19() && [(() => {
1969
+ var _el$200 = _$createElement("span"), _el$201 = _$createTextNode(`
1694
1970
  \u23F0 next run: `);
1695
- _$insertNode(_el$173, _el$174);
1696
- _$effect((_$p) => _$setProp(_el$173, "style", {
1971
+ _$insertNode(_el$200, _el$201);
1972
+ _$effect((_$p) => _$setProp(_el$200, "style", {
1697
1973
  fg: theme().accent
1698
1974
  }, _$p));
1699
- return _el$173;
1975
+ return _el$200;
1700
1976
  })(), (() => {
1701
- var _el$176 = _$createElement("span");
1702
- _$insert(_el$176, () => countdownLabel(rt().nextRunAt, clock()));
1703
- _$effect((_$p) => _$setProp(_el$176, "style", {
1977
+ var _el$203 = _$createElement("span");
1978
+ _$insert(_el$203, () => countdownLabel(rt().nextRunAt, clock()));
1979
+ _$effect((_$p) => _$setProp(_el$203, "style", {
1704
1980
  fg: theme().accent
1705
1981
  }, _$p));
1706
- return _el$176;
1982
+ return _el$203;
1707
1983
  })(), (() => {
1708
- var _el$177 = _$createElement("span"), _el$178 = _$createTextNode(` (`), _el$179 = _$createTextNode(` runs)`);
1709
- _$insertNode(_el$177, _el$178);
1710
- _$insertNode(_el$177, _el$179);
1711
- _$insert(_el$177, () => String(rt().scheduleRunCount || 0), _el$179);
1712
- _$effect((_$p) => _$setProp(_el$177, "style", {
1984
+ var _el$204 = _$createElement("span"), _el$205 = _$createTextNode(` (`), _el$206 = _$createTextNode(` runs)`);
1985
+ _$insertNode(_el$204, _el$205);
1986
+ _$insertNode(_el$204, _el$206);
1987
+ _$insert(_el$204, () => String(rt().scheduleRunCount || 0), _el$206);
1988
+ _$effect((_$p) => _$setProp(_el$204, "style", {
1713
1989
  fg: theme().textMuted
1714
1990
  }, _$p));
1715
- return _el$177;
1991
+ return _el$204;
1716
1992
  })()];
1717
1993
  })(), null);
1718
1994
  _$insert(_el$122, (() => {
1719
- var _c$19 = _$memo(() => !!rt()?.lastError);
1720
- return () => _c$19() && [(() => {
1721
- var _el$180 = _$createElement("span"), _el$181 = _$createTextNode(`
1995
+ var _c$20 = _$memo(() => !!rt()?.lastError);
1996
+ return () => _c$20() && [(() => {
1997
+ var _el$207 = _$createElement("span"), _el$208 = _$createTextNode(`
1722
1998
  \u26A0 `);
1723
- _$insertNode(_el$180, _el$181);
1724
- _$effect((_$p) => _$setProp(_el$180, "style", {
1999
+ _$insertNode(_el$207, _el$208);
2000
+ _$effect((_$p) => _$setProp(_el$207, "style", {
1725
2001
  fg: theme().error
1726
2002
  }, _$p));
1727
- return _el$180;
2003
+ return _el$207;
1728
2004
  })(), (() => {
1729
- var _el$183 = _$createElement("span");
1730
- _$insert(_el$183, () => rt().lastError.slice(0, 120));
1731
- _$effect((_$p) => _$setProp(_el$183, "style", {
2005
+ var _el$210 = _$createElement("span");
2006
+ _$insert(_el$210, () => rt().lastError.slice(0, 120));
2007
+ _$effect((_$p) => _$setProp(_el$210, "style", {
1732
2008
  fg: theme().error
1733
2009
  }, _$p));
1734
- return _el$183;
2010
+ return _el$210;
1735
2011
  })()];
1736
2012
  })(), null);
1737
2013
  _$effect((_p$) => {
@@ -1781,29 +2057,29 @@ function LoopDashboard(props) {
1781
2057
  },
1782
2058
  children: (ev) => [`
1783
2059
  `, (() => {
1784
- var _el$184 = _$createElement("span");
1785
- _$insert(_el$184, () => String(ev.type));
1786
- _$effect((_$p) => _$setProp(_el$184, "style", {
2060
+ var _el$211 = _$createElement("span");
2061
+ _$insert(_el$211, () => String(ev.type));
2062
+ _$effect((_$p) => _$setProp(_el$211, "style", {
1787
2063
  fg: eventColor(String(ev.type), theme()),
1788
2064
  bold: true
1789
2065
  }, _$p));
1790
- return _el$184;
2066
+ return _el$211;
1791
2067
  })(), (() => {
1792
- var _el$185 = _$createElement("span"), _el$186 = _$createTextNode(` `);
1793
- _$insertNode(_el$185, _el$186);
1794
- _$insert(_el$185, () => ev.goalID?.slice(0, 8), null);
1795
- _$effect((_$p) => _$setProp(_el$185, "style", {
2068
+ var _el$212 = _$createElement("span"), _el$213 = _$createTextNode(` `);
2069
+ _$insertNode(_el$212, _el$213);
2070
+ _$insert(_el$212, () => ev.goalID?.slice(0, 8), null);
2071
+ _$effect((_$p) => _$setProp(_el$212, "style", {
1796
2072
  fg: theme().textMuted
1797
2073
  }, _$p));
1798
- return _el$185;
2074
+ return _el$212;
1799
2075
  })(), _$memo(() => _$memo(() => !!ev.summary)() && (() => {
1800
- var _el$187 = _$createElement("span"), _el$188 = _$createTextNode(` \u2014 `);
1801
- _$insertNode(_el$187, _el$188);
1802
- _$insert(_el$187, () => String(ev.summary).slice(0, 60), null);
1803
- _$effect((_$p) => _$setProp(_el$187, "style", {
2076
+ var _el$214 = _$createElement("span"), _el$215 = _$createTextNode(` \u2014 `);
2077
+ _$insertNode(_el$214, _el$215);
2078
+ _$insert(_el$214, () => String(ev.summary).slice(0, 60), null);
2079
+ _$effect((_$p) => _$setProp(_el$214, "style", {
1804
2080
  fg: theme().text
1805
2081
  }, _$p));
1806
- return _el$187;
2082
+ return _el$214;
1807
2083
  })())]
1808
2084
  }), null);
1809
2085
  _$effect((_p$) => {
@@ -1857,18 +2133,6 @@ function LoopDashboard(props) {
1857
2133
  prevent(evt);
1858
2134
  return;
1859
2135
  }
1860
- if (name === "return" || name === "enter") {
1861
- prevent(evt);
1862
- debugLog("input enter -> execute");
1863
- executeCommand(commandInput());
1864
- return;
1865
- }
1866
- if (evt.ctrl && name.toLowerCase() === "n") {
1867
- prevent(evt);
1868
- debugLog("input ctrl+n -> normal");
1869
- returnToNormalMode();
1870
- return;
1871
- }
1872
2136
  });
1873
2137
  _$effect((_p$) => {
1874
2138
  var _v$4 = theme().border, _v$5 = {