refactor: Use librechat-data-provider app-wide 🔄 (#1326)

* chore: bump vite, vitejs/plugin-react, mark client package as esm, move react-query as a peer dep in data-provider

* chore: import changes due to new data-provider export strategy, also fix type imports where applicable

* chore: export react-query services as separate to avoid react dependencies in /api/

* chore: suppress sourcemap warnings and polyfill node:path which is used by filenamify
TODO: replace filenamify with an alternative and REMOVE polyfill

* chore: /api/ changes to support `librechat-data-provider`

* refactor: rewrite Dockerfile.multi in light of /api/ changes to support `librechat-data-provider`

* chore: remove volume mapping to node_modules directories in default compose file

* chore: remove schemas from /api/ as is no longer needed with use of `librechat-data-provider`

* fix(ci): jest `librechat-data-provider/react-query` module resolution
This commit is contained in:
Danny Avila 2023-12-11 14:48:40 -05:00 committed by GitHub
parent d4c846b543
commit df1dfa7d46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 1831 additions and 1343 deletions

View file

@ -1,36 +1,33 @@
# Build API, Client and Data Provider
FROM node:19-alpine AS base
# WORKDIR /app
# COPY config/loader.js ./config/
# RUN touch .env
# RUN npm install dotenv
WORKDIR /app/api
COPY api/package*.json ./
COPY api/ ./
RUN touch .env
RUN npm install
# React client build
FROM base AS client-build
WORKDIR /app/client
COPY ./client/ ./
FROM node:20-alpine AS base
# Build data-provider
FROM base AS data-provider-build
WORKDIR /app/packages/data-provider
COPY ./packages/data-provider ./
RUN npm install
RUN npm run build
# React client build
FROM data-provider-build AS client-build
WORKDIR /app/client
COPY ./client/ ./
# Copy data-provider to client's node_modules
RUN mkdir -p /app/client/node_modules/librechat-data-provider/
RUN cp -R /app/packages/data-provider/* /app/client/node_modules/librechat-data-provider/
WORKDIR /app/client
RUN npm install
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN npm run build
# Node API setup
FROM base AS api-build
FROM data-provider-build AS api-build
WORKDIR /app/api
COPY api/package*.json ./
COPY api/ ./
# Copy data-provider to API's node_modules
RUN mkdir -p /app/api/node_modules/librechat-data-provider/
RUN cp -R /app/packages/data-provider/* /app/api/node_modules/librechat-data-provider/
RUN npm install
COPY --from=client-build /app/client/dist /app/client/dist
EXPOSE 3080
ENV HOST=0.0.0.0

View file

@ -1,6 +1,6 @@
const Anthropic = require('@anthropic-ai/sdk');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const { getResponseSender, EModelEndpoint } = require('~/server/services/Endpoints');
const { getResponseSender, EModelEndpoint } = require('librechat-data-provider');
const { getModelMaxTokens } = require('~/utils');
const BaseClient = require('./BaseClient');

View file

@ -4,11 +4,7 @@ const { GoogleVertexAI } = require('langchain/llms/googlevertexai');
const { ChatGoogleVertexAI } = require('langchain/chat_models/googlevertexai');
const { AIMessage, HumanMessage, SystemMessage } = require('langchain/schema');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const {
getResponseSender,
EModelEndpoint,
endpointSettings,
} = require('~/server/services/Endpoints');
const { getResponseSender, EModelEndpoint, endpointSettings } = require('librechat-data-provider');
const { getModelMaxTokens } = require('~/utils');
const { formatMessage } = require('./prompts');
const BaseClient = require('./BaseClient');

View file

@ -1,7 +1,7 @@
const OpenAI = require('openai');
const { HttpsProxyAgent } = require('https-proxy-agent');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const { getResponseSender, EModelEndpoint } = require('~/server/services/Endpoints');
const { getResponseSender, EModelEndpoint } = require('librechat-data-provider');
const { encodeAndFormat, validateVisionModel } = require('~/server/services/Files/images');
const { getModelMaxTokens, genAzureChatCompletion, extractBaseURL } = require('~/utils');
const { truncateText, formatMessage, CUT_OFF_PROMPT } = require('./prompts');

View file

@ -3,7 +3,7 @@ const { CallbackManager } = require('langchain/callbacks');
const { BufferMemory, ChatMessageHistory } = require('langchain/memory');
const { initializeCustomAgent, initializeFunctionsAgent } = require('./agents');
const { addImages, buildErrorInput, buildPromptPrefix } = require('./output_parsers');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const { formatLangChainMessages } = require('./prompts');
const checkBalance = require('~/models/checkBalance');
const { SelfReflectionTool } = require('./tools');

View file

@ -1,5 +1,5 @@
const { promptTokensEstimate } = require('openai-chat-tokens');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const { formatFromLangChain } = require('~/app/clients/prompts');
const checkBalance = require('~/models/checkBalance');
const { isEnabled } = require('~/server/utils');

View file

@ -52,6 +52,7 @@
"keyv": "^4.5.4",
"keyv-file": "^0.2.0",
"langchain": "^0.0.186",
"librechat-data-provider": "*",
"lodash": "^4.17.21",
"meilisearch": "^0.33.0",
"module-alias": "^2.2.3",

View file

@ -1,6 +1,6 @@
const { sendMessage, createOnProgress } = require('~/server/utils');
const { saveMessage, getConvoTitle, getConvo } = require('~/models');
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { createAbortController, handleAbortError } = require('~/server/middleware');
const AskController = async (req, res, next, initializeClient) => {

View file

@ -1,6 +1,6 @@
const { sendMessage, createOnProgress } = require('~/server/utils');
const { saveMessage, getConvoTitle, getConvo } = require('~/models');
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { createAbortController, handleAbortError } = require('~/server/middleware');
const EditController = async (req, res, next, initializeClient) => {

View file

@ -3,7 +3,7 @@ const openAI = require('~/server/services/Endpoints/openAI');
const google = require('~/server/services/Endpoints/google');
const anthropic = require('~/server/services/Endpoints/anthropic');
const gptPlugins = require('~/server/services/Endpoints/gptPlugins');
const { parseConvo, EModelEndpoint } = require('~/server/services/Endpoints');
const { parseConvo, EModelEndpoint } = require('librechat-data-provider');
const buildFunction = {
[EModelEndpoint.openAI]: openAI.buildOptions,

View file

@ -1,7 +1,7 @@
const crypto = require('crypto');
const { saveMessage } = require('~/models');
const { sendMessage, sendError } = require('~/server/utils');
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
/**
* Denies a request by sending an error message and optionally saves the user's message.

View file

@ -1,6 +1,6 @@
const express = require('express');
const router = express.Router();
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { validateTools } = require('~/app');
const { addTitle } = require('~/server/services/Endpoints/openAI');
const { initializeClient } = require('~/server/services/Endpoints/gptPlugins');

View file

@ -6,7 +6,7 @@ const anthropic = require('./anthropic');
const gptPlugins = require('./gptPlugins');
const askChatGPTBrowser = require('./askChatGPTBrowser');
const { isEnabled } = require('~/server/utils');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const {
uaParser,
checkBan,

View file

@ -2,7 +2,7 @@ const express = require('express');
const router = express.Router();
const { sendMessage, createOnProgress } = require('~/server/utils');
const { saveMessage, getConvoTitle, getConvo } = require('~/models');
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { addTitle, initializeClient } = require('~/server/services/Endpoints/openAI');
const {
handleAbort,

View file

@ -2,7 +2,7 @@ const express = require('express');
const router = express.Router();
const { validateTools } = require('~/app');
const { saveMessage, getConvoTitle, getConvo } = require('~/models');
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { initializeClient } = require('~/server/services/Endpoints/gptPlugins');
const { sendMessage, createOnProgress, formatSteps, formatAction } = require('~/server/utils');
const {

View file

@ -4,7 +4,7 @@ const google = require('./google');
const anthropic = require('./anthropic');
const gptPlugins = require('./gptPlugins');
const { isEnabled } = require('~/server/utils');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const {
checkBan,
uaParser,

View file

@ -1,6 +1,6 @@
const express = require('express');
const router = express.Router();
const { getResponseSender } = require('~/server/services/Endpoints');
const { getResponseSender } = require('librechat-data-provider');
const { initializeClient } = require('~/server/services/Endpoints/openAI');
const { saveMessage, getConvoTitle, getConvo } = require('~/models');
const { sendMessage, createOnProgress } = require('~/server/utils');

View file

@ -1,4 +1,4 @@
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const {
OPENAI_API_KEY: openAIApiKey,

View file

@ -1,4 +1,4 @@
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const loadAsyncEndpoints = require('./loadAsyncEndpoints');
const { config } = require('./EndpointService');

View file

@ -3,7 +3,7 @@ const {
getChatGPTBrowserModels,
getAnthropicModels,
} = require('~/server/services/ModelService');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const { useAzurePlugins } = require('~/server/services/Config/EndpointService').config;
const fitlerAssistantModels = (str) => {

View file

@ -1,5 +1,5 @@
const { GoogleClient } = require('~/app');
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const { getUserKey, checkUserKeyExpiry } = require('~/server/services/UserService');
const initializeClient = async ({ req, res, endpointOption }) => {

View file

@ -1,5 +0,0 @@
const schemas = require('./schemas');
module.exports = {
...schemas,
};

View file

@ -1,445 +0,0 @@
const { z } = require('zod');
const EModelEndpoint = {
azureOpenAI: 'azureOpenAI',
openAI: 'openAI',
bingAI: 'bingAI',
chatGPTBrowser: 'chatGPTBrowser',
google: 'google',
gptPlugins: 'gptPlugins',
anthropic: 'anthropic',
assistant: 'assistant',
};
const alternateName = {
[EModelEndpoint.openAI]: 'OpenAI',
[EModelEndpoint.assistant]: 'Assistants',
[EModelEndpoint.azureOpenAI]: 'Azure OpenAI',
[EModelEndpoint.bingAI]: 'Bing',
[EModelEndpoint.chatGPTBrowser]: 'ChatGPT',
[EModelEndpoint.gptPlugins]: 'Plugins',
[EModelEndpoint.google]: 'Google',
[EModelEndpoint.anthropic]: 'Anthropic',
};
const endpointSettings = {
[EModelEndpoint.google]: {
model: {
default: 'chat-bison',
},
maxOutputTokens: {
min: 1,
max: 2048,
step: 1,
default: 1024,
},
temperature: {
min: 0,
max: 1,
step: 0.01,
default: 0.2,
},
topP: {
min: 0,
max: 1,
step: 0.01,
default: 0.8,
},
topK: {
min: 1,
max: 40,
step: 0.01,
default: 40,
},
},
};
const google = endpointSettings[EModelEndpoint.google];
const supportsFiles = {
[EModelEndpoint.openAI]: true,
[EModelEndpoint.assistant]: true,
};
const openAIModels = [
'gpt-3.5-turbo-16k-0613',
'gpt-3.5-turbo-16k',
'gpt-4-1106-preview',
'gpt-3.5-turbo',
'gpt-3.5-turbo-1106',
'gpt-4-vision-preview',
'gpt-4',
'gpt-3.5-turbo-instruct-0914',
'gpt-3.5-turbo-0613',
'gpt-3.5-turbo-0301',
'gpt-3.5-turbo-instruct',
'gpt-4-0613',
'text-davinci-003',
'gpt-4-0314',
];
const visionModels = ['gpt-4-vision', 'llava-13b'];
const eModelEndpointSchema = z.nativeEnum(EModelEndpoint);
const tPluginAuthConfigSchema = z.object({
authField: z.string(),
label: z.string(),
description: z.string(),
});
const tPluginSchema = z.object({
name: z.string(),
pluginKey: z.string(),
description: z.string(),
icon: z.string(),
authConfig: z.array(tPluginAuthConfigSchema),
authenticated: z.boolean().optional(),
isButton: z.boolean().optional(),
});
const tExampleSchema = z.object({
input: z.object({
content: z.string(),
}),
output: z.object({
content: z.string(),
}),
});
const tAgentOptionsSchema = z.object({
agent: z.string(),
skipCompletion: z.boolean(),
model: z.string(),
temperature: z.number(),
});
const tConversationSchema = z.object({
conversationId: z.string().nullable(),
title: z.string().nullable().or(z.literal('New Chat')).default('New Chat'),
user: z.string().optional(),
endpoint: eModelEndpointSchema.nullable(),
suggestions: z.array(z.string()).optional(),
messages: z.array(z.string()).optional(),
tools: z.array(tPluginSchema).optional(),
createdAt: z.string(),
updatedAt: z.string(),
systemMessage: z.string().nullable().optional(),
modelLabel: z.string().nullable().optional(),
examples: z.array(tExampleSchema).optional(),
chatGptLabel: z.string().nullable().optional(),
userLabel: z.string().optional(),
model: z.string().nullable().optional(),
promptPrefix: z.string().nullable().optional(),
temperature: z.number().optional(),
topP: z.number().optional(),
topK: z.number().optional(),
context: z.string().nullable().optional(),
top_p: z.number().optional(),
frequency_penalty: z.number().optional(),
presence_penalty: z.number().optional(),
jailbreak: z.boolean().optional(),
jailbreakConversationId: z.string().nullable().optional(),
conversationSignature: z.string().nullable().optional(),
parentMessageId: z.string().optional(),
clientId: z.string().nullable().optional(),
invocationId: z.number().nullable().optional(),
toneStyle: z.string().nullable().optional(),
maxOutputTokens: z.number().optional(),
agentOptions: tAgentOptionsSchema.nullable().optional(),
});
const openAISchema = tConversationSchema
.pick({
model: true,
chatGptLabel: true,
promptPrefix: true,
temperature: true,
top_p: true,
presence_penalty: true,
frequency_penalty: true,
})
.transform((obj) => ({
...obj,
model: obj.model ?? 'gpt-3.5-turbo',
chatGptLabel: obj.chatGptLabel ?? null,
promptPrefix: obj.promptPrefix ?? null,
temperature: obj.temperature ?? 1,
top_p: obj.top_p ?? 1,
presence_penalty: obj.presence_penalty ?? 0,
frequency_penalty: obj.frequency_penalty ?? 0,
}))
.catch(() => ({
model: 'gpt-3.5-turbo',
chatGptLabel: null,
promptPrefix: null,
temperature: 1,
top_p: 1,
presence_penalty: 0,
frequency_penalty: 0,
}));
const googleSchema = tConversationSchema
.pick({
model: true,
modelLabel: true,
promptPrefix: true,
examples: true,
temperature: true,
maxOutputTokens: true,
topP: true,
topK: true,
})
.transform((obj) => ({
...obj,
model: obj.model ?? google.model.default,
modelLabel: obj.modelLabel ?? null,
promptPrefix: obj.promptPrefix ?? null,
examples: obj.examples ?? [{ input: { content: '' }, output: { content: '' } }],
temperature: obj.temperature ?? google.temperature.default,
maxOutputTokens: obj.maxOutputTokens ?? google.maxOutputTokens.default,
topP: obj.topP ?? google.topP.default,
topK: obj.topK ?? google.topK.default,
}))
.catch(() => ({
model: google.model.default,
modelLabel: null,
promptPrefix: null,
examples: [{ input: { content: '' }, output: { content: '' } }],
temperature: google.temperature.default,
maxOutputTokens: google.maxOutputTokens.default,
topP: google.topP.default,
topK: google.topK.default,
}));
const bingAISchema = tConversationSchema
.pick({
jailbreak: true,
systemMessage: true,
context: true,
toneStyle: true,
jailbreakConversationId: true,
conversationSignature: true,
clientId: true,
invocationId: true,
})
.transform((obj) => ({
...obj,
model: '',
jailbreak: obj.jailbreak ?? false,
systemMessage: obj.systemMessage ?? null,
context: obj.context ?? null,
toneStyle: obj.toneStyle ?? 'creative',
jailbreakConversationId: obj.jailbreakConversationId ?? null,
conversationSignature: obj.conversationSignature ?? null,
clientId: obj.clientId ?? null,
invocationId: obj.invocationId ?? 1,
}))
.catch(() => ({
model: '',
jailbreak: false,
systemMessage: null,
context: null,
toneStyle: 'creative',
jailbreakConversationId: null,
conversationSignature: null,
clientId: null,
invocationId: 1,
}));
const anthropicSchema = tConversationSchema
.pick({
model: true,
modelLabel: true,
promptPrefix: true,
temperature: true,
maxOutputTokens: true,
topP: true,
topK: true,
})
.transform((obj) => ({
...obj,
model: obj.model ?? 'claude-1',
modelLabel: obj.modelLabel ?? null,
promptPrefix: obj.promptPrefix ?? null,
temperature: obj.temperature ?? 1,
maxOutputTokens: obj.maxOutputTokens ?? 4000,
topP: obj.topP ?? 0.7,
topK: obj.topK ?? 5,
}))
.catch(() => ({
model: 'claude-1',
modelLabel: null,
promptPrefix: null,
temperature: 1,
maxOutputTokens: 4000,
topP: 0.7,
topK: 5,
}));
const chatGPTBrowserSchema = tConversationSchema
.pick({
model: true,
})
.transform((obj) => ({
...obj,
model: obj.model ?? 'text-davinci-002-render-sha',
}))
.catch(() => ({
model: 'text-davinci-002-render-sha',
}));
const gptPluginsSchema = tConversationSchema
.pick({
model: true,
chatGptLabel: true,
promptPrefix: true,
temperature: true,
top_p: true,
presence_penalty: true,
frequency_penalty: true,
tools: true,
agentOptions: true,
})
.transform((obj) => ({
...obj,
model: obj.model ?? 'gpt-3.5-turbo',
chatGptLabel: obj.chatGptLabel ?? null,
promptPrefix: obj.promptPrefix ?? null,
temperature: obj.temperature ?? 0.8,
top_p: obj.top_p ?? 1,
presence_penalty: obj.presence_penalty ?? 0,
frequency_penalty: obj.frequency_penalty ?? 0,
tools: obj.tools ?? [],
agentOptions: obj.agentOptions ?? {
agent: 'functions',
skipCompletion: true,
model: 'gpt-3.5-turbo',
temperature: 0,
},
}))
.catch(() => ({
model: 'gpt-3.5-turbo',
chatGptLabel: null,
promptPrefix: null,
temperature: 0.8,
top_p: 1,
presence_penalty: 0,
frequency_penalty: 0,
tools: [],
agentOptions: {
agent: 'functions',
skipCompletion: true,
model: 'gpt-3.5-turbo',
temperature: 0,
},
}));
const assistantSchema = tConversationSchema
.pick({
model: true,
assistant_id: true,
thread_id: true,
})
.transform((obj) => {
const newObj = { ...obj };
Object.keys(newObj).forEach((key) => {
const value = newObj[key];
if (value === undefined || value === null) {
delete newObj[key];
}
});
return newObj;
})
.catch(() => ({}));
const endpointSchemas = {
[EModelEndpoint.openAI]: openAISchema,
[EModelEndpoint.assistant]: assistantSchema,
[EModelEndpoint.azureOpenAI]: openAISchema,
[EModelEndpoint.google]: googleSchema,
[EModelEndpoint.bingAI]: bingAISchema,
[EModelEndpoint.anthropic]: anthropicSchema,
[EModelEndpoint.chatGPTBrowser]: chatGPTBrowserSchema,
[EModelEndpoint.gptPlugins]: gptPluginsSchema,
};
function getFirstDefinedValue(possibleValues) {
let returnValue;
for (const value of possibleValues) {
if (value) {
returnValue = value;
break;
}
}
return returnValue;
}
const parseConvo = (endpoint, conversation, possibleValues) => {
const schema = endpointSchemas[endpoint];
if (!schema) {
throw new Error(`Unknown endpoint: ${endpoint}`);
}
const convo = schema.parse(conversation);
if (possibleValues && convo) {
convo.model = getFirstDefinedValue(possibleValues.model) ?? convo.model;
}
return convo;
};
const getResponseSender = (endpointOption) => {
const { model, endpoint, chatGptLabel, modelLabel, jailbreak } = endpointOption;
if (
[
EModelEndpoint.openAI,
EModelEndpoint.azureOpenAI,
EModelEndpoint.gptPlugins,
EModelEndpoint.chatGPTBrowser,
].includes(endpoint)
) {
if (chatGptLabel) {
return chatGptLabel;
} else if (model && model.includes('gpt-3')) {
return 'GPT-3.5';
} else if (model && model.includes('gpt-4')) {
return 'GPT-4';
}
return alternateName[endpoint] ?? 'ChatGPT';
}
if (endpoint === EModelEndpoint.bingAI) {
return jailbreak ? 'Sydney' : 'BingAI';
}
if (endpoint === EModelEndpoint.anthropic) {
return modelLabel ?? 'Claude';
}
if (endpoint === EModelEndpoint.google) {
if (modelLabel) {
return modelLabel;
} else if (model && model.includes('code')) {
return 'Codey';
}
return 'PaLM2';
}
return '';
};
module.exports = {
parseConvo,
getResponseSender,
EModelEndpoint,
supportsFiles,
openAIModels,
visionModels,
alternateName,
endpointSettings,
};

View file

@ -1,4 +1,4 @@
const { visionModels } = require('~/server/services/Endpoints');
const { visionModels } = require('librechat-data-provider');
function validateVisionModel(model) {
if (!model) {

View file

@ -1,4 +1,4 @@
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const models = [
'text-davinci-003',

View file

@ -1,4 +1,4 @@
const { EModelEndpoint } = require('~/server/services/Endpoints');
const { EModelEndpoint } = require('librechat-data-provider');
const { getModelMaxTokens, matchModelName, maxTokensMap } = require('./tokens');
describe('getModelMaxTokens', () => {

View file

@ -28,6 +28,7 @@ module.exports = {
'jest-file-loader',
'^test/(.*)$': '<rootDir>/test/$1',
'^~/(.*)$': '<rootDir>/src/$1',
'^librechat-data-provider/react-query$': '<rootDir>/../node_modules/librechat-data-provider/src/react-query',
},
restoreMocks: true,
testResultsProcessor: 'jest-junit',

View file

@ -2,6 +2,7 @@
"name": "@librechat/frontend",
"version": "0.6.1",
"description": "",
"type": "module",
"scripts": {
"data-provider": "cd .. && npm run build:data-provider",
"build": "cross-env NODE_ENV=production vite build",
@ -95,7 +96,7 @@
"@types/node": "^20.3.0",
"@types/react": "^18.2.11",
"@types/react-dom": "^18.2.4",
"@vitejs/plugin-react": "^4.0.4",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.13",
"babel-plugin-replace-ts-export-assignment": "^0.0.2",
"babel-plugin-root-import": "^6.6.0",
@ -114,7 +115,8 @@
"tailwindcss": "^3.2.6",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"vite": "^4.4.9",
"vite-plugin-html": "^3.2.0"
"vite": "^5.0.7",
"vite-plugin-html": "^3.2.0",
"vite-plugin-node-polyfills": "^0.17.0"
}
}

View file

@ -1,11 +1,5 @@
import type {
TConversation,
TMessage,
TPreset,
TMutation,
TLoginUser,
TUser,
} from 'librechat-data-provider';
import type { TConversation, TMessage, TPreset, TLoginUser, TUser } from 'librechat-data-provider';
import type { UseMutationResult } from '@tanstack/react-query';
export type TSetOption = (param: number | string) => (newValue: number | string | boolean) => void;
export type TSetExample = (
@ -155,7 +149,7 @@ export type TDangerButtonProps = {
className?: string;
disabled?: boolean;
showText?: boolean;
mutation?: TMutation;
mutation?: UseMutationResult<unknown>;
onClick: () => void;
infoTextCode: string;
actionTextCode: string;

View file

@ -1,11 +1,11 @@
import React, { useEffect } from 'react';
import LoginForm from './LoginForm';
import { useAuthContext } from '~/hooks/AuthContext';
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useLocalize } from '~/hooks';
import { useGetStartupConfig } from 'librechat-data-provider';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import { GoogleIcon, FacebookIcon, OpenIDIcon, GithubIcon, DiscordIcon } from '~/components';
import { useAuthContext } from '~/hooks/AuthContext';
import { getLoginError } from '~/utils';
import { useLocalize } from '~/hooks';
import LoginForm from './LoginForm';
function Login() {
const { login, error, isAuthenticated } = useAuthContext();

View file

@ -1,13 +1,10 @@
import { useForm } from 'react-hook-form';
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useForm } from 'react-hook-form';
import { useLocalize } from '~/hooks';
import {
useRegisterUserMutation,
TRegisterUser,
useGetStartupConfig,
} from 'librechat-data-provider';
import { useRegisterUserMutation, useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { TRegisterUser } from 'librechat-data-provider';
import { GoogleIcon, FacebookIcon, OpenIDIcon, GithubIcon, DiscordIcon } from '~/components';
import { useLocalize } from '~/hooks';
function Registration() {
const navigate = useNavigate();
@ -281,7 +278,8 @@ function Registration() {
<a
href="/login"
aria-label="Login"
className="p-1 font-medium text-green-500 hover:underline">
className="p-1 font-medium text-green-500 hover:underline"
>
{localize('com_auth_login')}
</a>
</p>

View file

@ -1,12 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useLocalize } from '~/hooks';
import { useState, useEffect } from 'react';
import {
useRequestPasswordResetMutation,
useGetStartupConfig,
TRequestPasswordReset,
TRequestPasswordResetResponse,
} from 'librechat-data-provider';
useRequestPasswordResetMutation,
} from 'librechat-data-provider/react-query';
import type { TRequestPasswordReset, TRequestPasswordResetResponse } from 'librechat-data-provider';
import { useLocalize } from '~/hooks';
function RequestPasswordReset() {
const localize = useLocalize();
@ -116,7 +115,8 @@ function RequestPasswordReset() {
></input>
<label
htmlFor="email"
className="pointer-events-none absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-100 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500">
className="pointer-events-none absolute left-2.5 top-4 z-10 origin-[0] -translate-y-4 scale-75 transform text-sm text-gray-500 duration-100 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:text-green-500"
>
{localize('com_auth_email_address')}
</label>
</div>
@ -131,7 +131,8 @@ function RequestPasswordReset() {
<button
type="submit"
disabled={!!errors.email}
className="w-full transform rounded-md bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none">
className="w-full transform rounded-md bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none"
>
{localize('com_auth_continue')}
</button>
</div>

View file

@ -1,9 +1,8 @@
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { useResetPasswordMutation, TResetPassword } from 'librechat-data-provider';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { useResetPasswordMutation } from 'librechat-data-provider/react-query';
import type { TResetPassword } from 'librechat-data-provider';
import { useLocalize } from '~/hooks';
function ResetPassword() {
@ -177,7 +176,8 @@ function ResetPassword() {
disabled={!!errors.password || !!errors.confirm_password}
type="submit"
aria-label={localize('com_auth_submit_registration')}
className="w-full transform rounded-md bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none">
className="w-full transform rounded-md bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-600 focus:bg-green-600 focus:outline-none"
>
{localize('com_auth_continue')}
</button>
</div>

View file

@ -1,9 +1,9 @@
import { render, waitFor } from 'test/layout-test-utils';
import userEvent from '@testing-library/user-event';
import Login from '../Login';
import * as mockDataProvider from 'librechat-data-provider';
import * as mockDataProvider from 'librechat-data-provider/react-query';
jest.mock('librechat-data-provider');
jest.mock('librechat-data-provider/react-query');
const setup = ({
useGetUserQueryReturnValue = {

View file

@ -1,9 +1,9 @@
import { render, waitFor, screen } from 'test/layout-test-utils';
import userEvent from '@testing-library/user-event';
import Registration from '../Registration';
import * as mockDataProvider from 'librechat-data-provider';
import * as mockDataProvider from 'librechat-data-provider/react-query';
jest.mock('librechat-data-provider');
jest.mock('librechat-data-provider/react-query');
const setup = ({
useGetUserQueryReturnValue = {

View file

@ -1,7 +1,7 @@
import { memo } from 'react';
import { useRecoilValue } from 'recoil';
import { useParams } from 'react-router-dom';
import { useGetMessagesByConvoId } from 'librechat-data-provider';
import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query';
import { useChatHelpers, useSSE } from '~/hooks';
// import GenerationButtons from './Input/GenerationButtons';
import MessagesView from './Messages/MessagesView';

View file

@ -1,6 +1,6 @@
// import { useState } from 'react';
import { Plus } from 'lucide-react';
import { useListAssistantsQuery } from 'librechat-data-provider';
import { useListAssistantsQuery } from 'librechat-data-provider/react-query';
import type { Assistant } from 'librechat-data-provider';
import type { UseFormReset, UseFormSetValue } from 'react-hook-form';
import type { CreationForm, Actions, Option } from '~/common';

View file

@ -1,7 +1,8 @@
import { Controller, useWatch } from 'react-hook-form';
import type { Tool } from 'librechat-data-provider';
import { Tools, EModelEndpoint } from 'librechat-data-provider';
import { useCreateAssistantMutation } from 'librechat-data-provider/react-query';
import type { CreationForm, Actions } from '~/common';
import { useCreateAssistantMutation, Tools, EModelEndpoint } from 'librechat-data-provider';
import type { Tool } from 'librechat-data-provider';
import { Separator } from '~/components/ui/Separator';
import { useAssistantsContext } from '~/Providers';
import { Switch } from '~/components/ui/Switch';

View file

@ -1,4 +1,4 @@
import { useGetStartupConfig } from 'librechat-data-provider';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import { useLocalize } from '~/hooks';
export default function Footer() {

View file

@ -1,6 +1,7 @@
import type { FC } from 'react';
import { Close } from '@radix-ui/react-popover';
import { EModelEndpoint, useGetEndpointsQuery, alternateName } from 'librechat-data-provider';
import { EModelEndpoint, alternateName } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import MenuSeparator from '../UI/MenuSeparator';
import MenuItem from './MenuItem';

View file

@ -1,5 +1,6 @@
import { Content, Portal, Root } from '@radix-ui/react-popover';
import { useGetEndpointsQuery, alternateName } from 'librechat-data-provider';
import { alternateName } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { FC } from 'react';
import EndpointItems from './Endpoints/MenuItems';
import { useChatContext } from '~/Providers';

View file

@ -1,5 +1,5 @@
import { useRecoilState } from 'recoil';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { cn, defaultTextProps, removeFocusOutlines, mapEndpoints } from '~/utils';
import { Input, Label, Dropdown, Dialog, DialogClose, DialogButton } from '~/components/';
import PopoverButtons from '~/components/Chat/Input/PopoverButtons';

View file

@ -1,5 +1,6 @@
import { useRef } from 'react';
import { useUpdateMessageMutation, EModelEndpoint } from 'librechat-data-provider';
import { EModelEndpoint } from 'librechat-data-provider';
import { useUpdateMessageMutation } from 'librechat-data-provider/react-query';
import Container from '~/components/Messages/Content/Container';
import { useChatContext } from '~/Providers';
import type { TEditProps } from '~/common';

View file

@ -1,6 +1,6 @@
import { useState, useRef } from 'react';
import { useRecoilState, useSetRecoilState } from 'recoil';
import { useUpdateConversationMutation } from 'librechat-data-provider';
import { useUpdateConversationMutation } from 'librechat-data-provider/react-query';
import { useConversations, useConversation } from '~/hooks';
import { MinimalIcon } from '~/components/Endpoints';
import { NotificationSeverity } from '~/common';

View file

@ -1,7 +1,7 @@
import { useRecoilValue } from 'recoil';
import { useState, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { useUpdateConversationMutation } from 'librechat-data-provider';
import { useUpdateConversationMutation } from 'librechat-data-provider/react-query';
import type { MouseEvent, FocusEvent, KeyboardEvent } from 'react';
import { useConversations, useNavigateToConvo } from '~/hooks';
import { MinimalIcon } from '~/components/Endpoints';

View file

@ -1,5 +1,5 @@
import { useParams } from 'react-router-dom';
import { useDeleteConversationMutation } from 'librechat-data-provider';
import { useDeleteConversationMutation } from 'librechat-data-provider/react-query';
import { useLocalize, useConversations, useConversation } from '~/hooks';
import { Dialog, DialogTrigger, Label } from '~/components/ui';
import DialogTemplate from '~/components/ui/DialogTemplate';

View file

@ -1,5 +1,5 @@
import { useParams } from 'react-router-dom';
import { useDeleteConversationMutation } from 'librechat-data-provider';
import { useDeleteConversationMutation } from 'librechat-data-provider/react-query';
import { useLocalize, useConversations, useNewConvo } from '~/hooks';
import { Dialog, DialogTrigger, Label } from '~/components/ui';
import DialogTemplate from '~/components/ui/DialogTemplate';

View file

@ -3,7 +3,7 @@ import { useEffect } from 'react';
import filenamify from 'filenamify';
import exportFromJSON from 'export-from-json';
import { useSetRecoilState, useRecoilState } from 'recoil';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TEditPresetProps } from '~/common';
import { useSetOptions, useLocalize } from '~/hooks';
import { Input, Label, Dropdown, Dialog, DialogClose, DialogButton } from '~/components/';

View file

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { useCreatePresetMutation } from 'librechat-data-provider';
import { useCreatePresetMutation } from 'librechat-data-provider/react-query';
import type { TEditPresetProps } from '~/common';
import { cn, defaultTextPropsLabel, removeFocusOutlines, cleanupPreset } from '~/utils/';
import DialogTemplate from '~/components/ui/DialogTemplate';

View file

@ -1,10 +1,11 @@
import { useEffect, useState } from 'react';
import TextareaAutosize from 'react-textarea-autosize';
import { useUpdateTokenCountMutation, TUpdateTokenCountResponse } from 'librechat-data-provider';
import type { TSettingsProps } from '~/common';
import { Label, Checkbox, SelectDropDown } from '~/components/ui';
import { useUpdateTokenCountMutation } from 'librechat-data-provider/react-query';
import type { TUpdateTokenCountResponse } from 'librechat-data-provider';
import { cn, defaultTextProps, removeFocusOutlines } from '~/utils/';
import { Label, Checkbox, SelectDropDown } from '~/components/ui';
import { useLocalize, useDebounce } from '~/hooks';
import type { TSettingsProps } from '~/common';
export default function Settings({ conversation, setOption, readonly }: TSettingsProps) {
const localize = useLocalize();

View file

@ -1,9 +1,10 @@
import { useState } from 'react';
import { useGetEndpointsQuery, alternateName } from 'librechat-data-provider';
import { Settings } from 'lucide-react';
import { alternateName } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { DropdownMenuRadioItem } from '~/components';
import { Icon } from '~/components/Endpoints';
import { SetKeyDialog } from '../SetKeyDialog';
import { Icon } from '~/components/Endpoints';
import { useLocalize } from '~/hooks';
import { cn } from '~/utils';

View file

@ -1,12 +1,12 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { Trash2 } from 'lucide-react';
import { useState, useEffect } from 'react';
import { useRecoilState } from 'recoil';
import { useState, useEffect } from 'react';
import {
useDeletePresetMutation,
useCreatePresetMutation,
useGetEndpointsQuery,
} from 'librechat-data-provider';
} from 'librechat-data-provider/react-query';
import { Icon, EditPresetDialog } from '~/components/Endpoints';
import EndpointItems from './EndpointItems';
import PresetItems from './PresetItems';

View file

@ -1,5 +1,4 @@
import React from 'react';
import { useGetStartupConfig } from 'librechat-data-provider';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import { useLocalize } from '~/hooks';
export default function Footer() {

View file

@ -1,7 +1,8 @@
import { useRecoilState } from 'recoil';
import { useState, useEffect } from 'react';
import { ChevronDownIcon } from 'lucide-react';
import { useAvailablePluginsQuery, TPlugin } from 'librechat-data-provider';
import { useAvailablePluginsQuery } from 'librechat-data-provider/react-query';
import type { TPlugin } from 'librechat-data-provider';
import type { TModelSelectProps } from '~/common';
import { SelectDropDown, MultiSelectDropDown, SelectDropDownPop, Button } from '~/components/ui';
import { useSetOptions, useAuthContext, useMediaQuery } from '~/hooks';

View file

@ -1,7 +1,8 @@
import { useRecoilState } from 'recoil';
import { useState, useEffect } from 'react';
import { ChevronDownIcon } from 'lucide-react';
import { useAvailablePluginsQuery, TPlugin } from 'librechat-data-provider';
import { useAvailablePluginsQuery } from 'librechat-data-provider/react-query';
import type { TPlugin } from 'librechat-data-provider';
import type { TModelSelectProps } from '~/common';
import {
SelectDropDown,

View file

@ -1,6 +1,6 @@
import { useRef } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useUpdateMessageMutation } from 'librechat-data-provider';
import { useUpdateMessageMutation } from 'librechat-data-provider/react-query';
import type { TEditProps } from '~/common';
import store from '~/store';
import Container from './Container';

View file

@ -1,6 +1,6 @@
import { Disclosure } from '@headlessui/react';
import { useCallback, memo, ReactNode } from 'react';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TResPlugin, TInput } from 'librechat-data-provider';
import { ChevronDownIcon, LucideProps } from 'lucide-react';
import { cn, formatJSON } from '~/utils';

View file

@ -1,5 +1,5 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useGetConversationByIdQuery } from 'librechat-data-provider';
import { useGetConversationByIdQuery } from 'librechat-data-provider/react-query';
import { useEffect } from 'react';
import { useSetRecoilState, useRecoilState, useRecoilValue } from 'recoil';
import copy from 'copy-to-clipboard';

View file

@ -2,7 +2,7 @@ import { useState } from 'react';
import { Dialog } from '~/components/ui/';
import DialogTemplate from '~/components/ui/DialogTemplate';
import { ClearChatsButton } from './SettingsTabs/';
import { useClearConversationsMutation } from 'librechat-data-provider';
import { useClearConversationsMutation } from 'librechat-data-provider/react-query';
import { useLocalize, useConversation, useConversations } from '~/hooks';
const ClearConvos = ({ open, onOpenChange }) => {

View file

@ -4,7 +4,7 @@ import { useRecoilCallback } from 'recoil';
import { useEffect, useState } from 'react';
import exportFromJSON from 'export-from-json';
import DialogTemplate from '~/components/ui/DialogTemplate';
import { useGetMessagesByConvoId } from 'librechat-data-provider';
import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query';
import { Dialog, DialogButton, Input, Label, Checkbox, Dropdown } from '~/components/ui/';
import { cn, defaultTextProps, removeFocusOutlines, cleanupPreset } from '~/utils/';
import { useScreenshot, useLocalize } from '~/hooks';

View file

@ -1,11 +1,7 @@
import {
TConversation,
useGetConversationsQuery,
useSearchQuery,
TSearchResults,
} from 'librechat-data-provider';
import { useSearchQuery, useGetConversationsQuery } from 'librechat-data-provider/react-query';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useCallback, useEffect, useRef, useState } from 'react';
import type { TConversation, TSearchResults } from 'librechat-data-provider';
import {
useAuthContext,
useMediaQuery,

View file

@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
import { Fragment, useState, memo } from 'react';
import { useLocation } from 'react-router-dom';
import { Menu, Transition } from '@headlessui/react';
import { useGetUserBalance, useGetStartupConfig } from 'librechat-data-provider';
import { useGetUserBalance, useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { TConversation } from 'librechat-data-provider';
import { ExportModal } from './ExportConversation';
import { LinkIcon, GearIcon } from '~/components';

View file

@ -1,5 +1,8 @@
import * as Tabs from '@radix-ui/react-tabs';
import { useRevokeAllUserKeysMutation, useRevokeUserKeyMutation } from 'librechat-data-provider';
import {
useRevokeAllUserKeysMutation,
useRevokeUserKeyMutation,
} from 'librechat-data-provider/react-query';
import React, { useState, useCallback, useRef } from 'react';
import { useOnClickOutside } from '~/hooks';
import DangerButton from './DangerButton';

View file

@ -1,7 +1,7 @@
import { useRecoilState } from 'recoil';
import * as Tabs from '@radix-ui/react-tabs';
import React, { useState, useContext, useCallback, useRef } from 'react';
import { useClearConversationsMutation } from 'librechat-data-provider';
import { useClearConversationsMutation } from 'librechat-data-provider/react-query';
import {
ThemeContext,
useLocalize,

View file

@ -1,21 +1,19 @@
import { useState, useEffect, useCallback } from 'react';
import { Dialog } from '@headlessui/react';
import { useRecoilState } from 'recoil';
import { Search, X } from 'lucide-react';
import store from '~/store';
import PluginStoreItem from './PluginStoreItem';
import PluginPagination from './PluginPagination';
import PluginAuthForm from './PluginAuthForm';
import { Dialog } from '@headlessui/react';
import { useState, useEffect, useCallback } from 'react';
import { tConversationSchema } from 'librechat-data-provider';
import {
useAvailablePluginsQuery,
useUpdateUserPluginsMutation,
TPlugin,
TPluginAction,
tConversationSchema,
TError,
} from 'librechat-data-provider';
} from 'librechat-data-provider/react-query';
import type { TError, TPlugin, TPluginAction } from 'librechat-data-provider';
import { useAuthContext } from '~/hooks/AuthContext';
import PluginPagination from './PluginPagination';
import PluginStoreItem from './PluginStoreItem';
import PluginAuthForm from './PluginAuthForm';
import { useLocalize } from '~/hooks';
import store from '~/store';
type TPluginStoreDialogProps = {
isOpen: boolean;

View file

@ -1,9 +1,9 @@
import { render, screen, fireEvent } from 'test/layout-test-utils';
import PluginStoreDialog from '../PluginStoreDialog';
import userEvent from '@testing-library/user-event';
import * as mockDataProvider from 'librechat-data-provider';
import * as mockDataProvider from 'librechat-data-provider/react-query';
jest.mock('librechat-data-provider');
jest.mock('librechat-data-provider/react-query');
class ResizeObserver {
observe() {

View file

@ -1,12 +1,12 @@
import React from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import LightningIcon from '~/components/svg/LightningIcon';
import useDocumentTitle from '~/hooks/useDocumentTitle';
import SunIcon from '../svg/SunIcon';
import LightningIcon from '../svg/LightningIcon';
import CautionIcon from '../svg/CautionIcon';
import store from '~/store';
import CautionIcon from '~/components/svg/CautionIcon';
import SunIcon from '~/components/svg/SunIcon';
import { useLocalize } from '~/hooks';
import { useGetStartupConfig } from 'librechat-data-provider';
import store from '~/store';
export default function Landing() {
const { data: config } = useGetStartupConfig();

View file

@ -7,15 +7,12 @@ import {
createContext,
useContext,
} from 'react';
import { TUser, TLoginResponse, setTokenHeader, TLoginUser } from 'librechat-data-provider';
import {
TUser,
TLoginResponse,
setTokenHeader,
useLoginUserMutation,
useGetUserQuery,
useLoginUserMutation,
useRefreshTokenMutation,
TLoginUser,
} from 'librechat-data-provider';
} from 'librechat-data-provider/react-query';
import { useNavigate } from 'react-router-dom';
import { TAuthConfig, TUserContext, TAuthContext, TResError } from '~/common';
import { useLogoutUserMutation } from '~/data-provider';

View file

@ -1,4 +1,5 @@
import { QueryKeys, modularEndpoints, useCreatePresetMutation } from 'librechat-data-provider';
import { QueryKeys, modularEndpoints } from 'librechat-data-provider';
import { useCreatePresetMutation } from 'librechat-data-provider/react-query';
import filenamify from 'filenamify';
import { useCallback, useEffect, useRef } from 'react';
import { useRecoilState, useSetRecoilState } from 'recoil';

View file

@ -1,4 +1,4 @@
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { useChatContext } from '~/Providers/ChatContext';
import useUserKey from './useUserKey';

View file

@ -1,9 +1,9 @@
import { useMemo, useCallback } from 'react';
import {
useUpdateUserKeysMutation,
useUserKeyQuery,
useGetEndpointsQuery,
} from 'librechat-data-provider';
useUpdateUserKeysMutation,
} from 'librechat-data-provider/react-query';
const useUserKey = (endpoint: string) => {
const { data: endpointsConfig } = useGetEndpointsQuery();

View file

@ -2,12 +2,8 @@ import { v4 } from 'uuid';
import { useCallback, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil';
import {
QueryKeys,
parseCompactConvo,
getResponseSender,
useGetMessagesByConvoId,
} from 'librechat-data-provider';
import { QueryKeys, parseCompactConvo, getResponseSender } from 'librechat-data-provider';
import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query';
import type {
TMessage,
TSubmission,

View file

@ -1,6 +1,6 @@
import { useCallback } from 'react';
import { useSetRecoilState, useResetRecoilState, useRecoilCallback } from 'recoil';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type {
TConversation,
TMessagesAtom,

View file

@ -1,5 +1,5 @@
import { useRecoilValue } from 'recoil';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TConversation, TPreset } from 'librechat-data-provider';
import { getDefaultEndpoint, buildDefaultConvo } from '~/utils';
import store from '~/store';

View file

@ -1,6 +1,7 @@
import { v4 } from 'uuid';
import { parseConvo, getResponseSender } from 'librechat-data-provider';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { parseConvo, getResponseSender, useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TMessage, TSubmission, TEndpointOption } from 'librechat-data-provider';
import type { TAskFunction } from '~/common';
import useUserKey from './Input/useUserKey';

View file

@ -1,5 +1,5 @@
import { useCallback } from 'react';
import { useGetEndpointsQuery } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import {
useSetRecoilState,
useResetRecoilState,

View file

@ -4,13 +4,12 @@ import {
/* @ts-ignore */
SSE,
createPayload,
useGetUserBalance,
tMessageSchema,
tConversationSchema,
useGetStartupConfig,
EModelEndpoint,
removeNullishValues,
} from 'librechat-data-provider';
import { useGetUserBalance, useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { TResPlugin, TMessage, TConversation, TSubmission } from 'librechat-data-provider';
import { useAuthContext } from './AuthContext';
import useChatHelpers from './useChatHelpers';

View file

@ -4,11 +4,10 @@ import {
/* @ts-ignore */
SSE,
createPayload,
useGetUserBalance,
tMessageSchema,
tConversationSchema,
useGetStartupConfig,
} from 'librechat-data-provider';
import { useGetUserBalance, useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { TResPlugin, TMessage, TConversation, TSubmission } from 'librechat-data-provider';
import useConversations from './useConversations';
import { useAuthContext } from './AuthContext';

View file

@ -1,6 +1,5 @@
import { useRecoilValue } from 'recoil';
import { useParams } from 'react-router-dom';
import { useGetMessagesByConvoId } from 'librechat-data-provider';
import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query';
import ChatView from '~/components/Chat/SingleChatView';
import useAuthRedirect from './useAuthRedirect';
import { buildTree } from '~/utils';

View file

@ -2,10 +2,10 @@ import { useState, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import {
useGetStartupConfig,
useGetMessagesByConvoId,
useGetConversationByIdMutation,
useGetStartupConfig,
} from 'librechat-data-provider';
} from 'librechat-data-provider/react-query';
import Landing from '~/components/ui/Landing';
import Messages from '~/components/Messages/Messages';

View file

@ -1,7 +1,7 @@
import { useRecoilValue } from 'recoil';
import { useEffect, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { useGetConvoIdQuery, useGetModelsQuery } from 'librechat-data-provider';
import { useGetConvoIdQuery, useGetModelsQuery } from 'librechat-data-provider/react-query';
import { useNewConvo, useConfigOverride } from '~/hooks';
import ChatView from '~/components/Chat/ChatView';
import useAuthRedirect from './useAuthRedirect';

View file

@ -2,10 +2,10 @@
import { useEffect, useState } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { Outlet, useLocation } from 'react-router-dom';
import { useGetModelsQuery, useGetSearchEnabledQuery } from 'librechat-data-provider';
import { useGetModelsQuery, useGetSearchEnabledQuery } from 'librechat-data-provider/react-query';
import type { ContextType } from '~/common';
import { Nav, MobileNav } from '~/components/Nav';
import { useAuthContext, useServerStream, useConversation } from '~/hooks';
import { Nav, MobileNav } from '~/components/Nav';
import store from '~/store';
export default function Root() {

View file

@ -1,5 +1,6 @@
import { atom, selector } from 'recoil';
import { TEndpointsConfig, EModelEndpoint } from 'librechat-data-provider';
import { EModelEndpoint } from 'librechat-data-provider';
import type { TEndpointsConfig } from 'librechat-data-provider';
const defaultConfig: TEndpointsConfig = {
[EModelEndpoint.azureOpenAI]: null,

View file

@ -22,7 +22,8 @@
"paths": {
"~/*": ["./client/src/*"],
"test/*": ["./client/test/*"],
"*": ["./client/*", "../node_modules/*"]
"*": ["./client/*", "../node_modules/*"],
"librechat-data-provider/*": ["./packages/data-provider/*"]
}
},
"types": ["node", "jest", "@testing-library/jest-dom"],

View file

@ -1,3 +1,4 @@
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import path, { resolve } from 'path';
@ -23,7 +24,7 @@ export default defineConfig({
// All other env variables are filtered out
envDir: '../',
envPrefix: ['VITE_', 'SCRIPT_', 'DOMAIN_', 'ALLOW_'],
plugins: [react(), sourcemapExclude({ excludeNodeModules: true })],
plugins: [react(), nodePolyfills(), sourcemapExclude({ excludeNodeModules: true })],
publicDir: './public',
build: {
sourcemap: process.env.NODE_ENV === 'development',
@ -37,6 +38,19 @@ export default defineConfig({
}
},
},
/**
* Ignore "use client" waning since we are not using SSR
* @see {@link https://github.com/TanStack/query/pull/5161#issuecomment-1477389761 Preserve 'use client' directives TanStack/query#5161}
*/
onwarn(warning, warn) {
if (
// warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
warning.message.includes('Error when using sourcemap')
) {
return;
}
warn(warning);
},
},
},
resolve: {

View file

@ -38,12 +38,10 @@ services:
- MEILI_HOST=http://meilisearch:7700
- MEILI_HTTP_ADDR=meilisearch:7700
volumes:
- /app/client/node_modules
- ./api:/app/api
- ./.env:/app/.env
- ./.env.development:/app/.env.development
- ./.env.production:/app/.env.production
- /app/api/node_modules
- ./images:/app/client/public/images
mongodb:
container_name: chat-mongodb

2205
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,22 @@
{
"name": "librechat-data-provider",
"version": "0.2.5",
"version": "0.3.0",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",
"types": "types/index.d.ts",
"types": "./types/index.d.ts",
"exports": {
".": {
"import": "./dist/index.es.js",
"require": "./dist/index.js",
"types": "./types/index.d.ts"
},
"./react-query": {
"import": "./dist/react-query/index.es.js",
"require": "./dist/react-query/index.js",
"types": "./types/react-query/index.d.ts"
}
},
"scripts": {
"clean": "rimraf dist",
"build": "npm run clean && rollup -c --silent --bundleConfigAsCjs",
@ -26,7 +38,6 @@
},
"homepage": "https://github.com/danny-avila/LibreChat#readme",
"dependencies": {
"@tanstack/react-query": "^4.28.0",
"axios": "^1.3.4",
"openai": "4.11.1",
"zod": "^3.22.4"
@ -37,7 +48,8 @@
"@babel/preset-typescript": "^7.21.0",
"@rollup/plugin-commonjs": "^25.0.2",
"@rollup/plugin-node-resolve": "^15.1.0",
"@tanstack/query-core": "^4.29.19",
"@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-terser": "^0.4.4",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.0",
"@types/react": "^18.2.18",
@ -45,9 +57,14 @@
"jest-junit": "^16.0.0",
"rimraf": "^5.0.1",
"rollup": "^3.26.0",
"rollup-plugin-generate-package-json": "^3.2.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-typescript2": "^0.35.0",
"typescript": "^5.0.4"
},
"peerDependencies": {
"@tanstack/react-query": "^4.28.0"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}

View file

@ -0,0 +1,10 @@
{
"name": "librechat-data-provider/react-query",
"private": true,
"main": "../index.js",
"module": "./index.es.js",
"types": "../types/react-query/index.d.ts",
"dependencies": {
"axios": "^1.3.4"
}
}

View file

@ -1,6 +1,38 @@
import typescript from 'rollup-plugin-typescript2';
import resolve from '@rollup/plugin-node-resolve';
import pkg from './package.json';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import terser from '@rollup/plugin-terser';
import generatePackageJson from 'rollup-plugin-generate-package-json';
const plugins = [
peerDepsExternal(),
resolve(),
replace({
__IS_DEV__: process.env.NODE_ENV === 'development',
}),
commonjs(),
typescript({
tsconfig: './tsconfig.json',
useTsconfigDeclarationDir: true,
}),
terser(),
];
const subfolderPlugins = (folderName) => [
...plugins,
generatePackageJson({
baseContents: {
name: `${pkg.name}/${folderName}`,
private: true,
main: '../index.js',
module: './index.es.js', // Adjust to match the output file
types: `../types/${folderName}/index.d.ts`, // Point to correct types file
},
}),
];
export default [
{
@ -9,10 +41,14 @@ export default [
{
file: pkg.main,
format: 'cjs',
sourcemap: true,
exports: 'named',
},
{
file: pkg.module,
format: 'esm',
sourcemap: true,
exports: 'named',
},
],
...{
@ -20,12 +56,33 @@ export default [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
'react',
'react-dom',
],
preserveSymlinks: true,
plugins: [
resolve(),
typescript({ useTsconfigDeclarationDir: true, tsconfig: './tsconfig.json' }),
],
plugins,
},
},
// Separate bundle for react-query related part
{
input: 'src/react-query/index.ts',
output: [
{
file: 'dist/react-query/index.es.js',
format: 'esm',
exports: 'named',
sourcemap: true,
},
],
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
'react',
'react-dom',
// 'librechat-data-provider', // Marking main part as external
],
preserveSymlinks: true,
plugins: subfolderPlugins('react-query'),
},
];

View file

@ -3,13 +3,7 @@ export * from './types';
export * from './types/assistants';
export * from './types/files';
export * from './types/mutations';
/*
* react query
* TODO: move to client, or move schemas/types to their own package
*/
export * from './react-query-service';
export * from './keys';
export * from './assistants';
/* api call helpers */
export * from './headers-helpers';
export { default as request } from './request';

View file

@ -5,9 +5,9 @@ import type {
QueryObserverResult,
UseInfiniteQueryOptions,
} from '@tanstack/react-query';
import * as t from './types/assistants';
import * as dataService from './data-service';
import { QueryKeys } from './keys';
import * as t from '../types/assistants';
import * as dataService from '../data-service';
import { QueryKeys } from '../keys';
/**
* Hook for listing all assistants, with optional parameters provided for pagination and sorting

View file

@ -0,0 +1,2 @@
export * from './react-query-service';
export * from './assistants';

View file

@ -6,12 +6,12 @@ import {
UseMutationResult,
QueryObserverResult,
} from '@tanstack/react-query';
import * as t from './types';
import * as s from './schemas';
import * as m from './types/mutations';
import * as dataService from './data-service';
import request from './request';
import { QueryKeys } from './keys';
import * as t from '../types';
import * as s from '../schemas';
import * as m from '../types/mutations';
import * as dataService from '../data-service';
import request from '../request';
import { QueryKeys } from '../keys';
export const useAbortRequestWithMessage = (): UseMutationResult<
void,
@ -292,20 +292,6 @@ export const useCreatePresetMutation = (): UseMutationResult<
});
};
export const useUpdatePresetMutation = (): UseMutationResult<
s.TPreset,
unknown,
s.TPreset,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: s.TPreset) => dataService.updatePreset(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.presets]);
},
});
};
export const useDeletePresetMutation = (): UseMutationResult<
m.PresetDeleteResponse,
unknown,

View file

@ -107,6 +107,8 @@ export const openAIModels = [
'gpt-4-0314',
];
export const visionModels = ['gpt-4-vision', 'llava-13b'];
export const eModelEndpointSchema = z.nativeEnum(EModelEndpoint);
export const tPluginAuthConfigSchema = z.object({

View file

@ -1,13 +1,10 @@
import OpenAI from 'openai';
import type { UseMutationResult } from '@tanstack/react-query';
import type { TResPlugin, TMessage, TConversation, TEndpointOption } from './schemas';
export type TOpenAIMessage = OpenAI.Chat.ChatCompletionMessageParam;
export type TOpenAIFunction = OpenAI.Chat.ChatCompletionCreateParams.Function;
export type TOpenAIFunctionCall = OpenAI.Chat.ChatCompletionCreateParams.FunctionCallOption;
export type TMutation = UseMutationResult<unknown>;
export * from './schemas';
export type TMessages = TMessage[];
@ -127,7 +124,7 @@ export type TConfig = {
export type TModelsConfig = Record<string, string[]>;
export type TEndpointsConfig = Record<string, TConfig>;
export type TEndpointsConfig = Record<string, TConfig | null>;
export type TUpdateTokenCountResponse = {
count: number;

View file

@ -1,7 +1,7 @@
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./types",
"declarationDir": "./dist/types",
"module": "esnext",
"noImplicitAny": true,
"outDir": "./types",
@ -17,11 +17,13 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": "src",
"sourceMap": true,
"baseUrl": ".", // This should be the root of your package
"paths": {
"@src/*": ["./*"]
// Add path mappings
"librechat-data-provider/react-query": ["./src/react-query/index.ts"]
}
},
"exclude": ["node_modules", "dist", "types"],
"include": ["src/**/*", "types/index.d.ts"]
"include": ["src/**/*", "types/index.d.ts", "types/react-query/index.d.ts"]
}