Rework the logging and terminal emulator on the ui to work like an actual emulator for better output.

This commit is contained in:
Jaret Burkett
2026-07-16 08:50:40 -06:00
parent 5cb54ba9cc
commit e1e1996c16
6 changed files with 327 additions and 37 deletions

View File

@@ -2,20 +2,21 @@
import { useEffect, useState, useRef } from 'react';
import { apiClient } from '@/utils/api';
import { TerminalEmulator } from '@/utils/terminalEmulator';
interface FileObject {
path: string;
size: number;
}
const clean = (text: string): string => {
// remove \x1B[A\x1B[A
text = text.replace(/\x1B\[A/g, '');
return text;
};
export default function useJobLog(jobID: string, reloadInterval: null | number = null) {
const [log, setLog] = useState<string>('');
// Emulates a terminal over the raw log stream so carriage returns, cursor
// movement, and erase sequences collapse lines like a real terminal.
const terminalRef = useRef<TerminalEmulator | null>(null);
if (terminalRef.current === null) {
terminalRef.current = new TerminalEmulator();
}
const didInitialLoadRef = useRef(false);
// Byte offset into the log file that we've already consumed. Sent to the
// server so it only returns newly appended content.
@@ -42,14 +43,13 @@ export default function useJobLog(jobID: string, reloadInterval: null | number =
.then(res => res.data)
.then(data => {
offsetRef.current = data.offset ?? null;
const cleanLog = clean(data.log ?? '');
const terminal = terminalRef.current!;
if (data.reset) {
// Log was reset/truncated (or initial load) — replace everything.
setLog(cleanLog);
} else if (cleanLog) {
// Incremental — append only the new content.
setLog(prev => prev + cleanLog);
terminal.reset();
}
terminal.write(data.log ?? '');
setLog(terminal.toString());
setStatus('success');
didInitialLoadRef.current = true;
})
@@ -67,6 +67,7 @@ export default function useJobLog(jobID: string, reloadInterval: null | number =
offsetRef.current = null;
didInitialLoadRef.current = false;
inFlightRef.current = false;
terminalRef.current?.reset();
setLog('');
refresh();
@@ -81,5 +82,5 @@ export default function useJobLog(jobID: string, reloadInterval: null | number =
}
}, [jobID]);
return { log, setLog, status, refresh };
return { log, status, refresh };
}