Integrate terminal emulator in server.ts (Phase 1)
This commit is contained in:
parent
c9908c87c3
commit
0366e459f5
1 changed files with 26 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ import {
|
||||||
updateLastSeen,
|
updateLastSeen,
|
||||||
updateSessionStats,
|
updateSessionStats,
|
||||||
} from "./db";
|
} from "./db";
|
||||||
|
import { createTerminal, disposeTerminal, type TerminalSession } from "./terminal";
|
||||||
import type {
|
import type {
|
||||||
AnswerResponse,
|
AnswerResponse,
|
||||||
ClientMessage,
|
ClientMessage,
|
||||||
|
|
@ -33,6 +34,7 @@ const sessionWebSockets = new Map<number, ServerWebSocket<SessionData>>();
|
||||||
const sessionStates = new Map<number, SessionState>();
|
const sessionStates = new Map<number, SessionState>();
|
||||||
// Buffer for incomplete ANSI sequences per session to avoid leaking partial control codes
|
// Buffer for incomplete ANSI sequences per session to avoid leaking partial control codes
|
||||||
const ansiCarryovers = new Map<number, string>();
|
const ansiCarryovers = new Map<number, string>();
|
||||||
|
const sessionTerminals = new Map<number, TerminalSession>();
|
||||||
|
|
||||||
interface SessionData {
|
interface SessionData {
|
||||||
deviceId: number;
|
deviceId: number;
|
||||||
|
|
@ -437,6 +439,10 @@ const server = Bun.serve<SessionData>({
|
||||||
// Initialize in-memory session state
|
// Initialize in-memory session state
|
||||||
sessionStates.set(session.id, createDefaultSessionState());
|
sessionStates.set(session.id, createDefaultSessionState());
|
||||||
|
|
||||||
|
// Create terminal emulator with default size (will be resized later)
|
||||||
|
const termSession = createTerminal(80, 24);
|
||||||
|
sessionTerminals.set(session.id, termSession);
|
||||||
|
|
||||||
console.debug(
|
console.debug(
|
||||||
`Session ${session.id} started for device ${device.id}`,
|
`Session ${session.id} started for device ${device.id}`,
|
||||||
);
|
);
|
||||||
|
|
@ -506,6 +512,12 @@ const server = Bun.serve<SessionData>({
|
||||||
|
|
||||||
appendOutput(sessionId, body); // Store raw ANSI without trailing incomplete fragment
|
appendOutput(sessionId, body); // Store raw ANSI without trailing incomplete fragment
|
||||||
|
|
||||||
|
// Write to terminal emulator
|
||||||
|
const termSession = sessionTerminals.get(sessionId);
|
||||||
|
if (termSession) {
|
||||||
|
termSession.terminal.write(msg.data);
|
||||||
|
}
|
||||||
|
|
||||||
broadcastSSE({
|
broadcastSSE({
|
||||||
type: "output",
|
type: "output",
|
||||||
session_id: sessionId,
|
session_id: sessionId,
|
||||||
|
|
@ -615,6 +627,13 @@ const server = Bun.serve<SessionData>({
|
||||||
console.debug(
|
console.debug(
|
||||||
`Session ${ws.data.sessionId} resized to ${msg.cols}x${msg.rows}`,
|
`Session ${ws.data.sessionId} resized to ${msg.cols}x${msg.rows}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Resize terminal emulator
|
||||||
|
const termSession = sessionTerminals.get(ws.data.sessionId);
|
||||||
|
if (termSession) {
|
||||||
|
termSession.terminal.resize(msg.cols, msg.rows);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -654,6 +673,13 @@ const server = Bun.serve<SessionData>({
|
||||||
sessionWebSockets.delete(ws.data.sessionId);
|
sessionWebSockets.delete(ws.data.sessionId);
|
||||||
ansiCarryovers.delete(ws.data.sessionId);
|
ansiCarryovers.delete(ws.data.sessionId);
|
||||||
|
|
||||||
|
// Dispose terminal emulator
|
||||||
|
const termSession = sessionTerminals.get(ws.data.sessionId);
|
||||||
|
if (termSession) {
|
||||||
|
disposeTerminal(termSession);
|
||||||
|
sessionTerminals.delete(ws.data.sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
// Persist final state before cleanup
|
// Persist final state before cleanup
|
||||||
const state = sessionStates.get(ws.data.sessionId);
|
const state = sessionStates.get(ws.data.sessionId);
|
||||||
if (state?.dirty) {
|
if (state?.dirty) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue