71 lines
5.8 KiB
TypeScript
71 lines
5.8 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'
|
|
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 proxyTemplate={...models.getModels('faux')[0],provider:'openai',baseUrl:'https://proxy.invalid/v1'}
|
|
models.setProvider({...faux.provider,id:'openai',getModels:()=>[proxyTemplate]})
|
|
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 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 fast family and thinking')
|
|
assert(agent.tools.map(t=>t.name).join(',')==='read,write','worker tools and project overlay')
|
|
assert(agent.instructions.includes('Worker body') && agent.instructions.includes('Project body'),'definition body and overlay')
|
|
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 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)
|
|
await fs.write('/src/sausage/agents/models.json',JSON.stringify({default:{model:'faux/faux-1'},fast:{model:'faux/faux-1',thinking:'high'}}))
|
|
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'}]})
|
|
await fs.write('/src/sausage/agents/models.json',JSON.stringify({default:{model:'faux/faux-1'},fast:{model:'faux/second'}}))
|
|
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 family changes next model without restart')
|
|
await fs.write('/src/sausage/agents/models.json',JSON.stringify({default:{model:'faux/faux-1'},fast:{model:'logical/new'}}))
|
|
faux.setResponses([fauxAssistantMessage('proxy')])
|
|
await (await worker.submit({type:'input',content:'proxy'},context)).wait(context)
|
|
assert(models.getModel('logical','new').baseUrl===proxyTemplate.baseUrl && models.getProvider('logical').auth===models.getProvider('openai').auth,'new model retains proxy transport and auth')
|
|
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 family selection')
|
|
await harness.commit(tx=>conversations.setStanding(tx,worker.id,true),context)
|
|
let refused=false;try{await harness.commit(tx=>conversations.concludeIn(tx,[worker.id]),context)}catch{refused=true}
|
|
assert(refused,'standing conversation cannot conclude')
|
|
} finally {await loader.close();await harness.close(context)}
|