@earendil-works/pi-coding-agent 0.80.6 → 0.80.7

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 (79) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +3 -1
  3. package/dist/core/agent-session.d.ts +1 -1
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +4 -4
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  8. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  9. package/dist/core/compaction/branch-summarization.js.map +1 -1
  10. package/dist/core/extensions/runner.d.ts +1 -0
  11. package/dist/core/extensions/runner.d.ts.map +1 -1
  12. package/dist/core/extensions/runner.js +5 -0
  13. package/dist/core/extensions/runner.js.map +1 -1
  14. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  15. package/dist/core/extensions/wrapper.js +22 -3
  16. package/dist/core/extensions/wrapper.js.map +1 -1
  17. package/dist/core/keybindings.d.ts +8 -3
  18. package/dist/core/keybindings.d.ts.map +1 -1
  19. package/dist/core/keybindings.js +7 -3
  20. package/dist/core/keybindings.js.map +1 -1
  21. package/dist/core/model-registry.d.ts.map +1 -1
  22. package/dist/core/model-registry.js +18 -2
  23. package/dist/core/model-registry.js.map +1 -1
  24. package/dist/core/model-resolver.d.ts.map +1 -1
  25. package/dist/core/model-resolver.js +1 -0
  26. package/dist/core/model-resolver.js.map +1 -1
  27. package/dist/core/package-manager.d.ts.map +1 -1
  28. package/dist/core/package-manager.js +7 -2
  29. package/dist/core/package-manager.js.map +1 -1
  30. package/dist/core/provider-display-names.d.ts.map +1 -1
  31. package/dist/core/provider-display-names.js +1 -0
  32. package/dist/core/provider-display-names.js.map +1 -1
  33. package/dist/core/radius.d.ts +21 -0
  34. package/dist/core/radius.d.ts.map +1 -0
  35. package/dist/core/radius.js +30 -0
  36. package/dist/core/radius.js.map +1 -0
  37. package/dist/core/system-prompt.d.ts.map +1 -1
  38. package/dist/core/system-prompt.js +1 -11
  39. package/dist/core/system-prompt.js.map +1 -1
  40. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  41. package/dist/modes/interactive/components/custom-editor.js +1 -1
  42. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  43. package/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  44. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  45. package/dist/modes/interactive/components/login-dialog.js +9 -2
  46. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  47. package/dist/modes/interactive/components/tree-selector.d.ts +5 -0
  48. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  49. package/dist/modes/interactive/components/tree-selector.js +49 -12
  50. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  51. package/dist/modes/interactive/interactive-mode.d.ts +1 -2
  52. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  53. package/dist/modes/interactive/interactive-mode.js +45 -41
  54. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  55. package/dist/utils/clipboard-native.d.ts +1 -0
  56. package/dist/utils/clipboard-native.d.ts.map +1 -1
  57. package/dist/utils/clipboard-native.js.map +1 -1
  58. package/dist/utils/clipboard.d.ts +2 -0
  59. package/dist/utils/clipboard.d.ts.map +1 -1
  60. package/dist/utils/clipboard.js +13 -0
  61. package/dist/utils/clipboard.js.map +1 -1
  62. package/docs/custom-provider.md +2 -0
  63. package/docs/extensions.md +138 -0
  64. package/docs/keybindings.md +1 -0
  65. package/docs/models.md +2 -0
  66. package/docs/providers.md +3 -0
  67. package/docs/quickstart.md +1 -1
  68. package/docs/usage.md +1 -0
  69. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  70. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  71. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  72. package/examples/extensions/gondolin/package-lock.json +2 -2
  73. package/examples/extensions/gondolin/package.json +1 -1
  74. package/examples/extensions/sandbox/package-lock.json +2 -2
  75. package/examples/extensions/sandbox/package.json +1 -1
  76. package/examples/extensions/with-deps/package-lock.json +2 -2
  77. package/examples/extensions/with-deps/package.json +1 -1
  78. package/npm-shrinkwrap.json +12 -12
  79. package/package.json +4 -4
@@ -27,7 +27,7 @@ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
27
27
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
28
28
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
29
29
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
30
- import { copyToClipboard } from "../../utils/clipboard.js";
30
+ import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
31
31
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
32
32
  import { parseGitUrl } from "../../utils/git.js";
33
33
  import { getCwdRelativePath } from "../../utils/paths.js";
@@ -125,7 +125,6 @@ export function formatResumeCommand(sessionManager) {
125
125
  function hasDefaultModelProvider(providerId) {
126
126
  return providerId in defaultModelPerProvider;
127
127
  }
128
- const BEDROCK_PROVIDER_ID = "amazon-bedrock";
129
128
  const BUILT_IN_MODEL_PROVIDERS = new Set(getProviders());
130
129
  export function isApiKeyLoginProvider(providerId, oauthProviderIds, builtInProviderIds = BUILT_IN_MODEL_PROVIDERS) {
131
130
  if (BUILT_IN_PROVIDER_DISPLAY_NAMES[providerId]) {
@@ -532,7 +531,7 @@ export class InteractiveMode {
532
531
  rawKeyHint("!!", "to run bash (no context)"),
533
532
  hint("app.message.followUp", "to queue follow-up"),
534
533
  hint("app.message.dequeue", "to edit all queued messages"),
535
- hint("app.clipboard.pasteImage", "to paste image"),
534
+ hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
536
535
  rawKeyHint("drop files", "to attach"),
537
536
  ].join("\n");
538
537
  const compactInstructions = [
@@ -2034,6 +2033,7 @@ export class InteractiveMode {
2034
2033
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2035
2034
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2036
2035
  this.defaultEditor.onAction("app.editor.external", () => this.openExternalEditor());
2036
+ this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
2037
2037
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2038
2038
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2039
2039
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
@@ -2047,26 +2047,30 @@ export class InteractiveMode {
2047
2047
  this.updateEditorBorderColor();
2048
2048
  }
2049
2049
  };
2050
- // Handle clipboard image paste (triggered on Ctrl+V)
2050
+ // Handle clipboard paste (triggered on Ctrl+V). Images are attached by path;
2051
+ // otherwise, paste plain text from the system clipboard.
2051
2052
  this.defaultEditor.onPasteImage = () => {
2052
- this.handleClipboardImagePaste();
2053
+ void this.handleClipboardPaste();
2053
2054
  };
2054
2055
  }
2055
- async handleClipboardImagePaste() {
2056
+ async handleClipboardPaste() {
2056
2057
  try {
2057
2058
  const image = await readClipboardImage();
2058
- if (!image) {
2059
+ if (image) {
2060
+ const tmpDir = os.tmpdir();
2061
+ const ext = extensionForImageMimeType(image.mimeType) ?? "png";
2062
+ const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
2063
+ const filePath = path.join(tmpDir, fileName);
2064
+ fs.writeFileSync(filePath, Buffer.from(image.bytes));
2065
+ this.editor.insertTextAtCursor?.(filePath);
2066
+ this.ui.requestRender();
2059
2067
  return;
2060
2068
  }
2061
- // Write to temp file
2062
- const tmpDir = os.tmpdir();
2063
- const ext = extensionForImageMimeType(image.mimeType) ?? "png";
2064
- const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
2065
- const filePath = path.join(tmpDir, fileName);
2066
- fs.writeFileSync(filePath, Buffer.from(image.bytes));
2067
- // Insert file path directly
2068
- this.editor.insertTextAtCursor?.(filePath);
2069
- this.ui.requestRender();
2069
+ const text = await readClipboardText();
2070
+ if (text) {
2071
+ this.editor.insertTextAtCursor?.(text);
2072
+ this.ui.requestRender();
2073
+ }
2070
2074
  }
2071
2075
  catch {
2072
2076
  // Silently ignore clipboard errors (may not have permission, etc.)
@@ -3901,6 +3905,19 @@ export class InteractiveMode {
3901
3905
  this.sessionManager.appendLabelChange(entryId, label);
3902
3906
  this.ui.requestRender();
3903
3907
  }, initialSelectedId, initialFilterMode);
3908
+ selector.onCopy = async (text) => {
3909
+ if (!text) {
3910
+ this.showError("Selected entry has no text to copy");
3911
+ return;
3912
+ }
3913
+ try {
3914
+ await copyToClipboard(text);
3915
+ this.showStatus("Copied selected message to clipboard");
3916
+ }
3917
+ catch (error) {
3918
+ this.showError(error instanceof Error ? error.message : String(error));
3919
+ }
3920
+ };
3904
3921
  return { component: selector, focus: selector };
3905
3922
  });
3906
3923
  }
@@ -4034,16 +4051,13 @@ export class InteractiveMode {
4034
4051
  if (providerOption.authType === "oauth") {
4035
4052
  await this.showLoginDialog(providerOption.id, providerOption.name);
4036
4053
  }
4037
- else if (providerOption.id === BEDROCK_PROVIDER_ID) {
4038
- this.showBedrockSetupDialog(providerOption.id, providerOption.name);
4039
- }
4040
4054
  else {
4041
4055
  await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
4042
4056
  }
4043
4057
  }
4044
4058
  showLoginAuthTypeSelector(providerOptions) {
4045
- const subscriptionLabel = "Use a subscription";
4046
- const apiKeyLabel = "Use an API key";
4059
+ const subscriptionLabel = "Sign in with an account";
4060
+ const apiKeyLabel = "Sign in with an API key";
4047
4061
  const availableAuthTypes = providerOptions
4048
4062
  ? new Set(providerOptions.map((provider) => provider.authType))
4049
4063
  : new Set(["oauth", "api_key"]);
@@ -4204,30 +4218,18 @@ export class InteractiveMode {
4204
4218
  }
4205
4219
  }
4206
4220
  }
4207
- showBedrockSetupDialog(providerId, providerName) {
4208
- const restoreEditor = () => {
4209
- this.editorContainer.clear();
4210
- this.editorContainer.addChild(this.editor);
4211
- this.ui.setFocus(this.editor);
4212
- this.ui.requestRender();
4213
- };
4214
- const dialog = new LoginDialogComponent(this.ui, providerId, () => restoreEditor(), providerName, "Amazon Bedrock setup");
4215
- dialog.showInfo([
4216
- theme.fg("text", "Amazon Bedrock uses AWS credentials instead of a single API key."),
4217
- theme.fg("text", "Configure an AWS profile, IAM keys, bearer token, or role-based credentials."),
4218
- theme.fg("muted", "See:"),
4219
- theme.fg("accent", ` ${path.join(getDocsPath(), "providers.md")}`),
4220
- ]);
4221
- this.editorContainer.clear();
4222
- this.editorContainer.addChild(dialog);
4223
- this.ui.setFocus(dialog);
4224
- this.ui.requestRender();
4225
- }
4226
4221
  async showApiKeyLoginDialog(providerId, providerName) {
4227
4222
  const previousModel = this.session.model;
4228
4223
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
4229
4224
  // Completion handled below
4230
4225
  }, providerName);
4226
+ if (providerId === "amazon-bedrock") {
4227
+ dialog.showDetails([
4228
+ theme.fg("text", "You can also use an AWS profile, IAM keys, or role-based credentials."),
4229
+ theme.fg("muted", "See:"),
4230
+ theme.fg("accent", ` ${path.join(getDocsPath(), "providers.md")}`),
4231
+ ]);
4232
+ }
4231
4233
  this.editorContainer.clear();
4232
4234
  this.editorContainer.addChild(dialog);
4233
4235
  this.ui.setFocus(dialog);
@@ -4793,6 +4795,7 @@ export class InteractiveMode {
4793
4795
  const toggleThinking = this.getAppKeyDisplay("app.thinking.toggle");
4794
4796
  const externalEditor = this.getAppKeyDisplay("app.editor.external");
4795
4797
  const cycleModelBackward = this.getAppKeyDisplay("app.model.cycleBackward");
4798
+ const copyMessage = this.getAppKeyDisplay("app.message.copy");
4796
4799
  const followUp = this.getAppKeyDisplay("app.message.followUp");
4797
4800
  const dequeue = this.getAppKeyDisplay("app.message.dequeue");
4798
4801
  const pasteImage = this.getAppKeyDisplay("app.clipboard.pasteImage");
@@ -4835,9 +4838,10 @@ export class InteractiveMode {
4835
4838
  | \`${expandTools}\` | Toggle tool output expansion |
4836
4839
  | \`${toggleThinking}\` | Toggle thinking block visibility |
4837
4840
  | \`${externalEditor}\` | Edit message in external editor |
4841
+ | \`${copyMessage}\` | Copy last assistant message |
4838
4842
  | \`${followUp}\` | Queue follow-up message |
4839
4843
  | \`${dequeue}\` | Restore queued messages |
4840
- | \`${pasteImage}\` | Paste image from clipboard |
4844
+ | \`${pasteImage}\` | Paste image or text from clipboard |
4841
4845
  | \`/\` | Slash commands |
4842
4846
  | \`!\` | Run bash command |
4843
4847
  | \`!!\` | Run bash command (excluded from context) |