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

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 (136) hide show
  1. package/CHANGELOG.md +55 -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/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";
@@ -170,9 +171,21 @@ function formatLoginProviderCompletionDescription(provider) {
170
171
  export function createInteractiveTui(options) {
171
172
  const terminal = options.terminal ?? new ProcessTerminal();
172
173
  if (options.tuiMode === "fullscreen") {
174
+ const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
173
175
  return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
176
+ searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
177
+ searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
174
178
  openUrl: openBrowser,
175
179
  onRightClickPaste: options.onRightClickPaste,
180
+ copySelection: async (text) => {
181
+ try {
182
+ await copyToClipboard(text);
183
+ return true;
184
+ }
185
+ catch {
186
+ return false;
187
+ }
188
+ },
176
189
  });
177
190
  }
178
191
  return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
@@ -259,6 +272,7 @@ export class InteractiveMode {
259
272
  // Status line tracking (for mutating immediately-sequential status updates)
260
273
  lastStatusSpacer = undefined;
261
274
  lastStatusText = undefined;
275
+ managedToolStatusStarted = false;
262
276
  // Streaming message tracking
263
277
  streamingComponent = undefined;
264
278
  streamingMessage = undefined;
@@ -339,6 +353,7 @@ export class InteractiveMode {
339
353
  });
340
354
  this.runtimeHost.setRebindSession(async () => {
341
355
  await this.rebindCurrentSession({ renderBeforeBind: true });
356
+ await this.themeController.applyFromSettings();
342
357
  });
343
358
  this.version = VERSION;
344
359
  this.renderer = createInteractiveTui({
@@ -381,7 +396,12 @@ export class InteractiveMode {
381
396
  this.outputPad = this.settingsManager.getOutputPad();
382
397
  // Register themes from resource loader and initialize
383
398
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
384
- this.themeController = new InteractiveThemeController(this.ui, this.settingsManager, (message) => this.showError(message), () => this.updateEditorBorderColor());
399
+ this.themeController = new InteractiveThemeController(this.ui, {
400
+ getSettingsManager: () => this.settingsManager,
401
+ showError: (message) => this.showError(message),
402
+ onChanged: () => this.updateEditorBorderColor(),
403
+ initialThemeSetting: options.initialThemeSetting,
404
+ });
385
405
  }
386
406
  getAutocompleteSourceTag(sourceInfo) {
387
407
  if (!sourceInfo) {
@@ -544,14 +564,14 @@ export class InteractiveMode {
544
564
  tui.setLayoutRoot(this.fullscreenLayoutRoot);
545
565
  }
546
566
  }
547
- stopInteractiveTui() {
548
- if (this.renderer.mode === "fullscreen") {
567
+ stopInteractiveTui(fullscreenExitOutput) {
568
+ if (this.renderer.mode === "fullscreen" && fullscreenExitOutput === "transcript") {
549
569
  while (this.renderer.hasOverlayEntries)
550
570
  this.renderer.hideOverlay();
551
571
  this.switchTuiMode("regular", false, false);
552
572
  this.renderer.renderNow();
553
573
  }
554
- this.ui.stop();
574
+ this.ui.stop({ preserveScreen: this.renderer.mode === "fullscreen" });
555
575
  }
556
576
  switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
557
577
  const previousUi = this.renderer;
@@ -608,10 +628,6 @@ export class InteractiveMode {
608
628
  this.registerSignalHandlers();
609
629
  // Load changelog (only show new entries, skip for resumed sessions)
610
630
  this.changelogMarkdown = this.getChangelogForDisplay();
611
- // Ensure fd and rg are available (downloads if missing, adds to PATH via getBinDir)
612
- // Both are needed: fd for autocomplete, rg for grep tool and bash commands
613
- const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg")]);
614
- this.fdPath = fdPath;
615
631
  if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
616
632
  const modelList = this.session.scopedModels
617
633
  .map((sm) => {
@@ -656,9 +672,11 @@ export class InteractiveMode {
656
672
  this.widgetContainerBelow,
657
673
  this.footerContainer,
658
674
  ]);
675
+ // Accept text while startup completes, but only enable interrupt, exit, and submission feedback.
676
+ this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
677
+ this.defaultEditor.onCtrlD = () => this.handleCtrlD();
678
+ this.defaultEditor.onSubmit = (text) => this.handleStartupSubmit(text);
659
679
  this.ui.setFocus(this.editor);
660
- this.setupKeyHandlers();
661
- this.setupEditorSubmitHandler();
662
680
  // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
663
681
  this.ui.start();
664
682
  this.isInitialized = true;
@@ -710,6 +728,18 @@ export class InteractiveMode {
710
728
  this.headerContainer.addChild(this.builtInHeader);
711
729
  }
712
730
  this.ui.requestRender();
731
+ // Ensure fd and rg are available after mounting the TUI (downloads if missing, adds to PATH via getBinDir)
732
+ // so slow downloads do not make startup appear frozen.
733
+ // Both are needed: fd for autocomplete, rg for grep tool and bash commands.
734
+ const [fdPath] = await Promise.all([
735
+ ensureTool("fd", (status) => this.showManagedToolStatus(status)),
736
+ ensureTool("rg", (status) => this.showManagedToolStatus(status)),
737
+ ]);
738
+ this.fdPath = fdPath;
739
+ // Enable the remaining input handlers only after managed-tool setup completes.
740
+ this.setupKeyHandlers();
741
+ this.setupEditorSubmitHandler();
742
+ this.ui.requestRender();
713
743
  // Initialize extensions first so resources are shown before messages
714
744
  await this.rebindCurrentSession();
715
745
  // Render initial messages AFTER showing loaded resources
@@ -749,8 +779,7 @@ export class InteractiveMode {
749
779
  if (!process.env.PI_OFFLINE) {
750
780
  const controller = new AbortController();
751
781
  const timeout = setTimeout(() => controller.abort(), 15_000);
752
- void this.session.modelRuntime
753
- .refresh({ signal: controller.signal })
782
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
754
783
  .then(() => this.updateAvailableProviderCount())
755
784
  .catch(() => { })
756
785
  .finally(() => clearTimeout(timeout));
@@ -1507,7 +1536,7 @@ export class InteractiveMode {
1507
1536
  const message = error instanceof Error ? error.message : String(error);
1508
1537
  this.showError(`${prefix}: ${message}`);
1509
1538
  stopThemeWatcher();
1510
- this.stop();
1539
+ this.stop("transcript");
1511
1540
  process.exit(1);
1512
1541
  }
1513
1542
  renderCurrentSessionState() {
@@ -2309,6 +2338,10 @@ export class InteractiveMode {
2309
2338
  // Silently ignore clipboard errors (may not have permission, etc.)
2310
2339
  }
2311
2340
  }
2341
+ handleStartupSubmit(text) {
2342
+ this.editor.setText(text);
2343
+ this.showStatus("Startup is still in progress");
2344
+ }
2312
2345
  setupEditorSubmitHandler() {
2313
2346
  this.defaultEditor.onSubmit = async (text) => {
2314
2347
  text = text.trim();
@@ -2791,6 +2824,19 @@ export class InteractiveMode {
2791
2824
  : message.content.filter((c) => c.type === "text");
2792
2825
  return textBlocks.map((c) => c.text).join("");
2793
2826
  }
2827
+ /** Show a managed-tool status update in the chat. */
2828
+ showManagedToolStatus(status) {
2829
+ if (!this.managedToolStatusStarted) {
2830
+ this.chatContainer.addChild(new Spacer(1));
2831
+ this.managedToolStatusStarted = true;
2832
+ }
2833
+ const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
2834
+ const color = status.type === "warning" ? "warning" : "dim";
2835
+ this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
2836
+ this.lastStatusSpacer = undefined;
2837
+ this.lastStatusText = undefined;
2838
+ this.ui.requestRender();
2839
+ }
2794
2840
  /**
2795
2841
  * Show a status message in the chat.
2796
2842
  *
@@ -3219,7 +3265,7 @@ export class InteractiveMode {
3219
3265
  this.ui.stop();
3220
3266
  }
3221
3267
  catch { }
3222
- console.error("pi exiting due to uncaughtException:");
3268
+ console.error(`${APP_NAME} exiting due to uncaughtException:`);
3223
3269
  console.error(error);
3224
3270
  process.exit(1);
3225
3271
  }
@@ -3704,7 +3750,7 @@ export class InteractiveMode {
3704
3750
  httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
3705
3751
  thinkingLevel: this.session.thinkingLevel,
3706
3752
  availableThinkingLevels: this.session.getAvailableThinkingLevels(),
3707
- currentTheme: this.settingsManager.getThemeSetting() || "dark",
3753
+ currentTheme: this.themeController.getThemeSelection() || "dark",
3708
3754
  terminalTheme: this.themeController.getTerminalTheme(),
3709
3755
  availableThemes: getAvailableThemes(),
3710
3756
  hideThinkingBlock: this.hideThinkingBlock,
@@ -3723,6 +3769,7 @@ export class InteractiveMode {
3723
3769
  clearOnShrink: this.settingsManager.getClearOnShrink(),
3724
3770
  showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
3725
3771
  tuiMode: this.ui.mode,
3772
+ fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3726
3773
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
3727
3774
  warnings: this.settingsManager.getWarnings(),
3728
3775
  }, {
@@ -3778,7 +3825,7 @@ export class InteractiveMode {
3778
3825
  },
3779
3826
  onThemeChange: (themeSetting) => {
3780
3827
  this.settingsManager.setTheme(themeSetting);
3781
- void this.themeController.applyFromSettings();
3828
+ void this.themeController.setThemeSetting(themeSetting);
3782
3829
  },
3783
3830
  onThemePreview: (themeName) => this.themeController.preview(themeName),
3784
3831
  onHideThinkingBlockChange: (hidden) => {
@@ -3877,6 +3924,9 @@ export class InteractiveMode {
3877
3924
  this.statusContainer.clear();
3878
3925
  this.showStatus(`TUI mode: ${mode}`);
3879
3926
  },
3927
+ onFullscreenExitOutputChange: (output) => {
3928
+ this.settingsManager.setFullscreenExitOutput(output);
3929
+ },
3880
3930
  onFullscreenScrollbarChange: (mode) => {
3881
3931
  this.settingsManager.setFullscreenScrollbar(mode);
3882
3932
  this.applyFullscreenScrollbarSetting();
@@ -3929,7 +3979,7 @@ export class InteractiveMode {
3929
3979
  controller.abort();
3930
3980
  }, 15_000);
3931
3981
  try {
3932
- const result = await this.session.modelRuntime.refresh({ signal: controller.signal });
3982
+ const result = await refreshModelCatalogs(this.session.modelRuntime, controller.signal);
3933
3983
  if (result.aborted && timedOut) {
3934
3984
  this.showWarning("Model refresh timed out; searching cached models.");
3935
3985
  }
@@ -4017,7 +4067,7 @@ export class InteractiveMode {
4017
4067
  onSelect: (selection) => {
4018
4068
  trustStore.setMany(selection.updates);
4019
4069
  done();
4020
- this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart pi for this to take effect.`);
4070
+ this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart ${APP_NAME} for this to take effect.`);
4021
4071
  },
4022
4072
  onCancel: () => {
4023
4073
  done();
@@ -4117,8 +4167,7 @@ export class InteractiveMode {
4117
4167
  this.ui.requestRender();
4118
4168
  },
4119
4169
  });
4120
- void this.session.modelRuntime
4121
- .refresh({ signal: controller.signal })
4170
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
4122
4171
  .then((result) => {
4123
4172
  if (disposed)
4124
4173
  return;
@@ -4672,7 +4721,7 @@ export class InteractiveMode {
4672
4721
  this.ui.requestRender();
4673
4722
  };
4674
4723
  const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => restoreEditor(), providerOption.name, `${providerOption.name} setup`);
4675
- dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside pi.`, [], true);
4724
+ dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
4676
4725
  this.editorContainer.clear();
4677
4726
  this.editorContainer.addChild(dialog);
4678
4727
  this.ui.setFocus(dialog);
@@ -4928,7 +4977,9 @@ export class InteractiveMode {
4928
4977
  this.showStatus(`Session exported to: ${filePath}`);
4929
4978
  }
4930
4979
  else {
4931
- const filePath = await this.session.exportToHtml(outputPath);
4980
+ const filePath = await this.session.exportToHtml(outputPath, {
4981
+ themeName: theme.name,
4982
+ });
4932
4983
  this.showStatus(`Session exported to: ${filePath}`);
4933
4984
  }
4934
4985
  }
@@ -5019,7 +5070,7 @@ export class InteractiveMode {
5019
5070
  // Export to a temp file
5020
5071
  const tmpFile = path.join(os.tmpdir(), "session.html");
5021
5072
  try {
5022
- await this.session.exportToHtml(tmpFile);
5073
+ await this.session.exportToHtml(tmpFile, { themeName: theme.name });
5023
5074
  }
5024
5075
  catch (error) {
5025
5076
  this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -5465,7 +5516,7 @@ export class InteractiveMode {
5465
5516
  // Ignore, will be emitted as an event
5466
5517
  }
5467
5518
  }
5468
- stop() {
5519
+ stop(fullscreenExitOutput = this.settingsManager.getFullscreenExitOutput()) {
5469
5520
  this.disposeActiveSelector();
5470
5521
  if (this.settingsManager.getShowTerminalProgress()) {
5471
5522
  this.ui.terminal.setProgress(false);
@@ -5479,7 +5530,7 @@ export class InteractiveMode {
5479
5530
  this.unsubscribe();
5480
5531
  }
5481
5532
  if (this.isInitialized) {
5482
- this.stopInteractiveTui();
5533
+ this.stopInteractiveTui(fullscreenExitOutput);
5483
5534
  this.isInitialized = false;
5484
5535
  }
5485
5536
  this.unregisterSignalHandlers();