import * as nodePty from "node-pty"; export interface PtyExitEvent { exitCode: number; signal: number | null; } export interface PtyProcess { readonly pid: number; write(data: string): void; resize(cols: number, rows: number): void; kill(signal?: string): void; onData(callback: (data: string) => void): () => void; onExit(callback: (event: PtyExitEvent) => void): () => void; } export interface PtySpawnInput { shell: string; cwd: string; cols: number; rows: number; env: NodeJS.ProcessEnv; } export interface PtyAdapter { spawn(input: PtySpawnInput): PtyProcess; } class NodePtyProcess implements PtyProcess { constructor(private readonly process: nodePty.IPty) {} get pid(): number { return this.process.pid; } write(data: string): void { this.process.write(data); } resize(cols: number, rows: number): void { this.process.resize(cols, rows); } kill(signal?: string): void { this.process.kill(signal); } onData(callback: (data: string) => void): () => void { const disposable = this.process.onData(callback); return () => { disposable.dispose(); }; } onExit(callback: (event: PtyExitEvent) => void): () => void { const disposable = this.process.onExit((event) => { callback({ exitCode: event.exitCode, signal: event.signal ?? null, }); }); return () => { disposable.dispose(); }; } } export class NodePtyAdapter implements PtyAdapter { spawn(input: PtySpawnInput): PtyProcess { const ptyProcess = nodePty.spawn(input.shell, [], { cwd: input.cwd, cols: input.cols, rows: input.rows, env: input.env, name: globalThis.process.platform === "win32" ? "xterm-color" : "xterm-256color", }); return new NodePtyProcess(ptyProcess); } }