@grasplabs/grasp
Version:
TypeScript SDK for browser automation and secure command execution in highly available and scalable cloud browser environments
125 lines • 4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TerminalService = void 0;
const logger_1 = require("../utils/logger");
const node_stream_1 = require("node:stream");
const uuid_1 = require("uuid");
class CommandSession {
/**
* Gets or creates a default logger instance
* @returns Logger instance
*/
getDefaultLogger() {
try {
return (0, logger_1.getLogger)().child('TerminalService');
}
catch (error) {
// If logger is not initialized, create a default one
const defaultLogger = new logger_1.Logger({
level: this.sandbox.isDebug ? 'debug' : 'info',
console: true,
});
return defaultLogger.child('TerminalService');
}
}
constructor(sandbox, connection, id = 'default0') {
this.cwd = '';
this.sandbox = sandbox;
this.connection = connection;
this.logger = this.getDefaultLogger();
this.id = id;
}
async getCwd() {
return this.cwd || (await this.updateCwd());
}
async updateCwd() {
try {
this.cwd = (await this.sandbox.readFileFromSandbox(`~/.pwd.${this.id}`, {
encoding: 'utf8',
})).trim();
}
catch (ex) {
this.cwd = '/home/user';
}
return this.cwd;
}
create() {
return new CommandSession(this.sandbox, this.connection, (0, uuid_1.v4)());
}
async runCommand(command, options = {}) {
try {
options.envs = options.envs || {};
options.envs.BROWSER_ENDPOINT = this.connection.wsUrl;
command = `${command} && pwd > ~/.pwd.${this.id}`;
const cwd = await this.getCwd();
const emitter = await this.sandbox.runCommand(command, {
cwd,
...options,
nohup: false,
background: true,
});
const task = emitter
.wait()
.then(async (res) => {
stdoutStream.push(null);
stderrStream.push(null);
cleanup();
await this.updateCwd();
return res;
})
.catch(ex => {
// this.logger.debug('Run command failed', ex);
return ex.result;
});
const stdoutStream = new node_stream_1.Readable({
read() { },
});
const stderrStream = new node_stream_1.Readable({
read() { },
});
// stdout 处理
const onStdout = (chunk) => {
stdoutStream.push(chunk);
};
// stderr 处理
const onStderr = (chunk) => {
stderrStream.push(chunk);
};
// 清理函数
const cleanup = () => {
emitter.off('stdout', onStdout);
emitter.off('stderr', onStderr);
};
emitter.on('stdout', onStdout);
emitter.on('stderr', onStderr);
return {
stdout: stdoutStream,
stderr: stderrStream,
end: async () => {
await task;
},
json: async () => task,
kill: async () => {
await emitter.kill();
stdoutStream.push(null);
stderrStream.push(null);
cleanup();
},
};
}
catch (error) {
this.logger.error('Run command failed', error);
throw error;
}
}
}
class TerminalService extends CommandSession {
constructor(sandbox, connection) {
super(sandbox, connection);
}
close() {
// TODO
}
}
exports.TerminalService = TerminalService;
//# sourceMappingURL=terminal.service.js.map