@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 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 sorted = [...list].sort((a, b) => {
217
- const order = { running: 0, success: 1, failed: 2, timeout: 3, stopped: 4, idle: 5 };
218
- const ao = order[a.status] ?? 9;
219
- const bo = order[b.status] ?? 9;
220
- if (ao !== bo) return ao - bo;
221
- return b.lastEventAt - a.lastEventAt;
222
- });
223
- const runningCount = list.filter((e) => e.status === "running").length;
224
- const totalLabel = totalCost > 0 ? `$${totalCost.toFixed(3)} \xB7 ${runningCount} active` : `${runningCount} active`;
225
- return /* @__PURE__ */ jsxs(
226
- Box,
227
- {
228
- flexDirection: "column",
229
- paddingX: 1,
230
- borderStyle: "single",
231
- borderTop: false,
232
- borderBottom: false,
233
- borderLeft: false,
234
- borderRight: false,
235
- children: [
236
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
237
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Fleet" }),
238
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
239
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
240
- list.length,
241
- " agent",
242
- list.length === 1 ? "" : "s"
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 fmtCost2(n) {
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: fmtCost2(e.cost) }),
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.filter((e) => !isTerminal(e.status));
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 ordered = [...live].sort((a, b) => {
890
- if (a.status === "running" && b.status !== "running") return -1;
891
- if (a.status !== "running" && b.status === "running") return 1;
892
- return a.startedAt - b.startedAt;
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((_, key) => {
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 ${fmtDuration2(elapsedMs)}` }),
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(fmtBytes2(entry.outputBytes));
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 ${fmtDuration2(entry.durationMs)}` }),
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 fmtDuration2(ms) {
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 ${fmtBytes2(bytes)}`];
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 [`${fmtBytes2(bytes)} read`];
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 ${fmtBytes2(text.length)}`];
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 ${fmtBytes2(text.length)}`];
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(fmtBytes2(Buffer.byteLength(content, "utf8")));
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(fmtDuration2(duration));
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 fmtBytes2(n) {
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 fmtBytes3(n) {
2458
+ function fmtBytes2(n) {
2559
2459
  if (n < 1024) return `${n}B`;
2560
2460
  return `${(n / 1024).toFixed(1)}KB`;
2561
2461
  }
2562
- function fmtRecentTool2(tool) {
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(fmtBytes3(tool.outputBytes));
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 fmtRecentMessage2(message) {
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(fmtRecentTool2).join(" | ");
2589
- const messageText = e.streamingText.trim() || (e.recentMessages ?? []).slice(-1).map(fmtRecentMessage2).join("");
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
- fmtRecentMessage2({ text: messageText})
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 = model ? ` \xB7 ${model}` : "";
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(model ? `${app} \xB7 ${model}` : app));
6049
+ write(setTitle(app));
6152
6050
  };
6153
6051
  }
6154
6052