diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 450ae72..0024ea4 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -7,16 +7,6 @@ import { nanoid } from '@/lib/utils' export const runtime = 'edge' -const configuration = new Configuration({ - apiKey: process.env.OPENAI_API_KEY -}) - -const openai = new OpenAIApi(configuration) - -if (!process.env.OPENAI_API_KEY) { - throw new Error('Missing env var from OpenAI') -} - export async function POST(req: Request) { const session = await auth() if (session == null) { @@ -24,7 +14,13 @@ export async function POST(req: Request) { } const json = await req.json() - const { messages } = json + const { messages, previewToken } = json + + const configuration = new Configuration({ + apiKey: previewToken || process.env.OPENAI_API_KEY + }) + + const openai = new OpenAIApi(configuration) const res = await openai.createChatCompletion({ model: 'gpt-3.5-turbo', diff --git a/components/chat.tsx b/components/chat.tsx index 165a77b..496e1bc 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -7,22 +7,44 @@ import { ChatList } from '@/components/chat-list' import { ChatPanel } from '@/components/chat-panel' import { EmptyScreen } from '@/components/empty-screen' import { ChatScrollAnchor } from '@/components/chat-scroll-anchor' +import { useLocalStorage } from '@/lib/hooks/use-local-storage' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog' +import { useState } from 'react' +import { Button } from './ui/button' +import { Input } from './ui/input' +const IS_PREVIEW = true || process.env.VERCEL_ENV === 'preview' export interface ChatProps extends React.ComponentProps<'div'> { initialMessages?: Message[] id?: string } export function Chat({ id, initialMessages, className }: ChatProps) { + const [previewToken, setPreviewToken] = useLocalStorage( + 'ai-token', + null + ) + const [previewTokenDialog, setPreviewTokenDialog] = useState( + IS_PREVIEW && previewToken == null + ) + const [previewTokenInput, setPreviewTokenInput] = useState(previewToken ?? '') const { messages, append, reload, stop, isLoading, input, setInput } = useChat({ initialMessages, id, body: { - id + id, + previewToken } }) - + console.log(previewToken) return ( <>
@@ -45,6 +67,43 @@ export function Chat({ id, initialMessages, className }: ChatProps) { input={input} setInput={setInput} /> + {IS_PREVIEW && previewToken == null && ( + + + + Enter your OpenAI Key + + If you have not obtained your OpenAI API key, you can do so by{' '} + + signing up + {' '} + on the OpenAI website. This is only necessary for preview + environments so that the open source community can test the app. + The token will be saved to your browser's local storage + under the name ai-token. + + + setPreviewTokenInput(e.target.value)} + /> + + + + + + )} ) } diff --git a/lib/hooks/use-local-storage.ts b/lib/hooks/use-local-storage.ts new file mode 100644 index 0000000..19f6b7e --- /dev/null +++ b/lib/hooks/use-local-storage.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' + +export const useLocalStorage = ( + key: string, + initialValue: T +): [T, (value: T) => void] => { + const [storedValue, setStoredValue] = useState(initialValue) + + useEffect(() => { + // Retrieve from localStorage + const item = window.localStorage.getItem(key) + if (item) { + setStoredValue(JSON.parse(item)) + } + }, [key]) + + const setValue = (value: T) => { + // Save state + setStoredValue(value) + // Save to localStorage + window.localStorage.setItem(key, JSON.stringify(value)) + } + return [storedValue, setValue] +}