Files
sausage/extensions/conversations/server.ts
T

44 lines
2.4 KiB
TypeScript

/** 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<number>((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<number>()
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))
}})]})
}