@@ -255,17 +255,24 @@ export function resolveRelayResponse(reqId: string, status: number, body: any):
255255// --- Shared terminal peer registry ---
256256// Centralized here to avoid circular imports between _share-terminal.ts and _share-relay.ts
257257
258+ const MAX_TERMINAL_BUFFER = 50 * 1024 ; // 50KB rolling replay buffer per terminal
259+
258260interface SharedTerminalEntry {
259261 peers : Set < Peer > ;
262+ outputBuffer : string ; // rolling buffer for late subscribers
260263}
261264const sharedTerminals = new Map < string , SharedTerminalEntry > ( ) ;
262265
263266export function registerTerminalPeer ( terminalId : string , peer : Peer ) : void {
264267 let entry = sharedTerminals . get ( terminalId ) ;
265268 if ( ! entry ) {
266- entry = { peers : new Set ( ) } ;
269+ entry = { peers : new Set ( ) , outputBuffer : "" } ;
267270 sharedTerminals . set ( terminalId , entry ) ;
268271 }
272+ // Replay buffered output to late subscriber
273+ if ( entry . outputBuffer . length > 0 ) {
274+ try { peer . send ( JSON . stringify ( { type : "output" , terminalId, data : entry . outputBuffer } ) ) ; } catch { }
275+ }
269276 entry . peers . add ( peer ) ;
270277}
271278
@@ -280,6 +287,13 @@ export function unregisterTerminalPeer(terminalId: string, peer: Peer): void {
280287export function broadcastToTerminalPeers ( terminalId : string , message : any ) : void {
281288 const entry = sharedTerminals . get ( terminalId ) ;
282289 if ( ! entry ) return ;
290+ // Accumulate output in rolling replay buffer for late subscribers
291+ if ( message . type === "output" && typeof message . data === "string" ) {
292+ entry . outputBuffer += message . data ;
293+ if ( entry . outputBuffer . length > MAX_TERMINAL_BUFFER ) {
294+ entry . outputBuffer = entry . outputBuffer . slice ( entry . outputBuffer . length - MAX_TERMINAL_BUFFER ) ;
295+ }
296+ }
283297 const msg = JSON . stringify ( message ) ;
284298 for ( const peer of entry . peers ) {
285299 try { peer . send ( msg ) ; } catch { }
0 commit comments