char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
6f4605c
main
1import { assert , assertEquals } from "@std/assert" ; 2import { until } from "@berry/util" ; 3import { viewContext , withDom } from "@berry/util/dom.ts" ; 4import type { ViewContext } from "@berry/api/web.ts" ; 5import { browserView } from "./view.ts" ; 6import type { BrowserViewData , Snapshot } from "./types.ts" ; 7 8const page = ( tab :string , title :string ) :Snapshot => ({ 9 tab, 10 title, 11url :"https://example.com/" , 12text :`<script>untrusted()</script> ${ title } ` , 13elements :[{ ref :"e1" , role :"button" , name :"Continue" }], 14truncated :false , 15frames :[], 16diagnostics :[ "HTTP 404: https://example.com/missing" ], 17}); 18const context = ( request :ViewContext [ "request" ], latest = 1 ) => 19viewContext ({ tid :"conversation" , latest, request}); 20 21Deno . test ( "the close button ends a live session and then shows it as ended" , () => 22withDom ( async () => { 23const view = browserView (); 24const requests :string [] = []; 25let active = true ; 26view . update ( context (( name ) => { 27requests . push ( name ); 28if ( name === "close" ) active = false ; 29return Promise . resolve ( 30name === "close" 31 ?null 32 :{ active, tabs :[ page ( "t1" , "First" )], history :[], screenshots :[] }, 33); 34})); 35try { 36const close = [ ...view . element . querySelectorAll ( "button" )] 37. find (( button ) => button . textContent === "Close browser" ) as HTMLButtonElement ; 38await until (() => ! close . disabled ); 39close . click (); 40await until (() => 41view . element . querySelector ( '[role="status"]' )?. textContent ?. includes ( "historical" ) ?? false 42); 43assertEquals ( requests , [ "view" , "close" , "view" ]); 44assert ( close . disabled ); 45} finally { 46view . dispose ?.(); 47} 48})); 49 50Deno . test ( "outdated view responses and disposed requests cannot replace the current conversation" , () => 51withDom ( async () => { 52const view = browserView (); 53let resolveOld ! :( value :BrowserViewData ) => void ; 54let oldSignal ! :AbortSignal ; 55const old = context (( _ , __ , options ) => { 56oldSignal = options ! . signal ! ; 57return new Promise < BrowserViewData >(( resolve ) => { 58resolveOld = resolve ; 59}); 60}); 61view . update ( old ); 62const fresh :BrowserViewData = { 63active :true , 64tabs :[ page ( "t8" , "Current" )], 65history :[], 66screenshots :[], 67}; 68view . update ({ ...context (() => Promise . resolve ( fresh )), tid :"another" }); 69await until (() => view . element . textContent ?. includes ( "Current" ) ?? false ); 70assert ( oldSignal . aborted ); 71resolveOld ({ active :false , tabs :[ page ( "t1" , "Outdated" )], history :[], screenshots :[] }); 72await Promise . resolve (); 73assert ( ! view . element . textContent ?. includes ( "Outdated" )); 74let signal ! :AbortSignal ; 75view . update ( context (( _ , __ , options ) => { 76signal = options ! . signal ! ; 77return new Promise (() => {}); 78}, 3 )); 79view . dispose ?.(); 80assert ( signal . aborted ); 81}));