@wrongstack/tui 0.8.6 → 0.9.0
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 +81 -178
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -162,156 +162,37 @@ function FilePicker({ query, matches, selected }) {
|
|
|
162
162
|
function highlight(path3, query) {
|
|
163
163
|
return path3;
|
|
164
164
|
}
|
|
165
|
-
var STATUS_ICON = {
|
|
166
|
-
idle: { icon: "\u25CB", color: "gray" },
|
|
167
|
-
running: { icon: "\u25CF", color: "green" },
|
|
168
|
-
success: { icon: "\u2713", color: "green" },
|
|
169
|
-
failed: { icon: "\u2717", color: "red" },
|
|
170
|
-
timeout: { icon: "\u23F1", color: "yellow" },
|
|
171
|
-
stopped: { icon: "\u2298", color: "yellow" }
|
|
172
|
-
};
|
|
173
|
-
function fmtCost(n) {
|
|
174
|
-
if (n === 0) return "\u2014";
|
|
175
|
-
return `$${n.toFixed(3)}`;
|
|
176
|
-
}
|
|
177
|
-
function fmtCount(n) {
|
|
178
|
-
if (n === 0) return "\u2014";
|
|
179
|
-
return String(n);
|
|
180
|
-
}
|
|
181
|
-
function fmtDuration(ms) {
|
|
182
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
183
|
-
return `${(ms / 1e3).toFixed(1)}s`;
|
|
184
|
-
}
|
|
185
|
-
function fmtBytes(n) {
|
|
186
|
-
if (n < 1024) return `${n}B`;
|
|
187
|
-
return `${(n / 1024).toFixed(1)}KB`;
|
|
188
|
-
}
|
|
189
|
-
function fmtRecentTool(tool) {
|
|
190
|
-
const status = tool.ok === false ? "fail" : "ok";
|
|
191
|
-
const name = tool.name.length > 24 ? `${tool.name.slice(0, 23)}...` : tool.name;
|
|
192
|
-
const parts = [status, name];
|
|
193
|
-
if (typeof tool.durationMs === "number") parts.push(fmtDuration(tool.durationMs));
|
|
194
|
-
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes(tool.outputBytes));
|
|
195
|
-
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
196
|
-
return parts.join(" ");
|
|
197
|
-
}
|
|
198
|
-
function fmtRecentMessage(message) {
|
|
199
|
-
const text = message.text.replace(/\s+/g, " ");
|
|
200
|
-
return text.length > 80 ? `${text.slice(0, 79)}...` : text;
|
|
201
|
-
}
|
|
202
|
-
function fmtModel(provider, model) {
|
|
203
|
-
if (!provider && !model) return "";
|
|
204
|
-
const p = provider ?? "";
|
|
205
|
-
const m = model ?? "";
|
|
206
|
-
return p && m ? `${p}/${m}` : p || m;
|
|
207
|
-
}
|
|
208
|
-
function resolveName(entry, roster) {
|
|
209
|
-
const rosterEntry = roster?.[entry.id];
|
|
210
|
-
if (rosterEntry) return rosterEntry.name;
|
|
211
|
-
return entry.name;
|
|
212
|
-
}
|
|
213
165
|
function FleetPanel({ entries, totalCost, roster }) {
|
|
214
166
|
const list = Object.values(entries);
|
|
215
167
|
if (list.length === 0) return null;
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
245
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: totalLabel })
|
|
246
|
-
] }),
|
|
247
|
-
sorted.map((entry) => {
|
|
248
|
-
const si = STATUS_ICON[entry.status];
|
|
249
|
-
const modelTag = fmtModel(entry.provider, entry.model);
|
|
250
|
-
const name = resolveName(entry, roster);
|
|
251
|
-
const recentTools = (entry.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
|
|
252
|
-
const recentMessages = (entry.recentMessages ?? []).slice(-2).map(fmtRecentMessage);
|
|
253
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
254
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
255
|
-
/* @__PURE__ */ jsx(Text, { color: si.color, children: si.icon }),
|
|
256
|
-
/* @__PURE__ */ jsx(Text, { children: name.slice(0, 16).padEnd(16) }),
|
|
257
|
-
modelTag ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
258
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
259
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: modelTag })
|
|
260
|
-
] }) : null,
|
|
261
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
262
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
263
|
-
fmtCount(entry.iterations).padStart(3),
|
|
264
|
-
"it"
|
|
265
|
-
] }),
|
|
266
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
267
|
-
fmtCount(entry.toolCalls).padStart(3),
|
|
268
|
-
"tc"
|
|
269
|
-
] }),
|
|
270
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
271
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children: fmtCost(entry.cost) })
|
|
272
|
-
] }),
|
|
273
|
-
entry.status === "running" && entry.currentTool ? /* @__PURE__ */ jsxs(Box, { paddingLeft: 2, children: [
|
|
274
|
-
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
275
|
-
"\u2192 ",
|
|
276
|
-
entry.currentTool.name
|
|
277
|
-
] }),
|
|
278
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
279
|
-
" (",
|
|
280
|
-
Math.max(0, Date.now() - entry.currentTool.startedAt),
|
|
281
|
-
"ms)"
|
|
282
|
-
] })
|
|
283
|
-
] }) : null,
|
|
284
|
-
recentTools ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
285
|
-
"tools: ",
|
|
286
|
-
recentTools
|
|
287
|
-
] }) }) : null,
|
|
288
|
-
recentMessages.map((message, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
289
|
-
"msg: ",
|
|
290
|
-
message
|
|
291
|
-
] }) }, `${entry.id}-msg-${index}-${message}`)),
|
|
292
|
-
entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
293
|
-
"\u26A1 hitting ",
|
|
294
|
-
entry.budgetWarning.kind,
|
|
295
|
-
" limit (",
|
|
296
|
-
entry.budgetWarning.used,
|
|
297
|
-
"/",
|
|
298
|
-
entry.budgetWarning.limit,
|
|
299
|
-
") \u2014 extending"
|
|
300
|
-
] }) }) : null,
|
|
301
|
-
entry.status === "running" && entry.streamingText ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
302
|
-
">",
|
|
303
|
-
" ",
|
|
304
|
-
entry.streamingText.slice(-80)
|
|
305
|
-
] }) }) : null,
|
|
306
|
-
entry.transcriptPath ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
307
|
-
"log: ",
|
|
308
|
-
entry.transcriptPath
|
|
309
|
-
] }) }) : null
|
|
310
|
-
] }, entry.id);
|
|
311
|
-
})
|
|
312
|
-
]
|
|
313
|
-
}
|
|
314
|
-
);
|
|
168
|
+
const running = list.filter((e) => e.status === "running");
|
|
169
|
+
const runningCount = running.length;
|
|
170
|
+
const costLabel = totalCost > 0 ? ` \xB7 $${totalCost.toFixed(3)}` : "";
|
|
171
|
+
const summaryLine = runningCount > 0 ? `${runningCount} running${costLabel}` : `idle${costLabel}`;
|
|
172
|
+
const shown = running.slice(0, 3);
|
|
173
|
+
const overflow = running.length > 3 ? running.length - 3 : 0;
|
|
174
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
175
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
176
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u26A1 Fleet" }),
|
|
177
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
178
|
+
/* @__PURE__ */ jsx(Text, { children: summaryLine })
|
|
179
|
+
] }),
|
|
180
|
+
shown.map((entry) => {
|
|
181
|
+
const name = roster?.[entry.id]?.name ?? entry.name;
|
|
182
|
+
const tool = entry.currentTool?.name ?? "\u2014";
|
|
183
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
184
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF" }),
|
|
185
|
+
/* @__PURE__ */ jsx(Text, { children: name.slice(0, 12).padEnd(12) }),
|
|
186
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
187
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: tool })
|
|
188
|
+
] }, entry.id);
|
|
189
|
+
}),
|
|
190
|
+
overflow > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
191
|
+
" +",
|
|
192
|
+
overflow,
|
|
193
|
+
" more running"
|
|
194
|
+
] }) : null
|
|
195
|
+
] });
|
|
315
196
|
}
|
|
316
197
|
function StatusBar({
|
|
317
198
|
model,
|
|
@@ -721,7 +602,7 @@ function fmtTokens(n) {
|
|
|
721
602
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
722
603
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
723
604
|
}
|
|
724
|
-
function
|
|
605
|
+
function fmtCost(n) {
|
|
725
606
|
if (n === 0) return "\u2014";
|
|
726
607
|
return `$${n.toFixed(3)}`;
|
|
727
608
|
}
|
|
@@ -832,7 +713,7 @@ function FleetMonitor({
|
|
|
832
713
|
/* @__PURE__ */ jsx(Text, { color: s2.color, children: e.status.padEnd(10) }),
|
|
833
714
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `L${e.iterations} ${e.toolCalls}t`.padEnd(8) }),
|
|
834
715
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed.padEnd(8).slice(0, 8) }),
|
|
835
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children:
|
|
716
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: fmtCost(e.cost) }),
|
|
836
717
|
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
837
718
|
" \u26A1\xD7",
|
|
838
719
|
e.extensions
|
|
@@ -865,6 +746,20 @@ var STATUS2 = {
|
|
|
865
746
|
function isTerminal(status) {
|
|
866
747
|
return status === "success" || status === "failed" || status === "timeout" || status === "stopped";
|
|
867
748
|
}
|
|
749
|
+
var IDLE_HIDE_MS = 6e4;
|
|
750
|
+
function selectLiveAgents(all, now, idleHideMs = IDLE_HIDE_MS) {
|
|
751
|
+
const visible = all.filter((e) => {
|
|
752
|
+
if (isTerminal(e.status)) return false;
|
|
753
|
+
if (e.status === "running") return true;
|
|
754
|
+
return now - e.lastEventAt < idleHideMs;
|
|
755
|
+
});
|
|
756
|
+
return visible.sort((a, b) => {
|
|
757
|
+
if (a.status === "running" && b.status !== "running") return -1;
|
|
758
|
+
if (a.status !== "running" && b.status === "running") return 1;
|
|
759
|
+
if (a.status === "running") return a.startedAt - b.startedAt;
|
|
760
|
+
return b.lastEventAt - a.lastEventAt;
|
|
761
|
+
});
|
|
762
|
+
}
|
|
868
763
|
function fmtTokens2(n) {
|
|
869
764
|
if (n < 1e3) return String(n);
|
|
870
765
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
@@ -882,15 +777,14 @@ function AgentsMonitor({
|
|
|
882
777
|
nowTick
|
|
883
778
|
}) {
|
|
884
779
|
const all = Object.values(entries);
|
|
885
|
-
const live = all
|
|
780
|
+
const live = selectLiveAgents(all, nowTick);
|
|
886
781
|
const running = live.filter((e) => e.status === "running").length;
|
|
887
782
|
const totalDone = all.filter((e) => e.status === "success").length;
|
|
888
783
|
const totalFailed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
});
|
|
784
|
+
const hiddenIdle = all.filter(
|
|
785
|
+
(e) => e.status === "idle" && nowTick - e.lastEventAt >= IDLE_HIDE_MS
|
|
786
|
+
).length;
|
|
787
|
+
const ordered = live;
|
|
894
788
|
const shown = ordered.slice(0, 8);
|
|
895
789
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
896
790
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
@@ -927,7 +821,12 @@ function AgentsMonitor({
|
|
|
927
821
|
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
928
822
|
"$",
|
|
929
823
|
totalCost.toFixed(3)
|
|
930
|
-
] })
|
|
824
|
+
] }),
|
|
825
|
+
hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
826
|
+
"\xB7 ",
|
|
827
|
+
hiddenIdle,
|
|
828
|
+
" idle hidden"
|
|
829
|
+
] }) : null
|
|
931
830
|
] }),
|
|
932
831
|
shown.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
|
|
933
832
|
shown.map((e) => {
|
|
@@ -1286,8 +1185,8 @@ function WorktreeMonitor({
|
|
|
1286
1185
|
nowTick,
|
|
1287
1186
|
onClose
|
|
1288
1187
|
}) {
|
|
1289
|
-
useInput((
|
|
1290
|
-
if (key.escape) onClose();
|
|
1188
|
+
useInput((input, key) => {
|
|
1189
|
+
if (key.escape || key.ctrl && input === "w") onClose();
|
|
1291
1190
|
});
|
|
1292
1191
|
const list = Object.values(worktrees);
|
|
1293
1192
|
const active = list.filter((w) => ["active", "committing", "merging"].includes(w.status)).length;
|
|
@@ -1607,7 +1506,7 @@ function ToolStreamBox({
|
|
|
1607
1506
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1608
1507
|
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25C6 " }),
|
|
1609
1508
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: name }),
|
|
1610
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${
|
|
1509
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
|
|
1611
1510
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
1612
1511
|
] }),
|
|
1613
1512
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
@@ -1702,7 +1601,7 @@ function Entry({
|
|
|
1702
1601
|
parts.push(`${entry.outputLines} L`);
|
|
1703
1602
|
}
|
|
1704
1603
|
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
1705
|
-
parts.push(
|
|
1604
|
+
parts.push(fmtBytes(entry.outputBytes));
|
|
1706
1605
|
}
|
|
1707
1606
|
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
1708
1607
|
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
@@ -1718,7 +1617,7 @@ function Entry({
|
|
|
1718
1617
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1719
1618
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: argSummary })
|
|
1720
1619
|
] }) : null,
|
|
1721
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${
|
|
1620
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
|
|
1722
1621
|
sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
|
|
1723
1622
|
] }),
|
|
1724
1623
|
outLines.map((line, i) => (
|
|
@@ -1830,7 +1729,7 @@ function fmtTok2(n) {
|
|
|
1830
1729
|
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
1831
1730
|
return String(n);
|
|
1832
1731
|
}
|
|
1833
|
-
function
|
|
1732
|
+
function fmtDuration(ms) {
|
|
1834
1733
|
if (ms < 1e3) return `${ms}ms`;
|
|
1835
1734
|
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1836
1735
|
const totalSec = Math.floor(ms / 1e3);
|
|
@@ -1958,7 +1857,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
1958
1857
|
const bytes = numOf(o["bytes_written"]) ?? numOf(o["bytes"]);
|
|
1959
1858
|
const created = o["created"] === true;
|
|
1960
1859
|
const tag = created ? "created" : "updated";
|
|
1961
|
-
if (bytes !== void 0) return [`${tag} \xB7 ${
|
|
1860
|
+
if (bytes !== void 0) return [`${tag} \xB7 ${fmtBytes(bytes)}`];
|
|
1962
1861
|
return [tag];
|
|
1963
1862
|
}
|
|
1964
1863
|
}
|
|
@@ -2023,17 +1922,17 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2023
1922
|
if (json && typeof json === "object") {
|
|
2024
1923
|
const o = json;
|
|
2025
1924
|
const bytes = numOf(o["bytes"]);
|
|
2026
|
-
if (bytes !== void 0) return [`${
|
|
1925
|
+
if (bytes !== void 0) return [`${fmtBytes(bytes)} read`];
|
|
2027
1926
|
}
|
|
2028
1927
|
const range = scanNumberedRange(text);
|
|
2029
1928
|
if (range.count > 0 && range.first !== void 0 && range.last !== void 0) {
|
|
2030
1929
|
if (range.first === range.last) {
|
|
2031
|
-
return [`L${range.first} \xB7 ${
|
|
1930
|
+
return [`L${range.first} \xB7 ${fmtBytes(text.length)}`];
|
|
2032
1931
|
}
|
|
2033
1932
|
const contiguous = range.count === range.last - range.first + 1;
|
|
2034
1933
|
const head = `L${range.first}\u2013${range.last}`;
|
|
2035
1934
|
const tail = contiguous ? `${range.count} line${range.count === 1 ? "" : "s"}` : `${range.count} lines (gaps)`;
|
|
2036
|
-
return [`${head} \xB7 ${tail} \xB7 ${
|
|
1935
|
+
return [`${head} \xB7 ${tail} \xB7 ${fmtBytes(text.length)}`];
|
|
2037
1936
|
}
|
|
2038
1937
|
}
|
|
2039
1938
|
if (toolName === "grep" || toolName === "glob") {
|
|
@@ -2091,7 +1990,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2091
1990
|
const head = [];
|
|
2092
1991
|
if (status !== void 0) head.push(`HTTP ${status}`);
|
|
2093
1992
|
if (ct) head.push(ct.split(";")[0] ?? ct);
|
|
2094
|
-
if (content) head.push(
|
|
1993
|
+
if (content) head.push(fmtBytes(Buffer.byteLength(content, "utf8")));
|
|
2095
1994
|
const lines = [];
|
|
2096
1995
|
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
2097
1996
|
if (url && status !== void 0 && (status < 200 || status >= 400)) {
|
|
@@ -2182,7 +2081,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2182
2081
|
if (runner && runner !== "none") head.push(runner);
|
|
2183
2082
|
head.push(`${passed}/${total} passed`);
|
|
2184
2083
|
if (failed > 0) head.push(`${failed} failed`);
|
|
2185
|
-
if (duration !== void 0) head.push(
|
|
2084
|
+
if (duration !== void 0) head.push(fmtDuration(duration));
|
|
2186
2085
|
return [head.join(" \xB7 ")];
|
|
2187
2086
|
}
|
|
2188
2087
|
}
|
|
@@ -2467,7 +2366,7 @@ function countLines(text) {
|
|
|
2467
2366
|
if (!text) return 0;
|
|
2468
2367
|
return text.replace(/\n$/, "").split("\n").length;
|
|
2469
2368
|
}
|
|
2470
|
-
function
|
|
2369
|
+
function fmtBytes(n) {
|
|
2471
2370
|
if (n < 1024) return `${n}B`;
|
|
2472
2371
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
2473
2372
|
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
@@ -2555,20 +2454,20 @@ function fmtElapsed6(ms) {
|
|
|
2555
2454
|
const s2 = Math.floor(ms % 6e4 / 1e3);
|
|
2556
2455
|
return `${m}m${s2.toString().padStart(2, "0")}s`;
|
|
2557
2456
|
}
|
|
2558
|
-
function
|
|
2457
|
+
function fmtBytes2(n) {
|
|
2559
2458
|
if (n < 1024) return `${n}B`;
|
|
2560
2459
|
return `${(n / 1024).toFixed(1)}KB`;
|
|
2561
2460
|
}
|
|
2562
|
-
function
|
|
2461
|
+
function fmtRecentTool(tool) {
|
|
2563
2462
|
const status = tool.ok === false ? "fail" : "ok";
|
|
2564
2463
|
const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
|
|
2565
2464
|
const parts = [status, name];
|
|
2566
2465
|
if (typeof tool.durationMs === "number") parts.push(fmtElapsed6(tool.durationMs));
|
|
2567
|
-
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(
|
|
2466
|
+
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes2(tool.outputBytes));
|
|
2568
2467
|
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
2569
2468
|
return parts.join(" ");
|
|
2570
2469
|
}
|
|
2571
|
-
function
|
|
2470
|
+
function fmtRecentMessage(message) {
|
|
2572
2471
|
const text = message.text.replace(/\s+/g, " ");
|
|
2573
2472
|
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
2574
2473
|
}
|
|
@@ -2585,8 +2484,8 @@ function LiveActivityStrip({
|
|
|
2585
2484
|
const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
|
|
2586
2485
|
const taskElapsed = now - e.startedAt;
|
|
2587
2486
|
const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed6(toolElapsed)})` : "idle between tools";
|
|
2588
|
-
const recentTools = (e.recentTools ?? []).slice(-2).map(
|
|
2589
|
-
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(
|
|
2487
|
+
const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
|
|
2488
|
+
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage).join("");
|
|
2590
2489
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2591
2490
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25CF" }),
|
|
2592
2491
|
/* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
|
|
@@ -2611,7 +2510,7 @@ function LiveActivityStrip({
|
|
|
2611
2510
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2612
2511
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2613
2512
|
"msg: ",
|
|
2614
|
-
|
|
2513
|
+
fmtRecentMessage({ text: messageText})
|
|
2615
2514
|
] })
|
|
2616
2515
|
] }) : null
|
|
2617
2516
|
] }, e.id);
|
|
@@ -3879,10 +3778,10 @@ function App({
|
|
|
3879
3778
|
const handleRewindTo = React2.useCallback(async (checkpointIndex) => {
|
|
3880
3779
|
const sessionId = agent.ctx.session.id;
|
|
3881
3780
|
if (!sessionId) return;
|
|
3882
|
-
const rewinder = new DefaultSessionRewinder(sessionsDir ?? "");
|
|
3781
|
+
const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", projectRoot ?? agent.ctx.cwd);
|
|
3883
3782
|
await rewinder.rewindToCheckpoint(sessionId, checkpointIndex);
|
|
3884
3783
|
await agent.ctx.session.truncateToCheckpoint(checkpointIndex);
|
|
3885
|
-
}, [agent.ctx.session, sessionsDir]);
|
|
3784
|
+
}, [agent.ctx.session, sessionsDir, projectRoot, agent.ctx.cwd]);
|
|
3886
3785
|
const setDraft = (buffer, cursor) => {
|
|
3887
3786
|
draftRef.current = { buffer, cursor };
|
|
3888
3787
|
dispatch({ type: "setBuffer", buffer, cursor });
|
|
@@ -5537,6 +5436,10 @@ function App({
|
|
|
5537
5436
|
return;
|
|
5538
5437
|
}
|
|
5539
5438
|
if (key.ctrl && input === "w") {
|
|
5439
|
+
if (state.worktreeMonitorOpen) {
|
|
5440
|
+
dispatch({ type: "worktreeMonitorToggle" });
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5540
5443
|
if (cursor === 0) return;
|
|
5541
5444
|
const beforeCursor = buffer.slice(0, cursor);
|
|
5542
5445
|
const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
|