@ryan_nookpi/pi-extension-clipboard 0.2.1 → 0.3.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 (3) hide show
  1. package/README.md +9 -2
  2. package/index.ts +112 -3
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ryan_nookpi/pi-extension-clipboard
2
2
 
3
- This extension lets pi copy generated text directly to your system clipboard.
3
+ This extension lets pi copy generated text directly to your system clipboard and paste your clipboard contents back into the conversation.
4
4
 
5
5
  It is especially handy for reply drafts, commit messages, PR descriptions, SQL queries, and other text you want to paste right away.
6
6
 
@@ -15,11 +15,18 @@ pi install npm:@ryan_nookpi/pi-extension-clipboard
15
15
  - "Write a reply draft and put it in my clipboard"
16
16
  - copying long outputs without selecting them manually
17
17
  - using clipboard copy from terminal or SSH-based workflows
18
+ - "Paste my clipboard and summarize / translate / refactor it"
19
+ - pulling logs, URLs, or snippets you just copied into the chat
18
20
 
19
21
  ## Example prompts
20
22
 
21
23
  - "Draft a Slack reply and copy it to my clipboard."
22
24
  - "Put this SQL query in my clipboard."
23
25
  - "Write a PR description and copy it for me."
26
+ - "Paste my clipboard and summarize what's in it."
27
+ - "Read my clipboard and translate it to English."
24
28
 
25
- After installation, pi can use the `copy_to_clipboard` tool to copy results instantly.
29
+ ## Tools
30
+
31
+ - `copy_to_clipboard` — copies text to the user's clipboard via OSC52 escape sequences (works over SSH and in most modern terminals).
32
+ - `paste_from_clipboard` — reads the current text contents of the user's clipboard using `pbpaste` (macOS), `xclip -selection clipboard -o` or `wl-paste` (Linux), or PowerShell `Get-Clipboard` (Windows).
package/index.ts CHANGED
@@ -1,14 +1,16 @@
1
1
  /**
2
2
  * Clipboard Extension
3
3
  *
4
- * Provides a tool that allows the LLM to copy text to the user's clipboard
5
- * using OSC52 escape sequences. This works across SSH sessions and most
6
- * modern terminal emulators.
4
+ * Provides tools that allow the LLM to copy text to the user's clipboard
5
+ * using OSC52 escape sequences and to paste text from the user's clipboard
6
+ * via OS-native commands (pbpaste / xclip / wl-paste / Get-Clipboard).
7
7
  *
8
8
  * Usage:
9
9
  * Ask the LLM: "write me a draft reply and put it into clipboard!"
10
+ * Ask the LLM: "paste my clipboard and summarize it."
10
11
  */
11
12
 
13
+ import { spawnSync } from "node:child_process";
12
14
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
13
15
  import { Type } from "@sinclair/typebox";
14
16
 
@@ -36,6 +38,63 @@ function copyToClipboard(text: string): void {
36
38
  process.stdout.write(osc52);
37
39
  }
38
40
 
41
+ interface PasteCommand {
42
+ command: string;
43
+ args: string[];
44
+ }
45
+
46
+ /**
47
+ * Resolve the OS-specific commands used to read the system clipboard.
48
+ * Linux returns multiple commands so the tool can fall back when one is missing.
49
+ */
50
+ function getPasteCommands(platform: NodeJS.Platform): PasteCommand[] {
51
+ switch (platform) {
52
+ case "darwin":
53
+ return [{ command: "pbpaste", args: [] }];
54
+ case "linux":
55
+ return [
56
+ { command: "xclip", args: ["-selection", "clipboard", "-o"] },
57
+ { command: "wl-paste", args: [] },
58
+ ];
59
+ case "win32":
60
+ return [
61
+ {
62
+ command: "powershell.exe",
63
+ args: ["-NoProfile", "-NonInteractive", "-Command", "Get-Clipboard"],
64
+ },
65
+ ];
66
+ default:
67
+ return [];
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Read the user's system clipboard text using the first available OS command.
73
+ * Throws when the platform is unsupported or every candidate command fails.
74
+ */
75
+ function readFromClipboard(): string {
76
+ const commands = getPasteCommands(process.platform);
77
+ if (commands.length === 0) {
78
+ throw new Error(`Clipboard read is not supported on ${process.platform}.`);
79
+ }
80
+
81
+ const errors: string[] = [];
82
+ for (const cmd of commands) {
83
+ const result = spawnSync(cmd.command, cmd.args, { encoding: "utf-8" });
84
+ if (result.error) {
85
+ errors.push(`${cmd.command}: ${result.error.message}`);
86
+ continue;
87
+ }
88
+ if (result.status !== 0) {
89
+ const stderr = (result.stderr ?? "").toString().trim();
90
+ errors.push(`${cmd.command} exited with ${result.status}${stderr ? `: ${stderr}` : ""}`);
91
+ continue;
92
+ }
93
+ return (result.stdout ?? "").toString();
94
+ }
95
+ throw new Error(`Failed to read clipboard. ${errors.join("; ")}`);
96
+ }
97
+
39
98
  export default function clipboardExtension(pi: ExtensionAPI): void {
40
99
  pi.registerTool({
41
100
  name: "copy_to_clipboard",
@@ -91,4 +150,54 @@ export default function clipboardExtension(pi: ExtensionAPI): void {
91
150
  }
92
151
  },
93
152
  });
153
+
154
+ pi.registerTool({
155
+ name: "paste_from_clipboard",
156
+ label: "Paste from Clipboard",
157
+ description:
158
+ "Read the current text contents of the user's system clipboard. Use this when the user " +
159
+ "asks you to read, paste, summarize, translate, or otherwise act on whatever they just " +
160
+ "copied. Uses pbpaste on macOS, xclip or wl-paste on Linux, and PowerShell Get-Clipboard " +
161
+ "on Windows.",
162
+ parameters: Type.Object({}),
163
+ async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
164
+ try {
165
+ const text = readFromClipboard();
166
+
167
+ if (!text || text.trim().length === 0) {
168
+ return {
169
+ content: [{ type: "text", text: "Clipboard is empty." }],
170
+ details: { success: false, error: "empty_clipboard" },
171
+ };
172
+ }
173
+
174
+ const charCount = text.length;
175
+ const preview = text.length > 100 ? `${text.slice(0, 100)}...` : text;
176
+
177
+ if (ctx.hasUI) {
178
+ ctx.ui.notify(`Pasted ${charCount} characters from clipboard`, "info");
179
+ }
180
+
181
+ return {
182
+ content: [
183
+ {
184
+ type: "text",
185
+ text: `Pasted ${charCount} characters from clipboard.\n\n${text}`,
186
+ },
187
+ ],
188
+ details: {
189
+ success: true,
190
+ characterCount: charCount,
191
+ preview,
192
+ },
193
+ };
194
+ } catch (error) {
195
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
196
+ return {
197
+ content: [{ type: "text", text: `Failed to paste from clipboard: ${errorMessage}` }],
198
+ details: { success: false, error: errorMessage },
199
+ };
200
+ }
201
+ },
202
+ });
94
203
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ryan_nookpi/pi-extension-clipboard",
3
- "version": "0.2.1",
4
- "description": "Clipboard copy tool extension for pi using OSC52 escape sequences.",
3
+ "version": "0.3.0",
4
+ "description": "Clipboard copy and paste tools for pi (OSC52 copy + pbpaste/xclip/wl-paste/Get-Clipboard paste).",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",