char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
b4fc6cf
main
1import { defineDoc } from "@earendil-works/pi-durable" ; 2import type { Context } from "@earendil-works/chord" ; 3import { directory } from "@berry/api/environment.ts" ; 4import { 5type Project , 6type ProjectIndex , 7type ProjectInput , 8workspacePath , 9} from "@berry/api/projects.ts" ; 10import type { Environments } from "./environment.ts" ; 11 12export const Projects = defineDoc < ProjectIndex >({ 13kind :"berry.projects" , 14version :1 , 15scope :"session" , 16initial :() => ({}), 17checkpointWhen :() => true , 18}); 19 20export const ProjectOrder = defineDoc <{ ids :string [] }>({ 21kind :"berry.project-order" , 22version :1 , 23scope :"session" , 24initial :() => ({ ids :[] }), 25checkpointWhen :() => true , 26}); 27 28export async function resolveProject ( 29input :ProjectInput , 30previous :Project | undefined , 31environments :Environments , 32context :Context , 33) :Promise < Project > { 34const name = input . name . trim (); 35if ( ! name ) throw new Error ( "A project needs a name" ); 36if ( ! input . roots . length ) throw new Error ( "A project needs a workspace" ); 37if ( ! Number . isInteger ( input . defaultRoot ) || ! input . roots [ input . defaultRoot ]) { 38throw new Error ( "Choose a default workspace" ); 39} 40const roots = []; 41for ( const root of input . roots ) { 42const saved = previous ?. roots . find (( saved ) => 43saved . environment === root . environment && saved . cwd === root . cwd 44); 45if ( saved ) roots . push ( saved ); 46else { 47const env = await environments . open ( root . environment , null , context ); 48roots . push ({ 49environment :root . environment , 50cwd :await directory ( env , root . cwd , context ), 51platform :env . platform , 52}); 53} 54} 55return { name, roots, defaultRoot :input . defaultRoot }; 56} 57 58export function validateRoots ( projects :ProjectIndex , id :string , project :Project ) :void { 59const seen = new Set < string >(); 60for ( 61const [, value ] of [ 62 ...Object . entries ( projects ). filter (([ key ]) => key !== id ), 63[ id , project ] as const , 64] 65) { 66for ( const root of value . roots ) { 67const path = root . environment + ":" + workspacePath ( root . cwd , root . platform ); 68if ( seen . has ( path )) { 69throw new Error ( `Workspace ${ root . environment } : ${ root . cwd } is already in a project` ); 70} 71seen . add ( path ); 72} 73} 74}