From 2e2e7eb053e860ab7d19869d5129b0626f4a301b Mon Sep 17 00:00:00 2001 From: Daniel Whiffing Date: Fri, 13 Sep 2024 14:37:07 -0400 Subject: [PATCH 1/4] Changes chat settings to modal --- app/page.tsx | 23 ++++---- components/ChatSettings.tsx | 106 +++++++++++++++++++++--------------- components/ChatWindow.tsx | 16 +++--- 3 files changed, 81 insertions(+), 64 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index 34827be..ab60e28 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -16,14 +16,9 @@ export default function Page() { const { contracts } = useContracts(); const [editContractKey, setEditContractKey] = useState(null); const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); - const { - magic, - teeWalletAddress, - isLoggedIn, - handleLogin, - handleLogout, - isLoading, - } = useMagic(); + const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false); + const { teeWalletAddress, isLoggedIn, handleLogin, handleLogout, isLoading } = + useMagic(); return (
@@ -37,7 +32,7 @@ export default function Page() { {/* Comment to hide side nav */} {process.env.NODE_ENV === "development" && (
-
+
Uploaded Contracts
@@ -71,8 +66,9 @@ export default function Page() { TEE Wallet: {teeWalletAddress}

)} - - + setIsSettingsModalOpen(false)} + />
diff --git a/components/ChatSettings.tsx b/components/ChatSettings.tsx index 4d9ad82..335c735 100644 --- a/components/ChatSettings.tsx +++ b/components/ChatSettings.tsx @@ -13,7 +13,18 @@ import { Checkbox } from "./ui/checkbox"; import { MODELS } from "@/constants"; import { findInferenceByModelName } from "@/utils/utils"; +import { Button } from "./ui/button"; +import { + Dialog, + DialogContent, + DialogTitle, + DialogHeader, + DialogFooter, +} from "./ui/dialog"; + type IChatSettingProps = { + isOpen: boolean; + onClose: () => void; clearOnChange: boolean; onClearOnChange: (value: boolean) => void; modelName: string; @@ -32,59 +43,68 @@ export function ChatSettings(props: IChatSettingProps) { }; return ( -
-

Settings

-
-
- - -
- {inferenceProvider && ( + + + + Settings + + +
- - - + - {MODELS[inferenceProvider].map((modelName) => ( - - {modelName} + {Object.keys(MODELS).map((i) => ( + + {i} ))}
- )} + {inferenceProvider && ( +
+ + +
+ )} + +
+ + +
-
- - + + +
-
-
+ + ); } diff --git a/components/ChatWindow.tsx b/components/ChatWindow.tsx index 5e57bae..283d3b6 100644 --- a/components/ChatWindow.tsx +++ b/components/ChatWindow.tsx @@ -5,13 +5,7 @@ import { useChat } from "ai/react"; import { useEffect, useRef, useState, type FormEvent } from "react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; -import { - Card, - CardHeader, - CardContent, - CardFooter, - CardTitle, -} from "@/components/ui/card"; +import { Card, CardContent, CardFooter } from "@/components/ui/card"; import { ChatMessageBubble } from "@/components/ChatMessageBubble"; import { LoadingIcon } from "@/components/LoadingIcon"; import { Label } from "@/components/ui/label"; @@ -21,8 +15,10 @@ import { useContracts } from "@/utils/useContracts"; import { ChatSettings } from "./ChatSettings"; import { MODELS } from "@/constants"; -export function ChatWindow(props: { titleText?: string }) { - const { titleText } = props; +export function ChatWindow(props: { + isSettingsOpen: boolean; + onCloseSettings: () => void; +}) { const chatContainerRef = useRef(null); const { disabledKeys } = useContracts(); const [modelName, setModelName] = useState(MODELS["openai"][0]); @@ -157,6 +153,8 @@ export function ChatWindow(props: { titleText?: string }) { Date: Fri, 13 Sep 2024 15:01:18 -0400 Subject: [PATCH 2/4] Adds ChatContext --- app/layout.tsx | 11 +-- app/page.tsx | 11 +-- components/ChatProvider.tsx | 69 +++++++++++++++++++ ...ChatSettings.tsx => ChatSettingsModal.tsx} | 28 +++++--- components/ChatWindow.tsx | 46 ++----------- 5 files changed, 107 insertions(+), 58 deletions(-) create mode 100644 components/ChatProvider.tsx rename components/{ChatSettings.tsx => ChatSettingsModal.tsx} (85%) diff --git a/app/layout.tsx b/app/layout.tsx index c24dc17..d776f1d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,5 @@ import MagicProvider from "@/components/MagicProvider"; +import ChatProvider from "@/components/ChatProvider"; import { Toaster } from "@/components/ui/sonner"; import "./globals.css"; @@ -24,10 +25,12 @@ export default function RootLayout({ -
- {children} -
- + +
+ {children} +
+ +
diff --git a/app/page.tsx b/app/page.tsx index ab60e28..d4c19fd 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -11,6 +11,7 @@ import { useContracts } from "@/utils/useContracts"; import { ScrollArea } from "@/components/ui/scroll-area"; import { EditContractModal } from "@/components/EditContractModal"; import { ConfirmAlert } from "@/components/ConfirmAlert"; +import { ChatSettingsModal } from "@/components/ChatSettingsModal"; export default function Page() { const { contracts } = useContracts(); @@ -78,13 +79,15 @@ export default function Page() {
- setIsSettingsModalOpen(false)} - /> +
+ setIsSettingsModalOpen(false)} + /> + setEditContractKey(null)} diff --git a/components/ChatProvider.tsx b/components/ChatProvider.tsx new file mode 100644 index 0000000..5468469 --- /dev/null +++ b/components/ChatProvider.tsx @@ -0,0 +1,69 @@ +"use client"; + +import { createContext, useContext, useState } from "react"; +import { UseChatHelpers, UseChatOptions, useChat as useAiChat } from "ai/react"; +import { MODELS } from "@/constants"; +import { useContracts } from "@/utils/useContracts"; +import { toast } from "sonner"; + +export const ChatContext = createContext< + Pick< + UseChatOptions & UseChatHelpers, + "messages" | "handleInputChange" | "handleSubmit" | "isLoading" | "input" + > & { + modelName: string; + clearOnChange: boolean; + onClearMessages: () => void; + setModelName: (name: string) => void; + setClearOnChange: (v: boolean) => void; + } +>({ + messages: [], + handleInputChange: () => {}, + handleSubmit: () => {}, + isLoading: false, + input: "", + modelName: "", + clearOnChange: false, + onClearMessages: () => {}, + setModelName: () => {}, + setClearOnChange: () => {}, +}); + +export const useChat = () => useContext(ChatContext); + +const ChatProvider = ({ children }: any) => { + const { disabledKeys } = useContracts(); + const [modelName, setModelName] = useState(MODELS["openai"][0]); + const [clearOnChange, setClearOnChange] = useState(false); + + const chatContext = useAiChat({ + api: "api/chat", + body: { disabledContractKeys: disabledKeys, modelName }, + streamProtocol: "text", + onError: (e) => { + toast(e.message); + }, + }); + + const onClearMessages = () => { + chatContext.setMessages([]); + }; + + return ( + + {children} + + ); +}; + +export default ChatProvider; diff --git a/components/ChatSettings.tsx b/components/ChatSettingsModal.tsx similarity index 85% rename from components/ChatSettings.tsx rename to components/ChatSettingsModal.tsx index 335c735..569808a 100644 --- a/components/ChatSettings.tsx +++ b/components/ChatSettingsModal.tsx @@ -21,19 +21,29 @@ import { DialogHeader, DialogFooter, } from "./ui/dialog"; +import { useChat } from "./ChatProvider"; type IChatSettingProps = { isOpen: boolean; onClose: () => void; - clearOnChange: boolean; - onClearOnChange: (value: boolean) => void; - modelName: string; - onModelNameChange: (value: string) => void; }; -export function ChatSettings(props: IChatSettingProps) { - const { modelName, onModelNameChange, clearOnChange, onClearOnChange } = - props; +export function ChatSettingsModal(props: IChatSettingProps) { + const { + modelName, + setModelName, + onClearMessages, + clearOnChange, + setClearOnChange, + } = useChat(); + + const onSetModelName = (value: string) => { + if (clearOnChange) { + onClearMessages(); + } + setModelName(value); + }; + const [inferenceProvider, setInferenceProvider] = useState(() => { return findInferenceByModelName(modelName); }); @@ -71,7 +81,7 @@ export function ChatSettings(props: IChatSettingProps) { {inferenceProvider && (
- @@ -90,7 +100,7 @@ export function ChatSettings(props: IChatSettingProps) {