Files
sausage/host/js/core-ext-test.ts
T

84 lines
6.4 KiB
TypeScript

/** Core extensions run through the real snapshot loader with a faux model. */
import { BACKGROUND_CONTEXT as context } from '@earendil-works/chord/context'
import { createModels } from '@earendil-works/pi-ai/models'
import { fauxProvider, fauxAssistantMessage } from '@earendil-works/pi-ai/providers/faux'
import { Harness, AgentDoc, createRegistry } from '@earendil-works/pi-durable'
import { openStorage } from './sqlite'
import { loadExtensions, fs } from './extensions'
import {readTestConfig,writeTestConfig} from './roster-fixture'
const assert = (ok:any,message:string)=>{if(!ok)throw new Error(message);Deno.core.ops.op_output(`ok - ${message}\n`)}
const models=createModels(), faux=fauxProvider({tokensPerSecond:100000});models.setProvider(faux.provider)
const storage=await openStorage(globalThis.storagePath), registry=createRegistry()
const harness=await Harness.open(storage,{models,registry,settings:{retry:{enabled:false},get extensions(){return registry.snapshot().installed()}}},context)
await harness.root(context,{agent:{model:{provider:'faux',modelId:'faux-1'}}})
const loader=await loadExtensions(harness,registry,storage,models,context)
try {
assert(!loader.state().error,`loader: ${loader.state().error ?? 'loaded'}`)
const {selection,conversations,State,metadata}=globalThis.core
const config = await readTestConfig(fs)
config.main_agent_name='worker'
config.roster=[{name:'worker',description:'Worker',model:'faux/faux-1',thinking:'low',tools:['read','write'],prompt:'Worker body'}]
const save = ()=>writeTestConfig(fs,config)
await save()
const worker=await selection.start({agent:'worker',cwd:'/project/sub'},context)
let agent=await worker.agent(context)
assert(agent.model.modelId==='faux-1' && agent.thinkingLevel==='low','worker roster model and thinking')
assert(agent.tools.map(t=>t.name).join(',')==='read,write','worker roster tools')
assert(agent.instructions.indexOf('## Sausage and the world') < agent.instructions.indexOf('Worker body'),'global prompt precedes role prompt')
const sections:any={}
for(const section of agent.sections) sections[section.key]=await section.render({conversationId:worker.id,agent},context)
assert(sections.project_context.includes('Root instructions') && sections.project_context.includes('Nested instructions'),'cwd and parent AGENTS.md')
assert(!sections.project_context.includes('Outside instructions'),'instructions stop at repo root')
assert(sections.skills.includes('builtin-skill') && sections.skills.includes('project-skill'),'builtin and project skills')
assert(sections.cwd==='/project/sub' && sections.tools.includes('read'),'cwd and tools sections')
const checkPrompt = (ctx: any, expected: string) => {
const prompt=JSON.stringify(ctx.messages.filter((message: any)=>message.role==='system'))
for (const route of ['whoami','conversations/ID/entries?after=N','events?after=N','models','extensions','credential-requests','/proc/processes','/proc/extensions','jaq']) assert(prompt.includes(route),`fresh system prompt includes ${route}`)
assert(prompt.includes(expected),'system prompt uses current global prompt')
assert(prompt.indexOf(expected)<prompt.indexOf('Worker body'),'system prompt places global prompt before role prompt')
}
faux.setResponses([(ctx)=>{checkPrompt(ctx,'## Sausage and the world');return fauxAssistantMessage('fresh')}])
harness.resume()
await (await worker.submit({type:'input',content:'fresh'},context)).wait(context)
config.prompt='Edited global prompt\\n'+config.prompt
await save()
faux.setResponses([(ctx)=>{checkPrompt(ctx,'Edited global prompt');return fauxAssistantMessage('edited')}])
await (await worker.submit({type:'input',content:'edited'},context)).wait(context)
const seed=await harness.commit(tx=>tx.appendEntry(worker.id,{kind:'test.seed'}),context)
const child=await worker.fork(seed.id,{ownership:{kind:'ownerless'}},context)
const unrelated=await harness.createConversation({ownership:{kind:'ownerless'}},context)
await harness.commit(async tx=>{
await conversations.concludeIn(tx,[worker.id,child.id,unrelated.id])
await conversations.setAutomaticSummaries(tx,worker.id,false)
;(await tx.doc(metadata,worker.id)).title='Generated'
await conversations.generatedTitle(tx,worker.id,'Generated')
},context)
assert((await harness.snapshot(State,worker.id,context)).automaticSummaries===false,'automatic summary seam')
assert((await harness.snapshot(State,worker.id,context)).generatedTitle==='Generated','generated title')
await child.submit({type:'write',entry:{kind:'test.note'}},context)
assert((await conversations.concluded(context)).size===3,'write does not resume')
faux.setResponses([fauxAssistantMessage('done')])
const receipt=await child.submit({type:'input',content:'resume'},context)
assert(JSON.stringify([...await conversations.concluded(context)])===JSON.stringify([unrelated.id]),'input placement atomically resumes ancestors')
harness.resume();await receipt.wait(context)
config.roster[0].thinking='high';await save()
faux.setResponses([fauxAssistantMessage('next')])
await (await worker.submit({type:'input',content:'next'},context)).wait(context)
agent=await worker.agent(context)
assert(agent.thinkingLevel==='high','model config edit applies next turn')
// A second faux model proves selection changes, not only the thinking level.
const provider=models.getProvider('faux'), template=models.getModels('faux')[0]
models.setProvider({...provider,getModels:()=>[template,{...template,id:'second'}]})
config.roster[0].model='faux/second';await save()
faux.setResponses([fauxAssistantMessage('second')])
await (await worker.submit({type:'input',content:'second'},context)).wait(context)
assert((await harness.snapshot(AgentDoc,worker.id,context)).model.modelId==='second','edited roster changes next model without restart')
globalThis.modelPin={provider:'faux',modelId:'faux-1'}
faux.setResponses([fauxAssistantMessage('pin')])
await (await worker.submit({type:'input',content:'pin'},context)).wait(context)
assert((await worker.agent(context)).model.provider==='faux','models.pin overrides roster selection')
await harness.commit(tx=>conversations.setMainAgent(tx,worker.id,true),context)
let refused=false;try{await harness.commit(tx=>conversations.concludeIn(tx,[worker.id]),context)}catch{refused=true}
assert(refused,'mainAgent conversation cannot conclude')
} finally {await loader.close();await harness.close(context)}