/** Child configuration and start events share the transaction that creates ownership. */ import { AgentDoc, configure } from '@earendil-works/pi-durable' import { ModelsApi } from '../models/api.ts' import { Started } from './refs.ts' import { Profile } from './api.ts' export async function started(host: any, tx: any, conversation: any, agent: string, kind: 'child'|'standing'|'branch') { const {model, thinkingLevel} = await tx.doc(AgentDoc, conversation.id) const parent = conversation.owner?.conversationId ?? conversation.parent?.conversationId await host.emit(tx, Started, {id:conversation.id, agent, kind, ...(model ? {model:`${model.provider}/${model.modelId}`} : {}), ...(thinkingLevel ? {thinking:thinkingLevel} : {}), ...(parent === undefined ? {} : {parent})}) } export async function createChild(host: any, tx: any, options: any) { const {definition} = options const child = options.fork ? await tx.forkConversation(options.fork.conversationId, options.fork.at, {ownership:options.owner}) : await tx.createConversation({ownership:options.owner}) await configureChild(host, tx, child.id, options) Object.assign(await tx.doc(host.metadata, child.id), {label:options.label, title:options.title}) if (definition) (await tx.doc(Profile, child.id)).definition = definition.name if (definition?.summaries === false) await host.want({name:'conversations'})?.setAutomaticSummaries(tx, child.id, false) return child } /** Standing refreshes and new children share the models service and persistent definition profile. */ export async function configureChild(host: any, tx: any, id: number, options: any) { await configure(tx, id, childConfiguration(options)) if (options.definition) await host.need(ModelsApi).configure(tx, id, { agent:options.definition.name, inheritedTools:options.parentAgent.tools.map((tool: any)=>tool.name), excludeTools:options.excludeTools, model:options.model, thinking:options.thinking, }) } function childConfiguration(options: any) { const {parentAgent:parent} = options return { tools:parent.tools.filter((tool: any) => !options.excludeTools?.includes(tool.name)), extensions:parent.extensions.filter((extension: any) => !options.excludeExtensions?.includes(extension.name)), instructions:parent.instructions ?? null, model:options.model ?? parent.model ?? null, thinkingLevel:options.thinking ?? parent.thinkingLevel ?? null, cwd:options.cwd ?? parent.cwd ?? '/src/sausage', } }