@earendil-works/pi-coding-agent 0.82.0 → 0.83.0

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 (84) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -1
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/credential-print.d.ts +23 -0
  7. package/dist/cli/credential-print.d.ts.map +1 -0
  8. package/dist/cli/credential-print.js +116 -0
  9. package/dist/cli/credential-print.js.map +1 -0
  10. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  11. package/dist/core/agent-session-runtime.js +3 -0
  12. package/dist/core/agent-session-runtime.js.map +1 -1
  13. package/dist/core/agent-session.d.ts +1 -1
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +15 -13
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/extensions/runner.d.ts +1 -0
  18. package/dist/core/extensions/runner.d.ts.map +1 -1
  19. package/dist/core/extensions/runner.js +7 -0
  20. package/dist/core/extensions/runner.js.map +1 -1
  21. package/dist/core/extensions/types.d.ts +9 -0
  22. package/dist/core/extensions/types.d.ts.map +1 -1
  23. package/dist/core/extensions/types.js.map +1 -1
  24. package/dist/core/footer-data-provider.d.ts +10 -0
  25. package/dist/core/footer-data-provider.d.ts.map +1 -1
  26. package/dist/core/footer-data-provider.js +1 -1
  27. package/dist/core/footer-data-provider.js.map +1 -1
  28. package/dist/core/model-resolver.d.ts +1 -0
  29. package/dist/core/model-resolver.d.ts.map +1 -1
  30. package/dist/core/model-resolver.js +13 -3
  31. package/dist/core/model-resolver.js.map +1 -1
  32. package/dist/core/model-runtime.d.ts +2 -0
  33. package/dist/core/model-runtime.d.ts.map +1 -1
  34. package/dist/core/model-runtime.js.map +1 -1
  35. package/dist/core/package-manager.d.ts.map +1 -1
  36. package/dist/core/package-manager.js +13 -6
  37. package/dist/core/package-manager.js.map +1 -1
  38. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  39. package/dist/core/remote-catalog-provider.js +19 -1
  40. package/dist/core/remote-catalog-provider.js.map +1 -1
  41. package/dist/core/resource-loader.d.ts +15 -0
  42. package/dist/core/resource-loader.d.ts.map +1 -1
  43. package/dist/core/resource-loader.js +66 -9
  44. package/dist/core/resource-loader.js.map +1 -1
  45. package/dist/extensions/llama/provider.d.ts.map +1 -1
  46. package/dist/extensions/llama/provider.js +7 -1
  47. package/dist/extensions/llama/provider.js.map +1 -1
  48. package/dist/main.d.ts.map +1 -1
  49. package/dist/main.js +43 -0
  50. package/dist/main.js.map +1 -1
  51. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  52. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  53. package/dist/modes/interactive/components/custom-message.js +10 -2
  54. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  55. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  56. package/dist/modes/interactive/components/model-selector.js +4 -1
  57. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  58. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  59. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  60. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  61. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  62. package/dist/modes/interactive/interactive-mode.js +48 -22
  63. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  64. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  65. package/dist/modes/rpc/rpc-mode.js +13 -0
  66. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  67. package/docs/custom-provider.md +9 -3
  68. package/docs/extensions.md +5 -3
  69. package/docs/providers.md +1 -0
  70. package/docs/session-format.md +2 -0
  71. package/examples/extensions/custom-provider-anthropic/index.ts +8 -2
  72. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  73. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  74. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  75. package/examples/extensions/gondolin/package-lock.json +2 -2
  76. package/examples/extensions/gondolin/package.json +1 -1
  77. package/examples/extensions/message-renderer.ts +2 -2
  78. package/examples/extensions/sandbox/package-lock.json +2 -2
  79. package/examples/extensions/sandbox/package.json +1 -1
  80. package/examples/extensions/with-deps/package-lock.json +2 -2
  81. package/examples/extensions/with-deps/package.json +1 -1
  82. package/examples/sdk/12-full-control.ts +2 -0
  83. package/npm-shrinkwrap.json +18 -18
  84. package/package.json +5 -5
@@ -17,7 +17,7 @@ import { FooterDataProvider } from "../../core/footer-data-provider.js";
17
17
  import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
18
18
  import { KeybindingsManager } from "../../core/keybindings.js";
19
19
  import { createCompactionSummaryMessage } from "../../core/messages.js";
20
- import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScope } from "../../core/model-resolver.js";
20
+ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScope, resolveModelScopeWithDiagnostics, } from "../../core/model-resolver.js";
21
21
  import { DefaultPackageManager } from "../../core/package-manager.js";
22
22
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
23
23
  import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
@@ -1106,7 +1106,12 @@ export class InteractiveMode {
1106
1106
  }
1107
1107
  }
1108
1108
  if (showListing) {
1109
- const contextFiles = this.session.resourceLoader.getAgentsFiles().agentsFiles;
1109
+ const systemPromptSource = this.session.resourceLoader.getSystemPromptSource();
1110
+ const contextFiles = [
1111
+ ...(systemPromptSource ? [systemPromptSource] : []),
1112
+ ...this.session.resourceLoader.getAppendSystemPromptSources(),
1113
+ ...this.session.resourceLoader.getAgentsFiles().agentsFiles,
1114
+ ];
1110
1115
  if (contextFiles.length > 0) {
1111
1116
  this.loadedResourcesContainer.addChild(new Spacer(1));
1112
1117
  const contextList = contextFiles
@@ -1306,16 +1311,19 @@ export class InteractiveMode {
1306
1311
  }
1307
1312
  }
1308
1313
  async rebindCurrentSession(options = {}) {
1314
+ const session = this.session;
1309
1315
  this.unsubscribe?.();
1310
1316
  this.unsubscribe = undefined;
1311
1317
  this.applyRuntimeSettings();
1312
1318
  if (options.renderBeforeBind) {
1313
1319
  this.renderCurrentSessionState();
1314
1320
  this.subscribeToAgent();
1315
- await this.bindCurrentSessionExtensions();
1316
1321
  }
1317
- else {
1318
- await this.bindCurrentSessionExtensions();
1322
+ await this.bindCurrentSessionExtensions();
1323
+ if (this.session !== session) {
1324
+ return;
1325
+ }
1326
+ if (!options.renderBeforeBind) {
1319
1327
  this.subscribeToAgent();
1320
1328
  }
1321
1329
  await this.updateAvailableProviderCount();
@@ -1361,6 +1369,7 @@ export class InteractiveMode {
1361
1369
  sessionManager: this.sessionManager,
1362
1370
  modelRegistry: extensionRunner.getModelRegistry(),
1363
1371
  model: this.session.model,
1372
+ scopedModels: this.session.scopedModels,
1364
1373
  thinkingLevel: this.session.thinkingLevel,
1365
1374
  isIdle: () => this.session.isIdle,
1366
1375
  isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
@@ -2622,7 +2631,7 @@ export class InteractiveMode {
2622
2631
  case "custom": {
2623
2632
  if (message.display) {
2624
2633
  const renderer = this.session.extensionRunner.getMessageRenderer(message.customType);
2625
- const component = new CustomMessageComponent(message, renderer, this.getMarkdownThemeWithSettings());
2634
+ const component = new CustomMessageComponent(message, renderer, this.getMarkdownThemeWithSettings(), this.outputPad);
2626
2635
  component.setExpanded(this.toolOutputExpanded);
2627
2636
  this.chatContainer.addChild(component);
2628
2637
  }
@@ -3118,7 +3127,7 @@ export class InteractiveMode {
3118
3127
  }
3119
3128
  }
3120
3129
  }
3121
- this.ui.requestRender();
3130
+ this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
3122
3131
  }
3123
3132
  toggleThinkingBlockVisibility() {
3124
3133
  this.hideThinkingBlock = !this.hideThinkingBlock;
@@ -3525,7 +3534,9 @@ export class InteractiveMode {
3525
3534
  this.outputPad = padding;
3526
3535
  if (this.streamingComponent || this.session.isStreaming) {
3527
3536
  for (const child of this.chatContainer.children) {
3528
- if (child instanceof AssistantMessageComponent || child instanceof UserMessageComponent) {
3537
+ if (child instanceof AssistantMessageComponent ||
3538
+ child instanceof CustomMessageComponent ||
3539
+ child instanceof UserMessageComponent) {
3529
3540
  child.setOutputPad(padding);
3530
3541
  }
3531
3542
  }
@@ -3710,12 +3721,17 @@ export class InteractiveMode {
3710
3721
  // Get all available models
3711
3722
  await this.session.modelRuntime.refresh();
3712
3723
  const allModels = [...(await this.session.modelRuntime.getAvailable())];
3713
- if (allModels.length === 0) {
3724
+ const allModelIds = new Set(allModels.map((model) => `${model.provider}/${model.id}`));
3725
+ const configuredPatterns = this.settingsManager.getEnabledModels();
3726
+ const sessionScopedModels = this.session.scopedModels;
3727
+ if (allModels.length === 0 && !configuredPatterns?.length && sessionScopedModels.length === 0) {
3714
3728
  this.showStatus("No models available");
3715
3729
  return;
3716
3730
  }
3731
+ const configuredScope = configuredPatterns?.length
3732
+ ? await resolveModelScopeWithDiagnostics(configuredPatterns, this.session.modelRuntime)
3733
+ : undefined;
3717
3734
  // Check if session has scoped models (from previous session-only changes or CLI --models)
3718
- const sessionScopedModels = this.session.scopedModels;
3719
3735
  const hasSessionScope = sessionScopedModels.length > 0;
3720
3736
  // Build enabled model IDs from session state or settings
3721
3737
  let currentEnabledIds = null;
@@ -3723,18 +3739,22 @@ export class InteractiveMode {
3723
3739
  // Use current session's scoped models
3724
3740
  currentEnabledIds = sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
3725
3741
  }
3726
- else {
3727
- // Fall back to settings
3728
- const patterns = this.settingsManager.getEnabledModels();
3729
- if (patterns !== undefined && patterns.length > 0) {
3730
- const scopedModels = await resolveModelScope(patterns, this.session.modelRuntime);
3731
- currentEnabledIds = scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
3732
- }
3742
+ else if (configuredScope) {
3743
+ currentEnabledIds = configuredScope.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
3744
+ }
3745
+ for (const diagnostic of configuredScope?.diagnostics ?? []) {
3746
+ if (diagnostic.code !== "no-match")
3747
+ continue;
3748
+ currentEnabledIds ??= [];
3749
+ if (!currentEnabledIds.includes(diagnostic.pattern))
3750
+ currentEnabledIds.push(diagnostic.pattern);
3733
3751
  }
3734
3752
  // Helper to update session's scoped models (session-only, no persist)
3735
3753
  const updateSessionModels = async (enabledIds) => {
3736
3754
  currentEnabledIds = enabledIds === null ? null : [...enabledIds];
3737
- if (enabledIds && enabledIds.length > 0 && enabledIds.length < allModels.length) {
3755
+ const hasEnabledAvailableModel = enabledIds?.some((id) => allModelIds.has(id)) ?? false;
3756
+ const allAvailableModelsEnabled = enabledIds !== null && [...allModelIds].every((id) => enabledIds.includes(id));
3757
+ if (enabledIds && hasEnabledAvailableModel && !allAvailableModelsEnabled) {
3738
3758
  const newScopedModels = await resolveModelScope(enabledIds, this.session.modelRuntime);
3739
3759
  this.session.setScopedModels(newScopedModels.map((sm) => ({
3740
3760
  model: sm.model,
@@ -3758,9 +3778,10 @@ export class InteractiveMode {
3758
3778
  },
3759
3779
  onPersist: (enabledIds) => {
3760
3780
  // Persist to settings
3761
- const newPatterns = enabledIds === null || enabledIds.length === allModels.length
3762
- ? undefined // All enabled = clear filter
3763
- : enabledIds;
3781
+ const allEnabled = enabledIds !== null &&
3782
+ enabledIds.length === allModels.length &&
3783
+ enabledIds.every((id) => allModelIds.has(id));
3784
+ const newPatterns = enabledIds === null || allEnabled ? undefined : enabledIds;
3764
3785
  this.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);
3765
3786
  this.showStatus("Model selection saved to settings");
3766
3787
  },
@@ -3831,7 +3852,7 @@ export class InteractiveMode {
3831
3852
  this.showSelector((done) => {
3832
3853
  const selector = new TreeSelectorComponent(tree, realLeafId, this.ui.terminal.rows, async (entryId) => {
3833
3854
  // Selecting the current leaf is a no-op (already there)
3834
- if (entryId === realLeafId) {
3855
+ if (entryId === this.sessionManager.getLeafId()) {
3835
3856
  done();
3836
3857
  this.showStatus("Already at this point");
3837
3858
  return;
@@ -3866,6 +3887,11 @@ export class InteractiveMode {
3866
3887
  break;
3867
3888
  }
3868
3889
  }
3890
+ // The user committed to navigating: stop the active response first.
3891
+ if (this.session.isStreaming) {
3892
+ this.restoreQueuedMessagesToEditor();
3893
+ await this.session.abort();
3894
+ }
3869
3895
  // Set up escape handler and status indicator if summarizing
3870
3896
  let showingSummaryIndicator = false;
3871
3897
  const originalOnEscape = this.defaultEditor.onEscape;