@averyyy/pi-coding-agent 0.80.6-piclient.5 → 0.80.6-piclient.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 (44) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -1
  3. package/dist/core/extensions/runner.d.ts +1 -0
  4. package/dist/core/extensions/runner.d.ts.map +1 -1
  5. package/dist/core/extensions/runner.js +5 -0
  6. package/dist/core/extensions/runner.js.map +1 -1
  7. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  8. package/dist/core/extensions/wrapper.js +22 -3
  9. package/dist/core/extensions/wrapper.js.map +1 -1
  10. package/dist/core/keybindings.d.ts +8 -3
  11. package/dist/core/keybindings.d.ts.map +1 -1
  12. package/dist/core/keybindings.js +7 -3
  13. package/dist/core/keybindings.js.map +1 -1
  14. package/dist/core/model-registry.d.ts.map +1 -1
  15. package/dist/core/model-registry.js +2 -0
  16. package/dist/core/model-registry.js.map +1 -1
  17. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  18. package/dist/modes/interactive/components/custom-editor.js +1 -1
  19. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  20. package/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  21. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  22. package/dist/modes/interactive/components/login-dialog.js +9 -2
  23. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  24. package/dist/modes/interactive/components/tree-selector.d.ts +5 -0
  25. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  26. package/dist/modes/interactive/components/tree-selector.js +49 -12
  27. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  28. package/dist/modes/interactive/interactive-mode.d.ts +1 -2
  29. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  30. package/dist/modes/interactive/interactive-mode.js +43 -39
  31. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  32. package/dist/utils/clipboard-native.d.ts +1 -0
  33. package/dist/utils/clipboard-native.d.ts.map +1 -1
  34. package/dist/utils/clipboard-native.js.map +1 -1
  35. package/dist/utils/clipboard.d.ts +2 -0
  36. package/dist/utils/clipboard.d.ts.map +1 -1
  37. package/dist/utils/clipboard.js +13 -0
  38. package/dist/utils/clipboard.js.map +1 -1
  39. package/docs/extensions.md +138 -0
  40. package/docs/keybindings.md +1 -0
  41. package/docs/providers.md +3 -0
  42. package/docs/quickstart.md +1 -1
  43. package/docs/usage.md +1 -0
  44. package/package.json +4 -4
@@ -28,7 +28,7 @@ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
28
28
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
29
29
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
30
30
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
31
- import { copyToClipboard } from "../../utils/clipboard.js";
31
+ import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
32
32
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
33
33
  import { parseGitUrl } from "../../utils/git.js";
34
34
  import { getCwdRelativePath } from "../../utils/paths.js";
@@ -126,7 +126,6 @@ export function formatResumeCommand(sessionManager) {
126
126
  function hasDefaultModelProvider(providerId) {
127
127
  return providerId in defaultModelPerProvider;
128
128
  }
129
- const BEDROCK_PROVIDER_ID = "amazon-bedrock";
130
129
  const BUILT_IN_MODEL_PROVIDERS = new Set(getProviders());
131
130
  export function isApiKeyLoginProvider(providerId, oauthProviderIds, builtInProviderIds = BUILT_IN_MODEL_PROVIDERS) {
132
131
  if (BUILT_IN_PROVIDER_DISPLAY_NAMES[providerId]) {
@@ -533,7 +532,7 @@ export class InteractiveMode {
533
532
  rawKeyHint("!!", "to run bash (no context)"),
534
533
  hint("app.message.followUp", "to queue follow-up"),
535
534
  hint("app.message.dequeue", "to edit all queued messages"),
536
- hint("app.clipboard.pasteImage", "to paste image"),
535
+ hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
537
536
  rawKeyHint("drop files", "to attach"),
538
537
  ].join("\n");
539
538
  const compactInstructions = [
@@ -2035,6 +2034,7 @@ export class InteractiveMode {
2035
2034
  this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
2036
2035
  this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
2037
2036
  this.defaultEditor.onAction("app.editor.external", () => this.openExternalEditor());
2037
+ this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
2038
2038
  this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
2039
2039
  this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
2040
2040
  this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
@@ -2048,26 +2048,30 @@ export class InteractiveMode {
2048
2048
  this.updateEditorBorderColor();
2049
2049
  }
2050
2050
  };
2051
- // Handle clipboard image paste (triggered on Ctrl+V)
2051
+ // Handle clipboard paste (triggered on Ctrl+V). Images are attached by path;
2052
+ // otherwise, paste plain text from the system clipboard.
2052
2053
  this.defaultEditor.onPasteImage = () => {
2053
- this.handleClipboardImagePaste();
2054
+ void this.handleClipboardPaste();
2054
2055
  };
2055
2056
  }
2056
- async handleClipboardImagePaste() {
2057
+ async handleClipboardPaste() {
2057
2058
  try {
2058
2059
  const image = await readClipboardImage();
2059
- if (!image) {
2060
+ if (image) {
2061
+ const tmpDir = os.tmpdir();
2062
+ const ext = extensionForImageMimeType(image.mimeType) ?? "png";
2063
+ const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
2064
+ const filePath = path.join(tmpDir, fileName);
2065
+ fs.writeFileSync(filePath, Buffer.from(image.bytes));
2066
+ this.editor.insertTextAtCursor?.(filePath);
2067
+ this.ui.requestRender();
2060
2068
  return;
2061
2069
  }
2062
- // Write to temp file
2063
- const tmpDir = os.tmpdir();
2064
- const ext = extensionForImageMimeType(image.mimeType) ?? "png";
2065
- const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
2066
- const filePath = path.join(tmpDir, fileName);
2067
- fs.writeFileSync(filePath, Buffer.from(image.bytes));
2068
- // Insert file path directly
2069
- this.editor.insertTextAtCursor?.(filePath);
2070
- this.ui.requestRender();
2070
+ const text = await readClipboardText();
2071
+ if (text) {
2072
+ this.editor.insertTextAtCursor?.(text);
2073
+ this.ui.requestRender();
2074
+ }
2071
2075
  }
2072
2076
  catch {
2073
2077
  // Silently ignore clipboard errors (may not have permission, etc.)
@@ -3908,6 +3912,19 @@ export class InteractiveMode {
3908
3912
  this.sessionManager.appendLabelChange(entryId, label);
3909
3913
  this.ui.requestRender();
3910
3914
  }, initialSelectedId, initialFilterMode);
3915
+ selector.onCopy = async (text) => {
3916
+ if (!text) {
3917
+ this.showError("Selected entry has no text to copy");
3918
+ return;
3919
+ }
3920
+ try {
3921
+ await copyToClipboard(text);
3922
+ this.showStatus("Copied selected message to clipboard");
3923
+ }
3924
+ catch (error) {
3925
+ this.showError(error instanceof Error ? error.message : String(error));
3926
+ }
3927
+ };
3911
3928
  return { component: selector, focus: selector };
3912
3929
  });
3913
3930
  }
@@ -4041,9 +4058,6 @@ export class InteractiveMode {
4041
4058
  if (providerOption.authType === "oauth") {
4042
4059
  await this.showLoginDialog(providerOption.id, providerOption.name);
4043
4060
  }
4044
- else if (providerOption.id === BEDROCK_PROVIDER_ID) {
4045
- this.showBedrockSetupDialog(providerOption.id, providerOption.name);
4046
- }
4047
4061
  else {
4048
4062
  await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
4049
4063
  }
@@ -4211,30 +4225,18 @@ export class InteractiveMode {
4211
4225
  }
4212
4226
  }
4213
4227
  }
4214
- showBedrockSetupDialog(providerId, providerName) {
4215
- const restoreEditor = () => {
4216
- this.editorContainer.clear();
4217
- this.editorContainer.addChild(this.editor);
4218
- this.ui.setFocus(this.editor);
4219
- this.ui.requestRender();
4220
- };
4221
- const dialog = new LoginDialogComponent(this.ui, providerId, () => restoreEditor(), providerName, "Amazon Bedrock setup");
4222
- dialog.showInfo([
4223
- theme.fg("text", "Amazon Bedrock uses AWS credentials instead of a single API key."),
4224
- theme.fg("text", "Configure an AWS profile, IAM keys, bearer token, or role-based credentials."),
4225
- theme.fg("muted", "See:"),
4226
- theme.fg("accent", ` ${path.join(getDocsPath(), "providers.md")}`),
4227
- ]);
4228
- this.editorContainer.clear();
4229
- this.editorContainer.addChild(dialog);
4230
- this.ui.setFocus(dialog);
4231
- this.ui.requestRender();
4232
- }
4233
4228
  async showApiKeyLoginDialog(providerId, providerName) {
4234
4229
  const previousModel = this.session.model;
4235
4230
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
4236
4231
  // Completion handled below
4237
4232
  }, providerName);
4233
+ if (providerId === "amazon-bedrock") {
4234
+ dialog.showDetails([
4235
+ theme.fg("text", "You can also use an AWS profile, IAM keys, or role-based credentials."),
4236
+ theme.fg("muted", "See:"),
4237
+ theme.fg("accent", ` ${path.join(getDocsPath(), "providers.md")}`),
4238
+ ]);
4239
+ }
4238
4240
  this.editorContainer.clear();
4239
4241
  this.editorContainer.addChild(dialog);
4240
4242
  this.ui.setFocus(dialog);
@@ -4819,6 +4821,7 @@ export class InteractiveMode {
4819
4821
  const toggleThinking = this.getAppKeyDisplay("app.thinking.toggle");
4820
4822
  const externalEditor = this.getAppKeyDisplay("app.editor.external");
4821
4823
  const cycleModelBackward = this.getAppKeyDisplay("app.model.cycleBackward");
4824
+ const copyMessage = this.getAppKeyDisplay("app.message.copy");
4822
4825
  const followUp = this.getAppKeyDisplay("app.message.followUp");
4823
4826
  const dequeue = this.getAppKeyDisplay("app.message.dequeue");
4824
4827
  const pasteImage = this.getAppKeyDisplay("app.clipboard.pasteImage");
@@ -4861,9 +4864,10 @@ export class InteractiveMode {
4861
4864
  | \`${expandTools}\` | Toggle tool output expansion |
4862
4865
  | \`${toggleThinking}\` | Toggle thinking block visibility |
4863
4866
  | \`${externalEditor}\` | Edit message in external editor |
4867
+ | \`${copyMessage}\` | Copy last assistant message |
4864
4868
  | \`${followUp}\` | Queue follow-up message |
4865
4869
  | \`${dequeue}\` | Restore queued messages |
4866
- | \`${pasteImage}\` | Paste image from clipboard |
4870
+ | \`${pasteImage}\` | Paste image or text from clipboard |
4867
4871
  | \`/\` | Slash commands |
4868
4872
  | \`!\` | Run bash command |
4869
4873
  | \`!!\` | Run bash command (excluded from context) |