class GridBufferInjector {
private sessions: Map<string, SessionState> = new Map();
public handleGridUpdate(sessionId: string, update: GridUpdate) {
const session = this.sessions.get(sessionId);
if (!session) return;
const term = session.terminal;
// 1. Epoch validation
if (update.epoch < session.currentEpoch) {
invoke("grid_ack", { sessionId });
return; // Stale update
}
// 2. Inject cells
this.inject(session, term, update);
// 3. Send ACK
invoke("grid_ack", { sessionId });
}
private inject(session: SessionState, term: Terminal, update: GridUpdate) {
const buffer = term._core._bufferService.buffer;
const cols = term.cols;
// Sync scrollback position
buffer.ybase = update.scrollback_lines;
// Inject viewport
for (let row = 0; row < update.viewport.length; row++) {
const lineIndex = buffer.ybase + row;
const line = buffer.lines.get(lineIndex);
const data = line._data as Uint32Array;
for (let col = 0; col < cols; col++) {
const cell = update.viewport[row][col];
const offset = col * 3;
data[offset] = cell.content;
data[offset + 1] = cell.fg;
data[offset + 2] = cell.bg;
}
}
// Update cursor
buffer.x = update.cursor_x;
buffer.y = update.cursor_y;
// Trigger WebGL render
term.refresh(0, term.rows - 1);
}
}