@averyyy/pi-coding-agent 0.85.1-piclient.1 → 0.85.1-piclient.3

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.
@@ -254,6 +254,8 @@ export class InteractiveMode {
254
254
  // Agent subscription unsubscribe function
255
255
  unsubscribe;
256
256
  signalCleanupHandlers = [];
257
+ abortInputListenerCleanup;
258
+ abortingStatusActive = false;
257
259
  // Track if editor is in bash mode (text starts with !)
258
260
  isBashMode = false;
259
261
  // Track current bash execution component
@@ -296,6 +298,9 @@ export class InteractiveMode {
296
298
  get session() {
297
299
  return this.runtimeHost.session;
298
300
  }
301
+ get sessionAbortError() {
302
+ return this.session.abortError;
303
+ }
299
304
  get agent() {
300
305
  return this.session.agent;
301
306
  }
@@ -582,6 +587,7 @@ export class InteractiveMode {
582
587
  }
583
588
  this.renderer = nextUi;
584
589
  this.options.tuiMode = mode;
590
+ this.bindAbortInputListener();
585
591
  this.mountInteractiveTui(nextUi, components);
586
592
  nextUi.invalidate();
587
593
  nextUi.setFocus(focus);
@@ -648,6 +654,7 @@ export class InteractiveMode {
648
654
  this.ui.setFocus(this.editor);
649
655
  // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
650
656
  this.ui.start();
657
+ this.bindAbortInputListener();
651
658
  this.isInitialized = true;
652
659
  await this.themeController.applyFromSettings();
653
660
  // Add header with keybindings from config (unless silenced)
@@ -836,7 +843,7 @@ export class InteractiveMode {
836
843
  while (true) {
837
844
  const userInput = await this.getUserInput();
838
845
  try {
839
- await this.session.prompt(userInput);
846
+ await this.session.prompt(userInput, this.session.isStreaming || this.session.isAborting ? { streamingBehavior: "steer" } : undefined);
840
847
  }
841
848
  catch (error) {
842
849
  const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
@@ -1618,14 +1625,14 @@ export class InteractiveMode {
1618
1625
  this.footerDataProvider.setExtensionStatus(key, text);
1619
1626
  this.ui.requestRender();
1620
1627
  }
1621
- setEditorWorkingStatusIndicator(indicator) {
1622
- this.defaultEditor.setWorkingStatusIndicator(undefined);
1623
- if (!isWorkingStatusEditor(this.editor))
1624
- return false;
1625
- this.editor.setWorkingStatusIndicator(indicator);
1626
- return true;
1627
- }
1628
- showStatusIndicator(indicator) {
1628
+ showStatusIndicator(indicator, force = false) {
1629
+ if (this.session.isAborting && !force) {
1630
+ indicator.dispose();
1631
+ if (!this.abortingStatusActive) {
1632
+ this.showAbortingStatusIndicator();
1633
+ }
1634
+ return;
1635
+ }
1629
1636
  this.activeStatusIndicator?.dispose();
1630
1637
  this.activeStatusIndicator = indicator;
1631
1638
  this.activeWorkingIndicatorEmbedded = false;
@@ -1637,12 +1644,38 @@ export class InteractiveMode {
1637
1644
  }
1638
1645
  this.statusContainer.addChild(indicator);
1639
1646
  }
1640
- clearStatusIndicator(kind) {
1647
+ setEditorWorkingStatusIndicator(indicator) {
1648
+ this.defaultEditor.setWorkingStatusIndicator(undefined);
1649
+ if (!isWorkingStatusEditor(this.editor))
1650
+ return false;
1651
+ this.editor.setWorkingStatusIndicator(indicator);
1652
+ return true;
1653
+ }
1654
+ showAbortingStatusIndicator() {
1655
+ if (this.sessionAbortError) {
1656
+ this.showCancellationFailedStatusIndicator();
1657
+ return;
1658
+ }
1659
+ this.abortingStatusActive = true;
1660
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, "Aborting..."), true);
1661
+ this.ui.requestRender();
1662
+ }
1663
+ showCancellationFailedStatusIndicator() {
1664
+ this.abortingStatusActive = true;
1665
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, `Cancellation not confirmed (${keyText("app.interrupt")} to retry)`), true);
1666
+ this.ui.requestRender();
1667
+ }
1668
+ clearStatusIndicator(kind, force = false) {
1669
+ if (this.session.isAborting && !force) {
1670
+ this.showAbortingStatusIndicator();
1671
+ return;
1672
+ }
1641
1673
  if (kind && this.activeStatusIndicator?.kind !== kind) {
1642
1674
  return;
1643
1675
  }
1644
1676
  const clearedIndicator = this.activeStatusIndicator;
1645
1677
  const clearedIndicatorWasEmbedded = clearedIndicator?.kind === "working" && this.activeWorkingIndicatorEmbedded;
1678
+ this.abortingStatusActive = false;
1646
1679
  clearedIndicator?.dispose();
1647
1680
  this.activeStatusIndicator = undefined;
1648
1681
  this.activeWorkingIndicatorEmbedded = false;
@@ -1674,6 +1707,10 @@ export class InteractiveMode {
1674
1707
  }
1675
1708
  setWorkingVisible(visible) {
1676
1709
  this.workingVisible = visible;
1710
+ if (this.session.isAborting) {
1711
+ this.showAbortingStatusIndicator();
1712
+ return;
1713
+ }
1677
1714
  if (!visible) {
1678
1715
  this.clearStatusIndicator("working");
1679
1716
  this.ui.requestRender();
@@ -1684,6 +1721,22 @@ export class InteractiveMode {
1684
1721
  }
1685
1722
  this.ui.requestRender();
1686
1723
  }
1724
+ refreshStatusIndicator() {
1725
+ if (this.session.isAborting) {
1726
+ this.showAbortingStatusIndicator();
1727
+ return;
1728
+ }
1729
+ if (this.session.isStreaming) {
1730
+ if (this.workingVisible) {
1731
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1732
+ }
1733
+ else {
1734
+ this.clearStatusIndicator(undefined, true);
1735
+ }
1736
+ return;
1737
+ }
1738
+ this.clearStatusIndicator(undefined, true);
1739
+ }
1687
1740
  setWorkingIndicator(options) {
1688
1741
  this.workingIndicatorOptions = options;
1689
1742
  if (this.activeStatusIndicator?.kind === "working") {
@@ -1776,7 +1829,7 @@ export class InteractiveMode {
1776
1829
  this.workingMessage = undefined;
1777
1830
  this.workingVisible = true;
1778
1831
  this.setWorkingIndicator();
1779
- if (this.activeStatusIndicator?.kind === "working") {
1832
+ if (this.activeStatusIndicator?.kind === "working" && !this.session.isAborting) {
1780
1833
  this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
1781
1834
  }
1782
1835
  this.setHiddenThinkingLabel();
@@ -1884,6 +1937,23 @@ export class InteractiveMode {
1884
1937
  subscription.unsubscribe = this.ui.addInputListener(subscription.handler);
1885
1938
  }
1886
1939
  }
1940
+ /**
1941
+ * Keep repeated interrupts from reaching editors or extension input handlers
1942
+ * while the session is completing an abort. Other input remains available so
1943
+ * prompts submitted during this window can be queued by AgentSession.
1944
+ */
1945
+ bindAbortInputListener() {
1946
+ this.abortInputListenerCleanup?.();
1947
+ this.abortInputListenerCleanup = this.ui.addInputListener((data) => {
1948
+ if (this.session.isAborting && this.keybindings.matches(data, "app.interrupt")) {
1949
+ if (this.sessionAbortError) {
1950
+ this.requestAbort();
1951
+ }
1952
+ return { consume: true };
1953
+ }
1954
+ return undefined;
1955
+ });
1956
+ }
1887
1957
  clearExtensionTerminalInputListeners() {
1888
1958
  for (const subscription of this.extensionTerminalInputSubscriptions)
1889
1959
  subscription.unsubscribe();
@@ -1916,7 +1986,7 @@ export class InteractiveMode {
1916
1986
  setStatus: (key, text) => this.setExtensionStatus(key, text),
1917
1987
  setWorkingMessage: (message) => {
1918
1988
  this.workingMessage = message;
1919
- if (this.activeStatusIndicator?.kind === "working") {
1989
+ if (this.activeStatusIndicator?.kind === "working" && !this.session.isAborting) {
1920
1990
  this.activeStatusIndicator.setMessage(message ?? this.defaultWorkingMessage);
1921
1991
  }
1922
1992
  },
@@ -2259,10 +2329,31 @@ export class InteractiveMode {
2259
2329
  // =========================================================================
2260
2330
  // Key Handlers
2261
2331
  // =========================================================================
2332
+ requestAbort() {
2333
+ if (this.session.isAborting && !this.sessionAbortError) {
2334
+ return;
2335
+ }
2336
+ this.showAbortingStatusIndicator();
2337
+ void this.session.abort().catch((error) => {
2338
+ if (!this.sessionAbortError) {
2339
+ this.showAbortError(error instanceof Error ? error.message : String(error));
2340
+ }
2341
+ this.refreshStatusIndicator();
2342
+ });
2343
+ }
2344
+ showAbortError(message) {
2345
+ this.showError(`Cancellation not confirmed: ${message}. Press ${keyText("app.interrupt")} to retry.`);
2346
+ }
2262
2347
  setupKeyHandlers() {
2263
2348
  // Set up handlers on defaultEditor - they use this.editor for text access
2264
2349
  // so they work correctly regardless of which editor is active
2265
2350
  this.defaultEditor.onEscape = () => {
2351
+ if (this.session.isAborting) {
2352
+ if (this.sessionAbortError) {
2353
+ this.requestAbort();
2354
+ }
2355
+ return;
2356
+ }
2266
2357
  if (this.session.isStreaming) {
2267
2358
  this.restoreQueuedMessagesToEditor({ abort: true });
2268
2359
  }
@@ -2310,10 +2401,22 @@ export class InteractiveMode {
2310
2401
  this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
2311
2402
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2312
2403
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2313
- this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
2314
- this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
2315
- this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
2316
- this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
2404
+ this.defaultEditor.onAction("app.session.new", () => {
2405
+ if (!this.session.isAborting)
2406
+ void this.handleClearCommand();
2407
+ });
2408
+ this.defaultEditor.onAction("app.session.tree", () => {
2409
+ if (!this.session.isAborting)
2410
+ this.showTreeSelector();
2411
+ });
2412
+ this.defaultEditor.onAction("app.session.fork", () => {
2413
+ if (!this.session.isAborting)
2414
+ this.showUserMessageSelector();
2415
+ });
2416
+ this.defaultEditor.onAction("app.session.resume", () => {
2417
+ if (!this.session.isAborting)
2418
+ this.showSessionSelector();
2419
+ });
2317
2420
  this.defaultEditor.onChange = (text) => {
2318
2421
  const wasBashMode = this.isBashMode;
2319
2422
  this.isBashMode = text.trimStart().startsWith("!");
@@ -2370,11 +2473,37 @@ export class InteractiveMode {
2370
2473
  this.editor.setText(text);
2371
2474
  this.showStatus("Startup is still in progress");
2372
2475
  }
2476
+ async submitStreamingMessage(text, streamingBehavior) {
2477
+ this.editor.addToHistory?.(text);
2478
+ this.editor.setText("");
2479
+ try {
2480
+ await this.session.prompt(text, { streamingBehavior });
2481
+ this.updatePendingMessagesDisplay();
2482
+ this.ui.requestRender();
2483
+ }
2484
+ catch (error) {
2485
+ const currentText = this.editor.getText().trim();
2486
+ this.editor.setText([text, currentText].filter((value) => value.length > 0).join("\n\n"));
2487
+ this.showError(`Failed to queue message: ${error instanceof Error ? error.message : String(error)}`);
2488
+ }
2489
+ }
2373
2490
  setupEditorSubmitHandler() {
2374
2491
  this.defaultEditor.onSubmit = async (text) => {
2375
2492
  text = text.trim();
2376
2493
  if (!text)
2377
2494
  return;
2495
+ // AgentSession owns the post-abort queue. Ordinary prompts can be queued
2496
+ // while cancellation is in flight, but commands must wait so their TUI
2497
+ // semantics are not changed into provider prompt text.
2498
+ if (this.session.isAborting) {
2499
+ if (this.isInteractiveCommand(text)) {
2500
+ this.editor.setText(text);
2501
+ this.showStatus("Wait for cancellation to finish before running commands.");
2502
+ return;
2503
+ }
2504
+ await this.submitStreamingMessage(text, "steer");
2505
+ return;
2506
+ }
2378
2507
  // Handle commands
2379
2508
  if (text === "/settings") {
2380
2509
  this.showSettingsSelector();
@@ -2542,11 +2671,7 @@ export class InteractiveMode {
2542
2671
  // If streaming, use prompt() with steer behavior
2543
2672
  // This handles extension commands (execute immediately), prompt template expansion, and queueing
2544
2673
  if (this.session.isStreaming) {
2545
- this.editor.addToHistory?.(text);
2546
- this.editor.setText("");
2547
- await this.session.prompt(text, { streamingBehavior: "steer" });
2548
- this.updatePendingMessagesDisplay();
2549
- this.ui.requestRender();
2674
+ await this.submitStreamingMessage(text, "steer");
2550
2675
  return;
2551
2676
  }
2552
2677
  // Normal message submission
@@ -2580,21 +2705,47 @@ export class InteractiveMode {
2580
2705
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2581
2706
  this.retryEscapeHandler = undefined;
2582
2707
  }
2708
+ if (this.session.isAborting) {
2709
+ this.showAbortingStatusIndicator();
2710
+ }
2711
+ else if (this.workingVisible) {
2712
+ this.showWorkingStatusIndicator();
2713
+ }
2714
+ else {
2715
+ this.clearStatusIndicator();
2716
+ }
2717
+ this.ui.requestRender();
2583
2718
  break;
2584
2719
  case "turn_start":
2585
2720
  if (this.settingsManager.getShowTerminalProgress()) {
2586
2721
  this.ui.terminal.setProgress(true);
2587
2722
  }
2588
- if (this.workingVisible) {
2589
- if (this.activeStatusIndicator?.kind !== "working") {
2590
- this.showWorkingStatusIndicator();
2591
- }
2723
+ if (this.workingVisible && this.activeStatusIndicator?.kind !== "working") {
2724
+ this.showWorkingStatusIndicator();
2592
2725
  }
2593
- else {
2726
+ else if (!this.workingVisible) {
2594
2727
  this.clearStatusIndicator();
2595
2728
  }
2596
2729
  this.ui.requestRender();
2597
2730
  break;
2731
+ case "abort_start":
2732
+ this.showAbortingStatusIndicator();
2733
+ if (this.settingsManager.getShowTerminalProgress()) {
2734
+ this.ui.terminal.setProgress(true);
2735
+ }
2736
+ break;
2737
+ case "abort_error":
2738
+ this.showAbortError(event.errorMessage);
2739
+ this.showCancellationFailedStatusIndicator();
2740
+ this.ui.requestRender();
2741
+ break;
2742
+ case "abort_end":
2743
+ this.refreshStatusIndicator();
2744
+ if (!this.session.isStreaming && !this.session.isCompacting && !this.session.isRetrying) {
2745
+ this.ui.terminal.setProgress(false);
2746
+ }
2747
+ this.ui.requestRender();
2748
+ break;
2598
2749
  case "queue_update":
2599
2750
  this.updatePendingMessagesDisplay();
2600
2751
  this.ui.requestRender();
@@ -2744,10 +2895,18 @@ export class InteractiveMode {
2744
2895
  this.ui.requestRender();
2745
2896
  break;
2746
2897
  case "agent_settled":
2747
- if (this.settingsManager.getShowTerminalProgress()) {
2748
- this.ui.terminal.setProgress(false);
2898
+ if (this.session.isAborting) {
2899
+ this.showAbortingStatusIndicator();
2900
+ }
2901
+ else if (this.session.isStreaming) {
2902
+ this.refreshStatusIndicator();
2903
+ }
2904
+ else if (!this.session.isCompacting && !this.session.isRetrying) {
2905
+ if (this.settingsManager.getShowTerminalProgress()) {
2906
+ this.ui.terminal.setProgress(false);
2907
+ }
2908
+ this.clearStatusIndicator("working", true);
2749
2909
  }
2750
- this.clearStatusIndicator("working");
2751
2910
  await this.checkShutdownRequested();
2752
2911
  break;
2753
2912
  case "compaction_start": {
@@ -2757,7 +2916,7 @@ export class InteractiveMode {
2757
2916
  // Keep editor active; submissions are queued during compaction.
2758
2917
  this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
2759
2918
  this.defaultEditor.onEscape = () => {
2760
- this.session.abortCompaction();
2919
+ this.restoreQueuedMessagesToEditor({ abort: true });
2761
2920
  };
2762
2921
  this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
2763
2922
  this.ui.requestRender();
@@ -2807,8 +2966,15 @@ export class InteractiveMode {
2807
2966
  this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
2808
2967
  }
2809
2968
  }
2810
- this.restoreWorkingStatusIndicatorIfStreaming();
2811
- void this.flushCompactionQueue({ willRetry: event.willRetry });
2969
+ if (this.session.isAborting) {
2970
+ this.showAbortingStatusIndicator();
2971
+ }
2972
+ else if (this.session.isStreaming) {
2973
+ this.restoreWorkingStatusIndicatorIfStreaming();
2974
+ }
2975
+ if (!event.aborted && !this.session.isAborting) {
2976
+ void this.flushCompactionQueue({ willRetry: event.willRetry });
2977
+ }
2812
2978
  this.ui.requestRender();
2813
2979
  break;
2814
2980
  }
@@ -2816,7 +2982,7 @@ export class InteractiveMode {
2816
2982
  // Set up escape to abort retry
2817
2983
  this.retryEscapeHandler = this.defaultEditor.onEscape;
2818
2984
  this.defaultEditor.onEscape = () => {
2819
- this.session.abortRetry();
2985
+ this.restoreQueuedMessagesToEditor({ abort: true });
2820
2986
  };
2821
2987
  this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
2822
2988
  this.ui.requestRender();
@@ -2833,7 +2999,12 @@ export class InteractiveMode {
2833
2999
  if (!event.success) {
2834
3000
  this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
2835
3001
  }
2836
- this.restoreWorkingStatusIndicatorIfStreaming();
3002
+ if (this.session.isAborting) {
3003
+ this.showAbortingStatusIndicator();
3004
+ }
3005
+ else if (this.session.isStreaming) {
3006
+ this.restoreWorkingStatusIndicatorIfStreaming();
3007
+ }
2837
3008
  this.ui.requestRender();
2838
3009
  break;
2839
3010
  }
@@ -2856,6 +3027,9 @@ export class InteractiveMode {
2856
3027
  }
2857
3028
  case "summarization_retry_finished": {
2858
3029
  this.clearStatusIndicator("retry");
3030
+ if (this.session.isAborting) {
3031
+ this.showAbortingStatusIndicator();
3032
+ }
2859
3033
  this.ui.requestRender();
2860
3034
  break;
2861
3035
  }
@@ -3392,6 +3566,14 @@ export class InteractiveMode {
3392
3566
  const text = (this.editor.getExpandedText?.() ?? this.editor.getText()).trim();
3393
3567
  if (!text)
3394
3568
  return;
3569
+ if (this.session.isAborting) {
3570
+ if (this.isInteractiveCommand(text)) {
3571
+ this.showStatus("Wait for cancellation to finish before running commands.");
3572
+ return;
3573
+ }
3574
+ await this.submitStreamingMessage(text, "followUp");
3575
+ return;
3576
+ }
3395
3577
  // Queue input during compaction (extension commands execute immediately)
3396
3578
  if (this.session.isCompacting) {
3397
3579
  if (this.isExtensionCommand(text)) {
@@ -3407,16 +3589,12 @@ export class InteractiveMode {
3407
3589
  // Alt+Enter queues a follow-up message (waits until agent finishes)
3408
3590
  // This handles extension commands (execute immediately), prompt template expansion, and queueing
3409
3591
  if (this.session.isStreaming) {
3410
- this.editor.addToHistory?.(text);
3411
- this.editor.setText("");
3412
- await this.session.prompt(text, { streamingBehavior: "followUp" });
3413
- this.updatePendingMessagesDisplay();
3414
- this.ui.requestRender();
3592
+ await this.submitStreamingMessage(text, "followUp");
3415
3593
  }
3416
3594
  // If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit)
3417
3595
  else if (this.editor.onSubmit) {
3418
3596
  this.editor.setText("");
3419
- this.editor.onSubmit(text);
3597
+ await this.editor.onSubmit(text);
3420
3598
  }
3421
3599
  }
3422
3600
  handleDequeue() {
@@ -3627,12 +3805,15 @@ export class InteractiveMode {
3627
3805
  }
3628
3806
  }
3629
3807
  restoreQueuedMessagesToEditor(options) {
3808
+ if (options?.abort && this.session.isAborting) {
3809
+ return 0;
3810
+ }
3630
3811
  const { steering, followUp } = this.clearAllQueues();
3631
3812
  const allQueued = [...steering, ...followUp];
3632
3813
  if (allQueued.length === 0) {
3633
3814
  this.updatePendingMessagesDisplay();
3634
3815
  if (options?.abort) {
3635
- this.agent.abort();
3816
+ this.requestAbort();
3636
3817
  }
3637
3818
  return 0;
3638
3819
  }
@@ -3642,7 +3823,7 @@ export class InteractiveMode {
3642
3823
  this.editor.setText(combinedText);
3643
3824
  this.updatePendingMessagesDisplay();
3644
3825
  if (options?.abort) {
3645
- this.agent.abort();
3826
+ this.requestAbort();
3646
3827
  }
3647
3828
  return allQueued.length;
3648
3829
  }
@@ -3661,6 +3842,15 @@ export class InteractiveMode {
3661
3842
  const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
3662
3843
  return !!extensionRunner.getCommand(commandName);
3663
3844
  }
3845
+ isInteractiveCommand(text) {
3846
+ if (text.startsWith("!"))
3847
+ return true;
3848
+ if (!text.startsWith("/"))
3849
+ return false;
3850
+ const spaceIndex = text.indexOf(" ");
3851
+ const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
3852
+ return BUILTIN_SLASH_COMMANDS.some((command) => command.name === commandName) || this.isExtensionCommand(text);
3853
+ }
3664
3854
  async flushCompactionQueue(options) {
3665
3855
  if (this.compactionQueuedMessages.length === 0) {
3666
3856
  return;
@@ -4424,7 +4614,7 @@ export class InteractiveMode {
4424
4614
  const originalOnEscape = this.defaultEditor.onEscape;
4425
4615
  if (wantsSummary) {
4426
4616
  this.defaultEditor.onEscape = () => {
4427
- this.session.abortBranchSummary();
4617
+ this.restoreQueuedMessagesToEditor({ abort: true });
4428
4618
  };
4429
4619
  this.chatContainer.addChild(new Spacer(1));
4430
4620
  this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
@@ -5543,8 +5733,10 @@ export class InteractiveMode {
5543
5733
  if (this.settingsManager.getShowTerminalProgress()) {
5544
5734
  this.ui.terminal.setProgress(false);
5545
5735
  }
5546
- this.clearStatusIndicator();
5736
+ this.clearStatusIndicator(undefined, true);
5547
5737
  this.themeController.disableAutoSync();
5738
+ this.abortInputListenerCleanup?.();
5739
+ this.abortInputListenerCleanup = undefined;
5548
5740
  this.clearExtensionTerminalInputListeners();
5549
5741
  this.footer.dispose();
5550
5742
  this.footerDataProvider.dispose();