"use client"; import { ActionBarPrimitive, AttachmentPrimitive, AuiIf, ComposerPrimitive, MessagePrimitive, ThreadPrimitive, useAuiState, } from "@assistant-ui/react"; import { ArrowUpIcon, CheckIcon, ChevronDownIcon, CopyIcon, EllipsisVertical, ImageIcon, Lightbulb, Mic, Paperclip, PencilIcon, PencilRuler, PlusIcon, RefreshCwIcon, Telescope, ThumbsDown, ThumbsUp, XIcon, } from "lucide-react"; import { type FC, useEffect, useState } from "react"; import { useShallow } from "zustand/shallow"; import { MarkdownText } from "@/components/assistant-ui/markdown-text"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; export const Gemini: FC = () => { return ( s.thread.messages.length === 0}>

How can I help you today?

s.thread.messages.length > 0}>

Gemini can make mistakes, so double-check it.

); }; const ghostBtnClass = "flex shrink-0 items-center justify-center rounded-full text-[#444746] transition-colors hover:bg-[#444746]/8 hover:text-[#1f1f1f] dark:text-[#c4c7c5] dark:hover:bg-[#c4c7c5]/10 dark:hover:text-[#e3e3e3]"; const Composer: FC = () => { return ( s.composer.attachments.length > 0}>
); }; const GEMINI_TOOLS = [ { id: "research", label: "Deep Research", Icon: Telescope }, { id: "canvas", label: "Canvas", Icon: PencilRuler }, { id: "image", label: "Create image", Icon: ImageIcon }, { id: "learn", label: "Guided Learning", Icon: Lightbulb }, ]; const GeminiPlusMenu: FC = () => { return ( }> Add photos & files {GEMINI_TOOLS.map(({ id, label, Icon }) => ( {label} ))} ); }; const GEMINI_MODELS = [ { id: "flash", name: "Flash", description: "Fast all-around help" }, { id: "thinking", name: "Thinking", description: "Reasoning, math & code", }, ]; const GeminiModelPicker: FC = () => { const [model, setModel] = useState(GEMINI_MODELS[0]!.id); const current = GEMINI_MODELS.find((m) => m.id === model); return ( {current?.name} {GEMINI_MODELS.map((m) => ( setModel(m.id)} className="items-start gap-3" > {m.id === model ? : null} {m.name} {m.description} ))} ); }; const sendBtnClass = "flex size-9 shrink-0 items-center justify-center rounded-full bg-[#1f3b9b] text-white transition-colors hover:bg-[#274aad]"; const GeminiSendButton: FC = () => { return ( <> !s.thread.isRunning && !s.composer.isEmpty}> s.thread.isRunning}> ); }; const actionBtnClass = "flex size-8 items-center justify-center rounded-full text-[#444746] transition-colors hover:bg-[#444746]/8 hover:text-[#1f1f1f] dark:text-[#c4c7c5] dark:hover:bg-[#c4c7c5]/10 dark:hover:text-[#e3e3e3]"; const ChatMessage: FC = () => { return ( s.message.role === "user"}>
s.message.role === "assistant"}>
s.message.isCopied}> !s.message.isCopied}>
); }; const useFileSrc = (file: File | undefined) => { const [src, setSrc] = useState(undefined); useEffect(() => { if (!file) { setSrc(undefined); return; } const objectUrl = URL.createObjectURL(file); setSrc(objectUrl); return () => { URL.revokeObjectURL(objectUrl); }; }, [file]); return src; }; const useAttachmentSrc = () => { const { file, src } = useAuiState( useShallow(({ attachment }): { file?: File; src?: string } => { if (attachment.type !== "image") return {}; if (attachment.file) return { file: attachment.file }; const src = attachment.content?.filter((c) => c.type === "image")[0] ?.image; if (!src) return {}; return { src }; }), ); return useFileSrc(file) ?? src; }; const GeminiAttachment: FC = () => { const isImage = useAuiState(({ attachment }) => attachment.type === "image"); const src = useAttachmentSrc(); return (
{isImage && src ? ( Attachment ) : (
)}
); };