char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
70e18bf
main
1import { assert , assertEquals , assertRejects , assertStringIncludes } from "@std/assert" ; 2import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context" ; 3import { Type } from "@earendil-works/pi-ai" ; 4import { fauxAssistantMessage , fauxToolCall } from "@earendil-works/pi-ai/providers/faux" ; 5import { defineExtension } from "@berry/api" ; 6import { localEnvironment } from "@berry/api/environment.ts" ; 7import { onPath , tempDir } from "@berry/util" ; 8import code from "../extensions/code/mod.ts" ; 9import { ShellEntry } from "./shell.ts" ; 10import { lastToolResult , script , sectionsSeen , setup , toolsOffered , turn } from "./fixture.ts" ; 11 12Deno . test ( "environment-gated tools disappear from both catalogs and cannot be called while disabled" , async () => { 13await usingroot = await tempDir (); 14let offline = false ; 15await usingh = await setup ({ 16open :( name , cwd ) => { 17if ( offline ) return Promise . reject ( new Error ( "offline" )); 18return Promise . resolve ( Object . assign ( localEnvironment ( cwd ?? root . path ), { 19 name, 20platform :name === "windows" ?"win32" :"linux" , 21})); 22}, 23close :() => Promise . resolve (), 24}); 25let calls = 0 ; 26await h . berry . install ( defineExtension ({ 27name :"conditional" , 28initial :() => null , 29setup ( ext ) { 30ext . tool ({ 31name :"windowsOnly" , 32description :"Windows only" , 33parameters :Type . Object ({}), 34expose :"both" , 35enabled :({ env}) => Promise . resolve ( env ?. platform === "win32" ), 36execute :() => ++ calls , 37}); 38}, 39})); 40await h . berry . install ( code ); 41const tid = await h . berry . create ({ extensions :{ conditional :{}, code :{} }, model :h . model }); 42const direct = fauxAssistantMessage ( fauxToolCall ( "windowsOnly" , {}), { stopReason :"toolUse" }); 43const disabled = await turn ( h , tid , [ direct , script ( "return await tools.windowsOnly({})" )]); 44assert ( ! toolsOffered ( disabled [ 0 ]). includes ( "windowsOnly" )); 45assert ( ! toolsOffered ( disabled [ 0 ]). includes ( "powershell" )); 46const catalog = sectionsSeen ( disabled [ 0 ]). at ( - 1 )?. codemode ?? "" ; 47assert ( ! catalog . includes ( "windowsOnly" )); 48assert ( ! catalog . includes ( "powershell" )); 49assert ( lastToolResult ( disabled [ 1 ]). isError ); 50assert ( lastToolResult ( disabled [ 2 ]). isError ); 51assertEquals ( calls , 0 ); 52 53await h . berry . configureExtension ( tid , "environment" , { environment :"windows" }); 54const enabled = await turn ( h , tid , [ direct , script ( "return await tools.windowsOnly({})" )]); 55assert ( toolsOffered ( enabled [ 0 ]). includes ( "powershell" )); 56assertStringIncludes ( sectionsSeen ( enabled [ 0 ]). at ( - 1 )?. codemode ?? "" , "powershell:" ); 57assertEquals ( calls , 2 ); 58 59offline = true ; 60const unavailable = await turn ( h , tid , [ 61script ( "return await tools.powershell({ command: 'Get-Location', timeout: 10 })" ), 62]); 63assert ( ! sectionsSeen ( unavailable [ 0 ]). at ( - 1 )?. codemode ?. includes ( "powershell" )); 64assert ( lastToolResult ( unavailable [ 1 ]). isError ); 65offline = false ; 66 67await h . berry . configureExtension ( tid , "environment" , { environment :"local" }); 68const [ again ] = await turn ( h , tid , []); 69assert ( ! toolsOffered ( again ). includes ( "powershell" )); 70assert ( ! toolsOffered ( again ). includes ( "windowsOnly" )); 71assert ( ! sectionsSeen ( again ). at ( - 1 )?. codemode ?. includes ( "powershell" )); 72}); 73 74Deno . test ({ 75name :"workspace command follows the target jj workspace and disappears for unavailable targets" , 76ignore :! onPath ( "jj" ), 77async fn () { 78await usingroot = await tempDir (); 79const repo = root . path + "/repo" ; 80const nested = repo + "/nested" ; 81const secondary = root . path + "/secondary" ; 82for ( 83const args of [ 84[ "git" , "init" , repo ], 85[ "-R" , repo , "workspace" , "add" , secondary ], 86] 87) { 88const result = await new Deno . Command ( "jj" , { args, stdout :"null" , stderr :"piped" }) 89. output (); 90assert ( result . success , new TextDecoder (). decode ( result . stderr )); 91} 92await Deno . mkdir ( nested ); 93let offline = false ; 94await usingh = await setup ({ 95open :( name , cwd ) => { 96if ( offline ) return Promise . reject ( new Error ( "offline" )); 97const env = localEnvironment ( cwd ?? root . path ); 98if ( name === "no-jj" ) env . exec = () => Promise . reject ( new Error ( "jj missing" )); 99return Promise . resolve ( env ); 100}, 101close :() => Promise . resolve (), 102}); 103await h . berry . install ( code ); 104const tid = await h . berry . create ({ extensions :{ code :{} }, model :h . model }); 105const offered = async () => 106( await h . berry . commands ( tid )). some (({ name}) => name === "workspace" ); 107assertEquals ( await offered (), false ); 108await assertRejects ( 109() => h . berry . command ( tid , "workspace" , "" ), 110Error , 111"No command /workspace" , 112); 113 114await h . berry . configureExtension ( tid , "environment" , { cwd :nested }); 115assertEquals ( await offered (), true ); 116await h . berry . configureExtension ( tid , "environment" , { cwd :secondary }); 117assertEquals ( await offered (), true ); 118await h . berry . command ( tid , "cd" , root . path ); 119assertEquals ( await offered (), false ); 120 121await h . berry . configureExtension ( tid , "environment" , { cwd :repo , environment :"no-jj" }); 122assertEquals ( await offered (), false ); 123await h . berry . configureExtension ( tid , "environment" , { environment :"local" , cwd :nested }); 124assertEquals ( await offered (), true ); 125offline = true ; 126assertEquals ( await offered (), false ); 127await assertRejects ( 128() => h . berry . command ( tid , "workspace" , "" ), 129Error , 130"No command /workspace" , 131); 132assert (( await h . berry . commands ( tid )). some (({ name}) => name === "cd" )); 133}, 134}); 135 136Deno . test ( "user shell commands choose PowerShell on the target Windows machine" , async () => { 137await usingroot = await tempDir (); 138await usingh = await setup ({ 139open :( name , cwd ) => 140Promise . resolve ( Object . assign ( localEnvironment ( cwd ?? root . path ), { 141 name, 142platform :"win32" , 143})), 144close :() => Promise . resolve (), 145}); 146await h . berry . install ( defineExtension ({ 147name :"code" , 148initial :() => null , 149setup () { 150return ( conv ) => { 151if ( conv . env ?. platform !== "win32" ) return ; 152conv . tool ({ 153name :"powershell" , 154description :"PowerShell" , 155expose :"codemode" , 156parameters :Type . Object ({ command :Type . String () }), 157execute :({ command}, { env}) => ({ shell :"powershell" , command, cwd :env . cwd }), 158}); 159}; 160}, 161})); 162const tid = await h . berry . create ({ extensions :{ code :{} }, model :h . model }); 163const task = await h . berry . shell ( tid , "Get-Location" ); 164await h . berry . harness . waitForTask ( task , BACKGROUND_CONTEXT ); 165const conversation = ( await h . berry . conversation ( tid )) ! ; 166await conversation . waitForIdle ( BACKGROUND_CONTEXT ); 167const entries = await conversation . entries ( 168{ order :"ascending" }, 169100 , 170undefined , 171BACKGROUND_CONTEXT , 172); 173assertEquals ( entries . items . find ( ShellEntry . is )?. data . result , { 174shell :"powershell" , 175command :"Get-Location" , 176cwd :root . path , 177}); 178});