UNPKG

@convex-dev/agent

Version:

A agent component for Convex.

97 lines 3.71 kB
import { validateVectorDimension } from "../component/vector/tables.js"; import { vMessageWithMetadata, } from "../validators.js"; import { serializeMessage } from "./index.js"; import { parse } from "convex-helpers/validators"; /** * List messages from a thread. * @param ctx A ctx object from a query, mutation, or action. * @param component The agent component, usually `components.agent`. * @param args.threadId The thread to list messages from. * @param args.paginationOpts Pagination options (e.g. via usePaginatedQuery). * @param args.excludeToolMessages Whether to exclude tool messages. * False by default. * @param args.statuses What statuses to include. All by default. * @returns The MessageDoc's in a format compatible with usePaginatedQuery. */ export async function listMessages(ctx, component, args) { if (args.paginationOpts.numItems === 0) { return { page: [], isDone: true, continueCursor: args.paginationOpts.cursor ?? "", }; } return ctx.runQuery(component.messages.listMessagesByThreadId, { order: "desc", ...args, }); } /** * Explicitly save messages associated with the thread (& user if provided) */ export async function saveMessages(ctx, component, args) { let embeddings; if (args.embeddings) { const dimension = args.embeddings.vectors.find((v) => v !== null)?.length; if (dimension) { validateVectorDimension(dimension); embeddings = { model: args.embeddings.model, dimension, vectors: args.embeddings.vectors, }; } } const result = await ctx.runMutation(component.messages.addMessages, { threadId: args.threadId, userId: args.userId ?? undefined, agentName: args.agentName, promptMessageId: args.promptMessageId, pendingMessageId: args.pendingMessageId, embeddings, messages: await Promise.all(args.messages.map(async (m, i) => { const { message, fileIds } = await serializeMessage(ctx, component, m); const allFileIds = args.metadata?.[i]?.fileIds ?? []; if (fileIds) { allFileIds.push(...fileIds); } return parse(vMessageWithMetadata, { ...args.metadata?.[i], message, fileIds: allFileIds.length > 0 ? allFileIds : undefined, }); })), failPendingSteps: args.failPendingSteps ?? false, }); return { messages: result.messages }; } /** * Save a message to the thread. * @param ctx A ctx object from a mutation or action. * @param args The message and what to associate it with (user / thread) * You can pass extra metadata alongside the message, e.g. associated fileIds. * @returns The messageId of the saved message. */ export async function saveMessage(ctx, component, args) { let embeddings; if (args.embedding && args.embedding.vector) { embeddings = { model: args.embedding.model, vectors: [args.embedding.vector], }; } const { messages } = await saveMessages(ctx, component, { threadId: args.threadId, userId: args.userId ?? undefined, agentName: args.agentName, pendingMessageId: args.pendingMessageId, messages: args.prompt !== undefined ? [{ role: "user", content: args.prompt }] : [args.message], metadata: args.metadata ? [args.metadata] : undefined, embeddings, }); const message = messages.at(-1); return { messageId: message._id, message }; } //# sourceMappingURL=messages.js.map