import { preprocessMessages } from "../endpoints/preprocessMessages"; import { generateTitleForConversation } from "./title"; import { type MessageUpdate, MessageUpdateType, MessageUpdateStatus, } from "$lib/types/MessageUpdate"; import { generate } from "./generate"; import { mergeAsyncGenerators } from "$lib/utils/mergeAsyncGenerators"; import type { TextGenerationContext } from "./types"; async function* keepAlive(done: AbortSignal): AsyncGenerator { while (!done.aborted) { yield { type: MessageUpdateType.Status, status: MessageUpdateStatus.KeepAlive, }; await new Promise((resolve) => setTimeout(resolve, 100)); } } export async function* textGeneration(ctx: TextGenerationContext) { const done = new AbortController(); const titleGen = generateTitleForConversation(ctx.conv, ctx.locals); const textGen = textGenerationWithoutTitle(ctx, done); const keepAliveGen = keepAlive(done.signal); // keep alive until textGen is done yield* mergeAsyncGenerators([titleGen, textGen, keepAliveGen]); } async function* textGenerationWithoutTitle( ctx: TextGenerationContext, done: AbortController ): AsyncGenerator { yield { type: MessageUpdateType.Status, status: MessageUpdateStatus.Started, }; const { conv, messages } = ctx; const convId = conv._id; const preprompt = conv.preprompt; const processedMessages = await preprocessMessages(messages, convId); yield* generate({ ...ctx, messages: processedMessages }, preprompt); done.abort(); }