Add realtime terminal tab badges

This commit is contained in:
Federico Jaramillo Martinez
2026-05-11 10:45:56 +02:00
parent 045f4e247a
commit 80cf879e0f
16 changed files with 219 additions and 27 deletions
+13 -1
View File
@@ -1,6 +1,8 @@
import { EventEmitter } from "node:events";
import { randomUUID } from "node:crypto";
import * as pty from "node-pty";
import type { TerminalUiEvent } from "../../shared/apiTypes.js";
import type { SessionEventHub } from "../realtime/sessionEventHub.js";
const MAX_REPLAY_BUFFER = 200_000;
@@ -22,6 +24,8 @@ interface TerminalRecord extends TerminalInfo {
export class TerminalService {
private readonly terminals = new Map<string, TerminalRecord>();
constructor(private readonly events?: SessionEventHub) {}
list(cwd: string): TerminalInfo[] {
return [...this.terminals.values()]
.filter((terminal) => terminal.cwd === cwd)
@@ -59,9 +63,12 @@ export class TerminalService {
record.exited = true;
record.exitCode = exitCode;
record.events.emit("exit", exitCode);
this.publish({ type: "terminal.exited", terminal: toInfo(record) });
});
this.terminals.set(id, record);
return toInfo(record);
const info = toInfo(record);
this.publish({ type: "terminal.created", terminal: info });
return info;
}
get(id: string): TerminalInfo | undefined {
@@ -101,6 +108,7 @@ export class TerminalService {
this.terminals.delete(id);
terminal.events.removeAllListeners();
if (!terminal.exited) terminal.pty.kill();
this.publish({ type: "terminal.closed", terminalId: id, cwd: terminal.cwd });
}
dispose(): void {
@@ -112,6 +120,10 @@ export class TerminalService {
if (terminal === undefined) throw new Error("Terminal not found");
return terminal;
}
private publish(event: TerminalUiEvent): void {
this.events?.publishRealtime(event);
}
}
function toInfo(record: TerminalRecord): TerminalInfo {