pi-interactive-shell 0.4.9 → 0.5.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/CHANGELOG.md +25 -0
- package/README.md +10 -4
- package/SKILL.md +20 -18
- package/index.ts +20 -11
- package/package.json +1 -1
- package/tool-schema.ts +30 -35
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the `pi-interactive-shell` extension will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.5.0] - 2026-01-22
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- **BREAKING: Split `input` into separate fields for Vertex AI compatibility** - The `input` parameter which previously accepted either a string or an object with `text/keys/hex/paste` fields has been split into separate parameters:
|
|
9
|
+
- `input` - Raw text/keystrokes (string only)
|
|
10
|
+
- `inputKeys` - Named keys array (e.g., `["ctrl+c", "enter"]`)
|
|
11
|
+
- `inputHex` - Hex bytes array for raw escape sequences
|
|
12
|
+
- `inputPaste` - Text for bracketed paste mode
|
|
13
|
+
|
|
14
|
+
This change was required because Claude's Vertex AI API (`google-antigravity` provider) rejects `anyOf` JSON schemas with mixed primitive/object types.
|
|
15
|
+
|
|
16
|
+
### Migration
|
|
17
|
+
```typescript
|
|
18
|
+
// Before (0.4.x)
|
|
19
|
+
interactive_shell({ sessionId: "abc", input: { keys: ["ctrl+c"] } })
|
|
20
|
+
interactive_shell({ sessionId: "abc", input: { paste: "code" } })
|
|
21
|
+
|
|
22
|
+
// After (0.5.0)
|
|
23
|
+
interactive_shell({ sessionId: "abc", inputKeys: ["ctrl+c"] })
|
|
24
|
+
interactive_shell({ sessionId: "abc", inputPaste: "code" })
|
|
25
|
+
|
|
26
|
+
// Combining text with keys (still works)
|
|
27
|
+
interactive_shell({ sessionId: "abc", input: "y", inputKeys: ["enter"] })
|
|
28
|
+
```
|
|
29
|
+
|
|
5
30
|
## [0.4.9] - 2026-01-21
|
|
6
31
|
|
|
7
32
|
### Fixed
|
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ interactive_shell({ sessionId: "calm-reef" })
|
|
|
60
60
|
// → { status: "running", output: "...", runtime: 45000 }
|
|
61
61
|
|
|
62
62
|
// Send input if needed
|
|
63
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
63
|
+
interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] })
|
|
64
64
|
|
|
65
65
|
// Kill when done
|
|
66
66
|
interactive_shell({ sessionId: "calm-reef", kill: true })
|
|
@@ -103,11 +103,17 @@ For multi-turn sessions where you need back-and-forth interaction, leave it disa
|
|
|
103
103
|
interactive_shell({ sessionId: "calm-reef", input: "SELECT * FROM users;\n" })
|
|
104
104
|
|
|
105
105
|
// Named keys
|
|
106
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
107
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
106
|
+
interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] })
|
|
107
|
+
interactive_shell({ sessionId: "calm-reef", inputKeys: ["down", "down", "enter"] })
|
|
108
108
|
|
|
109
109
|
// Bracketed paste (multiline without execution)
|
|
110
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
110
|
+
interactive_shell({ sessionId: "calm-reef", inputPaste: "line1\nline2\nline3" })
|
|
111
|
+
|
|
112
|
+
// Hex bytes (raw escape sequences)
|
|
113
|
+
interactive_shell({ sessionId: "calm-reef", inputHex: ["0x1b", "0x5b", "0x41"] })
|
|
114
|
+
|
|
115
|
+
// Combine text with keys
|
|
116
|
+
interactive_shell({ sessionId: "calm-reef", input: "y", inputKeys: ["enter"] })
|
|
111
117
|
```
|
|
112
118
|
|
|
113
119
|
### Configurable Output
|
package/SKILL.md
CHANGED
|
@@ -161,7 +161,9 @@ interactive_shell({ sessionId: "calm-reef", kill: true })
|
|
|
161
161
|
### Sending Input
|
|
162
162
|
```typescript
|
|
163
163
|
interactive_shell({ sessionId: "calm-reef", input: "/help\n" })
|
|
164
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
164
|
+
interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] })
|
|
165
|
+
interactive_shell({ sessionId: "calm-reef", inputPaste: "multi\nline\ncode" })
|
|
166
|
+
interactive_shell({ sessionId: "calm-reef", input: "y", inputKeys: ["enter"] }) // combine text + keys
|
|
165
167
|
```
|
|
166
168
|
|
|
167
169
|
### Query Output
|
|
@@ -223,14 +225,14 @@ Use the `sessionId` from updates to send input to a running hands-free session:
|
|
|
223
225
|
// Send text
|
|
224
226
|
interactive_shell({ sessionId: "shell-1", input: "/help\n" })
|
|
225
227
|
|
|
226
|
-
// Send with
|
|
227
|
-
interactive_shell({ sessionId: "shell-1", input:
|
|
228
|
+
// Send text with keys
|
|
229
|
+
interactive_shell({ sessionId: "shell-1", input: "/model", inputKeys: ["enter"] })
|
|
228
230
|
|
|
229
231
|
// Navigate menus
|
|
230
|
-
interactive_shell({ sessionId: "shell-1",
|
|
232
|
+
interactive_shell({ sessionId: "shell-1", inputKeys: ["down", "down", "enter"] })
|
|
231
233
|
|
|
232
234
|
// Interrupt
|
|
233
|
-
interactive_shell({ sessionId: "shell-1",
|
|
235
|
+
interactive_shell({ sessionId: "shell-1", inputKeys: ["ctrl+c"] })
|
|
234
236
|
```
|
|
235
237
|
|
|
236
238
|
### Named Keys
|
|
@@ -257,45 +259,45 @@ Note: `ic`/`dc`, `ppage`/`npage`, `bspace` are tmux-style aliases for compatibil
|
|
|
257
259
|
Supports `ctrl+`, `alt+`, `shift+` prefixes (or shorthand `c-`, `m-`, `s-`):
|
|
258
260
|
```typescript
|
|
259
261
|
// Cancel
|
|
260
|
-
|
|
262
|
+
inputKeys: ["ctrl+c"]
|
|
261
263
|
|
|
262
264
|
// Alt+Tab
|
|
263
|
-
|
|
265
|
+
inputKeys: ["alt+tab"]
|
|
264
266
|
|
|
265
267
|
// Ctrl+Alt+Delete
|
|
266
|
-
|
|
268
|
+
inputKeys: ["ctrl+alt+delete"]
|
|
267
269
|
|
|
268
270
|
// Shorthand syntax
|
|
269
|
-
|
|
271
|
+
inputKeys: ["c-c", "m-x", "s-tab"]
|
|
270
272
|
```
|
|
271
273
|
|
|
272
274
|
### Hex Bytes (Advanced)
|
|
273
275
|
Send raw escape sequences:
|
|
274
276
|
```typescript
|
|
275
|
-
|
|
277
|
+
inputHex: ["0x1b", "0x5b", "0x41"] // ESC[A (up arrow)
|
|
276
278
|
```
|
|
277
279
|
|
|
278
280
|
### Bracketed Paste
|
|
279
281
|
Paste multiline text without triggering autocompletion/execution:
|
|
280
282
|
```typescript
|
|
281
|
-
|
|
283
|
+
inputPaste: "function foo() {\n return 42;\n}"
|
|
282
284
|
```
|
|
283
285
|
|
|
284
286
|
### Model Selection Example
|
|
285
287
|
```typescript
|
|
286
288
|
// Step 1: Open model selector
|
|
287
|
-
interactive_shell({ sessionId: "shell-1", input:
|
|
289
|
+
interactive_shell({ sessionId: "shell-1", input: "/model", inputKeys: ["enter"] })
|
|
288
290
|
|
|
289
291
|
// Step 2: Filter and select (after ~500ms delay)
|
|
290
|
-
interactive_shell({ sessionId: "shell-1", input:
|
|
292
|
+
interactive_shell({ sessionId: "shell-1", input: "sonnet", inputKeys: ["enter"] })
|
|
291
293
|
|
|
292
294
|
// Or navigate with arrows:
|
|
293
|
-
interactive_shell({ sessionId: "shell-1",
|
|
295
|
+
interactive_shell({ sessionId: "shell-1", inputKeys: ["down", "down", "down", "enter"] })
|
|
294
296
|
```
|
|
295
297
|
|
|
296
298
|
### Context Compaction
|
|
297
299
|
```typescript
|
|
298
|
-
interactive_shell({ sessionId: "shell-1", input:
|
|
300
|
+
interactive_shell({ sessionId: "shell-1", input: "/compact", inputKeys: ["enter"] })
|
|
299
301
|
```
|
|
300
302
|
|
|
301
303
|
### Changing Update Settings
|
|
@@ -396,11 +398,11 @@ interactive_shell({
|
|
|
396
398
|
// Text with enter
|
|
397
399
|
interactive_shell({ sessionId: "calm-reef", input: "/compact\n" })
|
|
398
400
|
|
|
399
|
-
//
|
|
400
|
-
interactive_shell({ sessionId: "calm-reef", input:
|
|
401
|
+
// Text + named keys
|
|
402
|
+
interactive_shell({ sessionId: "calm-reef", input: "/model", inputKeys: ["enter"] })
|
|
401
403
|
|
|
402
404
|
// Menu navigation
|
|
403
|
-
interactive_shell({ sessionId: "calm-reef",
|
|
405
|
+
interactive_shell({ sessionId: "calm-reef", inputKeys: ["down", "down", "enter"] })
|
|
404
406
|
```
|
|
405
407
|
|
|
406
408
|
**Change update frequency:**
|
package/index.ts
CHANGED
|
@@ -31,6 +31,9 @@ export default function interactiveShellExtension(pi: ExtensionAPI) {
|
|
|
31
31
|
incremental,
|
|
32
32
|
settings,
|
|
33
33
|
input,
|
|
34
|
+
inputKeys,
|
|
35
|
+
inputHex,
|
|
36
|
+
inputPaste,
|
|
34
37
|
cwd,
|
|
35
38
|
name,
|
|
36
39
|
reason,
|
|
@@ -41,6 +44,12 @@ export default function interactiveShellExtension(pi: ExtensionAPI) {
|
|
|
41
44
|
timeout,
|
|
42
45
|
} = params as ToolParams;
|
|
43
46
|
|
|
47
|
+
// Build structured input from separate fields if any are provided
|
|
48
|
+
const hasStructuredInput = inputKeys?.length || inputHex?.length || inputPaste;
|
|
49
|
+
const effectiveInput = hasStructuredInput
|
|
50
|
+
? { text: input, keys: inputKeys, hex: inputHex, paste: inputPaste }
|
|
51
|
+
: input;
|
|
52
|
+
|
|
44
53
|
// Mode 1: Interact with existing session (query status, send input, kill, or change settings)
|
|
45
54
|
if (sessionId) {
|
|
46
55
|
const session = sessionManager.getActive(sessionId);
|
|
@@ -100,8 +109,8 @@ export default function interactiveShellExtension(pi: ExtensionAPI) {
|
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
// Send input if provided
|
|
103
|
-
if (
|
|
104
|
-
const translatedInput = translateInput(
|
|
112
|
+
if (effectiveInput !== undefined) {
|
|
113
|
+
const translatedInput = translateInput(effectiveInput);
|
|
105
114
|
const success = sessionManager.writeToActive(sessionId, translatedInput);
|
|
106
115
|
|
|
107
116
|
if (!success) {
|
|
@@ -113,17 +122,17 @@ export default function interactiveShellExtension(pi: ExtensionAPI) {
|
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
const inputDesc =
|
|
116
|
-
typeof
|
|
117
|
-
?
|
|
125
|
+
typeof effectiveInput === "string"
|
|
126
|
+
? effectiveInput.length === 0
|
|
118
127
|
? "(empty)"
|
|
119
|
-
:
|
|
120
|
-
? `${
|
|
121
|
-
:
|
|
128
|
+
: effectiveInput.length > 50
|
|
129
|
+
? `${effectiveInput.slice(0, 50)}...`
|
|
130
|
+
: effectiveInput
|
|
122
131
|
: [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
effectiveInput.text ?? "",
|
|
133
|
+
effectiveInput.keys ? `keys:[${effectiveInput.keys.join(",")}]` : "",
|
|
134
|
+
effectiveInput.hex ? `hex:[${effectiveInput.hex.length} bytes]` : "",
|
|
135
|
+
effectiveInput.paste ? `paste:[${effectiveInput.paste.length} chars]` : "",
|
|
127
136
|
]
|
|
128
137
|
.filter(Boolean)
|
|
129
138
|
.join(" + ") || "(empty)";
|
package/package.json
CHANGED
package/tool-schema.ts
CHANGED
|
@@ -54,13 +54,14 @@ Queries are limited to once every 60 seconds (configurable). If you query too so
|
|
|
54
54
|
the tool will automatically wait until the limit expires before returning.
|
|
55
55
|
|
|
56
56
|
SENDING INPUT:
|
|
57
|
-
- interactive_shell({ sessionId: "calm-reef", input: "/help\\n" })
|
|
58
|
-
- interactive_shell({ sessionId: "calm-reef",
|
|
57
|
+
- interactive_shell({ sessionId: "calm-reef", input: "/help\\n" }) - raw text/keystrokes
|
|
58
|
+
- interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] }) - named keys
|
|
59
|
+
- interactive_shell({ sessionId: "calm-reef", inputKeys: ["up", "up", "enter"] }) - multiple keys
|
|
60
|
+
- interactive_shell({ sessionId: "calm-reef", inputHex: ["0x1b", "0x5b", "0x41"] }) - raw escape sequences
|
|
61
|
+
- interactive_shell({ sessionId: "calm-reef", inputPaste: "multiline\\ntext" }) - bracketed paste (prevents auto-execution)
|
|
59
62
|
|
|
60
|
-
Named keys: up, down, left, right, enter, escape, tab, backspace, ctrl+c, ctrl+d, etc.
|
|
63
|
+
Named keys for inputKeys: up, down, left, right, enter, escape, tab, backspace, ctrl+c, ctrl+d, etc.
|
|
61
64
|
Modifiers: ctrl+x, alt+x, shift+tab, ctrl+alt+delete (or c-x, m-x, s-tab syntax)
|
|
62
|
-
Hex bytes: input: { hex: ["0x1b", "0x5b", "0x41"] } for raw escape sequences
|
|
63
|
-
Bracketed paste: input: { paste: "multiline\\ntext" } prevents auto-execution
|
|
64
65
|
|
|
65
66
|
TIMEOUT (for TUI commands that don't exit cleanly):
|
|
66
67
|
Use timeout to auto-kill after N milliseconds. Useful for capturing output from commands like "pi --help":
|
|
@@ -128,31 +129,22 @@ export const toolParameters = Type.Object({
|
|
|
128
129
|
}),
|
|
129
130
|
),
|
|
130
131
|
input: Type.Optional(
|
|
131
|
-
Type.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
paste: Type.Optional(
|
|
148
|
-
Type.String({
|
|
149
|
-
description: "Text to paste with bracketed paste mode (prevents auto-execution)",
|
|
150
|
-
}),
|
|
151
|
-
),
|
|
152
|
-
}),
|
|
153
|
-
],
|
|
154
|
-
{ description: "Input to send to an existing session (requires sessionId)" },
|
|
155
|
-
),
|
|
132
|
+
Type.String({ description: "Raw text/keystrokes to send to the session (requires sessionId). For special keys, use inputKeys instead." }),
|
|
133
|
+
),
|
|
134
|
+
inputKeys: Type.Optional(
|
|
135
|
+
Type.Array(Type.String(), {
|
|
136
|
+
description: "Named keys with modifier support: up, down, enter, ctrl+c, alt+x, shift+tab, ctrl+alt+delete, etc. (requires sessionId)",
|
|
137
|
+
}),
|
|
138
|
+
),
|
|
139
|
+
inputHex: Type.Optional(
|
|
140
|
+
Type.Array(Type.String(), {
|
|
141
|
+
description: "Hex bytes to send as raw escape sequences (e.g., ['0x1b', '0x5b', '0x41'] for ESC[A). (requires sessionId)",
|
|
142
|
+
}),
|
|
143
|
+
),
|
|
144
|
+
inputPaste: Type.Optional(
|
|
145
|
+
Type.String({
|
|
146
|
+
description: "Text to paste with bracketed paste mode - prevents shells from auto-executing multiline input. (requires sessionId)",
|
|
147
|
+
}),
|
|
156
148
|
),
|
|
157
149
|
cwd: Type.Optional(
|
|
158
150
|
Type.String({
|
|
@@ -171,15 +163,15 @@ export const toolParameters = Type.Object({
|
|
|
171
163
|
}),
|
|
172
164
|
),
|
|
173
165
|
mode: Type.Optional(
|
|
174
|
-
Type.
|
|
175
|
-
description: "interactive (default
|
|
166
|
+
Type.String({
|
|
167
|
+
description: "Mode: 'interactive' (default, user controls) or 'hands-free' (agent monitors, user can take over)",
|
|
176
168
|
}),
|
|
177
169
|
),
|
|
178
170
|
handsFree: Type.Optional(
|
|
179
171
|
Type.Object({
|
|
180
172
|
updateMode: Type.Optional(
|
|
181
|
-
Type.
|
|
182
|
-
description: "on-quiet (default
|
|
173
|
+
Type.String({
|
|
174
|
+
description: "Update mode: 'on-quiet' (default, emit when output stops) or 'interval' (emit on fixed schedule)",
|
|
183
175
|
}),
|
|
184
176
|
),
|
|
185
177
|
updateInterval: Type.Optional(
|
|
@@ -235,7 +227,10 @@ export interface ToolParams {
|
|
|
235
227
|
drain?: boolean;
|
|
236
228
|
incremental?: boolean;
|
|
237
229
|
settings?: { updateInterval?: number; quietThreshold?: number };
|
|
238
|
-
input?: string
|
|
230
|
+
input?: string;
|
|
231
|
+
inputKeys?: string[];
|
|
232
|
+
inputHex?: string[];
|
|
233
|
+
inputPaste?: string;
|
|
239
234
|
cwd?: string;
|
|
240
235
|
name?: string;
|
|
241
236
|
reason?: string;
|