/** * @copyright nhcarrigan * @license Naomi's Public License * @author Naomi Carrigan */ import { MessageFlags, type ChatInputCommandInteraction } from "discord.js"; import { personality } from "../config/personality.js"; import { ai } from "../utils/ai.js"; import { calculateCost } from "../utils/calculateCost.js"; import { isSubscribed } from "../utils/isSubscribed.js"; import { logger } from "../utils/logger.js"; import { replyToError } from "../utils/replyToError.js"; /** * Accepts an arbitrary question from the user, then sends it to Anthropic * to be answered. * @param interaction -- The interaction payload from Discord. */ export const query = async( interaction: ChatInputCommandInteraction, ): Promise => { try { await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); const sub = await isSubscribed(interaction); if (!sub) { return; } const prompt = interaction.options.getString("prompt", true); const messages = await ai.messages.create({ // eslint-disable-next-line @typescript-eslint/naming-convention -- Required key format for SDK. max_tokens: 2000, messages: [ { content: prompt, role: "user" } ], model: "claude-3-5-sonnet-latest", system: `${personality} Your role in this conversation is to answer the user's question to the best of your abilities. When possible, include links to relevant sources.`, temperature: 1, }); const response = messages.content.find((message) => { return message.type === "text"; }); await interaction.editReply( response?.text ?? "I'm sorry, I don't have an answer for that. Please try again later.", ); const { usage } = messages; await calculateCost(usage, interaction.user.username, "query"); } catch (error) { await replyToError(interaction); if (error instanceof Error) { await logger.error("query command", error); } } };