/** * The AI actions of the editor spend the site's credits: what one costs * against what is left, and the question asked before one runs a second * time on the same page the same day. */ /** The actions the server notes against a post when they went through. */ export type AiAction = 'fix' | 'rewrite' | 'links' | 'faq' | 'catalog'; const NAMES: Record = { fix: 'Fix with AI', rewrite: 'the content rewrite', links: 'the internal link suggestions', faq: 'the FAQ', catalog: 'Fix title & description', }; /** * The question to answer before running an action again, or null when it * has not run on this page today. * * @param action - What is about to run. * @param ranToday - The actions that already spent credits on the page today. * @param credits - What this run costs. * @param kind - The page's type, as the panel names it: "post", "product". * @return The question, or null. */ export const repeatQuestion = ( action: AiAction, ranToday: readonly string[], credits: number, kind: string ): string | null => ranToday.includes(action) ? `You ran ${NAMES[action]} on this ${kind.toLowerCase()} today. Running it again costs ${credits} credits more. Run it again?` : null; /** * What is left, said after the price: nothing while the balance is unknown. * * @param balance - Credits left, when Recomaze said. * @param cost - What the run costs. * @return " You have 245 credits.", or a warning when they do not cover it. */ export const balanceNote = ( balance: number | null | undefined, cost: number ): string => { if (balance === null || balance === undefined) { return ''; } return balance < cost ? ` You have ${balance}, not enough for this run.` : ` You have ${balance} credits.`; };