The server's serializeAsHTML() returns the full terminal screen state, not incremental chunks. Updated the dashboard to:
1. Handle initial_state event to receive current terminal state on connection
2. Replace output instead of appending (output event now replaces session.output)
3. Simplify renderSessionOutput() to always do full innerHTML replacement
This fixes the issue where output was being duplicated/appended incorrectly.
Removed the ansiCarryovers Map from server.ts since terminal emulation
now handles all ANSI sequence buffering internally. Marked ansi.ts and
ansi-carryover.ts as deprecated with JSDoc comments, but kept them for
backward compatibility and potential rollback.
When a dashboard connects via SSE, it now receives the current terminal
state for all active sessions. This allows dashboards to immediately
display the full terminal content without waiting for new output.
The output handler now:
- Writes raw data to terminal emulator
- Stores raw data in DB (unchanged)
- Serializes terminal state as HTML
- Broadcasts serialized HTML via SSE
This replaces the ansiToHtml() + splitAnsiCarryover() approach with
proper terminal emulation. The terminal emulator handles all ANSI
sequences internally, including incomplete sequences across chunks.
Creates new module providing terminal session management using @xterm/headless:
- createTerminal(): spawn headless terminal emulator instances
- serializeAsHTML(): export terminal state as HTML
- disposeTerminal(): clean up resources
This replaces stateless ANSI processing with proper VT emulation that tracks
cursor position, screen buffer, and terminal attributes across output chunks.
Embed SVG path data in TypeScript to enable runtime color switching based on app state (idle/processing/error) without maintaining multiple static SVG files.
Frontend now fetches existing sessions from /api/sessions when SSE connects.
Previously only listened for session_start events, causing sessions to
disappear after page reload.