@dmsdc-ai/aigentry-telepty 0.1.7 → 0.1.8
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/cli.js +29 -48
- package/interactive-terminal.js +54 -0
- package/package.json +4 -4
package/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ const prompts = require('prompts');
|
|
|
9
9
|
const updateNotifier = require('update-notifier');
|
|
10
10
|
const pkg = require('./package.json');
|
|
11
11
|
const { getConfig } = require('./auth');
|
|
12
|
+
const { attachInteractiveTerminal } = require('./interactive-terminal');
|
|
12
13
|
const { runInteractiveSkillInstaller } = require('./skill-installer');
|
|
13
14
|
const args = process.argv.slice(2);
|
|
14
15
|
|
|
@@ -92,29 +93,24 @@ async function ensureDaemonRunning() {
|
|
|
92
93
|
async function manageInteractiveAttach(sessionId, targetHost) {
|
|
93
94
|
const wsUrl = `ws://${targetHost}:${PORT}/api/sessions/${encodeURIComponent(sessionId)}?token=${encodeURIComponent(TOKEN)}`;
|
|
94
95
|
const ws = new WebSocket(wsUrl);
|
|
95
|
-
let
|
|
96
|
-
let resizeHandler = null;
|
|
96
|
+
let cleanupTerminal = null;
|
|
97
97
|
return new Promise((resolve) => {
|
|
98
98
|
ws.on('open', () => {
|
|
99
99
|
// Set Ghostty tab title to show session ID
|
|
100
100
|
process.stdout.write(`\x1b]0;⚡ telepty :: ${sessionId}\x07`);
|
|
101
101
|
console.log(`\n\x1b[32mEntered room '${sessionId}'.\x1b[0m\n`);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
process.stdout.on('resize', resizeHandler);
|
|
107
|
-
resizeHandler();
|
|
102
|
+
cleanupTerminal = attachInteractiveTerminal(process.stdin, process.stdout, {
|
|
103
|
+
onData: (d) => ws.send(JSON.stringify({ type: 'input', data: d.toString() })),
|
|
104
|
+
onResize: () => ws.send(JSON.stringify({ type: 'resize', cols: process.stdout.columns, rows: process.stdout.rows }))
|
|
105
|
+
});
|
|
108
106
|
});
|
|
109
107
|
ws.on('message', m => {
|
|
110
108
|
const msg = JSON.parse(m);
|
|
111
109
|
if (msg.type === 'output') process.stdout.write(msg.data);
|
|
112
110
|
});
|
|
113
111
|
ws.on('close', async () => {
|
|
114
|
-
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
115
112
|
process.stdout.write(`\x1b]0;\x07`); // Restore default terminal title
|
|
116
|
-
if (
|
|
117
|
-
if (resizeHandler) process.stdout.off('resize', resizeHandler);
|
|
113
|
+
if (cleanupTerminal) cleanupTerminal();
|
|
118
114
|
|
|
119
115
|
// Check if other clients are still attached before destroying
|
|
120
116
|
try {
|
|
@@ -480,11 +476,13 @@ async function main() {
|
|
|
480
476
|
process.stdout.write(`\x1b]0;⚡ telepty :: ${sessionId}\x07`);
|
|
481
477
|
console.log(`\x1b[32m⚡ '${command}' is now session '\x1b[36m${sessionId}\x1b[32m'. Inject allowed.\x1b[0m\n`);
|
|
482
478
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
479
|
+
const cleanupTerminal = attachInteractiveTerminal(process.stdin, process.stdout, {
|
|
480
|
+
onData: (data) => {
|
|
481
|
+
child.write(data.toString());
|
|
482
|
+
},
|
|
483
|
+
onResize: () => {
|
|
484
|
+
child.resize(process.stdout.columns, process.stdout.rows);
|
|
485
|
+
}
|
|
488
486
|
});
|
|
489
487
|
|
|
490
488
|
// Relay PTY output to current terminal + send to daemon for attach clients
|
|
@@ -495,14 +493,9 @@ async function main() {
|
|
|
495
493
|
}
|
|
496
494
|
});
|
|
497
495
|
|
|
498
|
-
// Handle terminal resize
|
|
499
|
-
process.stdout.on('resize', () => {
|
|
500
|
-
child.resize(process.stdout.columns, process.stdout.rows);
|
|
501
|
-
});
|
|
502
|
-
|
|
503
496
|
// Handle child exit
|
|
504
497
|
child.onExit(({ exitCode }) => {
|
|
505
|
-
|
|
498
|
+
cleanupTerminal();
|
|
506
499
|
process.stdout.write(`\x1b]0;\x07`);
|
|
507
500
|
console.log(`\n\x1b[33mSession '${sessionId}' exited (code ${exitCode}).\x1b[0m`);
|
|
508
501
|
|
|
@@ -551,8 +544,7 @@ async function main() {
|
|
|
551
544
|
|
|
552
545
|
const wsUrl = `ws://${targetHost}:${PORT}/api/sessions/${encodeURIComponent(sessionId)}?token=${encodeURIComponent(TOKEN)}`;
|
|
553
546
|
const ws = new WebSocket(wsUrl);
|
|
554
|
-
let
|
|
555
|
-
let resizeHandler = null;
|
|
547
|
+
let cleanupTerminal = null;
|
|
556
548
|
|
|
557
549
|
ws.on('open', () => {
|
|
558
550
|
// Set Ghostty tab title to show session ID
|
|
@@ -560,25 +552,18 @@ async function main() {
|
|
|
560
552
|
process.stdout.write(`\x1b]0;⚡ telepty :: ${sessionId}${hostSuffix}\x07`);
|
|
561
553
|
console.log(`\x1b[32mEntered room '${sessionId}'${hostSuffix ? ` (${targetHost})` : ''}.\x1b[0m\n`);
|
|
562
554
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
cols: process.stdout.columns,
|
|
576
|
-
rows: process.stdout.rows
|
|
577
|
-
}));
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
process.stdout.on('resize', resizeHandler);
|
|
581
|
-
resizeHandler(); // Initial resize
|
|
555
|
+
cleanupTerminal = attachInteractiveTerminal(process.stdin, process.stdout, {
|
|
556
|
+
onData: (data) => {
|
|
557
|
+
ws.send(JSON.stringify({ type: 'input', data: data.toString() }));
|
|
558
|
+
},
|
|
559
|
+
onResize: () => {
|
|
560
|
+
ws.send(JSON.stringify({
|
|
561
|
+
type: 'resize',
|
|
562
|
+
cols: process.stdout.columns,
|
|
563
|
+
rows: process.stdout.rows
|
|
564
|
+
}));
|
|
565
|
+
}
|
|
566
|
+
});
|
|
582
567
|
});
|
|
583
568
|
|
|
584
569
|
ws.on('message', (message) => {
|
|
@@ -589,12 +574,8 @@ async function main() {
|
|
|
589
574
|
});
|
|
590
575
|
|
|
591
576
|
ws.on('close', async (code, reason) => {
|
|
592
|
-
if (process.stdin.isTTY) {
|
|
593
|
-
process.stdin.setRawMode(false);
|
|
594
|
-
}
|
|
595
577
|
process.stdout.write(`\x1b]0;\x07`); // Restore default terminal title
|
|
596
|
-
if (
|
|
597
|
-
if (resizeHandler) process.stdout.off('resize', resizeHandler);
|
|
578
|
+
if (cleanupTerminal) cleanupTerminal();
|
|
598
579
|
|
|
599
580
|
// Check if other clients are still attached before destroying
|
|
600
581
|
try {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function removeListener(stream, eventName, handler) {
|
|
4
|
+
if (!handler || !stream) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (typeof stream.off === 'function') {
|
|
9
|
+
stream.off(eventName, handler);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (typeof stream.removeListener === 'function') {
|
|
14
|
+
stream.removeListener(eventName, handler);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function attachInteractiveTerminal(input, output, handlers = {}) {
|
|
19
|
+
const { onData = null, onResize = null } = handlers;
|
|
20
|
+
|
|
21
|
+
if (input && input.isTTY && typeof input.setRawMode === 'function') {
|
|
22
|
+
input.setRawMode(true);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (input && typeof input.resume === 'function') {
|
|
26
|
+
input.resume();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (input && onData) {
|
|
30
|
+
input.on('data', onData);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (output && onResize) {
|
|
34
|
+
output.on('resize', onResize);
|
|
35
|
+
onResize();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return () => {
|
|
39
|
+
removeListener(input, 'data', onData);
|
|
40
|
+
removeListener(output, 'resize', onResize);
|
|
41
|
+
|
|
42
|
+
if (input && input.isTTY && typeof input.setRawMode === 'function') {
|
|
43
|
+
input.setRawMode(false);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (input && typeof input.pause === 'function') {
|
|
47
|
+
input.pause();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
attachInteractiveTerminal
|
|
54
|
+
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dmsdc-ai/aigentry-telepty",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"main": "daemon.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"telepty": "cli.js",
|
|
7
7
|
"telepty-install": "install.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "node --test test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js",
|
|
11
|
-
"test:watch": "node --test --watch test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js",
|
|
12
|
-
"test:ci": "node --test --test-reporter=spec test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js"
|
|
10
|
+
"test": "node --test test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js test/interactive-terminal.test.js",
|
|
11
|
+
"test:watch": "node --test --watch test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js test/interactive-terminal.test.js",
|
|
12
|
+
"test:ci": "node --test --test-reporter=spec test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js test/interactive-terminal.test.js"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [],
|
|
15
15
|
"author": "",
|