tmux-manager 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/LICENSE +201 -0
- package/README.md +521 -0
- package/dist/index.d.mts +669 -0
- package/dist/index.d.ts +669 -0
- package/dist/index.js +1990 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1951 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +63 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import * as adapter_types from 'adapter-types';
|
|
3
|
+
import { SpawnConfig, CLIAdapter, AutoResponseRule, ToolRunningInfo, AdapterRegistry, LoginDetection, BlockingPromptDetection, ParsedOutput } from 'adapter-types';
|
|
4
|
+
export { AdapterFactoryConfig, AdapterRegistry, AutoResponseRule, BaseCLIAdapter, BlockingPromptDetection, BlockingPromptType, CLIAdapter, LoginDetection, MessageType, ParsedOutput, SpawnConfig, ToolRunningInfo, createAdapter } from 'adapter-types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ensure tmux is installed and accessible.
|
|
8
|
+
*
|
|
9
|
+
* Checks that tmux is available on PATH and returns its version.
|
|
10
|
+
* Throws a descriptive error if tmux is not found.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Verify that tmux is installed and usable.
|
|
14
|
+
* Caches the result after the first successful check.
|
|
15
|
+
*
|
|
16
|
+
* @param log - Optional log callback for status messages
|
|
17
|
+
* @returns The tmux version string (e.g., "3.4")
|
|
18
|
+
*/
|
|
19
|
+
declare function ensureTmux(log?: (msg: string) => void): string;
|
|
20
|
+
/**
|
|
21
|
+
* Reset the cached check (useful for testing).
|
|
22
|
+
*/
|
|
23
|
+
declare function resetTmuxCheck(): void;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Session lifecycle states
|
|
27
|
+
*/
|
|
28
|
+
type SessionStatus = 'pending' | 'starting' | 'authenticating' | 'ready' | 'busy' | 'stopping' | 'stopped' | 'error';
|
|
29
|
+
/**
|
|
30
|
+
* Handle to a running session
|
|
31
|
+
*/
|
|
32
|
+
interface SessionHandle {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
status: SessionStatus;
|
|
37
|
+
pid?: number;
|
|
38
|
+
startedAt?: Date;
|
|
39
|
+
lastActivityAt?: Date;
|
|
40
|
+
error?: string;
|
|
41
|
+
exitCode?: number;
|
|
42
|
+
/** Tmux session name (for reconnection) */
|
|
43
|
+
tmuxSessionName?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Message to/from a session
|
|
47
|
+
*/
|
|
48
|
+
interface SessionMessage {
|
|
49
|
+
id: string;
|
|
50
|
+
sessionId: string;
|
|
51
|
+
direction: 'inbound' | 'outbound';
|
|
52
|
+
type: adapter_types.MessageType;
|
|
53
|
+
content: string;
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
timestamp: Date;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Filter for listing sessions
|
|
59
|
+
*/
|
|
60
|
+
interface SessionFilter {
|
|
61
|
+
status?: SessionStatus | SessionStatus[];
|
|
62
|
+
type?: string | string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Normalized authentication methods for runtime event consumers.
|
|
66
|
+
*/
|
|
67
|
+
type AuthRequiredMethod = 'api_key' | 'cli_auth' | 'oauth_browser' | 'device_code' | 'unknown';
|
|
68
|
+
/**
|
|
69
|
+
* Structured authentication-required payload emitted by tmux session/manager.
|
|
70
|
+
*/
|
|
71
|
+
interface AuthRequiredInfo {
|
|
72
|
+
method: AuthRequiredMethod;
|
|
73
|
+
url?: string;
|
|
74
|
+
deviceCode?: string;
|
|
75
|
+
instructions?: string;
|
|
76
|
+
promptSnippet?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Blocking prompt info for events
|
|
80
|
+
*/
|
|
81
|
+
interface BlockingPromptInfo {
|
|
82
|
+
type: adapter_types.BlockingPromptType | string;
|
|
83
|
+
prompt?: string;
|
|
84
|
+
options?: string[];
|
|
85
|
+
canAutoRespond: boolean;
|
|
86
|
+
instructions?: string;
|
|
87
|
+
url?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Classification result from external stall analysis
|
|
91
|
+
*/
|
|
92
|
+
interface StallClassification {
|
|
93
|
+
/** What the external classifier determined */
|
|
94
|
+
state: 'waiting_for_input' | 'still_working' | 'task_complete' | 'error';
|
|
95
|
+
/** Description of the detected prompt (for waiting_for_input) */
|
|
96
|
+
prompt?: string;
|
|
97
|
+
/** Suggested response to send (for waiting_for_input with auto-respond) */
|
|
98
|
+
suggestedResponse?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Logger interface (bring your own logger)
|
|
102
|
+
*/
|
|
103
|
+
interface Logger {
|
|
104
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
105
|
+
debug(context: Record<string, unknown>, message: string): void;
|
|
106
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
107
|
+
info(context: Record<string, unknown>, message: string): void;
|
|
108
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
109
|
+
warn(context: Record<string, unknown>, message: string): void;
|
|
110
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
111
|
+
error(context: Record<string, unknown>, message: string): void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Options for stopping a session
|
|
115
|
+
*/
|
|
116
|
+
interface StopOptions {
|
|
117
|
+
/** Force kill without graceful shutdown */
|
|
118
|
+
force?: boolean;
|
|
119
|
+
/** Timeout in ms before force kill (default: 5000) */
|
|
120
|
+
timeout?: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Options for reading logs
|
|
124
|
+
*/
|
|
125
|
+
interface LogOptions {
|
|
126
|
+
/** Number of lines from the end */
|
|
127
|
+
tail?: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Terminal attachment for raw I/O streaming
|
|
131
|
+
*/
|
|
132
|
+
interface TerminalAttachment {
|
|
133
|
+
/** Subscribe to raw terminal output (returns unsubscribe function) */
|
|
134
|
+
onData: (callback: (data: string) => void) => () => void;
|
|
135
|
+
/** Write raw data to terminal */
|
|
136
|
+
write: (data: string) => void;
|
|
137
|
+
/** Resize the terminal */
|
|
138
|
+
resize: (cols: number, rows: number) => void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* TmuxManager configuration
|
|
142
|
+
*/
|
|
143
|
+
interface TmuxManagerConfig {
|
|
144
|
+
/** Logger instance (optional - uses console if not provided) */
|
|
145
|
+
logger?: Logger;
|
|
146
|
+
/** Maximum output log lines per session (default: 1000) */
|
|
147
|
+
maxLogLines?: number;
|
|
148
|
+
/** Enable stall detection (default: false) */
|
|
149
|
+
stallDetectionEnabled?: boolean;
|
|
150
|
+
/** Default stall timeout in ms (default: 8000). Can be overridden per-session via SpawnConfig. */
|
|
151
|
+
stallTimeoutMs?: number;
|
|
152
|
+
/**
|
|
153
|
+
* External classification callback invoked when a stall is detected.
|
|
154
|
+
*/
|
|
155
|
+
onStallClassify?: (sessionId: string, recentOutput: string, stallDurationMs: number) => Promise<StallClassification | null>;
|
|
156
|
+
/** Tmux scrollback history limit per session (default: 50000) */
|
|
157
|
+
historyLimit?: number;
|
|
158
|
+
/** Tmux session name prefix (default: 'parallax') */
|
|
159
|
+
sessionPrefix?: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Tmux Transport Layer
|
|
164
|
+
*
|
|
165
|
+
* Low-level interface to tmux sessions via the tmux CLI.
|
|
166
|
+
* Replaces node-pty as the PTY backend — no native addons required.
|
|
167
|
+
*/
|
|
168
|
+
interface TmuxSpawnOptions {
|
|
169
|
+
command: string;
|
|
170
|
+
args: string[];
|
|
171
|
+
cwd: string;
|
|
172
|
+
env: Record<string, string>;
|
|
173
|
+
cols: number;
|
|
174
|
+
rows: number;
|
|
175
|
+
historyLimit: number;
|
|
176
|
+
}
|
|
177
|
+
interface TmuxCaptureOptions {
|
|
178
|
+
/** Include ANSI escape codes (default: false) */
|
|
179
|
+
ansi?: boolean;
|
|
180
|
+
/** Number of lines from scrollback to include (default: visible only) */
|
|
181
|
+
scrollback?: number;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Mapping from our SPECIAL_KEYS names to tmux send-keys key names.
|
|
185
|
+
*/
|
|
186
|
+
declare const TMUX_KEY_MAP: Record<string, string>;
|
|
187
|
+
/**
|
|
188
|
+
* Low-level tmux session transport.
|
|
189
|
+
* Manages tmux sessions via CLI commands.
|
|
190
|
+
*/
|
|
191
|
+
declare class TmuxTransport {
|
|
192
|
+
private pollingTimers;
|
|
193
|
+
private lastCapture;
|
|
194
|
+
constructor();
|
|
195
|
+
/**
|
|
196
|
+
* Spawn a new tmux session running the given command.
|
|
197
|
+
*/
|
|
198
|
+
spawn(sessionName: string, options: TmuxSpawnOptions): void;
|
|
199
|
+
/**
|
|
200
|
+
* Check if a tmux session exists and is alive.
|
|
201
|
+
*/
|
|
202
|
+
isAlive(sessionName: string): boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Kill a tmux session.
|
|
205
|
+
*/
|
|
206
|
+
kill(sessionName: string): void;
|
|
207
|
+
/**
|
|
208
|
+
* Send a signal to the process in the tmux pane.
|
|
209
|
+
*/
|
|
210
|
+
signal(sessionName: string, sig: string): void;
|
|
211
|
+
/**
|
|
212
|
+
* Send literal text to the tmux session (no key interpretation).
|
|
213
|
+
*/
|
|
214
|
+
sendText(sessionName: string, text: string): void;
|
|
215
|
+
/**
|
|
216
|
+
* Send a named key to the tmux session.
|
|
217
|
+
* Uses TMUX_KEY_MAP for translation from our key names.
|
|
218
|
+
*/
|
|
219
|
+
sendKey(sessionName: string, key: string): void;
|
|
220
|
+
/**
|
|
221
|
+
* Capture the current pane content.
|
|
222
|
+
*/
|
|
223
|
+
capturePane(sessionName: string, options?: TmuxCaptureOptions): string;
|
|
224
|
+
/**
|
|
225
|
+
* Start polling output from a tmux session via capture-pane.
|
|
226
|
+
* Polls at the given interval and calls the callback with new/changed content.
|
|
227
|
+
*
|
|
228
|
+
* Uses capture-pane with ANSI codes (-e) and scrollback for full fidelity.
|
|
229
|
+
* Compares against last capture to detect changes and emit only new data.
|
|
230
|
+
*/
|
|
231
|
+
startOutputStreaming(sessionName: string, callback: (data: string) => void, pollIntervalMs?: number): void;
|
|
232
|
+
/**
|
|
233
|
+
* Stop polling output from a tmux session.
|
|
234
|
+
*/
|
|
235
|
+
stopOutputStreaming(sessionName: string): void;
|
|
236
|
+
/**
|
|
237
|
+
* Get the PID of the process running in the tmux pane.
|
|
238
|
+
*/
|
|
239
|
+
getPanePid(sessionName: string): number | undefined;
|
|
240
|
+
/**
|
|
241
|
+
* Get the pane dimensions.
|
|
242
|
+
*/
|
|
243
|
+
getPaneDimensions(sessionName: string): {
|
|
244
|
+
cols: number;
|
|
245
|
+
rows: number;
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Resize a tmux session window.
|
|
249
|
+
*/
|
|
250
|
+
resize(sessionName: string, cols: number, rows: number): void;
|
|
251
|
+
/**
|
|
252
|
+
* Check if the pane's process has exited.
|
|
253
|
+
* Uses remain-on-exit to detect dead panes.
|
|
254
|
+
*/
|
|
255
|
+
isPaneAlive(sessionName: string): boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Get the exit status of a dead pane.
|
|
258
|
+
*/
|
|
259
|
+
getPaneExitStatus(sessionName: string): number | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* List all tmux sessions matching a prefix.
|
|
262
|
+
*/
|
|
263
|
+
static listSessions(prefix?: string): Array<{
|
|
264
|
+
name: string;
|
|
265
|
+
created: string;
|
|
266
|
+
attached: boolean;
|
|
267
|
+
}>;
|
|
268
|
+
/**
|
|
269
|
+
* Clean up resources.
|
|
270
|
+
*/
|
|
271
|
+
destroy(): void;
|
|
272
|
+
private tmuxExec;
|
|
273
|
+
private shellEscape;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Tmux Session
|
|
278
|
+
*
|
|
279
|
+
* Manages a single tmux session for a CLI tool.
|
|
280
|
+
* Mirrors PTYSession's API but uses TmuxTransport instead of node-pty.
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
interface TmuxSessionEvents {
|
|
284
|
+
output: (data: string) => void;
|
|
285
|
+
ready: () => void;
|
|
286
|
+
login_required: (instructions?: string, url?: string) => void;
|
|
287
|
+
auth_required: (info: AuthRequiredInfo) => void;
|
|
288
|
+
blocking_prompt: (prompt: BlockingPromptInfo, autoResponded: boolean) => void;
|
|
289
|
+
message: (message: SessionMessage) => void;
|
|
290
|
+
question: (question: string) => void;
|
|
291
|
+
exit: (code: number) => void;
|
|
292
|
+
error: (error: Error) => void;
|
|
293
|
+
stall_detected: (recentOutput: string, stallDurationMs: number) => void;
|
|
294
|
+
status_changed: (status: SessionStatus) => void;
|
|
295
|
+
task_complete: () => void;
|
|
296
|
+
tool_running: (info: ToolRunningInfo) => void;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Special key mappings to escape sequences (for compatibility with adapters that reference SPECIAL_KEYS)
|
|
300
|
+
*/
|
|
301
|
+
declare const SPECIAL_KEYS: Record<string, string>;
|
|
302
|
+
declare class TmuxSession extends EventEmitter {
|
|
303
|
+
private adapter;
|
|
304
|
+
private transport;
|
|
305
|
+
private tmuxSessionName;
|
|
306
|
+
private outputBuffer;
|
|
307
|
+
private _status;
|
|
308
|
+
private _startedAt;
|
|
309
|
+
private _lastActivityAt;
|
|
310
|
+
private messageCounter;
|
|
311
|
+
private logger;
|
|
312
|
+
private sessionRules;
|
|
313
|
+
private _firedOnceRules;
|
|
314
|
+
private _lastBlockingPromptHash;
|
|
315
|
+
private _ruleOverrides;
|
|
316
|
+
private _disabledRulePatterns;
|
|
317
|
+
private _stallTimer;
|
|
318
|
+
private _stallTimeoutMs;
|
|
319
|
+
private _stallDetectionEnabled;
|
|
320
|
+
private _lastStallHash;
|
|
321
|
+
private _stallStartedAt;
|
|
322
|
+
private _lastContentHash;
|
|
323
|
+
private _stallBackoffMs;
|
|
324
|
+
private static readonly MAX_STALL_BACKOFF_MS;
|
|
325
|
+
private _stallEmissionCount;
|
|
326
|
+
private static readonly MAX_STALL_EMISSIONS;
|
|
327
|
+
private _taskCompleteTimer;
|
|
328
|
+
private _taskCompletePending;
|
|
329
|
+
private static readonly TASK_COMPLETE_DEBOUNCE_MS;
|
|
330
|
+
private _readySettleTimer;
|
|
331
|
+
private _readySettlePending;
|
|
332
|
+
private _lastToolRunningName;
|
|
333
|
+
private static readonly MAX_OUTPUT_BUFFER;
|
|
334
|
+
private _exitPollTimer;
|
|
335
|
+
private sessionPrefix;
|
|
336
|
+
private historyLimit;
|
|
337
|
+
readonly id: string;
|
|
338
|
+
readonly config: SpawnConfig;
|
|
339
|
+
constructor(adapter: CLIAdapter, config: SpawnConfig, logger?: Logger, stallDetectionEnabled?: boolean, defaultStallTimeoutMs?: number, transport?: TmuxTransport, sessionPrefix?: string, historyLimit?: number);
|
|
340
|
+
get status(): SessionStatus;
|
|
341
|
+
get pid(): number | undefined;
|
|
342
|
+
get startedAt(): Date | undefined;
|
|
343
|
+
get lastActivityAt(): Date | undefined;
|
|
344
|
+
/**
|
|
345
|
+
* Get the tmux session name (for reconnection/debugging).
|
|
346
|
+
*/
|
|
347
|
+
get tmuxName(): string;
|
|
348
|
+
addAutoResponseRule(rule: AutoResponseRule): void;
|
|
349
|
+
removeAutoResponseRule(pattern: RegExp): boolean;
|
|
350
|
+
setAutoResponseRules(rules: AutoResponseRule[]): void;
|
|
351
|
+
getAutoResponseRules(): AutoResponseRule[];
|
|
352
|
+
clearAutoResponseRules(): void;
|
|
353
|
+
private resetStallTimer;
|
|
354
|
+
private clearStallTimer;
|
|
355
|
+
private onStallTimerFired;
|
|
356
|
+
handleStallClassification(classification: StallClassification | null): void;
|
|
357
|
+
private scheduleTaskComplete;
|
|
358
|
+
private isTaskCompleteSignal;
|
|
359
|
+
private cancelTaskComplete;
|
|
360
|
+
private scheduleReadySettle;
|
|
361
|
+
private cancelReadySettle;
|
|
362
|
+
start(): Promise<void>;
|
|
363
|
+
/**
|
|
364
|
+
* Reconnect to an existing tmux session.
|
|
365
|
+
* Used for crash recovery.
|
|
366
|
+
*/
|
|
367
|
+
reconnect(existingTmuxName: string): Promise<void>;
|
|
368
|
+
private handleExit;
|
|
369
|
+
private stopExitPolling;
|
|
370
|
+
private processOutputBuffer;
|
|
371
|
+
private detectAndHandleBlockingPrompt;
|
|
372
|
+
private tryAutoResponse;
|
|
373
|
+
private tryParseOutput;
|
|
374
|
+
/**
|
|
375
|
+
* Write data to the session (formatted by adapter, with Enter)
|
|
376
|
+
*/
|
|
377
|
+
write(data: string): void;
|
|
378
|
+
/**
|
|
379
|
+
* Write raw data directly (no formatting, no Enter)
|
|
380
|
+
*/
|
|
381
|
+
writeRaw(data: string): void;
|
|
382
|
+
/**
|
|
383
|
+
* Send a task/message to the session
|
|
384
|
+
*/
|
|
385
|
+
send(message: string): SessionMessage;
|
|
386
|
+
/**
|
|
387
|
+
* Resize the terminal
|
|
388
|
+
*/
|
|
389
|
+
resize(cols: number, rows: number): void;
|
|
390
|
+
/**
|
|
391
|
+
* Send special keys to the session.
|
|
392
|
+
* Uses tmux send-keys with named keys.
|
|
393
|
+
*/
|
|
394
|
+
sendKeys(keys: string | string[]): void;
|
|
395
|
+
/**
|
|
396
|
+
* Select a TUI menu option by index (0-based).
|
|
397
|
+
*/
|
|
398
|
+
selectMenuOption(optionIndex: number): Promise<void>;
|
|
399
|
+
/**
|
|
400
|
+
* Send a sequence of keys with staggered timing.
|
|
401
|
+
*/
|
|
402
|
+
private sendKeySequence;
|
|
403
|
+
/**
|
|
404
|
+
* Paste text using bracketed paste mode
|
|
405
|
+
*/
|
|
406
|
+
paste(text: string, useBracketedPaste?: boolean): void;
|
|
407
|
+
/**
|
|
408
|
+
* Notify the session of an external hook event.
|
|
409
|
+
*/
|
|
410
|
+
notifyHookEvent(event: string): void;
|
|
411
|
+
/**
|
|
412
|
+
* Kill the session.
|
|
413
|
+
*/
|
|
414
|
+
kill(signal?: string): void;
|
|
415
|
+
/**
|
|
416
|
+
* Get current output buffer
|
|
417
|
+
*/
|
|
418
|
+
getOutputBuffer(): string;
|
|
419
|
+
/**
|
|
420
|
+
* Clear output buffer
|
|
421
|
+
*/
|
|
422
|
+
clearOutputBuffer(): void;
|
|
423
|
+
/**
|
|
424
|
+
* Convert to SessionHandle
|
|
425
|
+
*/
|
|
426
|
+
toHandle(): SessionHandle;
|
|
427
|
+
static buildSpawnEnv(config: SpawnConfig, adapterEnv: Record<string, string>): Record<string, string>;
|
|
428
|
+
static normalizeKeyList(keys: string[]): string[];
|
|
429
|
+
private delay;
|
|
430
|
+
private simpleHash;
|
|
431
|
+
private mapLoginTypeToAuthMethod;
|
|
432
|
+
private emitAuthRequired;
|
|
433
|
+
/**
|
|
434
|
+
* Strip ANSI codes for stall detection hashing.
|
|
435
|
+
* Simplified compared to pty-manager since tmux capture-pane can give clean text.
|
|
436
|
+
*/
|
|
437
|
+
private stripAnsiForStall;
|
|
438
|
+
/**
|
|
439
|
+
* Less-aggressive ANSI stripping for classifier context.
|
|
440
|
+
*/
|
|
441
|
+
private stripAnsiForClassifier;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Tmux Manager
|
|
446
|
+
*
|
|
447
|
+
* Manages multiple tmux sessions for CLI tools.
|
|
448
|
+
* Mirrors PTYManager's API but uses tmux as the transport layer.
|
|
449
|
+
*/
|
|
450
|
+
|
|
451
|
+
interface TmuxManagerEvents {
|
|
452
|
+
session_started: (session: SessionHandle) => void;
|
|
453
|
+
session_ready: (session: SessionHandle) => void;
|
|
454
|
+
session_stopped: (session: SessionHandle, reason: string) => void;
|
|
455
|
+
session_error: (session: SessionHandle, error: string) => void;
|
|
456
|
+
login_required: (session: SessionHandle, instructions?: string, url?: string) => void;
|
|
457
|
+
auth_required: (session: SessionHandle, info: AuthRequiredInfo) => void;
|
|
458
|
+
blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;
|
|
459
|
+
message: (message: SessionMessage) => void;
|
|
460
|
+
question: (session: SessionHandle, question: string) => void;
|
|
461
|
+
stall_detected: (session: SessionHandle, recentOutput: string, stallDurationMs: number) => void;
|
|
462
|
+
session_status_changed: (session: SessionHandle) => void;
|
|
463
|
+
task_complete: (session: SessionHandle) => void;
|
|
464
|
+
tool_running: (session: SessionHandle, info: ToolRunningInfo) => void;
|
|
465
|
+
}
|
|
466
|
+
declare class TmuxManager extends EventEmitter {
|
|
467
|
+
private sessions;
|
|
468
|
+
private outputLogs;
|
|
469
|
+
private maxLogLines;
|
|
470
|
+
private logger;
|
|
471
|
+
private transport;
|
|
472
|
+
readonly adapters: AdapterRegistry;
|
|
473
|
+
private _stallDetectionEnabled;
|
|
474
|
+
private _stallTimeoutMs;
|
|
475
|
+
private _onStallClassify?;
|
|
476
|
+
private _historyLimit;
|
|
477
|
+
private _sessionPrefix;
|
|
478
|
+
constructor(config?: TmuxManagerConfig);
|
|
479
|
+
/**
|
|
480
|
+
* Register a CLI adapter
|
|
481
|
+
*/
|
|
482
|
+
registerAdapter(adapter: CLIAdapter): void;
|
|
483
|
+
/**
|
|
484
|
+
* Spawn a new tmux session
|
|
485
|
+
*/
|
|
486
|
+
spawn(config: SpawnConfig): Promise<SessionHandle>;
|
|
487
|
+
/**
|
|
488
|
+
* Set up event handlers for a session
|
|
489
|
+
*/
|
|
490
|
+
private setupSessionEvents;
|
|
491
|
+
/**
|
|
492
|
+
* Stop a session
|
|
493
|
+
*/
|
|
494
|
+
stop(sessionId: string, options?: StopOptions): Promise<void>;
|
|
495
|
+
/**
|
|
496
|
+
* Stop all sessions
|
|
497
|
+
*/
|
|
498
|
+
stopAll(options?: StopOptions): Promise<void>;
|
|
499
|
+
/**
|
|
500
|
+
* Get a session by ID
|
|
501
|
+
*/
|
|
502
|
+
get(sessionId: string): SessionHandle | null;
|
|
503
|
+
/**
|
|
504
|
+
* List all sessions
|
|
505
|
+
*/
|
|
506
|
+
list(filter?: SessionFilter): SessionHandle[];
|
|
507
|
+
/**
|
|
508
|
+
* Send a message to a session
|
|
509
|
+
*/
|
|
510
|
+
send(sessionId: string, message: string): SessionMessage;
|
|
511
|
+
/**
|
|
512
|
+
* Get logs for a session
|
|
513
|
+
*/
|
|
514
|
+
logs(sessionId: string, options?: LogOptions): AsyncIterable<string>;
|
|
515
|
+
/**
|
|
516
|
+
* Get metrics for a session
|
|
517
|
+
*/
|
|
518
|
+
metrics(sessionId: string): {
|
|
519
|
+
uptime?: number;
|
|
520
|
+
messageCount?: number;
|
|
521
|
+
} | null;
|
|
522
|
+
/**
|
|
523
|
+
* Shutdown manager and stop all sessions
|
|
524
|
+
*/
|
|
525
|
+
shutdown(): Promise<void>;
|
|
526
|
+
/**
|
|
527
|
+
* Get count of sessions by status
|
|
528
|
+
*/
|
|
529
|
+
getStatusCounts(): Record<SessionStatus, number>;
|
|
530
|
+
/**
|
|
531
|
+
* Attach to a session's terminal for raw I/O streaming
|
|
532
|
+
*/
|
|
533
|
+
attachTerminal(sessionId: string): TerminalAttachment | null;
|
|
534
|
+
/**
|
|
535
|
+
* Check if a session exists
|
|
536
|
+
*/
|
|
537
|
+
has(sessionId: string): boolean;
|
|
538
|
+
/**
|
|
539
|
+
* Get the underlying TmuxSession (for advanced use)
|
|
540
|
+
*/
|
|
541
|
+
getSession(sessionId: string): TmuxSession | undefined;
|
|
542
|
+
/**
|
|
543
|
+
* List orphaned tmux sessions from previous runs.
|
|
544
|
+
* These are tmux sessions with the configured prefix that aren't tracked by this manager.
|
|
545
|
+
*/
|
|
546
|
+
listOrphanedSessions(): Array<{
|
|
547
|
+
name: string;
|
|
548
|
+
created: string;
|
|
549
|
+
attached: boolean;
|
|
550
|
+
}>;
|
|
551
|
+
/**
|
|
552
|
+
* Clean up orphaned tmux sessions from previous runs.
|
|
553
|
+
*/
|
|
554
|
+
cleanupOrphanedSessions(): number;
|
|
555
|
+
configureStallDetection(enabled: boolean, timeoutMs?: number, classify?: (sessionId: string, recentOutput: string, stallDurationMs: number) => Promise<StallClassification | null>): void;
|
|
556
|
+
addAutoResponseRule(sessionId: string, rule: AutoResponseRule): void;
|
|
557
|
+
removeAutoResponseRule(sessionId: string, pattern: RegExp): boolean;
|
|
558
|
+
setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): void;
|
|
559
|
+
getAutoResponseRules(sessionId: string): AutoResponseRule[];
|
|
560
|
+
clearAutoResponseRules(sessionId: string): void;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Task completion trace analysis helpers.
|
|
565
|
+
*
|
|
566
|
+
* Parses structured "Task completion trace" logs and builds a compact
|
|
567
|
+
* per-turn confidence timeline useful for debugging idle/completion detection.
|
|
568
|
+
*/
|
|
569
|
+
interface TaskCompletionTraceRecord {
|
|
570
|
+
sessionId?: string;
|
|
571
|
+
adapterType?: string;
|
|
572
|
+
event: string;
|
|
573
|
+
status?: string;
|
|
574
|
+
taskCompletePending?: boolean;
|
|
575
|
+
signal?: boolean;
|
|
576
|
+
wasPending?: boolean;
|
|
577
|
+
debounceMs?: number;
|
|
578
|
+
detectTaskComplete?: boolean;
|
|
579
|
+
detectReady?: boolean;
|
|
580
|
+
detectLoading?: boolean;
|
|
581
|
+
tailHash?: string;
|
|
582
|
+
tailSnippet?: string;
|
|
583
|
+
timestamp?: string | number | Date;
|
|
584
|
+
}
|
|
585
|
+
interface TaskCompletionTimelineStep {
|
|
586
|
+
event: string;
|
|
587
|
+
atIndex: number;
|
|
588
|
+
status: 'active' | 'active_loading' | 'likely_complete' | 'completed' | 'rejected';
|
|
589
|
+
confidence: number;
|
|
590
|
+
signal?: boolean;
|
|
591
|
+
detectTaskComplete?: boolean;
|
|
592
|
+
detectReady?: boolean;
|
|
593
|
+
detectLoading?: boolean;
|
|
594
|
+
}
|
|
595
|
+
interface TaskCompletionTurnTimeline {
|
|
596
|
+
turn: number;
|
|
597
|
+
startIndex: number;
|
|
598
|
+
endIndex: number;
|
|
599
|
+
completed: boolean;
|
|
600
|
+
maxConfidence: number;
|
|
601
|
+
finalConfidence: number;
|
|
602
|
+
events: TaskCompletionTimelineStep[];
|
|
603
|
+
}
|
|
604
|
+
interface TaskCompletionTimelineResult {
|
|
605
|
+
turns: TaskCompletionTurnTimeline[];
|
|
606
|
+
totalRecords: number;
|
|
607
|
+
ignoredRecords: number;
|
|
608
|
+
}
|
|
609
|
+
interface BuildTimelineOptions {
|
|
610
|
+
adapterType?: string;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Extract trace records from mixed log inputs.
|
|
614
|
+
*/
|
|
615
|
+
declare function extractTaskCompletionTraceRecords(entries: Array<string | Record<string, unknown>>): TaskCompletionTraceRecord[];
|
|
616
|
+
/**
|
|
617
|
+
* Build a per-turn confidence timeline from task-completion traces.
|
|
618
|
+
*/
|
|
619
|
+
declare function buildTaskCompletionTimeline(records: TaskCompletionTraceRecord[], options?: BuildTimelineOptions): TaskCompletionTimelineResult;
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Shell Adapter
|
|
623
|
+
*
|
|
624
|
+
* Built-in adapter for bash/zsh shell sessions.
|
|
625
|
+
*/
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Options for the shell adapter
|
|
629
|
+
*/
|
|
630
|
+
interface ShellAdapterOptions {
|
|
631
|
+
/** Shell to use (default: $SHELL or /bin/bash) */
|
|
632
|
+
shell?: string;
|
|
633
|
+
/** Custom prompt string (default: 'pty> ') */
|
|
634
|
+
prompt?: string;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Built-in adapter for shell sessions (bash/zsh)
|
|
638
|
+
*/
|
|
639
|
+
declare class ShellAdapter implements CLIAdapter {
|
|
640
|
+
readonly adapterType = "shell";
|
|
641
|
+
readonly displayName = "Shell";
|
|
642
|
+
readonly autoResponseRules: AutoResponseRule[];
|
|
643
|
+
private shell;
|
|
644
|
+
private promptStr;
|
|
645
|
+
constructor(options?: ShellAdapterOptions);
|
|
646
|
+
getCommand(): string;
|
|
647
|
+
getArgs(_config: SpawnConfig): string[];
|
|
648
|
+
getEnv(_config: SpawnConfig): Record<string, string>;
|
|
649
|
+
detectLogin(_output: string): LoginDetection;
|
|
650
|
+
detectBlockingPrompt(_output: string): BlockingPromptDetection;
|
|
651
|
+
detectReady(output: string): boolean;
|
|
652
|
+
private isContinuationPrompt;
|
|
653
|
+
detectExit(output: string): {
|
|
654
|
+
exited: boolean;
|
|
655
|
+
code?: number;
|
|
656
|
+
error?: string;
|
|
657
|
+
};
|
|
658
|
+
parseOutput(output: string): ParsedOutput | null;
|
|
659
|
+
formatInput(message: string): string;
|
|
660
|
+
getPromptPattern(): RegExp;
|
|
661
|
+
validateInstallation(): Promise<{
|
|
662
|
+
installed: boolean;
|
|
663
|
+
version?: string;
|
|
664
|
+
error?: string;
|
|
665
|
+
}>;
|
|
666
|
+
private stripAnsi;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export { type AuthRequiredInfo, type AuthRequiredMethod, type BlockingPromptInfo, type BuildTimelineOptions, type LogOptions, type Logger, SPECIAL_KEYS, type SessionFilter, type SessionHandle, type SessionMessage, type SessionStatus, ShellAdapter, type ShellAdapterOptions, type StallClassification, type StopOptions, TMUX_KEY_MAP, type TaskCompletionTimelineResult, type TaskCompletionTimelineStep, type TaskCompletionTraceRecord, type TaskCompletionTurnTimeline, type TerminalAttachment, type TmuxCaptureOptions, TmuxManager, type TmuxManagerConfig, type TmuxManagerEvents, TmuxSession, type TmuxSessionEvents, type TmuxSpawnOptions, TmuxTransport, buildTaskCompletionTimeline, ensureTmux, extractTaskCompletionTraceRecords, resetTmuxCheck };
|