@ashx-j/lunr 0.2.22 → 0.2.23

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/README.md +5 -3
  3. package/dist/builtin-extensions/lunr-browser.d.ts +7 -1
  4. package/dist/builtin-extensions/lunr-browser.d.ts.map +1 -1
  5. package/dist/builtin-extensions/lunr-browser.js +116 -3
  6. package/dist/builtin-extensions/lunr-browser.js.map +1 -1
  7. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +1 -1
  9. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  10. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +2 -0
  11. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  12. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +9 -0
  13. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  14. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +41 -3
  16. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +4 -0
  19. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +3 -2
  23. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -1
  24. package/dist/core/agent-session.d.ts +19 -0
  25. package/dist/core/agent-session.d.ts.map +1 -1
  26. package/dist/core/agent-session.js +230 -103
  27. package/dist/core/agent-session.js.map +1 -1
  28. package/dist/core/settings-manager.d.ts +4 -0
  29. package/dist/core/settings-manager.d.ts.map +1 -1
  30. package/dist/core/settings-manager.js +9 -0
  31. package/dist/core/settings-manager.js.map +1 -1
  32. package/dist/core/subagent-wait-interruption.d.ts +11 -0
  33. package/dist/core/subagent-wait-interruption.d.ts.map +1 -0
  34. package/dist/core/subagent-wait-interruption.js +19 -0
  35. package/dist/core/subagent-wait-interruption.js.map +1 -0
  36. package/dist/core/system-prompt.d.ts.map +1 -1
  37. package/dist/core/system-prompt.js +3 -1
  38. package/dist/core/system-prompt.js.map +1 -1
  39. package/dist/core/tools/render-utils.d.ts +3 -3
  40. package/dist/core/tools/render-utils.d.ts.map +1 -1
  41. package/dist/core/tools/render-utils.js +3 -3
  42. package/dist/core/tools/render-utils.js.map +1 -1
  43. package/dist/modes/interactive/components/assistant-message.d.ts +10 -2
  44. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  45. package/dist/modes/interactive/components/assistant-message.js +29 -5
  46. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  47. package/dist/modes/interactive/components/copyable-text.d.ts +2 -6
  48. package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -1
  49. package/dist/modes/interactive/components/copyable-text.js +26 -35
  50. package/dist/modes/interactive/components/copyable-text.js.map +1 -1
  51. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  52. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  53. package/dist/modes/interactive/components/settings-selector.js +13 -0
  54. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  55. package/dist/modes/interactive/components/thinking-tail.d.ts +9 -2
  56. package/dist/modes/interactive/components/thinking-tail.d.ts.map +1 -1
  57. package/dist/modes/interactive/components/thinking-tail.js +43 -1
  58. package/dist/modes/interactive/components/thinking-tail.js.map +1 -1
  59. package/dist/modes/interactive/components/tool-execution.d.ts +4 -3
  60. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  61. package/dist/modes/interactive/components/tool-execution.js +34 -45
  62. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  63. package/dist/modes/interactive/interactive-mode.d.ts +6 -0
  64. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  65. package/dist/modes/interactive/interactive-mode.js +118 -39
  66. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  67. package/dist/modes/interactive/theme/theme.d.ts +1 -0
  68. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  69. package/dist/modes/interactive/theme/theme.js +23 -0
  70. package/dist/modes/interactive/theme/theme.js.map +1 -1
  71. package/dist/node-runtime/{agent-session-services-NQ6GKOIK.js → agent-session-services-GZVSOGYR.js} +7 -7
  72. package/dist/node-runtime/{builtin-extensions-GVC6IFDU.js → builtin-extensions-QVCXNQT4.js} +3 -3
  73. package/dist/node-runtime/{chunk-6B2POMK7.js → chunk-6VYZ5UFP.js} +1 -1
  74. package/dist/node-runtime/{chunk-VJPTNWAP.js → chunk-DD5YWFSJ.js} +1 -1
  75. package/dist/node-runtime/{chunk-TDL7UWJ7.js → chunk-DQMGU675.js} +173 -57
  76. package/dist/node-runtime/{chunk-V2A7CEXK.js → chunk-EKVFP6YF.js} +2 -2
  77. package/dist/node-runtime/{chunk-5BNJ4JUH.js → chunk-GJ2RDBRL.js} +1 -1
  78. package/dist/node-runtime/{chunk-GNN7H3B7.js → chunk-GS42T6MX.js} +1 -1
  79. package/dist/node-runtime/{chunk-PC2Z5TKZ.js → chunk-HMBGROQK.js} +3 -3
  80. package/dist/node-runtime/{chunk-GJSAD4AB.js → chunk-HPUP7E4T.js} +10 -10
  81. package/dist/node-runtime/{chunk-IVXYUAJE.js → chunk-IF24A3FH.js} +1 -1
  82. package/dist/node-runtime/{chunk-BFNXONG3.js → chunk-LFZDVKSP.js} +2 -2
  83. package/dist/node-runtime/{chunk-EQ63ANHL.js → chunk-LLUIPGDR.js} +210 -125
  84. package/dist/node-runtime/{chunk-ORH324EP.js → chunk-PCEW76PM.js} +3 -3
  85. package/dist/node-runtime/{chunk-WADV2VDS.js → chunk-QAZOULTU.js} +7 -0
  86. package/dist/node-runtime/{chunk-6427XAWG.js → chunk-QH6YL7VK.js} +3 -3
  87. package/dist/node-runtime/{chunk-7QWNYZDI.js → chunk-RDDAZOMU.js} +16 -0
  88. package/dist/node-runtime/{chunk-QDGKKKUM.js → chunk-RIR5EDDJ.js} +1 -1
  89. package/dist/node-runtime/{chunk-H3XF4UVQ.js → chunk-RWTKOC3B.js} +1 -1
  90. package/dist/node-runtime/{chunk-IQIEU7SB.js → chunk-TVJUOJZJ.js} +2 -2
  91. package/dist/node-runtime/{chunk-UAFLNHSH.js → chunk-W64JC4E7.js} +8 -8
  92. package/dist/node-runtime/{chunk-LMBNLFXQ.js → chunk-X3URCYCU.js} +4 -4
  93. package/dist/node-runtime/{chunk-VSSXXL36.js → chunk-YDO2F2IA.js} +2 -2
  94. package/dist/node-runtime/{chunk-IWOWXRWU.js → chunk-YHQ3NBB3.js} +15 -15
  95. package/dist/node-runtime/cli-runtime.js +1 -1
  96. package/dist/node-runtime/{command-3JHHXOPX.js → command-PDVTBRWA.js} +3 -3
  97. package/dist/node-runtime/{commands-2JVNFGMQ.js → commands-XDCFGIGW.js} +5 -5
  98. package/dist/node-runtime/{export-html-KBFVV63J.js → export-html-KSOIMVPI.js} +1 -1
  99. package/dist/node-runtime/{extension-input-K24TVKVW.js → extension-input-E7BJZ35H.js} +4 -4
  100. package/dist/node-runtime/{extension-selector-SPNF7EDR.js → extension-selector-WU42XDTU.js} +4 -4
  101. package/dist/node-runtime/{gateway-VFO6SFKK.js → gateway-AYWM5DIO.js} +7 -7
  102. package/dist/node-runtime/index.js +17 -17
  103. package/dist/node-runtime/{install-cli-C3CF7O7N.js → install-cli-3BO4MMQ6.js} +1 -1
  104. package/dist/node-runtime/{interactive-mode-LOM6AIF6.js → interactive-mode-4MFRKAHG.js} +13 -13
  105. package/dist/node-runtime/{interactive-view-IDSCPPK7.js → interactive-view-TUZHCQM3.js} +5 -5
  106. package/dist/node-runtime/{lunr-browser-YNW7FTYX.js → lunr-browser-RYFIIVJN.js} +91 -4
  107. package/dist/node-runtime/{lunr-cron-BKHGNBKT.js → lunr-cron-YWXEPZMQ.js} +4 -4
  108. package/dist/node-runtime/main.js +14 -14
  109. package/dist/node-runtime/{mobile-commands-HMP25WBC.js → mobile-commands-LVHDAUDP.js} +4 -4
  110. package/dist/node-runtime/{package-manager-cli-VCK4E2RC.js → package-manager-cli-6GT3Z3CK.js} +9 -9
  111. package/dist/node-runtime/{pi-subagents-FEUDLJOE.js → pi-subagents-CDWK2AKY.js} +44 -10
  112. package/dist/node-runtime/rpc-entry.js +14 -14
  113. package/dist/node-runtime/{rpc-mode-P5ODXPEG.js → rpc-mode-O3XV4SID.js} +2 -2
  114. package/dist/node-runtime/{session-selector-LHRMJOKT.js → session-selector-GIM4DHQ2.js} +4 -4
  115. package/dist/node-runtime/{settings-manager-UUZ6NUXI.js → settings-manager-6VEMXRDL.js} +1 -1
  116. package/dist/node-runtime/{setup-NRXVZBLJ.js → setup-5SR2J35A.js} +1 -1
  117. package/dist/node-runtime/{subagent-executor-MLUMBWCP.js → subagent-executor-M5VWB3D3.js} +8 -4
  118. package/dist/node-runtime/{theme-U7IGOA7O.js → theme-UOO5RVFN.js} +1 -1
  119. package/dist/node-runtime/{update-cli-4TP25CNW.js → update-cli-UVKJWRRJ.js} +1 -1
  120. package/docs/features.md +2 -0
  121. package/docs/settings.md +1 -0
  122. package/docs/usage.md +2 -2
  123. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  124. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  125. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  126. package/examples/extensions/gondolin/package-lock.json +2 -2
  127. package/examples/extensions/gondolin/package.json +1 -1
  128. package/examples/extensions/sandbox/package-lock.json +2 -2
  129. package/examples/extensions/sandbox/package.json +1 -1
  130. package/examples/extensions/with-deps/package-lock.json +2 -2
  131. package/examples/extensions/with-deps/package.json +1 -1
  132. package/package.json +4 -4
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  BootScreenComponent,
22
22
  registerPermissionModeBridge
23
- } from "./chunk-H3XF4UVQ.js";
23
+ } from "./chunk-RWTKOC3B.js";
24
24
  import {
25
25
  nextModeForGoal,
26
26
  registerPermissionModeControlBridge
@@ -45,19 +45,19 @@ import {
45
45
  peekRollbackTurnsConsumed,
46
46
  rollbackLastTurn,
47
47
  setRollbackWarningHandler
48
- } from "./chunk-TDL7UWJ7.js";
48
+ } from "./chunk-DQMGU675.js";
49
49
  import {
50
50
  notifyTodosEnabledChanged
51
51
  } from "./chunk-CCCN2UCX.js";
52
52
  import {
53
53
  parseGitUrl
54
- } from "./chunk-IQIEU7SB.js";
54
+ } from "./chunk-TVJUOJZJ.js";
55
55
  import {
56
56
  createAllToolDefinitions,
57
57
  ensureTool,
58
58
  getToolPath,
59
59
  truncateToVisualLines
60
- } from "./chunk-VSSXXL36.js";
60
+ } from "./chunk-YDO2F2IA.js";
61
61
  import {
62
62
  DEFAULT_MAX_BYTES,
63
63
  DEFAULT_MAX_LINES,
@@ -86,7 +86,7 @@ import {
86
86
  SKILL_TAG_CHARACTERS,
87
87
  configureHttpDispatcher,
88
88
  formatHttpIdleTimeoutMs
89
- } from "./chunk-WADV2VDS.js";
89
+ } from "./chunk-QAZOULTU.js";
90
90
  import {
91
91
  SUBAGENT_SPINNER_LABELS,
92
92
  SUBAGENT_SPINNER_NAMES
@@ -166,7 +166,7 @@ import {
166
166
  } from "./chunk-2MI5OPMN.js";
167
167
  import {
168
168
  SessionSelectorComponent
169
- } from "./chunk-ORH324EP.js";
169
+ } from "./chunk-PCEW76PM.js";
170
170
  import {
171
171
  CustomEditor
172
172
  } from "./chunk-H2EOZYMP.js";
@@ -181,23 +181,23 @@ import {
181
181
  } from "./chunk-CCZJ3PYY.js";
182
182
  import {
183
183
  ExtensionSelectorComponent
184
- } from "./chunk-6427XAWG.js";
184
+ } from "./chunk-QH6YL7VK.js";
185
185
  import {
186
186
  ExtensionInputComponent
187
- } from "./chunk-PC2Z5TKZ.js";
187
+ } from "./chunk-HMBGROQK.js";
188
188
  import {
189
189
  CountdownTimer
190
190
  } from "./chunk-I6R76AG7.js";
191
191
  import {
192
192
  DynamicBorder
193
- } from "./chunk-6B2POMK7.js";
193
+ } from "./chunk-6VYZ5UFP.js";
194
194
  import {
195
195
  formatKeyText,
196
196
  keyDisplayText,
197
197
  keyHint,
198
198
  keyText,
199
199
  rawKeyHint
200
- } from "./chunk-GNN7H3B7.js";
200
+ } from "./chunk-GS42T6MX.js";
201
201
  import {
202
202
  FS_WATCH_RETRY_DELAY_MS,
203
203
  Theme,
@@ -223,7 +223,7 @@ import {
223
223
  stopThemeWatcher,
224
224
  theme,
225
225
  watchWithErrorHandler
226
- } from "./chunk-7QWNYZDI.js";
226
+ } from "./chunk-RDDAZOMU.js";
227
227
  import {
228
228
  APP_NAME,
229
229
  APP_TITLE,
@@ -245,7 +245,7 @@ import * as fs2 from "node:fs";
245
245
  import * as os2 from "node:os";
246
246
  import * as path2 from "node:path";
247
247
  import { getSupportedThinkingLevels } from "@ashx-j/lunr-ai/compat";
248
- import { CombinedAutocompleteProvider, Container as Container19, collectImageMarkerIds, formatImageMarker, fuzzyFilter as fuzzyFilter5, isFocusable, Markdown as Markdown10, matchesKey as matchesKey2, ProcessTerminal, Spacer as Spacer19, setKeybindings, Text as Text21, TruncatedText as TruncatedText2, TUI, visibleWidth as visibleWidth4 } from "@ashx-j/lunr-tui";
248
+ import { CombinedAutocompleteProvider, Container as Container19, collectImageMarkerIds, formatImageMarker, fuzzyFilter as fuzzyFilter5, isFocusable, Markdown as Markdown10, matchesKey as matchesKey2, ProcessTerminal, Spacer as Spacer19, setKeybindings, Text as Text21, TruncatedText as TruncatedText2, TUI, visibleWidth as visibleWidth6 } from "@ashx-j/lunr-tui";
249
249
  import chalk from "chalk";
250
250
  import { spawn as spawn3, spawnSync } from "child_process";
251
251
 
@@ -1118,7 +1118,7 @@ var ArminComponent = class {
1118
1118
  import { Container, Markdown as Markdown2, Spacer, Text } from "@ashx-j/lunr-tui";
1119
1119
 
1120
1120
  // packages/coding-agent/dist/modes/interactive/components/copyable-text.js
1121
- import { truncateToWidth, wrapTextWithAnsi } from "@ashx-j/lunr-tui";
1121
+ import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@ashx-j/lunr-tui";
1122
1122
  function sourceLines(source) {
1123
1123
  let lines = [], pattern = /([^\r\n]*)(\r\n|\r|\n|$)/g;
1124
1124
  for (let match of source.matchAll(pattern)) {
@@ -1192,35 +1192,36 @@ function parseCopyableTextSegments(source) {
1192
1192
  return emittedThrough < source.length && segments.push({ type: "markdown", text: source.slice(emittedThrough) }), segments;
1193
1193
  }
1194
1194
  var CopyableTextBlockComponent = class {
1195
- buttonRow = -1;
1196
- buttonStart = -1;
1197
- buttonEnd = -1;
1195
+ renderedRows = 0;
1198
1196
  payload;
1199
1197
  complete;
1200
1198
  outputPad;
1201
- markdownTheme;
1202
1199
  status;
1203
1200
  onCopy;
1204
- constructor(payload, complete, outputPad, markdownTheme, status, onCopy) {
1205
- this.payload = payload, this.complete = complete, this.outputPad = outputPad, this.markdownTheme = markdownTheme, this.status = status, this.onCopy = onCopy;
1201
+ constructor(payload, complete, outputPad, status, onCopy) {
1202
+ this.payload = payload, this.complete = complete, this.outputPad = outputPad, this.status = status, this.onCopy = onCopy;
1206
1203
  }
1207
1204
  invalidate() {
1208
- this.buttonRow = -1, this.buttonStart = -1, this.buttonEnd = -1;
1205
+ this.renderedRows = 0;
1209
1206
  }
1210
1207
  render(width) {
1211
- let pad = " ".repeat(this.outputPad), contentWidth = Math.max(1, width - this.outputPad - 2), lines = [truncateToWidth(`${pad}${this.markdownTheme.codeBlockBorder("\u256D\u2500 lunr-copy")}`, width, "")], payloadLines = this.payload.replace(/\t/g, " ").split(`
1208
+ if (width <= 0)
1209
+ return this.renderedRows = 0, [];
1210
+ let horizontalPad = Math.min(this.outputPad, Math.max(0, width - 1)), pad = " ".repeat(horizontalPad), contentWidth = Math.max(1, width - horizontalPad * 2), paint = (content) => {
1211
+ let line = truncateToWidth(`${pad}${content}`, width, "");
1212
+ return theme.bg("userMessageBg", `${line}${" ".repeat(Math.max(0, width - visibleWidth(line)))}`);
1213
+ }, lines = [paint("")], payloadLines = this.payload.replace(/\t/g, " ").split(`
1212
1214
  `);
1213
1215
  for (let payloadLine of payloadLines)
1214
1216
  for (let wrappedLine of wrapTextWithAnsi(payloadLine, contentWidth))
1215
- lines.push(truncateToWidth(`${pad}${this.markdownTheme.codeBlockBorder("\u2502 ")}${this.markdownTheme.codeBlock(wrappedLine)}`, width, ""));
1216
- if (lines.push(truncateToWidth(`${pad}${this.markdownTheme.codeBlockBorder(this.complete ? "\u2570\u2500" : "\u2570\u2500 receiving")}`, width, "")), this.buttonRow = -1, this.buttonStart = -1, this.buttonEnd = -1, this.complete) {
1217
- let button = "[ Copy ]", feedback = "";
1218
- this.status === "copying" ? feedback = theme.fg("dim", " Copying...") : this.status === "copied" ? feedback = theme.fg("success", " Copied") : typeof this.status == "object" && (feedback = theme.fg("error", ` Copy failed: ${this.status.error}`)), this.buttonRow = lines.length, this.buttonStart = this.outputPad, this.buttonEnd = Math.min(width, this.buttonStart + button.length), lines.push(truncateToWidth(`${pad}${theme.fg("accent", button)}${feedback}`, width, ""));
1219
- }
1220
- return lines;
1217
+ lines.push(paint(theme.fg("userMessageText", wrappedLine)));
1218
+ if (typeof this.status == "object")
1219
+ for (let wrappedLine of wrapTextWithAnsi(`Copy failed: ${this.status.error}`, contentWidth))
1220
+ lines.push(paint(theme.fg("error", wrappedLine)));
1221
+ return lines.push(paint("")), this.renderedRows = lines.length, lines;
1221
1222
  }
1222
1223
  handleClick(localY, width, localX) {
1223
- return this.render(width), !this.complete || this.status === "copying" || localX === void 0 || localY !== this.buttonRow || localX < this.buttonStart || localX >= this.buttonEnd ? !1 : (this.onCopy(), !0);
1224
+ return this.render(width), !this.complete || this.status === "copying" || localY < 0 || localY >= this.renderedRows || localX !== void 0 && (localX < 0 || localX >= width) ? !1 : (this.onCopy(), !0);
1224
1225
  }
1225
1226
  };
1226
1227
 
@@ -1270,7 +1271,7 @@ function isThinkingRunComplete(_hasFollowingBlock, timing, timingsAttached) {
1270
1271
  }
1271
1272
 
1272
1273
  // packages/coding-agent/dist/modes/interactive/components/thinking-tail.js
1273
- import { Markdown } from "@ashx-j/lunr-tui";
1274
+ import { Markdown, truncateToWidth as truncateToWidth2, visibleWidth as visibleWidth2 } from "@ashx-j/lunr-tui";
1274
1275
  var THINKING_TAIL_LINES = 4, ThinkingTailComponent = class {
1275
1276
  markdown;
1276
1277
  maxLines;
@@ -1284,6 +1285,28 @@ var THINKING_TAIL_LINES = 4, ThinkingTailComponent = class {
1284
1285
  let lines = this.markdown.render(width);
1285
1286
  return lines.length <= this.maxLines ? lines : lines.slice(-this.maxLines);
1286
1287
  }
1288
+ }, shimmerSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" }), SHIMMER_PERIOD_MS = 2800, ThinkingLineComponent = class extends ThinkingTailComponent {
1289
+ startedAt;
1290
+ palette = theme.getFgGradient("thinkingText", "white", 32);
1291
+ constructor(text, paddingX, markdownTheme, startedAt) {
1292
+ super(text, paddingX, 0, markdownTheme), this.startedAt = startedAt;
1293
+ }
1294
+ invalidate() {
1295
+ super.invalidate(), this.palette = theme.getFgGradient("thinkingText", "white", 32);
1296
+ }
1297
+ render(width) {
1298
+ if (width <= 0)
1299
+ return ["", "", ""];
1300
+ let lines = this.markdown.render(width), latest = "";
1301
+ for (let index = lines.length - 1; index >= 0 && (latest = stripAnsi(lines[index]).trimEnd(), !latest.trim()); index--)
1302
+ ;
1303
+ let text = stripAnsi(truncateToWidth2(latest, width, "")), length = visibleWidth2(text), band = Math.max(6, Math.min(18, length * 0.3)), progress = (performance.now() - this.startedAt) % SHIMMER_PERIOD_MS / SHIMMER_PERIOD_MS, center = -band + progress * (length + band * 2), column = 0, highlighted = "";
1304
+ for (let { segment } of shimmerSegmenter.segment(text)) {
1305
+ let cells = visibleWidth2(segment), distance = Math.abs(column + cells / 2 - center) / band, intensity = distance >= 1 ? 0 : (1 + Math.cos(Math.PI * distance)) / 2;
1306
+ highlighted += this.palette[Math.round(intensity * (this.palette.length - 1))] + segment, column += cells;
1307
+ }
1308
+ return ["", `\x1B[3m${highlighted}\x1B[23m\x1B[39m`, ""];
1309
+ }
1287
1310
  };
1288
1311
 
1289
1312
  // packages/coding-agent/dist/modes/interactive/components/assistant-message.js
@@ -1311,13 +1334,20 @@ var OSC133_ZONE_START = "\x1B]133;A\x07", OSC133_ZONE_END = "\x1B]133;B\x07", OS
1311
1334
  copyText;
1312
1335
  requestRender;
1313
1336
  copyStates = /* @__PURE__ */ new Map();
1314
- constructor(message, hideThinkingBlock = !1, markdownTheme = getMarkdownTheme(), hiddenThinkingLabel = "Thinking...", outputPad = 1, thinkingCollapse = !1, copyOptions = {}) {
1315
- super(), this.hideThinkingBlock = hideThinkingBlock, this.thinkingCollapse = thinkingCollapse, this.markdownTheme = markdownTheme, this.hiddenThinkingLabel = hiddenThinkingLabel, this.outputPad = outputPad, this.copyText = copyOptions.copyText ?? copyToClipboard, this.requestRender = copyOptions.requestRender ?? (() => {
1316
- }), this.contentContainer = new Container(), this.addChild(this.contentContainer), message && this.updateContent(message);
1337
+ reasoningDisplay;
1338
+ onThinkingAnimationChange;
1339
+ thinkingAnimationStart = performance.now();
1340
+ thinkingAnimationActive = !1;
1341
+ constructor(message, hideThinkingBlock = !1, markdownTheme = getMarkdownTheme(), hiddenThinkingLabel = "Thinking...", outputPad = 1, thinkingCollapse = !1, options = {}) {
1342
+ super(), this.hideThinkingBlock = hideThinkingBlock, this.thinkingCollapse = thinkingCollapse, this.markdownTheme = markdownTheme, this.hiddenThinkingLabel = hiddenThinkingLabel, this.outputPad = outputPad, this.copyText = options.copyText ?? copyToClipboard, this.requestRender = options.requestRender ?? (() => {
1343
+ }), this.reasoningDisplay = options.reasoningDisplay ?? "auto", this.onThinkingAnimationChange = options.onThinkingAnimationChange, this.contentContainer = new Container(), this.addChild(this.contentContainer), message && this.updateContent(message);
1317
1344
  }
1318
1345
  invalidate() {
1319
1346
  super.invalidate(), this.lastMessage && this.updateContent(this.lastMessage, this.thinkingSourceOptions());
1320
1347
  }
1348
+ setReasoningDisplay(display) {
1349
+ this.reasoningDisplay = display, this.lastMessage && this.updateContent(this.lastMessage, this.thinkingSourceOptions());
1350
+ }
1321
1351
  setHideThinkingBlock(hide) {
1322
1352
  this.hideThinkingBlock = hide, this.lastMessage && this.updateContent(this.lastMessage, this.thinkingSourceOptions());
1323
1353
  }
@@ -1368,7 +1398,7 @@ var OSC133_ZONE_START = "\x1B]133;A\x07", OSC133_ZONE_END = "\x1B]133;B\x07", OS
1368
1398
  return this.thinkingSource ? { thinkingSource: this.thinkingSource } : void 0;
1369
1399
  }
1370
1400
  updateContent(message, options) {
1371
- this.lastMessage = message, this.thinkingSource = options?.thinkingSource, this.contentContainer.clear();
1401
+ this.lastMessage = message, this.thinkingSource = options?.thinkingSource, this.thinkingAnimationActive = !1, this.contentContainer.clear();
1372
1402
  let sourceMessage = this.thinkingSource ?? message, sourceThinkingRuns = collectThinkingRuns(sourceMessage.content);
1373
1403
  message.content.some((c) => c.type === "text" && c.text.trim() || !this.hideThinkingBlock && c.type === "thinking" && c.thinking.trim()) && this.contentContainer.addChild(new Spacer(1));
1374
1404
  let isFirstTextBlock = !0, thinkingRunIndex = -1;
@@ -1387,7 +1417,7 @@ var OSC133_ZONE_START = "\x1B]133;A\x07", OSC133_ZONE_END = "\x1B]133;B\x07", OS
1387
1417
  continue;
1388
1418
  }
1389
1419
  let key = `${i}:${segment.start}`, copyState = this.copyStates.get(key), status = copyState?.payload === segment.payload ? copyState.status : "idle";
1390
- copyState && copyState.payload !== segment.payload && this.copyStates.delete(key), this.contentContainer.addChild(new CopyableTextBlockComponent(segment.payload, segment.complete, this.outputPad, this.markdownTheme, status, () => this.copyPayload(key, segment.payload)));
1420
+ copyState && copyState.payload !== segment.payload && this.copyStates.delete(key), this.contentContainer.addChild(new CopyableTextBlockComponent(segment.payload, segment.complete, this.outputPad, status, () => this.copyPayload(key, segment.payload)));
1391
1421
  }
1392
1422
  else if (content.type === "thinking") {
1393
1423
  thinkingRunIndex++;
@@ -1417,6 +1447,7 @@ var OSC133_ZONE_START = "\x1B]133;A\x07", OSC133_ZONE_END = "\x1B]133;B\x07", OS
1417
1447
  this.contentContainer.addChild(new Spacer(1)), this.contentContainer.addChild(new Text(theme.fg("error", `Error: ${errorMsg}`), this.outputPad, 0));
1418
1448
  }
1419
1449
  }
1450
+ this.onThinkingAnimationChange?.(this.thinkingAnimationActive);
1420
1451
  }
1421
1452
  copyPayload(key, payload) {
1422
1453
  this.copyStates.get(key)?.status !== "copying" && (this.copyStates.set(key, { payload, status: "copying" }), this.refreshCopyStatus(), Promise.resolve().then(() => this.copyText(payload)).then(() => {
@@ -1443,6 +1474,12 @@ var OSC133_ZONE_START = "\x1B]133;A\x07", OSC133_ZONE_END = "\x1B]133;B\x07", OS
1443
1474
  return;
1444
1475
  }
1445
1476
  if (!runComplete && !this.isRunExpanded(thinkingRunIndex)) {
1477
+ if (this.reasoningDisplay === "one-line" || this.reasoningDisplay === "auto" && displayMessage.provider === "openai-codex") {
1478
+ this.thinkingAnimationActive = !0, this.contentContainer.children.length === 1 && this.contentContainer.children[0] instanceof Spacer && this.contentContainer.clear(), wrap(new ThinkingLineComponent(thinkingBlocks.join(`
1479
+
1480
+ `), this.outputPad, this.markdownTheme, this.thinkingAnimationStart));
1481
+ return;
1482
+ }
1446
1483
  wrap(new ThinkingTailComponent(thinkingBlocks.join(`
1447
1484
 
1448
1485
  `), this.outputPad, 0, this.markdownTheme, {
@@ -1661,7 +1698,7 @@ var CompactionSummaryMessageComponent = class extends Box2 {
1661
1698
 
1662
1699
  // packages/coding-agent/dist/modes/interactive/components/footer.js
1663
1700
  import { isAbsolute, relative, resolve as resolve2, sep } from "node:path";
1664
- import { truncateToWidth as truncateToWidth2, visibleWidth } from "@ashx-j/lunr-tui";
1701
+ import { truncateToWidth as truncateToWidth3, visibleWidth as visibleWidth3 } from "@ashx-j/lunr-tui";
1665
1702
  function sanitizeStatusText(text) {
1666
1703
  return text.replace(/[\r\n\t]/g, " ").replace(/ +/g, " ").trim();
1667
1704
  }
@@ -1720,38 +1757,38 @@ var FooterComponent = class {
1720
1757
  }
1721
1758
  let contextPercentStr, autoIndicator = this.autoCompactEnabled ? " (auto)" : "", contextPercentDisplay = contextPercent === "?" ? `?/${formatTokens(contextWindow)}${autoIndicator}` : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
1722
1759
  contextPercentValue > 90 ? contextPercentStr = theme.fg("error", contextPercentDisplay) : contextPercentValue > 70 ? contextPercentStr = theme.fg("warning", contextPercentDisplay) : contextPercentStr = contextPercentDisplay, statsParts.push(contextPercentStr), areExperimentalFeaturesEnabled() && statsParts.push(`${theme.fg("dim", "\u2022")} ${theme.bold(theme.fg("warning", "xp"))}`);
1723
- let statsLeft = statsParts.join(" "), modelName = state.model?.id || "no-model", statsLeftWidth = visibleWidth(statsLeft);
1724
- statsLeftWidth > width && (statsLeft = truncateToWidth2(statsLeft, width, "..."), statsLeftWidth = visibleWidth(statsLeft));
1760
+ let statsLeft = statsParts.join(" "), modelName = state.model?.id || "no-model", statsLeftWidth = visibleWidth3(statsLeft);
1761
+ statsLeftWidth > width && (statsLeft = truncateToWidth3(statsLeft, width, "..."), statsLeftWidth = visibleWidth3(statsLeft));
1725
1762
  let minPadding = 2, rightSideWithoutProvider = modelName;
1726
1763
  if (state.model?.reasoning) {
1727
1764
  let thinkingLevel = state.thinkingLevel || "off";
1728
1765
  rightSideWithoutProvider = thinkingLevel === "off" ? `${modelName} \u2022 thinking off` : `${modelName} \u2022 ${thinkingLevel}`;
1729
1766
  }
1730
1767
  let rightSide = rightSideWithoutProvider;
1731
- this.footerData.getAvailableProviderCount() > 1 && state.model && (rightSide = `(${state.model.provider}) ${rightSideWithoutProvider}`, statsLeftWidth + minPadding + visibleWidth(rightSide) > width && (rightSide = rightSideWithoutProvider));
1732
- let rightSideWidth = visibleWidth(rightSide), totalNeeded = statsLeftWidth + minPadding + rightSideWidth, statsLine;
1768
+ this.footerData.getAvailableProviderCount() > 1 && state.model && (rightSide = `(${state.model.provider}) ${rightSideWithoutProvider}`, statsLeftWidth + minPadding + visibleWidth3(rightSide) > width && (rightSide = rightSideWithoutProvider));
1769
+ let rightSideWidth = visibleWidth3(rightSide), totalNeeded = statsLeftWidth + minPadding + rightSideWidth, statsLine;
1733
1770
  if (totalNeeded <= width) {
1734
1771
  let padding = " ".repeat(width - statsLeftWidth - rightSideWidth);
1735
1772
  statsLine = statsLeft + padding + rightSide;
1736
1773
  } else {
1737
1774
  let availableForRight = width - statsLeftWidth - minPadding;
1738
1775
  if (availableForRight > 0) {
1739
- let truncatedRight = truncateToWidth2(rightSide, availableForRight, ""), truncatedRightWidth = visibleWidth(truncatedRight), padding = " ".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));
1776
+ let truncatedRight = truncateToWidth3(rightSide, availableForRight, ""), truncatedRightWidth = visibleWidth3(truncatedRight), padding = " ".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));
1740
1777
  statsLine = statsLeft + padding + truncatedRight;
1741
1778
  } else
1742
1779
  statsLine = statsLeft;
1743
1780
  }
1744
- let dimStatsLeft = theme.fg("dim", statsLeft), remainder = statsLine.slice(statsLeft.length), dimRemainder = theme.fg("dim", remainder), lines = [truncateToWidth2(theme.fg("dim", pwd), width, theme.fg("dim", "...")), dimStatsLeft + dimRemainder], extensionStatuses = this.footerData.getExtensionStatuses();
1781
+ let dimStatsLeft = theme.fg("dim", statsLeft), remainder = statsLine.slice(statsLeft.length), dimRemainder = theme.fg("dim", remainder), lines = [truncateToWidth3(theme.fg("dim", pwd), width, theme.fg("dim", "...")), dimStatsLeft + dimRemainder], extensionStatuses = this.footerData.getExtensionStatuses();
1745
1782
  if (extensionStatuses.size > 0) {
1746
1783
  let statusLine = Array.from(extensionStatuses.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, text]) => sanitizeStatusText(text)).join(" ");
1747
- lines.push(truncateToWidth2(statusLine, width, theme.fg("dim", "...")));
1784
+ lines.push(truncateToWidth3(statusLine, width, theme.fg("dim", "...")));
1748
1785
  }
1749
1786
  return lines;
1750
1787
  }
1751
1788
  };
1752
1789
 
1753
1790
  // packages/coding-agent/dist/modes/interactive/components/usage-view.js
1754
- import { truncateToWidth as truncateToWidth3, visibleWidth as visibleWidth2 } from "@ashx-j/lunr-tui";
1791
+ import { truncateToWidth as truncateToWidth4, visibleWidth as visibleWidth4 } from "@ashx-j/lunr-tui";
1755
1792
  var BAR_CELLS = 20;
1756
1793
  function usageLevelColor(percent) {
1757
1794
  return percent > 90 ? "error" : percent > 70 ? "warning" : "success";
@@ -1789,9 +1826,9 @@ function planWindowLine(window, labelWidth) {
1789
1826
  return ` ${window.label.padEnd(labelWidth)} ${usageBar(window.usedPercent)} ${pct}${reset}`;
1790
1827
  }
1791
1828
  function renderThemedBox(headerText, content, maxWidth) {
1792
- let contentWidth = Math.max(...content.map((line) => visibleWidth2(line))), totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth))), innerWidth = totalWidth - 4, border = (text) => theme.fg("border", text), top = border(`\u256D${headerText}${"\u2500".repeat(Math.max(0, totalWidth - 2 - headerText.length))}\u256E`), bottom = border(`\u2570${"\u2500".repeat(totalWidth - 2)}\u256F`), lines = [top];
1829
+ let contentWidth = Math.max(...content.map((line) => visibleWidth4(line))), totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth))), innerWidth = totalWidth - 4, border = (text) => theme.fg("border", text), top = border(`\u256D${headerText}${"\u2500".repeat(Math.max(0, totalWidth - 2 - headerText.length))}\u256E`), bottom = border(`\u2570${"\u2500".repeat(totalWidth - 2)}\u256F`), lines = [top];
1793
1830
  for (let rawLine of content) {
1794
- let line = rawLine.length > 0 ? truncateToWidth3(rawLine, innerWidth, "") : "", padding = " ".repeat(Math.max(0, innerWidth - visibleWidth2(line)));
1831
+ let line = rawLine.length > 0 ? truncateToWidth4(rawLine, innerWidth, "") : "", padding = " ".repeat(Math.max(0, innerWidth - visibleWidth4(line)));
1795
1832
  lines.push(`${border("\u2502 ")}${line}${padding}${border(" \u2502")}`);
1796
1833
  }
1797
1834
  return lines.push(bottom), lines;
@@ -2568,7 +2605,7 @@ var PlanMessageComponent = class extends Container10 {
2568
2605
  };
2569
2606
 
2570
2607
  // packages/coding-agent/dist/modes/interactive/components/processes-selector.js
2571
- import { Container as Container11, getKeybindings as getKeybindings5, Spacer as Spacer12, Text as Text13, truncateToWidth as truncateToWidth4 } from "@ashx-j/lunr-tui";
2608
+ import { Container as Container11, getKeybindings as getKeybindings5, Spacer as Spacer12, Text as Text13, truncateToWidth as truncateToWidth5 } from "@ashx-j/lunr-tui";
2572
2609
  function formatElapsed(startedAt) {
2573
2610
  let ms = Date.now() - startedAt, s = Math.floor(ms / 1e3);
2574
2611
  if (s < 60)
@@ -2605,7 +2642,7 @@ var ProcessesSelectorComponent = class extends Container11 {
2605
2642
  continue;
2606
2643
  let elapsed = formatElapsed(p.startedAt), status;
2607
2644
  p.status === "exited" ? status = `exited(${p.exitCode ?? "?"})` : p.status === "paused" ? status = "paused" : status = "running";
2608
- let line = `${i === this.selected ? "\u25B8 " : " "}${p.pid} \xB7 ${status} \xB7 ${elapsed} \xB7 ${truncateToWidth4(p.command, 60)}`, colored = i === this.selected ? theme.fg("accent", line) : theme.fg("dim", line);
2645
+ let line = `${i === this.selected ? "\u25B8 " : " "}${p.pid} \xB7 ${status} \xB7 ${elapsed} \xB7 ${truncateToWidth5(p.command, 60)}`, colored = i === this.selected ? theme.fg("accent", line) : theme.fg("dim", line);
2609
2646
  this.addChild(new Text13(colored, 0, 0));
2610
2647
  }
2611
2648
  this.addChild(new Spacer12(1));
@@ -3580,6 +3617,14 @@ var ThemeSubmenu = class extends Container13 {
3580
3617
  values: ["true", "false"],
3581
3618
  disabled: () => config.hideThinkingBlock
3582
3619
  },
3620
+ {
3621
+ id: "reasoning-display",
3622
+ label: "Reasoning display",
3623
+ description: "Auto uses one line for OpenAI Codex, four lines for other models. One line has a soft moving highlight.",
3624
+ currentValue: config.reasoningDisplay ?? "auto",
3625
+ values: ["auto", "one-line", "four-lines"],
3626
+ disabled: () => config.hideThinkingBlock
3627
+ },
3583
3628
  {
3584
3629
  id: "cache-miss-notices",
3585
3630
  label: "Cache miss notices",
@@ -3909,6 +3954,9 @@ var ThemeSubmenu = class extends Container13 {
3909
3954
  case "thinking-collapse":
3910
3955
  callbacks.onThinkingCollapseChange(newValue === "true");
3911
3956
  break;
3957
+ case "reasoning-display":
3958
+ (newValue === "auto" || newValue === "one-line" || newValue === "four-lines") && callbacks.onReasoningDisplayChange(newValue);
3959
+ break;
3912
3960
  case "cache-miss-notices":
3913
3961
  callbacks.onShowCacheMissNoticesChange(newValue === "true");
3914
3962
  break;
@@ -4100,7 +4148,6 @@ var ToolExecutionComponent = class extends Container14 {
4100
4148
  hideComponent = !1;
4101
4149
  groupContinuation = !1;
4102
4150
  groupFollowed = !1;
4103
- groupPrev;
4104
4151
  groupNext;
4105
4152
  constructor(toolName, toolCallId, args, options = {}, toolDefinition, ui, cwd) {
4106
4153
  super(), this.toolName = toolName, this.toolCallId = toolCallId, this.args = args, this.toolDefinition = toolDefinition, this.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName], this.showImages = options.showImages ?? !0, this.imageWidthCells = options.imageWidthCells ?? 60, this.ui = ui, this.cwd = cwd, this.topSpacer = new Spacer15(1), this.addChild(this.topSpacer), this.contentBox = new Box7(1, 1, (text) => theme.bg("toolPendingBg", text)), this.contentText = new Text17("", 1, 1, (text) => theme.bg("toolPendingBg", text)), this.selfRenderContainer = new Container14(), this.hasRendererDefinition() ? this.addChild(this.getRenderShell() === "self" ? this.selfRenderContainer : this.contentBox) : this.addChild(this.contentText), this.updateDisplay();
@@ -4185,16 +4232,30 @@ var ToolExecutionComponent = class extends Container14 {
4185
4232
  }
4186
4233
  }
4187
4234
  setExpanded(expanded) {
4188
- this.expanded = expanded, this.updateDisplay(), this.refreshGroupTail();
4235
+ this.toolName !== "browser" && (this.expanded = expanded, this.updateDisplay(), this.refreshGroupTail());
4189
4236
  }
4190
4237
  handleClick(_localY, _width) {
4191
- return this.isPartial || this.toolName === "subagent" || this.toolName === "subagent_wait" ? !1 : (this.setExpanded(!this.expanded), this.ui.requestRender(), !0);
4238
+ return this.isPartial || this.toolName === "browser" || this.toolName === "subagent" || this.toolName === "subagent_wait" ? !1 : (this.setExpanded(!this.expanded), this.ui.requestRender(), !0);
4239
+ }
4240
+ beginNextExecution(toolCallId, args) {
4241
+ this.toolCallId = toolCallId, this.args = args, this.result = void 0, this.isPartial = !0, this.executionStarted = !1, this.argsComplete = !1, this.expanded = !1, this.disposeComponent(this.resultRendererComponent), this.resultRendererComponent = void 0, this.updateDisplay();
4242
+ }
4243
+ dispose() {
4244
+ let components = /* @__PURE__ */ new Set([this.callRendererComponent, this.resultRendererComponent]);
4245
+ for (let component of components)
4246
+ this.disposeComponent(component);
4247
+ }
4248
+ disposeComponent(component) {
4249
+ component?.dispose?.();
4192
4250
  }
4193
4251
  // lunr: consecutive same-tool grouping — exposes the tool name so the caller
4194
4252
  // can detect adjacency.
4195
4253
  getToolName() {
4196
4254
  return this.toolName;
4197
4255
  }
4256
+ matchesToolCall(toolCallId) {
4257
+ return this.toolCallId === toolCallId;
4258
+ }
4198
4259
  // lunr: consecutive same-tool grouping — continuation calls hide the top
4199
4260
  // spacer and top box pad so adjacent same-bg boxes read as one continuous
4200
4261
  // background; the last card in a run keeps its bottom pad.
@@ -4206,41 +4267,22 @@ var ToolExecutionComponent = class extends Container14 {
4206
4267
  setGroupFollowed(on) {
4207
4268
  this.groupFollowed = on, this.applyGroupPadding(), this.invalidate();
4208
4269
  }
4209
- // lunr: same-name run link so a later card can hoist earlier error bodies
4210
- // under the last leaf instead of splitting the tree.
4270
+ // lunr: same-name run link keeps the final card refreshed as earlier calls settle.
4211
4271
  linkGroupNext(next) {
4212
- this.groupNext = next, next.groupPrev = this;
4272
+ this.groupNext = next;
4213
4273
  }
4214
4274
  applyGroupPadding() {
4215
4275
  let top = this.groupContinuation ? 0 : 1, bottom = this.groupFollowed ? 0 : 1;
4216
4276
  this.contentBox.setPaddingTop(top), this.contentBox.setPaddingBottom(bottom), this.contentText.setPaddingTop(top), this.contentText.setPaddingBottom(bottom), this.getRenderShell() === "self" && this.callRendererComponent instanceof Box7 && (this.callRendererComponent.setPaddingTop(top), this.callRendererComponent.setPaddingBottom(bottom));
4217
4277
  }
4218
- shouldHideGroupedErrorBody() {
4219
- return !!this.result?.isError && this.groupFollowed && !this.expanded && !this.isPartial && this.getRenderShell() === "default" && this.toolName !== "subagent" && this.toolName !== "subagent_wait";
4220
- }
4221
4278
  shouldSkipCompactResult() {
4222
4279
  if (this.result === void 0 || this.isPartial || this.expanded)
4223
4280
  return !1;
4224
4281
  if (this.toolName === "subagent") {
4225
4282
  let details = this.result.details;
4226
- return !(this.result.isError || Array.isArray(details?.results) && details.results.length > 0 || details?.mode === "management");
4283
+ return !this.result.isError && this.args?.action === "steer" ? !0 : !(this.result.isError || Array.isArray(details?.results) && details.results.length > 0 || details?.mode === "management");
4227
4284
  }
4228
- return this.result.isError ? this.shouldHideGroupedErrorBody() : this.getRenderShell() === "default";
4229
- }
4230
- formatHoistedGroupErrors() {
4231
- if (this.groupFollowed || this.expanded)
4232
- return;
4233
- let texts = [], prev = this.groupPrev;
4234
- for (; prev; ) {
4235
- if (prev.shouldHideGroupedErrorBody()) {
4236
- let output = prev.getTextOutput().trim();
4237
- output && texts.unshift(output);
4238
- }
4239
- prev = prev.groupPrev;
4240
- }
4241
- return texts.length > 0 ? `
4242
- ${texts.join(`
4243
- `)}` : void 0;
4285
+ return this.toolName === "subagent_wait" ? !1 : this.result.isError ? !0 : this.getRenderShell() === "default";
4244
4286
  }
4245
4287
  refreshGroupTail() {
4246
4288
  let next = this.groupNext;
@@ -4308,8 +4350,6 @@ ${texts.join(`
4308
4350
  let component = this.createResultFallback();
4309
4351
  component && (renderContainer.addChild(component), hasContent = !0);
4310
4352
  }
4311
- let hoisted = this.formatHoistedGroupErrors();
4312
- hoisted && (renderContainer.addChild(new Text17(theme.fg("toolOutput", hoisted), 0, 0)), hasContent = !0);
4313
4353
  }
4314
4354
  } else
4315
4355
  this.contentText.setCustomBgFn(bgFn), this.contentText.setText(this.formatToolExecution()), hasContent = !0;
@@ -4339,7 +4379,7 @@ ${texts.join(`
4339
4379
  return getTextOutput(this.result, this.showImages);
4340
4380
  }
4341
4381
  formatToolExecution() {
4342
- let hideGroupedErrorBody = !!(this.result?.isError && this.groupFollowed && !this.expanded), compact = !this.isPartial && !this.expanded && (!this.result?.isError || hideGroupedErrorBody), text = formatGroupedCall({
4382
+ let compact = !this.isPartial && !this.expanded, text = formatGroupedCall({
4343
4383
  role: toolGroupRole(this.groupContinuation, this.groupFollowed),
4344
4384
  compact,
4345
4385
  tree: toolGroupTree({ expanded: this.expanded, isError: this.result?.isError }),
@@ -4355,8 +4395,7 @@ ${content}`);
4355
4395
  output && (text += `
4356
4396
  ${output}`);
4357
4397
  }
4358
- let hoisted = this.formatHoistedGroupErrors();
4359
- return hoisted && (text += hoisted), text;
4398
+ return text;
4360
4399
  }
4361
4400
  };
4362
4401
  function applySameToolGrouping(previous, next) {
@@ -4364,7 +4403,7 @@ function applySameToolGrouping(previous, next) {
4364
4403
  }
4365
4404
 
4366
4405
  // packages/coding-agent/dist/modes/interactive/components/tree-selector.js
4367
- import { Container as Container15, getKeybindings as getKeybindings8, Input as Input6, Spacer as Spacer16, sliceByColumn, Text as Text18, truncateToWidth as truncateToWidth5, visibleWidth as visibleWidth3, wrapTextWithAnsi as wrapTextWithAnsi2 } from "@ashx-j/lunr-tui";
4406
+ import { Container as Container15, getKeybindings as getKeybindings8, Input as Input6, Spacer as Spacer16, sliceByColumn, Text as Text18, truncateToWidth as truncateToWidth6, visibleWidth as visibleWidth5, wrapTextWithAnsi as wrapTextWithAnsi2 } from "@ashx-j/lunr-tui";
4368
4407
  var TREE_GUTTER_WIDTH = 2, MIN_VISIBLE_ANCHOR_CONTENT_WIDTH = 4, MAX_VISIBLE_ANCHOR_CONTENT_WIDTH = 20, MIN_ANCHOR_CONTEXT_WIDTH = 2, MAX_ANCHOR_CONTEXT_WIDTH = 12;
4369
4408
  function renderHorizontalViewport(rows, width) {
4370
4409
  let viewportWidth = Math.max(0, width - TREE_GUTTER_WIDTH), maxBodyWidth = rows.reduce((max, row) => Math.max(max, row.bodyWidth), 0), maxHorizontalScroll = Math.max(0, maxBodyWidth - viewportWidth), selectedRow = rows.find((row) => row.isSelected), horizontalScroll = 0;
@@ -4377,7 +4416,7 @@ function renderHorizontalViewport(rows, width) {
4377
4416
  }
4378
4417
  return rows.map((row) => {
4379
4418
  let line = horizontalScroll > 0 ? `${row.gutter}${sliceByColumn(row.body, horizontalScroll, viewportWidth, !0)}\x1B[0m` : row.gutter + row.body;
4380
- return truncateToWidth5(line, width, "");
4419
+ return truncateToWidth6(line, width, "");
4381
4420
  });
4382
4421
  }
4383
4422
  var TreeList = class {
@@ -4695,7 +4734,7 @@ var TreeList = class {
4695
4734
  render(width) {
4696
4735
  let lines = [];
4697
4736
  if (this.filteredNodes.length === 0)
4698
- return lines.push(truncateToWidth5(theme.fg("muted", " No entries found"), width)), lines.push(truncateToWidth5(theme.fg("muted", ` (0/0)${this.getStatusLabels()}`), width)), lines;
4737
+ return lines.push(truncateToWidth6(theme.fg("muted", " No entries found"), width)), lines.push(truncateToWidth6(theme.fg("muted", ` (0/0)${this.getStatusLabels()}`), width)), lines;
4699
4738
  let startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisibleLines / 2), this.filteredNodes.length - this.maxVisibleLines)), endIndex = Math.min(startIndex + this.maxVisibleLines, this.filteredNodes.length), renderedRows = [];
4700
4739
  for (let i = startIndex; i < endIndex; i++) {
4701
4740
  let flatNode = this.filteredNodes[i], entry = flatNode.node.entry, isSelected = i === this.selectedIndex, cursor = isSelected ? theme.fg("accent", "\u203A ") : " ", displayIndent = this.multipleRoots ? Math.max(0, flatNode.indent - 1) : flatNode.indent, connector = flatNode.showConnector && !flatNode.isVirtualRootChild ? flatNode.isLast ? "\u2514\u2500 " : "\u251C\u2500 " : "", connectorPosition = connector ? displayIndent - 1 : -1, totalChars = displayIndent * 3, prefixChars = [], isFolded = this.foldedNodes.has(entry.id);
@@ -4714,10 +4753,10 @@ var TreeList = class {
4714
4753
  else
4715
4754
  prefixChars.push(" ");
4716
4755
  }
4717
- let prefix = prefixChars.join(""), showsFoldInConnector = flatNode.showConnector && !flatNode.isVirtualRootChild, foldMarker = isFolded && !showsFoldInConnector ? theme.fg("accent", "\u229E ") : "", pathMarker = this.activePathIds.has(entry.id) ? theme.fg("accent", "\u2022 ") : "", label = flatNode.node.label ? theme.fg("warning", `[${flatNode.node.label}] `) : "", labelTimestamp = this.showLabelTimestamps && flatNode.node.label && flatNode.node.labelTimestamp ? theme.fg("muted", `${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `) : "", content = this.getEntryDisplayText(flatNode.node, isSelected), prefixPart = theme.fg("dim", prefix) + foldMarker + pathMarker, anchorCol = visibleWidth3(prefixPart), gutter = cursor, body = prefixPart + label + labelTimestamp + content;
4718
- isSelected && (gutter = theme.bg("selectedBg", gutter), body = theme.bg("selectedBg", body)), renderedRows.push({ gutter, body, anchorCol, bodyWidth: visibleWidth3(body), isSelected });
4756
+ let prefix = prefixChars.join(""), showsFoldInConnector = flatNode.showConnector && !flatNode.isVirtualRootChild, foldMarker = isFolded && !showsFoldInConnector ? theme.fg("accent", "\u229E ") : "", pathMarker = this.activePathIds.has(entry.id) ? theme.fg("accent", "\u2022 ") : "", label = flatNode.node.label ? theme.fg("warning", `[${flatNode.node.label}] `) : "", labelTimestamp = this.showLabelTimestamps && flatNode.node.label && flatNode.node.labelTimestamp ? theme.fg("muted", `${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `) : "", content = this.getEntryDisplayText(flatNode.node, isSelected), prefixPart = theme.fg("dim", prefix) + foldMarker + pathMarker, anchorCol = visibleWidth5(prefixPart), gutter = cursor, body = prefixPart + label + labelTimestamp + content;
4757
+ isSelected && (gutter = theme.bg("selectedBg", gutter), body = theme.bg("selectedBg", body)), renderedRows.push({ gutter, body, anchorCol, bodyWidth: visibleWidth5(body), isSelected });
4719
4758
  }
4720
- return lines.push(...renderHorizontalViewport(renderedRows, width)), lines.push(truncateToWidth5(theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredNodes.length})${this.getStatusLabels()}`), width)), lines;
4759
+ return lines.push(...renderHorizontalViewport(renderedRows, width)), lines.push(truncateToWidth6(theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredNodes.length})${this.getStatusLabels()}`), width)), lines;
4721
4760
  }
4722
4761
  getEntryDisplayText(node, isSelected) {
4723
4762
  let entry = node.entry, result, normalize = (s) => s.replace(/[\n\t]/g, " ").trim();
@@ -4976,7 +5015,7 @@ var TreeList = class {
4976
5015
  }
4977
5016
  render(width) {
4978
5017
  let query = this.treeList.getSearchQuery();
4979
- return query ? [truncateToWidth5(` ${theme.fg("muted", "Type to search:")} ${theme.fg("accent", query)}`, width)] : [truncateToWidth5(` ${theme.fg("muted", "Type to search:")}`, width)];
5018
+ return query ? [truncateToWidth6(` ${theme.fg("muted", "Type to search:")} ${theme.fg("accent", query)}`, width)] : [truncateToWidth6(` ${theme.fg("muted", "Type to search:")}`, width)];
4980
5019
  }
4981
5020
  handleInput(_keyData) {
4982
5021
  }
@@ -4989,12 +5028,12 @@ var TreeList = class {
4989
5028
  return text ? labelFirst ? `${label} ${text}` : `${text} ${label}` : label;
4990
5029
  }), availableWidth = Math.max(1, width), indent = " ", separator = " \xB7 ", lines = [], currentLine = "";
4991
5030
  for (let item of items) {
4992
- let candidate = currentLine ? `${currentLine}${separator}${item}` : visibleWidth3(`${indent}${item}`) <= availableWidth ? `${indent}${item}` : item;
4993
- if (!currentLine || visibleWidth3(candidate) <= availableWidth) {
5031
+ let candidate = currentLine ? `${currentLine}${separator}${item}` : visibleWidth5(`${indent}${item}`) <= availableWidth ? `${indent}${item}` : item;
5032
+ if (!currentLine || visibleWidth5(candidate) <= availableWidth) {
4994
5033
  currentLine = candidate;
4995
5034
  continue;
4996
5035
  }
4997
- lines.push(...wrapTextWithAnsi2(currentLine.trimEnd(), availableWidth)), currentLine = visibleWidth3(`${indent}${item}`) <= availableWidth ? `${indent}${item}` : item;
5036
+ lines.push(...wrapTextWithAnsi2(currentLine.trimEnd(), availableWidth)), currentLine = visibleWidth5(`${indent}${item}`) <= availableWidth ? `${indent}${item}` : item;
4998
5037
  }
4999
5038
  return currentLine && lines.push(...wrapTextWithAnsi2(currentLine.trimEnd(), availableWidth)), lines.map((line) => theme.fg("muted", line));
5000
5039
  }
@@ -5055,7 +5094,7 @@ var LabelInput = class {
5055
5094
  }
5056
5095
  render(width) {
5057
5096
  let lines = [], availableWidth = width - 2;
5058
- return lines.push(truncateToWidth5(` ${theme.fg("muted", "Label (empty to remove):")}`, width)), lines.push(...this.input.render(availableWidth).map((line) => truncateToWidth5(` ${line}`, width))), lines.push(truncateToWidth5(` ${keyHint("tui.select.confirm", "save")} ${keyHint("tui.select.cancel", "cancel")}`, width)), lines;
5097
+ return lines.push(truncateToWidth6(` ${theme.fg("muted", "Label (empty to remove):")}`, width)), lines.push(...this.input.render(availableWidth).map((line) => truncateToWidth6(` ${line}`, width))), lines.push(truncateToWidth6(` ${keyHint("tui.select.confirm", "save")} ${keyHint("tui.select.cancel", "cancel")}`, width)), lines;
5059
5098
  }
5060
5099
  handleInput(keyData) {
5061
5100
  let kb = getKeybindings8();
@@ -5172,7 +5211,7 @@ var OSC133_ZONE_START2 = "\x1B]133;A\x07", OSC133_ZONE_END2 = "\x1B]133;B\x07",
5172
5211
  };
5173
5212
 
5174
5213
  // packages/coding-agent/dist/modes/interactive/components/user-message-selector.js
5175
- import { Container as Container18, getKeybindings as getKeybindings10, Spacer as Spacer18, Text as Text20, truncateToWidth as truncateToWidth6 } from "@ashx-j/lunr-tui";
5214
+ import { Container as Container18, getKeybindings as getKeybindings10, Spacer as Spacer18, Text as Text20, truncateToWidth as truncateToWidth7 } from "@ashx-j/lunr-tui";
5176
5215
  var UserMessageList = class {
5177
5216
  messages = [];
5178
5217
  selectedIndex = 0;
@@ -5193,7 +5232,7 @@ var UserMessageList = class {
5193
5232
  return lines.push(theme.fg("muted", " No user messages found")), lines;
5194
5233
  let startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.messages.length - this.maxVisible)), endIndex = Math.min(startIndex + this.maxVisible, this.messages.length);
5195
5234
  for (let i = startIndex; i < endIndex; i++) {
5196
- let message = this.messages[i], isSelected = i === this.selectedIndex, normalizedMessage = message.text.replace(/\n/g, " ").trim(), cursor = isSelected ? theme.fg("accent", "\u203A ") : " ", maxMsgWidth = width - 2, truncatedMsg = truncateToWidth6(normalizedMessage, maxMsgWidth), messageLine = cursor + (isSelected ? theme.bold(truncatedMsg) : truncatedMsg);
5235
+ let message = this.messages[i], isSelected = i === this.selectedIndex, normalizedMessage = message.text.replace(/\n/g, " ").trim(), cursor = isSelected ? theme.fg("accent", "\u203A ") : " ", maxMsgWidth = width - 2, truncatedMsg = truncateToWidth7(normalizedMessage, maxMsgWidth), messageLine = cursor + (isSelected ? theme.bold(truncatedMsg) : truncatedMsg);
5197
5236
  lines.push(messageLine);
5198
5237
  let metadata = ` Message ${i + 1} of ${this.messages.length}`, metadataLine = theme.fg("muted", metadata);
5199
5238
  lines.push(metadataLine), lines.push("");
@@ -5615,8 +5654,10 @@ var InteractiveMode = class _InteractiveMode {
5615
5654
  streamingTargetMessage = void 0;
5616
5655
  streamingDisplayedLength = 0;
5617
5656
  smoothStreamingTimer = void 0;
5657
+ thinkingAnimationTimer;
5618
5658
  // Tool execution tracking: toolCallId -> component
5619
5659
  pendingTools = /* @__PURE__ */ new Map();
5660
+ browserActivityComponent;
5620
5661
  // Tool output expansion state
5621
5662
  toolOutputExpanded = !1;
5622
5663
  // Thinking block visibility state
@@ -6313,7 +6354,7 @@ ${warningLines}`, 0, 0)), this.loadedResourcesContainer.addChild(new Spacer19(1)
6313
6354
  replaceInstructions: options?.replaceInstructions,
6314
6355
  label: options?.label
6315
6356
  });
6316
- return result.cancelled ? { cancelled: !0 } : (this.chatContainer.clear(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Navigated to selected point"), this.flushCompactionQueue({ willRetry: !1 }), { cancelled: !1 });
6357
+ return result.cancelled ? { cancelled: !0 } : (this.clearChatContainer(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Navigated to selected point"), this.flushCompactionQueue({ willRetry: !1 }), { cancelled: !1 });
6317
6358
  },
6318
6359
  switchSession: async (sessionPath, options) => this.handleResumeSession(sessionPath, options),
6319
6360
  reload: async () => {
@@ -6364,7 +6405,7 @@ ${warningLines}`, 0, 0)), this.loadedResourcesContainer.addChild(new Spacer19(1)
6364
6405
  this.showError(`${prefix}: ${message}`), stopThemeWatcher(), this.stop(), process.exit(1);
6365
6406
  }
6366
6407
  renderCurrentSessionState() {
6367
- this.ui.setChatScroll(0), this.loadedResourcesContainer.clear(), this.chatContainer.clear(), this.pendingMessagesContainer.clear(), this.compactionQueuedMessages = [], this.pendingCompactionRender = void 0, this.stopSmoothStreaming(), this.streamingComponent = void 0, this.streamingMessage = void 0, this.pendingTools.clear(), this.renderInitialMessages();
6408
+ this.ui.setChatScroll(0), this.loadedResourcesContainer.clear(), this.clearChatContainer(), this.pendingMessagesContainer.clear(), this.compactionQueuedMessages = [], this.pendingCompactionRender = void 0, this.stopSmoothStreaming(), this.streamingComponent = void 0, this.streamingMessage = void 0, this.pendingTools.clear(), this.renderInitialMessages();
6368
6409
  }
6369
6410
  /**
6370
6411
  * Get a registered tool definition by name (for custom rendering).
@@ -7078,9 +7119,21 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7078
7119
  this.isExtensionCommand(text) ? (this.editor.addToHistory?.(text), this.editor.setText(""), await this.promptAfterDeferredBuiltins(text)) : this.queueCompactionMessage(text, "steer", images);
7079
7120
  return;
7080
7121
  }
7081
- if (this.session.isStreaming) {
7082
- this.editor.addToHistory?.(text), this.editor.setText(""), await this.promptAfterDeferredBuiltins(text, { streamingBehavior: "steer", images }), this.updatePendingMessagesDisplay(), this.ui.requestRender();
7083
- return;
7122
+ if (this.session.isStreaming || this.session.isWaitPromptHandoffActive) {
7123
+ if (!this.isExtensionCommand(text)) {
7124
+ await this.awaitDeferredBuiltinsForPrompt();
7125
+ let handoff = await this.session.interruptSubagentWaitWithPrompt(text, { images });
7126
+ if (handoff) {
7127
+ this.editor.addToHistory?.(text), this.editor.setText(""), handoff.completion.catch((error) => {
7128
+ this.showError(error instanceof Error ? error.message : String(error));
7129
+ }), this.ui.requestRender();
7130
+ return;
7131
+ }
7132
+ }
7133
+ if (this.session.isStreaming) {
7134
+ this.editor.addToHistory?.(text), this.editor.setText(""), await this.promptAfterDeferredBuiltins(text, { streamingBehavior: "steer", images }), this.updatePendingMessagesDisplay(), this.ui.requestRender();
7135
+ return;
7136
+ }
7084
7137
  }
7085
7138
  this.flushPendingBashComponents(), this.onInputCallback ? this.onInputCallback({ text, images }) : this.pendingUserInputs.push({ text, images }), this.editor.addToHistory?.(text);
7086
7139
  };
@@ -7090,6 +7143,13 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7090
7143
  getSmoothStreamingOptions() {
7091
7144
  return { hideThinking: this.hideThinkingBlock };
7092
7145
  }
7146
+ setThinkingAnimation(active) {
7147
+ if (!active) {
7148
+ this.thinkingAnimationTimer && clearInterval(this.thinkingAnimationTimer), this.thinkingAnimationTimer = void 0;
7149
+ return;
7150
+ }
7151
+ this.thinkingAnimationTimer || (this.thinkingAnimationTimer = setInterval(() => this.ui.requestRender(), 33), this.thinkingAnimationTimer.unref?.());
7152
+ }
7093
7153
  clearSmoothStreamingTimer() {
7094
7154
  this.smoothStreamingTimer && (clearInterval(this.smoothStreamingTimer), this.smoothStreamingTimer = void 0);
7095
7155
  }
@@ -7120,11 +7180,8 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7120
7180
  let component = this.pendingTools.get(content.id);
7121
7181
  component && component.updateArgs(content.arguments);
7122
7182
  } else {
7123
- let component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
7124
- showImages: this.settingsManager.getShowImages(),
7125
- imageWidthCells: this.settingsManager.getImageWidthCells()
7126
- }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
7127
- component.setExpanded(this.toolOutputExpanded), this.addToolComponentToChat(component), this.pendingTools.set(content.id, component);
7183
+ let component = content.name === "browser" && this.browserActivityComponent ? this.browserActivityComponent : this.createToolExecutionComponent(content.name, content.id, content.arguments);
7184
+ this.pendingTools.set(content.id, component);
7128
7185
  }
7129
7186
  }
7130
7187
  advanceSmoothStreaming() {
@@ -7142,7 +7199,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7142
7199
  this.streamingDisplayedLength += computeSmoothRevealStep(backlog), this.streamingDisplayedLength > total && (this.streamingDisplayedLength = total), this.paintSmoothStreamingFrame(), this.streamingDisplayedLength >= total && this.clearSmoothStreamingTimer();
7143
7200
  }
7144
7201
  stopSmoothStreaming() {
7145
- this.clearSmoothStreamingTimer(), this.streamingTargetMessage = void 0, this.streamingDisplayedLength = 0;
7202
+ this.setThinkingAnimation(!1), this.clearSmoothStreamingTimer(), this.streamingTargetMessage = void 0, this.streamingDisplayedLength = 0;
7146
7203
  }
7147
7204
  /** Apply a mid-stream smoothStreaming setting change without rewinding. */
7148
7205
  applySmoothStreamingSettingChange(enabled) {
@@ -7164,7 +7221,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7164
7221
  async handleEvent(event) {
7165
7222
  switch (this.isInitialized || await this.init(), this.footer.invalidate(), event.type) {
7166
7223
  case "agent_start":
7167
- this.pendingTools.clear(), this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!0), this.retryEscapeHandler && (this.defaultEditor.onEscape = this.retryEscapeHandler, this.retryEscapeHandler = void 0), this.workingVisible ? this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions)) : this.clearStatusIndicator(), this.ui.requestRender();
7224
+ this.pendingTools.clear(), this.browserActivityComponent = void 0, this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!0), this.retryEscapeHandler && (this.defaultEditor.onEscape = this.retryEscapeHandler, this.retryEscapeHandler = void 0), this.workingVisible ? this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions)) : this.clearStatusIndicator(), this.ui.requestRender();
7168
7225
  break;
7169
7226
  case "queue_update":
7170
7227
  this.updatePendingMessagesDisplay(), this.ui.requestRender();
@@ -7179,7 +7236,11 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7179
7236
  this.footer.invalidate(), this.updateEditorBorderColor();
7180
7237
  break;
7181
7238
  case "message_start":
7182
- event.message.role === "custom" ? (this.addMessageToChat(event.message), this.ui.requestRender()) : event.message.role === "user" ? (this.redoStack.length = 0, beginTurn(this.sessionManager.getCwd(), this.sessionManager.getSessionId()), this.stopSmoothStreaming(), this.addMessageToChat(event.message), this.updatePendingMessagesDisplay(), this.ui.requestRender()) : event.message.role === "assistant" && (this.streamingComponent = new AssistantMessageComponent(void 0, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.thinkingCollapse, { requestRender: () => this.ui.requestRender() }), this.thinkingRunTimings = [], this.streamingComponent.setThinkingTimings(this.thinkingRunTimings), this.streamingComponent.setExpanded(this.toolOutputExpanded), this.streamingMessage = event.message, this.streamingTargetMessage = event.message, this.streamingDisplayedLength = 0, this.chatContainer.addChild(this.streamingComponent), this.settingsManager.getSmoothStreaming() ? this.streamingComponent.updateContent(sliceMessageContent(this.streamingMessage, 0, this.getSmoothStreamingOptions()), { thinkingSource: this.streamingMessage }) : this.streamingComponent.updateContent(this.streamingMessage), this.ui.requestRender());
7239
+ event.message.role === "custom" ? (this.addMessageToChat(event.message), this.ui.requestRender()) : event.message.role === "user" ? (this.redoStack.length = 0, beginTurn(this.sessionManager.getCwd(), this.sessionManager.getSessionId()), this.stopSmoothStreaming(), this.addMessageToChat(event.message), this.updatePendingMessagesDisplay(), this.ui.requestRender()) : event.message.role === "assistant" && (this.streamingComponent = new AssistantMessageComponent(void 0, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.thinkingCollapse, {
7240
+ requestRender: () => this.ui.requestRender(),
7241
+ reasoningDisplay: this.settingsManager.getReasoningDisplay(),
7242
+ onThinkingAnimationChange: (active) => this.setThinkingAnimation(active)
7243
+ }), this.thinkingRunTimings = [], this.streamingComponent.setThinkingTimings(this.thinkingRunTimings), this.streamingComponent.setExpanded(this.toolOutputExpanded), this.streamingMessage = event.message, this.streamingTargetMessage = event.message, this.streamingDisplayedLength = 0, this.chatContainer.addChild(this.streamingComponent), this.settingsManager.getSmoothStreaming() ? this.streamingComponent.updateContent(sliceMessageContent(this.streamingMessage, 0, this.getSmoothStreamingOptions()), { thinkingSource: this.streamingMessage }) : this.streamingComponent.updateContent(this.streamingMessage), this.ui.requestRender());
7183
7244
  break;
7184
7245
  case "message_update":
7185
7246
  if (this.streamingComponent && event.message.role === "assistant")
@@ -7222,10 +7283,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7222
7283
  this.streamingDisplayedLength < needed && (this.streamingDisplayedLength = needed), this.paintSmoothStreamingFrame();
7223
7284
  }
7224
7285
  let component = this.pendingTools.get(event.toolCallId);
7225
- component || (component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
7226
- showImages: this.settingsManager.getShowImages(),
7227
- imageWidthCells: this.settingsManager.getImageWidthCells()
7228
- }, this.getRegisteredToolDefinition(event.toolName), this.ui, this.sessionManager.getCwd()), component.setExpanded(this.toolOutputExpanded), this.addToolComponentToChat(component), this.pendingTools.set(event.toolCallId, component)), component.markExecutionStarted(), this.ui.requestRender();
7286
+ component ? event.toolName === "browser" && !component.matchesToolCall(event.toolCallId) && component.beginNextExecution(event.toolCallId, event.args) : (component = this.createToolExecutionComponent(event.toolName, event.toolCallId, event.args), this.pendingTools.set(event.toolCallId, component)), component.markExecutionStarted(), this.ui.requestRender();
7229
7287
  break;
7230
7288
  }
7231
7289
  case "tool_execution_update": {
@@ -7239,7 +7297,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7239
7297
  break;
7240
7298
  }
7241
7299
  case "agent_end":
7242
- this.session.refreshModelFromRegistry(), this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!1), this.clearStatusIndicator("working"), this.stopSmoothStreaming(), this.streamingComponent && (this.chatContainer.removeChild(this.streamingComponent), this.streamingComponent = void 0, this.streamingMessage = void 0), this.pendingTools.clear(), this.maybeAutoNameSession(), captureTreeChanges(this.sessionManager.getCwd(), this.sessionManager.getSessionId()), this.ui.requestRender();
7300
+ this.session.refreshModelFromRegistry(), this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!1), this.clearStatusIndicator("working"), this.stopSmoothStreaming(), this.streamingComponent && (this.chatContainer.removeChild(this.streamingComponent), this.streamingComponent = void 0, this.streamingMessage = void 0), this.pendingTools.clear(), this.browserActivityComponent = void 0, this.maybeAutoNameSession(), captureTreeChanges(this.sessionManager.getCwd(), this.sessionManager.getSessionId()), this.ui.requestRender();
7243
7301
  break;
7244
7302
  case "agent_settled":
7245
7303
  if (this.pendingCompactionRender) {
@@ -7360,7 +7418,10 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7360
7418
  break;
7361
7419
  }
7362
7420
  case "assistant": {
7363
- let assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.thinkingCollapse, { requestRender: () => this.ui.requestRender() });
7421
+ let assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.thinkingCollapse, {
7422
+ requestRender: () => this.ui.requestRender(),
7423
+ reasoningDisplay: this.settingsManager.getReasoningDisplay()
7424
+ });
7364
7425
  assistantComponent.setThinkingTimings(this.thinkingTimingsByMessage.get(message)), assistantComponent.setExpanded(this.toolOutputExpanded), this.chatContainer.addChild(assistantComponent);
7365
7426
  break;
7366
7427
  }
@@ -7373,7 +7434,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7373
7434
  }
7374
7435
  renderSessionItems(items, options = {}) {
7375
7436
  this.pendingTools.clear();
7376
- let renderedPendingTools = /* @__PURE__ */ new Map(), cacheMisses = this.settingsManager.getShowCacheMissNotices() ? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime) : /* @__PURE__ */ new Map();
7437
+ let browserActivityComponent, renderedPendingTools = /* @__PURE__ */ new Map(), cacheMisses = this.settingsManager.getShowCacheMissNotices() ? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime) : /* @__PURE__ */ new Map();
7377
7438
  options.updateFooter && (this.footer.invalidate(), this.updateEditorBorderColor());
7378
7439
  for (let item of items) {
7379
7440
  if (isCustomSessionEntry(item)) {
@@ -7385,11 +7446,11 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7385
7446
  this.addMessageToChat(message);
7386
7447
  for (let content of message.content)
7387
7448
  if (content.type === "toolCall") {
7388
- let component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
7449
+ let component = content.name === "browser" ? browserActivityComponent : void 0;
7450
+ if (component ? component.beginNextExecution(content.id, content.arguments) : (component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
7389
7451
  showImages: this.settingsManager.getShowImages(),
7390
7452
  imageWidthCells: this.settingsManager.getImageWidthCells()
7391
- }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
7392
- if (component.setExpanded(this.toolOutputExpanded), this.addToolComponentToChat(component), message.stopReason === "aborted" || message.stopReason === "error") {
7453
+ }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd()), component.setExpanded(this.toolOutputExpanded), this.addToolComponentToChat(component), content.name === "browser" && (browserActivityComponent = component)), message.stopReason === "aborted" || message.stopReason === "error") {
7393
7454
  let errorMessage;
7394
7455
  if (message.stopReason === "aborted") {
7395
7456
  let retryAttempt = this.session.retryAttempt;
@@ -7408,7 +7469,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7408
7469
  let component = renderedPendingTools.get(message.toolCallId);
7409
7470
  component && (component.updateResult(message), renderedPendingTools.delete(message.toolCallId));
7410
7471
  } else
7411
- this.addMessageToChat(message, options);
7472
+ message.role === "user" && (browserActivityComponent = void 0), this.addMessageToChat(message, options);
7412
7473
  }
7413
7474
  for (let [toolCallId, component] of renderedPendingTools)
7414
7475
  this.pendingTools.set(toolCallId, component);
@@ -7467,7 +7528,7 @@ ${message}`, ["Yes", "No"], opts) === "Yes";
7467
7528
  });
7468
7529
  }
7469
7530
  rebuildChatFromMessages() {
7470
- this.chatContainer.clear(), this.renderSessionEntries(this.sessionManager.buildContextEntries());
7531
+ this.clearChatContainer(), this.renderSessionEntries(this.sessionManager.buildContextEntries());
7471
7532
  }
7472
7533
  // =========================================================================
7473
7534
  // Key handlers
@@ -7661,6 +7722,23 @@ Kill them before exit?`) && killAll(), this.stop(), await this.runtimeHost.dispo
7661
7722
  isExpandable(child) && child.setExpanded(expanded);
7662
7723
  globalThis[/* @__PURE__ */ Symbol.for("@lunr/tools-expanded-changed")]?.(expanded), this.ui.requestRender();
7663
7724
  }
7725
+ createToolExecutionComponent(toolName, toolCallId, args) {
7726
+ if (toolName === "browser" && this.browserActivityComponent)
7727
+ return this.browserActivityComponent.beginNextExecution(toolCallId, args), this.browserActivityComponent;
7728
+ let component = new ToolExecutionComponent(toolName, toolCallId, args, {
7729
+ showImages: this.settingsManager.getShowImages(),
7730
+ imageWidthCells: this.settingsManager.getImageWidthCells()
7731
+ }, this.getRegisteredToolDefinition(toolName), this.ui, this.sessionManager.getCwd());
7732
+ return component.setExpanded(this.toolOutputExpanded), this.addToolComponentToChat(component), toolName === "browser" && (this.browserActivityComponent = component), component;
7733
+ }
7734
+ disposeChatToolComponents() {
7735
+ for (let child of this.chatContainer.children)
7736
+ child instanceof ToolExecutionComponent && child.dispose();
7737
+ this.browserActivityComponent = void 0;
7738
+ }
7739
+ clearChatContainer() {
7740
+ this.disposeChatToolComponents(), this.chatContainer.clear();
7741
+ }
7664
7742
  // lunr: consecutive same-tool grouping — a tool component appended right after
7665
7743
  // another component for the SAME tool becomes a group continuation (no top
7666
7744
  // spacer / top pad); the previous card drops its bottom pad. Mixed neighbors
@@ -7670,7 +7748,7 @@ Kill them before exit?`) && killAll(), this.stop(), await this.runtimeHost.dispo
7670
7748
  applySameToolGrouping(last instanceof ToolExecutionComponent ? last : void 0, component), this.chatContainer.addChild(component);
7671
7749
  }
7672
7750
  toggleThinkingBlockVisibility() {
7673
- if (this.hideThinkingBlock = !this.hideThinkingBlock, this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock), this.chatContainer.clear(), this.rebuildChatFromMessages(), this.streamingComponent && this.streamingMessage) {
7751
+ if (this.hideThinkingBlock = !this.hideThinkingBlock, this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock), this.rebuildChatFromMessages(), this.streamingComponent && this.streamingMessage) {
7674
7752
  if (this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock), this.settingsManager.getSmoothStreaming() && this.streamingTargetMessage) {
7675
7753
  let opts = this.getSmoothStreamingOptions(), total = countMessageGraphemes(this.streamingTargetMessage, opts);
7676
7754
  this.streamingDisplayedLength > total && (this.streamingDisplayedLength = total), this.paintSmoothStreamingFrame(), this.streamingDisplayedLength < total && this.startSmoothStreaming();
@@ -7787,7 +7865,7 @@ Pi will resume when the editor exits.
7787
7865
  return !!extensionRunner.getCommand(commandName);
7788
7866
  }
7789
7867
  renderCompactionResult(result) {
7790
- this.chatContainer.clear(), this.rebuildChatFromMessages(), this.addMessageToChat(createCompactionSummaryMessage(result.summary, result.tokensBefore, (/* @__PURE__ */ new Date()).toISOString())), this.footer.invalidate();
7868
+ this.rebuildChatFromMessages(), this.addMessageToChat(createCompactionSummaryMessage(result.summary, result.tokensBefore, (/* @__PURE__ */ new Date()).toISOString())), this.footer.invalidate();
7791
7869
  }
7792
7870
  async flushCompactionQueue(options) {
7793
7871
  if (this.compactionQueuedMessages.length === 0)
@@ -7866,6 +7944,7 @@ Pi will resume when the editor exits.
7866
7944
  availableThemes: getAvailableThemes(),
7867
7945
  hideThinkingBlock: this.hideThinkingBlock,
7868
7946
  thinkingCollapse: this.thinkingCollapse,
7947
+ reasoningDisplay: this.settingsManager.getReasoningDisplay(),
7869
7948
  cacheRetention: this.settingsManager.getCacheRetention() ?? "short",
7870
7949
  doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
7871
7950
  treeFilterMode: this.settingsManager.getTreeFilterMode(),
@@ -7960,13 +8039,19 @@ Pi will resume when the editor exits.
7960
8039
  this.hideThinkingBlock = hidden, this.settingsManager.setHideThinkingBlock(hidden);
7961
8040
  for (let child of this.chatContainer.children)
7962
8041
  child instanceof AssistantMessageComponent && child.setHideThinkingBlock(hidden);
7963
- this.chatContainer.clear(), this.rebuildChatFromMessages();
8042
+ this.rebuildChatFromMessages();
7964
8043
  },
7965
8044
  onThinkingCollapseChange: (collapse) => {
7966
8045
  this.thinkingCollapse = collapse, this.settingsManager.setThinkingCollapse(collapse);
7967
8046
  for (let child of this.chatContainer.children)
7968
8047
  child instanceof AssistantMessageComponent && child.setThinkingCollapse(collapse);
7969
- this.chatContainer.clear(), this.rebuildChatFromMessages();
8048
+ this.rebuildChatFromMessages();
8049
+ },
8050
+ onReasoningDisplayChange: (display) => {
8051
+ this.settingsManager.setReasoningDisplay(display);
8052
+ for (let child of this.chatContainer.children)
8053
+ child instanceof AssistantMessageComponent && child.setReasoningDisplay(this.settingsManager.getReasoningDisplay());
8054
+ this.ui.requestRender();
7970
8055
  },
7971
8056
  onShowCacheMissNoticesChange: (shown) => {
7972
8057
  this.settingsManager.setShowCacheMissNotices(shown), this.rebuildChatFromMessages();
@@ -8514,7 +8599,7 @@ Pi will resume when the editor exits.
8514
8599
  this.showStatus("Navigation cancelled");
8515
8600
  return;
8516
8601
  }
8517
- this.chatContainer.clear(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Navigated to selected point"), this.flushCompactionQueue({ willRetry: !1 });
8602
+ this.clearChatContainer(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Navigated to selected point"), this.flushCompactionQueue({ willRetry: !1 });
8518
8603
  } catch (error) {
8519
8604
  this.showError(error instanceof Error ? error.message : String(error));
8520
8605
  } finally {
@@ -9102,7 +9187,7 @@ ${INIT_EXISTING_FILE_INSTRUCTIONS.append}`;
9102
9187
  this.showStatus(command === "undo" ? "Undo cancelled" : "Edit cancelled");
9103
9188
  return;
9104
9189
  }
9105
- return leafId && this.redoStack.push(leafId), this.chatContainer.clear(), this.renderInitialMessages(), this.flushCompactionQueue({ willRetry: !1 }), { editorText: result.editorText, editorImages: result.editorImages };
9190
+ return leafId && this.redoStack.push(leafId), this.clearChatContainer(), this.renderInitialMessages(), this.flushCompactionQueue({ willRetry: !1 }), { editorText: result.editorText, editorImages: result.editorImages };
9106
9191
  } catch (error) {
9107
9192
  this.showError(error instanceof Error ? error.message : String(error));
9108
9193
  return;
@@ -9134,7 +9219,7 @@ ${INIT_EXISTING_FILE_INSTRUCTIONS.append}`;
9134
9219
  this.redoStack.push(targetId), this.showStatus("Navigation cancelled");
9135
9220
  return;
9136
9221
  }
9137
- this.chatContainer.clear(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Redone"), this.flushCompactionQueue({ willRetry: !1 });
9222
+ this.clearChatContainer(), this.renderInitialMessages(), result.editorText && !this.editor.getText().trim() && this.restoreEditorFromTreeResult(result), this.showStatus("Redone"), this.flushCompactionQueue({ willRetry: !1 });
9138
9223
  } catch (error) {
9139
9224
  this.showError(error instanceof Error ? error.message : String(error));
9140
9225
  }
@@ -9750,7 +9835,7 @@ ${toggleThinking ? `| \`${toggleThinking}\` | Toggle thinking block visibility |
9750
9835
  "",
9751
9836
  "=== All rendered lines with visible widths ===",
9752
9837
  ...allLines.map((line, idx) => {
9753
- let vw = visibleWidth4(line), escaped = JSON.stringify(line);
9838
+ let vw = visibleWidth6(line), escaped = JSON.stringify(line);
9754
9839
  return `[${idx}] (w=${vw}) ${escaped}`;
9755
9840
  }),
9756
9841
  "",
@@ -9803,7 +9888,7 @@ ${theme.fg("muted", debugLogPath)}`, 1, 1)), this.ui.requestRender();
9803
9888
  }
9804
9889
  }
9805
9890
  stop() {
9806
- this.stopCatalogRefresh?.(), this.stopCatalogRefresh = void 0, this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!1), this.clearStatusIndicator(), this.themeController.disableAutoSync(), this.clearExtensionTerminalInputListeners(), this.footer.dispose(), this.footerDataProvider.dispose(), this.unsubscribe && this.unsubscribe(), this.isInitialized && (this.ui.stop(), this.isInitialized = !1), this.unregisterSignalHandlers();
9891
+ this.setThinkingAnimation(!1), this.stopCatalogRefresh?.(), this.stopCatalogRefresh = void 0, this.settingsManager.getShowTerminalProgress() && this.ui.terminal.setProgress(!1), this.clearStatusIndicator(), this.themeController.disableAutoSync(), this.clearExtensionTerminalInputListeners(), this.footer.dispose(), this.footerDataProvider.dispose(), this.disposeChatToolComponents(), this.unsubscribe && this.unsubscribe(), this.isInitialized && (this.ui.stop(), this.isInitialized = !1), this.unregisterSignalHandlers();
9807
9892
  }
9808
9893
  };
9809
9894