@mariozechner/pi-coding-agent 0.50.0 → 0.50.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 (73) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +2 -0
  3. package/dist/core/agent-session.d.ts +7 -3
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +24 -15
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/defaults.d.ts +3 -0
  8. package/dist/core/defaults.d.ts.map +1 -0
  9. package/dist/core/defaults.js +2 -0
  10. package/dist/core/defaults.js.map +1 -0
  11. package/dist/core/extensions/runner.d.ts +4 -0
  12. package/dist/core/extensions/runner.d.ts.map +1 -1
  13. package/dist/core/extensions/runner.js +9 -0
  14. package/dist/core/extensions/runner.js.map +1 -1
  15. package/dist/core/model-resolver.d.ts.map +1 -1
  16. package/dist/core/model-resolver.js +8 -6
  17. package/dist/core/model-resolver.js.map +1 -1
  18. package/dist/core/package-manager.d.ts +1 -0
  19. package/dist/core/package-manager.d.ts.map +1 -1
  20. package/dist/core/package-manager.js +34 -5
  21. package/dist/core/package-manager.js.map +1 -1
  22. package/dist/core/prompt-templates.d.ts.map +1 -1
  23. package/dist/core/prompt-templates.js.map +1 -1
  24. package/dist/core/sdk.d.ts +1 -1
  25. package/dist/core/sdk.d.ts.map +1 -1
  26. package/dist/core/sdk.js +3 -2
  27. package/dist/core/sdk.js.map +1 -1
  28. package/dist/core/settings-manager.d.ts +7 -0
  29. package/dist/core/settings-manager.d.ts.map +1 -1
  30. package/dist/core/settings-manager.js +71 -4
  31. package/dist/core/settings-manager.js.map +1 -1
  32. package/dist/main.d.ts.map +1 -1
  33. package/dist/main.js +2 -1
  34. package/dist/main.js.map +1 -1
  35. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  36. package/dist/modes/interactive/components/custom-editor.js +2 -1
  37. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  38. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  39. package/dist/modes/interactive/components/footer.js +17 -13
  40. package/dist/modes/interactive/components/footer.js.map +1 -1
  41. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  42. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  43. package/dist/modes/interactive/components/settings-selector.js +12 -0
  44. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  45. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  46. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  47. package/dist/modes/interactive/interactive-mode.js +60 -38
  48. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  49. package/dist/modes/print-mode.d.ts.map +1 -1
  50. package/dist/modes/print-mode.js +26 -29
  51. package/dist/modes/print-mode.js.map +1 -1
  52. package/dist/modes/rpc/rpc-client.d.ts +5 -1
  53. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  54. package/dist/modes/rpc/rpc-client.js +7 -0
  55. package/dist/modes/rpc/rpc-client.js.map +1 -1
  56. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  57. package/dist/modes/rpc/rpc-mode.js +63 -32
  58. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  59. package/dist/modes/rpc/rpc-types.d.ts +24 -0
  60. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  61. package/dist/modes/rpc/rpc-types.js.map +1 -1
  62. package/docs/extensions.md +2 -0
  63. package/docs/keybindings.md +3 -3
  64. package/docs/packages.md +9 -4
  65. package/docs/providers.md +1 -0
  66. package/docs/rpc.md +41 -0
  67. package/docs/settings.md +1 -0
  68. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  69. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  70. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  71. package/examples/extensions/with-deps/package-lock.json +2 -2
  72. package/examples/extensions/with-deps/package.json +1 -1
  73. package/package.json +4 -4
@@ -116,6 +116,8 @@ export class InteractiveMode {
116
116
  widgetContainerBelow;
117
117
  // Custom footer from extension (undefined = use built-in footer)
118
118
  customFooter = undefined;
119
+ // Header container that holds the built-in or custom header
120
+ headerContainer;
119
121
  // Built-in header (logo + keybinding hints + changelog)
120
122
  builtInHeader = undefined;
121
123
  // Custom header from extension (undefined = use built-in header)
@@ -135,6 +137,7 @@ export class InteractiveMode {
135
137
  this.session = session;
136
138
  this.version = VERSION;
137
139
  this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
140
+ this.headerContainer = new Container();
138
141
  this.chatContainer = new Container();
139
142
  this.pendingMessagesContainer = new Container();
140
143
  this.statusContainer = new Container();
@@ -142,7 +145,11 @@ export class InteractiveMode {
142
145
  this.widgetContainerBelow = new Container();
143
146
  this.keybindings = KeybindingsManager.create();
144
147
  const editorPaddingX = this.settingsManager.getEditorPaddingX();
145
- this.defaultEditor = new CustomEditor(this.ui, getEditorTheme(), this.keybindings, { paddingX: editorPaddingX });
148
+ const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
149
+ this.defaultEditor = new CustomEditor(this.ui, getEditorTheme(), this.keybindings, {
150
+ paddingX: editorPaddingX,
151
+ autocompleteMaxVisible,
152
+ });
146
153
  this.editor = this.defaultEditor;
147
154
  this.editorContainer = new Container();
148
155
  this.editorContainer.addChild(this.editor);
@@ -239,6 +246,8 @@ export class InteractiveMode {
239
246
  // Setup autocomplete with fd tool for file path completion
240
247
  this.fdPath = await ensureTool("fd");
241
248
  this.setupAutocomplete(this.fdPath);
249
+ // Add header container as first child
250
+ this.ui.addChild(this.headerContainer);
242
251
  // Add header with keybindings from config (unless silenced)
243
252
  if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
244
253
  const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
@@ -268,37 +277,38 @@ export class InteractiveMode {
268
277
  ].join("\n");
269
278
  this.builtInHeader = new Text(`${logo}\n${instructions}`, 1, 0);
270
279
  // Setup UI layout
271
- this.ui.addChild(new Spacer(1));
272
- this.ui.addChild(this.builtInHeader);
273
- this.ui.addChild(new Spacer(1));
280
+ this.headerContainer.addChild(new Spacer(1));
281
+ this.headerContainer.addChild(this.builtInHeader);
282
+ this.headerContainer.addChild(new Spacer(1));
274
283
  // Add changelog if provided
275
284
  if (this.changelogMarkdown) {
276
- this.ui.addChild(new DynamicBorder());
285
+ this.headerContainer.addChild(new DynamicBorder());
277
286
  if (this.settingsManager.getCollapseChangelog()) {
278
287
  const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
279
288
  const latestVersion = versionMatch ? versionMatch[1] : this.version;
280
289
  const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
281
- this.ui.addChild(new Text(condensedText, 1, 0));
290
+ this.headerContainer.addChild(new Text(condensedText, 1, 0));
282
291
  }
283
292
  else {
284
- this.ui.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
285
- this.ui.addChild(new Spacer(1));
286
- this.ui.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
287
- this.ui.addChild(new Spacer(1));
293
+ this.headerContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
294
+ this.headerContainer.addChild(new Spacer(1));
295
+ this.headerContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
296
+ this.headerContainer.addChild(new Spacer(1));
288
297
  }
289
- this.ui.addChild(new DynamicBorder());
298
+ this.headerContainer.addChild(new DynamicBorder());
290
299
  }
291
300
  }
292
301
  else {
293
302
  // Minimal header when silenced
294
303
  this.builtInHeader = new Text("", 0, 0);
304
+ this.headerContainer.addChild(this.builtInHeader);
295
305
  if (this.changelogMarkdown) {
296
306
  // Still show changelog notification even in silent mode
297
- this.ui.addChild(new Spacer(1));
307
+ this.headerContainer.addChild(new Spacer(1));
298
308
  const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
299
309
  const latestVersion = versionMatch ? versionMatch[1] : this.version;
300
310
  const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
301
- this.ui.addChild(new Text(condensedText, 1, 0));
311
+ this.headerContainer.addChild(new Text(condensedText, 1, 0));
302
312
  }
303
313
  }
304
314
  this.ui.addChild(this.chatContainer);
@@ -312,6 +322,8 @@ export class InteractiveMode {
312
322
  this.ui.setFocus(this.editor);
313
323
  this.setupKeyHandlers();
314
324
  this.setupEditorSubmitHandler();
325
+ // Render initial messages before starting the UI to avoid layout jump
326
+ this.renderInitialMessages();
315
327
  // Start the UI
316
328
  this.ui.start();
317
329
  this.isInitialized = true;
@@ -359,7 +371,6 @@ export class InteractiveMode {
359
371
  this.showNewVersionNotification(newVersion);
360
372
  }
361
373
  });
362
- this.renderInitialMessages();
363
374
  // Show startup warnings
364
375
  const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
365
376
  if (migratedProviders && migratedProviders.length > 0) {
@@ -741,12 +752,6 @@ export class InteractiveMode {
741
752
  * Initialize the extension system with TUI-based UI context.
742
753
  */
743
754
  async initExtensions() {
744
- const extensionRunner = this.session.extensionRunner;
745
- if (!extensionRunner) {
746
- this.showLoadedResources({ extensionPaths: [], force: false });
747
- return;
748
- }
749
- // Create extension UI context
750
755
  const uiContext = this.createExtensionUIContext();
751
756
  await this.session.bindExtensions({
752
757
  uiContext,
@@ -758,21 +763,20 @@ export class InteractiveMode {
758
763
  this.loadingAnimation = undefined;
759
764
  }
760
765
  this.statusContainer.clear();
761
- const success = await this.session.newSession({ parentSession: options?.parentSession });
766
+ // Delegate to AgentSession (handles setup + agent state sync)
767
+ const success = await this.session.newSession(options);
762
768
  if (!success) {
763
769
  return { cancelled: true };
764
770
  }
765
- if (options?.setup) {
766
- await options.setup(this.sessionManager);
767
- }
771
+ // Clear UI state
768
772
  this.chatContainer.clear();
769
773
  this.pendingMessagesContainer.clear();
770
774
  this.compactionQueuedMessages = [];
771
775
  this.streamingComponent = undefined;
772
776
  this.streamingMessage = undefined;
773
777
  this.pendingTools.clear();
774
- this.chatContainer.addChild(new Spacer(1));
775
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
778
+ // Render any messages added via setup, or show empty session
779
+ this.renderInitialMessages();
776
780
  this.ui.requestRender();
777
781
  return { cancelled: false };
778
782
  },
@@ -813,6 +817,11 @@ export class InteractiveMode {
813
817
  this.showExtensionError(error.extensionPath, error.error, error.stack);
814
818
  },
815
819
  });
820
+ const extensionRunner = this.session.extensionRunner;
821
+ if (!extensionRunner) {
822
+ this.showLoadedResources({ extensionPaths: [], force: false });
823
+ return;
824
+ }
816
825
  this.setupExtensionShortcuts(extensionRunner);
817
826
  this.showLoadedResources({ extensionPaths: extensionRunner.getExtensionPaths(), force: false });
818
827
  }
@@ -1020,22 +1029,26 @@ export class InteractiveMode {
1020
1029
  if (this.customHeader?.dispose) {
1021
1030
  this.customHeader.dispose();
1022
1031
  }
1023
- // Remove current header from UI
1024
- if (this.customHeader) {
1025
- this.ui.removeChild(this.customHeader);
1026
- }
1027
- else {
1028
- this.ui.removeChild(this.builtInHeader);
1029
- }
1032
+ // Find the index of the current header in the header container
1033
+ const currentHeader = this.customHeader || this.builtInHeader;
1034
+ const index = this.headerContainer.children.indexOf(currentHeader);
1030
1035
  if (factory) {
1031
- // Create and add custom header at position 1 (after initial spacer)
1036
+ // Create and add custom header
1032
1037
  this.customHeader = factory(this.ui, theme);
1033
- this.ui.children.splice(1, 0, this.customHeader);
1038
+ if (index !== -1) {
1039
+ this.headerContainer.children[index] = this.customHeader;
1040
+ }
1041
+ else {
1042
+ // If not found (e.g. builtInHeader was never added), add at the top
1043
+ this.headerContainer.children.unshift(this.customHeader);
1044
+ }
1034
1045
  }
1035
1046
  else {
1036
- // Restore built-in header at position 1
1047
+ // Restore built-in header
1037
1048
  this.customHeader = undefined;
1038
- this.ui.children.splice(1, 0, this.builtInHeader);
1049
+ if (index !== -1) {
1050
+ this.headerContainer.children[index] = this.builtInHeader;
1051
+ }
1039
1052
  }
1040
1053
  this.ui.requestRender();
1041
1054
  }
@@ -2479,6 +2492,7 @@ export class InteractiveMode {
2479
2492
  doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
2480
2493
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
2481
2494
  editorPaddingX: this.settingsManager.getEditorPaddingX(),
2495
+ autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
2482
2496
  quietStartup: this.settingsManager.getQuietStartup(),
2483
2497
  }, {
2484
2498
  onAutoCompactChange: (enabled) => {
@@ -2560,6 +2574,13 @@ export class InteractiveMode {
2560
2574
  this.editor.setPaddingX(padding);
2561
2575
  }
2562
2576
  },
2577
+ onAutocompleteMaxVisibleChange: (maxVisible) => {
2578
+ this.settingsManager.setAutocompleteMaxVisible(maxVisible);
2579
+ this.defaultEditor.setAutocompleteMaxVisible(maxVisible);
2580
+ if (this.editor !== this.defaultEditor && this.editor.setAutocompleteMaxVisible !== undefined) {
2581
+ this.editor.setAutocompleteMaxVisible(maxVisible);
2582
+ }
2583
+ },
2563
2584
  onCancel: () => {
2564
2585
  done();
2565
2586
  this.ui.requestRender();
@@ -3394,7 +3415,8 @@ export class InteractiveMode {
3394
3415
  `;
3395
3416
  for (const [key, shortcut] of shortcuts) {
3396
3417
  const description = shortcut.description ?? shortcut.extensionPath;
3397
- hotkeys += `| \`${key}\` | ${description} |\n`;
3418
+ const keyDisplay = key.replace(/\b\w/g, (c) => c.toUpperCase());
3419
+ hotkeys += `| \`${keyDisplay}\` | ${description} |\n`;
3398
3420
  }
3399
3421
  }
3400
3422
  }