@@ -172,10 +172,17 @@ test("terminal attach refuses an arbitrary replay suffix when the complete prese
172172
173173 assert . equal ( attached . ok , true ) ;
174174 assert . equal ( attached . result . fromPosition , 6 ) ;
175- assert . equal ( attached . result . events . length , 1 ) ;
176- assert . equal ( attached . result . events [ 0 ] . type , "presentation_unavailable" ) ;
177- assert . equal ( attached . result . events [ 0 ] . requestedFromPosition , 0 ) ;
178- assert . equal ( attached . result . events [ 0 ] . outputPosition , 6 ) ;
175+ assert . deepEqual ( attached . result . events [ 0 ] , {
176+ ...identity ,
177+ attachmentId : attached . result . attachmentId ,
178+ clientId : "client-a" ,
179+ type : "dimensions" ,
180+ cols : 80 ,
181+ rows : 24 ,
182+ } ) ;
183+ const unavailable = attached . result . events . find ( ( event ) => event . type === "presentation_unavailable" ) ;
184+ assert . equal ( unavailable . requestedFromPosition , 0 ) ;
185+ assert . equal ( unavailable . outputPosition , 6 ) ;
179186 } finally {
180187 await service . shutdown ( ) ;
181188 }
@@ -211,6 +218,70 @@ test("only the explicit presentation holder can forward emulator replies", async
211218 await service . shutdown ( ) ;
212219} ) ;
213220
221+ test ( "the presentation holder publishes canonical dimensions to every exact attachment" , async ( ) => {
222+ const pty = createPtyFactory ( ) ;
223+ const service = new TerminalService ( { serverId : "server-dimensions" , ptyFactory : pty , generateSessionId : ( ) => "session-dimensions" } ) ;
224+ const session = await service . createSession ( { projectId : "project-dimensions" , cols : 80 , rows : 24 } ) ;
225+ const journal = new OrderedEventJournal ( ) ;
226+ const registry = createTerminalOperationRegistry ( { service, eventJournal : journal , allowUnresolvedTestSessions : true } ) ;
227+ const dispatcher = createOperationDispatcher ( registry . operations ) ;
228+ const identity = { serverId : service . serverId , projectId : "project-dimensions" , sessionId : session . sessionId } ;
229+ const attach = async ( clientId ) => ( await dispatcher . command ( request (
230+ "terminal.attach" ,
231+ { clientId, identity, fromPosition : 0 } ,
232+ `attach-${ clientId } ` ,
233+ "write" ,
234+ clientId ,
235+ ) ) ) . result ;
236+ const resize = ( attachment , clientId , cols , rows , id ) => dispatcher . command ( request (
237+ "terminal.resize" ,
238+ { clientId, identity, attachmentId : attachment . attachmentId , cols, rows } ,
239+ id ,
240+ "write" ,
241+ clientId ,
242+ ) ) ;
243+
244+ try {
245+ const desktop = await attach ( "desktop" ) ;
246+ const browser = await attach ( "browser" ) ;
247+ assert . deepEqual ( desktop . events [ 0 ] , {
248+ ...identity ,
249+ attachmentId : desktop . attachmentId ,
250+ clientId : "desktop" ,
251+ type : "dimensions" ,
252+ cols : 80 ,
253+ rows : 24 ,
254+ } ) ;
255+
256+ assert . equal ( ( await resize ( desktop , "desktop" , 120 , 40 , "desktop-resize" ) ) . ok , true ) ;
257+ assert . equal ( ( await resize ( browser , "browser" , 40 , 16 , "observer-resize" ) ) . ok , false ) ;
258+
259+ const takeover = await dispatcher . command ( request (
260+ "terminal.presentation" ,
261+ { clientId : "browser" , identity, attachmentId : browser . attachmentId , mode : "takeover" } ,
262+ "browser-takeover" ,
263+ "write" ,
264+ "browser" ,
265+ ) ) ;
266+ assert . equal ( takeover . ok , true ) ;
267+ assert . equal ( ( await resize ( desktop , "desktop" , 100 , 30 , "stale-desktop-resize" ) ) . ok , false ) ;
268+ assert . equal ( ( await resize ( browser , "browser" , 40 , 16 , "browser-resize" ) ) . ok , true ) ;
269+
270+ assert . deepEqual ( pty . processes [ 0 ] . resizes , [ { cols : 120 , rows : 40 } , { cols : 40 , rows : 16 } ] ) ;
271+ const dimensions = journal . replay ( 0 ) . events
272+ . map ( ( event ) => event . payload )
273+ . filter ( ( event ) => event . type === "dimensions" ) ;
274+ assert . deepEqual ( dimensions . map ( ( event ) => [ event . clientId , event . attachmentId , event . cols , event . rows ] ) , [
275+ [ "desktop" , desktop . attachmentId , 120 , 40 ] ,
276+ [ "browser" , browser . attachmentId , 120 , 40 ] ,
277+ [ "desktop" , desktop . attachmentId , 40 , 16 ] ,
278+ [ "browser" , browser . attachmentId , 40 , 16 ] ,
279+ ] ) ;
280+ } finally {
281+ await service . shutdown ( ) ;
282+ }
283+ } ) ;
284+
214285test ( "fresh presentation replay preserves complete hostile control sequences at every emitted byte boundary" , async ( ) => {
215286 const pty = createPtyFactory ( ) ;
216287 const service = new TerminalService ( { serverId : "server-boundaries" , ptyFactory : pty , generateSessionId : ( ) => "session-boundaries" , maxReplayBytes : 64 * 1024 } ) ;
@@ -222,9 +293,9 @@ test("fresh presentation replay preserves complete hostile control sequences at
222293 for ( const byte of transcript ) pty . processes [ 0 ] . emitData ( new Uint8Array ( [ byte ] ) ) ;
223294 const attached = await dispatcher . command ( request ( "terminal.attach" , { clientId : "fresh" , identity, fromPosition : 0 , freshPresentation : true , maxInitialReplayBytes : 32 * 1024 } , "attach-boundaries" , "write" , "fresh" ) ) ;
224295 assert . equal ( attached . ok , true ) ;
225- assert . equal ( attached . result . events . length , 1 ) ;
226- assert . equal ( attached . result . events [ 0 ] . position , 0 ) ;
227- assert . deepEqual ( Buffer . from ( attached . result . events [ 0 ] . bytes , "base64" ) , Buffer . from ( transcript ) ) ;
296+ const replay = attached . result . events . find ( ( event ) => event . type === "output" ) ;
297+ assert . equal ( replay . position , 0 ) ;
298+ assert . deepEqual ( Buffer . from ( replay . bytes , "base64" ) , Buffer . from ( transcript ) ) ;
228299 await service . shutdown ( ) ;
229300} ) ;
230301
@@ -271,9 +342,14 @@ test("framed terminal attach keeps an overstated fragmented replay inside the pr
271342 maxInitialReplayBytes : 128 * 1024 ,
272343 } ) ;
273344
274- assert . equal ( attached . initialEvents . length , 1 ) ;
275- assert . equal ( attached . initialEvents [ 0 ] . type , "presentation_unavailable" ) ;
276- assert . equal ( attached . initialEvents [ 0 ] . requestedFromPosition , 0 ) ;
345+ assert . equal ( attached . initialEvents [ 0 ] . type , "dimensions" ) ;
346+ assert . equal ( attached . initialEvents [ 0 ] . serverId , "server-protocol-budget" ) ;
347+ assert . equal ( attached . initialEvents [ 0 ] . projectId , "project-protocol-budget" ) ;
348+ assert . equal ( attached . initialEvents [ 0 ] . sessionId , session . sessionId ) ;
349+ assert . equal ( attached . initialEvents [ 0 ] . cols , 80 ) ;
350+ assert . equal ( attached . initialEvents [ 0 ] . rows , 24 ) ;
351+ const unavailable = attached . initialEvents . find ( ( event ) => event . type === "presentation_unavailable" ) ;
352+ assert . equal ( unavailable . requestedFromPosition , 0 ) ;
277353 assert . equal ( attached . position , 40_000 ) ;
278354 } finally {
279355 await protocolClient . close ( ) ;
0 commit comments