diff --git a/app/chat/page.tsx b/app/chat/page.tsx index 345b630..50cbfe3 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -15,6 +15,8 @@ import { useLocalModels } from "@/hooks/use-local-models"; import { useState, useEffect, useRef } from "react"; import { useTheme } from "next-themes"; import { ImperativePanelHandle } from "react-resizable-panels"; +// @ts-ignore +import defaultFormatPrompt from "@/data/prompts/default-format.md"; export default function ChatPage() { const { messages, sendMessage, isLoading, stop } = useChat(); @@ -22,7 +24,8 @@ export default function ChatPage() { const { theme, setTheme } = useTheme(); const [selectedModel, setSelectedModel] = useState(""); - const [systemPrompt, setSystemPrompt] = useState("Você é um assistente útil e prestativo."); + // Initialize with default format prompt + const [systemPrompt, setSystemPrompt] = useState(defaultFormatPrompt || "Você é um assistente útil e prestativo."); const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); const sidebarRef = useRef(null); diff --git a/components/chat/chat-message.tsx b/components/chat/chat-message.tsx index 2eff8b3..82b085f 100644 --- a/components/chat/chat-message.tsx +++ b/components/chat/chat-message.tsx @@ -3,13 +3,15 @@ import remarkGfm from 'remark-gfm'; import { cn } from "@/lib/utils"; import { Message } from "@/hooks/use-chat"; import { Bot, User } from "lucide-react"; +import { markdownRenderers } from "./markdown-renderers"; +import { MessageActions } from "./message-actions"; export function ChatMessage({ message }: { message: Message }) { const isUser = message.role === 'user'; return (
@@ -20,14 +22,23 @@ export function ChatMessage({ message }: { message: Message }) { {isUser ? : }
-
+
- + {message.content}
+ + {/* Actions Toolbar - Absolute positioned or flex end */} + {!isUser && ( +
+ +
+ )}
); } - diff --git a/components/chat/code-block.tsx b/components/chat/code-block.tsx new file mode 100644 index 0000000..8456cb7 --- /dev/null +++ b/components/chat/code-block.tsx @@ -0,0 +1,45 @@ +import { Check, Copy } from "lucide-react"; +import { useState } from "react"; +import { Button } from "@/components/ui/button"; + +interface CodeBlockProps { + language: string; + children: string; +} + +export function CodeBlock({ language, children }: CodeBlockProps) { + const [copied, setCopied] = useState(false); + + const handleCopy = () => { + navigator.clipboard.writeText(children); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+
+ + {language || "text"} + + +
+
+ {children} +
+
+ ); +} + diff --git a/components/chat/markdown-renderers.tsx b/components/chat/markdown-renderers.tsx new file mode 100644 index 0000000..622f2f1 --- /dev/null +++ b/components/chat/markdown-renderers.tsx @@ -0,0 +1,138 @@ +import { Components } from "react-markdown"; +import { CodeBlock } from "./code-block"; +import { cn } from "@/lib/utils"; + +export const markdownRenderers: Components = { + h1: ({ className, ...props }) => ( +

+ ), + h2: ({ className, ...props }) => ( +

+ ), + h3: ({ className, ...props }) => ( +

+ ), + h4: ({ className, ...props }) => ( +

+ ), + p: ({ className, ...props }) => ( +

+ ), + ul: ({ className, ...props }) => ( +