@earendil-works/pi-coding-agent 0.84.1 → 0.84.2

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 (137) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +1 -0
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +11 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/auth-command.d.ts.map +1 -1
  8. package/dist/cli/auth-command.js +5 -4
  9. package/dist/cli/auth-command.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +7 -2
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +6 -6
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/experimental.d.ts +4 -0
  15. package/dist/core/experimental.d.ts.map +1 -1
  16. package/dist/core/experimental.js +4 -0
  17. package/dist/core/experimental.js.map +1 -1
  18. package/dist/core/extensions/types.d.ts +4 -0
  19. package/dist/core/extensions/types.d.ts.map +1 -1
  20. package/dist/core/extensions/types.js.map +1 -1
  21. package/dist/core/keybindings.d.ts +24 -0
  22. package/dist/core/keybindings.d.ts.map +1 -1
  23. package/dist/core/model-config.d.ts +5 -0
  24. package/dist/core/model-config.d.ts.map +1 -1
  25. package/dist/core/model-config.js +1 -0
  26. package/dist/core/model-config.js.map +1 -1
  27. package/dist/core/project-trust.d.ts.map +1 -1
  28. package/dist/core/project-trust.js +2 -2
  29. package/dist/core/project-trust.js.map +1 -1
  30. package/dist/core/sdk.d.ts +5 -3
  31. package/dist/core/sdk.d.ts.map +1 -1
  32. package/dist/core/sdk.js +2 -1
  33. package/dist/core/sdk.js.map +1 -1
  34. package/dist/core/session-manager.d.ts.map +1 -1
  35. package/dist/core/session-manager.js +2 -2
  36. package/dist/core/session-manager.js.map +1 -1
  37. package/dist/core/settings-manager.d.ts +6 -0
  38. package/dist/core/settings-manager.d.ts.map +1 -1
  39. package/dist/core/settings-manager.js +12 -0
  40. package/dist/core/settings-manager.js.map +1 -1
  41. package/dist/core/system-prompt.d.ts.map +1 -1
  42. package/dist/core/system-prompt.js +1 -1
  43. package/dist/core/system-prompt.js.map +1 -1
  44. package/dist/core/tools/bash.d.ts.map +1 -1
  45. package/dist/core/tools/bash.js +2 -0
  46. package/dist/core/tools/bash.js.map +1 -1
  47. package/dist/core/tools/edit.d.ts.map +1 -1
  48. package/dist/core/tools/edit.js +2 -0
  49. package/dist/core/tools/edit.js.map +1 -1
  50. package/dist/core/tools/find.d.ts.map +1 -1
  51. package/dist/core/tools/find.js +1 -1
  52. package/dist/core/tools/find.js.map +1 -1
  53. package/dist/core/tools/grep.d.ts.map +1 -1
  54. package/dist/core/tools/grep.js +1 -1
  55. package/dist/core/tools/grep.js.map +1 -1
  56. package/dist/core/tools/read.d.ts.map +1 -1
  57. package/dist/core/tools/read.js +2 -0
  58. package/dist/core/tools/read.js.map +1 -1
  59. package/dist/core/tools/write.d.ts.map +1 -1
  60. package/dist/core/tools/write.js +2 -0
  61. package/dist/core/tools/write.js.map +1 -1
  62. package/dist/index.d.ts +1 -1
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/main.d.ts.map +1 -1
  66. package/dist/main.js +5 -1
  67. package/dist/main.js.map +1 -1
  68. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  69. package/dist/modes/interactive/components/model-selector.js +2 -1
  70. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  71. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  72. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  73. package/dist/modes/interactive/components/settings-selector.js +10 -0
  74. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  75. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  76. package/dist/modes/interactive/components/tool-execution.js +10 -1
  77. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  78. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  79. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  80. package/dist/modes/interactive/interactive-mode.js +76 -25
  81. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  82. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  83. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  84. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  85. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  86. package/dist/modes/interactive/theme/dark.json +2 -0
  87. package/dist/modes/interactive/theme/light.json +2 -0
  88. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  89. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  90. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  91. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  92. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  93. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  94. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  95. package/dist/modes/interactive/theme/theme.js +12 -2
  96. package/dist/modes/interactive/theme/theme.js.map +1 -1
  97. package/dist/modes/json-event.d.ts +4 -1
  98. package/dist/modes/json-event.d.ts.map +1 -1
  99. package/dist/modes/json-event.js +5 -2
  100. package/dist/modes/json-event.js.map +1 -1
  101. package/dist/package-manager-cli.d.ts.map +1 -1
  102. package/dist/package-manager-cli.js +1 -1
  103. package/dist/package-manager-cli.js.map +1 -1
  104. package/dist/server/create-harness.d.ts.map +1 -1
  105. package/dist/server/create-harness.js +2 -0
  106. package/dist/server/create-harness.js.map +1 -1
  107. package/dist/utils/tools-manager.d.ts +10 -1
  108. package/dist/utils/tools-manager.d.ts.map +1 -1
  109. package/dist/utils/tools-manager.js +14 -19
  110. package/dist/utils/tools-manager.js.map +1 -1
  111. package/docs/compaction.md +6 -6
  112. package/docs/custom-provider.md +1 -1
  113. package/docs/environment-variables.md +8 -2
  114. package/docs/extensions.md +4 -0
  115. package/docs/json.md +6 -4
  116. package/docs/keybindings.md +8 -2
  117. package/docs/rpc.md +15 -4
  118. package/docs/sdk.md +9 -0
  119. package/docs/settings.md +31 -0
  120. package/docs/terminal-setup.md +23 -2
  121. package/docs/themes.md +24 -3
  122. package/docs/tui.md +2 -2
  123. package/docs/usage.md +3 -2
  124. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  125. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  126. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  127. package/examples/extensions/gondolin/package-lock.json +2 -2
  128. package/examples/extensions/gondolin/package.json +1 -1
  129. package/examples/extensions/sandbox/package-lock.json +2 -2
  130. package/examples/extensions/sandbox/package.json +1 -1
  131. package/examples/extensions/subagent/README.md +2 -0
  132. package/examples/extensions/subagent/agents.ts +40 -9
  133. package/examples/extensions/subagent/index.ts +21 -3
  134. package/examples/extensions/with-deps/package-lock.json +2 -2
  135. package/examples/extensions/with-deps/package.json +1 -1
  136. package/npm-shrinkwrap.json +27 -78
  137. package/package.json +6 -6
@@ -69,6 +69,7 @@ import { TrustSelectorComponent } from "./components/trust-selector.js";
69
69
  import { UserMessageComponent } from "./components/user-message.js";
70
70
  import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
71
71
  import { editInExternalEditor } from "./external-editor.js";
72
+ import { refreshModelCatalogs } from "./model-catalog-refresh.js";
72
73
  import { getModelSearchText } from "./model-search.js";
73
74
  import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
74
75
  import { InteractiveThemeController } from "./theme/theme-controller.js";
@@ -169,9 +170,21 @@ function formatLoginProviderCompletionDescription(provider) {
169
170
  export function createInteractiveTui(options) {
170
171
  const terminal = options.terminal ?? new ProcessTerminal();
171
172
  if (options.tuiMode === "fullscreen") {
173
+ const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
172
174
  return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
175
+ searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
176
+ searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
173
177
  openUrl: openBrowser,
174
178
  onRightClickPaste: options.onRightClickPaste,
179
+ copySelection: async (text) => {
180
+ try {
181
+ await copyToClipboard(text);
182
+ return true;
183
+ }
184
+ catch {
185
+ return false;
186
+ }
187
+ },
175
188
  });
176
189
  }
177
190
  return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
@@ -253,6 +266,7 @@ export class InteractiveMode {
253
266
  // Status line tracking (for mutating immediately-sequential status updates)
254
267
  lastStatusSpacer = undefined;
255
268
  lastStatusText = undefined;
269
+ managedToolStatusStarted = false;
256
270
  // Streaming message tracking
257
271
  streamingComponent = undefined;
258
272
  streamingMessage = undefined;
@@ -333,6 +347,7 @@ export class InteractiveMode {
333
347
  });
334
348
  this.runtimeHost.setRebindSession(async () => {
335
349
  await this.rebindCurrentSession({ renderBeforeBind: true });
350
+ await this.themeController.applyFromSettings();
336
351
  });
337
352
  this.version = VERSION;
338
353
  this.renderer = createInteractiveTui({
@@ -375,7 +390,12 @@ export class InteractiveMode {
375
390
  this.outputPad = this.settingsManager.getOutputPad();
376
391
  // Register themes from resource loader and initialize
377
392
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
378
- this.themeController = new InteractiveThemeController(this.ui, this.settingsManager, (message) => this.showError(message), () => this.updateEditorBorderColor());
393
+ this.themeController = new InteractiveThemeController(this.ui, {
394
+ getSettingsManager: () => this.settingsManager,
395
+ showError: (message) => this.showError(message),
396
+ onChanged: () => this.updateEditorBorderColor(),
397
+ initialThemeSetting: options.initialThemeSetting,
398
+ });
379
399
  }
380
400
  getAutocompleteSourceTag(sourceInfo) {
381
401
  if (!sourceInfo) {
@@ -538,14 +558,14 @@ export class InteractiveMode {
538
558
  tui.setLayoutRoot(this.fullscreenLayoutRoot);
539
559
  }
540
560
  }
541
- stopInteractiveTui() {
542
- if (this.renderer.mode === "fullscreen") {
561
+ stopInteractiveTui(fullscreenExitOutput) {
562
+ if (this.renderer.mode === "fullscreen" && fullscreenExitOutput === "transcript") {
543
563
  while (this.renderer.hasOverlayEntries)
544
564
  this.renderer.hideOverlay();
545
565
  this.switchTuiMode("regular", false, false);
546
566
  this.renderer.renderNow();
547
567
  }
548
- this.ui.stop();
568
+ this.ui.stop({ preserveScreen: this.renderer.mode === "fullscreen" });
549
569
  }
550
570
  switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
551
571
  const previousUi = this.renderer;
@@ -602,10 +622,6 @@ export class InteractiveMode {
602
622
  this.registerSignalHandlers();
603
623
  // Load changelog (only show new entries, skip for resumed sessions)
604
624
  this.changelogMarkdown = this.getChangelogForDisplay();
605
- // Ensure fd and rg are available (downloads if missing, adds to PATH via getBinDir)
606
- // Both are needed: fd for autocomplete, rg for grep tool and bash commands
607
- const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg")]);
608
- this.fdPath = fdPath;
609
625
  if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
610
626
  const modelList = this.session.scopedModels
611
627
  .map((sm) => {
@@ -649,9 +665,11 @@ export class InteractiveMode {
649
665
  this.widgetContainerBelow,
650
666
  this.footerContainer,
651
667
  ]);
668
+ // Accept text while startup completes, but only enable interrupt, exit, and submission feedback.
669
+ this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
670
+ this.defaultEditor.onCtrlD = () => this.handleCtrlD();
671
+ this.defaultEditor.onSubmit = (text) => this.handleStartupSubmit(text);
652
672
  this.ui.setFocus(this.editor);
653
- this.setupKeyHandlers();
654
- this.setupEditorSubmitHandler();
655
673
  // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
656
674
  this.ui.start();
657
675
  this.isInitialized = true;
@@ -703,6 +721,18 @@ export class InteractiveMode {
703
721
  this.headerContainer.addChild(this.builtInHeader);
704
722
  }
705
723
  this.ui.requestRender();
724
+ // Ensure fd and rg are available after mounting the TUI (downloads if missing, adds to PATH via getBinDir)
725
+ // so slow downloads do not make startup appear frozen.
726
+ // Both are needed: fd for autocomplete, rg for grep tool and bash commands.
727
+ const [fdPath] = await Promise.all([
728
+ ensureTool("fd", (status) => this.showManagedToolStatus(status)),
729
+ ensureTool("rg", (status) => this.showManagedToolStatus(status)),
730
+ ]);
731
+ this.fdPath = fdPath;
732
+ // Enable the remaining input handlers only after managed-tool setup completes.
733
+ this.setupKeyHandlers();
734
+ this.setupEditorSubmitHandler();
735
+ this.ui.requestRender();
706
736
  // Initialize extensions first so resources are shown before messages
707
737
  await this.rebindCurrentSession();
708
738
  // Render initial messages AFTER showing loaded resources
@@ -742,8 +772,7 @@ export class InteractiveMode {
742
772
  if (!process.env.PI_OFFLINE) {
743
773
  const controller = new AbortController();
744
774
  const timeout = setTimeout(() => controller.abort(), 15_000);
745
- void this.session.modelRuntime
746
- .refresh({ signal: controller.signal })
775
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
747
776
  .then(() => this.updateAvailableProviderCount())
748
777
  .catch(() => { })
749
778
  .finally(() => clearTimeout(timeout));
@@ -1499,7 +1528,7 @@ export class InteractiveMode {
1499
1528
  const message = error instanceof Error ? error.message : String(error);
1500
1529
  this.showError(`${prefix}: ${message}`);
1501
1530
  stopThemeWatcher();
1502
- this.stop();
1531
+ this.stop("transcript");
1503
1532
  process.exit(1);
1504
1533
  }
1505
1534
  renderCurrentSessionState() {
@@ -2291,6 +2320,10 @@ export class InteractiveMode {
2291
2320
  // Silently ignore clipboard errors (may not have permission, etc.)
2292
2321
  }
2293
2322
  }
2323
+ handleStartupSubmit(text) {
2324
+ this.editor.setText(text);
2325
+ this.showStatus("Startup is still in progress");
2326
+ }
2294
2327
  setupEditorSubmitHandler() {
2295
2328
  this.defaultEditor.onSubmit = async (text) => {
2296
2329
  text = text.trim();
@@ -2766,6 +2799,19 @@ export class InteractiveMode {
2766
2799
  : message.content.filter((c) => c.type === "text");
2767
2800
  return textBlocks.map((c) => c.text).join("");
2768
2801
  }
2802
+ /** Show a managed-tool status update in the chat. */
2803
+ showManagedToolStatus(status) {
2804
+ if (!this.managedToolStatusStarted) {
2805
+ this.chatContainer.addChild(new Spacer(1));
2806
+ this.managedToolStatusStarted = true;
2807
+ }
2808
+ const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
2809
+ const color = status.type === "warning" ? "warning" : "dim";
2810
+ this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
2811
+ this.lastStatusSpacer = undefined;
2812
+ this.lastStatusText = undefined;
2813
+ this.ui.requestRender();
2814
+ }
2769
2815
  /**
2770
2816
  * Show a status message in the chat.
2771
2817
  *
@@ -3137,7 +3183,7 @@ export class InteractiveMode {
3137
3183
  this.ui.stop();
3138
3184
  }
3139
3185
  catch { }
3140
- console.error("pi exiting due to uncaughtException:");
3186
+ console.error(`${APP_NAME} exiting due to uncaughtException:`);
3141
3187
  console.error(error);
3142
3188
  process.exit(1);
3143
3189
  }
@@ -3622,7 +3668,7 @@ export class InteractiveMode {
3622
3668
  httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
3623
3669
  thinkingLevel: this.session.thinkingLevel,
3624
3670
  availableThinkingLevels: this.session.getAvailableThinkingLevels(),
3625
- currentTheme: this.settingsManager.getThemeSetting() || "dark",
3671
+ currentTheme: this.themeController.getThemeSelection() || "dark",
3626
3672
  terminalTheme: this.themeController.getTerminalTheme(),
3627
3673
  availableThemes: getAvailableThemes(),
3628
3674
  hideThinkingBlock: this.hideThinkingBlock,
@@ -3641,6 +3687,7 @@ export class InteractiveMode {
3641
3687
  clearOnShrink: this.settingsManager.getClearOnShrink(),
3642
3688
  showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
3643
3689
  tuiMode: this.ui.mode,
3690
+ fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3644
3691
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
3645
3692
  warnings: this.settingsManager.getWarnings(),
3646
3693
  }, {
@@ -3696,7 +3743,7 @@ export class InteractiveMode {
3696
3743
  },
3697
3744
  onThemeChange: (themeSetting) => {
3698
3745
  this.settingsManager.setTheme(themeSetting);
3699
- void this.themeController.applyFromSettings();
3746
+ void this.themeController.setThemeSetting(themeSetting);
3700
3747
  },
3701
3748
  onThemePreview: (themeName) => this.themeController.preview(themeName),
3702
3749
  onHideThinkingBlockChange: (hidden) => {
@@ -3795,6 +3842,9 @@ export class InteractiveMode {
3795
3842
  this.statusContainer.clear();
3796
3843
  this.showStatus(`TUI mode: ${mode}`);
3797
3844
  },
3845
+ onFullscreenExitOutputChange: (output) => {
3846
+ this.settingsManager.setFullscreenExitOutput(output);
3847
+ },
3798
3848
  onFullscreenScrollbarChange: (mode) => {
3799
3849
  this.settingsManager.setFullscreenScrollbar(mode);
3800
3850
  this.applyFullscreenScrollbarSetting();
@@ -3847,7 +3897,7 @@ export class InteractiveMode {
3847
3897
  controller.abort();
3848
3898
  }, 15_000);
3849
3899
  try {
3850
- const result = await this.session.modelRuntime.refresh({ signal: controller.signal });
3900
+ const result = await refreshModelCatalogs(this.session.modelRuntime, controller.signal);
3851
3901
  if (result.aborted && timedOut) {
3852
3902
  this.showWarning("Model refresh timed out; searching cached models.");
3853
3903
  }
@@ -3935,7 +3985,7 @@ export class InteractiveMode {
3935
3985
  onSelect: (selection) => {
3936
3986
  trustStore.setMany(selection.updates);
3937
3987
  done();
3938
- this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart pi for this to take effect.`);
3988
+ this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart ${APP_NAME} for this to take effect.`);
3939
3989
  },
3940
3990
  onCancel: () => {
3941
3991
  done();
@@ -4035,8 +4085,7 @@ export class InteractiveMode {
4035
4085
  this.ui.requestRender();
4036
4086
  },
4037
4087
  });
4038
- void this.session.modelRuntime
4039
- .refresh({ signal: controller.signal })
4088
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
4040
4089
  .then((result) => {
4041
4090
  if (disposed)
4042
4091
  return;
@@ -4590,7 +4639,7 @@ export class InteractiveMode {
4590
4639
  this.ui.requestRender();
4591
4640
  };
4592
4641
  const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => restoreEditor(), providerOption.name, `${providerOption.name} setup`);
4593
- dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside pi.`, [], true);
4642
+ dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
4594
4643
  this.editorContainer.clear();
4595
4644
  this.editorContainer.addChild(dialog);
4596
4645
  this.ui.setFocus(dialog);
@@ -4827,7 +4876,9 @@ export class InteractiveMode {
4827
4876
  this.showStatus(`Session exported to: ${filePath}`);
4828
4877
  }
4829
4878
  else {
4830
- const filePath = await this.session.exportToHtml(outputPath);
4879
+ const filePath = await this.session.exportToHtml(outputPath, {
4880
+ themeName: theme.name,
4881
+ });
4831
4882
  this.showStatus(`Session exported to: ${filePath}`);
4832
4883
  }
4833
4884
  }
@@ -4918,7 +4969,7 @@ export class InteractiveMode {
4918
4969
  // Export to a temp file
4919
4970
  const tmpFile = path.join(os.tmpdir(), "session.html");
4920
4971
  try {
4921
- await this.session.exportToHtml(tmpFile);
4972
+ await this.session.exportToHtml(tmpFile, { themeName: theme.name });
4922
4973
  }
4923
4974
  catch (error) {
4924
4975
  this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -5364,7 +5415,7 @@ export class InteractiveMode {
5364
5415
  // Ignore, will be emitted as an event
5365
5416
  }
5366
5417
  }
5367
- stop() {
5418
+ stop(fullscreenExitOutput = this.settingsManager.getFullscreenExitOutput()) {
5368
5419
  this.disposeActiveSelector();
5369
5420
  if (this.settingsManager.getShowTerminalProgress()) {
5370
5421
  this.ui.terminal.setProgress(false);
@@ -5378,7 +5429,7 @@ export class InteractiveMode {
5378
5429
  this.unsubscribe();
5379
5430
  }
5380
5431
  if (this.isInitialized) {
5381
- this.stopInteractiveTui();
5432
+ this.stopInteractiveTui(fullscreenExitOutput);
5382
5433
  this.isInitialized = false;
5383
5434
  }
5384
5435
  this.unregisterSignalHandlers();