@astralyn/pi 0.82.6 → 0.83.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 (263) hide show
  1. package/CHANGELOG.md +61 -5099
  2. package/README.md +12 -111
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -2
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/credential-print.d.ts +23 -0
  7. package/dist/cli/credential-print.d.ts.map +1 -0
  8. package/dist/cli/credential-print.js +116 -0
  9. package/dist/cli/credential-print.js.map +1 -0
  10. package/dist/cli/session-picker.d.ts.map +1 -1
  11. package/dist/cli/session-picker.js +11 -13
  12. package/dist/cli/session-picker.js.map +1 -1
  13. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  14. package/dist/core/agent-session-runtime.js +3 -0
  15. package/dist/core/agent-session-runtime.js.map +1 -1
  16. package/dist/core/agent-session.d.ts +1 -1
  17. package/dist/core/agent-session.d.ts.map +1 -1
  18. package/dist/core/agent-session.js +13 -6
  19. package/dist/core/agent-session.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts +1 -0
  21. package/dist/core/extensions/runner.d.ts.map +1 -1
  22. package/dist/core/extensions/runner.js +7 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +11 -0
  25. package/dist/core/extensions/types.d.ts.map +1 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/footer-data-provider.d.ts +10 -0
  28. package/dist/core/footer-data-provider.d.ts.map +1 -1
  29. package/dist/core/footer-data-provider.js +1 -1
  30. package/dist/core/footer-data-provider.js.map +1 -1
  31. package/dist/core/model-runtime.d.ts +2 -0
  32. package/dist/core/model-runtime.d.ts.map +1 -1
  33. package/dist/core/model-runtime.js.map +1 -1
  34. package/dist/core/package-manager.d.ts.map +1 -1
  35. package/dist/core/package-manager.js +13 -6
  36. package/dist/core/package-manager.js.map +1 -1
  37. package/dist/core/resource-loader.d.ts +15 -0
  38. package/dist/core/resource-loader.d.ts.map +1 -1
  39. package/dist/core/resource-loader.js +70 -9
  40. package/dist/core/resource-loader.js.map +1 -1
  41. package/dist/core/session-manager.d.ts.map +1 -1
  42. package/dist/core/session-manager.js +2 -2
  43. package/dist/core/session-manager.js.map +1 -1
  44. package/dist/core/tools/bash.d.ts +1 -5
  45. package/dist/core/tools/bash.d.ts.map +1 -1
  46. package/dist/core/tools/bash.js +16 -41
  47. package/dist/core/tools/bash.js.map +1 -1
  48. package/dist/core/tools/edit.d.ts.map +1 -1
  49. package/dist/core/tools/edit.js +42 -11
  50. package/dist/core/tools/edit.js.map +1 -1
  51. package/dist/core/tools/find.d.ts.map +1 -1
  52. package/dist/core/tools/find.js +40 -11
  53. package/dist/core/tools/find.js.map +1 -1
  54. package/dist/core/tools/grep.d.ts.map +1 -1
  55. package/dist/core/tools/grep.js +17 -8
  56. package/dist/core/tools/grep.js.map +1 -1
  57. package/dist/core/tools/ls.d.ts.map +1 -1
  58. package/dist/core/tools/ls.js +3 -3
  59. package/dist/core/tools/ls.js.map +1 -1
  60. package/dist/core/tools/read.d.ts.map +1 -1
  61. package/dist/core/tools/read.js +4 -4
  62. package/dist/core/tools/read.js.map +1 -1
  63. package/dist/core/tools/render-utils.d.ts +7 -0
  64. package/dist/core/tools/render-utils.d.ts.map +1 -1
  65. package/dist/core/tools/render-utils.js +11 -0
  66. package/dist/core/tools/render-utils.js.map +1 -1
  67. package/dist/core/tools/write.d.ts.map +1 -1
  68. package/dist/core/tools/write.js +2 -3
  69. package/dist/core/tools/write.js.map +1 -1
  70. package/dist/core/trust-manager.d.ts.map +1 -1
  71. package/dist/core/trust-manager.js +48 -9
  72. package/dist/core/trust-manager.js.map +1 -1
  73. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  74. package/dist/extensions/deepwiki/render.js +34 -22
  75. package/dist/extensions/deepwiki/render.js.map +1 -1
  76. package/dist/extensions/index.d.ts.map +1 -1
  77. package/dist/extensions/index.js +0 -2
  78. package/dist/extensions/index.js.map +1 -1
  79. package/dist/extensions/llama/provider.d.ts.map +1 -1
  80. package/dist/extensions/llama/provider.js +1 -1
  81. package/dist/extensions/llama/provider.js.map +1 -1
  82. package/dist/extensions/question/dialog.d.ts.map +1 -1
  83. package/dist/extensions/question/dialog.js +29 -10
  84. package/dist/extensions/question/dialog.js.map +1 -1
  85. package/dist/extensions/question/index.d.ts.map +1 -1
  86. package/dist/extensions/question/index.js +7 -2
  87. package/dist/extensions/question/index.js.map +1 -1
  88. package/dist/extensions/question/render.d.ts +4 -8
  89. package/dist/extensions/question/render.d.ts.map +1 -1
  90. package/dist/extensions/question/render.js +202 -29
  91. package/dist/extensions/question/render.js.map +1 -1
  92. package/dist/extensions/question/results.d.ts.map +1 -1
  93. package/dist/extensions/question/results.js +1 -0
  94. package/dist/extensions/question/results.js.map +1 -1
  95. package/dist/extensions/question/schema.d.ts.map +1 -1
  96. package/dist/extensions/question/schema.js +2 -2
  97. package/dist/extensions/question/schema.js.map +1 -1
  98. package/dist/extensions/question/types.d.ts +1 -0
  99. package/dist/extensions/question/types.d.ts.map +1 -1
  100. package/dist/extensions/question/types.js +1 -1
  101. package/dist/extensions/question/types.js.map +1 -1
  102. package/dist/extensions/router/stream.d.ts +1 -0
  103. package/dist/extensions/router/stream.d.ts.map +1 -1
  104. package/dist/extensions/router/stream.js +44 -13
  105. package/dist/extensions/router/stream.js.map +1 -1
  106. package/dist/extensions/subagent/constants.d.ts +1 -0
  107. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  108. package/dist/extensions/subagent/constants.js +1 -0
  109. package/dist/extensions/subagent/constants.js.map +1 -1
  110. package/dist/extensions/subagent/index.d.ts.map +1 -1
  111. package/dist/extensions/subagent/index.js +2 -0
  112. package/dist/extensions/subagent/index.js.map +1 -1
  113. package/dist/extensions/subagent/render.d.ts.map +1 -1
  114. package/dist/extensions/subagent/render.js +121 -48
  115. package/dist/extensions/subagent/render.js.map +1 -1
  116. package/dist/extensions/subagent/retry.d.ts +17 -0
  117. package/dist/extensions/subagent/retry.d.ts.map +1 -0
  118. package/dist/extensions/subagent/retry.js +41 -0
  119. package/dist/extensions/subagent/retry.js.map +1 -0
  120. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  121. package/dist/extensions/subagent/runner.js +33 -5
  122. package/dist/extensions/subagent/runner.js.map +1 -1
  123. package/dist/extensions/subagent/sdk-runner.d.ts +6 -0
  124. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  125. package/dist/extensions/subagent/sdk-runner.js +46 -24
  126. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  127. package/dist/extensions/subagent/types.d.ts +7 -0
  128. package/dist/extensions/subagent/types.d.ts.map +1 -1
  129. package/dist/extensions/subagent/types.js.map +1 -1
  130. package/dist/extensions/todo/index.d.ts.map +1 -1
  131. package/dist/extensions/todo/index.js +1 -1
  132. package/dist/extensions/todo/index.js.map +1 -1
  133. package/dist/extensions/todo/state.d.ts.map +1 -1
  134. package/dist/extensions/todo/state.js +10 -2
  135. package/dist/extensions/todo/state.js.map +1 -1
  136. package/dist/extensions/todo/view.d.ts +1 -1
  137. package/dist/extensions/todo/view.d.ts.map +1 -1
  138. package/dist/extensions/todo/view.js +179 -34
  139. package/dist/extensions/todo/view.js.map +1 -1
  140. package/dist/main.d.ts.map +1 -1
  141. package/dist/main.js +43 -0
  142. package/dist/main.js.map +1 -1
  143. package/dist/migrations.d.ts.map +1 -1
  144. package/dist/migrations.js +2 -1
  145. package/dist/migrations.js.map +1 -1
  146. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  147. package/dist/modes/interactive/components/armin.js +5 -0
  148. package/dist/modes/interactive/components/armin.js.map +1 -1
  149. package/dist/modes/interactive/components/bash-execution.d.ts +1 -0
  150. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/bash-execution.js +4 -2
  152. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  153. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -6
  154. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  155. package/dist/modes/interactive/components/countdown-timer.js +54 -17
  156. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  157. package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
  158. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  159. package/dist/modes/interactive/components/extension-selector.js +10 -6
  160. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  161. package/dist/modes/interactive/components/keybinding-hints.d.ts +11 -1
  162. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/keybinding-hints.js +56 -0
  164. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  165. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/model-selector.js +4 -1
  167. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  168. package/dist/modes/interactive/components/session-selector.d.ts +3 -0
  169. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/session-selector.js +52 -2
  171. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
  173. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/tool-execution.js +133 -18
  175. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  176. package/dist/modes/interactive/components/tool-group.d.ts +1 -0
  177. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  178. package/dist/modes/interactive/components/tool-group.js +5 -0
  179. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  180. package/dist/modes/interactive/components/tree-selector.d.ts +10 -1
  181. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  182. package/dist/modes/interactive/components/tree-selector.js +55 -2
  183. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  184. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  185. package/dist/modes/interactive/external-editor.js +40 -3
  186. package/dist/modes/interactive/external-editor.js.map +1 -1
  187. package/dist/modes/interactive/interactive-mode.d.ts +5 -0
  188. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  189. package/dist/modes/interactive/interactive-mode.js +92 -24
  190. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  191. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  192. package/dist/modes/interactive/theme/theme.js +3 -2
  193. package/dist/modes/interactive/theme/theme.js.map +1 -1
  194. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  195. package/dist/modes/rpc/rpc-mode.js +13 -0
  196. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  197. package/dist/utils/paths.d.ts +5 -0
  198. package/dist/utils/paths.d.ts.map +1 -1
  199. package/dist/utils/paths.js +7 -0
  200. package/dist/utils/paths.js.map +1 -1
  201. package/docs/bundled/README.md +13 -15
  202. package/docs/bundled/extensions/deepwiki.md +1 -1
  203. package/docs/bundled/extensions/question.md +7 -5
  204. package/docs/bundled/extensions/router.md +3 -4
  205. package/docs/bundled/extensions/statusline.md +0 -1
  206. package/docs/bundled/extensions/subagent.md +4 -3
  207. package/docs/bundled/extensions/todo.md +1 -1
  208. package/docs/bundled/themes.md +1 -1
  209. package/docs/bundled/tool-presentation.md +17 -16
  210. package/docs/compaction.md +25 -30
  211. package/docs/custom-provider.md +298 -583
  212. package/docs/docs.json +0 -8
  213. package/docs/extensions.md +132 -121
  214. package/docs/index.md +18 -74
  215. package/docs/json.md +20 -14
  216. package/docs/models.md +193 -151
  217. package/docs/providers.md +2 -1
  218. package/docs/quickstart.md +3 -3
  219. package/docs/rpc.md +166 -124
  220. package/docs/sdk.md +119 -178
  221. package/docs/security.md +1 -1
  222. package/docs/session-format.md +139 -119
  223. package/docs/skills.md +0 -1
  224. package/docs/themes.md +2 -2
  225. package/docs/tui.md +411 -549
  226. package/docs/usage.md +3 -11
  227. package/examples/README.md +6 -1
  228. package/examples/extensions/README.md +13 -33
  229. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  230. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  231. package/examples/extensions/truncated-tool.ts +2 -2
  232. package/examples/sdk/12-full-control.ts +2 -0
  233. package/npm-shrinkwrap.json +25 -25
  234. package/package.json +5 -5
  235. package/dist/extensions/plan/constants.d.ts +0 -40
  236. package/dist/extensions/plan/constants.d.ts.map +0 -1
  237. package/dist/extensions/plan/constants.js +0 -69
  238. package/dist/extensions/plan/constants.js.map +0 -1
  239. package/dist/extensions/plan/index.d.ts +0 -3
  240. package/dist/extensions/plan/index.d.ts.map +0 -1
  241. package/dist/extensions/plan/index.js +0 -323
  242. package/dist/extensions/plan/index.js.map +0 -1
  243. package/dist/extensions/plan/schema.d.ts +0 -15
  244. package/dist/extensions/plan/schema.d.ts.map +0 -1
  245. package/dist/extensions/plan/schema.js +0 -13
  246. package/dist/extensions/plan/schema.js.map +0 -1
  247. package/dist/extensions/plan/state.d.ts +0 -29
  248. package/dist/extensions/plan/state.d.ts.map +0 -1
  249. package/dist/extensions/plan/state.js +0 -74
  250. package/dist/extensions/plan/state.js.map +0 -1
  251. package/dist/extensions/plan/storage.d.ts +0 -18
  252. package/dist/extensions/plan/storage.d.ts.map +0 -1
  253. package/dist/extensions/plan/storage.js +0 -58
  254. package/dist/extensions/plan/storage.js.map +0 -1
  255. package/dist/extensions/plan/view.d.ts +0 -36
  256. package/dist/extensions/plan/view.d.ts.map +0 -1
  257. package/dist/extensions/plan/view.js +0 -74
  258. package/dist/extensions/plan/view.js.map +0 -1
  259. package/docs/bundled/extensions/README.md +0 -19
  260. package/docs/bundled/extensions/plan.md +0 -33
  261. package/examples/extensions/plan-mode/README.md +0 -66
  262. package/examples/extensions/plan-mode/index.ts +0 -390
  263. package/examples/extensions/plan-mode/utils.ts +0 -168
@@ -186,6 +186,8 @@ export class InteractiveMode {
186
186
  onInputCallback;
187
187
  pendingUserInputs = [];
188
188
  activeStatusIndicator = undefined;
189
+ activeSelector = null;
190
+ activeSelectorCleanup = null;
189
191
  idleStatus = new IdleStatus();
190
192
  workingMessage = undefined;
191
193
  workingVisible = true;
@@ -1108,7 +1110,12 @@ export class InteractiveMode {
1108
1110
  }
1109
1111
  }
1110
1112
  if (showListing) {
1111
- const contextFiles = this.session.resourceLoader.getAgentsFiles().agentsFiles;
1113
+ const systemPromptSource = this.session.resourceLoader.getSystemPromptSource();
1114
+ const contextFiles = [
1115
+ ...(systemPromptSource ? [systemPromptSource] : []),
1116
+ ...this.session.resourceLoader.getAppendSystemPromptSources(),
1117
+ ...this.session.resourceLoader.getAgentsFiles().agentsFiles,
1118
+ ];
1112
1119
  if (contextFiles.length > 0) {
1113
1120
  this.loadedResourcesContainer.addChild(new Spacer(1));
1114
1121
  const contextList = contextFiles
@@ -1252,7 +1259,7 @@ export class InteractiveMode {
1252
1259
  if (result.cancelled) {
1253
1260
  return { cancelled: true };
1254
1261
  }
1255
- this.chatContainer.clear();
1262
+ this.clearChat();
1256
1263
  this.renderInitialMessages();
1257
1264
  if (result.editorText && !this.editor.getText().trim()) {
1258
1265
  this.editor.setText(result.editorText);
@@ -1308,16 +1315,19 @@ export class InteractiveMode {
1308
1315
  }
1309
1316
  }
1310
1317
  async rebindCurrentSession(options = {}) {
1318
+ const session = this.session;
1311
1319
  this.unsubscribe?.();
1312
1320
  this.unsubscribe = undefined;
1313
1321
  this.applyRuntimeSettings();
1314
1322
  if (options.renderBeforeBind) {
1315
1323
  this.renderCurrentSessionState();
1316
1324
  this.subscribeToAgent();
1317
- await this.bindCurrentSessionExtensions();
1318
1325
  }
1319
- else {
1320
- await this.bindCurrentSessionExtensions();
1326
+ await this.bindCurrentSessionExtensions();
1327
+ if (this.session !== session) {
1328
+ return;
1329
+ }
1330
+ if (!options.renderBeforeBind) {
1321
1331
  this.subscribeToAgent();
1322
1332
  }
1323
1333
  await this.updateAvailableProviderCount();
@@ -1331,14 +1341,34 @@ export class InteractiveMode {
1331
1341
  this.stop();
1332
1342
  process.exit(1);
1333
1343
  }
1344
+ disposeChatToolComponents() {
1345
+ for (const child of this.chatContainer.children) {
1346
+ if (child instanceof ToolExecutionComponent ||
1347
+ child instanceof ToolGroupComponent ||
1348
+ child instanceof ArminComponent ||
1349
+ child instanceof DaxnutsComponent) {
1350
+ child.dispose();
1351
+ }
1352
+ }
1353
+ }
1354
+ clearChat() {
1355
+ this.disposeChatToolComponents();
1356
+ this.chatContainer.clear();
1357
+ }
1358
+ clearPendingTools() {
1359
+ for (const component of this.pendingTools.values()) {
1360
+ component.dispose();
1361
+ }
1362
+ this.pendingTools.clear();
1363
+ }
1334
1364
  renderCurrentSessionState() {
1335
1365
  this.loadedResourcesContainer.clear();
1336
- this.chatContainer.clear();
1366
+ this.clearChat();
1337
1367
  this.pendingMessagesContainer.clear();
1338
1368
  this.compactionQueuedMessages = [];
1339
1369
  this.streamingComponent = undefined;
1340
1370
  this.streamingMessage = undefined;
1341
- this.pendingTools.clear();
1371
+ this.clearPendingTools();
1342
1372
  this.renderInitialMessages();
1343
1373
  }
1344
1374
  /**
@@ -1391,6 +1421,7 @@ export class InteractiveMode {
1391
1421
  sessionManager: this.sessionManager,
1392
1422
  modelRegistry: extensionRunner.getModelRegistry(),
1393
1423
  model: this.session.model,
1424
+ scopedModels: this.session.scopedModels,
1394
1425
  thinkingLevel: this.session.thinkingLevel,
1395
1426
  isIdle: () => this.session.isIdle,
1396
1427
  isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
@@ -2326,7 +2357,7 @@ export class InteractiveMode {
2326
2357
  case "agent_start":
2327
2358
  this.agentRunActive = true;
2328
2359
  this.coalescingTerminal.setScrollbackPreservation(true);
2329
- this.pendingTools.clear();
2360
+ this.clearPendingTools();
2330
2361
  if (this.settingsManager.getShowTerminalProgress()) {
2331
2362
  this.ui.terminal.setProgress(true);
2332
2363
  }
@@ -2495,7 +2526,7 @@ export class InteractiveMode {
2495
2526
  this.streamingComponent = undefined;
2496
2527
  this.streamingMessage = undefined;
2497
2528
  }
2498
- this.pendingTools.clear();
2529
+ this.clearPendingTools();
2499
2530
  this.ui.requestRender();
2500
2531
  break;
2501
2532
  case "agent_settled":
@@ -2537,7 +2568,7 @@ export class InteractiveMode {
2537
2568
  }
2538
2569
  else {
2539
2570
  if (event.result) {
2540
- this.chatContainer.clear();
2571
+ this.clearChat();
2541
2572
  this.rebuildChatFromMessages();
2542
2573
  this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
2543
2574
  this.footer.invalidate();
@@ -2733,7 +2764,7 @@ export class InteractiveMode {
2733
2764
  }
2734
2765
  }
2735
2766
  renderSessionItems(items, options = {}) {
2736
- this.pendingTools.clear();
2767
+ this.clearPendingTools();
2737
2768
  const renderedPendingTools = new Map();
2738
2769
  // Cache-miss notices are not persisted; re-derive them from the full entry
2739
2770
  // list and re-inject them after the assistant messages that paid for them.
@@ -2882,7 +2913,7 @@ export class InteractiveMode {
2882
2913
  });
2883
2914
  }
2884
2915
  rebuildChatFromMessages() {
2885
- this.chatContainer.clear();
2916
+ this.clearChat();
2886
2917
  this.renderSessionEntries(this.sessionManager.buildContextEntries());
2887
2918
  }
2888
2919
  // =========================================================================
@@ -3166,7 +3197,7 @@ export class InteractiveMode {
3166
3197
  }
3167
3198
  }
3168
3199
  }
3169
- this.ui.requestRender();
3200
+ this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
3170
3201
  }
3171
3202
  toggleThinkingBlockVisibility() {
3172
3203
  this.hideThinkingBlock = !this.hideThinkingBlock;
@@ -3174,7 +3205,7 @@ export class InteractiveMode {
3174
3205
  // Same reasoning as setToolsExpanded.
3175
3206
  this.coalescingTerminal.passNextFullRedraw();
3176
3207
  // Rebuild chat from session messages
3177
- this.chatContainer.clear();
3208
+ this.clearChat();
3178
3209
  this.rebuildChatFromMessages();
3179
3210
  // If streaming, re-add the streaming component with updated visibility and re-render
3180
3211
  if (this.streamingComponent && this.streamingMessage) {
@@ -3422,15 +3453,42 @@ export class InteractiveMode {
3422
3453
  * @param create Factory that receives a `done` callback and returns the component and focus target
3423
3454
  */
3424
3455
  showSelector(create) {
3456
+ this.activeSelectorCleanup?.();
3457
+ this.activeSelectorCleanup = null;
3458
+ this.activeSelector = null;
3459
+ let selector;
3460
+ let disposed = false;
3461
+ let closed = false;
3462
+ const dispose = () => {
3463
+ if (disposed || !selector)
3464
+ return;
3465
+ disposed = true;
3466
+ selector.dispose?.();
3467
+ };
3425
3468
  const done = () => {
3426
- this.editorContainer.clear();
3427
- this.editorContainer.addChild(this.editor);
3428
- this.ui.setFocus(this.editor);
3469
+ if (closed)
3470
+ return;
3471
+ closed = true;
3472
+ dispose();
3473
+ if (!selector || this.activeSelector === selector) {
3474
+ this.activeSelector = null;
3475
+ this.activeSelectorCleanup = null;
3476
+ this.editorContainer.clear();
3477
+ this.editorContainer.addChild(this.editor);
3478
+ this.ui.setFocus(this.editor);
3479
+ }
3429
3480
  };
3430
- const { component, focus } = create(done);
3481
+ const created = create(done);
3482
+ selector = created.component;
3483
+ if (closed) {
3484
+ dispose();
3485
+ return;
3486
+ }
3487
+ this.activeSelector = selector;
3488
+ this.activeSelectorCleanup = dispose;
3431
3489
  this.editorContainer.clear();
3432
- this.editorContainer.addChild(component);
3433
- this.ui.setFocus(focus);
3490
+ this.editorContainer.addChild(selector);
3491
+ this.ui.setFocus(created.focus);
3434
3492
  this.ui.requestRender();
3435
3493
  }
3436
3494
  showSettingsSelector() {
@@ -3530,7 +3588,7 @@ export class InteractiveMode {
3530
3588
  child.setHideThinkingBlock(hidden);
3531
3589
  }
3532
3590
  }
3533
- this.chatContainer.clear();
3591
+ this.clearChat();
3534
3592
  this.rebuildChatFromMessages();
3535
3593
  },
3536
3594
  onShowCacheMissNoticesChange: (shown) => {
@@ -3889,7 +3947,7 @@ export class InteractiveMode {
3889
3947
  this.showSelector((done) => {
3890
3948
  const selector = new TreeSelectorComponent(tree, realLeafId, this.ui.terminal.rows, async (entryId) => {
3891
3949
  // Selecting the current leaf is a no-op (already there)
3892
- if (entryId === realLeafId) {
3950
+ if (entryId === this.sessionManager.getLeafId()) {
3893
3951
  done();
3894
3952
  this.showStatus("Already at this point");
3895
3953
  return;
@@ -3924,6 +3982,11 @@ export class InteractiveMode {
3924
3982
  break;
3925
3983
  }
3926
3984
  }
3985
+ // The user committed to navigating: stop the active response first.
3986
+ if (this.session.isStreaming) {
3987
+ this.restoreQueuedMessagesToEditor();
3988
+ await this.session.abort();
3989
+ }
3927
3990
  // Set up escape handler and status indicator if summarizing
3928
3991
  let showingSummaryIndicator = false;
3929
3992
  const originalOnEscape = this.defaultEditor.onEscape;
@@ -3952,7 +4015,7 @@ export class InteractiveMode {
3952
4015
  return;
3953
4016
  }
3954
4017
  // Update UI
3955
- this.chatContainer.clear();
4018
+ this.clearChat();
3956
4019
  this.renderInitialMessages();
3957
4020
  if (result.editorText && !this.editor.getText().trim()) {
3958
4021
  this.editor.setText(result.editorText);
@@ -3975,7 +4038,7 @@ export class InteractiveMode {
3975
4038
  }, (entryId, label) => {
3976
4039
  this.sessionManager.appendLabelChange(entryId, label);
3977
4040
  this.ui.requestRender();
3978
- }, initialSelectedId, initialFilterMode);
4041
+ }, initialSelectedId, initialFilterMode, () => this.ui.requestRender());
3979
4042
  selector.onCopy = async (text) => {
3980
4043
  if (!text) {
3981
4044
  this.showError("Selected entry has no text to copy");
@@ -5082,12 +5145,17 @@ export class InteractiveMode {
5082
5145
  }
5083
5146
  }
5084
5147
  stop() {
5148
+ this.activeSelectorCleanup?.();
5149
+ this.activeSelectorCleanup = null;
5150
+ this.activeSelector = null;
5085
5151
  if (this.settingsManager.getShowTerminalProgress()) {
5086
5152
  this.ui.terminal.setProgress(false);
5087
5153
  }
5088
5154
  this.clearStatusIndicator();
5089
5155
  this.themeController.disableAutoSync();
5090
5156
  this.clearExtensionTerminalInputListeners();
5157
+ this.clearPendingTools();
5158
+ this.disposeChatToolComponents();
5091
5159
  this.footer.dispose();
5092
5160
  this.footerDataProvider.dispose();
5093
5161
  if (this.unsubscribe) {