Update package dependencies to include node-pty for improved terminal handling. Refactor stat-vit-term.js to utilize node-pty for process management and streamline input simulation. Clean up example.js by removing unnecessary input commands.
This commit is contained in:
17
package-lock.json
generated
17
package-lock.json
generated
@@ -42,6 +42,7 @@
|
|||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"node-domexception": "^1.0.0",
|
"node-domexception": "^1.0.0",
|
||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
|
"node-pty": "^1.0.0",
|
||||||
"openai": "^4.104.0",
|
"openai": "^4.104.0",
|
||||||
"resolve-pkg-maps": "^1.0.0",
|
"resolve-pkg-maps": "^1.0.0",
|
||||||
"terminal-kit": "^3.1.2",
|
"terminal-kit": "^3.1.2",
|
||||||
@@ -945,6 +946,12 @@
|
|||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/nan": {
|
||||||
|
"version": "2.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
|
||||||
|
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ndarray": {
|
"node_modules/ndarray": {
|
||||||
"version": "1.0.19",
|
"version": "1.0.19",
|
||||||
"resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz",
|
"resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz",
|
||||||
@@ -1022,6 +1029,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-pty": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/omggif": {
|
"node_modules/omggif": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "cli.js",
|
"main": "cli.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"terminal-kit": "^3.1.2",
|
|
||||||
"dotenv": "^16.4.5",
|
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"agentkeepalive": "^4.6.0",
|
"agentkeepalive": "^4.6.0",
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
@@ -13,6 +11,7 @@
|
|||||||
"chalk": "^5.5.0",
|
"chalk": "^5.5.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"delayed-stream": "^1.0.0",
|
"delayed-stream": "^1.0.0",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
"dunder-proto": "^1.0.1",
|
"dunder-proto": "^1.0.1",
|
||||||
"es-define-property": "^1.0.1",
|
"es-define-property": "^1.0.1",
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
@@ -38,8 +37,10 @@
|
|||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"node-domexception": "^1.0.0",
|
"node-domexception": "^1.0.0",
|
||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
|
"node-pty": "^1.0.0",
|
||||||
"openai": "^4.104.0",
|
"openai": "^4.104.0",
|
||||||
"resolve-pkg-maps": "^1.0.0",
|
"resolve-pkg-maps": "^1.0.0",
|
||||||
|
"terminal-kit": "^3.1.2",
|
||||||
"tr46": "^0.0.3",
|
"tr46": "^0.0.3",
|
||||||
"tsx": "^4.20.3",
|
"tsx": "^4.20.3",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ termSession.on('ready', () => {
|
|||||||
console.log('\n--- Ping abbrechen mit ^C ---');
|
console.log('\n--- Ping abbrechen mit ^C ---');
|
||||||
termSession.input('^C');
|
termSession.input('^C');
|
||||||
|
|
||||||
termSession.input("sdfsdfsdaf\n");
|
|
||||||
termSession.input("\n");
|
|
||||||
termSession.input("\n");
|
|
||||||
termSession.input("\n");
|
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
// Nach 4 Sekunden beenden
|
// Nach 4 Sekunden beenden
|
||||||
|
|||||||
@@ -1,138 +1,45 @@
|
|||||||
// stat-vit-term.js
|
// src/stat-vit-term.js
|
||||||
import { EventEmitter } from 'events';
|
|
||||||
import { spawn } from 'child_process';
|
|
||||||
|
|
||||||
|
import pty from 'node-pty';
|
||||||
|
|
||||||
class StatVitTerm extends EventEmitter {
|
const shell = process.platform === 'win32' ? 'powershell.exe' : 'bash';
|
||||||
constructor(options = {}) {
|
|
||||||
super();
|
|
||||||
this.options = {
|
|
||||||
shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash',
|
|
||||||
cwd: process.cwd(),
|
|
||||||
env: {
|
|
||||||
...process.env,
|
|
||||||
PS1: '$ ',
|
|
||||||
TERM: 'xterm-256color'
|
|
||||||
},
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
this.process = null;
|
|
||||||
this.isRunning = false;
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
_init() {
|
const ptyProcess = pty.spawn(shell, [], {
|
||||||
try {
|
name: 'xterm-256color',
|
||||||
// Wichtige Änderung: Shell im richtigen Modus starten
|
cols: 120,
|
||||||
const args = process.platform === 'win32' ? [] : ['-l']; // login shell
|
rows: 30,
|
||||||
this.process = spawn(this.options.shell, args, {
|
cwd: process.cwd(),
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
env: {
|
||||||
cwd: this.options.cwd,
|
...process.env,
|
||||||
env: this.options.env,
|
TERM: 'xterm-256color',
|
||||||
detached: true // Wichtig für Signalbehandlung
|
COLORTERM: 'truecolor',
|
||||||
});
|
LANG: 'en_US.UTF-8',
|
||||||
|
PWD: process.cwd(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.process.stdout.on('data', (data) => {
|
// Handle output
|
||||||
this.emit('std', data.toString());
|
ptyProcess.onData((data) => {
|
||||||
});
|
process.stdout.write(data); // Preserve formatting
|
||||||
|
});
|
||||||
|
|
||||||
this.process.stderr.on('data', (data) => {
|
// Handle exit
|
||||||
this.emit('std', data.toString());
|
ptyProcess.onExit(({ exitCode, signal }) => {
|
||||||
});
|
console.log(`\n\n✨ Shell exited with code ${exitCode}${signal ? ` (via signal ${signal})` : ''}`);
|
||||||
|
});
|
||||||
|
|
||||||
this.process.on('close', (code) => {
|
// Simulate input
|
||||||
this.isRunning = false;
|
setTimeout(() => {
|
||||||
this.emit('close', code);
|
console.log('\n[INPUT] Starting ping...');
|
||||||
});
|
ptyProcess.write('ping 127.0.0.1\r');
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
this.process.on('error', (err) => {
|
setTimeout(() => {
|
||||||
this.emit('err', err.message);
|
console.log('\n[INPUT] Sending Ctrl+C...');
|
||||||
});
|
ptyProcess.write('\x03'); // Ctrl+C
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
this.isRunning = true;
|
setTimeout(() => {
|
||||||
|
console.log('\n[INPUT] Exiting shell...');
|
||||||
setTimeout(() => {
|
ptyProcess.write('exit\r');
|
||||||
this.emit('ready');
|
}, 7000);
|
||||||
}, 500);
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
this.emit('err', err.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input(data) {
|
|
||||||
if (!this.isRunning || !this.process) {
|
|
||||||
this.emit('err', 'Terminal is not running');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (data === '^C') {
|
|
||||||
// Methode 1: SIGINT an die Prozessgruppe senden
|
|
||||||
if (process.platform !== 'win32' && this.process.pid) {
|
|
||||||
try {
|
|
||||||
process.kill(-this.process.pid, 'SIGINT');
|
|
||||||
} catch (e) {
|
|
||||||
// Fallback: Ctrl+C direkt senden
|
|
||||||
this.process.stdin.write('\x03');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.process.stdin.write('\x03');
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (data === '^Z') {
|
|
||||||
if (process.platform !== 'win32' && this.process.pid) {
|
|
||||||
try {
|
|
||||||
process.kill(-this.process.pid, 'SIGTSTP');
|
|
||||||
} catch (e) {
|
|
||||||
this.process.stdin.write('\x1A');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.process.stdin.write('\x1A');
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.process.stdin.write(data);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
this.emit('err', err.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kill() {
|
|
||||||
if (this.process) {
|
|
||||||
try {
|
|
||||||
if (process.platform !== 'win32' && this.process.pid) {
|
|
||||||
// SIGINT an Prozessgruppe
|
|
||||||
process.kill(-this.process.pid, 'SIGINT');
|
|
||||||
setTimeout(() => {
|
|
||||||
if (this.process) {
|
|
||||||
this.process.kill('SIGTERM');
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
} else {
|
|
||||||
this.process.kill('SIGTERM');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
try {
|
|
||||||
this.process.kill('SIGKILL');
|
|
||||||
} catch (err2) {
|
|
||||||
this.emit('err', 'Could not kill process');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get pid() {
|
|
||||||
return this.process ? this.process.pid : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get running() {
|
|
||||||
return this.isRunning;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default StatVitTerm;
|
|
||||||
Reference in New Issue
Block a user