char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
ba8ed3c
main
1import { assert , assertEquals , assertMatch , assertRejects } from "@std/assert" ; 2import { join } from "node:path" ; 3import { tempDir } from "@berry/util" ; 4import { denoCheck , type ExtensionEntry } from "./loader.ts" ; 5import { extensionWeb } from "./web.ts" ; 6import { extension , fixture , open , put } from "./loader-fixture.ts" ; 7 8Deno . test ( "an aborted check rejects with its reason instead of reporting a failure" , async () => { 9const stopping = new AbortController (); 10stopping . abort ( new Error ( "berry is stopping" )); 11await assertRejects ( 12() => denoCheck ( Deno . cwd (), [ "server/main.ts" ], stopping . signal ), 13Error , 14"berry is stopping" , 15); 16}); 17 18Deno . test ( "startup traces include slow and failed imports and survive later reloads" , () => 19fixture ({ 20"slow/mod.ts" :`await new Promise((resolve) => setTimeout(resolve, 20));\n ${ extension ( "slow" )} ` , 21"slow/version.ts" :`export const VERSION = "one";` , 22"slow/web.tsx" :`export default {};` , 23"broken/mod.ts" :`await new Promise((resolve) => setTimeout(resolve, 20)); 24throw new Error("broken import");` , 25}, async ( root ) => { 26const { loader, close} = await open ( root ); 27try { 28await loader . loadAll (); 29const startup = loader . entries (). find (( entry ) => entry . name === "slow" ) ! . startup ; 30assert ( startup ); 31assert ( startup . phases . find (( phase ) => phase . name === "import" ) ! . durationMs >= 10 ); 32assertEquals ( startup . phases . find (( phase ) => phase . name === "frontend" ) ! . source , "build" ); 33assert ( startup . phases . some (( phase ) => phase . name === "install" )); 34assert ( startup . totalMs >= startup . phases . reduce (( sum , phase ) => sum + phase . durationMs , 0 )); 35const failed = loader . entries (). find (( entry ) => entry . name === "broken" ) ! . startup ; 36assert ( failed ); 37assertEquals ( failed . status , "failed" ); 38assert ( failed . phases . find (( phase ) => phase . name === "import" ) ! . durationMs >= 10 ); 39assert ( ! failed . phases . some (( phase ) => phase . name === "install" )); 40await loader . reload ( "slow" ); 41assertEquals ( loader . entries (). find (( entry ) => entry . name === "slow" ) ! . startup , startup ); 42await put ( join ( root , "extensions/slow" ), { "version.ts" :`export const VERSION = ;` }); 43await loader . reload ( "slow" ); 44const current = loader . entries (). find (( entry ) => entry . name === "slow" ) ! ; 45assertEquals ( current . status , "failed" ); 46assertEquals ( current . startup , startup ); 47} finally { 48await close (); 49} 50})); 51 52Deno . test ( "startup traces distinguish restored frontends from failed builds" , () => 53fixture ({ 54"cached/mod.ts" :extension ( "cached" , `const VERSION = "one";` ), 55"cached/web.tsx" :"export default {};" , 56"badweb/mod.ts" :extension ( "badweb" , `const VERSION = "one";` ), 57"badweb/web.tsx" :"export default (;" , 58}, async ( root ) => { 59await usingcache = await tempDir (); 60await extensionWeb ({ cacheDirectory :cache . path }). build ( 61"cached" , 62join ( root , "extensions/cached/web.tsx" ), 63); 64const { loader, close} = await open ( 65root , 66undefined , 67extensionWeb ({ cacheDirectory :cache . path }), 68); 69try { 70await loader . loadAll (); 71const restored = loader . entries (). find (( entry ) => entry . name === "cached" ) ! . startup ! ; 72assertEquals ( restored . status , "loaded" ); 73assertEquals ( restored . phases . find (( phase ) => phase . name === "frontend" ) ! . source , "cache" ); 74const failed = loader . entries (). find (( entry ) => entry . name === "badweb" ) ! . startup ! ; 75assertEquals ( failed . status , "failed" ); 76assertEquals ( failed . phases . find (( phase ) => phase . name === "frontend" ) ! . source , "build" ); 77} finally { 78await close (); 79} 80})); 81 82Deno . test ( "subagent is a selectable builtin and disk reloads cannot replace it" , () => 83fixture ({ 84"subagent/mod.ts" :extension ( "subagent" ), 85"subagent/version.ts" :`export const VERSION = "shadow";` , 86}, async ( root ) => { 87const { loader, close} = await open ( root ); 88const feed = loader . feed (); 89try { 90await loader . loadAll (); 91const installed = ( feed . value as ExtensionEntry []). find (( ext ) => ext . name === "subagent" ); 92assert ( installed ); 93assert ( installed . builtin && installed . running ); 94const result = await loader . reload ( "subagent" ); 95assertEquals ( result . status , "failed" ); 96assertMatch ( result . error ! , / restart berry / ); 97assertEquals (( feed . value as ExtensionEntry []). filter (( ext ) => ext . name === "subagent" ), [ 98installed , 99]); 100} finally { 101await feed . stop (); 102await close (); 103} 104})); 105 106Deno . test ( "the ui lists extensions by configuration order, and those without one after them by name" , () => 107fixture ({ 108"middle/mod.ts" :extension ( "middle" , `const VERSION = "middle";` , 20 ), 109"beta/mod.ts" :extension ( "beta" , `const VERSION = "beta";` ), 110"alpha/mod.ts" :extension ( "alpha" , `const VERSION = "alpha";` ), 111}, async ( root ) => { 112const { loader, close} = await open ( root ); 113const feed = loader . feed (); 114try { 115await loader . loadAll (); 116assertEquals ( 117( feed . value as ExtensionEntry []). map (( entry ) => entry . name ), 118[ "environment" , "middle" , "subagent" , "alpha" , "beta" ], 119); 120} finally { 121await feed . stop (); 122await close (); 123} 124})); 125 126Deno . test ( "the ui sees which extensions a new conversation starts with" , () => 127fixture ({ 128"lean/mod.ts" :`import { defineExtension } from "@berry/api"; 129export default defineExtension({ 130name: "lean", 131defaultEnabled: true, 132initial: () => null, 133setup() {}, 134});` , 135"shy/mod.ts" :extension ( "shy" ), 136}, async ( root ) => { 137const { loader, close} = await open ( root ); 138try { 139await loader . loadAll (); 140const byName = Object . fromEntries ( loader . entries (). map (( entry ) => [ entry . name , entry ])); 141assertEquals ( byName . lean . defaultEnabled , true ); 142assertEquals ( byName . shy . defaultEnabled , false ); 143} finally { 144await close (); 145} 146})); 147 148Deno . test ( "each extension loads on its own, and one that fails stops none of the others" , () => 149fixture ({ 150"good/mod.ts" :extension ( "good" ), 151"good/version.ts" :`export const VERSION = "one";` , 152"misnamed/mod.ts" :extension ( "other" , `const VERSION = "x";` ), 153"empty/notes.md" :"no mod.ts here" , 154}, async ( root ) => { 155const { loader, close, describe} = await open ( root ); 156await loader . loadAll (); 157const byName = Object . fromEntries ( loader . entries (). map (( e ) => [ e . name , e ])); 158assertEquals ( byName . good . status , "loaded" ); 159assertEquals ( describe ( "good" ), "one" ); 160assertEquals ( byName . misnamed . status , "failed" ); 161assertMatch ( byName . misnamed . error ! , / names itself other / ); 162assertMatch ( byName . empty . error ! , / has no mod\.ts / ); 163await close (); 164}));