@ebowwa/terminal 0.2.1 → 0.3.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.
@@ -1,1026 +0,0 @@
1
- "use strict";
2
- /**
3
- * Multi-Node Tmux Session Manager
4
- * Provides unified management of tmux sessions across multiple VPS nodes
5
- * Supports batch operations, session tracking, and parallel execution
6
- */
7
- var __assign = (this && this.__assign) || function () {
8
- __assign = Object.assign || function(t) {
9
- for (var s, i = 1, n = arguments.length; i < n; i++) {
10
- s = arguments[i];
11
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
12
- t[p] = s[p];
13
- }
14
- return t;
15
- };
16
- return __assign.apply(this, arguments);
17
- };
18
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
19
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
- return new (P || (P = Promise))(function (resolve, reject) {
21
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
- step((generator = generator.apply(thisArg, _arguments || [])).next());
25
- });
26
- };
27
- var __generator = (this && this.__generator) || function (thisArg, body) {
28
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
29
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
30
- function verb(n) { return function (v) { return step([n, v]); }; }
31
- function step(op) {
32
- if (f) throw new TypeError("Generator is already executing.");
33
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
34
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
35
- if (y = 0, t) op = [op[0] & 2, t.value];
36
- switch (op[0]) {
37
- case 0: case 1: t = op; break;
38
- case 4: _.label++; return { value: op[1], done: false };
39
- case 5: _.label++; y = op[1]; op = [0]; continue;
40
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
41
- default:
42
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
43
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
44
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
45
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
46
- if (t[2]) _.ops.pop();
47
- _.trys.pop(); continue;
48
- }
49
- op = body.call(thisArg, _);
50
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
51
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
52
- }
53
- };
54
- Object.defineProperty(exports, "__esModule", { value: true });
55
- exports.TmuxSessionManager = void 0;
56
- exports.getTmuxManager = getTmuxManager;
57
- exports.resetTmuxManager = resetTmuxManager;
58
- var tmux_js_1 = require("./tmux.js");
59
- /**
60
- * Multi-Node Tmux Session Manager
61
- * Manages tmux sessions across multiple VPS nodes
62
- */
63
- var TmuxSessionManager = /** @class */ (function () {
64
- function TmuxSessionManager() {
65
- this.nodes = new Map();
66
- this.sessionCache = new Map();
67
- this.cacheTimeout = 30000; // 30 seconds
68
- this.lastCacheUpdate = new Map();
69
- }
70
- /**
71
- * Add or update a node in the manager
72
- */
73
- TmuxSessionManager.prototype.addNode = function (node) {
74
- this.nodes.set(node.id, __assign({}, node));
75
- // Invalidate cache for this node
76
- this.sessionCache.delete(node.id);
77
- this.lastCacheUpdate.delete(node.id);
78
- };
79
- /**
80
- * Remove a node from the manager
81
- */
82
- TmuxSessionManager.prototype.removeNode = function (nodeId) {
83
- this.nodes.delete(nodeId);
84
- this.sessionCache.delete(nodeId);
85
- this.lastCacheUpdate.delete(nodeId);
86
- };
87
- /**
88
- * Get a node by ID
89
- */
90
- TmuxSessionManager.prototype.getNode = function (nodeId) {
91
- return this.nodes.get(nodeId);
92
- };
93
- /**
94
- * Get all nodes
95
- */
96
- TmuxSessionManager.prototype.getAllNodes = function () {
97
- return Array.from(this.nodes.values());
98
- };
99
- /**
100
- * Get nodes by tag
101
- */
102
- TmuxSessionManager.prototype.getNodesByTag = function (tag) {
103
- return this.getAllNodes().filter(function (node) { var _a; return (_a = node.tags) === null || _a === void 0 ? void 0 : _a.includes(tag); });
104
- };
105
- /**
106
- * Get active nodes (running and reachable)
107
- */
108
- TmuxSessionManager.prototype.getActiveNodes = function () {
109
- return this.getAllNodes().filter(function (node) { return node.status === "running"; });
110
- };
111
- /**
112
- * Get SSH options for a node
113
- */
114
- TmuxSessionManager.prototype.getSSHOptions = function (node) {
115
- return {
116
- host: node.ip,
117
- user: node.user,
118
- port: node.port,
119
- keyPath: node.keyPath,
120
- timeout: 30,
121
- };
122
- };
123
- /**
124
- * Invalidate session cache for a node or all nodes
125
- */
126
- TmuxSessionManager.prototype.invalidateCache = function (nodeId) {
127
- if (nodeId) {
128
- this.sessionCache.delete(nodeId);
129
- this.lastCacheUpdate.delete(nodeId);
130
- }
131
- else {
132
- this.sessionCache.clear();
133
- this.lastCacheUpdate.clear();
134
- }
135
- };
136
- /**
137
- * Check if cache is valid for a node
138
- */
139
- TmuxSessionManager.prototype.isCacheValid = function (nodeId) {
140
- var lastUpdate = this.lastCacheUpdate.get(nodeId);
141
- if (!lastUpdate)
142
- return false;
143
- return Date.now() - lastUpdate < this.cacheTimeout;
144
- };
145
- /**
146
- * Create a new tmux session on a node
147
- */
148
- TmuxSessionManager.prototype.createSession = function (nodeId_1) {
149
- return __awaiter(this, arguments, void 0, function (nodeId, options) {
150
- var node, sshOpts, tmuxCheck, sessionName, exists, createCmd, getSSHPool, pool, error_1;
151
- if (options === void 0) { options = {}; }
152
- return __generator(this, function (_a) {
153
- switch (_a.label) {
154
- case 0:
155
- node = this.getNode(nodeId);
156
- if (!node) {
157
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " not found") }];
158
- }
159
- if (node.status !== "running") {
160
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " is not running") }];
161
- }
162
- _a.label = 1;
163
- case 1:
164
- _a.trys.push([1, 10, , 11]);
165
- sshOpts = this.getSSHOptions(node);
166
- return [4 /*yield*/, (0, tmux_js_1.ensureTmux)(sshOpts)];
167
- case 2:
168
- tmuxCheck = _a.sent();
169
- if (!tmuxCheck.success) {
170
- return [2 /*return*/, { success: false, error: tmuxCheck.message }];
171
- }
172
- sessionName = options.sessionName || (0, tmux_js_1.generateSessionName)(node.ip, node.user);
173
- return [4 /*yield*/, (0, tmux_js_1.hasTmuxSession)(sessionName, sshOpts)];
174
- case 3:
175
- exists = _a.sent();
176
- if (exists) {
177
- return [2 /*return*/, { success: true, sessionName: sessionName }];
178
- }
179
- createCmd = options.initialCommand
180
- ? "tmux new-session -d -s \"".concat(sessionName, "\" -n \"main\" \"").concat(options.initialCommand, "\"")
181
- : "tmux new-session -d -s \"".concat(sessionName, "\" -n \"main\"");
182
- return [4 /*yield*/, Promise.resolve().then(function () { return require("./pool.js"); })];
183
- case 4:
184
- getSSHPool = (_a.sent()).getSSHPool;
185
- pool = getSSHPool();
186
- return [4 /*yield*/, pool.exec(createCmd, sshOpts)];
187
- case 5:
188
- _a.sent();
189
- if (!options.cwd) return [3 /*break*/, 7];
190
- return [4 /*yield*/, pool.exec("tmux set-option -t \"".concat(sessionName, "\" default-path \"").concat(options.cwd, "\""), sshOpts)];
191
- case 6:
192
- _a.sent();
193
- _a.label = 7;
194
- case 7:
195
- if (!options.layout) return [3 /*break*/, 9];
196
- return [4 /*yield*/, pool.exec("tmux select-layout -t \"".concat(sessionName, "\" ").concat(options.layout), sshOpts)];
197
- case 8:
198
- _a.sent();
199
- _a.label = 9;
200
- case 9:
201
- // Invalidate cache
202
- this.invalidateCache(nodeId);
203
- return [2 /*return*/, { success: true, sessionName: sessionName }];
204
- case 10:
205
- error_1 = _a.sent();
206
- return [2 /*return*/, {
207
- success: false,
208
- error: error_1 instanceof Error ? error_1.message : String(error_1),
209
- }];
210
- case 11: return [2 /*return*/];
211
- }
212
- });
213
- });
214
- };
215
- /**
216
- * Attach to a tmux session on a node (returns SSH command args)
217
- */
218
- TmuxSessionManager.prototype.attachSession = function (nodeId, sessionName) {
219
- return __awaiter(this, void 0, void 0, function () {
220
- var node, result, error_2;
221
- return __generator(this, function (_a) {
222
- switch (_a.label) {
223
- case 0:
224
- node = this.getNode(nodeId);
225
- if (!node) {
226
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " not found") }];
227
- }
228
- if (node.status !== "running") {
229
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " is not running") }];
230
- }
231
- _a.label = 1;
232
- case 1:
233
- _a.trys.push([1, 3, , 4]);
234
- return [4 /*yield*/, (0, tmux_js_1.createOrAttachTmuxSession)(node.ip, node.user, node.keyPath, { sessionName: sessionName })];
235
- case 2:
236
- result = _a.sent();
237
- return [2 /*return*/, {
238
- success: true,
239
- sshArgs: result.sshArgs,
240
- sessionName: result.sessionName,
241
- }];
242
- case 3:
243
- error_2 = _a.sent();
244
- return [2 /*return*/, {
245
- success: false,
246
- error: error_2 instanceof Error ? error_2.message : String(error_2),
247
- }];
248
- case 4: return [2 /*return*/];
249
- }
250
- });
251
- });
252
- };
253
- /**
254
- * List all sessions across nodes
255
- */
256
- TmuxSessionManager.prototype.listSessions = function () {
257
- return __awaiter(this, arguments, void 0, function (options) {
258
- var nodes, allSessions, _loop_1, this_1, _i, nodes_1, node;
259
- var _this = this;
260
- if (options === void 0) { options = {}; }
261
- return __generator(this, function (_a) {
262
- switch (_a.label) {
263
- case 0:
264
- nodes = options.nodeIds
265
- ? options.nodeIds.map(function (id) { return _this.getNode(id); }).filter(Boolean)
266
- : options.tags
267
- ? options.tags.flatMap(function (tag) { return _this.getNodesByTag(tag); })
268
- : this.getActiveNodes();
269
- allSessions = [];
270
- _loop_1 = function (node) {
271
- var sshOpts_1, sessionNames, sessions, _b;
272
- return __generator(this, function (_c) {
273
- switch (_c.label) {
274
- case 0:
275
- if (node.status !== "running")
276
- return [2 /*return*/, "continue"];
277
- // Use cache if valid
278
- if (this_1.isCacheValid(node.id) && this_1.sessionCache.has(node.id)) {
279
- allSessions.push.apply(allSessions, this_1.sessionCache.get(node.id));
280
- return [2 /*return*/, "continue"];
281
- }
282
- _c.label = 1;
283
- case 1:
284
- _c.trys.push([1, 4, , 5]);
285
- sshOpts_1 = this_1.getSSHOptions(node);
286
- return [4 /*yield*/, (0, tmux_js_1.listTmuxSessions)(sshOpts_1)];
287
- case 2:
288
- sessionNames = _c.sent();
289
- return [4 /*yield*/, Promise.all(sessionNames.map(function (name) { return __awaiter(_this, void 0, void 0, function () {
290
- var info;
291
- var _a;
292
- return __generator(this, function (_b) {
293
- switch (_b.label) {
294
- case 0: return [4 /*yield*/, (0, tmux_js_1.getTmuxSessionInfo)(name, sshOpts_1)];
295
- case 1:
296
- info = _b.sent();
297
- return [2 /*return*/, {
298
- name: name,
299
- nodeId: node.id,
300
- windows: info === null || info === void 0 ? void 0 : info.windows,
301
- panes: info === null || info === void 0 ? void 0 : info.panes,
302
- exists: (_a = info === null || info === void 0 ? void 0 : info.exists) !== null && _a !== void 0 ? _a : true,
303
- }];
304
- }
305
- });
306
- }); }))];
307
- case 3:
308
- sessions = _c.sent();
309
- // Update cache
310
- this_1.sessionCache.set(node.id, sessions);
311
- this_1.lastCacheUpdate.set(node.id, Date.now());
312
- allSessions.push.apply(allSessions, sessions);
313
- return [3 /*break*/, 5];
314
- case 4:
315
- _b = _c.sent();
316
- return [2 /*return*/, "continue"];
317
- case 5: return [2 /*return*/];
318
- }
319
- });
320
- };
321
- this_1 = this;
322
- _i = 0, nodes_1 = nodes;
323
- _a.label = 1;
324
- case 1:
325
- if (!(_i < nodes_1.length)) return [3 /*break*/, 4];
326
- node = nodes_1[_i];
327
- return [5 /*yield**/, _loop_1(node)];
328
- case 2:
329
- _a.sent();
330
- _a.label = 3;
331
- case 3:
332
- _i++;
333
- return [3 /*break*/, 1];
334
- case 4: return [2 /*return*/, allSessions];
335
- }
336
- });
337
- });
338
- };
339
- /**
340
- * Get detailed session information
341
- */
342
- TmuxSessionManager.prototype.getDetailedSession = function (nodeId, sessionName) {
343
- return __awaiter(this, void 0, void 0, function () {
344
- var node, sshOpts, info, _a;
345
- return __generator(this, function (_b) {
346
- switch (_b.label) {
347
- case 0:
348
- node = this.getNode(nodeId);
349
- if (!node || node.status !== "running") {
350
- return [2 /*return*/, null];
351
- }
352
- _b.label = 1;
353
- case 1:
354
- _b.trys.push([1, 3, , 4]);
355
- sshOpts = this.getSSHOptions(node);
356
- return [4 /*yield*/, (0, tmux_js_1.getDetailedSessionInfo)(sessionName, sshOpts)];
357
- case 2:
358
- info = _b.sent();
359
- if (!info || !info.exists) {
360
- return [2 /*return*/, null];
361
- }
362
- return [2 /*return*/, {
363
- name: sessionName,
364
- nodeId: node.id,
365
- exists: true,
366
- windows: info.windows,
367
- }];
368
- case 3:
369
- _a = _b.sent();
370
- return [2 /*return*/, null];
371
- case 4: return [2 /*return*/];
372
- }
373
- });
374
- });
375
- };
376
- /**
377
- * Kill a session on a node
378
- */
379
- TmuxSessionManager.prototype.killSession = function (nodeId, sessionName) {
380
- return __awaiter(this, void 0, void 0, function () {
381
- var node, sshOpts, killed, error_3;
382
- return __generator(this, function (_a) {
383
- switch (_a.label) {
384
- case 0:
385
- node = this.getNode(nodeId);
386
- if (!node) {
387
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " not found") }];
388
- }
389
- if (node.status !== "running") {
390
- return [2 /*return*/, { success: false, error: "Node ".concat(nodeId, " is not running") }];
391
- }
392
- _a.label = 1;
393
- case 1:
394
- _a.trys.push([1, 3, , 4]);
395
- sshOpts = this.getSSHOptions(node);
396
- return [4 /*yield*/, (0, tmux_js_1.killTmuxSession)(sessionName, sshOpts)];
397
- case 2:
398
- killed = _a.sent();
399
- // Invalidate cache
400
- this.invalidateCache(nodeId);
401
- return [2 /*return*/, { success: killed }];
402
- case 3:
403
- error_3 = _a.sent();
404
- return [2 /*return*/, {
405
- success: false,
406
- error: error_3 instanceof Error ? error_3.message : String(error_3),
407
- }];
408
- case 4: return [2 /*return*/];
409
- }
410
- });
411
- });
412
- };
413
- /**
414
- * Send a command to a specific session on a node
415
- */
416
- TmuxSessionManager.prototype.sendCommand = function (nodeId_1, sessionName_1, command_1) {
417
- return __awaiter(this, arguments, void 0, function (nodeId, sessionName, command, paneIndex) {
418
- var node, sshOpts, result, error_4;
419
- if (paneIndex === void 0) { paneIndex = "0"; }
420
- return __generator(this, function (_a) {
421
- switch (_a.label) {
422
- case 0:
423
- node = this.getNode(nodeId);
424
- if (!node || node.status !== "running") {
425
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
426
- }
427
- _a.label = 1;
428
- case 1:
429
- _a.trys.push([1, 3, , 4]);
430
- sshOpts = this.getSSHOptions(node);
431
- return [4 /*yield*/, (0, tmux_js_1.sendCommandToPane)(sessionName, command, paneIndex, sshOpts)];
432
- case 2:
433
- result = _a.sent();
434
- return [2 /*return*/, { success: result }];
435
- case 3:
436
- error_4 = _a.sent();
437
- return [2 /*return*/, {
438
- success: false,
439
- error: error_4 instanceof Error ? error_4.message : String(error_4),
440
- }];
441
- case 4: return [2 /*return*/];
442
- }
443
- });
444
- });
445
- };
446
- /**
447
- * Send command to multiple nodes (batch operation)
448
- */
449
- TmuxSessionManager.prototype.sendCommandToNodes = function (nodeIds_1, sessionName_1, command_1) {
450
- return __awaiter(this, arguments, void 0, function (nodeIds, sessionName, command, options) {
451
- var _a, parallel, _b, continueOnError, _c, paneIndex, _d, timeout, nodes, results, successful, failed, executeCommand, resultsArray, _i, nodes_2, node, result, error_5;
452
- var _this = this;
453
- if (options === void 0) { options = {}; }
454
- return __generator(this, function (_e) {
455
- switch (_e.label) {
456
- case 0:
457
- _a = options.parallel, parallel = _a === void 0 ? true : _a, _b = options.continueOnError, continueOnError = _b === void 0 ? true : _b, _c = options.paneIndex, paneIndex = _c === void 0 ? "0" : _c, _d = options.timeout, timeout = _d === void 0 ? 30 : _d;
458
- nodes = nodeIds.map(function (id) { return _this.getNode(id); }).filter(Boolean);
459
- results = [];
460
- successful = 0;
461
- failed = 0;
462
- executeCommand = function (node) { return __awaiter(_this, void 0, void 0, function () {
463
- var sshOpts, result, error_6;
464
- return __generator(this, function (_a) {
465
- switch (_a.label) {
466
- case 0:
467
- if (node.status !== "running") {
468
- failed++;
469
- return [2 /*return*/, {
470
- nodeId: node.id,
471
- nodeName: node.name,
472
- success: false,
473
- error: "Node is ".concat(node.status),
474
- }];
475
- }
476
- _a.label = 1;
477
- case 1:
478
- _a.trys.push([1, 3, , 4]);
479
- sshOpts = __assign(__assign({}, this.getSSHOptions(node)), { timeout: timeout });
480
- return [4 /*yield*/, (0, tmux_js_1.sendCommandToPane)(sessionName, command, paneIndex, sshOpts)];
481
- case 2:
482
- result = _a.sent();
483
- if (result) {
484
- successful++;
485
- return [2 /*return*/, {
486
- nodeId: node.id,
487
- nodeName: node.name,
488
- success: true,
489
- }];
490
- }
491
- else {
492
- failed++;
493
- return [2 /*return*/, {
494
- nodeId: node.id,
495
- nodeName: node.name,
496
- success: false,
497
- error: "Failed to send command",
498
- }];
499
- }
500
- return [3 /*break*/, 4];
501
- case 3:
502
- error_6 = _a.sent();
503
- failed++;
504
- return [2 /*return*/, {
505
- nodeId: node.id,
506
- nodeName: node.name,
507
- success: false,
508
- error: error_6 instanceof Error ? error_6.message : String(error_6),
509
- }];
510
- case 4: return [2 /*return*/];
511
- }
512
- });
513
- }); };
514
- if (!parallel) return [3 /*break*/, 2];
515
- return [4 /*yield*/, Promise.allSettled(nodes.map(executeCommand))];
516
- case 1:
517
- resultsArray = _e.sent();
518
- resultsArray.forEach(function (result) {
519
- if (result.status === "fulfilled") {
520
- results.push(result.value);
521
- }
522
- else {
523
- results.push({
524
- nodeId: "unknown",
525
- nodeName: "unknown",
526
- success: false,
527
- error: String(result.reason),
528
- });
529
- }
530
- });
531
- return [3 /*break*/, 8];
532
- case 2:
533
- _i = 0, nodes_2 = nodes;
534
- _e.label = 3;
535
- case 3:
536
- if (!(_i < nodes_2.length)) return [3 /*break*/, 8];
537
- node = nodes_2[_i];
538
- _e.label = 4;
539
- case 4:
540
- _e.trys.push([4, 6, , 7]);
541
- return [4 /*yield*/, executeCommand(node)];
542
- case 5:
543
- result = _e.sent();
544
- results.push(result);
545
- if (!result.success && !continueOnError) {
546
- return [3 /*break*/, 8];
547
- }
548
- return [3 /*break*/, 7];
549
- case 6:
550
- error_5 = _e.sent();
551
- failed++;
552
- results.push({
553
- nodeId: node.id,
554
- nodeName: node.name,
555
- success: false,
556
- error: error_5 instanceof Error ? error_5.message : String(error_5),
557
- });
558
- if (!continueOnError) {
559
- return [3 /*break*/, 8];
560
- }
561
- return [3 /*break*/, 7];
562
- case 7:
563
- _i++;
564
- return [3 /*break*/, 3];
565
- case 8: return [2 /*return*/, {
566
- total: nodes.length,
567
- successful: successful,
568
- failed: failed,
569
- results: results,
570
- }];
571
- }
572
- });
573
- });
574
- };
575
- /**
576
- * Split a pane in a session
577
- */
578
- TmuxSessionManager.prototype.splitPaneOnNode = function (nodeId_1, sessionName_1) {
579
- return __awaiter(this, arguments, void 0, function (nodeId, sessionName, direction, command, windowIndex) {
580
- var node, sshOpts, result, error_7;
581
- if (direction === void 0) { direction = "v"; }
582
- if (command === void 0) { command = null; }
583
- if (windowIndex === void 0) { windowIndex = "0"; }
584
- return __generator(this, function (_a) {
585
- switch (_a.label) {
586
- case 0:
587
- node = this.getNode(nodeId);
588
- if (!node || node.status !== "running") {
589
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
590
- }
591
- _a.label = 1;
592
- case 1:
593
- _a.trys.push([1, 3, , 4]);
594
- sshOpts = this.getSSHOptions(node);
595
- return [4 /*yield*/, (0, tmux_js_1.splitPane)(sessionName, direction, command, sshOpts)];
596
- case 2:
597
- result = _a.sent();
598
- return [2 /*return*/, {
599
- success: result !== null,
600
- newPaneIndex: result || undefined,
601
- }];
602
- case 3:
603
- error_7 = _a.sent();
604
- return [2 /*return*/, {
605
- success: false,
606
- error: error_7 instanceof Error ? error_7.message : String(error_7),
607
- }];
608
- case 4: return [2 /*return*/];
609
- }
610
- });
611
- });
612
- };
613
- /**
614
- * Capture pane output from a session
615
- */
616
- TmuxSessionManager.prototype.capturePaneOutput = function (nodeId_1, sessionName_1) {
617
- return __awaiter(this, arguments, void 0, function (nodeId, sessionName, paneIndex) {
618
- var node, sshOpts, output, error_8;
619
- if (paneIndex === void 0) { paneIndex = "0"; }
620
- return __generator(this, function (_a) {
621
- switch (_a.label) {
622
- case 0:
623
- node = this.getNode(nodeId);
624
- if (!node || node.status !== "running") {
625
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
626
- }
627
- _a.label = 1;
628
- case 1:
629
- _a.trys.push([1, 3, , 4]);
630
- sshOpts = this.getSSHOptions(node);
631
- return [4 /*yield*/, (0, tmux_js_1.capturePane)(sessionName, paneIndex, sshOpts)];
632
- case 2:
633
- output = _a.sent();
634
- return [2 /*return*/, {
635
- success: output !== null,
636
- output: output || undefined,
637
- }];
638
- case 3:
639
- error_8 = _a.sent();
640
- return [2 /*return*/, {
641
- success: false,
642
- error: error_8 instanceof Error ? error_8.message : String(error_8),
643
- }];
644
- case 4: return [2 /*return*/];
645
- }
646
- });
647
- });
648
- };
649
- /**
650
- * Get pane history (scrollback buffer)
651
- */
652
- TmuxSessionManager.prototype.getPaneHistory = function (nodeId_1, sessionName_1) {
653
- return __awaiter(this, arguments, void 0, function (nodeId, sessionName, paneIndex, lines) {
654
- var node, sshOpts, history_1, error_9;
655
- if (paneIndex === void 0) { paneIndex = "0"; }
656
- if (lines === void 0) { lines = -1; }
657
- return __generator(this, function (_a) {
658
- switch (_a.label) {
659
- case 0:
660
- node = this.getNode(nodeId);
661
- if (!node || node.status !== "running") {
662
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
663
- }
664
- _a.label = 1;
665
- case 1:
666
- _a.trys.push([1, 3, , 4]);
667
- sshOpts = this.getSSHOptions(node);
668
- return [4 /*yield*/, (0, tmux_js_1.getPaneHistory)(sessionName, paneIndex, lines, sshOpts)];
669
- case 2:
670
- history_1 = _a.sent();
671
- return [2 /*return*/, {
672
- success: history_1 !== null,
673
- history: history_1 || undefined,
674
- }];
675
- case 3:
676
- error_9 = _a.sent();
677
- return [2 /*return*/, {
678
- success: false,
679
- error: error_9 instanceof Error ? error_9.message : String(error_9),
680
- }];
681
- case 4: return [2 /*return*/];
682
- }
683
- });
684
- });
685
- };
686
- /**
687
- * List windows in a session
688
- */
689
- TmuxSessionManager.prototype.listWindows = function (nodeId, sessionName) {
690
- return __awaiter(this, void 0, void 0, function () {
691
- var node, sshOpts, windows, error_10;
692
- return __generator(this, function (_a) {
693
- switch (_a.label) {
694
- case 0:
695
- node = this.getNode(nodeId);
696
- if (!node || node.status !== "running") {
697
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
698
- }
699
- _a.label = 1;
700
- case 1:
701
- _a.trys.push([1, 3, , 4]);
702
- sshOpts = this.getSSHOptions(node);
703
- return [4 /*yield*/, (0, tmux_js_1.listSessionWindows)(sessionName, sshOpts)];
704
- case 2:
705
- windows = _a.sent();
706
- return [2 /*return*/, {
707
- success: true,
708
- windows: windows,
709
- }];
710
- case 3:
711
- error_10 = _a.sent();
712
- return [2 /*return*/, {
713
- success: false,
714
- error: error_10 instanceof Error ? error_10.message : String(error_10),
715
- }];
716
- case 4: return [2 /*return*/];
717
- }
718
- });
719
- });
720
- };
721
- /**
722
- * List panes in a window
723
- */
724
- TmuxSessionManager.prototype.listPanes = function (nodeId_1, sessionName_1) {
725
- return __awaiter(this, arguments, void 0, function (nodeId, sessionName, windowIndex) {
726
- var node, sshOpts, panes, error_11;
727
- if (windowIndex === void 0) { windowIndex = "0"; }
728
- return __generator(this, function (_a) {
729
- switch (_a.label) {
730
- case 0:
731
- node = this.getNode(nodeId);
732
- if (!node || node.status !== "running") {
733
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
734
- }
735
- _a.label = 1;
736
- case 1:
737
- _a.trys.push([1, 3, , 4]);
738
- sshOpts = this.getSSHOptions(node);
739
- return [4 /*yield*/, (0, tmux_js_1.listWindowPanes)(sessionName, windowIndex, sshOpts)];
740
- case 2:
741
- panes = _a.sent();
742
- return [2 /*return*/, {
743
- success: true,
744
- panes: panes,
745
- }];
746
- case 3:
747
- error_11 = _a.sent();
748
- return [2 /*return*/, {
749
- success: false,
750
- error: error_11 instanceof Error ? error_11.message : String(error_11),
751
- }];
752
- case 4: return [2 /*return*/];
753
- }
754
- });
755
- });
756
- };
757
- /**
758
- * Switch to a different window in a session
759
- */
760
- TmuxSessionManager.prototype.switchToWindow = function (nodeId, sessionName, windowIndex) {
761
- return __awaiter(this, void 0, void 0, function () {
762
- var node, sshOpts, result, error_12;
763
- return __generator(this, function (_a) {
764
- switch (_a.label) {
765
- case 0:
766
- node = this.getNode(nodeId);
767
- if (!node || node.status !== "running") {
768
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
769
- }
770
- _a.label = 1;
771
- case 1:
772
- _a.trys.push([1, 3, , 4]);
773
- sshOpts = this.getSSHOptions(node);
774
- return [4 /*yield*/, (0, tmux_js_1.switchWindow)(sessionName, windowIndex, sshOpts)];
775
- case 2:
776
- result = _a.sent();
777
- return [2 /*return*/, { success: result }];
778
- case 3:
779
- error_12 = _a.sent();
780
- return [2 /*return*/, {
781
- success: false,
782
- error: error_12 instanceof Error ? error_12.message : String(error_12),
783
- }];
784
- case 4: return [2 /*return*/];
785
- }
786
- });
787
- });
788
- };
789
- /**
790
- * Switch to a different pane in a session
791
- */
792
- TmuxSessionManager.prototype.switchToPane = function (nodeId, sessionName, paneIndex) {
793
- return __awaiter(this, void 0, void 0, function () {
794
- var node, sshOpts, result, error_13;
795
- return __generator(this, function (_a) {
796
- switch (_a.label) {
797
- case 0:
798
- node = this.getNode(nodeId);
799
- if (!node || node.status !== "running") {
800
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
801
- }
802
- _a.label = 1;
803
- case 1:
804
- _a.trys.push([1, 3, , 4]);
805
- sshOpts = this.getSSHOptions(node);
806
- return [4 /*yield*/, (0, tmux_js_1.switchPane)(sessionName, paneIndex, sshOpts)];
807
- case 2:
808
- result = _a.sent();
809
- return [2 /*return*/, { success: result }];
810
- case 3:
811
- error_13 = _a.sent();
812
- return [2 /*return*/, {
813
- success: false,
814
- error: error_13 instanceof Error ? error_13.message : String(error_13),
815
- }];
816
- case 4: return [2 /*return*/];
817
- }
818
- });
819
- });
820
- };
821
- /**
822
- * Rename a window in a session
823
- */
824
- TmuxSessionManager.prototype.renameWindowInSession = function (nodeId, sessionName, windowIndex, newName) {
825
- return __awaiter(this, void 0, void 0, function () {
826
- var node, sshOpts, result, error_14;
827
- return __generator(this, function (_a) {
828
- switch (_a.label) {
829
- case 0:
830
- node = this.getNode(nodeId);
831
- if (!node || node.status !== "running") {
832
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
833
- }
834
- _a.label = 1;
835
- case 1:
836
- _a.trys.push([1, 3, , 4]);
837
- sshOpts = this.getSSHOptions(node);
838
- return [4 /*yield*/, (0, tmux_js_1.renameWindow)(sessionName, windowIndex, newName, sshOpts)];
839
- case 2:
840
- result = _a.sent();
841
- return [2 /*return*/, { success: result }];
842
- case 3:
843
- error_14 = _a.sent();
844
- return [2 /*return*/, {
845
- success: false,
846
- error: error_14 instanceof Error ? error_14.message : String(error_14),
847
- }];
848
- case 4: return [2 /*return*/];
849
- }
850
- });
851
- });
852
- };
853
- /**
854
- * Kill a pane in a session
855
- */
856
- TmuxSessionManager.prototype.killPaneInSession = function (nodeId, sessionName, paneIndex) {
857
- return __awaiter(this, void 0, void 0, function () {
858
- var node, sshOpts, result, error_15;
859
- return __generator(this, function (_a) {
860
- switch (_a.label) {
861
- case 0:
862
- node = this.getNode(nodeId);
863
- if (!node || node.status !== "running") {
864
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
865
- }
866
- _a.label = 1;
867
- case 1:
868
- _a.trys.push([1, 3, , 4]);
869
- sshOpts = this.getSSHOptions(node);
870
- return [4 /*yield*/, (0, tmux_js_1.killPane)(sessionName, paneIndex, sshOpts)];
871
- case 2:
872
- result = _a.sent();
873
- return [2 /*return*/, { success: result }];
874
- case 3:
875
- error_15 = _a.sent();
876
- return [2 /*return*/, {
877
- success: false,
878
- error: error_15 instanceof Error ? error_15.message : String(error_15),
879
- }];
880
- case 4: return [2 /*return*/];
881
- }
882
- });
883
- });
884
- };
885
- /**
886
- * Cleanup old sessions on a node
887
- */
888
- TmuxSessionManager.prototype.cleanupOldSessions = function (nodeId_1) {
889
- return __awaiter(this, arguments, void 0, function (nodeId, ageLimitMs) {
890
- var node, sshOpts, result, error_16;
891
- if (ageLimitMs === void 0) { ageLimitMs = 30 * 24 * 60 * 60 * 1000; }
892
- return __generator(this, function (_a) {
893
- switch (_a.label) {
894
- case 0:
895
- node = this.getNode(nodeId);
896
- if (!node || node.status !== "running") {
897
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
898
- }
899
- _a.label = 1;
900
- case 1:
901
- _a.trys.push([1, 3, , 4]);
902
- sshOpts = this.getSSHOptions(node);
903
- return [4 /*yield*/, (0, tmux_js_1.cleanupOldTmuxSessions)(sshOpts, { sessionAgeLimit: ageLimitMs })];
904
- case 2:
905
- result = _a.sent();
906
- // Invalidate cache
907
- this.invalidateCache(nodeId);
908
- return [2 /*return*/, {
909
- success: true,
910
- cleaned: result.cleaned,
911
- errors: result.errors,
912
- }];
913
- case 3:
914
- error_16 = _a.sent();
915
- return [2 /*return*/, {
916
- success: false,
917
- error: error_16 instanceof Error ? error_16.message : String(error_16),
918
- }];
919
- case 4: return [2 /*return*/];
920
- }
921
- });
922
- });
923
- };
924
- /**
925
- * Get resource usage for sessions on a node
926
- */
927
- TmuxSessionManager.prototype.getResourceUsage = function (nodeId) {
928
- return __awaiter(this, void 0, void 0, function () {
929
- var node, sshOpts, usage, error_17;
930
- return __generator(this, function (_a) {
931
- switch (_a.label) {
932
- case 0:
933
- node = this.getNode(nodeId);
934
- if (!node || node.status !== "running") {
935
- return [2 /*return*/, { success: false, error: node ? "Node ".concat(nodeId, " is not running") : "Node ".concat(nodeId, " not found") }];
936
- }
937
- _a.label = 1;
938
- case 1:
939
- _a.trys.push([1, 3, , 4]);
940
- sshOpts = this.getSSHOptions(node);
941
- return [4 /*yield*/, (0, tmux_js_1.getTmuxResourceUsage)(sshOpts)];
942
- case 2:
943
- usage = _a.sent();
944
- return [2 /*return*/, {
945
- success: usage !== null,
946
- usage: usage || undefined,
947
- }];
948
- case 3:
949
- error_17 = _a.sent();
950
- return [2 /*return*/, {
951
- success: false,
952
- error: error_17 instanceof Error ? error_17.message : String(error_17),
953
- }];
954
- case 4: return [2 /*return*/];
955
- }
956
- });
957
- });
958
- };
959
- /**
960
- * Get summary statistics across all nodes
961
- */
962
- TmuxSessionManager.prototype.getSummary = function () {
963
- return __awaiter(this, void 0, void 0, function () {
964
- var nodes, sessions, totalMemoryUsageMB, nodesWithSessions, _i, sessions_1, session, _a, nodes_3, node, usage;
965
- return __generator(this, function (_b) {
966
- switch (_b.label) {
967
- case 0:
968
- nodes = this.getActiveNodes();
969
- return [4 /*yield*/, this.listSessions()];
970
- case 1:
971
- sessions = _b.sent();
972
- totalMemoryUsageMB = 0;
973
- nodesWithSessions = new Set();
974
- // Group sessions by node
975
- for (_i = 0, sessions_1 = sessions; _i < sessions_1.length; _i++) {
976
- session = sessions_1[_i];
977
- nodesWithSessions.add(session.nodeId);
978
- }
979
- _a = 0, nodes_3 = nodes;
980
- _b.label = 2;
981
- case 2:
982
- if (!(_a < nodes_3.length)) return [3 /*break*/, 5];
983
- node = nodes_3[_a];
984
- return [4 /*yield*/, this.getResourceUsage(node.id)];
985
- case 3:
986
- usage = _b.sent();
987
- if (usage.success && usage.usage) {
988
- totalMemoryUsageMB += usage.usage.estimatedMemoryMB;
989
- }
990
- _b.label = 4;
991
- case 4:
992
- _a++;
993
- return [3 /*break*/, 2];
994
- case 5: return [2 /*return*/, {
995
- totalNodes: this.nodes.size,
996
- activeNodes: nodes.length,
997
- totalSessions: sessions.length,
998
- totalMemoryUsageMB: totalMemoryUsageMB,
999
- nodesWithSessions: nodesWithSessions.size,
1000
- }];
1001
- }
1002
- });
1003
- });
1004
- };
1005
- return TmuxSessionManager;
1006
- }());
1007
- exports.TmuxSessionManager = TmuxSessionManager;
1008
- /**
1009
- * Global singleton instance
1010
- */
1011
- var globalManager = null;
1012
- /**
1013
- * Get the global tmux session manager instance
1014
- */
1015
- function getTmuxManager() {
1016
- if (!globalManager) {
1017
- globalManager = new TmuxSessionManager();
1018
- }
1019
- return globalManager;
1020
- }
1021
- /**
1022
- * Reset the global manager (for testing)
1023
- */
1024
- function resetTmuxManager() {
1025
- globalManager = null;
1026
- }