diff --git a/src/@types/parseable/api/about.ts b/src/@types/parseable/api/about.ts index c83321a7..560ded50 100644 --- a/src/@types/parseable/api/about.ts +++ b/src/@types/parseable/api/about.ts @@ -1,11 +1,13 @@ -export type AboutData ={ - commit : string; - deploymentId : string; - latestVersion : string; - license : string; - mode : string; - staging : string; - store : string; - updateAvailable : boolean; - version : string; -} \ No newline at end of file +export type AboutData = { + commit: string; + deploymentId: string; + latestVersion: string; + license: string; + mode: string; + staging: string; + store: string; + updateAvailable: boolean; + version: string; + llmActive: boolean; + llmProvider: string; +}; diff --git a/src/api/constants.ts b/src/api/constants.ts index 75aa334b..07abda2a 100644 --- a/src/api/constants.ts +++ b/src/api/constants.ts @@ -20,3 +20,4 @@ export const USER_PASSWORD_URL = (username: string) => `${USER_URL(username)}/ge // LLM queries export const LLM_QUERY_URL = `${API_V1}/llm`; +export const IS_LLM_ACTIVE_URL = `${LLM_QUERY_URL}/isactive`; diff --git a/src/components/Navbar/infoModal.tsx b/src/components/Navbar/infoModal.tsx index 7939e024..ae555a98 100644 --- a/src/components/Navbar/infoModal.tsx +++ b/src/components/Navbar/infoModal.tsx @@ -1,5 +1,5 @@ import { Box, Button, Modal, Text, Tooltip, px } from '@mantine/core'; -import { FC, useEffect } from 'react'; +import { FC, useEffect, useMemo } from 'react'; import { useInfoModalStyles } from './styles'; import { useGetAbout } from '@/hooks/useGetAbout'; import { IconAlertCircle, IconBook2, IconBrandGithub, IconBrandSlack, IconBusinessplan } from '@tabler/icons-react'; @@ -69,6 +69,14 @@ const InfoModal: FC = (props) => { }; }, []); + const llmStatus = useMemo(() => { + let status = 'LLM API Key not set'; + if (data?.llmActive) { + status = `${data.llmProvider} configured`; + } + return status; + }, [data?.llmActive]); + const { classes } = useInfoModalStyles(); const { container, @@ -80,96 +88,91 @@ const InfoModal: FC = (props) => { aboutTextKey, aboutTextValue, aboutTextInnerBox, - actionBtnRed + actionBtnRed, } = classes; return ( - + - - About Parseable - Important info about your Parseable deployment - {error ? ( - Error... - ) : loading ? ( - Loading... - ) : data ? ( - <> - - - License: - {data.license} - - - - - Commit: - {data.commit} - - - Version: - {data.version} - {data.updateAvailable ? ( - ): null} - - + + ) : null} - - - Deployment Id: - {data.deploymentId} - - - Mode - {data.mode} - - - Staging - {data.staging} - - - Store - {data.store} - + + + + Deployment Id: + {data.deploymentId} - - ) : null} - - Need help? - Ensure uninterrupted deployment + + Mode + {data.mode} + + + Staging + {data.staging} + + + Store + {data.store} + + + LLM Status + {llmStatus} + + + + ) : null} - - {helpResources.map((data) => ( - - ))} - + Need help? + Ensure uninterrupted deployment + + {helpResources.map((data) => ( + + ))} - + ); }; diff --git a/src/pages/Query/QueryCodeEditor.tsx b/src/pages/Query/QueryCodeEditor.tsx index 832aa3b4..a264eb04 100644 --- a/src/pages/Query/QueryCodeEditor.tsx +++ b/src/pages/Query/QueryCodeEditor.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect } from 'react'; +import React, { FC, useCallback, useEffect, useMemo } from 'react'; import Editor from '@monaco-editor/react'; import { useQueryPageContext } from './Context'; import { useHeaderContext } from '@/layouts/MainLayout/Context'; @@ -13,6 +13,7 @@ import dayjs from 'dayjs'; import { notify } from '@/utils/notification'; import { Axios } from '@/api/axios'; import { LLM_QUERY_URL } from '@/api/constants'; +import { useGetAbout } from '@/hooks/useGetAbout'; const QueryCodeEditor: FC = () => { const { @@ -30,13 +31,20 @@ const QueryCodeEditor: FC = () => { const [currentStreamName, setCurrentStreamName] = useMountedState(subLogQuery.get().streamName); const [query, setQuery] = useMountedState(''); const [aiQuery, setAiQuery] = useMountedState('Show all records'); + const { data: aboutData, getAbout } = useGetAbout(); + const isLlmActive = useMemo(() => aboutData?.llmActive, [aboutData?.llmActive]); - const handleAIGenerate = async () => { + const handleAIGenerate = useCallback(async () => { if (!aiQuery?.length) { notify({ message: 'Please enter a valid query' }); return; } - notify({ message: 'AI based SQL being generated.', title: 'Getting suggestions', autoClose: 3000, color: 'blue' }); + notify({ + message: 'AI based SQL being generated.', + title: 'Getting suggestions', + autoClose: 3000, + color: 'blue', + }); const resp = await Axios().post(LLM_QUERY_URL, { prompt: aiQuery, stream: currentStreamName }); if (resp.status !== 200) { @@ -51,7 +59,7 @@ const QueryCodeEditor: FC = () => { const warningMsg = '-- Parseable AI is experimental and may produce incorrect answers\n-- Always verify the generated SQL before executing\n\n'; setQuery(warningMsg + resp.data); - }; + }, [aiQuery]); const handleEditorChange = (code: any) => { setQuery(code); @@ -91,6 +99,7 @@ const QueryCodeEditor: FC = () => { if (subLogQuery.get().streamName) { setQuery(`SELECT * FROM ${subLogQuery.get().streamName} LIMIT 100 ; `); } + getAbout(); }, []); function handleEditorDidMount(editor: any, monaco: any) { @@ -176,6 +185,11 @@ const QueryCodeEditor: FC = () => { Query + {!isLlmActive ? ( + + Enable SQL generation with OpenAI + + ) : null} { - - setAiQuery(e.target.value)} - placeholder="Ask Parseable AI" - /> - - + {isLlmActive ? ( + + setAiQuery(e.target.value)} + placeholder="Ask Parseable AI" + /> + + + ) : null}