"use client"; import { ActionButton } from "@/components/ui/action-button"; import { Form, FormControl, FormField, FormItem, FormMessage, } from "@/components/ui/form"; import { FullPageSpinner } from "@/components/ui/full-page-spinner"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { toast } from "@/components/ui/use-toast"; import { useClientConfig } from "@/lib/clientConfig"; import { useTranslation } from "@/lib/i18n/client"; import { api } from "@/lib/trpc"; import { zodResolver } from "@hookform/resolvers/zod"; import { Plus, Save, Trash2 } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { buildImagePrompt, buildSummaryPromptUntruncated, buildTextPromptUntruncated, } from "@karakeep/shared/prompts"; import { zNewPromptSchema, ZPrompt, zUpdatePromptSchema, } from "@karakeep/shared/types/prompts"; export function PromptEditor() { const { t } = useTranslation(); const apiUtils = api.useUtils(); const form = useForm>({ resolver: zodResolver(zNewPromptSchema), defaultValues: { text: "", appliesTo: "all_tagging", }, }); const { mutateAsync: createPrompt, isPending: isCreating } = api.prompts.create.useMutation({ onSuccess: () => { toast({ description: "Prompt has been created!", }); apiUtils.prompts.list.invalidate(); }, }); return (
{ await createPrompt(value); form.resetField("text"); })} > { return ( ); }} /> { return ( ); }} /> {t("actions.add")} ); } export function PromptRow({ prompt }: { prompt: ZPrompt }) { const { t } = useTranslation(); const apiUtils = api.useUtils(); const { mutateAsync: updatePrompt, isPending: isUpdating } = api.prompts.update.useMutation({ onSuccess: () => { toast({ description: "Prompt has been updated!", }); apiUtils.prompts.list.invalidate(); }, }); const { mutate: deletePrompt, isPending: isDeleting } = api.prompts.delete.useMutation({ onSuccess: () => { toast({ description: "Prompt has been deleted!", }); apiUtils.prompts.list.invalidate(); }, }); const form = useForm>({ resolver: zodResolver(zUpdatePromptSchema), defaultValues: { promptId: prompt.id, text: prompt.text, appliesTo: prompt.appliesTo, }, }); return (
{ await updatePrompt(value); })} > { return ( ); }} /> { return ( ); }} /> { return ( ); }} /> {t("actions.save")} deletePrompt({ promptId: prompt.id })} className="items-center" type="button" > {t("actions.delete")} ); } export function TaggingRules() { const { t } = useTranslation(); const { data: prompts, isLoading } = api.prompts.list.useQuery(); return (
{t("settings.ai.tagging_rules")}

{t("settings.ai.tagging_rule_description")}

{isLoading && } {prompts && prompts.length == 0 && (

You don't have any custom prompts yet.

)} {prompts && prompts.map((prompt) => )}
); } export function PromptDemo() { const { t } = useTranslation(); const { data: prompts } = api.prompts.list.useQuery(); const clientConfig = useClientConfig(); return (
{t("settings.ai.prompt_preview")}

{t("settings.ai.text_prompt")}

{buildTextPromptUntruncated( clientConfig.inference.inferredTagLang, (prompts ?? []) .filter( (p) => p.appliesTo == "text" || p.appliesTo == "all_tagging", ) .map((p) => p.text), "\n\n", ).trim()}

{t("settings.ai.images_prompt")}

{buildImagePrompt( clientConfig.inference.inferredTagLang, (prompts ?? []) .filter( (p) => p.appliesTo == "images" || p.appliesTo == "all_tagging", ) .map((p) => p.text), ).trim()}

{t("settings.ai.summarization_prompt")}

{buildSummaryPromptUntruncated( clientConfig.inference.inferredTagLang, (prompts ?? []) .filter((p) => p.appliesTo == "summary") .map((p) => p.text), "\n\n", ).trim()}
); } export default function AISettings() { const { t } = useTranslation(); return ( <>
{t("settings.ai.ai_settings")}
); }