@@ -18,6 +18,7 @@ import {
1818} from "./shell/chrome" ;
1919import { createAppShell } from "./shell/index" ;
2020import { splitAtSettledHeading } from "./markdown-parser" ;
21+ import { attachSessionBridge , createRecordingPort } from "./runtime-bridge" ;
2122import { isMarkdownRow } from "./stream" ;
2223
2324const WIDE = { width : 80 , height : 24 } as const ;
@@ -396,42 +397,67 @@ describe("markdown transcript rows", () => {
396397 } , WIDE ) ;
397398 } ) ;
398399
399- test ( "frozen assignment work stays constant when stream size doubles " , async ( ) => {
400+ test ( "bridge keeps frozen assignment work sub-quadratic " , async ( ) => {
400401 await withTestRenderer ( async ( h ) => {
401- function measure ( size : number ) : FrozenWork {
402+ async function measure ( size : number ) : Promise < FrozenWork > {
402403 const shell = createAppShell ( h . renderer , shellOpts ) ;
404+ const bridge = attachSessionBridge ( shell , createRecordingPort ( ) , {
405+ schedule : ( ) => ( ) => undefined ,
406+ } ) ;
403407 const frozen = [
404408 ...Array . from ( { length : size } , ( _ , i ) => `settled line ${ i } ` ) ,
405409 "### Title" ,
406410 ] . join ( "\n" ) ;
407- const initial = `${ frozen } \n\nx` ;
408- appendStreamRow ( shell , {
409- role : "assistant" ,
410- streaming : true ,
411- text : initial ,
412- } ) ;
413- const { frozenNode } = splitMarkdownNodes ( shell ) ;
414- const work = observeFrozenAssignments ( frozenNode , ( ) => {
415- for ( let i = 1 ; i <= size ; i += 1 ) {
416- replaceStreamRowAt ( shell , shell . streamLog . length - 1 , {
417- role : "assistant" ,
418- streaming : true ,
419- text : `${ initial } ${ "x" . repeat ( i ) } ` ,
420- } ) ;
411+ try {
412+ bridge . handle ( {
413+ type : "assistant.delta" ,
414+ text : `${ frozen } \n\nx` ,
415+ } ) ;
416+ await h . renderOnce ( ) ;
417+ const { frozenNode } = splitMarkdownNodes ( shell ) ;
418+ const descriptor = defined (
419+ Object . getOwnPropertyDescriptor (
420+ MarkdownRenderable . prototype ,
421+ "content" ,
422+ ) ,
423+ ) ;
424+ const work : FrozenWork = { assignments : 0 , chars : 0 } ;
425+ Object . defineProperty ( frozenNode , "content" , {
426+ configurable : true ,
427+ get : ( ) => descriptor . get ?. call ( frozenNode ) ,
428+ set : ( value : string ) => {
429+ work . assignments += 1 ;
430+ work . chars += value . length ;
431+ descriptor . set ?. call ( frozenNode , value ) ;
432+ } ,
433+ } ) ;
434+ try {
435+ for ( let i = 0 ; i < size ; i += 1 ) {
436+ bridge . handle ( { type : "assistant.delta" , text : "x" } ) ;
437+ await h . renderOnce ( ) ;
438+ expect ( splitMarkdownNodes ( shell ) . frozenNode ) . toBe ( frozenNode ) ;
439+ }
440+ expect ( splitMarkdownNodes ( shell ) . liveNode . content ) . toBe (
441+ "x" . repeat ( size + 1 ) ,
442+ ) ;
443+ } finally {
444+ Reflect . deleteProperty ( frozenNode , "content" ) ;
421445 }
422- } ) ;
423- shell . dispose ( ) ;
424- return work ;
446+ return work ;
447+ } finally {
448+ bridge . dispose ( ) ;
449+ shell . dispose ( ) ;
450+ }
425451 }
426452
427- const n = measure ( 20 ) ;
428- const twoN = measure ( 40 ) ;
453+ const n = await measure ( 20 ) ;
454+ const twoN = await measure ( 40 ) ;
429455 const ratio = ( twoN . chars + 1 ) / ( n . chars + 1 ) ;
430- expect ( { n , twoN , ratio } ) . toEqual ( {
431- n : { assignments : 0 , chars : 0 } ,
432- twoN : { assignments : 0 , chars : 0 } ,
433- ratio : 1 ,
434- } ) ;
456+ const headingTransitions = 0 ;
457+ const maxAssignments = headingTransitions + 1 ;
458+ expect ( ratio ) . toBeLessThan ( 3 ) ;
459+ expect ( n . assignments ) . toBeLessThanOrEqual ( maxAssignments ) ;
460+ expect ( twoN . assignments ) . toBeLessThanOrEqual ( maxAssignments ) ;
435461 } , WIDE ) ;
436462 } ) ;
437463
0 commit comments