diff --git a/app/components/JoinForm.tsx b/app/components/JoinForm.tsx index 430ed95..eba012c 100644 --- a/app/components/JoinForm.tsx +++ b/app/components/JoinForm.tsx @@ -4,6 +4,7 @@ import { useHMSActions } from '@100mslive/react-sdk' import { useState, FormEvent } from 'react' import { useSearchParams } from 'next/navigation' import { ROLES } from './constants' +import { RiskyButCoolAPIKeyInput } from './RiskyButCoolAPIKeyInput' const JoinForm = () => { const [activeTabRole, setActiveTabRole] = useState(ROLES.TEACHER) @@ -111,6 +112,9 @@ const JoinForm = () => { onChange={(e) => setName(e.target.value)} /> + + + {roomCodeParam ? null : (
Join as
diff --git a/app/components/RiskyButCoolAPIKeyInput.tsx b/app/components/RiskyButCoolAPIKeyInput.tsx index cf0362e..5151a9a 100644 --- a/app/components/RiskyButCoolAPIKeyInput.tsx +++ b/app/components/RiskyButCoolAPIKeyInput.tsx @@ -1,13 +1,10 @@ -import { Icon, useBreakpoint } from '@tldraw/tldraw' import { ChangeEvent, useCallback } from 'react' +import { QuestionIcon } from '@100mslive/react-icons' export function RiskyButCoolAPIKeyInput() { - const breakpoint = useBreakpoint() - - // Store the API key locally, but ONLY in development mode const handleChange = useCallback((e: ChangeEvent) => { - if (process.env.NODE_ENV === 'development') { - localStorage.setItem('makeitreal_key', e.target.value) + if (typeof window !== 'undefined') { + sessionStorage.setItem('OPEN_AI_KEY', e.target.value) } }, []) @@ -18,19 +15,14 @@ export function RiskyButCoolAPIKeyInput() { }, []) return ( -
-
-
- -
+
+
+ Your OpenAI API Key
+
) } diff --git a/app/globals.css b/app/globals.css index a0ccbb9..bed2b01 100644 --- a/app/globals.css +++ b/app/globals.css @@ -167,7 +167,7 @@ h4 { } .input__wrapper:not(:focus-within)::after { - content: 'Your OpenAI API Key (risky but cool)'; + content: 'Enter your OpenAI API Key (risky but cool)'; display: block; position: absolute; inset: 0px; @@ -322,10 +322,11 @@ input::placeholder { } .input-label { + display: flex; font-size: 14px; font-weight: 500; margin-bottom: 5px; - align-items: start; + align-items: center; } .tabs-container { diff --git a/app/lib/fetchFromOpenAi.tsx b/app/lib/fetchFromOpenAi.tsx index 0e18a2e..4967ea6 100644 --- a/app/lib/fetchFromOpenAi.tsx +++ b/app/lib/fetchFromOpenAi.tsx @@ -1,9 +1,11 @@ 'use server' +import { toast } from 'react-toastify' + export async function fetchFromOpenAi( providedApiKey: string, body: GPT4VCompletionRequest -): Promise { +): Promise { const apiKey = providedApiKey ?? process.env.OPENAI_API_KEY if (!apiKey) { @@ -11,9 +13,8 @@ export async function fetchFromOpenAi( 'You need to provide an API key. Make sure OPENAI_API_KEY is set in your .env file.' ) } - try { - const repsonse = await fetch('https://api.openai.com/v1/chat/completions', { + const response = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -21,11 +22,15 @@ export async function fetchFromOpenAi( }, body: JSON.stringify(body), }) + const jsonData = await response.json() - return await repsonse.json() + if (jsonData.error) { + throw jsonData.error + } + return jsonData } catch (e) { console.error(e) - throw new Error('Sorry, there was an error fetching from OpenAI') + return e.message } } diff --git a/app/makeReal.tsx b/app/makeReal.tsx index 9d0f373..ccf3de3 100644 --- a/app/makeReal.tsx +++ b/app/makeReal.tsx @@ -7,6 +7,7 @@ import { MessageContent, fetchFromOpenAi, } from './lib/fetchFromOpenAi' +import { toast } from 'react-toastify' const SYSTEM_PROMPT = `You are an expert at constructing interative polls and quizzes for audiences. Your job is to accept a design and turn it into a poll with multiple options for attendees to vote on to make a session more interative. @@ -38,13 +39,11 @@ export async function makeReal( // If you're using the API key input, we preference the key from there. // It's okay if this is undefined—it will just mean that we'll use the // one in the .env file instead. - const apiKeyFromDangerousApiKeyInput = ( - document.body.querySelector('#openai_key_risky_but_cool') as HTMLInputElement - )?.value + const apiKeyFromDangerousApiKeyInput = sessionStorage.getItem('OPEN_AI_KEY') // make a request to openai. `fetchFromOpenAi` is a next.js server action, // so our api key is hidden. - const openAiResponse: GPT4VCompletionResponse = await fetchFromOpenAi( + const openAiResponse: GPT4VCompletionResponse | string = await fetchFromOpenAi( apiKeyFromDangerousApiKeyInput, { model: 'gpt-4-vision-preview', @@ -53,6 +52,9 @@ export async function makeReal( messages: prompt, } ) + if (typeof openAiResponse === 'string') { + throw openAiResponse + } if ('choices' in openAiResponse) { const messageContent = openAiResponse.choices[0].message.content @@ -62,7 +64,7 @@ export async function makeReal( } catch (e) { // if something went wrong, get rid of the unnecessary response shape // editor.deleteShape(responseShapeId) - throw e + toast.error(e) } }