@astralyn/pi 0.81.1-1 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +690 -677
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts.map +1 -1
  7. package/dist/cli/config-selector.js +1 -1
  8. package/dist/cli/config-selector.js.map +1 -1
  9. package/dist/cli/startup-ui.d.ts.map +1 -1
  10. package/dist/cli/startup-ui.js +1 -1
  11. package/dist/cli/startup-ui.js.map +1 -1
  12. package/dist/cli.js +0 -0
  13. package/dist/core/agent-session.d.ts +11 -0
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +7 -8
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/compaction/compaction.d.ts.map +1 -1
  18. package/dist/core/compaction/compaction.js +11 -3
  19. package/dist/core/compaction/compaction.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts.map +1 -1
  21. package/dist/core/extensions/runner.js +4 -0
  22. package/dist/core/extensions/runner.js.map +1 -1
  23. package/dist/core/extensions/types.d.ts +9 -1
  24. package/dist/core/extensions/types.d.ts.map +1 -1
  25. package/dist/core/extensions/types.js.map +1 -1
  26. package/dist/core/model-config.d.ts +30 -0
  27. package/dist/core/model-config.d.ts.map +1 -1
  28. package/dist/core/model-config.js +6 -0
  29. package/dist/core/model-config.js.map +1 -1
  30. package/dist/core/model-registry.d.ts.map +1 -1
  31. package/dist/core/model-registry.js +2 -2
  32. package/dist/core/model-registry.js.map +1 -1
  33. package/dist/core/model-resolver.d.ts.map +1 -1
  34. package/dist/core/model-resolver.js +7 -0
  35. package/dist/core/model-resolver.js.map +1 -1
  36. package/dist/core/model-runtime.d.ts +0 -1
  37. package/dist/core/model-runtime.d.ts.map +1 -1
  38. package/dist/core/model-runtime.js +3 -5
  39. package/dist/core/model-runtime.js.map +1 -1
  40. package/dist/core/remote-catalog-provider.d.ts +1 -1
  41. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  42. package/dist/core/remote-catalog-provider.js +5 -10
  43. package/dist/core/remote-catalog-provider.js.map +1 -1
  44. package/dist/core/settings-manager.d.ts +1 -1
  45. package/dist/core/settings-manager.d.ts.map +1 -1
  46. package/dist/core/settings-manager.js.map +1 -1
  47. package/dist/core/system-prompt.d.ts.map +1 -1
  48. package/dist/core/system-prompt.js +1 -1
  49. package/dist/core/system-prompt.js.map +1 -1
  50. package/dist/core/tools/bash.d.ts +2 -1
  51. package/dist/core/tools/bash.d.ts.map +1 -1
  52. package/dist/core/tools/bash.js +114 -24
  53. package/dist/core/tools/bash.js.map +1 -1
  54. package/dist/core/tools/find.d.ts.map +1 -1
  55. package/dist/core/tools/find.js +1 -0
  56. package/dist/core/tools/find.js.map +1 -1
  57. package/dist/core/tools/read.d.ts.map +1 -1
  58. package/dist/core/tools/read.js +4 -3
  59. package/dist/core/tools/read.js.map +1 -1
  60. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  61. package/dist/core/tools/tool-definition-wrapper.js +5 -1
  62. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  63. package/dist/extensions/index.d.ts.map +1 -1
  64. package/dist/extensions/index.js +2 -0
  65. package/dist/extensions/index.js.map +1 -1
  66. package/dist/extensions/llama/provider.d.ts.map +1 -1
  67. package/dist/extensions/llama/provider.js +1 -2
  68. package/dist/extensions/llama/provider.js.map +1 -1
  69. package/dist/extensions/subagent/activity.d.ts +16 -0
  70. package/dist/extensions/subagent/activity.d.ts.map +1 -0
  71. package/dist/extensions/subagent/activity.js +150 -0
  72. package/dist/extensions/subagent/activity.js.map +1 -0
  73. package/dist/extensions/subagent/agents.d.ts +7 -0
  74. package/dist/extensions/subagent/agents.d.ts.map +1 -0
  75. package/dist/extensions/subagent/agents.js +218 -0
  76. package/dist/extensions/subagent/agents.js.map +1 -0
  77. package/dist/extensions/subagent/constants.d.ts +22 -0
  78. package/dist/extensions/subagent/constants.d.ts.map +1 -0
  79. package/dist/extensions/subagent/constants.js +32 -0
  80. package/dist/extensions/subagent/constants.js.map +1 -0
  81. package/dist/extensions/subagent/index.d.ts +3 -0
  82. package/dist/extensions/subagent/index.d.ts.map +1 -0
  83. package/dist/extensions/subagent/index.js +249 -0
  84. package/dist/extensions/subagent/index.js.map +1 -0
  85. package/dist/extensions/subagent/picker.d.ts +31 -0
  86. package/dist/extensions/subagent/picker.d.ts.map +1 -0
  87. package/dist/extensions/subagent/picker.js +116 -0
  88. package/dist/extensions/subagent/picker.js.map +1 -0
  89. package/dist/extensions/subagent/render.d.ts +8 -0
  90. package/dist/extensions/subagent/render.d.ts.map +1 -0
  91. package/dist/extensions/subagent/render.js +322 -0
  92. package/dist/extensions/subagent/render.js.map +1 -0
  93. package/dist/extensions/subagent/resolve.d.ts +16 -0
  94. package/dist/extensions/subagent/resolve.d.ts.map +1 -0
  95. package/dist/extensions/subagent/resolve.js +103 -0
  96. package/dist/extensions/subagent/resolve.js.map +1 -0
  97. package/dist/extensions/subagent/runner.d.ts +30 -0
  98. package/dist/extensions/subagent/runner.d.ts.map +1 -0
  99. package/dist/extensions/subagent/runner.js +355 -0
  100. package/dist/extensions/subagent/runner.js.map +1 -0
  101. package/dist/extensions/subagent/schema.d.ts +28 -0
  102. package/dist/extensions/subagent/schema.d.ts.map +1 -0
  103. package/dist/extensions/subagent/schema.js +33 -0
  104. package/dist/extensions/subagent/schema.js.map +1 -0
  105. package/dist/extensions/subagent/sdk-runner.d.ts +14 -0
  106. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -0
  107. package/dist/extensions/subagent/sdk-runner.js +210 -0
  108. package/dist/extensions/subagent/sdk-runner.js.map +1 -0
  109. package/dist/extensions/subagent/settings.d.ts +9 -0
  110. package/dist/extensions/subagent/settings.d.ts.map +1 -0
  111. package/dist/extensions/subagent/settings.js +131 -0
  112. package/dist/extensions/subagent/settings.js.map +1 -0
  113. package/dist/extensions/subagent/types.d.ts +99 -0
  114. package/dist/extensions/subagent/types.d.ts.map +1 -0
  115. package/dist/extensions/subagent/types.js +2 -0
  116. package/dist/extensions/subagent/types.js.map +1 -0
  117. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  118. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/extension-editor.js +16 -46
  120. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  121. package/dist/modes/interactive/components/index.d.ts +1 -0
  122. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  123. package/dist/modes/interactive/components/index.js +1 -0
  124. package/dist/modes/interactive/components/index.js.map +1 -1
  125. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  126. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  127. package/dist/modes/interactive/components/tool-execution.js +25 -4
  128. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  129. package/dist/modes/interactive/components/tool-group.d.ts +16 -0
  130. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -0
  131. package/dist/modes/interactive/components/tool-group.js +64 -0
  132. package/dist/modes/interactive/components/tool-group.js.map +1 -0
  133. package/dist/modes/interactive/external-editor.d.ts +12 -0
  134. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  135. package/dist/modes/interactive/external-editor.js +37 -0
  136. package/dist/modes/interactive/external-editor.js.map +1 -0
  137. package/dist/modes/interactive/interactive-mode.d.ts +3 -1
  138. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  139. package/dist/modes/interactive/interactive-mode.js +61 -62
  140. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  141. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  142. package/dist/modes/rpc/rpc-mode.js +1 -0
  143. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  144. package/dist/rpc-entry.js +0 -0
  145. package/dist/utils/clipboard.d.ts.map +1 -1
  146. package/dist/utils/clipboard.js +19 -8
  147. package/dist/utils/clipboard.js.map +1 -1
  148. package/dist/utils/version-check.d.ts.map +1 -1
  149. package/dist/utils/version-check.js +3 -1
  150. package/dist/utils/version-check.js.map +1 -1
  151. package/docs/compaction.md +401 -401
  152. package/docs/containerization.md +111 -111
  153. package/docs/custom-provider.md +766 -763
  154. package/docs/environment-variables.md +88 -0
  155. package/docs/extensions.md +2961 -2953
  156. package/docs/index.md +80 -77
  157. package/docs/models.md +6 -2
  158. package/docs/packages.md +228 -228
  159. package/docs/providers.md +8 -1
  160. package/docs/quickstart.md +165 -165
  161. package/docs/rpc.md +1576 -1559
  162. package/docs/sdk.md +1186 -1186
  163. package/docs/session-format.md +436 -436
  164. package/docs/settings.md +1 -1
  165. package/docs/termux.md +127 -127
  166. package/docs/tui.md +942 -942
  167. package/docs/usage.md +0 -13
  168. package/examples/extensions/README.md +213 -213
  169. package/examples/extensions/custom-compaction.ts +3 -0
  170. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  171. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  172. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  173. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  174. package/examples/extensions/doom-overlay/doom/build.sh +0 -0
  175. package/examples/extensions/gondolin/package-lock.json +2 -2
  176. package/examples/extensions/gondolin/package.json +1 -1
  177. package/examples/extensions/handoff.ts +9 -1
  178. package/examples/extensions/sandbox/package-lock.json +2 -2
  179. package/examples/extensions/sandbox/package.json +1 -1
  180. package/examples/extensions/summarize.ts +3 -0
  181. package/examples/extensions/with-deps/package-lock.json +2 -2
  182. package/examples/extensions/with-deps/package.json +1 -1
  183. package/examples/sdk/README.md +140 -140
  184. package/npm-shrinkwrap.json +16 -15
  185. package/package.json +10 -4
@@ -58,10 +58,12 @@ import { SettingsSelectorComponent } from "./components/settings-selector.js";
58
58
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
59
59
  import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
60
60
  import { ToolExecutionComponent } from "./components/tool-execution.js";
61
+ import { ToolGroupComponent } from "./components/tool-group.js";
61
62
  import { TreeSelectorComponent } from "./components/tree-selector.js";
62
63
  import { TrustSelectorComponent } from "./components/trust-selector.js";
63
64
  import { UserMessageComponent } from "./components/user-message.js";
64
65
  import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
66
+ import { editInExternalEditor } from "./external-editor.js";
65
67
  import { getModelSearchText } from "./model-search.js";
66
68
  import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
67
69
  import { InteractiveThemeController } from "./theme/theme-controller.js";
@@ -270,7 +272,7 @@ export class InteractiveMode {
270
272
  await this.rebindCurrentSession({ renderBeforeBind: true });
271
273
  });
272
274
  this.version = VERSION;
273
- this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
275
+ this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor(), getAgentDir());
274
276
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
275
277
  this.headerContainer = new Container();
276
278
  this.loadedResourcesContainer = new Container();
@@ -777,8 +779,15 @@ export class InteractiveMode {
777
779
  * Get a short path relative to the package root for display.
778
780
  */
779
781
  getShortPath(fullPath, sourceInfo) {
782
+ const normalizedFullPath = fullPath.replace(/\\/g, "/");
780
783
  const baseDir = sourceInfo?.baseDir;
781
784
  if (baseDir && this.isPackageSource(sourceInfo)) {
785
+ const normalizedBaseDir = baseDir.replace(/\\/g, "/");
786
+ const npmRootMatch = normalizedBaseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
787
+ // If fullPath is under the same node_modules root as baseDir, preserve that relative topology.
788
+ if (npmRootMatch?.[1] && normalizedFullPath.startsWith(`${npmRootMatch[1]}/`)) {
789
+ return path.posix.relative(normalizedBaseDir, normalizedFullPath);
790
+ }
782
791
  const relativePath = path.relative(path.resolve(baseDir), path.resolve(fullPath));
783
792
  if (relativePath &&
784
793
  relativePath !== "." &&
@@ -789,11 +798,11 @@ export class InteractiveMode {
789
798
  }
790
799
  }
791
800
  const source = sourceInfo?.source ?? "";
792
- const npmMatch = fullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
801
+ const npmMatch = normalizedFullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
793
802
  if (npmMatch && source.startsWith("npm:")) {
794
803
  return npmMatch[2];
795
804
  }
796
- const gitMatch = fullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
805
+ const gitMatch = normalizedFullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
797
806
  if (gitMatch && source.startsWith("git:")) {
798
807
  return gitMatch[1];
799
808
  }
@@ -1317,6 +1326,34 @@ export class InteractiveMode {
1317
1326
  getRegisteredToolDefinition(toolName) {
1318
1327
  return this.session.getToolDefinition(toolName);
1319
1328
  }
1329
+ createToolExecutionComponent(toolName, toolCallId, args) {
1330
+ const component = new ToolExecutionComponent(toolName, toolCallId, args, {
1331
+ showImages: this.settingsManager.getShowImages(),
1332
+ imageWidthCells: this.settingsManager.getImageWidthCells(),
1333
+ }, this.getRegisteredToolDefinition(toolName), this.ui, this.sessionManager.getCwd());
1334
+ component.setExpanded(this.toolOutputExpanded);
1335
+ return component;
1336
+ }
1337
+ appendToolExecutionComponent(component) {
1338
+ const toolGroup = component.toolGroup?.trim();
1339
+ if (!toolGroup) {
1340
+ this.chatContainer.addChild(component);
1341
+ return;
1342
+ }
1343
+ const children = this.chatContainer.children;
1344
+ const lastChild = children[children.length - 1];
1345
+ if (lastChild instanceof ToolGroupComponent && lastChild.toolGroup === toolGroup) {
1346
+ lastChild.addTool(component);
1347
+ return;
1348
+ }
1349
+ if (lastChild instanceof ToolExecutionComponent && lastChild.toolGroup?.trim() === toolGroup) {
1350
+ const group = new ToolGroupComponent(toolGroup, [lastChild, component]);
1351
+ group.setExpanded(this.toolOutputExpanded);
1352
+ children[children.length - 1] = group;
1353
+ return;
1354
+ }
1355
+ this.chatContainer.addChild(component);
1356
+ }
1320
1357
  /**
1321
1358
  * Set up keyboard shortcuts registered by extensions.
1322
1359
  */
@@ -1333,6 +1370,7 @@ export class InteractiveMode {
1333
1370
  sessionManager: this.sessionManager,
1334
1371
  modelRegistry: extensionRunner.getModelRegistry(),
1335
1372
  model: this.session.model,
1373
+ thinkingLevel: this.session.thinkingLevel,
1336
1374
  isIdle: () => this.session.isIdle,
1337
1375
  isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
1338
1376
  signal: this.session.agent.signal,
@@ -2018,7 +2056,7 @@ export class InteractiveMode {
2018
2056
  this.defaultEditor.onAction("app.model.select", () => this.showModelSelector());
2019
2057
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2020
2058
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2021
- this.defaultEditor.onAction("app.editor.external", () => this.openExternalEditor());
2059
+ this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
2022
2060
  this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
2023
2061
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2024
2062
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
@@ -2321,12 +2359,8 @@ export class InteractiveMode {
2321
2359
  for (const content of this.streamingMessage.content) {
2322
2360
  if (content.type === "toolCall") {
2323
2361
  if (!this.pendingTools.has(content.id)) {
2324
- const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
2325
- showImages: this.settingsManager.getShowImages(),
2326
- imageWidthCells: this.settingsManager.getImageWidthCells(),
2327
- }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
2328
- component.setExpanded(this.toolOutputExpanded);
2329
- this.chatContainer.addChild(component);
2362
+ const component = this.createToolExecutionComponent(content.name, content.id, content.arguments);
2363
+ this.appendToolExecutionComponent(component);
2330
2364
  this.pendingTools.set(content.id, component);
2331
2365
  }
2332
2366
  else {
@@ -2380,15 +2414,14 @@ export class InteractiveMode {
2380
2414
  }
2381
2415
  this.ui.requestRender();
2382
2416
  break;
2417
+ case "bash_execution_update":
2418
+ // The bash execution callback handles TUI output rendering.
2419
+ break;
2383
2420
  case "tool_execution_start": {
2384
2421
  let component = this.pendingTools.get(event.toolCallId);
2385
2422
  if (!component) {
2386
- component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
2387
- showImages: this.settingsManager.getShowImages(),
2388
- imageWidthCells: this.settingsManager.getImageWidthCells(),
2389
- }, this.getRegisteredToolDefinition(event.toolName), this.ui, this.sessionManager.getCwd());
2390
- component.setExpanded(this.toolOutputExpanded);
2391
- this.chatContainer.addChild(component);
2423
+ component = this.createToolExecutionComponent(event.toolName, event.toolCallId, event.args);
2424
+ this.appendToolExecutionComponent(component);
2392
2425
  this.pendingTools.set(event.toolCallId, component);
2393
2426
  }
2394
2427
  component.markExecutionStarted();
@@ -2677,12 +2710,8 @@ export class InteractiveMode {
2677
2710
  // Render tool call components
2678
2711
  for (const content of message.content) {
2679
2712
  if (content.type === "toolCall") {
2680
- const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
2681
- showImages: this.settingsManager.getShowImages(),
2682
- imageWidthCells: this.settingsManager.getImageWidthCells(),
2683
- }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
2684
- component.setExpanded(this.toolOutputExpanded);
2685
- this.chatContainer.addChild(component);
2713
+ const component = this.createToolExecutionComponent(content.name, content.id, content.arguments);
2714
+ this.appendToolExecutionComponent(component);
2686
2715
  if (message.stopReason === "aborted" || message.stopReason === "error") {
2687
2716
  let errorMessage;
2688
2717
  if (message.stopReason === "aborted") {
@@ -3102,51 +3131,21 @@ export class InteractiveMode {
3102
3131
  }
3103
3132
  this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
3104
3133
  }
3105
- async openExternalEditor() {
3134
+ async handleOpenExternalEditor() {
3106
3135
  const editorCmd = this.settingsManager.getExternalEditorCommand();
3107
- if (!editorCmd) {
3108
- this.showWarning("No editor configured. Set externalEditor in settings.json or $VISUAL/$EDITOR.");
3109
- return;
3110
- }
3111
- const currentText = this.editor.getExpandedText?.() ?? this.editor.getText();
3112
- const tmpFile = path.join(os.tmpdir(), `pi-editor-${Date.now()}.pi.md`);
3136
+ const content = this.editor.getExpandedText?.() ?? this.editor.getText();
3137
+ this.ui.stop();
3113
3138
  try {
3114
- // Write current content to temp file
3115
- fs.writeFileSync(tmpFile, currentText, "utf-8");
3116
- // Stop TUI to release terminal
3117
- this.ui.stop();
3118
- // Split by space to support editor arguments (e.g., "code --wait")
3119
- const [editor, ...editorArgs] = editorCmd.split(" ");
3120
- process.stdout.write(`Launching external editor: ${editorCmd}\nPi will resume when the editor exits.\n`);
3121
- // Do not use spawnSync here. On Windows, synchronous child_process calls can keep
3122
- // Node/libuv's console input read active after ui.stop() pauses stdin, racing
3123
- // vim/nvim for the console input buffer until Ctrl+C cancels the pending read.
3124
- const status = await new Promise((resolve) => {
3125
- const child = spawn(editor, [...editorArgs, tmpFile], {
3126
- stdio: "inherit",
3127
- shell: process.platform === "win32",
3128
- });
3129
- child.on("error", () => resolve(null));
3130
- child.on("close", (code) => resolve(code));
3139
+ const result = await editInExternalEditor({
3140
+ command: editorCmd,
3141
+ content,
3131
3142
  });
3132
- // On successful exit (status 0), replace editor content
3133
- if (status === 0) {
3134
- const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
3135
- this.editor.setText(newContent);
3143
+ if (result.status === "complete") {
3144
+ this.editor.setText(result.content);
3136
3145
  }
3137
- // On non-zero exit, keep original text (no action needed)
3138
3146
  }
3139
3147
  finally {
3140
- // Clean up temp file
3141
- try {
3142
- fs.unlinkSync(tmpFile);
3143
- }
3144
- catch {
3145
- // Ignore cleanup errors
3146
- }
3147
- // Restart TUI
3148
3148
  this.ui.start();
3149
- // Force full re-render since external editor uses alternate screen
3150
3149
  this.ui.requestRender(true);
3151
3150
  }
3152
3151
  }
@@ -3422,7 +3421,7 @@ export class InteractiveMode {
3422
3421
  onShowImagesChange: (enabled) => {
3423
3422
  this.settingsManager.setShowImages(enabled);
3424
3423
  for (const child of this.chatContainer.children) {
3425
- if (child instanceof ToolExecutionComponent) {
3424
+ if (child instanceof ToolExecutionComponent || child instanceof ToolGroupComponent) {
3426
3425
  child.setShowImages(enabled);
3427
3426
  }
3428
3427
  }
@@ -3430,7 +3429,7 @@ export class InteractiveMode {
3430
3429
  onImageWidthCellsChange: (width) => {
3431
3430
  this.settingsManager.setImageWidthCells(width);
3432
3431
  for (const child of this.chatContainer.children) {
3433
- if (child instanceof ToolExecutionComponent) {
3432
+ if (child instanceof ToolExecutionComponent || child instanceof ToolGroupComponent) {
3434
3433
  child.setImageWidthCells(width);
3435
3434
  }
3436
3435
  }