@astralyn/pi 0.84.4 → 0.84.6

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 +57 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +11 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/auth-command.d.ts.map +1 -1
  7. package/dist/cli/auth-command.js +5 -4
  8. package/dist/cli/auth-command.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +6 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +11 -6
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/experimental.d.ts +4 -0
  14. package/dist/core/experimental.d.ts.map +1 -1
  15. package/dist/core/experimental.js +4 -0
  16. package/dist/core/experimental.js.map +1 -1
  17. package/dist/core/extensions/index.d.ts +1 -1
  18. package/dist/core/extensions/index.d.ts.map +1 -1
  19. package/dist/core/extensions/index.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 +10 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +19 -1
  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/keybindings.d.ts +29 -0
  28. package/dist/core/keybindings.d.ts.map +1 -1
  29. package/dist/core/keybindings.js +4 -0
  30. package/dist/core/keybindings.js.map +1 -1
  31. package/dist/core/model-config.d.ts +5 -0
  32. package/dist/core/model-config.d.ts.map +1 -1
  33. package/dist/core/model-config.js +1 -0
  34. package/dist/core/model-config.js.map +1 -1
  35. package/dist/core/model-registry.d.ts +2 -0
  36. package/dist/core/model-registry.d.ts.map +1 -1
  37. package/dist/core/model-registry.js +4 -0
  38. package/dist/core/model-registry.js.map +1 -1
  39. package/dist/core/project-trust.js +2 -2
  40. package/dist/core/project-trust.js.map +1 -1
  41. package/dist/core/sdk.d.ts +5 -3
  42. package/dist/core/sdk.d.ts.map +1 -1
  43. package/dist/core/sdk.js +2 -1
  44. package/dist/core/sdk.js.map +1 -1
  45. package/dist/core/session-manager.js +2 -2
  46. package/dist/core/session-manager.js.map +1 -1
  47. package/dist/core/settings-manager.d.ts +6 -0
  48. package/dist/core/settings-manager.d.ts.map +1 -1
  49. package/dist/core/settings-manager.js +12 -0
  50. package/dist/core/settings-manager.js.map +1 -1
  51. package/dist/core/system-prompt.js +1 -1
  52. package/dist/core/system-prompt.js.map +1 -1
  53. package/dist/core/tools/bash.d.ts +7 -1
  54. package/dist/core/tools/bash.d.ts.map +1 -1
  55. package/dist/core/tools/bash.js +4 -2
  56. package/dist/core/tools/bash.js.map +1 -1
  57. package/dist/core/tools/edit.d.ts.map +1 -1
  58. package/dist/core/tools/edit.js +2 -0
  59. package/dist/core/tools/edit.js.map +1 -1
  60. package/dist/core/tools/find.js +1 -1
  61. package/dist/core/tools/find.js.map +1 -1
  62. package/dist/core/tools/grep.js +1 -1
  63. package/dist/core/tools/grep.js.map +1 -1
  64. package/dist/core/tools/read.d.ts.map +1 -1
  65. package/dist/core/tools/read.js +2 -0
  66. package/dist/core/tools/read.js.map +1 -1
  67. package/dist/core/tools/write.d.ts.map +1 -1
  68. package/dist/core/tools/write.js +2 -0
  69. package/dist/core/tools/write.js.map +1 -1
  70. package/dist/extensions/background/index.d.ts +149 -0
  71. package/dist/extensions/background/index.d.ts.map +1 -0
  72. package/dist/extensions/background/index.js +666 -0
  73. package/dist/extensions/background/index.js.map +1 -0
  74. package/dist/extensions/background/manager.d.ts +95 -0
  75. package/dist/extensions/background/manager.d.ts.map +1 -0
  76. package/dist/extensions/background/manager.js +421 -0
  77. package/dist/extensions/background/manager.js.map +1 -0
  78. package/dist/extensions/background/registry.d.ts +220 -0
  79. package/dist/extensions/background/registry.d.ts.map +1 -0
  80. package/dist/extensions/background/registry.js +589 -0
  81. package/dist/extensions/background/registry.js.map +1 -0
  82. package/dist/extensions/background/render.d.ts +50 -0
  83. package/dist/extensions/background/render.d.ts.map +1 -0
  84. package/dist/extensions/background/render.js +260 -0
  85. package/dist/extensions/background/render.js.map +1 -0
  86. package/dist/extensions/index.d.ts.map +1 -1
  87. package/dist/extensions/index.js +2 -0
  88. package/dist/extensions/index.js.map +1 -1
  89. package/dist/extensions/subagent/activity.d.ts +3 -6
  90. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  91. package/dist/extensions/subagent/activity.js +9 -93
  92. package/dist/extensions/subagent/activity.js.map +1 -1
  93. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  94. package/dist/extensions/subagent/agents-command.js +270 -169
  95. package/dist/extensions/subagent/agents-command.js.map +1 -1
  96. package/dist/extensions/subagent/agents.d.ts +5 -6
  97. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  98. package/dist/extensions/subagent/agents.js +28 -192
  99. package/dist/extensions/subagent/agents.js.map +1 -1
  100. package/dist/extensions/subagent/budget.d.ts +15 -0
  101. package/dist/extensions/subagent/budget.d.ts.map +1 -0
  102. package/dist/extensions/subagent/budget.js +96 -0
  103. package/dist/extensions/subagent/budget.js.map +1 -0
  104. package/dist/extensions/subagent/cancellation.d.ts +29 -0
  105. package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
  106. package/dist/extensions/subagent/cancellation.js +73 -0
  107. package/dist/extensions/subagent/cancellation.js.map +1 -0
  108. package/dist/extensions/subagent/constants.d.ts +4 -5
  109. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  110. package/dist/extensions/subagent/constants.js +11 -7
  111. package/dist/extensions/subagent/constants.js.map +1 -1
  112. package/dist/extensions/subagent/index.d.ts +0 -3
  113. package/dist/extensions/subagent/index.d.ts.map +1 -1
  114. package/dist/extensions/subagent/index.js +59 -208
  115. package/dist/extensions/subagent/index.js.map +1 -1
  116. package/dist/extensions/subagent/model-selection.d.ts +16 -0
  117. package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
  118. package/dist/extensions/subagent/model-selection.js +51 -0
  119. package/dist/extensions/subagent/model-selection.js.map +1 -0
  120. package/dist/extensions/subagent/render.d.ts +7 -2
  121. package/dist/extensions/subagent/render.d.ts.map +1 -1
  122. package/dist/extensions/subagent/render.js +219 -576
  123. package/dist/extensions/subagent/render.js.map +1 -1
  124. package/dist/extensions/subagent/resolve.d.ts +2 -2
  125. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  126. package/dist/extensions/subagent/resolve.js +24 -35
  127. package/dist/extensions/subagent/resolve.js.map +1 -1
  128. package/dist/extensions/subagent/runner.d.ts +4 -6
  129. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  130. package/dist/extensions/subagent/runner.js +101 -316
  131. package/dist/extensions/subagent/runner.js.map +1 -1
  132. package/dist/extensions/subagent/schema.d.ts +4 -10
  133. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  134. package/dist/extensions/subagent/schema.js +8 -13
  135. package/dist/extensions/subagent/schema.js.map +1 -1
  136. package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
  137. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  138. package/dist/extensions/subagent/sdk-runner.js +169 -161
  139. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  140. package/dist/extensions/subagent/settings.d.ts +2 -2
  141. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  142. package/dist/extensions/subagent/settings.js +27 -14
  143. package/dist/extensions/subagent/settings.js.map +1 -1
  144. package/dist/extensions/subagent/state.d.ts +89 -0
  145. package/dist/extensions/subagent/state.d.ts.map +1 -0
  146. package/dist/extensions/subagent/state.js +294 -0
  147. package/dist/extensions/subagent/state.js.map +1 -0
  148. package/dist/extensions/subagent/text.d.ts +7 -0
  149. package/dist/extensions/subagent/text.d.ts.map +1 -0
  150. package/dist/extensions/subagent/text.js +91 -0
  151. package/dist/extensions/subagent/text.js.map +1 -0
  152. package/dist/extensions/subagent/types.d.ts +16 -43
  153. package/dist/extensions/subagent/types.d.ts.map +1 -1
  154. package/dist/extensions/subagent/types.js.map +1 -1
  155. package/dist/extensions/subagent/ui/choices.d.ts +36 -0
  156. package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
  157. package/dist/extensions/subagent/ui/choices.js +54 -0
  158. package/dist/extensions/subagent/ui/choices.js.map +1 -0
  159. package/dist/extensions/subagent/ui/model-list.d.ts +4 -3
  160. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  161. package/dist/extensions/subagent/ui/model-list.js +20 -22
  162. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  163. package/dist/index.d.ts +2 -2
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js.map +1 -1
  166. package/dist/main.d.ts.map +1 -1
  167. package/dist/main.js +5 -1
  168. package/dist/main.js.map +1 -1
  169. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/model-selector.js +2 -1
  171. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  173. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/settings-selector.js +10 -0
  175. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  176. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  177. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  178. package/dist/modes/interactive/interactive-mode.js +77 -25
  179. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  180. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  181. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  182. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  183. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  184. package/dist/modes/interactive/theme/dark.json +2 -0
  185. package/dist/modes/interactive/theme/light.json +2 -0
  186. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  187. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  188. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  189. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  190. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  191. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  192. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  193. package/dist/modes/interactive/theme/theme.js +12 -2
  194. package/dist/modes/interactive/theme/theme.js.map +1 -1
  195. package/dist/modes/json-event.d.ts +4 -1
  196. package/dist/modes/json-event.d.ts.map +1 -1
  197. package/dist/modes/json-event.js +5 -2
  198. package/dist/modes/json-event.js.map +1 -1
  199. package/dist/package-manager-cli.js +1 -1
  200. package/dist/package-manager-cli.js.map +1 -1
  201. package/dist/server/create-harness.d.ts.map +1 -1
  202. package/dist/server/create-harness.js +2 -0
  203. package/dist/server/create-harness.js.map +1 -1
  204. package/dist/utils/tools-manager.d.ts +10 -1
  205. package/dist/utils/tools-manager.d.ts.map +1 -1
  206. package/dist/utils/tools-manager.js +14 -19
  207. package/dist/utils/tools-manager.js.map +1 -1
  208. package/docs/bundled/README.md +1 -0
  209. package/docs/bundled/extensions/background.md +99 -0
  210. package/docs/bundled/extensions/subagent.md +83 -71
  211. package/docs/compaction.md +6 -6
  212. package/docs/custom-provider.md +1 -1
  213. package/docs/docs.json +4 -0
  214. package/docs/environment-variables.md +8 -2
  215. package/docs/extensions.md +19 -2
  216. package/docs/json.md +6 -4
  217. package/docs/keybindings.md +9 -2
  218. package/docs/rpc.md +15 -4
  219. package/docs/sdk.md +9 -0
  220. package/docs/settings.md +31 -0
  221. package/docs/terminal-setup.md +23 -2
  222. package/docs/themes.md +24 -3
  223. package/docs/tui.md +2 -2
  224. package/docs/usage.md +4 -3
  225. package/examples/README.md +1 -1
  226. package/examples/extensions/README.md +0 -1
  227. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  228. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  229. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  230. package/examples/extensions/gondolin/package-lock.json +2 -2
  231. package/examples/extensions/gondolin/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +170 -221
  237. package/package.json +6 -6
  238. package/dist/extensions/subagent/display-name.d.ts +0 -6
  239. package/dist/extensions/subagent/display-name.d.ts.map +0 -1
  240. package/dist/extensions/subagent/display-name.js +0 -13
  241. package/dist/extensions/subagent/display-name.js.map +0 -1
  242. package/dist/extensions/subagent/retry.d.ts +0 -17
  243. package/dist/extensions/subagent/retry.d.ts.map +0 -1
  244. package/dist/extensions/subagent/retry.js +0 -41
  245. package/dist/extensions/subagent/retry.js.map +0 -1
  246. package/dist/extensions/subagent/ui/profile-editor.d.ts +0 -54
  247. package/dist/extensions/subagent/ui/profile-editor.d.ts.map +0 -1
  248. package/dist/extensions/subagent/ui/profile-editor.js +0 -154
  249. package/dist/extensions/subagent/ui/profile-editor.js.map +0 -1
  250. package/dist/extensions/subagent/ui/profile-picker.d.ts +0 -32
  251. package/dist/extensions/subagent/ui/profile-picker.d.ts.map +0 -1
  252. package/dist/extensions/subagent/ui/profile-picker.js +0 -149
  253. package/dist/extensions/subagent/ui/profile-picker.js.map +0 -1
  254. package/examples/extensions/subagent/README.md +0 -175
  255. package/examples/extensions/subagent/agents/planner.md +0 -37
  256. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  257. package/examples/extensions/subagent/agents/scout.md +0 -50
  258. package/examples/extensions/subagent/agents/worker.md +0 -24
  259. package/examples/extensions/subagent/agents.ts +0 -126
  260. package/examples/extensions/subagent/index.ts +0 -1009
  261. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  262. package/examples/extensions/subagent/prompts/implement.md +0 -10
  263. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -70,6 +70,7 @@ import { TrustSelectorComponent } from "./components/trust-selector.js";
70
70
  import { UserMessageComponent } from "./components/user-message.js";
71
71
  import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
72
72
  import { editInExternalEditor } from "./external-editor.js";
73
+ import { refreshModelCatalogs } from "./model-catalog-refresh.js";
73
74
  import { getModelSearchText } from "./model-search.js";
74
75
  import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
75
76
  import { InteractiveThemeController } from "./theme/theme-controller.js";
@@ -168,9 +169,21 @@ function formatLoginProviderCompletionDescription(provider) {
168
169
  export function createInteractiveTui(options) {
169
170
  const terminal = options.terminal ?? new ProcessTerminal();
170
171
  if (options.tuiMode === "fullscreen") {
172
+ const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
171
173
  return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
174
+ searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
175
+ searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
172
176
  openUrl: openBrowser,
173
177
  onRightClickPaste: options.onRightClickPaste,
178
+ copySelection: async (text) => {
179
+ try {
180
+ await copyToClipboard(text);
181
+ return true;
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ },
174
187
  });
175
188
  }
176
189
  return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
@@ -244,6 +257,7 @@ export class InteractiveMode {
244
257
  // Status line tracking (for mutating immediately-sequential status updates)
245
258
  this.lastStatusSpacer = undefined;
246
259
  this.lastStatusText = undefined;
260
+ this.managedToolStatusStarted = false;
247
261
  // Streaming message tracking
248
262
  this.streamingComponent = undefined;
249
263
  this.streamingMessage = undefined;
@@ -303,6 +317,7 @@ export class InteractiveMode {
303
317
  });
304
318
  this.runtimeHost.setRebindSession(async () => {
305
319
  await this.rebindCurrentSession({ renderBeforeBind: true });
320
+ await this.themeController.applyFromSettings();
306
321
  });
307
322
  this.version = VERSION;
308
323
  this.renderer = createInteractiveTui({
@@ -345,7 +360,12 @@ export class InteractiveMode {
345
360
  this.outputPad = this.settingsManager.getOutputPad();
346
361
  // Register themes from resource loader and initialize
347
362
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
348
- this.themeController = new InteractiveThemeController(this.ui, this.settingsManager, (message) => this.showError(message), () => this.updateEditorBorderColor());
363
+ this.themeController = new InteractiveThemeController(this.ui, {
364
+ getSettingsManager: () => this.settingsManager,
365
+ showError: (message) => this.showError(message),
366
+ onChanged: () => this.updateEditorBorderColor(),
367
+ initialThemeSetting: options.initialThemeSetting,
368
+ });
349
369
  }
350
370
  getAutocompleteSourceTag(sourceInfo) {
351
371
  if (!sourceInfo) {
@@ -508,14 +528,14 @@ export class InteractiveMode {
508
528
  tui.setLayoutRoot(this.fullscreenLayoutRoot);
509
529
  }
510
530
  }
511
- stopInteractiveTui() {
512
- if (this.renderer.mode === "fullscreen") {
531
+ stopInteractiveTui(fullscreenExitOutput) {
532
+ if (this.renderer.mode === "fullscreen" && fullscreenExitOutput === "transcript") {
513
533
  while (this.renderer.hasOverlayEntries)
514
534
  this.renderer.hideOverlay();
515
535
  this.switchTuiMode("regular", false, false);
516
536
  this.renderer.renderNow();
517
537
  }
518
- this.ui.stop();
538
+ this.ui.stop({ preserveScreen: this.renderer.mode === "fullscreen" });
519
539
  }
520
540
  switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
521
541
  const previousUi = this.renderer;
@@ -572,10 +592,6 @@ export class InteractiveMode {
572
592
  this.registerSignalHandlers();
573
593
  // Load changelog (only show new entries, skip for resumed sessions)
574
594
  this.changelogMarkdown = this.getChangelogForDisplay();
575
- // Ensure fd and rg are available (downloads if missing, adds to PATH via getBinDir)
576
- // Both are needed: fd for autocomplete, rg for grep tool and bash commands
577
- const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg")]);
578
- this.fdPath = fdPath;
579
595
  if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
580
596
  const modelList = this.session.scopedModels
581
597
  .map((sm) => {
@@ -619,9 +635,11 @@ export class InteractiveMode {
619
635
  this.widgetContainerBelow,
620
636
  this.footerContainer,
621
637
  ]);
638
+ // Accept text while startup completes, but only enable interrupt, exit, and submission feedback.
639
+ this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
640
+ this.defaultEditor.onCtrlD = () => this.handleCtrlD();
641
+ this.defaultEditor.onSubmit = (text) => this.handleStartupSubmit(text);
622
642
  this.ui.setFocus(this.editor);
623
- this.setupKeyHandlers();
624
- this.setupEditorSubmitHandler();
625
643
  // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
626
644
  this.ui.start();
627
645
  this.isInitialized = true;
@@ -673,6 +691,18 @@ export class InteractiveMode {
673
691
  this.headerContainer.addChild(this.builtInHeader);
674
692
  }
675
693
  this.ui.requestRender();
694
+ // Ensure fd and rg are available after mounting the TUI (downloads if missing, adds to PATH via getBinDir)
695
+ // so slow downloads do not make startup appear frozen.
696
+ // Both are needed: fd for autocomplete, rg for grep tool and bash commands.
697
+ const [fdPath] = await Promise.all([
698
+ ensureTool("fd", (status) => this.showManagedToolStatus(status)),
699
+ ensureTool("rg", (status) => this.showManagedToolStatus(status)),
700
+ ]);
701
+ this.fdPath = fdPath;
702
+ // Enable the remaining input handlers only after managed-tool setup completes.
703
+ this.setupKeyHandlers();
704
+ this.setupEditorSubmitHandler();
705
+ this.ui.requestRender();
676
706
  // Initialize extensions first so resources are shown before messages
677
707
  await this.rebindCurrentSession();
678
708
  // Render initial messages AFTER showing loaded resources
@@ -712,8 +742,7 @@ export class InteractiveMode {
712
742
  if (!process.env.PI_OFFLINE) {
713
743
  const controller = new AbortController();
714
744
  const timeout = setTimeout(() => controller.abort(), 15_000);
715
- void this.session.modelRuntime
716
- .refresh({ signal: controller.signal })
745
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
717
746
  .then(() => this.updateAvailableProviderCount())
718
747
  .catch(() => { })
719
748
  .finally(() => clearTimeout(timeout));
@@ -1472,7 +1501,7 @@ export class InteractiveMode {
1472
1501
  const message = error instanceof Error ? error.message : String(error);
1473
1502
  this.showError(`${prefix}: ${message}`);
1474
1503
  stopThemeWatcher();
1475
- this.stop();
1504
+ this.stop("transcript");
1476
1505
  process.exit(1);
1477
1506
  }
1478
1507
  disposeChatToolComponents() {
@@ -1555,6 +1584,7 @@ export class InteractiveMode {
1555
1584
  cwd: this.sessionManager.getCwd(),
1556
1585
  sessionManager: this.sessionManager,
1557
1586
  modelRegistry: extensionRunner.getModelRegistry(),
1587
+ modelRuntime: extensionRunner.getModelRegistry().getRuntime(),
1558
1588
  model: this.session.model,
1559
1589
  scopedModels: this.session.scopedModels,
1560
1590
  thinkingLevel: this.session.thinkingLevel,
@@ -2317,6 +2347,10 @@ export class InteractiveMode {
2317
2347
  // Silently ignore clipboard errors (may not have permission, etc.)
2318
2348
  }
2319
2349
  }
2350
+ handleStartupSubmit(text) {
2351
+ this.editor.setText(text);
2352
+ this.showStatus("Startup is still in progress");
2353
+ }
2320
2354
  setupEditorSubmitHandler() {
2321
2355
  this.defaultEditor.onSubmit = async (text) => {
2322
2356
  text = text.trim();
@@ -2796,6 +2830,19 @@ export class InteractiveMode {
2796
2830
  : message.content.filter((c) => c.type === "text");
2797
2831
  return textBlocks.map((c) => c.text).join("");
2798
2832
  }
2833
+ /** Show a managed-tool status update in the chat. */
2834
+ showManagedToolStatus(status) {
2835
+ if (!this.managedToolStatusStarted) {
2836
+ this.chatContainer.addChild(new Spacer(1));
2837
+ this.managedToolStatusStarted = true;
2838
+ }
2839
+ const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
2840
+ const color = status.type === "warning" ? "warning" : "dim";
2841
+ this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
2842
+ this.lastStatusSpacer = undefined;
2843
+ this.lastStatusText = undefined;
2844
+ this.ui.requestRender();
2845
+ }
2799
2846
  /**
2800
2847
  * Show a status message in the chat.
2801
2848
  *
@@ -3157,7 +3204,7 @@ export class InteractiveMode {
3157
3204
  this.ui.stop();
3158
3205
  }
3159
3206
  catch { }
3160
- console.error("pi exiting due to uncaughtException:");
3207
+ console.error(`${APP_NAME} exiting due to uncaughtException:`);
3161
3208
  console.error(error);
3162
3209
  process.exit(1);
3163
3210
  }
@@ -3644,7 +3691,7 @@ export class InteractiveMode {
3644
3691
  httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
3645
3692
  thinkingLevel: this.session.thinkingLevel,
3646
3693
  availableThinkingLevels: this.session.getAvailableThinkingLevels(),
3647
- currentTheme: this.settingsManager.getThemeSetting() || "dark",
3694
+ currentTheme: this.themeController.getThemeSelection() || "dark",
3648
3695
  terminalTheme: this.themeController.getTerminalTheme(),
3649
3696
  availableThemes: getAvailableThemes(),
3650
3697
  hideThinkingBlock: this.hideThinkingBlock,
@@ -3663,6 +3710,7 @@ export class InteractiveMode {
3663
3710
  clearOnShrink: this.settingsManager.getClearOnShrink(),
3664
3711
  showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
3665
3712
  tuiMode: this.ui.mode,
3713
+ fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3666
3714
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
3667
3715
  warnings: this.settingsManager.getWarnings(),
3668
3716
  }, {
@@ -3718,7 +3766,7 @@ export class InteractiveMode {
3718
3766
  },
3719
3767
  onThemeChange: (themeSetting) => {
3720
3768
  this.settingsManager.setTheme(themeSetting);
3721
- void this.themeController.applyFromSettings();
3769
+ void this.themeController.setThemeSetting(themeSetting);
3722
3770
  },
3723
3771
  onThemePreview: (themeName) => this.themeController.preview(themeName),
3724
3772
  onHideThinkingBlockChange: (hidden) => {
@@ -3816,6 +3864,9 @@ export class InteractiveMode {
3816
3864
  this.statusContainer.clear();
3817
3865
  this.showStatus(`TUI mode: ${mode}`);
3818
3866
  },
3867
+ onFullscreenExitOutputChange: (output) => {
3868
+ this.settingsManager.setFullscreenExitOutput(output);
3869
+ },
3819
3870
  onFullscreenScrollbarChange: (mode) => {
3820
3871
  this.settingsManager.setFullscreenScrollbar(mode);
3821
3872
  this.applyFullscreenScrollbarSetting();
@@ -3868,7 +3919,7 @@ export class InteractiveMode {
3868
3919
  controller.abort();
3869
3920
  }, 15_000);
3870
3921
  try {
3871
- const result = await this.session.modelRuntime.refresh({ signal: controller.signal });
3922
+ const result = await refreshModelCatalogs(this.session.modelRuntime, controller.signal);
3872
3923
  if (result.aborted && timedOut) {
3873
3924
  this.showWarning("Model refresh timed out; searching cached models.");
3874
3925
  }
@@ -3956,7 +4007,7 @@ export class InteractiveMode {
3956
4007
  onSelect: (selection) => {
3957
4008
  trustStore.setMany(selection.updates);
3958
4009
  done();
3959
- this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart pi for this to take effect.`);
4010
+ this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart ${APP_NAME} for this to take effect.`);
3960
4011
  },
3961
4012
  onCancel: () => {
3962
4013
  done();
@@ -4056,8 +4107,7 @@ export class InteractiveMode {
4056
4107
  this.ui.requestRender();
4057
4108
  },
4058
4109
  });
4059
- void this.session.modelRuntime
4060
- .refresh({ signal: controller.signal })
4110
+ void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
4061
4111
  .then((result) => {
4062
4112
  if (disposed)
4063
4113
  return;
@@ -4611,7 +4661,7 @@ export class InteractiveMode {
4611
4661
  this.ui.requestRender();
4612
4662
  };
4613
4663
  const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => restoreEditor(), providerOption.name, `${providerOption.name} setup`);
4614
- dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside pi.`, [], true);
4664
+ dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
4615
4665
  this.editorContainer.clear();
4616
4666
  this.editorContainer.addChild(dialog);
4617
4667
  this.ui.setFocus(dialog);
@@ -4848,7 +4898,9 @@ export class InteractiveMode {
4848
4898
  this.showStatus(`Session exported to: ${filePath}`);
4849
4899
  }
4850
4900
  else {
4851
- const filePath = await this.session.exportToHtml(outputPath);
4901
+ const filePath = await this.session.exportToHtml(outputPath, {
4902
+ themeName: theme.name,
4903
+ });
4852
4904
  this.showStatus(`Session exported to: ${filePath}`);
4853
4905
  }
4854
4906
  }
@@ -4939,7 +4991,7 @@ export class InteractiveMode {
4939
4991
  // Export to a temp file
4940
4992
  const tmpFile = path.join(os.tmpdir(), "session.html");
4941
4993
  try {
4942
- await this.session.exportToHtml(tmpFile);
4994
+ await this.session.exportToHtml(tmpFile, { themeName: theme.name });
4943
4995
  }
4944
4996
  catch (error) {
4945
4997
  this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -5385,7 +5437,7 @@ export class InteractiveMode {
5385
5437
  // Ignore, will be emitted as an event
5386
5438
  }
5387
5439
  }
5388
- stop() {
5440
+ stop(fullscreenExitOutput = this.settingsManager.getFullscreenExitOutput()) {
5389
5441
  this.disposeActiveSelector();
5390
5442
  if (this.settingsManager.getShowTerminalProgress()) {
5391
5443
  this.ui.terminal.setProgress(false);
@@ -5401,7 +5453,7 @@ export class InteractiveMode {
5401
5453
  this.unsubscribe();
5402
5454
  }
5403
5455
  if (this.isInitialized) {
5404
- this.stopInteractiveTui();
5456
+ this.stopInteractiveTui(fullscreenExitOutput);
5405
5457
  this.isInitialized = false;
5406
5458
  }
5407
5459
  this.unregisterSignalHandlers();