diff --git a/src/components/modals/SettingsModal.tsx b/src/components/modals/SettingsModal.tsx index 530fd83..1ea1e57 100644 --- a/src/components/modals/SettingsModal.tsx +++ b/src/components/modals/SettingsModal.tsx @@ -1,6 +1,7 @@ import { MIXPANEL_TOKEN } from "../../main"; +import { checkModelAccess } from "../../utils/apikey"; import { getFluxNodeTypeDarkColor } from "../../utils/color"; -import { DEFAULT_SETTINGS, SUPPORTED_MODELS } from "../../utils/constants"; +import { DEFAULT_SETTINGS, SUPPORTED_MODELS, TOAST_CONFIG } from "../../utils/constants"; import { Settings, FluxNodeType } from "../../utils/types"; import { APIKeyInput } from "../utils/APIKeyInput"; import { LabeledSelect, LabeledSlider } from "../utils/LabeledInputs"; @@ -15,6 +16,7 @@ import { ModalHeader, ModalOverlay, Checkbox, + useToast, } from "@chakra-ui/react"; import mixpanel from "mixpanel-browser"; import { ChangeEvent, memo } from "react"; @@ -34,6 +36,8 @@ export const SettingsModal = memo(function SettingsModal({ apiKey: string | null; setApiKey: (apiKey: string) => void; }) { + const toast = useToast(); + const reset = () => { if ( confirm( @@ -68,6 +72,29 @@ export const SettingsModal = memo(function SettingsModal({ } }; + const handleChangeModel = async (v: string) => { + if (await checkModelAccess(v)) { + setSettings({ ...settings, model: v }); + } else { + let errorText = ""; + if (v === "gpt-4") { + errorText = "You don't have access to GPT-4, sign up for the waitlist at https://openai.com/waitlist/gpt-4-api"; + } else if (v === "gpt-4-32k") { + errorText = "You don't have access to GPT-4 32k."; + } else { + errorText = "Something went wrong."; + } + + toast({ + title: errorText, + status: "error", + ...TOAST_CONFIG, + }); + } + + if (MIXPANEL_TOKEN) mixpanel.track("Changed model"); + }; + return ( <Modal isOpen={isOpen} onClose={onClose} size="2xl"> <ModalOverlay /> @@ -79,11 +106,7 @@ export const SettingsModal = memo(function SettingsModal({ label="Model" value={settings.model} options={SUPPORTED_MODELS} - setValue={(v: string) => { - setSettings({ ...settings, model: v }); - - if (MIXPANEL_TOKEN) mixpanel.track("Changed model"); - }} + setValue={handleChangeModel} /> <APIKeyInput mt={4} width="100%" apiKey={apiKey} setApiKey={setApiKey} /> @@ -145,4 +168,4 @@ export const SettingsModal = memo(function SettingsModal({ </ModalContent> </Modal> ); -}); +}); \ No newline at end of file diff --git a/src/utils/apikey.ts b/src/utils/apikey.ts index addf041..d5b60c9 100644 --- a/src/utils/apikey.ts +++ b/src/utils/apikey.ts @@ -1,3 +1,29 @@ +import { API_KEY_LOCAL_STORAGE_KEY } from "./constants"; + export function isValidAPIKey(apiKey: string | null) { return apiKey?.length == 51 && apiKey?.startsWith("sk-"); } + +export async function checkModelAccess(model: string): Promise<boolean> { + try { + const response = await fetch("https://api.openai.com/v1/models", { + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${API_KEY_LOCAL_STORAGE_KEY}`, + }, + }); + + if (response.ok) { + const data = await response.json(); + const models = data.data; + return models.some((m: { id: string }) => m.id === model); + } else { + console.error("Error fetching models:", response.status); + return false; + } + } catch (error) { + console.error("Error fetching models:", error); + return false; + } +} \ No newline at end of file