From 5291d18f38fc046b12ac0d73fa615e0306201968 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 19 Feb 2024 01:31:38 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=80=20fix:=20Endpoint=20Type=20Mismatc?= =?UTF-8?q?h=20when=20Switching=20Conversations=20(#1834)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(useUpdateUserKeysMutation): only invalidate the endpoint whose key is being updated by user * fix(assistants): await `getUserKeyExpiry` call * chore: fix spinner loading color * refactor(initializeClient): make known which endpoint api Key is missing * fix: prevent an `endpointType` mismatch by making it impossible to assign when the `endpointsConfig` doesn't have a `type` defined, also prefer `getQueryData` call to useQuery in useChatHelpers --- .../services/Endpoints/assistant/initializeClient.js | 7 +++++-- .../services/Endpoints/gptPlugins/initializeClient.js | 2 +- .../Endpoints/gptPlugins/initializeClient.spec.js | 7 ++++--- api/server/services/Endpoints/openAI/initializeClient.js | 2 +- .../services/Endpoints/openAI/initializeClient.spec.js | 7 ++++--- client/src/components/svg/Spinner.tsx | 2 +- client/src/hooks/useChatHelpers.ts | 9 ++++++--- client/src/hooks/useNewConvo.ts | 2 ++ client/src/routes/ChatRoute.tsx | 2 +- .../data-provider/src/react-query/react-query-service.ts | 6 +++--- 10 files changed, 28 insertions(+), 18 deletions(-) diff --git a/api/server/services/Endpoints/assistant/initializeClient.js b/api/server/services/Endpoints/assistant/initializeClient.js index 886a037ad1..3ffba002cc 100644 --- a/api/server/services/Endpoints/assistant/initializeClient.js +++ b/api/server/services/Endpoints/assistant/initializeClient.js @@ -32,7 +32,10 @@ const initializeClient = async ({ req, res, endpointOption, initAppClient = fals let userKey = null; if (isUserProvided) { - const expiresAt = getUserKeyExpiry({ userId: req.user.id, name: EModelEndpoint.assistants }); + const expiresAt = await getUserKeyExpiry({ + userId: req.user.id, + name: EModelEndpoint.assistants, + }); checkUserKeyExpiry( expiresAt, 'Your Assistants API key has expired. Please provide your API key again.', @@ -43,7 +46,7 @@ const initializeClient = async ({ req, res, endpointOption, initAppClient = fals let apiKey = isUserProvided ? userKey : credentials; if (!apiKey) { - throw new Error('API key not provided.'); + throw new Error(`${EModelEndpoint.assistants} API key not provided.`); } /** @type {OpenAIClient} */ diff --git a/api/server/services/Endpoints/gptPlugins/initializeClient.js b/api/server/services/Endpoints/gptPlugins/initializeClient.js index cf15c66723..b667b2c0be 100644 --- a/api/server/services/Endpoints/gptPlugins/initializeClient.js +++ b/api/server/services/Endpoints/gptPlugins/initializeClient.js @@ -66,7 +66,7 @@ const initializeClient = async ({ req, res, endpointOption }) => { } if (!apiKey) { - throw new Error('API key not provided.'); + throw new Error(`${endpoint} API key not provided.`); } const client = new PluginsClient(apiKey, clientOptions); diff --git a/api/server/services/Endpoints/gptPlugins/initializeClient.spec.js b/api/server/services/Endpoints/gptPlugins/initializeClient.spec.js index 5b772209c6..f3e7c89e30 100644 --- a/api/server/services/Endpoints/gptPlugins/initializeClient.spec.js +++ b/api/server/services/Endpoints/gptPlugins/initializeClient.spec.js @@ -1,7 +1,8 @@ // gptPlugins/initializeClient.spec.js -const { PluginsClient } = require('~/app'); +const { EModelEndpoint } = require('librechat-data-provider'); +const { getUserKey } = require('~/server/services/UserService'); const initializeClient = require('./initializeClient'); -const { getUserKey } = require('../../UserService'); +const { PluginsClient } = require('~/app'); // Mock getUserKey since it's the only function we want to mock jest.mock('~/server/services/UserService', () => ({ @@ -112,7 +113,7 @@ describe('gptPlugins/initializeClient', () => { const endpointOption = { modelOptions: { model: 'default-model' } }; await expect(initializeClient({ req, res, endpointOption })).rejects.toThrow( - 'API key not provided.', + `${EModelEndpoint.openAI} API key not provided.`, ); }); diff --git a/api/server/services/Endpoints/openAI/initializeClient.js b/api/server/services/Endpoints/openAI/initializeClient.js index b6427823e1..329749bdd6 100644 --- a/api/server/services/Endpoints/openAI/initializeClient.js +++ b/api/server/services/Endpoints/openAI/initializeClient.js @@ -58,7 +58,7 @@ const initializeClient = async ({ req, res, endpointOption }) => { } if (!apiKey) { - throw new Error('API key not provided.'); + throw new Error(`${endpoint} API key not provided.`); } const client = new OpenAIClient(apiKey, clientOptions); diff --git a/api/server/services/Endpoints/openAI/initializeClient.spec.js b/api/server/services/Endpoints/openAI/initializeClient.spec.js index 03f5677441..792b73c664 100644 --- a/api/server/services/Endpoints/openAI/initializeClient.spec.js +++ b/api/server/services/Endpoints/openAI/initializeClient.spec.js @@ -1,6 +1,7 @@ -const { OpenAIClient } = require('~/app'); -const initializeClient = require('./initializeClient'); +const { EModelEndpoint } = require('librechat-data-provider'); const { getUserKey } = require('~/server/services/UserService'); +const initializeClient = require('./initializeClient'); +const { OpenAIClient } = require('~/app'); // Mock getUserKey since it's the only function we want to mock jest.mock('~/server/services/UserService', () => ({ @@ -145,7 +146,7 @@ describe('initializeClient', () => { const endpointOption = {}; await expect(initializeClient({ req, res, endpointOption })).rejects.toThrow( - 'API key not provided.', + `${EModelEndpoint.openAI} API key not provided.`, ); }); diff --git a/client/src/components/svg/Spinner.tsx b/client/src/components/svg/Spinner.tsx index 32d05e8423..b32904224f 100644 --- a/client/src/components/svg/Spinner.tsx +++ b/client/src/components/svg/Spinner.tsx @@ -3,7 +3,7 @@ import { cn } from '~/utils/'; export default function Spinner({ className = 'm-auto', size = '1em' }) { return ( ([QueryKeys.endpoints]); + const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); + // set the endpoint option const convo = parseCompactConvo({ endpoint, diff --git a/client/src/hooks/useNewConvo.ts b/client/src/hooks/useNewConvo.ts index a7c12c21c8..58c11f1225 100644 --- a/client/src/hooks/useNewConvo.ts +++ b/client/src/hooks/useNewConvo.ts @@ -77,6 +77,8 @@ const useNewConvo = (index = 0) => { const endpointType = getEndpointField(endpointsConfig, defaultEndpoint, 'type'); if (!conversation.endpointType && endpointType) { conversation.endpointType = endpointType; + } else if (conversation.endpointType && !endpointType) { + conversation.endpointType = undefined; } if (!conversation.assistant_id && defaultEndpoint === EModelEndpoint.assistants) { diff --git a/client/src/routes/ChatRoute.tsx b/client/src/routes/ChatRoute.tsx index 39baa8170f..dd00ef134c 100644 --- a/client/src/routes/ChatRoute.tsx +++ b/client/src/routes/ChatRoute.tsx @@ -67,7 +67,7 @@ export default function ChatRoute() { }, [initialConvoQuery.data, modelsQuery.data, endpointsQuery.data]); if (endpointsQuery.isLoading || modelsQuery.isLoading) { - return ; + return ; } if (!isAuthenticated) { diff --git a/packages/data-provider/src/react-query/react-query-service.ts b/packages/data-provider/src/react-query/react-query-service.ts index 159be64dc6..7e83df84ab 100644 --- a/packages/data-provider/src/react-query/react-query-service.ts +++ b/packages/data-provider/src/react-query/react-query-service.ts @@ -117,8 +117,8 @@ export const useUpdateUserKeysMutation = (): UseMutationResult< > => { const queryClient = useQueryClient(); return useMutation((payload: t.TUpdateUserKeyRequest) => dataService.updateUserKey(payload), { - onSuccess: () => { - queryClient.invalidateQueries([QueryKeys.name]); + onSuccess: (data, variables) => { + queryClient.invalidateQueries([QueryKeys.name, variables.name]); }, }); }; @@ -136,7 +136,7 @@ export const useRevokeUserKeyMutation = (name: string): UseMutationResult dataService.revokeUserKey(name), { onSuccess: () => { - queryClient.invalidateQueries([QueryKeys.name]); + queryClient.invalidateQueries([QueryKeys.name, name]); if (name === s.EModelEndpoint.assistants) { queryClient.invalidateQueries([QueryKeys.assistants, defaultOrderQuery]); queryClient.invalidateQueries([QueryKeys.assistantDocs]);