@ebowwa/terminal 0.3.1 → 0.3.2

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.
Files changed (77) hide show
  1. package/package.json +8 -70
  2. package/dist/api.d.ts +0 -7
  3. package/dist/client.d.ts +0 -14
  4. package/dist/config.d.ts +0 -85
  5. package/dist/cpufeatures-vxqw2k6s.node +0 -0
  6. package/dist/error.d.ts +0 -7
  7. package/dist/exec.d.ts +0 -46
  8. package/dist/files.d.ts +0 -123
  9. package/dist/fingerprint.d.ts +0 -66
  10. package/dist/index.d.ts +0 -20
  11. package/dist/manager.d.ts +0 -102
  12. package/dist/mcp/cpufeatures-vxqw2k6s.node +0 -0
  13. package/dist/mcp/index.d.ts +0 -8
  14. package/dist/mcp/sshcrypto-gez6h7ch.node +0 -0
  15. package/dist/mcp/stdio.d.ts +0 -8
  16. package/dist/network-error-detector.d.ts +0 -18
  17. package/dist/pool.d.ts +0 -142
  18. package/dist/pty.d.ts +0 -58
  19. package/dist/resources.d.ts +0 -62
  20. package/dist/scp.d.ts +0 -29
  21. package/dist/sessions.d.ts +0 -100
  22. package/dist/sshcrypto-gez6h7ch.node +0 -0
  23. package/dist/tmux-exec.d.ts +0 -49
  24. package/dist/tmux-local.d.ts +0 -272
  25. package/dist/tmux-manager.d.ts +0 -327
  26. package/dist/tmux.d.ts +0 -212
  27. package/dist/types.d.ts +0 -17
  28. package/mcp/README.md +0 -181
  29. package/mcp/package.json +0 -40
  30. package/mcp/stdio.js +0 -555
  31. package/mcp/test-fix.sh +0 -273
  32. package/mcp/wrapper.mjs +0 -10
  33. package/src/api.js +0 -861
  34. package/src/api.ts +0 -752
  35. package/src/client.js +0 -92
  36. package/src/client.ts +0 -55
  37. package/src/config.js +0 -490
  38. package/src/config.ts +0 -489
  39. package/src/error.js +0 -32
  40. package/src/error.ts +0 -13
  41. package/src/exec.js +0 -183
  42. package/src/exec.ts +0 -128
  43. package/src/files.js +0 -521
  44. package/src/files.ts +0 -636
  45. package/src/fingerprint.js +0 -336
  46. package/src/fingerprint.ts +0 -263
  47. package/src/index.js +0 -127
  48. package/src/index.ts +0 -148
  49. package/src/manager.js +0 -358
  50. package/src/manager.ts +0 -319
  51. package/src/mcp/index.js +0 -555
  52. package/src/mcp/index.ts +0 -467
  53. package/src/mcp/stdio.js +0 -840
  54. package/src/mcp/stdio.ts +0 -708
  55. package/src/network-error-detector.js +0 -101
  56. package/src/network-error-detector.ts +0 -121
  57. package/src/pool.js +0 -840
  58. package/src/pool.ts +0 -662
  59. package/src/pty.js +0 -344
  60. package/src/pty.ts +0 -285
  61. package/src/resources.js +0 -64
  62. package/src/resources.ts +0 -72
  63. package/src/scp.js +0 -166
  64. package/src/scp.ts +0 -109
  65. package/src/sessions.js +0 -895
  66. package/src/sessions.ts +0 -861
  67. package/src/tmux-exec.js +0 -169
  68. package/src/tmux-exec.ts +0 -96
  69. package/src/tmux-local.js +0 -937
  70. package/src/tmux-local.ts +0 -839
  71. package/src/tmux-manager.js +0 -1026
  72. package/src/tmux-manager.ts +0 -962
  73. package/src/tmux.js +0 -826
  74. package/src/tmux.ts +0 -711
  75. package/src/types.js +0 -5
  76. package/src/types.ts +0 -19
  77. package/tsconfig.json +0 -28
package/src/api.ts DELETED
@@ -1,752 +0,0 @@
1
- /**
2
- * API routes for Multi-Node Tmux Session Manager
3
- * Provides REST API for managing tmux sessions across multiple VPS nodes
4
- */
5
-
6
- import { Hono } from "hono";
7
- import { z } from "zod";
8
- import { addActivity } from "../lib/activities";
9
- import {
10
- getTmuxManager,
11
- type Node,
12
- type BatchOperationResult,
13
- type DetailedTmuxSession,
14
- } from "./tmux-manager.js";
15
- import {
16
- TmuxManagerAddNodeSchema,
17
- TmuxManagerCreateSessionSchema,
18
- TmuxManagerAttachSessionSchema,
19
- TmuxManagerKillSessionSchema,
20
- TmuxManagerSendCommandSchema,
21
- TmuxManagerBatchSendCommandSchema,
22
- TmuxManagerSplitPaneSchema,
23
- TmuxManagerCapturePaneSchema,
24
- TmuxManagerGetHistorySchema,
25
- TmuxManagerListWindowsSchema,
26
- TmuxManagerListPanesSchema,
27
- TmuxManagerSwitchWindowSchema,
28
- TmuxManagerSwitchPaneSchema,
29
- TmuxManagerRenameWindowSchema,
30
- TmuxManagerKillPaneSchema,
31
- TmuxManagerCleanupOldSessionsSchema,
32
- TmuxManagerDetailedSessionSchema,
33
- TmuxManagerListSessionsQuerySchema,
34
- } from "@ebowwa/codespaces-types/runtime/api";
35
-
36
- const tmuxApi = new Hono();
37
-
38
- /**
39
- * Helper function to validate request body against Zod schema
40
- */
41
- function validateRequest<T>(
42
- schema: z.ZodSchema<T>,
43
- data: unknown
44
- ): { success: true; data: T } | { success: false; error: string } {
45
- try {
46
- const result = schema.safeParse(data);
47
- if (result.success) {
48
- return { success: true, data: result.data };
49
- } else {
50
- return {
51
- success: false,
52
- error: result.error.issues
53
- .map((e) => `${e.path.join(".")}: ${e.message}`)
54
- .join(", "),
55
- };
56
- }
57
- } catch (error) {
58
- return { success: false, error: String(error) };
59
- }
60
- }
61
-
62
- // ============================================
63
- // Node Management
64
- // ============================================
65
-
66
- /**
67
- * POST /api/tmux/manager/nodes - Add a node to the manager
68
- */
69
- tmuxApi.post("/manager/nodes", async (c) => {
70
- const body = await c.req.json();
71
- const validation = validateRequest(TmuxManagerAddNodeSchema, body);
72
-
73
- if (!validation.success) {
74
- return c.json({ success: false, error: validation.error }, 400);
75
- }
76
-
77
- try {
78
- const manager = getTmuxManager();
79
- manager.addNode(validation.data);
80
- return c.json({ success: true, node: validation.data });
81
- } catch (error) {
82
- return c.json({ success: false, error: String(error) }, 500);
83
- }
84
- });
85
-
86
- /**
87
- * GET /api/tmux/manager/nodes - List all nodes
88
- */
89
- tmuxApi.get("/manager/nodes", async (c) => {
90
- try {
91
- const manager = getTmuxManager();
92
- const nodes = manager.getAllNodes();
93
- return c.json({ success: true, nodes });
94
- } catch (error) {
95
- return c.json({ success: false, error: String(error) }, 500);
96
- }
97
- });
98
-
99
- /**
100
- * GET /api/tmux/manager/nodes/:id - Get a specific node
101
- */
102
- tmuxApi.get("/manager/nodes/:id", async (c) => {
103
- const id = c.req.param("id");
104
- if (!id) {
105
- return c.json({ success: false, error: "Node ID is required" }, 400);
106
- }
107
-
108
- try {
109
- const manager = getTmuxManager();
110
- const node = manager.getNode(id);
111
- if (!node) {
112
- return c.json({ success: false, error: "Node not found" }, 404);
113
- }
114
- return c.json({ success: true, node });
115
- } catch (error) {
116
- return c.json({ success: false, error: String(error) }, 500);
117
- }
118
- });
119
-
120
- /**
121
- * DELETE /api/tmux/manager/nodes/:id - Remove a node
122
- */
123
- tmuxApi.delete("/manager/nodes/:id", async (c) => {
124
- const id = c.req.param("id");
125
- if (!id) {
126
- return c.json({ success: false, error: "Node ID is required" }, 400);
127
- }
128
-
129
- try {
130
- const manager = getTmuxManager();
131
- const node = manager.getNode(id);
132
- if (!node) {
133
- return c.json({ success: false, error: "Node not found" }, 404);
134
- }
135
- manager.removeNode(id);
136
- return c.json({ success: true });
137
- } catch (error) {
138
- return c.json({ success: false, error: String(error) }, 500);
139
- }
140
- });
141
-
142
- // ============================================
143
- // Session Management
144
- // ============================================
145
-
146
- /**
147
- * POST /api/tmux/manager/sessions - Create a new session
148
- */
149
- tmuxApi.post("/manager/sessions", async (c) => {
150
- const body = await c.req.json();
151
- const validation = validateRequest(TmuxManagerCreateSessionSchema, body);
152
-
153
- if (!validation.success) {
154
- return c.json({ success: false, error: validation.error }, 400);
155
- }
156
-
157
- try {
158
- const manager = getTmuxManager();
159
- const result = await manager.createSession(
160
- validation.data.nodeId,
161
- validation.data
162
- );
163
-
164
- if (result.success) {
165
- const node = manager.getNode(validation.data.nodeId);
166
- if (node) {
167
- addActivity({
168
- environmentId: node.id,
169
- action: "tmux_session_created",
170
- environmentName: node.name,
171
- details: result.sessionName
172
- ? `Session "${result.sessionName}" created`
173
- : "Session created",
174
- });
175
- }
176
- }
177
-
178
- return c.json(result);
179
- } catch (error) {
180
- return c.json({ success: false, error: String(error) }, 500);
181
- }
182
- });
183
-
184
- /**
185
- * GET /api/tmux/manager/sessions - List all sessions
186
- */
187
- tmuxApi.get("/manager/sessions", async (c) => {
188
- try {
189
- const manager = getTmuxManager();
190
-
191
- // Parse query parameters
192
- const nodeIds = c.req.queries()["nodeIds"];
193
- const tags = c.req.queries()["tags"];
194
- const detailed = c.req.query("detailed") === "true";
195
- const includeInactive = c.req.query("includeInactive") === "true";
196
-
197
- const sessions = await manager.listSessions({
198
- nodeIds,
199
- tags,
200
- detailed,
201
- includeInactive,
202
- });
203
-
204
- return c.json({ success: true, sessions });
205
- } catch (error) {
206
- return c.json({ success: false, error: String(error) }, 500);
207
- }
208
- });
209
-
210
- /**
211
- * POST /api/tmux/manager/sessions/attach - Attach to a session
212
- */
213
- tmuxApi.post("/manager/sessions/attach", async (c) => {
214
- const body = await c.req.json();
215
- const validation = validateRequest(TmuxManagerAttachSessionSchema, body);
216
-
217
- if (!validation.success) {
218
- return c.json({ success: false, error: validation.error }, 400);
219
- }
220
-
221
- try {
222
- const manager = getTmuxManager();
223
- const result = await manager.attachSession(
224
- validation.data.nodeId,
225
- validation.data.sessionName
226
- );
227
-
228
- if (result.success) {
229
- const node = manager.getNode(validation.data.nodeId);
230
- if (node) {
231
- addActivity({
232
- environmentId: node.id,
233
- action: "tmux_session_attached",
234
- environmentName: node.name,
235
- details: `Attached to session "${result.sessionName}"`,
236
- });
237
- }
238
- }
239
-
240
- return c.json(result);
241
- } catch (error) {
242
- return c.json({ success: false, error: String(error) }, 500);
243
- }
244
- });
245
-
246
- /**
247
- * DELETE /api/tmux/manager/sessions - Kill a session
248
- */
249
- tmuxApi.delete("/manager/sessions", async (c) => {
250
- const body = await c.req.json();
251
- const validation = validateRequest(TmuxManagerKillSessionSchema, body);
252
-
253
- if (!validation.success) {
254
- return c.json({ success: false, error: validation.error }, 400);
255
- }
256
-
257
- try {
258
- const manager = getTmuxManager();
259
- const node = manager.getNode(validation.data.nodeId);
260
- const result = await manager.killSession(
261
- validation.data.nodeId,
262
- validation.data.sessionName
263
- );
264
-
265
- if (result.success && node) {
266
- addActivity({
267
- environmentId: node.id,
268
- action: "tmux_session_killed",
269
- environmentName: node.name,
270
- details: `Session "${validation.data.sessionName}" killed`,
271
- });
272
- }
273
-
274
- return c.json(result);
275
- } catch (error) {
276
- return c.json({ success: false, error: String(error) }, 500);
277
- }
278
- });
279
-
280
- // ============================================
281
- // Command Execution
282
- // ============================================
283
-
284
- /**
285
- * POST /api/tmux/manager/sessions/command - Send command to a session
286
- */
287
- tmuxApi.post("/manager/sessions/command", async (c) => {
288
- const body = await c.req.json();
289
- const validation = validateRequest(TmuxManagerSendCommandSchema, body);
290
-
291
- if (!validation.success) {
292
- return c.json({ success: false, error: validation.error }, 400);
293
- }
294
-
295
- try {
296
- const manager = getTmuxManager();
297
- const node = manager.getNode(validation.data.nodeId);
298
- const result = await manager.sendCommand(
299
- validation.data.nodeId,
300
- validation.data.sessionName,
301
- validation.data.command,
302
- validation.data.paneIndex
303
- );
304
-
305
- if (result.success && node) {
306
- addActivity({
307
- environmentId: node.id,
308
- action: "tmux_command_sent",
309
- environmentName: node.name,
310
- details: `Command: ${validation.data.command.slice(0, 100)}${validation.data.command.length > 100 ? "..." : ""}`,
311
- });
312
- }
313
-
314
- return c.json(result);
315
- } catch (error) {
316
- return c.json({ success: false, error: String(error) }, 500);
317
- }
318
- });
319
-
320
- /**
321
- * POST /api/tmux/manager/sessions/command/batch - Send command to multiple nodes
322
- */
323
- tmuxApi.post("/manager/sessions/command/batch", async (c) => {
324
- const body = await c.req.json();
325
- const validation = validateRequest(TmuxManagerBatchSendCommandSchema, body);
326
-
327
- if (!validation.success) {
328
- return c.json({ success: false, error: validation.error }, 400);
329
- }
330
-
331
- try {
332
- const manager = getTmuxManager();
333
- const result: BatchOperationResult = await manager.sendCommandToNodes(
334
- validation.data.nodeIds,
335
- validation.data.sessionName,
336
- validation.data.command,
337
- {
338
- paneIndex: validation.data.paneIndex,
339
- parallel: validation.data.parallel,
340
- continueOnError: validation.data.continueOnError,
341
- timeout: validation.data.timeout,
342
- }
343
- );
344
-
345
- // Log activity per node
346
- for (const r of result.results) {
347
- if (r.success) {
348
- const node = manager.getNode(r.nodeId);
349
- if (node) {
350
- addActivity({
351
- environmentId: node.id,
352
- action: "tmux_batch_command_sent",
353
- environmentName: node.name,
354
- details: `Batch command to ${result.total} nodes: ${validation.data.command.slice(0, 80)}${validation.data.command.length > 80 ? "..." : ""}`,
355
- });
356
- }
357
- }
358
- }
359
-
360
- return c.json({ success: true, result });
361
- } catch (error) {
362
- return c.json({ success: false, error: String(error) }, 500);
363
- }
364
- });
365
-
366
- // ============================================
367
- // Pane Operations
368
- // ============================================
369
-
370
- /**
371
- * POST /api/tmux/manager/sessions/split - Split a pane
372
- */
373
- tmuxApi.post("/manager/sessions/split", async (c) => {
374
- const body = await c.req.json();
375
- const validation = validateRequest(TmuxManagerSplitPaneSchema, body);
376
-
377
- if (!validation.success) {
378
- return c.json({ success: false, error: validation.error }, 400);
379
- }
380
-
381
- try {
382
- const manager = getTmuxManager();
383
- const node = manager.getNode(validation.data.nodeId);
384
- const result = await manager.splitPaneOnNode(
385
- validation.data.nodeId,
386
- validation.data.sessionName,
387
- validation.data.direction,
388
- validation.data.command,
389
- validation.data.windowIndex
390
- );
391
-
392
- if (result.success && node) {
393
- addActivity({
394
- environmentId: node.id,
395
- action: "tmux_pane_split",
396
- environmentName: node.name,
397
- details: `Split pane ${validation.data.direction === "h" ? "horizontally" : "vertically"}${validation.data.command ? ` with command: ${validation.data.command.slice(0, 50)}...` : ""}`,
398
- });
399
- }
400
-
401
- return c.json(result);
402
- } catch (error) {
403
- return c.json({ success: false, error: String(error) }, 500);
404
- }
405
- });
406
-
407
- /**
408
- * POST /api/tmux/manager/sessions/capture - Capture pane output
409
- */
410
- tmuxApi.post("/manager/sessions/capture", async (c) => {
411
- const body = await c.req.json();
412
- const validation = validateRequest(TmuxManagerCapturePaneSchema, body);
413
-
414
- if (!validation.success) {
415
- return c.json({ success: false, error: validation.error }, 400);
416
- }
417
-
418
- try {
419
- const manager = getTmuxManager();
420
- const result = await manager.capturePaneOutput(
421
- validation.data.nodeId,
422
- validation.data.sessionName,
423
- validation.data.paneIndex
424
- );
425
- return c.json(result);
426
- } catch (error) {
427
- return c.json({ success: false, error: String(error) }, 500);
428
- }
429
- });
430
-
431
- /**
432
- * POST /api/tmux/manager/sessions/history - Get pane history
433
- */
434
- tmuxApi.post("/manager/sessions/history", async (c) => {
435
- const body = await c.req.json();
436
- const validation = validateRequest(TmuxManagerGetHistorySchema, body);
437
-
438
- if (!validation.success) {
439
- return c.json({ success: false, error: validation.error }, 400);
440
- }
441
-
442
- try {
443
- const manager = getTmuxManager();
444
- const result = await manager.getPaneHistory(
445
- validation.data.nodeId,
446
- validation.data.sessionName,
447
- validation.data.paneIndex,
448
- validation.data.lines
449
- );
450
- return c.json(result);
451
- } catch (error) {
452
- return c.json({ success: false, error: String(error) }, 500);
453
- }
454
- });
455
-
456
- /**
457
- * DELETE /api/tmux/manager/sessions/pane - Kill a pane
458
- */
459
- tmuxApi.delete("/manager/sessions/pane", async (c) => {
460
- const body = await c.req.json();
461
- const validation = validateRequest(TmuxManagerKillPaneSchema, body);
462
-
463
- if (!validation.success) {
464
- return c.json({ success: false, error: validation.error }, 400);
465
- }
466
-
467
- try {
468
- const manager = getTmuxManager();
469
- const node = manager.getNode(validation.data.nodeId);
470
- const result = await manager.killPaneInSession(
471
- validation.data.nodeId,
472
- validation.data.sessionName,
473
- validation.data.paneIndex
474
- );
475
-
476
- if (result.success && node) {
477
- addActivity({
478
- environmentId: node.id,
479
- action: "tmux_pane_killed",
480
- environmentName: node.name,
481
- details: `Pane ${validation.data.paneIndex} killed in session "${validation.data.sessionName}"`,
482
- });
483
- }
484
-
485
- return c.json(result);
486
- } catch (error) {
487
- return c.json({ success: false, error: String(error) }, 500);
488
- }
489
- });
490
-
491
- // ============================================
492
- // Window Operations
493
- // ============================================
494
-
495
- /**
496
- * POST /api/tmux/manager/sessions/windows - List windows in a session
497
- */
498
- tmuxApi.post("/manager/sessions/windows", async (c) => {
499
- const body = await c.req.json();
500
- const validation = validateRequest(TmuxManagerListWindowsSchema, body);
501
-
502
- if (!validation.success) {
503
- return c.json({ success: false, error: validation.error }, 400);
504
- }
505
-
506
- try {
507
- const manager = getTmuxManager();
508
- const result = await manager.listWindows(
509
- validation.data.nodeId,
510
- validation.data.sessionName
511
- );
512
- return c.json(result);
513
- } catch (error) {
514
- return c.json({ success: false, error: String(error) }, 500);
515
- }
516
- });
517
-
518
- /**
519
- * POST /api/tmux/manager/sessions/panes - List panes in a window
520
- */
521
- tmuxApi.post("/manager/sessions/panes", async (c) => {
522
- const body = await c.req.json();
523
- const validation = validateRequest(TmuxManagerListPanesSchema, body);
524
-
525
- if (!validation.success) {
526
- return c.json({ success: false, error: validation.error }, 400);
527
- }
528
-
529
- try {
530
- const manager = getTmuxManager();
531
- const result = await manager.listPanes(
532
- validation.data.nodeId,
533
- validation.data.sessionName,
534
- validation.data.windowIndex
535
- );
536
- return c.json(result);
537
- } catch (error) {
538
- return c.json({ success: false, error: String(error) }, 500);
539
- }
540
- });
541
-
542
- /**
543
- * POST /api/tmux/manager/sessions/windows/switch - Switch to a window
544
- */
545
- tmuxApi.post("/manager/sessions/windows/switch", async (c) => {
546
- const body = await c.req.json();
547
- const validation = validateRequest(TmuxManagerSwitchWindowSchema, body);
548
-
549
- if (!validation.success) {
550
- return c.json({ success: false, error: validation.error }, 400);
551
- }
552
-
553
- try {
554
- const manager = getTmuxManager();
555
- const node = manager.getNode(validation.data.nodeId);
556
- const result = await manager.switchToWindow(
557
- validation.data.nodeId,
558
- validation.data.sessionName,
559
- validation.data.windowIndex
560
- );
561
-
562
- if (result.success && node) {
563
- addActivity({
564
- environmentId: node.id,
565
- action: "tmux_window_switched",
566
- environmentName: node.name,
567
- details: `Switched to window ${validation.data.windowIndex} in session "${validation.data.sessionName}"`,
568
- });
569
- }
570
-
571
- return c.json(result);
572
- } catch (error) {
573
- return c.json({ success: false, error: String(error) }, 500);
574
- }
575
- });
576
-
577
- /**
578
- * POST /api/tmux/manager/sessions/panes/switch - Switch to a pane
579
- */
580
- tmuxApi.post("/manager/sessions/panes/switch", async (c) => {
581
- const body = await c.req.json();
582
- const validation = validateRequest(TmuxManagerSwitchPaneSchema, body);
583
-
584
- if (!validation.success) {
585
- return c.json({ success: false, error: validation.error }, 400);
586
- }
587
-
588
- try {
589
- const manager = getTmuxManager();
590
- const node = manager.getNode(validation.data.nodeId);
591
- const result = await manager.switchToPane(
592
- validation.data.nodeId,
593
- validation.data.sessionName,
594
- validation.data.paneIndex
595
- );
596
-
597
- if (result.success && node) {
598
- addActivity({
599
- environmentId: node.id,
600
- action: "tmux_pane_switched",
601
- environmentName: node.name,
602
- details: `Switched to pane ${validation.data.paneIndex} in session "${validation.data.sessionName}"`,
603
- });
604
- }
605
-
606
- return c.json(result);
607
- } catch (error) {
608
- return c.json({ success: false, error: String(error) }, 500);
609
- }
610
- });
611
-
612
- /**
613
- * PUT /api/tmux/manager/sessions/windows/rename - Rename a window
614
- */
615
- tmuxApi.put("/manager/sessions/windows/rename", async (c) => {
616
- const body = await c.req.json();
617
- const validation = validateRequest(TmuxManagerRenameWindowSchema, body);
618
-
619
- if (!validation.success) {
620
- return c.json({ success: false, error: validation.error }, 400);
621
- }
622
-
623
- try {
624
- const manager = getTmuxManager();
625
- const node = manager.getNode(validation.data.nodeId);
626
- const result = await manager.renameWindowInSession(
627
- validation.data.nodeId,
628
- validation.data.sessionName,
629
- validation.data.windowIndex,
630
- validation.data.newName
631
- );
632
-
633
- if (result.success && node) {
634
- addActivity({
635
- environmentId: node.id,
636
- action: "tmux_window_renamed",
637
- environmentName: node.name,
638
- details: `Renamed window ${validation.data.windowIndex} to "${validation.data.newName}" in session "${validation.data.sessionName}"`,
639
- });
640
- }
641
-
642
- return c.json(result);
643
- } catch (error) {
644
- return c.json({ success: false, error: String(error) }, 500);
645
- }
646
- });
647
-
648
- // ============================================
649
- // Maintenance & Monitoring
650
- // ============================================
651
-
652
- /**
653
- * GET /api/tmux/manager/sessions/detailed - Get detailed session info
654
- */
655
- tmuxApi.get("/manager/sessions/detailed", async (c) => {
656
- const nodeId = c.req.query("nodeId");
657
- const sessionName = c.req.query("sessionName");
658
-
659
- if (!nodeId || !sessionName) {
660
- return c.json({ success: false, error: "nodeId and sessionName are required" }, 400);
661
- }
662
-
663
- try {
664
- const manager = getTmuxManager();
665
- const result = await manager.getDetailedSession(nodeId, sessionName);
666
- return c.json({ success: result !== null, session: result });
667
- } catch (error) {
668
- return c.json({ success: false, error: String(error) }, 500);
669
- }
670
- });
671
-
672
- /**
673
- * POST /api/tmux/manager/sessions/cleanup - Cleanup old sessions
674
- */
675
- tmuxApi.post("/manager/sessions/cleanup", async (c) => {
676
- const body = await c.req.json();
677
- const validation = validateRequest(TmuxManagerCleanupOldSessionsSchema, body);
678
-
679
- if (!validation.success) {
680
- return c.json({ success: false, error: validation.error }, 400);
681
- }
682
-
683
- try {
684
- const manager = getTmuxManager();
685
- const node = manager.getNode(validation.data.nodeId);
686
- const result = await manager.cleanupOldSessions(
687
- validation.data.nodeId,
688
- validation.data.ageLimitMs
689
- );
690
-
691
- if (result.success && result.cleaned && result.cleaned > 0 && node) {
692
- addActivity({
693
- environmentId: node.id,
694
- action: "tmux_sessions_cleaned",
695
- environmentName: node.name,
696
- details: `Cleaned up ${result.cleaned} old tmux sessions`,
697
- });
698
- }
699
-
700
- return c.json(result);
701
- } catch (error) {
702
- return c.json({ success: false, error: String(error) }, 500);
703
- }
704
- });
705
-
706
- /**
707
- * GET /api/tmux/manager/nodes/:id/resources - Get resource usage for a node
708
- */
709
- tmuxApi.get("/manager/nodes/:id/resources", async (c) => {
710
- const id = c.req.param("id");
711
- if (!id) {
712
- return c.json({ success: false, error: "Node ID is required" }, 400);
713
- }
714
-
715
- try {
716
- const manager = getTmuxManager();
717
- const result = await manager.getResourceUsage(id);
718
- return c.json(result);
719
- } catch (error) {
720
- return c.json({ success: false, error: String(error) }, 500);
721
- }
722
- });
723
-
724
- /**
725
- * GET /api/tmux/manager/summary - Get summary statistics
726
- */
727
- tmuxApi.get("/manager/summary", async (c) => {
728
- try {
729
- const manager = getTmuxManager();
730
- const summary = await manager.getSummary();
731
- return c.json({ success: true, summary });
732
- } catch (error) {
733
- return c.json({ success: false, error: String(error) }, 500);
734
- }
735
- });
736
-
737
- /**
738
- * POST /api/tmux/manager/cache/invalidate - Invalidate session cache
739
- */
740
- tmuxApi.post("/manager/cache/invalidate", async (c) => {
741
- try {
742
- const manager = getTmuxManager();
743
- const body = await c.req.json().catch(() => ({}));
744
- const nodeId = body?.nodeId;
745
- manager.invalidateCache(nodeId);
746
- return c.json({ success: true });
747
- } catch (error) {
748
- return c.json({ success: false, error: String(error) }, 500);
749
- }
750
- });
751
-
752
- export { tmuxApi };