/** Conversation metadata and lifecycle. Summaries remain disabled until the summary port supplies them. */ import { defineExtension, GenerationTask, hook, ROOT_CONVERSATION_ID } from '@earendil-works/pi-durable' import { ConversationsApi, State, Concluded } from './api.ts' export default function conversations(host: any) { const concludedIn = async (tx: any) => new Set((await tx.doc(Concluded)).ids) host.implement(ConversationsApi, { concludedIn, concluded: async (context: any) => host.harness().commit(concludedIn,context), concludeIn: async (tx: any, ids: number[]) => { for (const id of ids) { const record = await tx.conversation(id) if (!record) throw new Error(`Unknown conversation ${id}`) if (record.owner) throw new Error(`Conversation ${id} is owned`) if (id === ROOT_CONVERSATION_ID || (await tx.doc(State,id)).mainAgent) throw new Error(`Conversation ${id} is fixed`) } const state = await tx.doc(Concluded) state.ids = [...new Set([...state.ids,...ids])] }, setMainAgent: async (tx: any, id: number, mainAgent: boolean) => { (await tx.doc(State,id)).mainAgent = mainAgent }, setAutomaticSummaries: async (tx: any, id: number, enabled: boolean) => { (await tx.doc(State,id)).automaticSummaries = enabled }, generatedTitle: async (tx: any, id: number, title: string) => { const state = await tx.doc(State,id) if (state.generatedTitle === undefined && (await tx.doc(host.metadata,id)).title === title) state.generatedTitle = title }, subject: async (id: number, context: any) => { const metadata = await host.harness().snapshot(host.metadata,id,context) return metadata?.title ? {title:metadata.title} : {} }, // Later summaries can supply these without changing lifecycle callers. summaryModel: async () => undefined, requestSummary: async () => {}, }) return defineExtension({name:'conversations',hooks:[hook(GenerationTask,{beforeInput:async (_input,{tx,conversationId})=>{ const ancestors = new Set() for (let id = conversationId; id !== undefined && !ancestors.has(id);) { ancestors.add(id) const record = await tx.conversation(id) id = record?.owner?.conversationId ?? record?.parent?.conversationId } const state = await tx.doc(Concluded) state.ids = state.ids.filter(id=>!ancestors.has(id)) }})]}) }