diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/app/chat/page.tsx b/app/chat/page.tsx new file mode 100644 index 0000000..345b630 --- /dev/null +++ b/app/chat/page.tsx @@ -0,0 +1,208 @@ +'use client'; + +import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { MessageSquare, Settings, Server, Moon, Sun, PanelLeftClose, PanelLeftOpen } from "lucide-react"; +import { ChatInput } from "@/components/chat/chat-input"; +import { ChatMessage } from "@/components/chat/chat-message"; +import { SystemPanel } from "@/components/chat/system-panel"; +import { PromptGeneratorDialog } from "@/components/chat/prompt-generator"; +import { useChat } from "@/hooks/use-chat"; +import { useLocalModels } from "@/hooks/use-local-models"; +import { useState, useEffect, useRef } from "react"; +import { useTheme } from "next-themes"; +import { ImperativePanelHandle } from "react-resizable-panels"; + +export default function ChatPage() { + const { messages, sendMessage, isLoading, stop } = useChat(); + const { models } = useLocalModels(); + const { theme, setTheme } = useTheme(); + + const [selectedModel, setSelectedModel] = useState(""); + const [systemPrompt, setSystemPrompt] = useState("Você é um assistente útil e prestativo."); + const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); + + const sidebarRef = useRef(null); + + // Auto-select first model + useEffect(() => { + if (models.length > 0 && !selectedModel) { + setSelectedModel(models[0].name); + } + }, [models, selectedModel]); + + const handleSend = (content: string) => { + if (!selectedModel) return; + sendMessage(content, selectedModel, systemPrompt); + }; + + const toggleSidebar = () => { + const panel = sidebarRef.current; + if (panel) { + if (isSidebarCollapsed) { + panel.expand(); + } else { + panel.collapse(); + } + } + }; + + return ( +
+ {/* Left Sidebar (Nav) */} + + + setIsSidebarCollapsed(true)} + onExpand={() => setIsSidebarCollapsed(false)} + className="border-r flex flex-col items-center py-4 gap-4 bg-muted/20 min-w-[60px]" + > + + +
+ + + + + + + {/* Main Chat Area */} + +
+ {/* Header */} +
+
+ {isSidebarCollapsed && ( + + )} + {!isSidebarCollapsed && ( + + )} +
Chat
+
+ +
+ +
+
+ + {/* Messages */} +
+ {messages.length === 0 ? ( +
+
+ +
+

Inicie uma conversa com {selectedModel}

+
+ ) : ( +
+ {messages.map((msg, i) => ( + + ))} + {isLoading && ( +
+ Gerando resposta... +
+ )} +
+ )} +
+ + {/* Input */} + +
+
+ + + + {/* Right Sidebar (Settings & Monitor) */} + + +
+ + + Parâmetros + + + Sistema + + +
+ + +
+
+ + +
+