@wrongstack/tui 0.8.6 → 0.9.1
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 +85 -187
- 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,
|
|
@@ -334,7 +215,8 @@ function StatusBar({
|
|
|
334
215
|
processCount,
|
|
335
216
|
hiddenItems,
|
|
336
217
|
eternalStage,
|
|
337
|
-
goalSummary
|
|
218
|
+
goalSummary,
|
|
219
|
+
autoProceedCountdown
|
|
338
220
|
}) {
|
|
339
221
|
const hiddenSet = new Set(hiddenItems);
|
|
340
222
|
const usage = tokenCounter?.total();
|
|
@@ -721,7 +603,7 @@ function fmtTokens(n) {
|
|
|
721
603
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
722
604
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
723
605
|
}
|
|
724
|
-
function
|
|
606
|
+
function fmtCost(n) {
|
|
725
607
|
if (n === 0) return "\u2014";
|
|
726
608
|
return `$${n.toFixed(3)}`;
|
|
727
609
|
}
|
|
@@ -832,7 +714,7 @@ function FleetMonitor({
|
|
|
832
714
|
/* @__PURE__ */ jsx(Text, { color: s2.color, children: e.status.padEnd(10) }),
|
|
833
715
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `L${e.iterations} ${e.toolCalls}t`.padEnd(8) }),
|
|
834
716
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed.padEnd(8).slice(0, 8) }),
|
|
835
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children:
|
|
717
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: fmtCost(e.cost) }),
|
|
836
718
|
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
837
719
|
" \u26A1\xD7",
|
|
838
720
|
e.extensions
|
|
@@ -865,6 +747,20 @@ var STATUS2 = {
|
|
|
865
747
|
function isTerminal(status) {
|
|
866
748
|
return status === "success" || status === "failed" || status === "timeout" || status === "stopped";
|
|
867
749
|
}
|
|
750
|
+
var IDLE_HIDE_MS = 6e4;
|
|
751
|
+
function selectLiveAgents(all, now, idleHideMs = IDLE_HIDE_MS) {
|
|
752
|
+
const visible = all.filter((e) => {
|
|
753
|
+
if (isTerminal(e.status)) return false;
|
|
754
|
+
if (e.status === "running") return true;
|
|
755
|
+
return now - e.lastEventAt < idleHideMs;
|
|
756
|
+
});
|
|
757
|
+
return visible.sort((a, b) => {
|
|
758
|
+
if (a.status === "running" && b.status !== "running") return -1;
|
|
759
|
+
if (a.status !== "running" && b.status === "running") return 1;
|
|
760
|
+
if (a.status === "running") return a.startedAt - b.startedAt;
|
|
761
|
+
return b.lastEventAt - a.lastEventAt;
|
|
762
|
+
});
|
|
763
|
+
}
|
|
868
764
|
function fmtTokens2(n) {
|
|
869
765
|
if (n < 1e3) return String(n);
|
|
870
766
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
@@ -882,15 +778,14 @@ function AgentsMonitor({
|
|
|
882
778
|
nowTick
|
|
883
779
|
}) {
|
|
884
780
|
const all = Object.values(entries);
|
|
885
|
-
const live = all
|
|
781
|
+
const live = selectLiveAgents(all, nowTick);
|
|
886
782
|
const running = live.filter((e) => e.status === "running").length;
|
|
887
783
|
const totalDone = all.filter((e) => e.status === "success").length;
|
|
888
784
|
const totalFailed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
});
|
|
785
|
+
const hiddenIdle = all.filter(
|
|
786
|
+
(e) => e.status === "idle" && nowTick - e.lastEventAt >= IDLE_HIDE_MS
|
|
787
|
+
).length;
|
|
788
|
+
const ordered = live;
|
|
894
789
|
const shown = ordered.slice(0, 8);
|
|
895
790
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
896
791
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
@@ -927,7 +822,12 @@ function AgentsMonitor({
|
|
|
927
822
|
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
928
823
|
"$",
|
|
929
824
|
totalCost.toFixed(3)
|
|
930
|
-
] })
|
|
825
|
+
] }),
|
|
826
|
+
hiddenIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
827
|
+
"\xB7 ",
|
|
828
|
+
hiddenIdle,
|
|
829
|
+
" idle hidden"
|
|
830
|
+
] }) : null
|
|
931
831
|
] }),
|
|
932
832
|
shown.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
|
|
933
833
|
shown.map((e) => {
|
|
@@ -1286,8 +1186,8 @@ function WorktreeMonitor({
|
|
|
1286
1186
|
nowTick,
|
|
1287
1187
|
onClose
|
|
1288
1188
|
}) {
|
|
1289
|
-
useInput((
|
|
1290
|
-
if (key.escape) onClose();
|
|
1189
|
+
useInput((input, key) => {
|
|
1190
|
+
if (key.escape || key.ctrl && input === "w") onClose();
|
|
1291
1191
|
});
|
|
1292
1192
|
const list = Object.values(worktrees);
|
|
1293
1193
|
const active = list.filter((w) => ["active", "committing", "merging"].includes(w.status)).length;
|
|
@@ -1607,7 +1507,7 @@ function ToolStreamBox({
|
|
|
1607
1507
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1608
1508
|
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25C6 " }),
|
|
1609
1509
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: name }),
|
|
1610
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${
|
|
1510
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
|
|
1611
1511
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
1612
1512
|
] }),
|
|
1613
1513
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
@@ -1702,7 +1602,7 @@ function Entry({
|
|
|
1702
1602
|
parts.push(`${entry.outputLines} L`);
|
|
1703
1603
|
}
|
|
1704
1604
|
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
1705
|
-
parts.push(
|
|
1605
|
+
parts.push(fmtBytes(entry.outputBytes));
|
|
1706
1606
|
}
|
|
1707
1607
|
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
1708
1608
|
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
@@ -1718,7 +1618,7 @@ function Entry({
|
|
|
1718
1618
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
1719
1619
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: argSummary })
|
|
1720
1620
|
] }) : null,
|
|
1721
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${
|
|
1621
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
|
|
1722
1622
|
sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
|
|
1723
1623
|
] }),
|
|
1724
1624
|
outLines.map((line, i) => (
|
|
@@ -1830,7 +1730,7 @@ function fmtTok2(n) {
|
|
|
1830
1730
|
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
1831
1731
|
return String(n);
|
|
1832
1732
|
}
|
|
1833
|
-
function
|
|
1733
|
+
function fmtDuration(ms) {
|
|
1834
1734
|
if (ms < 1e3) return `${ms}ms`;
|
|
1835
1735
|
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1836
1736
|
const totalSec = Math.floor(ms / 1e3);
|
|
@@ -1958,7 +1858,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
1958
1858
|
const bytes = numOf(o["bytes_written"]) ?? numOf(o["bytes"]);
|
|
1959
1859
|
const created = o["created"] === true;
|
|
1960
1860
|
const tag = created ? "created" : "updated";
|
|
1961
|
-
if (bytes !== void 0) return [`${tag} \xB7 ${
|
|
1861
|
+
if (bytes !== void 0) return [`${tag} \xB7 ${fmtBytes(bytes)}`];
|
|
1962
1862
|
return [tag];
|
|
1963
1863
|
}
|
|
1964
1864
|
}
|
|
@@ -2023,17 +1923,17 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2023
1923
|
if (json && typeof json === "object") {
|
|
2024
1924
|
const o = json;
|
|
2025
1925
|
const bytes = numOf(o["bytes"]);
|
|
2026
|
-
if (bytes !== void 0) return [`${
|
|
1926
|
+
if (bytes !== void 0) return [`${fmtBytes(bytes)} read`];
|
|
2027
1927
|
}
|
|
2028
1928
|
const range = scanNumberedRange(text);
|
|
2029
1929
|
if (range.count > 0 && range.first !== void 0 && range.last !== void 0) {
|
|
2030
1930
|
if (range.first === range.last) {
|
|
2031
|
-
return [`L${range.first} \xB7 ${
|
|
1931
|
+
return [`L${range.first} \xB7 ${fmtBytes(text.length)}`];
|
|
2032
1932
|
}
|
|
2033
1933
|
const contiguous = range.count === range.last - range.first + 1;
|
|
2034
1934
|
const head = `L${range.first}\u2013${range.last}`;
|
|
2035
1935
|
const tail = contiguous ? `${range.count} line${range.count === 1 ? "" : "s"}` : `${range.count} lines (gaps)`;
|
|
2036
|
-
return [`${head} \xB7 ${tail} \xB7 ${
|
|
1936
|
+
return [`${head} \xB7 ${tail} \xB7 ${fmtBytes(text.length)}`];
|
|
2037
1937
|
}
|
|
2038
1938
|
}
|
|
2039
1939
|
if (toolName === "grep" || toolName === "glob") {
|
|
@@ -2091,7 +1991,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2091
1991
|
const head = [];
|
|
2092
1992
|
if (status !== void 0) head.push(`HTTP ${status}`);
|
|
2093
1993
|
if (ct) head.push(ct.split(";")[0] ?? ct);
|
|
2094
|
-
if (content) head.push(
|
|
1994
|
+
if (content) head.push(fmtBytes(Buffer.byteLength(content, "utf8")));
|
|
2095
1995
|
const lines = [];
|
|
2096
1996
|
if (head.length > 0) lines.push(head.join(" \xB7 "));
|
|
2097
1997
|
if (url && status !== void 0 && (status < 200 || status >= 400)) {
|
|
@@ -2182,7 +2082,7 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
2182
2082
|
if (runner && runner !== "none") head.push(runner);
|
|
2183
2083
|
head.push(`${passed}/${total} passed`);
|
|
2184
2084
|
if (failed > 0) head.push(`${failed} failed`);
|
|
2185
|
-
if (duration !== void 0) head.push(
|
|
2085
|
+
if (duration !== void 0) head.push(fmtDuration(duration));
|
|
2186
2086
|
return [head.join(" \xB7 ")];
|
|
2187
2087
|
}
|
|
2188
2088
|
}
|
|
@@ -2467,7 +2367,7 @@ function countLines(text) {
|
|
|
2467
2367
|
if (!text) return 0;
|
|
2468
2368
|
return text.replace(/\n$/, "").split("\n").length;
|
|
2469
2369
|
}
|
|
2470
|
-
function
|
|
2370
|
+
function fmtBytes(n) {
|
|
2471
2371
|
if (n < 1024) return `${n}B`;
|
|
2472
2372
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
2473
2373
|
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
@@ -2555,20 +2455,20 @@ function fmtElapsed6(ms) {
|
|
|
2555
2455
|
const s2 = Math.floor(ms % 6e4 / 1e3);
|
|
2556
2456
|
return `${m}m${s2.toString().padStart(2, "0")}s`;
|
|
2557
2457
|
}
|
|
2558
|
-
function
|
|
2458
|
+
function fmtBytes2(n) {
|
|
2559
2459
|
if (n < 1024) return `${n}B`;
|
|
2560
2460
|
return `${(n / 1024).toFixed(1)}KB`;
|
|
2561
2461
|
}
|
|
2562
|
-
function
|
|
2462
|
+
function fmtRecentTool(tool) {
|
|
2563
2463
|
const status = tool.ok === false ? "fail" : "ok";
|
|
2564
2464
|
const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
|
|
2565
2465
|
const parts = [status, name];
|
|
2566
2466
|
if (typeof tool.durationMs === "number") parts.push(fmtElapsed6(tool.durationMs));
|
|
2567
|
-
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(
|
|
2467
|
+
if (typeof tool.outputBytes === "number" && tool.outputBytes > 0) parts.push(fmtBytes2(tool.outputBytes));
|
|
2568
2468
|
if (typeof tool.outputLines === "number" && tool.outputLines > 0) parts.push(`${tool.outputLines}L`);
|
|
2569
2469
|
return parts.join(" ");
|
|
2570
2470
|
}
|
|
2571
|
-
function
|
|
2471
|
+
function fmtRecentMessage(message) {
|
|
2572
2472
|
const text = message.text.replace(/\s+/g, " ");
|
|
2573
2473
|
return text.length > 48 ? `${text.slice(0, 47)}...` : text;
|
|
2574
2474
|
}
|
|
@@ -2585,8 +2485,8 @@ function LiveActivityStrip({
|
|
|
2585
2485
|
const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
|
|
2586
2486
|
const taskElapsed = now - e.startedAt;
|
|
2587
2487
|
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(
|
|
2488
|
+
const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
|
|
2489
|
+
const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage).join("");
|
|
2590
2490
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2591
2491
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25CF" }),
|
|
2592
2492
|
/* @__PURE__ */ jsx(Text, { children: e.name.slice(0, 14).padEnd(14) }),
|
|
@@ -2611,7 +2511,7 @@ function LiveActivityStrip({
|
|
|
2611
2511
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "|" }),
|
|
2612
2512
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2613
2513
|
"msg: ",
|
|
2614
|
-
|
|
2514
|
+
fmtRecentMessage({ text: messageText})
|
|
2615
2515
|
] })
|
|
2616
2516
|
] }) : null
|
|
2617
2517
|
] }, e.id);
|
|
@@ -3879,10 +3779,10 @@ function App({
|
|
|
3879
3779
|
const handleRewindTo = React2.useCallback(async (checkpointIndex) => {
|
|
3880
3780
|
const sessionId = agent.ctx.session.id;
|
|
3881
3781
|
if (!sessionId) return;
|
|
3882
|
-
const rewinder = new DefaultSessionRewinder(sessionsDir ?? "");
|
|
3782
|
+
const rewinder = new DefaultSessionRewinder(sessionsDir ?? "", projectRoot ?? agent.ctx.cwd);
|
|
3883
3783
|
await rewinder.rewindToCheckpoint(sessionId, checkpointIndex);
|
|
3884
3784
|
await agent.ctx.session.truncateToCheckpoint(checkpointIndex);
|
|
3885
|
-
}, [agent.ctx.session, sessionsDir]);
|
|
3785
|
+
}, [agent.ctx.session, sessionsDir, projectRoot, agent.ctx.cwd]);
|
|
3886
3786
|
const setDraft = (buffer, cursor) => {
|
|
3887
3787
|
draftRef.current = { buffer, cursor };
|
|
3888
3788
|
dispatch({ type: "setBuffer", buffer, cursor });
|
|
@@ -5537,6 +5437,10 @@ function App({
|
|
|
5537
5437
|
return;
|
|
5538
5438
|
}
|
|
5539
5439
|
if (key.ctrl && input === "w") {
|
|
5440
|
+
if (state.worktreeMonitorOpen) {
|
|
5441
|
+
dispatch({ type: "worktreeMonitorToggle" });
|
|
5442
|
+
return;
|
|
5443
|
+
}
|
|
5540
5444
|
if (cursor === 0) return;
|
|
5541
5445
|
const beforeCursor = buffer.slice(0, cursor);
|
|
5542
5446
|
const lastWordStart = beforeCursor.lastIndexOf(" ") + 1;
|
|
@@ -6086,11 +5990,6 @@ function fmtTok3(n) {
|
|
|
6086
5990
|
// src/terminal-title.ts
|
|
6087
5991
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
6088
5992
|
var setTitle = (s2) => `\x1B]0;${s2}\x07`;
|
|
6089
|
-
function shortModel(model) {
|
|
6090
|
-
if (!model) return "";
|
|
6091
|
-
const base = model.split("/").pop() ?? model;
|
|
6092
|
-
return base.replace(/-\d{8}$/, "").replace(/\[.*?\]$/, "");
|
|
6093
|
-
}
|
|
6094
5993
|
function marquee(text, offset, width) {
|
|
6095
5994
|
const padded = `${text} `;
|
|
6096
5995
|
const start = offset % padded.length;
|
|
@@ -6103,9 +6002,8 @@ function startTerminalTitle(opts) {
|
|
|
6103
6002
|
};
|
|
6104
6003
|
}
|
|
6105
6004
|
const app = opts.appName ?? "WrongStack";
|
|
6106
|
-
const model = shortModel(opts.model);
|
|
6107
6005
|
const idleAfter = opts.idleAfterMs ?? 3500;
|
|
6108
|
-
const suffix =
|
|
6006
|
+
const suffix = ` \xB7 ${app}`;
|
|
6109
6007
|
let frame = 0;
|
|
6110
6008
|
let scroll = 0;
|
|
6111
6009
|
let phase = "idle";
|
|
@@ -6148,7 +6046,7 @@ function startTerminalTitle(opts) {
|
|
|
6148
6046
|
return () => {
|
|
6149
6047
|
clearInterval(timer);
|
|
6150
6048
|
for (const off of offs) off();
|
|
6151
|
-
write(setTitle(
|
|
6049
|
+
write(setTitle(app));
|
|
6152
6050
|
};
|
|
6153
6051
|
}
|
|
6154
6052
|
|