@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.
package/src/tmux.js DELETED
@@ -1,826 +0,0 @@
1
- "use strict";
2
- /**
3
- * tmux-based Terminal Sessions
4
- * Provides persistent terminal sessions using tmux on remote servers
5
- * Includes automatic tmux installation and session management
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
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
56
- if (ar || !(i in from)) {
57
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
58
- ar[i] = from[i];
59
- }
60
- }
61
- return to.concat(ar || Array.prototype.slice.call(from));
62
- };
63
- Object.defineProperty(exports, "__esModule", { value: true });
64
- exports.generateSessionName = generateSessionName;
65
- exports.isTmuxInstalled = isTmuxInstalled;
66
- exports.installTmux = installTmux;
67
- exports.ensureTmux = ensureTmux;
68
- exports.listTmuxSessions = listTmuxSessions;
69
- exports.hasTmuxSession = hasTmuxSession;
70
- exports.createOrAttachTmuxSession = createOrAttachTmuxSession;
71
- exports.killTmuxSession = killTmuxSession;
72
- exports.getTmuxSessionInfo = getTmuxSessionInfo;
73
- exports.cleanupOldTmuxSessions = cleanupOldTmuxSessions;
74
- exports.getTmuxResourceUsage = getTmuxResourceUsage;
75
- exports.sendCommandToPane = sendCommandToPane;
76
- exports.splitPane = splitPane;
77
- exports.listSessionWindows = listSessionWindows;
78
- exports.listWindowPanes = listWindowPanes;
79
- exports.capturePane = capturePane;
80
- exports.getPaneHistory = getPaneHistory;
81
- exports.switchWindow = switchWindow;
82
- exports.switchPane = switchPane;
83
- exports.renameWindow = renameWindow;
84
- exports.killPane = killPane;
85
- exports.getDetailedSessionInfo = getDetailedSessionInfo;
86
- var pool_js_1 = require("./pool.js");
87
- var ssh_1 = require("@codespaces/ssh");
88
- var DEFAULT_CONFIG = {
89
- sessionPrefix: "codespaces",
90
- defaultShell: "/bin/bash",
91
- term: "xterm-256color",
92
- timeout: 30,
93
- historyLimit: 10000, // 10k lines ~ 1-2MB per session
94
- sessionAgeLimit: 30 * 24 * 60 * 60 * 1000, // 30 days
95
- };
96
- /**
97
- * Generate a tmux session name for a host
98
- */
99
- function generateSessionName(host, user) {
100
- if (user === void 0) { user = "root"; }
101
- var sanitizedHost = host.replace(/[.]/g, "-");
102
- return "".concat(DEFAULT_CONFIG.sessionPrefix, "-").concat(sanitizedHost);
103
- }
104
- /**
105
- * Check if tmux is installed on the remote server
106
- */
107
- function isTmuxInstalled(options) {
108
- return __awaiter(this, void 0, void 0, function () {
109
- var pool, result, _a;
110
- return __generator(this, function (_b) {
111
- switch (_b.label) {
112
- case 0:
113
- pool = (0, pool_js_1.getSSHPool)();
114
- _b.label = 1;
115
- case 1:
116
- _b.trys.push([1, 3, , 4]);
117
- return [4 /*yield*/, pool.exec("type tmux", __assign(__assign({}, options), { timeout: 5 }))];
118
- case 2:
119
- result = _b.sent();
120
- return [2 /*return*/, result !== "0"];
121
- case 3:
122
- _a = _b.sent();
123
- return [2 /*return*/, false];
124
- case 4: return [2 /*return*/];
125
- }
126
- });
127
- });
128
- }
129
- /**
130
- * Install tmux on the remote server
131
- *
132
- * FALLBACK MECHANISM: This should NOT be the primary installation method.
133
- * tmux should be installed via cloud-init during initial node provisioning.
134
- *
135
- * This function exists for:
136
- * - Legacy nodes provisioned before cloud-init included tmux
137
- * - Manual node provisioning outside cheapspaces
138
- * - Recovery scenarios where cloud-init failed
139
- *
140
- * @see workspace/docs/design/node-agent/TMUX-INSTALLATION.md
141
- * @see workspace/src/lib/bootstrap/cloud-init.ts - where tmux should be added to packages
142
- *
143
- * Supports Debian/Ubuntu (apt) and CentOS/RHEL (yum/dnf)
144
- */
145
- function installTmux(options) {
146
- return __awaiter(this, void 0, void 0, function () {
147
- var pool, installCmd, installed, error_1;
148
- return __generator(this, function (_a) {
149
- switch (_a.label) {
150
- case 0:
151
- pool = (0, pool_js_1.getSSHPool)();
152
- _a.label = 1;
153
- case 1:
154
- _a.trys.push([1, 4, , 5]);
155
- installCmd = "\n if command -v apt-get >/dev/null 2>&1; then\n # Debian/Ubuntu\n export DEBIAN_FRONTEND=noninteractive\n apt-get update -qq && apt-get install -y -qq tmux\n elif command -v yum >/dev/null 2>&1; then\n # CentOS/RHEL (older)\n yum install -y -q tmux\n elif command -v dnf >/dev/null 2>&1; then\n # Fedora/RHEL (newer)\n dnf install -y -q tmux\n elif command -v apk >/dev/null 2>&1; then\n # Alpine\n apk add --no-cache tmux\n else\n echo \"ERROR: No supported package manager found\"\n exit 1\n fi\n ";
156
- return [4 /*yield*/, pool.exec(installCmd, __assign(__assign({}, options), { timeout: 120 }))];
157
- case 2:
158
- _a.sent();
159
- return [4 /*yield*/, isTmuxInstalled(options)];
160
- case 3:
161
- installed = _a.sent();
162
- if (installed) {
163
- return [2 /*return*/, { success: true, message: "tmux installed successfully" }];
164
- }
165
- else {
166
- return [2 /*return*/, { success: false, message: "tmux installation failed" }];
167
- }
168
- return [3 /*break*/, 5];
169
- case 4:
170
- error_1 = _a.sent();
171
- return [2 /*return*/, {
172
- success: false,
173
- message: "tmux installation error: ".concat(error_1 instanceof Error ? error_1.message : String(error_1)),
174
- }];
175
- case 5: return [2 /*return*/];
176
- }
177
- });
178
- });
179
- }
180
- /**
181
- * Ensure tmux is available, installing if necessary
182
- */
183
- function ensureTmux(options) {
184
- return __awaiter(this, void 0, void 0, function () {
185
- var installed;
186
- return __generator(this, function (_a) {
187
- switch (_a.label) {
188
- case 0: return [4 /*yield*/, isTmuxInstalled(options)];
189
- case 1:
190
- installed = _a.sent();
191
- if (installed) {
192
- return [2 /*return*/, { success: true, message: "tmux already installed" }];
193
- }
194
- console.log("[Tmux] Not installed, attempting installation...");
195
- return [4 /*yield*/, installTmux(options)];
196
- case 2: return [2 /*return*/, _a.sent()];
197
- }
198
- });
199
- });
200
- }
201
- /**
202
- * List existing tmux sessions on the remote server
203
- */
204
- function listTmuxSessions(options) {
205
- return __awaiter(this, void 0, void 0, function () {
206
- var pool, result, _a;
207
- return __generator(this, function (_b) {
208
- switch (_b.label) {
209
- case 0:
210
- pool = (0, pool_js_1.getSSHPool)();
211
- _b.label = 1;
212
- case 1:
213
- _b.trys.push([1, 3, , 4]);
214
- return [4 /*yield*/, pool.exec("tmux list-sessions -F '#{session_name}' 2>/dev/null || echo ''", __assign(__assign({}, options), { timeout: 5 }))];
215
- case 2:
216
- result = _b.sent();
217
- if (!result || result === "0" || result.trim() === "") {
218
- return [2 /*return*/, []];
219
- }
220
- return [2 /*return*/, result.trim().split("\n")];
221
- case 3:
222
- _a = _b.sent();
223
- return [2 /*return*/, []];
224
- case 4: return [2 /*return*/];
225
- }
226
- });
227
- });
228
- }
229
- /**
230
- * Check if a specific tmux session exists
231
- */
232
- function hasTmuxSession(sessionName, options) {
233
- return __awaiter(this, void 0, void 0, function () {
234
- var sessions;
235
- return __generator(this, function (_a) {
236
- switch (_a.label) {
237
- case 0: return [4 /*yield*/, listTmuxSessions(options)];
238
- case 1:
239
- sessions = _a.sent();
240
- return [2 /*return*/, sessions.includes(sessionName)];
241
- }
242
- });
243
- });
244
- }
245
- /**
246
- * Create or attach to a tmux session
247
- * Returns the SSH command arguments to connect to the tmux session
248
- */
249
- function createOrAttachTmuxSession(host_1) {
250
- return __awaiter(this, arguments, void 0, function (host, user, keyPath, config) {
251
- var fullConfig, sessionName, pool, sshOptions, tmuxCheck, sessionExists, flags, sshArgs, tmuxCmd, _a;
252
- if (user === void 0) { user = "root"; }
253
- if (config === void 0) { config = {}; }
254
- return __generator(this, function (_b) {
255
- switch (_b.label) {
256
- case 0:
257
- fullConfig = __assign(__assign({}, DEFAULT_CONFIG), config);
258
- sessionName = generateSessionName(host, user);
259
- pool = (0, pool_js_1.getSSHPool)();
260
- sshOptions = {
261
- host: host,
262
- user: user,
263
- port: 22,
264
- keyPath: keyPath,
265
- timeout: fullConfig.timeout,
266
- };
267
- return [4 /*yield*/, ensureTmux(sshOptions)];
268
- case 1:
269
- tmuxCheck = _b.sent();
270
- if (!tmuxCheck.success) {
271
- throw new Error("Failed to setup tmux: ".concat(tmuxCheck.message));
272
- }
273
- return [4 /*yield*/, hasTmuxSession(sessionName, sshOptions)];
274
- case 2:
275
- sessionExists = _b.sent();
276
- flags = __spreadArray(__spreadArray([], ssh_1.SSHPresets.default, true), [
277
- ssh_1.SSHFlags.port(22),
278
- ssh_1.SSHFlags.forceTTY(2), // -tt for forced PTY
279
- ], false);
280
- if (keyPath) {
281
- flags.push(ssh_1.SSHFlags.identity(String(keyPath)));
282
- }
283
- sshArgs = (0, ssh_1.buildSSHArgs)(flags, host, user);
284
- tmuxCmd = [
285
- "tmux",
286
- "new-session",
287
- "-A",
288
- "-s", sessionName,
289
- "-n", "codespaces",
290
- ];
291
- sshArgs.push.apply(sshArgs, tmuxCmd);
292
- if (!!sessionExists) return [3 /*break*/, 6];
293
- _b.label = 3;
294
- case 3:
295
- _b.trys.push([3, 5, , 6]);
296
- return [4 /*yield*/, pool.exec("tmux set-option -t \"".concat(sessionName, "\" history-limit ").concat(fullConfig.historyLimit, " 2>/dev/null"), __assign(__assign({}, sshOptions), { timeout: 5 }))];
297
- case 4:
298
- _b.sent();
299
- return [3 /*break*/, 6];
300
- case 5:
301
- _a = _b.sent();
302
- return [3 /*break*/, 6];
303
- case 6: return [2 /*return*/, {
304
- sshArgs: sshArgs,
305
- sessionName: sessionName,
306
- newlyCreated: !sessionExists,
307
- }];
308
- }
309
- });
310
- });
311
- }
312
- /**
313
- * Kill a tmux session on the remote server
314
- */
315
- function killTmuxSession(sessionName, options) {
316
- return __awaiter(this, void 0, void 0, function () {
317
- var pool, _a;
318
- return __generator(this, function (_b) {
319
- switch (_b.label) {
320
- case 0:
321
- pool = (0, pool_js_1.getSSHPool)();
322
- _b.label = 1;
323
- case 1:
324
- _b.trys.push([1, 3, , 4]);
325
- return [4 /*yield*/, pool.exec("tmux kill-session -t \"".concat(sessionName, "\" 2>/dev/null"), __assign(__assign({}, options), { timeout: 5 }))];
326
- case 2:
327
- _b.sent();
328
- return [2 /*return*/, true];
329
- case 3:
330
- _a = _b.sent();
331
- return [2 /*return*/, false];
332
- case 4: return [2 /*return*/];
333
- }
334
- });
335
- });
336
- }
337
- /**
338
- * Get tmux session information
339
- */
340
- function getTmuxSessionInfo(sessionName, options) {
341
- return __awaiter(this, void 0, void 0, function () {
342
- var pool, result, _a, windows, panes, _b;
343
- return __generator(this, function (_c) {
344
- switch (_c.label) {
345
- case 0:
346
- pool = (0, pool_js_1.getSSHPool)();
347
- _c.label = 1;
348
- case 1:
349
- _c.trys.push([1, 3, , 4]);
350
- return [4 /*yield*/, pool.exec("tmux display-message -t \"".concat(sessionName, "\" -p '#{session_windows} #{window_panes}' 2>/dev/null || echo \"\""), __assign(__assign({}, options), { timeout: 5 }))];
351
- case 2:
352
- result = _c.sent();
353
- if (!result || result.trim() === "" || result === "0") {
354
- return [2 /*return*/, { exists: false }];
355
- }
356
- _a = result.trim().split(" ").map(Number), windows = _a[0], panes = _a[1];
357
- return [2 /*return*/, { exists: true, windows: windows, panes: panes }];
358
- case 3:
359
- _b = _c.sent();
360
- return [2 /*return*/, { exists: false }];
361
- case 4: return [2 /*return*/];
362
- }
363
- });
364
- });
365
- }
366
- /**
367
- * Cleanup old tmux sessions on a remote server
368
- * Kills sessions with matching prefix that are older than specified age limit
369
- * @param options SSH connection options
370
- * @param config Optional configuration (uses default age limit if not provided)
371
- * @returns Object with cleaned count and errors
372
- */
373
- function cleanupOldTmuxSessions(options_1) {
374
- return __awaiter(this, arguments, void 0, function (options, config) {
375
- var fullConfig, pool, errors, cleaned, sessions, codespacesSessions, _i, codespacesSessions_1, sessionName, ageCheckCmd, ageResult, ageMs, err_1, err_2;
376
- if (config === void 0) { config = {}; }
377
- return __generator(this, function (_a) {
378
- switch (_a.label) {
379
- case 0:
380
- fullConfig = __assign(__assign({}, DEFAULT_CONFIG), config);
381
- pool = (0, pool_js_1.getSSHPool)();
382
- errors = [];
383
- cleaned = 0;
384
- _a.label = 1;
385
- case 1:
386
- _a.trys.push([1, 11, , 12]);
387
- return [4 /*yield*/, listTmuxSessions(options)];
388
- case 2:
389
- sessions = _a.sent();
390
- codespacesSessions = sessions.filter(function (s) { return s.startsWith(fullConfig.sessionPrefix); });
391
- _i = 0, codespacesSessions_1 = codespacesSessions;
392
- _a.label = 3;
393
- case 3:
394
- if (!(_i < codespacesSessions_1.length)) return [3 /*break*/, 10];
395
- sessionName = codespacesSessions_1[_i];
396
- _a.label = 4;
397
- case 4:
398
- _a.trys.push([4, 8, , 9]);
399
- ageCheckCmd = "\n find /tmp -type s -name \"*".concat(sessionName, "*\" 2>/dev/null | head -1 | while read socket; do\n if [ -n \"$socket\" ]; then\n # Get file modification time in seconds since epoch\n mtime=$(stat -c %Y \"$socket\" 2>/dev/null || stat -f %m \"$socket\" 2>/dev/null)\n if [ -n \"$mtime\" ]; then\n now=$(date +%s)\n age=$((now - mtime))\n age_ms=$((age * 1000))\n echo \"$age_ms\"\n fi\n fi\n done\n ");
400
- return [4 /*yield*/, pool.exec(ageCheckCmd, __assign(__assign({}, options), { timeout: 10 }))];
401
- case 5:
402
- ageResult = _a.sent();
403
- ageMs = parseInt(ageResult.trim());
404
- if (!(!isNaN(ageMs) && ageMs > fullConfig.sessionAgeLimit)) return [3 /*break*/, 7];
405
- console.log("[Tmux] Cleaning up old session \"".concat(sessionName, "\" (age: ").concat(Math.round(ageMs / 86400000), " days)"));
406
- return [4 /*yield*/, killTmuxSession(sessionName, options)];
407
- case 6:
408
- _a.sent();
409
- cleaned++;
410
- _a.label = 7;
411
- case 7: return [3 /*break*/, 9];
412
- case 8:
413
- err_1 = _a.sent();
414
- errors.push("".concat(sessionName, ": ").concat(err_1 instanceof Error ? err_1.message : String(err_1)));
415
- return [3 /*break*/, 9];
416
- case 9:
417
- _i++;
418
- return [3 /*break*/, 3];
419
- case 10: return [2 /*return*/, { cleaned: cleaned, errors: errors }];
420
- case 11:
421
- err_2 = _a.sent();
422
- errors.push("Cleanup failed: ".concat(err_2 instanceof Error ? err_2.message : String(err_2)));
423
- return [2 /*return*/, { cleaned: cleaned, errors: errors }];
424
- case 12: return [2 /*return*/];
425
- }
426
- });
427
- });
428
- }
429
- /**
430
- * Get resource usage information for tmux sessions on a remote server
431
- * @param options SSH connection options
432
- * @returns Resource usage summary
433
- */
434
- function getTmuxResourceUsage(options) {
435
- return __awaiter(this, void 0, void 0, function () {
436
- var pool, sessions, codespacesSessions, estimatedMemoryMB, _a;
437
- return __generator(this, function (_b) {
438
- switch (_b.label) {
439
- case 0:
440
- pool = (0, pool_js_1.getSSHPool)();
441
- _b.label = 1;
442
- case 1:
443
- _b.trys.push([1, 3, , 4]);
444
- return [4 /*yield*/, listTmuxSessions(options)];
445
- case 2:
446
- sessions = _b.sent();
447
- codespacesSessions = sessions.filter(function (s) { return s.startsWith(DEFAULT_CONFIG.sessionPrefix); });
448
- estimatedMemoryMB = codespacesSessions.length * 11;
449
- return [2 /*return*/, {
450
- totalSessions: sessions.length,
451
- codespacesSessions: codespacesSessions.length,
452
- estimatedMemoryMB: estimatedMemoryMB,
453
- }];
454
- case 3:
455
- _a = _b.sent();
456
- return [2 /*return*/, null];
457
- case 4: return [2 /*return*/];
458
- }
459
- });
460
- });
461
- }
462
- /**
463
- * Send a command to a specific pane in a tmux session
464
- * @param sessionName Target tmux session name
465
- * @param paneIndex Pane index (default: 0 for first pane)
466
- * @param command Command to execute (sent as keystrokes)
467
- * @param options SSH connection options
468
- */
469
- function sendCommandToPane(sessionName_1, command_1) {
470
- return __awaiter(this, arguments, void 0, function (sessionName, command, paneIndex, options) {
471
- var pool, escapedCmd, error_2;
472
- if (paneIndex === void 0) { paneIndex = "0"; }
473
- return __generator(this, function (_a) {
474
- switch (_a.label) {
475
- case 0:
476
- pool = (0, pool_js_1.getSSHPool)();
477
- _a.label = 1;
478
- case 1:
479
- _a.trys.push([1, 3, , 4]);
480
- escapedCmd = command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
481
- return [4 /*yield*/, pool.exec("tmux send-keys -t \"".concat(sessionName, ":").concat(paneIndex, "\" \"").concat(escapedCmd, "\" Enter"), __assign(__assign({}, options), { timeout: 5 }))];
482
- case 2:
483
- _a.sent();
484
- return [2 /*return*/, true];
485
- case 3:
486
- error_2 = _a.sent();
487
- console.error("[Tmux] Failed to send command to ".concat(sessionName, ":").concat(paneIndex, ":"), error_2);
488
- return [2 /*return*/, false];
489
- case 4: return [2 /*return*/];
490
- }
491
- });
492
- });
493
- }
494
- /**
495
- * Split a pane horizontally or vertically in a tmux session
496
- * @param sessionName Target tmux session name
497
- * @param windowIndex Window index (default: 0)
498
- * @param direction Split direction: "h" (horizontal) or "v" (vertical)
499
- * @param command Optional command to run in the new pane
500
- * @param options SSH connection options
501
- * @returns The new pane index
502
- */
503
- function splitPane(sessionName_1) {
504
- return __awaiter(this, arguments, void 0, function (sessionName, direction, command, options) {
505
- var pool, splitCmd, result, error_3;
506
- if (direction === void 0) { direction = "v"; }
507
- if (command === void 0) { command = null; }
508
- return __generator(this, function (_a) {
509
- switch (_a.label) {
510
- case 0:
511
- pool = (0, pool_js_1.getSSHPool)();
512
- _a.label = 1;
513
- case 1:
514
- _a.trys.push([1, 3, , 4]);
515
- splitCmd = command
516
- ? "tmux split-window -".concat(direction, " -t \"").concat(sessionName, "\" -c \"#{pane_current_path}\" \"").concat(command, "\"")
517
- : "tmux split-window -".concat(direction, " -t \"").concat(sessionName, "\"");
518
- return [4 /*yield*/, pool.exec(splitCmd, __assign(__assign({}, options), { timeout: 10 }))];
519
- case 2:
520
- result = _a.sent();
521
- // Return the result which contains the new pane ID
522
- return [2 /*return*/, (result === null || result === void 0 ? void 0 : result.trim()) || null];
523
- case 3:
524
- error_3 = _a.sent();
525
- console.error("[Tmux] Failed to split pane in ".concat(sessionName, ":"), error_3);
526
- return [2 /*return*/, null];
527
- case 4: return [2 /*return*/];
528
- }
529
- });
530
- });
531
- }
532
- /**
533
- * List all windows in a tmux session
534
- * @param sessionName Target tmux session name
535
- * @param options SSH connection options
536
- */
537
- function listSessionWindows(sessionName, options) {
538
- return __awaiter(this, void 0, void 0, function () {
539
- var pool, result, _a;
540
- return __generator(this, function (_b) {
541
- switch (_b.label) {
542
- case 0:
543
- pool = (0, pool_js_1.getSSHPool)();
544
- _b.label = 1;
545
- case 1:
546
- _b.trys.push([1, 3, , 4]);
547
- return [4 /*yield*/, pool.exec("tmux list-windows -t \"".concat(sessionName, "\" -F '#{window_index} #{window_name} #{window_active}' 2>/dev/null || echo ''"), __assign(__assign({}, options), { timeout: 5 }))];
548
- case 2:
549
- result = _b.sent();
550
- if (!result || result.trim() === "" || result === "0") {
551
- return [2 /*return*/, []];
552
- }
553
- return [2 /*return*/, result.trim().split("\n").map(function (line) {
554
- var _a = line.split(" "), index = _a[0], name = _a[1], active = _a[2];
555
- return { index: index, name: name, active: active === "1" };
556
- })];
557
- case 3:
558
- _a = _b.sent();
559
- return [2 /*return*/, []];
560
- case 4: return [2 /*return*/];
561
- }
562
- });
563
- });
564
- }
565
- /**
566
- * List all panes in a tmux session window
567
- * @param sessionName Target tmux session name
568
- * @param windowIndex Window index (default: 0)
569
- * @param options SSH connection options
570
- */
571
- function listWindowPanes(sessionName_1) {
572
- return __awaiter(this, arguments, void 0, function (sessionName, windowIndex, options) {
573
- var pool, result, _a;
574
- if (windowIndex === void 0) { windowIndex = "0"; }
575
- return __generator(this, function (_b) {
576
- switch (_b.label) {
577
- case 0:
578
- pool = (0, pool_js_1.getSSHPool)();
579
- _b.label = 1;
580
- case 1:
581
- _b.trys.push([1, 3, , 4]);
582
- return [4 /*yield*/, pool.exec("tmux list-panes -t \"".concat(sessionName, ":").concat(windowIndex, "\" -F '#{pane_index} #{pane_current_path} #{pane_pid} #{pane_active}' 2>/dev/null || echo ''"), __assign(__assign({}, options), { timeout: 5 }))];
583
- case 2:
584
- result = _b.sent();
585
- if (!result || result.trim() === "" || result === "0") {
586
- return [2 /*return*/, []];
587
- }
588
- return [2 /*return*/, result.trim().split("\n").map(function (line) {
589
- var _a = line.split(" "), index = _a[0], currentPath = _a[1], pid = _a[2], active = _a[3];
590
- return { index: index, currentPath: currentPath, pid: pid, active: active === "1" };
591
- })];
592
- case 3:
593
- _a = _b.sent();
594
- return [2 /*return*/, []];
595
- case 4: return [2 /*return*/];
596
- }
597
- });
598
- });
599
- }
600
- /**
601
- * Capture the current output of a pane
602
- * @param sessionName Target tmux session name
603
- * @param paneIndex Pane index (default: 0)
604
- * @param options SSH connection options
605
- */
606
- function capturePane(sessionName_1) {
607
- return __awaiter(this, arguments, void 0, function (sessionName, paneIndex, options) {
608
- var pool, result, error_4;
609
- if (paneIndex === void 0) { paneIndex = "0"; }
610
- return __generator(this, function (_a) {
611
- switch (_a.label) {
612
- case 0:
613
- pool = (0, pool_js_1.getSSHPool)();
614
- _a.label = 1;
615
- case 1:
616
- _a.trys.push([1, 3, , 4]);
617
- return [4 /*yield*/, pool.exec("tmux capture-pane -t \"".concat(sessionName, ":").concat(paneIndex, "\" -p"), __assign(__assign({}, options), { timeout: 5 }))];
618
- case 2:
619
- result = _a.sent();
620
- return [2 /*return*/, result || null];
621
- case 3:
622
- error_4 = _a.sent();
623
- console.error("[Tmux] Failed to capture pane ".concat(sessionName, ":").concat(paneIndex, ":"), error_4);
624
- return [2 /*return*/, null];
625
- case 4: return [2 /*return*/];
626
- }
627
- });
628
- });
629
- }
630
- /**
631
- * Get scrollback/history from a pane
632
- * @param sessionName Target tmux session name
633
- * @param paneIndex Pane index (default: 0)
634
- * @param lines Number of lines to retrieve (default: all)
635
- * @param options SSH connection options
636
- */
637
- function getPaneHistory(sessionName_1) {
638
- return __awaiter(this, arguments, void 0, function (sessionName, paneIndex, lines, options) {
639
- var pool, linesArg, result, error_5;
640
- if (paneIndex === void 0) { paneIndex = "0"; }
641
- if (lines === void 0) { lines = -1; }
642
- return __generator(this, function (_a) {
643
- switch (_a.label) {
644
- case 0:
645
- pool = (0, pool_js_1.getSSHPool)();
646
- _a.label = 1;
647
- case 1:
648
- _a.trys.push([1, 3, , 4]);
649
- linesArg = lines > 0 ? "-S -".concat(lines) : "-S -";
650
- return [4 /*yield*/, pool.exec("tmux capture-pane ".concat(linesArg, " -t \"").concat(sessionName, ":").concat(paneIndex, "\" -p"), __assign(__assign({}, options), { timeout: 10 }))];
651
- case 2:
652
- result = _a.sent();
653
- return [2 /*return*/, result || null];
654
- case 3:
655
- error_5 = _a.sent();
656
- console.error("[Tmux] Failed to get history for ".concat(sessionName, ":").concat(paneIndex, ":"), error_5);
657
- return [2 /*return*/, null];
658
- case 4: return [2 /*return*/];
659
- }
660
- });
661
- });
662
- }
663
- /**
664
- * Switch to a specific window in a tmux session
665
- * @param sessionName Target tmux session name
666
- * @param windowIndex Target window index
667
- * @param options SSH connection options
668
- */
669
- function switchWindow(sessionName, windowIndex, options) {
670
- return __awaiter(this, void 0, void 0, function () {
671
- var pool, _a;
672
- return __generator(this, function (_b) {
673
- switch (_b.label) {
674
- case 0:
675
- pool = (0, pool_js_1.getSSHPool)();
676
- _b.label = 1;
677
- case 1:
678
- _b.trys.push([1, 3, , 4]);
679
- return [4 /*yield*/, pool.exec("tmux select-window -t \"".concat(sessionName, ":").concat(windowIndex, "\""), __assign(__assign({}, options), { timeout: 5 }))];
680
- case 2:
681
- _b.sent();
682
- return [2 /*return*/, true];
683
- case 3:
684
- _a = _b.sent();
685
- return [2 /*return*/, false];
686
- case 4: return [2 /*return*/];
687
- }
688
- });
689
- });
690
- }
691
- /**
692
- * Switch to a specific pane in a tmux session window
693
- * @param sessionName Target tmux session name
694
- * @param paneIndex Target pane index (e.g., "0", "1", "0.1" for window.pane)
695
- * @param options SSH connection options
696
- */
697
- function switchPane(sessionName, paneIndex, options) {
698
- return __awaiter(this, void 0, void 0, function () {
699
- var pool, _a;
700
- return __generator(this, function (_b) {
701
- switch (_b.label) {
702
- case 0:
703
- pool = (0, pool_js_1.getSSHPool)();
704
- _b.label = 1;
705
- case 1:
706
- _b.trys.push([1, 3, , 4]);
707
- return [4 /*yield*/, pool.exec("tmux select-pane -t \"".concat(sessionName, ":").concat(paneIndex, "\""), __assign(__assign({}, options), { timeout: 5 }))];
708
- case 2:
709
- _b.sent();
710
- return [2 /*return*/, true];
711
- case 3:
712
- _a = _b.sent();
713
- return [2 /*return*/, false];
714
- case 4: return [2 /*return*/];
715
- }
716
- });
717
- });
718
- }
719
- /**
720
- * Rename a window in a tmux session
721
- * @param sessionName Target tmux session name
722
- * @param windowIndex Window index (default: 0)
723
- * @param newName New window name
724
- * @param options SSH connection options
725
- */
726
- function renameWindow(sessionName, windowIndex, newName, options) {
727
- return __awaiter(this, void 0, void 0, function () {
728
- var pool, _a;
729
- return __generator(this, function (_b) {
730
- switch (_b.label) {
731
- case 0:
732
- pool = (0, pool_js_1.getSSHPool)();
733
- _b.label = 1;
734
- case 1:
735
- _b.trys.push([1, 3, , 4]);
736
- return [4 /*yield*/, pool.exec("tmux rename-window -t \"".concat(sessionName, ":").concat(windowIndex, "\" \"").concat(newName, "\""), __assign(__assign({}, options), { timeout: 5 }))];
737
- case 2:
738
- _b.sent();
739
- return [2 /*return*/, true];
740
- case 3:
741
- _a = _b.sent();
742
- return [2 /*return*/, false];
743
- case 4: return [2 /*return*/];
744
- }
745
- });
746
- });
747
- }
748
- /**
749
- * Kill a specific pane in a tmux session
750
- * @param sessionName Target tmux session name
751
- * @param paneIndex Pane index to kill
752
- * @param options SSH connection options
753
- */
754
- function killPane(sessionName, paneIndex, options) {
755
- return __awaiter(this, void 0, void 0, function () {
756
- var pool, _a;
757
- return __generator(this, function (_b) {
758
- switch (_b.label) {
759
- case 0:
760
- pool = (0, pool_js_1.getSSHPool)();
761
- _b.label = 1;
762
- case 1:
763
- _b.trys.push([1, 3, , 4]);
764
- return [4 /*yield*/, pool.exec("tmux kill-pane -t \"".concat(sessionName, ":").concat(paneIndex, "\""), __assign(__assign({}, options), { timeout: 5 }))];
765
- case 2:
766
- _b.sent();
767
- return [2 /*return*/, true];
768
- case 3:
769
- _a = _b.sent();
770
- return [2 /*return*/, false];
771
- case 4: return [2 /*return*/];
772
- }
773
- });
774
- });
775
- }
776
- /**
777
- * Get detailed information about all panes in a session
778
- * @param sessionName Target tmux session name
779
- * @param options SSH connection options
780
- */
781
- function getDetailedSessionInfo(sessionName, options) {
782
- return __awaiter(this, void 0, void 0, function () {
783
- var pool, exists, windows, windowsWithPanes, error_6;
784
- var _this = this;
785
- return __generator(this, function (_a) {
786
- switch (_a.label) {
787
- case 0:
788
- pool = (0, pool_js_1.getSSHPool)();
789
- _a.label = 1;
790
- case 1:
791
- _a.trys.push([1, 5, , 6]);
792
- return [4 /*yield*/, hasTmuxSession(sessionName, options)];
793
- case 2:
794
- exists = _a.sent();
795
- if (!exists) {
796
- return [2 /*return*/, { exists: false, windows: [] }];
797
- }
798
- return [4 /*yield*/, listSessionWindows(sessionName, options)];
799
- case 3:
800
- windows = _a.sent();
801
- return [4 /*yield*/, Promise.all(windows.map(function (window) { return __awaiter(_this, void 0, void 0, function () {
802
- var panes;
803
- return __generator(this, function (_a) {
804
- switch (_a.label) {
805
- case 0: return [4 /*yield*/, listWindowPanes(sessionName, window.index, options)];
806
- case 1:
807
- panes = _a.sent();
808
- return [2 /*return*/, __assign(__assign({}, window), { panes: panes })];
809
- }
810
- });
811
- }); }))];
812
- case 4:
813
- windowsWithPanes = _a.sent();
814
- return [2 /*return*/, {
815
- exists: true,
816
- windows: windowsWithPanes,
817
- }];
818
- case 5:
819
- error_6 = _a.sent();
820
- console.error("[Tmux] Failed to get detailed info for ".concat(sessionName, ":"), error_6);
821
- return [2 /*return*/, null];
822
- case 6: return [2 /*return*/];
823
- }
824
- });
825
- });
826
- }