char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
ae32111
main
1import { Buffer } from "node:buffer" ; 2import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context" ; 3import type { Environment } from "@berry/api" ; 4 5function variable ( env :Environment , name :string ) :string | undefined { 6// windows spells its variables in any case 7return Object . entries ( env . variables ). find (([ key ]) => 8env . platform === "win32" ?key . toUpperCase () === name :key === name 9)?.[ 1 ]; 10} 11 12async function findCommand ( env :Environment , command :string ) :Promise < string | undefined > { 13const windows = env . platform === "win32" ; 14const names = windows 15 ?( variable ( env , "PATHEXT" ) ?? ".EXE" ). split ( ";" ). filter ( Boolean ). map (( ext ) => command + ext ) 16 :[ command ]; 17for ( const dir of ( variable ( env , "PATH" ) ?? "" ). split ( windows ?";" :":" ). filter ( Boolean )) { 18for ( const name of names ) { 19const file = await env . joinPath ([ dir . replace ( / ^"(.*)"$ / , "$1" ), name ], BACKGROUND_CONTEXT ); 20if ( ! file . ok ) continue ; 21const info = await env . fileInfo ( file . value , BACKGROUND_CONTEXT ); 22if ( info . ok && info . value . kind !== "directory" ) return file . value ; 23} 24} 25} 26 27const commands = new Map < string , Promise < boolean >>(); 28 29/** Whether `command` is on the environment's PATH: asked once of each machine and PATH. */ 30export function hasCommand ( env :Environment , command :string ) :Promise < boolean > { 31const key = JSON . stringify ([ 32env . id , 33env . cwd , 34env . platform , 35variable ( env , "PATH" ), 36variable ( env , "PATHEXT" ), 37command , 38]); 39let found = commands . get ( key ); 40if ( found === undefined ) { 41found = findCommand ( env , command ). then (( path ) => path !== undefined ); 42commands . set ( key , found ); 43} 44return found ; 45} 46 47/** PowerShell on this machine, favoring PS7 even when only PS5 is on PATH. */ 48export async function powershellCommand ( env :Environment , command :string ) :Promise < string []> { 49let shell = await findCommand ( env , "pwsh" ); 50for ( 51const [ root , parts ] of [ 52[ "PROGRAMFILES" , [ "PowerShell" , "7" , "pwsh.exe" ]], 53[ "PROGRAMW6432" , [ "PowerShell" , "7" , "pwsh.exe" ]], 54] as const 55) { 56if ( shell !== undefined ) break ; 57const dir = variable ( env , root ); 58if ( ! dir ) continue ; 59const file = await env . joinPath ([ dir , ...parts ], BACKGROUND_CONTEXT ); 60if ( ! file . ok ) continue ; 61const info = await env . fileInfo ( file . value , BACKGROUND_CONTEXT ); 62if ( info . ok && info . value . kind !== "directory" ) shell = file . value ; 63} 64shell ??= await findCommand ( env , "powershell" ); 65if ( shell === undefined ) { 66const root = variable ( env , "SYSTEMROOT" ); 67if ( root ) { 68const file = await env . joinPath ([ 69root , 70"System32" , 71"WindowsPowerShell" , 72"v1.0" , 73"powershell.exe" , 74], BACKGROUND_CONTEXT ); 75if ( file . ok ) { 76const info = await env . fileInfo ( file . value , BACKGROUND_CONTEXT ); 77if ( info . ok && info . value . kind !== "directory" ) shell = file . value ; 78} 79} 80} 81if ( shell === undefined ) { 82throw new Error ( "PowerShell not found. Install PowerShell 7 or add it to PATH." ); 83} 84// encoded commands survive windows argument quoting and PS5's legacy input encoding 85const script = [ 86"[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)" , 87"$OutputEncoding = [Console]::OutputEncoding" , 88"$ProgressPreference = 'SilentlyContinue'" , 89command , 90"if ($?) { exit 0 }; if ($LASTEXITCODE) { exit $LASTEXITCODE }; exit 1" , 91]. join ( "\n" ); 92return [ 93shell , 94"-NoLogo" , 95"-NoProfile" , 96"-NonInteractive" , 97"-OutputFormat" , 98"Text" , 99"-EncodedCommand" , 100Buffer . from ( script , "utf16le" ). toString ( "base64" ), 101]; 102}