@ryan_nookpi/pi-extension-clipboard 0.1.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.
- package/README.md +15 -0
- package/index.ts +94 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @ryan_nookpi/pi-extension-clipboard
|
|
2
|
+
|
|
3
|
+
Clipboard copy tool for pi using OSC52 escape sequences.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install /Users/creatrip/Documents/pi-extension/packages/clipboard
|
|
9
|
+
pi install npm:@ryan_nookpi/pi-extension-clipboard
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What it provides
|
|
13
|
+
|
|
14
|
+
- `copy_to_clipboard` tool
|
|
15
|
+
- `./index.ts` entry
|
package/index.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clipboard Extension
|
|
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.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* Ask the LLM: "write me a draft reply and put it into clipboard!"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
13
|
+
import { Type } from "@sinclair/typebox";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Encode text to base64 for OSC52
|
|
17
|
+
*/
|
|
18
|
+
function toBase64(text: string): string {
|
|
19
|
+
return Buffer.from(text, "utf-8").toString("base64");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Copy text to clipboard using OSC52 escape sequence.
|
|
24
|
+
* OSC52 is supported by most modern terminal emulators including:
|
|
25
|
+
* - iTerm2, Kitty, Alacritty, WezTerm, foot, Windows Terminal
|
|
26
|
+
* - tmux (with set-clipboard on), screen (with proper config)
|
|
27
|
+
*/
|
|
28
|
+
function copyToClipboard(text: string): void {
|
|
29
|
+
const base64Text = toBase64(text);
|
|
30
|
+
// OSC 52 ; c ; <base64-text> ST
|
|
31
|
+
// \x1b] = OSC (Operating System Command)
|
|
32
|
+
// 52 = clipboard operation
|
|
33
|
+
// c = clipboard selection (could also be p for primary, s for secondary)
|
|
34
|
+
// \x07 = ST (String Terminator) - also \x1b\\ works
|
|
35
|
+
const osc52 = `\x1b]52;c;${base64Text}\x07`;
|
|
36
|
+
process.stdout.write(osc52);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default function clipboardExtension(pi: ExtensionAPI): void {
|
|
40
|
+
pi.registerTool({
|
|
41
|
+
name: "copy_to_clipboard",
|
|
42
|
+
label: "Copy to Clipboard",
|
|
43
|
+
description:
|
|
44
|
+
"Copy text to the user's system clipboard. Use this when the user asks you to " +
|
|
45
|
+
"put something in their clipboard, write a draft reply to clipboard, or copy any " +
|
|
46
|
+
"generated text for easy pasting. The text will be available for pasting immediately.",
|
|
47
|
+
parameters: Type.Object({
|
|
48
|
+
text: Type.String({
|
|
49
|
+
description: "The text to copy to the clipboard",
|
|
50
|
+
}),
|
|
51
|
+
}),
|
|
52
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
53
|
+
const { text } = params as { text: string };
|
|
54
|
+
|
|
55
|
+
if (!text || text.trim().length === 0) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: "Error: No text provided to copy." }],
|
|
58
|
+
details: { success: false, error: "empty_text" },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
copyToClipboard(text);
|
|
64
|
+
|
|
65
|
+
const preview = text.length > 100 ? `${text.slice(0, 100)}...` : text;
|
|
66
|
+
const charCount = text.length;
|
|
67
|
+
|
|
68
|
+
if (ctx.hasUI) {
|
|
69
|
+
ctx.ui.notify(`Copied ${charCount} characters to clipboard`, "info");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
content: [
|
|
74
|
+
{
|
|
75
|
+
type: "text",
|
|
76
|
+
text: `Successfully copied ${charCount} characters to clipboard.\n\nPreview:\n${preview}`,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
details: {
|
|
80
|
+
success: true,
|
|
81
|
+
characterCount: charCount,
|
|
82
|
+
preview,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text", text: `Failed to copy to clipboard: ${errorMessage}` }],
|
|
89
|
+
details: { success: false, error: errorMessage },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ryan_nookpi/pi-extension-clipboard",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Clipboard copy tool extension for pi using OSC52 escape sequences.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package"
|
|
8
|
+
],
|
|
9
|
+
"files": [
|
|
10
|
+
"index.ts",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"pi": {
|
|
14
|
+
"extensions": [
|
|
15
|
+
"./index.ts"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
20
|
+
"@sinclair/typebox": "*"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
}
|
|
25
|
+
}
|