├── packages ├── api │ ├── .gitignore │ ├── src │ │ ├── endpoints │ │ │ ├── index.ts │ │ │ └── openai │ │ │ │ └── index.ts │ │ ├── files │ │ │ └── index.ts │ │ ├── mcp │ │ │ └── enum.ts │ │ ├── types │ │ │ ├── events.ts │ │ │ ├── index.ts │ │ │ ├── run.ts │ │ │ └── azure.ts │ │ ├── agents │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── index.ts │ │ │ └── events.ts │ │ ├── index.ts │ │ └── flow │ │ │ └── types.ts │ ├── babel.config.cjs │ ├── tsconfig.spec.json │ └── jest.config.mjs ├── data-provider │ ├── .gitignore │ ├── src │ │ ├── react-query │ │ │ └── index.ts │ │ ├── headers-helpers.ts │ │ ├── ocr.ts │ │ └── types │ │ │ └── runs.ts │ ├── babel.config.js │ ├── tsconfig.spec.json │ ├── react-query │ │ └── package.json │ └── jest.config.js └── data-schemas │ ├── .gitignore │ ├── babel.config.cjs │ ├── tsconfig.spec.json │ ├── src │ ├── types │ │ ├── banner.ts │ │ ├── assistant.ts │ │ ├── balance.ts │ │ ├── index.ts │ │ └── file.ts │ ├── models │ │ ├── memory.ts │ │ ├── key.ts │ │ ├── preset.ts │ │ ├── prompt.ts │ │ ├── project.ts │ │ ├── role.ts │ │ ├── user.ts │ │ ├── sharedLink.ts │ │ ├── agent.ts │ │ ├── file.ts │ │ ├── token.ts │ │ ├── toolCall.ts │ │ ├── action.ts │ │ ├── banner.ts │ │ ├── pluginAuth.ts │ │ ├── balance.ts │ │ ├── session.ts │ │ ├── assistant.ts │ │ ├── transaction.ts │ │ ├── promptGroup.ts │ │ └── conversationTag.ts │ ├── index.ts │ ├── schema │ │ ├── categories.ts │ │ ├── session.ts │ │ ├── key.ts │ │ └── pluginAuth.ts │ └── crypto │ │ └── index.ts │ ├── jest.config.mjs │ └── tsconfig.json ├── client ├── src │ ├── components │ │ ├── Plugins │ │ │ ├── index.ts │ │ │ └── Store │ │ │ │ ├── styles.module.css │ │ │ │ ├── index.ts │ │ │ │ └── PluginStoreLinkButton.tsx │ │ ├── Banners │ │ │ └── index.ts │ │ ├── Web │ │ │ └── index.ts │ │ ├── Input │ │ │ ├── ModelSelect │ │ │ │ └── index.ts │ │ │ ├── SetKeyDialog │ │ │ │ ├── index.ts │ │ │ │ └── OtherConfig.tsx │ │ │ └── Generations │ │ │ │ ├── Stop.tsx │ │ │ │ ├── Regenerate.tsx │ │ │ │ └── __tests__ │ │ │ │ └── Stop.spec.tsx │ │ ├── Nav │ │ │ ├── ExportConversation │ │ │ │ └── index.ts │ │ │ ├── SettingsTabs │ │ │ │ ├── Account │ │ │ │ │ └── TwoFactorPhases │ │ │ │ │ │ └── index.ts │ │ │ │ ├── Speech │ │ │ │ │ ├── STT │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── TTS │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── VoiceDropdown.tsx │ │ │ │ ├── Beta │ │ │ │ │ ├── Beta.tsx │ │ │ │ │ └── ChatBadges.tsx │ │ │ │ ├── Data │ │ │ │ │ └── RevokeAllKeys.tsx │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── Chat │ │ │ ├── Messages │ │ │ │ ├── Content │ │ │ │ │ ├── Parts │ │ │ │ │ │ ├── OpenAIImageGen │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── EmptyText.tsx │ │ │ │ │ │ └── Stdout.tsx │ │ │ │ │ ├── CancelledIcon.tsx │ │ │ │ │ ├── InProgressCall.tsx │ │ │ │ │ └── Container.tsx │ │ │ │ ├── ui │ │ │ │ │ └── PlaceholderRow.tsx │ │ │ │ ├── SubRow.tsx │ │ │ │ └── MessageAudio.tsx │ │ │ ├── Menus │ │ │ │ ├── Presets │ │ │ │ │ └── index.ts │ │ │ │ ├── Endpoints │ │ │ │ │ └── components │ │ │ │ │ │ └── index.ts │ │ │ │ ├── UI │ │ │ │ │ ├── index.ts │ │ │ │ │ └── MenuSeparator.tsx │ │ │ │ └── index.ts │ │ │ └── Input │ │ │ │ ├── Files │ │ │ │ └── Table │ │ │ │ │ └── index.ts │ │ │ │ ├── ActiveSetting.tsx │ │ │ │ └── TextareaHeader.tsx │ │ ├── Messages │ │ │ └── Content │ │ │ │ ├── index.ts │ │ │ │ ├── Container.tsx │ │ │ │ └── SubRow.tsx │ │ ├── SidePanel │ │ │ ├── Agents │ │ │ │ └── ActionsTable │ │ │ │ │ └── index.ts │ │ │ ├── Builder │ │ │ │ └── ActionsTable │ │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── Memories │ │ │ │ └── index.ts │ │ │ ├── Files │ │ │ │ └── Panel.tsx │ │ │ ├── Bookmarks │ │ │ │ └── BookmarkPanel.tsx │ │ │ └── Parameters │ │ │ │ └── index.ts │ │ ├── Tools │ │ │ └── index.ts │ │ ├── Endpoints │ │ │ ├── Settings │ │ │ │ ├── MultiView │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── Files │ │ │ ├── VectorStore │ │ │ │ ├── VectorStoreFilter.tsx │ │ │ │ ├── EmptyVectorStorePreview.tsx │ │ │ │ ├── VectorStoreButton.tsx │ │ │ │ └── VectorStoreList.tsx │ │ │ ├── FileList │ │ │ │ ├── EmptyFilePreview.tsx │ │ │ │ └── UploadFileButton.tsx │ │ │ ├── DeleteIconButton.tsx │ │ │ └── ActionButton.tsx │ │ ├── ui │ │ │ ├── DelayedRender.tsx │ │ │ ├── Collapsible.tsx │ │ │ ├── Skeleton.tsx │ │ │ ├── QuestionMark.tsx │ │ │ ├── TextareaAutosize.tsx │ │ │ ├── Label.tsx │ │ │ ├── Input.tsx │ │ │ └── FileUpload.tsx │ │ ├── Conversations │ │ │ ├── index.ts │ │ │ ├── ConvoOptions │ │ │ │ ├── index.js │ │ │ │ └── index.ts │ │ │ └── ToggleContext.ts │ │ ├── Prompts │ │ │ ├── EmptyPromptPreview.tsx │ │ │ ├── index.ts │ │ │ └── SkeletonForm.tsx │ │ ├── Auth │ │ │ ├── ErrorMessage.tsx │ │ │ ├── index.ts │ │ │ ├── ApiErrorWatcher.tsx │ │ │ ├── BlinkAnimation.tsx │ │ │ └── SocialButton.tsx │ │ ├── Bookmarks │ │ │ └── index.ts │ │ └── svg │ │ │ ├── UserIcon.tsx │ │ │ ├── DarkModeIcon.tsx │ │ │ ├── Files │ │ │ ├── CodePaths.tsx │ │ │ ├── SheetPaths.tsx │ │ │ └── FileIcon.tsx │ │ │ ├── SquirclePlusIcon.tsx │ │ │ ├── LockIcon.tsx │ │ │ ├── XAIcon.tsx │ │ │ ├── SendIcon.tsx │ │ │ ├── OpenIDIcon.tsx │ │ │ ├── ConvoIcon.tsx │ │ │ ├── LightningIcon.tsx │ │ │ ├── LikeIcon.tsx │ │ │ ├── DislikeIcon.tsx │ │ │ ├── CrossIcon.tsx │ │ │ ├── SendMessageIcon.tsx │ │ │ ├── ListeningIcon.tsx │ │ │ ├── ContinueIcon.tsx │ │ │ ├── StopGeneratingIcon.tsx │ │ │ ├── CircleHelpIcon.tsx │ │ │ ├── SpeechIcon.tsx │ │ │ ├── AnthropicMinimalIcon.tsx │ │ │ ├── CautionIcon.tsx │ │ │ ├── ChatGPTMinimalIcon.tsx │ │ │ ├── Blocks.tsx │ │ │ ├── DotsIcon.tsx │ │ │ ├── MessagesSquared.tsx │ │ │ ├── MobileSidebar.tsx │ │ │ └── LogOutIcon.tsx │ ├── data-provider │ │ ├── Misc │ │ │ └── index.ts │ │ ├── Endpoints │ │ │ └── index.ts │ │ ├── Memories │ │ │ └── index.ts │ │ ├── Auth │ │ │ └── index.ts │ │ ├── Files │ │ │ └── index.ts │ │ ├── Tools │ │ │ └── index.ts │ │ ├── Agents │ │ │ └── index.ts │ │ ├── Messages │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── __tests__ │ │ │ └── memories.test.ts │ │ └── tags.ts │ ├── hooks │ │ ├── Generic │ │ │ └── index.ts │ │ ├── Roles │ │ │ └── index.ts │ │ ├── Nav │ │ │ └── index.ts │ │ ├── Agents │ │ │ ├── index.ts │ │ │ └── useAgentsMap.ts │ │ ├── Prompts │ │ │ └── index.ts │ │ ├── Endpoint │ │ │ └── index.ts │ │ ├── Config │ │ │ └── index.ts │ │ ├── Assistants │ │ │ └── index.ts │ │ ├── SSE │ │ │ └── index.ts │ │ ├── Audio │ │ │ └── index.ts │ │ ├── Files │ │ │ ├── useSetFilesToDelete.ts │ │ │ ├── useFileMap.ts │ │ │ └── index.ts │ │ ├── Plugins │ │ │ └── index.ts │ │ ├── Chat │ │ │ └── index.ts │ │ ├── Input │ │ │ ├── useDebounce.ts │ │ │ ├── useGetAudioSettings.ts │ │ │ ├── useMultipleKeys.ts │ │ │ └── index.ts │ │ ├── usePersonalizationAccess.ts │ │ ├── useDocumentTitle.ts │ │ ├── useMediaQuery.tsx │ │ ├── Messages │ │ │ └── index.ts │ │ ├── Conversations │ │ │ ├── useBookmarkSuccess.ts │ │ │ └── useGetSender.ts │ │ └── useLocalize.ts │ ├── a11y │ │ ├── index.ts │ │ ├── LiveMessenger.tsx │ │ ├── Announcer.tsx │ │ └── MessageBlock.tsx │ ├── common │ │ ├── a11y.ts │ │ ├── tools.ts │ │ ├── index.ts │ │ ├── artifacts.ts │ │ ├── selector.ts │ │ └── mcp.ts │ ├── routes │ │ └── ShareRoute.tsx │ ├── store │ │ ├── text.ts │ │ ├── temporary.ts │ │ ├── toast.ts │ │ ├── language.ts │ │ ├── user.ts │ │ ├── preset.ts │ │ └── search.ts │ ├── @types │ │ └── i18next.d.ts │ ├── Providers │ │ ├── ShareContext.tsx │ │ ├── DashboardContext.tsx │ │ ├── ChatFormContext.tsx │ │ ├── ChatContext.tsx │ │ ├── FileMapContext.tsx │ │ ├── AddedChatContext.tsx │ │ ├── AgentsMapContext.tsx │ │ ├── SearchContext.tsx │ │ ├── BookmarkContext.tsx │ │ ├── AssistantsMapContext.tsx │ │ ├── MessageContext.tsx │ │ ├── SetConvoContext.tsx │ │ └── ToastContext.tsx │ ├── vite-env.d.ts │ ├── utils │ │ ├── citations.ts │ │ ├── cn.ts │ │ ├── scaleImage.ts │ │ ├── resetConvo.ts │ │ └── getLoginError.ts │ └── main.jsx ├── public │ ├── robots.txt │ ├── assets │ │ ├── mlx.png │ │ ├── apipie.png │ │ ├── bingai.png │ │ ├── cohere.png │ │ ├── groq.png │ │ ├── ollama.png │ │ ├── unify.webp │ │ ├── anyscale.png │ │ ├── mistral.png │ │ ├── silence.mp3 │ │ ├── together.png │ │ ├── bingai-jb.png │ │ ├── fireworks.png │ │ ├── openrouter.png │ │ ├── openweather.png │ │ ├── perplexity.png │ │ ├── shuttleai.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── icon-192x192.png │ │ ├── image_gen_oai.png │ │ ├── maskable-icon.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── c.svg │ │ ├── google.svg │ │ ├── cplusplus.svg │ │ └── tsnode.svg │ └── fonts │ │ ├── Inter-Bold.woff2 │ │ ├── Inter-Italic.woff2 │ │ ├── Inter-Regular.woff2 │ │ ├── Inter-SemiBold.woff2 │ │ ├── Inter-BoldItalic.woff2 │ │ ├── Inter-SemiBoldItalic.woff2 │ │ ├── roboto-mono-latin-400-italic.woff2 │ │ ├── roboto-mono-latin-400-normal.woff2 │ │ └── roboto-mono-latin-700-normal.woff2 ├── postcss.config.cjs ├── test │ ├── resizeObserver.mock │ ├── matchMedia.mock │ └── localStorage.mock └── scripts │ └── post-build.cjs ├── bun.lockb ├── e2e ├── types.ts ├── jestSetup.js ├── config.local.example.ts ├── setup │ ├── global-setup.local.ts │ ├── global-teardown.local.ts │ ├── global-teardown.ts │ └── global-setup.ts └── specs │ └── popup.spec.ts ├── api ├── server │ ├── utils │ │ ├── removePorts.js │ │ └── import │ │ │ └── index.js │ ├── middleware │ │ ├── abortControllers.js │ │ ├── validate │ │ │ └── index.js │ │ ├── roles │ │ │ ├── index.js │ │ │ └── admin.js │ │ ├── noIndex.js │ │ ├── setHeaders.js │ │ ├── validateRegistration.js │ │ ├── validatePasswordReset.js │ │ ├── validateEndpoint.js │ │ └── requireLdapAuth.js │ ├── services │ │ ├── Files │ │ │ ├── Code │ │ │ │ └── index.js │ │ │ ├── OpenAI │ │ │ │ └── index.js │ │ │ ├── VectorDB │ │ │ │ └── index.js │ │ │ ├── Local │ │ │ │ └── index.js │ │ │ ├── Azure │ │ │ │ └── index.js │ │ │ ├── S3 │ │ │ │ └── index.js │ │ │ ├── Firebase │ │ │ │ └── index.js │ │ │ ├── images │ │ │ │ └── index.js │ │ │ └── Audio │ │ │ │ └── index.js │ │ ├── Threads │ │ │ └── index.js │ │ ├── Config │ │ │ ├── loadOverrideConfig.js │ │ │ ├── ldap.js │ │ │ └── index.js │ │ ├── Endpoints │ │ │ ├── agents │ │ │ │ └── index.js │ │ │ ├── bedrock │ │ │ │ └── index.js │ │ │ ├── custom │ │ │ │ └── index.js │ │ │ ├── gptPlugins │ │ │ │ └── index.js │ │ │ ├── azureAssistants │ │ │ │ └── index.js │ │ │ ├── anthropic │ │ │ │ └── index.js │ │ │ ├── assistants │ │ │ │ └── index.js │ │ │ ├── google │ │ │ │ └── index.js │ │ │ └── openAI │ │ │ │ └── index.js │ │ ├── Runs │ │ │ └── index.js │ │ └── cleanup.js │ ├── routes │ │ ├── files │ │ │ └── speech │ │ │ │ ├── stt.js │ │ │ │ ├── customConfigSpeech.js │ │ │ │ └── index.js │ │ ├── assistants │ │ │ ├── tools.js │ │ │ ├── documents.js │ │ │ └── index.js │ │ ├── static.js │ │ ├── balance.js │ │ ├── models.js │ │ ├── plugins.js │ │ ├── endpoints.js │ │ ├── banner.js │ │ ├── categories.js │ │ ├── tokenizer.js │ │ ├── edit │ │ │ ├── google.js │ │ │ ├── anthropic.js │ │ │ ├── openAI.js │ │ │ └── custom.js │ │ └── ask │ │ │ ├── google.js │ │ │ ├── anthropic.js │ │ │ ├── custom.js │ │ │ └── openAI.js │ └── controllers │ │ └── EndpointController.js ├── app │ ├── index.js │ └── clients │ │ ├── document │ │ └── index.js │ │ ├── memory │ │ └── index.js │ │ ├── callbacks │ │ └── index.js │ │ ├── output_parsers │ │ └── index.js │ │ ├── chains │ │ └── index.js │ │ ├── tools │ │ ├── util │ │ │ └── index.js │ │ ├── structured │ │ │ └── credentials.js │ │ └── .well-known │ │ │ ├── qrCodes.json │ │ │ ├── web_search.json │ │ │ ├── uberchord.json │ │ │ └── DreamInterpreter.json │ │ ├── agents │ │ ├── index.js │ │ └── Functions │ │ │ └── addToolDescriptions.js │ │ ├── llm │ │ └── index.js │ │ ├── index.js │ │ └── prompts │ │ └── index.js ├── db │ ├── models.js │ └── index.js ├── lib │ └── utils │ │ └── misc.js ├── cache │ ├── index.js │ └── keyvFiles.js ├── test │ ├── __mocks__ │ │ ├── openid-client-passport.js │ │ └── auth.mock.json │ ├── .env.test.example │ └── jestSetup.js ├── utils │ ├── loadYaml.js │ ├── logger.js │ └── index.js ├── jsconfig.json └── jest.config.js ├── .husky ├── lint-staged.config.js └── pre-commit ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── helm ├── librechat-rag-api │ ├── readme.md │ └── templates │ │ ├── configmap.yaml │ │ ├── tests │ │ └── test-connection.yaml │ │ ├── vectordb-secret.yaml │ │ └── service.yaml └── librechat │ ├── templates │ ├── _checks.yaml │ ├── configmap.yaml │ ├── tests │ │ └── test-connection.yaml │ ├── service.yaml │ └── persistentvolumeclaim.yaml │ └── .helmignore ├── .dockerignore ├── start.sh ├── config ├── prepare.js ├── translations │ ├── tsconfig.json │ └── file.ts └── stop-backend.js ├── utils └── docker │ ├── docker-build.sh │ └── docker-push.sh ├── .vscode └── launch.json ├── .prettierrc ├── preset.json └── rag.yml /packages/api/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test_bundle/ 3 | -------------------------------------------------------------------------------- /client/src/components/Plugins/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Store'; 2 | -------------------------------------------------------------------------------- /packages/api/src/endpoints/index.ts: -------------------------------------------------------------------------------- 1 | export * from './openai'; 2 | -------------------------------------------------------------------------------- /packages/api/src/files/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mistral/crud'; 2 | -------------------------------------------------------------------------------- /packages/data-provider/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test_bundle/ 3 | -------------------------------------------------------------------------------- /packages/data-schemas/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test_bundle/ 3 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /api/ 3 | Allow: / -------------------------------------------------------------------------------- /client/src/data-provider/Misc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | -------------------------------------------------------------------------------- /client/src/hooks/Generic/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useLazyEffect'; 2 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/bun.lockb -------------------------------------------------------------------------------- /client/src/components/Banners/index.ts: -------------------------------------------------------------------------------- 1 | export { Banner } from './Banner'; 2 | -------------------------------------------------------------------------------- /client/src/data-provider/Endpoints/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | -------------------------------------------------------------------------------- /client/src/a11y/index.ts: -------------------------------------------------------------------------------- 1 | export { default as LiveAnnouncer } from './LiveAnnouncer'; 2 | -------------------------------------------------------------------------------- /e2e/types.ts: -------------------------------------------------------------------------------- 1 | export type User = { email: string; name: string; password: string }; 2 | -------------------------------------------------------------------------------- /client/src/data-provider/Memories/index.ts: -------------------------------------------------------------------------------- 1 | /* Memories */ 2 | export * from './queries'; 3 | -------------------------------------------------------------------------------- /client/src/hooks/Roles/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useHasAccess } from './useHasAccess'; 2 | -------------------------------------------------------------------------------- /packages/api/src/mcp/enum.ts: -------------------------------------------------------------------------------- 1 | export enum CONSTANTS { 2 | mcp_delimiter = '_mcp_', 3 | } 4 | -------------------------------------------------------------------------------- /packages/data-provider/src/react-query/index.ts: -------------------------------------------------------------------------------- 1 | export * from './react-query-service'; 2 | -------------------------------------------------------------------------------- /api/server/utils/removePorts.js: -------------------------------------------------------------------------------- 1 | module.exports = (req) => req?.ip?.replace(/:\d+[^:]*$/, ''); 2 | -------------------------------------------------------------------------------- /client/src/components/Web/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugin'; 2 | export type * from './types'; 3 | -------------------------------------------------------------------------------- /api/server/middleware/abortControllers.js: -------------------------------------------------------------------------------- 1 | // abortControllers.js 2 | module.exports = new Map(); 3 | -------------------------------------------------------------------------------- /client/src/data-provider/Auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | export * from './mutations'; 3 | -------------------------------------------------------------------------------- /client/src/data-provider/Files/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | export * from './mutations'; 3 | -------------------------------------------------------------------------------- /client/src/data-provider/Tools/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | export * from './mutations'; 3 | -------------------------------------------------------------------------------- /packages/api/src/endpoints/openai/index.ts: -------------------------------------------------------------------------------- 1 | export * from './llm'; 2 | export * from './initialize'; 3 | -------------------------------------------------------------------------------- /client/src/components/Input/ModelSelect/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ModelSelect } from './ModelSelect'; 2 | -------------------------------------------------------------------------------- /client/src/data-provider/Agents/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | export * from './mutations'; 3 | -------------------------------------------------------------------------------- /client/src/data-provider/Messages/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queries'; 2 | export * from './mutations'; 3 | -------------------------------------------------------------------------------- /api/app/index.js: -------------------------------------------------------------------------------- 1 | const clients = require('./clients'); 2 | 3 | module.exports = { 4 | ...clients, 5 | }; 6 | -------------------------------------------------------------------------------- /client/public/assets/mlx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/mlx.png -------------------------------------------------------------------------------- /client/src/components/Input/SetKeyDialog/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SetKeyDialog } from './SetKeyDialog'; 2 | -------------------------------------------------------------------------------- /client/src/components/Nav/ExportConversation/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ExportModal } from './ExportModal'; 2 | -------------------------------------------------------------------------------- /client/public/assets/apipie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/apipie.png -------------------------------------------------------------------------------- /client/public/assets/bingai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/bingai.png -------------------------------------------------------------------------------- /client/public/assets/cohere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/cohere.png -------------------------------------------------------------------------------- /client/public/assets/groq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/groq.png -------------------------------------------------------------------------------- /client/public/assets/ollama.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/ollama.png -------------------------------------------------------------------------------- /client/public/assets/unify.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/unify.webp -------------------------------------------------------------------------------- /client/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ui'; 2 | export * from './Plugins'; 3 | export * from './svg'; 4 | -------------------------------------------------------------------------------- /client/public/assets/anyscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/anyscale.png -------------------------------------------------------------------------------- /client/public/assets/mistral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/mistral.png -------------------------------------------------------------------------------- /client/public/assets/silence.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/silence.mp3 -------------------------------------------------------------------------------- /client/public/assets/together.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/together.png -------------------------------------------------------------------------------- /client/src/components/Plugins/Store/styles.module.css: -------------------------------------------------------------------------------- 1 | a { 2 | text-decoration: underline; 3 | color: white; 4 | } 5 | -------------------------------------------------------------------------------- /api/server/services/Files/Code/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | 3 | module.exports = { 4 | ...crud, 5 | }; 6 | -------------------------------------------------------------------------------- /api/server/services/Files/OpenAI/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | 3 | module.exports = { 4 | ...crud, 5 | }; 6 | -------------------------------------------------------------------------------- /api/server/services/Threads/index.js: -------------------------------------------------------------------------------- 1 | const manage = require('./manage'); 2 | 3 | module.exports = { 4 | ...manage, 5 | }; 6 | -------------------------------------------------------------------------------- /client/public/assets/bingai-jb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/bingai-jb.png -------------------------------------------------------------------------------- /client/public/assets/fireworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/fireworks.png -------------------------------------------------------------------------------- /client/public/assets/openrouter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/openrouter.png -------------------------------------------------------------------------------- /client/public/assets/openweather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/openweather.png -------------------------------------------------------------------------------- /client/public/assets/perplexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/perplexity.png -------------------------------------------------------------------------------- /client/public/assets/shuttleai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/shuttleai.png -------------------------------------------------------------------------------- /client/public/fonts/Inter-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-Bold.woff2 -------------------------------------------------------------------------------- /api/server/services/Files/VectorDB/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | 3 | module.exports = { 4 | ...crud, 5 | }; 6 | -------------------------------------------------------------------------------- /client/public/assets/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/favicon-16x16.png -------------------------------------------------------------------------------- /client/public/assets/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/favicon-32x32.png -------------------------------------------------------------------------------- /client/public/assets/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/icon-192x192.png -------------------------------------------------------------------------------- /client/public/assets/image_gen_oai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/image_gen_oai.png -------------------------------------------------------------------------------- /client/public/assets/maskable-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/maskable-icon.png -------------------------------------------------------------------------------- /client/public/fonts/Inter-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-Italic.woff2 -------------------------------------------------------------------------------- /api/app/clients/document/index.js: -------------------------------------------------------------------------------- 1 | const tokenSplit = require('./tokenSplit'); 2 | 3 | module.exports = { 4 | tokenSplit, 5 | }; 6 | -------------------------------------------------------------------------------- /client/public/fonts/Inter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-Regular.woff2 -------------------------------------------------------------------------------- /client/public/fonts/Inter-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-SemiBold.woff2 -------------------------------------------------------------------------------- /client/src/hooks/Nav/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useNavScrolling } from './useNavScrolling'; 2 | export * from './useNavHelpers'; 3 | -------------------------------------------------------------------------------- /client/public/fonts/Inter-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-BoldItalic.woff2 -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/Parts/OpenAIImageGen/index.ts: -------------------------------------------------------------------------------- 1 | export { default as OpenAIImageGen } from './OpenAIImageGen'; 2 | -------------------------------------------------------------------------------- /packages/api/src/types/events.ts: -------------------------------------------------------------------------------- 1 | export type ServerSentEvent = { 2 | data: string | Record; 3 | event?: string; 4 | }; 5 | -------------------------------------------------------------------------------- /api/app/clients/memory/index.js: -------------------------------------------------------------------------------- 1 | const summaryBuffer = require('./summaryBuffer'); 2 | 3 | module.exports = { 4 | ...summaryBuffer, 5 | }; 6 | -------------------------------------------------------------------------------- /client/public/fonts/Inter-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/Inter-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /client/src/components/Messages/Content/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SubRow } from './SubRow'; 2 | export { default as Plugin } from './Plugin'; 3 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Agents/ActionsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ActionsTable } from './Table'; 2 | export * from './Columns'; 3 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Builder/ActionsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ActionsTable } from './Table'; 2 | export * from './Columns'; 3 | -------------------------------------------------------------------------------- /packages/api/src/agents/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config'; 2 | export * from './memory'; 3 | export * from './resources'; 4 | export * from './run'; 5 | -------------------------------------------------------------------------------- /api/server/middleware/validate/index.js: -------------------------------------------------------------------------------- 1 | const validateConvoAccess = require('./convoAccess'); 2 | module.exports = { 3 | validateConvoAccess, 4 | }; 5 | -------------------------------------------------------------------------------- /client/public/assets/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/assets/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /client/src/components/SidePanel/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SidePanelGroup } from './SidePanelGroup'; 2 | export { default as SideNav } from './Nav'; 3 | -------------------------------------------------------------------------------- /e2e/jestSetup.js: -------------------------------------------------------------------------------- 1 | // v0.7.8 2 | // See .env.test.example for an example of the '.env.test' file. 3 | require('dotenv').config({ path: './e2e/.env.test' }); 4 | -------------------------------------------------------------------------------- /api/app/clients/callbacks/index.js: -------------------------------------------------------------------------------- 1 | const createStartHandler = require('./createStartHandler'); 2 | 3 | module.exports = { 4 | createStartHandler, 5 | }; 6 | -------------------------------------------------------------------------------- /client/src/components/Tools/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ToolSelectDialog } from './ToolSelectDialog'; 2 | export { default as ToolItem } from './ToolItem'; 3 | -------------------------------------------------------------------------------- /client/src/hooks/Agents/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAgentsMap } from './useAgentsMap'; 2 | export { default as useSelectAgent } from './useSelectAgent'; 3 | -------------------------------------------------------------------------------- /client/public/fonts/roboto-mono-latin-400-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/roboto-mono-latin-400-italic.woff2 -------------------------------------------------------------------------------- /client/public/fonts/roboto-mono-latin-400-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/roboto-mono-latin-400-normal.woff2 -------------------------------------------------------------------------------- /client/public/fonts/roboto-mono-latin-700-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSignal/LibreChat/main/client/public/fonts/roboto-mono-latin-700-normal.woff2 -------------------------------------------------------------------------------- /.husky/lint-staged.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '*.{js,jsx,ts,tsx}': ['prettier --write', 'eslint --fix', 'eslint'], 3 | '*.json': ['prettier --write'], 4 | }; 5 | -------------------------------------------------------------------------------- /client/src/common/a11y.ts: -------------------------------------------------------------------------------- 1 | export interface AnnounceOptions { 2 | message: string; 3 | isStatus?: boolean; 4 | } 5 | 6 | export const MESSAGE_UPDATE_INTERVAL = 7000; 7 | -------------------------------------------------------------------------------- /client/src/hooks/Prompts/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useCategories } from './useCategories'; 2 | export { default as usePromptGroupsNav } from './usePromptGroupsNav'; 3 | -------------------------------------------------------------------------------- /client/src/routes/ShareRoute.tsx: -------------------------------------------------------------------------------- 1 | import ShareView from '~/components/Share/ShareView'; 2 | 3 | export default function ShareRoute() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -e 3 | . "$(dirname -- "$0")/_/husky.sh" 4 | [ -n "$CI" ] && exit 0 5 | npx lint-staged --config ./.husky/lint-staged.config.js 6 | -------------------------------------------------------------------------------- /client/src/store/text.ts: -------------------------------------------------------------------------------- 1 | import { atom } from 'recoil'; 2 | 3 | const text = atom({ 4 | key: 'text', 5 | default: '', 6 | }); 7 | 8 | export default { text }; 9 | -------------------------------------------------------------------------------- /packages/api/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './azure'; 2 | export * from './events'; 3 | export * from './mistral'; 4 | export * from './openai'; 5 | export * from './run'; 6 | -------------------------------------------------------------------------------- /api/server/services/Files/Local/index.js: -------------------------------------------------------------------------------- 1 | const images = require('./images'); 2 | const crud = require('./crud'); 3 | 4 | module.exports = { 5 | ...crud, 6 | ...images, 7 | }; 8 | -------------------------------------------------------------------------------- /client/src/components/Chat/Menus/Presets/index.ts: -------------------------------------------------------------------------------- 1 | export { default as EditPresetDialog } from './EditPresetDialog'; 2 | export { default as PresetItems } from './PresetItems'; 3 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Memories/index.ts: -------------------------------------------------------------------------------- 1 | export { default as MemoryViewer } from './MemoryViewer'; 2 | export { default as MemoryEditDialog } from './MemoryEditDialog'; 3 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-bullseye 2 | 3 | RUN useradd -m -s /bin/bash vscode 4 | RUN mkdir -p /workspaces && chown -R vscode:vscode /workspaces 5 | WORKDIR /workspaces 6 | -------------------------------------------------------------------------------- /client/src/common/tools.ts: -------------------------------------------------------------------------------- 1 | import type { AuthType } from 'librechat-data-provider'; 2 | 3 | export type ApiKeyFormData = { 4 | apiKey: string; 5 | authType?: string | AuthType; 6 | }; 7 | -------------------------------------------------------------------------------- /client/src/components/Endpoints/Settings/MultiView/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GoogleSettings } from './GoogleSettings'; 2 | export { default as PluginSettings } from './PluginSettings'; 3 | -------------------------------------------------------------------------------- /api/server/services/Config/loadOverrideConfig.js: -------------------------------------------------------------------------------- 1 | // fetch some remote config 2 | async function loadOverrideConfig() { 3 | return false; 4 | } 5 | 6 | module.exports = loadOverrideConfig; 7 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/agents/index.js: -------------------------------------------------------------------------------- 1 | const build = require('./build'); 2 | const initialize = require('./initialize'); 3 | 4 | module.exports = { 5 | ...build, 6 | ...initialize, 7 | }; 8 | -------------------------------------------------------------------------------- /api/db/models.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { createModels } = require('@librechat/data-schemas'); 3 | const models = createModels(mongoose); 4 | 5 | module.exports = { ...models }; 6 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/bedrock/index.js: -------------------------------------------------------------------------------- 1 | const build = require('./build'); 2 | const initialize = require('./initialize'); 3 | 4 | module.exports = { 5 | ...build, 6 | ...initialize, 7 | }; 8 | -------------------------------------------------------------------------------- /client/src/components/Chat/Menus/Endpoints/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ModelSpecItem'; 2 | export * from './EndpointModelItem'; 3 | export * from './EndpointItem'; 4 | export * from './SearchResults'; 5 | -------------------------------------------------------------------------------- /client/src/store/temporary.ts: -------------------------------------------------------------------------------- 1 | import { atomWithLocalStorage } from '~/store/utils'; 2 | 3 | const isTemporary = atomWithLocalStorage('isTemporary', false); 4 | 5 | export default { 6 | isTemporary, 7 | }; 8 | -------------------------------------------------------------------------------- /api/app/clients/output_parsers/index.js: -------------------------------------------------------------------------------- 1 | const addImages = require('./addImages'); 2 | const handleOutputs = require('./handleOutputs'); 3 | 4 | module.exports = { 5 | addImages, 6 | ...handleOutputs, 7 | }; 8 | -------------------------------------------------------------------------------- /api/lib/utils/misc.js: -------------------------------------------------------------------------------- 1 | const cleanUpPrimaryKeyValue = (value) => { 2 | // For Bing convoId handling 3 | return value.replace(/--/g, '|'); 4 | }; 5 | 6 | module.exports = { 7 | cleanUpPrimaryKeyValue, 8 | }; 9 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/custom/index.js: -------------------------------------------------------------------------------- 1 | const initializeClient = require('./initialize'); 2 | const buildOptions = require('./build'); 3 | 4 | module.exports = { 5 | initializeClient, 6 | buildOptions, 7 | }; 8 | -------------------------------------------------------------------------------- /client/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-preset-env'), 5 | require('tailwindcss'), 6 | require('autoprefixer'), 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /client/src/components/Chat/Menus/UI/index.ts: -------------------------------------------------------------------------------- 1 | export { default as MenuItem } from './MenuItem'; 2 | export { default as MenuSeparator } from './MenuSeparator'; 3 | export { default as TitleButton } from './TitleButton'; 4 | -------------------------------------------------------------------------------- /helm/librechat-rag-api/readme.md: -------------------------------------------------------------------------------- 1 | # Librechat RAG API Helm CHart 2 | 3 | > [!WARNING] 4 | > This Helm-Chart is needed for LibreChat and Deployment information is documented in (the librechat chart)[../librechat/readme.md] -------------------------------------------------------------------------------- /packages/api/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], 3 | plugins: ['babel-plugin-replace-ts-export-assignment'], 4 | }; 5 | -------------------------------------------------------------------------------- /api/app/clients/chains/index.js: -------------------------------------------------------------------------------- 1 | const runTitleChain = require('./runTitleChain'); 2 | const predictNewSummary = require('./predictNewSummary'); 3 | 4 | module.exports = { 5 | runTitleChain, 6 | predictNewSummary, 7 | }; 8 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/gptPlugins/index.js: -------------------------------------------------------------------------------- 1 | const buildOptions = require('./build'); 2 | const initializeClient = require('./initialize'); 3 | 4 | module.exports = { 5 | buildOptions, 6 | initializeClient, 7 | }; 8 | -------------------------------------------------------------------------------- /api/server/utils/import/index.js: -------------------------------------------------------------------------------- 1 | const importers = require('./importers'); 2 | const importConversations = require('./importConversations'); 3 | 4 | module.exports = { 5 | ...importers, 6 | importConversations, 7 | }; 8 | -------------------------------------------------------------------------------- /client/src/components/Chat/Menus/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PresetsMenu } from './PresetsMenu'; 2 | export { default as OpenSidebar } from './OpenSidebar'; 3 | export { default as HeaderNewChat } from './HeaderNewChat'; 4 | -------------------------------------------------------------------------------- /client/src/components/Files/VectorStore/VectorStoreFilter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const VectorStoreFilter = () => { 4 | return
VectorStoreFilter
; 5 | }; 6 | 7 | export default VectorStoreFilter; 8 | -------------------------------------------------------------------------------- /client/src/components/ui/DelayedRender.tsx: -------------------------------------------------------------------------------- 1 | import { useDelayedRender } from '~/hooks'; 2 | 3 | const DelayedRender = ({ delay, children }) => useDelayedRender(delay)(() => children); 4 | 5 | export default DelayedRender; 6 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/azureAssistants/index.js: -------------------------------------------------------------------------------- 1 | const buildOptions = require('./build'); 2 | const initializeClient = require('./initialize'); 3 | 4 | module.exports = { 5 | buildOptions, 6 | initializeClient, 7 | }; 8 | -------------------------------------------------------------------------------- /client/src/hooks/Endpoint/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useKeyDialog } from './useKeyDialog'; 2 | export { default as useEndpoints } from './useEndpoints'; 3 | export { default as useSelectorEffects } from './useSelectorEffects'; 4 | -------------------------------------------------------------------------------- /packages/data-provider/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], 3 | plugins: ['babel-plugin-replace-ts-export-assignment'], 4 | }; 5 | -------------------------------------------------------------------------------- /packages/data-schemas/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], 3 | plugins: ['babel-plugin-replace-ts-export-assignment'], 4 | }; 5 | -------------------------------------------------------------------------------- /api/cache/index.js: -------------------------------------------------------------------------------- 1 | const keyvFiles = require('./keyvFiles'); 2 | const getLogStores = require('./getLogStores'); 3 | const logViolation = require('./logViolation'); 4 | 5 | module.exports = { ...keyvFiles, getLogStores, logViolation }; 6 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Account/TwoFactorPhases/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BackupPhase'; 2 | export * from './QRPhase'; 3 | export * from './VerifyPhase'; 4 | export * from './SetupPhase'; 5 | export * from './DisablePhase'; 6 | -------------------------------------------------------------------------------- /client/src/hooks/Config/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAppStartup } from './useAppStartup'; 2 | export { default as useClearStates } from './useClearStates'; 3 | export { default as useSpeechSettingsInit } from './useSpeechSettingsInit'; 4 | -------------------------------------------------------------------------------- /api/server/middleware/roles/index.js: -------------------------------------------------------------------------------- 1 | const checkAdmin = require('./admin'); 2 | const { checkAccess, generateCheckAccess } = require('./access'); 3 | 4 | module.exports = { 5 | checkAdmin, 6 | checkAccess, 7 | generateCheckAccess, 8 | }; 9 | -------------------------------------------------------------------------------- /client/src/components/Conversations/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Fork } from '../Chat/Messages/Fork'; 2 | export { default as Pages } from './Pages'; 3 | export { default as Conversations } from './Conversations'; 4 | export * from './ConvoOptions'; 5 | -------------------------------------------------------------------------------- /client/src/components/Chat/Input/Files/Table/index.ts: -------------------------------------------------------------------------------- 1 | export { columns } from './Columns'; 2 | export { default as DataTable } from './DataTable'; 3 | export { default as TemplateTable } from './TemplateTable'; 4 | export { files } from './fakeData'; 5 | -------------------------------------------------------------------------------- /client/src/hooks/Assistants/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAssistantsMap } from './useAssistantsMap'; 2 | export { default as useSelectAssistant } from './useSelectAssistant'; 3 | export { default as useAssistantListMap } from './useAssistantListMap'; 4 | -------------------------------------------------------------------------------- /helm/librechat/templates/_checks.yaml: -------------------------------------------------------------------------------- 1 | 2 | {{ if hasKey .Values.env }} 3 | {{ fail "The Value env has been renamed and moved to librechat.configEnv. Refer to https://www.librechat.ai/docs/local/helm_chart#migrate for more information" }} 4 | {{ end }} -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.circleci 2 | **/.editorconfig 3 | **/.dockerignore 4 | **/.git 5 | **/.DS_Store 6 | **/.vscode 7 | **/node_modules 8 | 9 | # Specific patterns to ignore 10 | data-node 11 | meili_data* 12 | librechat* 13 | Dockerfile* 14 | docs 15 | -------------------------------------------------------------------------------- /api/server/services/Files/Azure/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | const images = require('./images'); 3 | const initialize = require('./initialize'); 4 | 5 | module.exports = { 6 | ...crud, 7 | ...images, 8 | ...initialize, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/services/Files/S3/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | const images = require('./images'); 3 | const initialize = require('./initialize'); 4 | 5 | module.exports = { 6 | ...crud, 7 | ...images, 8 | ...initialize, 9 | }; 10 | -------------------------------------------------------------------------------- /client/test/resizeObserver.mock: -------------------------------------------------------------------------------- 1 | Object.defineProperty(window, 'ResizeObserver', { 2 | writable: true, 3 | value: jest.fn().mockImplementation(() => ({ 4 | disconnect: jest.fn(), 5 | observe: jest.fn(), 6 | unobserve: jest.fn(), 7 | })) 8 | }); -------------------------------------------------------------------------------- /api/app/clients/tools/util/index.js: -------------------------------------------------------------------------------- 1 | const { validateTools, loadTools } = require('./handleTools'); 2 | const handleOpenAIErrors = require('./handleOpenAIErrors'); 3 | 4 | module.exports = { 5 | handleOpenAIErrors, 6 | validateTools, 7 | loadTools, 8 | }; 9 | -------------------------------------------------------------------------------- /api/server/routes/files/speech/stt.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { speechToText } = require('~/server/services/Files/Audio'); 3 | 4 | const router = express.Router(); 5 | 6 | router.post('/', speechToText); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /api/server/services/Files/Firebase/index.js: -------------------------------------------------------------------------------- 1 | const crud = require('./crud'); 2 | const images = require('./images'); 3 | const initialize = require('./initialize'); 4 | 5 | module.exports = { 6 | ...crud, 7 | ...images, 8 | ...initialize, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/routes/assistants/tools.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { getAvailableTools } = require('~/server/controllers/PluginController'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', getAvailableTools); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /client/src/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './a11y'; 2 | export * from './artifacts'; 3 | export * from './types'; 4 | export * from './menus'; 5 | export * from './tools'; 6 | export * from './selector'; 7 | export * from './assistants-types'; 8 | export * from './agents-types'; 9 | -------------------------------------------------------------------------------- /client/src/components/Conversations/ConvoOptions/index.js: -------------------------------------------------------------------------------- 1 | export * from './DeleteButton'; 2 | export { default as ShareButton } from './ShareButton'; 3 | export { default as SharedLinkButton } from './SharedLinkButton'; 4 | export { default as ConvoOptions } from './ConvoOptions'; 5 | -------------------------------------------------------------------------------- /client/src/components/Conversations/ConvoOptions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DeleteButton'; 2 | export { default as ShareButton } from './ShareButton'; 3 | export { default as SharedLinkButton } from './SharedLinkButton'; 4 | export { default as ConvoOptions } from './ConvoOptions'; 5 | -------------------------------------------------------------------------------- /e2e/config.local.example.ts: -------------------------------------------------------------------------------- 1 | // copy as `config.local.ts` 2 | import type { User } from './types'; 3 | 4 | const localUser: User = { 5 | email: 'testuser@example.com', 6 | name: 'Test User', 7 | password: 'securepassword123', 8 | }; 9 | 10 | export default localUser; 11 | -------------------------------------------------------------------------------- /api/server/routes/static.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const staticCache = require('../utils/staticCache'); 3 | const paths = require('~/config/paths'); 4 | 5 | const router = express.Router(); 6 | router.use(staticCache(paths.imageOutput)); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/anthropic/index.js: -------------------------------------------------------------------------------- 1 | const addTitle = require('./title'); 2 | const buildOptions = require('./build'); 3 | const initializeClient = require('./initialize'); 4 | 5 | module.exports = { 6 | addTitle, 7 | buildOptions, 8 | initializeClient, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/assistants/index.js: -------------------------------------------------------------------------------- 1 | const addTitle = require('./title'); 2 | const buildOptions = require('./build'); 3 | const initializeClient = require('./initalize'); 4 | 5 | module.exports = { 6 | addTitle, 7 | buildOptions, 8 | initializeClient, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/google/index.js: -------------------------------------------------------------------------------- 1 | const addTitle = require('./title'); 2 | const buildOptions = require('./build'); 3 | const initializeClient = require('./initialize'); 4 | 5 | module.exports = { 6 | addTitle, 7 | buildOptions, 8 | initializeClient, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/services/Endpoints/openAI/index.js: -------------------------------------------------------------------------------- 1 | const addTitle = require('./title'); 2 | const buildOptions = require('./build'); 3 | const initializeClient = require('./initialize'); 4 | 5 | module.exports = { 6 | addTitle, 7 | buildOptions, 8 | initializeClient, 9 | }; 10 | -------------------------------------------------------------------------------- /api/test/__mocks__/openid-client-passport.js: -------------------------------------------------------------------------------- 1 | // api/test/__mocks__/openid-client-passport.js 2 | const Strategy = jest.fn().mockImplementation((options, verify) => { 3 | return { name: 'mocked-openid-passport-strategy', options, verify }; 4 | }); 5 | 6 | module.exports = { Strategy }; 7 | -------------------------------------------------------------------------------- /client/src/@types/i18next.d.ts: -------------------------------------------------------------------------------- 1 | import { defaultNS, resources } from '~/locales/i18n'; 2 | 3 | declare module 'i18next' { 4 | interface CustomTypeOptions { 5 | defaultNS: typeof defaultNS; 6 | resources: typeof resources.en; 7 | strictKeyChecks: true 8 | } 9 | } -------------------------------------------------------------------------------- /client/src/components/Messages/Content/Container.tsx: -------------------------------------------------------------------------------- 1 | // Container Component 2 | const Container = ({ children }: { children: React.ReactNode }) => ( 3 |
{children}
4 | ); 5 | 6 | export default Container; 7 | -------------------------------------------------------------------------------- /api/app/clients/agents/index.js: -------------------------------------------------------------------------------- 1 | const initializeCustomAgent = require('./CustomAgent/initializeCustomAgent'); 2 | const initializeFunctionsAgent = require('./Functions/initializeFunctionsAgent'); 3 | 4 | module.exports = { 5 | initializeCustomAgent, 6 | initializeFunctionsAgent, 7 | }; 8 | -------------------------------------------------------------------------------- /api/app/clients/llm/index.js: -------------------------------------------------------------------------------- 1 | const createLLM = require('./createLLM'); 2 | const RunManager = require('./RunManager'); 3 | const createCoherePayload = require('./createCoherePayload'); 4 | 5 | module.exports = { 6 | createLLM, 7 | RunManager, 8 | createCoherePayload, 9 | }; 10 | -------------------------------------------------------------------------------- /client/src/hooks/SSE/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useSSE } from './useSSE'; 2 | export { default as useStepHandler } from './useStepHandler'; 3 | export { default as useContentHandler } from './useContentHandler'; 4 | export { default as useAttachmentHandler } from './useAttachmentHandler'; 5 | -------------------------------------------------------------------------------- /packages/api/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './axios'; 2 | export * from './azure'; 3 | export * from './common'; 4 | export * from './events'; 5 | export * from './files'; 6 | export * from './generators'; 7 | export * from './openid'; 8 | export { default as Tokenizer } from './tokenizer'; 9 | -------------------------------------------------------------------------------- /packages/api/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "outDir": "./dist/tests", 6 | "baseUrl": "." 7 | }, 8 | "include": ["specs/**/*", "src/**/*"], 9 | "exclude": ["node_modules", "dist"] 10 | } 11 | -------------------------------------------------------------------------------- /api/db/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { createModels } = require('@librechat/data-schemas'); 3 | const { connectDb } = require('./connect'); 4 | const indexSync = require('./indexSync'); 5 | 6 | createModels(mongoose); 7 | 8 | module.exports = { connectDb, indexSync }; 9 | -------------------------------------------------------------------------------- /client/src/Providers/ShareContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | type TShareContext = { isSharedConvo?: boolean }; 3 | 4 | export const ShareContext = createContext({} as TShareContext); 5 | export const useShareContext = () => useContext(ShareContext); 6 | -------------------------------------------------------------------------------- /packages/data-schemas/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "outDir": "./dist/tests", 6 | "baseUrl": "." 7 | }, 8 | "include": ["specs/**/*", "src/**/*"], 9 | "exclude": ["node_modules", "dist"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/data-provider/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "outDir": "./dist/tests", 6 | "baseUrl": "." 7 | }, 8 | "include": ["specs/**/*", "src/**/*"], 9 | "exclude": ["node_modules", "dist"] 10 | } 11 | -------------------------------------------------------------------------------- /api/server/routes/balance.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const controller = require('../controllers/Balance'); 4 | const { requireJwtAuth } = require('../middleware/'); 5 | 6 | router.get('/', requireJwtAuth, controller); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /packages/data-schemas/src/types/banner.ts: -------------------------------------------------------------------------------- 1 | import type { Document } from 'mongoose'; 2 | 3 | export interface IBanner extends Document { 4 | bannerId: string; 5 | message: string; 6 | displayFrom: Date; 7 | displayTo?: Date; 8 | type: 'banner' | 'popup'; 9 | isPublic: boolean; 10 | } 11 | -------------------------------------------------------------------------------- /client/src/components/Files/FileList/EmptyFilePreview.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function EmptyFilePreview() { 4 | return ( 5 |
6 | Select a file to view details. 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /client/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_ENABLE_LOGGER: string; 5 | readonly VITE_LOGGER_FILTER: string; 6 | // Add other env variables here 7 | } 8 | 9 | interface ImportMeta { 10 | readonly env: ImportMetaEnv; 11 | } 12 | -------------------------------------------------------------------------------- /helm/librechat/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.librechat.configYamlContent }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "librechat.fullname" $ }}-config 6 | data: 7 | librechat.yaml: | 8 | {{ .Values.librechat.configYamlContent | toYaml | indent 4 }} 9 | 10 | {{- end }} -------------------------------------------------------------------------------- /packages/data-provider/react-query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "librechat-data-provider/react-query", 3 | "private": true, 4 | "main": "../index.js", 5 | "module": "./index.es.js", 6 | "types": "../dist/types/react-query/index.d.ts", 7 | "dependencies": { 8 | "axios": "^1.7.7" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /api/server/middleware/noIndex.js: -------------------------------------------------------------------------------- 1 | const noIndex = (req, res, next) => { 2 | const shouldNoIndex = process.env.NO_INDEX ? process.env.NO_INDEX === 'true' : true; 3 | 4 | if (shouldNoIndex) { 5 | res.setHeader('X-Robots-Tag', 'noindex'); 6 | } 7 | 8 | next(); 9 | }; 10 | 11 | module.exports = noIndex; 12 | -------------------------------------------------------------------------------- /client/src/components/Prompts/EmptyPromptPreview.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function EmptyPromptPreview() { 4 | return ( 5 |
6 | Select or Create a Prompt 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | func_term() { 4 | echo "Caught SIGTERM signal!" 5 | kill -TERM "$child" 2>/dev/null 6 | } 7 | trap func_term SIGTERM 8 | 9 | npm run backend & 10 | 11 | npm run create-user cosmo@example.com Cosmo Cosmo W3LoveCosmo -- --email-verified=y 12 | 13 | child=$! 14 | wait "$child" 15 | -------------------------------------------------------------------------------- /api/server/controllers/EndpointController.js: -------------------------------------------------------------------------------- 1 | const { getEndpointsConfig } = require('~/server/services/Config'); 2 | 3 | async function endpointController(req, res) { 4 | const endpointsConfig = await getEndpointsConfig(req); 5 | res.send(JSON.stringify(endpointsConfig)); 6 | } 7 | 8 | module.exports = endpointController; 9 | -------------------------------------------------------------------------------- /e2e/setup/global-setup.local.ts: -------------------------------------------------------------------------------- 1 | import { FullConfig } from '@playwright/test'; 2 | import localUser from '../config.local'; 3 | import authenticate from './authenticate'; 4 | 5 | async function globalSetup(config: FullConfig) { 6 | await authenticate(config, localUser); 7 | } 8 | 9 | export default globalSetup; 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/memory.ts: -------------------------------------------------------------------------------- 1 | import memorySchema from '~/schema/memory'; 2 | import type { IMemoryEntry } from '~/types/memory'; 3 | 4 | export function createMemoryModel(mongoose: typeof import('mongoose')) { 5 | return mongoose.models.MemoryEntry || mongoose.model('MemoryEntry', memorySchema); 6 | } 7 | -------------------------------------------------------------------------------- /api/cache/keyvFiles.js: -------------------------------------------------------------------------------- 1 | const { KeyvFile } = require('keyv-file'); 2 | 3 | const logFile = new KeyvFile({ filename: './data/logs.json' }).setMaxListeners(20); 4 | const violationFile = new KeyvFile({ filename: './data/violations.json' }).setMaxListeners(20); 5 | 6 | module.exports = { 7 | logFile, 8 | violationFile, 9 | }; 10 | -------------------------------------------------------------------------------- /api/server/routes/models.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { modelController } = require('~/server/controllers/ModelController'); 3 | const { requireJwtAuth } = require('~/server/middleware/'); 4 | 5 | const router = express.Router(); 6 | router.get('/', requireJwtAuth, modelController); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /api/utils/loadYaml.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const yaml = require('js-yaml'); 3 | 4 | function loadYaml(filepath) { 5 | try { 6 | let fileContents = fs.readFileSync(filepath, 'utf8'); 7 | return yaml.load(fileContents); 8 | } catch (e) { 9 | return e; 10 | } 11 | } 12 | 13 | module.exports = loadYaml; 14 | -------------------------------------------------------------------------------- /client/src/Providers/DashboardContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | type TDashboardContext = { 3 | prevLocationPath: string; 4 | }; 5 | 6 | export const DashboardContext = createContext({} as TDashboardContext); 7 | export const useDashboardContext = () => useContext(DashboardContext); 8 | -------------------------------------------------------------------------------- /client/src/components/Chat/Menus/UI/MenuSeparator.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | 3 | const MenuSeparator: FC = () => ( 4 |
9 | ); 10 | 11 | export default MenuSeparator; 12 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/ui/PlaceholderRow.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | 3 | const PlaceholderRow = memo(({ isCard }: { isCard?: boolean }) => { 4 | if (!isCard) { 5 | return null; 6 | } 7 | return
; 8 | }); 9 | 10 | export default PlaceholderRow; 11 | -------------------------------------------------------------------------------- /client/src/components/Files/VectorStore/EmptyVectorStorePreview.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function EmptyVectorStorePreview() { 4 | return ( 5 |
6 | Select a vector store to view details. 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /api/server/services/Runs/index.js: -------------------------------------------------------------------------------- 1 | const handle = require('./handle'); 2 | const methods = require('./methods'); 3 | const RunManager = require('./RunManager'); 4 | const StreamRunManager = require('./StreamRunManager'); 5 | 6 | module.exports = { 7 | ...handle, 8 | ...methods, 9 | RunManager, 10 | StreamRunManager, 11 | }; 12 | -------------------------------------------------------------------------------- /e2e/setup/global-teardown.local.ts: -------------------------------------------------------------------------------- 1 | import localUser from '../config.local'; 2 | import cleanupUser from './cleanupUser'; 3 | 4 | async function globalTeardown() { 5 | try { 6 | await cleanupUser(localUser); 7 | } catch (error) { 8 | console.error('Error:', error); 9 | } 10 | } 11 | 12 | export default globalTeardown; 13 | -------------------------------------------------------------------------------- /client/src/hooks/Audio/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MediaSourceAppender'; 2 | export { default as useCustomAudioRef } from './useCustomAudioRef'; 3 | export { default as usePauseGlobalAudio } from './usePauseGlobalAudio'; 4 | export { default as useTTSExternal } from './useTTSExternal'; 5 | export { default as useTTSBrowser } from './useTTSBrowser'; 6 | -------------------------------------------------------------------------------- /client/src/Providers/ChatFormContext.tsx: -------------------------------------------------------------------------------- 1 | import { createFormContext } from './CustomFormContext'; 2 | import type { ChatFormValues } from '~/common'; 3 | 4 | const { CustomFormProvider, useCustomFormContext } = createFormContext(); 5 | 6 | export { CustomFormProvider as ChatFormProvider, useCustomFormContext as useChatFormContext }; 7 | -------------------------------------------------------------------------------- /client/src/hooks/Files/useSetFilesToDelete.ts: -------------------------------------------------------------------------------- 1 | import { LocalStorageKeys } from 'librechat-data-provider'; 2 | 3 | export default function useSetFilesToDelete() { 4 | const setFilesToDelete = (files: Record) => 5 | localStorage.setItem(LocalStorageKeys.FILES_TO_DELETE, JSON.stringify(files)); 6 | return setFilesToDelete; 7 | } 8 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/key.ts: -------------------------------------------------------------------------------- 1 | import keySchema, { IKey } from '~/schema/key'; 2 | 3 | /** 4 | * Creates or returns the Key model using the provided mongoose instance and schema 5 | */ 6 | export function createKeyModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.Key || mongoose.model('Key', keySchema); 8 | } 9 | -------------------------------------------------------------------------------- /api/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "CommonJS", 5 | // "checkJs": true, // Report errors in JavaScript files 6 | "baseUrl": "./", 7 | "paths": { 8 | "*": ["*", "node_modules/*"], 9 | "~/*": ["./*"] 10 | } 11 | }, 12 | "exclude": ["node_modules"] 13 | } 14 | -------------------------------------------------------------------------------- /api/server/routes/files/speech/customConfigSpeech.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const { getCustomConfigSpeech } = require('~/server/services/Files/Audio'); 5 | 6 | router.get('/get', async (req, res) => { 7 | await getCustomConfigSpeech(req, res); 8 | }); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /client/src/Providers/ChatContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import useChatHelpers from '~/hooks/Chat/useChatHelpers'; 3 | type TChatContext = ReturnType; 4 | 5 | export const ChatContext = createContext({} as TChatContext); 6 | export const useChatContext = () => useContext(ChatContext); 7 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/CancelledIcon.tsx: -------------------------------------------------------------------------------- 1 | import { X } from 'lucide-react'; 2 | 3 | export default function CancelledIcon() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /api/test/__mocks__/auth.mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "", 4 | "private_key_id": "", 5 | "private_key": "", 6 | "client_email": "", 7 | "client_id": "", 8 | "auth_uri": "", 9 | "token_uri": "", 10 | "auth_provider_x509_cert_url": "", 11 | "client_x509_cert_url": "", 12 | "universe_domain": "" 13 | } 14 | -------------------------------------------------------------------------------- /packages/data-provider/src/headers-helpers.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export function setAcceptLanguageHeader(value: string): void { 4 | axios.defaults.headers.common['Accept-Language'] = value; 5 | } 6 | 7 | export function setTokenHeader(token: string) { 8 | axios.defaults.headers.common['Authorization'] = 'Bearer ' + token; 9 | } 10 | -------------------------------------------------------------------------------- /api/server/services/Files/images/index.js: -------------------------------------------------------------------------------- 1 | const avatar = require('./avatar'); 2 | const convert = require('./convert'); 3 | const encode = require('./encode'); 4 | const parse = require('./parse'); 5 | const resize = require('./resize'); 6 | 7 | module.exports = { 8 | ...convert, 9 | ...encode, 10 | ...parse, 11 | ...resize, 12 | avatar, 13 | }; 14 | -------------------------------------------------------------------------------- /client/src/Providers/FileMapContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import { useFileMap } from '~/hooks/Files'; 3 | type FileMapContextType = ReturnType; 4 | 5 | export const FileMapContext = createContext({} as FileMapContextType); 6 | export const useFileMapContext = () => useContext(FileMapContext); 7 | -------------------------------------------------------------------------------- /client/src/components/Chat/Input/ActiveSetting.tsx: -------------------------------------------------------------------------------- 1 | export default function ActiveSetting() { 2 | return ( 3 |
4 | Talking to{' '} 5 | [latest] Tailwind CSS GPT 6 |
7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/store/toast.ts: -------------------------------------------------------------------------------- 1 | import { atom } from 'recoil'; 2 | import { NotificationSeverity } from '~/common'; 3 | 4 | const toastState = atom({ 5 | key: 'toastState', 6 | default: { 7 | open: false, 8 | message: '', 9 | severity: NotificationSeverity.SUCCESS, 10 | showIcon: true, 11 | }, 12 | }); 13 | 14 | export default { toastState }; 15 | -------------------------------------------------------------------------------- /client/src/components/Conversations/ToggleContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | const defaultFunction: (value: boolean) => void = () => ({}); 4 | export const ToggleContext = createContext({ 5 | setPopoverActive: defaultFunction, 6 | isPopoverActive: false, 7 | }); 8 | 9 | export const useToggle = () => useContext(ToggleContext); 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './crypto'; 2 | export * from './schema'; 3 | export { createModels } from './models'; 4 | export { createMethods } from './methods'; 5 | export type * from './types'; 6 | export type * from './methods'; 7 | export { default as logger } from './config/winston'; 8 | export { default as meiliLogger } from './config/meiliLogger'; 9 | -------------------------------------------------------------------------------- /api/server/routes/plugins.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { getAvailablePluginsController } = require('../controllers/PluginController'); 3 | const requireJwtAuth = require('../middleware/requireJwtAuth'); 4 | 5 | const router = express.Router(); 6 | 7 | router.get('/', requireJwtAuth, getAvailablePluginsController); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /api/server/services/Files/Audio/index.js: -------------------------------------------------------------------------------- 1 | const getCustomConfigSpeech = require('./getCustomConfigSpeech'); 2 | const TTSService = require('./TTSService'); 3 | const STTService = require('./STTService'); 4 | const getVoices = require('./getVoices'); 5 | 6 | module.exports = { 7 | getVoices, 8 | getCustomConfigSpeech, 9 | ...STTService, 10 | ...TTSService, 11 | }; 12 | -------------------------------------------------------------------------------- /client/src/hooks/Files/useFileMap.ts: -------------------------------------------------------------------------------- 1 | import { useGetFiles } from '~/data-provider'; 2 | import { mapFiles } from '~/utils'; 3 | 4 | export default function useFileMap({ isAuthenticated }: { isAuthenticated: boolean }) { 5 | const { data: fileMap } = useGetFiles({ 6 | select: mapFiles, 7 | enabled: isAuthenticated, 8 | }); 9 | 10 | return fileMap; 11 | } 12 | -------------------------------------------------------------------------------- /config/prepare.js: -------------------------------------------------------------------------------- 1 | const { exec } = require('child_process'); 2 | 3 | if (process.env.NODE_ENV !== 'CI') { 4 | exec('npx husky install', (error, stdout, stderr) => { 5 | if (error) { 6 | console.error(`exec error: ${error}`); 7 | return; 8 | } 9 | console.log(`stdout: ${stdout}`); 10 | console.error(`stderr: ${stderr}`); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/preset.ts: -------------------------------------------------------------------------------- 1 | import presetSchema, { IPreset } from '~/schema/preset'; 2 | 3 | /** 4 | * Creates or returns the Preset model using the provided mongoose instance and schema 5 | */ 6 | export function createPresetModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.Preset || mongoose.model('Preset', presetSchema); 8 | } 9 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/prompt.ts: -------------------------------------------------------------------------------- 1 | import promptSchema, { IPrompt } from '~/schema/prompt'; 2 | 3 | /** 4 | * Creates or returns the Prompt model using the provided mongoose instance and schema 5 | */ 6 | export function createPromptModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.Prompt || mongoose.model('Prompt', promptSchema); 8 | } 9 | -------------------------------------------------------------------------------- /api/server/middleware/setHeaders.js: -------------------------------------------------------------------------------- 1 | function setHeaders(req, res, next) { 2 | res.writeHead(200, { 3 | Connection: 'keep-alive', 4 | 'Content-Type': 'text/event-stream', 5 | 'Cache-Control': 'no-cache, no-transform', 6 | 'Access-Control-Allow-Origin': '*', 7 | 'X-Accel-Buffering': 'no', 8 | }); 9 | next(); 10 | } 11 | 12 | module.exports = setHeaders; 13 | -------------------------------------------------------------------------------- /client/src/Providers/AddedChatContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import useAddedResponse from '~/hooks/Chat/useAddedResponse'; 3 | type TAddedChatContext = ReturnType; 4 | 5 | export const AddedChatContext = createContext({} as TAddedChatContext); 6 | export const useAddedChatContext = () => useContext(AddedChatContext); 7 | -------------------------------------------------------------------------------- /client/src/Providers/AgentsMapContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import useAgentsMap from '~/hooks/Agents/useAgentsMap'; 3 | type AgentsMapContextType = ReturnType; 4 | 5 | export const AgentsMapContext = createContext({} as AgentsMapContextType); 6 | export const useAgentsMapContext = () => useContext(AgentsMapContext); 7 | -------------------------------------------------------------------------------- /client/src/hooks/Plugins/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAuthCodeTool } from './useAuthCodeTool'; 2 | export { default as usePluginInstall } from './usePluginInstall'; 3 | export { default as useCodeApiKeyForm } from './useCodeApiKeyForm'; 4 | export { default as useSearchApiKeyForm } from './useSearchApiKeyForm'; 5 | export { default as usePluginDialogHelpers } from './usePluginDialogHelpers'; 6 | -------------------------------------------------------------------------------- /client/src/components/ui/Collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; 2 | 3 | const Collapsible = CollapsiblePrimitive.Root; 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }; 10 | -------------------------------------------------------------------------------- /packages/api/src/types/run.ts: -------------------------------------------------------------------------------- 1 | import type { AgentModelParameters, EModelEndpoint } from 'librechat-data-provider'; 2 | import type { OpenAIConfiguration } from './openai'; 3 | 4 | export type RunLLMConfig = { 5 | provider: EModelEndpoint; 6 | streaming: boolean; 7 | streamUsage: boolean; 8 | usage?: boolean; 9 | configuration?: OpenAIConfiguration; 10 | } & AgentModelParameters; 11 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/project.ts: -------------------------------------------------------------------------------- 1 | import projectSchema, { IMongoProject } from '~/schema/project'; 2 | 3 | /** 4 | * Creates or returns the Project model using the provided mongoose instance and schema 5 | */ 6 | export function createProjectModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.Project || mongoose.model('Project', projectSchema); 8 | } 9 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/role.ts: -------------------------------------------------------------------------------- 1 | import roleSchema from '~/schema/role'; 2 | import type { IRole } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Role model using the provided mongoose instance and schema 6 | */ 7 | export function createRoleModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Role || mongoose.model('Role', roleSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/user.ts: -------------------------------------------------------------------------------- 1 | import userSchema from '~/schema/user'; 2 | import type * as t from '~/types'; 3 | 4 | /** 5 | * Creates or returns the User model using the provided mongoose instance and schema 6 | */ 7 | export function createUserModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.User || mongoose.model('User', userSchema); 9 | } 10 | -------------------------------------------------------------------------------- /api/utils/logger.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston'); 2 | 3 | const logger = winston.createLogger({ 4 | level: 'info', 5 | format: winston.format.combine(winston.format.timestamp(), winston.format.json()), 6 | transports: [ 7 | new winston.transports.Console(), 8 | new winston.transports.File({ filename: 'login-logs.log' }), 9 | ], 10 | }); 11 | 12 | module.exports = logger; 13 | -------------------------------------------------------------------------------- /client/src/components/Auth/ErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | export const ErrorMessage = ({ children }: { children: React.ReactNode }) => ( 2 |
7 | {children} 8 |
9 | ); 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/sharedLink.ts: -------------------------------------------------------------------------------- 1 | import shareSchema, { ISharedLink } from '~/schema/share'; 2 | 3 | /** 4 | * Creates or returns the SharedLink model using the provided mongoose instance and schema 5 | */ 6 | export function createSharedLinkModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.SharedLink || mongoose.model('SharedLink', shareSchema); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/utils/citations.ts: -------------------------------------------------------------------------------- 1 | export const SPAN_REGEX = /(\\ue203.*?\\ue204)/g; 2 | export const COMPOSITE_REGEX = /(\\ue200.*?\\ue201)/g; 3 | export const STANDALONE_PATTERN = /\\ue202turn(\d+)(search|image|news|video|ref)(\d+)/g; 4 | export const CLEANUP_REGEX = /\\ue200|\\ue201|\\ue202|\\ue203|\\ue204|\\ue206/g; 5 | export const INVALID_CITATION_REGEX = /\s*\\ue202turn\d+(search|news|image|video|ref)\d+/g; 6 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/agent.ts: -------------------------------------------------------------------------------- 1 | import agentSchema from '~/schema/agent'; 2 | import type { IAgent } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Agent model using the provided mongoose instance and schema 6 | */ 7 | export function createAgentModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Agent || mongoose.model('Agent', agentSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/file.ts: -------------------------------------------------------------------------------- 1 | import fileSchema from '~/schema/file'; 2 | import type { IMongoFile } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the File model using the provided mongoose instance and schema 6 | */ 7 | export function createFileModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.File || mongoose.model('File', fileSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/token.ts: -------------------------------------------------------------------------------- 1 | import tokenSchema from '~/schema/token'; 2 | import type * as t from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Token model using the provided mongoose instance and schema 6 | */ 7 | export function createTokenModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Token || mongoose.model('Token', tokenSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/toolCall.ts: -------------------------------------------------------------------------------- 1 | import toolCallSchema, { IToolCallData } from '~/schema/toolCall'; 2 | 3 | /** 4 | * Creates or returns the ToolCall model using the provided mongoose instance and schema 5 | */ 6 | export function createToolCallModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.ToolCall || mongoose.model('ToolCall', toolCallSchema); 8 | } 9 | -------------------------------------------------------------------------------- /api/app/clients/tools/structured/credentials.js: -------------------------------------------------------------------------------- 1 | const { getEnvironmentVariable } = require('@langchain/core/utils/env'); 2 | 3 | function getApiKey(envVar, override) { 4 | const key = getEnvironmentVariable(envVar); 5 | if (!key && !override) { 6 | throw new Error(`Missing ${envVar} environment variable.`); 7 | } 8 | return key; 9 | } 10 | 11 | module.exports = { 12 | getApiKey, 13 | }; 14 | -------------------------------------------------------------------------------- /api/server/routes/endpoints.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const endpointController = require('~/server/controllers/EndpointController'); 4 | const overrideController = require('~/server/controllers/OverrideController'); 5 | 6 | router.get('/', endpointController); 7 | router.get('/config/override', overrideController); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /client/src/store/language.ts: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie'; 2 | import { atomWithLocalStorage } from './utils'; 3 | 4 | const defaultLang = () => { 5 | const userLang = navigator.language || navigator.languages[0]; 6 | return Cookies.get('lang') || localStorage.getItem('lang') || userLang; 7 | }; 8 | 9 | const lang = atomWithLocalStorage('lang', defaultLang()); 10 | 11 | export default { lang }; 12 | -------------------------------------------------------------------------------- /client/src/Providers/SearchContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import type { SearchResultData } from 'librechat-data-provider'; 3 | 4 | type SearchContext = { 5 | searchResults?: { [key: string]: SearchResultData }; 6 | }; 7 | 8 | export const SearchContext = createContext({} as SearchContext); 9 | export const useSearchContext = () => useContext(SearchContext); 10 | -------------------------------------------------------------------------------- /client/src/components/Nav/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ExportConversation'; 2 | export * from './SettingsTabs/'; 3 | export { default as MobileNav } from './MobileNav'; 4 | export { default as Nav } from './Nav'; 5 | export { default as NavLink } from './NavLink'; 6 | export { default as NewChat } from './NewChat'; 7 | export { default as SearchBar } from './SearchBar'; 8 | export { default as Settings } from './Settings'; 9 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/action.ts: -------------------------------------------------------------------------------- 1 | import actionSchema from '~/schema/action'; 2 | import type { IAction } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Action model using the provided mongoose instance and schema 6 | */ 7 | export function createActionModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Action || mongoose.model('Action', actionSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/banner.ts: -------------------------------------------------------------------------------- 1 | import bannerSchema from '~/schema/banner'; 2 | import type { IBanner } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Banner model using the provided mongoose instance and schema 6 | */ 7 | export function createBannerModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Banner || mongoose.model('Banner', bannerSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/pluginAuth.ts: -------------------------------------------------------------------------------- 1 | import pluginAuthSchema, { IPluginAuth } from '~/schema/pluginAuth'; 2 | 3 | /** 4 | * Creates or returns the PluginAuth model using the provided mongoose instance and schema 5 | */ 6 | export function createPluginAuthModel(mongoose: typeof import('mongoose')) { 7 | return mongoose.models.PluginAuth || mongoose.model('PluginAuth', pluginAuthSchema); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/components/ui/Skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | function Skeleton({ className, ...props }: React.HTMLAttributes) { 4 | return ( 5 |
12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /client/src/store/user.ts: -------------------------------------------------------------------------------- 1 | import { atom } from 'recoil'; 2 | import type { TUser, TPlugin } from 'librechat-data-provider'; 3 | 4 | const user = atom({ 5 | key: 'user', 6 | default: undefined, 7 | }); 8 | 9 | const availableTools = atom>({ 10 | key: 'availableTools', 11 | default: {}, 12 | }); 13 | 14 | export default { 15 | user, 16 | availableTools, 17 | }; 18 | -------------------------------------------------------------------------------- /helm/librechat-rag-api/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "rag.fullname" $ | lower}}-config 5 | data: 6 | POSTGRES_DB: {{ .Values.postgresql.auth.database }} 7 | POSTGRES_USER: {{ .Values.postgresql.auth.username }} 8 | DB_HOST: {{ .Release.Name }}-postgresql.{{ .Release.Namespace | lower }}.svc.cluster.local 9 | {{- toYaml .Values.rag.configEnv | nindent 2 }} -------------------------------------------------------------------------------- /packages/data-schemas/src/models/balance.ts: -------------------------------------------------------------------------------- 1 | import balanceSchema from '~/schema/balance'; 2 | import type * as t from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Balance model using the provided mongoose instance and schema 6 | */ 7 | export function createBalanceModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Balance || mongoose.model('Balance', balanceSchema); 9 | } 10 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/session.ts: -------------------------------------------------------------------------------- 1 | import sessionSchema from '~/schema/session'; 2 | import type * as t from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Session model using the provided mongoose instance and schema 6 | */ 7 | export function createSessionModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Session || mongoose.model('Session', sessionSchema); 9 | } 10 | -------------------------------------------------------------------------------- /client/src/Providers/BookmarkContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import type { TConversationTag } from 'librechat-data-provider'; 3 | 4 | type TBookmarkContext = { bookmarks: TConversationTag[] }; 5 | 6 | export const BookmarkContext = createContext({ 7 | bookmarks: [], 8 | } as TBookmarkContext); 9 | export const useBookmarkContext = () => useContext(BookmarkContext); 10 | -------------------------------------------------------------------------------- /api/utils/index.js: -------------------------------------------------------------------------------- 1 | const loadYaml = require('./loadYaml'); 2 | const tokenHelpers = require('./tokens'); 3 | const deriveBaseURL = require('./deriveBaseURL'); 4 | const extractBaseURL = require('./extractBaseURL'); 5 | const findMessageContent = require('./findMessageContent'); 6 | 7 | module.exports = { 8 | loadYaml, 9 | deriveBaseURL, 10 | extractBaseURL, 11 | ...tokenHelpers, 12 | findMessageContent, 13 | }; 14 | -------------------------------------------------------------------------------- /client/src/store/preset.ts: -------------------------------------------------------------------------------- 1 | import { atom } from 'recoil'; 2 | import { TPreset } from 'librechat-data-provider'; 3 | 4 | const defaultPreset = atom({ 5 | key: 'defaultPreset', 6 | default: null, 7 | }); 8 | 9 | const presetModalVisible = atom({ 10 | key: 'presetModalVisible', 11 | default: false, 12 | }); 13 | 14 | export default { 15 | defaultPreset, 16 | presetModalVisible, 17 | }; 18 | -------------------------------------------------------------------------------- /e2e/setup/global-teardown.ts: -------------------------------------------------------------------------------- 1 | import cleanupUser from './cleanupUser'; 2 | 3 | async function globalTeardown() { 4 | const user = { 5 | email: String(process.env.E2E_USER_EMAIL), 6 | password: String(process.env.E2E_USER_PASSWORD), 7 | }; 8 | 9 | try { 10 | await cleanupUser(user); 11 | } catch (error) { 12 | console.error('Error:', error); 13 | } 14 | } 15 | 16 | export default globalTeardown; 17 | -------------------------------------------------------------------------------- /client/src/Providers/AssistantsMapContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import { useAssistantsMap } from '~/hooks/Assistants'; 3 | type AssistantsMapContextType = ReturnType; 4 | 5 | export const AssistantsMapContext = createContext( 6 | {} as AssistantsMapContextType, 7 | ); 8 | export const useAssistantsMapContext = () => useContext(AssistantsMapContext); 9 | -------------------------------------------------------------------------------- /client/src/Providers/MessageContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | type MessageContext = { 3 | messageId: string; 4 | nextType?: string; 5 | partIndex?: number; 6 | isExpanded: boolean; 7 | conversationId?: string | null; 8 | }; 9 | 10 | export const MessageContext = createContext({} as MessageContext); 11 | export const useMessageContext = () => useContext(MessageContext); 12 | -------------------------------------------------------------------------------- /config/translations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": false, 4 | "baseUrl": ".", 5 | "outDir": "./dist", 6 | "strict": true, 7 | "moduleResolution": "node", 8 | "esModuleInterop": true, 9 | "target": "es6", 10 | "module": "esnext", 11 | "lib": ["dom", "es6"], 12 | "paths": { 13 | "~/*": ["../../api/*"] 14 | } 15 | }, 16 | "include": ["*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /e2e/setup/global-setup.ts: -------------------------------------------------------------------------------- 1 | import { FullConfig } from '@playwright/test'; 2 | import authenticate from './authenticate'; 3 | 4 | async function globalSetup(config: FullConfig) { 5 | const user = { 6 | name: 'test', 7 | email: String(process.env.E2E_USER_EMAIL), 8 | password: String(process.env.E2E_USER_PASSWORD), 9 | }; 10 | 11 | await authenticate(config, user); 12 | } 13 | 14 | export default globalSetup; 15 | -------------------------------------------------------------------------------- /utils/docker/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ "$1" = -x ] && shift && set -x 3 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 4 | 5 | cd ${DIR}/../.. 6 | 7 | TAG=$1 8 | 9 | if [[ -z "${TAG}" ]]; then 10 | TAG=${LIBRE_CHAT_DOCKER_TAG} 11 | fi 12 | 13 | if [[ -z "${TAG}" ]]; then 14 | TAG=latest 15 | fi 16 | 17 | LOCAL_DOCKER_IMG=librechat:${TAG} 18 | 19 | set -e 20 | 21 | docker build -t ${LOCAL_DOCKER_IMG} . 22 | -------------------------------------------------------------------------------- /client/src/hooks/Chat/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useChatHelpers } from './useChatHelpers'; 2 | export { default as useAddedHelpers } from './useAddedHelpers'; 3 | export { default as useAddedResponse } from './useAddedResponse'; 4 | export { default as useChatFunctions } from './useChatFunctions'; 5 | export { default as useIdChangeEffect } from './useIdChangeEffect'; 6 | export { default as useFocusChatEffect } from './useFocusChatEffect'; 7 | -------------------------------------------------------------------------------- /client/src/utils/cn.ts: -------------------------------------------------------------------------------- 1 | import { twMerge } from 'tailwind-merge'; 2 | import { type ClassValue, clsx } from 'clsx'; 3 | 4 | /** 5 | * Merges the tailwind clases (using twMerge). Conditionally removes false values 6 | * @param inputs The tailwind classes to merge 7 | * @returns className string to apply to an element or HOC 8 | */ 9 | export default function cn(...inputs: ClassValue[]) { 10 | return twMerge(clsx(inputs)); 11 | } 12 | -------------------------------------------------------------------------------- /client/src/components/Bookmarks/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DeleteBookmarkButton } from './DeleteBookmarkButton'; 2 | export { default as EditBookmarkButton } from './EditBookmarkButton'; 3 | export { default as BookmarkEditDialog } from './BookmarkEditDialog'; 4 | export { default as BookmarkItems } from './BookmarkItems'; 5 | export { default as BookmarkItem } from './BookmarkItem'; 6 | export { default as BookmarkForm } from './BookmarkForm'; 7 | -------------------------------------------------------------------------------- /client/test/matchMedia.mock: -------------------------------------------------------------------------------- 1 | Object.defineProperty(window, 'matchMedia', { 2 | writable: true, 3 | value: jest.fn().mockImplementation((query) => ({ 4 | matches: false, 5 | media: query, 6 | onchange: null, 7 | addListener: jest.fn(), // deprecated 8 | removeListener: jest.fn(), // deprecated 9 | addEventListener: jest.fn(), 10 | removeEventListener: jest.fn(), 11 | dispatchEvent: jest.fn(), 12 | })), 13 | }); -------------------------------------------------------------------------------- /packages/data-schemas/src/models/assistant.ts: -------------------------------------------------------------------------------- 1 | import assistantSchema from '~/schema/assistant'; 2 | import type { IAssistant } from '~/types'; 3 | 4 | /** 5 | * Creates or returns the Assistant model using the provided mongoose instance and schema 6 | */ 7 | export function createAssistantModel(mongoose: typeof import('mongoose')) { 8 | return mongoose.models.Assistant || mongoose.model('Assistant', assistantSchema); 9 | } 10 | -------------------------------------------------------------------------------- /api/server/middleware/roles/admin.js: -------------------------------------------------------------------------------- 1 | const { SystemRoles } = require('librechat-data-provider'); 2 | 3 | function checkAdmin(req, res, next) { 4 | try { 5 | if (req.user.role !== SystemRoles.ADMIN) { 6 | return res.status(403).json({ message: 'Forbidden' }); 7 | } 8 | next(); 9 | } catch (error) { 10 | res.status(500).json({ message: 'Internal Server Error' }); 11 | } 12 | } 13 | 14 | module.exports = checkAdmin; 15 | -------------------------------------------------------------------------------- /packages/api/src/index.ts: -------------------------------------------------------------------------------- 1 | /* MCP */ 2 | export * from './mcp/manager'; 3 | /* Utilities */ 4 | export * from './mcp/utils'; 5 | export * from './utils'; 6 | /* Flow */ 7 | export * from './flow/manager'; 8 | /* Agents */ 9 | export * from './agents'; 10 | /* Endpoints */ 11 | export * from './endpoints'; 12 | /* Files */ 13 | export * from './files'; 14 | /* types */ 15 | export type * from './mcp/types'; 16 | export type * from './flow/types'; 17 | -------------------------------------------------------------------------------- /client/src/components/Plugins/Store/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PluginStoreDialog } from './PluginStoreDialog'; 2 | export { default as PluginStoreItem } from './PluginStoreItem'; 3 | export { default as PluginPagination } from './PluginPagination'; 4 | export { default as PluginStoreLinkButton } from './PluginStoreLinkButton'; 5 | export { default as PluginAuthForm } from './PluginAuthForm'; 6 | export { default as PluginTooltip } from './PluginTooltip'; 7 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/transaction.ts: -------------------------------------------------------------------------------- 1 | import transactionSchema, { ITransaction } from '~/schema/transaction'; 2 | 3 | /** 4 | * Creates or returns the Transaction model using the provided mongoose instance and schema 5 | */ 6 | export function createTransactionModel(mongoose: typeof import('mongoose')) { 7 | return ( 8 | mongoose.models.Transaction || mongoose.model('Transaction', transactionSchema) 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /packages/data-schemas/src/types/assistant.ts: -------------------------------------------------------------------------------- 1 | import { Document, Types } from 'mongoose'; 2 | 3 | export interface IAssistant extends Document { 4 | user: Types.ObjectId; 5 | assistant_id: string; 6 | avatar?: { 7 | filepath: string; 8 | source: string; 9 | }; 10 | conversation_starters?: string[]; 11 | access_level?: number; 12 | file_ids?: string[]; 13 | actions?: string[]; 14 | append_current_datetime?: boolean; 15 | } 16 | -------------------------------------------------------------------------------- /packages/data-schemas/src/types/balance.ts: -------------------------------------------------------------------------------- 1 | import { Document, Types } from 'mongoose'; 2 | 3 | export interface IBalance extends Document { 4 | user: Types.ObjectId; 5 | tokenCredits: number; 6 | // Automatic refill settings 7 | autoRefillEnabled: boolean; 8 | refillIntervalValue: number; 9 | refillIntervalUnit: 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'; 10 | lastRefill: Date; 11 | refillAmount: number; 12 | } 13 | -------------------------------------------------------------------------------- /api/server/services/cleanup.js: -------------------------------------------------------------------------------- 1 | const { logger } = require('~/config'); 2 | const { deleteNullOrEmptyConversations } = require('~/models/Conversation'); 3 | const cleanup = async () => { 4 | try { 5 | await deleteNullOrEmptyConversations(); 6 | } catch (error) { 7 | logger.error('[cleanup] Error during app cleanup', error); 8 | } finally { 9 | logger.debug('Startup cleanup complete'); 10 | } 11 | }; 12 | 13 | module.exports = { cleanup }; 14 | -------------------------------------------------------------------------------- /api/server/middleware/validateRegistration.js: -------------------------------------------------------------------------------- 1 | const { isEnabled } = require('~/server/utils'); 2 | 3 | function validateRegistration(req, res, next) { 4 | if (req.invite) { 5 | return next(); 6 | } 7 | 8 | if (isEnabled(process.env.ALLOW_REGISTRATION)) { 9 | next(); 10 | } else { 11 | return res.status(403).json({ 12 | message: 'Registration is not allowed.', 13 | }); 14 | } 15 | } 16 | 17 | module.exports = validateRegistration; 18 | -------------------------------------------------------------------------------- /client/src/components/Auth/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Login } from './Login'; 2 | export { default as Registration } from './Registration'; 3 | export { default as ResetPassword } from './ResetPassword'; 4 | export { default as VerifyEmail } from './VerifyEmail'; 5 | export { default as ApiErrorWatcher } from './ApiErrorWatcher'; 6 | export { default as RequestPasswordReset } from './RequestPasswordReset'; 7 | export { default as TwoFactorScreen } from './TwoFactorScreen'; 8 | -------------------------------------------------------------------------------- /client/scripts/post-build.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | 3 | async function postBuild() { 4 | try { 5 | await fs.copy('public/assets', 'dist/assets'); 6 | await fs.copy('public/robots.txt', 'dist/robots.txt'); 7 | console.log('✅ PWA icons and robots.txt copied successfully. Glob pattern warnings resolved.'); 8 | } catch (err) { 9 | console.error('❌ Error copying files:', err); 10 | process.exit(1); 11 | } 12 | } 13 | 14 | postBuild(); 15 | -------------------------------------------------------------------------------- /helm/librechat/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/promptGroup.ts: -------------------------------------------------------------------------------- 1 | import promptGroupSchema, { IPromptGroupDocument } from '~/schema/promptGroup'; 2 | 3 | /** 4 | * Creates or returns the PromptGroup model using the provided mongoose instance and schema 5 | */ 6 | export function createPromptGroupModel(mongoose: typeof import('mongoose')) { 7 | return ( 8 | mongoose.models.PromptGroup || 9 | mongoose.model('PromptGroup', promptGroupSchema) 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /client/src/data-provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Auth'; 2 | export * from './Agents'; 3 | export * from './Endpoints'; 4 | export * from './Files'; 5 | /* Memories */ 6 | export * from './Memories'; 7 | export * from './Messages'; 8 | export * from './Misc'; 9 | export * from './Tools'; 10 | export * from './connection'; 11 | export * from './mutations'; 12 | export * from './prompts'; 13 | export * from './queries'; 14 | export * from './roles'; 15 | export * from './tags'; 16 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Launch LibreChat (debug)", 8 | "skipFiles": ["/**"], 9 | "program": "${workspaceFolder}/api/server/index.js", 10 | "env": { 11 | "NODE_ENV": "production" 12 | }, 13 | "console": "integratedTerminal", 14 | "envFile": "${workspaceFolder}/.env" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /helm/librechat-rag-api/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "rag.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "rag.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "rag.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /api/server/middleware/validatePasswordReset.js: -------------------------------------------------------------------------------- 1 | const { isEnabled } = require('~/server/utils'); 2 | const { logger } = require('~/config'); 3 | 4 | function validatePasswordReset(req, res, next) { 5 | if (isEnabled(process.env.ALLOW_PASSWORD_RESET)) { 6 | next(); 7 | } else { 8 | logger.warn(`Password reset attempt while not allowed. IP: ${req.ip}`); 9 | res.status(403).send('Password reset is not allowed.'); 10 | } 11 | } 12 | 13 | module.exports = validatePasswordReset; 14 | -------------------------------------------------------------------------------- /client/src/a11y/LiveMessenger.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnnouncerContext from '~/Providers/AnnouncerContext'; 3 | 4 | interface LiveMessengerProps { 5 | children: (context: React.ContextType) => React.ReactNode; 6 | } 7 | 8 | const LiveMessenger: React.FC = ({ children }) => ( 9 | {(contextProps) => children(contextProps)} 10 | ); 11 | 12 | export default LiveMessenger; 13 | -------------------------------------------------------------------------------- /helm/librechat/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "librechat.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "librechat.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "librechat.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /packages/data-schemas/src/schema/categories.ts: -------------------------------------------------------------------------------- 1 | import { Schema, Document } from 'mongoose'; 2 | 3 | export interface ICategory extends Document { 4 | label: string; 5 | value: string; 6 | } 7 | 8 | const categoriesSchema = new Schema({ 9 | label: { 10 | type: String, 11 | required: true, 12 | unique: true, 13 | }, 14 | value: { 15 | type: String, 16 | required: true, 17 | unique: true, 18 | }, 19 | }); 20 | 21 | export default categoriesSchema; 22 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Speech/STT/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AutoSendTextSelector } from './AutoSendTextSelector'; 2 | export { default as SpeechToTextSwitch } from './SpeechToTextSwitch'; 3 | export { default as EngineSTTDropdown } from './EngineSTTDropdown'; 4 | export { default as DecibelSelector } from './DecibelSelector'; 5 | export { default as AutoTranscribeAudioSwitch } from './AutoTranscribeAudioSwitch'; 6 | export { default as LanguageSTTDropdown } from './LanguageSTTDropdown'; 7 | -------------------------------------------------------------------------------- /client/src/hooks/Files/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useDeleteFilesFromTable } from './useDeleteFilesFromTable'; 2 | export { default as useSetFilesToDelete } from './useSetFilesToDelete'; 3 | export { default as useFileHandling } from './useFileHandling'; 4 | export { default as useFileDeletion } from './useFileDeletion'; 5 | export { default as useUpdateFiles } from './useUpdateFiles'; 6 | export { default as useDragHelpers } from './useDragHelpers'; 7 | export { default as useFileMap } from './useFileMap'; 8 | -------------------------------------------------------------------------------- /packages/data-schemas/src/models/conversationTag.ts: -------------------------------------------------------------------------------- 1 | import conversationTagSchema, { IConversationTag } from '~/schema/conversationTag'; 2 | 3 | /** 4 | * Creates or returns the ConversationTag model using the provided mongoose instance and schema 5 | */ 6 | export function createConversationTagModel(mongoose: typeof import('mongoose')) { 7 | return ( 8 | mongoose.models.ConversationTag || 9 | mongoose.model('ConversationTag', conversationTagSchema) 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "dockerComposeFile": "docker-compose.yml", 3 | "service": "app", 4 | "workspaceFolder": "/workspaces", 5 | "customizations": { 6 | "vscode": { 7 | "extensions": [], 8 | "settings": { 9 | "terminal.integrated.profiles.linux": { 10 | "bash": null 11 | } 12 | } 13 | } 14 | }, 15 | "postCreateCommand": "", 16 | "features": { "ghcr.io/devcontainers/features/git:1": {} }, 17 | "remoteUser": "vscode" 18 | } 19 | -------------------------------------------------------------------------------- /client/public/assets/c.svg: -------------------------------------------------------------------------------- 1 | C -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/InProgressCall.tsx: -------------------------------------------------------------------------------- 1 | import CancelledIcon from './CancelledIcon'; 2 | 3 | export default function InProgressCall({ 4 | error, 5 | isSubmitting, 6 | progress, 7 | children, 8 | }: { 9 | error?: boolean; 10 | isSubmitting: boolean; 11 | progress: number; 12 | children: React.ReactNode; 13 | }) { 14 | if ((!isSubmitting && progress < 1) || error === true) { 15 | return ; 16 | } 17 | 18 | return <>{children}; 19 | } 20 | -------------------------------------------------------------------------------- /api/server/routes/assistants/documents.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const controllers = require('~/server/controllers/assistants/v1'); 3 | 4 | const router = express.Router(); 5 | 6 | /** 7 | * Returns a list of the user's assistant documents (metadata saved to database). 8 | * @route GET /assistants/documents 9 | * @returns {AssistantDocument[]} 200 - success response - application/json 10 | */ 11 | router.get('/', controllers.getAssistantDocuments); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /api/test/.env.test.example: -------------------------------------------------------------------------------- 1 | # Test DB URI. You can use your actual MONGO_URI if you don't mind it potentially including test data. 2 | MONGO_URI=mongodb://127.0.0.1:27017/chatgpt-jest 3 | 4 | # Credential encryption/decryption for testing 5 | CREDS_KEY=c3301ad2f69681295e022fb135e92787afb6ecfeaa012a10f8bb4ddf6b669e6d 6 | CREDS_IV=cd02538f4be2fa37aba9420b5924389f 7 | 8 | # For testing the ChatAgent 9 | OPENAI_API_KEY=your-api-key 10 | 11 | BAN_VIOLATIONS=true 12 | BAN_DURATION=7200000 13 | BAN_INTERVAL=20 14 | -------------------------------------------------------------------------------- /helm/librechat-rag-api/templates/vectordb-secret.yaml: -------------------------------------------------------------------------------- 1 | {{ if not .Values.postgresql.auth.existingSecret }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: librechat-vectordb 6 | type: Opaque 7 | data: 8 | # generate 32 chars long random string, base64 encode it and then double-quote the result string. 9 | postgres-password: {{ randAlphaNum 32 | b64enc | quote }} 10 | password: {{ randAlphaNum 32 | b64enc | quote }} 11 | replication-password: {{ randAlphaNum 32 | b64enc | quote }} 12 | {{ end }} -------------------------------------------------------------------------------- /api/server/routes/banner.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const { getBanner } = require('~/models/Banner'); 4 | const optionalJwtAuth = require('~/server/middleware/optionalJwtAuth'); 5 | const router = express.Router(); 6 | 7 | router.get('/', optionalJwtAuth, async (req, res) => { 8 | try { 9 | res.status(200).send(await getBanner(req.user)); 10 | } catch (error) { 11 | res.status(500).json({ message: 'Error getting banner' }); 12 | } 13 | }); 14 | 15 | module.exports = router; 16 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Files/Panel.tsx: -------------------------------------------------------------------------------- 1 | import type { TFile } from 'librechat-data-provider'; 2 | import { useGetFiles } from '~/data-provider'; 3 | import { columns } from './PanelColumns'; 4 | import DataTable from './PanelTable'; 5 | 6 | export default function FilesPanel() { 7 | const { data: files = [] } = useGetFiles(); 8 | 9 | return ( 10 |
11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /client/src/components/ui/QuestionMark.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | export const QuestionMark = ({ className = '' }) => { 3 | return ( 4 | 5 |
11 | ? 12 |
13 |
14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /api/test/jestSetup.js: -------------------------------------------------------------------------------- 1 | // See .env.test.example for an example of the '.env.test' file. 2 | require('dotenv').config({ path: './test/.env.test' }); 3 | 4 | process.env.MONGO_URI = 'mongodb://127.0.0.1:27017/dummy-uri'; 5 | process.env.BAN_VIOLATIONS = 'true'; 6 | process.env.BAN_DURATION = '7200000'; 7 | process.env.BAN_INTERVAL = '20'; 8 | process.env.CI = 'true'; 9 | process.env.JWT_SECRET = 'test'; 10 | process.env.JWT_REFRESH_SECRET = 'test'; 11 | process.env.CREDS_KEY = 'test'; 12 | process.env.CREDS_IV = 'test'; 13 | -------------------------------------------------------------------------------- /client/src/components/svg/UserIcon.tsx: -------------------------------------------------------------------------------- 1 | export default function UserIcon() { 2 | return ( 3 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /client/src/hooks/Input/useDebounce.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | function useDebounce(value: string, delay: number) { 4 | const [debouncedValue, setDebouncedValue] = useState(value); 5 | 6 | useEffect(() => { 7 | const handler = setTimeout(() => { 8 | setDebouncedValue(value); 9 | }, delay); 10 | 11 | return () => { 12 | clearTimeout(handler); 13 | }; 14 | }, [value, delay]); 15 | 16 | return debouncedValue; 17 | } 18 | 19 | export default useDebounce; 20 | -------------------------------------------------------------------------------- /packages/data-provider/src/ocr.ts: -------------------------------------------------------------------------------- 1 | import type { TCustomConfig } from '../src/config'; 2 | import { OCRStrategy } from '../src/config'; 3 | 4 | export function loadOCRConfig(config: TCustomConfig['ocr']): TCustomConfig['ocr'] { 5 | const baseURL = config?.baseURL ?? ''; 6 | const apiKey = config?.apiKey ?? ''; 7 | const mistralModel = config?.mistralModel ?? ''; 8 | return { 9 | apiKey, 10 | baseURL, 11 | mistralModel, 12 | strategy: config?.strategy ?? OCRStrategy.MISTRAL_OCR, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /client/src/store/search.ts: -------------------------------------------------------------------------------- 1 | import { atom } from 'recoil'; 2 | 3 | export type SearchState = { 4 | enabled: boolean | null; 5 | query: string; 6 | debouncedQuery: string; 7 | isSearching: boolean; 8 | isTyping: boolean; 9 | }; 10 | 11 | export const search = atom({ 12 | key: 'search', 13 | default: { 14 | enabled: null, 15 | query: '', 16 | debouncedQuery: '', 17 | isSearching: false, 18 | isTyping: false, 19 | }, 20 | }); 21 | 22 | export default { 23 | search, 24 | }; 25 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/Parts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Attachment'; 2 | export * from './OpenAIImageGen'; 3 | 4 | export { default as Text } from './Text'; 5 | export { default as Reasoning } from './Reasoning'; 6 | export { default as EmptyText } from './EmptyText'; 7 | export { default as LogContent } from './LogContent'; 8 | export { default as ExecuteCode } from './ExecuteCode'; 9 | export { default as AgentUpdate } from './AgentUpdate'; 10 | export { default as EditTextPart } from './EditTextPart'; 11 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/SubRow.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | type TSubRowProps = { 4 | children: React.ReactNode; 5 | classes?: string; 6 | subclasses?: string; 7 | onClick?: () => void; 8 | }; 9 | 10 | export default function SubRow({ children, classes = '', onClick }: TSubRowProps) { 11 | return ( 12 |
16 | {children} 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /client/src/components/Endpoints/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Icon } from './Icon'; 2 | export { default as MinimalIcon } from './MinimalIcon'; 3 | export { default as ConvoIcon } from './ConvoIcon'; 4 | export { default as EndpointIcon } from './EndpointIcon'; 5 | export { default as ConvoIconURL } from './ConvoIconURL'; 6 | export { default as EndpointSettings } from './EndpointSettings'; 7 | export { default as SaveAsPresetDialog } from './SaveAsPresetDialog'; 8 | export { default as AlternativeSettings } from './AlternativeSettings'; 9 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Beta/Beta.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import CodeArtifacts from './CodeArtifacts'; 3 | import ChatBadges from './ChatBadges'; 4 | 5 | function Beta() { 6 | return ( 7 |
8 |
9 | 10 |
11 | {/*
12 | 13 |
*/} 14 |
15 | ); 16 | } 17 | 18 | export default memo(Beta); 19 | -------------------------------------------------------------------------------- /packages/api/src/types/azure.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Azure OpenAI configuration interface 3 | */ 4 | export interface AzureOptions { 5 | azureOpenAIApiKey?: string; 6 | azureOpenAIApiInstanceName?: string; 7 | azureOpenAIApiDeploymentName?: string; 8 | azureOpenAIApiVersion?: string; 9 | azureOpenAIBasePath?: string; 10 | } 11 | 12 | /** 13 | * Client with azure property for setting deployment name 14 | */ 15 | export interface GenericClient { 16 | azure: { 17 | azureOpenAIApiDeploymentName?: string; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /client/src/components/Files/DeleteIconButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CrossIcon, TrashIcon } from '~/components/svg'; 3 | import { Button } from '~/components/ui'; 4 | 5 | type DeleteIconButtonProps = { 6 | onClick: () => void; 7 | }; 8 | 9 | export default function DeleteIconButton({ onClick }: DeleteIconButtonProps) { 10 | return ( 11 |
12 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /helm/librechat-rag-api/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "rag.fullname" . }} 5 | labels: 6 | {{- include "rag.labels" . | nindent 4 }} 7 | annotations: 8 | {{- toYaml .Values.service.annotations | nindent 4 }} 9 | spec: 10 | type: {{ .Values.service.type }} 11 | ports: 12 | - port: {{ .Values.service.port }} 13 | targetPort: http 14 | protocol: TCP 15 | name: http 16 | selector: 17 | {{- include "rag.selectorLabels" . | nindent 4 }} 18 | -------------------------------------------------------------------------------- /packages/data-schemas/src/schema/session.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema } from 'mongoose'; 2 | import { ISession } from '~/types'; 3 | 4 | const sessionSchema: Schema = new Schema({ 5 | refreshTokenHash: { 6 | type: String, 7 | required: true, 8 | }, 9 | expiration: { 10 | type: Date, 11 | required: true, 12 | expires: 0, 13 | }, 14 | user: { 15 | type: mongoose.Schema.Types.ObjectId, 16 | ref: 'User', 17 | required: true, 18 | }, 19 | }); 20 | 21 | export default sessionSchema; 22 | -------------------------------------------------------------------------------- /api/app/clients/agents/Functions/addToolDescriptions.js: -------------------------------------------------------------------------------- 1 | const addToolDescriptions = (prefix, tools) => { 2 | const text = tools.reduce((acc, tool) => { 3 | const { name, description_for_model, lc_kwargs } = tool; 4 | const description = description_for_model ?? lc_kwargs?.description_for_model; 5 | if (!description) { 6 | return acc; 7 | } 8 | return acc + `## ${name}\n${description}\n`; 9 | }, '# Tools:\n'); 10 | 11 | return `${prefix}\n${text}`; 12 | }; 13 | 14 | module.exports = addToolDescriptions; 15 | -------------------------------------------------------------------------------- /packages/data-schemas/src/types/index.ts: -------------------------------------------------------------------------------- 1 | import type { Types } from 'mongoose'; 2 | 3 | export type ObjectId = Types.ObjectId; 4 | export * from './user'; 5 | export * from './token'; 6 | export * from './convo'; 7 | export * from './session'; 8 | export * from './balance'; 9 | export * from './banner'; 10 | export * from './message'; 11 | export * from './agent'; 12 | export * from './role'; 13 | export * from './action'; 14 | export * from './assistant'; 15 | export * from './file'; 16 | /* Memories */ 17 | export * from './memory'; 18 | -------------------------------------------------------------------------------- /client/src/components/Plugins/Store/PluginStoreLinkButton.tsx: -------------------------------------------------------------------------------- 1 | type TPluginStoreLinkButtonProps = { 2 | onClick: () => void; 3 | label: string; 4 | }; 5 | 6 | function PluginStoreLinkButton({ onClick, label }: TPluginStoreLinkButtonProps) { 7 | return ( 8 |
13 | {label} 14 |
15 | ); 16 | } 17 | 18 | export default PluginStoreLinkButton; 19 | -------------------------------------------------------------------------------- /client/src/hooks/usePersonalizationAccess.ts: -------------------------------------------------------------------------------- 1 | import { PermissionTypes, Permissions } from 'librechat-data-provider'; 2 | import useHasAccess from './Roles/useHasAccess'; 3 | 4 | export default function usePersonalizationAccess() { 5 | const hasMemoryOptOut = useHasAccess({ 6 | permissionType: PermissionTypes.MEMORIES, 7 | permission: Permissions.OPT_OUT, 8 | }); 9 | 10 | const hasAnyPersonalizationFeature = hasMemoryOptOut; 11 | 12 | return { 13 | hasMemoryOptOut, 14 | hasAnyPersonalizationFeature, 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /helm/librechat/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "librechat.fullname" . }} 5 | labels: 6 | {{- include "librechat.labels" . | nindent 4 }} 7 | annotations: 8 | {{- toYaml .Values.service.annotations | nindent 4 }} 9 | spec: 10 | type: {{ .Values.service.type }} 11 | ports: 12 | - port: {{ .Values.service.port }} 13 | targetPort: http 14 | protocol: TCP 15 | name: http 16 | selector: 17 | {{- include "librechat.selectorLabels" . | nindent 4 }} 18 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tailwindConfig": "./client/tailwind.config.cjs", 3 | "printWidth": 100, 4 | "tabWidth": 2, 5 | "useTabs": false, 6 | "semi": true, 7 | "singleQuote": true, 8 | "trailingComma": "all", 9 | "arrowParens": "always", 10 | "embeddedLanguageFormatting": "auto", 11 | "insertPragma": false, 12 | "proseWrap": "preserve", 13 | "quoteProps": "as-needed", 14 | "requirePragma": false, 15 | "rangeStart": 0, 16 | "endOfLine": "auto", 17 | "jsxSingleQuote": false, 18 | "plugins": ["prettier-plugin-tailwindcss"] 19 | } -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Speech/TTS/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CloudBrowserVoicesSwitch } from './CloudBrowserVoicesSwitch'; 2 | export { default as AutomaticPlaybackSwitch } from './AutomaticPlaybackSwitch'; 3 | export { default as TextToSpeechSwitch } from './TextToSpeechSwitch'; 4 | export { default as EngineTTSDropdown } from './EngineTTSDropdown'; 5 | export { default as CacheTTSSwitch } from './CacheTTSSwitch'; 6 | export { default as VoiceDropdown } from './VoiceDropdown'; 7 | export { default as PlaybackRate } from './PlaybackRate'; 8 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/Container.tsx: -------------------------------------------------------------------------------- 1 | import { TMessage } from 'librechat-data-provider'; 2 | import Files from './Files'; 3 | 4 | const Container = ({ children, message }: { children: React.ReactNode; message?: TMessage }) => ( 5 |
9 | {message?.isCreatedByUser === true && } 10 | {children} 11 |
12 | ); 13 | 14 | export default Container; 15 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Data/RevokeAllKeys.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RevokeKeysButton } from './RevokeKeysButton'; 3 | import { Label } from '~/components/ui'; 4 | import { useLocalize } from '~/hooks'; 5 | 6 | export const RevokeAllKeys = () => { 7 | const localize = useLocalize(); 8 | 9 | return ( 10 |
11 | 12 | 13 |
14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /client/src/components/svg/DarkModeIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function DarkModeIcon() { 4 | return ( 5 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/svg/Files/CodePaths.tsx: -------------------------------------------------------------------------------- 1 | export default function CodePaths() { 2 | return ( 3 | <> 4 | 11 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/Input/Generations/Stop.tsx: -------------------------------------------------------------------------------- 1 | import type { TGenButtonProps } from '~/common'; 2 | import { StopGeneratingIcon } from '~/components/svg'; 3 | import Button from './Button'; 4 | import { useLocalize } from '~/hooks'; 5 | 6 | export default function Stop({ onClick }: TGenButtonProps) { 7 | const localize = useLocalize(); 8 | 9 | return ( 10 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /client/src/components/svg/SquirclePlusIcon.tsx: -------------------------------------------------------------------------------- 1 | export default function SquirclePlusIcon() { 2 | return ( 3 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /api/app/clients/index.js: -------------------------------------------------------------------------------- 1 | const ChatGPTClient = require('./ChatGPTClient'); 2 | const OpenAIClient = require('./OpenAIClient'); 3 | const PluginsClient = require('./PluginsClient'); 4 | const GoogleClient = require('./GoogleClient'); 5 | const TextStream = require('./TextStream'); 6 | const AnthropicClient = require('./AnthropicClient'); 7 | const toolUtils = require('./tools/util'); 8 | 9 | module.exports = { 10 | ChatGPTClient, 11 | OpenAIClient, 12 | PluginsClient, 13 | GoogleClient, 14 | TextStream, 15 | AnthropicClient, 16 | ...toolUtils, 17 | }; 18 | -------------------------------------------------------------------------------- /api/server/routes/categories.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { requireJwtAuth } = require('~/server/middleware'); 4 | const { getCategories } = require('~/models/Categories'); 5 | 6 | router.get('/', requireJwtAuth, async (req, res) => { 7 | try { 8 | const categories = await getCategories(); 9 | res.status(200).send(categories); 10 | } catch (error) { 11 | res.status(500).send({ message: 'Failed to retrieve categories', error: error.message }); 12 | } 13 | }); 14 | 15 | module.exports = router; 16 | -------------------------------------------------------------------------------- /client/src/components/svg/LockIcon.tsx: -------------------------------------------------------------------------------- 1 | export default function LockIcon() { 2 | return ( 3 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /client/src/components/svg/XAIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function XAIcon({ className = '' }) { 4 | return ( 5 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /client/src/components/Input/Generations/Regenerate.tsx: -------------------------------------------------------------------------------- 1 | import type { TGenButtonProps } from '~/common'; 2 | import { RegenerateIcon } from '~/components/svg'; 3 | import Button from './Button'; 4 | import { useLocalize } from '~/hooks'; 5 | 6 | export default function Regenerate({ onClick }: TGenButtonProps) { 7 | const localize = useLocalize(); 8 | 9 | return ( 10 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /client/src/components/Auth/ApiErrorWatcher.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useApiErrorBoundary } from '~/hooks/ApiErrorBoundaryContext'; 3 | import { useNavigate } from 'react-router-dom'; 4 | 5 | const ApiErrorWatcher = () => { 6 | const { error } = useApiErrorBoundary(); 7 | const navigate = useNavigate(); 8 | React.useEffect(() => { 9 | if (error?.response?.status === 500) { 10 | // do something with error 11 | // navigate('/login'); 12 | } 13 | }, [error, navigate]); 14 | 15 | return null; 16 | }; 17 | 18 | export default ApiErrorWatcher; 19 | -------------------------------------------------------------------------------- /client/src/components/svg/SendIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | export default function SendIcon({ size = 24, className = '' }) { 4 | return ( 5 | 12 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /client/src/hooks/useDocumentTitle.ts: -------------------------------------------------------------------------------- 1 | // useDocumentTitle.js 2 | import { useEffect } from 'react'; 3 | 4 | // function useDocumentTitle(title, prevailOnUnmount = false) { 5 | // const defaultTitle = useRef(document.title); 6 | function useDocumentTitle(title: string) { 7 | useEffect(() => { 8 | document.title = title; 9 | }, [title]); 10 | 11 | // useEffect( 12 | // () => () => { 13 | // if (!prevailOnUnmount) { 14 | // document.title = defaultTitle.current; 15 | // } 16 | // }, [] 17 | // ); 18 | } 19 | 20 | export default useDocumentTitle; 21 | -------------------------------------------------------------------------------- /packages/api/src/flow/types.ts: -------------------------------------------------------------------------------- 1 | import type { Logger } from 'winston'; 2 | export type FlowStatus = 'PENDING' | 'COMPLETED' | 'FAILED'; 3 | 4 | export interface FlowMetadata { 5 | [key: string]: unknown; 6 | } 7 | 8 | export interface FlowState { 9 | type: string; 10 | status: FlowStatus; 11 | metadata: FlowMetadata; 12 | createdAt: number; 13 | result?: T; 14 | error?: string; 15 | completedAt?: number; 16 | failedAt?: number; 17 | } 18 | 19 | export interface FlowManagerOptions { 20 | ttl: number; 21 | ci?: boolean; 22 | logger?: Logger; 23 | } 24 | -------------------------------------------------------------------------------- /client/src/components/svg/Files/SheetPaths.tsx: -------------------------------------------------------------------------------- 1 | export default function SheetPaths() { 2 | return ( 3 | <> 4 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /client/public/assets/google.svg: -------------------------------------------------------------------------------- 1 | Gemini -------------------------------------------------------------------------------- /client/src/a11y/Announcer.tsx: -------------------------------------------------------------------------------- 1 | // client/src/a11y/Announcer.tsx 2 | import React from 'react'; 3 | 4 | interface AnnouncerProps { 5 | statusMessage: string; 6 | logMessage: string; 7 | } 8 | 9 | const Announcer: React.FC = ({ statusMessage, logMessage }) => { 10 | return ( 11 |
12 |
13 | {statusMessage} 14 |
15 |
16 | {logMessage} 17 |
18 |
19 | ); 20 | }; 21 | 22 | export default Announcer; 23 | -------------------------------------------------------------------------------- /client/src/components/Messages/Content/SubRow.tsx: -------------------------------------------------------------------------------- 1 | type TSubRowProps = { 2 | children: React.ReactNode; 3 | classes?: string; 4 | subclasses?: string; 5 | onClick?: () => void; 6 | }; 7 | 8 | export default function SubRow({ children, classes = '', subclasses = '', onClick }: TSubRowProps) { 9 | return ( 10 |
11 |
14 | {children} 15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /client/src/components/svg/OpenIDIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function OpenIDIcon() { 4 | return ( 5 | 6 | 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /packages/data-provider/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!/node_modules/'], 3 | coveragePathIgnorePatterns: ['/node_modules/', '/dist/'], 4 | coverageReporters: ['text', 'cobertura'], 5 | testResultsProcessor: 'jest-junit', 6 | moduleNameMapper: { 7 | '^@src/(.*)$': '/src/$1', 8 | }, 9 | // coverageThreshold: { 10 | // global: { 11 | // statements: 58, 12 | // branches: 49, 13 | // functions: 50, 14 | // lines: 57, 15 | // }, 16 | // }, 17 | restoreMocks: true, 18 | }; 19 | -------------------------------------------------------------------------------- /api/server/routes/assistants/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { uaParser, checkBan, requireJwtAuth } = require('~/server/middleware'); 4 | 5 | const { v1 } = require('./v1'); 6 | const chatV1 = require('./chatV1'); 7 | const v2 = require('./v2'); 8 | const chatV2 = require('./chatV2'); 9 | 10 | router.use(requireJwtAuth); 11 | router.use(checkBan); 12 | router.use(uaParser); 13 | router.use('/v1/', v1); 14 | router.use('/v1/chat', chatV1); 15 | router.use('/v2/', v2); 16 | router.use('/v2/chat', chatV2); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /client/src/components/svg/ConvoIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function ConvoIcon() { 4 | return ( 5 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /client/src/hooks/useMediaQuery.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export default function useMediaQuery(query: string) { 4 | const [matches, setMatches] = useState(false); 5 | 6 | useEffect(() => { 7 | const media = window.matchMedia(query); 8 | if (media.matches !== matches) { 9 | setMatches(media.matches); 10 | } 11 | const listener = () => setMatches(media.matches); 12 | media.addEventListener('change', listener); 13 | return () => media.removeEventListener('change', listener); 14 | }, [matches, query]); 15 | 16 | return matches; 17 | } 18 | -------------------------------------------------------------------------------- /client/src/main.jsx: -------------------------------------------------------------------------------- 1 | import 'regenerator-runtime/runtime'; 2 | import { createRoot } from 'react-dom/client'; 3 | import './locales/i18n'; 4 | import App from './App'; 5 | import './style.css'; 6 | import './mobile.css'; 7 | import { ApiErrorBoundaryProvider } from './hooks/ApiErrorBoundaryContext'; 8 | import 'katex/dist/katex.min.css'; 9 | import 'katex/dist/contrib/copy-tex.js'; 10 | 11 | const container = document.getElementById('root'); 12 | const root = createRoot(container); 13 | 14 | root.render( 15 | 16 | 17 | , 18 | ); 19 | -------------------------------------------------------------------------------- /helm/librechat/templates/persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.librechat.imageVolume.enabled }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: {{ include "librechat.fullname" $ }}-images 6 | spec: 7 | accessModes: 8 | - {{ .Values.librechat.imageVolume.accessModes }} 9 | {{- if .Values.librechat.imageVolume.storageClassName }} 10 | storageClassName: {{ .Values.librechat.imageVolume.storageClassName }} 11 | {{- end }} 12 | volumeMode: Filesystem 13 | resources: 14 | requests: 15 | storage: {{ .Values.librechat.imageVolume.size }} 16 | {{- end }} -------------------------------------------------------------------------------- /client/src/components/Endpoints/Settings/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Advanced } from './Advanced'; 2 | export { default as AssistantsSettings } from './Assistants'; 3 | export { default as BedrockSettings } from './Bedrock'; 4 | export { default as OpenAISettings } from './OpenAI'; 5 | export { default as GoogleSettings } from './Google'; 6 | export { default as PluginsSettings } from './Plugins'; 7 | export { default as Examples } from './Examples'; 8 | export { default as AgentSettings } from './AgentSettings'; 9 | export { default as AnthropicSettings } from './Anthropic'; 10 | export * from './settings'; 11 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Bookmarks/BookmarkPanel.tsx: -------------------------------------------------------------------------------- 1 | import { useConversationTagsQuery } from '~/data-provider'; 2 | import { BookmarkContext } from '~/Providers/BookmarkContext'; 3 | import BookmarkTable from './BookmarkTable'; 4 | 5 | const BookmarkPanel = () => { 6 | const { data } = useConversationTagsQuery(); 7 | 8 | return ( 9 |
10 | 11 | 12 | 13 |
14 | ); 15 | }; 16 | export default BookmarkPanel; 17 | -------------------------------------------------------------------------------- /client/src/components/Auth/BlinkAnimation.tsx: -------------------------------------------------------------------------------- 1 | export const BlinkAnimation = ({ 2 | active, 3 | children, 4 | }: { 5 | active: boolean; 6 | children: React.ReactNode; 7 | }) => { 8 | const style = ` 9 | @keyframes blink-animation { 10 | 0%, 11 | 100% { 12 | opacity: 1; 13 | } 14 | 50% { 15 | opacity: 0; 16 | } 17 | }`; 18 | 19 | if (!active) { 20 | return <>{children}; 21 | } 22 | 23 | return ( 24 | <> 25 | 26 |
{children}
27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/index.ts: -------------------------------------------------------------------------------- 1 | export { default as General } from './General/General'; 2 | export { default as Chat } from './Chat/Chat'; 3 | export { default as Data } from './Data/Data'; 4 | export { default as Beta } from './Beta/Beta'; 5 | export { default as Commands } from './Commands/Commands'; 6 | export { RevokeKeysButton } from './Data/RevokeKeysButton'; 7 | export { default as Account } from './Account/Account'; 8 | export { default as Balance } from './Balance/Balance'; 9 | export { default as Speech } from './Speech/Speech'; 10 | export { default as Personalization } from './Personalization'; 11 | -------------------------------------------------------------------------------- /client/src/components/svg/LightningIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | export default function LightningIcon({ className = '' }) { 4 | return ( 5 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/svg/LikeIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function LikeIcon() { 4 | return ( 5 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/SidePanel/Parameters/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DynamicCombobox } from './DynamicCombobox'; 2 | export { default as DynamicDropdown } from './DynamicDropdown'; 3 | export { default as DynamicCheckbox } from './DynamicCheckbox'; 4 | export { default as DynamicTextarea } from './DynamicTextarea'; 5 | export { default as DynamicSlider } from './DynamicSlider'; 6 | export { default as DynamicSwitch } from './DynamicSwitch'; 7 | export { default as DynamicInput } from './DynamicInput'; 8 | export { default as DynamicTags } from './DynamicTags'; 9 | export { default as OptionHoverAlt } from './OptionHover'; 10 | -------------------------------------------------------------------------------- /client/src/components/Files/FileList/UploadFileButton.tsx: -------------------------------------------------------------------------------- 1 | import { PlusIcon } from 'lucide-react'; 2 | import React from 'react'; 3 | import { Button } from '~/components/ui'; 4 | 5 | type UploadFileProps = { 6 | onClick: () => void; 7 | }; 8 | 9 | export default function UploadFileButton({ onClick }: UploadFileProps) { 10 | return ( 11 |
12 | 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /client/src/hooks/Input/useGetAudioSettings.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | import { useRecoilValue } from 'recoil'; 3 | import store from '~/store'; 4 | 5 | const useGetAudioSettings = () => { 6 | const engineSTT = useRecoilValue(store.engineSTT); 7 | const engineTTS = useRecoilValue(store.engineTTS); 8 | 9 | const speechToTextEndpoint = engineSTT; 10 | const textToSpeechEndpoint = engineTTS; 11 | 12 | return useMemo( 13 | () => ({ speechToTextEndpoint, textToSpeechEndpoint }), 14 | [speechToTextEndpoint, textToSpeechEndpoint], 15 | ); 16 | }; 17 | 18 | export default useGetAudioSettings; 19 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/Parts/EmptyText.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | 3 | const EmptyTextPart = memo(() => { 4 | return ( 5 |
6 |
7 |
8 |

9 | 10 |

11 |
12 |
13 |
14 | ); 15 | }); 16 | 17 | export default EmptyTextPart; 18 | -------------------------------------------------------------------------------- /client/src/hooks/Messages/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAvatar } from './useAvatar'; 2 | export { default as useProgress } from './useProgress'; 3 | export { default as useAttachments } from './useAttachments'; 4 | export { default as useSubmitMessage } from './useSubmitMessage'; 5 | export { default as useMessageActions } from './useMessageActions'; 6 | export { default as useMessageProcess } from './useMessageProcess'; 7 | export { default as useMessageHelpers } from './useMessageHelpers'; 8 | export { default as useCopyToClipboard } from './useCopyToClipboard'; 9 | export { default as useMessageScrolling } from './useMessageScrolling'; 10 | -------------------------------------------------------------------------------- /packages/api/jest.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!/node_modules/'], 3 | coveragePathIgnorePatterns: ['/node_modules/', '/dist/'], 4 | coverageReporters: ['text', 'cobertura'], 5 | testResultsProcessor: 'jest-junit', 6 | moduleNameMapper: { 7 | '^@src/(.*)$': '/src/$1', 8 | '~/(.*)': '/src/$1', 9 | }, 10 | // coverageThreshold: { 11 | // global: { 12 | // statements: 58, 13 | // branches: 49, 14 | // functions: 50, 15 | // lines: 57, 16 | // }, 17 | // }, 18 | restoreMocks: true, 19 | testTimeout: 15000, 20 | }; -------------------------------------------------------------------------------- /client/src/Providers/SetConvoContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useRef } from 'react'; 2 | import type { MutableRefObject } from 'react'; 3 | 4 | type SetConvoContext = MutableRefObject; 5 | 6 | export const SetConvoContext = createContext({} as SetConvoContext); 7 | 8 | export const SetConvoProvider = ({ children }: { children: React.ReactNode }) => { 9 | const hasSetConversation = useRef(false); 10 | 11 | return {children}; 12 | }; 13 | 14 | export const useSetConvoContext = () => useContext(SetConvoContext); 15 | -------------------------------------------------------------------------------- /client/src/common/artifacts.ts: -------------------------------------------------------------------------------- 1 | export interface CodeBlock { 2 | id: string; 3 | language: string; 4 | content: string; 5 | } 6 | 7 | export interface Artifact { 8 | id: string; 9 | lastUpdateTime: number; 10 | index?: number; 11 | messageId?: string; 12 | identifier?: string; 13 | language?: string; 14 | content?: string; 15 | title?: string; 16 | type?: string; 17 | } 18 | 19 | export type ArtifactFiles = 20 | | { 21 | 'App.tsx': string; 22 | 'index.tsx': string; 23 | '/components/ui/MermaidDiagram.tsx': string; 24 | } 25 | | Partial<{ 26 | [x: string]: string | undefined; 27 | }>; 28 | -------------------------------------------------------------------------------- /client/src/components/Files/VectorStore/VectorStoreButton.tsx: -------------------------------------------------------------------------------- 1 | import { PlusIcon } from 'lucide-react'; 2 | import React from 'react'; 3 | import { Button } from '~/components/ui'; 4 | 5 | type VectorStoreButtonProps = { 6 | onClick: () => void; 7 | }; 8 | 9 | export default function VectorStoreButton({ onClick }: VectorStoreButtonProps) { 10 | return ( 11 |
12 | 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /client/src/components/svg/DislikeIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function DislikeIcon() { 4 | return ( 5 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/data-schemas/src/crypto/index.ts: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken'; 2 | import { webcrypto } from 'node:crypto'; 3 | import { SignPayloadParams } from '~/types'; 4 | 5 | export async function signPayload({ 6 | payload, 7 | secret, 8 | expirationTime, 9 | }: SignPayloadParams): Promise { 10 | return jwt.sign(payload, secret!, { expiresIn: expirationTime }); 11 | } 12 | 13 | export async function hashToken(str: string): Promise { 14 | const data = new TextEncoder().encode(str); 15 | const hashBuffer = await webcrypto.subtle.digest('SHA-256', data); 16 | return Buffer.from(hashBuffer).toString('hex'); 17 | } 18 | -------------------------------------------------------------------------------- /client/src/components/svg/CrossIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { cn } from '~/utils/'; 3 | 4 | export default function CrossIcon({ className = '' }) { 5 | return ( 6 | 18 | 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /client/src/components/svg/SendMessageIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function SendMessageIcon() { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /client/src/components/svg/ListeningIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils/'; 2 | 3 | export default function ListeningIcon({ className }) { 4 | return ( 5 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/api/src/utils/events.ts: -------------------------------------------------------------------------------- 1 | import type { Response as ServerResponse } from 'express'; 2 | import type { ServerSentEvent } from '~/types'; 3 | 4 | /** 5 | * Sends message data in Server Sent Events format. 6 | * @param res - The server response. 7 | * @param event - The message event. 8 | * @param event.event - The type of event. 9 | * @param event.data - The message to be sent. 10 | */ 11 | export function sendEvent(res: ServerResponse, event: ServerSentEvent): void { 12 | if (typeof event.data === 'string' && event.data.length === 0) { 13 | return; 14 | } 15 | res.write(`event: message\ndata: ${JSON.stringify(event)}\n\n`); 16 | } 17 | -------------------------------------------------------------------------------- /api/server/middleware/validateEndpoint.js: -------------------------------------------------------------------------------- 1 | const { handleError } = require('../utils'); 2 | 3 | function validateEndpoint(req, res, next) { 4 | const { endpoint: _endpoint, endpointType } = req.body; 5 | const endpoint = endpointType ?? _endpoint; 6 | 7 | if (!req.body.text || req.body.text.length === 0) { 8 | return handleError(res, { text: 'Prompt empty or too short' }); 9 | } 10 | 11 | const pathEndpoint = req.baseUrl.split('/')[3]; 12 | 13 | if (endpoint !== pathEndpoint) { 14 | return handleError(res, { text: 'Illegal request: Endpoint mismatch' }); 15 | } 16 | 17 | next(); 18 | } 19 | 20 | module.exports = validateEndpoint; 21 | -------------------------------------------------------------------------------- /api/server/services/Config/ldap.js: -------------------------------------------------------------------------------- 1 | const { isEnabled } = require('~/server/utils'); 2 | 3 | /** @returns {TStartupConfig['ldap'] | undefined} */ 4 | const getLdapConfig = () => { 5 | const ldapLoginEnabled = !!process.env.LDAP_URL && !!process.env.LDAP_USER_SEARCH_BASE; 6 | 7 | const ldap = { 8 | enabled: ldapLoginEnabled, 9 | }; 10 | const ldapLoginUsesUsername = isEnabled(process.env.LDAP_LOGIN_USES_USERNAME); 11 | if (!ldapLoginEnabled) { 12 | return ldap; 13 | } 14 | 15 | if (ldapLoginUsesUsername) { 16 | ldap.username = true; 17 | } 18 | 19 | return ldap; 20 | }; 21 | 22 | module.exports = { 23 | getLdapConfig, 24 | }; 25 | -------------------------------------------------------------------------------- /packages/data-schemas/jest.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!/node_modules/'], 3 | coveragePathIgnorePatterns: ['/node_modules/', '/dist/'], 4 | coverageReporters: ['text', 'cobertura'], 5 | testResultsProcessor: 'jest-junit', 6 | moduleNameMapper: { 7 | '^@src/(.*)$': '/src/$1', 8 | '^~/(.*)$': '/src/$1', 9 | }, 10 | // coverageThreshold: { 11 | // global: { 12 | // statements: 58, 13 | // branches: 49, 14 | // functions: 50, 15 | // lines: 57, 16 | // }, 17 | // }, 18 | restoreMocks: true, 19 | testTimeout: 15000, 20 | }; 21 | -------------------------------------------------------------------------------- /api/server/routes/tokenizer.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const requireJwtAuth = require('~/server/middleware/requireJwtAuth'); 4 | const { countTokens } = require('~/server/utils'); 5 | const { logger } = require('~/config'); 6 | 7 | router.post('/', requireJwtAuth, async (req, res) => { 8 | try { 9 | const { arg } = req.body; 10 | const count = await countTokens(arg?.text ?? arg); 11 | res.send({ count }); 12 | } catch (e) { 13 | logger.error('[/tokenizer] Error counting tokens', e); 14 | res.status(500).json('Error counting tokens'); 15 | } 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /client/src/components/Input/SetKeyDialog/OtherConfig.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import InputWithLabel from './InputWithLabel'; 3 | import type { TConfigProps } from '~/common'; 4 | import { useLocalize } from '~/hooks'; 5 | 6 | const OtherConfig = ({ userKey, setUserKey, endpoint }: TConfigProps) => { 7 | const localize = useLocalize(); 8 | return ( 9 | ) => setUserKey(e.target.value ?? '')} 13 | label={localize('com_endpoint_config_key_name')} 14 | /> 15 | ); 16 | }; 17 | 18 | export default OtherConfig; 19 | -------------------------------------------------------------------------------- /client/src/components/svg/ContinueIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | export default function ContinueIcon({ className = '' }: { className?: string }) { 4 | return ( 5 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/svg/StopGeneratingIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | 3 | export default function StopGeneratingIcon({ className = '' }: { className?: string }) { 4 | return ( 5 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/data-provider/src/types/runs.ts: -------------------------------------------------------------------------------- 1 | export enum ContentTypes { 2 | TEXT = 'text', 3 | THINK = 'think', 4 | TEXT_DELTA = 'text_delta', 5 | TOOL_CALL = 'tool_call', 6 | IMAGE_FILE = 'image_file', 7 | IMAGE_URL = 'image_url', 8 | AGENT_UPDATE = 'agent_update', 9 | ERROR = 'error', 10 | } 11 | 12 | export enum StepTypes { 13 | TOOL_CALLS = 'tool_calls', 14 | MESSAGE_CREATION = 'message_creation', 15 | } 16 | 17 | export enum ToolCallTypes { 18 | FUNCTION = 'function', 19 | RETRIEVAL = 'retrieval', 20 | FILE_SEARCH = 'file_search', 21 | CODE_INTERPRETER = 'code_interpreter', 22 | /* Agents Tool Call */ 23 | TOOL_CALL = 'tool_call', 24 | } 25 | -------------------------------------------------------------------------------- /api/server/routes/files/speech/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { createTTSLimiters, createSTTLimiters } = require('~/server/middleware'); 3 | 4 | const stt = require('./stt'); 5 | const tts = require('./tts'); 6 | const customConfigSpeech = require('./customConfigSpeech'); 7 | 8 | const router = express.Router(); 9 | 10 | const { sttIpLimiter, sttUserLimiter } = createSTTLimiters(); 11 | const { ttsIpLimiter, ttsUserLimiter } = createTTSLimiters(); 12 | router.use('/stt', sttIpLimiter, sttUserLimiter, stt); 13 | router.use('/tts', ttsIpLimiter, ttsUserLimiter, tts); 14 | 15 | router.use('/config', customConfigSpeech); 16 | 17 | module.exports = router; 18 | -------------------------------------------------------------------------------- /packages/data-schemas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "declaration": true, 7 | "declarationDir": "dist/types", 8 | "outDir": "dist", 9 | "strict": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "skipLibCheck": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "resolveJsonModule": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "~/*": ["./src/*"] 19 | } 20 | }, 21 | "include": ["src/**/*"], 22 | "exclude": ["node_modules", "dist", "tests"] 23 | } 24 | -------------------------------------------------------------------------------- /api/server/routes/edit/google.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const EditController = require('~/server/controllers/EditController'); 3 | const { initializeClient } = require('~/server/services/Endpoints/google'); 4 | const { 5 | setHeaders, 6 | validateModel, 7 | validateEndpoint, 8 | buildEndpointOption, 9 | } = require('~/server/middleware'); 10 | 11 | const router = express.Router(); 12 | 13 | router.post( 14 | '/', 15 | validateEndpoint, 16 | validateModel, 17 | buildEndpointOption, 18 | setHeaders, 19 | async (req, res, next) => { 20 | await EditController(req, res, next, initializeClient); 21 | }, 22 | ); 23 | 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /client/src/components/svg/CircleHelpIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils/'; 2 | 3 | export default function CircleHelpIcon({ className = 'icon-md-heavy', size = '1em' }) { 4 | return ( 5 | 17 | 18 | 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /api/server/routes/edit/anthropic.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const EditController = require('~/server/controllers/EditController'); 3 | const { initializeClient } = require('~/server/services/Endpoints/anthropic'); 4 | const { 5 | setHeaders, 6 | validateModel, 7 | validateEndpoint, 8 | buildEndpointOption, 9 | } = require('~/server/middleware'); 10 | 11 | const router = express.Router(); 12 | 13 | router.post( 14 | '/', 15 | validateEndpoint, 16 | validateModel, 17 | buildEndpointOption, 18 | setHeaders, 19 | async (req, res, next) => { 20 | await EditController(req, res, next, initializeClient); 21 | }, 22 | ); 23 | 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/Content/Parts/Stdout.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react'; 2 | 3 | interface StdoutProps { 4 | output?: string; 5 | } 6 | 7 | const Stdout: React.FC = ({ output = '' }) => { 8 | const processedContent = useMemo(() => { 9 | if (!output) { 10 | return ''; 11 | } 12 | 13 | const parts = output.split('Generated files:'); 14 | return parts[0].trim(); 15 | }, [output]); 16 | 17 | return ( 18 | processedContent && ( 19 |
20 |         
{processedContent}
21 |
22 | ) 23 | ); 24 | }; 25 | 26 | export default Stdout; 27 | -------------------------------------------------------------------------------- /client/src/components/Prompts/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PromptName } from './PromptName'; 2 | export { default as PromptsView } from './PromptsView'; 3 | export { default as PromptEditor } from './PromptEditor'; 4 | export { default as PromptForm } from './PromptForm'; 5 | export { default as PreviewLabels } from './PreviewLabels'; 6 | export { default as PromptGroupsList } from './Groups/List'; 7 | export { default as DashGroupItem } from './Groups/DashGroupItem'; 8 | export { default as EmptyPromptPreview } from './EmptyPromptPreview'; 9 | export { default as PromptSidePanel } from './Groups/GroupSidePanel'; 10 | export { default as CreatePromptForm } from './Groups/CreatePromptForm'; 11 | -------------------------------------------------------------------------------- /config/stop-backend.js: -------------------------------------------------------------------------------- 1 | const { promisify } = require('util'); 2 | const { exec } = require('child_process'); 3 | 4 | const isWindows = process.platform === 'win32'; 5 | const execAsync = promisify(exec); 6 | 7 | async function main() { 8 | try { 9 | if (isWindows) { 10 | console.red('The backend process has been terminated'); 11 | await execAsync('taskkill /F /IM node.exe /T'); 12 | } else { 13 | await execAsync('pkill -f api/server/index.js'); 14 | console.orange('The backend process has been terminated'); 15 | } 16 | } catch (err) { 17 | console.red('The backend process has been terminated', err.message); 18 | } 19 | } 20 | 21 | main(); 22 | -------------------------------------------------------------------------------- /utils/docker/docker-push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ "$1" = -x ] && shift && set -x 3 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 4 | 5 | cd ${DIR}/../.. 6 | 7 | TAG=$1 8 | 9 | if [[ -z "${TAG}" ]]; then 10 | TAG=${LIBRE_CHAT_DOCKER_TAG} 11 | fi 12 | 13 | if [[ -z "${TAG}" ]]; then 14 | TAG=latest 15 | fi 16 | 17 | LOCAL_DOCKER_IMG=librechat:${TAG} 18 | 19 | if [[ -z "${DOCKER_REMOTE_REGISTRY}" ]]; then 20 | echo "DOCKER_REMOTE_REGISTRY is not set" >&2 21 | 22 | exit 1 23 | fi 24 | 25 | REMOTE_DOCKER_IMG=${DOCKER_REMOTE_REGISTRY}/${LOCAL_DOCKER_IMG} 26 | 27 | set -e 28 | 29 | docker tag ${LOCAL_DOCKER_IMG} ${REMOTE_DOCKER_IMG} 30 | 31 | docker push ${REMOTE_DOCKER_IMG} 32 | -------------------------------------------------------------------------------- /api/app/clients/tools/.well-known/qrCodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "v1", 3 | "name_for_human": "QR Codes", 4 | "name_for_model": "qrCodes", 5 | "description_for_human": "Create QR codes.", 6 | "description_for_model": "Plugin for generating QR codes.", 7 | "auth": { 8 | "type": "none" 9 | }, 10 | "api": { 11 | "type": "openapi", 12 | "url": "https://chatgpt-qrcode-46d7d4ebefc8.herokuapp.com/openapi.yaml" 13 | }, 14 | "logo_url": "https://chatgpt-qrcode-46d7d4ebefc8.herokuapp.com/logo.png", 15 | "contact_email": "chrismountzou@gmail.com", 16 | "legal_info_url": "https://raw.githubusercontent.com/mountzou/qrCodeGPTv1/master/legal" 17 | } 18 | -------------------------------------------------------------------------------- /client/src/a11y/MessageBlock.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const offScreenStyle: React.CSSProperties = { 4 | border: 0, 5 | clip: 'rect(0 0 0 0)', 6 | height: '1px', 7 | margin: '-1px', 8 | overflow: 'hidden', 9 | whiteSpace: 'nowrap', 10 | padding: 0, 11 | width: '1px', 12 | position: 'absolute', 13 | }; 14 | 15 | interface MessageBlockProps { 16 | message: string; 17 | 'aria-live': 'polite' | 'assertive'; 18 | } 19 | 20 | const MessageBlock: React.FC = ({ message, 'aria-live': ariaLive }) => ( 21 |
22 | {message} 23 |
24 | ); 25 | 26 | export default MessageBlock; 27 | -------------------------------------------------------------------------------- /client/src/components/svg/SpeechIcon.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils/'; 2 | 3 | export default function SpeechIcon({ className }) { 4 | return ( 5 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /client/src/hooks/Conversations/useBookmarkSuccess.ts: -------------------------------------------------------------------------------- 1 | import { useSetRecoilState } from 'recoil'; 2 | import useUpdateTagsInConvo from './useUpdateTagsInConvo'; 3 | import store from '~/store'; 4 | 5 | const useBookmarkSuccess = (conversationId: string) => { 6 | const updateConversation = useSetRecoilState(store.updateConversationSelector(conversationId)); 7 | const { updateTagsInConversation } = useUpdateTagsInConvo(); 8 | 9 | return (newTags: string[]) => { 10 | if (!conversationId) { 11 | return; 12 | } 13 | updateTagsInConversation(conversationId, newTags); 14 | updateConversation({ tags: newTags }); 15 | }; 16 | }; 17 | 18 | export default useBookmarkSuccess; 19 | -------------------------------------------------------------------------------- /client/test/localStorage.mock: -------------------------------------------------------------------------------- 1 | let store = {}; 2 | Object.defineProperty(window, 'localStorage', { 3 | writable: true, 4 | value: { 5 | getItem: jest.fn().mockImplementation((key) => { 6 | if(key in store) { 7 | return store[key]; 8 | } 9 | return null; 10 | }), 11 | setItem: jest.fn().mockImplementation((key, value) => { 12 | store[key] = value.toString(); 13 | }), 14 | clear: jest.fn().mockImplementation(() => { 15 | store = {}; 16 | }), 17 | removeItem: jest.fn().mockImplementation(() => { 18 | delete store[key]; 19 | }), 20 | }, 21 | }); -------------------------------------------------------------------------------- /api/server/routes/ask/google.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const AskController = require('~/server/controllers/AskController'); 3 | const { initializeClient, addTitle } = require('~/server/services/Endpoints/google'); 4 | const { 5 | setHeaders, 6 | validateModel, 7 | validateEndpoint, 8 | buildEndpointOption, 9 | } = require('~/server/middleware'); 10 | 11 | const router = express.Router(); 12 | 13 | router.post( 14 | '/', 15 | validateEndpoint, 16 | validateModel, 17 | buildEndpointOption, 18 | setHeaders, 19 | async (req, res, next) => { 20 | await AskController(req, res, next, initializeClient, addTitle); 21 | }, 22 | ); 23 | 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /api/server/middleware/requireLdapAuth.js: -------------------------------------------------------------------------------- 1 | const passport = require('passport'); 2 | 3 | const requireLdapAuth = (req, res, next) => { 4 | passport.authenticate('ldapauth', (err, user, info) => { 5 | if (err) { 6 | console.log({ 7 | title: '(requireLdapAuth) Error at passport.authenticate', 8 | parameters: [{ name: 'error', value: err }], 9 | }); 10 | return next(err); 11 | } 12 | if (!user) { 13 | console.log({ 14 | title: '(requireLdapAuth) Error: No user', 15 | }); 16 | return res.status(404).send(info); 17 | } 18 | req.user = user; 19 | next(); 20 | })(req, res, next); 21 | }; 22 | module.exports = requireLdapAuth; 23 | -------------------------------------------------------------------------------- /client/src/components/svg/AnthropicMinimalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function AnthropicMinimalIcon() { 4 | return ( 5 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/svg/CautionIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function CautionIcon() { 4 | return ( 5 | 17 | 18 | 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /packages/data-schemas/src/types/file.ts: -------------------------------------------------------------------------------- 1 | import { Document, Types } from 'mongoose'; 2 | 3 | export interface IMongoFile extends Omit { 4 | user: Types.ObjectId; 5 | conversationId?: string; 6 | file_id: string; 7 | temp_file_id?: string; 8 | bytes: number; 9 | text?: string; 10 | filename: string; 11 | filepath: string; 12 | object: 'file'; 13 | embedded?: boolean; 14 | type: string; 15 | context?: string; 16 | usage: number; 17 | source: string; 18 | model?: string; 19 | width?: number; 20 | height?: number; 21 | metadata?: { 22 | fileIdentifier?: string; 23 | }; 24 | expiresAt?: Date; 25 | createdAt?: Date; 26 | updatedAt?: Date; 27 | } 28 | -------------------------------------------------------------------------------- /client/src/components/Files/ActionButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from '~/components/ui'; 3 | import { useLocalize } from '~/hooks'; 4 | 5 | type ActionButtonProps = { 6 | onClick: () => void; 7 | }; 8 | 9 | export default function ActionButton({ onClick }: ActionButtonProps) { 10 | const localize = useLocalize(); 11 | return ( 12 |
13 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /client/src/components/svg/ChatGPTMinimalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function ChatGPTMinimalIcon() { 4 | return ( 5 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /api/app/clients/tools/.well-known/web_search.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "v1", 3 | "name_for_human": "Web Search", 4 | "name_for_model": "web_search", 5 | "description_for_human": "Search for information from the internet", 6 | "description_for_model": "Search for information from the internet", 7 | "auth": { 8 | "type": "none" 9 | }, 10 | "api": { 11 | "type": "openapi", 12 | "url": "https://websearch.plugsugar.com/api/openapi_yaml", 13 | "is_user_authenticated": false 14 | }, 15 | "logo_url": "https://websearch.plugsugar.com/200x200.png", 16 | "contact_email": "support@plugsugar.com", 17 | "legal_info_url": "https://websearch.plugsugar.com/contact" 18 | } 19 | -------------------------------------------------------------------------------- /client/src/Providers/ToastContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import type { TShowToast } from '~/common'; 3 | import useToast from '~/hooks/useToast'; 4 | 5 | type ToastContextType = { 6 | showToast: ({ message, severity, showIcon, duration }: TShowToast) => void; 7 | }; 8 | 9 | export const ToastContext = createContext({ 10 | showToast: () => ({}), 11 | }); 12 | 13 | export function useToastContext() { 14 | return useContext(ToastContext); 15 | } 16 | 17 | export default function ToastProvider({ children }) { 18 | const { showToast } = useToast(); 19 | 20 | return {children}; 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/svg/Blocks.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils'; 2 | export default function Blocks({ className = '' }: { className?: string }) { 3 | return ( 4 | 16 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/svg/DotsIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function DotsIcon({ 4 | className = 'h-4 w-4 flex-shrink-0 text-gray-500', 5 | }: { 6 | className?: string; 7 | }) { 8 | return ( 9 | 21 | 22 | 23 | 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "agentOptions": null, 3 | "defaultPreset": true, 4 | "endpoint": "bedrock", 5 | "isArchived": false, 6 | "maxContextTokens": 444, 7 | "maxTokens": 8192, 8 | "model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", 9 | "modelLabel": "Foobie", 10 | "order": 0, 11 | "region": "us-east-2", 12 | "resendFiles": true, 13 | "system": "Your name is Foobie and you are an international man of mystery. You always end your responses with your catchphrase: \"Foobie out!\"", 14 | "tags": [], 15 | "temperature": 0.53, 16 | "thinking": true, 17 | "thinkingBudget": 2000, 18 | "title": "Foobie2", 19 | "topK": 146, 20 | "topP": 0.72 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/Chat/Input/TextareaHeader.tsx: -------------------------------------------------------------------------------- 1 | import AddedConvo from './AddedConvo'; 2 | import type { TConversation } from 'librechat-data-provider'; 3 | import type { SetterOrUpdater } from 'recoil'; 4 | 5 | export default function TextareaHeader({ 6 | addedConvo, 7 | setAddedConvo, 8 | }: { 9 | addedConvo: TConversation | null; 10 | setAddedConvo: SetterOrUpdater; 11 | }) { 12 | if (!addedConvo) { 13 | return null; 14 | } 15 | return ( 16 |
17 | 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /config/translations/file.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import main from './main'; 3 | 4 | async function processFile(baseFilePath: string, compareFilename: string) { 5 | await main(baseFilePath, compareFilename); 6 | } 7 | 8 | const args = process.argv.slice(-1); 9 | 10 | if (args.length !== 1) { 11 | console.log(process.argv, args); 12 | console.error('Usage: bun file.ts '); 13 | process.exit(1); 14 | } 15 | 16 | const languagesDir = './client/src/localization/languages'; 17 | const baseFilePath = path.resolve(languagesDir, 'Eng.ts'); 18 | 19 | const compareFilename = path.resolve(languagesDir, `${args[0]}.ts`); 20 | 21 | processFile(baseFilePath, compareFilename).catch(console.error); 22 | -------------------------------------------------------------------------------- /client/src/common/selector.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TModelSpec, TStartupConfig } from 'librechat-data-provider'; 3 | 4 | export interface Endpoint { 5 | value: string; 6 | label: string; 7 | hasModels: boolean; 8 | models?: Array<{ name: string; isGlobal?: boolean }>; 9 | icon: React.ReactNode; 10 | agentNames?: Record; 11 | assistantNames?: Record; 12 | modelIcons?: Record; 13 | } 14 | 15 | export interface SelectedValues { 16 | endpoint: string | null; 17 | model: string | null; 18 | modelSpec: string | null; 19 | } 20 | 21 | export interface ModelSelectorProps { 22 | startupConfig: TStartupConfig | undefined; 23 | } 24 | -------------------------------------------------------------------------------- /client/src/hooks/Agents/useAgentsMap.ts: -------------------------------------------------------------------------------- 1 | import { TAgentsMap } from 'librechat-data-provider'; 2 | import { useMemo } from 'react'; 3 | import { useListAgentsQuery } from '~/data-provider'; 4 | import { mapAgents } from '~/utils'; 5 | 6 | export default function useAgentsMap({ 7 | isAuthenticated, 8 | }: { 9 | isAuthenticated: boolean; 10 | }): TAgentsMap | undefined { 11 | const { data: agentsList = null } = useListAgentsQuery(undefined, { 12 | select: (res) => mapAgents(res.data), 13 | enabled: isAuthenticated, 14 | }); 15 | 16 | const agents = useMemo(() => { 17 | return agentsList !== null ? agentsList : undefined; 18 | }, [agentsList]); 19 | 20 | return agents; 21 | } 22 | -------------------------------------------------------------------------------- /api/server/routes/ask/anthropic.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const AskController = require('~/server/controllers/AskController'); 3 | const { addTitle, initializeClient } = require('~/server/services/Endpoints/anthropic'); 4 | const { 5 | setHeaders, 6 | handleAbort, 7 | validateModel, 8 | validateEndpoint, 9 | buildEndpointOption, 10 | } = require('~/server/middleware'); 11 | 12 | const router = express.Router(); 13 | 14 | router.post( 15 | '/', 16 | validateEndpoint, 17 | validateModel, 18 | buildEndpointOption, 19 | setHeaders, 20 | async (req, res, next) => { 21 | await AskController(req, res, next, initializeClient, addTitle); 22 | }, 23 | ); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /client/src/components/Chat/Messages/MessageAudio.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import { useRecoilValue } from 'recoil'; 3 | import type { TMessageAudio } from '~/common'; 4 | import { BrowserTTS, ExternalTTS } from '~/components/Audio/TTS'; 5 | import { TTSEndpoints } from '~/common'; 6 | import store from '~/store'; 7 | 8 | function MessageAudio(props: TMessageAudio) { 9 | const engineTTS = useRecoilValue(store.engineTTS); 10 | 11 | const TTSComponents = { 12 | [TTSEndpoints.browser]: BrowserTTS, 13 | [TTSEndpoints.external]: ExternalTTS, 14 | }; 15 | 16 | const SelectedTTS = TTSComponents[engineTTS]; 17 | return ; 18 | } 19 | 20 | export default memo(MessageAudio); 21 | -------------------------------------------------------------------------------- /client/src/hooks/Conversations/useGetSender.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { getResponseSender } from 'librechat-data-provider'; 3 | import type { TEndpointOption, TEndpointsConfig } from 'librechat-data-provider'; 4 | import { useGetEndpointsQuery } from '~/data-provider'; 5 | 6 | export default function useGetSender() { 7 | const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery(); 8 | return useCallback( 9 | (endpointOption: TEndpointOption) => { 10 | const { modelDisplayLabel } = endpointsConfig?.[endpointOption.endpoint ?? ''] ?? {}; 11 | return getResponseSender({ ...endpointOption, modelDisplayLabel }); 12 | }, 13 | [endpointsConfig], 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /client/src/common/mcp.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AuthorizationTypeEnum, 3 | AuthTypeEnum, 4 | TokenExchangeMethodEnum, 5 | } from 'librechat-data-provider'; 6 | import { MCPForm } from '~/common/types'; 7 | 8 | export const defaultMCPFormValues: MCPForm = { 9 | type: AuthTypeEnum.None, 10 | saved_auth_fields: false, 11 | api_key: '', 12 | authorization_type: AuthorizationTypeEnum.Basic, 13 | custom_auth_header: '', 14 | oauth_client_id: '', 15 | oauth_client_secret: '', 16 | authorization_url: '', 17 | client_url: '', 18 | scope: '', 19 | token_exchange_method: TokenExchangeMethodEnum.DefaultPost, 20 | name: '', 21 | description: '', 22 | url: '', 23 | tools: [], 24 | icon: '', 25 | trust: false, 26 | }; 27 | -------------------------------------------------------------------------------- /client/src/components/svg/MessagesSquared.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '~/utils/'; 2 | 3 | export default function MessagesSquared({ className }: { className?: string }) { 4 | return ( 5 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/svg/MobileSidebar.tsx: -------------------------------------------------------------------------------- 1 | export default function MobileSidebar({ className }: { className?: string }) { 2 | return ( 3 | 11 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /client/src/components/ui/TextareaAutosize.tsx: -------------------------------------------------------------------------------- 1 | import { useRecoilValue } from 'recoil'; 2 | import { forwardRef, useLayoutEffect, useState } from 'react'; 3 | import ReactTextareaAutosize from 'react-textarea-autosize'; 4 | import type { TextareaAutosizeProps } from 'react-textarea-autosize'; 5 | import store from '~/store'; 6 | 7 | export const TextareaAutosize = forwardRef( 8 | (props, ref) => { 9 | const [, setIsRerendered] = useState(false); 10 | const chatDirection = useRecoilValue(store.chatDirection).toLowerCase(); 11 | useLayoutEffect(() => setIsRerendered(true), []); 12 | return ; 13 | }, 14 | ); 15 | -------------------------------------------------------------------------------- /api/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | clearMocks: true, 4 | roots: [''], 5 | coverageDirectory: 'coverage', 6 | setupFiles: [ 7 | './test/jestSetup.js', 8 | './test/__mocks__/logger.js', 9 | './test/__mocks__/fetchEventSource.js', 10 | ], 11 | moduleNameMapper: { 12 | '~/(.*)': '/$1', 13 | '~/data/auth.json': '/__mocks__/auth.mock.json', 14 | '^openid-client/passport$': '/test/__mocks__/openid-client-passport.js', // Mock for the passport strategy part 15 | '^openid-client$': '/test/__mocks__/openid-client.js', 16 | }, 17 | transformIgnorePatterns: ['/node_modules/(?!(openid-client|oauth4webapi|jose)/).*/'], 18 | }; 19 | -------------------------------------------------------------------------------- /api/server/routes/edit/openAI.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const EditController = require('~/server/controllers/EditController'); 3 | const { initializeClient } = require('~/server/services/Endpoints/openAI'); 4 | const { 5 | setHeaders, 6 | validateModel, 7 | validateEndpoint, 8 | buildEndpointOption, 9 | moderateText, 10 | } = require('~/server/middleware'); 11 | 12 | const router = express.Router(); 13 | router.use(moderateText); 14 | 15 | router.post( 16 | '/', 17 | validateEndpoint, 18 | validateModel, 19 | buildEndpointOption, 20 | setHeaders, 21 | async (req, res, next) => { 22 | await EditController(req, res, next, initializeClient); 23 | }, 24 | ); 25 | 26 | module.exports = router; 27 | -------------------------------------------------------------------------------- /client/src/components/Files/VectorStore/VectorStoreList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import VectorStoreListItem from './VectorStoreListItem'; 3 | import { TVectorStore } from '~/common'; 4 | 5 | type VectorStoreListProps = { 6 | vectorStores: TVectorStore[]; 7 | deleteVectorStore: (id: string | undefined) => void; 8 | }; 9 | 10 | export default function VectorStoreList({ vectorStores, deleteVectorStore }: VectorStoreListProps) { 11 | return ( 12 |
13 | {vectorStores.map((vectorStore, index) => ( 14 | 19 | ))} 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /packages/data-schemas/src/schema/key.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema, Document, Types } from 'mongoose'; 2 | 3 | export interface IKey extends Document { 4 | userId: Types.ObjectId; 5 | name: string; 6 | value: string; 7 | expiresAt?: Date; 8 | } 9 | 10 | const keySchema: Schema = new Schema({ 11 | userId: { 12 | type: mongoose.Schema.Types.ObjectId, 13 | ref: 'User', 14 | required: true, 15 | }, 16 | name: { 17 | type: String, 18 | required: true, 19 | }, 20 | value: { 21 | type: String, 22 | required: true, 23 | }, 24 | expiresAt: { 25 | type: Date, 26 | }, 27 | }); 28 | 29 | keySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 }); 30 | 31 | export default keySchema; 32 | -------------------------------------------------------------------------------- /client/src/components/ui/Label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as LabelPrimitive from '@radix-ui/react-label'; 3 | 4 | import { cn } from '../../utils'; 5 | 6 | const Label = React.forwardRef< 7 | React.ElementRef, 8 | React.ComponentPropsWithoutRef 9 | >(({ className = '', ...props }, ref) => ( 10 | 18 | )); 19 | Label.displayName = LabelPrimitive.Root.displayName; 20 | 21 | export { Label }; 22 | -------------------------------------------------------------------------------- /client/src/hooks/useLocalize.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { TOptions } from 'i18next'; 3 | import { useRecoilValue } from 'recoil'; 4 | import { useTranslation } from 'react-i18next'; 5 | import { resources } from '~/locales/i18n'; 6 | import store from '~/store'; 7 | 8 | export type TranslationKeys = keyof typeof resources.en.translation; 9 | 10 | export default function useLocalize() { 11 | const lang = useRecoilValue(store.lang); 12 | const { t, i18n } = useTranslation(); 13 | 14 | useEffect(() => { 15 | if (i18n.language !== lang) { 16 | i18n.changeLanguage(lang); 17 | } 18 | }, [lang, i18n]); 19 | 20 | return (phraseKey: TranslationKeys, options?: TOptions) => t(phraseKey, options); 21 | } 22 | -------------------------------------------------------------------------------- /e2e/specs/popup.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from '@playwright/test'; 2 | 3 | test.describe('Endpoints Presets suite', () => { 4 | test('Endpoints Suite', async ({ page }) => { 5 | await page.goto('http://localhost:3080/', { timeout: 5000 }); 6 | await page.getByTestId('new-conversation-menu').click(); 7 | 8 | // includes the icon + endpoint names in obj property 9 | const endpointItem = page.getByRole('menuitemradio', { name: 'ChatGPT OpenAI' }); 10 | await endpointItem.click(); 11 | 12 | await page.getByTestId('new-conversation-menu').click(); 13 | // Check if the active class is set on the selected endpoint 14 | expect(await endpointItem.getAttribute('class')).toContain('active'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /api/server/services/Config/index.js: -------------------------------------------------------------------------------- 1 | const { config } = require('./EndpointService'); 2 | const getCustomConfig = require('./getCustomConfig'); 3 | const loadCustomConfig = require('./loadCustomConfig'); 4 | const loadConfigModels = require('./loadConfigModels'); 5 | const loadDefaultModels = require('./loadDefaultModels'); 6 | const getEndpointsConfig = require('./getEndpointsConfig'); 7 | const loadOverrideConfig = require('./loadOverrideConfig'); 8 | const loadAsyncEndpoints = require('./loadAsyncEndpoints'); 9 | 10 | module.exports = { 11 | config, 12 | loadCustomConfig, 13 | loadConfigModels, 14 | loadDefaultModels, 15 | loadOverrideConfig, 16 | loadAsyncEndpoints, 17 | ...getCustomConfig, 18 | ...getEndpointsConfig, 19 | }; 20 | -------------------------------------------------------------------------------- /client/src/components/Input/Generations/__tests__/Stop.spec.tsx: -------------------------------------------------------------------------------- 1 | import { render, fireEvent } from 'test/layout-test-utils'; 2 | import Stop from '../Stop'; 3 | 4 | describe('Stop', () => { 5 | it('should render the Stop button', () => { 6 | const { getByText } = render( 7 | { 9 | (''); 10 | }} 11 | />, 12 | ); 13 | expect(getByText('Stop')).toBeInTheDocument(); 14 | }); 15 | 16 | it('should call onClick when the button is clicked', () => { 17 | const handleClick = jest.fn(); 18 | const { getByText } = render(); 19 | fireEvent.click(getByText('Stop')); 20 | expect(handleClick).toHaveBeenCalledTimes(1); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /client/src/utils/scaleImage.ts: -------------------------------------------------------------------------------- 1 | export default function scaleImage({ 2 | originalWidth, 3 | originalHeight, 4 | containerRef, 5 | }: { 6 | originalWidth?: number; 7 | originalHeight?: number; 8 | containerRef: React.RefObject; 9 | }) { 10 | const containerWidth = containerRef.current?.offsetWidth ?? 0; 11 | 12 | if (containerWidth === 0 || originalWidth == null || originalHeight == null) { 13 | return { width: 'auto', height: 'auto' }; 14 | } 15 | 16 | const aspectRatio = originalWidth / originalHeight; 17 | const scaledWidth = Math.min(containerWidth, originalWidth); 18 | const scaledHeight = scaledWidth / aspectRatio; 19 | 20 | return { width: `${scaledWidth}px`, height: `${scaledHeight}px` }; 21 | } 22 | -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Speech/TTS/VoiceDropdown.tsx: -------------------------------------------------------------------------------- 1 | import { useRecoilValue } from 'recoil'; 2 | import { BrowserVoiceDropdown, ExternalVoiceDropdown } from '~/components/Audio/Voices'; 3 | import store from '~/store'; 4 | import { TTSEndpoints } from '~/common'; 5 | 6 | const voiceDropdownComponentsMap = { 7 | [TTSEndpoints.browser]: BrowserVoiceDropdown, 8 | [TTSEndpoints.external]: ExternalVoiceDropdown, 9 | }; 10 | 11 | export default function VoiceDropdown() { 12 | const engineTTS = useRecoilValue(store.engineTTS); 13 | const VoiceDropdownComponent = voiceDropdownComponentsMap[engineTTS]; 14 | 15 | if (!VoiceDropdownComponent) { 16 | return null; 17 | } 18 | 19 | return ; 20 | } 21 | -------------------------------------------------------------------------------- /client/src/components/Prompts/SkeletonForm.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from '~/components/ui'; 2 | 3 | export default function SkeletonForm() { 4 | return ( 5 |
6 |
7 | 8 |
9 |
10 | {/* Left Section */} 11 |
12 | 13 |
14 |
15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /client/src/components/ui/Input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { cn } from '~/utils'; 4 | 5 | export type InputProps = React.InputHTMLAttributes; 6 | 7 | const Input = React.forwardRef(({ className, ...props }, ref) => { 8 | return ( 9 | 17 | ); 18 | }); 19 | 20 | Input.displayName = 'Input'; 21 | 22 | export { Input }; 23 | -------------------------------------------------------------------------------- /client/src/data-provider/__tests__/memories.test.ts: -------------------------------------------------------------------------------- 1 | import { dataService as _dataService } from 'librechat-data-provider'; 2 | import axios from 'axios'; 3 | 4 | jest.mock('axios'); 5 | 6 | const mockedAxios = axios as jest.Mocked; 7 | 8 | describe('getMemories', () => { 9 | it('should fetch memories from /api/memories', async () => { 10 | const mockData = [{ key: 'foo', value: 'bar', updated_at: '2024-05-01T00:00:00Z' }]; 11 | 12 | mockedAxios.get.mockResolvedValueOnce({ data: mockData } as any); 13 | 14 | const result = await (_dataService as any).getMemories(); 15 | 16 | expect(mockedAxios.get).toHaveBeenCalledWith('/api/memories', expect.any(Object)); 17 | expect(result).toEqual(mockData); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /client/src/utils/resetConvo.ts: -------------------------------------------------------------------------------- 1 | import type { TMessage } from 'librechat-data-provider'; 2 | 3 | export default function resetConvo(messages: TMessage[], sender: string) { 4 | if (messages.length === 0) { 5 | return false; 6 | } 7 | const modelMessages = messages.filter((message) => !message.isCreatedByUser); 8 | const lastModel = modelMessages[modelMessages.length - 1].sender; 9 | if (lastModel !== sender) { 10 | console.log( 11 | 'Model change! Resetting convo. Original messages: ', 12 | messages, 13 | 'filtered messages: ', 14 | modelMessages, 15 | 'last model: ', 16 | lastModel, 17 | 'sender: ', 18 | sender, 19 | ); 20 | return true; 21 | } 22 | 23 | return false; 24 | } 25 | -------------------------------------------------------------------------------- /api/server/routes/ask/custom.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const AskController = require('~/server/controllers/AskController'); 3 | const { initializeClient } = require('~/server/services/Endpoints/custom'); 4 | const { addTitle } = require('~/server/services/Endpoints/openAI'); 5 | const { 6 | setHeaders, 7 | validateModel, 8 | validateEndpoint, 9 | buildEndpointOption, 10 | } = require('~/server/middleware'); 11 | 12 | const router = express.Router(); 13 | 14 | router.post( 15 | '/', 16 | validateEndpoint, 17 | validateModel, 18 | buildEndpointOption, 19 | setHeaders, 20 | async (req, res, next) => { 21 | await AskController(req, res, next, initializeClient, addTitle); 22 | }, 23 | ); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /client/src/components/Auth/SocialButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SocialButton = ({ id, enabled, serverDomain, oauthPath, Icon, label }) => { 4 | if (!enabled) { 5 | return null; 6 | } 7 | 8 | return ( 9 | 20 | ); 21 | }; 22 | 23 | export default SocialButton; 24 | -------------------------------------------------------------------------------- /client/src/hooks/Input/useMultipleKeys.ts: -------------------------------------------------------------------------------- 1 | import { isJson } from '~/utils/json'; 2 | 3 | export default function useMultipleKeys(setUserKey: React.Dispatch>) { 4 | function getMultiKey(name: string, userKey: string) { 5 | if (isJson(userKey)) { 6 | const newKey = JSON.parse(userKey); 7 | return newKey[name]; 8 | } else { 9 | return ''; 10 | } 11 | } 12 | 13 | function setMultiKey(name: string, value: number | string | boolean, userKey: string) { 14 | let newKey = {}; 15 | if (isJson(userKey)) { 16 | newKey = JSON.parse(userKey); 17 | } 18 | newKey[name] = value; 19 | 20 | setUserKey(JSON.stringify(newKey)); 21 | } 22 | 23 | return { getMultiKey, setMultiKey }; 24 | } 25 | -------------------------------------------------------------------------------- /client/src/utils/getLoginError.ts: -------------------------------------------------------------------------------- 1 | import { TranslationKeys } from '~/hooks'; 2 | 3 | const getLoginError = (errorText: string): TranslationKeys => { 4 | const defaultError: TranslationKeys = 'com_auth_error_login'; 5 | 6 | if (!errorText) { 7 | return defaultError; 8 | } 9 | 10 | switch (true) { 11 | case errorText.includes('429'): 12 | return 'com_auth_error_login_rl'; 13 | case errorText.includes('403'): 14 | return 'com_auth_error_login_ban'; 15 | case errorText.includes('500'): 16 | return 'com_auth_error_login_server'; 17 | case errorText.includes('422'): 18 | return 'com_auth_error_login_unverified'; 19 | default: 20 | return defaultError; 21 | } 22 | }; 23 | 24 | export default getLoginError; 25 | -------------------------------------------------------------------------------- /packages/data-schemas/src/schema/pluginAuth.ts: -------------------------------------------------------------------------------- 1 | import { Schema, Document } from 'mongoose'; 2 | 3 | export interface IPluginAuth extends Document { 4 | authField: string; 5 | value: string; 6 | userId: string; 7 | pluginKey?: string; 8 | createdAt?: Date; 9 | updatedAt?: Date; 10 | } 11 | 12 | const pluginAuthSchema: Schema = new Schema( 13 | { 14 | authField: { 15 | type: String, 16 | required: true, 17 | }, 18 | value: { 19 | type: String, 20 | required: true, 21 | }, 22 | userId: { 23 | type: String, 24 | required: true, 25 | }, 26 | pluginKey: { 27 | type: String, 28 | }, 29 | }, 30 | { timestamps: true }, 31 | ); 32 | 33 | export default pluginAuthSchema; 34 | -------------------------------------------------------------------------------- /rag.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | vectordb: 5 | image: ankane/pgvector:latest 6 | environment: 7 | POSTGRES_DB: mydatabase 8 | POSTGRES_USER: myuser 9 | POSTGRES_PASSWORD: mypassword 10 | volumes: 11 | - pgdata2:/var/lib/postgresql/data 12 | ports: 13 | - "5433:5432" 14 | 15 | rag_api: 16 | image: ghcr.io/danny-avila/librechat-rag-api-dev:latest 17 | environment: 18 | - DB_HOST=vectordb 19 | - DB_PORT=5432 20 | - POSTGRES_DB=mydatabase 21 | - POSTGRES_USER=myuser 22 | - POSTGRES_PASSWORD=mypassword 23 | ports: 24 | - "${RAG_PORT}:${RAG_PORT}" 25 | depends_on: 26 | - vectordb 27 | env_file: 28 | - .env 29 | 30 | volumes: 31 | pgdata2: 32 | -------------------------------------------------------------------------------- /api/server/routes/ask/openAI.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const AskController = require('~/server/controllers/AskController'); 3 | const { addTitle, initializeClient } = require('~/server/services/Endpoints/openAI'); 4 | const { 5 | handleAbort, 6 | setHeaders, 7 | validateModel, 8 | validateEndpoint, 9 | buildEndpointOption, 10 | moderateText, 11 | } = require('~/server/middleware'); 12 | 13 | const router = express.Router(); 14 | router.use(moderateText); 15 | 16 | router.post( 17 | '/', 18 | validateEndpoint, 19 | validateModel, 20 | buildEndpointOption, 21 | setHeaders, 22 | async (req, res, next) => { 23 | await AskController(req, res, next, initializeClient, addTitle); 24 | }, 25 | ); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /client/public/assets/cplusplus.svg: -------------------------------------------------------------------------------- 1 | C++ -------------------------------------------------------------------------------- /client/src/components/Nav/SettingsTabs/Beta/ChatBadges.tsx: -------------------------------------------------------------------------------- 1 | import { useSetRecoilState } from 'recoil'; 2 | import { Button } from '~/components/ui'; 3 | import { useLocalize } from '~/hooks'; 4 | import store from '~/store'; 5 | 6 | export default function ChatBadges() { 7 | const setIsEditing = useSetRecoilState(store.isEditingBadges); 8 | const localize = useLocalize(); 9 | 10 | const handleEditChatBadges = () => { 11 | setIsEditing(true); 12 | }; 13 | 14 | return ( 15 |
16 |
{localize('com_nav_edit_chat_badges')}
17 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /client/src/hooks/Input/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useAutoSave'; 2 | export { default as useUserKey } from './useUserKey'; 3 | export { default as useDebounce } from './useDebounce'; 4 | export { default as useTextarea } from './useTextarea'; 5 | export { default as useCombobox } from './useCombobox'; 6 | export { default as useQueryParams } from './useQueryParams'; 7 | export { default as useHandleKeyUp } from './useHandleKeyUp'; 8 | export { default as useRequiresKey } from './useRequiresKey'; 9 | export { default as useMultipleKeys } from './useMultipleKeys'; 10 | export { default as useSpeechToText } from './useSpeechToText'; 11 | export { default as useTextToSpeech } from './useTextToSpeech'; 12 | export { default as useGetAudioSettings } from './useGetAudioSettings'; 13 | -------------------------------------------------------------------------------- /api/app/clients/tools/.well-known/uberchord.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "v1", 3 | "name_for_human": "Uberchord", 4 | "name_for_model": "uberchord", 5 | "description_for_human": "Find guitar chord diagrams by specifying the chord name.", 6 | "description_for_model": "Fetch guitar chord diagrams, their positions on the guitar fretboard.", 7 | "auth": { 8 | "type": "none" 9 | }, 10 | "api": { 11 | "type": "openapi", 12 | "url": "https://guitarchords.pluginboost.com/.well-known/openapi.yaml", 13 | "is_user_authenticated": false 14 | }, 15 | "logo_url": "https://guitarchords.pluginboost.com/logo.png", 16 | "contact_email": "info.bluelightweb@gmail.com", 17 | "legal_info_url": "https://guitarchords.pluginboost.com/legal" 18 | } 19 | -------------------------------------------------------------------------------- /client/public/assets/tsnode.svg: -------------------------------------------------------------------------------- 1 | ts-node -------------------------------------------------------------------------------- /client/src/components/svg/Files/FileIcon.tsx: -------------------------------------------------------------------------------- 1 | import type { TFile } from 'librechat-data-provider'; 2 | import type { ExtendedFile } from '~/common'; 3 | 4 | export default function FileIcon({ 5 | file, 6 | fileType, 7 | }: { 8 | file?: Partial; 9 | fileType: { 10 | fill: string; 11 | paths: React.FC; 12 | title: string; 13 | }; 14 | }) { 15 | return ( 16 | 24 | 25 | {(file?.['progress'] ?? 1) >= 1 && <>{}} 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /api/app/clients/prompts/index.js: -------------------------------------------------------------------------------- 1 | const addCacheControl = require('./addCacheControl'); 2 | const formatMessages = require('./formatMessages'); 3 | const summaryPrompts = require('./summaryPrompts'); 4 | const handleInputs = require('./handleInputs'); 5 | const instructions = require('./instructions'); 6 | const titlePrompts = require('./titlePrompts'); 7 | const truncate = require('./truncate'); 8 | const createVisionPrompt = require('./createVisionPrompt'); 9 | const createContextHandlers = require('./createContextHandlers'); 10 | 11 | module.exports = { 12 | addCacheControl, 13 | ...formatMessages, 14 | ...summaryPrompts, 15 | ...handleInputs, 16 | ...instructions, 17 | ...titlePrompts, 18 | ...truncate, 19 | createVisionPrompt, 20 | createContextHandlers, 21 | }; 22 | -------------------------------------------------------------------------------- /api/server/routes/edit/custom.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const EditController = require('~/server/controllers/EditController'); 3 | const { initializeClient } = require('~/server/services/Endpoints/custom'); 4 | const { addTitle } = require('~/server/services/Endpoints/openAI'); 5 | const { 6 | handleAbort, 7 | setHeaders, 8 | validateModel, 9 | validateEndpoint, 10 | buildEndpointOption, 11 | } = require('~/server/middleware'); 12 | 13 | const router = express.Router(); 14 | 15 | router.post( 16 | '/', 17 | validateEndpoint, 18 | validateModel, 19 | buildEndpointOption, 20 | setHeaders, 21 | async (req, res, next) => { 22 | await EditController(req, res, next, initializeClient, addTitle); 23 | }, 24 | ); 25 | 26 | module.exports = router; 27 | -------------------------------------------------------------------------------- /client/src/components/svg/LogOutIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function LogOutIcon() { 4 | return ( 5 | 13 | 19 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /client/src/data-provider/tags.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query'; 2 | import type { UseQueryOptions, QueryObserverResult } from '@tanstack/react-query'; 3 | import type { TConversationTagsResponse } from 'librechat-data-provider'; 4 | import { QueryKeys, dataService } from 'librechat-data-provider'; 5 | 6 | export const useGetConversationTags = ( 7 | config?: UseQueryOptions, 8 | ): QueryObserverResult => { 9 | return useQuery( 10 | [QueryKeys.conversationTags], 11 | () => dataService.getConversationTags(), 12 | { 13 | refetchOnWindowFocus: false, 14 | refetchOnReconnect: false, 15 | refetchOnMount: false, 16 | ...config, 17 | }, 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /api/app/clients/tools/.well-known/DreamInterpreter.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "v1", 3 | "name_for_model": "DreamInterpreter", 4 | "name_for_human": "Dream Interpreter", 5 | "description_for_model": "Interprets your dreams using advanced techniques.", 6 | "description_for_human": "Interprets your dreams using advanced techniques.", 7 | "auth": { 8 | "type": "none" 9 | }, 10 | "api": { 11 | "type": "openapi", 12 | "url": "https://dreamplugin.bgnetmobile.com/.well-known/openapi.json", 13 | "has_user_authentication": false 14 | }, 15 | "logo_url": "https://dreamplugin.bgnetmobile.com/.well-known/logo.png", 16 | "contact_email": "ismail.orkler@bgnetmobile.com", 17 | "legal_info_url": "https://dreamplugin.bgnetmobile.com/terms.html" 18 | } 19 | -------------------------------------------------------------------------------- /client/src/components/ui/FileUpload.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | 3 | type FileUploadProps = { 4 | className?: string; 5 | onClick?: () => void; 6 | children: React.ReactNode; 7 | handleFileChange: (event: React.ChangeEvent) => void; 8 | }; 9 | 10 | const FileUpload = forwardRef( 11 | ({ children, handleFileChange }, ref) => { 12 | return ( 13 | <> 14 | {children} 15 | 22 | 23 | ); 24 | }, 25 | ); 26 | 27 | FileUpload.displayName = 'FileUpload'; 28 | 29 | export default FileUpload; 30 | --------------------------------------------------------------------------------