ai-code-connect 0.2.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 +330 -0
- package/dist/adapters/base.d.ts +57 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +28 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude.d.ts +45 -0
- package/dist/adapters/claude.d.ts.map +1 -0
- package/dist/adapters/claude.js +201 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/gemini.d.ts +31 -0
- package/dist/adapters/gemini.d.ts.map +1 -0
- package/dist/adapters/gemini.js +168 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +4 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +131 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/dist/persistent-pty.d.ts +154 -0
- package/dist/persistent-pty.d.ts.map +1 -0
- package/dist/persistent-pty.js +477 -0
- package/dist/persistent-pty.js.map +1 -0
- package/dist/sdk-session.d.ts +65 -0
- package/dist/sdk-session.d.ts.map +1 -0
- package/dist/sdk-session.js +1238 -0
- package/dist/sdk-session.js.map +1 -0
- package/dist/utils.d.ts +49 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +166 -0
- package/dist/utils.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +54 -0
- package/dist/version.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { IPty } from 'node-pty';
|
|
2
|
+
/**
|
|
3
|
+
* State machine for persistent PTY lifecycle
|
|
4
|
+
*/
|
|
5
|
+
export declare enum PtyState {
|
|
6
|
+
SPAWNING = "spawning",// PTY starting up, waiting for first prompt
|
|
7
|
+
IDLE = "idle",// Showing prompt, ready for input
|
|
8
|
+
PROCESSING = "processing",// Tool is generating a response
|
|
9
|
+
ATTACHED = "attached",// User is in interactive mode
|
|
10
|
+
DEAD = "dead"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for a persistent PTY session
|
|
14
|
+
*/
|
|
15
|
+
export interface PtyConfig {
|
|
16
|
+
/** Tool name (e.g., 'claude', 'gemini') */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Command to run (e.g., 'claude', 'gemini') */
|
|
19
|
+
command: string;
|
|
20
|
+
/** Arguments for the command */
|
|
21
|
+
args: string[];
|
|
22
|
+
/** Regex pattern to detect when tool is ready for input */
|
|
23
|
+
promptPattern: RegExp;
|
|
24
|
+
/** Fallback timeout in ms - if no output for this long, assume response complete */
|
|
25
|
+
idleTimeout: number;
|
|
26
|
+
/** Function to clean response output (remove UI noise) */
|
|
27
|
+
cleanResponse: (raw: string) => string;
|
|
28
|
+
/** ANSI color for this tool */
|
|
29
|
+
color: string;
|
|
30
|
+
/** Display name for this tool */
|
|
31
|
+
displayName: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Callback types for PTY events
|
|
35
|
+
*/
|
|
36
|
+
export interface PtyCallbacks {
|
|
37
|
+
/** Called when PTY process exits */
|
|
38
|
+
onExit?: (exitCode: number) => void;
|
|
39
|
+
/** Called when state changes */
|
|
40
|
+
onStateChange?: (state: PtyState) => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Manages a persistent PTY session for a single tool.
|
|
44
|
+
*
|
|
45
|
+
* The PTY runs continuously in the background:
|
|
46
|
+
* - Regular messages: Write to stdin, capture response via prompt detection
|
|
47
|
+
* - Interactive mode: Attach (forward stdin/stdout), detach (keep running)
|
|
48
|
+
*/
|
|
49
|
+
export declare class PersistentPtyManager {
|
|
50
|
+
private config;
|
|
51
|
+
private pty;
|
|
52
|
+
private state;
|
|
53
|
+
private outputBuffer;
|
|
54
|
+
private currentCapture;
|
|
55
|
+
private callbacks;
|
|
56
|
+
private cwd;
|
|
57
|
+
private headlessTerminal;
|
|
58
|
+
private serializeAddon;
|
|
59
|
+
private isAttached;
|
|
60
|
+
private attachedOutputHandler;
|
|
61
|
+
private isReady;
|
|
62
|
+
private readyPromise;
|
|
63
|
+
private readyResolve;
|
|
64
|
+
private suppressExitMessage;
|
|
65
|
+
constructor(config: PtyConfig);
|
|
66
|
+
/**
|
|
67
|
+
* Initialize the headless terminal for screen state tracking.
|
|
68
|
+
* This is used to properly capture output when tools use cursor positioning
|
|
69
|
+
* to redraw content (like Gemini's streaming).
|
|
70
|
+
*/
|
|
71
|
+
private initHeadlessTerminal;
|
|
72
|
+
/**
|
|
73
|
+
* Get current state
|
|
74
|
+
*/
|
|
75
|
+
getState(): PtyState;
|
|
76
|
+
/**
|
|
77
|
+
* Check if PTY is dead and needs respawn
|
|
78
|
+
*/
|
|
79
|
+
isDead(): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Check if PTY is processing a response
|
|
82
|
+
*/
|
|
83
|
+
isProcessing(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Check if user is currently attached
|
|
86
|
+
*/
|
|
87
|
+
isUserAttached(): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Get the output buffer (for reattach screen restore)
|
|
90
|
+
* Uses the headless terminal to get the actual visible screen content.
|
|
91
|
+
*/
|
|
92
|
+
getOutputBuffer(): string;
|
|
93
|
+
/**
|
|
94
|
+
* Clear the output buffer (used after sending a prompt to avoid capturing the typed input)
|
|
95
|
+
*/
|
|
96
|
+
clearOutputBuffer(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Set callbacks
|
|
99
|
+
*/
|
|
100
|
+
setCallbacks(callbacks: PtyCallbacks): void;
|
|
101
|
+
/**
|
|
102
|
+
* Spawn the PTY process
|
|
103
|
+
* @param cwd Working directory
|
|
104
|
+
* @param waitForReady If false, returns immediately after spawning (for interactive mode)
|
|
105
|
+
*/
|
|
106
|
+
spawn(cwd: string, waitForReady?: boolean): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Handle incoming data from PTY
|
|
109
|
+
*/
|
|
110
|
+
private handleData;
|
|
111
|
+
/**
|
|
112
|
+
* Reset the idle timeout (called on each output chunk)
|
|
113
|
+
*/
|
|
114
|
+
private resetIdleTimeout;
|
|
115
|
+
/**
|
|
116
|
+
* Complete the current response capture
|
|
117
|
+
*/
|
|
118
|
+
private completeCapture;
|
|
119
|
+
/**
|
|
120
|
+
* Handle PTY exit
|
|
121
|
+
*/
|
|
122
|
+
private handleExit;
|
|
123
|
+
/**
|
|
124
|
+
* Set state and notify callback
|
|
125
|
+
*/
|
|
126
|
+
private setState;
|
|
127
|
+
/**
|
|
128
|
+
* Send a message and capture the response.
|
|
129
|
+
* Waits for prompt detection or idle timeout to know when complete.
|
|
130
|
+
*/
|
|
131
|
+
sendAndCapture(message: string, timeout?: number): Promise<string>;
|
|
132
|
+
/**
|
|
133
|
+
* Write directly to PTY (for interactive mode)
|
|
134
|
+
*/
|
|
135
|
+
write(data: string): void;
|
|
136
|
+
/**
|
|
137
|
+
* Attach to PTY - forward output to stdout, allow stdin forwarding
|
|
138
|
+
*/
|
|
139
|
+
attach(): void;
|
|
140
|
+
/**
|
|
141
|
+
* Detach from PTY - stop forwarding, PTY keeps running
|
|
142
|
+
*/
|
|
143
|
+
detach(): void;
|
|
144
|
+
/**
|
|
145
|
+
* Kill the PTY process
|
|
146
|
+
* @param silent If true, suppress the onExit callback (for intentional kills)
|
|
147
|
+
*/
|
|
148
|
+
kill(silent?: boolean): void;
|
|
149
|
+
/**
|
|
150
|
+
* Get the underlying PTY for advanced operations
|
|
151
|
+
*/
|
|
152
|
+
getPty(): IPty | null;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=persistent-pty.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistent-pty.d.ts","sourceRoot":"","sources":["../src/persistent-pty.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import * as pty from 'node-pty';
|
|
2
|
+
import xtermHeadless from '@xterm/headless';
|
|
3
|
+
import serializeAddonPkg from '@xterm/addon-serialize';
|
|
4
|
+
import { stripAnsi } from './utils.js';
|
|
5
|
+
// ESM/CJS compatibility
|
|
6
|
+
const { Terminal } = xtermHeadless;
|
|
7
|
+
const { SerializeAddon } = serializeAddonPkg;
|
|
8
|
+
/**
|
|
9
|
+
* State machine for persistent PTY lifecycle
|
|
10
|
+
*/
|
|
11
|
+
export var PtyState;
|
|
12
|
+
(function (PtyState) {
|
|
13
|
+
PtyState["SPAWNING"] = "spawning";
|
|
14
|
+
PtyState["IDLE"] = "idle";
|
|
15
|
+
PtyState["PROCESSING"] = "processing";
|
|
16
|
+
PtyState["ATTACHED"] = "attached";
|
|
17
|
+
PtyState["DEAD"] = "dead"; // Process exited, needs respawn
|
|
18
|
+
})(PtyState || (PtyState = {}));
|
|
19
|
+
// Terminal sequences to filter
|
|
20
|
+
const FOCUS_IN_SEQ = '\x1b[I';
|
|
21
|
+
const FOCUS_OUT_SEQ = '\x1b[O';
|
|
22
|
+
/**
|
|
23
|
+
* Manages a persistent PTY session for a single tool.
|
|
24
|
+
*
|
|
25
|
+
* The PTY runs continuously in the background:
|
|
26
|
+
* - Regular messages: Write to stdin, capture response via prompt detection
|
|
27
|
+
* - Interactive mode: Attach (forward stdin/stdout), detach (keep running)
|
|
28
|
+
*/
|
|
29
|
+
export class PersistentPtyManager {
|
|
30
|
+
config;
|
|
31
|
+
pty = null;
|
|
32
|
+
state = PtyState.DEAD;
|
|
33
|
+
outputBuffer = '';
|
|
34
|
+
currentCapture = null;
|
|
35
|
+
callbacks = {};
|
|
36
|
+
cwd = process.cwd();
|
|
37
|
+
// Headless terminal for proper screen state tracking
|
|
38
|
+
// This handles cursor positioning, screen clears, etc. properly
|
|
39
|
+
headlessTerminal = null;
|
|
40
|
+
serializeAddon = null;
|
|
41
|
+
// For attach/detach
|
|
42
|
+
isAttached = false;
|
|
43
|
+
attachedOutputHandler = null;
|
|
44
|
+
// Track if we've seen the first prompt (tool is ready)
|
|
45
|
+
isReady = false;
|
|
46
|
+
readyPromise = null;
|
|
47
|
+
readyResolve = null;
|
|
48
|
+
// Flag to suppress exit messages when intentionally killed
|
|
49
|
+
suppressExitMessage = false;
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.config = config;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize the headless terminal for screen state tracking.
|
|
55
|
+
* This is used to properly capture output when tools use cursor positioning
|
|
56
|
+
* to redraw content (like Gemini's streaming).
|
|
57
|
+
*/
|
|
58
|
+
initHeadlessTerminal() {
|
|
59
|
+
this.headlessTerminal = new Terminal({
|
|
60
|
+
cols: process.stdout.columns || 80,
|
|
61
|
+
rows: process.stdout.rows || 24,
|
|
62
|
+
scrollback: 1000, // Keep scrollback for longer responses
|
|
63
|
+
});
|
|
64
|
+
this.serializeAddon = new SerializeAddon();
|
|
65
|
+
this.headlessTerminal.loadAddon(this.serializeAddon);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get current state
|
|
69
|
+
*/
|
|
70
|
+
getState() {
|
|
71
|
+
return this.state;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if PTY is dead and needs respawn
|
|
75
|
+
*/
|
|
76
|
+
isDead() {
|
|
77
|
+
return this.state === PtyState.DEAD;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check if PTY is processing a response
|
|
81
|
+
*/
|
|
82
|
+
isProcessing() {
|
|
83
|
+
return this.state === PtyState.PROCESSING;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if user is currently attached
|
|
87
|
+
*/
|
|
88
|
+
isUserAttached() {
|
|
89
|
+
return this.isAttached;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get the output buffer (for reattach screen restore)
|
|
93
|
+
* Uses the headless terminal to get the actual visible screen content.
|
|
94
|
+
*/
|
|
95
|
+
getOutputBuffer() {
|
|
96
|
+
// If we have a headless terminal, extract visible text from the screen
|
|
97
|
+
// This correctly handles cursor positioning and screen redraws
|
|
98
|
+
if (this.headlessTerminal) {
|
|
99
|
+
try {
|
|
100
|
+
const buffer = this.headlessTerminal.buffer.active;
|
|
101
|
+
const lines = [];
|
|
102
|
+
// Only read the VISIBLE viewport, not the scrollback
|
|
103
|
+
// This avoids capturing intermediate streaming frames
|
|
104
|
+
const viewportStart = buffer.baseY;
|
|
105
|
+
const viewportEnd = viewportStart + this.headlessTerminal.rows;
|
|
106
|
+
for (let y = viewportStart; y < viewportEnd && y < buffer.length; y++) {
|
|
107
|
+
const line = buffer.getLine(y);
|
|
108
|
+
if (line) {
|
|
109
|
+
// translateToString(true) = trim trailing whitespace
|
|
110
|
+
lines.push(line.translateToString(true));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Join lines and trim empty lines from start/end
|
|
114
|
+
let text = lines.join('\n').trim();
|
|
115
|
+
// If viewport is mostly empty (just prompt), try getting more from scrollback
|
|
116
|
+
if (text.length < 50 && buffer.length > viewportEnd) {
|
|
117
|
+
// Get the last screenful from scrollback instead
|
|
118
|
+
const scrollbackLines = [];
|
|
119
|
+
const startY = Math.max(0, buffer.length - this.headlessTerminal.rows * 2);
|
|
120
|
+
for (let y = startY; y < buffer.length; y++) {
|
|
121
|
+
const line = buffer.getLine(y);
|
|
122
|
+
if (line) {
|
|
123
|
+
scrollbackLines.push(line.translateToString(true));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
text = scrollbackLines.join('\n').trim();
|
|
127
|
+
}
|
|
128
|
+
if (text.length > 0) {
|
|
129
|
+
return text;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Fall back to raw buffer if extraction fails
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return this.outputBuffer;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Clear the output buffer (used after sending a prompt to avoid capturing the typed input)
|
|
140
|
+
*/
|
|
141
|
+
clearOutputBuffer() {
|
|
142
|
+
this.outputBuffer = '';
|
|
143
|
+
// Also reset the headless terminal
|
|
144
|
+
if (this.headlessTerminal) {
|
|
145
|
+
this.headlessTerminal.reset();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Set callbacks
|
|
150
|
+
*/
|
|
151
|
+
setCallbacks(callbacks) {
|
|
152
|
+
this.callbacks = callbacks;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Spawn the PTY process
|
|
156
|
+
* @param cwd Working directory
|
|
157
|
+
* @param waitForReady If false, returns immediately after spawning (for interactive mode)
|
|
158
|
+
*/
|
|
159
|
+
spawn(cwd, waitForReady = true) {
|
|
160
|
+
if (this.pty && this.state !== PtyState.DEAD) {
|
|
161
|
+
return Promise.resolve();
|
|
162
|
+
}
|
|
163
|
+
this.cwd = cwd;
|
|
164
|
+
this.state = PtyState.SPAWNING;
|
|
165
|
+
this.outputBuffer = '';
|
|
166
|
+
this.isReady = false;
|
|
167
|
+
// Initialize headless terminal for screen state tracking
|
|
168
|
+
this.initHeadlessTerminal();
|
|
169
|
+
// Create a promise that resolves when we see the first prompt OR after short timeout
|
|
170
|
+
this.readyPromise = new Promise((resolve) => {
|
|
171
|
+
this.readyResolve = resolve;
|
|
172
|
+
// Short fallback: if we don't detect prompt within 2 seconds, assume ready anyway
|
|
173
|
+
// For interactive mode, users will see the startup screen directly
|
|
174
|
+
setTimeout(() => {
|
|
175
|
+
if (!this.isReady && this.state === PtyState.SPAWNING) {
|
|
176
|
+
this.isReady = true;
|
|
177
|
+
this.setState(PtyState.IDLE);
|
|
178
|
+
resolve();
|
|
179
|
+
}
|
|
180
|
+
}, 2000);
|
|
181
|
+
});
|
|
182
|
+
this.pty = pty.spawn(this.config.command, this.config.args, {
|
|
183
|
+
name: 'xterm-256color',
|
|
184
|
+
cols: process.stdout.columns || 80,
|
|
185
|
+
rows: process.stdout.rows || 24,
|
|
186
|
+
cwd: this.cwd,
|
|
187
|
+
env: process.env,
|
|
188
|
+
});
|
|
189
|
+
// Handle output
|
|
190
|
+
this.pty.onData((data) => {
|
|
191
|
+
this.handleData(data);
|
|
192
|
+
});
|
|
193
|
+
// Handle exit
|
|
194
|
+
this.pty.onExit(({ exitCode }) => {
|
|
195
|
+
this.handleExit(exitCode);
|
|
196
|
+
});
|
|
197
|
+
// Handle resize
|
|
198
|
+
const onResize = () => {
|
|
199
|
+
const cols = process.stdout.columns || 80;
|
|
200
|
+
const rows = process.stdout.rows || 24;
|
|
201
|
+
if (this.pty) {
|
|
202
|
+
this.pty.resize(cols, rows);
|
|
203
|
+
}
|
|
204
|
+
// Also resize the headless terminal to match
|
|
205
|
+
if (this.headlessTerminal) {
|
|
206
|
+
this.headlessTerminal.resize(cols, rows);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
process.stdout.on('resize', onResize);
|
|
210
|
+
// For interactive mode, return immediately so user sees startup
|
|
211
|
+
if (!waitForReady) {
|
|
212
|
+
return Promise.resolve();
|
|
213
|
+
}
|
|
214
|
+
return this.readyPromise;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Handle incoming data from PTY
|
|
218
|
+
*/
|
|
219
|
+
handleData(data) {
|
|
220
|
+
// Detect screen clears and reset buffer
|
|
221
|
+
if (data.includes('\x1b[2J') || data.includes('\x1b[H\x1b[2J')) {
|
|
222
|
+
this.outputBuffer = '';
|
|
223
|
+
}
|
|
224
|
+
// Add to buffer (raw, kept for backwards compatibility)
|
|
225
|
+
this.outputBuffer += data;
|
|
226
|
+
// Also write to headless terminal for proper screen state tracking
|
|
227
|
+
// This correctly handles cursor positioning, screen redraws, etc.
|
|
228
|
+
if (this.headlessTerminal) {
|
|
229
|
+
this.headlessTerminal.write(data);
|
|
230
|
+
}
|
|
231
|
+
// Limit buffer size (keep last 100KB)
|
|
232
|
+
const MAX_BUFFER = 100 * 1024;
|
|
233
|
+
if (this.outputBuffer.length > MAX_BUFFER) {
|
|
234
|
+
this.outputBuffer = this.outputBuffer.slice(-MAX_BUFFER);
|
|
235
|
+
}
|
|
236
|
+
// If attached, forward to stdout (filtered)
|
|
237
|
+
if (this.isAttached) {
|
|
238
|
+
let filteredData = data
|
|
239
|
+
.split(FOCUS_IN_SEQ).join('')
|
|
240
|
+
.split(FOCUS_OUT_SEQ).join('');
|
|
241
|
+
// Filter terminal response sequences that leak through
|
|
242
|
+
// These include DA responses, keyboard protocol responses, etc.
|
|
243
|
+
const beforeFilter = filteredData;
|
|
244
|
+
filteredData = filteredData
|
|
245
|
+
.replace(/\x1b\[\?[\d;]*[uc]/g, '') // ESC[?...c or ESC[?...u (full sequences)
|
|
246
|
+
.replace(/\x1b\[>[\d;]*c/g, '') // ESC[>...c (Secondary DA)
|
|
247
|
+
.replace(/\x1b\[[\d;]*u/g, '') // ESC[...u (CSI u)
|
|
248
|
+
.replace(/\x1b\[c/g, '') // ESC[c Primary DA query - DON'T send to terminal!
|
|
249
|
+
.replace(/\x1b\[>c/g, '') // ESC[>c Secondary DA query
|
|
250
|
+
// Orphaned remnants from fragmented escape sequences
|
|
251
|
+
.replace(/\b0u\b/g, '') // Keyboard enhancement "0u"
|
|
252
|
+
.replace(/\b\d{2,};[\d;]+c\b/g, ''); // DA response "64;1;2;...c"
|
|
253
|
+
// Debug: log filtered sequences when AIC_DEBUG=1
|
|
254
|
+
if (process.env.AIC_DEBUG === '1' && beforeFilter !== filteredData) {
|
|
255
|
+
console.log(`\n[DEBUG] PTY filtered ${beforeFilter.length - filteredData.length} bytes of terminal sequences`);
|
|
256
|
+
}
|
|
257
|
+
if (filteredData.length > 0) {
|
|
258
|
+
process.stdout.write(filteredData);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Check for prompt (tool is ready for input)
|
|
262
|
+
const strippedRecent = stripAnsi(this.outputBuffer.slice(-500));
|
|
263
|
+
if (this.config.promptPattern.test(strippedRecent)) {
|
|
264
|
+
// Tool is showing prompt
|
|
265
|
+
if (!this.isReady) {
|
|
266
|
+
// First prompt - tool is initialized
|
|
267
|
+
this.isReady = true;
|
|
268
|
+
this.setState(PtyState.IDLE);
|
|
269
|
+
if (this.readyResolve) {
|
|
270
|
+
this.readyResolve();
|
|
271
|
+
this.readyResolve = null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else if (this.currentCapture) {
|
|
275
|
+
// We have a pending capture and saw prompt - response is complete!
|
|
276
|
+
this.completeCapture();
|
|
277
|
+
}
|
|
278
|
+
else if (this.state === PtyState.PROCESSING) {
|
|
279
|
+
// Was processing, now idle
|
|
280
|
+
this.setState(PtyState.IDLE);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// If capturing, accumulate output
|
|
284
|
+
if (this.currentCapture) {
|
|
285
|
+
this.currentCapture.output += data;
|
|
286
|
+
// Only reset idle timeout on "real" content, not spinner/ANSI noise
|
|
287
|
+
// Strip ANSI codes and spinner frames to check if there's actual content
|
|
288
|
+
const stripped = data
|
|
289
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '') // ANSI codes
|
|
290
|
+
.replace(/\x1b\[\??\d+[hl]/g, '') // Mode changes
|
|
291
|
+
.replace(/\x1b\[\d* ?q/g, '') // Cursor style
|
|
292
|
+
.replace(/[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/g, '') // Spinner frames
|
|
293
|
+
.replace(/\r/g, '') // Carriage returns
|
|
294
|
+
.trim();
|
|
295
|
+
// Only reset timer if there's actual content (not just control sequences)
|
|
296
|
+
if (stripped.length > 0) {
|
|
297
|
+
this.resetIdleTimeout();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Reset the idle timeout (called on each output chunk)
|
|
303
|
+
*/
|
|
304
|
+
resetIdleTimeout() {
|
|
305
|
+
if (!this.currentCapture)
|
|
306
|
+
return;
|
|
307
|
+
// Clear existing idle timeout
|
|
308
|
+
if (this.currentCapture.idleTimeoutId) {
|
|
309
|
+
clearTimeout(this.currentCapture.idleTimeoutId);
|
|
310
|
+
}
|
|
311
|
+
// Set new idle timeout
|
|
312
|
+
this.currentCapture.idleTimeoutId = setTimeout(() => {
|
|
313
|
+
// No output for idleTimeout ms - assume response is complete
|
|
314
|
+
if (this.currentCapture) {
|
|
315
|
+
this.completeCapture();
|
|
316
|
+
}
|
|
317
|
+
}, this.config.idleTimeout);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Complete the current response capture
|
|
321
|
+
*/
|
|
322
|
+
completeCapture() {
|
|
323
|
+
if (!this.currentCapture)
|
|
324
|
+
return;
|
|
325
|
+
// Clear timeouts
|
|
326
|
+
clearTimeout(this.currentCapture.timeoutId);
|
|
327
|
+
if (this.currentCapture.idleTimeoutId) {
|
|
328
|
+
clearTimeout(this.currentCapture.idleTimeoutId);
|
|
329
|
+
}
|
|
330
|
+
// Clean and resolve
|
|
331
|
+
const rawOutput = this.currentCapture.output;
|
|
332
|
+
const cleanedOutput = this.config.cleanResponse(rawOutput);
|
|
333
|
+
this.currentCapture.resolve(cleanedOutput);
|
|
334
|
+
this.currentCapture = null;
|
|
335
|
+
this.setState(PtyState.IDLE);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Handle PTY exit
|
|
339
|
+
*/
|
|
340
|
+
handleExit(exitCode) {
|
|
341
|
+
this.setState(PtyState.DEAD);
|
|
342
|
+
this.pty = null;
|
|
343
|
+
this.isReady = false;
|
|
344
|
+
// If killed silently, don't show messages or call callbacks
|
|
345
|
+
if (this.suppressExitMessage) {
|
|
346
|
+
this.suppressExitMessage = false;
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
// Reject any pending capture
|
|
350
|
+
if (this.currentCapture) {
|
|
351
|
+
clearTimeout(this.currentCapture.timeoutId);
|
|
352
|
+
if (this.currentCapture.idleTimeoutId) {
|
|
353
|
+
clearTimeout(this.currentCapture.idleTimeoutId);
|
|
354
|
+
}
|
|
355
|
+
this.currentCapture.reject(new Error(`${this.config.displayName} exited with code ${exitCode}`));
|
|
356
|
+
this.currentCapture = null;
|
|
357
|
+
}
|
|
358
|
+
// Notify callback
|
|
359
|
+
if (this.callbacks.onExit) {
|
|
360
|
+
this.callbacks.onExit(exitCode);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Set state and notify callback
|
|
365
|
+
*/
|
|
366
|
+
setState(state) {
|
|
367
|
+
if (this.state !== state) {
|
|
368
|
+
this.state = state;
|
|
369
|
+
if (this.callbacks.onStateChange) {
|
|
370
|
+
this.callbacks.onStateChange(state);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Send a message and capture the response.
|
|
376
|
+
* Waits for prompt detection or idle timeout to know when complete.
|
|
377
|
+
*/
|
|
378
|
+
async sendAndCapture(message, timeout = 120000) {
|
|
379
|
+
// Ensure PTY is running
|
|
380
|
+
if (this.state === PtyState.DEAD) {
|
|
381
|
+
await this.spawn(this.cwd);
|
|
382
|
+
}
|
|
383
|
+
// Wait for tool to be ready (only if not ready yet)
|
|
384
|
+
if (!this.isReady && this.readyPromise) {
|
|
385
|
+
await this.readyPromise;
|
|
386
|
+
}
|
|
387
|
+
// Clear the promise once resolved to avoid holding references
|
|
388
|
+
this.readyPromise = null;
|
|
389
|
+
// Can't send while already processing
|
|
390
|
+
if (this.state === PtyState.PROCESSING) {
|
|
391
|
+
throw new Error(`${this.config.displayName} is still processing a previous request`);
|
|
392
|
+
}
|
|
393
|
+
// Can't send while attached
|
|
394
|
+
if (this.isAttached) {
|
|
395
|
+
throw new Error(`Cannot send message while attached. Use /i to interact directly.`);
|
|
396
|
+
}
|
|
397
|
+
return new Promise((resolve, reject) => {
|
|
398
|
+
// Set up capture
|
|
399
|
+
const timeoutId = setTimeout(() => {
|
|
400
|
+
if (this.currentCapture) {
|
|
401
|
+
if (this.currentCapture.idleTimeoutId) {
|
|
402
|
+
clearTimeout(this.currentCapture.idleTimeoutId);
|
|
403
|
+
}
|
|
404
|
+
this.currentCapture = null;
|
|
405
|
+
this.setState(PtyState.IDLE);
|
|
406
|
+
reject(new Error(`Response timeout after ${timeout / 1000} seconds`));
|
|
407
|
+
}
|
|
408
|
+
}, timeout);
|
|
409
|
+
this.currentCapture = {
|
|
410
|
+
output: '',
|
|
411
|
+
resolve,
|
|
412
|
+
reject,
|
|
413
|
+
timeoutId,
|
|
414
|
+
startTime: Date.now()
|
|
415
|
+
};
|
|
416
|
+
// Start idle timeout
|
|
417
|
+
this.resetIdleTimeout();
|
|
418
|
+
// Send message
|
|
419
|
+
this.setState(PtyState.PROCESSING);
|
|
420
|
+
this.pty.write(message + '\n');
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Write directly to PTY (for interactive mode)
|
|
425
|
+
*/
|
|
426
|
+
write(data) {
|
|
427
|
+
if (this.pty && this.state !== PtyState.DEAD) {
|
|
428
|
+
this.pty.write(data);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Attach to PTY - forward output to stdout, allow stdin forwarding
|
|
433
|
+
*/
|
|
434
|
+
attach() {
|
|
435
|
+
if (this.isAttached)
|
|
436
|
+
return;
|
|
437
|
+
this.isAttached = true;
|
|
438
|
+
this.setState(PtyState.ATTACHED);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Detach from PTY - stop forwarding, PTY keeps running
|
|
442
|
+
*/
|
|
443
|
+
detach() {
|
|
444
|
+
if (!this.isAttached)
|
|
445
|
+
return;
|
|
446
|
+
this.isAttached = false;
|
|
447
|
+
this.setState(PtyState.IDLE);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Kill the PTY process
|
|
451
|
+
* @param silent If true, suppress the onExit callback (for intentional kills)
|
|
452
|
+
*/
|
|
453
|
+
kill(silent = false) {
|
|
454
|
+
if (silent) {
|
|
455
|
+
// Set flag to suppress exit message in handleExit
|
|
456
|
+
this.suppressExitMessage = true;
|
|
457
|
+
}
|
|
458
|
+
if (this.pty) {
|
|
459
|
+
this.pty.kill();
|
|
460
|
+
this.pty = null;
|
|
461
|
+
}
|
|
462
|
+
// Dispose headless terminal
|
|
463
|
+
if (this.headlessTerminal) {
|
|
464
|
+
this.headlessTerminal.dispose();
|
|
465
|
+
this.headlessTerminal = null;
|
|
466
|
+
this.serializeAddon = null;
|
|
467
|
+
}
|
|
468
|
+
this.setState(PtyState.DEAD);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get the underlying PTY for advanced operations
|
|
472
|
+
*/
|
|
473
|
+
getPty() {
|
|
474
|
+
return this.pty;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=persistent-pty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistent-pty.js","sourceRoot":"","sources":["../src/persistent-pty.ts"],"names":[],"mappings":"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"}
|