34 lines
3.2 KiB
TypeScript
34 lines
3.2 KiB
TypeScript
/** Pause cases use snapshot modules and isolated durable storage, as Ultimate's fixture does. */
|
|
import { BACKGROUND_CONTEXT as context } from '@earendil-works/chord/context'
|
|
import { obj } from '@earendil-works/pi-schema'
|
|
import { createModels } from '@earendil-works/pi-ai/models'
|
|
import { fauxProvider } from '@earendil-works/pi-ai/providers/faux'
|
|
import { Harness,createRegistry,defineExtension,defineTask,defineTool } from '@earendil-works/pi-durable'
|
|
import { openStorage } from './sqlite'
|
|
import { Metadata } from './extensions'
|
|
let serial=0
|
|
export const hosts:any[]=[]
|
|
export const streamTask=(released:Promise<void>)=>defineTask({name:'pause-test.stream',version:1,initial:()=>({phase:'stream'}),phases:{stream:async(_task:any,runtime:any,ctx:any)=>{await released;await runtime.commit(()=>({status:'terminal',outcome:{status:'completed',result:null}}),ctx)}},abort:(_task:any,runtime:any,ctx:any)=>runtime.commit(()=>({status:'terminal',outcome:{status:'aborted'}}),ctx)})
|
|
export async function fixture(home?:string,retry:any={}) {
|
|
home??=`${globalThis.storagePath}.pause-${++serial}`
|
|
const registry=createRegistry(),models=createModels(),faux=fauxProvider({tokensPerSecond:100000});models.setProvider(faux.provider)
|
|
let finish:any,finished=0,opened:any,storage:any
|
|
const background=Promise.withResolvers<void>(),openers:any[]=[],closers:any[]=[],services=new Map(),resources=new Map()
|
|
registry.install(defineExtension({name:'pause-test',tasks:[streamTask(background.promise)],tools:[defineTool({name:'work',description:'Work until released',parameters:obj({}),execute:async()=>{await new Promise(resolve=>{finish=resolve});finished++;return {content:[{type:'text',text:'worked'}]}}})]}))
|
|
const host:any={harness:()=>opened.harness,metadata:Metadata,implement:(api:any,value:any)=>services.set(api.name,value),want:(api:any)=>services.get(api.name),resource:(key:string,create:any)=>{if(!resources.has(key))resources.set(key,create());return resources.get(key)},onOpen:(cb:any)=>openers.push(cb),onClose:(cb:any)=>closers.push(cb)}
|
|
const module=await import(/* @vite-ignore */ `${globalThis.automationBase}/pause/server.ts`)
|
|
registry.install(module.default(host))
|
|
const open=async()=>{
|
|
storage=await openStorage(home!)
|
|
const harness=await Harness.open(storage,{models,registry,settings:{retry:{baseDelayMs:1,...retry},get extensions(){return registry.snapshot().installed()}}},context)
|
|
const root=await harness.root(context,{agent:{model:{provider:'faux',modelId:'faux-1'}}})
|
|
opened={harness,root,close:async()=>{for(const cb of closers)await cb();await harness.close(context);await storage.close()}}
|
|
hosts.push(opened)
|
|
for(const cb of openers)await cb()
|
|
harness.resume()
|
|
return opened
|
|
}
|
|
return {home,prepared:{registry,faux},open,action:(name:string)=>module.actions[name](null,{host}),setAutoPlay:(minutes:number|null)=>module.actions.autoPlay({minutes},{host}),autoPlay:(now:number)=>module.autoPlay(host,now),paused:()=>services.get('pause').paused(),get opened(){return opened},get finish(){return finish},finished:()=>finished,background,stream:streamTask(background.promise),close:async()=>{await opened.close();hosts.splice(hosts.indexOf(opened),1)}}
|
|
}
|
|
export async function clean() {for(const host of hosts.splice(0))await host.close()}
|