@seflless/ghosttown 1.7.0 → 1.10.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.
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Session Manager
3
+ *
4
+ * Core session management without tmux. Handles:
5
+ * - Direct PTY spawning via node-pty
6
+ * - Session persistence to disk
7
+ * - Session restoration on server restart
8
+ * - Multi-client connections
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import type { IPty } from '@lydell/node-pty';
12
+ import { HistoryReplay } from './history-replay.js';
13
+ import { type OutputChunk } from './output-recorder.js';
14
+ import type { CreateSessionOptions, Session, SessionId, SessionInfo, SessionManagerConfig, SessionPaths } from './types.js';
15
+ /**
16
+ * Get the default shell for the current platform.
17
+ */
18
+ declare function getDefaultShell(): string;
19
+ /**
20
+ * Get default environment variables for terminal sessions.
21
+ */
22
+ declare function getDefaultEnv(): Record<string, string>;
23
+ /**
24
+ * SessionManager handles all session lifecycle operations.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const manager = new SessionManager();
29
+ * await manager.init();
30
+ *
31
+ * // Create a new session
32
+ * const session = await manager.createSession({ name: 'dev' });
33
+ *
34
+ * // Get the PTY for I/O
35
+ * const pty = manager.getPty(session.id);
36
+ * pty.onData((data) => console.log(data));
37
+ * pty.write('echo hello\n');
38
+ *
39
+ * // List all sessions
40
+ * const sessions = await manager.listSessions();
41
+ *
42
+ * // Delete a session
43
+ * await manager.deleteSession(session.id);
44
+ * ```
45
+ */
46
+ export declare class SessionManager extends EventEmitter {
47
+ private config;
48
+ private paths;
49
+ private sessions;
50
+ private ptyProcesses;
51
+ private outputRecorders;
52
+ private initialized;
53
+ constructor(config?: SessionManagerConfig);
54
+ /**
55
+ * Initialize the session manager.
56
+ * Loads persisted sessions from disk.
57
+ */
58
+ init(): Promise<void>;
59
+ /**
60
+ * Create a new session.
61
+ */
62
+ createSession(options?: CreateSessionOptions): Promise<Session>;
63
+ /**
64
+ * Get a session by ID.
65
+ */
66
+ getSession(sessionId: SessionId): Session | undefined;
67
+ /**
68
+ * Get the PTY process for a session.
69
+ * Returns undefined if the process is not running.
70
+ */
71
+ getPty(sessionId: SessionId): IPty | undefined;
72
+ /**
73
+ * List all sessions with summary info.
74
+ */
75
+ listSessions(): Promise<SessionInfo[]>;
76
+ /**
77
+ * Delete a session and all associated data.
78
+ */
79
+ deleteSession(sessionId: SessionId): Promise<void>;
80
+ /**
81
+ * Rename a session.
82
+ */
83
+ renameSession(sessionId: SessionId, newName: string): Promise<void>;
84
+ /**
85
+ * Resize a session's terminal.
86
+ */
87
+ resizeSession(sessionId: SessionId, cols: number, rows: number): Promise<void>;
88
+ /**
89
+ * Connect to a session, respawning the process if needed.
90
+ * Returns the PTY for I/O.
91
+ */
92
+ connectToSession(sessionId: SessionId): Promise<IPty>;
93
+ /**
94
+ * Write data to a session's PTY.
95
+ */
96
+ write(sessionId: SessionId, data: string): void;
97
+ /**
98
+ * Get the storage paths for session data.
99
+ */
100
+ getPaths(): SessionPaths;
101
+ /**
102
+ * Get the buffered output for a session (for replay on reconnect).
103
+ * Returns the concatenated output as a single string.
104
+ * Note: This loads all scrollback into memory. For large histories,
105
+ * use getScrollbackChunks() instead.
106
+ */
107
+ getScrollback(sessionId: SessionId): Promise<string>;
108
+ /**
109
+ * Get scrollback chunks for a session with pagination.
110
+ * @param sessionId Session ID
111
+ * @param offset Number of chunks to skip from the start
112
+ * @param limit Maximum number of chunks to return
113
+ */
114
+ getScrollbackChunks(sessionId: SessionId, offset?: number, limit?: number): Promise<OutputChunk[]>;
115
+ /**
116
+ * Get the total number of scrollback chunks for a session.
117
+ */
118
+ getScrollbackLength(sessionId: SessionId): number;
119
+ /**
120
+ * Create a history replay for streaming scrollback to a client.
121
+ * The replay emits 'data', 'progress', and 'complete' events.
122
+ */
123
+ createHistoryReplay(sessionId: SessionId): Promise<HistoryReplay | null>;
124
+ /**
125
+ * Spawn a PTY process for a session.
126
+ */
127
+ private spawnProcess;
128
+ /**
129
+ * Persist a session's metadata to disk.
130
+ */
131
+ private persistSession;
132
+ /**
133
+ * Load persisted sessions from disk.
134
+ */
135
+ private loadPersistedSessions;
136
+ /**
137
+ * Generate a display name for a new session.
138
+ * Returns the next available number (1, 2, 3, ...).
139
+ */
140
+ private generateDisplayName;
141
+ /**
142
+ * Clean up all resources.
143
+ */
144
+ destroy(): Promise<void>;
145
+ }
146
+ export declare function getSessionManager(config?: SessionManagerConfig): SessionManager;
147
+ export { getDefaultShell, getDefaultEnv };
@@ -0,0 +1,489 @@
1
+ /**
2
+ * Session Manager
3
+ *
4
+ * Core session management without tmux. Handles:
5
+ * - Direct PTY spawning via node-pty
6
+ * - Session persistence to disk
7
+ * - Session restoration on server restart
8
+ * - Multi-client connections
9
+ */
10
+ import { randomUUID } from 'crypto';
11
+ import { EventEmitter } from 'events';
12
+ import { existsSync, mkdirSync } from 'fs';
13
+ import { homedir } from 'os';
14
+ import path from 'path';
15
+ import fs from 'fs/promises';
16
+ import { HistoryReplay } from './history-replay.js';
17
+ import { OutputRecorder } from './output-recorder.js';
18
+ // Dynamic import for node-pty (CommonJS module)
19
+ let ptyModule = null;
20
+ async function getPty() {
21
+ if (!ptyModule) {
22
+ ptyModule = await import('@lydell/node-pty');
23
+ }
24
+ return ptyModule;
25
+ }
26
+ /**
27
+ * Default configuration values.
28
+ */
29
+ const DEFAULTS = {
30
+ storageDir: path.join(homedir(), '.config', 'ghosttown', 'sessions'),
31
+ scrollbackLimit: 10000,
32
+ defaultShell: process.env.SHELL || '/bin/sh',
33
+ defaultCols: 80,
34
+ defaultRows: 24,
35
+ };
36
+ /**
37
+ * Get the default shell for the current platform.
38
+ */
39
+ function getDefaultShell() {
40
+ if (process.platform === 'win32') {
41
+ return process.env.COMSPEC || 'cmd.exe';
42
+ }
43
+ return process.env.SHELL || '/bin/sh';
44
+ }
45
+ /**
46
+ * Get default environment variables for terminal sessions.
47
+ */
48
+ function getDefaultEnv() {
49
+ return {
50
+ TERM: 'xterm-256color',
51
+ COLORTERM: 'truecolor',
52
+ LANG: process.env.LANG || 'en_US.UTF-8',
53
+ LC_ALL: process.env.LC_ALL || 'en_US.UTF-8',
54
+ TERM_PROGRAM: 'ghosttown',
55
+ };
56
+ }
57
+ /**
58
+ * SessionManager handles all session lifecycle operations.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const manager = new SessionManager();
63
+ * await manager.init();
64
+ *
65
+ * // Create a new session
66
+ * const session = await manager.createSession({ name: 'dev' });
67
+ *
68
+ * // Get the PTY for I/O
69
+ * const pty = manager.getPty(session.id);
70
+ * pty.onData((data) => console.log(data));
71
+ * pty.write('echo hello\n');
72
+ *
73
+ * // List all sessions
74
+ * const sessions = await manager.listSessions();
75
+ *
76
+ * // Delete a session
77
+ * await manager.deleteSession(session.id);
78
+ * ```
79
+ */
80
+ export class SessionManager extends EventEmitter {
81
+ constructor(config = {}) {
82
+ super();
83
+ this.sessions = new Map();
84
+ this.ptyProcesses = new Map();
85
+ this.outputRecorders = new Map(); // Disk-backed scrollback
86
+ this.initialized = false;
87
+ this.config = {
88
+ storageDir: config.storageDir ?? DEFAULTS.storageDir,
89
+ scrollbackLimit: config.scrollbackLimit ?? DEFAULTS.scrollbackLimit,
90
+ defaultShell: config.defaultShell ?? getDefaultShell(),
91
+ };
92
+ this.paths = {
93
+ baseDir: this.config.storageDir,
94
+ sessionDir: (id) => path.join(this.config.storageDir, id),
95
+ metadataFile: (id) => path.join(this.config.storageDir, id, 'metadata.json'),
96
+ scrollbackFile: (id) => path.join(this.config.storageDir, id, 'scrollback.jsonl'),
97
+ };
98
+ }
99
+ /**
100
+ * Initialize the session manager.
101
+ * Loads persisted sessions from disk.
102
+ */
103
+ async init() {
104
+ if (this.initialized)
105
+ return;
106
+ // Ensure storage directory exists
107
+ if (!existsSync(this.paths.baseDir)) {
108
+ mkdirSync(this.paths.baseDir, { recursive: true });
109
+ }
110
+ // Load persisted sessions
111
+ await this.loadPersistedSessions();
112
+ this.initialized = true;
113
+ }
114
+ /**
115
+ * Create a new session.
116
+ */
117
+ async createSession(options = {}) {
118
+ if (!this.initialized) {
119
+ throw new Error('SessionManager not initialized. Call init() first.');
120
+ }
121
+ const id = randomUUID();
122
+ const displayName = options.name ?? this.generateDisplayName();
123
+ const now = Date.now();
124
+ const session = {
125
+ id,
126
+ displayName,
127
+ createdAt: now,
128
+ lastActivity: now,
129
+ process: {
130
+ pid: null,
131
+ shell: options.shell ?? this.config.defaultShell,
132
+ args: options.args ?? [],
133
+ cwd: options.cwd ?? homedir(),
134
+ env: {
135
+ ...getDefaultEnv(),
136
+ ...options.env,
137
+ },
138
+ },
139
+ terminal: {
140
+ cols: options.cols ?? DEFAULTS.defaultCols,
141
+ rows: options.rows ?? DEFAULTS.defaultRows,
142
+ cursorX: 0,
143
+ cursorY: 0,
144
+ cursorStyle: 'block',
145
+ cursorVisible: true,
146
+ },
147
+ scrollbackFile: 'scrollback.jsonl',
148
+ scrollbackLength: 0,
149
+ sharing: null,
150
+ };
151
+ // Create session directory
152
+ const sessionDir = this.paths.sessionDir(id);
153
+ mkdirSync(sessionDir, { recursive: true });
154
+ // Spawn PTY process if requested (default: true)
155
+ // Web sessions use startProcess: false to wait for client connection
156
+ if (options.startProcess !== false) {
157
+ await this.spawnProcess(session);
158
+ }
159
+ // Save to memory and disk
160
+ this.sessions.set(id, session);
161
+ await this.persistSession(session);
162
+ this.emit('session:created', session);
163
+ return session;
164
+ }
165
+ /**
166
+ * Get a session by ID.
167
+ */
168
+ getSession(sessionId) {
169
+ return this.sessions.get(sessionId);
170
+ }
171
+ /**
172
+ * Get the PTY process for a session.
173
+ * Returns undefined if the process is not running.
174
+ */
175
+ getPty(sessionId) {
176
+ return this.ptyProcesses.get(sessionId);
177
+ }
178
+ /**
179
+ * List all sessions with summary info.
180
+ */
181
+ async listSessions() {
182
+ const sessions = [];
183
+ for (const session of this.sessions.values()) {
184
+ sessions.push({
185
+ id: session.id,
186
+ displayName: session.displayName,
187
+ lastActivity: session.lastActivity,
188
+ isRunning: session.process.pid !== null,
189
+ connectionCount: 0, // TODO: Track connections
190
+ isShared: session.sharing?.enabled ?? false,
191
+ });
192
+ }
193
+ // Sort by last activity (most recent first)
194
+ sessions.sort((a, b) => b.lastActivity - a.lastActivity);
195
+ return sessions;
196
+ }
197
+ /**
198
+ * Delete a session and all associated data.
199
+ */
200
+ async deleteSession(sessionId) {
201
+ const session = this.sessions.get(sessionId);
202
+ if (!session) {
203
+ throw new Error(`Session not found: ${sessionId}`);
204
+ }
205
+ // Kill the PTY process if running
206
+ const pty = this.ptyProcesses.get(sessionId);
207
+ if (pty) {
208
+ pty.kill();
209
+ this.ptyProcesses.delete(sessionId);
210
+ }
211
+ // Close the output recorder
212
+ const recorder = this.outputRecorders.get(sessionId);
213
+ if (recorder) {
214
+ await recorder.close();
215
+ this.outputRecorders.delete(sessionId);
216
+ }
217
+ // Remove from memory
218
+ this.sessions.delete(sessionId);
219
+ // Remove from disk
220
+ const sessionDir = this.paths.sessionDir(sessionId);
221
+ if (existsSync(sessionDir)) {
222
+ await fs.rm(sessionDir, { recursive: true, force: true });
223
+ }
224
+ this.emit('session:deleted', sessionId);
225
+ }
226
+ /**
227
+ * Rename a session.
228
+ */
229
+ async renameSession(sessionId, newName) {
230
+ const session = this.sessions.get(sessionId);
231
+ if (!session) {
232
+ throw new Error(`Session not found: ${sessionId}`);
233
+ }
234
+ session.displayName = newName;
235
+ session.lastActivity = Date.now();
236
+ await this.persistSession(session);
237
+ }
238
+ /**
239
+ * Resize a session's terminal.
240
+ */
241
+ async resizeSession(sessionId, cols, rows) {
242
+ const session = this.sessions.get(sessionId);
243
+ if (!session) {
244
+ throw new Error(`Session not found: ${sessionId}`);
245
+ }
246
+ // Update session state first
247
+ session.terminal.cols = cols;
248
+ session.terminal.rows = rows;
249
+ session.lastActivity = Date.now();
250
+ // Persist before attempting PTY resize (so state is saved even if PTY fails)
251
+ await this.persistSession(session);
252
+ // Try to resize the PTY (may fail if process exited)
253
+ const pty = this.ptyProcesses.get(sessionId);
254
+ if (pty) {
255
+ try {
256
+ pty.resize(cols, rows);
257
+ }
258
+ catch {
259
+ // PTY may have exited, that's ok - state is already updated
260
+ }
261
+ }
262
+ }
263
+ /**
264
+ * Connect to a session, respawning the process if needed.
265
+ * Returns the PTY for I/O.
266
+ */
267
+ async connectToSession(sessionId) {
268
+ const session = this.sessions.get(sessionId);
269
+ if (!session) {
270
+ throw new Error(`Session not found: ${sessionId}`);
271
+ }
272
+ // Respawn process if it's not running
273
+ const hasPty = this.ptyProcesses.has(sessionId);
274
+ if (!hasPty) {
275
+ await this.spawnProcess(session);
276
+ }
277
+ const pty = this.ptyProcesses.get(sessionId);
278
+ if (!pty) {
279
+ throw new Error(`Failed to get PTY for session: ${sessionId}`);
280
+ }
281
+ session.lastActivity = Date.now();
282
+ await this.persistSession(session);
283
+ return pty;
284
+ }
285
+ /**
286
+ * Write data to a session's PTY.
287
+ */
288
+ write(sessionId, data) {
289
+ const pty = this.ptyProcesses.get(sessionId);
290
+ if (!pty) {
291
+ throw new Error(`No PTY for session: ${sessionId}`);
292
+ }
293
+ pty.write(data);
294
+ const session = this.sessions.get(sessionId);
295
+ if (session) {
296
+ session.lastActivity = Date.now();
297
+ }
298
+ }
299
+ /**
300
+ * Get the storage paths for session data.
301
+ */
302
+ getPaths() {
303
+ return this.paths;
304
+ }
305
+ /**
306
+ * Get the buffered output for a session (for replay on reconnect).
307
+ * Returns the concatenated output as a single string.
308
+ * Note: This loads all scrollback into memory. For large histories,
309
+ * use getScrollbackChunks() instead.
310
+ */
311
+ async getScrollback(sessionId) {
312
+ const recorder = this.outputRecorders.get(sessionId);
313
+ if (!recorder) {
314
+ return '';
315
+ }
316
+ const chunks = await recorder.readAll();
317
+ return chunks.map((c) => c.d).join('');
318
+ }
319
+ /**
320
+ * Get scrollback chunks for a session with pagination.
321
+ * @param sessionId Session ID
322
+ * @param offset Number of chunks to skip from the start
323
+ * @param limit Maximum number of chunks to return
324
+ */
325
+ async getScrollbackChunks(sessionId, offset = 0, limit = 1000) {
326
+ const recorder = this.outputRecorders.get(sessionId);
327
+ if (!recorder) {
328
+ return [];
329
+ }
330
+ return recorder.read(offset, limit);
331
+ }
332
+ /**
333
+ * Get the total number of scrollback chunks for a session.
334
+ */
335
+ getScrollbackLength(sessionId) {
336
+ const recorder = this.outputRecorders.get(sessionId);
337
+ return recorder ? recorder.getChunkCount() : 0;
338
+ }
339
+ /**
340
+ * Create a history replay for streaming scrollback to a client.
341
+ * The replay emits 'data', 'progress', and 'complete' events.
342
+ */
343
+ async createHistoryReplay(sessionId) {
344
+ const recorder = this.outputRecorders.get(sessionId);
345
+ if (!recorder) {
346
+ return null;
347
+ }
348
+ const chunks = await recorder.readAll();
349
+ const replay = new HistoryReplay({
350
+ chunkSize: 100,
351
+ batchDelay: 10,
352
+ });
353
+ // Start replay in next tick to allow event handler setup
354
+ setImmediate(() => {
355
+ replay.start(chunks).catch((err) => replay.emit('error', err));
356
+ });
357
+ return replay;
358
+ }
359
+ /**
360
+ * Spawn a PTY process for a session.
361
+ */
362
+ async spawnProcess(session) {
363
+ const pty = await getPty();
364
+ const ptyProcess = pty.spawn(session.process.shell, session.process.args, {
365
+ name: 'xterm-256color',
366
+ cols: session.terminal.cols,
367
+ rows: session.terminal.rows,
368
+ cwd: session.process.cwd,
369
+ env: {
370
+ ...process.env,
371
+ ...session.process.env,
372
+ },
373
+ });
374
+ session.process.pid = ptyProcess.pid;
375
+ this.ptyProcesses.set(session.id, ptyProcess);
376
+ // Initialize output recorder for scrollback (disk-backed)
377
+ if (!this.outputRecorders.has(session.id)) {
378
+ const recorder = new OutputRecorder({
379
+ filePath: this.paths.scrollbackFile(session.id),
380
+ maxChunks: this.config.scrollbackLimit,
381
+ });
382
+ await recorder.init();
383
+ this.outputRecorders.set(session.id, recorder);
384
+ }
385
+ // Handle output
386
+ ptyProcess.onData((data) => {
387
+ // Record output to disk-backed scrollback
388
+ const recorder = this.outputRecorders.get(session.id);
389
+ if (recorder) {
390
+ recorder.record(data);
391
+ }
392
+ this.emit('session:output', session.id, data);
393
+ session.lastActivity = Date.now();
394
+ });
395
+ // Handle exit
396
+ ptyProcess.onExit(({ exitCode }) => {
397
+ session.process.pid = null;
398
+ this.ptyProcesses.delete(session.id);
399
+ // Flush scrollback before persisting session
400
+ const recorder = this.outputRecorders.get(session.id);
401
+ if (recorder) {
402
+ recorder.flush().catch(console.error);
403
+ }
404
+ this.persistSession(session).catch(console.error);
405
+ this.emit('session:exit', session.id, exitCode);
406
+ });
407
+ }
408
+ /**
409
+ * Persist a session's metadata to disk.
410
+ */
411
+ async persistSession(session) {
412
+ const metadataPath = this.paths.metadataFile(session.id);
413
+ const data = JSON.stringify(session, null, 2);
414
+ await fs.writeFile(metadataPath, data, 'utf-8');
415
+ }
416
+ /**
417
+ * Load persisted sessions from disk.
418
+ */
419
+ async loadPersistedSessions() {
420
+ const baseDir = this.paths.baseDir;
421
+ if (!existsSync(baseDir)) {
422
+ return;
423
+ }
424
+ const entries = await fs.readdir(baseDir, { withFileTypes: true });
425
+ for (const entry of entries) {
426
+ if (!entry.isDirectory())
427
+ continue;
428
+ const sessionId = entry.name;
429
+ const metadataPath = this.paths.metadataFile(sessionId);
430
+ if (!existsSync(metadataPath))
431
+ continue;
432
+ try {
433
+ const data = await fs.readFile(metadataPath, 'utf-8');
434
+ const session = JSON.parse(data);
435
+ // Mark process as not running (it died when server stopped)
436
+ session.process.pid = null;
437
+ this.sessions.set(sessionId, session);
438
+ }
439
+ catch (error) {
440
+ console.error(`Failed to load session ${sessionId}:`, error);
441
+ }
442
+ }
443
+ }
444
+ /**
445
+ * Generate a display name for a new session.
446
+ * Returns the next available number (1, 2, 3, ...).
447
+ */
448
+ generateDisplayName() {
449
+ const existingNames = new Set(Array.from(this.sessions.values()).map((s) => s.displayName));
450
+ let num = 1;
451
+ while (existingNames.has(String(num))) {
452
+ num++;
453
+ }
454
+ return String(num);
455
+ }
456
+ /**
457
+ * Clean up all resources.
458
+ */
459
+ async destroy() {
460
+ // Kill all PTY processes
461
+ for (const pty of this.ptyProcesses.values()) {
462
+ pty.kill();
463
+ }
464
+ this.ptyProcesses.clear();
465
+ // Close all output recorders (flushes pending data)
466
+ for (const recorder of this.outputRecorders.values()) {
467
+ await recorder.close();
468
+ }
469
+ this.outputRecorders.clear();
470
+ // Persist all sessions
471
+ for (const session of this.sessions.values()) {
472
+ await this.persistSession(session);
473
+ }
474
+ this.removeAllListeners();
475
+ }
476
+ }
477
+ /**
478
+ * Singleton instance for convenience.
479
+ * For most use cases, you can use this directly.
480
+ */
481
+ let defaultManager = null;
482
+ export function getSessionManager(config) {
483
+ if (!defaultManager) {
484
+ defaultManager = new SessionManager(config);
485
+ }
486
+ return defaultManager;
487
+ }
488
+ export { getDefaultShell, getDefaultEnv };
489
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["session-manager.ts"],"names":[],"mappings":"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"}