lit-shell.js 0.1.4 → 1.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.
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Session manager for multiplexed terminal sessions.
3
+ *
4
+ * Responsibilities:
5
+ * - Manage shared session lifecycle
6
+ * - Track client connections per session
7
+ * - Handle orphan session cleanup
8
+ * - Maintain history buffers
9
+ * - Broadcast messages to session clients
10
+ */
11
+ import { EventEmitter } from 'events';
12
+ import type { WebSocket } from 'ws';
13
+ import { CircularBuffer } from './circular-buffer.js';
14
+ import type { SessionType, SharedSessionInfo, SessionListFilter } from '../shared/types.js';
15
+ /**
16
+ * Session manager configuration
17
+ */
18
+ export interface SessionManagerConfig {
19
+ /** Maximum clients per session (default: 10) */
20
+ maxClientsPerSession?: number;
21
+ /** Orphan timeout in ms before killing session (default: 60000) */
22
+ orphanTimeout?: number;
23
+ /** History buffer size in characters (default: 50000) */
24
+ historySize?: number;
25
+ /** Enable history by default (default: true) */
26
+ historyEnabled?: boolean;
27
+ /** Maximum total sessions (default: 100) */
28
+ maxSessionsTotal?: number;
29
+ /** Verbose logging (default: false) */
30
+ verbose?: boolean;
31
+ }
32
+ /**
33
+ * Client info for session management
34
+ */
35
+ export interface ClientInfo {
36
+ id: string;
37
+ ws: WebSocket;
38
+ joinedAt: Date;
39
+ lastActivity: Date;
40
+ }
41
+ /**
42
+ * Shared terminal session supporting multiple clients
43
+ */
44
+ export interface SharedSession {
45
+ id: string;
46
+ type: SessionType;
47
+ pty: any;
48
+ shell: string;
49
+ cwd: string;
50
+ cols: number;
51
+ rows: number;
52
+ createdAt: Date;
53
+ lastActivity: Date;
54
+ container?: string;
55
+ clients: Map<string, ClientInfo>;
56
+ owner: string;
57
+ label?: string;
58
+ accepting: boolean;
59
+ historyBuffer: CircularBuffer;
60
+ historyEnabled: boolean;
61
+ orphanedAt: Date | null;
62
+ }
63
+ /**
64
+ * Events emitted by SessionManager
65
+ */
66
+ export interface SessionManagerEvents {
67
+ sessionCreated: (session: SharedSession) => void;
68
+ sessionClosed: (sessionId: string, reason: string) => void;
69
+ clientJoined: (sessionId: string, clientId: string, clientCount: number) => void;
70
+ clientLeft: (sessionId: string, clientId: string, clientCount: number) => void;
71
+ sessionOrphaned: (sessionId: string) => void;
72
+ error: (error: Error, context: string) => void;
73
+ }
74
+ export declare class SessionManager extends EventEmitter {
75
+ private sessions;
76
+ private clientToSessions;
77
+ private orphanTimers;
78
+ private config;
79
+ constructor(config?: SessionManagerConfig);
80
+ private log;
81
+ /**
82
+ * Create a new shared session.
83
+ */
84
+ createSession(options: {
85
+ id: string;
86
+ type: SessionType;
87
+ pty: any;
88
+ shell: string;
89
+ cwd: string;
90
+ cols: number;
91
+ rows: number;
92
+ ownerId: string;
93
+ ownerWs: WebSocket;
94
+ container?: string;
95
+ label?: string;
96
+ allowJoin?: boolean;
97
+ enableHistory?: boolean;
98
+ }): SharedSession;
99
+ /**
100
+ * Get a session by ID.
101
+ */
102
+ getSession(sessionId: string): SharedSession | undefined;
103
+ /**
104
+ * Get all sessions, optionally filtered.
105
+ */
106
+ getSessions(filter?: SessionListFilter): SharedSession[];
107
+ /**
108
+ * Close a session and clean up.
109
+ */
110
+ closeSession(sessionId: string, reason: string): void;
111
+ /**
112
+ * Check if a session exists.
113
+ */
114
+ hasSession(sessionId: string): boolean;
115
+ /**
116
+ * Get session count.
117
+ */
118
+ getSessionCount(): number;
119
+ /**
120
+ * Add a client to a session.
121
+ */
122
+ addClient(sessionId: string, clientId: string, ws: WebSocket): boolean;
123
+ /**
124
+ * Remove a client from a session.
125
+ */
126
+ removeClient(sessionId: string, clientId: string): void;
127
+ /**
128
+ * Remove a client from all sessions.
129
+ */
130
+ removeClientFromAllSessions(clientId: string): string[];
131
+ /**
132
+ * Get all clients in a session.
133
+ */
134
+ getSessionClients(sessionId: string): ClientInfo[];
135
+ /**
136
+ * Get client count for a session.
137
+ */
138
+ getClientCount(sessionId: string): number;
139
+ /**
140
+ * Check if a client is in a session.
141
+ */
142
+ isClientInSession(sessionId: string, clientId: string): boolean;
143
+ /**
144
+ * Get all sessions a client is in.
145
+ */
146
+ getClientSessions(clientId: string): string[];
147
+ private trackClientSession;
148
+ /**
149
+ * Broadcast a message to all clients in a session.
150
+ */
151
+ broadcastToSession(sessionId: string, message: object, excludeClientId?: string): void;
152
+ /**
153
+ * Send a message to a specific client in a session.
154
+ */
155
+ sendToClient(sessionId: string, clientId: string, message: object): boolean;
156
+ /**
157
+ * Append data to a session's history buffer.
158
+ */
159
+ appendHistory(sessionId: string, data: string): void;
160
+ /**
161
+ * Get history from a session.
162
+ */
163
+ getHistory(sessionId: string, limit?: number): string;
164
+ /**
165
+ * Clear history for a session.
166
+ */
167
+ clearHistory(sessionId: string): void;
168
+ /**
169
+ * Update last activity timestamp for a session.
170
+ */
171
+ updateSessionActivity(sessionId: string): void;
172
+ /**
173
+ * Update last activity for a client.
174
+ */
175
+ updateClientActivity(sessionId: string, clientId: string): void;
176
+ private handleOrphanedSession;
177
+ private clearOrphanTimer;
178
+ /**
179
+ * Convert a session to SharedSessionInfo for client consumption.
180
+ */
181
+ toSharedSessionInfo(session: SharedSession): SharedSessionInfo;
182
+ /**
183
+ * Clean up all sessions and resources.
184
+ */
185
+ cleanup(): void;
186
+ /**
187
+ * Get manager statistics.
188
+ */
189
+ getStats(): {
190
+ sessionCount: number;
191
+ clientCount: number;
192
+ orphanedCount: number;
193
+ };
194
+ }
195
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/server/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,448 @@
1
+ /**
2
+ * Session manager for multiplexed terminal sessions.
3
+ *
4
+ * Responsibilities:
5
+ * - Manage shared session lifecycle
6
+ * - Track client connections per session
7
+ * - Handle orphan session cleanup
8
+ * - Maintain history buffers
9
+ * - Broadcast messages to session clients
10
+ */
11
+ import { EventEmitter } from 'events';
12
+ import { CircularBuffer } from './circular-buffer.js';
13
+ export class SessionManager extends EventEmitter {
14
+ constructor(config = {}) {
15
+ super();
16
+ this.sessions = new Map();
17
+ this.clientToSessions = new Map(); // clientId -> sessionIds
18
+ this.orphanTimers = new Map();
19
+ this.config = {
20
+ maxClientsPerSession: config.maxClientsPerSession ?? 10,
21
+ orphanTimeout: config.orphanTimeout ?? 60000,
22
+ historySize: config.historySize ?? 50000,
23
+ historyEnabled: config.historyEnabled ?? true,
24
+ maxSessionsTotal: config.maxSessionsTotal ?? 100,
25
+ verbose: config.verbose ?? false,
26
+ };
27
+ }
28
+ log(message, level = 'info') {
29
+ if (this.config.verbose || level === 'error') {
30
+ const prefix = `[SessionManager]`;
31
+ if (level === 'error') {
32
+ console.error(`${prefix} ${message}`);
33
+ }
34
+ else if (level === 'warn') {
35
+ console.warn(`${prefix} ${message}`);
36
+ }
37
+ else {
38
+ console.log(`${prefix} ${message}`);
39
+ }
40
+ }
41
+ }
42
+ // ==========================================================================
43
+ // Session CRUD
44
+ // ==========================================================================
45
+ /**
46
+ * Create a new shared session.
47
+ */
48
+ createSession(options) {
49
+ if (this.sessions.size >= this.config.maxSessionsTotal) {
50
+ throw new Error('Maximum number of sessions reached');
51
+ }
52
+ const now = new Date();
53
+ const session = {
54
+ id: options.id,
55
+ type: options.type,
56
+ pty: options.pty,
57
+ shell: options.shell,
58
+ cwd: options.cwd,
59
+ cols: options.cols,
60
+ rows: options.rows,
61
+ createdAt: now,
62
+ lastActivity: now,
63
+ container: options.container,
64
+ clients: new Map(),
65
+ owner: options.ownerId,
66
+ label: options.label,
67
+ accepting: options.allowJoin !== false,
68
+ historyBuffer: new CircularBuffer(this.config.historySize),
69
+ historyEnabled: options.enableHistory !== false && this.config.historyEnabled,
70
+ orphanedAt: null,
71
+ };
72
+ // Add owner as first client
73
+ session.clients.set(options.ownerId, {
74
+ id: options.ownerId,
75
+ ws: options.ownerWs,
76
+ joinedAt: now,
77
+ lastActivity: now,
78
+ });
79
+ // Track client -> sessions mapping
80
+ this.trackClientSession(options.ownerId, session.id);
81
+ this.sessions.set(session.id, session);
82
+ this.log(`Created session ${session.id} (type: ${session.type}, owner: ${options.ownerId})`);
83
+ this.emit('sessionCreated', session);
84
+ return session;
85
+ }
86
+ /**
87
+ * Get a session by ID.
88
+ */
89
+ getSession(sessionId) {
90
+ return this.sessions.get(sessionId);
91
+ }
92
+ /**
93
+ * Get all sessions, optionally filtered.
94
+ */
95
+ getSessions(filter) {
96
+ let sessions = Array.from(this.sessions.values());
97
+ if (filter) {
98
+ if (filter.type) {
99
+ sessions = sessions.filter((s) => s.type === filter.type);
100
+ }
101
+ if (filter.container) {
102
+ sessions = sessions.filter((s) => s.container === filter.container);
103
+ }
104
+ if (filter.accepting !== undefined) {
105
+ sessions = sessions.filter((s) => s.accepting === filter.accepting);
106
+ }
107
+ }
108
+ return sessions;
109
+ }
110
+ /**
111
+ * Close a session and clean up.
112
+ */
113
+ closeSession(sessionId, reason) {
114
+ const session = this.sessions.get(sessionId);
115
+ if (!session)
116
+ return;
117
+ this.log(`Closing session ${sessionId} (reason: ${reason})`);
118
+ // Clear orphan timer if any
119
+ this.clearOrphanTimer(sessionId);
120
+ // Kill PTY
121
+ try {
122
+ session.pty.kill();
123
+ }
124
+ catch (e) {
125
+ this.log(`Error killing PTY for session ${sessionId}: ${e}`, 'warn');
126
+ }
127
+ // Remove session from all client mappings
128
+ for (const clientId of session.clients.keys()) {
129
+ const clientSessions = this.clientToSessions.get(clientId);
130
+ if (clientSessions) {
131
+ clientSessions.delete(sessionId);
132
+ if (clientSessions.size === 0) {
133
+ this.clientToSessions.delete(clientId);
134
+ }
135
+ }
136
+ }
137
+ // Remove session
138
+ this.sessions.delete(sessionId);
139
+ this.emit('sessionClosed', sessionId, reason);
140
+ }
141
+ /**
142
+ * Check if a session exists.
143
+ */
144
+ hasSession(sessionId) {
145
+ return this.sessions.has(sessionId);
146
+ }
147
+ /**
148
+ * Get session count.
149
+ */
150
+ getSessionCount() {
151
+ return this.sessions.size;
152
+ }
153
+ // ==========================================================================
154
+ // Client Management
155
+ // ==========================================================================
156
+ /**
157
+ * Add a client to a session.
158
+ */
159
+ addClient(sessionId, clientId, ws) {
160
+ const session = this.sessions.get(sessionId);
161
+ if (!session) {
162
+ this.log(`Cannot add client to non-existent session ${sessionId}`, 'warn');
163
+ return false;
164
+ }
165
+ if (!session.accepting) {
166
+ this.log(`Session ${sessionId} is not accepting new clients`, 'warn');
167
+ return false;
168
+ }
169
+ if (session.clients.size >= this.config.maxClientsPerSession) {
170
+ this.log(`Session ${sessionId} is full`, 'warn');
171
+ return false;
172
+ }
173
+ // If session was orphaned, clear the timer
174
+ if (session.orphanedAt) {
175
+ session.orphanedAt = null;
176
+ this.clearOrphanTimer(sessionId);
177
+ this.log(`Session ${sessionId} is no longer orphaned`);
178
+ }
179
+ const now = new Date();
180
+ session.clients.set(clientId, {
181
+ id: clientId,
182
+ ws,
183
+ joinedAt: now,
184
+ lastActivity: now,
185
+ });
186
+ this.trackClientSession(clientId, sessionId);
187
+ this.log(`Client ${clientId} joined session ${sessionId} (${session.clients.size} clients)`);
188
+ this.emit('clientJoined', sessionId, clientId, session.clients.size);
189
+ return true;
190
+ }
191
+ /**
192
+ * Remove a client from a session.
193
+ */
194
+ removeClient(sessionId, clientId) {
195
+ const session = this.sessions.get(sessionId);
196
+ if (!session)
197
+ return;
198
+ if (!session.clients.has(clientId))
199
+ return;
200
+ session.clients.delete(clientId);
201
+ // Update client -> sessions mapping
202
+ const clientSessions = this.clientToSessions.get(clientId);
203
+ if (clientSessions) {
204
+ clientSessions.delete(sessionId);
205
+ if (clientSessions.size === 0) {
206
+ this.clientToSessions.delete(clientId);
207
+ }
208
+ }
209
+ this.log(`Client ${clientId} left session ${sessionId} (${session.clients.size} clients remaining)`);
210
+ this.emit('clientLeft', sessionId, clientId, session.clients.size);
211
+ // Check if session is now orphaned
212
+ if (session.clients.size === 0) {
213
+ this.handleOrphanedSession(session);
214
+ }
215
+ }
216
+ /**
217
+ * Remove a client from all sessions.
218
+ */
219
+ removeClientFromAllSessions(clientId) {
220
+ const clientSessions = this.clientToSessions.get(clientId);
221
+ if (!clientSessions)
222
+ return [];
223
+ const sessionIds = Array.from(clientSessions);
224
+ for (const sessionId of sessionIds) {
225
+ this.removeClient(sessionId, clientId);
226
+ }
227
+ return sessionIds;
228
+ }
229
+ /**
230
+ * Get all clients in a session.
231
+ */
232
+ getSessionClients(sessionId) {
233
+ const session = this.sessions.get(sessionId);
234
+ return session ? Array.from(session.clients.values()) : [];
235
+ }
236
+ /**
237
+ * Get client count for a session.
238
+ */
239
+ getClientCount(sessionId) {
240
+ const session = this.sessions.get(sessionId);
241
+ return session ? session.clients.size : 0;
242
+ }
243
+ /**
244
+ * Check if a client is in a session.
245
+ */
246
+ isClientInSession(sessionId, clientId) {
247
+ const session = this.sessions.get(sessionId);
248
+ return session ? session.clients.has(clientId) : false;
249
+ }
250
+ /**
251
+ * Get all sessions a client is in.
252
+ */
253
+ getClientSessions(clientId) {
254
+ const clientSessions = this.clientToSessions.get(clientId);
255
+ return clientSessions ? Array.from(clientSessions) : [];
256
+ }
257
+ trackClientSession(clientId, sessionId) {
258
+ let clientSessions = this.clientToSessions.get(clientId);
259
+ if (!clientSessions) {
260
+ clientSessions = new Set();
261
+ this.clientToSessions.set(clientId, clientSessions);
262
+ }
263
+ clientSessions.add(sessionId);
264
+ }
265
+ // ==========================================================================
266
+ // Broadcasting
267
+ // ==========================================================================
268
+ /**
269
+ * Broadcast a message to all clients in a session.
270
+ */
271
+ broadcastToSession(sessionId, message, excludeClientId) {
272
+ const session = this.sessions.get(sessionId);
273
+ if (!session)
274
+ return;
275
+ const messageStr = JSON.stringify(message);
276
+ for (const [clientId, client] of session.clients) {
277
+ if (clientId === excludeClientId)
278
+ continue;
279
+ try {
280
+ if (client.ws.readyState === 1) {
281
+ // WebSocket.OPEN
282
+ client.ws.send(messageStr);
283
+ }
284
+ }
285
+ catch (e) {
286
+ this.log(`Error broadcasting to client ${clientId}: ${e}`, 'warn');
287
+ }
288
+ }
289
+ }
290
+ /**
291
+ * Send a message to a specific client in a session.
292
+ */
293
+ sendToClient(sessionId, clientId, message) {
294
+ const session = this.sessions.get(sessionId);
295
+ if (!session)
296
+ return false;
297
+ const client = session.clients.get(clientId);
298
+ if (!client)
299
+ return false;
300
+ try {
301
+ if (client.ws.readyState === 1) {
302
+ client.ws.send(JSON.stringify(message));
303
+ return true;
304
+ }
305
+ }
306
+ catch (e) {
307
+ this.log(`Error sending to client ${clientId}: ${e}`, 'warn');
308
+ }
309
+ return false;
310
+ }
311
+ // ==========================================================================
312
+ // History
313
+ // ==========================================================================
314
+ /**
315
+ * Append data to a session's history buffer.
316
+ */
317
+ appendHistory(sessionId, data) {
318
+ const session = this.sessions.get(sessionId);
319
+ if (session && session.historyEnabled) {
320
+ session.historyBuffer.append(data);
321
+ }
322
+ }
323
+ /**
324
+ * Get history from a session.
325
+ */
326
+ getHistory(sessionId, limit) {
327
+ const session = this.sessions.get(sessionId);
328
+ if (!session || !session.historyEnabled)
329
+ return '';
330
+ return session.historyBuffer.toString(limit);
331
+ }
332
+ /**
333
+ * Clear history for a session.
334
+ */
335
+ clearHistory(sessionId) {
336
+ const session = this.sessions.get(sessionId);
337
+ if (session) {
338
+ session.historyBuffer.clear();
339
+ }
340
+ }
341
+ // ==========================================================================
342
+ // Activity Tracking
343
+ // ==========================================================================
344
+ /**
345
+ * Update last activity timestamp for a session.
346
+ */
347
+ updateSessionActivity(sessionId) {
348
+ const session = this.sessions.get(sessionId);
349
+ if (session) {
350
+ session.lastActivity = new Date();
351
+ }
352
+ }
353
+ /**
354
+ * Update last activity for a client.
355
+ */
356
+ updateClientActivity(sessionId, clientId) {
357
+ const session = this.sessions.get(sessionId);
358
+ if (session) {
359
+ session.lastActivity = new Date();
360
+ const client = session.clients.get(clientId);
361
+ if (client) {
362
+ client.lastActivity = new Date();
363
+ }
364
+ }
365
+ }
366
+ // ==========================================================================
367
+ // Orphan Handling
368
+ // ==========================================================================
369
+ handleOrphanedSession(session) {
370
+ session.orphanedAt = new Date();
371
+ this.log(`Session ${session.id} is now orphaned, starting cleanup timer`);
372
+ this.emit('sessionOrphaned', session.id);
373
+ // Start orphan timer
374
+ const timer = setTimeout(() => {
375
+ // Check if still orphaned
376
+ if (session.clients.size === 0) {
377
+ this.log(`Orphan timeout for session ${session.id}, closing`);
378
+ this.closeSession(session.id, 'orphan_timeout');
379
+ }
380
+ }, this.config.orphanTimeout);
381
+ this.orphanTimers.set(session.id, timer);
382
+ }
383
+ clearOrphanTimer(sessionId) {
384
+ const timer = this.orphanTimers.get(sessionId);
385
+ if (timer) {
386
+ clearTimeout(timer);
387
+ this.orphanTimers.delete(sessionId);
388
+ }
389
+ }
390
+ // ==========================================================================
391
+ // Session Info
392
+ // ==========================================================================
393
+ /**
394
+ * Convert a session to SharedSessionInfo for client consumption.
395
+ */
396
+ toSharedSessionInfo(session) {
397
+ return {
398
+ sessionId: session.id,
399
+ type: session.type,
400
+ shell: session.shell,
401
+ cwd: session.cwd,
402
+ cols: session.cols,
403
+ rows: session.rows,
404
+ createdAt: session.createdAt,
405
+ container: session.container,
406
+ clientCount: session.clients.size,
407
+ accepting: session.accepting,
408
+ ownerId: session.owner,
409
+ label: session.label,
410
+ historyEnabled: session.historyEnabled,
411
+ };
412
+ }
413
+ // ==========================================================================
414
+ // Cleanup
415
+ // ==========================================================================
416
+ /**
417
+ * Clean up all sessions and resources.
418
+ */
419
+ cleanup() {
420
+ this.log('Cleaning up all sessions');
421
+ // Clear all orphan timers
422
+ for (const timer of this.orphanTimers.values()) {
423
+ clearTimeout(timer);
424
+ }
425
+ this.orphanTimers.clear();
426
+ // Close all sessions
427
+ for (const sessionId of this.sessions.keys()) {
428
+ this.closeSession(sessionId, 'cleanup');
429
+ }
430
+ this.clientToSessions.clear();
431
+ }
432
+ /**
433
+ * Get manager statistics.
434
+ */
435
+ getStats() {
436
+ let orphanedCount = 0;
437
+ for (const session of this.sessions.values()) {
438
+ if (session.orphanedAt)
439
+ orphanedCount++;
440
+ }
441
+ return {
442
+ sessionCount: this.sessions.size,
443
+ clientCount: this.clientToSessions.size,
444
+ orphanedCount,
445
+ };
446
+ }
447
+ }
448
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/server/session-manager.ts"],"names":[],"mappings":"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"}