@wrongstack/tui 0.10.0 → 0.10.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 +242 -93
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -35,6 +35,8 @@ var theme = Object.freeze({
|
|
|
35
35
|
diffAddBg: "greenBright",
|
|
36
36
|
diffDelBg: "redBright"
|
|
37
37
|
});
|
|
38
|
+
var COMPACT_THRESHOLD = 50;
|
|
39
|
+
var COMFORTABLE_THRESHOLD = 90;
|
|
38
40
|
function StatusBar({
|
|
39
41
|
model,
|
|
40
42
|
version,
|
|
@@ -58,6 +60,18 @@ function StatusBar({
|
|
|
58
60
|
eternalStage,
|
|
59
61
|
goalSummary
|
|
60
62
|
}) {
|
|
63
|
+
const { stdout } = useStdout();
|
|
64
|
+
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const handleResize = () => setTermWidth(stdout?.columns ?? 90);
|
|
67
|
+
handleResize();
|
|
68
|
+
process.stdout.on("resize", handleResize);
|
|
69
|
+
return () => {
|
|
70
|
+
process.stdout.off("resize", handleResize);
|
|
71
|
+
};
|
|
72
|
+
}, [stdout]);
|
|
73
|
+
const isCompact = termWidth < COMPACT_THRESHOLD;
|
|
74
|
+
const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
|
|
61
75
|
const hiddenSet = new Set(hiddenItems);
|
|
62
76
|
const usage = tokenCounter?.total();
|
|
63
77
|
const cost = tokenCounter?.estimateCost();
|
|
@@ -77,74 +91,87 @@ function StatusBar({
|
|
|
77
91
|
borderLeft: false,
|
|
78
92
|
borderRight: false,
|
|
79
93
|
children: [
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: isCompact ? (
|
|
95
|
+
// Ultra-compact: state · model
|
|
96
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
+
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
98
|
+
"\u25CF",
|
|
99
|
+
stateLabel
|
|
100
|
+
] }),
|
|
101
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
102
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: model })
|
|
103
|
+
] })
|
|
104
|
+
) : (
|
|
105
|
+
// Full mode: version · state · model · context · tokens · cost · queue · processes · hint
|
|
106
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
107
|
+
version ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
108
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", bold: true, children: "WS" }),
|
|
110
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
111
|
+
" v",
|
|
112
|
+
version
|
|
113
|
+
] })
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
|
|
116
|
+
] }) : null,
|
|
117
|
+
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
118
|
+
"\u25CF ",
|
|
119
|
+
stateLabel
|
|
88
120
|
] }),
|
|
89
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" })
|
|
90
|
-
] }) : null,
|
|
91
|
-
/* @__PURE__ */ jsxs(Text, { color: stateColor, children: [
|
|
92
|
-
"\u25CF ",
|
|
93
|
-
stateLabel
|
|
94
|
-
] }),
|
|
95
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
96
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
|
|
97
|
-
context && context.max > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
99
|
-
/* @__PURE__ */ jsx(ContextChip, { ctx: context })
|
|
100
|
-
] }) : null,
|
|
101
|
-
usage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
102
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
103
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
104
|
-
"\u2191",
|
|
105
|
-
" ",
|
|
106
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)) }),
|
|
107
|
-
" ",
|
|
108
|
-
"\u2193 ",
|
|
109
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.output) })
|
|
110
|
-
] })
|
|
111
|
-
] }) : null,
|
|
112
|
-
cache2 && cache2.hitRatio > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
113
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
114
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
115
|
-
"cache ",
|
|
116
|
-
(cache2.hitRatio * 100).toFixed(0),
|
|
117
|
-
"%"
|
|
118
|
-
] })
|
|
119
|
-
] }) : null,
|
|
120
|
-
cost && cost.total > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
121
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
122
|
-
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
123
|
-
"$",
|
|
124
|
-
cost.total.toFixed(4)
|
|
125
|
-
] })
|
|
126
|
-
] }) : null,
|
|
127
|
-
queueCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
128
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
129
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
130
|
-
"\u231B queued: ",
|
|
131
|
-
queueCount
|
|
132
|
-
] })
|
|
133
|
-
] }) : null,
|
|
134
|
-
typeof processCount === "number" && processCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
135
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
136
|
-
/* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
137
|
-
"\u26A1 ",
|
|
138
|
-
processCount,
|
|
139
|
-
" process",
|
|
140
|
-
processCount === 1 ? "" : "es"
|
|
141
|
-
] })
|
|
142
|
-
] }) : null,
|
|
143
|
-
hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
144
121
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
145
|
-
/* @__PURE__ */ jsx(Text, {
|
|
146
|
-
|
|
147
|
-
|
|
122
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: model }),
|
|
123
|
+
context && context.max > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
125
|
+
/* @__PURE__ */ jsx(ContextChip, { ctx: context })
|
|
126
|
+
] }) : null,
|
|
127
|
+
usage && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
128
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
129
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
130
|
+
"\u2191",
|
|
131
|
+
" ",
|
|
132
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)) }),
|
|
133
|
+
" ",
|
|
134
|
+
"\u2193 ",
|
|
135
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: fmtTok(usage.output) })
|
|
136
|
+
] })
|
|
137
|
+
] }) : null,
|
|
138
|
+
cache2 && cache2.hitRatio > 0 && isComfortable ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
139
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
140
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
141
|
+
"cache ",
|
|
142
|
+
(cache2.hitRatio * 100).toFixed(0),
|
|
143
|
+
"%"
|
|
144
|
+
] })
|
|
145
|
+
] }) : null,
|
|
146
|
+
cost && cost.total > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
147
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
148
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
149
|
+
"$",
|
|
150
|
+
cost.total.toFixed(4)
|
|
151
|
+
] })
|
|
152
|
+
] }) : null,
|
|
153
|
+
queueCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
154
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
155
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
156
|
+
"\u231B queued: ",
|
|
157
|
+
queueCount
|
|
158
|
+
] })
|
|
159
|
+
] }) : null,
|
|
160
|
+
typeof processCount === "number" && processCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
161
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
162
|
+
/* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
163
|
+
"\u26A1 ",
|
|
164
|
+
processCount,
|
|
165
|
+
" process",
|
|
166
|
+
processCount === 1 ? "" : "es"
|
|
167
|
+
] })
|
|
168
|
+
] }) : null,
|
|
169
|
+
hint ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
170
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
171
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hint })
|
|
172
|
+
] }) : null
|
|
173
|
+
] })
|
|
174
|
+
) }),
|
|
148
175
|
hasSecondLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
149
176
|
yolo ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
|
|
150
177
|
autonomy && autonomy !== "off" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -1029,8 +1056,19 @@ function highlight(path3, _query) {
|
|
|
1029
1056
|
return path3;
|
|
1030
1057
|
}
|
|
1031
1058
|
function FleetPanel({ entries, totalCost, collabSession }) {
|
|
1059
|
+
const { stdout } = useStdout();
|
|
1060
|
+
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
1061
|
+
useEffect(() => {
|
|
1062
|
+
const handleResize = () => setTermWidth(stdout?.columns ?? 90);
|
|
1063
|
+
handleResize();
|
|
1064
|
+
process.stdout.on("resize", handleResize);
|
|
1065
|
+
return () => {
|
|
1066
|
+
process.stdout.off("resize", handleResize);
|
|
1067
|
+
};
|
|
1068
|
+
}, [stdout]);
|
|
1032
1069
|
const list = Object.values(entries);
|
|
1033
1070
|
if (list.length === 0 && !collabSession) return null;
|
|
1071
|
+
const nameMaxLen = Math.max(6, Math.min(14, termWidth - 30));
|
|
1034
1072
|
const leader = list.find((e) => e.id === "leader");
|
|
1035
1073
|
const subagents = list.filter((e) => e.id !== "leader");
|
|
1036
1074
|
const running = subagents.filter((e) => e.status === "running");
|
|
@@ -1050,16 +1088,16 @@ function FleetPanel({ entries, totalCost, collabSession }) {
|
|
|
1050
1088
|
] }),
|
|
1051
1089
|
hasCollab && leader ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1052
1090
|
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25CF" }),
|
|
1053
|
-
/* @__PURE__ */ jsx(Text, { children: leader.name.slice(0,
|
|
1091
|
+
/* @__PURE__ */ jsx(Text, { children: leader.name.slice(0, nameMaxLen) }),
|
|
1054
1092
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
1055
1093
|
/* @__PURE__ */ jsx(Text, { color: "yellow", children: leaderTool })
|
|
1056
1094
|
] }) : null,
|
|
1057
1095
|
shown.map((entry) => {
|
|
1058
|
-
const name = entry.name && entry.name !== entry.id ? entry.name : entry.id.slice(0,
|
|
1096
|
+
const name = entry.name && entry.name !== entry.id ? entry.name : entry.id.slice(0, nameMaxLen);
|
|
1059
1097
|
const tool = entry.currentTool?.name ?? "\u2014";
|
|
1060
1098
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1061
1099
|
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF" }),
|
|
1062
|
-
/* @__PURE__ */ jsx(Text, { children: name.slice(0,
|
|
1100
|
+
/* @__PURE__ */ jsx(Text, { children: name.slice(0, nameMaxLen) }),
|
|
1063
1101
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
1064
1102
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: tool })
|
|
1065
1103
|
] }, entry.id);
|
|
@@ -1069,7 +1107,7 @@ function FleetPanel({ entries, totalCost, collabSession }) {
|
|
|
1069
1107
|
"+",
|
|
1070
1108
|
overflow,
|
|
1071
1109
|
": ",
|
|
1072
|
-
running[3]?.name?.slice(0,
|
|
1110
|
+
running[3]?.name?.slice(0, nameMaxLen - 2) ?? "agent",
|
|
1073
1111
|
"\u2026"
|
|
1074
1112
|
] }) : null
|
|
1075
1113
|
] });
|
|
@@ -1631,6 +1669,14 @@ function parseAlign(sep2) {
|
|
|
1631
1669
|
if (right) return "right";
|
|
1632
1670
|
return "left";
|
|
1633
1671
|
}
|
|
1672
|
+
function parseSeparatorWidths(sepCells) {
|
|
1673
|
+
return sepCells.map((cell) => {
|
|
1674
|
+
const trimmed = cell.trim();
|
|
1675
|
+
const dashes = trimmed.replace(/:/g, "");
|
|
1676
|
+
if (/^-+$/.test(dashes)) return dashes.length;
|
|
1677
|
+
return null;
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1634
1680
|
function renderTable(tableLines, maxWidth) {
|
|
1635
1681
|
const header = parseCells(tableLines[0] ?? "");
|
|
1636
1682
|
const sepCells = parseCells(tableLines[1] ?? "");
|
|
@@ -1644,7 +1690,8 @@ function renderTable(tableLines, maxWidth) {
|
|
|
1644
1690
|
while (row.length < cols) row.push("");
|
|
1645
1691
|
row.length = cols;
|
|
1646
1692
|
}
|
|
1647
|
-
const
|
|
1693
|
+
const sepWidths = parseSeparatorWidths(sepCells);
|
|
1694
|
+
const widths = computeWidths([header, ...dataRows], cols, maxWidth, sepWidths);
|
|
1648
1695
|
const lines = [];
|
|
1649
1696
|
lines.push(border("\u250C", "\u252C", "\u2510", widths));
|
|
1650
1697
|
lines.push(...renderRow(header, widths, aligns));
|
|
@@ -1655,7 +1702,7 @@ function renderTable(tableLines, maxWidth) {
|
|
|
1655
1702
|
lines.push(border("\u2514", "\u2534", "\u2518", widths));
|
|
1656
1703
|
return lines.join("\n");
|
|
1657
1704
|
}
|
|
1658
|
-
function computeWidths(allRows, cols, maxWidth) {
|
|
1705
|
+
function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
1659
1706
|
const overhead = 3 * cols + 1;
|
|
1660
1707
|
const avail = Math.max(cols * MIN_COL_WIDTH, maxWidth - overhead);
|
|
1661
1708
|
const natural = new Array(cols).fill(0);
|
|
@@ -1663,9 +1710,16 @@ function computeWidths(allRows, cols, maxWidth) {
|
|
|
1663
1710
|
for (let c = 0; c < cols; c++) {
|
|
1664
1711
|
const cell = row[c] ?? "";
|
|
1665
1712
|
const w = longestWord(cell);
|
|
1666
|
-
const total = cell
|
|
1667
|
-
natural[c] = Math.max(natural[c], total);
|
|
1668
|
-
|
|
1713
|
+
const total = strWidth(cell);
|
|
1714
|
+
natural[c] = Math.max(natural[c], w, total);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
if (sepWidths) {
|
|
1718
|
+
for (let c = 0; c < cols && c < sepWidths.length; c++) {
|
|
1719
|
+
const sepW = sepWidths[c];
|
|
1720
|
+
if (sepW != null) {
|
|
1721
|
+
natural[c] = Math.max(natural[c], sepW);
|
|
1722
|
+
}
|
|
1669
1723
|
}
|
|
1670
1724
|
}
|
|
1671
1725
|
const sumNatural = natural.reduce((s2, n) => s2 + n, 0);
|
|
@@ -1689,9 +1743,51 @@ function computeWidths(allRows, cols, maxWidth) {
|
|
|
1689
1743
|
return widths;
|
|
1690
1744
|
}
|
|
1691
1745
|
var MIN_COL_WIDTH = 4;
|
|
1746
|
+
function strWidth(s2) {
|
|
1747
|
+
let width = 0;
|
|
1748
|
+
for (const cp of s2) {
|
|
1749
|
+
const code = cp.codePointAt(0);
|
|
1750
|
+
if (code < 32 || code >= 127 && code < 160) {
|
|
1751
|
+
continue;
|
|
1752
|
+
}
|
|
1753
|
+
if (code >= 126976 || // Supplementary Pictographs (U+1F000-U+1FFFF)
|
|
1754
|
+
code >= 9728 && code <= 10175 || // Miscellaneous Symbols, Dingbats
|
|
1755
|
+
code >= 8960 && code <= 9215 || // Miscellaneous Technical
|
|
1756
|
+
code >= 11088 && code <= 11093 || // Stars and similar
|
|
1757
|
+
code >= 10548 && code <= 10549 || // Arrow forms
|
|
1758
|
+
code >= 8592 && code <= 8703 || // Arrows
|
|
1759
|
+
code >= 9632 && code <= 9727 || // Geometric Shapes
|
|
1760
|
+
code >= 9664 && code <= 9726 || // More Geometric Shapes (includes ▶)
|
|
1761
|
+
code >= 9984 && code <= 10175) {
|
|
1762
|
+
width += 2;
|
|
1763
|
+
continue;
|
|
1764
|
+
}
|
|
1765
|
+
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
1766
|
+
code === 9001 || // LEFT-POINTING ANGLE BRACKET
|
|
1767
|
+
code === 9002 || // RIGHT-POINTING ANGLE BRACKET
|
|
1768
|
+
code >= 11904 && code <= 12350 || // CJK Radicals Supplement
|
|
1769
|
+
code >= 12352 && code <= 42191 || // Hiragana, Katakana, CJK
|
|
1770
|
+
code >= 44032 && code <= 55203 || // Hangul Syllables
|
|
1771
|
+
code >= 63744 && code <= 64249 || // CJK Compatibility Ideographs
|
|
1772
|
+
code >= 65040 && code <= 65055 || // Vertical forms
|
|
1773
|
+
code >= 65072 && code <= 65135 || // CJK Compatibility Forms
|
|
1774
|
+
code >= 65280 && code <= 65376 || // Fullwidth Forms
|
|
1775
|
+
code >= 65504 && code <= 65510 || // Halfwidth and Fullwidth Forms
|
|
1776
|
+
code >= 131072 && code <= 196605 || // CJK Extension B+
|
|
1777
|
+
code >= 196608 && code <= 262141) {
|
|
1778
|
+
width += 2;
|
|
1779
|
+
continue;
|
|
1780
|
+
}
|
|
1781
|
+
width += 1;
|
|
1782
|
+
}
|
|
1783
|
+
return width;
|
|
1784
|
+
}
|
|
1692
1785
|
function longestWord(s2) {
|
|
1693
1786
|
let max = 0;
|
|
1694
|
-
for (const w of s2.split(/\s+/))
|
|
1787
|
+
for (const w of s2.split(/\s+/)) {
|
|
1788
|
+
const visualWidth = strWidth(w);
|
|
1789
|
+
if (visualWidth > max) max = visualWidth;
|
|
1790
|
+
}
|
|
1695
1791
|
return max;
|
|
1696
1792
|
}
|
|
1697
1793
|
function border(left, mid, right, widths) {
|
|
@@ -1713,43 +1809,86 @@ function renderRow(cells, widths, aligns) {
|
|
|
1713
1809
|
return out;
|
|
1714
1810
|
}
|
|
1715
1811
|
function wrapCell(text, width) {
|
|
1716
|
-
if (text
|
|
1812
|
+
if (strWidth(text) <= width) return [text];
|
|
1717
1813
|
const out = [];
|
|
1718
1814
|
const words = text.split(/(\s+)/);
|
|
1719
1815
|
let cur = "";
|
|
1816
|
+
let curWidth = 0;
|
|
1720
1817
|
for (const word of words) {
|
|
1721
1818
|
if (!word) continue;
|
|
1722
|
-
|
|
1819
|
+
const wordWidth = strWidth(word);
|
|
1820
|
+
if (curWidth + wordWidth <= width) {
|
|
1723
1821
|
cur += word;
|
|
1822
|
+
curWidth += wordWidth;
|
|
1724
1823
|
continue;
|
|
1725
1824
|
}
|
|
1726
1825
|
if (cur) {
|
|
1727
|
-
out.push(cur
|
|
1826
|
+
out.push(padVisual(cur, width));
|
|
1728
1827
|
cur = "";
|
|
1828
|
+
curWidth = 0;
|
|
1729
1829
|
}
|
|
1730
|
-
if (
|
|
1830
|
+
if (wordWidth > width) {
|
|
1731
1831
|
let rest = word;
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1832
|
+
let restWidth = wordWidth;
|
|
1833
|
+
while (restWidth > width) {
|
|
1834
|
+
let collected = "";
|
|
1835
|
+
let collectedWidth = 0;
|
|
1836
|
+
for (const cp of rest) {
|
|
1837
|
+
const cpWidth = strWidth(cp);
|
|
1838
|
+
if (collectedWidth + cpWidth > width) break;
|
|
1839
|
+
collected += cp;
|
|
1840
|
+
collectedWidth += cpWidth;
|
|
1841
|
+
}
|
|
1842
|
+
out.push(padVisual(collected, width));
|
|
1843
|
+
rest = rest.slice([...collected].join("").length);
|
|
1844
|
+
restWidth = strWidth(rest);
|
|
1735
1845
|
}
|
|
1736
1846
|
cur = rest;
|
|
1847
|
+
curWidth = strWidth(rest);
|
|
1737
1848
|
} else if (!/^\s+$/.test(word)) {
|
|
1738
1849
|
cur = word;
|
|
1850
|
+
curWidth = wordWidth;
|
|
1739
1851
|
}
|
|
1740
1852
|
}
|
|
1741
|
-
if (cur) out.push(cur
|
|
1853
|
+
if (cur) out.push(padVisual(cur, width));
|
|
1742
1854
|
return out.length === 0 ? [""] : out;
|
|
1743
1855
|
}
|
|
1856
|
+
function padVisual(text, targetWidth) {
|
|
1857
|
+
const w = strWidth(text);
|
|
1858
|
+
if (w >= targetWidth) {
|
|
1859
|
+
let taken = 0;
|
|
1860
|
+
let endIdx = 0;
|
|
1861
|
+
for (const cp of text) {
|
|
1862
|
+
const cpw = strWidth(cp);
|
|
1863
|
+
if (taken + cpw > targetWidth) break;
|
|
1864
|
+
taken += cpw;
|
|
1865
|
+
endIdx += [...cp].join("").length;
|
|
1866
|
+
}
|
|
1867
|
+
return text.slice(0, endIdx);
|
|
1868
|
+
}
|
|
1869
|
+
return text + " ".repeat(targetWidth - w);
|
|
1870
|
+
}
|
|
1744
1871
|
function padCell(text, width, align) {
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
if (
|
|
1872
|
+
const visualLen = strWidth(text);
|
|
1873
|
+
let displayText = text;
|
|
1874
|
+
if (visualLen > width) {
|
|
1875
|
+
let takenWidth = 0;
|
|
1876
|
+
let endIdx = 0;
|
|
1877
|
+
for (const cp of text) {
|
|
1878
|
+
const cpWidth = strWidth(cp);
|
|
1879
|
+
if (takenWidth + cpWidth > width) break;
|
|
1880
|
+
takenWidth += cpWidth;
|
|
1881
|
+
endIdx += [...cp].join("").length;
|
|
1882
|
+
}
|
|
1883
|
+
displayText = text.slice(0, endIdx);
|
|
1884
|
+
}
|
|
1885
|
+
const pad = width - strWidth(displayText);
|
|
1886
|
+
if (align === "right") return " ".repeat(pad) + displayText;
|
|
1748
1887
|
if (align === "center") {
|
|
1749
1888
|
const l = Math.floor(pad / 2);
|
|
1750
|
-
return " ".repeat(l) +
|
|
1889
|
+
return " ".repeat(l) + displayText + " ".repeat(pad - l);
|
|
1751
1890
|
}
|
|
1752
|
-
return
|
|
1891
|
+
return displayText + " ".repeat(pad);
|
|
1753
1892
|
}
|
|
1754
1893
|
function parseInline(text) {
|
|
1755
1894
|
const tokens = [];
|
|
@@ -5760,6 +5899,12 @@ function App({
|
|
|
5760
5899
|
}, [agent.ctx.meta]);
|
|
5761
5900
|
const prevAnyOverlayOpen = useRef(false);
|
|
5762
5901
|
const prevEntriesCount = useRef(0);
|
|
5902
|
+
const eraseLiveRegion = () => {
|
|
5903
|
+
try {
|
|
5904
|
+
process.stdout.write("\x1B[J");
|
|
5905
|
+
} catch {
|
|
5906
|
+
}
|
|
5907
|
+
};
|
|
5763
5908
|
useEffect(() => {
|
|
5764
5909
|
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.confirmQueue.length > 0;
|
|
5765
5910
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
@@ -5767,10 +5912,7 @@ function App({
|
|
|
5767
5912
|
prevAnyOverlayOpen.current = anyOpenNow;
|
|
5768
5913
|
prevEntriesCount.current = state.entries.length;
|
|
5769
5914
|
if (overlayClosed || newEntryCommitted) {
|
|
5770
|
-
|
|
5771
|
-
process.stdout.write("\x1B[J");
|
|
5772
|
-
} catch {
|
|
5773
|
-
}
|
|
5915
|
+
eraseLiveRegion();
|
|
5774
5916
|
}
|
|
5775
5917
|
}, [
|
|
5776
5918
|
state.picker.open,
|
|
@@ -5781,6 +5923,13 @@ function App({
|
|
|
5781
5923
|
state.confirmQueue.length,
|
|
5782
5924
|
state.entries.length
|
|
5783
5925
|
]);
|
|
5926
|
+
useEffect(() => {
|
|
5927
|
+
const handleResize = () => eraseLiveRegion();
|
|
5928
|
+
process.stdout.on("resize", handleResize);
|
|
5929
|
+
return () => {
|
|
5930
|
+
process.stdout.off("resize", handleResize);
|
|
5931
|
+
};
|
|
5932
|
+
}, []);
|
|
5784
5933
|
useEffect(() => {
|
|
5785
5934
|
const detected = detectAtToken(state.buffer, state.cursor);
|
|
5786
5935
|
if (!detected) {
|