feat: update sidebar agent workflow and host filter UI

This commit is contained in:
Mohamed Boudra
2026-02-15 08:59:17 +07:00
parent 9da5b26db0
commit 41d1fa6d97
31 changed files with 2482 additions and 1133 deletions
+57 -5
View File
@@ -64,6 +64,7 @@ export interface TerminalSession {
cwd: string;
send(msg: ClientMessage): void;
subscribe(listener: (msg: ServerMessage) => void): () => void;
onExit(listener: () => void): () => void;
subscribeRaw(
listener: (chunk: TerminalRawChunk) => void,
options?: { fromOffset?: number }
@@ -190,6 +191,7 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
const id = randomUUID();
const listeners = new Set<(msg: ServerMessage) => void>();
const rawListeners = new Set<(chunk: TerminalRawChunk) => void>();
const exitListeners = new Set<() => void>();
const rawOutputChunks: Array<{
startOffset: number;
endOffset: number;
@@ -199,6 +201,8 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
let rawBufferBytes = 0;
let outputOffset = 0;
let killed = false;
let disposed = false;
let exitEmitted = false;
// Create xterm.js headless terminal
const terminal = new Terminal({
@@ -221,6 +225,32 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
},
});
function emitExit(): void {
if (exitEmitted) {
return;
}
exitEmitted = true;
for (const listener of Array.from(exitListeners)) {
try {
listener();
} catch {
// no-op
}
}
exitListeners.clear();
}
function disposeResources(): void {
if (disposed) {
return;
}
disposed = true;
terminal.dispose();
listeners.clear();
rawListeners.clear();
exitListeners.clear();
}
function appendRawOutputChunk(data: string): void {
const chunkBytes = Buffer.byteLength(data);
if (chunkBytes <= 0) {
@@ -292,6 +322,8 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
ptyProcess.onExit(() => {
killed = true;
emitExit();
disposeResources();
});
function getState(): TerminalState {
@@ -340,6 +372,24 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
};
}
function onExit(listener: () => void): () => void {
if (killed) {
queueMicrotask(() => {
try {
listener();
} catch {
// no-op
}
});
return () => {};
}
exitListeners.add(listener);
return () => {
exitListeners.delete(listener);
};
}
function subscribeRaw(
listener: (chunk: TerminalRawChunk) => void,
options?: { fromOffset?: number }
@@ -380,11 +430,12 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
}
function kill(): void {
if (killed) return;
killed = true;
ptyProcess.kill();
terminal.dispose();
rawListeners.clear();
if (!killed) {
killed = true;
ptyProcess.kill();
emitExit();
}
disposeResources();
}
// Small delay to let shell initialize
@@ -396,6 +447,7 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
cwd,
send,
subscribe,
onExit,
subscribeRaw,
getOutputOffset,
getState,