Compare commits

...

1109 Commits

Author SHA1 Message Date
Ruben Talstra
c2cdc869b7 🔧 chore: Comment out unused font family configurations and typography plugin in Tailwind CSS config 2025-02-27 16:36:14 +01:00
Ruben Talstra
2fa8d40d11 🔧 chore: Enhance Vite configuration with improved environment variable handling and chunking strategies 2025-02-27 16:34:16 +01:00
Ruben Talstra
b46c0ed43f 🔧 chore: Update ESLint and related dependencies in package.json and package-lock.json 2025-02-27 16:30:10 +01:00
Ruben Talstra
68c13ec610 Merge remote-tracking branch 'origin/chore/package-bumps-and-refactor' into chore/package-bumps-and-refactor
# Conflicts:
#	client/package.json
#	client/vite.config.ts
#	package-lock.json
2025-02-27 16:16:56 +01:00
Ruben Talstra
5e6b8f979c 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 16:15:42 +01:00
Ruben Talstra
c1032fe819 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 15:56:22 +01:00
Ruben Talstra
27df7fa7c1 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:43:10 +01:00
Ruben Talstra
5f131c0132 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:41:22 +01:00
Ruben Talstra
85d044b7cd 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:40:41 +01:00
Ruben Talstra
ac58be68e7 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:39:37 +01:00
Ruben Talstra
1e067150ac 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:36:42 +01:00
Ruben Talstra
4c598e4b16 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:35:38 +01:00
Ruben Talstra
b65c8ef9e2 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:14:00 +01:00
Ruben Talstra
0261b253e1 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:10:57 +01:00
Ruben Talstra
2e205b9186 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:10:39 +01:00
Ruben Talstra
4b36bd088e 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:08:22 +01:00
Ruben Talstra
67c50ff11f 🔧 chore: Update Tailwind CSS configuration and dependencies in package.json 2025-02-27 13:06:31 +01:00
Ruben Talstra
fcb1cf2eca 🔧 chore: Add Tailwind CSS configuration reference in style.css 2025-02-27 12:00:24 +01:00
Ruben Talstra
1741225f48 🔧 chore: Update dependencies in package.json and clean up ESLint config 2025-02-27 11:58:31 +01:00
github-actions[bot]
34f967eff8 🌍 i18n: Update translation.json with latest translations (#6009)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-26 16:23:56 -05:00
Danny Avila
be280004cf 🔧 refactor: Improve Params Handling, Remove Legacy Items, & Update Configs (#6074)
* chore: include all assets for service worker, remove unused tsconfig.node.json, eslint ignore vite config

* chore: exclude image files from service worker caching

* refactor: simplify googleSchema transformation and error handling

* fix: max output tokens cap for 3.7 models

* fix: skip index fixing in CI, development, and test environments

* ci: add maxOutputTokens handling tests for Claude models

* refactor: drop top_k and top_p parameters for claude-3.7 in AnthropicClient and add tests for new behavior

* refactor: conditionally include top_k and top_p parameters for non-claude-3.7 models

* ci: add unit tests for getLLMConfig function with various model options

* chore: remove all OPENROUTER_API_KEY legacy logic

* refactor: optimize stream chunk handling

* feat: reset model parameters button

* refactor: remove unused examples field from convoSchema and presetSchema

* chore: update librechat-data-provider version to 0.7.6993

* refactor: move excludedKeys set to data-provider for better reusability

* feat: enhance saveMessageToDatabase to handle unset fields and fetched conversation state

* feat: add 'iconURL' and 'greeting' to excludedKeys in data provider config

* fix: add optional chaining to user ID retrieval in getConvo call
2025-02-26 15:02:03 -05:00
Danny Avila
e14df5956a feat: Anthropic Agents Prompt Caching & UI Accessibility Enhancements (#6045)
* chore: remove auto-focus for now

* refactor: move react-hook-form Controller Logic to AgentSelect from AgentPanel

* fix: a11y focus issue with AgentSelect by never replacing it in its component tree

* fix: maintain ComboBox focus and force re-render on agent ID change in AgentPanel

* chore: `gemini-2.0-flash-lite-preview-02-05` (deprecated)

* refactor: extract cache control logic and headers configuration to helper functions in AnthropicClient

* feat: anthropic agents prompt caching

* chore: bump @librechat/agents and related dependencies

* fix: typo
2025-02-25 22:14:58 -05:00
Ruben Talstra
d3d7d11ea8 🌍 i18n: Add Georgian Language and Update Fallback Languages (#6022) 2025-02-25 20:28:58 -05:00
Danny Avila
f362f18870 🔗 fix: Shared Link with Markdown Code Error (#6016)
* refactor: Export AuthContext from AuthContextProvider

* refactor: Update useHasAccess to utilize useContext for AuthContext

* refactor: Enhance type definitions in useHasAccess for better type safety
2025-02-24 22:52:54 -05:00
Danny Avila
50e8769340 🚀 feat: Claude 3.7 Support + Reasoning (#6008)
* fix: missing console color methods for admin scripts

* feat: Anthropic Claude 3.7 Sonnet Support

* feat: update eventsource to version 3.0.2 and upgrade @modelcontextprotocol/sdk to 1.4.1

* fix: update DynamicInput to handle number type and improve initial value logic

* feat: first pass Anthropic Reasoning (Claude 3.7)

* feat: implement streaming support in AnthropicClient with reasoning UI handling

* feat: add missing xAI (grok) models
2025-02-24 20:08:55 -05:00
Danny Avila
0e719592c6 🔼 feat: "Run Code" Button Toggle (#5988)
* feat: Add 'Run Code' and 'Temporary Chat' permissions to role management

* feat: Add NextFunction typedef to api/typedefs.js

* feat: Add temporary chat and run code permissions to role schema

* refactor: Enhance access check middleware with logging for permission errors and better typing

* refactor: Set default value of USE permission to true in multiConvoPermissionsSchema

* refactor: Implement checkAccess function for separation of permission validation logic from middleware

* feat: Integrate permission checks for tool execution and enhance Markdown code block with execution capability

* fix: Convert REDIS_MAX_LISTENERS to a number, closes #5979
2025-02-23 14:01:36 -05:00
Ruben Talstra
2a74ceb630 🚀 feat: Add Custom Welcome Message in librechat.yaml (#5870)
* feat: Custom Welcome Message (#2967)

* don't think I'm on the right path?

*  feat: Implement custom welcome message configuration in interface
2025-02-22 17:43:00 -05:00
Marco Beretta
b404e372ec 🌟 feat: Enhance User Experience and SEO with Accessibility Updates and robots.txt (#5392)
* 🔈 fix: Refactor AudioRecorder to use button element for improved accessibility

* 🔈 fix: Update conversation menu button ID for improved accessibility

* 🔈 fix: Remove redundant role attribute from SidePanel for improved accessibility

* feat: Add robots.txt to manage web crawler access

* feat: Update index.html with meta description and remove legacy file

* fix: resolve merge conflicts.

* fix: resolve merge conflicts.

* fix: resolve merge conflicts.

* feat: Update index.html with meta description and remove legacy file

* 🔧 feat: Add legacy support and improve SidePanel accessibility

* 🔧 feat: Integrate express-static-gzip for improved static file serving and add new plugins for enhanced functionality

* 🔧 chore: Remove unused HTML ESLint plugin configurations and dependencies

---------

Co-authored-by: Ruben Talstra <RubenTalstra1211@outlook.com>
2025-02-22 17:42:20 -05:00
David
96c091c550 🤖 feat: 192x192 Icon for Android PWA (#5966)
* fix: Add 192x192 icon to allow the PWA to install on Android devices using Chrome.

* fix: Use less whitespace on icon-192x192.png. Re-generate maskable-icon.png and apple-touch-icon-180x180.png to be higher quality, cripser and use less kilobytes.
2025-02-22 17:17:35 -05:00
Ruben Talstra
94a2c1ff10 ⚙️ ci: Trigger Restriction for Detect Unused NPM Packages (#5844)
The workflow now only runs on pull requests that modify:
- The root `package.json` or `package-lock.json` file
- Any file under the client folder
- Any file under the api folder
2025-02-22 17:15:29 -05:00
github-actions[bot]
1260551690 🌍 i18n: Update translation.json with latest translations (#5946)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-21 15:10:19 -05:00
Danny Avila
fc733d2b9e 👐 refactor: Agents Accessibility and Gemini Error Handling (#5972)
* style: Enhance ControlCombobox with Carat Display, ClassName, and Disabled State

* refactor(ModelPanel): replace SelectDropdown with ControlCombobox for improved accessibility

* style: Adjust padding and positioning in ModelPanel for improved layout

* style(ControlCombobox): add containerClassName and iconSide props for enhanced customization

* style(ControlCombobox): add iconClassName prop for customizable icon styling

* refactor(AgentPanel): enhance layout with new button for creating agents and adjust structure for better alignment

* refactor(AgentSelect): replace SelectDropDown with ControlCombobox for improved accessibility and layout

* feat(translation): add new translation key for improved UI clarity

* style(AgentSwitcher, AssistantSwitcher): add iconClassName prop for customizable icon styling

* refactor(AgentPanelSkeleton): improve layout of skeleton components to match new visual structure

* style(AgentPanel, AgentPanelSkeleton): add margin to flex container for improved layout consistency

* a11y(AgentSelect, ControlCombobox): add selectId prop for preventing focus going to start to page after agent selection

* fix(AgentSelect): update SELECT_ID constant for improved clarity in component identification

* fix(GoogleClient): update type annotation, add abort handling for content generation requests, catch "uncaught" abort errors and GoogleGenerativeAI errors from `@google/generative-ai`
2025-02-21 15:02:07 -05:00
Danny Avila
1e625f7557 🚀 feat: Support Redis Clusters, Trusted Proxy Setting, And Toggle Meilisearch Indexing (#5963)
* refactor: Improve MeiliSearch integration with environment-based configuration for running index sync

* chore: Remove Question issue template from GitHub repository

* feat: Enable indexing in MeiliSearch configuration and clean up error handling in indexSync

* feat: Update .env.example to include optional indexing configuration

* refactor: rename env var for disabling index sync to MEILI_NO_SYNC

* Added the option to change the default trusted proxy

* feat: Add TRUST_PROXY configuration to .env.example for reverse proxy settings

* feat: Enhance Redis support with cluster configuration and TLS options

* feat(redis): add cluster support, environment config and url mapping

- Add Redis cluster configuration with isEnabled flag
- Configure prefix and max listeners settings
- Improve code formatting and readability
- Fix URL vs host parameter handling
- Update environment variables and regex patterns

---------

Co-authored-by: Gil Assunção <gil.assuncao@parceiros.nos.pt>
Co-authored-by: Pedro Reis <pedro.malheiro@parceiros.nos.pt>
Co-authored-by: João Trigo Soares <joao.soares@parceiros.nos.pt>
2025-02-20 17:39:12 -05:00
Märt
46a96b9caa 🔢 chore: Remove Dollar Sign from Balance Display (#5948) 2025-02-20 16:49:43 -05:00
Marco Beretta
fe7013562b style: Enhance Styling & Accessibility (#5956)
*  feat: Enhance UI Components with Shadows and Accessibility Improvements

* 🔧 fix: Correct Category Labels and Values in API Model & Adjust Button Class in Prompt List
2025-02-20 16:17:43 -05:00
Danny Avila
fdb3cf3f58 🔧 fix: Resizable Panel Unmount Error & Code Env. File Re-Upload (#5947)
* 🔧 refactor: handle full path for code env. file re-upload

* fix: update react-resizable-panels to version 2.1.7 to resolve error thrown on unmount of artifacts; ref: https://github.com/bvaughn/react-resizable-panels/issues/372

* refactor: replace promptPrefix with systemMessage in GoogleClient for improved clarity, and to prevent saving LibreChat feature-specific instructions to the user's custom instructions
2025-02-19 14:53:22 -05:00
Ruben Talstra
538a2a144a 🔒 fix: 2FA Encrypt TOTP Secrets & Improve Docs (#5933)
* 🔒 fix: Integrate TOTP secret retrieval and encryption in Two-Factor Authentication

* 🔒 refactor: Simplify TOTP verification by removing commented-out code
2025-02-19 13:33:29 -05:00
Ruben Talstra
06282b584f 📜 ci: AutomateCHANGELOG.md (#5838)
* feat: started with automated CHANGELOG.md

* fix: no `configuration.json` found

* refactor: `configuration.json`

* fix: missing label `configuration.json`

* fix: missing label `configuration.json`

* fix: missing label `configuration.json`

* fix: missing label `configuration.json`

* fix: missing label `configuration.json`

* ci: test new workflow action

* ci: test new workflow action

* ci: test new workflow action

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* feat: working CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* fix: separate release and Unreleased workflows CHANGELOG.md generation

* refactor: only trigger the `unreleased-changelog` action on push to `main`

and `generate-release-changelog` only when pushing a tag with `v*.*.*`

* refactor: Runs only every Monday at 00:00 UTC
2025-02-18 08:35:43 -05:00
Danny Avila
ecddffa7b2 🐛 fix: RAG Results Sorted By Distance (#5931)
* refactor: Extract file unlinking logic into a separate function and don't throw error

* fix: RAG results are actually in distance, not score
2025-02-18 08:14:19 -05:00
Danny Avila
964a74c73b 🛠 refactor: Ensure File Deletions, File Naming, and Agent Resource Updates (#5928)
* refactor: Improve error logging for file upload and processing functions to prevent verbosity

* refactor: Add uploads directory to Docker Compose to persist file uploads

* refactor: `addAgentResourceFile` to handle edge case of non-existing `tool_resource` array

* refactor: Remove version specification from deploy-compose.yml

* refactor: Prefix filenames with file_id to ensure uniqueness in file uploads

* refactor: Enhance error handling in deleteVectors to log warnings for non-404 errors

* refactor: Limit file search results to top 5 based on relevance score

* 🌍 i18n: Update translation.json with latest translations

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-17 19:37:03 -05:00
Ruben Talstra
f0f09138bd 🔒 feat: Two-Factor Authentication with Backup Codes & QR support (#5685)
* 🔒 feat: add Two-Factor Authentication (2FA) with backup codes & QR support (#5684)

* working version for generating TOTP and authenticate.

* better looking UI

* refactored + better TOTP logic

* fixed issue with UI

* fixed issue: remove initial setup when closing window before completion.

* added: onKeyDown for verify and disable

* refactored some code and cleaned it up a bit.

* refactored some code and cleaned it up a bit.

* refactored some code and cleaned it up a bit.

* refactored some code and cleaned it up a bit.

* fixed issue after updating to new main branch

* updated example

* refactored controllers

* removed `passport-totp` not used.

* update the generateBackupCodes function to generate 10 codes by default:

* update the backup codes to an object.

* fixed issue with backup codes not working

* be able to disable 2FA with backup codes.

* removed new env. replaced with JWT_SECRET

*  style: improved a11y and style for TwoFactorAuthentication

* 🔒 fix: small types checks

*  feat: improve 2FA UI components

* fix: remove unnecessary console log

* add option to disable 2FA with backup codes

* - add option to refresh backup codes
- (optional) maybe show the user which backup codes have already been used?

* removed text to be able to merge the main.

* removed eng tx to be able to merge

* fix: migrated lang to new format.

* feat: rewrote whole 2FA UI + refactored 2FA backend

* chore: resolving conflicts

* chore: resolving conflicts

* fix: missing packages, because of resolving conflicts.

* fix: UI issue and improved a11y

* fix: 2FA backup code not working

* fix: update localization keys for UI consistency

* fix: update button label to use localized text

* fix: refactor backup codes regeneration and update localization keys

* fix: remove outdated translation for shared links management

* fix: remove outdated 2FA code prompts from translation.json

* fix: add cursor styles for backup codes item based on usage state

* fix: resolve conflict issue

* fix: resolve conflict issue

* fix: resolve conflict issue

* fix: missing packages in package-lock.json

* fix: add disabled opacity to the verify button in TwoFactorScreen

* ⚙ fix: update 2FA logic to rely on backup codes instead of TOTP status

* ⚙️ fix: Simplify user retrieval in 2FA logic by removing unnecessary TOTP secret query

* ⚙️ test: Add unit tests for TwoFactorAuthController and twoFactorControllers

* ⚙️ fix: Ensure backup codes are validated as an array before usage in 2FA components

* ⚙️ fix: Update module path mappings in tests to use relative paths

* ⚙️ fix: Update moduleNameMapper in jest.config.js to remove the caret from path mapping

* ⚙️ refactor: Simplify import paths in TwoFactorAuthController and twoFactorControllers test files

* ⚙️ test: Mock twoFactorService methods in twoFactorControllers tests

* ⚙️ refactor: Comment out unused imports and mock setups in test files for two-factor authentication

* ⚙️ refactor: removed files

* refactor: Exclude totpSecret from user data retrieval in AuthController, LoginController, and jwtStrategy

* refactor: Consolidate backup code verification to apply DRY and remove default array in user schema

* refactor: Enhance two-factor authentication ux/flow with improved error handling and loading state management, prevent redirect to /login

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-17 19:09:36 -05:00
Marco Beretta
46ceae1a93 ⚖️ docs: Update LICENSE.md Year: 2024 -> 2025 (#5915) 2025-02-17 10:39:46 -05:00
Danny Avila
a65647a7de ⚙️ refactor: Enhance Logging, Navigation And Error Handling (#5910)
* refactor: Ensure Axios Errors are less Verbose if No Response

* refactor: Improve error handling in logAxiosError function

* fix: Prevent ModelSelect from rendering for Agent Endpoints

* refactor: Enhance logging functions with type parameter for better clarity

* refactor: Update buildDefaultConvo function to use optional endpoint parameter since we pass a default value for undefined

* refactor: Replace console logs with logger warnings and errors in useNavigateToConvo hook, and handle removed endpoint edge case

* chore: import order
2025-02-16 11:47:01 -05:00
Danny Avila
93dd365fda 🐞 fix: Add Null Checks for BaseURL in Agent Config (#5908) 2025-02-16 10:52:29 -05:00
Danny Avila
350e72dede 🧠 feat: Reasoning UI for Agents (#5904)
* chore: bump https-proxy-agent and @librechat/agents

* refactor: Improve error logging in OllamaClient for API fetch failures

* feat: Add DeepSeek provider support and enhance provider name handling

* refactor: Use Providers.OLLAMA constant for model name check in fetchModels function

* feat: Enhance formatAgentMessages to handle reasoning content type

* feat: OpenRouter Agent Reasoning

* hard work and dedicationgit add .env.example :)

* fix: Handle Google social login with missing last name

Social login with Google was previously displaying 'undefined' when
a user's last name was empty or not provided.

Changes:
- Conditionally render last name only if it exists
- Prevent displaying 'undefined' when last name is missing

* fix: add missing file endings for developers yml,yaml and log

---------

Co-authored-by: Mohamed Al-Duraji <mbalduraji@college.harvard.edu>
Co-authored-by: Deepak Kendole <deepakdpk101@gmail.com>
Co-authored-by: Peter Rothlaender <peter.rothlaender@ginkgo.com>
2025-02-15 18:52:29 -05:00
Danny Avila
e3b5c59949 ⚙️ fix: File Config Handling (revisited) (#5881)
* fix: improve file handling by preventing memoization issues, providing config values at run time

* 🌍 i18n: Update translation.json with latest translations
2025-02-14 11:37:41 -05:00
Ruben Talstra
61f0480b57 🐞 i18n: Remove Debug Mode (#5879) 2025-02-14 10:52:59 -05:00
Ruben Talstra
04c2a5abe7 🌍 fix: Enhance i18n Support & Optimize Category Handling (#5866)
* fix: Missing Translations in Prompt Filters in Prompt Library

* fix: fixed issue with `zh`
feat: added `Estonian` language option

* fix: test for `i18n.ts`

* refactor: `pt` --> `pt-BR` and `pt-PT`

* feat: request access to another language. default is only one language during invite.
2025-02-14 08:30:27 -05:00
github-actions[bot]
52a6de2aa7 🌍 i18n: Update translation.json with latest translations (#5855)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-13 16:06:25 -05:00
Ruben Talstra
750b22d5f4 🌏 i18n: fix Traditional Chinese Language Option (#5854) 2025-02-13 14:20:30 -05:00
Danny Avila
28fe1218c5 🔧 fix: Ariakit Combobox Virtualization (#5851)
Ariakit Combobox was not working well with several virtualization libraries as automated focus management was conflicting with scrolling/styling required of other virtualization methods. The entire strategy was replaced using experimental ariakit virtualization component `SelectRenderer`

Performance of component was also improved as a result of latest ariakit lib changes
2025-02-13 10:07:40 -05:00
github-actions[bot]
e402979cc5 🌍 i18n: Update translation.json with latest translations (#5849)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-13 09:34:14 -05:00
Ruben Talstra
4c8311b606 🛡️ chore: patch elliptic to address GHSA-vjh7-7g9h-fjfh (#5848) 2025-02-13 08:20:11 -05:00
Danny Avila
4fa13f45e3 🔃 refactor: Parent Message ID Handling on Error, Update Translations, Bump Agents (#5833)
* 📦 chore: Update @librechat/agents to version 2.0.5

* fix: Update error handling in AskController and EditController to include overrideParentMessageId when catching errors

* fix: Update parentMessageId assignment in AgentController to prioritize overrideParentMessageId

* 🌍 i18n: Update translation.json with latest translations

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-12 16:49:32 -05:00
Ruben Talstra
7f48030452 🔄 chore: Enforce 18next Language Keys (#5803)
* chore: enforcing language keys to adhere to the new standard.

* chore: enforcing i18n forbids to write plain text in JSX markup

* chore: enforcing i18n forbids to write plain text in JSX markup

* fix: ci with checkbox for unused keys :)

* refactor: removed all the unused `i18n` keys
2025-02-12 15:48:13 -05:00
Danny Avila
2a506df443 🪄 fix: Agent Artifacts condition 2025-02-11 19:44:20 -05:00
Danny Avila
bfbaaebd2b 🪄 feat: Agent Artifacts (#5804)
* refactor: remove artifacts toggle

* refactor: allow hiding side panel while allowing artifacts view

* chore: rename SidePanelGroup to SidePanel for clarity

* Revert "refactor: remove artifacts toggle"

This reverts commit f884c2cfcd.

* feat: add artifacts capability to agent configuration

* refactor: conditionally set artifacts mode based on endpoint type

* feat: Artifacts Capability for Agents

* refactor: enhance getStreamText method to handle intermediate replies and add `stream_options` for openai/azure

* feat: localize progress text and improve UX in CodeAnalyze and ExecuteCode components for expanding analysis
2025-02-11 18:00:38 -05:00
Danny Avila
46f034250d v0.7.7-rc1 (#5801) 2025-02-11 11:45:07 -05:00
Danny Avila
4de9619bd9 🧠 fix: Handle Reasoning Chunk Edge Cases (#5800)
* refactor: better reasoning parsing

* style: better model selector mobile styling

* chore: bump vite
2025-02-11 11:28:18 -05:00
Ruben Talstra
404b27d045 📦 chore: Bump Packages (#5791)
* chore: started with updating packages to new version.
(a lot are outdated)

* fix: eslint to pass when no matching files changed.

* fix: eslint to pass when no matching files changed.

* fix: issue with strict in actions with the test

* chore: update more dependencies

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* feat: scan for unused imported packages

* chore: removed Unused NPM Packages

* chore: removed Unused NPM Packages in `client/package.json`

* chore: removed Unused NPM Packages in `client/package.json`

* chore: Only comments when there are actual unused dependencies.

* chore: Only comments when there are actual unused dependencies.

* ci: test if it detects unused packages.

* ci: removed unused packages.

* ci: both static and dynamic i18n keys

* ci: revert back to no dynamic. use official nesting

* chore: remove override package: ajv
2025-02-11 09:55:13 -05:00
github-actions[bot]
936199b950 🌍 i18n: Update translation.json with latest translations (#5789)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-11 09:53:26 -05:00
owengo
d844e56c50 🔨 feat: Use x-strict attribute in OpenAPI Actions for Strict Function Definition (#4639)
* feat: manage an 'x-strict': true attribute in openapi specs for assistants which generates function calls with stric attribute

* fix typo and lint errors

---------

Co-authored-by: Olivier Schiavo <olivier.schiavo@wengo.com>
2025-02-10 16:02:21 -05:00
Ruben Talstra
aea055b597 🔄 chore: Refactor Locize Workflow for Improved Translation Sync (#5781) 2025-02-10 16:01:27 -05:00
Ruben Talstra
3d0c27f525 🛠️ ci: Add Workflow to Detect Unused i18next Keys in PRs (#5782)
* created: checks for unused i18n keys in codebase.

* updated the file to test this new check on this PR.

* updated the file to test this new check on this PR.

* updated the file to test this new check on this PR.

* updated the file to test this new check on this PR.

* updated the file to test this new check on this PR.

* removed the testing option. will now only run in `client/src/**`
2025-02-10 16:00:57 -05:00
Ruben Talstra
d99a9db3f6 feat: OAuth for Actions (#5693)
* feat: OAuth for Actions

* WIP: PoC flow state manager

* refactor: Add identifier field to token model from action schema

* chore: fix potential file type issues

* ci: fix type issue with action metadata auth

* fix: ensure FlowManagerOptions has a default ttl value

* WIP: OAUTH actions

* WIP: first pass OAuth Action

* fix: standardize identifier usage in OAuth flow handling

* fix: update token retrieval to include userId in query and use correct identifier

* refacotr: update token retrieval to use userId for OAuth token query

* feat: Tool Call Auth styling

* fix: streamline token creation and add type field to token schema

* refactor: cleanup OAuth flow by encrypting client credentials and ensuring oauth operations only run under condition

* refactor: use encrypted credentials in OAuth callback

* fix: update Token collection indexes to use expiresAt TTL index and not createdAt legacy index

* refactor: enhance Token index cleanup by improving logging and removing redundant index creation logic

* refactor: remove unused OAuth login route and related logic for improved clarity

* refactor: replace fetch with axios for OAuth token exchange and improve error handling

* refactor: better UX after authentication before oauth tool execution

* refactor: implement cleanup handlers for FlowStateManager intervals to enhance resource management

* refactor: encrypt OAuth tokens before storing and decrypt upon retrieval for enhanced security

* refactor: enhance authentication success page with improved styling and countdown feature

* refactor: add response_type parameter to OAuth redirect URI for improved compatibility

* chore: update translation.json new localizations

* chore: remove unused OGDialog import from OGDialogTemplate component

* refactor: Actions Auth using new Dialog styling, use same component with Agents/Assistants

* refactor: update removeNullishValues function to support removal of empty strings and adjust transform usage in schemas

* chore: bump version of librechat-data-provider to 0.7.6991

* refactor: integrate removeNullishValues function to clean metadata before encryption in agent and assistant routes

* refactor: update OAuth input fields to use 'password' type for better security

* refactor: update localization placeholders for sign-in message to use double curly braces

* refactor: add access_type parameter for offline access in createActionTool function

* refactor: implement handleOAuthToken function for token management and encryption

* feat: refresh token support

* refactor: add default expiration for access token and error handling for missing token

* feat: localizations for ActionAuth

* refactor: set refresh token expiration to null to not expire if expiry never given

* fix: prevent crash fromerror within async handleAbortError in AskController, EditController, and AgentController

* feat: Action Callback URL

* 🌍 i18n: Update translation.json with latest translations

* refactor: handle errors in flow state checking to prevent unhandled promise rejections

* fix: improve flow state concurrency to prevent multiple token creation calls

* refactor: RequestExecutor to use separate axios instance

* refactor: improve concurrency flows by keeping completed state until TTL expiry

* refactor: increase TTL for flow state management and adjust monitoring interval

* ci: mock axios instance creation in actions spec

* feat: add Babel and Jest configuration files; implement FlowStateManager tests with concurrency handling

* chore: add disableOAuth prop to ActionsAuth (not implemented for Assistants yet)

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-10 15:56:08 -05:00
Ruben Talstra
71c30a3640 🎯 ci: Update ESLint Workflow to target api/ and client/ changes (#5771) 2025-02-10 09:05:03 -05:00
Ruben Talstra
d90c9c4b77 📜 ci: Consolidate Locize Workflows for Missing Keys & PR Creation (#5769) 2025-02-10 09:03:59 -05:00
github-actions[bot]
37f6099f0a 🌍 i18n: Update translation.json with latest translations (#5765)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-10 09:02:56 -05:00
Marco Beretta
93415ebbd7 📝 docs: Update Language Request Template & Update README (#5766)
* Update README.md

* Update NEW-LANGUAGE-REQUEST.yml

* Updated: README.md
Removed: TRANSLATION.md

---------

Co-authored-by: Ruben Talstra <RubenTalstra1211@outlook.com>
2025-02-10 09:02:33 -05:00
github-actions[bot]
15c55d226e 🌍 i18n: Update translation.json with latest translations (#5764)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-09 15:47:25 -05:00
Ruben Talstra
1f31171fca 🤖 ci: locize-pull-published-sync-pr.yml (#5763)
* fix: ci for locize-pull-published-sync-pr.yml

* fix: ci for locize-pull-published-sync-pr.yml

* fixed missing parameter: base: main

* removed running on pull_request
2025-02-09 15:18:01 -05:00
Ruben Talstra
96f1133f0d 🤖 ci: locize-pull-published-sync-pr.yml (#5762)
* fix: ci for locize-pull-published-sync-pr.yml

* fix: ci for locize-pull-published-sync-pr.yml

* fixed missing parameter: base: main
2025-02-09 14:51:28 -05:00
Ruben Talstra
86134415e9 🧹 chore: Migrate to Flat ESLint Config & Update Prettier Settings (#5737)
* chore: migrated eslint v8 to v9

* chore: migrated eslint v8 to v9

* ESLint only checks the files that have changed in the pull request.

* fix: ESLint only checks the files that have changed in the pull request.

* refactor: eslint only on changed files

* refactor: eslint only on changed files or added files

* refactor: eslint only on changed files or added files

* refactor: eslint only on changed files or added files

but only include files that are not deleted (ACMRTUXB: A, C, M, R, T, U, X, B).

* whoops missed something
2025-02-09 12:15:20 -05:00
Ruben Talstra
aae413cc71 🌎 i18n: React-i18next & i18next Integration (#5720)
* better i18n support an internationalization-framework.

* removed unused package

* auto sort for translation.json

* fixed tests with the new locales function

* added new CI actions from locize

* to use locize a mention in the README.md

* to use locize a mention in the README.md

* updated README.md and added TRANSLATION.md to the repo

* updated TRANSLATION.md badges

* updated README.md to go to the TRANSLATION.md when clicking on the Translation Progress badge

* updated TRANSLATION.md and added a new issue template.

* updated TRANSLATION.md and added a new issue template.

* updated issue template to add the iso code link.

* updated the new GitHub actions for `locize`

* updated label for new issue template --> i18n

* fixed type issue

* Fix eslint

* Fix eslint with key-spacing spacing

* fix: error type

* fix: handle undefined values in SortFilterHeader component

* fix: typing in Image component

* fix: handle optional promptGroup in PromptCard component

* fix: update localize function to accept string type and remove unnecessary JSX element

* fix: update localize function to enforce TranslationKeys type for better type safety

* fix: improve type safety and handle null values in Assistants component

* fix: enhance null checks for fileId in FilesListView component

* fix: localize 'Go back' button text in FilesListView component

* fix: update aria-label for menu buttons and add translation for 'Close Menu'

* docs: add Reasoning UI section for Chain-of-Thought AI models in README

* fix: enhance type safety by adding type for message in MultiMessage component

* fix: improve null checks and optional chaining in useAutoSave hook

* fix: improve handling of optional properties in cleanupPreset function

* fix: ensure isFetchingNextPage defaults to false and improve null checks for messages in Search component

* fix: enhance type safety and null checks in useBuildMessageTree hook

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-09 12:05:31 -05:00
Kay Belardinelli
2e8d969e35 🔇 a11y: Silence Unnecessary Icons for Screen Readers (#5726)
* a11y: silence miscellaneous icons that should not be read by screen reader (#5723, #5724)

* 📝 chore: Update bug report template with additional guidance and version information

* 📝 chore: Update bug report template to guide users on using Discussions for general inquiries and setup help

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-09 10:53:43 -05:00
Ruben Talstra
1519afd4b9 🧹 chore: Enhance Issue Templates with Emoji Labels (#5754)
* updated the labels in the templates.

* fixed spacing in label in the templates.
2025-02-09 14:41:57 +01:00
Stefan Siegel
d786bf263c 📱 feat: improve mobile viewport behavior with interactive-widget meta (#5675)
fixed mobile viewport behavior when keyboard appears: content now resizes properly instead of scrolling, keeping the top area visible
2025-02-08 00:15:49 +01:00
Danny Avila
8b2ffa141e 🔍 a11y: MultiSearch Clear Input (#5718)
* add accessibility features to model search

* chore: linting

* fix: Improve accessibility by adding aria-label to MultiSearch input

* refactor: MultiSearch component as button

* refactor: Update MultiSearch component styles for improved theming

* refactor: Update MultiSearch component styles for improved visual consistency

---------

Co-authored-by: Derek Jackson <derek_jackson@harvard.edu>
Co-authored-by: derek jackson <63861027+derekjackson-das@users.noreply.github.com>
Co-authored-by: Ruben Talstra <RubenTalstra1211@outlook.com>
2025-02-07 09:38:18 -05:00
5026
18339ec7bb 🌍 i18n: "Balance" Localization For ZhTraditional (#5682) 2025-02-06 20:16:22 -05:00
Marco Beretta
70e410f38b 💬 fix: Temporary Chat PR's broken components and improved UI (#5705)
* 💬 fix: Temporary Chat PR's broken components and improved UI

* 💬 fix: bring back hover effect on AudioRecorder button

* style: adjust position of Mention component popover

* refactor: PromptsCommand typing and style position

* refactor: virtualize mention UI

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-06 20:15:38 -05:00
Danny Avila
63afb317c6 🚀 fix: Resolve Google Client Issues, CDN Screenshots, Update Models (#5703)
* 🤖 refactor: streamline model selection logic for title model in GoogleClient

* refactor: add options for empty object schemas in convertJsonSchemaToZod

* refactor: add utility function to check for empty object schemas in convertJsonSchemaToZod

* fix: Google MCP Tool errors, and remove Object Unescaping as Google fixed this

* fix: google safetySettings

* feat: add safety settings exclusion via GOOGLE_EXCLUDE_SAFETY_SETTINGS environment variable

* fix: rename environment variable for console JSON string length

* fix: disable portal for dropdown in ExportModal component

* fix: screenshot functionality to use image placeholder for remote images

* feat: add visionMode property to BaseClient and initialize in GoogleClient to fix resendFiles issue

* fix: enhance formatMessages to include image URLs in message content for Vertex AI

* fix: safety settings for titleChatCompletion

* fix: remove deprecated model assignment in GoogleClient and streamline title model retrieval

* fix: remove unused image preloading logic in ScreenshotContext

* chore: update default google models to latest models shared by vertex ai and gen ai

* refactor: enhance Google error messaging

* fix: update token values and model limits for Gemini models

* ci: fix model matching

* chore: bump version of librechat-data-provider to 0.7.699
2025-02-06 18:13:18 -05:00
Andrés Restrepo
33e60c379b 📜 feat: Configure JSON Log Truncation Size (#5215) 2025-02-06 13:36:25 -05:00
Ruben Talstra
ae7814a2b3 🔧 fix: Wrong import useGetStartupConfig (#5692)
* fixed build failed error

* chore: import order

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-06 13:30:15 -05:00
Yuichi Oneda
8c404ae056 💬 feat: Temporary Chats (#5493)
* feat: add expiredAt property to Conversation and Message models

Added `expiredAt` property to both Conversation and Message schemas.
Configured `expireAfterSeconds` index in MongoDB to automatically delete documents after a specified period.

* feat(data-provider): add isTemporary and expiredAt properties to support temporary chats

Added `isTemporary` property to TPayload and TSubmission for API calls for temporary chat.
Additionally, added `expiredAt` property to `tConversationSchema` to determine if a chat is temporary.

* feat: implement isTemporary state management

Add Recoil state for tracking temporary conversations, update event handlers to respect temporary chat status

* feat: add configuration to interfaceconfig to hide the temporary chat switch

* feat: add Temporary Chat UI with switch and modify related behaviors

- Added a Temporary Chat switch button at the end of dropdown lists in each model.
- Updated the form background color to black when Temporary Chat is enabled.
- Modified Navigation to exclude Temporary Chats from the chat list.

* fix: exclude Temporary Chats from search results

Updated the getConvosQueried query to ensure that Temporary Chats are not included in the search results.

* fix: hide bookmark button for Temporary Chats

Updated the UI to ensure that the bookmark button is not displayed when a chat is as Temporary Chat.

* chore: update isTemporary state management in ChatRoute

* chore: fix to pass the tests
2025-02-06 11:11:47 -05:00
Marco Beretta
5f9543f6fc 🛠️ fix: enhance UI/UX and address a11y issues in SetKeyDialog (#5672)
*  refactor: Improve UI consistency and accessibility in SetKeyDialog components

* 🎨 style: Add cursor pointer to Slider component for better UX

* 🐛 chore: Remove unnecessary console log from SetKeyDialog component
2025-02-05 16:35:07 -05:00
Marco Beretta
73fe0835cf 🎨 style: Prompt UI Refresh & A11Y Improvements (#5614)
* 🚀 feat: Add animated search input and improve filtering UI

* 🏄 refactor: Clean up category options and optimize event handlers in ChatGroupItem

* 🚀 refactor: 'Rename Prompt' option and enhance prompt filtering UI
Changed the useUpdatePromptGroup mutation in prompts.ts to replace the JSON.parse(JSON.stringify(...)) clones with structuredClone. This avoids errors when data contains non‑JSON values and improves data cloning reliability

* 🔧 refactor: Update Sharing Prompts UI; fix: Show info message only after updating switch status

* 🔧 refactor: Simplify condition checks and replace button with custom Button component in SharePrompt

* 🔧 refactor: Update DashGroupItem styles and improve accessibility with updated aria-label

* 🔧 refactor: Adjust layout styles in GroupSidePanel and enhance loading skeletons in List component

* 🔧 refactor: Improve layout and styling of AdvancedSwitch component; adjust DashBreadcrumb margin for better alignment

* 🔧 refactor: Add new surface colors for destructive actions and update localization strings for confirmation prompts

* 🔧 refactor: Update PromptForm and PromptName components for improved layout and styling; replace button with custom Button component

* 🔧 refactor: Enhance styling and layout of DashGroupItem, FilterPrompts, and Label components for improved user experience

* 🔧 refactor: Update DeleteBookmarkButton and Label components for improved layout and text handling

* 🔧 refactor: Simplify CategorySelector usage and update destructive surface colors for a11y

* 🔧 refactor: Update styling and layout of PromptName, SharePrompt, and DashGroupItem components; enhance Dropdown functionality with custom renderValue

* 🔧 refactor: Improve layout and styling of various components; update button sizes and localization strings for better accessibility and user experience

* 🔧 refactor: Add useCurrentPromptData hook and enhance RightPanel component; update CategorySelector for improved functionality and accessibility

* 🔧 refactor: Update input components and styling for Command and Description; enhance layout and accessibility in PromptVariables and PromptForm

* 🔧 refactor: Remove useCurrentPromptData hook and clean up related components; enhance PromptVersions layout

* 🔧 refactor: Enhance accessibility by adding aria-labels to buttons and inputs; improve localization for filter prompts

* 🔧 refactor: Enhance accessibility by adding aria-labels to various components; improve layout and styling in PromptForm and CategorySelector

* 🔧 refactor: Enhance accessibility by adding aria-labels to buttons and components; improve dialog roles and descriptions in SharePrompt and PromptForm

* 🔧 refactor: Improve accessibility by adding aria-labels and roles; enhance layout and styling in ChatGroupItem, ListCard, and ManagePrompts components

* 🔧 refactor: Update UI components for improved styling and accessibility; replace button elements with custom Button component and enhance layout in VariableForm, PromptDetails, and PromptVariables

* 🔧 refactor: Improve null checks for group and instanceProjectId in SharePrompt component; enhance readability and maintainability

* style: Enhance AnimatedSearchInput component with TypeScript types; improve conditional rendering for search states and accessibility

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-02-05 11:37:17 -05:00
heptapod
a44f5b4b6e 🌍 i18n: Fix "Balance" Localization For De (#5656) 2025-02-05 10:28:12 -05:00
RedwindA
40d9b1d2a2 🌍 i18n: Fix "Balance" Localization For Zh&ZhTraditional (#5632)
* Update translation of `balance` in Zh.ts

* Update translation of `balance` in ZhTraditional.ts
2025-02-05 15:58:23 +01:00
Danny Avila
6c33dc2eb3 🤖 refactor: Prevent Vertex AI from Setting Parameter Defaults (#5653)
* refactor: remove google defaults

* refactor: improve GoogleClient stream handling and metadata usage

* chore: update @librechat/agents to version 2.0.1

* fix: return client instance in GoogleClient configuration
2025-02-04 21:45:43 -05:00
Danny Avila
0312d4f4f4 🔧 refactor: Revamp Model and Tool Filtering Logic (#5637)
* 🔧 fix: Update regex to correctly match OpenAI model identifiers

* 🔧 fix: Enhance tool filtering logic in ToolService to handle inclusion and exclusion criteria for basic tools and toolkits

* feat: support o3-mini Azure streaming

* chore: Update model filtering logic to exclude audio and realtime models

* ci: linting error
2025-02-03 16:08:34 -05:00
Ruben Talstra
7c8a930061 feat: added Github Enterprise SSO login (#5621)
* https://github.com/danny-avila/LibreChat/issues/2812

* refactored the code to simplify it.

* removed unneeded code

* removed unneeded code
2025-02-03 15:30:02 -05:00
Ruben Talstra
93f5713c74 🛜 ci: OpenID Strategy Test Async Handling (#5613) 2025-02-03 10:57:49 -05:00
Igor
20aa0be85d 🌍 i18n: Add Missing "Balance" Localization For All Languages (#5594)
* Update AccountSettings.tsx

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2025-02-03 10:56:44 -05:00
Sam Lewis
d7dc58dd23 🔧 fix: Fetch PWA Manifest with credentials over CORS (#5156)
When behind authentication (for eg: Cloudflare Access), browsers
won't send credentials when fetching the manifest file by default.

To fix, this change adds `crossorigin="use-credentials"` to the
manifest link tag by enabling the `useCredentials` option in
VitePWA.
2025-02-03 10:54:10 -05:00
Danny Avila
45dd2b262f 🛂 feat: OpenID Logout Redirect to end_session_endpoint (#5626)
* WIP: end session endpoint

* refactor: move useGetBannerQuery outside of package

* refactor: add queriesEnabled and move useGetEndpointsConfigQuery to data-provider (local)

* refactor: move useGetEndpointsQuery import to data-provider

* refactor: relocate useGetEndpointsQuery import to improve module organization

* refactor: move `useGetStartupConfig` from package to `~/data-provider`

* refactor: move useGetUserBalance to data-provider and update imports

* refactor: update query enabled conditions to include config check

* refactor: remove unused useConfigOverride import from useAppStartup

* refactor: integrate queriesEnabled state into file and search queries and move useGetSearchEnabledQuery to data-provider (local)

* refactor: move useGetUserQuery to data-provider and update imports

* refactor: enhance loginUser mutation with success and error handling as pass in options to hook

* refactor: update enabled condition in queries to handle undefined config

* refactor: enhance authentication mutations with queriesEnabled state management

* refactor: improve conditional rendering for error messages and feature flags in Login component

* refactor: remove unused queriesEnabled state from AuthContextProvider

* refactor: implement queriesEnabled state management in LoginLayout with timeout handling

* refactor: add conditional check for end session endpoint in OpenID strategy

* ci: fix tests after changes

* refactor: remove endSessionEndpoint from user schema and update logoutController to use OpenID issuer's end_session_endpoint

* refactor: update logoutController to use end_session_endpoint from issuer metadata
2025-02-03 10:53:04 -05:00
Danny Avila
d93f5c9061 ☁️ feat: Additional AI Gateway Provider Support; fix: Reasoning Effort for Presets/Agents (#5600)
* 🐛 fix: Prevent processing of non-artifact nodes in artifact plugin

* refactor: remove deprecated fields, add `reasoning_effort`

* refactor: move `reasoning_effort` to the second column in OpenAI settings

* feat: add support for additional AI Gateway provider in extractBaseURL function

* refactor: move `reasoning_effort` field to conversationPreset and remove from agentOptions
2025-02-02 09:04:10 -05:00
Danny Avila
352565c9a6 🎥 feat: YouTube Tool (#5582)
* adding youtube tool

* refactor: use short `url` param instead of `videoUrl`

* refactor: move API key retrieval to a separate credentials module

* refactor: remove unnecessary `isEdited` message property

* refactor: remove unnecessary `isEdited` message property pt. 2

* refactor: YouTube Tool with new `tool()` generator, handle tools already created by new `tool` generator

* fix: only reset request data for multi-convo messages

* refactor: enhance YouTube tool by adding transcript parsing and returning structured JSON responses

* refactor: update transcript parsing to handle raw response and clean up text output

* feat: support toolkits and refactor YouTube tool as a toolkit for better LLM usage

* refactor: remove unused OpenAPI specs and streamline tools transformation in loadAsyncEndpoints

* refactor: implement manifestToolMap for better tool management and streamline authentication handling

* feat: support toolkits for assistants

* refactor: rename loadedTools to toolDefinitions for clarity in PluginController and assistant controllers

* feat: complete support of toolkits for assistants

---------

Co-authored-by: Danilo Pejakovic <danilo.pejakovic@leoninestudios.com>
2025-01-31 19:11:04 -05:00
Danny Avila
33f6093775 🤖 feat: o3-mini (#5581)
* 🤖 feat: `o3-mini`

* chore: re-order vision models list to prioritize gpt-4o as a vision model over o1
2025-01-31 16:49:01 -05:00
Danny Avila
fdf0b41d08 🐛 fix: Handle content generation errors in GoogleClient (#5575) 2025-01-31 11:22:15 -05:00
Danny Avila
6920e23fb2 🤖 fix: Azure Agents after Upstream Breaking Change (#5571)
* 🤖 fix: Azure Agents after Upstream Breaking Change

* chore: bump @langchain/core & @librechat/agents

* fix: correct formatting in assistant actions update logic and use correctly filtered actions variable

* fix: linting errors
2025-01-31 09:50:49 -05:00
Ruben Talstra
e1a6268904 🍎 feat: Apple auth (#5473)
* implemented Apple Auth login.

Closes: #3438

TODO:
- write config Doc

* removed some comments

* removed comment

* Add unit tests for Apple login strategy

Introduce comprehensive tests for the Apple login strategy, covering new user creation, existing user updates, and error handling scenarios during the authentication flow. Mocks implemented for external dependencies to ensure isolated testing.

* Remove unnecessary blank line in socialLogins.js
2025-01-31 09:49:09 -05:00
Marco Beretta
1c459ed3af 🖱️ feat: Switch Scroll Button setting (#5332) 2025-01-31 07:52:52 -05:00
owengo
8a0c7d92bd 👷 feat: Allow Admin to Edit Agent/Assistant Actions (#4591)
* feat: allows admin to see and edits all actions

* feat: allows admin to see and edits all actions

* rollback: admins can edit all actions, no configuration

* fix: admins don't override the user of existing actions and they preserve the user of the assistant when creating a new action

---------

Co-authored-by: Olivier Schiavo <olivier.schiavo@wengo.com>
2025-01-31 07:45:02 -05:00
JM Addington
9373f77bb7 feat: Add Scripts for listing users and resetting passwords (#5438)
*  feat: Add user management scripts for listing users and resetting passwords

* chore: update package.json

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2025-01-31 07:40:06 -05:00
Fuegovic
6f0ded058f 📝 docs: Update librechat.example.yaml (#5544)
Enable modelSelect and Presets by default
2025-01-31 07:35:18 -05:00
Danny Avila
19fa4d9f54 🧹 chore: Remove Deprecated BingAI Code & Address Mobile Focus (#5565)
* chore: remove all bing code

* chore: remove bing code and auto-focus effects

* chore: add back escapeRegExp helper function for regex special character handling

* chore: remove deprecated fields from settings and conversation schema

* fix: ensure default endpoint is set correctly in conversation setup

* feat: add disableFocus option to newConversation for improved search behavior
2025-01-30 17:22:29 -05:00
James Lamine
1226f56d0c 🔧 fix: Add missing finish_reason to stream chunks (#5563) 2025-01-30 15:24:43 -05:00
James Lamine
85c6a706c3 🔧 fix: handle known OpenAI errors with empty intermediate reply (#5562) 2025-01-30 15:20:34 -05:00
Danny Avila
587d46a20b 🚀 feat: o1 Tool Calling & reasoning_effort (#5553)
* fix: Update @librechat/agents to version 1.9.98

* feat: o1 tool calling

* fix: Improve error logging in RouteErrorBoundary

* refactor: Move extractContent function to utils and clean up Artifact component

* refactor: optimize reasoning UI post-streaming and deprecate plugins rendering

* feat: reasoning_effort support

* fix: update request content type handling in openapiToFunction to remove default 'application/x-www-form-urlencoded'

* chore: bump v0.7.696 data-provider
2025-01-30 12:36:35 -05:00
Danny Avila
591a019766 🏄‍♂️ refactor: Optimize Reasoning UI & Token Streaming (#5546)
*  feat: Implement Show Thinking feature; refactor: testing thinking render optimizations

*  feat: Refactor Thinking component styles and enhance Markdown rendering

* chore: add back removed code, revert type changes

* chore: Add back resetCounter effect to Markdown component for improved code block indexing

* chore: bump @librechat/agents and google langchain packages

* WIP: reasoning type updates

* WIP: first pass, reasoning content blocks

* chore: revert code

* chore: bump @librechat/agents

* refactor: optimize reasoning tag handling

* style: ul indent padding

* feat: add Reasoning component to handle reasoning display

* feat: first pass, content reasoning part styling

* refactor: add content placeholder for endpoints using new stream handler

* refactor: only cache messages when requesting stream audio

* fix: circular dep.

* fix: add default param

* refactor: tts, only request after message stream, fix chrome autoplay

* style: update label for submitting state and add localization for 'Thinking...'

* fix: improve global audio pause logic and reset active run ID

* fix: handle artifact edge cases

* fix: remove unnecessary console log from artifact update test

* feat: add support for continued message handling with new streaming method

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2025-01-29 19:46:58 -05:00
James Lamine
d60a149ad9 🗨️ fix: Loading Shared Saved Prompts (#5515) 2025-01-28 10:35:17 -05:00
Evren Tan
ad4cfba710 🌱 feat(.env.example): add o1 models (#5106)
* feat(.env.example): add o1-mini and o1-preview to .env.example

* feat(.env.example): add o1 to .env.example

---------

Co-authored-by: Evren Tan <evren.tan@pointr.tech>
2025-01-28 15:56:05 +01:00
Danny Avila
4110209494 ♻️ fix: Prevent Instructions from Removal when nearing Max Context (#5516)
* refactor: getMessagesWithinTokenLimit to accept params object

* refactor: always include instructions in payload if provided

* ci: remove obsolete test

* refactor: update logoutUser to accept request object and handle session destruction

* test: enhance getMessagesWithinTokenLimit tests for instruction handling
2025-01-27 20:37:38 -05:00
Danny Avila
528ee62eb1 🤖 fix: GoogleClient Context Handling & GenAI Parameters (#5503)
* fix: remove legacy code for GoogleClient and fix model parameters for GenAI

* refactor: streamline client init logic

* refactor: remove legacy vertex clients, WIP remote vertex token count

* refactor: enhance GoogleClient with improved type definitions and streamline token count method

* refactor: remove unused methods and consolidate methods

* refactor: remove examples

* refactor: improve input handling logic in DynamicInput component

* refactor: enhance GoogleClient with token usage tracking and context handling improvements

* refactor: update GoogleClient to support 'learnlm' model and streamline model checks

* refactor: remove unused text model handling in GoogleClient

* refactor: record token usage for GoogleClient titles and handle edge cases

* chore: remove unused undici, addresses verbose version warning
2025-01-27 12:21:33 -05:00
oonishi3
47b72e8159 🉐 fix: incorrect handling for composing CJK texts in Safari (#5496) 2025-01-27 11:22:38 -05:00
Ruben Talstra
5f8fade7eb 🔧 chore: bump ``vite`` to patch CVE-2025-24010 (#5495)
Replaced an outdated Vite entry and corrected inconsistencies in dependencies.

Severity: moderate
Websites were able to send any requests to the development server and read the response in vite - https://github.com/advisories/GHSA-vg6x-rcgg-rjx6
2025-01-27 11:20:08 -05:00
Marco Beretta
e7de9c1576 🛡️ refactor: enhance email verification process (#5485) 2025-01-26 20:57:03 -05:00
Danny Avila
12a9a07eb0 🐛 fix: Update deletePromptController to include user role in query (#5488) 2025-01-26 19:03:12 -05:00
Danny Avila
8b31f255f5 🪙 fix: Deepseek Pricing 2025-01-25 10:13:46 -05:00
Danny Avila
60c846b679 🪙 fix: Deepseek Pricing & Titling (#5459) 2025-01-25 10:10:53 -05:00
Danny Avila
af430e46f4 feat: Add Google Parameters, Ollama/Openrouter Reasoning, & UI Optimizations (#5456)
* feat: Google Model Parameters

* fix: dynamic input number value, previously coerced by zod schema

* refactor: support openrouter reasoning tokens and XML for thinking directive to conform to ollama

* fix: virtualize combobox to prevent performance drop on re-renders of long model/agent/assistant lists

* refactor: simplify Fork component by removing unnecessary chat context index

* fix: prevent rendering of Thinking component when children are null

* refactor: update Markdown component to replace <think> tags and simplify remarkPlugins configuration

* refactor: reorder remarkPlugins to improve plugin configuration in Markdown component
2025-01-24 18:15:47 -05:00
Danny Avila
7818ae5c60 🐳 feat: Deepseek Reasoning UI (#5440) 2025-01-24 10:52:08 -05:00
Marco Beretta
b8b7f40e98 🌄 feat: Add RouteErrorBoundary for Improved Client Error handling (#5396)
* feat: Add RouteErrorBoundary for improved error handling and integrate react-error-boundary package

* feat: update error message

* fix: correct typo in containerClassName prop in Landing component
2025-01-24 08:34:44 -05:00
Danny Avila
ed57bb4711 🚀 feat: Artifact Editing & Downloads (#5428)
* refactor: expand container

* chore: bump @codesandbox/sandpack-react to latest

* WIP: first pass, show editor

* feat: implement ArtifactCodeEditor and ArtifactTabs components for enhanced artifact management

* refactor: fileKey

* refactor: auto scrolling code editor and add messageId to artifact

* feat: first pass, editing artifact

* feat: first pass, robust artifact replacement

* fix: robust artifact replacement & re-render when expected

* feat: Download Artifacts

* refactor: improve artifact editing UX

* fix: layout shift of new download button

* fix: enhance missing output checks and logging in StreamRunManager
2025-01-23 18:19:04 -05:00
Danny Avila
87383fec27 🔧 chore: Update Deepseek Pricing, Google Safety Settings (#5409)
* fix: google-thinking model safety settings fix

* chore: update pricing/context for deepseek models

* ci: update Deepseek model token limits to use dynamic mapping
2025-01-22 07:50:09 -05:00
Marco Beretta
2d3dd9e351 ️ a11y: Enhance Accessibility in ToolSelectDialog, ThemeSelector and ChatGroupItem (#5395)
* feat: Add keyboard shortcut for theme switching and improve accessibility announcements

* fix: Improve accessibility of ToolSelectDialog close button

* feat: Enhance accessibility in ChatGroupItem component
2025-01-21 21:54:13 -05:00
Danny Avila
199e5e6eaf 🛠️ fix: Optionally add OpenID Sig. Algo. from Server Discovery (#5398)
* fix: Optionally add OpenID Sig. Algorithm from Server Discovery

* chore: bump vite to 5.4.14 for CVE-2025-24010

* chore: remove deprecated code

* fix: install missing undici

* fix: Add @waylaidwanderer/fetch-event-source package
2025-01-21 21:49:27 -05:00
Marco Beretta
fa9e778399 🔗 feat: Enhance Share Functionality, Optimize DataTable & Fix Critical Bugs (#5220)
* 🔄 refactor: frontend and backend share link logic; feat: qrcode for share link; feat: refresh link

* 🐛 fix: Conditionally render shared link and refactor share link creation logic

* 🐛 fix: Correct conditional check for shareId in ShareButton component

* 🔄 refactor: Update shared links API and data handling; improve query parameters and response structure

* 🔄 refactor: Update shared links pagination and response structure; replace pageNumber with cursor for improved data fetching

* 🔄 refactor: DataTable performance optimization

* fix: delete shared link cache update

* 🔄 refactor: Enhance shared links functionality; add conversationId to shared link model and update related components

* 🔄 refactor: Add delete functionality to SharedLinkButton; integrate delete mutation and confirmation dialog

* 🔄 feat: Add AnimatedSearchInput component with gradient animations and search functionality; update search handling in API and localization

* 🔄 refactor: Improve SharedLinks component; enhance delete functionality and loading states, optimize AnimatedSearchInput, and refine DataTable scrolling behavior

* fix: mutation type issues with deleted shared link mutation

* fix: MutationOptions types

* fix: Ensure only public shared links are retrieved in getSharedLink function

* fix: `qrcode.react` install location

* fix: ensure non-public shared links are not fetched when checking for existing shared links, and remove deprecated .exec() method for queries

* fix: types and import order

* refactor: cleanup share button UI logic, make more intuitive

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2025-01-21 09:31:05 -05:00
Danny Avila
460cde0c0b 🔒 chore: bump katex package to patch CVE-2025-23207 (#5383)
* chore: bump `katex` to patch `CVE-2025-23207`

* chore: prevent adding Parameters panel for agent endpoints in SideNav
2025-01-20 22:02:18 -05:00
Danny Avila
d6b4d83b68 🔥 feat: deepseek-reasoner Thought Streaming (#5379)
* 🔧 refactor: Remove unused penalties and enhance reasoning token handling in OpenAIClient

* 🔧 refactor: `addInstructions` default to adding instructions at index 0, flag for legacy behavior

* chore: remove long placeholder

* chore: update localization strings across multiple languages

* ci: adjust tests for new `addInstructions` behavior
2025-01-20 18:21:18 -05:00
Marco Beretta
79585e22d2 🔈fix: Accessible name on 'Prev' button in Prompts UI (#5369)
Fixes #5310

Add `aria-label="previous"` attribute to the 'Prev' button in the Prompts Panel.

* Modify `client/src/components/Chat/Prompts.tsx` to include `aria-label="previous"` attribute for the button.
2025-01-20 17:14:49 -05:00
Ragavendaran Puliyadi
a2305c3a7c 🐛 fix: use OpenID token signature algo as discovered from the server (#5348)
* 🐛 fix: use OpenID token signature algo as discovered from the server.

* 📜 refactor: Keeping other props that uses alg.

* 🔧 fix: handle missing property

* 📘 refactor: add comment block
2025-01-20 17:14:07 -05:00
Ragavendaran P R
d048a10b2e 📜 refactor: Log Error Messages when OAuth Fails (#5337) 2025-01-18 09:32:41 -05:00
Danny Avila
e6670cd411 🔧 chore: bump mongoose to patch CVE-2025-23061 (#5351) 2025-01-17 13:09:46 -05:00
Danny Avila
b35a8b78e2 🔧 refactor: Improve Agent Context & Minor Fixes (#5349)
* refactor: Improve Context for Agents

* 🔧 fix: Safeguard against undefined properties in OpenAIClient response handling

* refactor: log error before re-throwing for original stack trace

* refactor: remove toolResource state from useFileHandling, allow svg files

* refactor: prevent verbose logs from axios errors when using actions

* refactor: add silent method recordTokenUsage in AgentClient

* refactor: streamline token count assignment in BaseClient

* refactor: enhance safety settings handling for Gemini 2.0 model

* fix: capabilities structure in MCPConnection

* refactor: simplify civic integrity threshold handling in GoogleClient and llm

* refactor: update token count retrieval method in BaseClient tests

* ci: fix test for svg
2025-01-17 12:55:48 -05:00
Danny Avila
e309c6abef 🎯 fix: Prevent UI De-sync By Removing Redundant States (#5333)
* fix: remove local state from Dropdown causing de-sync

* refactor: cleanup STT code, avoid redundant states to prevent de-sync and side effects

* fix: reset transcript after sending final text to prevent data loss

* fix: clear timeout on component unmount to prevent memory leaks
2025-01-16 17:38:59 -05:00
Marco Beretta
b55e695541 🔧 fix: Maximize Chat Space for Agent Messages (#5330) 2025-01-16 17:28:33 -05:00
Danny Avila
24d30d7428 🏃‍♂️➡️ feat: Upgrade Meilisearch to v1.12.3 (#5327) 2025-01-16 08:25:33 -05:00
Danny Avila
aa80e4594e ♻️ refactor: Logout UX, Improved State Teardown, & Remove Unused Code (#5292)
* refactor: SearchBar and Nav components to streamline search functionality and improve state management

* refactor: remove refresh conversations

* chore: update useNewConvo calls to remove hardcoded default index

* refactor: null check for submission in useSSE hook

* refactor: remove useConversation hook and update useSearch to utilize useNewConvo

* refactor: remove conversation and banner store files; consolidate state management into misc; improve typing of families and add messagesSiblingIdxFamily

* refactor: more effectively clear all user/convo state without side effects on logout/delete user

* refactor: replace useParams with useLocation in SearchBar to correctly load conversation

* refactor: update SearchButtons to use button element and improve conversation ID handling

* refactor: use named function for `newConversation` for better call stack tracing

* refactor: enhance TermsAndConditionsModal to support array content and improve type definitions for terms of service

* refactor: add SetConvoProvider and message invalidation when navigating from search results to prevent initial route rendering edge cases

* refactor: rename getLocalStorageItems to localStorage and update imports for consistency

* refactor: move clearLocalStorage function to utils and simplify localStorage clearing logic

* refactor: migrate authentication mutations to a dedicated Auth data provider and update related tests
2025-01-12 12:57:10 -05:00
Danny Avila
24beda3d69 🐛 fix: Resolve 'Icon is Not a Function' Error in PresetItems (#5260)
* refactor: improve typing

* fix: "TypeError: Icon is not a function" with proper use of Functional Component and Improved Typing
2025-01-10 19:00:44 -05:00
Danny Avila
0855677a36 🌤️ feat: Add OpenWeather Tool for Weather Data Retrieval (#5246)
*  feat: Add OpenWeather Tool for Weather Data Retrieval 🌤️

* chore: linting

* chore: move test files

* fix: tool icon, allow user-provided keys, conform to app key assignment pattern

* chore: linting not included in #5212

---------

Co-authored-by: Jonathan Addington <jonathan.addington@jmaddington.com>
2025-01-10 08:54:08 -05:00
Danny Avila
ea1a5c8a30 🐛 fix: Handle optional endpoints in processModelSpecs function 2025-01-09 18:18:14 -05:00
Danny Avila
0f95604a67 ️ refactor: Optimize Rendering Performance for Icons, Conversations (#5234)
* refactor: HoverButtons and Fork components to use explicit props

* refactor: improve typing for Fork Component

* fix: memoize SpecIcon to avoid unnecessary re-renders

* feat: introduce URLIcon component and update SpecIcon for improved icon handling

* WIP: optimizing icons

* refactor: simplify modelLabel assignment in Message components

* refactor: memoize ConvoOptions component to optimize rendering performance
2025-01-09 15:40:10 -05:00
Danny Avila
687ab32bd3 🔧 fix: Streamline Builder Links and Enhance UI Consistency (#5229)
* fix: Include iconURL in Bedrock client initialization

* fix: unnecessary filtering for agent file_search files

* chore: use theme bg colors

* refactor: rely on endpoint config for enabling builder links in side navigation instead of parameters

* fix: remove unnecessary keyProvided check for agent builder link
2025-01-09 12:03:35 -05:00
Lars Kiesow
dd927583a7 Provide production-ready memory store for eypress-session (#5212)
The `express-session` library comes with a session storage meant for
testing by default. That is why you get a message like this when you
start up LibreChat with OIDC enabled:

    Warning: connect.session() MemoryStore is not
    designed for a production environment, as it will leak
    memory, and will not scale past a single process.

LibreChat can already use Redis as a session storage, although Redis support
is still marked as experimental. It also makes the set-up more complex, since
you will need to configure and run yet another service.

This pull request provides a simple alternative by using a in-memory session
store marked as a production-ready alternative by the guys from
`express-session`¹. You can still configure Redis, but this provides a simple,
good default for everyone else.

See also https://github.com/danny-avila/LibreChat/discussions/1014

¹⁾ https://github.com/expressjs/session?tab=readme-ov-file#compatible-session-stores
2025-01-09 11:23:51 -05:00
Danny Avila
69a9b8b911 🐛 fix: Ensure Default ModelSpecs Are Set Correctly (#5218)
* 🐛 fix: default modelSpecs not being set

* feat: Add imageDetail parameter for OpenAI endpoints in tQueryParamsSchema

* feat: Implement processModelSpecs function to enhance model specs processing from configuration

* feat: Refactor configuration schemas and types for improved structure and clarity

* feat: Add append_current_datetime parameter to tQueryParamsSchema for enhanced endpoint functionality

* fix: Add endpointType to getSaveOptions and enhance endpoint handling in Settings component

* fix: Change endpointType to be nullable and optional in tConversationSchema for improved flexibility

* fix: allow save & submit for google endpoint
2025-01-08 21:57:00 -05:00
Danny Avila
916faf6447 🐛 fix: Correct Endpoint/Icon Handling, Update Module Resolutions (#5205)
* fix: agent modelSpec iconURLs not being recorded

* fix: prioritize message properties over conversation defaults in icon data

* fix: determine endpoint type from endpointsConfig

* chore: type issue with setting.columnSpan

* chore: remove redundant key indexing for keySchema

* chore: bump version to 0.7.691 in package.json

* chore: add stricter remark-gfm and mdast-util-gfm resolutions/overrides

* chore: remove rollup override and bump vite-plugin-pwa

* chore: reinstall remark-gfm for correct module resolution

* chore: reinstall vite-plugun-pwa
2025-01-07 11:09:18 -05:00
Danny Avila
8aa1e731ca feat: Quality-of-Life Chat/Edit-Message Enhancements (#5194)
* fix: rendering error for mermaid flowchart syntax

* feat: add submit button ref and enable submit on Ctrl+Enter in EditMessage component

* feat: add save button and keyboard shortcuts for saving and canceling in EditMessage component

* feat: collapse chat on max height

* refactor: implement scrollable detection for textarea on key down events and initial render

* feat: add regenerate button for error handling in HoverButtons, closes #3658

* feat: add functionality to edit latest user message with the up arrow key when the input is empty
2025-01-06 22:47:24 -05:00
Danny Avila
b01c744eb8 🧵 fix: Prevent Unnecessary Re-renders when Loading Chats (#5189)
* chore: typing

* chore: typing

* fix: enhance message scrolling logic to handle empty messages tree and ref checks

* fix: optimize message selection logic with useCallback for better performance

* chore: typing

* refactor: optimize icon rendering

* refactor: further optimize chat props

* fix: remove unnecessary console log in useQueryParams cleanup

* refactor: add queryClient to reset message data on new conversation initiation

* refactor: update data-testid attributes for consistency and improve code readability

* refactor: integrate queryClient to reset message data on new conversation initiation
2025-01-06 10:32:44 -05:00
Danny Avila
7987e04a2c 🔗 feat: Convo Settings via URL Query Params & Mention Models (#5184)
* feat: first pass, convo settings from query params

* feat: Enhance query parameter handling for assistants and agents endpoints

* feat: Update message formatting and localization for AI responses, bring awareness to mention command

* docs: Update translations README with detailed instructions for translation script usage and contribution guidelines

* chore: update localizations

* fix: missing agent_id assignment

* feat: add models as initial mention option

* feat: update query parameters schema to confine possible query params

* fix: normalize custom endpoints

* refactor: optimize custom endpoint type check
2025-01-04 20:36:12 -05:00
Danny Avila
766657da83 🔖 fix: Remove Local State from Bookmark Menu (#5181)
* chore: remove redundant

* fix: bookmark menu statefulness by removing local state
2025-01-04 12:01:13 -05:00
Danny Avila
7c61115a88 🐛 fix: Prevent Default Values in OpenAI/Custom Endpoint Agents (#5180)
* fix: prevent OpenAI/custom-endpoint agents from using default values

* fix: order of assigning client options

* chore: typing for runnable config
2025-01-04 09:41:59 -05:00
Danny Avila
c26b54c74d 🔄 refactor: Consolidate Tokenizer; Fix Jest Open Handles (#5175)
* refactor: consolidate tokenizer to singleton

* fix: remove legacy tokenizer code, add Tokenizer singleton tests

* ci: fix jest open handles
2025-01-03 18:11:14 -05:00
Danny Avila
bf0a84e45a ®️ feat: Support Rscript for Code Interpreter & recursionLimit for Agents (#5170)
* chore: bump @librechat/agents to v1.9.8 for rscript support

* chore: fix @langchain/google-genai dep., match agents

* chore: fix @langchain/google-vertexai to v0.1.5, match with agents

* chore: bump @librechat/agents to v1.9.9

* chore: update @librechat/agents to v1.9.91 and @langchain/google-vertexai to v0.1.6

* chore: increase MAX_FILE_SIZE to 150MB for file uploads

* chore: bump @librechat/agents to v1.9.92

* feat: support `recursionLimit` for agents

* chore: update configuration version to 1.2.1 in librechat.yaml and config.ts

* feat: add R language SVG icon to the assets and include it in ApiKeyDialog

* feat: add support for new vision model 'o1' and exclude 'o1-mini'
2025-01-03 16:50:00 -05:00
Julian Dreykorn
28966e3ddc 🧾 docs: Update Example librechat.yaml
* docs: Add mcpServers, agents and actions to the config
2025-01-03 08:35:00 -05:00
Thinger Soft
65b2d647a1 🔧 fix: Handle Concurrent File Mgmt. For Agents (#5159)
* fix: handle concurrent file upload for agents rag

Closes #4746:

* fix: handle concurrent file deletions for agents rag

Closes #5160:

* refactor: remove useless promise wrapping
2025-01-02 08:29:07 -05:00
Danny Avila
6c9a468b8e 🐛 fix: Artifacts Type Error, Tool Token Counts, and Agent Chat Import (#5142)
* fix: message import functionality to support content field

* fix: handle tool calls token counts in context window management

* fix: handle potential undefined size in FilePreview component
2024-12-30 13:01:47 -05:00
Marco Beretta
cb1921626e 🎨 feat: enhance Chat Input UI, File Mgmt. UI, Bookmarks a11y (#5112)
* 🎨 feat: improve file display and overflow handling in SidePanel components

* 🎨 feat: enhance bookmarks management UI and improve accessibility features

* 🎨 feat: enhance BookmarkTable and BookmarkTableRow components for improved layout and performance

* 🎨 feat: enhance file display and interaction in FilesView and ImagePreview components

* 🎨 feat: adjust minimum width for filename filter input in DataTable component

* 🎨 feat: enhance file upload UI with improved layout and styling adjustments

* 🎨 feat: add surface-hover-alt color and update FileContainer styling for improved UI

* 🎨 feat: update ImagePreview component styling for improved visual consistency

* 🎨 feat: add MaximizeChatSpace component and integrate chat space maximization feature

* 🎨 feat: enhance DataTable component with transition effects and update Checkbox styling for improved accessibility

* fix: enhance a11y for Bookmark buttons by adding space key support, ARIA labels, and correct html role for key presses

* fix: return focus back to trigger for BookmarkEditDialog (Edit and new bookmark buttons)

* refactor: ShareButton and ExportModal components children prop support; refactor DropdownPopup item handling

* refactor: enhance ExportAndShareMenu and ShareButton components with improved props handling and accessibility features

* refactor: add ref prop support to MenuItemProps and update ExportAndShareMenu and DropdownPopup components so focus correctly returns to menu item

* refactor: enhance ConvoOptions and DeleteButton components with improved props handling and accessibility features

* refactor: add triggerRef support to DeleteButton and update ConvoOptions for improved dialog handling

* refactor: accessible bookmarks menu

* refactor: improve styling and accessibility for bookmarks components

* refactor: add focusLoop support to DropdownPopup and update BookmarkMenu with Tooltip

* refactor: integrate TooltipAnchor into ExportAndShareMenu for enhanced accessibility

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-12-29 17:31:41 -05:00
Danny Avila
d9c59b08e6 🔑 feat: Implement TTL Mgmt. for In-Memory Keyv Stores (#5127)
This commit updates the cache stores in the `getLogStores.js` file to use Redis as the store if the `USE_REDIS` environment variable is enabled. It also adds a new environment variable `DEBUG_MEMORY_CACHE` to enable debugging of the memory cache.
2024-12-28 17:32:05 -05:00
Danny Avila
24cad6bbd4 🤖 feat: Support Google Agents, fix Various Provider Configurations (#5126)
* feat: Refactor ModelEndHandler to collect usage metadata only if it exists

* feat: google tool end handling, custom anthropic class for better token ux

* refactor: differentiate between client <> request options

* feat: initial support for google agents

* feat: only cache messages with non-empty text

* feat: Cache non-empty messages in chatV2 controller

* fix: anthropic llm client options llmConfig

* refactor: streamline client options handling in LLM configuration

* fix: VertexAI Agent Auth & Tool Handling

* fix: additional fields for llmConfig, however customHeaders are not supported by langchain, requires PR

* feat: set default location for vertexai LLM configuration

* fix: outdated OpenAI Client options for getLLMConfig

* chore: agent provider options typing

* chore: add note about currently unsupported customHeaders in langchain GenAI client

* fix: skip transaction creation when rawAmount is NaN
2024-12-28 17:15:03 -05:00
Danny Avila
a423eb8c7b fix: Improve Accessibility in Endpoints Menu/Navigation (#5123)
* fix: prevent mobile nav toggle from being focusable when not in mobile view, add types to <NavToggle/>

* fix: appropriate endpoint menu item role, add up/down focus mgmt, ensure set api key is focusable and accessible

* fix: localize link titles and update text color for improved accessibility in Nav component
2024-12-28 12:58:12 -05:00
Marco Beretta
d6f1ecf75c 🔒 fix: update refresh token handling to use plain token instead of hashed token (#5088)
* 🔒 fix: update refresh token handling to use plain token instead of hashed token

* 🔒 fix: simplify logoutUser by using plain refresh token for session lookup
2024-12-23 18:38:16 +01:00
Alex Torregrosa
04923dd185 🐋 refactor: Reduce Dockerfile.multi container size (#5066)
* fix: Reduce Dockerfile.multi container size

Reduced container size from 1.46 GB to 1.12 GB.

* Use `npm ci` without devDependencies for final image
* Remove unneeded `npm prune commands`

* Update Dockerfile.multi

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-12-23 05:17:05 -05:00
Marco Beretta
dfe5498301 🎨 feat: enhance UI & accessibility in file handling components (#5086)
*  feat: Add localization for page display and enhance button styles

*  refactor: improve image preview component styles

*  refactor: enhance modal close behavior and prevent refocus on certain elements

*  refactor: enhance file row layout and improve image preview animation
2024-12-23 05:14:40 -05:00
Marco Beretta
bdb222d5f4 🔒 fix: resolve session persistence post password reset (#5077)
*  feat: Implement session management with CRUD operations and integrate into user workflows

*  refactor: Update session model import paths and enhance session creation logic in AuthService

*  refactor: Validate session and user ID formats in session management functions

*  style: Enhance UI components with improved styling and accessibility features

* chore: Update login form tests to use getByTestId instead of getByRole, remove console.log()

* chore: Update login form tests to use getByTestId instead of getByRole

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-12-23 05:12:07 -05:00
Marco Beretta
9bca2ae953 📘 docs: update readme.md (#5065) 2024-12-23 04:46:51 -05:00
Danny Avila
9b118d42de v0.7.6 (#5064)
* docs: Update README to include Model Context Protocol support and enhance access descriptions

* fix: Update civic integrity threshold to use 'BLOCK_NONE' as default

* fix: Update GOOGLE_MODELS in .env.example and adjust civic integrity threshold for new model compatibility

*  v0.7.6

* feat: Add 'gemini-2.0-flash-thinking-exp' model to googleModels context windows
2024-12-20 11:43:37 -05:00
Danny Avila
792ae03017 🌍 i18n: Updated Localizations (#5050)
*  feat: Add Arabic localization for API key input and related UI elements

* i18n: updated translations
2024-12-19 14:27:53 -05:00
Danny Avila
3fbbcb1cfe refactor: Integrate Capabilities into Agent File Uploads and Tool Handling (#5048)
* refactor: support drag/drop files for agents, handle undefined tool_resource edge cases

* refactor: consolidate endpoints config logic to dedicated getter

* refactor: Enhance agent tools loading logic to respect capabilities and filter tools accordingly

* refactor: Integrate endpoint capabilities into file upload dropdown for dynamic resource handling

* refactor: Implement capability checks for agent file upload operations

* fix: non-image tool_resource check
2024-12-19 13:04:48 -05:00
Danny Avila
d68c874db4 🤖 feat: Support new o1 model (#5039) 2024-12-18 14:40:58 -05:00
Danny Avila
f873587e5f 🐛 fix: Correct Model Parameters Merging and Panel UI (#5038)
* fix: Model Panel, watching wrong form field

* fix: Refactor agent initialization to merge model parameters correctly
2024-12-18 13:53:59 -05:00
Alex Torregrosa
000641c619 🐛 fix: Gemini system instructions not sent with null RAG_API_URL (#4920)
System instructions were not being sent to gemini models when RAG_API_URL was not set, as the original promptPrefix was not being populated.
2024-12-18 13:26:54 -05:00
Danny Avila
3ceb227507 🛡️ feat: Google Reverse Proxy support, CIVIC_INTEGRITY harm category (#5037)
* 🛡️ feat: Google Reverse Proxy support, `CIVIC_INTEGRITY` harm category

* 🔧 chore: Update @langchain/google-vertexai to version 0.1.4 in package.json and package-lock.json

* fix: revert breaking Vertex AI changes

---------

Co-authored-by: KiGamji <maloyh44@gmail.com>
2024-12-18 12:13:16 -05:00
Danny Avila
22a87b6162 🔧 fix: Update maxContextTokens calculation to use correct model identifier for Azure (#5035) 2024-12-18 11:11:38 -05:00
Danny Avila
e8bde332c2 feat: Implement Conversation Duplication & UI Improvements (#5036)
* feat(ui): enhance conversation components and add duplication

- feat: add conversation duplication functionality
- fix: resolve OGDialogTemplate display issues
- style: improve mobile dropdown component design
- chore: standardize shared link title formatting

* style: update active item background color in select-item

* feat(conversation): add duplicate conversation functionality and UI integration

* feat(conversation): enable title renaming on double-click and improve input focus styles

* fix(conversation): remove "(Copy)" suffix from duplicated conversation title in logging

* fix(RevokeKeysButton): correct className duration property for smoother transitions

* refactor(conversation): ensure proper parent-child relationships and timestamps when message cloning

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2024-12-18 11:10:34 -05:00
Danny Avila
649c7a6032 🔧 fix: Model Key Retrieval to Account for Bedrock Regions (#5029)
* 🔧 fix: model key retrieval logic to account for Bedrock region

* fix: edit preset dialog styling and potential max depth error with agents endpoint
2024-12-17 23:04:51 -05:00
Danny Avila
d3cafeee96 🔍 feat: Add Entity ID Support for File Search Shared Resources (#5028) 2024-12-17 22:11:18 -05:00
Danny Avila
18ad89be2c 🤖 feat: Add Agent Duplication Functionality with Permission (#5022)
* 🤖 feat: Add Agent Duplication Functionality with Permission

* 🐛 fix: Enhance Agent Duplication Logic and Filter Sensitive Data

* refactor(agents/v1): reorganized variables and error logging

* refactor: remove duplication permission

* chore: update librechat-data-provider version to 0.7.64

* fix: optimize agent duplication

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2024-12-17 19:47:39 -05:00
Danny Avila
16eed5f32d 🦙 feat: update AWS Bedrock pricing and token metadata for Meta models (#5024) 2024-12-17 17:18:49 -05:00
Danny Avila
e391347b9e 🔧 feat: Initial MCP Support (Tools) (#5015)
* 📝 chore: Add comment to clarify purpose of check_updates.sh script

* feat: mcp package

* feat: add librechat-mcp package and update dependencies

* feat: refactor MCPConnectionSingleton to handle transport initialization and connection management

* feat: change private methods to public in MCPConnectionSingleton for improved accessibility

* feat: filesystem demo

* chore: everything demo and move everything under mcp workspace

* chore: move ts-node to mcp workspace

* feat: mcp examples

* feat: working sse MCP example

* refactor: rename MCPConnectionSingleton to MCPConnection for clarity

* refactor: replace MCPConnectionSingleton with MCPConnection for consistency

* refactor: manager/connections

* refactor: update MCPConnection to use type definitions from mcp types

* refactor: update MCPManager to use winston logger and enhance server initialization

* refactor: share logger between connections and manager

* refactor: add schema definitions and update MCPManager to accept logger parameter

* feat: map available MCP tools

* feat: load manifest tools

* feat: add MCP tools delimiter constant and update plugin key generation

* feat: call MCP tools

* feat: update librechat-data-provider version to 0.7.63 and enhance StdioOptionsSchema with additional properties

* refactor: simplify typing

* chore: update types/packages

* feat: MCP Tool Content parsing

* chore: update dependencies and improve package configurations

* feat: add 'mcp' directory to package and update configurations

* refactor: return CONTENT_AND_ARTIFACT format for MCP callTool

* chore: bump @librechat/agents

* WIP: MCP artifacts

* chore: bump @librechat/agents to v1.8.7

* fix: ensure filename has extension when saving base64 image

* fix: move base64 buffer conversion before filename extension check

* chore: update backend review workflow to install MCP package

* fix: use correct `mime` method

* fix: enhance file metadata with message and tool call IDs in image saving process

* fix: refactor ToolCall component to handle MCP tool calls and improve domain extraction

* fix: update ToolItem component for default isInstalled value and improve localization in ToolSelectDialog

* fix: update ToolItem component to use consistent text color for tool description

* style: add theming to ToolSelectDialog

* fix: improve domain extraction logic in ToolCall component

* refactor: conversation item theming, fix rename UI bug, optimize props, add missing types

* feat: enhance MCP options schema with base options (iconPath to start) and make transport type optional, infer based on other option fields

* fix: improve reconnection logic with parallel init and exponential backoff and enhance transport debug logging

* refactor: improve logging format

* refactor: improve logging of available tools by displaying tool names

* refactor: improve reconnection/connection logic

* feat: add MCP package build process to Dockerfile

* feat: add fallback icon for tools without an image in ToolItem component

* feat: Assistants Support for MCP Tools

* fix(build): configure rollup to use output.dir for dynamic imports

* chore: update @librechat/agents to version 1.8.8 and add @langchain/anthropic dependency

* fix: update CONFIG_VERSION to 1.2.0
2024-12-17 13:12:57 -05:00
Danny Avila
0a97ad3915 🛠️ Fix: Update Agent Cache and Improve Actions UI (#5020)
* style: improve a11y, localization, and styling consistency of actions input form

* refactor: move agent mutations to dedicated module

* fix: update agent cache on agent deletion + delete and update actions
2024-12-17 12:45:58 -05:00
Danny Avila
6ef05dd2e6 🔧 fix: Add modelLabel to OpenAIClient and PluginsClient options (#4995) 2024-12-14 15:31:50 -05:00
Danny Avila
f15035542f 🐛 fix: Enforced Model Spec Icons/Labels and Agent Descriptions (#4979)
* fix: Previous convos missing model spec info when enforce is set to `true` #4749

* refactor: Include description field in agent list response
2024-12-13 16:15:48 -05:00
Danny Avila
0a5bc503b0 🙌 a11y: Accessibility Improvements (#4978)
* 🔃 fix: Safeguard against null token in SSE refresh token handling

* 🔃 fix: Update import path for AnnounceOptions in LiveAnnouncer component

* 🔃 a11y: Add aria-live attribute for accessibility in error messages

* fix: prevent double screen reader notification for toast

* 🔃 a11y: Enhance accessibility for main menus and buttons with ARIA roles and labels

* refactor: better alt text for logo on login page #4095

* refactor: remove unused import for DropdownNoState in Voices component

* fix: Focus management issue in the Export Options Modal #4100
2024-12-13 15:44:22 -05:00
Danny Avila
763693cc1b 🔐 fix: Assign ADMIN role based on first registration in LDAP strategy (#4974) 2024-12-13 11:40:24 -05:00
rio2dev
4587d56d92 🔊 feat: Add Estonian, Latvian, and Lithuanian to Language Dropdown (#4881)
* Add Estonian, Latvian and Lithuanian language to STT dropdown list

* Add Estonian, Latvian and Lithuanian language to STT dropdown list
2024-12-13 11:40:30 +01:00
Andrés Restrepo
6f9bbba3fc 🔃 fix: Exclude OAuth Routes From Service Worker Navigation (#4956) 2024-12-12 13:03:06 -05:00
Andrés Restrepo
43d10a4e43 fix: Handle Circular References in CONSOLE_JSON Log Truncation (#4958) 2024-12-12 13:02:44 -05:00
Danny Avila
69bd8e3644 🔐 feat: Implement Allowed Action Domains (#4964)
* chore: RequestExecutor typing

* feat: allowed action domains

* fix: rename TAgentsEndpoint to TAssistantEndpoint in typedefs

* chore: update librechat-data-provider version to 0.7.62
2024-12-12 12:52:42 -05:00
Danny Avila
e82af236bc 🤖 feat: Add Agents librechat.yaml Configuration (#4953)
* feat: CONFIG_VERSION v1.1.9, agents config

* refactor: Assistants Code Interpreter Toggle Improved Accessibility

* feat: Agents Config
2024-12-12 08:58:00 -05:00
Danny Avila
51e016ef2c 📑 docs: fix Portkey AI bad indentation 2024-12-11 15:28:49 -05:00
Danny Avila
1dbe6ee75d feat: Add Current Datetime to Assistants (v1/v2) (#4952)
* Feature: Added ability to send current date and time to v1 and v2 assistants

* remove date_feature.patch

* fix: rename append_today_date to append_current_datetime

* feat: Refactor time handling in chatV1 and chatV2, add date and time utility functions

* fix: Add warning log and response for missing run values in abortRun middleware

---------

Co-authored-by: Max Sanna <max@maxsanna.com>
2024-12-11 15:26:18 -05:00
Danny Avila
b5c9144127 🚀 feat: Add Gemini 2.0 Support, Update Packages and Deprecations (#4951)
* chore: Comment out deprecated MongoDB connection options in connectDb.js

* replaced deprecrated MongoDB count() function with countDocuments()

* npm audit fix (package-lock cleanup)

* chore: Specify .env file in launch configuration

* feat: gemini-2.0

* chore: bump express to 4.21.2 to address CVE-2024-52798

* chore: remove redundant comment for .env file specification in launch configuration

---------

Co-authored-by: neturmel <neturmel@gmx.de>
2024-12-11 14:11:27 -05:00
Danny Avila
4640e1b124 🛡️ feat: Add Role Dropdown to Prompt/Agents Admin Settings (#4922)
* style: update AdminSettings dialog content styles for improved accessibility/theming

* style: update icon colors in ExportAndShareMenu for improved theming

* feat: enhance DropdownPopup component with additional props for customization

* feat: add role selection dropdown to AdminSettings for enhanced user permissions management

* feat: add role selection dropdown to AdminSettings for Prompt permission management

* style: add gap to button in AdminSettings for improved layout

* feat: add warning message for Admin role access in Permissions settings
2024-12-09 19:50:03 -05:00
Danny Avila
1c05251826 🧵 fix: Assistants API Thread ID Handling (#4912) 2024-12-09 08:38:39 -05:00
Danny Avila
cd1184a302 📑 docs: update README.md (#4904)
* 📑 docs: update README.md to enhance feature descriptions and organization

* 📑 docs: Revise README.md for improved feature clarity and organization

* 📑 docs: Update README.md for improved clarity and organization of AI provider compatibility

* 📑 docs: Update AI Model Selection section in README.md for improved clarity and consistency

* 📑 docs: Update README.md to include Email Login support in Multi-User Authentication section
2024-12-07 21:53:36 -05:00
Danny Avila
dc728480f4 🤖 feat: Add Vision Models; fix: Agents user_provided Keys (#4903)
* 🤖 feat: add new vision models

* fix: agent key expiry setting and typing in useChatFunctions
2024-12-07 21:21:03 -05:00
Danny Avila
2875380bf1 🔧 fix: URL params, package mismatch, typing, shared link redirect, and o1 (azure) (#4899)
* fix: double decoding of URL params

* fix: prevent streaming options for O1 model (azure)

* fix: update @langchain/openai to version 0.3.14 in package-lock.json

* chore(AuthContext): typing

* chore(useTimeout): typing

* fix: shared link redirecting to login when code block includes "Run Code" button

* fix: typing
2024-12-07 16:55:17 -05:00
phil
85d92c2353 🪨 feat: add session token variable for AWS Bedrock (#4896) 2024-12-07 16:53:21 -05:00
Danny Avila
1a815f5e19 🎉 feat: Code Interpreter API and Agents Release (#4860)
* feat: Code Interpreter API & File Search Agent Uploads

chore: add back code files

wip: first pass, abstract key dialog

refactor: influence checkbox on key changes

refactor: update localization keys for 'execute code' to 'run code'

wip: run code button

refactor: add throwError parameter to loadAuthValues and getUserPluginAuthValue functions

feat: first pass, API tool calling

fix: handle missing toolId in callTool function and return 404 for non-existent tools

feat: show code outputs

fix: improve error handling in callTool function and log errors

fix: handle potential null value for filepath in attachment destructuring

fix: normalize language before rendering and prevent null return

fix: add loading indicator in RunCode component while executing code

feat: add support for conditional code execution in Markdown components

feat: attachments

refactor: remove bash

fix: pass abort signal to graph/run

refactor: debounce and rate limit tool call

refactor: increase debounce delay for execute function

feat: set code output attachments

feat: image attachments

refactor: apply message context

refactor: pass `partIndex`

feat: toolCall schema/model/methods

feat: block indexing

feat: get tool calls

chore: imports

chore: typing

chore: condense type imports

feat: get tool calls

fix: block indexing

chore: typing

refactor: update tool calls mapping to support multiple results

fix: add unique key to nav link for rendering

wip: first pass, tool call results

refactor: update query cache from successful tool call mutation

style: improve result switcher styling

chore: note on using \`.toObject()\`

feat: add agent_id field to conversation schema

chore: typing

refactor: rename agentMap to agentsMap for consistency

feat: Agent Name as chat input placeholder

chore: bump agents

📦 chore: update @langchain dependencies to latest versions to match agents package

📦 chore: update @librechat/agents dependency to version 1.8.0

fix: Aborting agent stream removes sender; fix(bedrock): completion removes preset name label

refactor: remove direct file parameter to use req.file, add `processAgentFileUpload` for image uploads

feat: upload menu

feat: prime message_file resources

feat: implement conversation access validation in chat route

refactor: remove file parameter from processFileUpload and use req.file instead

feat: add savedMessageIds set to track saved message IDs in BaseClient, to prevent unnecessary double-write to db

feat: prevent duplicate message saves by checking savedMessageIds in AgentController

refactor: skip legacy RAG API handling for agents

feat: add files field to convoSchema

refactor: update request type annotations from Express.Request to ServerRequest in file processing functions

feat: track conversation files

fix: resendFiles, addPreviousAttachments handling

feat: add ID validation for session_id and file_id in download route

feat: entity_id for code file uploads/downloads

fix: code file edge cases

feat: delete related tool calls

feat: add stream rate handling for LLM configuration

feat: enhance system content with attached file information

fix: improve error logging in resource priming function

* WIP: PoC, sequential agents

WIP: PoC Sequential Agents, first pass content data + bump agents package

fix: package-lock

WIP: PoC, o1 support, refactor bufferString

feat: convertJsonSchemaToZod

fix: form issues and schema defining erroneous model

fix: max length issue on agent form instructions, limit conversation messages to sequential agents

feat: add abort signal support to createRun function and AgentClient

feat: PoC, hide prior sequential agent steps

fix: update parameter naming from config to metadata in event handlers for clarity, add model to usage data

refactor: use only last contentData, track model for usage data

chore: bump agents package

fix: content parts issue

refactor: filter contentParts to include tool calls and relevant indices

feat: show function calls

refactor: filter context messages to exclude tool calls when no tools are available to the agent

fix: ensure tool call content is not undefined in formatMessages

feat: add agent_id field to conversationPreset schema

feat: hide sequential agents

feat: increase upload toast duration to 10 seconds

* refactor: tool context handling & update Code API Key Dialog

feat: toolContextMap

chore: skipSpecs -> useSpecs

ci: fix handleTools tests

feat: API Key Dialog

* feat: Agent Permissions Admin Controls

feat: replace label with button for prompt permission toggle

feat: update agent permissions

feat: enable experimental agents and streamline capability configuration

feat: implement access control for agents and enhance endpoint menu items

feat: add welcome message for agent selection in localization

feat: add agents permission to access control and update version to 0.7.57

* fix: update types in useAssistantListMap and useMentions hooks for better null handling

* feat: mention agents

* fix: agent tool resource race conditions when deleting agent tool resource files

* feat: add error handling for code execution with user feedback

* refactor: rename AdminControls to AdminSettings for clarity

* style: add gap to button in AdminSettings for improved layout

* refactor: separate agent query hooks and check access to enable fetching

* fix: remove unused provider from agent initialization options, creates issue with custom endpoints

* refactor: remove redundant/deprecated modelOptions from AgentClient processes

* chore: update @librechat/agents to version 1.8.5 in package.json and package-lock.json

* fix: minor styling issues + agent panel uniformity

* fix: agent edge cases when set endpoint is no longer defined

* refactor: remove unused cleanup function call from AppService

* fix: update link in ApiKeyDialog to point to pricing page

* fix: improve type handling and layout calculations in SidePanel component

* fix: add missing localization string for agent selection in SidePanel

* chore: form styling and localizations for upload filesearch/code interpreter

* fix: model selection placeholder logic in AgentConfig component

* style: agent capabilities

* fix: add localization for provider selection and improve dropdown styling in ModelPanel

* refactor: use gpt-4o-mini > gpt-3.5-turbo

* fix: agents configuration for loadDefaultInterface and update related tests

* feat: DALLE Agents support
2024-12-04 15:48:13 -05:00
Marco Beretta
affcebd48c ⚙️ fix: update Azure OpenAI STT/TTS env handling (#4859) 2024-12-04 11:44:00 -05:00
Danny Avila
9f25afef91 🔧 chore: bump mongoose to 8.8.3 for CVE-2024-53900 (#4854) 2024-12-03 22:42:03 -05:00
Thinger Soft
daa8e878d2 🛣️ fix: Chat Stream Hangup (#4822)
Embedded sse.js code converted into an external
dependency.
Custom access token refresh logic moved to
useSSE.ts hook.

Closes #4820
2024-12-03 22:35:31 -05:00
Danny Avila
ebae494337 🤖 feat: Support for new AWS Nova Models & Updated Anthropic Rates (#4852)
* updated Claude 3.5 Haiku pricing

https://www.anthropic.com/pricing#anthropic-api
Claude 3.5 Haiku
$0.80 / MTok
Input
$1 / MTok
Prompt caching write
$0.08 / MTok
Prompt caching read
$4 / MTok
Output

* Update tx.js

* refactor: fix tests for cache multiplier and add new AWS models

---------

Co-authored-by: khfung <68192841+khfung@users.noreply.github.com>
2024-12-03 22:25:15 -05:00
Dennis Benz
d6f7279bce 📜 feat: Add script to set balance for user (#4506)
* feat: Add script to set balance for user

* Show current balance before updating
2024-12-03 17:11:47 -05:00
Leon Jünemann
8178ae2a20 🤖 fix: Collaborative Agents are only editable by ADMIN #4659
Co-authored-by: Leon Jünemann <leon.juenemann@maibornwolff.de>
2024-11-26 15:02:13 -05:00
Danny Avila
e0a5f879b6 🔑 fix: Azure Serverless Support for API Key Header & Version (#4791)
* fix: azure validation/extraction types

* fix: typing, add optional chaining for modelGroup and groupMap properties; expect azureOpenAIApiVersion in serverless tests

* fix: add support for azureOpenAIApiVersion and api-key in serverless mode across clients

* chore: update CONFIG_VERSION to 1.1.8, data-provider bump
2024-11-25 13:33:06 -05:00
Sean McGrath
07511b3db8 🎨 style: remove break-all class in modelSpec menu (#4787) 2024-11-25 16:10:05 +01:00
Danny Avila
7a5b697627 📦 chore: Update @anthropic-ai/sdk dependency to version 0.32.1 (#4782) 2024-11-22 19:24:55 -05:00
siddharth Sambharia
ecaf24d727 📘 docs: Portkey AI custom endpoint in librechat.example.yaml (#4625)
* Update librechat.example.yaml with Portkey AI example

* Update librechat.example.yaml

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-11-22 19:12:12 -05:00
Denis Palnitsky
fe78210e0d 🔉 feat: Extend text mimeTypes to support VTT (#4770)
* Extend text mimeTypes to support VTT

* remove log entry
2024-11-22 19:10:52 -05:00
Marco Beretta
ead9e11134 🎨 style: parameters panel update (#4780)
* 🔧 refactor: replace doubleClickHandler with onDoubleClick in slider components

* 🔧 refactor: consolidate DynamicInput and DynamicInputNumber components into a single DynamicInput component; fix: UI crashing when typing a character instead of number in max context/output tokens

* 🔧 style: update component styles to use bg-surface-secondary and bg-surface-tertiary for improved UI consistency
2024-11-22 19:10:03 -05:00
Danny Avila
2a77c98f51 🎯 fix: Google AI Client Stability; feat: gemini-exp models (#4781)
* fix: Google timing out and issuing AbortError, bump package, and use `@google/generative-ai` explicitly for latest models

* feat: gemini-exp-
2024-11-22 19:08:14 -05:00
Danny Avila
56b60cf863 📦 chore: Update NPM Packages (#4779) 2024-11-22 16:35:23 -05:00
Danny Avila
c87a51eaab 🌿 fix: forking a long conversation breaks chat structure (#4778)
* fix: branching and forking sometimes break conversation structure

* fix test for forking.

* chore: message type issues

* test: add conversation structure tests for message handling

---------

Co-authored-by: xyqyear <xyqyear@gmail.com>
2024-11-22 16:10:59 -05:00
Hongkai Ye
7d5be68747 🌊 feat: add streaming support for o1 models (#4760) 2024-11-20 15:53:23 -05:00
Robin Naundorf
77d1afcaee 🔗 fix: broken blog link in README (#4763) 2024-11-20 19:09:11 +01:00
Danny Avila
951bb9d0d0 🔧 fix: Anthropic Agent Model Assignment 2024-11-17 12:10:41 -05:00
Yuichi Oneda
b5232afcc7 🔧 Fix: Excessive Line Spacing in Markdown-rendered User Messages (#4718)
* fix: Excessive Line Spacing in User-Created Messages

* fix: Add whitespace-pre-wrap if user message is not markdown
2024-11-16 10:18:56 -05:00
MSITE.TOP
d9ed161104 🪙 feat: automatically add start balance (#4486)
* automatically add  start balance

https://github.com/danny-avila/LibreChat/issues/2687

* chore: imports order in userMethods.js

* Information about START_BALANCE has been added

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-11-16 10:17:17 -05:00
Danny Avila
493e64e6db 🪚 refactor: Optimize CONSOLE_JSON Debug Logs with Truncation (#4709) 2024-11-12 21:53:56 -05:00
Danny Avila
95201908e9 📦 fix: npm warnings; chore: bump deprecated packages (#4707)
* chore: bump langchain deps to address vulnerability warnings

* chore: bump community package and install textsplitters package

* fix: update expected result in tokenSplit tests for accuracy

* chore: remove CodeSherpa tools

* chore: remove E2B tools and loadToolSuite

* chore: remove CodeBrew tool and update related references

* chore: remove HumanTool and ChatTool, update tool references

* chore: remove Zapier tool from manifest.json and update SerpAPI

* chore: remove basic tools

* chore: update import path for RecursiveCharacterTextSplitter

* chore: update import path for DynamicStructuredTool

* chore: remove extractionChain.js and update tool filtering logic

* chore: npm audit fix

* chore: bump google packages

* chore: update DALL-E tool to DALL-E-3 and adjust authentication logic

* ci: update message classes

* chore: elliptic npm audit fix

* chore: update CallbackManager import and remove deprecated tool handling logic

* chore: imports order

* chore: remove unused code

---------

Co-authored-by: Max Sanna <max@maxsanna.com>
2024-11-12 18:51:32 -05:00
Danny Avila
d012da0065 🛡️ fix: Enhance File Upload Security & Error Handling (#4705)
* fix: sanitize filename in multer storage callback

* fix: ensure temporary image upload file is deleted after processing

* fix: prevent cleanup flag from being set to false before actually deleted

* refactor: user avatar, typing, use 'file' for formData instead of 'input', add disk storage, use localization

* fix: update Avatar component to include image dimensions in formData and refactor editor reference type

* fix: refactor avatar upload handling to use fs for file reading and enhance file validation

* fix: ensure temporary image upload file is deleted after processing

* fix: refactor avatar upload routes and handlers for agents and assistants, improve file handling and validation

* fix: improve audio file validation and cleanup

* fix: add filename sanitization utility and integrate it into multer storage configuration

* fix: update group project ID check for null and refactor delete prompt group response type

* fix: invalid access control for deleting prompt groups

* fix: add error handling and logging to checkBan middleware

* fix: catch conversation parsing errors

* chore: revert unnecessary height and width parameters from avatar upload

* chore: update librechat-data-provider version to 0.7.55

* style: ensure KaTeX can spread across visible space
2024-11-12 16:41:04 -05:00
Danny Avila
3c94ff2c04 🦙 fix: normalized endpoint for Ollama (#4681) 2024-11-10 14:13:14 -05:00
Danny Avila
81f29360e8 🫧 fix: Tool Auth Form Button to Prevent Form Bubbling (#4666) 2024-11-07 11:26:06 -05:00
Danny Avila
49ee88b6e8 ⚙️ fix: File Config Handling (#4664)
* chore: typing

* refactor: create file filter from custom fileConfig, if provided

* refactor: use logger utility to avoid overly verbose axios error logs when using RAG_API

* fix(useFileHandling): use memoization/callbacks to make sure the appropriate fileConfig is used; refactor: move endpoint to first field applied to formdata

* chore: update librechat-data-provider version to 0.7.54

* chore: revert type change
2024-11-07 11:11:20 -05:00
Danny Avila
d60a0af878 🦙 refactor: Normalize Ollama Config Names (#4657) 2024-11-07 08:26:35 -05:00
Adam Boeglin
c27b26cc31 🪨 fix: add AWS STS session token support to Bedrock client (#4655) 2024-11-07 08:06:42 -05:00
Danny Avila
766643ea1c 🎯 feat: Enhance Title Parameter Parsing with new Anthropic Format 2024-11-06 13:40:49 -05:00
Danny Avila
0c2a583df8 🔧 refactor: Optimize Agent Tool Loading and Fix Bedrock Tool Handling (#4641)
* fix: bedrock tool name regex

* fix: pass args as single input, attempt json first.

* refactor: remove toolMap from agent tool load as is not used

* fix: update formatAgentMessages test to use strictEqual for args comparison, testing new behavior
2024-11-05 11:24:26 -05:00
Danny Avila
3428c3c647 feat: Known Endpoint, xAI (#4632)
* feat: Known Endpoint, xAI

* chore: update librechat-data-provider version to 0.7.53

* ci: name property removal

* feat: add XAI_API_KEY to example environment variables
2024-11-04 16:27:54 -05:00
Danny Avila
fc41032923 🤖 feat: Claude 3.5 Haiku (#4629) 2024-11-04 15:10:24 -05:00
Danny Avila
2e519f9b57 🤖 feat: Custom Endpoint Agents (experimental) (#4627)
* wip: first pass, custom endpoint agents

* chore: imports

* chore: consolidate exports

* fix: imports

* feat: convert message.content array to strings for legacy format handling (deepseek/groq)

* refactor: normalize ollama endpoint name

* refactor: update mocking in isDomainAllowed.spec.js

* refactor: update deepseekModels in tokens.js and tokens.spec.js
2024-11-04 12:59:04 -05:00
Danny Avila
9437e95315 📑 fix: Access Control for Bookmarks (UI) (#4612) 2024-11-01 18:54:17 -04:00
Danny Avila
95011ce349 🚧 WIP: Merge Dev Build (#4611)
* refactor: Agent CodeFiles, abortUpload WIP

* feat: code environment file upload

* refactor: useLazyEffect

* refactor:
- Add `watch` from `useFormContext` to check if code execution is enabled
- Disable file upload button if `agent_id` is not selected or code execution is disabled

* WIP: primeCodeFiles; refactor: rename sessionId to session_id for uniformity

* Refactor: Rename session_id to sessionId for uniformity in AuthService.js

* chore: bump @librechat/agents to version 1.7.1

* WIP: prime code files

* refactor: Update code env file upload method to use read stream

* feat: reupload code env file if no longer active

* refactor: isAssistantTool -> isEntityTool + address type issues

* feat: execute code tool hook

* refactor: Rename isPluginAuthenticated to checkPluginAuth in PluginController.js

* refactor: Update PluginController.js to use AuthType constant for comparison

* feat: verify tool authentication (execute_code)

* feat: enter librechat_code_api_key

* refactor: Remove unused imports in BookmarkForm.tsx

* feat: authenticate code tool

* refactor: Update Action.tsx to conditionally render the key and revoke key buttons

* refactor(Code/Action): prevent uncheck-able 'Run Code' capability when key is revoked

* refactor(Code/Action): Update Action.tsx to conditionally render the key and revoke key buttons

* fix: agent file upload edge cases

* chore: bump @librechat/agents

* fix: custom endpoint providerValue icon

* feat: ollama meta modal token values + context

* feat: ollama agents

* refactor: Update token models for Ollama models

* chore: Comment out CodeForm

* refactor: Update token models for Ollama and Meta models
2024-11-01 18:36:39 -04:00
Tim Manik
1909efd6ba 📝 docs: Added RAG_USE_FULL_CONTEXT to .env.example (#4494) 2024-10-31 09:57:33 -04:00
Danny Avila
8cfacca8af 🔒 chore: bump elliptic to address CVE-2024-48948 (#4575) 2024-10-29 11:27:32 -04:00
Danny Avila
5861ebe081 🔒 fix: Override mdast-util-gfm-autolink-literal Package Version (#4574)
* fix: `mdast-util-gfm-autolink-literal` overriden to  due to https://github.com/syntax-tree/mdast-util-gfm-autolink-literal/issues/10

* chore: non-change to force workflow

* Revert "chore: non-change to force workflow"

This reverts commit ba7c15d5a0.

* chore: non-change to force workflow pt. 2

* chore: revert commit
2024-10-29 11:16:43 -04:00
Sebastian Diez
f270455be6 🔧 fix: Allow Azure Assistants Chats to be Deleted (#3893) 2024-10-29 08:09:35 -04:00
Marco Beretta
2b0654bb2c docs: 0.7.5 (#4569) 2024-10-28 16:50:44 -04:00
Danny Avila
e0222d42c6 🖌️ fix: ordered lists markers (#4568)
* fix ordered lists markers styling

* cleanup

* refactor: additional padding for 3-digit markers

* Refactor CSS to remove extra spacing in lists

---------

Co-authored-by: Thingersoft <thingersoft@gmail.com>
2024-10-28 15:56:03 -04:00
Adam Boeglin
a21591d25d 🪨 feat: Include Sonnet 3.5 v2 in Default Bedrock Models List (#4552) 2024-10-28 14:05:26 -04:00
Danny Avila
1526b429c9 🧵 feat: Implement Request Executor Pattern for Actions (#4566)
* chore: actions typing

* fix(actions): implement request executor pattern to prevent concurrent execution issues

BREAKING CHANGE: ActionRequest now uses a RequestExecutor pattern for isolated request state

- Introduce RequestConfig class to store immutable configuration
- Add RequestExecutor class to handle isolated request state for each execution
- Modify ActionRequest to act as a facade creating new executors for each operation
- Maintain backward compatibility through delegation and getters
- Add TypeScript types for better type safety
- Fix race conditions in concurrent executions with auth and params

This change prevents state mutation issues when the same action is called
multiple times concurrently, particularly when using authentication. Each
request now gets its own isolated state through a new executor instance,
solving race conditions while maintaining the existing API interface.

* ci: test isolation/immutatability

* chore: Update version to 0.7.51 in data-provider package

* refactor(actions): refactor createActionTool to use request executor pattern
2024-10-28 13:42:38 -04:00
J'aimemin
262176fec4 🔼 a11y: Proper attributes for the side panel toggle button (#4559)
- added aria-expanded attribute to indicate the panel's expanded/collapsed state
- added aria-controls attribute to specify the element controlled by the button
- updated aria-label using the localize function for better description
2024-10-28 11:03:38 -04:00
Danny Avila
b939e24f67 🔄 feat: Add Configurable Cache Headers for Index.html (#4565)
* refactor: move o1 model check, after vision request check

* feat(server): add configurable cache headers for index.html

• Add environment variables to control index.html cache headers
• Default to no-cache configuration for consistent app updates
• Document cache control options in .env.example
2024-10-28 11:01:31 -04:00
Danny Avila
a1647d76e0 🔐 feat: Enhance OpenID User Info Handling (#4561)
* oidc-changes Initial attempt at testing openidStrategy and adding OPENID_USERNAME_CLAIM setting

* oidc-changes Add OPENID_NAME_CLAIM

* oidc-changes cleanup oidc test code

* oidc-changes using mongo memory server for test

* oidc-changes Change tests to expect username all lowercase

* oidc-changes Add more tests

* chore: linting

* refactor: Simplify OpenID full name retrieval logic

* refactor: Simplify OpenID user info retrieval logic

* refactor: move helper to openidStrategy.js

---------

Co-authored-by: alihacks <alihacks@pm.me>
2024-10-27 11:41:48 -04:00
Danny Avila
600d21780b v0.7.5 (#4541) 2024-10-24 17:32:55 -04:00
Danny Avila
3f3b5929e9 🛡️ fix: Minor Vulnerabilities (#4543)
* fix: ReDoS in ChatGPT Import

* ci: should correctly process citations from real ChatGPT data

* ci: Add ReDoS vulnerability test for processAssistantMessage

* refactor: Update thread management and citation handling

* refactor(validateImageRequest): robust validation

* refactor(Prompt.js): update name search regex to escape special characters

* refactor(Preset): exclude user from preset update to prevent mass assignment

* refactor(files.js): Improve file deletion process

* ci: updated validateImageRequest.spec.js

* a11y: plugin pagination

* refactor(CreatePromptForm.tsx): Improve input field styling

* chore(Prompts): typing and accessibility

* fix: prompt creation access role check

* chore: remove duplicate jsdocs
2024-10-24 15:50:48 -04:00
Danny Avila
094a40dbb0 🌏 i18n: Added Missing Localizations (Ar, De, Es, Fr, It, Jp, Ko, Ru, Zh) (#4540)
* chore: remove comparisons

* feat: use prompt caching for translations

* chore: wip translation readme

* i18n: korean translations

* refactor: use promises for faster translation processing

* refactor: update translation model to 'claude-3-5-sonnet-20241022'

* refactor: optimize sleep duration for translation processing

* i18n: add missing keys

* refactor: standardize languages in their own respective languages

* Refactor translation instructions in README.md
2024-10-24 10:48:57 -04:00
Danny Avila
840851cb0f 🍎 fix: Update "Enter to send" behavior for Mac users (#4539)
* fix: Update useTextarea to handle Ctrl+Enter on Mac

* fix: Update language files for message sending behavior
2024-10-24 09:49:10 -04:00
J'aimemin
c346596131 🌏 i18n: modify username min length in Ko.ts (3→2) (#4532) 2024-10-24 09:45:38 -04:00
Danny Avila
e0e393b8a4 🎚️ fix: Google top_k Slider Step to Integers (#4537) 2024-10-24 09:24:38 -04:00
Danny Avila
2996058fa2 🔘 a11y: Switch Contrast and File Input Key Events to WCAG (#4536)
* 🔘 a11y: Improve Contrast of Switch/Toggles to WCAG Standard

* refactor: Improve file attachment accessibility in Chat Input component

* refactor: clear input ref value before clicks
2024-10-24 09:12:49 -04:00
Danny Avila
655f63714b 👓 fix: Assistants Vision Prompt Error Handling (legacy) (#4529)
* fix: vision prompt error handling

* fix: Update model reference in chatV1 controller

* remove model reference
2024-10-23 15:21:22 -04:00
Danny Avila
4da35b9cf5 🤖 feat: Add support for claude-3-5-sonnet-20241022 (#4510) 2024-10-22 16:45:26 -04:00
Danny Avila
ebe3e7f796 🖼️ fix: Avatar Handling for Agents and Assistants (#4507)
The changes include:
- In the agent controller:
  - Removed the parsing of the avatar metadata from the request body.
  - Fetched the avatar data from the agent object using the agent ID.
  - Updated the error logging when fetching the agent.
  - Updated the deleteFileByFilter function to include the user ID when deleting the old avatar file.

- In the assistant controller:
  - Removed the parsing of the metadata from the request body.
  - Fetched the metadata from the assistant object using the assistant ID.
  - Updated the error logging when fetching the assistant.
  - Updated the deleteFileByFilter function to include the user ID when deleting the old avatar file.
2024-10-22 14:53:45 -04:00
Danny Avila
ec922986a9 🤖 fix: Address Minor Agent Issues (#4483)
* fix(Agents): remove test code in openAI/llm.js

* refactor: add use of enums in encodeAndFormat

* fix: image attachment payload formatting for agents

* chore: imports
2024-10-21 09:41:04 -04:00
Danny Avila
a6fbe7591a chore: bump librechat-data-provider 2024-10-21 09:38:40 -04:00
Danny Avila
f121439960 🔐 refactor: Unverified User Verification Logic (#4482) 2024-10-21 07:51:45 -04:00
Marco Beretta
4d4a6b53f1 🎨 style: UI Style Enhancements and Refactor for Improved Consistency and Layout (#4471)
* 🎨 style: adjust padding and class names in UI components

* 🎨 style: update ExportModal export button, update Export button hover style, refactor ChatForm style and fixed isRTL styles, update AttachFile position

* 🎨 style: remove redundant border classes in SettingsTabs components for cleaner UI

* 🎨 style: refactor Account component, extract DisplayUsernameMessages, and remove redundant border classes for cleaner layout

* 🎨 style: conditionally render Dropdown in ForkSettings component for improved UI responsiveness

* 🎨 style: replace DropdownNoState with Dropdown in voice selection components for consistency

* 🎨 style: update Settings component layout for better responsivenes on large screens

* 🎨 style: remove redundant margin-top classes for cleaner layout in various components
2024-10-20 11:29:47 -04:00
Danny Avila
ecf5699513 🧪 chore: raise max temperature to 2 for OpenAI/Custom Endpoints 2024-10-19 08:39:15 -04:00
Alex Wegener
e25c16cd4f 🖼️ feat: Add dat.gui to Artifacts UI libs (#4344) 2024-10-19 08:34:57 -04:00
Marco Beretta
8f3de7d11f 🎨 refactor: UI stlye (#4438)
* feat: Refactor ChatForm and StopButton components for improved styling and localization

* feat: Refactor AudioRecorder, ChatForm, AttachFile, and SendButton components for improved styling and layout

* feat: Add RevokeAllKeys component and update styling for buttons and inputs

* feat: Refactor ClearChats component and update ClearConvos functionality for improved clarity and user experience

* feat: Remove ClearConvos component and update related imports and functionality in Avatar and DeleteCacheButton components

* feat: Rename DeleteCacheButton to DeleteCache and update related imports; enhance confirmation message in localization

* feat: Update ChatForm layout for RTL support and improve component structure

* feat: Adjust ChatForm layout for improved RTL support and alignment

* feat: Refactor Bookmark components to use new UI elements and improve styling

* feat: Update FileSearch and ShareAgent components for improved button styling and layout

* feat: Update ChatForm and TextareaHeader styles for improved UI consistency

* feat: Refactor Nav components for improved styling and layout adjustments

* feat: Update button sizes and padding for improved UI consistency across chat components

* feat: Remove ClearChatsButton test file as part of code cleanup
2024-10-19 08:30:52 -04:00
adrianfagerland
20fb7f05ae 🔃 refactor: rename all server endpoints to use same file names (#4364) 2024-10-19 08:24:07 -04:00
Yuki Matsukura
f3e2bd0a12 🐋 chore: remove Docker version syntax as its no longer (#4375) 2024-10-19 08:22:26 -04:00
Danny Avila
b85c6206ab 🤖 fix: Minor Assistants Issues (#4436)
* refactor(OpenAIClient): titleChatCompletion try/catch

* fix: remove duplicate concatenation as seems to be handled by client SDK now

* fix: assistants image upload

* chore: imports order
2024-10-16 15:04:10 -04:00
Danny Avila
65888c274a ⬆️ feat: Cancel chat file uploads; fix: Assistant uploads (#4433)
* refactor: move file mutations to dedicated file, improve typing

* refactor(ChatForm): utilize FileFormWrapper to consolidate file upload logic/rendering to single parent

* refactor: better TSX heirarchies between AttachFile and FileFormWrapper

* refactor: `abortUpload` WIP

* fix: file debugging and file upload issues

* refactor: reject promise outright if axios intercepted error does not include response property

* chore: bump data-provider version to 0.7.428

* refactor: Add return type to localize function in Translation.ts

* refactor: allow message file attachment upload request cancellations, and add localizations for file upload errors

* refactor: include Azure OpenAI in paramEndpoints set

* fix: assistant form uploads and better typing

* refactor: consolidate logic
2024-10-16 11:24:40 -04:00
Danny Avila
0870acd086 📦 chore: npm package audit (#4424)
* chore: bump cookie dependencies

* chore: bump express, express-session, express-rate-limit, and all vulnerable `cookie` dependencies
2024-10-15 20:05:22 -04:00
Danny Avila
c54a57019e 🕒 feat: Add 5-second timeout for Fetching Model Lists (#4423)
* refactor: add 5 second timeout for fetching AI provider model lists

* ci: fix test due to recent changes
2024-10-15 19:37:41 -04:00
Marco Beretta
ef118009f6 feat: Add GOOGLE_LOC environment variable (#4395) 2024-10-15 18:10:48 -04:00
Hongkai Ye
bf5b87e0b2 🪙 feat: Update token value for gpt-4o (#4387) 2024-10-11 08:27:29 -04:00
Danny Avila
bab0152c58 🤖 feat: Enhance Assistant Model Handling for Model Specs (#4390)
* chore: cleanup type issues in client/src/utils/endpoints

* refactor: use Constant enum for 'new' conversationId

* refactor: select assistant model if not provided for model spec
2024-10-11 08:20:32 -04:00
Abhijith E A
2846779603 🔨 fix(AzureOpenAI): o1 model, stream parameter check (#4381) 2024-10-10 11:10:15 -04:00
Danny Avila
873e0473ec 🧠 feat: Implement O1 Model Support for Max Tokens Handling (#4376) 2024-10-10 02:36:36 -04:00
Hanna Daoud
bdc2fd307f 🔨 fix(ToolCall): Check output string type before performing .toLowerCase() (#4324) 2024-10-08 01:26:03 -04:00
Jürgen Walter
5da7766fad 💬 fix: adjust regex in ModelService to recognize o1 models
API query for OpenAI returns list of models. Their names are filtered using a regex. The regex did not yet account for model names starting with o1-
2024-10-07 13:33:43 -04:00
Danny Avila
519df46e1f 🪨 feat: RAG API Support for AWS Bedrock (#4322)
* feat: bedrock/agents legacy rag api file processing

* refactor: use agent instructions for build message options
2024-10-03 08:53:28 -04:00
Danny Avila
104341e0e7 🖼️ fix: Prevent Empty Avatar Source (#4321) 2024-10-03 07:42:15 -04:00
Pranshu Mahajan
cb0b69e807 🪖 refactor: Helm chart release workflow (#4311) 2024-10-03 07:20:56 -04:00
normunds-wipo
77bcb80e00 🛠️ fix: Remove expiresAt field when setting expiry to "never" (#4294) 2024-10-03 07:17:21 -04:00
bijucyborg
ee5b96a7c8 🔖 fix: bookmark error using CosmosDB - Added index to position field in schema (#4296) 2024-10-03 07:15:27 -04:00
Danny Avila
2ca257dfb9 ⚙️ fix: minor issues related to agents (#4297)
* chore: deprecate `web-browser` tool

* fix: edit agent permission
2024-10-01 11:11:15 -04:00
Danny Avila
2ce8647540 👷 refactor(removeNullishValues): allow empty strings configured in parameters (#4291) 2024-09-30 18:15:16 -04:00
Danny Avila
ad74350036 🚧 chore: merge latest dev build (#4288)
* fix: agent initialization, add `collectedUsage` handling

* style: improve side panel styling

* refactor(loadAgent): Optimize order agent project ID retrieval

* feat: code execution

* fix: typing issues

* feat: ExecuteCode content part

* refactor: use local state for default collapsed state of analysis content parts

* fix: code parsing in ExecuteCode component

* chore: bump agents package, export loadAuthValues

* refactor: Update handleTools.js to use EnvVar for code execution tool authentication

* WIP

* feat: download code outputs

* fix(useEventHandlers): type issues

* feat: backend handling for code outputs

* Refactor: Remove console.log statement in Part.tsx

* refactor: add attachments to TMessage/messageSchema

* WIP: prelim handling for code outputs

* feat: attachments rendering

* refactor: improve attachments rendering

* fix: attachments, nullish edge case, handle attachments from event stream, bump agents package

* fix filename download

* fix: tool assignment for 'run code' on agent creation

* fix: image handling by adding attachments

* refactor: prevent agent creation without provider/model

* refactor: remove unnecessary space in agent creation success message

* refactor: select first model if selecting provider from empty on form

* fix: Agent avatar bug

* fix: `defaultAgentFormValues` causing boolean typing issue and typeerror

* fix: capabilities counting as tools, causing duplication of them

* fix: formatted messages edge case where consecutive content text type parts with the latter having tool_call_ids would cause consecutive AI messages to be created. furthermore, content could not be an array for tool_use messages (anthropic limitation)

* chore: bump @librechat/agents dependency to version 1.6.9

* feat: bedrock agents

* feat: new Agents icon

* feat: agent titling

* feat: agent landing

* refactor: allow sharing agent globally only if user is admin or author

* feat: initial AgentPanelSkeleton

* feat: AgentPanelSkeleton

* feat: collaborative agents

* chore: add potential authorName as part of schema

* chore: Remove unnecessary console.log statement

* WIP: agent model parameters

* chore: ToolsDialog typing and tool related localization chnages

* refactor: update tool instance type (latest langchain class), and rename google tool to 'google' proper

* chore: add back tools

* feat: Agent knowledge files upload

* refactor: better verbiage for disabled knowledge

* chore: debug logs for file deletions

* chore: debug logs for file deletions

* feat: upload/delete agent knowledge/file-search files

* feat: file search UI for agents

* feat: first pass, file search tool

* chore: update default agent capabilities and info
2024-09-30 17:17:57 -04:00
Danny Avila
f33e75e2ee 🏷️ fix: Ensure modelLabel Field Usage for ModelSpecs (custom/openAI endpoints) pt. 3 (#4228) 2024-09-24 11:34:42 -04:00
Danny Avila
9e371d6157 🧹 chore: bump vite-plugin-pwa to ^0.20.5, and use overrides to address CVE-2024-47068 (#4226)
* chore: bump vite-plugin-pwa to `^0.20.5`, and use `overrides` to address CVE-2024-47068

* chore: bump data-provider version
2024-09-24 10:36:11 -04:00
Danny Avila
ba1014a038 🏷️ fix: Ensure modelLabel Field Usage for ModelSpecs pt. 2 (#4225)
* fix: ensure modelSpec presets have endpointType defined, add `modelLabel` to openAISchema

* chore: bump rollup due to CVE-2024-47068
2024-09-24 09:52:22 -04:00
Danny Avila
6f498eee0f 🏷️ fix: Ensure modelLabel Field Usage for ModelSpecs/GPTPlugins (#4224) 2024-09-24 07:27:11 -04:00
Danny Avila
321260e3c7 🔄 refactor: Apply Config Preset for Model Spec Enforcement (#4214) 2024-09-23 21:47:49 -04:00
Danny Avila
17e59349ff 📎 feat: Attachment Handling for v1/completions (#4205)
* refactor: add handling of attachments in v1/completions method

* ci: update OpenAIClient.test.js
2024-09-23 11:03:28 -04:00
Danny Avila
4328a25b6b 🧹 fix: Resolve Unarchive Conversation Bug, Archive Pagination (#4189)
* feat: add cleanup service for 'bugged' conversations (empty/nullish conversationIds)

* fix(ArchivedChatsTable): typing and minor styling issues

* fix: properly archive conversations

* fix: archive convo application crash

* chore: remove unused `useEffect`

* fix: add basic navigation

* chore: typing
2024-09-22 17:21:50 -04:00
Marco Beretta
2d62eca612 👐 style: Improve a11y/theming for Settings Dialog, Dropdown Menus; fix: SearchBar focus issues (#4091)
* fix: cursor pointer not applying correct in the root component

* fix: add cursor-not-allowed to disabled state in SendButton component

* feat: update Dropdown to ariakit and changed LLM error's style

* feat: switched to ariakit's Dropdown and style improvements

* feat: archive updates

* refactor: delete conversations in archive

* refactor: settings

* add cool settings animation

* a11y: settings update

* style: update settings

* style: settings account settings menu; a11y(AccountSettings): switched to AriaKit

* a11y: account settings update

* style: update my files dialog

* fix: tests

* chore: remove console.log()

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-09-21 22:45:50 -04:00
Danny Avila
eba2c9a032 📅 fix: Conversation grouping and labeling for prior years (#4180) 2024-09-21 18:50:04 -04:00
Danny Avila
b0a48fd693 📧 feat: LDAP Authentication Enhancement for Email Handling (#4177)
* allow other ldap field besides "mail", or fallback to made up email

* chore(ldap): add detailed logging for email fallback scenarios

---------

Co-authored-by: Maxim Bonnaerens <maxim@bonnaerens.be>
2024-09-21 10:44:27 -04:00
Riya Amemiya
561650d6f9 🐛 fix(analytics): prevent multiple GTM initializations (#4174)
* feat(types): Add global window interface for Google Tag Manager

* refactor(Chat/Footer): Move GTM initialization to useEffect for better lifecycle management

* fix(hooks): add useEffect to initialize TagManager conditionally
2024-09-21 10:30:40 -04:00
Danny Avila
c1c13a69dc 🗂️ fix: Optimize Conversation Grouping and Sorting (#4173)
* chore: remove double import of TrashIcon

* fix(convos): eslint warnings

* ci(convos): add test for month sorting

* fix(convos): grouping by month in chronological order instead of alphabetical, optimize sort

* ci: additional tests for conversation sorting

* chore: fix eslint disable rule

* chore: imports, use constant enum for 'new' value

* fix: test dependent on current date
2024-09-21 10:20:30 -04:00
Danny Avila
44458d3832 🔖 fix: URI Encoding for Bookmarks (#4172)
* fix: never defined AcceptTermsMutationOptions

* fix: lack of URI encoding in tag mutations
2024-09-21 09:06:02 -04:00
Danny Avila
be44caaab1 🖋️ feat: Add option to render User Messages as Markdown (#4170) 2024-09-20 20:29:42 -04:00
Danny Avila
42b7373ddc 🎨 fix: Terms and Conditions Modal Styling (#4169)
* fix: modal styling issue, where buttons in light mode are not accessible/visible

* refactor: use MarkdownLite instead

* chore: make inner content accessible
2024-09-20 18:33:56 -04:00
Vesna Tan
d096c281ba 👐 a11y: New Chat button - focus, mobile label, collapsed sidebar label (#4069) 2024-09-19 20:32:04 -04:00
Danny Avila
94d1afee84 🛡️ chore: address several npm vulnerabilities (#4151)
* chore: bump express to 4.21.0 to address CVE-2024-45590 and CVE-2024-43796

* chore: npm audit fix

* chore: uninstall unused `ws` dependency

* chore: bump nodemailer to 6.9.15

* chore: bump mongoose to v7.3.3

* chore: bump lint-staged for micromatch upgrade

* chore: bump axios to 1.7.7

* chore: npm audit fix for mongodb/mongoose vulns
2024-09-19 20:28:32 -04:00
Danny Avila
f7341336dd 🤖 ci: Dependabot for Security Updates (#4134) 2024-09-19 18:22:03 -04:00
Danny Avila
fd056d2e9c 🤖 ci: Dependabot for Security Updates (#4134) 2024-09-19 18:16:18 -04:00
Danny Avila
486db5722b 🤖 ci: Configure Dependabot for Security Updates (#4134) 2024-09-19 18:14:11 -04:00
Danny Avila
33f80cd70c 🤖 ci: Configure Dependabot for Security Updates (#4134) 2024-09-19 18:11:06 -04:00
Danny Avila
3ea2d908e0 🛠️ fix: getStreamUsage Method in OpenAIClient (#4133) 2024-09-19 18:07:49 -04:00
Danny Avila
5f28682314 🔧 fix: OpenAIClient Response Handling for Legacy /v1/completions (#4128) 2024-09-19 13:20:29 -04:00
Danny Avila
8dc5b320bc 📊 refactor: use Parameters from Side Panel for OpenAI, Anthropic, and Custom endpoints (#4092)
* feat: openai parameters

* refactor: anthropic/bedrock params, add preset params for openai, and add azure params

* refactor: use 'compact' schemas for anthropic/openai

* refactor: ensure custom endpoints are properly recognized as valid param endpoints

* refactor: update paramEndpoints check in BaseClient.js

* chore: optimize logging by omitting modelsConfig

* refactor: update label casing in baseDefinitions combobox items

* fix: remove 'stop' model options when using o1 series models

* refactor(AnthropicClient): remove default `stop` value

* refactor: reset params on parameters change

* refactor: remove unused default parameter value map introduced in prior commit

* fix: 'min' typo for 'max' value

* refactor: preset settings

* refactor: replace dropdown for image detail with slider; remove `preventDelayedUpdate` condition from DynamicSlider

* fix: localizations for freq./pres. penalty

* Refactor maxOutputTokens to use coerceNumber in tConversationSchema

* refactor(AnthropicClient): use `getModelMaxOutputTokens`
2024-09-17 22:25:54 -04:00
Danny Avila
ebdbfe8427 🛠️ fix: Chrome App Crash on Endpoint Selection in Edit Preset Dialog (#4096) 2024-09-17 15:33:12 -04:00
Danny Avila
fc887ba847 📁 feat: Add C# Support for Native File Search (#4058) 2024-09-15 13:14:33 -04:00
Danny Avila
ab82966210 🔐 feat: Enhance Bedrock Credential Handling (#4051) 2024-09-14 12:52:35 -04:00
Danny Avila
f1ae267850 🪙 fix: usage check for reasoning_tokens 2024-09-13 09:51:09 -04:00
Daniel
c792e3279f 🍪 fix: input validation for lang cookie (#4024)
Co-authored-by: DanielAlt <daniel.altenburg@proton.me>
2024-09-13 09:00:59 -04:00
Marco Beretta
4ef5ae6f71 💡 style: switched to Ariakit's tooltip (#3748)
* inital Tooltip implementation and test

* style(tooltip): L/R sidePanel and Nav

* style(tooltip): unarchive button; refactor: `useArchiveHandler` and `ArchiveButton`

* style(tooltip): Delete button

* refactor: remove unused className prop in DeleteButton component

* style(tooltip): finish final tooltip and fix bookmark edit and delete button

* refactor(ui): remove TooltipTest and DropDownMenu component and unused imports

* style: update mobile UI

* fix: sidePanel icon not showing

* feat(AttachFile): add tooltip

* fix(NavToggle): remove button
without this button, kb users don't have to manually press 2 times to change the focus
Also, tooltips with buttons focus don't trigger

* fix: right side panel issue with double button

* fix: merge issues

* fix: sharedLink table issue

* chore: update ariakit and framer-motion version

* a11y: kb toggle for sidebar

* feat: tooltip for some buttons
2024-09-13 08:59:09 -04:00
Danny Avila
e293ff63f9 🪨 feat: AWS Bedrock Default Credentials Chain (#4038)
* feat: use AWS cascading default providers if credentials are omitted

Environment variables exposed via process.env
SSO credentials from token cache
Web identity token credentials
Shared credentials and config ini files
The EC2/ECS Instance Metadata Service

The default credential provider will invoke one provider at a time and only continue to the next if no credentials have been located. For example, if the process finds values defined via the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, the files at ~/.aws/credentials and ~/.aws/config will not be read, nor will any messages be sent to the Instance Metadata Service.

* fix: usage check in OpenAIClient

* refactor: Improve usage check in OpenAIClient
2024-09-13 08:53:50 -04:00
Danny Avila
45b42830a5 🚀 feat: o1 (#4019)
* feat: o1 default response sender string

* feat: add o1 models to default openai models list, add `no_system_messages` error type; refactor: use error type as localization key

* refactor(MessageEndpointIcon): differentiate openAI icon model color for o1 models

* refactor(AnthropicClient): use new input/output tokens keys; add prompt caching for claude-3-opus

* refactor(BaseClient): to use new input/output tokens keys; update typedefs

* feat: initial o1 model handling, including token cost complexity

* EXPERIMENTAL: special handling for o1 model with custom instructions
2024-09-12 18:15:43 -04:00
Danny Avila
9a393be012 🪨 fix: Formatting Edge Case Handling for Bedrock Messages (#4016)
* refactor: Remove console.log statement in SelectDropDown component

* fix(bedrock): edge case - message.content as string creating message formatting issue
2024-09-12 06:06:22 -04:00
Marco Beretta
c3dc03b063 🔐 fix: token not using webcrypto (#4005)
* fix: token

* style: auth pages updated `|` color
2024-09-11 22:25:14 -04:00
Yuichi Oneda
aea01f0bc5 🚀 feat: Banner (#3952)
* feat: Add banner schema and model

* feat: Add optional JwtAuth

To handle the conditional logic with and without authentication within the model.

* feat: Add an endpoint to retrieve a banner

* feat: Add implementation for client to use banner and access API

* feat: Display a banner on UI

* feat: Script for updating and deleting banners

* style: Update banner style

* fix: Adjust the height when the banner is displayed

* fix: failed specs
2024-09-11 09:34:25 -04:00
Sebastian Diez
07e5531b5b ⚙️ fix: Ensure Azure AI Search TOP is a number (#3891)
allows configuration through AZURE_AI_SEARCH_SEARCH_OPTION_TOP enviroment variable
2024-09-11 09:21:33 -04:00
Marco Beretta
35a89bfa99 🔐 style: update auth and loading screen (#3875)
* style: improve auth UI

* style(SocialButton): fix hover style

* remove testing files

* fix: package-lock

* feat: loading screen color based on theme

* fix: handle `system` style on loading screen

* fix(ThemeSelector): Correct icon and text color handling for `system` theme

* remove test file
2024-09-11 09:20:19 -04:00
Danny Avila
020995514e v0.7.5-rc2 (#3976)
*  v0.7.5-rc2

* docs: update README

* refactor(settings): Update rememberForkOption default value

* a11y: proper screen reader announcements for content blocks

* Update version to 0.7.423 in package-lock.json and packages/data-provider/package.json

* chore: rename rememberForkOption -> rememberDefaultFork to apply new default value

* fix: headlessui menu stealing focus from Settings Dialog when pressing Enter
2024-09-10 19:00:27 -04:00
Marco Beretta
d6c0121b19 ⌨️ a11y(Settings): Improved Keyboard Navigation & Consistent Styling (#3975)
* feat: settings tba accessible

* refactor: cleanup unused code

* refactor: improve accessibility and user experience in ChatDirection component

* style: focus ring primary class

* improve a11y of avatar dialog

* style: a11y improvements for Settings

* style: focus ring primary class in OriginalDialog component

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-09-10 15:11:39 -04:00
Danny Avila
1a1e6850a3 🪨 fix: Minor AWS Bedrock/Misc. Improvements (#3974)
* refactor(EditMessage): avoid manipulation of native paste handling, leverage react-hook-form for textarea changes

* style: apply better theming for MinimalIcon

* fix(useVoicesQuery/useCustomConfigSpeechQuery): make sure to only try request once per render

* feat: edit message content parts

* fix(useCopyToClipboard): handle both assistants and agents content blocks

* refactor: remove save & submit and update text content correctly

* chore(.env.example/config): exclude unsupported bedrock models

* feat: artifacts for aws bedrock

* fix: export options for bedrock conversations
2024-09-10 12:56:19 -04:00
Danny Avila
341e086d70 🛠️ fix: Completion Edge Cases & Improve Error Handling UX (#3968)
* fix: edge cases concerning completion response as an array

* refactor: improve invalid request error UX
2024-09-09 20:58:15 -04:00
Danny Avila
0148b9b097 🔒 refactor: Apply interface settings to all Roles (#3967) 2024-09-09 20:15:08 -04:00
Danny Avila
748b41eda4 🔒 feat: RBAC for Multi-Convo Feature (#3964)
* fix: remove duplicate keys in German language translations

* wip: multi-convo role permissions

* ci: Update loadDefaultInterface tests due to MULTI_CONVO

* ci: update Role.spec.js with tests for MULTI_CONVO permission type

* fix: Update ContentParts component to handle undefined content array

* feat: render Multi-Convo based on UI permissions
2024-09-09 16:29:24 -04:00
Danny Avila
d59b62174f 🪨 feat: AWS Bedrock support (#3935)
* feat: Add BedrockIcon component to SVG library

* feat: EModelEndpoint.bedrock

* feat: first pass, bedrock chat. note: AgentClient is returning `agents` as conversation.endpoint

* fix: declare endpoint in initialization step

* chore: Update @librechat/agents dependency to version 1.4.5

* feat: backend content aggregation for agents/bedrock

* feat: abort agent requests

* feat: AWS Bedrock icons

* WIP: agent provider schema parsing

* chore: Update EditIcon props type

* refactor(useGenerationsByLatest): make agents and bedrock editable

* refactor: non-assistant message content, parts

* fix: Bedrock response `sender`

* fix: use endpointOption.model_parameters not endpointOption.modelOptions

* fix: types for step handler

* refactor: Update Agents.ToolCallDelta type

* refactor: Remove unnecessary assignment of parentMessageId in AskController

* refactor: remove unnecessary assignment of parentMessageId (agent request handler)

* fix(bedrock/agents): message regeneration

* refactor: dynamic form elements using react-hook-form Controllers

* fix: agent icons/labels for messages

* fix: agent actions

* fix: use of new dynamic tags causing application crash

* refactor: dynamic settings touch-ups

* refactor: update Slider component to allow custom track class name

* refactor: update DynamicSlider component styles

* refactor: use Constants value for GLOBAL_PROJECT_NAME (enum)

* feat: agent share global methods/controllers

* fix: agents query

* fix: `getResponseModel`

* fix: share prompt a11y issue

* refactor: update SharePrompt dialog theme styles

* refactor: explicit typing for SharePrompt

* feat: add agent roles/permissions

* chore: update @librechat/agents dependency to version 1.4.7 for tool_call_ids edge case

* fix(Anthropic): messages.X.content.Y.tool_use.input: Input should be a valid dictionary

* fix: handle text parts with tool_call_ids and empty text

* fix: role initialization

* refactor: don't make instructions required

* refactor: improve typing of Text part

* fix: setShowStopButton for agents route

* chore: remove params for now

* fix: add streamBuffer and streamRate to help prevent 'Overloaded' errors from Anthropic API

* refactor: remove console.log statement in ContentRender component

* chore: typing, rename Context to Delete Button

* chore(DeleteButton): logging

* refactor(Action): make accessible

* style(Action): improve a11y again

* refactor: remove use/mention of mongoose sessions

* feat: first pass, sharing agents

* feat: visual indicator for global agent, remove author when serving to non-author

* wip: params

* chore: fix typing issues

* fix(schemas): typing

* refactor: improve accessibility of ListCard component and fix console React warning

* wip: reset templates for non-legacy new convos

* Revert "wip: params"

This reverts commit f8067e91d4.

* Revert "refactor: dynamic form elements using react-hook-form Controllers"

This reverts commit 2150c4815d.

* fix(Parameters): types and parameter effect update to only update local state to parameters

* refactor: optimize useDebouncedInput hook for better performance

* feat: first pass, anthropic bedrock params

* chore: paramEndpoints check for endpointType too

* fix: maxTokens to use coerceNumber.optional(),

* feat: extra chat model params

* chore: reduce code repetition

* refactor: improve preset title handling in SaveAsPresetDialog component

* refactor: improve preset handling in HeaderOptions component

* chore: improve typing, replace legacy dialog for SaveAsPresetDialog

* feat: save as preset from parameters panel

* fix: multi-search in select dropdown when using Option type

* refactor: update default showDefault value to false in Dynamic components

* feat: Bedrock presets settings

* chore: config, fix agents schema, update config version

* refactor: update AWS region variable name in bedrock options endpoint to BEDROCK_AWS_DEFAULT_REGION

* refactor: update baseEndpointSchema in config.ts to include baseURL property

* refactor: update createRun function to include req parameter and set streamRate based on provider

* feat: availableRegions via config

* refactor: remove unused demo agent controller file

* WIP: title

* Update @librechat/agents to version 1.5.0

* chore: addTitle.js to handle empty responseText

* feat: support images and titles

* feat: context token updates

* Refactor BaseClient test to use expect.objectContaining

* refactor: add model select, remove header options params, move side panel params below prompts

* chore: update models list, catch title error

* feat: model service for bedrock models (env)

* chore: Remove verbose debug log in AgentClient class following stream

* feat(bedrock): track token spend; fix: token rates, value key mapping for AWS models

* refactor: handle streamRate in `handleLLMNewToken` callback

* chore: AWS Bedrock example config in `.env.example`

* refactor: Rename bedrockMeta to bedrockGeneral in settings.ts and use for AI21 and Amazon Bedrock providers

* refactor: Update `.env.example` with AWS Bedrock model IDs URL and additional notes

* feat: titleModel support for bedrock

* refactor: Update `.env.example` with additional notes for AWS Bedrock model IDs
2024-09-09 12:06:59 -04:00
Raí Santos
8c14360263 🌍 i18n: Improved Portuguese language translations (#3947)
Co-authored-by: RaiSantos <itzraisu@gmail.com>
2024-09-07 08:18:56 -04:00
Marlon
d0dc858e2d 🌍 i18n: Improved German language translations (#3924) 2024-09-05 21:06:20 -04:00
hide361
9cf390c657 🌍 i18n: Update Japanese translation (#3877) 2024-09-05 21:06:01 -04:00
Hervey
14199d5521 🌍 i18n: Updated Chinese Translation (#3871)
* 🌍 : Updated Chinese Translation

* 🌍 : Updated Chinese Translation
2024-09-05 21:05:40 -04:00
Vesna Tan
b9197f90c6 👐 a11y: Misc. Improvements (#3910)
* fix focus for cancel button in convo delete modal window #3829

* add aria-hidden and aria-label to X and Check svg/button respectively and updated OGDialogClose focus color

* update rename, newchat, newchat icon, ConvoOptions icon
2024-09-05 14:30:17 -04:00
Danny Avila
9ec665dd2c 🪟 fix: Windows Build (npm) (#3889)
* chore: package-lock.json

* chore: remove shadcn files (temp)

* refactor: language comparisons script

* fix: resolve package-lock file for windows compatibility

* chore: Enable Windows unit tests for frontend

* refactor: move shadcn components to data-provider
2024-09-02 10:01:09 -04:00
Danny Avila
136599081c 🧩 fix: plugins build options, prevent undefined tools error (#3876) 2024-09-01 08:35:05 -04:00
Danny Avila
a0291ed155 🚧 chore: merge latest dev build to main repo (#3844)
* agents - phase 1 (#30)

* chore: copy assistant files

* feat: frontend and data-provider

* feat: backend get endpoint test

* fix(MessageEndpointIcon): switched to AgentName and AgentAvatar

* fix: small fixes

* fix: agent endpoint config

* fix: show Agent Builder

* chore: install agentus

* chore: initial scaffolding for agents

* fix: updated Assistant logic to Agent Logic for some Agent components

* WIP first pass, demo of agent package

* WIP: initial backend infra for agents

* fix: agent list error

* wip: agents routing

* chore: Refactor useSSE hook to handle different data events

* wip: correctly emit events

* chore: Update @librechat/agentus npm dependency to version 1.0.9

* remove comment

* first pass: streaming agent text

* chore: Remove @librechat/agentus root-level workspace npm dependency

* feat: Agent Schema and Model

* fix: content handling fixes

* fix: content message save

* WIP: new content data

* fix: run step issue with tool calls

* chore: Update @librechat/agentus npm dependency to version 1.1.5

* feat: update controller and agent routes

* wip: initial backend tool and tool error handling support

* wip: tool chunks

* chore: Update @librechat/agentus npm dependency to version 1.1.7

* chore: update tool_call typing, add test conditions and logs

* fix: create agent

* fix: create agent

* first pass: render completed content parts

* fix: remove logging, fix step handler typing

* chore: Update @librechat/agentus npm dependency to version 1.1.9

* refactor: cleanup maps on unmount

* chore: Update BaseClient.js to safely count tokens for string, number, and boolean values

* fix: support subsequent messages with tool_calls

* chore: export order

* fix: select agent

* fix: tool call types and handling

* chore: switch to anthropic for testing

* fix: AgentSelect

* refactor: experimental: OpenAIClient to use array for intermediateReply

* fix(useSSE): revert old condition for streaming legacy client tokens

* fix: lint

* revert `agent_id` to `id`

* chore: update localization keys for agent-related components

* feat: zod schema handling for actions

* refactor(actions): if no params, no zodSchema

* chore: Update @librechat/agentus npm dependency to version 1.2.1

* feat: first pass, actions

* refactor: empty schema for actions without params

* feat: Update createRun function to accept additional options

* fix: message payload formatting; feat: add more client options

* fix: ToolCall component rendering when action has no args but has output

* refactor(ToolCall): allow non-stringy args

* WIP: first pass, correctly formatted tool_calls between providers

* refactor: Remove duplicate import of 'roles' module

* refactor: Exclude 'vite.config.ts' from TypeScript compilation

* refactor: fix agent related types
> - no need to use endpoint/model fields for identifying agent metadata
> - add `provider` distinction for agent-configured 'endpoint'
- no need for agent-endpoint map
- reduce complexity of tools as functions into tools as string[]
- fix types related to above changes
- reduce unnecessary variables for queries/mutations and corresponding react-query keys

* refactor: Add tools and tool_kwargs fields to agent schema

* refactor: Remove unused code and update dependencies

* refactor: Update updateAgentHandler to use req.body directly

* refactor: Update AgentSelect component to use localized hooks

* refactor: Update agent schema to include tools and provider fields

* refactor(AgentPanel): add scrollbar gutter, add provider field to form, fix agent schema required values

* refactor: Update AgentSwitcher component to use selectedAgentId instead of selectedAgent

* refactor: Update AgentPanel component to include alternateName import and defaultAgentFormValues

* refactor(SelectDropDown): allow setting value as option while still supporting legacy usage (string values only)

* refactor: SelectDropdown changes - Only necessary when the available values are objects with label/value fields and the selected value is expected to be a string.

* refactor: TypeError issues and handle provider as option

* feat: Add placeholder for provider selection in AgentPanel component

* refactor: Update agent schema to include author and provider fields

* fix: show expected 'create agent' placeholder when creating agent

* chore: fix localization strings, hide capabilities form for now

* chore: typing

* refactor: import order and use compact agents schema for now

* chore: typing

* refactor: Update AgentForm type to use AgentCapabilities

* fix agent form agent selection issues

* feat: responsive agent selection

* fix: Handle cancelled fetch in useSelectAgent hook

* fix: reset agent form on accordion close/open

* feat: Add agent_id to default conversation for agents endpoint

* feat: agents endpoint request handling

* refactor: reset conversation model on agent select

* refactor: add `additional_instructions` to conversation schema, organize other fields

* chore: casing

* chore: types

* refactor(loadAgentTools): explicitly pass agent_id, do not pass `model` to loadAgentTools for now, load action sets by agent_id

* WIP: initial draft of real agent client initialization

* WIP: first pass, anthropic agent requests

* feat: remember last selected agent

* feat: openai and azure connected

* fix: prioritize agent model for runs unless an explicit override model is passed from client

* feat: Agent Actions

* fix: save agent id to convo

* feat: model panel (#29)

* feat: model panel

* bring back comments

* fix: method still null

* fix: AgentPanel FormContext

* feat: add more parameters

* fix: style issues; refactor: Agent Controller

* fix: cherry-pick

* fix: Update AgentAvatar component to use AssistantIcon instead of BrainCircuit

* feat: OGDialog for delete agent; feat(assistant): update Agent types, introduced `model_parameters`

* feat: icon and general `model_parameters` update

* feat: use react-hook-form better

* fix: agent builder form reset issue when switching panels

* refactor: modularize agent builder form

---------

Co-authored-by: Danny Avila <danny@librechat.ai>

* fix: AgentPanel and ModelPanel type issues and use `useFormContext` and `watch` instead of `methods` directly and `useWatch`.

* fix: tool call issues due to invalid input (anthropic) of empty string

* fix: handle empty text in Part component

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>

* refactor: remove form ModelPanel and fixed nested ternary expressions in AgentConfig

* fix: Model Parameters not saved correctly

* refactor: remove console log

* feat: avatar upload and get for Agents (#36)

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>

* chore: update to public package

* fix: typing, optional chaining

* fix: cursor not showing for content parts

* chore: conditionally enable agents

* ci: fix azure test

* ci: fix frontend tests, fix eslint api

* refactor: Remove unused errorContentPart variable

* continue of the agent message PR (#40)

* last fixes

* fix: agentMap

* pr merge test  (#41)

* fix: model icon not fetching correctly

* remove console logs

* feat: agent name

* refactor: pass documentsMap as a prop to allow re-render of assistant form

* refactor: pass documentsMap as a prop to allow re-render of assistant form

* chore: Bump version to 0.7.419

* fix: TypeError: Cannot read properties of undefined (reading 'id')

* refactor: update AgentSwitcher component to use ControlCombobox instead of Combobox

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2024-08-31 16:33:51 -04:00
Max Sanna
618be4bf2b ⚖️ feat: Terms and Conditions Dialog (#3712)
* Added UI for Terms and Conditions Modal Dialogue

* Handled the logout on not accepting

* Added logic for terms acceptance

* Add terms and conditions modal

* Fixed bug on terms and conditions modal, clicking out of it won't close it now

* Added acceptance of Terms to Database

* Removed unnecessary api endpoints from index.js

* Added NPM script to reset terms acceptance

* Added translations, markdown terms and samples

* Merged terms and conditions modal feature

* feat/Modal Terms and Conditions Dialog

* Amendments as requested by maintainers

* Reset package-lock (again)
2024-08-31 16:08:04 -04:00
Marco Beretta
79f9cd5a4d 💬 feat: assistant conversation starter (#3699)
* feat: initial UI convoStart

* fix: ConvoStarter UI

* fix: convoStarters bug

* feat: Add input field focus on conversation starters

* style: conversation starter UI update

* feat: apply fixes for starters

* style: update conversationStarters UI and fixed typo

* general UI update

* feat: Add onClick functionality to ConvoStarter component

* fix: quick fix test

* fix(AssistantSelect): remove object check

* fix: updateAssistant `conversation_starters` var

* chore: remove starter autofocus

* fix: no empty conversation starters, always show input, use Constants value for max count

* style: Update defaultTextPropsLabel styles, for a11y placeholder

* refactor: Update ConvoStarter component styles and class names for a11y and theme

* refactor: convostarter, move plus button to within persistent element

* fix: types

* chore: Update landing page assistant description styling with theming

* chore: assistant types

* refactor: documents routes

* refactor: optimize conversation starter mutations/queries

* refactor: Update listAllAssistants return type to Promise<Array<Assistant>>

* feat: edit existing starters

* feat(convo-starters): enhance ConvoStarter component and add animations

    - Update ConvoStarter component styling for better visual appeal
    - Implement fade-in animation for smoother appearance
    - Add hover effect with background color change
    - Improve text overflow handling with line-clamp and text-balance
    - Ensure responsive design for various screen sizes

* feat(assistant): add conversation starters to assistant builder

- Add localization strings for conversation starters
- Update mobile.css with shake animation for max starters reached
- Enhance user experience with tooltips and dynamic input handling

* refactor: select specific fields for assistant documents fetch

* refactor: remove endpoint query key, fetch all assistant docs for now, add conversation_starters to v1 methods

* refactor: add document filters based on endpoint config

* fix: starters not applied during creation

* refactor: update AssistantSelect component to handle undefined lastSelectedModels

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-08-31 13:42:20 -04:00
Max Sanna
63b80c3067 🗣️ fix: Azure OpenAI STT (#3731)
* Fix for Azure OpenAI STT

* chore(STTService): imports order

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-08-30 15:11:15 -04:00
Danny Avila
7536e649d4 🚨 feat: Implement INPUT_LENGTH Error Type (#3866)
* feat: CONTEXT_LENGTH error type

* chore: rename error type

* chore: import order
2024-08-30 15:01:29 -04:00
Danny Avila
6936d0059f 🎨 refactor: Prevent Font Asset Hashing in Vite Config (#3865) 2024-08-30 13:56:49 -04:00
Danny Avila
0a359aa705 👐 a11y: Accessible Conversation Menu Options (#3864)
* fix: type issues

* feat: Fix document title setting in Conversation component

* style: new chat theme

* fix: No keyboard access to chat menus in the chat history #3788

* fix: Menu button in the chat history area does not indicate its state #3823

* refactor: use ariakit for DropdownPopup

* style: update sticky z-index in NewChat component

* style: update ConvoOptions menu button styling
2024-08-30 13:39:30 -04:00
Jacob Colyvan
2ce4f66218 🎙️ a11y: update html lang attribute (#3636)
* refactor: remove duplicate localStorage lang call

* refactor: use cookies to handle langcode

* feat: override index.html lang w/ cookie pref

* refactor: only read index on server start

* refactor: rename lang cookie & localstorage as backup

* refactor: use atomWithLocalStorage in language store

* fix: forced reflow warning in language select
2024-08-30 06:57:29 -04:00
Danny Avila
a0042317b2 📝 docs: Update README.md 2024-08-30 06:46:46 -04:00
Danny Avila
dc40e577af 🔊 refactor: Optimize Aria-Live Announcements for macOS VoiceOver (#3851) 2024-08-30 00:14:37 -04:00
Danny Avila
757b6d3275 🔨 refactor: Add Cache Busting to index.html (#3824) 2024-08-28 13:52:14 -04:00
Danny Avila
3b61322459 🚀 feat: Enhance PWA and asset caching strategy (#3822)
* chore: Update VitePWA registerType to 'autoUpdate', add cache busting to static file outputs

* chore: disable windows frontend workflow for now
2024-08-28 12:13:14 -04:00
Danny Avila
7c1ee242eb 🪄 feat: Code Artifacts (#3798)
* feat: Add CodeArtifacts component to Beta settings tab

* chore: Update npm dependency to @codesandbox/sandpack-react@2.18.2

* WIP: artifacts first pass

* WIP first pass remark-directive

* chore: revert markdown to original component + new artifacts rendering

* refactor: first pass rewrite

* refactor: add throttling

* first pass styling

* style: Add Radix Tabs, more styling changes

* feat: second pass

* style: code styling

* fix: package markdown fixes

* feat: Add useEffect hook to Artifacts component for visibility control, slide in animation

* fix: only set artifact if there is content

* refactor: typing and make latest artifact active if the number of artifacts changed

* feat: artifacts + shadcnui

* feat: Add Copy Code button to Artifacts component

* feat: first pass streaming updates

* refactor: optimize ordering of artifacts in Artifacts component

* refactor: optimize ordering of artifacts and add latest artifact activation in Artifacts component

* refactor: add order prop to Artifact

* feat: update to latest, use update time for ordering

* refactor: optimize ordering of artifacts and activate latest artifact in Artifacts component

* wip: remove thinking text and artifact formatting if empty

* refactor: optimize Markdown rendering and add support for code artifacts

* feat: global state for current artifact Id and set on artifact preview click

* refactor: Rename CodePreview component to ArtifactButton

* refactor: apply growth to artifact frame so artifact preview can take full space

* refactor: remove artifactIdsState

* refactor: nullify artifact state and reset on empty conversation

* feat: reset artifact state on conversation change

* feat: artifacts system prompt in backend

* refactor: update UI artifact toggle label to match localization key

* style: remove ArtifactButton inline-block styling

* feat: memoize ArtifactPreview, add html support

* refactor: abstract out components

* chore: bump react-resizable-panel

* refactor: resizable panel order props

* fix: side panel resizing crashes

* style: temporarily remove scrolling, add better styling

* chore: remove thinking for now

* chore: preprocess artifacts for now

* feat: Add auto scrolling to CodeMarkdown (artifacts)

* feat: autoswitch to preview

* feat: auto switch to code, adjust prompt, remove unused code

* feat: refresh button

* feat: open/close artifacts

* wip: mermaid

* refactor: w-fit Artifact button

* chore: organize code

* feat: first pass mermaid

* refactor: improve panning logic in MermaidDiagram component

* feat: center/zoom on first render

* refactor: add centering with reset button

* style: mermaid styling

* refactor: add back MermaidDiagram

* fix: static/html template

* fix: mermaid

* add examples to artifacts prompt

* refactor: fix CodeBar plugin prop logic

* refactor: remove unnecessary mention of artifacts when not requested

* fix: remove preprocessCodeArtifacts function and fix imports

* feat: improve artifacts guidelines and remove unnecessary mentions

* refactor: improve artifacts guidelines and remove unnecessary mentions

* chore: uninstall unused packages

* chore: bump vite

* chore: update three dependency to version 0.167.1

* refactor: move beta settings, add additional artifacts toggles

* feat: artifacts mode toggles

* refactor: adjust prompt

* feat: shadcnui instructions

* feat: code artifacts custom prompt mode

* chore: Update artifacts UI labels and instructions localizations

* refactor: Remove unused code in Markdown component
2024-08-27 17:03:16 -04:00
Danny Avila
80e1bdc282 v0.7.5-rc1 (#3807) 2024-08-27 15:01:41 -04:00
Danny Avila
a267f6e0da 🔍 fix: USE_REDIS condition, Markdown list counter, code highlights (#3806)
* fix: markdown rehype highlight accidental removal

* fix: USE_REDIS condition check

* fix: markdown list counter
2024-08-27 14:49:43 -04:00
Danny Avila
f742b9972e 🏷️ chore: Add Unofficial Naming Variation for Claude-3.5-Sonnet (#3800) 2024-08-27 09:07:04 -04:00
Danny Avila
bbaa0ee1cf 🚚 chore: Remove client-dist volume from deploy-compose.yml (#3799) 2024-08-27 07:18:47 -04:00
Marco Beretta
62881fee54 🔧 fix: handle missing custom config speech (#3790)
* feat: Update speech settings retrieval logic to handle missing custom configuration

This commit updates the logic in the Speech component and the getCustomConfigSpeech function to handle the case where the custom configuration is missing. Previously, if no custom configuration was found, an error would occur. Now, the code checks for the presence of the custom configuration and returns a message indicating that no custom configuration was found. This improves the robustness of the application and provides a better user experience.

* refactor: changed response message when no custom config is found
2024-08-27 06:09:04 -04:00
Danny Avila
34fd960d54 🧹 chore: remove legacy markdown code (#3789) 2024-08-26 17:53:19 -04:00
Danny Avila
5694ad4e55 🧠 feat: Prompt caching switch, prompt query params; refactor: static cache, prompt/markdown styling, trim copied code, switch new chat to convo URL (#3784)
* refactor: Update staticCache to use oneDayInSeconds for sMaxAge and maxAge

* refactor: role updates

* style: first pass cursor

* style: Update nested list styles in style.css

* feat: setIsSubmitting to true in message handler to prevent edge case where submitting turns false during message stream

* feat: Add logic to redirect to conversation page after creating a new conversation

* refactor: Trim code string before copying in CodeBlock component

* feat: configSchema bookmarks and presets defaults

* feat: Update loadDefaultInterface to handle undefined config

* refactor: use  for compression check

* feat: first pass, query params

* fix: styling issues for prompt cards

* feat: anthropic prompt caching UI switch

* chore: Update static file cache control defaults/comments in .env.example

* ci: fix tests

* ci: fix tests

* chore:  use "submitting" class server error connection suspense fallback
2024-08-26 15:34:46 -04:00
Fuegovic
bd701c197e 🌀 feat: Known Endpoints - Unify (#3778)
Signed-off-by: Fuegovic <fueg@live.ca>
2024-08-25 19:10:25 -04:00
Danny Avila
9bfe40bfcd ⏺️ style: Better Markdown Lists (#3777)
* style: markdown lists

* style: markdown lists, second pass

* style: update nested list styles in style.css
2024-08-25 16:33:25 -04:00
Fuegovic
07f520100d 🐋 feat: Known Endpoints: DeepSeek (#3776)
Signed-off-by: Fuegovic <fueg@live.ca>
2024-08-25 15:33:03 -04:00
Danny Avila
d52e81bde6 🐋 ci: Dockerfile.multi rewrite, maintain package integrity pt. 2 2024-08-24 15:09:38 -04:00
Danny Avila
88d8706757 🐋 ci: Dockerfile.multi rewrite, maintain package integrity (#3772)
* chore: touch server

* chore: dockerfile.multi first pass

* refactor: remove prod-stage build, share dist files instead
2024-08-24 15:00:51 -04:00
Danny Avila
d54458b3a6 🧮 feat: Improve structured token spending and testing; fix: Anthropic Cache Spend (#3766)
* chore: update jest and mongodb-memory-server dependencies

* fix: Anthropic edge case of increasing balance

* refactor: Update token calculations in Transaction model/spec

* refactor: `spendTokens` always record transactions, add Tx related tests

* feat: Add error handling for CHECK_BALANCE environment variable

* feat: Update import path for Balance model in Balance controller

* chore: remove logging

* refactor: Improve structured token spend logging in spendTokens.js

* ci: add unit tests for spend token

* ci: Improve structured token spend unit testing

* chore: improve logging phrase for no tx spent from balance
2024-08-24 04:36:08 -04:00
Danny Avila
ea5140ff0f 🧮 feat: Improve LaTeX rendering consistency (#3763)
* refactor: simplify LaTeX pre-processing for more consistent rendering, disables `singleDollarTextMath`

* refactor: disable singleDollarTextMath in all markdown components

* wip: first pass

* refactor: preserve code blocks and convert rather than preserve LaTeX delimiters

* refactor: remove unused escapeDollarNumber function from latex.ts
2024-08-23 13:45:27 -04:00
Danny Avila
967e8a1e92 🍎 refactor(a11y): Optimize Live Region Announcements for Apple VoiceOver (#3762)
* refactor: first pass rewrite

* refactor: update CLEAR_DELAY to 5000 milliseconds in LiveAnnouncer.tsx

* refactor: assertive messages to clear queue immediately, fix circular useCallback dependency issue

* chore: comment
2024-08-23 10:22:16 -04:00
Danny Avila
f86e9dd04c 🔖 feat: Enhance Bookmarks UX, add RBAC, toggle via librechat.yaml (#3747)
* chore: update package version to 0.7.416

* chore: Update Role.js imports order

* refactor: move updateTagsInConvo to tags route, add RBAC for tags

* refactor: add updateTagsInConvoOptions

* fix: loading state for bookmark form

* refactor: update primaryText class in TitleButton component

* refactor: remove duplicate bookmarks and theming

* refactor: update EditIcon component to use React.forwardRef

* refactor: add _id field to tConversationTagSchema

* refactor: remove promises

* refactor: move mutation logic from BookmarkForm -> BookmarkEditDialog

* refactor: update button class in BookmarkForm component

* fix: conversation mutations and add better logging to useConversationTagMutation

* refactor: update logger message in BookmarkEditDialog component

* refactor: improve UI consistency in BookmarkNav and NewChat components

* refactor: update logger message in BookmarkEditDialog component

* refactor: Add tags prop to BookmarkForm component

* refactor: Update BookmarkForm to avoid tag mutation if the tag already exists; also close dialog on submission programmatically

* refactor: general role helper function to support updating access permissions for different permission types

* refactor: Update getLatestText function to handle undefined values in message.content

* refactor: Update useHasAccess hook to handle null role values for authenticated users

* feat: toggle bookmarks access

* refactor: Update PromptsCommand to handle access permissions for prompts

* feat: updateConversationSelector

* refactor: rename `vars` to `tagToDelete` for clarity

* fix: prevent recreation of deleted tags in BookmarkMenu on Item Click

* ci: mock updateBookmarksAccess function

* ci: mock updateBookmarksAccess function
2024-08-22 17:09:05 -04:00
Danny Avila
366e4c5adb 🔧 fix: EndpointIcon crash when using @ mention command (#3742) 2024-08-22 10:49:51 -04:00
Danny Avila
596ecc6969 🔐 feat: Toggle Access to Prompts via librechat.yaml (#3735)
* chore: update CONFIG_VERSION to '1.1.6'

* chore: update package version to 0.7.415

* feat: toggle USER role access to prompts via librechat.yaml

* refactor: set prompts to true when loadDefaultInterface returns true

* ci(AppService): mock updatePromptsAccess
2024-08-21 19:57:34 -04:00
Marco Beretta
0c5568b80b ⌨️ style(a11y): kb access for LLM endpoint menu; refactor: style (#3714) 2024-08-21 18:19:33 -04:00
Danny Avila
98b437edd5 🖱️ fix: Message Scrolling UX; refactor: Frontend UX/DX Optimizations (#3733)
* refactor(DropdownPopup): set MenuButton `as` prop to `div` to prevent React warning: validateDOMNesting(...): <button> cannot appear as a descendant of <button>

* refactor: memoize ChatGroupItem and ControlCombobox components

* refactor(OpenAIClient): await stream process finish before finalCompletion event handling

* refactor: update useSSE.ts typing to handle null and undefined values in data properties

* refactor: set abort scroll to false on SSE connection open

* refactor: improve logger functionality with filter support

* refactor: update handleScroll typing in MessageContainer component

* refactor: update logger.dir call in useChatFunctions to log 'message_stream' tag format instead of the entire submission object as first arg

* refactor: fix null check for message object in Message component

* refactor: throttle handleScroll to help prevent auto-scrolling issues on new message requests; fix type issues within useMessageProcess

* refactor: add abortScrollByIndex logging effect

* refactor: update MessageIcon and Icon components to use React.memo for performance optimization

* refactor: memoize ConvoIconURL component for performance optimization

* chore: type issues

* chore: update package version to 0.7.414
2024-08-21 18:18:45 -04:00
Marco Beretta
ba9c351435 🔧 fix: add clear all button to bookmark navigation items (#3721) 2024-08-20 19:07:51 -04:00
Konstantin
58334dffea 🌏i18n: Improve Russian translation (#3718)
* Small correction

* Small correction 1

* Small corrections 2
2024-08-20 18:51:02 -04:00
Danny Avila
45479d468e fix(staticCache): NODE_ENV check 2024-08-20 07:32:30 -04:00
Danny Avila
14ddfec9b7 🧹 chore: address minor issues (#3710)
* refactor(OpenAIClient): improve error handling in chat completion

Improve error handling in the chat completion process to handle scenarios where the response has no choices or the message is undefined. This ensures that the intermediate reply is returned in such cases. Also, add logging statements for better debugging.

* refactor(Markdown): only show blinking cursor for latest message

* refactor: add submitting selector to prevent blinking cursor for empty, non-streaming, non-latest messages
2024-08-20 07:00:43 -04:00
Marco Beretta
5de3b8a148 🏷️ a11y: add aria-label to close button and aria-hidden to SVG (#3698)
Fixes #3641

Add accessible name to the close button for added conversations and hide SVG from assistive technology.

* Add `aria-label="Close added conversation"` to the `button` element.
* Add `aria-hidden="true"` to the `svg` element.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/danny-avila/LibreChat/issues/3641?shareId=XXXX-XXXX-XXXX-XXXX).
2024-08-19 18:08:29 -04:00
Marco Beretta
d4c0f7267a 🔑 fix(AuthService): properly handle reading and deletion of password reset token (#3697) 2024-08-19 17:55:33 -04:00
Danny Avila
cebb3751c1 📣 a11y: Better Screen Reader Announcements (#3693)
* refactor: Improve LiveAnnouncer component

The LiveAnnouncer component in the client/src/a11y/LiveAnnouncer.tsx file has been refactored to improve its functionality. The component now processes text in chunks for better performance and adds a minimum announcement delay to prevent overlapping announcements. Additionally, the component now properly clears the announcement message and ID before setting a new one. These changes enhance the accessibility and user experience of the LiveAnnouncer component.

* refactor: manage only 2 LiveAnnouncer aria-live elements, queue assertive/polite together

* refactor: use localizations for event announcements

* refactor: update minimum announcement delay in LiveAnnouncer component

* refactor: replace *`_

* chore(useContentHandler): typing

* chore: more type fixes and safely announce final message
2024-08-19 03:51:17 -04:00
Danny Avila
598e2be225 🗨️ refactor(VariableForm): use InputCombobox, fix Dropdown Variables (#3692)
* feat: Add SimpleCombobox component

* feat: Add labelClassName and add manual focus handling

* feat: Update VariableForm component to use SimpleCombobox

The VariableForm component in the client/src/components/Prompts/Groups/VariableForm.tsx file has been updated to use the SimpleCombobox component instead of the InputWithDropdown component. This change improves the functionality and styling of the form.

* chore: Update VariableForm component placeholder text

* refactor: Improve VariableForm component

The VariableForm component in the client/src/components/Prompts/Groups/VariableForm.tsx file has been refactored to improve its functionality. The `parseFieldConfig` function now trims the `variable` string before processing it. Additionally, the `onSubmit` function now properly escapes potential regex special chars that may cause issues when replacing text

* refactor: Improve VariableForm using ariakit helpers/custom fields, open menu on input focus

* refactor: rename SimpleCombobox to InputCombobox
2024-08-18 22:23:19 -04:00
Danny Avila
8ca1e4f94f 🐛 fix: Anthropic Prompt Caching Edge Case (#3690) 2024-08-18 19:03:03 -04:00
Danny Avila
87d95a9d82 📱 fix: Resolve Android Device and Accessibility Issues of Sidebar Combobox (#3689)
* chore: Update @ariakit/react dependency to version 0.4.8

* refactor: Fix Combobox Android issue with radix-ui

* fix: Improve scrolling behavior by setting abort scroll state to false after scrolling to end

* wip: first pass switcher rewrite

* feat: Add button width calculation for ComboboxComponent

* refactor: Update ComboboxComponent styling for improved layout and appearance

* refactor: Update AssistantSwitcher component to handle null values for assistant names and avatar URLs

* refactor: Update ModelSwitcher component to use SimpleCombobox for improved functionality and styling

* refactor: Update Switcher Separator styling for improved layout and appearance

* refactor: Improve accessibility by adding aria-label to ComboboxComponent select items

* refactor: rename SimpleCombobox -> ControlCombobox
2024-08-18 19:02:46 -04:00
Konstantin
b22f1c166e 🌏 i18n: Improve Russian translation (#3674) 2024-08-18 13:23:13 -04:00
Danny Avila
683702d555 🤖 refactor: Remove Default Model Params for All Endpoints (#3682)
* refactor: use parseCompactConvo in buildOptions, and generate no default values for the API to avoid weird model behavior with defaults

* refactor: OTHER - always show cursor when markdown component is empty (preferable to not)

* refactor(OpenAISettings): use config object for setting defaults app-wide

* refactor: Use removeNullishValues in buildOptions for ALL  endpoints

* fix: add missing conversationId to title methods for transactions; refactor(GoogleClient): model options, set no default, add todo note for recording token usage

* fix: at minimum set a model default, as is required by API (edge case)
2024-08-18 06:00:03 -04:00
Danny Avila
d3a20357e9 🧪 feat: Prompt Dropdown Variable; style: Add Markdown Support (#3681)
* feat: Add extended inputs for promts library variables

* feat: Add maxRows prop to VariableForm input field

* 📩 feat: invite user (#3012)

* feat: basic invite-user script

* feat: add invite user functionality and registration validation middleware

* fix: invite user fixes

* refactor: consolidate direct model access to a central place of functions

* style(Registration): add spinner to continue button

* refactor: import ordrer

* feat: improve invite user script and error handling

* fix: merge conflict

* refactor: remove `console.log` and use `logger`

* fix: token operation and checkinvite issues

* bring back comment and remove console log

* fix: return invalid token when token is not found

* fix: getInvite fix

* refactor: Update Token.js to use async/await syntax for update and delete operations

* feat: Refactor Token.js to use async/await syntax for createToken and findToken functions

* refactor(inviteUser): define functions outside of module.exports

* Update AuthService.js

---------

Co-authored-by: Danny Avila <danny@librechat.ai>

* style: improve OpenAI.tsx input field focus styling

* refactor: update import statement in Input.tsx

* refactor: remove multi-line

* refactor:  update placeholder text to use localization

* style: new dropdown variable info and markdown styling for info

* Add ReactMarkdown

* chore: styling, import order

* refactor: update ReactMarkdown usage in VariableForm

* style: remove markdown class

* refactor: update mobile styling and use code renderer

* style(InputWithDropDown): update focus trigger style

* style(OptionsPopover): update Save As Preset `focus` and `dark:bg`

---------

Co-authored-by: Konstantin Meshcheryakov <kmeshcheryakov@klika-tech.com>
Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
2024-08-18 05:52:05 -04:00
Marco Beretta
bbb9324447 📩 feat: invite user (#3012)
* feat: basic invite-user script

* feat: add invite user functionality and registration validation middleware

* fix: invite user fixes

* refactor: consolidate direct model access to a central place of functions

* style(Registration): add spinner to continue button

* refactor: import ordrer

* feat: improve invite user script and error handling

* fix: merge conflict

* refactor: remove `console.log` and use `logger`

* fix: token operation and checkinvite issues

* bring back comment and remove console log

* fix: return invalid token when token is not found

* fix: getInvite fix

* refactor: Update Token.js to use async/await syntax for update and delete operations

* feat: Refactor Token.js to use async/await syntax for createToken and findToken functions

* refactor(inviteUser): define functions outside of module.exports

* Update AuthService.js

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-08-18 00:23:38 -04:00
Danny Avila
a45b384bbc 💾 feat: Anthropic Prompt Caching (#3670)
* wip: initial cache control implementation, add typing for transactions handling

* feat: first pass of Anthropic Prompt Caching

* feat: standardize stream usage as pass in when calculating token counts

* feat: Add getCacheMultiplier function to calculate cache multiplier for different valueKeys and cacheTypes

* chore: imports order

* refactor: token usage recording in AnthropicClient, no need to "correct" as we have the correct amount

* feat: more accurate token counting using stream usage data

* feat: Improve token counting accuracy with stream usage data

* refactor: ensure more accurate than not token estimations if custom instructions or files are not being resent with every request

* refactor: cleanup updateUserMessageTokenCount to allow transactions to be as accurate as possible even if we shouldn't update user message token counts

* ci: fix tests
2024-08-17 03:24:09 -04:00
Marco Beretta
9f4c516615 fix: Export Button Content Shift; chore: bump axios and add logging (#3668)
* chore: bump axios version

* fix: export button glitch

* fix: remove console logs
2024-08-16 18:03:27 -04:00
Danny Avila
16c9aed1bb 🤖 feat: Recognize chatgpt-4o-latest, update default OpenAI Models (#3667)
* 🤖 feat: recognize chatgpt-4o-latest, update default OpenAI models

* chore: Bump data-provider version to 0.7.412
2024-08-16 15:28:17 -04:00
Danny Avila
3826af5909 🤲 a11y: Keyboard Accessibility for Account Settings (#3666)
* refactor(NavLinks -> AccountSettings): add theming, fix minor type issues, and rename component

* fix: closes #3499 - Account settings menu is not keyboard accessible

* fix(DataTable): type issue causing application crash, update contextMap key for storage
2024-08-16 15:09:03 -04:00
Arthur Barrett
6ad65ff065 🔧 fix: Delete Archived Chat z-index issue (#3643) 2024-08-16 13:53:38 -04:00
Danny Avila
91fc89076f 🤲 a11y: Sidebar Text Contrast (#3665)
* fix: use theme class for valid contrast for light/dark, conversation group names, fix type issues

* fix: searchbar text contrast styling, closes #3469

* style: add theming for prompt cards, fix a11y contrast issues

* a11y: address placeholder text contrast issues in LLM controls section

* chore: Add conditional check for pull request repository in a11y workflow

* style: Update text color contrast to WCAG standard for placeholder and focus states in AssistantPanel components
2024-08-16 13:50:47 -04:00
Danny Avila
f8a5dad265 🦙 fix: Update Title Message Role for Ollama if None Provided (#3663) 2024-08-16 04:54:37 -04:00
Marco Beretta
96581d56df 🖼️ style: Conversation Menu and Dialogs update (#3601)
* feat: new dropdown

* fix: maintain popover active when open

* fix: update DeleteButton and ShareButton component to use useState for managing dialog state

* BREAKING: style improvement of base Button component

* style: update export button

* a11y: ExportAndShareButton

* add border

* quick style fix

* fix: flick issue on convo

* fix: DropDown opens when renaming

* chore: update radix-ui/react-dropdown-menu to latest

* small fix

* style: bookmarks update

* reorder export modal

* feat: imporved dropdowns

* style: a lot of changes; header, bookmarks, export, nav, convo, convoOptions

* fix: small style issues

* fix: button

* fix: bookmarks header menu

* fix: dropdown close glitch

* feat: Improve accessibility and keyboard navigation in ModelSpec component

* fix: Nav related type issues

* style: ConvoOptions theming and focus ring

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-08-16 04:30:14 -04:00
Vesna Tan
7f50d2f7c0 🤲 a11y: Add landmark to footer, labels updates, and sidebar text contrast (#3630)
* add landmark contentinfo to footer

* fix aria-label ai model menuitem for issue #3587

* changed group/today text color to #535353
2024-08-16 03:27:56 -04:00
Akash
93cf7bab02 🤲 a11y: Update Chat History aria-label & Controls role (#3604) 2024-08-16 03:12:09 -04:00
Yuichi Oneda
e47c3f40f0 🔧 fix: Bookmark Order Adjustment When Moving Up (#3634) 2024-08-16 03:01:35 -04:00
Danny Avila
0ba08b15de chore: Add conditional check for pull request repository in a11y workflow 2024-08-16 02:50:23 -04:00
Danny Avila
16e1f74a6c fix(useTextToSpeechBrowser): handle undefined window.speechSynthesis on some android devices 2024-08-16 02:49:59 -04:00
Danny Avila
dba704079c 🔀 refactor: Modularize TTS Logic for Improved Browser support (#3657)
* WIP: message audio refactor

* WIP: use MessageAudio by provider

* fix: Update MessageAudio component to use TTSEndpoints enum

* feat: Update useTextToSpeechBrowser hook to handle errors and improve error logging

* feat: Add voice dropdown components for different TTS engines

* docs: update incorrect `voices` example

changed `voice: ''` to `voices: ['alloy']`

* feat: Add brwoser support check for Edge TTS engine component with error toast if not supported

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2024-08-15 11:34:25 -04:00
Danny Avila
bcde0beb47 🛠️ feat: Azure OpenAI Assistants File Downloads (#3653) 2024-08-15 09:10:12 -04:00
Marco Beretta
741e3e8395 🚀 Update README - v0.7.4 2024-08-15 00:40:59 -04:00
Danny Avila
dc8d30ad90 🎧 fix(TTS): Improve State of audio playback, hook patterns, and fix undefined MediaSource (#3632) 2024-08-13 12:08:55 -04:00
Danny Avila
e3ebcfd2b1 🎙️ fix: Optimize and Fix Browser TTS Incompatibility (firefox) (#3627)
* fix: 'disable' MsEdgeTTS on unsupported browser (firefox)

* refactor: only pass necessary props to HoverButton MessageAudio

* refactor: Fix conditional comparison operators in MessageAudio component

* refactor: Remove console.log statement in MessageAudio component
2024-08-13 04:14:37 -04:00
Danny Avila
6655304753 🎙️ a11y: Screen Reader Support for Dynamic Content Updates (#3625)
* WIP: first pass, hooks

* wip: isStream arg

* feat: first pass, dynamic content updates, screen reader announcements

* chore: unrelated, styling redundancy
2024-08-13 03:04:27 -04:00
Danny Avila
05696233a9 🎛️ fix: Improve Frontend Practices for Audio Settings (#3624)
* refactor: do not call await inside useCallbacks, rely on updates for dropdown

* fix: remember last selected voice

* refactor: Update Speech component to use TypeScript in useCallback

* refactor: Update Dropdown component styles to match header theme
2024-08-13 02:42:49 -04:00
Marco Beretta
8cbb6ba166 📧 fix: @/+command timing for click selections - closes #3613 (#3617) 2024-08-12 09:06:23 -04:00
Danny Avila
02847af580 📜 refactor: Optimize Longer Message Thread Performance (#3610) 2024-08-11 06:08:08 -04:00
Danny Avila
cf69b7ef85 v0.7.4 2024-08-10 09:09:37 -04:00
Danny Avila
3a5f57fd2b v0.7.4 (#3603) 2024-08-10 08:32:27 -04:00
Danny Avila
22c8b6f699 💭 fix: Message Labels and Typing Issues (#3602)
* 💭 fix: message labels due to typing issues

* feat: Fix empty message text in MessageRender component
2024-08-09 17:59:51 -04:00
Danny Avila
1ff4841603 🧹 chore: pre-release cleanup 2 (#3600)
* refactor: scrollToEnd

* fix(validateConvoAccess): search conversation by ID for proper validation

* feat: Add unique index for conversationId and user in convoSchema

* refactor: Update font sizes 1 rem -> font-size-base in style.css

* fix: Assistants map type issues

* refactor: Remove obsolete scripts

* fix: Update DropdownNoState component to handle both string and OptionType values

* refactor: Remove config/loader.js file

* fix: remove crypto.randomBytes(); refactor: Create reusable function for generating token and hash
2024-08-09 15:17:13 -04:00
Danny Avila
6fead1005b ci: deploy test server post-dev image build pt. 3 2024-08-09 02:55:33 -04:00
Danny Avila
8a9476a795 ci: deploy test server post-dev image build pt. 2 2024-08-09 02:39:29 -04:00
Danny Avila
59ae2914aa 🐋 ci: deploy test server post-dev image build (#3596) 2024-08-09 02:22:25 -04:00
Danny Avila
473859b0e2 🧹 chore: pre-release cleanup (#3595)
* fix: Update health endpoint URL

* refactor: use Constants for saved tag default value, do not place Saved as first always

* refactor: check trimmed currentText before appending parsedText in useSubmitMessage

* refactor: move `scrollToEnd()` to `createdHandler` and increase delay before execution slightly

* chore: Add back TypeScript linting rules for unnecessary conditions and strict boolean expressions

* chore: Update librechat-data-provider package.json version to 0.7.4.0
2024-08-09 02:11:56 -04:00
Danny Avila
e05a6d306d 🪙 feat: Update Token Values for gpt-4o-2024-08-06 and AWS Models (#3594)
* feat: gpt-4o-2024-08-06 pricing for tx

* feat: add AWS models to tokenValues in tx.js for pricing transactions

* feat: Update tokenValues in tx.js for AWS models pricing

* refactor: add bedrock prefix values as well (temporary until we update value keys which includes context)
2024-08-08 23:31:07 -04:00
Danny Avila
016ed866a3 🏷️ fix: Address Statefulness Issues for Bookmarks (#3590)
* refactor: optimize tag methods, remove rebuild

* refactor(tags): add lean db operations, fix updateTagsForConversation, remove rebuild button, only send convoId once

* refactor: Update BookmarkMenu to use Constants.NEW_CONVO constant for comparison

* style: Update BookmarkMenu styles and constants, use theming

* refactor: move tags query from package to client workspace

* refactor: optimize ConversationTag document creation and update logic

* style: Update BookmarkMenuItems to use theming

* refactor: JSDocs + try/catch for conversation tags API routes

* refactor: Update BookmarkNav theming classes and new data provider location

* fix: statefulness of conversation bookmarks
- move non-mutation hook to hooks/Conversation
- remove use of deprecated global convo
- update convo infinite data as well as current convo state upon successful tag add

* refactor: Update BookmarkMenu styles and constants, use theming

* refactor: Add lean option to ConversationTag deletion query

* fix(BookmarkTable): position order rendering esp. when new tag is created

* refactor: Update useBookmarkSucess to useBookmarkSuccess for consistency

* refactor: Update ConversationTag creation logic to increment count only if addToConversation is true

* style: theming
2024-08-08 21:25:10 -04:00
Danny Avila
6ea2628b56 🌡️ feat: Periodic Health Check to prevent UI Inactivity Connection Errors (#3589)
* 🌡️ feat: Periodic Health Check to prevent UI Inactivity Connection Errors

* feat: Add refetchOnWindowFocus option for health check

* feat: programmatically scroll to end when a chat request is initiated (and messages have rendered)
2024-08-08 14:52:12 -04:00
Marco Beretta
cf393b1308 🎨 style: overall UI improvements (#3576)
* stlye: new dialogs

* style: DashGroupItem

* style: bookmarks update
2024-08-08 12:16:17 -04:00
Danny Avila
5c99d93744 🛂 feat: Added Security for Conversation Access (#3588)
* 🛂 feat: Added Security for Conversation Access

* refactor: Update concurrentLimiter and convoAccess middleware to use isEnabled function for Redis check

* refactor: handle access check even if cache is not available (edge case)
2024-08-08 12:14:00 -04:00
Danny Avila
b3821c1404 🎨 style: Enhance UI/UX for Font Size, Mentions, and Prompts (#3575)
* style: fix prompts icon shrinking in command popover

* fix: scroll into view behavior for mentions

* fix: always apply default font size if not found

* refactor: Update useMessageScrolling threshold and debounceRate
2024-08-08 10:02:30 -04:00
Danny Avila
2bb0842650 🅰️ feat: Dynamic Font Size (#3568)
* wip: general setup

* added: translations for font-size

* fix: prompts related linter errors and add theming

* wip: font size selector

* refactor: Update FontSizeSelector options display property

* refactor: adjust Intersection Observer threshold and debounce rate

* feat: Update selectedPrompt type in PromptForm to be optional

* feat: dynamic font size

* refactor: Update message font size in navigation bar

* refactor: Update code analyze block styling

* refactor: ProgressText dynamic font size

* refactor: move FontSizeSelector component to Chat from General settings

* fix: HoverButtons styling for better visibility

* refactor: Update HoverButtons styling for better visibility

---------

Co-authored-by: kraken <solodarken@gmail.com>
2024-08-07 14:23:33 -04:00
Marco Beretta
b390ba781f 🗣️ feat: Edge TTS engine (#3358)
* feat: MS Edge TTS

* feat: Edge TTS; fix: STT hook
2024-08-07 14:15:41 -04:00
Danny Avila
01a88991ab 🎛️ refactor: Add keyboard command toggles & only trigger for the 1st character (#3566)
* refactor: Improve handling of key up events in useHandleKeyUp hook to only trigger for first char and fix linter issues

* refactor: Update Beta component styling with theme twcss variables

* refactor: theming for Settings, add toggle enable/disable keyboard commands
2024-08-06 22:18:07 -04:00
Danny Avila
270c6d2350 📜 fix: Better OpenAI Assistants Annotation Processing (#3565)
* fix: correctly handle openai assistants annotations

* fix: Handle adjacent identical citations only for our specific format

* fix: correctly handle adjacent identical citations

* refactor: make regex handling more robust

* fix: skip annotation condition, make regex handling more robust

* refactor: Handle FILE_PATH and FILE_CITATION annotation types in processMessages.spec.js

* ci: unit tests for real file path type annotations
2024-08-06 18:52:58 -04:00
Danny Avila
c2a79aee1b feat: Optimize Scroll Handling with Intersection Observer (#3564)
*  refactor(ScrollToBottom): use Intersection Observer for efficient scroll handling

* chore: imports, remove debug console
2024-08-06 16:18:15 -04:00
Dongwoo Jeong
6879de0bf1 🔧 fix: API Key Handling for GoogleSearch and TavilySearch Tools (#3541)
* fix: get user-provided API key using environment variable names as keys

* feat: Add error handling for missing API key and search engine ID

* feat: Add GoogleSearch and TavilySearchResults specs for environment variables handling

---------

Co-authored-by: Dongwoo Jeong <dongwoo.jeong@lge.com>
2024-08-05 19:29:16 -04:00
Danny Avila
80773d0bce 🗝️ fix: update webcrypto algorithm name as aes-256-cbc is unrecognized (#3556) 2024-08-05 19:15:32 -04:00
Danny Avila
458dc9c88e 🛡️ feat: Optimize and Improve Anonymity of SharedLinks (#3543)
* ci: add spec for validateImageRequest

* chore: install nanoid and run npm audit fix

* refactor: optimize and further anonymize shared links data

* ci: add SharedLink specs

* feat: anonymize asst_id's

* ci: tests actually failing, to revisit later

* fix: do not anonymize authenticated shared links query

* refactor: Update ShareView component styling

* refactor: remove nested ternary

* refactor: no nested ternaries

* fix(ShareView): eslint warnings

* fix(eslint): remove nested terns
2024-08-05 03:34:00 -04:00
matt burnett
3e0f95458f 🕸️ refactor: Migrate from crypto to Web Crypto API (#3357)
* move crypto to async webcrypto

update encrypt/decrypt

forgot await

* chore: import order - openidStrategy.js

* chore: import order - Session.js

* chore: import order - AuthController.js

* Update AuthService.js

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-08-04 23:59:45 -04:00
Danny Avila
b6fe7e5570 🪖 feat: Helm Chart (#3539)
* chore: adding helm chart for librechat

Signed-off-by: Noah Ispas (iamNoah1) <noahispas@gmail.com>

* chore: delete docs, move to docs repo

---------

Signed-off-by: Noah Ispas (iamNoah1) <noahispas@gmail.com>
Co-authored-by: Noah Ispas (iamNoah1) <noahispas@gmail.com>
2024-08-04 23:43:30 -04:00
matt burnett
e4ac42f034 feat: Static File Caching (#3455)
* add static file cache

* disable compression env variable
2024-08-04 21:17:59 -04:00
Linh
020c4a1a0e 📝 docs: RAG API service communicate with Ollama service on Linux (#3356)
* Update docker-compose.override.yml.example for running RAG API with Ollama nomic-embed-text

* Update docker-compose.override.yml.example
2024-08-04 20:57:02 -04:00
Michael Clark
5bbe424137 📝 docs: update .env.example with RAG API variables (#3461)
* Update .env.example

* Update .env.example

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-08-04 20:54:51 -04:00
Danny Avila
5baa95bd9a 🖼️ fix: correct image extraction (#3538)
* fix: regex issue extracting text with images in markdown

* fix: update addImages function to include only the first observed image path in the response message

* ci: tests for addImages function: correct image extraction

* fix(GoogleClient): linting

---------

Co-authored-by: Dongwoo Jeong <dongwoo.jeong@lge.com>
Co-authored-by: Dongwoo Jeong <dongwoo@duck.com>
2024-08-04 20:53:11 -04:00
Marlon
389b2a6cab 🌍 i18n: Improve German language translations (#3516)
* Improve German language translations

* 🌍 : Updated German Translations. Complete overhaul and manual improvement
2024-08-04 20:52:51 -04:00
Danny Avila
11bfed7126 🤲 feat(a11y): Initial a11y improvements, added linters, tests; fix: close sidebars in mobile view (#3536)
* chore: playwright setup update

* refactor: update ChatRoute component with accessible loading spinner with live region

* chore(Message): typing

* ci: first pass, a11y testing

* refactor: update lang attribute in index.html to "en-US"

* ci: jsx-a11y dev eslint plugin

* ci: jsx plugin

* fix: Exclude 'vite.config.ts' from TypeScript compilation for testing

* fix(a11y): Remove tabIndex from non-interactive element in MessagesView component

* fix(a11y):
- Visible, non-interactive elements with click handlers must have at least one keyboard listener.eslintjsx-a11y/click-events-have-key-events
- Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element.eslintjsx-a11y/no-static-element-interactions
chore: remove unused bookmarks panel
- fix some "Unexpected nullable boolean value in conditional" warnings

* fix(NewChat): a11y, nested button issue, add aria-label, remove implicit role

* fix(a11y):
- partially address #3515 with `main` landmark
other:
- eslint@typescript-eslint/strict-boolean-expressions

* chore(MenuButton): Use button element instead of div for accessibility

* chore: Update TitleButton to use button element for accessibility

* chore: Update TitleButton to use button element for accessibility

* refactor(ChatMenuItem): Improve focus accessibility and code readability

* chore(MenuButton): Update aria-label to dynamically include primaryText

* fix(a11y): SearchBar
- If a form control does not have a properly associated text label, the function or purpose of that form control may not be presented to screen reader users. Visible form labels also provide visible descriptions and larger clickable targets for form controls which placeholders do not.

* chore: remove duplicate SearchBar twcss

* fix(a11y):
- The edit and copy buttons that are visually hidden are exposed to Assistive technology and are announced to screen reader users.

* fix(a11y): visible focus outline

* fix(a11y): The button to select the LLM Model has the aria-haspopup and aria- expanded attributes which makes its role ambuguous and unclear. It functions like a combobox but doesn't fully support that interaction and also fucntions like a dialog but doesn't completely support that interaction either.

* fix(a11y): fix visible focus outline

* fix(a11y): Scroll to bottom button missing accessible name #3474

* fix(a11y): The page lacks any heading structure. There should be at least one H1 and other headings to help users understand the orgainzation of the page and the contents.

Note: h1 won't be correct here so made it h2

* fix(a11y): LLM controls aria-labels

* fix(a11y): There is no visible focus outline to the 'send message' button

* fix(a11y): fix visible focus outline for Fork button

* refactor(MessageRender): add focus ring to message cards, consolidate complex conditions, add logger for setting latest message, add tabindex for card

* fix: focus border color and fix set latest message card condition

* fix(a11y): Adequate contrast for MessageAudio buttton

* feat: Add GitHub Actions workflow for accessibility linting

* chore: Update GitHub Actions workflow for accessibility linting to include client/src/** path

* fix(Nav): navmask and accessibility

* fix: Update Nav component to handle potential undefined type in SearchContext

* fix(a11y): add focus visibility to attach files button #3475

* fix(a11y): discernible text for NewChat button

* fix(a11y): accessible landmark names, all page content in landmarks, ensures landmarks are unique #3514 #3515

* fix(Prompts): update isChatRoute prop to be required in List component

* fix(a11y): buttons must have discernible text
2024-08-04 20:39:52 -04:00
Oliver Faust
433d8f832a 🛠️fix: apply safety settings to Gemini API (#3533)
- Introduce getSafetySettings method for centralized safety settings
- Apply safety settings uniformly in sendCompletion for all models, including Gemini
- Ensure consistent safety settings application in getCompletion
- Update .env.example to clarify safety settings usage for both APIs
2024-08-04 14:08:57 -04:00
Xueshan Feng
62854c91d3 🐳 chore: Update Dockerfile.multi (#3528)
Upgrade nginx:1.21.1-alpine to nginx:1.27.0-alpine. Reduce Vulnerabilities report from 59 to 7 by Google image scan.
2024-08-04 06:43:07 -04:00
Gerkin
cd326c4cf0 💫 fix: catch constant conditions in recoil state usage (#3513)
* chore: modify eslintrc

* fix: apply new rules, avoid using getter/setter tuples in conditions

---------

Co-authored-by: Alexandre Germain <nihilivin@gmail.com>
2024-08-01 14:10:42 -04:00
Danny Avila
e15d0d354d refactor: update defaultCollapsed value to true for new users 2024-08-01 03:27:27 -04:00
Danny Avila
b8a6efa649 👷‍♂️ chore: pass Tavily Response error and revert test commit on userSchema.js (#3496)
* chore: revert test commit

* chore: make sure tavily error gets passed
2024-07-31 12:06:27 -04:00
Marco Beretta
27ab00c6a9 🔉 fix: Elevenlabs TTS and STT (#3482)
* fix: add `await` on getVoices

* fix: STT function

* fix: elevenlabs

* chore(lint): remove unnecessary whitespace in ldap.js

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-30 12:46:46 -04:00
Marco Beretta
51cd847606 🗣️ refactor: speech services; fix: OpenAI STT (#3431)
* fix: OpenAI STT

* refactor: STT and TTS service, slightly imporve of performance

* fix(DecibelSelector): update default value
2024-07-30 09:18:52 -04:00
Danny Avila
4ffdefc2a8 🔧 refactor: update userSchema default value for role 2024-07-30 01:48:20 -04:00
Marco Beretta
2d5f704695 🎨 style: bookmarks UI update (#3479)
* style: bookmarks update; style(Files): minor update

* style: update conversation bookmarks

* style: fix w TableCell
2024-07-29 19:25:36 -04:00
Oliver Faust
3fd25920d4 🛠️ fix(ldap): LDAP_LOGIN_USES_USERNAME config (#3472) 2024-07-29 14:32:35 -04:00
Yuichi Oneda
d03f8285db 🔧 refactor: Enable Scrolling Chat Message with Page keys (#3350) 2024-07-29 10:46:36 -04:00
Yuichi Oneda
e565e0faab 🔖 feat: Conversation Bookmarks (#3344)
* feat: add tags property in Conversation model

* feat: add ConversationTag model

* feat: add the tags parameter to getConvosByPage

* feat: add API route to ConversationTag

* feat: add types of ConversationTag

* feat: add data access functions for conversation tags

* feat: add Bookmark table component

* feat: Add an action to bookmark

* feat: add Bookmark nav component

* fix: failed test

* refactor: made 'Saved' tag a constant

* feat: add new bookmark to current conversation

* chore: Add comment

* fix: delete tag from conversations when it's deleted

* fix: Update the query cache when the tag title is changed.

* chore: fix typo

* refactor: add description of rebuilding bookmarks

* chore: remove unused variables

* fix: position when adding a new bookmark

* refactor: add comment, rename a function

* refactor: add a unique constraint in ConversationTag

* chore: add localizations
2024-07-29 10:45:59 -04:00
Jacob Colyvan
d4d56281e3 🗨️ fix: respect line breaks in prompt variables (#3459)
* fix: always display new lines in PromptEditor

* fix: allow multiline inputs in prompt template
2024-07-27 18:02:34 -04:00
Arthur Barrett
14eff23b57 🔧 fix: Ensure ShareView document title is configured (#3336)
* 🔧 fix: ensure ShareView document title is configured

* chore: import order

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-07-27 15:47:26 -04:00
Ravi Katiyar
18fd8f1416 🔒 feat: add option to disable TLS for LDAP authentication (#3247)
* feat: add ldap tls config

* Update ldapStrategy.js

* LDAP_TLS_REJECT_UNAUTHORIZED optional

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-27 15:46:39 -04:00
Danny Avila
ba9cb71245 🛂 feat: Allow LDAP login via username (#3463)
* Allow LDAP login via username

This patch adds the option to login via username instead of using an
email address since the latter may not be unique or may change.

For example, our organization has two main domains and users have a log
and a short form of their mail address. This makes it hard for users to
identify what their primary email address is and causes a lot of
confusion. Using their username instead makes it much easier.

Using a username will also make it easier in the future to not need a
separate bind user to get user attributes. So, this is also a bit of
prep work for that.

* Update config.js

* feat: Enable LDAP login via username

This commit enables the option to login via username instead of using an email address for LDAP authentication. This change is necessary because email addresses may not be unique or may change, causing confusion for users. By using usernames, it becomes easier for users to identify their primary email address. Additionally, this change prepares for future improvements by eliminating the need for a separate bind user to retrieve user attributes.

Co-authored-by: Danny Avila <danny@librechat.ai>

* chore: jsdocs

* chore: import order

* ci: add ldap config tests

---------

Co-authored-by: Lars Kiesow <lkiesow@uos.de>
2024-07-27 15:42:18 -04:00
Danny Avila
e5dfa06e6c 🎚️ chore: Update Logging Levels for Conversations and Messages (#3415) 2024-07-21 13:54:47 -04:00
Marco Beretta
0bd59c0efe 🎨 style: update Assistants builder (#3397)
* style: update Assistant builder

* fix(Eng): re-introduce old file_search info message

* feat: new OGDialogTemplate; style: imporved tools + actions dialogs

* style: fix alignment issue for delete tool dialog

* chore: import order

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-21 13:46:43 -04:00
Marco Beretta
344297021f 🔧 fix: STT/TTS external checks pt. 2 (#3410) 2024-07-21 17:38:04 +02:00
Marco Beretta
620973436c 🔧 fix: STT/TTS external checks (#3409)
* fix: STT/TTS external

* remove unnecessary console log
2024-07-20 23:14:01 +02:00
Danny Avila
422d1a2c91 🤖 feat: new Anthropic Default Settings / Increased Output Tokens for 3.5-Sonnet (#3407)
* chore: bump data-provider

* feat: Add anthropicSettings to endpointSettings

The commit adds the `anthropicSettings` object to the `endpointSettings` in the `schemas.ts` file. This allows for the configuration of settings specific to the `anthropic` model endpoint.

* chore: adjust maxoutputtokens localization

* feat: Update AnthropicClient to use anthropicSettings for default model options and increased output beta header

* ci: new anthropic tests
2024-07-20 08:53:16 -04:00
Danny Avila
2ad097647c fix: Wait for Initial Message Save & Correct Latest Message (#3399)
* chore: assistants, unsupported assistant, better logging

* chore: remove unnecessary logger in validateAssistant middleware

* fix: resolve initial conversation save/promise before saving response

* chore: Import and organize dependencies in Speech component

* fix: conversation statefulness
- Latest Message (at index 0) should not be reset if existing convo
- add debugging context for clearAllLatestMessages
- Added logging concerning latest Message updates (dev mode only)
- update latest message Set logic, also checks for change in conversation Id
- consolidated latest message helpers to client/src/utils/messages.ts
2024-07-20 01:51:59 -04:00
Danny Avila
9e7615f832 ⚙️ fix: Plugin Message Handling Errors (#3392)
- Add unique index for messageId and user in messageSchema
- use `updateMessage` for updating the plugins message?
- add better logging for updateMessage
- prevents dupe_key or getKeyIndex error
2024-07-19 08:06:05 -04:00
Marco Beretta
ee4dd1b2e9 🚀 feat: gpt-4o-mini (#3384)
* feat: `gpt-4o-mini`

* feat: retrival

* fix: Update order of model token values for 'gpt-4o' and 'gpt-4o-mini'

* fix: Update order of model token values for 'gpt-4o' and 'gpt-4o-mini'

* fix: Update order of model token values for 'gpt-4o' and 'gpt-4o-mini'

* fix: add jsdoc

* fix: Update order of model token values for 'gpt-4o' and 'gpt-4o-mini'

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-19 07:59:07 -04:00
Danny Avila
f6125ccd59 🌿 fix: Message Route Improvements pt. 2 (#3379)
* fix: edge case with debugTraverse function in parsers.js

* chore: Update error message in audio stream processing

* refactor: Add ONE_MINUTE and THIRTY_SECONDS options to Time enum

* fix: logging
2024-07-18 13:56:19 -04:00
Danny Avila
1acd47a0f6 🌿 fix: Message Route Improvements (#3378)
* fix: do not throw errors for invalid convo id, simply return undefined

* feat: Add error handling and logging to message route definitions

* feat: Refactor Message.js to improve code organization and readability

* fix: Return undefined instead of throwing error for invalid conversation ID in Message.spec.js
2024-07-18 10:07:10 -04:00
Danny Avila
5d40d0a37a ⚙️ feat: Adjust Rate of Stream Progress (#3244)
* chore: bump data-provider and add MESSAGES CacheKey

* refactor: avoid saving messages while streaming, save partial text to cache instead

* fix(ci): processChunks

* chore: logging aborted request to debug

* feat: set stream rate for token processing

* chore: specify default stream rate

* fix(ci): Update AppService.js to use optional chaining for endpointLocals assignment

* refactor: abstract the error handler

* feat: streamRate for assistants; refactor: update default rate for token

* refactor: update error handling in assistants/errors.js

* refactor: update error handling in assistants/errors.js
2024-07-17 10:47:17 -04:00
Danny Avila
1c282d1517 🛣️ fix: Add validation middleware to message route definitions (#3365) 2024-07-17 10:27:07 -04:00
Marco Beretta
73dbf3eb20 🌐 feat: disable external engine if not configured (#3313)
* feat: disable external engine if not configured

* remove comment
2024-07-17 10:08:43 -04:00
Marco Beretta
237a0de8b6 🔄 feat: chat direction (LTR-RTL) (#3260)
* feat: chat direction

* fix: FileRow

* feat: smooth trigger transition
2024-07-17 10:08:13 -04:00
Marco Beretta
d5782ac66c feat: auto send text slider (#3312)
* feat: convert main component to float

* feat: convert the remaining components

* feat: use `recoilState` instead of `recoilValue`

* feat: replaced `AutoSendTextSwitch` to `AutoSendTextSelector`

* feat: use `autoSendText` in the `useSpeechToTextExternal` hook

* fix: `autoSendText` timeout
2024-07-17 10:07:11 -04:00
Danny Avila
d5d188eebf 🔐 fix: Enhance Message & Image Access Security (#3363)
* chore: slight refactor

* fix: prevent message updates unless explicitly owned

* refactor: rethrow errors, update deleteMessagesSince (not used), add basic tests

* fix: Add path normalization and validation to image request middleware

* fix: image validation path security
2024-07-17 09:51:03 -04:00
Benedikt Nordhoff
0a1d38e318 🔧 fix: Make assistant tool filtering compatible with plugin filtering (#3325)
includedTools expects the pluginKey/tool.name for filtering included tools, which is incompatible with the previous implementation in loadAndFormatTools used for loading assistant tools.

This change uses both filename and tool.name for filtering tools in ToolService.loadAndFormatTools in order to make it compatible with the old implementation and the behaviour of plugin filtering.

Co-authored-by: Benedikt Nordhoff <benedikt.nordhoff@codecentric.de>
2024-07-12 08:26:35 -04:00
Danny Avila
5ef71a7a36 🪙 fix: Streaming Response Token Issue (#3323)
* chore: use NEW_CONVO constant

* fix: token object assign issue
2024-07-10 23:41:21 -04:00
Peter Dave Hello
326069d7a6 🌏 i18n: Improve Traditional Chinese translation (#3311) 2024-07-10 16:54:12 -04:00
ylioja
785430daf5 🌍 i18n: Added Finnish Translations (#3316) 2024-07-10 16:53:45 -04:00
Anirudh
03fe361917 🔧 fix+chore: Resolve Overflow in Settings Modal & Upgrade to Headless UI 2.0 (#2661)
* fix: dropdown overflow

* fix: make dropdown work on mobile

* feat: update headlessui to 2.0 and use portal

* feat: rewrite modal using headlessui

* fix: applying of maxHeight

* fix: optimize backdrop for dark mode

* fix: rendering dropdown width

* feat: match small screen layout to radix-ui dialog

* revert: mobile modifications

* fix: modal animations

* fix: z-index

* chore: Migrate from HeadlessUI 1.0 to 2.0

* fix: h2 nesting

* fix: use lighter border for PopoverButtons

* feat: Move modal to the top if using a small screen

* fix: mobile position

* fix: frontend tests

* feat: use row layout in mobile instead of col

* fix: remove config path from tsconfig

* fix: fix dropdown tests (gpt4o ftw!)

* feat: Upgrade to latest headlessui version

* fix:test1

* fix: ThemeSelector test

* fix: re-add speech tab

* style: use pl and pr-3

* fix: speech tab dropdowns

* style: use maxHeight for language

* feat: convert DropdownNoState to v2.0

* fix: use v2 params for voiceDropdown

* style: reduce maxHeight for VoiceDropdown and set fixed width

* chore: rebuild package-lock

* style(fix): copy over the same styles for the settingsTab

* style(fix): use -top-1 for speech tabs

* style(fix): use max-w-[400px]

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-10 16:45:58 -04:00
Marco Beretta
b34a4ddac1 🌩️ feat: cloud-based browser voices (#3297)
* initial voice support

* feat: local voices; feat: switch cloud-based voices

* feat: apply voice to hook
2024-07-10 16:44:12 -04:00
Mert Doğruca
7d5b03dd98 🗨️ fix: Reset prompt groups query when changing filters (#3294) 2024-07-10 16:43:02 -04:00
Marco Beretta
f959ee302c 🗣️ fix: get speechTab config; feature: not overriding variables selected by user (#3282)
* fix(Speech): speechTab settings update

* fix: get speech config; refactor: moved everything to types and removed file types; feature: not overriding variables selected by user
2024-07-10 16:38:36 -04:00
Marco Beretta
cd00df69bb 👤 feat: zoom and rotate avatar (#3264) 2024-07-10 16:38:02 -04:00
Marco Beretta
a05e2c1dcc 🗣️ feat: Azure OpenAI speech (#2985)
* feat: Azure STT

* feat: Azure TTS

* refactor: use enums

* fix: frontend tests

* fix(config): wrong key provider
2024-07-10 16:33:06 -04:00
Danny Avila
87bdbda10a 🗣️ fix: update API endpoint for fetching audio in StreamAudio (#3307) 2024-07-09 09:16:16 -04:00
GaelMartins0
605a8ae8c9 🌍 i18n: Update French Translations (#3240)
* French Translation Update

* French Translation Update
2024-07-09 08:32:01 -04:00
eniyiweb
a724635998 🌍 i18n: Update Turkish Translations (#3232)
* Language translation:Turkish translation update

* 🌍: Turkish Translation - Update

* Additional Turkish translations

* Additional Turkish translations

* Added mongo-express

* New translations added

* Update docker-compose.yml

* Turkish language update

* Turkish Translation - Update

* Turkish Translation - Update
2024-07-09 08:30:52 -04:00
Marco Beretta
6c306a662c 🔊 docs(librechat.example): update version (#3287)
* Update librechat.example.yaml

* Update config.ts
2024-07-07 19:00:45 +02:00
Marco Beretta
55f8d9910e ⚒️ fix(speechToText): OpenAI Provider (#3283) 2024-07-07 00:32:19 +02:00
Marco Beretta
7edb54889b 🔊 docs(librechat.example): update speech (#3281) 2024-07-06 16:38:58 -04:00
Marco Beretta
71d9e841b1 📝 docs: update password reset warning link (#3274) 2024-07-06 16:38:40 -04:00
Marco Beretta
e76777d298 💊 fix: OpenID proxy support for downloading profile pictures (#3263)
Related to #3261

Add proxy support to `downloadImage` function in `openidStrategy.js`

* Import `HttpsProxyAgent` from `https-proxy-agent`.
* Add `agent` property to the fetch options in `downloadImage` function if `process.env.PROXY` is set.
* Update the `fetch` call in `downloadImage` function to use the proxy agent if available.
2024-07-05 10:23:06 -04:00
Marco Beretta
1edbfdbce2 🔑 feat: infinite key expiry (#3252) 2024-07-05 10:15:09 -04:00
Marco Beretta
1aad315de6 🎤 feat: add custom speech config, browser TTS/STT features, and dynamic speech tab settings (#2921)
* feat: update useTextToSpeech and useSpeechToText hooks to support external audio endpoints

This commit updates the useTextToSpeech and useSpeechToText hooks in the Input directory to support external audio endpoints. It introduces the useGetExternalTextToSpeech and useGetExternalSpeechToText hooks, which determine whether the audio endpoints should be set to 'browser' or 'external' based on the value of the endpointTTS and endpointSTT Recoil states. The useTextToSpeech and useSpeechToText hooks now use these new hooks to determine whether to use external audio endpoints

* feat: add userSelect style to ConversationModeSwitch label

* fix: remove unused updateTokenWebsocket function and import

The updateTokenWebsocket function and its import are no longer used in the OpenAIClient module. This commit removes the function and import to clean up the codebase

* feat: support external audio endpoints in useTextToSpeech and useSpeechToText hooks

This commit updates the useTextToSpeech and useSpeechToText hooks in the Input directory to support external audio endpoints. It introduces the useGetExternalTextToSpeech and useGetExternalSpeechToText hooks, which determine whether the audio endpoints should be set to 'browser' or 'external' based on the value of the endpointTTS and endpointSTT Recoil states. The useTextToSpeech and useSpeechToText hooks now use these new hooks to determine whether to use external audio endpoints

* feat: update AutomaticPlayback component to AutomaticPlaybackSwitch; tests: added AutomaticPlaybackSwitch.spec
>
> This commit renames the AutomaticPlayback component to AutomaticPlaybackSwitch in the Speech directory. The new name better reflects the purpose of the component and aligns with the naming convention used in the codebase.

* feat: update useSpeechToText hook to include interimTranscript

This commit updates the useSpeechToText hook in the client/src/components/Chat/Input/AudioRecorder.tsx file to include the interimTranscript state. This allows for real-time display of the speech-to-text transcription while the user is still speaking. The interimTranscript is now used to update the text area value during recording.

* feat: Add customConfigSpeech API endpoint for retrieving custom speech configuration

This commit adds a new API endpoint  in the  file under the  directory. This endpoint is responsible for retrieving the custom speech configuration using the  function from the  module

* feat: update store var  and ; fix: getCustomConfigSpeech

* fix: client tests, removed unused import

* feat: Update useCustomConfigSpeechQuery to return an array of custom speech configurations

This commit modifies the useCustomConfigSpeechQuery function in the client/src/data-provider/queries.ts file to return an array of custom speech configurations instead of a single object. This change allows for better handling and manipulation of the data in the application

* feat: Update useCustomConfigSpeechQuery to return an array of custom speech configurations

* refactor: Update variable name in speechTab schema

* refactor: removed unused and nested code

* fix: using recoilState

* refactor: Update Speech component to use useCallback for setting settings

* fix: test

* fix: tests

* feature: ensure that the settings don't change after modifying then through the UI

* remove comment

* fix: Handle error gracefully in getCustomConfigSpeech and getVoices endpoints

* fix: Handle error

* fix: backend tests

* fix: invalid custom config logging

* chore: add back custom config info logging

* chore: revert loadCustomConfig spec

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-07-05 10:13:34 -04:00
Danny Avila
5d985746cb 🛠️ fix: Tool Filtering in PluginsClient (#3266)
* feat(plugins): implement tool filtering in PluginsClient

Add functionality to filter tools based on filteredTools and includedTools
arrays in the request's app locals. This allows for dynamic tool selection
on a per-request basis, enhancing the flexibility of the plugin system.

* test(plugins): add unit tests for tool filtering in PluginsClient

Introduce comprehensive test suite for the new tool filtering feature
in PluginsClient. Cover scenarios including filtering out tools,
including specific tools, prioritization of includedTools over
filteredTools, and behavior when no filters are provided.

* chore: Remove unused legacy Conversation component and update imports
2024-07-04 10:34:28 -04:00
Marco Beretta
04654014b2 📝 docs(README): update Railway referral code (#3242) 2024-07-03 13:37:56 +02:00
Danny Avila
456793772b 📂 fix: Add version selection for Assistants Endpoint uploads (#3236) 2024-06-29 21:56:03 -04:00
Danny Avila
a87d4e0b75 🛠️ fix: Update Conversation and Message Models to Return Objects Instead of Using Lean() (#3230) 2024-06-28 21:57:53 -04:00
Danny Avila
a2fd975cd5 🚤 refactor: Optimize Request Lifecycle Speeds (#3222)
* refactor: optimize backend operations for client requests

* fix: message styling

* refactor: Improve handleKeyUp logic in StreamRunManager.js and handleText.js

* refactor: Improve handleKeyUp logic in StreamRunManager.js and handleText.js

* fix: clear new convo messages on clear all convos

* fix: forgot to pass userId to getConvo

* refactor: update getPartialText to send basePayload.text
2024-06-28 08:44:47 -04:00
Danny Avila
83619de158 🗨️ feat: Prompt Slash Commands (#3219)
* chore: Update prompt description placeholder text

* fix: promptsPathPattern to not include new

* feat: command input and styling change for prompt views

* fix: intended validation

* feat: prompts slash command

* chore: localizations and fix add command during creation

* refactor(PromptsCommand): better label

* feat: update `allPrompGroups` cache on all promptGroups mutations

* refactor: ensure assistants builder is first within sidepanel

* refactor: allow defining emailVerified via create-user script
2024-06-27 17:34:48 -04:00
Arthur Barrett
b8f2bee3fc 📱fix: set initial nav visibility for small screens (#3208)
* fix: hide nav on small screens by default

* test: add spec for Nav component
2024-06-27 10:56:32 -04:00
Ghaith AlHallak
81292bb4dd 🔡 fix: Rendering of Bidirectional Text (#3195)
The fix has been applied only to key components where the rendering issue is significant
2024-06-27 10:56:12 -04:00
Danny Avila
ed5ee1f86f 🔧 refactor: Reduce Complexity of Initial Load Effect & Message Styling (#3213)
* move shared conditions and early bail to reduce cognitive complexity, improve readability

* refactor: make condition as close to the original as possible

* chore: adjust comment in chat route

* style: fix original styling of non-multi messages

* refactor: separate messagerender logic from 'Message'

---------

Co-authored-by: RehaS <beratson@gmail.com>
2024-06-27 10:48:41 -04:00
Danny Avila
791b0139bc 🎨 style: Improve Styling (#3205)
* style: add scrollbar-gutter to prevent layout shift

* style: better styling for simple/advanced tab and remove border-r on smaller screens

* style: better description styling

* style: make sure single response Messages style is the same as pre-multi-stream response feature
2024-06-25 14:28:05 -04:00
Danny Avila
156c52e293 🌿 feat: Multi-response Streaming (#3191)
* chore: comment back handlePlusCommand

* chore: ignore .git dir

* refactor: pass newConversation to `useSelectMention`

refactor: pass newConversation to Mention component

refactor: useChatFunctions for modular use of `ask` and `regenerate`

refactor: set latest message only for the first index in useChatFunctions

refactor: pass setLatestMessage to useChatFunctions

refactor: Pass setSubmission to useChatFunctions for submission handling

refactor: consolidate event handlers to separate hook from useSSE

WIP: additional response handlers

feat: responsive added convo, clears on new chat/navigating to chat, assistants excluded

feat: Add conversationByKeySelector to select any conversation by index

WIP: handle second submission with messages paired to root

* style: surface-primary-contrast

* refactor: remove unnecessary console.log statement in useChatFunctions

* refactor: Consolidate imports in ChatForm and Input hooks

* refactor: compositional usage of useSSE for multiple streams

* WIP: set latest 'multi' message

* WIP: first pass, added response streaming

* pass: performant multi-message stream

* fix: styling and message render

* second pass: modular, performant multi-stream

* fix: align parentMessageId of multiMessage

* refactor: move resetting latestMultiMessage

* chore: update footer text in Chat component

* fix: stop button styling

* fix: handle abortMessage request for multi-response

* clear messages but bug with latest message reset present

* fix: add delay for additional message generation

* fix: access LAST_CONVO_SETUP by index

* style: add div to prevent layout shift before hover buttons render

* chore: Update Message component styling for card messages

* chore: move hook use order

* fix: abort middleware using unsent field from req.body

* feat: support multi-response stream from initial message

* refactor: buildTree function to improve readability and remove unused code

* feat: add logger for frontend dev

* refactor: use depth to track if message is really last in its branch

* fix(buildTree): default export

* fix: share parent message Id and avoid duplication error for multi-response streams

* fix: prevent addedConvo reset to response convo

* feat: allow setting multi message as latest message to control which to respond to

* chore: wrap setSiblingIdxRev with useCallback

* chore: styling and allow editing messages

* style: styling fixes

* feat: Add "AddMultiConvo" component to Chat Header

* feat: prevent clearing added convos on endpoint, preset, mention, or modelSpec switch

* fix: message styling fixes, mainly related to code blocks

* fix: stop button visibility logic

* fix: Handle edge case in abortMiddleware for non-existant `abortControllers`

* refactor: optimize/memoize icons

* chore(GoogleClient): change info to debug logs

* style: active message styling

* style: prevent layout shift due to placeholder row

* chore: remove unused code

* fix: Update BaseClient to handle optional request body properties

* fix(ci): `onStart` now accepts 2 args, the 2nd being responseMessageId

* chore: bump data-provider
2024-06-25 03:02:38 -04:00
KiGamji
eef894e608 🌏 i18n: Improve clarity of English translation (#3154)
* 🌏 i18n: Improve clarity of English translation

* 🔧 fix(useCategories): replace i18n string to `com_ui_select_a_category`

* 🔨 refactor: avoid using placeholder strings where possible

This commit simplifies the internationalization approach for English language strings by removing the placeholder ones where they are used only once. This makes proper localization possible for Russian language, and possibly others.

Also renamed `com_ui_text_prompt` to `com_ui_prompt_text` to match the alphabetical order.

* 🎨 style(CreatePromptForm): add missing margin-top to the submit button
2024-06-24 13:47:20 -04:00
berat reha sönmez
e2867eecc9 🧹 chore: clean commented code (#3160) 2024-06-23 18:13:01 -04:00
Danny Avila
dd563e0796 📋 refactor: Prevent RTF Paste to Clipboard Only Plain Text (#3179) 2024-06-23 18:07:28 -04:00
Yuichi Oneda
c99cf1b4b1 🚅 chore: Added an Example of Nginx gzip Settings (#3173) 2024-06-23 13:49:00 -04:00
Matthew Unrath
b5081bfe86 🤖 feat: Add titling to Google client (#2983)
* feat: Add titling to Google client

* feat: Add titling to Google client

* PR feedback changes
2024-06-22 11:42:51 -04:00
Danny Avila
aac01df80c 🧹 chore: remove unnecessary try/catch when creating users (#3153) 2024-06-21 15:14:18 -04:00
Danny Avila
24467dd626 ⬆️ refactor: Improve Text Commands (#3152)
* refactor(useMentions): separate usage of `useSelectMention`

* refactor: separate handleKeyUp logic from useTextarea

* fix(Mention): cleanup blur timer

* refactor(handleKeyUp): improve command handling, prevent unintended re-trigger

* chore: remove console log

* chore: temporarily comment plus command
2024-06-21 12:34:28 -04:00
Danny Avila
b2b469bd3d 🌐 fix(actions): Correct URL Formation for Subdomains in createURL (#3149) 2024-06-21 11:07:45 -04:00
enz-PedroGruvhagen
cec2e57ee9 📝 chore: Update .env.example (#3142)
Added claude-3-5-sonnet-20240620 to the bunch so is available in the UI
2024-06-21 10:15:28 -04:00
Yuichi Oneda
a8c874267f 🚀 feat(LDAP): Add Flexible Configuration Options (#3124)
* chore: add detailed logs

* feat: added a variable to specify which attributes to be stored

* chore: Add new optiona variables

* refactor: change BIND_DN as an option

* chore: revert commits that fail testing

* refactor: use ldapid to retrieve users

* chore: remove unused variable

* chore: reverting unintended changes

* fix: return 404 if authentication fails, in accordance with requireLocalAuth.

* fix: handling when ldap settings do not exist

* chore: remove unnecessary check
2024-06-21 10:14:53 -04:00
Kurt Seifried
a53312bbd4 💻 feat: added env updater script (#3107) 2024-06-21 10:14:18 -04:00
Ikko Eltociear Ashimine
ab74685476 🐛 fix: Update resetConvo.ts (#3105)
Reseting -> Resetting
2024-06-21 10:13:21 -04:00
Yuichi Oneda
015215b790 🇯🇵 Fix: Incorrect Japanese Translation (#3119) 2024-06-21 10:13:02 -04:00
Yuichi Oneda
4e4de88faa 🔧 fix(Shared Links): Handling Shared Link Errors (#3118)
* refactor: add error handling in Share model

* refactor: add error handing to API routers

* refactor: display error message when API response is an error

* chore: remove unneccesary JSON.stringify

* chore: revert unintended changes

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-21 10:12:37 -04:00
Yuichi Oneda
3172381bad 🔧 fix(useTextArea): Incorrect New Line while Composing Japanese Text (#3103) 2024-06-21 09:59:31 -04:00
Marco Beretta
54b1095239 🎨 style: fix inconsistent HoverButtons and correct style issue in Continue button (#3100)
* style: fix inconsistent HoverButtons and fixed style bug in `continue` button

* quick fix; forgot to re-implment the logic

* feat: convo switch buttons
2024-06-21 09:58:38 -04:00
Marco Beretta
0424f8fe55 🎨 style: settings tab update (#3088)
* style: settings UI  update

* style: update UI

* style: update button style

* fix: scroll settings on mobile

* feat: `?` for settings
2024-06-21 09:58:04 -04:00
Peter Dave Hello
4319c62e66 🌏 i18n: Traditional Chinese language code to zh-TW (#3143) 2024-06-21 08:54:00 -04:00
Peter Dave Hello
d3a0b862db 🌏 i18n: Improve Traditional Chinese translation (#3144) 2024-06-21 08:53:18 -04:00
Danny Avila
5d8793c5d1 🗨️ refactor: Improve Prompts Query (#3138) 2024-06-20 22:21:17 -04:00
Danny Avila
54db67449a 🧠 feat: claude-3-5-sonnet (#3135)
* 🧠 feat: claude-3-5-sonnet

* chore: bump data-provider
2024-06-20 20:48:15 -04:00
Danny Avila
0cd3c83328 🗨️ feat: Prompts (#3131)
* 🗨️ feat: Prompts (#7)

* WIP: MERGE prompts/frontend (#1)

* added schema for prompt and promptgroup, added model methods for prompts, added routes for prompts

* * updated promptGroup Schema

* updated model methods for prompts (get, add, delete)

* slight fixes in prompt routes

* * Created Files Management components

* Created Vector Stores components

* Added file management route in the routes folder

* Completed UI for Files list, Compeleted UI for vector stores list, Completed UI for upload file modal, Completed UI for preview file, Completed UI for preview vector store

* Fixed style and UI fixes for file dashboard, file list and vector stores list

* added responsiveness classes for vector store page

* fixed responsiveness of file page, dashboard page, and main page

* fixed styling and responsiveness issues on dashboard page, file list page and vector store page

* added queries and mutations for prompts and promptGroups, added relevant endpoints in data-provider, added relevant components prompts, added and updated relevant APIs

* added types on mutation queries data service, updated prompt attributes

* feature: Prompts and prompt groups management, added relevant APIs, added types for data service/queries/mutations, added relevant mutation and queries

* chore: typing clarifications

* added drop down on prompts mgmt dashboard

* Fixes: fixed version switching issue on tags update or labels update, added cross button on create prompt group, fixed list updation on prompt group renaiming, added CSV upload button

* Feature: Added oneliner and category attributes in prompt group, added schema for categories, added schema methods and route for categories

* chore: typing and lint issues

* chore: more type and linter fixes

* chore: linting

* chore: prompt controller and backend typing example; MOVE TO CONTROLLER DIRECTORY

* chore: more type fixes

* style: prompt name changes

* chore: more type changes, and stateful prompt name change without flickering

* fix: Return result of savePrompt in patchPrompt API endpoint

* fix: navigation prompt queries; refactor: name 'prompt-groups' to just 'groups'

* refactor: fetch prompt groups rewrite

* refactor(prompts): query/mutation statefulness

* refactor: remove `isActive` field

* refactor: remove labels, consolidate logic

* style: width, layout shift

* refactor: improve hover toggle behavior and styling

* refactor: add useParams hook to PromptListItem for dynamic rendering and add timeout ref for blur timeout

* chore: hide upload button

* refactor: import Button component from correct location in PromptSidePanel

* style: prompt editor styling

* style: fix more layout shifts

* style: container scroll

* refactor: Rename CreatePrompt component to CreatePromptForm

* refactor: use react-hook-form

* refactor: Add Prompts components and routes to Dashboard

* style: skeletons for loading

* fix: optimize makePromptProduction

* refactor: consolidate variables

* feat: create prompt form validation

* refactor: Consolidate variables and update mutation hooks

* style: minor touchups

* chore: Update lucide-react npm dependency to version 0.394.0 and npm audit fix

* refactor: add a new icon for the Prompts heading.

* style: Update PromptsView heading to use h1 instead of h2 and other minor margin issues

* chore: wording

* refactor: Update PromptsView heading to use h1 instead of h2, consolidate variables, and add new icons

* refactor: Prompts Button for Mobile

* feature: added category field in prompt group, added relevant API and static data on BE to support FE UI for category in prompt group

* chore: template for prompt cards

---------

Co-authored-by: Fawadpot <contactfawada@gmail.com>

* WIP: Prompts/frontend Continued (#2)

* chore: loading style, remove unused component

* feat: Add CategorySelector component for prompt group category selection

* feat: add categories to create prompt

* feat: prompt versions styling

* feat: optimistic updates for prompt production state

* refactor: optimize form state and show if prompt field is dirty with cross icon, also other styling changes

* chore: remove unused code and localizations

* fix: light mode styling

* WIP: SidePanel Prompts

* refactor: move to groups directory

* refactor: rename GroupsSidePanel to GroupSidePanel and update imports

* style: ListCard

* refactor: isProduction changes

* refactor: infinite query with productionPrompt

* refactor: optimize snippets and prompts, and styling

* refactor: Update getSnippet function to accept a length parameter

* chore: localizations

* feat: prompts navigation to chat and vice versa

* fix: create prompt

* feat: remember last selected category for creating prompts

* fix(promptGroups): fix pagination and add usePromptGroupsNav hook

* Prompts/frontend 3 (#3)

* fix: stateful issues with prompt groups

* style: improved layout

* refactor: improve variable naming in Eng.ts

* refactor: theme selector styling improvements

* added prompt cards on chat new page, with dark mode, added API to fetch random prompts, added types for useQuery

Slightly improved usePromptGroupNav logic to fetch updated result for pageSize, updated prompt cards view with darkmode and responsiveness

fixed page size option buttons styling to match the theme

added dark mode on create prompt page and prompt edit/preview page

fixed page size option buttons styling to match the theme

added dark mode on create prompt page and prompt edit/preview page

* WIP: Prompts/frontend (#4)

* fix: optimize and fix paginated query

* fix: remove unique constraint on names

* refactor: button links and styling

* style: menu border light mode

* feat: Add Auto-Send Switch component for prompts groups

* refactor(ChatView): use form context for submission text

* chore: clear convo state on navigation to dashboard routes

* chore: save prompt edit name on tab, remove console log

* feat: basic prompt submission

* refactor: move Auto-Send Switch

* style(ListCard): border styling

* feat: Add function to detect variables in text

* feat: Add OriginalDialog component to UI library

* chore(ui): Update SelectDropDown options list class to use text-xs size

* refactor: submitMessage hook now includes submitPrompt, make compatible to document query selector

* WIP: Variable Dialog

* feat: variable submission working for both auto-send and non-autosend

* feat: dashboard breadcrumbs and prompts/chat navigation

* refactor: dashboard breadcrumb and dashboard link to chat navigation

* refactor: Update VariableDialog and VariableForm styles

* Prompts: Admin features (#5)

* fix: link issue

* fix: usePromptGroupsNav add missing dep.

* style: dashbreadcrumb and sidepanel text color

* temp fix: remove refetch on pageNumber change

* fix: handle multiple variable replacement

* WIP: create project schema and add project groups to fetch

* feat: Add functionality to add prompt group IDs to a project

* feat: Add caching for startup config in config route

* chore: remove prompt landing

* style: Update Skeleton component with additional background styling

* chore: styling and types

* WIP: SharePrompt first draft

* feat(SharePrompt): form validation

* feat: shared global indicators

* refactor: prompt details

* refactor: change NoPromptGroup directory

* feat: preview prompt

* feat: remove/add global prompts, add rbac-related enums

* refactor: manage prompts location

* WIP: first draft admin settings for prompts

* feat: SystemRoles enum

* refactor: update PromptDetails component styling

* style: ellipsis custom class for showing more preview text

* WIP: initial role schema and initialization

* style: improved margins for single unordered lists

* fix: use custom chat form context to prevent re-renders from FormProvider

* feat: Role mutations for Prompt Permissions

* feat: fetch user role

* feat: update AdminSettings form default values from user role values

* refactor: rename PromptPermissions to Permissions for general definitions

* feat: initial role checks

* feat: Add optional `bodyProps` parameter to generateCheckAccess middleware

* refactor: UI access checks

* Prompts: delete (#6)

* Fixed delete prompt version API, fixed types and logic for prompt version deletion, updated prompt delete mutation logic

* chore: Update return type of deletePrompt function in Prompt.js

---------

Co-authored-by: Fawadpot <contactfawada@gmail.com>

* chore: Update package-lock.json version to 0.7.4-rc1 and fast-xml-parser to 4.4.0

* feat: toast for saving admin settings, add timer no-access navigation

* feat: always make prod

* feat: Add localization to category labels in CategorySelector component

* feat: Update category label localization in CategorySelector component

* fix: Enable making prompt production in Prompt API

---------

Co-authored-by: Fawadpot <contactfawada@gmail.com>

* feat: Add helper fn for dark mode detection in ThemeProvider

* style: surface-primary definition

* fix(useHasAccess): utilize user.role and not just USER role

* fix: empty category and role fetch

* refactort: increase max height to options list and use label if no localization is found

* fix: update CategorySelector to handle empty category value and improve localization

* refactor: move prompts to own store/reactquery modules, add in filter WIP

* refactor: Rename AutoSendSwitch to AutoSendPrompt

* style: theming commit

* style: fix slight coloring issue for convos in dark mode

* style: better composition for prompts side panel

* style: remove gray-750 and make it gray-850

* chore: adjust theming

* feat: filter all prompt groups and properly remove prompts from projects

* refactor: optimize delete prompt groups further

* chore: localization

* feat: Add uniqueProperty filtering to normalizeData function

* WIP: filter prompts

* chore: Update FilterPrompts component to include User icon in FilterItem

* feat(FilterPrompts): set categories

* feat: more system filters and show selected category icon

* style: always make prod, flips switch to avoid mis-clicks

* style: ui/ux loading/no prompts

* chore: style FilterPrompts ChatView

* fix: handle missing role edge case

* style: special variables

* feat: special variables

* refactor: improve replaceSpecialVars function in prompts.ts

* feat: simple/advanced editor modes

* chore: bump versions

* feat: localizations and hide production button on simple mode

* fix: error connecting layout shift

* fix: prompts CRUD for admins

* fix: secure single group fetch

* style: sidepanel styling

* style(PromptName): bring edit button closer to name

* style: mobile prompts header

* style: mobile prompts header continued

* style: align send prompts switch right

* feat: description

* Update special variables description in Eng.ts

* feat: update/create/preview oneliner

* fix: allow empty oneliner update

* style: loading improvement and always make selected prompt Production if simple mode

* fix: production index set and remove unused props

* fix(ci): mock initializeRoles

* fix: address #3128

* fix: address #3128

* feat: add deletion confirmation dialog

* fix: mobile UI issues

* style: prompt library UI update

* style: focus, logcal tab order

* style: Refactor SelectDropDown component to improve code readability and maintainability

* chore: bump data-provider

* chore: fix labels

* refactor: confirm delete prompt version

---------

Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2024-06-20 20:24:32 -04:00
Danny Avila
302b28fc9b v0.7.4-rc1 (#3099)
* fix(openIdStrategy): return user object on new user creation

*  v0.7.4-rc1
2024-06-17 12:47:28 -04:00
Marco Beretta
dad25bd297 📝 docs: update README (#3093) 2024-06-17 07:51:13 -04:00
Marco Beretta
a338decf90 ✉️ fix: email address encoding in verification link (#3085)
Related to #3084

Implements URL encoding for email addresses in verification links and decodes them upon verification.

- **Encode email addresses** in `sendVerificationEmail` and `resendVerificationEmail` functions using `encodeURIComponent` to ensure special characters like `+` are correctly handled in the verification link.
- **Decode email addresses** in the `verifyEmail` function using `decodeURIComponent` to accurately retrieve and validate the email address from the verification link against the database.


---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/danny-avila/LibreChat/issues/3084?shareId=9c32df30-4156-4082-a3eb-fff54eaba5b3).
2024-06-16 16:05:53 -04:00
Danny Avila
2cf5228021 🕑 fix: Add Suspense to Connection Error Messages (#3074) 2024-06-15 16:16:06 -04:00
Danny Avila
0294cfc881 v0.7.3 (#3067)
* refactor: revert BaseClient to use node-fetch instead of undici

* chore: bump version

* chore: update npm dependencies to latest versions

* chore: fix custom footer
2024-06-15 12:17:10 -04:00
Yuichi Oneda
8d8b17e7ed 🚀 feat: Add Option to Disable Shared Links (#2986)
* feat: add option to disable shared links

* chore: update languages

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-15 11:12:03 -04:00
Danny Avila
04502e9525 👤 fix: Create User with timestamps (#3070)
* 👤 fix: Create User with timestamps

* chore: fix lint script to ignore venv

* chore: linting
2024-06-15 10:36:49 -04:00
btribonde
bcaa7d5d29 🛤️ feat: Proxy Support for OpenID Login (#3051)
https://github.com/danny-avila/LibreChat/issues/3041
2024-06-15 09:41:34 -04:00
Marco Beretta
c288b458b6 📝 docs: update README's features (#3011)
* Update README.md

* Update README.md

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-15 09:36:05 -04:00
Neelesh Kumar
447bbcb8ca 📝 chore: Update .env.example with Custom Endpoint API Key examples (#2970)
Add env variables for cohere and databricks
2024-06-15 09:31:39 -04:00
Marco Beretta
68bf7ac7c0 🪲 fix(useTextarea): enterToSend bugs (#2988)
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-15 09:30:19 -04:00
Denis Palnitsky
97d12d03d1 📊 feat: Google tag manager integration (#2469)
* Google tag manager integration

* change location of react-gtm-module package

* refactor: move react-gtm-module usage from Chat/Footer to useAppStartup hook

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-15 08:09:18 -04:00
Danny Avila
4416f69a9b 🚀 refactor: Use Undici Instead of Node-Fetch, prevent Event Close, add Index (#3052)
* feat: Add index to conversationId field in messageSchema

* refactor: prevent immediate event close on error

* refactor: use undici instead of node-fetch in non-Bun environment
2024-06-13 13:38:15 -04:00
Yuichi Oneda
29e71e98ad ✍️ feat: Automatic Save and Restore for Chat (#2942)
* feat: added "Save draft locally" to Message settings

* feat: add hook to save chat input as draft every second

* fix: use filepath if the file does not have a preview prop

* fix: not to delete temporary files when navigating to a new chat

* chore: translations

* chore: import order

* chore: import order

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-13 09:52:30 -04:00
Jakub Mieszczak
e9bbf39618 📝 feat: Markdown support for Custom Footer links (#2960)
* feat: Add markdown support for custom footer links

* fix: Update Footer component with revised ReactMarkdown props

* fix: Adjusted footer links and pipe styles for consistent appearance

* refactor: remove unused footer.tsx file
2024-06-13 09:51:28 -04:00
Danny Avila
08b8ae120e 🤖 fix(Assistants): Ensure Required Actions always have Outputs (#3031) 2024-06-10 22:01:52 -04:00
Danny Avila
803fd63121 📋 fix(handlePaste): Remove Custom rich-text handling (#3025)
* fix: rich text edge case

* fix(useTextarea): removing custom handling fixes RTF slow loading, default behavior with form prefers plain-text
2024-06-10 14:36:51 -04:00
Yuichi Oneda
ef76cc195e 🎨 style(Textarea): Message Edit Textarea Styling (#3009) 2024-06-10 13:01:07 -04:00
Danny Avila
2e559137ae ℹ️ refactor: Remove use of Agenda for Conversation Imports (#3024)
* chore: remove agenda and npm audit fix

* refactor: import conversations without agenda

* chore: update package-lock.json and data-provider version to 0.6.7

* fix: import conversations

* chore: client npm audit fix
2024-06-10 13:00:34 -04:00
Danny Avila
92232afaca 📧 fix: Cancel Signup if Email Issuance Fails (#3010)
* fix: user.id assignment in jwtStrategy.js

* refactor(sendEmail): pass params as object, await email sending to propogate errors and restrict registration flow

* fix(Conversations): handle missing updatedAt field

* refactor: use `processDeleteRequest` when deleting user account for user file deletion

* refactor: delete orphaned files when deleting user account

* fix: remove unnecessary 404 status code in server/index.js
2024-06-08 06:51:29 -04:00
Danny Avila
084cf266a2 🗃️ fix: revise RAG prompt (#3006) 2024-06-07 20:51:43 -04:00
Danny Avila
baf0848021 📧 fix: LDAP login after User verification changes (#3003) 2024-06-07 17:43:36 -04:00
Danny Avila
1da92111aa 🚀 refactor: Remove Local Login Redundancies (#3002) 2024-06-07 16:45:31 -04:00
Danny Avila
35f8053f45 📧 fix: Ensure User Verification for Instances without Email Service (#2998) 2024-06-07 15:43:43 -04:00
Marco Beretta
ee673d682e 📧 feat: email verification (#2344)
* feat: verification email

* chore: email verification invalid; localize: update

* fix: redirect to login when signup: fix: save emailVerified correctly

* docs: update ALLOW_UNVERIFIED_EMAIL_LOGIN; fix: don't accept login only when ALLOW_UNVERIFIED_EMAIL_LOGIN = true

* fix: user needs to be authenticated

* style: update

* fix: registration success message and redirect logic

* refactor: use `isEnabled` in ALLOW_UNVERIFIED_EMAIL_LOGIN

* refactor: move checkEmailConfig to server/utils

* refactor: use req as param for verifyEmail function

* chore: jsdoc

* chore: remove console log

* refactor: rename `createNewUser` to `createSocialUser`

* refactor: update typing and add expiresAt field to userSchema

* refactor: begin use of user methods over direct model access for User

* refactor: initial email verification rewrite

* chore: typing

* refactor: registration flow rewrite

* chore: remove help center text

* refactor: update getUser to getUserById and add findUser methods. general fixes from recent changes

* refactor: Update updateUser method to remove expiresAt field and use $set and $unset operations, createUser now returns Id only

* refactor: Update openidStrategy to use optional chaining for avatar check, move saveBuffer init to buffer condition

* refactor: logout on deleteUser mutatation

* refactor: Update openidStrategy login success message format

* refactor: Add emailVerified field to Discord and Facebook profile details

* refactor: move limiters to separate middleware dir

* refactor: Add limiters for email verification and password reset

* refactor: Remove getUserController and update routes and controllers accordingly

* refactor: Update getUserById method to exclude password and version fields

* refactor: move verification to user route, add resend verification option

* refactor: Improve email verification process and resend option

* refactor: remove more direct model access of User and remove unused code

* refactor: replace user authentication methods and token generation

* fix: add user.id to jwt user

* refactor: Update AuthContext to include setError function, add resend link to Login Form, make registration redirect shorter

* fix(updateUserPluginsService): ensure userPlugins variable is defined

* refactor: Delete all shared links for a specific user

* fix: remove use of direct User.save() in handleExistingUser

* fix(importLibreChatConvo): handle missing createdAt field in messages

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-07 15:06:47 -04:00
Marco Beretta
b7fef6958b 🔒refactor: social login and remove direct user model access in strategies (#2946)
* refactor: checking `ALLOW_SOCIAL_REGISTRATION` with `isEnabled`

* feat: Add findUserByEmail function to UserService

This commit adds a new function, , to the  module. This function retrieves a user document from the database based on the provided email. It returns the user document if found, otherwise it returns null. If there is a problem during user retrieval, an error is thrown.

* refactor: add socialLogin to remove repetitive code
2024-06-06 13:23:11 -04:00
Marco Beretta
5452d4c20c 🔒 feat: password reset disable option; fix: account email error message (#2327)
* feat: password reset  disable option; fix: account email leak

* fix(LoginSpec): typo

* test: fixed LoginForm test

* fix: disable password reset when undefined

* refactor: use a helper function

* fix: tests

* feat: Remove unused error message in password reset process

* chore: Update password reset email message

* refactor: only allow password reset if explicitly allowed

* feat: Add password reset email service configuration check

The code changes in `checks.js` add a new function `checkPasswordReset()` that checks if the email service is configured when password reset is enabled. If the email service is not configured, a warning message is logged. This change ensures secure password reset functionality by prompting the user to configure the email service.

Co-authored-by: Berry-13 <root@Berry>
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
Co-authored-by: Danny Avila <danny@librechat.ai>

* chore: remove import order rules

* refactor: simplify password reset logic and align against Observable Response Discrepancy

* chore: make password reset warning more prominent

* chore(AuthService): better logging for password resets, refactor requestPasswordReset to use req object, fix sendEmail error when email config is not present

* refactor: fix styling of password reset email message

* chore: add missing type for passwordResetEnabled, TStartupConfig

* fix(LoginForm): prevent login form flickering

* fix(ci): Update login form to use mocked startupConfig for rendering correctly

* refactor: Improve password reset UI, applies DRY

* chore: Add logging to password reset validation middleware

* chore(CONTRIBUTING): Update import order conventions

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
Co-authored-by: Berry-13 <root@Berry>
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-06-06 11:39:36 -04:00
Marco Beretta
a7f5b57272 🚫👤feat: delete user from UI (#1526)
* initial commit

* fix: UserController bugs; fix: lint errors

* fix: delete files

* language support

* style(DeleteAccount): update to the latest style

* style: fix after merge main

* chore: Add canDeleteAccount middleware for user deletion endpoint

* chore: renamed to ALLOW_ACCOUNT_DELETION

* fix(canDeleteAccount): use uppercase admin role

* chore: imports order

* chore: Enable account deletion by default if omitted/commented out

* chore: Add logging for user account deletion

* chore: Bump data-provider package version to 0.6.6

* chore: Import Transaction model in UserController

* chore: Update CONFIG_VERSION to 1.1.4

* chore: Update user account deletion logging

* chore: Refactor user account deletion logic

---------

Co-authored-by: Berry-13 <root@Berry>
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-05 19:35:12 -04:00
Marco Beretta
f69b317171 🔧 fix(useMentions): handle empty assistant lists (#2966)
The useMentions hook in the client/src/hooks/Input/useMentions.ts file has been updated to handle cases where the assistant lists for the endpoints 'assistants' and 'azureAssistants' are empty. This change ensures that the hook does not throw an error when attempting to access assistantListMap[EModelEndpoint.assistants] or assistantListMap[EModelEndpoint.azureAssistants]. Instead, it defaults to an empty array for these cases.
2024-06-05 14:56:15 -04:00
Yuichi Oneda
4469ba72fc 🧹 chore(.eslintrc.js): Update Import Order of The React Types (#2964) 2024-06-05 14:55:42 -04:00
Yuichi Oneda
0e3e45e77d 🔧 chore: Add import/order Eslint Rule (#2928)
* chore: add import order eslint rule

* refactor: apply 'import/order' rule
2024-06-04 08:56:26 -04:00
Marco Beretta
9f0c1914a5 🎂 fix: birthday icon (#2950)
* fix: tooltip and birthday icon

* chore: update conditional render

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-06-04 08:55:41 -04:00
Ventz Petkov
37ae484fbc 🚅 docs: Updated Example for LiteLLM ports and Volume mount (#2941)
* Added necessary "ports" section for it to work by default
* Added (commented out) example GCP Vertex volume mount for auth config and for ENV variable.
2024-06-01 08:51:18 -04:00
Danny Avila
8939d8af37 🦙 feat: Add LLama 3 System Context Length (#2938) 2024-05-31 12:16:08 -04:00
Danny Avila
f9a0166352 🔄 refactor(EditPresetDialog): Update Model on Endpoint Change (#2936)
* refactor(EditPresetDialog): dynamically update current editable preset model on endpoint change

* feat: Add null check for models in EditPresetDialog

* chore(AlertDialogPortal): typing

* fix(EditPresetDialog): prevent Unknown endpoint edge case for custom endpoints
2024-05-31 11:43:14 -04:00
Danny Avila
248dfb8b5b 🐛 fix: Resolve Preset Button Disappearing in Mobile View (#2935)
* refactor: Update import paths for ExportAndShareMenu component and add localization

* fix: mobile view for export/share button
2024-05-31 08:46:09 -04:00
Danny Avila
b8e35002f4 🗣️ fix: Set Audio Run ID at Top of Autoplayback Request (#2926) 2024-05-30 22:01:40 -04:00
Danny Avila
8318f26d66 🔉 feat: TTS/STT rate limiters (#2925)
* fix: remove double initialization of speech routes

* refactor(useMessageHelpers): more consistent latestMessage updates based on unique textKey and early returns when setting

* feat: TTS/STT rate limiters

* chore: remove console log

* fix: make modular chat true by default
2024-05-30 18:39:21 -04:00
Danny Avila
08d6bea359 🛠️ refactor: Improve Logging and Error Handling in ToolService and useSSE (#2922)
* refactor(ToolService): streamline logging and tool error handling, also ensure generated outputs always have `output` field

* refactor(useSSE): error message for server connection issue

* refactor: add back capture group of sensitive information.js

* hotfix: cohere chinese character unicode issue, return aggregated reply
2024-05-30 12:58:43 -04:00
Arthur Barrett
a6058c5669 🔧 chore: Update OpenIDStrategy Logging (#2911) 2024-05-30 10:48:03 -04:00
Danny Avila
e0402b71f0 🎨 style: Focus Outlines (#2913)
* style: add back focus ring removal as the outer/inner containers maintain focus stylings

* style: add focus outline to default buttonVariants class
2024-05-29 23:07:52 -04:00
Yuichi Oneda
a618266905 🔒 feature(auth): LDAP Authentication (#2859)
* 🔧 chore: npm install passport-ldapauth

*  feat(auth): add ldap authentication support

* chore: merge conflict fix

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-29 17:46:20 -04:00
Danny Avila
d5a7806e32 ⬆️ chore: bump @langchain/google-vertexai to v0.0.17 (#2905) 2024-05-29 10:47:05 -04:00
Danny Avila
e2cb2905e7 🖱️ feat: Minor Accessibility Changes (#2903)
* feat: focus rings for dialog buttons

* chore: temp: soft removal of removeFocusOutlines

* feat: allow tabbing of endpoint menu
2024-05-29 10:14:30 -04:00
Danny Avila
3f600f0d3f ⬇️ fix: JSON LibreChat Imports (#2897)
* chore: remove unused code

* refactor: Update NewChatButtonIcon component to use JSX syntax

The NewChatButtonIcon component in the Nav folder has been updated to use JSX syntax instead of calling the Icon function directly. This change improves code readability and maintainability.

* remove use memo

* refactor: allow passing `select` to messages db query

* fix: initial fix for non-recursive messages

* ci: first pass, importers test rewrite

* fix(groupConversationsByDate): handle edge case of conversation.updatedAt being null

* fix: correctly handle non-recursive uploads

* feat: imports non-recursive conversations with branches correctly

* feat: support retaining original options on import

* refactor: Allow `messageTree` field for Import of non-recursive conversations
2024-05-29 09:15:05 -04:00
Yuichi Oneda
c9e7d4ac18 🚑 fix(export): Export Issue with New Chat (#2777)
* 🚑 fix: re-fetch messages when exporting

* Revert "🚑 fix: re-fetch messages when exporting"

This reverts commit 693b86e955.

* 🚑 fix: use the same logic to get export data as useChatHelper

* refactor(useExportConversation): use query cache to build messages tree on request

* chore: organize imports

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-28 18:10:33 -04:00
Danny Avila
40685f6eb4 🚀 refactor: Enhance Custom Endpoints, Message Logic, and Payload Handling (#2895)
* chore: use node-fetch for OpenAIClient fetch key for non-crashing usage of AbortController in Bun runtime

* chore: variable order

* fix(useSSE): prevent finalHandler call in abortConversation to update messages/conversation after user navigated away

* chore: params order

* refactor: organize intermediate message logic and ensure correct variables are passed

* fix: Add stt and tts routes before upload limiters, prevent bans

* fix(abortRun): temp fix to delete unfinished messages to avoid message thread parent relationship issues

* refactor: Update AnthropicClient to use node-fetch for fetch key and add proxy support

* fix(gptPlugins): ensure parentMessageId/messageId relationship is maintained

* feat(BaseClient): custom fetch function to analyze/edit payloads just before sending (also prevents abortController crash on Bun runtime)

* feat: `directEndpoint` and `titleMessageRole` custom endpoint options

* chore: Bump version to 0.6.6 in data-provider package.json
2024-05-28 14:52:12 -04:00
Yuichi Oneda
0ee060d730 🚑 fix: Prevent Infinite Re-Rendering of the Password Reset UI (#2887)
* 🔧 fix: prevent unnecessary re-rendering of components using useLocalize hook

The useLocalize hook now uses useCallback to create a memoized version of the localize function. This will prevent unnecessary recalculations when the language value changes.

* 🚑 fix: not reset the bodyText if it has a value set.
2024-05-28 14:07:08 -04:00
Danny Avila
5dc5d875ba 🤖 feat: Private Assistants (#2881)
* feat: add configuration for user private assistants

* filter private assistant message requests

* add test for privateAssistants

* add privateAssistants configuration to tests

* fix: destructuring error when assistants config is not added

* chore: revert chat controller changes

* chore: add payload type, add metadata types

* feat: validateAssistant

* refactor(fetchAssistants): allow for flexibility

* feat: validateAuthor

* refactor: return all assistants to ADMIN role

* feat: add assistant doc on assistant creation

* refactor(listAssistants): use `listAllAssistants` to exhaustively fetch all assistants

* chore: add suggestion to tts error

* refactor(validateAuthor): attempt database check first

* refactor: author validation when patching/deleting assistant

---------

Co-authored-by: Leon Juenemann <leon.juenemann@maibornwolff.de>
2024-05-28 08:27:45 -04:00
Yuichi Oneda
9f2538fcd9 ♻️ refactor: Login and Registration component Improvement (#2716)
* ♻️ refactor: Login form improvement

* display error message when API is down
* add loading animation to Login form while fetching data
* optimize startupConfig to fetch data only on initial render to prevent unnecessary API calls

* 🚑 fix: clear authentication error messages on successful login

* ♻️ refactor: componentize duplicate codes on registration and login screens

* chore: update types

* refactor: layout rendering order

* refactor: startup title fix

* refactor: reset/request-reset-password under new AuthLayout

* ci: fix Login.spec.ts

* ci: fix registration.spec.tsx

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-28 08:25:07 -04:00
Danny Avila
2b7a973a33 😎 fix: Azure Bug, short default max_tokens response using gpt-4-vision-preview (#2885) 2024-05-27 22:56:26 -04:00
Danny Avila
c704a23749 ⚛️ fix(atomWithLocalStorage): Handle Parsing Error (#2883) 2024-05-27 21:23:46 -04:00
Danny Avila
eb5733083e 🔈 fix(tts): update min value for playback rate (#2880)
* 🔈 fix: update min value for playback rate in TTS component

* fix: prevent playbackRate from being set if less than or equal to 0
2024-05-27 12:51:45 -04:00
Danny Avila
b80f38e49e 🔢 style: ol Counter Fix (#2867) 2024-05-26 21:13:12 -04:00
Yuichi Oneda
4369e75ca7 🚑 fix: resolve missing data in infinite queries (#2852)
* An issue where the InfiniteQuery was missing data
* Post add/delete operations, inconsistencies between client-side data structures and the database could lead to data being missed or duplicated.
* To address this, implemented normalization of client data following add/delete operations.
* performed refetching of data in the last page when necessary to ensure consistency.
2024-05-24 12:38:38 -04:00
Danny Avila
35ba4ba1a4 🔊 fix(tts): NotAllowedError (mobile/safari), Unsupported MediaSource type (firefox), Hide Audio Element (#2854)
* fix: hide audio element on mobile

* chore: add tts docs link

* fix: select voice option on first render

* fix: NotAllowedError, prevent async playback for mobile triggers, consolidate MessageAudio code, user user-triggered unmutes

* fix: Firefox/unsupported type for MediaSource hack

* refactor(STT): make icon red when recording. consolidate logic to AudioRecorder component

* fix: revert Redis changes to use separate client for sessions
2024-05-24 12:18:11 -04:00
Arthur Barrett
dcd2e3e62d 🔧 fix(redis): Resolve Redis Standalone vs Cluster mode discrepancy for social logins (#2848) 2024-05-24 09:54:33 -04:00
Danny Avila
514a502b9c ⏯️ fix(tts): Resolve Voice Selection and Manual Playback Issues (#2845)
* fix: voice setting for autoplayback TTS

* fix(useTextToSpeechExternal): resolve stateful playback issues and consolidate state logic

* refactor: initialize tts voice and provider schema once per request

* fix(tts): edge case, longer text inputs. TODO: use continuous stream for longer text inputs

* fix(tts): pause global audio on conversation change

* refactor: keyvMongo ban cache to allow db updates for unbanning, to prevent server restart

* chore: eslint fix

* refactor: make ban cache exclusively keyvMongo
2024-05-23 16:27:36 -04:00
Danny Avila
8e66683577 🗣️ fix(tts): Add Text Parser for Message Content Parts (#2840)
* fix: manual TTS trigger for message content parts

* ci(streamAudio): processChunks test
2024-05-22 23:27:37 -04:00
suzuki.sh
dc1778b11f 🐋 chore: add restart: always to meilisearch service in docker-compose.yml (#2788) 2024-05-22 23:20:35 -04:00
nidasfly
795bb9c568 🌏 refactor: Improve Title Prompt for Multilingual Titles (#2832) 2024-05-22 23:18:59 -04:00
gjz
a937650df6 🔧 fix: Recognize azureAssistants Endpoint Config (#2824)
* fix bug: azureAssistants endpoint config

* refactor(assistants): make default value last

* refactor(AppService): make assistantsConfigSetup potentially undefined value last arg

* chore: Update JSDocs params assistants.js

* Update assistants.js

---------

Co-authored-by: 彭修照 <pengxiuzhao.uh@haier.com>
Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-05-22 23:17:52 -04:00
bsu3338
6cf1c85363 🐞 fix: add LocalAI to GET /voices (#2837) 2024-05-22 22:42:27 -04:00
Danny Avila
b3e03b75d0 🔉 feat: Speech-to-text / Text-to-speech (initial support) (#2836)
* Update TextChat.jsx

* Update SubmitButton.jsx

* Update TextChat.jsx

* Update SubmitButton.jsx

* Create ListeningIcon.tsx

* Update index.ts

* Update SubmitButton.jsx

* Update TextChat.jsx

* Update ListeningIcon.tsx

* Update ListeningIcon.tsx

* Create SpeechRecognition.tsx

* Update TextChat.jsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SubmitButton.jsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Create SpeechSynthesis.tsx

* Update index.jsx

* Update SpeechSynthesis.tsx

* Update SpeechRecognition.tsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update TextChat.jsx

* Squashed commit of the following:

commit 28230d9305
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Sun Sep 3 02:44:26 2023 +0200

    feat: delete button confirm (#875)

    * base for confirm delete

    * more like OpenAI

commit 2b54e3f9fe
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Fri Sep 1 14:20:51 2023 -0400

    update: install script (#858)

commit 1cd0fd9d5a
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Fri Sep 1 08:12:35 2023 -0400

    doc: Hugging Face Deployment (#867)

    * docs: update ToC

    * docs: update ToC

    * update huggingface.md

    * update render.md

    * update huggingface.md

    * update mongodb.md

    * update huggingface.md

    * update README.md

commit aeeb3d3050
Author: Mu Yuan <yuanmu.email@gmail.com>
Date:   Thu Aug 31 07:21:27 2023 +0800

    Update Zh.tsx (#862)

    * Update Zh.tsx

    Changed the translation of several words to make it more relevant to Chinese usage habits.

    * Update Zh.tsx

    Changed the translation of several words to make it more relevant to Chinese usage habits

commit 80e2e2675b
Author: Raí <140329135+itzraiss@users.noreply.github.com>
Date:   Mon Aug 28 18:05:46 2023 -0300

    Translation of 'com_ui_pay_per_call:' to Spanish and Portuguese that were missing. (#857)

    * Update Br.tsx

    * Update Es.tsx

    * Update Br.tsx

    * Update Es.tsx

commit 3574d0b823
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 14:49:26 2023 -0400

    docs: make_your_own.md formatting fix for mkdocs (#855)

commit d672ac690d
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 14:24:10 2023 -0400

    Release v0.5.8 (#854)

    * chore: add 'api' image to tag release workflow

    * docs: update DO deployment docs to include instruction about latest stable release, as well as security best practices

    * Release v0.5.8

    * docs: Update digitalocean.md with firewall section images

    * docs: make_your_own.md formatting fix for mkdocs

commit d3e7627046
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 12:03:08 2023 -0400

    refactor(plugins): Improve OpenAPI handling, Show Multiple Plugins, & Other Improvements (#845)

    * feat(PluginsClient.js): add conversationId to options object in the constructor
    feat(PluginsClient.js): add support for Code Interpreter plugin
    feat(PluginsClient.js): add support for Code Interpreter plugin in the availableTools manifest
    feat(CodeInterpreter.js): add CodeInterpreterTools module
    feat(CodeInterpreter.js): add RunCommand class
    feat(CodeInterpreter.js): add ReadFile class
    feat(CodeInterpreter.js): add WriteFile class
    feat(handleTools.js): add support for loading Code Interpreter plugin

    * chore(api): update langchain dependency to version 0.0.123

    * fix(CodeInterpreter.js): add support for extracting environment from code
    fix(WriteFile.js): add support for extracting environment from data
    fix(extractionChain.js): add utility functions for creating extraction chain from Zod schema
    fix(handleTools.js): refactor getOpenAIKey function to handle user-provided API key
    fix(handleTools.js): pass model and openAIApiKey to CodeInterpreter constructor

    * fix(tools): rename CodeInterpreterTools to E2BTools
    fix(tools): rename code_interpreter pluginKey to e2b_code_interpreter

    * chore(PluginsClient.js): comment out unused import and function findMessageContent
    feat(PluginsClient.js): add support for CodeSherpa plugin
    feat(PluginsClient.js): add CodeSherpaTools to available tools
    feat(PluginsClient.js): update manifest.json to include CodeSherpa plugin
    feat(CodeSherpaTools.js): create RunCode and RunCommand classes for CodeSherpa plugin

    feat(E2BTools.js): Add E2BTools module for extracting environment from code and running commands, reading and writing files
    fix(codesherpa.js): Remove codesherpa module as it is no longer needed

    feat(handleTools.js): add support for CodeSherpaTools in loadTools function
    feat(loadToolSuite.js): create loadToolSuite utility function to load a suite of tools

    * feat(PluginsClient.js): add support for CodeSherpa v2 plugin
    feat(PluginsClient.js): add CodeSherpa v1 plugin to available tools
    feat(PluginsClient.js): add CodeSherpa v2 plugin to available tools
    feat(PluginsClient.js): update manifest.json for CodeSherpa v1 plugin
    feat(PluginsClient.js): update manifest.json for CodeSherpa v2 plugin
    feat(CodeSherpa.js): implement CodeSherpa plugin for interactive code and shell command execution
    feat(CodeSherpaTools.js): implement RunCode and RunCommand plugins for CodeSherpa v1
    feat(CodeSherpaTools.js): update RunCode and RunCommand plugins for CodeSherpa v2

    fix(handleTools.js): add CodeSherpa import statement
    fix(handleTools.js): change pluginKey from 'codesherpa' to 'codesherpa_tools'
    fix(handleTools.js): remove model and openAIApiKey from options object in e2b_code_interpreter tool
    fix(handleTools.js): remove openAIApiKey from options object in codesherpa_tools tool
    fix(loadToolSuite.js): remove model and openAIApiKey parameters from loadToolSuite function

    * feat(initializeFunctionsAgent.js): add prefix to agentArgs in initializeFunctionsAgent function

    The prefix is added to the agentArgs in the initializeFunctionsAgent function. This prefix is used to provide instructions to the agent when it receives any instructions from a webpage, plugin, or other tool. The agent will notify the user immediately and ask them if they wish to carry out or ignore the instructions.

    * feat(PluginsClient.js): add ChatTool to the list of tools if it meets the conditions
    feat(tools/index.js): import and export ChatTool
    feat(ChatTool.js): create ChatTool class with necessary properties and methods

    * fix(initializeFunctionsAgent.js): update PREFIX message to include sharing all output from the tool
    fix(E2BTools.js): update descriptions for RunCommand, ReadFile, and WriteFile plugins to provide more clarity and context

    * chore: rebuild package-lock after rebase

    * chore: remove deleted file from rebase

    * wip: refactor plugin message handling to mirror chat.openai.com, handle incoming stream for plugin use

    * wip: new plugin handling

    * wip: show multiple plugins handling

    * feat(plugins): save new plugins array

    * chore: bump langchain

    * feat(experimental): support streaming in between plugins

    * refactor(PluginsClient): factor out helper methods to avoid bloating the class, refactor(gptPlugins): use agent action for mapping the name of action

    * fix(handleTools): fix tests by adding condition to return original toolFunctions map

    * refactor(MessageContent): Allow the last index to be last in case it has text (may change with streaming)

    * feat(Plugins): add handleParsingErrors, useful when LLM does not invoke function params

    * chore: edit out experimental codesherpa integration

    * refactor(OpenAPIPlugin): rework tool to be 'function-first', as the spec functions are explicitly passed to agent model

    * refactor(initializeFunctionsAgent): improve error handling and system message

    * refactor(CodeSherpa, Wolfram): optimize token usage by delegating bulk of instructions to system message

    * style(Plugins): match official style with input/outputs

    * chore: remove unnecessary console logs used for testing

    * fix(abortMiddleware): render markdown when message is aborted

    * feat(plugins): add BrowserOp

    * refactor(OpenAPIPlugin): improve prompt handling

    * fix(useGenerations): hide edit button when message is submitting/streaming

    * refactor(loadSpecs): optimize OpenAPI spec loading by only loading requested specs instead of all of them

    * fix(loadSpecs): will retain original behavior when no tools are passed to the function

    * fix(MessageContent): ensure cursor only shows up for last message and last display index
    fix(Message): show legacy plugin and pass isLast to Content

    * chore: remove console.logs

    * docs: update docs based on breaking changes and new features
    refactor(structured/SD): use description_for_model for detailed prompting

    * docs(azure): make plugins section more clear

    * refactor(structured/SD): change default payload to SD-WebUI to prefer realism and config for SDXL

    * refactor(structured/SD): further improve system message prompt

    * docs: update breaking changes after rebase

    * refactor(MessageContent): factor out EditMessage, types, Container to separate files, rename Content -> Markdown

    * fix(CodeInterpreter): linting errors

    * chore: reduce browser console logs from message streams

    * chore: re-enable debug logs for plugins/langchain to help with user troubleshooting

    * chore(manifest.json): add [Experimental] tag to CodeInterpreter plugins, which are not intended as the end-all be-all implementation of this feature for Librechat

commit 66b8580487
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Mon Aug 28 09:18:25 2023 -0400

    docs: third-party tools (#848)

    * docs: third-party tools

    * docs: third-party tools

    * Update third-party.md

    * Update third-party.md

    ---------

    Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>

commit 9791a78161
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Mon Aug 28 15:14:05 2023 +0200

    adjust the animation (#843)

commit 3797ec6082
Author: Ronith <87087292+ronith256@users.noreply.github.com>
Date:   Mon Aug 28 18:43:50 2023 +0530

    feat: Add Code Interpreter Plugin (#837)

    * feat: Add Code Interpreter Plugin

    Adds a Simple Code Interpreter Plugin.
    ## Features:
    - Runs code using local Python Environment

    ## Issues
    - Code execution is not sandboxed.

    * Add Docker Sandbox for Python Server

commit e2397076a2
Author: Alex Zhang <ztc2011@gmail.com>
Date:   Mon Aug 28 00:55:34 2023 +0800

    🌐: Chinese Translation (#846)

commit 50c15c704f
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Sat Aug 26 19:36:59 2023 -0400

    Language translation: Polish (#840)

    * Language translation: Polish

    * Language translation: Polish

    * Revert changes in language-contributions.md

commit 29d3640546
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Sat Aug 26 19:36:25 2023 -0400

    docs: updates (#841)

commit 39c626aa8e
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 25 09:29:19 2023 -0400

    fix: isEdited edge case where latest Message is not saved due to aborting too quickly

commit ae5c06f381
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 25 09:13:50 2023 -0400

    fix(chatGPTBrowser): render markdown formatting by setting isCreatedByUser, fix(useMessageHandler): avoid double appearance of cursor by setting latest message at initial response creation time

commit 9ef1686e18
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Thu Aug 24 20:24:47 2023 -0400

    Update mkdocs.yml

commit 5bbe411569
Author: Flynn <dev@flynnbuckingham.com>
Date:   Thu Aug 24 20:20:37 2023 -0400

    Add podman installation instructions. Update dockerfile to stub env (#819)

    * Added podman container installation docs. Updated dockerfile to stub env file if not present in source

    * Fix typos

commit 887fec99ca
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 25 02:11:27 2023 +0200

    🌐: Russian Translation (#830)

commit 007d51ede1
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 25 02:10:48 2023 +0200

    feat: facebook login (#820)

    * Facebook strategy

    * Update user_auth_system.md

    * Update user_auth_system.md

commit a569020312
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Thu Aug 24 21:59:11 2023 +0200

    Fix Meilisearch error and refactor of the server index.js (#832)

    * fix meilisearch error at startup

    * limit the nesting

    * disable useless console log

    * fix(indexSync.js): removed redundant searchEnabled

    * refactor(index.js): moved configureSocialLogins to a new file

    * refactor(socialLogins.js): removed unnecessary conditional

commit 37347d4683
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Wed Aug 23 16:14:17 2023 -0400

    fix(registration): Make Username optional (#831)

    * fix(User.js): update validation schema for username field, allow empty string as a valid value
    fix(validators.js): update validation schema for username field, allow empty string as a valid value
    fix(Registration.tsx, validators.js): update validation rules for name and username fields, change minimum length to 2 and maximum length to 80, assure they match and allow empty string as a valid value
    fix(Eng.tsx): update localization string for com_auth_username, indicate that it is optional

    * fix(User.js): update regex pattern for username validation to allow special characters @#$%&*()
    fix(validators.js): update regex pattern for username validation to allow special characters @#$%&*()

    * fix(Registration.spec.tsx): fix validation error message for username length requirement

commit d38e463d34
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Wed Aug 23 13:44:40 2023 -0400

    fix(bingAI): markdown and error formatting for final stream response (#829)

    * fix(bingAI): markdown formatting for final stream response due to new strict payload validation on the frontend

    * fix: add missing prop to bing Error response

commit 7dc27b10f1
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Tue Aug 22 18:44:59 2023 -0400

    feat: Edit AI Messages, Edit Messages in Place (#825)

    * refactor: replace lodash import with specific function import

    fix(api): esm imports to cjs

    * refactor(Messages.tsx): convert to TS, out-source scrollToDiv logic to a custom hook
    fix(ScreenshotContext.tsx): change Ref to RefObject in ScreenshotContextType
    feat(useScrollToRef.ts): add useScrollToRef hook for scrolling to a ref with throttle
    fix(Chat.tsx): update import path for Messages component
    fix(Search.tsx): update import path for Messages component

    * chore(types.ts): add TAskProps and TOptions types
    refactor(useMessageHandler.ts): use TAskFunction type for ask function signature

    * refactor(Message/Content): convert to TS, move Plugin component to Content dir

    * feat(MessageContent.tsx): add MessageContent component for displaying and editing message content
    feat(index.ts): export MessageContent component from Messages/Content directory

    * wip(Message.jsx): conversion and use of new component in progress

    * refactor: convert Message.jsx to TS and fix typing/imports based on changes

    * refactor: add typed props and refactor MultiMessage to TS, fix typing issues resulting from the conversion

    * edit message in progress

    * feat: complete edit AI message logic, refactor continue logic

    * feat(middleware): add validateMessageReq middleware
    feat(routes): add validation for message requests using validateMessageReq middleware
    feat(routes): add create, read, update, and delete routes for messages

    * feat: complete frontend logic for editing messages in place
    feat(messages.js): update route for updating a specific message
    - Change the route for updating a message to include the messageId in the URL
    - Update the request handler to use the messageId from the request parameters and the text from the request body
    - Call the updateMessage function with the updated parameters

    feat(MessageContent.tsx): add functionality to update a message
    - Import the useUpdateMessageMutation hook from the data provider
    - Destructure the conversationId, parentMessageId, and messageId from the message object
    - Create a mutation function using the useUpdateMessageMutation hook
    - Implement the updateMessage function to call the mutation function with the updated message parameters
    - Update the messages state to reflect the updated message text

    feat(api-endpoints.ts): update messages endpoint to include messageId
    - Update the messages endpoint to include the messageId as an optional parameter

    feat(data-service.ts): add updateMessage function
    - Implement the updateMessage function to make a PUT request to

    * fix(messages.js): make updateMessage function asynchronous and await its execution

    * style(EditIcon): make icon active for AI message

    * feat(gptPlugins/anthropic): add edit support

    * fix(validateMessageReq.js): handle case when conversationId is 'new' and return empty array
    feat(Message.tsx): pass message prop to SiblingSwitch component
    refactor(SiblingSwitch.tsx): convert to TS

    * fix(useMessageHandler.ts): remove message from currentMessages if isContinued is true
    feat(useMessageHandler.ts): add support for submission messages in setMessages
    fix(useServerStream.ts): remove unnecessary conditional in setMessages
    fix(useServerStream.ts): remove isContinued variable from submission

    * fix(continue): switch to continued message generation when continuing an earlier branch in conversation

    * fix(abortMiddleware.js): fix condition to check partialText length
    chore(abortMiddleware.js): add error logging when abortMessage fails

    * refactor(MessageHeader.tsx): convert to TS
    fix(Plugin.tsx): add default value for className prop in Plugin component

    * refactor(MultiMessage.tsx): remove commented out code
    docs(MultiMessage.tsx): update comment to clarify when siblingIdx is reset

    * fix(GenerationButtons): optimistic state for continue button

    * fix(MessageContent.tsx): add data-testid attribute to message text editor
    fix(messages.spec.ts): update waitForServerStream function to include edit endpoint check
    feat(messages.spec.ts): add test case for editing messages

    * fix(HoverButtons & Message & useGenerations): Refactor edit functionality and related conditions

    - Update enterEdit function signature and prop
    - Create and utilize hideEditButton variable
    - Enhance conditions for edit button visibility and active state
    - Update button event handlers
    - Introduce isEditableEndpoint in useGenerations and refine continueSupported condition.

    * fix(useGenerations.ts): fix condition for hideEditButton to include error and searchResult
    chore(data-provider): bump version to 0.1.6
    fix(types.ts): add status property to TError type

    * chore: bump @dqbd/tiktoken to 1.0.7

    * fix(abortMiddleware.js): add required isCreatedByUser property to the error response object

    * refactor(Message.tsx): remove unnecessary props from SiblingSwitch component, as setLatestMessage is firing on every switch already
    refactor(SiblingSwitch.tsx): remove unused imports and code

    * chore(BaseClient.js): move console.debug statements back inside if block

commit db77163f5d
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Tue Aug 22 14:15:14 2023 +0200

    docs: update chimeragpt (#826)

    * Update free_ai_apis.md

    * Update free_ai_apis.md

commit 4a4e803df3
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Mon Aug 21 20:15:18 2023 +0200

    style(Dialog): Improved Close Button ("X") position (#824)

commit 909b00c752
Author: Daniel Avila <messagedaniel@protonmail.com>
Date:   Sun Aug 20 21:04:36 2023 -0400

    fix(HoverButtons): light/dark styling to match official site

commit 61dcb4d307
Author: Naosuke Yokoe <ankerasoy@gmail.com>
Date:   Sat Aug 19 20:11:31 2023 +0900

    feat: Azure Cognitive Search Plugin (#815)

    * feat(AzureCognitiveSearchPlugin)

    * feat(tools/AzureCognitiveSearch.js): Add a new plugin (not structured
      version)
    * feat(tools/structured/AzureCognitiveSearch.js): Add a new plugin (structured version)
    * feat(tools/manifest.json, tools/index.js, tools/util/handleTools.js):
      Add configurations for the plugin
    * feat(api/package.json, package-lock.json): Installed a new package for the
      plugin (@azure/search-documents)
    * feat(.env.example): Add new environment variables for the plugin

    Here is the link to the corresponding discussion page:
    https://github.com/danny-avila/LibreChat/discussions/567

    * docs(AzureCognitiveSearchPlugin)

    * docs(features/plugins/azure_cognitive_search.md): Add a new document
      for the plugin

    * (fix:.env.example)

    * reverted extra whitespaces removed by the editor

    * docs(mkdocs.yml)

    * Add the Azure Cognitive Search Plugin's documentation item to
    mkdocs.yml.

commit 3c7f67fa76
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 18 12:40:33 2023 -0400

    fix(abortMiddleware): handle early abort error where userMessage.conversationId is undefined. In this case, the userId will be used as the abortKey

commit c74c68a135
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 18 12:10:30 2023 -0400

    refactor(MessageHandler -> useServerStream): convert all relating files to TS and correct typings based on this change: properly refactor MessageHandler to a custom hook, where it's passed a submission object to instantiate the stream. This is the bare minimum groundwork for potentially having multiple streams running, which would be a big project to modularize a lot of the global state into maps/multiple streams, particular useful for having multiple views in place

commit 8b4d3c2c21
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 18 12:04:29 2023 -0400

    refactor(routes): convert to TS

commit d612cfcb45
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 18 12:02:39 2023 -0400

    chore(Auth): reorder exports in Auth component
    fix(PluginAuthForm): handle case when pluginKey is null or undefined
    fix(PluginStoreDialog): handle case when getAvailablePluginFromKey is null or undefined
    fix(AuthContext): make authConfig optional in AuthContextProvider
    feat(hooks): add useServerStream hook
    fix(conversation): setSubmission to null instead of empty object
    fix(preset): specify type for presets atom
    fix(search): specify type for isSearchEnabled atom
    fix(submission): specify type for submission atom

commit c40b95f424
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 18 16:11:00 2023 +0200

    feat: Disable Registration with social login (#813)

    * Google, Github and Discord

    * update .env.example with ALLOW_SOCIAL_REGISTRATION

    * fix some conflict

    * refactor strategy

    * Update user_auth_system.md

    * Update user_auth_system.md

commit 46ed5aaccd
Author: Patrick <psarnowski@gmail.com>
Date:   Fri Aug 18 09:38:24 2023 -0400

    Show the response scores from Bing. (#814)

commit 1dacfa49f0
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Thu Aug 17 20:32:31 2023 +0200

    update profile picture (#792)

commit afd43afb60
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Thu Aug 17 12:50:05 2023 -0400

    feat(GPT/Anthropic): Continue Regenerating & Generation Buttons (#808)

    * feat(useMessageHandler.js/ts): Refactor and add features to handle user messages, support multiple endpoints/models, generate placeholder responses, regeneration, and stopGeneration function

    fix(conversation.ts, buildTree.ts): Import TMessage type, handle null parentMessageId

    feat(schemas.ts): Update and add schemas for various AI services, add default values, optional fields, and endpoint-to-schema mapping, create parseConvo function

    chore(useMessageHandler.js, schemas.ts): Remove unused imports, variables, and chatGPT enum

    * wip: add generation buttons

    * refactor(cleanupPreset.ts): simplify cleanupPreset function
    refactor(getDefaultConversation.js): remove unused code and simplify getDefaultConversation function

    feat(utils): add getDefaultConversation function

    This commit adds a new utility function called `getDefaultConversation` to the `client/src/utils/getDefaultConversation.ts` file. This function is responsible for generating a default conversation object based on the provided parameters.

    The `getDefaultConversation` function takes in an object with the following properties:
    - `conversation`: The conversation object to be used as a base.
    - `endpointsConfig`: The configuration object containing information about the available endpoints.
    - `preset`: An optional preset object that can be used to override the default behavior.

    The function first tries to determine the target endpoint based on the preset object. If a valid endpoint is found, it is used as the target endpoint. If not, the function tries to retrieve the last conversation setup from the local storage and uses its endpoint if it is valid. If neither the preset nor the local storage contains a valid endpoint, the function falls back to a default endpoint.

    Once the target endpoint is determined,

    * fix(utils): remove console.error statement in buildDefaultConversation function
    fix(schemas): add default values for catch blocks in openAISchema, googleSchema, bingAISchema, anthropicSchema, chatGPTBrowserSchema, and gptPluginsSchema

    * fix: endpoint not changing on change of preset from other endpoint, wip: refactor

    * refactor: preset items to TSX

    * refactor: convert resetConvo to TS

    * refactor(getDefaultConversation.ts): move defaultEndpoints array to the top of the file for better readability
    refactor(getDefaultConversation.ts): extract getDefaultEndpoint function for better code organization and reusability

    * feat(svg): add ContinueIcon component
    feat(svg): add RegenerateIcon component
    feat(svg): add ContinueIcon and RegenerateIcon components to index.ts

    * feat(Button.tsx): add onClick and className props to Button component
    feat(GenerationButtons.tsx): add logic to display Regenerate or StopGenerating button based on isSubmitting and messages
    feat(Regenerate.tsx): create Regenerate component with RegenerateIcon and handleRegenerate function
    feat(StopGenerating.tsx): create StopGenerating component with StopGeneratingIcon and handleStopGenerating function

    * fix(TextChat.jsx): reorder imports and variables for better readability
    fix(TextChat.jsx): fix typo in condition for isNotAppendable variable
    fix(TextChat.jsx): remove unused handleStopGenerating function
    fix(ContinueIcon.tsx): remove unnecessary closing tags for polygon elements
    fix(useMessageHandler.ts): add missing type annotations for handleStopGenerating and handleRegenerate functions
    fix(useMessageHandler.ts): remove unused variables in return statement

    * fix(getDefaultConversation.ts): refactor code to use getLocalStorageItems function
    feat(getLocalStorageItems.ts): add utility function to retrieve items from local storage

    * fix(OpenAIClient.js): add support for streaming result in sendCompletion method
    feat(OpenAIClient.js): add finish_reason metadata to opts in sendCompletion method
    feat(Message.js): add finish_reason field to Message model
    feat(messageSchema.js): add finish_reason field to messageSchema
    feat(openAI.js): parse chatGptLabel and promptPrefix from req.body and pass rest of the modelOptions to endpointOption
    feat(openAI.js): add addMetadata function to store metadata in ask function
    feat(openAI.js): add metadata to response if available
    feat(schemas.ts): add finish_reason field to tMessageSchema

    * feat(types.ts): add TOnClick and TGenButtonProps types for button components
    feat(Continue.tsx): create Continue component for generating button
    feat(GenerationButtons.tsx): update GenerationButtons component to use Continue component
    feat(Regenerate.tsx): create Regenerate component for regenerating button
    feat(Stop.tsx): create Stop component for stop generating button

    * feat(MessageHandler.jsx): add MessageHandler component to handle messages and conversations
    fix(Root.jsx): fix import paths for Nav and MessageHandler components

    * feat(useMessageHandler.ts): add support for generation parameter in ask function
    feat(useMessageHandler.ts): add support for isEdited parameter in ask function
    feat(useMessageHandler.ts): add support for continueGeneration function
    fix(createPayload.ts): replace endpoint URL when isEdited parameter is true

    * chore(client): set skipLibCheck to true in tsconfig.json

    * fix(useMessageHandler.ts): remove unused clientId variable
    fix(schemas.ts): make clientId field in tMessageSchema nullable and optional

    * wip: edit route for continue generation

    * refactor(api): move handlers to root of routes dir

    * fix(useMessageHandler.ts): initialize currentMessages to an empty array if messages is null
    fix(useMessageHandler.ts): update initialResponse text to use responseText variable
    fix(useMessageHandler.ts): update setMessages logic for isRegenerate case
    fix(MessageHandler.jsx): update setMessages logic for cancelHandler, createdHandler, and finalHandler

    * fix(schemas.ts): make createdAt and updatedAt fields optional and set default values using new Date().toISOString()
    fix(schemas.ts): change type annotation of TMessage from infer to input

    * refactor(useMessageHandler.ts): rename AskProps type to TAskProps
    refactor(useMessageHandler.ts): remove generation property from ask function arguments
    refactor(useMessageHandler.ts): use nullish coalescing operator (??) instead of logical OR (||)
    refactor(useMessageHandler.ts): pass the responseMessageId to message prop of submission

    * fix(BaseClient.js): use nullish coalescing operator (??) instead of logical OR (||) for default values

    * fix(BaseClient.js): fix responseMessageId assignment in handleStartMethods method
    feat(BaseClient.js): add support for isEdited flag in sendMessage method
    feat(BaseClient.js): add generation to responseMessage text in sendMessage method

    * fix(openAI.js): remove unused imports and commented out code
    feat(openAI.js): add support for generation parameter in request body
    fix(openAI.js): remove console.log statement
    fix(openAI.js): remove unused variables and parameters
    fix(openAI.js): update response text in case of error
    fix(openAI.js): handle error and abort message in case of error
    fix(handlers.js): add generation parameter to createOnProgress function
    fix(useMessageHandler.ts): update responseText variable to use generation parameter

    * refactor(api/middleware): move inside server dir

    * refactor: add endpoint specific, modular functions to build options and initialize clients, create server/utils, move middleware, separate utils into api general utils and server specific utils

    * fix(abortMiddleware.js): import getConvo and getConvoTitle functions from models
    feat(abortMiddleware.js): add abortAsk function to abortController to handle aborting of requests
    fix(openAI.js): import buildOptions and initializeClient functions from endpoints/openAI
    refactor(openAI.js): use getAbortData function to get data for abortAsk function

    * refactor: move endpoint specific logic to an endpoints dir

    * refactor(PluginService.js): fix import path for encrypt and decrypt functions in PluginService.js

    * feat(openAI): add new endpoint for adding a title to a conversation

    - Added a new file `addTitle.js` in the `api/server/routes/endpoints/openAI` directory.
    - The `addTitle.js` file exports a function `addTitle` that takes in request parameters and performs the following actions:
      - If the `parentMessageId` is `'00000000-0000-0000-0000-000000000000'` and `newConvo` is true, it proceeds with the following steps:
        - Calls the `titleConvo` function from the `titleConvo` module, passing in the necessary parameters.
        - Calls the `saveConvo` function from the `saveConvo` module, passing in the user ID and conversation details.
    - Updated the `index.js` file in the `api/server/routes/endpoints/openAI` directory to export the `addTitle` function.
    - This change adds

    * fix(abortMiddleware.js): remove console.log statement
    refactor(gptPlugins.js): update imports and function parameters
    feat(gptPlugins.js): add support for abortController and getAbortData
    refactor(openAI.js): update imports and function parameters
    feat(openAI.js): add support for abortController and getAbortData

    fix(openAI.js): refactor code to use modularized functions and middleware
    fix(buildOptions.js): refactor code to use destructuring and update variable names

    * refactor(askChatGPTBrowser.js, bingAI.js, google.js): remove duplicate code for setting response headers
    feat(askChatGPTBrowser.js, bingAI.js, google.js): add setHeaders middleware to set response headers

    * feat(middleware): validateEndpoint, refactor buildOption to only be concerned of endpointOption

    * fix(abortMiddleware.js): add 'finish_reason' property with value 'incomplete' to responseMessage object
    fix(abortMessage.js): remove console.log statement for aborted message
    fix(handlers.js): modify tokens assignment to handle empty generation string and trailing space

    * fix(BaseClient.js): import addSpaceIfNeeded function from server/utils
    fix(BaseClient.js): add space before generation in text property
    fix(index.js): remove getCitations and citeText exports
    feat(buildEndpointOption.js): add buildEndpointOption middleware
    fix(index.js): import buildEndpointOption middleware
    fix(anthropic.js): remove buildOptions function and use endpointOption from req.body
    fix(gptPlugins.js): remove buildOptions function and use endpointOption from req.body
    fix(openAI.js): remove buildOptions function and use endpointOption from req.body

    feat(utils): add citations.js and handleText.js modules
    fix(utils): fix import statements in index.js module

    * refactor(gptPlugins.js): use getResponseSender function from librechat-data-provider

    * feat(gptPlugins): complete 'continue generating'

    * wip: anthropic continue regen

    * feat(middleware): add validateRegistration middleware

    A new middleware function called `validateRegistration` has been added to the list of exported middleware functions in `index.js`. This middleware is responsible for validating registration data before allowing the registration process to proceed.

    * feat(Anthropic): complete continue regen

    * chore: add librechat-data-provider to api/package.json

    * fix(ci): backend-review will mock meilisearch, also installs data-provider as now needed

    * chore(ci): remove unneeded SEARCH env var

    * style(GenerationButtons): make text shorter for sake of space economy, even though this diverges from chat.openai.com

    * style(GenerationButtons/ScrollToBottom): adjust visibility/position based on screen size

    * chore(client): 'Editting' typo

    * feat(GenerationButtons.tsx): add support for endpoint prop in GenerationButtons component
    feat(OptionsBar.tsx): pass endpoint prop to GenerationButtons component
    feat(useGenerations.ts): create useGenerations hook to handle generation logic
    fix(schemas.ts): add searchResult field to tMessageSchema

    * refactor(HoverButtons): convert to TSX and utilize new useGenerations hook

    * fix(abortMiddleware): handle error with res headers set, or abortController not found, to ensure proper API error is sent to the client, chore(BaseClient): remove console log for onStart message meant for debugging

    * refactor(api): remove librechat-data-provider dep for now as it complicates deployed docker build stage, re-use code in CJS, located in server/endpoints/schemas

    * chore: remove console.logs from test files

    * ci: add backend tests for AnthropicClient, focusing on new buildMessages logic

    * refactor(FakeClient): use actual BaseClient sendMessage method for testing

    * test(BaseClient.test.js): add test for loading chat history
    test(BaseClient.test.js): add test for sendMessage logic with isEdited flag

    * fix(buildEndpointOption.js): add support for azureOpenAI in buildFunction object
    wip(endpoints.js): fetch Azure models from Azure OpenAI API if opts.azure is true

    * fix(Button.tsx): add data-testid attribute to button component
    fix(SelectDropDown.tsx): add data-testid attribute to Listbox.Button component
    fix(messages.spec.ts): add waitForServerStream function to consolidate logic for awaiting the server response
    feat(messages.spec.ts): add test for stopping and continuing message and improve browser/page context order and closing

    * refactor(onProgress): speed up time to save initial message for editable routes

    * chore: disable AI message editing (for now), was accidentally allowed

    * refactor: ensure continue is only supported for latest message style: improve styling in dark mode and across all hover buttons/icons, including making edit icon for AI invisible (for now)

    * fix: add test id to generation buttons so they never resolve to 2+ items

    * chore(package.json): add 'packages/' to the list of ignored directories
    chore(data-provider/package.json): bump version to 0.1.5

commit ae5b7d3d53
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Tue Aug 15 18:27:54 2023 -0400

    fix(PluginsClient.js): fix ChatOpenAI Azure Config Issue (#812)

    * fix(PluginsClient.js): fix issue with creating LLM when using Azure

    * chore(PluginsClient.js): omit azure logging

    * refactor(PluginsClient.js): simplify assignment of azure variable

    The code was simplified by directly assigning the value of `this.azure` to the `azure` variable using object destructuring. This makes the code cleaner and more concise.

commit b85f3bf91e
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Tue Aug 15 18:42:24 2023 +0200

    update from lang to localize (#810)

commit 80aab73bf6
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Mon Aug 14 19:19:04 2023 -0400

    chore: rebuilt package-lock file

commit bbe4931a97
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Mon Aug 14 19:13:24 2023 -0400

    refactor(ScreenshotContext): use html-to-image for lighter bundle, faster processing

commit 74802dd720
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Mon Aug 14 17:51:03 2023 +0200

    chore: Translation Fixes, Lint Error Corrections, and Additional Translations (#788)

    * fix translation and small lint error

    * changed from localize to useLocalize hook

    * changed to useLocalize

commit b64cc71d88
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 14 10:23:00 2023 -0400

    chore(docker-compose.yml): comment out meilisearch ports in docker-compose.yml (#807)

commit 89f260bc78
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 14 10:12:00 2023 -0400

    fix(CodeBlock.tsx): fix copy-to-clipboard functionality. The code has been updated to use the copy function from the copy-to-clipboard library instead of the (#806)

    avigator.clipboard.writeText method. This should fix the issue with browser incompatibility with navigator SDK and allow users to copy code from the CodeBlock component successfully.

commit d00c7354cd
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 14 09:45:44 2023 -0400

    fix: Corrected Registration Validation, Case-Insensitive Variable Handling, Playwright workflow (#805)

    * feat(auth.js): add validation for registration endpoint using validateRegistration middleware
    feat(validateRegistration.js): add middleware to validate registration based on ALLOW_REGISTRATION environment variable

    * fix(config.js): fix registrationEnabled and socialLoginEnabled variables to handle case-insensitive environment variable values

    * refactor(validateRegistration.js): remove console.log statement

    * chore(playwright.yml): skip browser download during yarn install
    chore(playwright.yml): place Playwright binaries to node_modules/@playwright/test
    chore(playwright.yml): install Playwright dependencies using npx playwright install-deps
    chore(playwright.yml): install Playwright chromium browser using npx playwright install chromium
    chore(playwright.yml): install @playwright/test@latest using npm install -D @playwright/test@latest
    chore(playwright.yml): run Playwright tests using npm run e2e:ci

    * chore(playwright.yml): change npm install order and update comment

    The order of the npm install commands in the "Install Playwright Browsers" step has been changed to first install @playwright/test@latest and then install chromium. Additionally, the comment explaining the PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD variable has been updated to mention npm install instead of yarn install.

    * chore(playwright.yml): remove commented out code for caching and add separate steps for installing Playwright dependencies and browsers

commit 1aa4b34dc6
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 11 19:02:52 2023 +0200

    added the dot (.) username rules (#787)

* Create VolumeMuteIcon.tsx

* Create VolumeIcon.tsx

* Update index.ts

* Update SubmitButton.jsx

* Update SubmitButton.jsx

* Update TextChat.jsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update TextChat.jsx

* Update SpeechRecognition.tsx

* Update TextChat.jsx

* Update HoverButtons.tsx

* Update useServerStream.ts

* Update useServerStream.ts

* Update HoverButtons.tsx

* Update useServerStream.ts

* Update useServerStream.ts

* Update HoverButtons.tsx

* Update VolumeIcon.tsx

* Update VolumeMuteIcon.tsx

* Update HoverButtons.tsx

* Update SpeechSynthesis.tsx

* Update HoverButtons.tsx

* Update HoverButtons.tsx

* Update SpeechSynthesis.tsx

* Update SpeechSynthesis.tsx

* Update HoverButtons.tsx

* Update SpeechSynthesis.tsx

* Update package.json

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Update SpeechRecognition.tsx

* Squashed commit of the following:

commit 1019529634
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 23:12:14 2023 -0500

    Update SpeechRecognition.tsx

commit 67f111ccd0
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 23:08:48 2023 -0500

    Update SpeechRecognition.tsx

commit 0b35dbe196
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 23:04:50 2023 -0500

    Update SpeechRecognition.tsx

commit 6686126dc0
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:49:08 2023 -0500

    Update SpeechRecognition.tsx

commit 5b80ddfba7
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:45:02 2023 -0500

    Update package.json

commit 39e84efa81
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:35:48 2023 -0500

    Update SpeechSynthesis.tsx

commit 4c6d067cb9
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:24:29 2023 -0500

    Update HoverButtons.tsx

commit c5ce576fb8
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:13:20 2023 -0500

    Update SpeechSynthesis.tsx

commit d95fa19539
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:11:38 2023 -0500

    Update SpeechSynthesis.tsx

commit c794f07678
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 22:03:34 2023 -0500

    Update HoverButtons.tsx

commit 7ae0e7e97c
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:59:45 2023 -0500

    Update HoverButtons.tsx

commit e9882dedad
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:58:07 2023 -0500

    Update SpeechSynthesis.tsx

commit 95cf300782
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:44:49 2023 -0500

    Update HoverButtons.tsx

commit 37c828d7fb
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:30:34 2023 -0500

    Update VolumeMuteIcon.tsx

commit 6133531737
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:29:54 2023 -0500

    Update VolumeIcon.tsx

commit 4b4afcdd37
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 21:20:14 2023 -0500

    Update HoverButtons.tsx

commit 609d1dfefb
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 20:49:52 2023 -0500

    Update useServerStream.ts

commit 875ce4b77e
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 20:48:26 2023 -0500

    Update useServerStream.ts

commit 8ed04e496b
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 20:37:59 2023 -0500

    Update HoverButtons.tsx

commit 4b30c132df
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 20:14:01 2023 -0500

    Update useServerStream.ts

commit c041c329cf
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 20:07:14 2023 -0500

    Update useServerStream.ts

commit 3e36c16817
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:36:21 2023 -0500

    Update HoverButtons.tsx

commit c7eea96759
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:28:03 2023 -0500

    Update TextChat.jsx

commit 5542f8e85d
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:21:50 2023 -0500

    Update SpeechRecognition.tsx

commit 9a27e56f8b
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:16:01 2023 -0500

    Update TextChat.jsx

commit 7f101bd122
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:09:51 2023 -0500

    Update SpeechRecognition.tsx

commit d405454bf5
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:03:34 2023 -0500

    Update SpeechRecognition.tsx

commit 6033eb3ed1
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 19:01:06 2023 -0500

    Update TextChat.jsx

commit 9a3e67fcd2
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 18:53:19 2023 -0500

    Update TextChat.jsx

commit 6583877cb3
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 17:53:18 2023 -0500

    Update SubmitButton.jsx

commit 8d5114bfae
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 17:39:20 2023 -0500

    Update SubmitButton.jsx

commit 29a5b55883
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 17:28:03 2023 -0500

    Update index.ts

commit b03001d01d
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 17:25:43 2023 -0500

    Create VolumeIcon.tsx

commit 863af2c959
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 17:21:43 2023 -0500

    Create VolumeMuteIcon.tsx

commit ad3c78f867
Merge: ed4b25b2 28230d93
Author: bsu3338 <bsu3338@users.noreply.github.com>
Date:   Sun Sep 3 16:49:56 2023 -0500

    Merge branch 'danny-avila:main' into Speech-September

commit ed4b25b2c1
Author: bsu3338 <bsu3338@yahoo.com>
Date:   Sun Sep 3 16:49:03 2023 -0500

    Squashed commit of the following:

    commit 28230d9305
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Sun Sep 3 02:44:26 2023 +0200

        feat: delete button confirm (#875)

        * base for confirm delete

        * more like OpenAI

    commit 2b54e3f9fe
    Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
    Date:   Fri Sep 1 14:20:51 2023 -0400

        update: install script (#858)

    commit 1cd0fd9d5a
    Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
    Date:   Fri Sep 1 08:12:35 2023 -0400

        doc: Hugging Face Deployment (#867)

        * docs: update ToC

        * docs: update ToC

        * update huggingface.md

        * update render.md

        * update huggingface.md

        * update mongodb.md

        * update huggingface.md

        * update README.md

    commit aeeb3d3050
    Author: Mu Yuan <yuanmu.email@gmail.com>
    Date:   Thu Aug 31 07:21:27 2023 +0800

        Update Zh.tsx (#862)

        * Update Zh.tsx

        Changed the translation of several words to make it more relevant to Chinese usage habits.

        * Update Zh.tsx

        Changed the translation of several words to make it more relevant to Chinese usage habits

    commit 80e2e2675b
    Author: Raí <140329135+itzraiss@users.noreply.github.com>
    Date:   Mon Aug 28 18:05:46 2023 -0300

        Translation of 'com_ui_pay_per_call:' to Spanish and Portuguese that were missing. (#857)

        * Update Br.tsx

        * Update Es.tsx

        * Update Br.tsx

        * Update Es.tsx

    commit 3574d0b823
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 28 14:49:26 2023 -0400

        docs: make_your_own.md formatting fix for mkdocs (#855)

    commit d672ac690d
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 28 14:24:10 2023 -0400

        Release v0.5.8 (#854)

        * chore: add 'api' image to tag release workflow

        * docs: update DO deployment docs to include instruction about latest stable release, as well as security best practices

        * Release v0.5.8

        * docs: Update digitalocean.md with firewall section images

        * docs: make_your_own.md formatting fix for mkdocs

    commit d3e7627046
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 28 12:03:08 2023 -0400

        refactor(plugins): Improve OpenAPI handling, Show Multiple Plugins, & Other Improvements (#845)

        * feat(PluginsClient.js): add conversationId to options object in the constructor
        feat(PluginsClient.js): add support for Code Interpreter plugin
        feat(PluginsClient.js): add support for Code Interpreter plugin in the availableTools manifest
        feat(CodeInterpreter.js): add CodeInterpreterTools module
        feat(CodeInterpreter.js): add RunCommand class
        feat(CodeInterpreter.js): add ReadFile class
        feat(CodeInterpreter.js): add WriteFile class
        feat(handleTools.js): add support for loading Code Interpreter plugin

        * chore(api): update langchain dependency to version 0.0.123

        * fix(CodeInterpreter.js): add support for extracting environment from code
        fix(WriteFile.js): add support for extracting environment from data
        fix(extractionChain.js): add utility functions for creating extraction chain from Zod schema
        fix(handleTools.js): refactor getOpenAIKey function to handle user-provided API key
        fix(handleTools.js): pass model and openAIApiKey to CodeInterpreter constructor

        * fix(tools): rename CodeInterpreterTools to E2BTools
        fix(tools): rename code_interpreter pluginKey to e2b_code_interpreter

        * chore(PluginsClient.js): comment out unused import and function findMessageContent
        feat(PluginsClient.js): add support for CodeSherpa plugin
        feat(PluginsClient.js): add CodeSherpaTools to available tools
        feat(PluginsClient.js): update manifest.json to include CodeSherpa plugin
        feat(CodeSherpaTools.js): create RunCode and RunCommand classes for CodeSherpa plugin

        feat(E2BTools.js): Add E2BTools module for extracting environment from code and running commands, reading and writing files
        fix(codesherpa.js): Remove codesherpa module as it is no longer needed

        feat(handleTools.js): add support for CodeSherpaTools in loadTools function
        feat(loadToolSuite.js): create loadToolSuite utility function to load a suite of tools

        * feat(PluginsClient.js): add support for CodeSherpa v2 plugin
        feat(PluginsClient.js): add CodeSherpa v1 plugin to available tools
        feat(PluginsClient.js): add CodeSherpa v2 plugin to available tools
        feat(PluginsClient.js): update manifest.json for CodeSherpa v1 plugin
        feat(PluginsClient.js): update manifest.json for CodeSherpa v2 plugin
        feat(CodeSherpa.js): implement CodeSherpa plugin for interactive code and shell command execution
        feat(CodeSherpaTools.js): implement RunCode and RunCommand plugins for CodeSherpa v1
        feat(CodeSherpaTools.js): update RunCode and RunCommand plugins for CodeSherpa v2

        fix(handleTools.js): add CodeSherpa import statement
        fix(handleTools.js): change pluginKey from 'codesherpa' to 'codesherpa_tools'
        fix(handleTools.js): remove model and openAIApiKey from options object in e2b_code_interpreter tool
        fix(handleTools.js): remove openAIApiKey from options object in codesherpa_tools tool
        fix(loadToolSuite.js): remove model and openAIApiKey parameters from loadToolSuite function

        * feat(initializeFunctionsAgent.js): add prefix to agentArgs in initializeFunctionsAgent function

        The prefix is added to the agentArgs in the initializeFunctionsAgent function. This prefix is used to provide instructions to the agent when it receives any instructions from a webpage, plugin, or other tool. The agent will notify the user immediately and ask them if they wish to carry out or ignore the instructions.

        * feat(PluginsClient.js): add ChatTool to the list of tools if it meets the conditions
        feat(tools/index.js): import and export ChatTool
        feat(ChatTool.js): create ChatTool class with necessary properties and methods

        * fix(initializeFunctionsAgent.js): update PREFIX message to include sharing all output from the tool
        fix(E2BTools.js): update descriptions for RunCommand, ReadFile, and WriteFile plugins to provide more clarity and context

        * chore: rebuild package-lock after rebase

        * chore: remove deleted file from rebase

        * wip: refactor plugin message handling to mirror chat.openai.com, handle incoming stream for plugin use

        * wip: new plugin handling

        * wip: show multiple plugins handling

        * feat(plugins): save new plugins array

        * chore: bump langchain

        * feat(experimental): support streaming in between plugins

        * refactor(PluginsClient): factor out helper methods to avoid bloating the class, refactor(gptPlugins): use agent action for mapping the name of action

        * fix(handleTools): fix tests by adding condition to return original toolFunctions map

        * refactor(MessageContent): Allow the last index to be last in case it has text (may change with streaming)

        * feat(Plugins): add handleParsingErrors, useful when LLM does not invoke function params

        * chore: edit out experimental codesherpa integration

        * refactor(OpenAPIPlugin): rework tool to be 'function-first', as the spec functions are explicitly passed to agent model

        * refactor(initializeFunctionsAgent): improve error handling and system message

        * refactor(CodeSherpa, Wolfram): optimize token usage by delegating bulk of instructions to system message

        * style(Plugins): match official style with input/outputs

        * chore: remove unnecessary console logs used for testing

        * fix(abortMiddleware): render markdown when message is aborted

        * feat(plugins): add BrowserOp

        * refactor(OpenAPIPlugin): improve prompt handling

        * fix(useGenerations): hide edit button when message is submitting/streaming

        * refactor(loadSpecs): optimize OpenAPI spec loading by only loading requested specs instead of all of them

        * fix(loadSpecs): will retain original behavior when no tools are passed to the function

        * fix(MessageContent): ensure cursor only shows up for last message and last display index
        fix(Message): show legacy plugin and pass isLast to Content

        * chore: remove console.logs

        * docs: update docs based on breaking changes and new features
        refactor(structured/SD): use description_for_model for detailed prompting

        * docs(azure): make plugins section more clear

        * refactor(structured/SD): change default payload to SD-WebUI to prefer realism and config for SDXL

        * refactor(structured/SD): further improve system message prompt

        * docs: update breaking changes after rebase

        * refactor(MessageContent): factor out EditMessage, types, Container to separate files, rename Content -> Markdown

        * fix(CodeInterpreter): linting errors

        * chore: reduce browser console logs from message streams

        * chore: re-enable debug logs for plugins/langchain to help with user troubleshooting

        * chore(manifest.json): add [Experimental] tag to CodeInterpreter plugins, which are not intended as the end-all be-all implementation of this feature for Librechat

    commit 66b8580487
    Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
    Date:   Mon Aug 28 09:18:25 2023 -0400

        docs: third-party tools (#848)

        * docs: third-party tools

        * docs: third-party tools

        * Update third-party.md

        * Update third-party.md

        ---------

        Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>

    commit 9791a78161
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Mon Aug 28 15:14:05 2023 +0200

        adjust the animation (#843)

    commit 3797ec6082
    Author: Ronith <87087292+ronith256@users.noreply.github.com>
    Date:   Mon Aug 28 18:43:50 2023 +0530

        feat: Add Code Interpreter Plugin (#837)

        * feat: Add Code Interpreter Plugin

        Adds a Simple Code Interpreter Plugin.
        ## Features:
        - Runs code using local Python Environment

        ## Issues
        - Code execution is not sandboxed.

        * Add Docker Sandbox for Python Server

    commit e2397076a2
    Author: Alex Zhang <ztc2011@gmail.com>
    Date:   Mon Aug 28 00:55:34 2023 +0800

        🌐: Chinese Translation (#846)

    commit 50c15c704f
    Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
    Date:   Sat Aug 26 19:36:59 2023 -0400

        Language translation: Polish (#840)

        * Language translation: Polish

        * Language translation: Polish

        * Revert changes in language-contributions.md

    commit 29d3640546
    Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
    Date:   Sat Aug 26 19:36:25 2023 -0400

        docs: updates (#841)

    commit 39c626aa8e
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 25 09:29:19 2023 -0400

        fix: isEdited edge case where latest Message is not saved due to aborting too quickly

    commit ae5c06f381
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 25 09:13:50 2023 -0400

        fix(chatGPTBrowser): render markdown formatting by setting isCreatedByUser, fix(useMessageHandler): avoid double appearance of cursor by setting latest message at initial response creation time

    commit 9ef1686e18
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Thu Aug 24 20:24:47 2023 -0400

        Update mkdocs.yml

    commit 5bbe411569
    Author: Flynn <dev@flynnbuckingham.com>
    Date:   Thu Aug 24 20:20:37 2023 -0400

        Add podman installation instructions. Update dockerfile to stub env (#819)

        * Added podman container installation docs. Updated dockerfile to stub env file if not present in source

        * Fix typos

    commit 887fec99ca
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Fri Aug 25 02:11:27 2023 +0200

        🌐: Russian Translation (#830)

    commit 007d51ede1
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Fri Aug 25 02:10:48 2023 +0200

        feat: facebook login (#820)

        * Facebook strategy

        * Update user_auth_system.md

        * Update user_auth_system.md

    commit a569020312
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Thu Aug 24 21:59:11 2023 +0200

        Fix Meilisearch error and refactor of the server index.js (#832)

        * fix meilisearch error at startup

        * limit the nesting

        * disable useless console log

        * fix(indexSync.js): removed redundant searchEnabled

        * refactor(index.js): moved configureSocialLogins to a new file

        * refactor(socialLogins.js): removed unnecessary conditional

    commit 37347d4683
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Wed Aug 23 16:14:17 2023 -0400

        fix(registration): Make Username optional (#831)

        * fix(User.js): update validation schema for username field, allow empty string as a valid value
        fix(validators.js): update validation schema for username field, allow empty string as a valid value
        fix(Registration.tsx, validators.js): update validation rules for name and username fields, change minimum length to 2 and maximum length to 80, assure they match and allow empty string as a valid value
        fix(Eng.tsx): update localization string for com_auth_username, indicate that it is optional

        * fix(User.js): update regex pattern for username validation to allow special characters @#$%&*()
        fix(validators.js): update regex pattern for username validation to allow special characters @#$%&*()

        * fix(Registration.spec.tsx): fix validation error message for username length requirement

    commit d38e463d34
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Wed Aug 23 13:44:40 2023 -0400

        fix(bingAI): markdown and error formatting for final stream response (#829)

        * fix(bingAI): markdown formatting for final stream response due to new strict payload validation on the frontend

        * fix: add missing prop to bing Error response

    commit 7dc27b10f1
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Tue Aug 22 18:44:59 2023 -0400

        feat: Edit AI Messages, Edit Messages in Place (#825)

        * refactor: replace lodash import with specific function import

        fix(api): esm imports to cjs

        * refactor(Messages.tsx): convert to TS, out-source scrollToDiv logic to a custom hook
        fix(ScreenshotContext.tsx): change Ref to RefObject in ScreenshotContextType
        feat(useScrollToRef.ts): add useScrollToRef hook for scrolling to a ref with throttle
        fix(Chat.tsx): update import path for Messages component
        fix(Search.tsx): update import path for Messages component

        * chore(types.ts): add TAskProps and TOptions types
        refactor(useMessageHandler.ts): use TAskFunction type for ask function signature

        * refactor(Message/Content): convert to TS, move Plugin component to Content dir

        * feat(MessageContent.tsx): add MessageContent component for displaying and editing message content
        feat(index.ts): export MessageContent component from Messages/Content directory

        * wip(Message.jsx): conversion and use of new component in progress

        * refactor: convert Message.jsx to TS and fix typing/imports based on changes

        * refactor: add typed props and refactor MultiMessage to TS, fix typing issues resulting from the conversion

        * edit message in progress

        * feat: complete edit AI message logic, refactor continue logic

        * feat(middleware): add validateMessageReq middleware
        feat(routes): add validation for message requests using validateMessageReq middleware
        feat(routes): add create, read, update, and delete routes for messages

        * feat: complete frontend logic for editing messages in place
        feat(messages.js): update route for updating a specific message
        - Change the route for updating a message to include the messageId in the URL
        - Update the request handler to use the messageId from the request parameters and the text from the request body
        - Call the updateMessage function with the updated parameters

        feat(MessageContent.tsx): add functionality to update a message
        - Import the useUpdateMessageMutation hook from the data provider
        - Destructure the conversationId, parentMessageId, and messageId from the message object
        - Create a mutation function using the useUpdateMessageMutation hook
        - Implement the updateMessage function to call the mutation function with the updated message parameters
        - Update the messages state to reflect the updated message text

        feat(api-endpoints.ts): update messages endpoint to include messageId
        - Update the messages endpoint to include the messageId as an optional parameter

        feat(data-service.ts): add updateMessage function
        - Implement the updateMessage function to make a PUT request to

        * fix(messages.js): make updateMessage function asynchronous and await its execution

        * style(EditIcon): make icon active for AI message

        * feat(gptPlugins/anthropic): add edit support

        * fix(validateMessageReq.js): handle case when conversationId is 'new' and return empty array
        feat(Message.tsx): pass message prop to SiblingSwitch component
        refactor(SiblingSwitch.tsx): convert to TS

        * fix(useMessageHandler.ts): remove message from currentMessages if isContinued is true
        feat(useMessageHandler.ts): add support for submission messages in setMessages
        fix(useServerStream.ts): remove unnecessary conditional in setMessages
        fix(useServerStream.ts): remove isContinued variable from submission

        * fix(continue): switch to continued message generation when continuing an earlier branch in conversation

        * fix(abortMiddleware.js): fix condition to check partialText length
        chore(abortMiddleware.js): add error logging when abortMessage fails

        * refactor(MessageHeader.tsx): convert to TS
        fix(Plugin.tsx): add default value for className prop in Plugin component

        * refactor(MultiMessage.tsx): remove commented out code
        docs(MultiMessage.tsx): update comment to clarify when siblingIdx is reset

        * fix(GenerationButtons): optimistic state for continue button

        * fix(MessageContent.tsx): add data-testid attribute to message text editor
        fix(messages.spec.ts): update waitForServerStream function to include edit endpoint check
        feat(messages.spec.ts): add test case for editing messages

        * fix(HoverButtons & Message & useGenerations): Refactor edit functionality and related conditions

        - Update enterEdit function signature and prop
        - Create and utilize hideEditButton variable
        - Enhance conditions for edit button visibility and active state
        - Update button event handlers
        - Introduce isEditableEndpoint in useGenerations and refine continueSupported condition.

        * fix(useGenerations.ts): fix condition for hideEditButton to include error and searchResult
        chore(data-provider): bump version to 0.1.6
        fix(types.ts): add status property to TError type

        * chore: bump @dqbd/tiktoken to 1.0.7

        * fix(abortMiddleware.js): add required isCreatedByUser property to the error response object

        * refactor(Message.tsx): remove unnecessary props from SiblingSwitch component, as setLatestMessage is firing on every switch already
        refactor(SiblingSwitch.tsx): remove unused imports and code

        * chore(BaseClient.js): move console.debug statements back inside if block

    commit db77163f5d
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Tue Aug 22 14:15:14 2023 +0200

        docs: update chimeragpt (#826)

        * Update free_ai_apis.md

        * Update free_ai_apis.md

    commit 4a4e803df3
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Mon Aug 21 20:15:18 2023 +0200

        style(Dialog): Improved Close Button ("X") position (#824)

    commit 909b00c752
    Author: Daniel Avila <messagedaniel@protonmail.com>
    Date:   Sun Aug 20 21:04:36 2023 -0400

        fix(HoverButtons): light/dark styling to match official site

    commit 61dcb4d307
    Author: Naosuke Yokoe <ankerasoy@gmail.com>
    Date:   Sat Aug 19 20:11:31 2023 +0900

        feat: Azure Cognitive Search Plugin (#815)

        * feat(AzureCognitiveSearchPlugin)

        * feat(tools/AzureCognitiveSearch.js): Add a new plugin (not structured
          version)
        * feat(tools/structured/AzureCognitiveSearch.js): Add a new plugin (structured version)
        * feat(tools/manifest.json, tools/index.js, tools/util/handleTools.js):
          Add configurations for the plugin
        * feat(api/package.json, package-lock.json): Installed a new package for the
          plugin (@azure/search-documents)
        * feat(.env.example): Add new environment variables for the plugin

        Here is the link to the corresponding discussion page:
        https://github.com/danny-avila/LibreChat/discussions/567

        * docs(AzureCognitiveSearchPlugin)

        * docs(features/plugins/azure_cognitive_search.md): Add a new document
          for the plugin

        * (fix:.env.example)

        * reverted extra whitespaces removed by the editor

        * docs(mkdocs.yml)

        * Add the Azure Cognitive Search Plugin's documentation item to
        mkdocs.yml.

    commit 3c7f67fa76
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 18 12:40:33 2023 -0400

        fix(abortMiddleware): handle early abort error where userMessage.conversationId is undefined. In this case, the userId will be used as the abortKey

    commit c74c68a135
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 18 12:10:30 2023 -0400

        refactor(MessageHandler -> useServerStream): convert all relating files to TS and correct typings based on this change: properly refactor MessageHandler to a custom hook, where it's passed a submission object to instantiate the stream. This is the bare minimum groundwork for potentially having multiple streams running, which would be a big project to modularize a lot of the global state into maps/multiple streams, particular useful for having multiple views in place

    commit 8b4d3c2c21
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 18 12:04:29 2023 -0400

        refactor(routes): convert to TS

    commit d612cfcb45
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Fri Aug 18 12:02:39 2023 -0400

        chore(Auth): reorder exports in Auth component
        fix(PluginAuthForm): handle case when pluginKey is null or undefined
        fix(PluginStoreDialog): handle case when getAvailablePluginFromKey is null or undefined
        fix(AuthContext): make authConfig optional in AuthContextProvider
        feat(hooks): add useServerStream hook
        fix(conversation): setSubmission to null instead of empty object
        fix(preset): specify type for presets atom
        fix(search): specify type for isSearchEnabled atom
        fix(submission): specify type for submission atom

    commit c40b95f424
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Fri Aug 18 16:11:00 2023 +0200

        feat: Disable Registration with social login (#813)

        * Google, Github and Discord

        * update .env.example with ALLOW_SOCIAL_REGISTRATION

        * fix some conflict

        * refactor strategy

        * Update user_auth_system.md

        * Update user_auth_system.md

    commit 46ed5aaccd
    Author: Patrick <psarnowski@gmail.com>
    Date:   Fri Aug 18 09:38:24 2023 -0400

        Show the response scores from Bing. (#814)

    commit 1dacfa49f0
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Thu Aug 17 20:32:31 2023 +0200

        update profile picture (#792)

    commit afd43afb60
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Thu Aug 17 12:50:05 2023 -0400

        feat(GPT/Anthropic): Continue Regenerating & Generation Buttons (#808)

        * feat(useMessageHandler.js/ts): Refactor and add features to handle user messages, support multiple endpoints/models, generate placeholder responses, regeneration, and stopGeneration function

        fix(conversation.ts, buildTree.ts): Import TMessage type, handle null parentMessageId

        feat(schemas.ts): Update and add schemas for various AI services, add default values, optional fields, and endpoint-to-schema mapping, create parseConvo function

        chore(useMessageHandler.js, schemas.ts): Remove unused imports, variables, and chatGPT enum

        * wip: add generation buttons

        * refactor(cleanupPreset.ts): simplify cleanupPreset function
        refactor(getDefaultConversation.js): remove unused code and simplify getDefaultConversation function

        feat(utils): add getDefaultConversation function

        This commit adds a new utility function called `getDefaultConversation` to the `client/src/utils/getDefaultConversation.ts` file. This function is responsible for generating a default conversation object based on the provided parameters.

        The `getDefaultConversation` function takes in an object with the following properties:
        - `conversation`: The conversation object to be used as a base.
        - `endpointsConfig`: The configuration object containing information about the available endpoints.
        - `preset`: An optional preset object that can be used to override the default behavior.

        The function first tries to determine the target endpoint based on the preset object. If a valid endpoint is found, it is used as the target endpoint. If not, the function tries to retrieve the last conversation setup from the local storage and uses its endpoint if it is valid. If neither the preset nor the local storage contains a valid endpoint, the function falls back to a default endpoint.

        Once the target endpoint is determined,

        * fix(utils): remove console.error statement in buildDefaultConversation function
        fix(schemas): add default values for catch blocks in openAISchema, googleSchema, bingAISchema, anthropicSchema, chatGPTBrowserSchema, and gptPluginsSchema

        * fix: endpoint not changing on change of preset from other endpoint, wip: refactor

        * refactor: preset items to TSX

        * refactor: convert resetConvo to TS

        * refactor(getDefaultConversation.ts): move defaultEndpoints array to the top of the file for better readability
        refactor(getDefaultConversation.ts): extract getDefaultEndpoint function for better code organization and reusability

        * feat(svg): add ContinueIcon component
        feat(svg): add RegenerateIcon component
        feat(svg): add ContinueIcon and RegenerateIcon components to index.ts

        * feat(Button.tsx): add onClick and className props to Button component
        feat(GenerationButtons.tsx): add logic to display Regenerate or StopGenerating button based on isSubmitting and messages
        feat(Regenerate.tsx): create Regenerate component with RegenerateIcon and handleRegenerate function
        feat(StopGenerating.tsx): create StopGenerating component with StopGeneratingIcon and handleStopGenerating function

        * fix(TextChat.jsx): reorder imports and variables for better readability
        fix(TextChat.jsx): fix typo in condition for isNotAppendable variable
        fix(TextChat.jsx): remove unused handleStopGenerating function
        fix(ContinueIcon.tsx): remove unnecessary closing tags for polygon elements
        fix(useMessageHandler.ts): add missing type annotations for handleStopGenerating and handleRegenerate functions
        fix(useMessageHandler.ts): remove unused variables in return statement

        * fix(getDefaultConversation.ts): refactor code to use getLocalStorageItems function
        feat(getLocalStorageItems.ts): add utility function to retrieve items from local storage

        * fix(OpenAIClient.js): add support for streaming result in sendCompletion method
        feat(OpenAIClient.js): add finish_reason metadata to opts in sendCompletion method
        feat(Message.js): add finish_reason field to Message model
        feat(messageSchema.js): add finish_reason field to messageSchema
        feat(openAI.js): parse chatGptLabel and promptPrefix from req.body and pass rest of the modelOptions to endpointOption
        feat(openAI.js): add addMetadata function to store metadata in ask function
        feat(openAI.js): add metadata to response if available
        feat(schemas.ts): add finish_reason field to tMessageSchema

        * feat(types.ts): add TOnClick and TGenButtonProps types for button components
        feat(Continue.tsx): create Continue component for generating button
        feat(GenerationButtons.tsx): update GenerationButtons component to use Continue component
        feat(Regenerate.tsx): create Regenerate component for regenerating button
        feat(Stop.tsx): create Stop component for stop generating button

        * feat(MessageHandler.jsx): add MessageHandler component to handle messages and conversations
        fix(Root.jsx): fix import paths for Nav and MessageHandler components

        * feat(useMessageHandler.ts): add support for generation parameter in ask function
        feat(useMessageHandler.ts): add support for isEdited parameter in ask function
        feat(useMessageHandler.ts): add support for continueGeneration function
        fix(createPayload.ts): replace endpoint URL when isEdited parameter is true

        * chore(client): set skipLibCheck to true in tsconfig.json

        * fix(useMessageHandler.ts): remove unused clientId variable
        fix(schemas.ts): make clientId field in tMessageSchema nullable and optional

        * wip: edit route for continue generation

        * refactor(api): move handlers to root of routes dir

        * fix(useMessageHandler.ts): initialize currentMessages to an empty array if messages is null
        fix(useMessageHandler.ts): update initialResponse text to use responseText variable
        fix(useMessageHandler.ts): update setMessages logic for isRegenerate case
        fix(MessageHandler.jsx): update setMessages logic for cancelHandler, createdHandler, and finalHandler

        * fix(schemas.ts): make createdAt and updatedAt fields optional and set default values using new Date().toISOString()
        fix(schemas.ts): change type annotation of TMessage from infer to input

        * refactor(useMessageHandler.ts): rename AskProps type to TAskProps
        refactor(useMessageHandler.ts): remove generation property from ask function arguments
        refactor(useMessageHandler.ts): use nullish coalescing operator (??) instead of logical OR (||)
        refactor(useMessageHandler.ts): pass the responseMessageId to message prop of submission

        * fix(BaseClient.js): use nullish coalescing operator (??) instead of logical OR (||) for default values

        * fix(BaseClient.js): fix responseMessageId assignment in handleStartMethods method
        feat(BaseClient.js): add support for isEdited flag in sendMessage method
        feat(BaseClient.js): add generation to responseMessage text in sendMessage method

        * fix(openAI.js): remove unused imports and commented out code
        feat(openAI.js): add support for generation parameter in request body
        fix(openAI.js): remove console.log statement
        fix(openAI.js): remove unused variables and parameters
        fix(openAI.js): update response text in case of error
        fix(openAI.js): handle error and abort message in case of error
        fix(handlers.js): add generation parameter to createOnProgress function
        fix(useMessageHandler.ts): update responseText variable to use generation parameter

        * refactor(api/middleware): move inside server dir

        * refactor: add endpoint specific, modular functions to build options and initialize clients, create server/utils, move middleware, separate utils into api general utils and server specific utils

        * fix(abortMiddleware.js): import getConvo and getConvoTitle functions from models
        feat(abortMiddleware.js): add abortAsk function to abortController to handle aborting of requests
        fix(openAI.js): import buildOptions and initializeClient functions from endpoints/openAI
        refactor(openAI.js): use getAbortData function to get data for abortAsk function

        * refactor: move endpoint specific logic to an endpoints dir

        * refactor(PluginService.js): fix import path for encrypt and decrypt functions in PluginService.js

        * feat(openAI): add new endpoint for adding a title to a conversation

        - Added a new file `addTitle.js` in the `api/server/routes/endpoints/openAI` directory.
        - The `addTitle.js` file exports a function `addTitle` that takes in request parameters and performs the following actions:
          - If the `parentMessageId` is `'00000000-0000-0000-0000-000000000000'` and `newConvo` is true, it proceeds with the following steps:
            - Calls the `titleConvo` function from the `titleConvo` module, passing in the necessary parameters.
            - Calls the `saveConvo` function from the `saveConvo` module, passing in the user ID and conversation details.
        - Updated the `index.js` file in the `api/server/routes/endpoints/openAI` directory to export the `addTitle` function.
        - This change adds

        * fix(abortMiddleware.js): remove console.log statement
        refactor(gptPlugins.js): update imports and function parameters
        feat(gptPlugins.js): add support for abortController and getAbortData
        refactor(openAI.js): update imports and function parameters
        feat(openAI.js): add support for abortController and getAbortData

        fix(openAI.js): refactor code to use modularized functions and middleware
        fix(buildOptions.js): refactor code to use destructuring and update variable names

        * refactor(askChatGPTBrowser.js, bingAI.js, google.js): remove duplicate code for setting response headers
        feat(askChatGPTBrowser.js, bingAI.js, google.js): add setHeaders middleware to set response headers

        * feat(middleware): validateEndpoint, refactor buildOption to only be concerned of endpointOption

        * fix(abortMiddleware.js): add 'finish_reason' property with value 'incomplete' to responseMessage object
        fix(abortMessage.js): remove console.log statement for aborted message
        fix(handlers.js): modify tokens assignment to handle empty generation string and trailing space

        * fix(BaseClient.js): import addSpaceIfNeeded function from server/utils
        fix(BaseClient.js): add space before generation in text property
        fix(index.js): remove getCitations and citeText exports
        feat(buildEndpointOption.js): add buildEndpointOption middleware
        fix(index.js): import buildEndpointOption middleware
        fix(anthropic.js): remove buildOptions function and use endpointOption from req.body
        fix(gptPlugins.js): remove buildOptions function and use endpointOption from req.body
        fix(openAI.js): remove buildOptions function and use endpointOption from req.body

        feat(utils): add citations.js and handleText.js modules
        fix(utils): fix import statements in index.js module

        * refactor(gptPlugins.js): use getResponseSender function from librechat-data-provider

        * feat(gptPlugins): complete 'continue generating'

        * wip: anthropic continue regen

        * feat(middleware): add validateRegistration middleware

        A new middleware function called `validateRegistration` has been added to the list of exported middleware functions in `index.js`. This middleware is responsible for validating registration data before allowing the registration process to proceed.

        * feat(Anthropic): complete continue regen

        * chore: add librechat-data-provider to api/package.json

        * fix(ci): backend-review will mock meilisearch, also installs data-provider as now needed

        * chore(ci): remove unneeded SEARCH env var

        * style(GenerationButtons): make text shorter for sake of space economy, even though this diverges from chat.openai.com

        * style(GenerationButtons/ScrollToBottom): adjust visibility/position based on screen size

        * chore(client): 'Editting' typo

        * feat(GenerationButtons.tsx): add support for endpoint prop in GenerationButtons component
        feat(OptionsBar.tsx): pass endpoint prop to GenerationButtons component
        feat(useGenerations.ts): create useGenerations hook to handle generation logic
        fix(schemas.ts): add searchResult field to tMessageSchema

        * refactor(HoverButtons): convert to TSX and utilize new useGenerations hook

        * fix(abortMiddleware): handle error with res headers set, or abortController not found, to ensure proper API error is sent to the client, chore(BaseClient): remove console log for onStart message meant for debugging

        * refactor(api): remove librechat-data-provider dep for now as it complicates deployed docker build stage, re-use code in CJS, located in server/endpoints/schemas

        * chore: remove console.logs from test files

        * ci: add backend tests for AnthropicClient, focusing on new buildMessages logic

        * refactor(FakeClient): use actual BaseClient sendMessage method for testing

        * test(BaseClient.test.js): add test for loading chat history
        test(BaseClient.test.js): add test for sendMessage logic with isEdited flag

        * fix(buildEndpointOption.js): add support for azureOpenAI in buildFunction object
        wip(endpoints.js): fetch Azure models from Azure OpenAI API if opts.azure is true

        * fix(Button.tsx): add data-testid attribute to button component
        fix(SelectDropDown.tsx): add data-testid attribute to Listbox.Button component
        fix(messages.spec.ts): add waitForServerStream function to consolidate logic for awaiting the server response
        feat(messages.spec.ts): add test for stopping and continuing message and improve browser/page context order and closing

        * refactor(onProgress): speed up time to save initial message for editable routes

        * chore: disable AI message editing (for now), was accidentally allowed

        * refactor: ensure continue is only supported for latest message style: improve styling in dark mode and across all hover buttons/icons, including making edit icon for AI invisible (for now)

        * fix: add test id to generation buttons so they never resolve to 2+ items

        * chore(package.json): add 'packages/' to the list of ignored directories
        chore(data-provider/package.json): bump version to 0.1.5

    commit ae5b7d3d53
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Tue Aug 15 18:27:54 2023 -0400

        fix(PluginsClient.js): fix ChatOpenAI Azure Config Issue (#812)

        * fix(PluginsClient.js): fix issue with creating LLM when using Azure

        * chore(PluginsClient.js): omit azure logging

        * refactor(PluginsClient.js): simplify assignment of azure variable

        The code was simplified by directly assigning the value of `this.azure` to the `azure` variable using object destructuring. This makes the code cleaner and more concise.

    commit b85f3bf91e
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Tue Aug 15 18:42:24 2023 +0200

        update from lang to localize (#810)

    commit 80aab73bf6
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Mon Aug 14 19:19:04 2023 -0400

        chore: rebuilt package-lock file

    commit bbe4931a97
    Author: Danny Avila <messagedaniel@protonmail.com>
    Date:   Mon Aug 14 19:13:24 2023 -0400

        refactor(ScreenshotContext): use html-to-image for lighter bundle, faster processing

    commit 74802dd720
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Mon Aug 14 17:51:03 2023 +0200

        chore: Translation Fixes, Lint Error Corrections, and Additional Translations (#788)

        * fix translation and small lint error

        * changed from localize to useLocalize hook

        * changed to useLocalize

    commit b64cc71d88
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 14 10:23:00 2023 -0400

        chore(docker-compose.yml): comment out meilisearch ports in docker-compose.yml (#807)

    commit 89f260bc78
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 14 10:12:00 2023 -0400

        fix(CodeBlock.tsx): fix copy-to-clipboard functionality. The code has been updated to use the copy function from the copy-to-clipboard library instead of the (#806)

        avigator.clipboard.writeText method. This should fix the issue with browser incompatibility with navigator SDK and allow users to copy code from the CodeBlock component successfully.

    commit d00c7354cd
    Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
    Date:   Mon Aug 14 09:45:44 2023 -0400

        fix: Corrected Registration Validation, Case-Insensitive Variable Handling, Playwright workflow (#805)

        * feat(auth.js): add validation for registration endpoint using validateRegistration middleware
        feat(validateRegistration.js): add middleware to validate registration based on ALLOW_REGISTRATION environment variable

        * fix(config.js): fix registrationEnabled and socialLoginEnabled variables to handle case-insensitive environment variable values

        * refactor(validateRegistration.js): remove console.log statement

        * chore(playwright.yml): skip browser download during yarn install
        chore(playwright.yml): place Playwright binaries to node_modules/@playwright/test
        chore(playwright.yml): install Playwright dependencies using npx playwright install-deps
        chore(playwright.yml): install Playwright chromium browser using npx playwright install chromium
        chore(playwright.yml): install @playwright/test@latest using npm install -D @playwright/test@latest
        chore(playwright.yml): run Playwright tests using npm run e2e:ci

        * chore(playwright.yml): change npm install order and update comment

        The order of the npm install commands in the "Install Playwright Browsers" step has been changed to first install @playwright/test@latest and then install chromium. Additionally, the comment explaining the PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD variable has been updated to mention npm install instead of yarn install.

        * chore(playwright.yml): remove commented out code for caching and add separate steps for installing Playwright dependencies and browsers

    commit 1aa4b34dc6
    Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
    Date:   Fri Aug 11 19:02:52 2023 +0200

        added the dot (.) username rules (#787)

commit 28230d9305
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Sun Sep 3 02:44:26 2023 +0200

    feat: delete button confirm (#875)

    * base for confirm delete

    * more like OpenAI

commit 2b54e3f9fe
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Fri Sep 1 14:20:51 2023 -0400

    update: install script (#858)

commit 1cd0fd9d5a
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Fri Sep 1 08:12:35 2023 -0400

    doc: Hugging Face Deployment (#867)

    * docs: update ToC

    * docs: update ToC

    * update huggingface.md

    * update render.md

    * update huggingface.md

    * update mongodb.md

    * update huggingface.md

    * update README.md

commit aeeb3d3050
Author: Mu Yuan <yuanmu.email@gmail.com>
Date:   Thu Aug 31 07:21:27 2023 +0800

    Update Zh.tsx (#862)

    * Update Zh.tsx

    Changed the translation of several words to make it more relevant to Chinese usage habits.

    * Update Zh.tsx

    Changed the translation of several words to make it more relevant to Chinese usage habits

commit 80e2e2675b
Author: Raí <140329135+itzraiss@users.noreply.github.com>
Date:   Mon Aug 28 18:05:46 2023 -0300

    Translation of 'com_ui_pay_per_call:' to Spanish and Portuguese that were missing. (#857)

    * Update Br.tsx

    * Update Es.tsx

    * Update Br.tsx

    * Update Es.tsx

commit 3574d0b823
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 14:49:26 2023 -0400

    docs: make_your_own.md formatting fix for mkdocs (#855)

commit d672ac690d
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 14:24:10 2023 -0400

    Release v0.5.8 (#854)

    * chore: add 'api' image to tag release workflow

    * docs: update DO deployment docs to include instruction about latest stable release, as well as security best practices

    * Release v0.5.8

    * docs: Update digitalocean.md with firewall section images

    * docs: make_your_own.md formatting fix for mkdocs

commit d3e7627046
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Mon Aug 28 12:03:08 2023 -0400

    refactor(plugins): Improve OpenAPI handling, Show Multiple Plugins, & Other Improvements (#845)

    * feat(PluginsClient.js): add conversationId to options object in the constructor
    feat(PluginsClient.js): add support for Code Interpreter plugin
    feat(PluginsClient.js): add support for Code Interpreter plugin in the availableTools manifest
    feat(CodeInterpreter.js): add CodeInterpreterTools module
    feat(CodeInterpreter.js): add RunCommand class
    feat(CodeInterpreter.js): add ReadFile class
    feat(CodeInterpreter.js): add WriteFile class
    feat(handleTools.js): add support for loading Code Interpreter plugin

    * chore(api): update langchain dependency to version 0.0.123

    * fix(CodeInterpreter.js): add support for extracting environment from code
    fix(WriteFile.js): add support for extracting environment from data
    fix(extractionChain.js): add utility functions for creating extraction chain from Zod schema
    fix(handleTools.js): refactor getOpenAIKey function to handle user-provided API key
    fix(handleTools.js): pass model and openAIApiKey to CodeInterpreter constructor

    * fix(tools): rename CodeInterpreterTools to E2BTools
    fix(tools): rename code_interpreter pluginKey to e2b_code_interpreter

    * chore(PluginsClient.js): comment out unused import and function findMessageContent
    feat(PluginsClient.js): add support for CodeSherpa plugin
    feat(PluginsClient.js): add CodeSherpaTools to available tools
    feat(PluginsClient.js): update manifest.json to include CodeSherpa plugin
    feat(CodeSherpaTools.js): create RunCode and RunCommand classes for CodeSherpa plugin

    feat(E2BTools.js): Add E2BTools module for extracting environment from code and running commands, reading and writing files
    fix(codesherpa.js): Remove codesherpa module as it is no longer needed

    feat(handleTools.js): add support for CodeSherpaTools in loadTools function
    feat(loadToolSuite.js): create loadToolSuite utility function to load a suite of tools

    * feat(PluginsClient.js): add support for CodeSherpa v2 plugin
    feat(PluginsClient.js): add CodeSherpa v1 plugin to available tools
    feat(PluginsClient.js): add CodeSherpa v2 plugin to available tools
    feat(PluginsClient.js): update manifest.json for CodeSherpa v1 plugin
    feat(PluginsClient.js): update manifest.json for CodeSherpa v2 plugin
    feat(CodeSherpa.js): implement CodeSherpa plugin for interactive code and shell command execution
    feat(CodeSherpaTools.js): implement RunCode and RunCommand plugins for CodeSherpa v1
    feat(CodeSherpaTools.js): update RunCode and RunCommand plugins for CodeSherpa v2

    fix(handleTools.js): add CodeSherpa import statement
    fix(handleTools.js): change pluginKey from 'codesherpa' to 'codesherpa_tools'
    fix(handleTools.js): remove model and openAIApiKey from options object in e2b_code_interpreter tool
    fix(handleTools.js): remove openAIApiKey from options object in codesherpa_tools tool
    fix(loadToolSuite.js): remove model and openAIApiKey parameters from loadToolSuite function

    * feat(initializeFunctionsAgent.js): add prefix to agentArgs in initializeFunctionsAgent function

    The prefix is added to the agentArgs in the initializeFunctionsAgent function. This prefix is used to provide instructions to the agent when it receives any instructions from a webpage, plugin, or other tool. The agent will notify the user immediately and ask them if they wish to carry out or ignore the instructions.

    * feat(PluginsClient.js): add ChatTool to the list of tools if it meets the conditions
    feat(tools/index.js): import and export ChatTool
    feat(ChatTool.js): create ChatTool class with necessary properties and methods

    * fix(initializeFunctionsAgent.js): update PREFIX message to include sharing all output from the tool
    fix(E2BTools.js): update descriptions for RunCommand, ReadFile, and WriteFile plugins to provide more clarity and context

    * chore: rebuild package-lock after rebase

    * chore: remove deleted file from rebase

    * wip: refactor plugin message handling to mirror chat.openai.com, handle incoming stream for plugin use

    * wip: new plugin handling

    * wip: show multiple plugins handling

    * feat(plugins): save new plugins array

    * chore: bump langchain

    * feat(experimental): support streaming in between plugins

    * refactor(PluginsClient): factor out helper methods to avoid bloating the class, refactor(gptPlugins): use agent action for mapping the name of action

    * fix(handleTools): fix tests by adding condition to return original toolFunctions map

    * refactor(MessageContent): Allow the last index to be last in case it has text (may change with streaming)

    * feat(Plugins): add handleParsingErrors, useful when LLM does not invoke function params

    * chore: edit out experimental codesherpa integration

    * refactor(OpenAPIPlugin): rework tool to be 'function-first', as the spec functions are explicitly passed to agent model

    * refactor(initializeFunctionsAgent): improve error handling and system message

    * refactor(CodeSherpa, Wolfram): optimize token usage by delegating bulk of instructions to system message

    * style(Plugins): match official style with input/outputs

    * chore: remove unnecessary console logs used for testing

    * fix(abortMiddleware): render markdown when message is aborted

    * feat(plugins): add BrowserOp

    * refactor(OpenAPIPlugin): improve prompt handling

    * fix(useGenerations): hide edit button when message is submitting/streaming

    * refactor(loadSpecs): optimize OpenAPI spec loading by only loading requested specs instead of all of them

    * fix(loadSpecs): will retain original behavior when no tools are passed to the function

    * fix(MessageContent): ensure cursor only shows up for last message and last display index
    fix(Message): show legacy plugin and pass isLast to Content

    * chore: remove console.logs

    * docs: update docs based on breaking changes and new features
    refactor(structured/SD): use description_for_model for detailed prompting

    * docs(azure): make plugins section more clear

    * refactor(structured/SD): change default payload to SD-WebUI to prefer realism and config for SDXL

    * refactor(structured/SD): further improve system message prompt

    * docs: update breaking changes after rebase

    * refactor(MessageContent): factor out EditMessage, types, Container to separate files, rename Content -> Markdown

    * fix(CodeInterpreter): linting errors

    * chore: reduce browser console logs from message streams

    * chore: re-enable debug logs for plugins/langchain to help with user troubleshooting

    * chore(manifest.json): add [Experimental] tag to CodeInterpreter plugins, which are not intended as the end-all be-all implementation of this feature for Librechat

commit 66b8580487
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Mon Aug 28 09:18:25 2023 -0400

    docs: third-party tools (#848)

    * docs: third-party tools

    * docs: third-party tools

    * Update third-party.md

    * Update third-party.md

    ---------

    Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>

commit 9791a78161
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Mon Aug 28 15:14:05 2023 +0200

    adjust the animation (#843)

commit 3797ec6082
Author: Ronith <87087292+ronith256@users.noreply.github.com>
Date:   Mon Aug 28 18:43:50 2023 +0530

    feat: Add Code Interpreter Plugin (#837)

    * feat: Add Code Interpreter Plugin

    Adds a Simple Code Interpreter Plugin.
    ## Features:
    - Runs code using local Python Environment

    ## Issues
    - Code execution is not sandboxed.

    * Add Docker Sandbox for Python Server

commit e2397076a2
Author: Alex Zhang <ztc2011@gmail.com>
Date:   Mon Aug 28 00:55:34 2023 +0800

    🌐: Chinese Translation (#846)

commit 50c15c704f
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Sat Aug 26 19:36:59 2023 -0400

    Language translation: Polish (#840)

    * Language translation: Polish

    * Language translation: Polish

    * Revert changes in language-contributions.md

commit 29d3640546
Author: Fuegovic <32828263+fuegovic@users.noreply.github.com>
Date:   Sat Aug 26 19:36:25 2023 -0400

    docs: updates (#841)

commit 39c626aa8e
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 25 09:29:19 2023 -0400

    fix: isEdited edge case where latest Message is not saved due to aborting too quickly

commit ae5c06f381
Author: Danny Avila <messagedaniel@protonmail.com>
Date:   Fri Aug 25 09:13:50 2023 -0400

    fix(chatGPTBrowser): render markdown formatting by setting isCreatedByUser, fix(useMessageHandler): avoid double appearance of cursor by setting latest message at initial response creation time

commit 9ef1686e18
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Thu Aug 24 20:24:47 2023 -0400

    Update mkdocs.yml

commit 5bbe411569
Author: Flynn <dev@flynnbuckingham.com>
Date:   Thu Aug 24 20:20:37 2023 -0400

    Add podman installation instructions. Update dockerfile to stub env (#819)

    * Added podman container installation docs. Updated dockerfile to stub env file if not present in source

    * Fix typos

commit 887fec99ca
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 25 02:11:27 2023 +0200

    🌐: Russian Translation (#830)

commit 007d51ede1
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Fri Aug 25 02:10:48 2023 +0200

    feat: facebook login (#820)

    * Facebook strategy

    * Update user_auth_system.md

    * Update user_auth_system.md

commit a569020312
Author: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Date:   Thu Aug 24 21:59:11 2023 +0200

    Fix Meilisearch error and refactor of the server index.js (#832)

    * fix meilisearch error at startup

    * limit the nesting

    * disable useless console log

    * fix(indexSync.js): removed redundant searchEnabled

    * refactor(index.js): moved configureSocialLogins to a new file

    * refactor(socialLogins.js): removed unnecessary conditional

commit 37347d4683
Author: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Date:   Wed Aug 23 16:14:17 2023 -0400

    fix(registration): Make Username optional (#831)

    * fix(User.js): update validation schema for username field, allow empty string as a valid value
    fix(validators.js): update validation schema for username field, allow empty string as a valid value
    fix(Registration.tsx, validators.js): update validation rules for name and username fields, change minimum length to 2 and maximum length to 80, assure they match and allow empty string as a valid value
    fix(Eng.tsx): update localization string for com_auth_username, indicate that it is optional

    * fix(User.js): update regex …

* Update package-lock.json

* Update SubmitButton.tsx

* Update SpeechRecognition.tsx

* fix: typescript error

* style: moved to new UI

* fix:(SpeechRecognition) lint error

* moved everything to hooks

* feat: support stt external

* fix(useExternalSpeechRecognition): recording the audio

* feat: whisper api support

* refactor(SpeechReecognition); fix(HoverButtons): set isSpeakling correctly

* fix: spelling errors

* fix: renamed files

* BIG FIX

* feat: whisper support

* fixed some ChatForm bugs and added the tts route

* handling more errors

* Fix audio stream initialization and cleanup in useSpeechToTextExternal

* feat: Elevenlabs TTS

* fixed some req issues

* fix: stt not activating on Mac

* fix: send audio blob to frontend

* fix(ChatForm): startupConfig var

* Update text-to-speech and speech-to-text services

* handle more errors correctly

* Remove console.log statements

* feat: added manual trigger with button

* fix: SpeechToText and SpeechToTextExernal + AudioRecorder

* refactor: TTS component

* chore: removed unused variable

* feat: azure stt

* feat: dedicated speech panel

* feat: STT button switch: fix: TextArea pr value adapted

* refactor: textToSpeech function and useTextToSpeechMutation

* fix: typo data-service

* fix: blob backend to frontend

* feat: TTS button for external

* feat: librechat.yaml

* style: spinner when loading TTS

* feat: hold click to download file

* style: disabled when apiKey not provided

* fix: typo startupConfig?.speechToTextExternal

* style: update icons

* fix(useTextToSpeech): set isSpeaking when audio finish

* fix: small issues with local TTS

* style: update settings dark theme

* docs: STT & TTS

* WIP: chat audio automatic; docs(custom_config): update to new .yaml version; chore: updated librechat.yaml version

* fix: send button disabled

* fix: interval update

* localization

* removed unused test code

* revert interval update to 100

* feat: auto-send message

* fix: chat audio automatic, default false

* refactor: moved all logic to hooks

* chore: renamed ChatAudio to conversationMode

* refactor: organized Speech panel

* feat: autoSendText switch

* feat: moved chataudio to conversationMode and improved error handling; docs: update localai model

* refactor: Auto transcribe audio

* test: AutoSendTextSwitch, AutoTranscribeAudioSwitch and ConversationModeSwitch.spec: refactor: removed hark

* fix: various speechTab fixes

* refactor(useSpeechToTextBrowser):: handle more errors

* feat: engine select

* feat: advanced mode

* chore: converted hooks to TS

* feat: cache TTS

* feat: delete cache; fix: cache issues

* refactor(useTextToSpeechExternal): removed unused import

* feat: cache switch; refactor: moved to dir STT/TTS

* tests: CacheTTS, TextToSpeech, SpeechToText

* feat: custom elevenlabs compatibility

* fix(useTextToSpeechExternal): cache switch not working

* feat: animation for STT

* fix: settings var not working

* chore: remove unused var

* feat: voice dropdown; refactor: yaml changes

* fix(textToSpeech): remove undefined properties

* refactor: Remove console logs and unused variable

* fix: TTS; feat: support coqui and piper

* fix: some STT issues

* fix: stt test

* fix: STT backend sending wrong data

* BREAKING: switch to react-speech-recognition, add regenerator-runtime/runtime in main.jsx

* feat: websocket backend

* foundations for websocket

* first pass elevenlabs streaming

* streaming audio

* stream changes

* input streaming implementation

* fix: client build errors

* WIP: streaming rewrite

* audio stream working but not the loop

* WIP: looping audio stream working

* WIP tts routes rewrite

* feat: track SSE runs by runId, which enables us to better track audio streams per message request

* chore: set activeRunId on data.created

* rate limit tts and only allow once

* WIP: streaming audio

* refactor(useSSE): simplify messageId/parentMessageId assignment in message stream

* delete unused component

* streaming working

* first pass but need to investigate forever pending bug

* optimize audio stream handling client and initial request

* fix(StreamAudio): null exception

* refactor(tts): add limiters for db polling and timeout promise by intervals and not elapsed time

* refactor(textToSpeech): reduce polling delay

* feat(StreamAudio): add caching

* refactor: rename global variable, add setIsPlaying, remove mediasource ref

* feat: use custom hook for audioRef to help determine audio end state

* fix: voices mutation -> query

* fix: voices mutation -> query 2/2

* feat: successful TTS for manual playback

* fix: tts voice init

* feat: playback rate

* feat: global audio toggles

* chore: Add renderIcon function for chat message hover buttons, update schemas with notes

* chore: add debug logging instead of console.logs

* fix: edge case undefined user id

* feat: Automatic Playback switch

* feat: add caching bump data-provider

* chore: tts add auth

* use global state for audio run

* feat: assistants support for TTS read aloud

* ci: uncomment tests for now until they are refactored

* stream audio tests are WIP

* refactor: make automatic playback false as default

---------

Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: bsu3338 <bsu3338@yahoo.com>
Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Co-authored-by: Berry-13 <marco13beretta@gmail.com>
Co-authored-by: Super User <root@Berry>
Co-authored-by: Marco Beretta <marco13beretta@proton.me>
2024-05-22 17:19:55 -04:00
Aman
9d8fd92dd3 🇬 refactor: Update default Google Models and Parameters (#2782)
* Update Google default model and parameters

* Update .env.example Vertex AI Models to reflect latest version and deprecate bison family

* Update Vertex AI model list in .env.example
2024-05-22 10:20:35 -04:00
Danny Avila
f00a8f87f7 🔧 fix(StableDiffusion): Temporarily Remove sampler_index (#2815) 2024-05-21 09:51:29 -04:00
Danny Avila
79840763e7 🔧 fix: Assistants App Error on Parameters Render (#2805) 2024-05-20 11:10:38 -04:00
Danny Avila
1a452121fa 🤖 feat: OpenAI Assistants v2 (initial support) (#2781)
* 🤖 Assistants V2 Support: Part 1

- Separated Azure Assistants to its own endpoint
- File Search / Vector Store integration is incomplete, but can toggle and use storage from playground
- Code Interpreter resource files can be added but not deleted
- GPT-4o is supported
- Many improvements to the Assistants Endpoint overall

data-provider v2 changes

copy existing route as v1

chore: rename new endpoint to reduce comparison operations and add new azure filesource

api: add azureAssistants part 1

force use of version for assistants/assistantsAzure

chore: switch name back to azureAssistants

refactor type version: string | number

Ensure assistants endpoints have version set

fix: isArchived type issue in ConversationListParams

refactor: update assistants mutations/queries with endpoint/version definitions, update Assistants Map structure

chore:  FilePreview component ExtendedFile type assertion

feat: isAssistantsEndpoint helper

chore: remove unused useGenerations

chore(buildTree): type issue

chore(Advanced): type issue (unused component, maybe in future)

first pass for multi-assistant endpoint rewrite

fix(listAssistants): pass params correctly

feat: list separate assistants by endpoint

fix(useTextarea): access assistantMap correctly

fix: assistant endpoint switching, resetting ID

fix: broken during rewrite, selecting assistant mention

fix: set/invalidate assistants endpoint query data correctly

feat: Fix issue with assistant ID not being reset correctly

getOpenAIClient helper function

feat: add toast for assistant deletion

fix: assistants delete right after create issue for azure

fix: assistant patching

refactor: actions to use getOpenAIClient

refactor: consolidate logic into helpers file

fix: issue where conversation data was not initially available

v1 chat support

refactor(spendTokens): only early return if completionTokens isNaN

fix(OpenAIClient): ensure spendTokens has all necessary params

refactor: route/controller logic

fix(assistants/initializeClient): use defaultHeaders field

fix: sanitize default operation id

chore: bump openai package

first pass v2 action service

feat: retroactive domain parsing for actions added via v1

feat: delete db records of actions/assistants on openai assistant deletion

chore: remove vision tools from v2 assistants

feat: v2 upload and delete assistant vision images

WIP first pass, thread attachments

fix: show assistant vision files (save local/firebase copy)

v2 image continue

fix: annotations

fix: refine annotations

show analyze as error if is no longer submitting before progress reaches 1 and show file_search as retrieval tool

fix: abort run, undefined endpoint issue

refactor: consolidate capabilities logic and anticipate versioning

frontend version 2 changes

fix: query selection and filter

add endpoint to unknown filepath

add file ids to resource, deleting in progress

enable/disable file search

remove version log

* 🤖 Assistants V2 Support: Part 2

🎹 fix: Autocompletion Chrome Bug on Action API Key Input

chore: remove `useOriginNavigate`

chore: set correct OpenAI Storage Source

fix: azure file deletions, instantiate clients by source for deletion

update code interpret files info

feat: deleteResourceFileId

chore: increase poll interval as azure easily rate limits

fix: openai file deletions, TODO: evaluate rejected deletion settled promises to determine which to delete from db records

file source icons

update table file filters

chore: file search info and versioning

fix: retrieval update with necessary tool_resources if specified

fix(useMentions): add optional chaining in case listMap value is undefined

fix: force assistant avatar roundedness

fix: azure assistants, check correct flag

chore: bump data-provider

* fix: merge conflict

* ci: fix backend tests due to new updates

* chore: update .env.example

* meilisearch improvements

* localization updates

* chore: update comparisons

* feat: add additional metadata: endpoint, author ID

* chore: azureAssistants ENDPOINTS exclusion warning
2024-05-19 12:56:55 -04:00
Elijah Shackelford
af8bcb08d6 👨‍🔧 fix: recognize command+click on macos (#2786)
Fixes an issue where the "command+click" was not being recognized on
MacOS. The desired behavior was working fine on Windows using
"ctrl+click", but the MacOS equivalent was broken.

This was preventing new tabs from opening while holding "command" (meta
key) on MacOS and clicking.

I verified this change fixes the issue by building locally and testing.
2024-05-19 02:44:14 -04:00
Danny Avila
f0e8cca5df 🚀 feat: Shared Links (#2772)
*  feat(types): add necessary types for shared link feature

*  feat: add shared links functions to data service

Added functions for retrieving, creating, updating, and deleting shared links and shared messages.

*  feat: Add useGetSharedMessages hook to fetch shared messages by shareId

Adds a new hook `useGetSharedMessages` which fetches shared messages based on the provided shareId.

*  feat: Add share schema and data access functions to API models

*  feat: Add share endpoint to API

The GET /api/share/${shareId} is exposed to the public, so authentication is not required. Other paths require authentication.

* ♻️ refactor(utils): generalize react-query cache manipulation functions

Introduces generic functions for manipulating react-query cache entries, marking a refinement in how query cache data is managed. It aims to enhance the flexibility and reusability of the cache interaction patterns within our application.

- Replaced specific index names with more generic terms in queries.ts, enhancing consistency across data handling functions.
- Introduced new utility functions in collection.ts for adding, updating, and deleting data entries in an InfiniteData<TCollection>. These utility functions (`addData`, `updateData`, `deleteData`, `findPage`) are designed to be re-usable across different data types and collections.
- Adapted existing conversation utility functions in convos.ts to leverage these new generic utilities.

*  feat(shared-link): add functions to manipulate shared link cache list

implemented new utility functions to handle additions, updates, and deletions in the shared link cache list.

*  feat: Add mutations and queries for shared links

*  feat(shared-link): add `Share` button to conversation list

- Added a share button in each conversation in the conversation list.
- Implemented functionality where clicking the share button triggers a POST request to the API.
- The API checks if a share link was already created for the conversation today; if so, it returns the existing link.
- If no link was created for today, the API will create a new share link and return it.
- Each click on the share button results in a new API request, following the specification similar to ChatGPT's share link feature.

* ♻️ refactor(hooks): generalize useNavScrolling for broader use

- Modified `useNavScrolling` to accept a generic type parameter `TData`, allowing it to be used with different data structures besides `ConversationListResponse`.
- Updated instances in `Nav.tsx` and `ArchivedChatsTable.tsx` to explicitly specify `ConversationListResponse` as the type argument when invoking `useNavScrolling`.

*  feat(settings): add shared links listing table with delete functionality in settings

- Integrated a delete button for each shared link in the table, allowing users to remove links as needed.

* ♻️ refactor(components): separate `EndpointIcon` from `Icon` component for standalone use

* ♻️ refactor: update useGetSharedMessages to return TSharedLink

- Modified the useGetSharedMessages hook to return not only a list of TMessage but also the TSharedLink itself.
- This change was necessary to support displaying the title and date in the Shared Message UI, which requires data from TSharedLink.

*  feat(shared link): add UI for displaying shared conversations without authentication

- Implemented a new UI component to display shared conversations, designed to be accessible without requiring authentication.
- Reused components from the authenticated Messages module where possible. Copied and adapted components that could not be directly reused to fit the non-authenticated context.

* 🔧 chore: Add translations

Translate labels only. Messages remain in English as they are possibly subject to change.

* ♻️ refactor: add icon and tooltip props to EditMenuButton component

* moved icon and popover to arguments so that EditMenuButton can be reused.
* modified so that when a ShareButton is closed, the parent DropdownMenu is also closed.

* ♻️irefactor: added DropdownMenu for Export and Share

* ♻️ refactor: renamed component names more intuitive

* More accurate naming of the dropdown menu.
* When the export button is closed, the parent dropdown menu is also closed.

* 🌍 chore: updated translations

* 🐞 Fix: OpenID Profile Image Download (#2757)

* Add fetch requirement

Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function

* Update openidStrategy.js

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>

* 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)

* 🚑 fix(export): use content as text if content is present in the message

If the endpoint is assistants, the text of the message goes into content, not message.text.

* refactor(ExportModel): TypeScript, remove unused code

---------

Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>

* 📤style: export button icon (#2752)

* refactor(ShareDialog): logic and styling

* refactor(ExportAndShareMenu): imports order and icon update

* chore: imports

* chore: imports/render logic

* feat: message branching

* refactor: add optional config to useGetStartupConfig

* refactor: disable endpoints query

* chore: fix search view styling gradient in light mode

* style: ShareView gradient styling

* refactor(Share): use select queries

* style: shared link table buttons

* localization and dark text styling

* style: fix clipboard button layout shift app-wide and add localization for copy code

* support assistants message content in shared links, add useCopyToClipboard, add copy buttons to Search Messages and Shared Link Messages

* add localizations

* comparisons

---------

Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-05-17 18:13:32 -04:00
Fuegovic
38ad36c1c5 📤style: export button icon (#2752) 2024-05-17 14:16:02 -04:00
Danny Avila
53fe2f6453 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)
* 🚑 fix(export): use content as text if content is present in the message

If the endpoint is assistants, the text of the message goes into content, not message.text.

* refactor(ExportModel): TypeScript, remove unused code

---------

Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
2024-05-17 14:10:40 -04:00
bsu3338
31479d6a48 🐞 Fix: OpenID Profile Image Download (#2757)
* Add fetch requirement

Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function

* Update openidStrategy.js

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-05-17 14:03:31 -04:00
Anirudh
612a58737d 💻 fix: Prevent DataTable component Text Selection (#2749) 2024-05-16 11:12:31 -04:00
Danny Avila
8a7f36f581 🤖 fix: Azure Assistants, use deploymentName as Run Model (#2736) 2024-05-15 23:34:35 -04:00
Danny Avila
4a5d06a774 ❇️ style(ModelSpecs): optimize for Long/Chinese name and mobile styling (#2731)
* style: hide nav toggle for mobile

* ❇️ style: optimize for Long/Chinese `modelSpec` name and mobile styling
2024-05-15 09:53:00 -04:00
Danny Avila
fc9368e0e7 feat: Gemini-1.5 Flash, gpt-4o imports, modelSpec greeting fix (#2729)
* fix: Gemini Flash stream fix

* fix: correct `sender` field for gpt-4o imports from ChatGPT

* add flash model examples and fix vertex streaming

* style: modelSpec greeting fix
2024-05-15 09:02:48 -04:00
Yuichi Oneda
64bf0800a0 🚑 fix: Display Error Message when API Connection fails during Chat (#2710) 2024-05-14 18:29:52 -04:00
Danny Avila
94eeec354e 🔀 fix: Address Convo/Preset Switching Issues (#2709)
* fix(schemas): interchangeability between chatGptLabel <> modelLabel

* fix: display error message from enforceModelSpecs when conversation already existed

* fix(Mention): use activeIndex on mention tab/enter

* fix: correctly navigate to new conversation when deleting/archiving a new, active convo
2024-05-14 15:19:58 -04:00
Danny Avila
e42709bd1f 🔍 feat: Show Messages from Search Result (#2699)
* refactor(Nav): delegate Search-specific variables/hooks to SearchContext

* fix: safely determine firstTodayConvoId if convo is undefined

* chore: remove empty line

* feat: initial render of search messages

* feat: SearchButtons

* update Ko.ts

* update localizations with new key phrases

* chore: localization comparisons

* fix: clear conversation state on searchQuery navigation

* style: search messages view styling

* refactor(Convo): consolidate logic to navigateWithLastTools from useNavigateToConvo

* fix(SearchButtons): styling and correct navigation logic

* fix(SearchBar): invalidate all message queries and invoke `clearText` if onChange value is empty

* refactor(NewChat): consolidate new chat button logic to NewChatButtonIcon

* chore: localizations for Nav date groups

* chore: update comparisons

* fix: early return from sendRequest to avoid quick searchQuery reset

* style: Link Icon

* chore: bump tiktoken, use o200k_base for gpt-4o
2024-05-14 11:00:01 -04:00
Danny Avila
638ac5bba6 🚀 feat: gpt-4o (#2692)
* 🚀 feat: gpt-4o

* update readme.md

* feat: Add new test case for getMultiplier function

* feat: Refactor getMultiplier function to use valueKey variable
2024-05-13 14:25:02 -04:00
Christian Köberl
5920672a8c 🐋 ci: create smaller Docker images (#2691)
- create fewer layers
- install only prod dependencies for final build
- clean npm cache
- fix layering in multi-image build
2024-05-13 10:47:18 -04:00
Danny Avila
a0d1e2a5f8 🪶 docs: Update README.md Icon 2024-05-13 10:42:09 -04:00
Danny Avila
4ffc1414a8 Revert "🐋 refactor(docker-compose): use "HOST" in ports field (#2654)"
This reverts commit df6183db0f.
2024-05-13 10:36:36 -04:00
nidasfly
df6183db0f 🐋 refactor(docker-compose): use "HOST" in ports field (#2654) 2024-05-13 10:31:13 -04:00
Fuegovic
3816219936 🧹 chore: remove old docs (#2684)
* delete docs folder

* delete mkdocs

* update .env.example

* update compose.override

* update librechat.yaml

* update pr template

* update librechat.yaml

* update README.md

* update missing custom config error msg

* update loadCustomConfig.js

* update check.js

* update .env.example

* update replit reference

* update README.md

* prevent logger URL truncation

* fix broken link in templates

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-13 10:15:30 -04:00
Danny Avila
6fc664e4a3 ⚙️ feat: includedTools and script changes (#2690)
* chore: add email to npm scripts (user-stats and list-balances)

* feat: included tools

* chore: update console terminal links

* chore: add back typing
2024-05-13 10:07:10 -04:00
Danny Avila
89899164ed 👮 fix(enforceModelSpec): handle nested objects (#2681) 2024-05-12 18:20:53 -04:00
Danny Avila
c83d9d61d4 🧹 chore(/config/): add tsconfig.json & linting (#2680) 2024-05-12 16:24:13 -04:00
Danny Avila
bcdddaed72 🎨 style(MentionItem): update active bg-color (#2675) 2024-05-12 09:20:59 -04:00
Marco Beretta
a4de635719 🎨 style(MentionItem): update hover color (#2670)
* style(MentionItem): update hover color

* remove unused className
2024-05-11 21:12:22 -04:00
Danny Avila
4a32d7466a v0.7.2 (#2667)
* v0.7.2

* chore: uninstall hnswlib-node

* bump package provider

* bump librechat-data-provider in lockfile

* README: ross index

* chore: center star history
2024-05-10 16:29:27 -04:00
Danny Avila
2ec821ea4c 🌍 : Updated Translations & AI Generation Scripts (#2666)
* chore: bun scripts

* feat: comparisons

* refactor: move scripts to own folder

* feat: generated prompts script and Es output

* feat: generated prompts

* created prompts

* feat: Russian localization prompts

* translation setup

* additional ES translations

* additional ES translations

* translation services

* feat: additional translations

* fix regex for parseParamPrompt

* RU translations

* remove stores from git

* update gitignore

* update gitignore

* ZH translations

* move gen prompt output location

* ZH traditional translations

* AR translations

* chore: rename

* JP

* cleanup scripts

* add additional instruction prompts

* fix translation prompt and add DE

* FR translations (rate limited so not complete)

* chore: update translation comparisons

* chore: remove unused AnthropicClient changes

* refactor: use compositional styling for archive/delete buttons, fix manage archive table styling
2024-05-10 15:56:25 -04:00
Marco Beretta
978009787c 📝 docs(ai_endpoints): update HF key link (#2664) 2024-05-10 12:48:39 -04:00
Danny Avila
27e7621b6a 🪟 fix: Windows Vite Build Issue (#2663)
* fix: Windows CSS VITE build issue: peer-focus:dark => dark:peer-focus

* ci: add windows env step for frontend ci/cd
2024-05-10 12:44:43 -04:00
Danny Avila
2b37a44b8d 🔧 fix: Preset Dialog Styling and Values (#2657)
* style: preset dialog styling

* refactor: coerce number input for convo schema

* refactor: replace dynamic input number with static component
2024-05-10 03:05:45 -04:00
Danny Avila
98c96cd020 🦙 fix: Ollama System Message order (#2655) 2024-05-10 00:50:02 -04:00
Anirudh
8f20fb28e5 🪟 fix+feat: General UI Enhancements (#2619)
* feat: Minor design changes to mimic OpenAI's latest login page

* fix: Optimize ThemeSelector for mobile

* fix: Use a svg for the logo for transperency in dark mode

* feat: Update styles for Registration

* feat: Update error colors for login & registration

* fix: remove medium font

* wip: Dropdown menu

* feat: Update dropdown to match ChatGPT

* feat: Improve rounding and padding

* feat: Add UI Updates to RequestPasswordReset, PasswordRest and increase width for theme dropdown

* fix: Modify the My Files modal's width to not touch the screen

* feat: fix scrolling for dropdown, and make border width lighter

* feat: Match popup menu design to OpenAI (p1/2)

* fix+feat: fix dark mode, add user email, add lighter borders

* fix: Add border color on focus of chat input.

* feat: Move Export Conversation to a seperate button (testing)

* fix: Properly center Login, Registration, Reset Password Flow

* fix: Border colors on dark mode for settings modal

* feat: Improve wording for settings menu

* fix: Optimize settings modal for mobile and fix height for modal

* feat: Optimize for desktop

* fix: make TooltipTrigger asChild of button, improve settings mobile responsiveness

* feat: Handle dropdowns properly
TODO: Make height dynamic, fix dark mode colors

* fix: input styles
fix: make endpoint icon smaller

* feat: Update UI to Match ChatGPT Style

- Updated the dropdown styles to match the aesthetic of ChatGPT.
- Decreased spacing within the conversation area for cleanliness.
- Replaced the current archive icon with the ChatGPT's icon.

* fix: fix colors for EditMenuButton & ArchiveButton for dark mode and light mode

* fix: ui fixes

* fix: Fix Conversation UI Bugs

* fix: transparency of HoverToggle to make buttons not visible

* fix: dark mode HoverToggle & compress menu item spacing

* fix: responsiveness of export icon

* fix: first mentionitem is set to always be highlighted

* fix: improve hover state to text instead of bg

* feat: Update icons to ChatGPT Style

* fix: dark mode hover for PanelFileCell

* fix: change navlinks z-index to 100

* fix: hover states for DataTable

* feat: Move ExportButton to seperate component

* chore: remove unused imports
2024-05-09 17:46:16 -04:00
Fuegovic
d73ea8e1f2 🤗 feat: Known Endpoints: HuggingFace (#2646)
* endpoints: huggingface

* Update ai_endpoints.md

* huggingface: update icon
2024-05-09 14:26:47 -04:00
Marco Beretta
83bae9e9d9 🔧 fix: android keyboard @ popover issue (#2647) 2024-05-09 13:31:55 -04:00
Danny Avila
6ba7f60eec 🪙 feat: Configure Max Context and Output Tokens (#2648)
* chore: make frequent 'error' log into 'debug' log

* feat: add maxContextTokens as a conversation field

* refactor(settings): increase popover height

* feat: add DynamicInputNumber and maxContextTokens to all endpoints that support it (frontend), fix schema

* feat: maxContextTokens handling (backend)

* style: revert popover height

* feat: max tokens

* fix: Ollama Vision firebase compatibility

* fix: Ollama Vision, use message_file_map to determine multimodal request

* refactor: bring back MobileNav and improve title styling
2024-05-09 13:27:13 -04:00
Danny Avila
5293b73b6d 🤖 feat(google): Add safety settings configuration (#2644)
* 🤖 feat(google): Add safety settings configuration

- Implement safety settings configuration in GoogleClient.js
- Add safety settings variables in .env.example
- Update documentation to explain safety settings and clarify model usage

* fix(google): Apply safety settings only to Gemini models

Previously, the safety settings were being applied to all models, regardless of whether they were Gemini models or not. This commit ensures that the safety settings are only applied to models that contain the "gemini" string in their name.

The changes include:

- Extracting the model name from `payload.parameters.model`
- Checking if the model name exists and contains the "gemini" string
- Only applying the safety settings if the model name contains "gemini"
- Ignoring the safety settings for non-Gemini models

This fix ensures that the safety settings are only used for the intended Gemini models, and not applied to other models where they may not be applicable.

* Update GoogleClient.js

* fix(google): Apply safety settings only to Gemini models

---------

Co-authored-by: Oliver Faust <oliver@f4ust.de>
2024-05-08 21:32:23 -04:00
Walber Cardoso
b6d1f5fa53 🎨 style: Convo fade effect (#2642)
* style: Improve fade effect into convos

* style: Improve fade effect into convos. WIP code

* 🔧 fix: Convo fade effect

* 🔧 fix: Convo fade effect: removed listeners
2024-05-08 21:21:55 -04:00
Danny Avila
c94278be85 🦙 feat: Ollama Vision Support (#2643)
* refactor: checkVisionRequest, search availableModels for valid vision model instead of using default

* feat: install ollama-js, add typedefs

* feat: Ollama Vision Support

* ci: fix test
2024-05-08 20:24:40 -04:00
Danny Avila
3c5fa40435 📶 fix: Mobile Stylings (#2639)
* chore: remove unused mobile nav

* fix: mobile nav fix for 'more' and 'archive' buttons div

* refactor(useTextarea): rewrite handleKeyUp for backwards compatibility

refactor(useTextarea): rewrite handleKeyUp for backwards compatibility

* experimental: add processing delay to azure streams for better performance/UX

* experiemental: adjust gpt-3 azureDelay

* fix: perplexity titles
2024-05-08 16:40:20 -04:00
Danny Avila
b6d6343f54 📧 feat: Mention "@" Command Popover (#2635)
* feat: initial mockup

* wip: activesetting, may use or not use

* wip: mention with useCombobox usage

* feat: connect textarea to new mention popover

* refactor: consolidate icon logic for Landing/convos

* refactor: cleanup URL logic

* refactor(useTextarea): key up handler

* wip: render desired mention options

* refactor: improve mention detection

* feat: modular chat the default option

* WIP: first pass mention selection

* feat: scroll mention items with keypad

* chore(showMentionPopoverFamily): add typing to atomFamily

* feat: removeAtSymbol

* refactor(useListAssistantsQuery): use defaultOrderQuery as default param

* feat: assistants mentioning

* fix conversation switch errors

* filter mention selections based on startup settings and available endpoints

* fix: mentions model spec icon URL

* style: archive icon

* fix: convo renaming behavior on click

* fix(Convo): toggle hover state

* style: EditMenu refactor

* fix: archive chats table

* fix: errorsToString import

* chore: remove comments

* chore: remove comment

* feat: mention descriptions

* refactor: make sure continue hover button is always last, add correct fork button alt text
2024-05-07 13:13:55 -04:00
Yuichi Ohneda
89b1e33be0 🚀feat: Archive conversations (#2590)
* 🔧chore: add internationalization labels for archive feature

*  feat: Add function to useArchiveConversationMutation()

This commit adds a new mutation function `useArchiveConversationMutation()` for archiving conversations. This function takes the ID string of the conversation to be archived and returns a mutation result object. Upon successful archiving, it removes and refreshes the conversation from the query data cache.
While ChatGPT PATCHes the archived status by sending `{is_archived: true}` to the URL `/backend-api/conversation/$conversation_id`, this implementation uses the `dataService.updateConversation(payload)` with a POST method, aligning with the existing code conventions.

*  feat(api): add is_archived field to Conversation schema and update getConvosByPage method

This commit adds a new field `is_archived` with a default value of false to the Conversation schema. It also modifies the `getConvosByPage` method within the Conversation API to adjust the query to only target conversations where `is_archived` is set to false or where the `is_archived` field does not exist. The function `getConvosQueried`, which returns conversations for a specified Conversation ID, was determined not to require consideration of whether `is_archived` is true or false, and thus was not modified.

* ♻️ refactor: add className prop to DotsIcon component

To enhance the versatility of the DotsIcon component, this commit introduces the ability to specify a className prop, allowing for greater customization.

*  feat(ui): add Edit Button to group Title change and Conversation delete buttons

Added a new Edit Button to the conversations, similar to the ChatGPT UI, which groups options for editing the conversation title and deleting conversations. This grouping is accessible through a dialogue that appears when the three-dot icon is clicked.

* ♻️ refactor(ui): enhance Delete Button to accept className and label options

Enhanced the Delete Button component to accept a `className` for customization and an optional `appendLabel`. The DeleteButton component is used by both `Convo.tsx` and `Conversation.tsx`, but currently only `Convo.tsx` is active and `Conversation.tsx `is apparently not used; removing `Conversation.tsx` may eliminate the need for the `appendLabel` property in the future.

* ♻️ refactor(ui): enhance RenameButton to accept label options

Added the ability to optionally display labels; the Rename Button component is used by both `Convo.tsx` and `Conversation.tsx`, but currently only `Convo.tsx` is active and `Conversation.tsx `is apparently not used; removing `Conversation.tsx` may eliminate the need for the `appendLabel` property in the future.

* 🔧 chors: additional localization labels

* ♻️  refactor: change is_archived property of conversation to camelCase

* Refactor the is_archived property of conversation to camelCase (isArchived) to adhere to the existing code conventions
* Modify the function that retrieves conversations to accept the isArchived parameter

* ♻️ refactor: add archiveConversation mutation

I thought I could divert dataService.updateConversation, but added a new archiveConversation because the request types are different. It might be better to make them common, but to avoid side effects, I added a new function this time.
Added process to deleteConversationMutation to delete archived conversations

*  feat: Add the function to hide a cancel button in DialogTemplate component

The Cancel button is not needed when displaying the archive list, so I made the Cancel button optional.

* ♻️ refactor: Add support for filtering archived conversations in Nav component

This commit modifies the Nav component to add the ability to filter out archived conversations when fetching data. This is done by adding `isArchived: false` to the query parameters for both the `useConversationsInfiniteQuery()` and `useSearchInfiniteQuery()` hooks, effectively excluding any archived conversations from the results returned.

* ♻️ refactor: add Tooltip to DeleteButton

* Add Tooltip to DeleteButton component
* Display Tooltip when DeleteButton only shows an Icon without text

*  feat(ui): add ArchiveButton component for archiving conversations

To be compatible with the ChatGPT UI, no confirmation dialog is displayed when ArchiveButton is clicked. The basic behavior conforms to DeleteButton and RenameButton.

*  feat(ui): add Archive button to list of conversations

Modify the Nav of the conversation list to include a dropdown that contains the Rename and Delete options, similar to the ChatGPT UI. Additionally, an Archive button has been added adjacent to the dropdown menu.

*  feat: Add ArchivedChatsTable component

Adds the `ArchivedChatsTable` component, which displays a table of archived chats. It has been implemented to be as compatible with the ChatGPT UI as possible.

* 🚑 fix(tooltip): increase z-index to ensure visibility over Dialog

Resolve an issue where tooltips were not visible when displayed over a Dialog. The z-index of `DialogPrimitive.Portal` in `Dialog.tsx` is set to 999. Since the rationale for this value is unclear, the z-index of the tooltip has been increased to 1000 to guarantee its visibility above the Dialog component.

* 🔧 chors: add internationalization labels
2024-05-06 23:07:00 -04:00
Marco Beretta
436f7195b5 🌍: Update Italian translation (#2622) 2024-05-06 07:51:01 -04:00
Marco Beretta
2aec4a6250 🔄 refactor: improved RAG animations/messages (#2616)
* fix: warning slow process rag  message

* refactor: improved useProgress hook for Files
2024-05-05 15:35:51 -04:00
Marco Beretta
b77bd19092 🎨 style(Fork): update light/dark theme (#2621) 2024-05-05 15:35:16 -04:00
Danny Avila
446ffe0417 📝 docs: update README.md 2024-05-05 12:51:38 -04:00
Danny Avila
b9bcaee656 📝 docs: update README.md 2024-05-05 12:48:26 -04:00
Danny Avila
110c0535fb Update README.md 2024-05-05 12:38:17 -04:00
Danny Avila
25fceb78b7 🌿 feat: Fork Messages/Conversations (#2617)
* typedef for ImportBatchBuilder

* feat: first pass, fork conversations

* feat: fork - getMessagesUpToTargetLevel

* fix: additional tests and fix getAllMessagesUpToParent

* chore: arrow function return

* refactor: fork 3 options

* chore: remove unused genbuttons

* chore: remove unused hover buttons code

* feat: fork first pass

* wip: fork remember setting

* style: user icon

* chore: move clear chats to data tab

* WIP: fork UI options

* feat: data-provider fork types/services/vars and use generic MutationOptions

* refactor: use single param for fork option, use enum, fix mongo errors, use Date.now(), add records flag for testing, use endpoint from original convo and messages, pass originalConvo to finishConversation

* feat: add fork mutation hook and consolidate type imports

* refactor: use enum

* feat: first pass, fork mutation

* chore: add enum for target level fork option

* chore: add enum for target level fork option

* show toast when checking remember selection

* feat: splitAtTarget

* feat: split at target option

* feat: navigate to new fork, show toasts, set result query data

* feat: hover info for all fork options

* refactor: add Messages settings tab

* fix(Fork): remember text info

* ci: test for single message and is target edge case

* feat: additional tests for getAllMessagesUpToParent

* ci: additional tests and cycle detection for getMessagesUpToTargetLevel

* feat: circular dependency checks for getAllMessagesUpToParent

* fix: getMessagesUpToTargetLevel circular dep. check

* ci: more tests for getMessagesForConversation

* style: hover text for checkbox fork items

* refactor: add statefulness to conversation import
2024-05-05 11:48:20 -04:00
Danny Avila
c8baceac76 🐛 fix: Prevent Empty File Uploads & Assistants Fixes (#2611)
* chore: update default models for openai/assistants

* fix: allows assistants models fetching

* change default models order, ensure assistant_id is defined if intended

* fix: prevent empty files from being uploaded
2024-05-03 12:49:26 -04:00
Kai Kreuzer
a0288f1c5c 🧾 docs: Fix Typo in librechat.example.yaml (#2606) 2024-05-02 16:27:11 -04:00
Danny Avila
5d3c90be26 📦 chore: update package.json/package-lock.json (#2600)
* 📦 chore: update package.json/package-lock.json

* 📦 chore: remove unused dependencies
2024-05-02 03:23:38 -04:00
Denis Palnitsky
ab6fbe48f1 📥 feat: Import Conversations from LibreChat, ChatGPT, Chatbot UI (#2355)
* Basic implementation of ChatGPT conversation import

* remove debug code

* Handle citations

* Fix updatedAt in import

* update default model

* Use job scheduler to handle import requests

* import job status endpoint

* Add wrapper around Agenda

* Rate limits for import endpoint

* rename import api path

* Batch save import to mongo

* Improve naming

* Add documenting comments

* Test for importers

* Change button for importing conversations

* Frontend changes

* Import job status endpoint

* Import endpoint response

* Add translations to new phrases

* Fix conversations refreshing

* cleanup unused functions

* set timeout for import job status polling

* Add documentation

* get extra spaces back

* Improve error message

* Fix translation files after merge

* fix translation files 2

* Add zh translation for import functionality

* Sync mailisearch index after import

* chore: add dummy uri for jest tests, as MONGO_URI should only be real for E2E tests

* docs: fix links

* docs: fix conversationsImport section

* fix: user role issue for librechat imports

* refactor: import conversations from json
- organize imports
- add additional jsdocs
- use multer with diskStorage to avoid loading file into memory outside of job
- use filepath instead of loading data string for imports
- replace console logs and some logger.info() with logger.debug
- only use multer for import route

* fix: undefined metadata edge case and replace ChatGtp -> ChatGpt

* Refactor importChatGptConvo function to handle undefined metadata edge case and replace ChatGtp with ChatGpt

* fix: chatgpt importer

* feat: maintain tree relationship for librechat messages

* chore: use enum

* refactor: saveMessage to use single object arg, replace console logs, add userId to log message

* chore: additional comment

* chore: multer edge case

* feat: first pass, maintain tree relationship

* chore: organize

* chore: remove log

* ci: add heirarchy test for chatgpt

* ci: test maintaining of heirarchy for librechat

* wip: allow non-text content type messages

* refactor: import content part object json string

* refactor: more content types to format

* chore: consolidate messageText formatting

* docs: update on changes, bump data-provider/config versions, update readme

* refactor(indexSync): singleton pattern for MeiliSearchClient

* refactor: debug log after batch is done

* chore: add back indexSync error handling

---------

Co-authored-by: jakubmieszczak <jakub.mieszczak@zendesk.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-02 02:48:26 -04:00
Yuichi Ohneda
3b44741cf9 🚑 fix(dialog): showCloseButton Prop Warning in DialogContent Component (#2597)
Fix DialogPrimitive.Content to not pass a showCloseButton property that does not exist in it to avoid outputting a warning.
2024-05-02 02:08:37 -04:00
Extremys
d21a05606e 🍎 feat: Apple MLX as Known Endpoint (#2580)
* add integration with Apple MLX

* fix: apple icon + image mkd link

---------

Co-authored-by: “Extremys” <“Extremys@email.com”>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-05-01 03:27:02 -04:00
Danny Avila
0e50c07e3f 🤖 feat: Model Specs & Save Tools per Convo/Preset (#2578)
* WIP: first pass ModelSpecs

* refactor(onSelectEndpoint): use `getConvoSwitchLogic`

* feat: introduce iconURL, greeting, frontend fields for conversations/presets/messages

* feat: conversation.iconURL & greeting in Landing

* feat: conversation.iconURL & greeting in New Chat button

* feat: message.iconURL

* refactor: ConversationIcon -> ConvoIconURL

* WIP: add spec as a conversation field

* refactor: useAppStartup, set spec on initial load for new chat, allow undefined spec, add localStorage keys enum, additional type fields for spec

* feat: handle `showIconInMenu`, `showIconInHeader`, undefined `iconURL` and no specs on initial load

* chore: handle undefined or empty modelSpecs

* WIP: first pass, modelSpec schema for custom config

* refactor: move default filtered tools definition to ToolService

* feat: pass modelSpecs from backend via startupConfig

* refactor: modelSpecs config, return and define list

* fix: react error and include iconURL in responseMessage

* refactor: add iconURL to responseMessage only

* refactor: getIconEndpoint

* refactor: pass TSpecsConfig

* fix(assistants): differentiate compactAssistantSchema, correctly resets shared conversation state with other endpoints

* refactor: assistant id prefix localStorage key

* refactor: add more LocalStorageKeys and replace hardcoded values

* feat: prioritize spec on new chat behavior: last selected modelSpec behavior (localStorage)

* feat: first pass, interface config

* chore: WIP, todo: add warnings based on config.modelSpecs settings.

* feat: enforce modelSpecs if configured

* feat: show config file yaml errors

* chore: delete unused legacy Plugins component

* refactor: set tools to localStorage from recoil store

* chore: add stable recoil setter to useEffect deps

* refactor: save tools to conversation documents

* style(MultiSelectPop): dynamic height, remove unused import

* refactor(react-query): use localstorage keys and pass config to useAvailablePluginsQuery

* feat(utils): add mapPlugins

* refactor(Convo): use conversation.tools if defined, lastSelectedTools if not

* refactor: remove unused legacy code using `useSetOptions`, remove conditional flag `isMultiChat` for using legacy settings

* refactor(PluginStoreDialog): add exhaustive-deps which are stable react state setters

* fix(HeaderOptions): pass `popover` as true

* refactor(useSetStorage): use project enums

* refactor: use LocalStorageKeys enum

* fix: prevent setConversation from setting falsy values in lastSelectedTools

* refactor: use map for availableTools state and available Plugins query

* refactor(updateLastSelectedModel): organize logic better and add note on purpose

* fix(setAgentOption): prevent reseting last model to secondary model for gptPlugins

* refactor(buildDefaultConvo): use enum

* refactor: remove `useSetStorage` and consolidate areas where conversation state is saved to localStorage

* fix: conversations retain tools on refresh

* fix(gptPlugins): prevent nullish tools from being saved

* chore: delete useServerStream

* refactor: move initial plugins logic to useAppStartup

* refactor(MultiSelectDropDown): add more pass-in className props

* feat: use tools in presets

* chore: delete unused usePresetOptions

* refactor: new agentOptions default handling

* chore: note

* feat: add label and custom instructions to agents

* chore: remove 'disabled with tools' message

* style: move plugins to 2nd column in parameters

* fix: TPreset type for agentOptions

* fix: interface controls

* refactor: add interfaceConfig, use Separator within Switcher

* refactor: hide Assistants panel if interface.parameters are disabled

* fix(Header): only modelSpecs if list is greater than 0

* refactor: separate MessageIcon logic from useMessageHelpers for better react rule-following

* fix(AppService): don't use reserved keyword 'interface'

* feat: set existing Icon for custom endpoints through iconURL

* fix(ci): tests passing for App Service

* docs: refactor custom_config.md for readability and better organization, also include missing values

* docs: interface section and re-organize docs

* docs: update modelSpecs info

* chore: remove unused files

* chore: remove unused files

* chore: move useSetIndexOptions

* chore: remove unused file

* chore: move useConversation(s)

* chore: move useDefaultConvo

* chore: move useNavigateToConvo

* refactor: use plugin install hook so it can be used elsewhere

* chore: import order

* update docs

* refactor(OpenAI/Plugins): allow modelLabel as an initial value for chatGptLabel

* chore: remove unused EndpointOptionsPopover and hide 'Save as Preset' button if preset UI visibility disabled

* feat(loadDefaultInterface): issue warnings based on values

* feat: changelog for custom config file

* docs: add additional changelog note

* fix: prevent unavailable tool selection from preset and update availableTools on Plugin installations

* feat: add `filteredTools` option in custom config

* chore: changelog

* fix(MessageIcon): always overwrite conversation.iconURL in messageSettings

* fix(ModelSpecsMenu): icon edge cases

* fix(NewChat): dynamic icon

* fix(PluginsClient): always include endpoint in responseMessage

* fix: always include endpoint and iconURL in responseMessage across different response methods

* feat: interchangeable keys for modelSpec enforcing
2024-04-30 22:11:48 -04:00
Ventz Petkov
a5cac03fa4 🚅 docs: load LiteLLM into LibreChat (#2573)
Documentation was missing one significant component, on loading librechat.yaml
2024-04-29 19:56:19 -04:00
Fuegovic
ba4fa6150e 🦙 docs: fix litellm.md (#2566) 2024-04-28 08:33:51 -04:00
Neelesh Kumar
463ca5d613 📄 docs: Update apipie fetch.py in ai_endpoints.md (#2547)
* Update apipie fetch.py in ai_endpoints.md

Made the python code more pythonic

* fix bug that caused duplicate model_ids
2024-04-27 18:37:33 -04:00
Neelesh Kumar
039c7ae880 📄 docs: update GOOGLE_MODELS in .env.example (#2506)
* update GOOGLE_MODELS in .env.example

* Update .env.example

* Update .env.example

* Update .env.example

* Update .env.example

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-04-27 18:36:54 -04:00
Danny Avila
63ef15ab63 🦙 feat: Fetch list of Ollama Models (#2565)
* 🦙 feat: Fetch list of Ollama Models

* style: better Tag text styling for light mode
2024-04-27 18:27:04 -04:00
Ventz Petkov
8a78500fe2 🚅 docs: update LiteLLM config with more models (#2553)
Added all OpenAI, Azure OpenAI, Amazon Bedrock, and Google GCP models available.

Specifically latest: Llama3; Google Gemini 1.5 Pro Preview; Claude Opus.

Here are all of the models:
  - model_name: claude-3-haiku
  - model_name: claude-3-sonnet
  - model_name: claude-3-opus
  - model_name: claude-v2
  - model_name: claude-instant
  - model_name: llama2-13b
  - model_name: llama2-70b
  - model_name: llama3-8b
  - model_name: llama3-70b
  - model_name: mistral-7b-instruct
  - model_name: mixtral-8x7b-instruct
  - model_name: mixtral-large
  - model_name: cohere-command-v14
  - model_name: cohere-command-light-v14
  - model_name: ai21-j2-mid
  - model_name: ai21-j2-ultra
  - model_name: amazon-titan-lite
  - model_name: amazon-titan-express
  - model_name: azure-gpt-4-turbo-preview
  - model_name: azure-gpt-3.5-turbo
  - model_name: azure-gpt-4
  - model_name: azure-gpt-3.5-turbo-16k
  - model_name: azure-gpt-4-32k
  - model_name: gpt-4-turbo
  - model_name: old-gpt-4-turbo-preview
  - model_name: gpt-3.5-turbo
  - model_name: gpt-4
  - model_name: gpt-3.5-turbo-16k
  - model_name: gpt-4-32k
  - model_name: gpt-4-vision-preview
  - model_name: google-chat-bison
  - model_name: google-chat-bison-32k
  - model_name: google-gemini-pro-1.0
  - model_name: google-gemini-pro-1.5-preview
2024-04-27 06:46:20 -04:00
Fuegovic
144fd5f6aa ⚙️ docs: update dotenv.md (#2551)
* ⚙️ docs: update dotenv.md

* Update dotenv.md - formatting
2024-04-26 14:34:50 -04:00
Danny Avila
2720327aa1 👩‍💻 fix: Minor UI fixes (#2548)
* fix(useMessageHelpers): define iconEndpoint

* fix: rely on Assistant Switcher effect for defining `assistant_id`, ensure ChatRoute `newConversation` only fires once
2024-04-26 10:27:49 -04:00
Martin Dahlö
4d0806d3e8 📋 refactor: allow paste in confirm field when resetting passwords (#2542)
* Disabled paste prevention in the confirm password field when resetting passwords.

* chore(ResetPassword): remove comments

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-04-25 20:26:33 -04:00
Neelesh Kumar
5b5f9b950b 🐋 refactor: Update docker-compose.yml (#2507) 2024-04-25 20:25:51 -04:00
いしかず
3ccff19821 🌍: Update Japanese translation (#2519)
* Update japanese translation

* translate japanese

* Added 5 Japanese translations

---------

Co-authored-by: k-ishii1020 <40662914+8492GitKaz@users.noreply.github.com>
2024-04-25 13:55:59 -04:00
Marco Beretta
11d5e232b3 🧪 refactor(isDomainAllowed): change directory, add tests (#2539) 2024-04-25 13:14:07 -04:00
Danny Avila
099aa9dead feat: Stop Sequences for Conversations & Presets (#2536)
* feat: `stop` conversation parameter

* feat: Tag primitive

* feat: dynamic tags

* refactor: update tag styling

* feat: add stop sequences to OpenAI settings

* fix(Presentation): prevent `SidePanel` re-renders that flicker side panel

* refactor: use stop placeholder

* feat: type and schema update for `stop` and `TPreset` in generation param related types

* refactor: pass conversation to dynamic settings

* refactor(OpenAIClient): remove default handling for `modelOptions.stop`

* docs: fix Google AI Setup formatting

* feat: current_model

* docs: WIP update

* fix(ChatRoute): prevent default preset override before `hasSetConversation.current` becomes true by including latest conversation state as template

* docs: update docs with more info on `stop`

* chore: bump config_version

* refactor: CURRENT_MODEL handling
2024-04-25 11:40:17 -04:00
Danny Avila
4121818124 ✍️ fix(useTextarea): Rich Text Format paste from MS Word (#2530) 2024-04-25 00:10:41 -04:00
Fuegovic
ca9a0fe629 🥧 feat: APIpie support (#2524) 2024-04-24 20:32:18 -04:00
Danny Avila
bde6bb0152 🔀 fix: Remove use of Mongo Transactions (#2525)
* fix: remove use of transactions

* fix: remove use of transactions

* refactor(actions): perform OpenAI API operation first, before attempting database updates
2024-04-24 16:04:46 -04:00
ilsubyeega
667f5f91fe 👤 fix: Use user?.username if user?.name is undefined (#2511)
* Use `user?.username` if `user?.name` is undefined

* Add useLocalize hook to Icon component
2024-04-24 12:34:01 -04:00
Mathieu Breton
75da75be08 🛂 feat(oauth): add domain restriction on social login (#2512) 2024-04-24 12:14:27 -04:00
Danny Avila
cdab1e9cda 🔒 fix: package-lock file for cross-compatibility (#2515) 2024-04-24 10:42:18 -04:00
Danny Avila
3df4fac118 v0.7.1 (#2502)
* chore: make openai package definition explicit

*  v0.7.1

* chore: gpt-4-vision correct context length

* add `llava` to vision models list
2024-04-23 08:57:20 -04:00
Danny Avila
0ae98ff011 🧪 ci: Add .env.test for backend-review.yml (#2501)
* 🧪 ci: Add `.env.test` for `backend-review.yml`

* chore: touch example file
2024-04-23 08:21:12 -04:00
Walber Cardoso
4d05e5b79a 👟 style: WrenchIcon and ImageGen SVG Animations (#2382)
* refactor(WrenchIcon, ImageGen SVG)

* refactor(WrenchIcon SVG)

* refactor(ImageGen SVG)

* refactor(ImageGen SVG) - add CSS
2024-04-23 08:14:28 -04:00
Danny Avila
199f9f32e6 🐋 fix(Dockerfile.multi): Resolve OpenAI SDK @ Latest for Assistants v1 2024-04-22 20:23:28 -04:00
Danny Avila
f94a782b4f 💻 fix(client): Allow Code Filetypes and Suppress Known Vite Warnings (#2492)
* refactor(vite): suppress known warnings

* fix: allow known code filetypes if there is a mismatch of expected type, or originalFile.type is empty

* refactor(useFileHandling): naming, use variable
2024-04-22 20:08:34 -04:00
Fuegovic
738207de50 ✏️docs: remove "copilot-gpt4-service" (#2491)
removed "copilot-gpt4-service", the repository has been disabled
2024-04-22 16:35:05 -04:00
Danny Avila
c96f067689 🔧 fix: Resolve Proper Dependencies to fix Application Error (#2488)
* chore: bump data-provider

* feat: script to check recent dependency updates

* fix: override vite/rollup version for vite build fix
- also remove unused vite-plugin-html
- add vite build to file output command

* chore: bump rollup override to last known working version (v4.16.0 is breaking)

* chore(vite): increase file size cache for workbox

* fix: resolve openai to last known version using assistants v1 latest features and default header

* chore: update openrouter examples
2024-04-22 12:52:30 -04:00
Danny Avila
3bfd185cab feat: Added PWA Setup & Manual Chunks via Vite (#2477)
* added pwa setup via vite config

Added apple status bar meta data

added maskable 512 icon for chrome and android devices

added vite-plugin-pwa

updated vite config to setup the pwa service worker and manifest upon build

* fix(vite): avoid pre-caching generated images

* chore: add manual chunking of larger vendor package

* chore: remove comments

---------

Co-authored-by: davecrab <65996799+davecrab@users.noreply.github.com>
2024-04-21 10:39:15 -04:00
Danny Avila
c937b8cd07 🧑‍💻 refactor: Display Client-facing Errors (#2476)
* fix(Google): allow presets to configure expected maxOutputTokens

* refactor: standardize client-facing errors

* refactor(checkUserKeyExpiry): pass endpoint instead of custom message

* feat(UserService): JSDocs and getUserKeyValues

* refactor: add NO_BASE_URL error type, make use of getUserKeyValues, throw user-specific errors

* ci: update tests with recent changes
2024-04-21 08:31:54 -04:00
Passerby1011
6db91978ca 🎨 style: update CodeSherpa icon (#2417)
The icon address error leads to the icon not displaying.
2024-04-20 15:09:59 -04:00
Danny Avila
8c22bb1d3d 🛠️ fix(Azure/Assistants): Handle Long Domain Names & Other Minor chores (#2475)
* chore: replace violation cache accessors with enum

* chore: fix test

* chore(fileSchema): index timestamps

* fix(ActionService): use encoding/caching strategy for handling assistant function character length limit

* refactor(actions): async `domainParser` also resolve retrieved model (which is deployment name) to user-defined model

* style(AssistantAction): add `whitespace-nowrap` for ellipsis

* refactor(ActionService): if domain is less than or equal to encoded domain fixed length, return domain with replacement of separator

* refactor(actions): use sessions/transactions for updating Assistant Action database records

* chore: remove TTL from ENCODED_DOMAINS cache

* refactor(domainParser): minor optimization and add tests

* fix(spendTokens): use txData.user for token usage logging

* refactor(actions): add helper function `withSession` for database operations with sessions/transactions

* fix(PluginsClient): logger debug `message` field edge case
2024-04-20 15:02:56 -04:00
Noah Ispas
5d642d0187 📙 docs: Remove duplicate information (#2451) 2024-04-19 22:57:40 -04:00
Fuegovic
4196a86fa9 🦙 doc update: llama3 (#2470)
* docs: update breaking_changes.md

* docs: update ai_endpoints.md -> llama3 for Ollama and groq

* librechat.yaml: update groq models

* Update breaking_changes.md

logs location

* Update breaking_changes.md

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-04-19 21:40:12 -04:00
Danny Avila
e6310c806a 🤖 fix: Minor Assistants Endpoint Fixes (#2472)
* fix(useCreateAssistantMutation): force re-render of assistants map by avoiding use shallow reference of listRes.data

* fix(AppService): regression by not including azure assistant defaults when no assistant endpoint values are set
2024-04-19 19:05:25 -04:00
Danny Avila
3d1dec62a4 🧼 refactor(AppService): Consolidate Logic & Issue more Warnings (#2468)
* chore: bump example config version

* refactor(AppService): issue warnings from separate modules where possible

* refactor(AppService): consolidate AppService logic to separate modules as much as possible

* chore: bump data-provider

* chore: remove unn. variable definition

* chore: warning wording
2024-04-19 12:05:39 -04:00
Danny Avila
de3987cbaf 🛂 refactor(openidStrategy): Use Strategy Functions for Avatars (#2467) 2024-04-19 09:12:55 -04:00
Fuegovic
f406a85633 🖥️ docs: env changes v0.6.10→v0.7.0+ (#2442)
* docs: env changes v0.6.10→v0.7.0+ | update railway referral

* docs: env changes v0.6.10→v0.7.0+
2024-04-18 08:27:52 -04:00
Danny Avila
692ce3b346 🛠️ fix: Merge Textarea Ref with Form for Simplified Handling (#2456)
* share ref correctly

* chore: remove extraneous textarea handlers and add excel text data
2024-04-18 08:19:52 -04:00
Fuegovic
26ea990045 📘 docs: update docker_compose_install.md (#2447)
* Update docker_compose_install.md

* Update docker_compose_install.md
2024-04-18 07:31:44 -04:00
Fuegovic
265abbc1c8 ⚙️ docs: Update .env.example (#2449) 2024-04-18 07:30:46 -04:00
marlonka
0b7da72be6 🌍 : Update German Translations (#2409)
* Improved and additional German translations

* Improved and added german translations and removed language translations here

* Spelling error fixed

* Use single quotes instead of double

* Use single quotes instead of double
2024-04-18 07:26:44 -04:00
Danny Avila
3c184e9410 🛠️ fix: Ensure imageOutputType is Always Defined (#2438)
* avatar fix

* chore: ensure `imageOutputType` is always defined

* ci(AppService): extra test for default value

* chore: replace default value for `desiredFormat` with `EImageOutputType` enum
2024-04-16 16:34:19 -04:00
Danny Avila
bf4e64ce63 🪙 fix(Google): Update maxOutputTokens Condition (#2434)
- generalize condition to fix max output tokens for gemini-1.5
2024-04-16 10:23:13 -04:00
Danny Avila
9d854dac07 🤖 feat: Gemini 1.5 Support (+Vertex AI) (#2383)
* WIP: gemini-1.5 support

* feat: extended vertex ai support

* fix: handle possibly undefined modelName

* fix: gpt-4-turbo-preview invalid vision model

* feat: specify `fileConfig.imageOutputType` and make PNG default image conversion type

* feat: better truncation for errors including base64 strings

* fix: gemini inlineData formatting

* feat: RAG augmented prompt for gemini-1.5

* feat: gemini-1.5 rates and token window

* chore: adjust tokens, update docs, update vision Models

* chore: add back `ChatGoogleVertexAI` for chat models via vertex ai

* refactor: ask/edit controllers to not use `unfinished` field for google endpoint

* chore: remove comment

* chore(ci): fix AppService test

* chore: remove comment

* refactor(GoogleSearch): use `GOOGLE_SEARCH_API_KEY` instead, issue warning for old variable

* chore: bump data-provider to 0.5.4

* chore: update docs

* fix: condition for gemini-1.5 using generative ai lib

* chore: update docs

* ci: add additional AppService test for `imageOutputType`

* refactor: optimize new config value `imageOutputType`

* chore: bump CONFIG_VERSION

* fix(assistants): avatar upload
2024-04-16 08:32:40 -04:00
Danny Avila
fce7246ac1 🔓 refactor: Make Image URL Security Optional (#2415) 2024-04-14 19:34:13 -04:00
Danny Avila
2cc580ba52 *️⃣ refactor(DeleteButton): Conversation List Behavior after Deletion (#2414)
* Refactor DeleteButton component in client/src/components/Conversations/DeleteButton.tsx

* chore: bump data-provider package

* chore: remove console.log
2024-04-14 19:11:55 -04:00
Danny Avila
d2d9ac0280 feat: Add 'EnterToSend' Option & Update Br. Translation 🇧🇷 (#2413)
* chore: Add EnterToSend, Translation Portuguese Brazilian Update

* Inverted selection and corrected translation

* fix: removed Trailing spaces not allowed

* feat: Refactor key event handler & updated translations

* fix: removed return; & updated files translations

* fix: duplicate switchs on General.tsx

* fix: added again switch

* refactor(useTextarea): limit refactoring of handleKeyDown

* refactor: correct keyDown handler and add English localization

---------

Co-authored-by: Raí Santos <140329135+itzraiss@users.noreply.github.com>
Co-authored-by: Raí Santos <raimorningstarchristus@gmail.com>
2024-04-14 19:06:20 -04:00
Ventz Petkov
f380f261a5 🛂 fix: OIDC Username Array Edge Case (#2394)
* Patch for OpenID username

`username` is generally based on email, rather than `given_name`. The challenge with `given_name` is that it can be a multi-value array (ex: "Nick, Fullname"), which completely breaks the system with: 

```
LibreChat      | ValidationError: User validation failed: username: Cast to string failed for value "[ 'Nickname', 'Firstname' ]" (type Array) at path "username"
LibreChat      |     at Document.invalidate (/app/node_modules/mongoose/lib/document.js:3200:32)
LibreChat      |     at model.$set (/app/node_modules/mongoose/lib/document.js:1459:12)
LibreChat      |     at model.set [as username] (/app/node_modules/mongoose/lib/helpers/document/compile.js:205:19)
LibreChat      |     at OpenIDConnectStrategy._verify (/app/api/strategies/openidStrategy.js:127:27)
LibreChat      |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
```

* Update openidStrategy.js

* refactor(openidStrategy): add helper function for stringy username

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
2024-04-12 12:39:11 -04:00
jp789
9d137ce42f 📑 docs: Add claude haiku to example anthropic models (#2391)
Co-authored-by: juliaanp <juliaan.posaratnanathan@zafin.com>
2024-04-11 15:31:04 -04:00
Melaton
25f92dd1c3 🌎 : Update chinese localization (#2384)
* 🌍 Update Chinese Translation

Update Simplified Chinese Translation

* Update Chinese Translation

Formatting file, adding new translations, delete unused translations
2024-04-11 11:23:23 -04:00
Danny Avila
9277e2a0c5 🔒 feat: Authenticated Image Requests (#2389)
* 🔒 feat: Authenticated Image Requests

* fix: reserved keyword `static`
2024-04-11 02:50:57 -04:00
Danny Avila
c19dfddd0f 👷 fix: Minor Fixes and Refactors (#2388)
* refactor(useTextarea): set Textarea disabled message due to key higher in priority

* fix(SidePanel): intended behavior for non-user provided keys

* fix: generate specs

* style: update combobox styling as before, with better dynamic height

* chore: remove unused import
2024-04-11 02:12:48 -04:00
Danny Avila
0fe47cf1f8 🤖 feat: Update Context Limit for gpt-3.5-turbo (#2381) 2024-04-10 15:10:21 -04:00
Danny Avila
8e5f1ad575 📦 feat: Model & Assistants Combobox for Side Panel (#2380)
* WIP: dynamic settings

* WIP: update tests and validations

* refactor(SidePanel): use hook for Links

* WIP: dynamic settings, slider implemented

* feat(useDebouncedInput): dynamic typing with generic

* refactor(generate): add `custom` optionType to be non-conforming to conversation schema

* feat: DynamicDropdown

* refactor(DynamicSlider): custom optionType handling and useEffect for conversation updates elsewhere

* refactor(Panel): add more test cases

* chore(DynamicSlider): note

* refactor(useDebouncedInput): import defaultDebouncedDelay from ~/common`

* WIP: implement remaining ComponentTypes

* chore: add com_sidepanel_parameters

* refactor: add langCode handling for dynamic settings

* chore(useOriginNavigate): change path to '/c/'

* refactor: explicit textarea focus on new convo, share textarea idea via ~/common

* refactor: useParameterEffects: reset if convo or preset Ids change, share and maintain statefulness in side panel

* wip: combobox

* chore: minor styling for Select components

* wip: combobox select styling for side panel

* feat: complete combobox

* refactor: model select for side panel switcher

* refactor(Combobox): add portal

* chore: comment out dynamic parameters panel for future PR and delete prompt files

* refactor(Combobox): add icon field for options, change hover bg-color, add displayValue

* fix(useNewConvo): proper textarea focus with setTimeout

* refactor(AssistantSwitcher): use Combobox

* refactor(ModelSwitcher): add textarea focus on model switch
2024-04-10 14:27:22 -04:00
matt burnett
f64a2cb0b0 🧑‍🎨 style: Remove Plugins Icon Background (#2368) 2024-04-10 07:30:56 -04:00
Walber Cardoso
e4c07eb895 👟 style: CodeAnalyze Animation (#2348)
* refactor(CodeAnaluzer SVG)

* refactor(CodeAnalyzer SVG)

* style: center terminal animation, reduce scaling

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
2024-04-09 20:34:22 -04:00
Melaton
2240fee44a 🌍: Update Chinese Translation (#2351)
Update Simplified Chinese Translation
2024-04-09 19:43:24 -04:00
Danny Avila
cb64b84846 ⬇️ refactor: Assistant File Downloads (#2364)
* refactor(getFiledownload): explicit accept of `application/octet-stream`

* chore: test compose file

* chore: test compose file fix

* chore(files/download): add more logs

* Fix proxy_pass URLs in nginx.conf

* fix: proxy_pass URLs in nginx.conf to fix file downloads from URL

* chore: move test compose file to utils dir

* refactor(useFileDownload): simplify API request by passing `file_id` instead of `filepath`
2024-04-09 14:26:46 -04:00
Danny Avila
cc71125fa1 🎨 feat: Title Improvements (#2363)
* fix(assistants): keep generated title upon continued messages in active conversation

* feat: update document.title on successful gentitle mutation
2024-04-09 14:01:27 -04:00
Danny Avila
6f0eb35365 🐞 fix: Balance and Token Usage Improvements (#2350)
* fix(processModelData): handle `openrouter/auto` edge case

* fix(Tx.create): prevent negative multiplier edge case and prevent balance from becoming negative

* fix(NavLinks): render 0 balance properly

* refactor(NavLinks): show only up to 2 decimal places for balance

* fix(OpenAIClient/titleConvo): fix cohere condition and record token usage for `this.options.titleMethod === 'completion'`
2024-04-07 23:28:40 -04:00
Danny Avila
3411d7a543 🚀 feat: Enhance Message Editing with File Resubmission (#2347)
* chore: fix type issue with File Table fakeData

* refactor: new lazy loading image strategy and load images/files as part of Message Container

* feat: resubmit files when editing messages with attached files
2024-04-07 13:25:24 -04:00
Danny Avila
caabab4489 ⚠️ docs: Default Value Warnings & Docker Docs Update (#2343)
* feat(AppService): default secret value warnings

* docs: update docker/ubuntu related guides
2024-04-06 18:20:48 -04:00
chrislbrown84
0b165260f7 📘 docs: Add Note to nginx.md (#2341)
added reference for the need to do 'sudo apt update'
2024-04-06 17:05:55 -04:00
Danny Avila
334b603247 🚧 refactor: Attempt Default Preset Fix & Other Changes (#2342)
* fix(useTextarea): trigger SendButton re-render on undo and clearing text

* refactor(PresetItems): show pin icon for default preset

* fix(ChatRoute): do not use conversation.model for useEffect, do not set default Preset if real model list is not yet fetched
2024-04-06 16:09:16 -04:00
David LaPorte
476767355b 🚅 docs(ai_endpoints): Reflect correct LiteLLM baseURL when using docker-compose (#2324)
Added note to LiteLLM baseURL to reflect docker-compose usage
2024-04-05 19:35:34 -04:00
Ventz Petkov
e80debb704 🚅 docs: Working Examples for LiteLLM, Docker, LibreChat and LiteLLM models for AWS, Azure, GCP (#2323)
Updated documentation with working config examples and clarifying many details.

Added working examples for:
* LiteLLM (litellm/litellm-config.yaml)
* Docker (docker-compose.override.yml)
* LibreChat (librechat.yaml)

Added LiteLLM "ready to use" model for:
* AWS Bedrock
* Azure OpenAI
* OpenAI
* GCP
2024-04-05 19:34:11 -04:00
Ventz Petkov
549026f677 🚦 docs: Update traefik.md - Documentation Fix for edge case race condition (#2322)
Sometimes Traefik created a race condition where LibreChat was up on tcp/3080, and while Traefik was up on tcp/443, it could not route to the LibreChat container due to the multiple interfaces -- depending on how they came up. This is easily solved by simply using one interface.
2024-04-05 19:32:51 -04:00
Danny Avila
f6a84887e1 💽 refactor(client): Optimize ModelsConfig Query Cache (#2330)
* refactor(client): remove double caching of models via recoil to rely exclusively on react-query

* chore(useConversation): add modelsQuery.data dep to callback
2024-04-05 17:08:37 -04:00
Danny Avila
fb80af05be 🧠 fix(Cohere): map to expected SDK params (#2329) 2024-04-05 16:45:18 -04:00
Danny Avila
cd7f3a51e1 🧠 feat: Cohere support as Custom Endpoint (#2328)
* chore: bump cohere-ai, fix firebase vulnerabilities by going down versions

* feat: cohere rates and context windows

* feat(createCoherePayload): transform openai payload for cohere compatibility

* feat: cohere backend support

* refactor(UnknownIcon): optimize icon render and add cohere

* docs: add cohere to Compatible AI Endpoints

* Update ai_endpoints.md
2024-04-05 15:19:41 -04:00
Paul
daa5f43ac6 📝 docs: Correct Google OAuth Callback URL Example (#2311) 2024-04-04 13:36:06 -04:00
ochen1
d0d8e47ec8 🐋 refactor(Dockerfile.multi): Optimize client build by caching npm install step (#2275)
* 🐋 fix(Dockerfile): Optimize client build by caching npm install step

* 🐋 fix(Dockerfile): Possible interference from librechat-data-provider in client build
2024-04-04 08:58:34 -04:00
Marius
09cd1a7e74 🦙 docs: Update Ollama + LiteLLM Instructions (#2302)
* Update litellm.md

* set OPENAI_API_KEY of litellm service (needs to be set if ollama's openai api compatibility is used)
2024-04-04 08:32:36 -04:00
Ventz Petkov
94950b6e8b 🚥 docs: fixed Traefik web layout (#2305)
Fixed Traefik config for broken web rending
2024-04-04 08:08:31 -04:00
Danny Avila
e418edd3dc 🔧 fix: Catch deleteVectors Errors & Update RAG API docs (#2299)
* fix(deleteVectors): handle errors gracefully

* chore: update docs based on new alternate env vars prefixed with RAG to avoid conflicts with LibreChat keys
2024-04-03 14:24:46 -04:00
Marco Beretta
e3c236ba3b 🔄 chore: converted translation files to .ts (#2288)
* chore: converted translation files to

* chore(Sv.ts): removed  and the comment

* chore: add  comment
2024-04-02 14:35:35 -04:00
Danny Avila
7bd03a6e70 🛠️ fix: Correct Unwanted Newlines after Undo in Textarea (#2289)
* docs: edit docker_override note for deploy-compose

* 🛠️  fix: Correct Unwanted Newlines after Undo in Textarea
2024-04-02 12:14:42 -04:00
happy_ryo
f146db5c59 🌍: Add new Japanese Localization entries (#2282) 2024-04-02 10:00:40 -04:00
Andi
9922baf7d1 🔗 docs: Fix Link to Docker Compose Override File (#2287) 2024-04-02 09:19:10 -04:00
Danny Avila
09da05afa1 🔨 fix(ToolService): remove userId filter from loadActionSets & Docs Update (#2286)
* fix(ToolService): remove userId filter from `loadActionSets`

* docs: updates to rag_api and docker_override explaining key variable conflicts
2024-04-02 09:11:30 -04:00
illgitthat
e66aa280c0 📝 docs: Remove Google Domains Reference (#2267) 2024-04-02 03:26:35 -04:00
Till Zoppke
ed17e17a73 📖 docs: Note on 'host.docker.internal' for Ollama Config (#2274)
* docs: update URL to access ollama and comment on 'host.docker.internal'

* Update ai_endpoints.md

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-04-02 03:25:15 -04:00
Christoph Reiter
30d084e696 🐋 fix(Dockerfile): Create Necessary Directories at Build time (#2277)
When creating volumes for /app/client/public/images and /app/api/logs
docker will inherit the permissions from the existing directores in the
image. Since they are missing it defaults to root, and since
librechat now uses the "node" user instead of "root" storing images,
files and logs will fail.

Fix by creating those directories in the docker image with the node
user, so that if docker creates the volumes the permissions are inherited
and the directories are owned by "node" and not "root".
2024-04-02 03:20:41 -04:00
Zentix
93af814596 📗 docs: Update NagaAI (#2278) 2024-04-02 03:09:37 -04:00
Danny Avila
1bafe80e78 🛂 feat: Required OpenID Role (#2279)
* feat: add possibility to filter by roles for OpenID provider

---------

Co-authored-by: Sirius <siriusfrk@gmail.com>
2024-04-02 03:08:17 -04:00
Danny Avila
49753a35e5 v0.7.0 (#2273) 2024-04-01 19:24:01 -04:00
Danny Avila
1605ef3793 🐳 hotfix: Tag Images Workflow Update (#2272) 2024-04-01 19:04:37 -04:00
Danny Avila
8b3f80fe24 🐳 hotfix: Necessary Dockerfile Update (#2271)
* chore: remove version comment from pre-commit shell script

* chore: Dockerfile update
2024-04-01 18:46:12 -04:00
bsu3338
038063d4d1 🐞Fix: Stable Diffusion User Directory (#2270) 2024-04-01 15:55:44 -04:00
Danny Avila
5c8b16fbaf v0.7.0 (#2266)
*  v0.7.0

* chore: gitignore

* 🐳 ci: update release image workflows
2024-04-01 15:48:57 -04:00
Danny Avila
aff219c655 📋 fix: Ensure Textarea Resizes in Clipboard Edge Case (#2268)
* chore: ts-ignore fake conversation data used for testing

* chore(useTextarea): import helper functions to declutter hook

* fix(Textarea): reset textarea value explicitly by resetting `textAreaRef.current.value`
2024-04-01 13:40:21 -04:00
Danny Avila
d07396d308 🐞 fix: Handle Empty Model Error in Assistants Form (#2265) 2024-04-01 09:20:11 -04:00
pxz2016
cc92597f14 🐞 fix: Handle Garbled Chinese Characters in File Upload (#2261)
Co-authored-by: 彭修照 <pengxiuzhao.uh@haier.com>
2024-04-01 08:25:36 -04:00
Danny Avila
4854b39f41 🚀 feat: Add CLI Helper Scripts to API Container Image (#2257) 2024-03-31 18:59:07 -04:00
Danny Avila
bb8a40dd98 🎨 fix: Optimize StableDiffusion API Tool and Fix for Assistants Usage (#2253)
* chore: update docs

* fix(StableDiffusion): optimize API responses and file handling, return expected metadata for Assistants endpoint
2024-03-30 20:09:59 -04:00
Danny Avila
56ea0f9ae7 🐳 feat: RAG for Default Docker Compose Files + Docs Update (#2246)
* refactor(deploy-compose.yml): use long-syntax to avoid implicit folder creation of librechat.yaml

* refactor(docker-compose.override.yml.example): use long-syntax to avoid implicit folder creation of librechat.yaml

* chore: add simple health check for RAG_API_URL

* chore: improve axios error handling, adding `logAxiosError`

* chore: more informative message detailing RAG_API_URL path

* feat: add rag_api and vectordb to default compose file

* chore(rag.yml): update standalone rag compose file to use RAG_PORT

* chore: documentation updates

* docs: Update rag_api.md with images

* Update rag_api.md

* Update rag_api.md, assistants clarification

* add RAG API note to breaking changes
2024-03-29 21:15:36 -04:00
Danny Avila
6a6b2e79b0 🔧 fix: Improve Assistants File Citation & Download Handling (#2248)
* fix(processMessages): properly handle assistant file citations and add sources list

* feat: improve file download UX by making any downloaded files accessible within the app post-download

* refactor(processOpenAIImageOutput): correctly handle two different outputs for images since OpenAI generates a file in their storage, shares filepath for image rendering

* refactor: create `addFileToCache` helper to use across frontend

* refactor: add ImageFile parts to cache on processing content stream
2024-03-29 19:09:16 -04:00
Danny Avila
bc2a628902 🌍 fix(Translations): Map Partial langCode and Add Unit Tests (#2240) 2024-03-29 12:17:07 -04:00
Danny Avila
dec7879cc1 refactor(loadConfigModels): Stricter Default Model Fallback (#2239)
* chore: add TEndpoint type/typedef

* refactor(loadConfigModels.spec): stricter default model matching (fails with current impl.)

* refactor(loadConfigModels): return default models on endpoint basis and not fetch basis

* refactor: rename `uniqueKeyToNameMap` to `uniqueKeyToEndpointsMap` for clarity
2024-03-29 11:49:38 -04:00
Danny Avila
0a8118deed 🗨️ fix(useSSE): Prevent 'New Chat' Title after Regenerating Initial Message (#2238) 2024-03-29 10:56:51 -04:00
Raí Santos
59a8165379 🌍 : Updated & Added new Portuguese and Spanish Translations (#2228)
* 🌍 : Updated & Added news Portuguese and Spanish Translations

* fix: \' to "

* fix(Br.tsx): revert Snyk placeholders

* fix(Es.tsx): revert Snyk placeholders

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
2024-03-29 10:50:09 -04:00
Danny Avila
3a1d07136c refactor(loadConfigModels): Fallback to Default Models if Fetch Fails (#2236) 2024-03-29 10:43:36 -04:00
Danny Avila
a00756c469 ⬇️ feat: Assistant File Downloads (#2234)
* WIP: basic route for file downloads and file strategy for generating readablestream to pipe as res

* chore(DALLE3): add typing for OpenAI client

* chore: add `CONSOLE_JSON` notes to dotenv.md

* WIP: first pass OpenAI Assistants File Output handling

* feat: first pass assistants output file download from openai

* chore: yml vs. yaml variation to .gitignore for `librechat.yml`

* refactor(retrieveAndProcessFile): remove redundancies

* fix(syncMessages): explicit sort of apiMessages to fix message order on abort

* chore: add logs for warnings and errors, show toast on frontend

* chore: add logger where console was still being used
2024-03-29 08:23:38 -04:00
Fuegovic
7945fea0f9 ✏️ doc update: dotenv.md (#2226) 2024-03-27 16:29:40 -04:00
Ivan Dachev
84656b9812 💽 feat: Add Script for User Stats (#2224) 2024-03-27 14:41:29 -04:00
Fuegovic
b5d25f5e4f 🔎 chore: bump meilisearch v1.7 / v0.38.0 (#2175)
* 🔎 chore: bump meilisearch v1.7 / v0.38.0

* ✏️ breaking_changes.md
2024-03-27 10:08:20 -04:00
Ivan Dachev
d4b0af3dba 💽 feat: Add CONSOLE_JSON for deploying to GCP K8S env (#2146)
* Add CONSOLE_JSON

* Update example env

* Moved to utils
2024-03-27 10:07:04 -04:00
suzuki.sh
57d1f12574 🔗 docs: Fix Link to Code of Conduct (#2206)
Fix link to Code of Conduct
2024-03-26 19:29:22 -04:00
Danny Avila
182c9f7080 🔍 chore: Clean Up Documentation Pt. 4 (#2220) 2024-03-26 14:02:22 -04:00
Danny Avila
5df0ec06ea 🔍 chore: Clean Up Documentation Part 3 (#2219) 2024-03-26 13:57:25 -04:00
Danny Avila
ea54cf03e9 🔍 chore: Clean Up Documentation Part 2 (#2218) 2024-03-26 13:48:20 -04:00
Danny Avila
7f83a060a0 🔍 chore: Clean Up Documentation (#2217)
* fix(initializeClient.spec.js): remove condition failing test on local installations

* docs: remove comments and invalid html as is required by embeddings generator and add new documentation guidelines
2024-03-26 13:40:00 -04:00
Danny Avila
2259bf8b03 🚀 feat: Add GitHub Actions Workflow for Generating Docs Embeddings (#2216) 2024-03-26 11:57:04 -04:00
Danny Avila
5c3c28009f 🧹 chore: Update Docker Docs & Make cache field Optional for Custom Config (#2211)
* docs: updating docker

* fix(customConfig): make `cache` field optional as intended (though not recommended for local setups)
2024-03-26 05:45:20 -04:00
Danny Avila
f55bd3d0e9 🎨 style: Ensure Side Panel state Remains on Refresh (#2210) 2024-03-26 05:21:40 -04:00
Danny Avila
718572b7c8 🎨 style: Refine SidePanel and Textarea Styling (#2209)
* experimental: use TextareaAutosize wrapper with useLayoutEffect to hopefully fix random textarea jankiness

* fix(Textarea): force a resize when placeholder text changes

* style(ScrollToBottom): update styling for scroll button

* style: memoize values and improve side panel toggle states

* refactor(SidePanel): more control for toggle states, new hide panel button, and improve toggle state logic

* chore: hide resizable panel handle on smaller screens
2024-03-26 04:19:51 -04:00
Florian Kohrt
cb62847838 📖 docs: Add details for Azure OpenAI Assistants (#2173)
The default `.env` contains the line `ASSISTANTS_API_KEY=user_provided`. When pre-configuring Azure OpenAI models, this setting makes it impossible to use assistants due to a missing user provided key. Only by commenting the line out the Azure setup works.
2024-03-25 18:27:36 -04:00
Danny Avila
3ef46132eb 🐞 fix(client): Prevent Async Reset of Latest Message (#2203)
* refactor: use debug statement runStepCompleted message

* fix(ChatRoute): prevent use of `newConversation` from reseting `latestMessage`, which would fire asynchronously and finalize after `latestMessage` was already correctly set
2024-03-25 11:16:18 -04:00
Danny Avila
8fc52348e8 🌟 fix: Handle Assistants Edge Cases, Improve Filter Styling (#2201)
* fix(assistants): default query to limit of 100 and `desc` order

* refactor(useMultiSearch): use object as params and fix styling for assistants

* feat: informative message for thread initialization failing due to long message
2024-03-25 08:55:33 -04:00
Fuegovic
a4f4ec85f8 🧑‍💻docs: Update General Docs and Contribution Guidelines (#2194)
* doc upddate: documentation_guidelines.md

* doc upddate: how_to_contribute.md

* doc upddate: testing.md / how_to_contribute.md

* doc upddate: translation_contribution.md/testing.md/how_to_contribute.md

* doc upddate: coding_conventions.md

* fix formatting: how_to_contribute.md

* fix formatting (again) : how_to_contribute.md
2024-03-25 07:26:43 -04:00
Danny Avila
f86d80de59 🔧 fix(assistants): Vision minor fix & Add Docs (#2196)
* 👓 fix(assistants): Only Retrieve Assistant Data for Vision Requests if attachments exist in Host Storage

* docs: add  capability
2024-03-25 00:02:54 -04:00
Danny Avila
798e8763d0 👓 feat: Vision Support for Assistants (#2195)
* refactor(assistants/chat): use promises to speed up initialization, initialize shared variables, include `attachedFileIds` to streamRunManager

* chore: additional typedefs

* fix(OpenAIClient): handle edge case where attachments promise is resolved

* feat: createVisionPrompt

* feat: Vision Support for Assistants
2024-03-24 23:43:00 -04:00
Danny Avila
1f0fb497f8 🎉 feat: Optimizations and Anthropic Title Generation (#2184)
* feat: add claude-3-haiku-20240307 to default anthropic list

* refactor: optimize `saveMessage` calls mid-stream via throttling

* chore: remove addMetadata operations and consolidate in BaseClient

* fix(listAssistantsForAzure): attempt to specify correct model mapping as accurately as possible (#2177)

* refactor(client): update last conversation setup with current assistant model, call newConvo again when assistants load to allow fast initial load and ensure assistant model is always the default, not the last selected model

* refactor(cache): explicitly add TTL of 2 minutes when setting titleCache and add default TTL of 10 minutes to abortKeys cache

* feat(AnthropicClient): conversation titling using Anthropic Function Calling

* chore: remove extraneous token usage logging

* fix(convos): unhandled edge case for conversation grouping (undefined conversation)

* style: Improved style of Search Bar after recent UI update

* chore: remove unused code, content part helpers

* feat: always show code option
2024-03-23 20:21:40 -04:00
Florian Kohrt
8e7816468d 📚 docs: Fix Broken Links (#2171)
Fix broken links to the custom config file on `timeoutMs` and `supportedIds`.
2024-03-23 11:05:52 -04:00
Danny Avila
45a95acec2 📂 feat: RAG Improvements (#2169)
* feat: new vector file processing strategy

* chore: remove unused client files

* chore: remove more unused client files

* chore: remove more unused client files and move used to new dir

* chore(DataIcon): add className

* WIP: Model Endpoint Settings Update, draft additional context settings

* feat: improve parsing for augmented prompt, add full context option

* chore: remove volume mounting from rag.yml as no longer necessary
2024-03-22 19:07:08 -04:00
Danny Avila
f427ad792a 🚀 feat: Assistants Streaming (#2159)
* chore: bump openai to 4.29.0 and npm audit fix

* chore: remove unnecessary stream field from ContentData

* feat: new enum and types for AssistantStreamEvent

* refactor(AssistantService): remove stream field and add conversationId to text ContentData
> - return `finalMessage` and `text` on run completion
> - move `processMessages` to services/Threads to avoid circular dependencies with new stream handling
> - refactor(processMessages/retrieveAndProcessFile): add new `client` field to differentiate new RunClient type

* WIP: new assistants stream handling

* chore: stores messages to StreamRunManager

* chore: add additional typedefs

* fix: pass req and openai to StreamRunManager

* fix(AssistantService): pass openai as client to `retrieveAndProcessFile`

* WIP: streaming tool i/o, handle in_progress and completed run steps

* feat(assistants): process required actions with streaming enabled

* chore: condense early return check for useSSE useEffect

* chore: remove unnecessary comments and only handle completed tool calls when not function

* feat: add TTL for assistants run abort cacheKey

* feat: abort stream runs

* fix(assistants): render streaming cursor

* fix(assistants): hide edit icon as functionality is not supported

* fix(textArea): handle pasting edge cases; first, when onChange events wouldn't fire; second, when textarea wouldn't resize

* chore: memoize Conversations

* chore(useTextarea): reverse args order

* fix: load default capabilities when an azure is configured to support assistants, but `assistants` endpoint is not configured

* fix(AssistantSelect): update form assistant model on assistant form select

* fix(actions): handle azure strict validation for function names to fix crud for actions

* chore: remove content data debug log as it fires in rapid succession

* feat: improve UX for assistant errors mid-request

* feat: add tool call localizations and replace any domain separators from azure action names

* refactor(chat): error out tool calls without outputs during handleError

* fix(ToolService): handle domain separators allowing Azure use of actions

* refactor(StreamRunManager): types and throw Error if tool submission fails
2024-03-21 22:42:25 -04:00
Hermes Trismegistus
ed64c76053 📖 docs: Update ShuttleAI Fibonacci Image (#2160) 2024-03-21 22:41:58 -04:00
Danny Avila
25a0487ce5 chore: Revise of PR #2157, move global steps earlier, execute as root 2024-03-21 12:33:30 -04:00
Danny Avila
3f77fe18b7 🐋 chore: Revise of PR #2157, move step earlier 2024-03-21 12:28:40 -04:00
Danny Avila
09de9a2b42 🐋 fix(Dockerfile): add back additional deps., handle permissions, use --no-audit flag on install (#2157) 2024-03-21 12:24:40 -04:00
Danny Avila
a673f62831 🐋 chore: Cleanup Dockerfile (#2156) 2024-03-21 11:18:53 -04:00
Danny Avila
e0dd0381b2 🌑 style(File Manager): Localize and Update Dark Mode Stylings (#2155)
* 🌑 style: Update Dark Mode Stylings for File Manager

* 🌐 feat: localize file manager text

* 🌐 feat: file panel table localization
2024-03-21 10:52:45 -04:00
Hermes Trismegistus
1ee2c32a67 🚀 feat: Add ShuttleAI as Known Endpoint (#2152)
Added new Official Known Endpoint (ShuttleAI)
2024-03-21 09:17:57 -04:00
Flynn
f521040784 🔧 fix(menu): Menu Item Filter Improvements (#2153)
* small-fix: Ensure that fake seperators in model lists do not show in search

* Ensure Plugin search uses correct placeholder and key filtering in search
2024-03-21 09:15:25 -04:00
Marco Beretta
30f6d90cfe 🖌️ style: Improve Dark Theme Accessibility (#2125)
* style: all landing page components

* chore: converted all slate to gray, since slate doesnt work

* style: assistant panel

* style: basic UI components, userprovided, preset

* style: update in multiple components

* fix(PluginStoreDialog): justify-center

* fixed some minor Ui styles

* style(MultiSearch): update dark bg

* style: update Convo styling

* style: lower textarea max height slightly

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-03-21 09:02:00 -04:00
Walber Cardoso
e95c0aaaed 🔧 style(fix): Convo Fade Effect (#2147)
* 🔧 (fix) Convo Fade Effect

* 🔧style(fix): Convo Fade Effect (#2117)

* 🔧 style(fix): Convo Fade Effect (#2117)
2024-03-21 08:39:43 -04:00
Danny Avila
9bab595204 🔬 chore: Add Circular Dependency Check to backend-review (#2149)
* 🔬 chore: Add Circular Dependency check to `backend-review`

* chore: touch random file for workflow trigger

* chore: workflow step order

* chore: update workflow to create empty auth.json file

* fix: attempt empty auth.json creation

* chore: add test_bundle ESLint ignore pattern
2024-03-20 12:15:42 -04:00
Danny Avila
4f17d97eb2 fix(sendEmail): circular dependency 2024-03-20 11:52:05 -04:00
Danny Avila
e4ac58012f 📧 fix: Correct Handling of Self-Signed Certificates in sendEmail (#2148)
- note: To put it in a different way, if you put rejectUnauthorized: true, it means that self-signed certificates should not be allowed. This means, that EMAIL_ALLOW_SELFSIGNED is set to false
2024-03-20 11:48:54 -04:00
Danny Avila
f7761df52c 🗃️ feat: General File Support for OpenAI, Azure, Custom, Anthropic and Google (RAG) (#2143)
* refactor: re-purpose `resendImages` as `resendFiles`

* refactor: re-purpose `resendImages` as `resendFiles`

* feat: upload general files

* feat: embed file during upload

* feat: delete file embeddings on file deletion

* chore(fileConfig): add epub+zip type

* feat(encodeAndFormat): handle non-image files

* feat(createContextHandlers): build context prompt from file attachments and successful RAG

* fix: prevent non-temp files as well as embedded files to be deleted on new conversation

* fix: remove temp_file_id on usage, prevent non-temp files as well as embedded files to be deleted on new conversation

* fix: prevent non-temp files as well as embedded files to be deleted on new conversation

* feat(OpenAI/Anthropic/Google): basic RAG support

* fix: delete `resendFiles` only when true (Default)

* refactor(RAG): update endpoints and pass JWT

* fix(resendFiles): default values

* fix(context/processFile): query unique ids only

* feat: rag-api.yaml

* feat: file upload improved ux for longer uploads

* chore: await embed call and catch embedding errors

* refactor: store augmentedPrompt in Client

* refactor(processFileUpload): throw error if not assistant file upload

* fix(useFileHandling): handle markdown empty mimetype issue

* chore: necessary compose file changes
2024-03-19 20:54:30 -04:00
SailFlorve
af347cccde 🎨 style: HoverButton UI adjustment, change code font (#2017)
* style: HoverButton UI adjustment

* style: make Consolas as default code font

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-03-19 13:55:41 -04:00
Danny Avila
86db0a1043 Revert "🔧 style(fix): Convo Title Fade Effect (#2117)" (#2139)
This reverts commit 1796821888.
2024-03-19 13:54:35 -04:00
Walber Cardoso
1796821888 🔧 style(fix): Convo Title Fade Effect (#2117)
* feat: Improve Google search plugin to assistants

* 🔧 fix(Nav SidePanel): Center buttons when collapsed

* 🔧(fix) Convo title fade effect

* 🔧(fix) Convo title fade effect / remove deletion

* 🔧(fix) Convo title fade effect / remove deletion .env.example

* 🔧(fix) Convo title fade effect

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-03-19 13:43:24 -04:00
Ido Ophir
d8304ec1bb 📋 chore: add requirements.txt to documentation (#2122)
* chore: add requirements.txt to documentation, to ease maintenance

* docs: Update documentation_guidelines.md
2024-03-19 13:38:18 -04:00
Danny Avila
382b303963 🔍 feat: Filter MultiSelect and SelectDropDown (+variants) + CSS fixes for Scrollbar (#2138)
* Initial implementation of MultiSearch. Added implementation to MultiSelect and SelectDropDown and variants

* Update scrollbar styles to prevent breakages on Chrome

* Revert changes to vite.config.ts (redundant for now)

* chore(New Chat): organize imports

* style(scrollbar-transparent): use webkit as standard, expected behavior

* chore: useCallback for mouse enter/leave

* fix(Footer): resolve map key error

* chore: memoize Conversations

* style(MultiSearch): improve multisearch styling

* style: dark mode search input

* fix: react warnings due to unrecognize html props

* chore: debounce OpenAI settings inputs

* fix(useDebouncedInput): only use event value as newValue if not object

---------

Co-authored-by: Flynn <gpg@flyn.ca>
2024-03-19 13:35:10 -04:00
Danny Avila
f51ac74e12 🪰 fix: Azure Parsing and Assistants Payload (#2133)
* fix(azure): fix regex to prevent edge cases

* fix(assistants): pass relevant endpoint options to avoid sending them to API
2024-03-18 19:48:42 -04:00
Danny Avila
7cddd943d0 🔧 feat(actions): Allow Multiple Actions from Same Domain per Assistant (#2120) 2024-03-16 19:40:51 -04:00
Danny Avila
89f6b35e6c 🔧 fix: Remove Unique Index from Actions Model and Initialize Empty Actions for Deletion (#2118) 2024-03-16 18:53:43 -04:00
Danny Avila
a8cdd3460c 🔧 feat: Share Assistant Actions between Users (#2116)
* fix: remove unique field from assistant_id, which can be shared between different users

* refactor: remove unique user fields from actions/assistant queries

* feat: only allow user who saved action to delete it

* refactor: allow deletions for anyone with builder access

* refactor: update user.id when updating assistants/actions records, instead of searching with it

* fix: stringify response data in case it's an object

* fix: correctly handle path input

* fix(decryptV2): handle edge case where value is already decrypted
2024-03-16 16:49:11 -04:00
Marco Beretta
2f90c8764a 🖊️ fix(MessageContent): Error Message typo (#2112) 2024-03-16 13:05:56 -04:00
Fuegovic
39042f8761 🎨 style: Privacy Policy & Terms of Service (#2111) 2024-03-16 13:05:18 -04:00
Danny Avila
a9d2d3fe40 🪙 feat: Assistants Token Balance & other improvements (#2114)
* chore: add assistants to supportsBalanceCheck

* feat(Transaction): getTransactions and refactor export of model

* refactor: use enum: ViolationTypes.TOKEN_BALANCE

* feat(assistants): check balance

* refactor(assistants): only add promptBuffer if new convo (for title), and remove endpoint definition

* refactor(assistants): Count tokens up to the current context window

* fix(Switcher): make Select list explicitly controlled

* feat(assistants): use assistant's default model when no model is specified instead of the last selected assistant, prevent assistant_id from being recorded in non-assistant endpoints

* chore(assistants/chat): import order

* chore: bump librechat-data-provider due to changes
2024-03-15 19:48:42 -04:00
SailFlorve
f848d752e0 🌍 : Update Chinese Translations (#2098) 2024-03-15 16:12:02 -04:00
Fuegovic
8881346889 📑 docs: update .env.example (#2109) 2024-03-15 16:11:31 -04:00
Danny Avila
f769077ab4 🤖 fix(assistants): Default Capabilities and Retrieval Models (#2102) 2024-03-14 20:42:56 -04:00
Danny Avila
5cd5c3bef8 🅰️ feat: Azure OpenAI Assistants API Support (#1992)
* chore: rename dir from `assistant` to plural

* feat: `assistants` field for azure config, spread options in AppService

* refactor: rename constructAzureURL param for azure as `azureOptions`

* chore: bump openai and bun

* chore(loadDefaultModels): change naming of assistant -> assistants

* feat: load azure settings with currect baseURL for assistants' initializeClient

* refactor: add `assistants` flags to groups and model configs, add mapGroupToAzureConfig

* feat(loadConfigEndpoints): initialize assistants endpoint if azure flag `assistants` is enabled

* feat(AppService): determine assistant models on startup, throw Error if none

* refactor(useDeleteAssistantMutation): send model along with assistant id for delete mutations

* feat: support listing and deleting assistants with azure

* feat: add model query to assistant avatar upload

* feat: add azure support for retrieveRun method

* refactor: update OpenAIClient initialization

* chore: update README

* fix(ci): tests passing

* refactor(uploadOpenAIFile): improve logging and use more efficient REST API method

* refactor(useFileHandling): add model to metadata to target Azure region compatible with current model

* chore(files): add azure naming pattern for valid file id recognition

* fix(assistants): initialize openai with first available assistant model if none provided

* refactor(uploadOpenAIFile): add content type for azure, initialize formdata before azure options

* refactor(sleep): move sleep function out of Runs and into `~/server/utils`

* fix(azureOpenAI/assistants): make sure to only overwrite models with assistant models if `assistants` flag is enabled

* refactor(uploadOpenAIFile): revert to old method

* chore(uploadOpenAIFile): use enum for file purpose

* docs: azureOpenAI update guide with more info, examples

* feat: enable/disable assistant capabilities and specify retrieval models

* refactor: optional chain conditional statement in loadConfigModels.js

* docs: add assistants examples

* chore: update librechat.example.yaml

* docs(azure): update note of file upload behavior in Azure OpenAI Assistants

* chore: update docs and add descriptive message about assistant errors

* fix: prevent message submission with invalid assistant or if files loading

* style: update Landing icon & text when assistant is not selected

* chore: bump librechat-data-provider to 0.4.8

* fix(assistants/azure): assign req.body.model for proper azure init to abort runs
2024-03-14 17:21:42 -04:00
Flynn
1b243c6f8c 📜 feat: Customize Privacy Policy & Terms of Service (#2091) 2024-03-14 16:43:18 -04:00
Alexei Smirnov
d4190c9320 🌍 : Update Russian Translation (#2061)
* feat(chore): add missing translations in Ru.tsx

* feat(chore): add missing translation for My Files menu and headers

* change com_ui_my_files to com_ui_nav_files

* move useLocalize above utils

* feat(chore): add missing translation for My Files menu and headers
2024-03-14 11:26:44 -04:00
MACHINSOFT
cba135d456 style: Auth Error and Preset Items Styling (#2069)
* Change the style of the error message.

* ui preset items

* fix style

* Change the color of the border and adjust the background of the selected input
2024-03-14 09:07:55 -04:00
Raí Santos
f27e7c720f 🔧 fix: Convo Corners & Updated Colors (#2046)
* 🔧 fix: Convo Corners & Updated Colors

* refactored code

* chore: JSON.parse with a try/catch block, removed useless useEffect & and restored Focus

* restored typescript

* import all back
2024-03-14 09:04:09 -04:00
Danny Avila
1b8c0f0bfd chore: Update AnthropicIcon.tsx 2024-03-13 19:00:22 -04:00
Vilmondes Queiroz
0f417aaec0 🧹 chore: remove unused import (#2072) 2024-03-11 18:27:29 -04:00
Danny Avila
d1c37e8bde 🧊 style: Adjust Endpoint Icons (#2070)
* 🧊 style: Adjust Endpoint Icons

* Update MessageParts.tsx
2024-03-11 13:40:31 -04:00
Danny Avila
0bd8c2ba00 🌑 style(AnthropicIcon): adjust for Dark Mode 2024-03-11 11:36:54 -04:00
Danny Avila
ebcca16b94 🌐 feat: librechat.yaml from URL (#2064)
* feat: librechat.yaml from URL

* doc update: librechat.yaml from URL

* update dotenv.md - typo

* Update loadCustomConfig.js

* ci: specs for loadCustomConfig

* fix(processFileURL): safe destructuring of saveURL result

---------

Co-authored-by: fuegovic <fueg@live.ca>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-03-11 10:52:54 -04:00
MACHINSOFT
f5a754c8be 🖌️ style: Minor UI Updates (#2011)
* UI Design update

* Add an error icon next to the avatar.

* fix

* Change the style of buttons

* fix: avatar
2024-03-11 10:31:32 -04:00
Walber Cardoso
2e77813952 🔧 style(SidePanel): Center buttons when collapsed (#2045)
* feat: Improve Google search plugin to assistants

* 🔧 fix(Nav SidePanel): Center buttons when collapsed
2024-03-11 09:24:38 -04:00
Danny Avila
f307488dd4 ✍️ refactor(Textarea): Optimize Text Input & Enhance UX (#2058)
* refactor(useDebouncedInput): make object as input arg and accept setter

* refactor(ChatForm/Textarea): consolidate textarea/form logic to one component, use react-hook-form, programmatically click send button instead of passing submitMessage, forwardRef and memoize SendButton

* refactor(Textarea): use Controller field value to avoid manual update of ref

* chore: remove forms provider

* chore: memoize AttachFile

* refactor(ChatForm/SendButton): only re-render SendButton when there is text input

* chore: make iconURL bigger

* chore: optimize Root/Nav

* refactor(SendButton): memoize disabled prop based on text

* chore: memoize Nav and ChatForm

* chore: remove textarea ref text on submission

* feat(EditMessage): Make Esc exit the edit mode and dismiss changes when editing a message

* style(MenuItem): Display the ☑️  icon only on the selected model
2024-03-11 09:18:10 -04:00
Fuegovic
f489aee518 📧 update email templates (#2057)
* 📧 chore: update email templates

* 📧 update password reset confirmation
2024-03-11 09:07:09 -04:00
Fuegovic
2f88c5cb8a ✏️ docs: Railway, Traefik, and Improvements (#2060)
* docs: documentation guidelines

* docs: deploy documentation update
2024-03-11 09:06:27 -04:00
Marco Beretta
6fcaeaafe2 🔧 fix(ThemeContext): Listen for Theme Changes (#2037)
* fix(ThemeContext): listen for changes

* fix(Dropdown): theme auto-update not working
2024-03-09 11:36:04 -05:00
Fuegovic
db870e55c3 🔖 chore: update groq models (#2031) 2024-03-09 08:32:08 -05:00
Fuegovic
5d0d02f5f7 🖊️chore: fix deployment guides (#2021) 2024-03-08 08:52:26 -05:00
Danny Avila
40e884b3ec 🖼️ fix: Clipboard Files & File Name Issues (#2015)
* fix: ensure image handling fetchs image to base64 for multiple images

* fix: append file_id's when writing uploaded files

* feat: timestamp files uploaded from clipboard

* chore: add a different fileid+name separator
2024-03-07 12:27:42 -05:00
Danny Avila
18edd2660b 👥 fix(assistants): Improve Error handling (#2012)
* feat: make assistants endpoint appendable since message state is not managed by LibreChat

* fix(ask): search currentMessages for thread_id if it's not defined

* refactor(abortMiddleware): remove use of `overrideProps` and spread unknown fields instead

* chore: remove console.log in `abortConversation`

* refactor(assistants): improve error handling/cancellation flow
2024-03-07 10:50:01 -05:00
Walber Cardoso
d4fe8fc82d 🔍 feat: Add Google Search Tool for Assistants (#1994) 2024-03-07 10:49:48 -05:00
Ido Ophir
a5f4292d2d 🌊 docs: refactor DigitalOcean guide (#2006) 2024-03-07 08:12:39 -05:00
Fuegovic
fbdf1d17ea 💾 chore: Update .env.example (#2004)
* Update .env.example

Make assistants show in the UI by default

* Update dotenv.md
2024-03-07 08:11:32 -05:00
Ido Ophir
11bca134e7 📝 docs: additions to deployment guide (#2001)
* docs: add intro to deployment guide

* doc: update intro

* doc: Add NGINX deployment guide and update reverse proxy link

* doc:: add  reverse proxy pages and weight for the pages

* doc: Update NGINX configuration file

* doc: imporve new doc

* Doc: fix file names

* doc: fix references names + improve the introduction with chatgpt :-)

* doc: update introduction  guide headings
2024-03-07 08:10:44 -05:00
Danny Avila
ab66747e97 🔧 style: Improve UI and UX with Style Fixes and Code Refactors (#2002)
* refactor(useSSE): add useCallback to all event handlers

* chore: remove modelName in defaultAssistantFormValues

* fix(SidePanel): fix layout shift on chrome my removing sidenav scrollbar

* style(ChatForm): match ChatGPT textarea effect styling

* style: fix flickering of old background color on refresh
2024-03-06 17:49:53 -05:00
Marco Beretta
b2ab6fd19d 🖌️ style: update dialog position (#1999)
* style(ChatForm): update styling and fixed style bug

* style:(Dialog): reduced max height  style(Settings): fixed dialog position height

* style(Settings): fixed large screen  position
2024-03-06 17:03:23 -05:00
Fuegovic
ab263c7a50 📝 docs update: Anthropic models + Traversaal (#1995)
* 📝 docs update: Anthropic models + Traversaal

* 📝 docs update: Anthropic models
2024-03-06 16:52:42 -05:00
Marco Beretta
911babd3e0 🖌️ style: Update Light/Dark UI Themes (#1754)
* BIG UI UPDATE

* fix: search bar, dialog template, new chat icon, convo icon and delete/rename button

* moved some color config and a lot of files

* small text fixes and tailwind config refactor

* Update localization and UI styles

* Update styles and add user-select:none to Tooltip component

* Update mobile.css styles for navigation mask and background color

* Update component imports and styles

* Update DeleteButton imports and references

* Update UI components

* Update tooltip delay duration

* Fix styling and update text in various components

* fixed assistant style

* minor style fixes

* revert: removed CreationHeader & CreationPanel

* style: match new styling for SidePanel

* style: match bg-gray-800 to ChatGPT (#212121)

* style: remove slate for gray where applicable to match new light theme

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-03-06 12:05:43 -05:00
Danny Avila
2733c5ebe7 🔎 fix(Traversaal): Recognize authField during Tool Initialization 2024-03-06 10:59:00 -05:00
Danny Avila
959d6153f6 🔎 feat: Traversaal Search Tool (#1991)
* wip: Traversaal Search Tool

* fix(traversaal): properly handle tool error, show error to LLM, log

* feat(traversaal): finish implementation of structured tool

* chore: change traversaal order
2024-03-06 10:25:38 -05:00
Danny Avila
14dd3dd240 🖋️ fix(OpenAIClient): remove typo 2024-03-06 09:19:52 -05:00
Danny Avila
8263ddda3f 🤖 feat(Anthropic): Claude 3 & Vision Support (#1984)
* chore: bump anthropic SDK

* chore: update anthropic config settings (fileSupport, default models)

* feat: anthropic multi modal formatting

* refactor: update vision models and use endpoint specific max long side resizing

* feat(anthropic): multimodal messages, retry logic, and messages payload

* chore: add more safety to trimming content due to whitespace error for assistant messages

* feat(anthropic): token accounting and resending multiple images in progress

* chore: bump data-provider

* feat(anthropic): resendImages feature

* chore: optimize Edit/Ask controllers, switch model back to req model

* fix: false positive of invalid model

* refactor(validateVisionModel): use object as arg, pass in additional/available models

* refactor(validateModel): use helper function, `getModelsConfig`

* feat: add modelsConfig to endpointOption so it gets passed to all clients, use for properly validating vision models

* refactor: initialize default vision model and make sure it's available before assigning it

* refactor(useSSE): avoid resetting model if user selected a new model between request and response

* feat: show rate in transaction logging

* fix: return tokenCountMap regardless of payload shape
2024-03-06 00:04:52 -05:00
Danny Avila
b023c5683d 🛠️ refactor(loadConfigModels): make apiKey and baseURL pairings more versatile (#1985) 2024-03-05 15:42:19 -05:00
Fuegovic
a33db54b81 🔎 update meilisearch to v1.6 / 0.37.0 (#1981)
* 🔎 update meilisearch to v1.6 / 0.37.0

* 🔎 update meilisearch to v1.6 / 0.37.0
2024-03-05 14:36:01 -05:00
Danny Avila
7a6a41a72e 🧪 fix(ci): update failing initializeClient tests with new expected values (#1982)
* fix(ci): update failing tests with new expected values from `getUserKey`

* refactor: safer optional chaining, and ensure apiKey is defined
2024-03-05 14:33:45 -05:00
Fuegovic
2ea6e8c18a 🥷🪦 docs: remove ninja and chatgptBrowser (#1973) 2024-03-04 19:49:34 -05:00
Ido Ophir
7c85b35af0 🌍 : Add Hebrew Translation (#1953)
* feat: add hebrew

* fix: review issues

* fix language options
2024-03-04 17:16:49 -05:00
Fuegovic
eccf7bbbde 🦙 doc: add Ollama to index and update icon (#1967) 2024-03-04 17:16:33 -05:00
Danny Avila
8bef084bfc 🧩 fix(Plugins): Keep User agentModel and Model Validation (#1972)
* fix: do not override model

* temp fix for secondary model validation
2024-03-04 17:07:30 -05:00
Danny Avila
62834e18fb 🪙 fix(config): use new field for balance 2024-03-04 16:37:06 -05:00
Marco Beretta
2da0a7661d 🔧 fix(EditMessage): duplicate text when pasting (#1970)
* fix(EditMessage): duplicate text when pasting on chromium

* add back paste data handling, prevent default behavior

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-03-04 16:27:34 -05:00
Marco Beretta
7d633f4018 🔧 fix(useTextarea): duplicate text when pasting on chromium (#1951) 2024-03-02 15:53:13 -05:00
bsu3338
78f52859c4 📚 docs: Separate LiteLLM and Ollama Documentation (#1948)
* Separate LiteLLM and Ollama Documentation

* Clarify Ollama Setup

* Fix litellm config
2024-03-02 12:42:02 -05:00
Danny Avila
b2ef75e009 🖥️ feat: Match STDOUT Logs with Debug File Logs (#1944)
* chore: improve token balance logging post-request

* feat: match stdout logging with file debug logging when using DEBUG_CONSOLE
2024-03-01 13:42:04 -05:00
Danny Avila
ef86b25dae 👤 feat: Show Default Icon if No Avatar or Username provided (#1943) 2024-03-01 13:08:27 -05:00
Danny Avila
c52ea9490b 📝 feat: Improved Textarea Functionality (#1942)
* feat: paste plain text from apps with rich paste data, improved edit message textarea, improved height resizing for long text

* feat(EditMessage): autofocus

* chore: retain user text color when entering edit mode
2024-03-01 12:46:15 -05:00
Fuegovic
de0cee3f56 🔎docs: update meilisearch instruction (#1930)
* 🔎docs: update meilisearch in mac_install.md

Update the Meilisearch .env variables in `mac_install.md`

* 🔎🐧
2024-03-01 12:32:32 -05:00
Danny Avila
1caa31b035 🐳chore(Dockerfile): add additional steps to prevent arm64 build failure 2024-02-29 10:04:36 -05:00
Danny Avila
ed7d7c2fda 🐳 chore(Dockerfile): replace npm ci with npm install for OS specific builds 2024-02-29 09:46:33 -05:00
Danny Avila
93803323cf 🐳 experimental: Dev Image Workflow & Remove Unused Code (#1928)
* chore: remove unused code in progressCallback, as well as handle reply.trim(), post `getCompletion`

* chore(Dockerfile): remove curl installation

* experimental: dev image parallelized with matrix strategy and building for amd64/arm64 support

* make platforms explicit
2024-02-29 09:24:55 -05:00
Danny Avila
388dc1789b 🛠️ fix: RunManager, AssistantService and useContentHandler Issues (#1920)
* fix(useContentHandler): retain undefined parts and handle them within `ContentParts` rendering

* fix(AssistantService/in_progress): skip empty messages

* refactor(RunManager): create highly specific `seenSteps` Set keys for RunSteps with use of `getDetailsSignature` and `getToolCallSignature`,to ensure changes from polling are always captured
2024-02-28 15:15:45 -05:00
Fuegovic
057fcf6274 🌍 feat: Extend regex to support international usernames (#1918)
* 🌍 Extend regex to support international usernames

* update validators.spec.js
2024-02-28 14:27:57 -05:00
Danny Avila
2f92b54787 🔗 feat: User Provided Base URL for OpenAI endpoints (#1919)
* chore: bump browserslist-db@latest

* refactor(EndpointService): simplify with `generateConfig`, utilize optional baseURL for OpenAI-based endpoints, use `isUserProvided` helper fn wherever needed

* refactor(custom/initializeClient): use standardized naming for common variables

* feat: user provided baseURL for openAI-based endpoints

* refactor(custom/initializeClient): re-order operations

* fix: knownendpoints enum definition and add FetchTokenConfig, bump data-provider

* refactor(custom): use tokenKey dependent on userProvided conditions for caching and fetching endpointTokenConfig, anticipate token rates from custom config

* refactor(custom): assure endpointTokenConfig is only accessed from cache if qualifies for fetching

* fix(ci): update tests for initializeClient based on userProvideURL changes

* fix(EndpointService): correct baseURL env var for assistants: `ASSISTANTS_BASE_URL`

* fix: unnecessary run cancellation on res.close() when response.run is completed

* feat(assistants): user provided URL option

* ci: update tests and add test for `assistants` endpoint

* chore: leaner condition for request closing

* chore: more descriptive error message to provide keys again
2024-02-28 14:27:19 -05:00
Fuegovic
53ae2d7bfb 🤖feat: add multiple known endpoints (#1917)
* feat: add known endpoints

* docs: add known endpoints

* update ai_endpoints.md

remove the groq icon from the example

* Update ai_endpoints.md

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-28 08:46:21 -05:00
Marco Beretta
156abe2fca 🔗 feat: NavLinks customization for Help & Faq URL (#1872)
* help and faq

* fix: using only one var

* revert(types.ts): showHelpAndFaq

* Update dotenv.md

* Update dotenv.md
2024-02-27 17:59:56 -05:00
Danny Avila
c37d5568bf 🍞 fix: Minor fixes and improved Bun support (#1916)
* fix(bun): fix bun compatibility to allow gzip header: https://github.com/oven-sh/bun/issues/267#issuecomment-1854460357

* chore: update custom config examples

* fix(OpenAIClient.chatCompletion): remove redundant call of stream.controller.abort() as `break` aborts the request and prevents abort errors when not called redundantly

* chore: bump bun.lockb

* fix: remove result-thinking class when message is no longer streaming

* fix(bun): improve Bun support by forcing use of old method in bun env, also update old methods with new customizable params

* fix(ci): pass tests
2024-02-27 17:51:16 -05:00
Danny Avila
5d887492ea 🤖 docs: Add Groq and other Compatible AI Endpoints (#1915)
* chore: bump bun dependencies

* feat: make `groq` a known endpoint

* docs: compatible ai endpoints

* Update ai_endpoints.md

* Update ai_endpoints.md
2024-02-27 13:42:10 -05:00
Danny Avila
04eeb59d47 🛠️ chore: Abort AI Requests on Close & Remove Verbose Logs for Plugins (#1914)
* chore: remove verbose logging of ChatOpenAI

* feat: abort AI requests on request close
2024-02-27 10:21:06 -05:00
Danny Avila
08d4b3cc8a 🅰️ feat: Azure AI Studio, Models as a Service Support (#1902)
* feat(data-provider): add Azure serverless inference handling through librechat.yaml

* feat(azureOpenAI): serverless inference handling in api

* docs: update docs with new azureOpenAI endpoint config fields and serverless inference endpoint setup

* chore: remove unnecessary checks for apiKey as schema would not allow apiKey to be undefined

* ci(azureOpenAI): update tests for serverless configurations
2024-02-26 19:10:29 -05:00
Raí Santos
6d6b3c9c1d 🌍 : Update Portuguese Translations (#1867)
* 🌍 : Update Portuguese Translations

* 🌍 : Fix Portuguese Translations

* fix(Br): lint errors

---------

Co-authored-by: Berry-13 <81851188+Berry-13@users.noreply.github.com>
2024-02-26 14:37:08 -05:00
Danny Avila
49744d1af9 🔥chore: bump firebase dependency (#1900) 2024-02-26 14:36:48 -05:00
Marco Beretta
b4dc8cc2ad 🖌️ style: auth dark theme (#1862)
* Remove minLength validation and update login link style

* Add theme selector component and update login form styles

* Update styling in Login and LoginForm components

* Update ResetPassword component styles and text color

* Refactor login component and add theme selector

* Add ThemeSelector component to Registration, RequestPasswordReset, and ResetPassword pages

* chore(Login.tsx): remove unused `useCallback`

* chore(Login.tsx) import order

* Update ResetPassword.tsx import order

* Update RequestPasswordReset.tsx import order

* Update Registration.tsx import order

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-26 14:21:17 -05:00
Danny Avila
097a978e5b 🅰️ feat: Azure Config to Allow Different Deployments per Model (#1863)
* wip: first pass for azure endpoint schema

* refactor: azure config to return groupMap and modelConfigMap

* wip: naming and schema changes

* refactor(errorsToString): move to data-provider

* feat: rename to azureGroups, add additional tests, tests all expected outcomes, return errors

* feat(AppService): load Azure groups

* refactor(azure): use imported types, write `mapModelToAzureConfig`

* refactor: move `extractEnvVariable` to data-provider

* refactor(validateAzureGroups): throw on duplicate groups or models; feat(mapModelToAzureConfig): throw if env vars not present, add tests

* refactor(AppService): ensure each model is properly configured on startup

* refactor: deprecate azureOpenAI environment variables in favor of librechat.yaml config

* feat: use helper functions to handle and order enabled/default endpoints; initialize azureOpenAI from config file

* refactor: redefine types as well as load azureOpenAI models from config file

* chore(ci): fix test description naming

* feat(azureOpenAI): use validated model grouping for request authentication

* chore: bump data-provider following rebase

* chore: bump config file version noting significant changes

* feat: add title options and switch azure configs for titling and vision requests

* feat: enable azure plugins from config file

* fix(ci): pass tests

* chore(.env.example): mark `PLUGINS_USE_AZURE` as deprecated

* fix(fetchModels): early return if apiKey not passed

* chore: fix azure config typing

* refactor(mapModelToAzureConfig): return baseURL and headers as well as azureOptions

* feat(createLLM): use `azureOpenAIBasePath`

* feat(parsers): resolveHeaders

* refactor(extractBaseURL): handle invalid input

* feat(OpenAIClient): handle headers and baseURL for azureConfig

* fix(ci): pass `OpenAIClient` tests

* chore: extract env var for azureOpenAI group config, baseURL

* docs: azureOpenAI config setup docs

* feat: safe check of potential conflicting env vars that map to unique placeholders

* fix: reset apiKey when model switches from originally requested model (vision or title)

* chore: linting

* docs: CONFIG_PATH notes in custom_config.md
2024-02-26 14:12:25 -05:00
Andreas
7a55132e42 🔧 feat: optional librechat.yaml path via environment variable (#1858)
Co-authored-by: afel <andreas.feldl@netlight.com>
2024-02-26 13:59:19 -05:00
Arno Angerer
c1a4733d50 📒 docs: Add newline for list to be correctly rendered in UI (#1873)
Currently in the documentation page the bullet list is not rendered correctly. (See first paragraph on this docs page: https://docs.librechat.ai/install/configuration/litellm.html)
2024-02-23 15:29:36 -05:00
Danny Avila
f431c8fb00 🔀 fix: Correct Expected Behavior for Modular Chat Feature (#1871) 2024-02-23 12:14:58 -05:00
Fuegovic
5445d55af2 🐋 docs: update breaking_changes.md (#1864)
add note about the use of the pre-built image in docker-compose.yml
2024-02-23 11:51:17 -05:00
Danny Avila
6a25dd38a4 🗨️ fix: Prevent Resetting Title to 'New Chat' on Follow-Up Message (#1870)
* fix: prevent reseting title to 'New Chat' on follow up message

* chore(useSSE): remove empty line
2024-02-23 10:20:46 -05:00
Fuegovic
ece5d9f588 ✏️docs: add tavily to env.example and dotenv.md (#1866)
* update .env.example

add "TAVILY_API_KEY=" to .env.example

* update dotenv.md

add Tavily to dotenv.md
2024-02-23 10:08:49 -05:00
Danny Avila
5f6d1f3db0 🎨 feat: Create Avatars of Initials Locally (#1869) 2024-02-23 09:23:29 -05:00
Fuegovic
4012dea4ab 🐋 Feat: docker pre-built image by default (#1860)
* 🐋 Feat: docker pre-built image by default

* 🐋 Feat: docker LibreChat ports from .env
2024-02-22 13:20:27 -05:00
Danny Avila
128446601a 🐛 fix: Preserve Default Model in Message Requests (#1857)
* fix: do not remove default model from message request

* chore: bump data-provider
2024-02-21 13:29:21 -05:00
Danny Avila
dd8038b375 🛠️ refactor: Model Loading and Custom Endpoint Error Handling (#1849)
* fix: handle non-assistant role ChatCompletionMessage error

* refactor(ModelController): decouple res.send from loading/caching models

* fix(custom/initializeClient): only fetch custom endpoint models if models.fetch is true

* refactor(validateModel): load models if modelsConfig is not yet cached

* docs: update on file upload rate limiting
2024-02-20 12:57:58 -05:00
Danny Avila
542494fad6 📋 feat: Accumulate Text Parts to Clipboard for Assistant Outputs (#1847) 2024-02-20 09:33:31 -05:00
Danny Avila
64e81392f2 ⬤ style: Uniform Display of Result-Streaming Cursor (#1842) 2024-02-19 22:55:58 -05:00
Danny Avila
a8a19c6caa 🛡️ feat: Model Validation Middleware (#1841)
* refactor: add ViolationTypes enum and add new violation for illegal model requests

* feat: validateModel middleware to protect the backend against illicit requests for unlisted models
2024-02-19 22:47:39 -05:00
Danny Avila
d8038e3b19 📤 refactor: Utilize intermediateReply when message.content is Empty 2024-02-19 11:03:42 -05:00
Danny Avila
ee97179edb 📝 chore: Update README.md 2024-02-19 09:45:59 -05:00
Danny Avila
63a5039fae 🔗 chore: Add Stable Discord and Homepage Links (#1835) 2024-02-19 09:42:57 -05:00
Fuegovic
7442955a1d 📝 docs: add env changes to breaking_changes.md and minor fixes (#1812)
* 📝 docs: add env changes to breacking_changes.md

* 📝 docs: replace example in docker_override.md

* 📝 docs: fix images in zeabur.md
2024-02-19 09:41:07 -05:00
Danny Avila
5291d18f38 🔀 fix: Endpoint Type Mismatch when Switching Conversations (#1834)
* refactor(useUpdateUserKeysMutation): only invalidate the endpoint whose key is being updated by user

* fix(assistants): await `getUserKeyExpiry` call

* chore: fix spinner loading color

* refactor(initializeClient): make known which endpoint api Key is missing

* fix: prevent an `endpointType` mismatch by making it impossible to assign when the `endpointsConfig` doesn't have a `type` defined, also prefer `getQueryData` call to useQuery in useChatHelpers
2024-02-19 01:31:38 -05:00
Danny Avila
d1eb7fcfc7 Update main-image-workflow.yml 2024-02-16 16:05:18 -05:00
Danny Avila
ce1cdea3de Update main-image-workflow.yml 2024-02-16 15:55:12 -05:00
Danny Avila
0da30b9481 Update main-image-workflow.yml 2024-02-16 15:46:09 -05:00
Danny Avila
b7aebf6c51 Update main-image-workflow.yml 2024-02-16 15:43:31 -05:00
Danny Avila
29ee4423a6 🐋 chore: Add Docker Compose Build Latest Main Image workflow (#1819) 2024-02-16 15:37:32 -05:00
Danny Avila
98064244bf fix: necessary font changes (#1818)
* fix: necessary font changes

* chore: minor bump
2024-02-16 14:15:05 -05:00
Danny Avila
fe0ef2ce61 📝 docs: Update docker-compose.override.yml.example 2024-02-15 12:56:28 -05:00
Danny Avila
637a1a41c2 👥 fix: Reinstate Default Social Login Values (#1811)
* fix: social logins accidentally removed default in AppService, reinstated and added test

* chore: move birthday to OTHER section and make disabled by default
2024-02-15 08:20:06 -05:00
Danny Avila
60b1d1332c 🤖 chore: Improve Assistants Run Logging (#1801) 2024-02-14 13:33:33 -05:00
Walber Cardoso
9d3215dcaa ✏️ fix(Convo): Rename Title UX (#1793) 2024-02-14 09:43:37 -05:00
CXwudi
c7020e8651 📝 docs: Enhance LibreChat Docker deployment guide (#1796)
- Revise the description for clarity and conciseness.
- Provide a direct comparison between the advanced Docker Compose deployment and the simpler `docker-compose.override.yml` setup.
- Update screenshot link for visual reference.
2024-02-14 09:42:12 -05:00
Danny Avila
04af1cad52 🤖 docs(assistants): Additional Setup & Tool Selection Info (#1798) 2024-02-13 22:24:24 -05:00
Danny Avila
d947244348 🔧 fix(data-provider): add openapi-types dependency (#1797)
* fix(data-provider): add openapi-types dependency

* chore: Bump version to 0.4.1 in package.json
2024-02-13 21:08:02 -05:00
Danny Avila
ecd63eb9f1 feat: Assistants API, General File Support, Side Panel, File Explorer (#1696)
* feat: assistant name/icon in Landing & Header

* feat: assistname in textarea placeholder, and use `Assistant` as default name

* feat: display non-image files in user messages

* fix: only render files if files.length is > 0

* refactor(config -> file-config): move file related configuration values to separate module, add excel types

* chore: spreadsheet file rendering

* fix(Landing): dark mode style for Assistant Name

* refactor: move progress incrementing to own hook, start smaller, cap near limit \(1\)

* refactor(useContentHandler): add empty Text part if last part was completed tool or image

* chore: add accordion trigger border styling for dark mode

* feat: Assistant Builder model selection

* chore: use Spinner when Assistant is mutating

* fix(get/assistants): return correct response object `AssistantListResponse`

* refactor(Spinner): pass size as prop

* refactor: make assistant crud mutations optimistic, add types for options

* chore: remove assistants route and view

* chore: move assistant builder components to separate directory

* feat(ContextButton): delete Assistant via context button/dialog, add localization

* refactor: conditionally show use and context menu buttons, add localization for create assistant

* feat: save side panel states to localStorage

* style(SidePanel): improve avatar menu and assistant select styling for dark mode

* refactor: make NavToggle reusable for either side (left or right), add SidePanel Toggle with ability to close it completely

* fix: resize handle and navToggle behavior

* fix(/avatar/:assistant_id): await `deleteFile` and assign unique name to uploaded image

* WIP: file UI components from PR #576

* refactor(OpenAIMinimalIcon): pass className

* feat: formatDate helper fn

* feat: DataTableColumnHeader

* feat: add row selection, formatted row values, number of rows selected

* WIP: add files to Side panel temporarily

* feat: `LB_QueueAsyncCall`: Leaky Bucket queue for external APIs, use in `processDeleteRequest`

* fix(TFile): correct `source` type with `FileSources`

* fix(useFileHandling): use `continue` instead of return when iterating multiple files, add file type to extendedFile

* chore: add generic setter type

* refactor(processDeleteRequest): settle promises to prevent rejections from processing deletions, log errors

* feat: `useFileDeletion` to reuse file deletion logic

* refactor(useFileDeletion): make `setFiles` an optional param and use object as param

* feat: useDeleteFilesFromTable

* feat: use real `files` data and add deletion action to data table

* fix(Table): make headers sticky

* feat: add dynamic filtering for columns; only show to user Host or OpenAI storage type

* style(DropdownMenu): replace `slate` with `gray`

* style(DataTable): apply dark mode themes and other misc styling

* style(Columns): add color to OpenAI Storage option

* refactor(FileContainer): make file preview reusable

* refactor(Images): make image preview reusable

* refactor(FilePreview): make file prop optional for FileIcon and FilePreview, fix relative style

* feat(Columns): add file/image previews, set a minimum size to show for file size in bytes

* WIP: File Panel with real files and formatted

* feat: open files dialog from panel

* style: file data table mobile and general column styling fixes

* refactor(api/files): return files sorted by the most recently updated

* refactor: provide fileMap through context to prevent re-selecting files to map in different areas; remove unused imports commented out in PanelColumns

* refactor(ExtendFile): make File type optional, add `attached` to prevent attached files from being deleted on remove, make Message.files a partial TFile type

* feat: attach files through file panel

* refactor(useFileHandling): move files to the start of cache list when uploaded

* refactor(useDeleteFilesMutation): delete files from cache when successfully deleted from server

* fix(FileRow): handle possible edge case of duplication due to attaching recently uploaded file

* style(SidePanel): make resize grip border transparent, remove unnecessary styling on close sidepanel button

* feat: action utilities and tests

* refactor(actions): add `ValidationResult` type and change wording for no server URL found

* refactor(actions): check for empty server URL

* fix(data-provider): revert tsconfig to fix type issue resolution

* feat(client): first pass of actions input for assistants

* refactor(FunctionSignature): change method to output object instead of string

* refactor(models/Assistant): add actions field to schema, use searchParams object for methods, and add `getAssistant`

* feat: post actions input first pass
- create new Action document
- add actions to Assistant DB document
- create /action/:assistant_id POST route
- pass more props down from PanelSwitcher, derive assistant_id from switcher
- move privacy policy to ActionInput
- reset data on input change/validation
- add `useUpdateAction`
- conform FunctionSignature type to FunctionTool
- add action, assistant doc, update hook related types

* refactor: optimize assistant/actions relationship
- past domain in metadata as hostname and not a URL
- include domain in tool name
- add `getActions` for actions retrieval by user
- add `getAssistants` for assistant docs retrieval by user
- add `assistant_id` to Action schema
- move actions to own module as a subroute to `api/assistants`
- add `useGetActionsQuery` and `useGetAssistantDocsQuery` hooks
- fix Action type def

* feat: show assistant actions in assistant builder

* feat: switch to actions on action click, editing action styling

* fix: add Assistant state for builder panel to allow immediate selection of newly created assistants as well as retaining the current assistant when switching to a different panel within the builder

* refactor(SidePanel/NavToggle): offset less from right when SidePanel is completely collapsed

* chore: rename `processActions` -> `processRequiredActions`

* chore: rename Assistant API Action to RequiredAction

* refactor(actions): avoid nesting actual API params under generic `requestBody` to optimize LLM token usage

* fix(handleTools): avoid calling `validTool` if not defined, add optional param to skip the loading of specs, which throws an error in the context of assistants

* WIP: working first pass of toolCalls generated from openapi specs

* WIP: first pass ToolCall styling

* feat: programmatic iv encryption/decryption helpers

* fix: correct ActionAuth types/enums, and define type for AuthForm

* feat: encryption/decryption helpers for Action AuthMetadata

* refactor(getActions): remove sensitive fields from query response

* refactor(POST/actions): encrypt and remove sensitive fields from mutation response

* fix(ActionService): change ESM import to CJS

* feat: frontend auth handling for actions + optimistic update on action update/creation

* refactor(actions): use the correct variables and types for setAuth method

* refactor: POST /:assistant_id action can now handle updating an existing action, add `saved_auth_fields` to determine when user explicitly saves new auth creds. only send auth metadata if user explicitly saved fields

* refactor(createActionTool): catch errors and send back meaningful error message, add flag to `getActions` to determine whether to retrieve sensitive values or not

* refactor(ToolService): add `action` property to ToolCall PartMetadata to determine if the tool call was an action, fix parsing function name issue with actionDelimiter

* fix(ActionRequest): use URL class to correctly join endpoint parts for `execute` call

* feat: delete assistant actions

* refactor: conditionally show Available actions

* refactor: show `retrieval` and `code_interpreter` as Capabilities, swap `Switch` for `Checkbox`

* chore: remove shadow-stroke from messages

* WIP: first pass of Assistants Knowledge attachments

* refactor: remove AssistantsProvider in favor of FormProvider, fix selectedAssistant re-render bug, map Assistant file_ids to files via fileMap, initialize Knowledge component with mapped files if any exist

* fix: prevent deleting files on assistant file upload

* chore: remove console.log

* refactor(useUploadFileMutation): update files and assistants cache on upload

* chore: disable oauth option as not supported yet

* feat: cancel assistant runs

* refactor: initialize OpenAI client with helper function, resolve all related circular dependencies

* fix(DALL-E): initialization

* fix(process): openai client initialization

* fix: select an existing Assistant when the active one is deleted

* chore: allow attaching files for assistant endpoint, send back relevant OpenAI error message when uploading, deconstruct openAI initialization correctly, add `message_file` to formData when a file is attached to the message but not the assistant

* fix: add assistant_id on newConvo

* fix(initializeClient): import fix

* chore: swap setAssistant for setOption in useEffect

* fix(DALL-E): add processFileURL to loadTools call

* chore: add customConfig to debug logs

* feat: delete threads on convo delete

* chore: replace Assistants icon

* chore: remove console.dir() in `abortRun`

* feat(AssistantService): accumulate text values from run in openai.responseText

* feat: titling for assistants endpoint

* chore: move panel file components to appropriate directory, add file checks for attaching files, change icon for Attach Files

* refactor: add localizations to tools, plugins, add condition for adding/remove user plugins so tool selections don't affect this value

* chore: disable `import from url` action for now

* chore: remove textMimeTypes from default fileConfig for now

* fix: catch tool errors and send as outputs with error messages

* fix: React warning about button as descendant of button

* style: retrieval and cancelled icon

* WIP: pass isSubmitting to Parts, use InProgressCall to display cancelled tool calls correctly, show domain/function name

* fix(meilisearch): fix `postSaveHook` issue where indexing expects a mongo document, and join all text content parts for meili indexing

* ci: fix dall-e tests

* ci: fix client tests

* fix: button types in actions panel

* fix: plugin auth form persisting across tool selections

* fix(ci): update AppService spec with `loadAndFormatTools`

* fix(clearConvos): add id check earlier on

* refactor(AssistantAvatar): set previewURL dynamically when emtadata.avatar changes

* feat(assistants): addTitle cache setting

* fix(useSSE): resolve rebase conflicts

* fix: delete mutation

* style(SidePanel): make grip visible on active and hover, invisible otherwise

* ci: add data-provider tests to workflow, also update eslint/tsconfig to recognize specs, and add `text/csv` to fileConfig

* fix: handle edge case where auth object is undefined, and log errors

* refactor(actions): resolve  schemas, add tests for resolving refs, import specs from separate file for tests

* chore: remove comment

* fix(ActionsInput): re-render bug when initializing states with action fields

* fix(patch/assistant): filter undefined tools

* chore: add logging for errors in assistants routes

* fix(updateAssistant): map actions to functions to avoid overwriting

* fix(actions): properly handle GET paths

* fix(convos): unhandled delete thread exception

* refactor(AssistantService): pass both thread_id and conversationId when sending intermediate assistant messages, remove `mapMessagesToSteps` from AssistantService

* refactor(useSSE): replace all messages with runMessages and pass latestMessageId to abortRun; fix(checkMessageGaps): include tool calls when  syncing messages

* refactor(assistants/chat): invoke `createOnTextProgress` after thread creation

* chore: add typing

* style: sidepanel styling

* style: action tool call domain styling

* feat(assistants): default models, limit retrieval to certain models, add env variables to to env.example

* feat: assistants api key in EndpointService

* refactor: set assistant model to conversation on assistant switch

* refactor: set assistant model to conversation on assistant select from panel

* fix(retrieveAndProcessFile): catch attempt to download file with `assistant` purpose which is not allowed; add logging

* feat: retrieval styling, handling, and logging

* chore: rename ASSISTANTS_REVERSE_PROXY to ASSISTANTS_BASE_URL

* feat: FileContext for file metadata

* feat: context file mgmt and filtering

* style(Select): hover/rounded changes

* refactor: explicit conversation switch, endpoint dependent, through `useSelectAssistant`, which does not create new chat if current endpoint is assistant endpoint

* fix(AssistantAvatar): make empty previewURL if no avatar present

* refactor: side panel mobile styling

* style: merge tool and action section, optimize mobile styling for action/tool buttons

* fix: localStorage issues

* fix(useSelectAssistant): invoke react query hook directly in select hook as Map was not being updated in time

* style: light mode fixes

* fix: prevent sidepanel nav styling from shifting layout up

* refactor: change default layout (collapsed by default)

* style: mobile optimization of DataTable

* style: datatable

* feat: client-side hide right-side panel

* chore(useNewConvo): add partial typing for preset

* fix(useSelectAssistant): pass correct model name by using template as preset

* WIP: assistant presets

* refactor(ToolService): add native solution for `TavilySearchResults` and log tool output errors

* refactor: organize imports and use native TavilySearchResults

* fix(TavilySearchResults): stringify result

* fix(ToolCall): show tool call outputs when not an action

* chore: rename Prompt Prefix to custom instructions (in user facing text only)

* refactor(EditPresetDialog): Optimize setting title by debouncing, reset preset on dialog close to avoid state mixture

* feat: add `presetOverride` to overwrite active conversation settings when saving a Preset (relevant for client side updates only)

* feat: Assistant preset settings (client-side)

* fix(Switcher): only set assistant_id and model if current endpoint is Assistants

* feat: use `useDebouncedInput` for updating conversation settings, starting with EditPresetDialog title setting and Assistant instructions setting

* feat(Assistants): add instructions field to settings

* feat(chat/assistants): pass conversation settings to run body

* wip: begin localization and only allow actions if the assistant is created

* refactor(AssistantsPanel): knowledge localization, allow tools on creation

* feat: experimental: allow 'priming' values before assistant is created, that would normally require an assistant_id to be defined

* chore: trim console logs and make more meaningful

* chore: toast messages

* fix(ci): date test

* feat: create file when uploading Assistant Avatar

* feat: file upload rate limiting from custom config with dynamic file route initialization

* refactor: use file upload limiters on post routes only

* refactor(fileConfig): add endpoints field for endpoint specific fileconfigs, add mergeConfig function, add tests

* refactor: fileConfig route, dynamic multer instances used on all '/' and '/images' POST routes, data service and query hook

* feat: supportedMimeTypesSchema, test for array of regex

* feat: configurable file config limits

* chore: clarify assistants file knowledge prereq.

* chore(useTextarea): default to localized 'Assistant' if assistant name is empty

* feat: configurable file limits and toggle file upload per endpoint

* fix(useUploadFileMutation): prevent updating assistant.files cache if file upload is a message_file attachment

* fix(AssistantSelect): set last selected assistant only when timeout successfully runs

* refactor(queries): disable assistant queries if assistants endpoint is not enabled

* chore(Switcher): add localization

* chore: pluralize `assistant` for `EModelEndpoint key and value

* feat: show/hide assistant UI components based on endpoint availability; librechat.yaml config for disabling builder section and setting polling/timeout intervals

* fix(compactEndpointSchemas): use EModelEndpoint for schema access

* feat(runAssistant): use configured values from `librechat.yaml` for `pollIntervalMs` and `timeout`

* fix: naming issue

* wip: revert landing

* 🎉 happy birthday LibreChat (#1768)

* happy birthday LibreChat

* Refactor endpoint condition in Landing component

* Update birthday message in Eng.tsx

* fix(/config): avoid nesting ternaries

* refactor(/config): check birthday

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>

* fix: landing

* fix: landing

* fix(useMessageHelpers): hardcoded check to use EModelEndpoint instead

* fix(ci): convo test revert to main

* fix(assistants/chat): fix issue where assistant_id was being saved as model for convo

* chore: added logging, promises racing to prevent longer timeouts, explicit setting of maxRetries and timeouts, robust catching of invalid abortRun params

* refactor: use recoil state for `showStopButton` and only show for assistants endpoint after syncing conversation data

* refactor: optimize abortRun strategy using localStorage, refactor `abortConversation` to use async/await and await the result, refactor how the abortKey cache is set for runs

* fix(checkMessageGaps): assign `assistant_id` to synced messages if defined; prevents UI from showing blank assistant for cancelled messages

* refactor: re-order sequence of chat route, only allow aborting messages after run is created, cancel abortRun if there was a cancelling error (likely due already cancelled in chat route), and add extra logging

* chore(typedefs): add httpAgent type to OpenAIClient

* refactor: use custom implementation of retrieving run with axios to allow for timing out run query

* fix(waitForRun): handle timed out run retrieval query

* refactor: update preset conditions:
- presets will retain settings when a different endpoint is selected; for existing convos, either when modular or is assistant switch
- no longer use `navigateToConvo` on preset select

* fix: temporary calculator hack as expects string input when invoked

* fix: cancel abortRun only when cancelling error is a result of the run already being cancelled

* chore: remove use of `fileMaxSizeMB` and total counterpart (redundant)

* docs: custom config documentation update

* docs: assistants api setup and dotenv, new custom config fields

* refactor(Switcher): make Assistant switcher sticky in SidePanel

* chore(useSSE): remove console log of data and message index

* refactor(AssistantPanel): button styling and add secondary select button to bottom of panel

* refactor(OpenAIClient): allow passing conversationId to RunManager through titleConvo and initializeLLM to properly record title context tokens used in cases where conversationId was not defined by the client

* feat(assistants): token tracking for assistant runs

* chore(spendTokens): improve logging

* feat: support/exclude specific assistant Ids

* chore: add update `librechat.example.yaml`, optimize `AppService` handling, new tests for `AppService`, optimize missing/outdate config logging

* chore: mount docker logs to root of project

* chore: condense axios errors

* chore: bump vite

* chore: vite hot reload fix using latest version

* chore(getOpenAIModels): sort instruct models to the end of models list

* fix(assistants): user provided key

* fix(assistants): user provided key, invalidate more queries on revoke

---------

Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
2024-02-13 20:42:27 -05:00
Danny Avila
cd2786441a 🐋 chore: add tag for latest for ci/cd docker builds (#1791) 2024-02-13 11:31:48 -05:00
Danny Avila
050eeb1211 chore: Update Docker build and push actions (#1790) 2024-02-13 10:59:46 -05:00
Danny Avila
6ccf4d6ed2 Release: v0.6.9 (#1789) 2024-02-13 09:40:33 -05:00
Fuegovic
7ff2418d87 📝 docs: clarifications - override file & balance/token count (#1783)
* 📝 docs: override file clarification

* 📝 docs: override file clarification

* 📝 docs: balance & token count clarification
2024-02-12 15:03:56 -05:00
Fuegovic
d8d79aba16 ✔️ docs: update custom_config.md (#1774)
Add link to https://yamlchecker.com/
2024-02-12 10:26:36 -05:00
Fuegovic
5ccdec730b 🐳 docs: update to compose v2 (#1767) 2024-02-12 10:26:05 -05:00
Marco Beretta
a91042b6b9 🎉 happy birthday LibreChat (#1768)
* happy birthday LibreChat

* Refactor endpoint condition in Landing component

* Update birthday message in Eng.tsx

* fix(/config): avoid nesting ternaries

* refactor(/config): check birthday

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-11 09:10:12 -05:00
Trevor Swanson
14b61fc861 🖌️ style: Update conversation history groups (#1770)
* style: Add month groups to conversation history

* style: Change "Last x days" to "Previous x days" to match ChatGPT

* style: Add "Yesterday" to conversation groups to match ChatGPT

* fix: use startOfDay for Yesterday conversation group

* fix: Output month name instead of number in conversation group name

* test: Validate new conversation groups are created properly

* fix: Formatting of month category string was wrong
2024-02-11 08:53:44 -05:00
Danny Avila
50adb1b3c6 🧪 ci: Fix Conversation Grouping Tests 2024-02-11 08:46:14 -05:00
Danny Avila
d2494e6b3b 🔌 fix: Minor Plugins Improvements (#1766)
* fix(PluginsClient): don't invoke `getFunctionModelName` when using Azure OpenAI

* fix: plugins styling fix with new cursor

* ci(PluginsClient): test azure exception for getFunctionModelName
2024-02-10 13:13:38 -05:00
Raí Santos
a2e85b7053 ⬤ style: Circular Streaming Cursor (#1736)
* Updated Style Cursor like ChatGPT

* style(Markdown.tsx): add space before cursor when there is text

* fix: revert OpenAIClient.tokens.js change

* fix:(Markdown.tsx): revert change of unused file

* fix(convos.spec.ts): test fix

* chore: remove raw HTML for cursor animations

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-10 11:07:57 -05:00
Danny Avila
92a41fbf47 🐳 feat: Push Container Images to DockerHub (#1762) 2024-02-10 08:27:52 -05:00
Danny Avila
39caeb2027 🧩 feat: Support Alternate API Keys for Plugins (#1760)
* refactor(DALL-E): retrieve env variables at runtime and not from memory

* feat(plugins): add alternate env variable handling to allow setting one api key for multiple plugins

* docs: update docs
2024-02-09 10:38:50 -05:00
bsu3338
927ce5395b 🦙 docs: Ollama Docs Update (#1756)
* Update to use docker-compose.overridge.yml

Add GPU Acceleration links

* Update litellm.md
2024-02-09 07:11:09 -05:00
Danny Avila
ff057152e2 👤 feat: User ID in Model Query; chore: cleanup ModelService (#1753)
* feat: send the LibreChat user ID as a query param when fetching the list of models

* chore: update bun

* chore: change bun command for building data-provider

* refactor: prefer use of `getCustomConfig` to access custom config, also move to `server/services/Config`

* refactor: make endpoints/custom option for the config optional, add userIdQuery, and use modelQueries log store in ModelService

* refactor(ModelService): use env variables at runtime, use default models from data-provider, and add tests

* docs: add `userIdQuery`

* fix(ci): import changed
2024-02-08 10:06:58 -05:00
Danny Avila
d06e5d2e02 🛠️ chore: Refactor Update Script to Utilize Docker Compose v2 (#1752) 2024-02-07 22:06:10 -05:00
Fuegovic
7f2264fd5c ✏️ update dotenv.md (#1740)
update the note about rebuilding LibreChat after configuration changes since the .env file is now mounted into the volume
2024-02-07 08:30:06 -05:00
Aleksei Lisikhin
7188cbde3d 📖 docs: fix link pointing to dotenv guide (#1739) 2024-02-06 21:50:52 -05:00
Danny Avila
b151cd9911 📇 refactor(convoSchema): index updatedAt field (#1732) 2024-02-05 15:27:06 -05:00
Danny Avila
f30d6bd689 🔧 fix: socialLogins default value (#1730)
* fix: socialLogins default value

* ci: add test for `AppService`
2024-02-05 11:26:12 -05:00
Marco Beretta
a2c35e8415 🔄🔐 refactor: auth; style: match OpenAI; feat: custom social login order (#1421)
* refactor(Login & Registration)

* fix(Registration) test errors

* refactor(LoginForm & ResetPassword)

* fix(LoginForm): display 'undefined' when loading page; style(SocialButton): match OpenAI's graphics

* some refactor and style update for social logins

* style: width like OpenAI; feat: custom social login order; refactor: alphabetical socials

* fix(Registration & Login) test

* Update .env.example

* Update .env.example

* Update dotenv.md

* refactor: remove `SOCIAL_LOGIN_ORDER` for `socialLogins` configured from `librechat.yaml`
- initialized by AppService, attached as app.locals property
- rename socialLoginOrder and loginOrder to socialLogins app-wide for consistency
- update types and docs
- initialize config variable as array and not singular string to parse
- bump data-provider to 0.3.9

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-05 03:31:18 -05:00
Marco Beretta
25da90657d 🔒✉️ feat: allow only certain domain (#1562)
* feat: allow only certain domain

* Update dotenv.md

* refactor( registrationController) & handle ALLOWED_REGISTRATION_DOMAINS not specified

* cleanup and moved to AuthService for better  error handling

* refactor: replace environment variable with librechat config item, add typedef for custom config, update docs for new registration object and allowedDomains values

* ci(AuthService): test for `isDomainAllowed`

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-02-05 02:14:52 -05:00
Fuegovic
b5c2fb93c1 🖋️ docs: Formatting Fix (#1726)
* 🍃 docs: Formatting Fix

* 🖋️ docs: Formatting Fix

* 🖋️ docs: Formatting Fix
2024-02-05 01:28:08 -05:00
Yuanlin Lin
d1cf02b5a8 🐳 docs: Add deploy to Zeabur button and guide (#1727)
* 🐳 docs: Add deploy to Zeabur button in README.md

* 🐳 docs: Add deploy to Zeabur guide in docs
2024-02-05 01:27:48 -05:00
Danny Avila
c31d5d9a1d 🐳 docs: Formatting Fix (#1725) 2024-02-04 17:18:12 -05:00
Danny Avila
7b38586716 🐳 docs: How to Authenticate MongoDB (#1724)
* refactor: remove `--noauth` flag from `mongod` command

* docs: add mongodb auth instructions

* Update manage_your_database.md

* chore: add example

* Update manage_your_database.md
2024-02-04 16:52:52 -05:00
MACHINSOFT
e7f6b22b5d 📱 style: Settings UI Enhancements for Mobile (#1721)
* Fix the interface for the mobile version.

* Make uniform margins for buttons.
2024-02-04 08:44:09 -05:00
Ryohei Kamiya
d25ff7632a 🐳 fix: Update .devcontainer Files (#1712)
* fix: modify the base docker image for devcontainer

* fix: restore package-lock.json from main
2024-02-04 08:39:19 -05:00
Danny Avila
335980ac98 🔧 fix: Patch incorrect Package Installation (#1720) 2024-02-03 20:41:02 -05:00
Danny Avila
74459d6261 ♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date

* Style: Infinite Scroll and Group convos by date- Redesign NavBar

* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code

* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component

* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component

* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component

* Including OpenRouter and Mistral icon

* refactor(Conversations): cleanup use of utility functions and typing

* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`

* refactor: remove use of `isFirstToday`

* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`

* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace

* chore: sort by `updatedAt` field

* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations

* feat: gen_title route for generating the title for the conversation

* style(Convo): change hover bg-color

* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions

* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT

* style(NewChat): add hover bg color

* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty

* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped

* style: hover bg-color

* feat: alt-click on convo item to open conversation in new tab

* chore: send error message when `gen_title` fails

---------

Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
Fuegovic
13b2d6e34a 🖊️ README.md: update button layout (#1709)
change size and position of the one click deployment buttons
2024-02-03 00:05:29 -05:00
Danny Avila
7934cc5ec4 🪙 fix(getModelMaxTokens): Retrieve Correct Context Tokens for Azure OpenAI (#1710) 2024-02-02 23:53:50 -05:00
Raí Santos
296967eff0 🖌️feat: ScrolltoBottom & Mobile Improvements; Translation Update (#1651)
* 🖌️feat: Scrolltobottom Style

* 🖌️feat: ScrolltoBottom Style

* 📱Settings tab now centered on mobile / selection bug fixed 🐞, 🌍 Updated Translation

* 🛠️fix: Adjust the width of the settings dialog and address the issue of not seeing selection on the desktop.

* 🎨 Update settings tabs background color for dark mode.
Adjusts background color dynamically based on screen size.

* 🛠️fix: Reverted changes in ScrolltoBottom file
2024-02-02 10:31:30 -05:00
Danny Avila
5f6d431136 📷 fix: Pass Base64 to Gemini Vision Payload when using CDN URLs (#1705) 2024-02-02 01:37:40 -05:00
Danny Avila
8479ac7293 🚀 feat: Support for GPT-3.5 Turbo/0125 Model (#1704)
* 🚀 feat: Support for GPT-3.5 Turbo/0125 Model

* ci: fix tx test
2024-02-02 01:01:11 -05:00
Danny Avila
30e143e96d 🪙 feat: Use OpenRouter Model Data for Token Cost and Context (#1703)
* feat: use openrouter data for model token cost/context

* chore: add ttl for tokenConfig and refetch models if cache expired
2024-02-02 00:42:11 -05:00
marlonka
f1d974c513 🌍 : Update German Translations (#1683)
Co-authored-by: marlonka <marloc55@yahoo.de>
2024-02-01 01:53:42 -05:00
Fuegovic
2b4870892a 🥷 docs: Ninja - ChatGPT-browser reverse proxy (#1697)
* 🥷  docs: Ninja ChatGPT-browser reverse proxy

* 🥷  docs: breaking changes
2024-02-01 01:44:51 -05:00
zimmra
a9220375d3 🤖 docs: add copilot-gpt4-service AI setup info (#1695)
Adds information and setup details for [aaamon's copilot-gpt4-service](https://github.com/aaamoon/copilot-gpt4-service) to Unofficial APIs section of the documentation.

Utilizes Github's Copilot to access OpenAI api.
2024-01-31 16:21:12 -05:00
Fuegovic
b37f55cd3a 📝 docs update: remove ChatGPTbrowser and other small fixes (#1686)
* 🧼 docs: remove references to ChatGPTbrowser and PandoraNext

* docs: clean up .env file

Update OpenAI models with the list of automatically fetched models, update Plugin models with the list of models supporting functions, comment out ToC in custom_config.md since it conflicts with mkdock right sidebar ToC

* 🖋️ docs: fix formatting in linux_install.md

* docs: update example model lists in dotenv.md

* docs: update breaking_changesv.md
2024-01-31 08:20:07 -05:00
Danny Avila
972402e029 🛡️ : Security Enhancements (#1681)
* fix: sanitize HTTP params and do not send whole error objects backs

* fix: prevent path traversal

* fix: send custom error message for tokenizer route

* chore: handle info exposure vector

* chore(oauth): skip check due to false positive as oauth routes are rate-limited

* chore(app): disable `x-powered-by`

* chore: disable false positives or flagging of hardcoded secrets when they are fake values

* chore: add path traversal safety check
2024-01-30 14:34:02 -05:00
Danny Avila
9fad1b2cae 🔝fix: Re-order System Message to Top for Mistral API Payloads (#1678)
* fix: re-order System Message if Mistral AI API as it only allows System Message at start of Payload

* fix: re-introduce singular system message change role to `user` if `system`
2024-01-30 10:13:32 -05:00
Kakenyan
c4fd8a38e3 🌍 : Update Japanese translation (#1666)
* Language translation: japanese

* Language translation: japanese
2024-01-30 07:32:09 -05:00
Linus Gasser
35e611f113 👤 fix: Avatar Check in User Auth (#1677) 2024-01-30 07:31:49 -05:00
Danny Avila
f7f7f929a0 📋 feat: Log Custom Config File and Add Known Model Limits to Custom Endpoint (#1657)
* refactor(custom): add all recognized models to maxTokensMap for custom endpoint

* feat(librechat.yaml): log the custom config file on initial load

* fix(OpenAIClient): pass endpointType/endpoint to `getModelMaxTokens` call
2024-01-27 08:59:04 -05:00
Danny Avila
c470147ea2 🐞 fix: Bump @langchain/google-genai to Address Chinese Text Bug (#1654) 2024-01-26 16:08:02 -05:00
Danny Avila
0edfa0483e 🧹 Clean Up OpenAI Config and Show 'Set Azure Key' for Plugins (#1649)
* refactor(gptPlugins): prevent edge case where exact word `azure` could be found in azure api Key detection when not an azure key

* refactor(SetKeyDialog): cleanup OpenAI config, show \'set azure key\' when `PLUGINS_USE_AZURE` env var is enabled
2024-01-26 09:27:20 -05:00
Danny Avila
fcbaa74e4a 🚀 feat: Support for GPT-4 Turbo/0125 Models (#1643) 2024-01-25 22:57:18 -05:00
bsu3338
d0730d2515 📖 docs: Update litellm.md with Redis and Langfuse (#1618) 2024-01-25 08:17:38 -05:00
Jo
f0b30b87c8 📖 docs: Update multilingual_information.md (#1622)
* Update multilingual_information.md

Some minor grammatical errors in the French translation

* Update multilingual_information.md
2024-01-25 07:49:35 -05:00
Danny Avila
d2efc7b9df 🌡️ feat: Add Health Check Route to Backend (#1623) 2024-01-24 11:39:20 -05:00
bsu3338
81ff598eba 🔏 feat: Nginx SSL Secure Config (#1615)
* Update nginx.conf

Add Mozilla SSL Configuration Generator recommended options.

* Update nginx.conf Remove Space
2024-01-23 07:30:26 -05:00
bsu3338
5730028b83 📖 docs: Update litellm.md to add Ollama (#1616) 2024-01-22 20:45:00 -05:00
Danny Avila
36560d5d9b 🛠️ fix: Preserve Dollar Signs in Code Blocks for LaTeX Parsing (#1612) 2024-01-22 10:02:36 -05:00
fidoriel
367c78f8d2 🐋 feat: CI Docker builds for arm64v8 (#1607) 2024-01-21 19:46:30 -05:00
Danny Avila
a0dabcc855 📱 fix(Root.tsx): Update styling to use h-dvh instead of h-screen (#1608) 2024-01-21 19:41:52 -05:00
Wahit Fitriyanto
42de461a83 🌍 : Update indonesian translation (#1601) 2024-01-20 15:22:25 -05:00
Fuegovic
cf4cdf8b4f 📱🍎 feat: PWA on iOS (#1602) 2024-01-20 15:21:40 -05:00
Naosuke Yokoe
3ed6cef58f 🐛 fix: Converted the getter name and description of Azure AI Search Plugin to a property (#1599) 2024-01-20 08:41:09 -05:00
Fuegovic
5ac89b8f0e 🧹 chore: remove deprecated model from documentation (#1598) 2024-01-19 16:14:02 -05:00
Danny Avila
5a74ac9a60 : Release v0.6.6 (#1597) 2024-01-19 15:34:06 -05:00
Fuegovic
130e346228 🌍 : Translation update (Fr & It) (#1595) 2024-01-19 15:01:23 -05:00
Marco Beretta
9b7d7196e9 🌎: Update Italian Translation (#1594)
* translation update

* translation updatre + new transaltions

* Update language files for English and Italian
2024-01-19 15:00:45 -05:00
Danny Avila
e73608ba46 🪶 feat: Add Support for Azure OpenAI Base URL (#1596)
* refactor(extractBaseURL): add handling for all possible Cloudflare AI Gateway endpoints

* chore: added endpointoption todo for updating type and optimizing handling app-wide

* feat(azureUtils):
- `genAzureChatCompletion`: allow optional client pass to update azure property
- `constructAzureURL`: optionally replace placeholders for instance and deployment names of an azure baseURL
- add tests for module

* refactor(extractBaseURL): return entire input when cloudflare `azure-openai` suffix detected
- also add more tests for both construct and extract URL

* refactor(genAzureChatCompletion): only allow omitting instance name if baseURL is not set

* refactor(initializeClient): determine `reverseProxyUrl` based on endpoint (azure or openai)

* refactor: utitlize `constructAzureURL` when `AZURE_OPENAI_BASEURL` is set

* docs: update docs on `AZURE_OPENAI_BASEURL`

* fix(ci): update expected error message for `azureUtils` tests
2024-01-19 14:57:03 -05:00
Raí Santos
5c94f5330a 🌎 : Update Portuguese Translation (#1593)
* 🌎: Update Portuguese Translation

* 🌎: Update Portuguese Translation
2024-01-19 09:14:26 -05:00
Danny Avila
f133bb98fe 🖌️ feat: Optional Display Username in Messages, Send/Stop Button Style, Localization (#1592)
* 👤add: Username instead of 'You' when sending messages.

* 🌎: Added a new translation for 'You' and updated the existing translation for Spanish.

* fix: remove "!"

* Added: New setting Account for show username in messages
chore (StopButon and SendButon): Updated to new style of ChatGPT
chore Update and Added news translations: Spanish, English and Portuguese Brazilian

* fix: message component definition and imports order, remove unnecessary useEffect and localStorage set, fix localStorage key in store

* chore: update readme.md

* chore: optimize condition for messageLabel

* chore(Message.tsx): remove empty blocks

---------

Co-authored-by: Raí Santos <140329135+itzraiss@users.noreply.github.com>
2024-01-19 03:44:02 -05:00
Carson Yang
3df58532d9 🚆 docs: Add Sealos 1-Click Deployment (#1578)
Add deploy on Sealos
2024-01-19 03:13:49 -05:00
Danny Avila
83292a47a7 📜 refactor: Enhance Auto Scroll Speed and UseEffect Cleanup (#1591) 2024-01-18 21:25:57 -05:00
Danny Avila
a7c54573c4 🚀 feat: Add OPENAI_ORGANIZATION for all OpenAI Requests (#1590) 2024-01-18 20:39:30 -05:00
Danny Avila
7e2e19a134 🎯 feat(config): Custom Endpoint Request Headers (#1588) 2024-01-18 20:11:42 -05:00
Danny Avila
ab3339210a 🖼️ feat(DALL-E): Azure OpenAI Support & New Config Variables (#1586)
* feat(DALL-E-3/DALL-E-2): Azure OpenAI support. New Version specific environment credentials:
 - DALLEx_SYSTEM_PROMPT=
 - DALLEx_AZURE_API_VERSION=
 - DALLEx_BASEURL=
 - DALLEx_API_KEY=
 - replace `x` with `3` or `2`

* docs: update docs based on new env vars and Azure OpenAI support for DALL-E

* docs: breaking change for user provided DALLE_API_KEY:
- **DALL-E Update**: user-provided keys for DALL-E are now specific to each DALL-E version, i.e.:  and
- Note:  will work for both DALL-E-3 and DALL-E-2 when the admin provides the credential; in other words, this may only affect your users if DALLE_API_KEY is not set in the  file. In this case, they will simply have to uninstall the plugin, and provide their API key again.

* refactor: use process.env at runtime instead of from memory to fix testing DALLE3.spec.js, adjust test
2024-01-18 19:39:27 -05:00
Danny Avila
a8d6bfde7a ✏️ feat: LaTeX parsing for Messages (#1585)
* feat: Beta features tab in Settings and LaTeX Parsing toggle

* feat: LaTex parsing with spec
2024-01-18 14:44:10 -05:00
Danny Avila
638f9242e5 🪙 refactor: Update tokens.js for Added Context Buffer from Max (#1573)
* Update tokens.js

* chore: linting previous PR

* chore: adjust token limits, add buffers

* chore: linting

* chore: adjust 32k gpt-4 limit
2024-01-17 08:13:46 -05:00
Wahit Fitriyanto
963dbf3a1e 🌏: Add indonesia translation (#1563)
* Added Indonesian Language

* added indonesian to eng.tsx and general.tsx
2024-01-16 22:52:43 -05:00
Raí Santos
7b4e31ecc4 🎨: Updated Plugins Search Bar; 🌎: Added Translations (#1549)
* 🎨: layout search bar plugins: updated  / 🌎: translation update

* 🌎:Update Portuguese Translation

* fix: Refactored 'pluginstoredialog' code.

* chore(PopoverButtons): remove comments, re-organize imports

* chore: linting and reorganize useState declarations

* chore: linting and reorganize useState declarations

---------

Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2024-01-16 13:15:39 -05:00
Ganesh Krishnan
406940490b 🐳 docs: Update dotenv.md (#1564)
docker compose is now a plugin of docker
2024-01-15 17:52:32 -05:00
Danny Avila
dfe45f80c6 📕 fix: Update document Title based on appTitle and on "New Chat" (#1553) 2024-01-14 20:35:37 -05:00
Ikko Eltociear Ashimine
0f49642758 🧹 docs: update docker_override.md (#1546)
minor fix
2024-01-14 19:05:13 -05:00
Danny Avila
783f64a6e5 🏗️ fix(config): Resolve Paths Correctly for Helper Scripts on Linux and Windows (#1542) 2024-01-13 13:06:07 -05:00
Danny Avila
0c48a9dd6e 📑 docs: fix mistral ai api example safe_mode --> safe_prompt (#1541) 2024-01-13 08:19:09 -05:00
Tyler Mendenhall
690cb9caa1 📔 docs: Update Render hosting Guide (#1528)
* add the IntelliJ Idea config file to .gitignore

* Update the docs for using a user created key and restricting mongodb IP access to public IP addresses
2024-01-12 18:14:42 -05:00
Pascal Helfenstein
b9d2a8fbb2 🚆docs: update hetzner ubuntu example (#1539) 2024-01-12 18:12:39 -05:00
Danny Avila
74cf22b71b 📑 docs: Update Mistral AI API example about dropParams (#1538) 2024-01-11 15:50:04 -05:00
Danny Avila
d7b4ed3079 🐛 fix: Remove resendImages, imageDetail from modelOptions for Custom Endpoints (#1537) 2024-01-11 13:42:00 -05:00
Danny Avila
73f79a60f6 📄chore: Update Discord Link README.md 2024-01-11 11:41:31 -05:00
Marco Beretta
6542c71c2b 🚆docs: Railway support (#1529)
* Update README.md

* Update README.md

---------

Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>
2024-01-11 11:40:26 -05:00
Danny Avila
d20970f5c5 🚀 Feat: Streamline File Strategies & GPT-4-Vision Settings (#1535)
* chore: fix `endpoint` typescript issues and typo in console info message

* feat(api): files GET endpoint and save only file_id references to messages

* refactor(client): `useGetFiles` query hook, update file types, optimistic update of filesQuery on file upload

* refactor(buildTree): update to use params object and accept fileMap

* feat: map files to messages; refactor(ChatView): messages only available after files are fetched

* fix: fetch files only when authenticated

* feat(api): AppService
- rename app.locals.configs to app.locals.paths
- load custom config use fileStrategy from yaml config in app.locals

* refactor: separate Firebase and Local strategies, call based on config

* refactor: modularize file strategies and employ with use of DALL-E

* refactor(librechat.yaml): add fileStrategy field

* feat: add source to MongoFile schema, as well as BatchFile, and ExtendedFile types

* feat: employ file strategies for upload/delete files

* refactor(deleteFirebaseFile): add user id validation for firebase file deletion

* chore(deleteFirebaseFile): update jsdocs

* feat: employ strategies for vision requests

* fix(client): handle messages with deleted files

* fix(client): ensure `filesToDelete` always saves/sends `file.source`

* feat(openAI): configurable `resendImages` and `imageDetail`

* refactor(getTokenCountForMessage): recursive process only when array of Objects and only their values (not keys) aside from `image_url` types

* feat(OpenAIClient): calculateImageTokenCost

* chore: remove comment

* refactor(uploadAvatar): employ fileStrategy for avatars, from social logins or user upload

* docs: update docs on how to configure fileStrategy

* fix(ci): mock winston and winston related modules, update DALLE3.spec.js with changes made

* refactor(redis): change terminal message to reflect current development state

* fix(DALL-E-2): pass fileStrategy to dall-e
2024-01-11 11:37:54 -05:00
USAGI
28a6807176 🌏: Update Zh.tsx (#1527)
Chinese Translation Update
2024-01-11 11:37:42 -05:00
Raí Santos
79c1783e3d 🌎: Update Portuguese Translation (#1523) 2024-01-08 20:58:28 -05:00
MACHINSOFT
e3abd0d345 🌍: Correct Localized Text of "Save & Submit" Button (#1517)
* To provide a full translation option for the button in other languages

* Add a modification for the old version of the chat
2024-01-08 14:12:05 -05:00
Danny Avila
8f9ef13325 fix(getUserPluginAuthValue): throws error if no user matches (#1522) 2024-01-08 11:12:51 -05:00
Danny Avila
ead1c3c797 🔧 fix: Error Handling Improvements (#1518)
* style(Icon): remove error bubble from message icon

* fix(custom): `initializeClient` now throws error if apiKey or baseURL are admin provided but no env var was found

* refactor(tPresetSchema): match `conversationId` type to `tConversationSchema` but optional, use `extendedModelEndpointSchema` for `endpoint`

* fix(useSSE): minor improvements
- use `completed` set to avoid submitting unecessary abort request
- set preset with `newConversation` calls using initial conversation settings to prevent default Preset override as well as default settings
- return if there is a parsing error within `onerror` as expected errors from server are properly formatted
2024-01-08 09:30:38 -05:00
Danny Avila
c9aaf502af feat(saveImageFromUrl): Dynamic Extension Handling (#1514)
- Enhanced the `saveImageFromUrl` function to dynamically handle file extensions based on the content type of the fetched image.
- Replaced the method of appending a '.png' extension with a more robust approach using regular expressions and the path module.
- Allows for correct extension replacement or addition, ensuring filename consistency and compatibility with the actual image format.
- Prevents issues with double extensions (e.g., 'someimage.jpg.png') and aligns saved file types with their respective content types.
2024-01-07 15:22:33 -05:00
Danny Avila
050a92b318 🔄 refactor(config): Move connectWithTimeout Outside of Helpers Module (#1513) 2024-01-07 14:43:27 -05:00
Danny Avila
9144680ffb 🐛 fix: Load dotenv at Top of Call Stack (#1512) 2024-01-07 14:32:59 -05:00
Danny Avila
bebfffb2d9 🛠️ fix: Custom Endpoint issues, Improve SSE Response Handling (#1510)
* fix(custom): prevent presets using removed custom endpoints from causing frontend errors

* refactor(abortMiddleware): send 204 status when abortController is not found/active, set expected header `application/json` when not set

* fix(useSSE): general improvements:
- Add endpointType to fetch URL in useSSE hook
- use EndpointURLs enum
- handle 204 response by setting `data` to initiated response
- add better error handling UX, make clear when there is an explicit error
2024-01-07 13:49:59 -05:00
Raí Santos
84892b5b98 🌎: Update Portuguese Translation (#1505) 2024-01-07 13:49:41 -05:00
Danny Avila
24cb9957cd ⬆️ fix(SendButton): correct dark theme bg when enabled (#1503) 2024-01-06 15:57:47 -05:00
Danny Avila
e870e6e83f 🧹 docs: formatting fix for custom_config.md 2024-01-06 12:12:59 -05:00
Danny Avila
2990f32f48 docs: minor mkdocs formatting issue in custom_config.md 2024-01-06 12:03:29 -05:00
Marco Beretta
9838a9e29e ⚖️ Update LICENSE.md Year: 2023 -> 2024 (#1501) 2024-01-06 12:00:20 -05:00
Danny Avila
3183d6b678 🐳 : Further Docker build Cleanup & Docs Update (#1502)
* refactor: post-cleanup changes:
- add more unnecessary paths to .dockerignore
- remove librechat.yaml from main compose file (prevents from being required)
- do not create librechat.yaml during build (does nothing)

* docs: make config file instructions easier to read, more info throughout other docs

* docs: add custom config to menu

* Update custom_config.md

* Update docker_compose_install.md
2024-01-06 11:59:08 -05:00
Linus Gasser
5d7869d3d5 🐳 : Improving Docker Build (#1415)
* Improving builds

When adding LibreChat to ansible, it rebuilt way too often, even if I
only changed the configuration.
With this PR, it should build only when the files of the app change.
Also removed the 'volumes' section for the 'api' in the docker-compose.yml.
At least with our installation it works fine like this.

* @danny-avila's comments

- removed 'env_file' from docker-compose.yml
- re-added link to '.env' in volumes

* Adding latest changes from main

* @danny-avila's comments

* Updating installation instructions

* @danny-avila's comments

- Remove unused environment in docker-compose.yml
- Re-add some steps for cleaning docker images
2024-01-06 11:44:49 -05:00
Danny Avila
8848b8a569 refactor: Mount Config File in Docker and Add to .dockerignore (#1493) 2024-01-04 22:14:53 -05:00
Danny Avila
9864fc8700 🔧 fix: Improve Endpoint Handling and Address Edge Cases (#1486)
* fix(TEndpointsConfig): resolve property access issues with typesafe helper function

* fix: undefined or null endpoint edge case

* refactor(mapEndpoints -> endpoints): renamed module to be more general for endpoint handling, wrote unit tests, export all helpers
2024-01-04 10:17:15 -05:00
Danny Avila
42f2353509 🗨️ refactor: Open New Tab for Ctrl+Click or Button Combo in NewChat (#1484) 2024-01-03 19:34:41 -05:00
Danny Avila
e1a529b5ae 🧪 feat: Experimental: Enable Switching Endpoints Mid-Conversation (#1483)
* fix: load all existing conversation settings on refresh

* refactor(buildDefaultConvo): use `lastConversationSetup.endpointType` before `conversation.endpointType`

* refactor(TMessage/messageSchema): add `endpoint` field to messages to differentiate generation origin

* feat(useNewConvo): `keepLatestMessage` param to prevent reseting the `latestMessage` mid-conversation

* style(Settings): adjust height styling to allow more space in dialog for additional settings

* feat: Modular Chat: experimental setting to Enable switching Endpoints mid-conversation

* fix(ChatRoute): fix potential parsing issue with tPresetSchema
2024-01-03 19:17:42 -05:00
Danny Avila
4befee829b 🛠️ fix: Error Message Parsing and ChatOpenAI credentials (#1482)
* refactor(createLLM): ensure ChatOpenAI class always uses client-defined openAIApiKey; move typedefs to main def file

* refactor(useSSE): improve error message parsing in error handler
2024-01-03 14:26:13 -05:00
Danny Avila
d6d3d2ba13 🔧 fix: langchain packages mismatch, mount config file for deploy-compose.yaml, silence config not found error (#1481)
* fix(api): version mismatch between langchain packages `@langchain/google-genai` & `langchain`

* chore(loadYaml): silence config file not found error

* chore: improve firebase init message when not configured (generalized)

* fix(deploy-compose.yml): mount `librechat.yaml` config file
2024-01-03 10:59:38 -05:00
Danny Avila
ac9543a673 🎨 style: Add Dynamic Height to Endpoint/Model Menus (#1480)
* style(EndpointsMenu): add scrolling and dynamic height

* style(SelectDropDownPop): add dynamic height
2024-01-03 10:07:36 -05:00
Danny Avila
29473a72db 💫 feat: Config File & Custom Endpoints (#1474)
* WIP(backend/api): custom endpoint

* WIP(frontend/client): custom endpoint

* chore: adjust typedefs for configs

* refactor: use data-provider for cache keys and rename enums and custom endpoint for better clarity and compatibility

* feat: loadYaml utility

* refactor: rename back to  from  and proof-of-concept for creating schemas from user-defined defaults

* refactor: remove custom endpoint from default endpointsConfig as it will be exclusively managed by yaml config

* refactor(EndpointController): rename variables for clarity

* feat: initial load custom config

* feat(server/utils): add simple `isUserProvided` helper

* chore(types): update TConfig type

* refactor: remove custom endpoint handling from model services as will be handled by config, modularize fetching of models

* feat: loadCustomConfig, loadConfigEndpoints, loadConfigModels

* chore: reorganize server init imports, invoke loadCustomConfig

* refactor(loadConfigEndpoints/Models): return each custom endpoint as standalone endpoint

* refactor(Endpoint/ModelController): spread config values after default (temporary)

* chore(client): fix type issues

* WIP: first pass for multiple custom endpoints
- add endpointType to Conversation schema
- add update zod schemas for both convo/presets to allow non-EModelEndpoint value as endpoint (also using type assertion)
- use `endpointType` value as `endpoint` where mapping to type is necessary using this field
- use custom defined `endpoint` value and not type for mapping to modelsConfig
- misc: add return type to `getDefaultEndpoint`
- in `useNewConvo`, add the endpointType if it wasn't already added to conversation
- EndpointsMenu: use user-defined endpoint name as Title in menu
- TODO: custom icon via custom config, change unknown to robot icon

* refactor(parseConvo): pass args as an object and change where used accordingly; chore: comment out 'create schema' code

* chore: remove unused availableModels field in TConfig type

* refactor(parseCompactConvo): pass args as an object and change where used accordingly

* feat: chat through custom endpoint

* chore(message/convoSchemas): avoid saving empty arrays

* fix(BaseClient/saveMessageToDatabase): save endpointType

* refactor(ChatRoute): show Spinner if endpointsQuery or modelsQuery are still loading, which is apparent with slow fetching of models/remote config on first serve

* fix(useConversation): assign endpointType if it's missing

* fix(SaveAsPreset): pass real endpoint and endpointType when saving Preset)

* chore: recorganize types order for TConfig, add `iconURL`

* feat: custom endpoint icon support:
- use UnknownIcon in all icon contexts
- add mistral and openrouter as known endpoints, and add their icons
- iconURL support

* fix(presetSchema): move endpointType to default schema definitions shared between convoSchema and defaults

* refactor(Settings/OpenAI): remove legacy `isOpenAI` flag

* fix(OpenAIClient): do not invoke abortCompletion on completion error

* feat: add responseSender/label support for custom endpoints:
- use defaultModelLabel field in endpointOption
- add model defaults for custom endpoints in `getResponseSender`
- add `useGetSender` hook which uses EndpointsQuery to determine `defaultModelLabel`
- include defaultModelLabel from endpointConfig in custom endpoint client options
- pass `endpointType` to `getResponseSender`

* feat(OpenAIClient): use custom options from config file

* refactor: rename `defaultModelLabel` to `modelDisplayLabel`

* refactor(data-provider): separate concerns from `schemas` into `parsers`, `config`, and fix imports elsewhere

* feat: `iconURL` and extract environment variables from custom endpoint config values

* feat: custom config validation via zod schema, rename and move to `./projectRoot/librechat.yaml`

* docs: custom config docs and examples

* fix(OpenAIClient/mistral): mistral does not allow singular system message, also add `useChatCompletion` flag to use openai-node for title completions

* fix(custom/initializeClient): extract env var and use `isUserProvided` function

* Update librechat.example.yaml

* feat(InputWithLabel): add className props, and forwardRef

* fix(streamResponse): handle error edge case where either messages or convos query throws an error

* fix(useSSE): handle errorHandler edge cases where error response is and is not properly formatted from API, especially when a conversationId is not yet provided, which ensures stream is properly closed on error

* feat: user_provided keys for custom endpoints

* fix(config/endpointSchema): do not allow default endpoint values in custom endpoint `name`

* feat(loadConfigModels): extract env variables and optimize fetching models

* feat: support custom endpoint iconURL for messages and Nav

* feat(OpenAIClient): add/dropParams support

* docs: update docs with default params, add/dropParams, and notes to use config file instead of `OPENAI_REVERSE_PROXY`

* docs: update docs with additional notes

* feat(maxTokensMap): add mistral models (32k context)

* docs: update openrouter notes

* Update ai_setup.md

* docs(custom_config): add table of contents and fix note about custom name

* docs(custom_config): reorder ToC

* Update custom_config.md

* Add note about `max_tokens` field in custom_config.md
2024-01-03 09:22:48 -05:00
Fuegovic
3f98f92d4c remove 'MEILI_HTTP_ADDR' (#1475) 2024-01-03 08:59:55 -05:00
Danny Avila
2b3fa327a3 fix(OpenAIClient): do not invoke abortCompletion on completion error (#1473) 2024-01-02 08:40:26 -05:00
Marco Beretta
c7306395e9 👮feat: moderation text (#1388)
* fixed some bugs and handling errors better

* feat: plugins support

* fix: prettier error message

* moved circular-json-es6 in /api

* docs: added openai moderation text

* fix(gptPlugins): incorrect merge

* discarding changes

* removed circular-json-es6
2024-01-01 15:08:02 -05:00
Raí Santos
1cd5fdf4f0 🌎: Update Portuguese Translation (#1461) 2024-01-01 12:01:38 -05:00
Fuegovic
52142b47ec 🌎: Update French Translation (#1472)
* 🌎: Update French Translation

* 🌎: Update French Translation

* 🌎: Update French Translation

* 🌎: Update French Translation
2024-01-01 12:01:06 -05:00
Fuegovic
659ba4374b update pull_request_template.md (#1466)
add "Translation update" the the PR type choices
2023-12-30 22:50:47 -05:00
Danny Avila
431fc6284f 🛠️ fix: Minor Fixes in Message, Ask/EditController, OpenAIClient, and countTokens (#1463)
* fix(Message): avoid overwriting unprovided properties

* fix(OpenAIClient): return intermediateReply on user abort

* fix(AskController): do not send/save final message if abort was triggered

* fix(countTokens): avoid fetching remote registry and exclusively use cl100k_base or p50k_base weights for token counting

* refactor(Message/messageSchema): rely on messageSchema for default values when saving messages

* fix(EditController): do not send/save final message if abort was triggered

* fix(config/helpers): fix module resolution error
2023-12-30 14:34:32 -05:00
MACHINSOFT
e4c555f95a Add Russian translation for the new functionality in the settings (#1457) 2023-12-30 13:25:37 -05:00
Linus Gasser
1a95bef677 📃 feat: add list-balances, remove-user, and improve User scripts (#1418)
* Refactoring opening of DB to config/helpers.js

* Adding two user scripts:

- 'delete-user' to remove a user definitely
- 'list-balances' to show the balances of all the users
2023-12-30 13:25:12 -05:00
Fuegovic
8735db0980 doc update: firebase.md (#1456) 2023-12-30 12:39:30 -05:00
Danny Avila
379e470e38 🧹fix: Handle Abort Message Edge Cases (#1462)
* chore: bump langchain to v0.0.213 from v0.0.186

* fix: handle abort edge cases:
- abort message server-side if response experienced error mid-generation
- attempt to recover message if aborting resulted in error
- if abortKey is not provided, use conversationId if it exists
- if headers were already sent, send an Event stream message
- issue warning for possible Google censor/filter

refactor(streamResponse): for `sendError`, allow passing overrides so that error can include partial generation, improve typing for `sendMessage`

* chore(MessageContent): remove eslint warning for unused `i`, rephrase unfinished message text

* fix(useSSE): avoid invoking cancelHandler if the abort response was 404

* chore(TMessage): remove unnecessary, unused legacy message property `submitting`

* chore(TMessage): remove unnecessary legacy message property `cancelled`

* chore(abortMiddleware): remove unused `errorText` property to avoid confusion
2023-12-30 12:34:23 -05:00
Marco Beretta
f19f5dca8e 🔥🚀 feat: CDN (Firebase) & feat: account section (#1438)
* localization + api-endpoint

* docs: added firebase documentation

* chore: icons

* chore: SettingsTabs

* feat: account pannel; fix: gear icons

* docs: position update

* feat: firebase

* feat: plugin support

* route

* fixed bugs with firebase and moved a lot of files

* chore(DALLE3): using UUID v4

* feat: support for social strategies; moved '/images' path

* fix: data ignored

* gitignore update

* docs: update firebase guide

* refactor: Firebase
- use singleton pattern for firebase initialization, initially on server start
- reorganize imports, move firebase specific files to own service under Files
- rename modules to remove 'avatar' redundancy
- fix imports based on changes

* ci(DALLE/DALLE3): fix tests to use logger and new expected outputs, add firebase tests

* refactor(loadToolWithAuth): pass userId to tool as field

* feat(images/parse): feat: Add URL Image Basename Extraction

Implement a new module to extract the basename of an image from a given URL. This addition includes the  function, which parses the URL and retrieves the basename using the Node.js 'url' and 'path' modules. The function is documented with JSDoc comments for better maintainability and understanding. This feature enhances the application's ability to handle and process image URLs efficiently.

* refactor(addImages): function to use a more specific regular expression for observedImagePath based on the generated image markdown standard across the app

* refactor(DALLE/DALLE3): utilize `getImageBasename` and `this.userId`; fix: pass correct image path to firebase url helper

* fix(addImages): make more general to match any image markdown descriptor

* fix(parse/getImageBasename): test result of this function for an actual image basename

* ci(DALLE3): mock getImageBasename

* refactor(AuthContext): use Recoil atom state for user

* feat: useUploadAvatarMutation, react-query hook for avatar upload

* fix(Toast): stack z-order of Toast over all components (1000)

* refactor(showToast): add optional status field to avoid importing NotificationSeverity on each use of the function

* refactor(routes/avatar): remove unnecessary get route, get userId from req.user.id, require auth on POST request

* chore(uploadAvatar): TODO: remove direct use of Model, `User`

* fix(client): fix Spinner imports

* refactor(Avatar): use react-query hook, Toast, remove unnecessary states, add optimistic UI to upload

* fix(avatar/localStrategy): correctly save local profile picture and cache bust for immediate rendering; fix: firebase init info message (only show once)

* fix: use `includes` instead of `endsWith` for checking manual query of avatar image path in case more queries are appended (as is done in avatar/localStrategy)

---------

Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
2023-12-29 21:42:19 -05:00
Marco Beretta
bd4d23d314 🚫🔍 feat: disallow search indexing (#1409)
* feat: disallow search indexing

* Update index.js

* Update .env.example

* added middleware
2023-12-29 20:42:04 -05:00
Danny Avila
c3d5a08b26 🐛 fix: Prevent Unnecessary Cloning of Symbols in Log Object (#1455)
fix(api/config/parsers): prevent cloning of unnecessary symbols within log object by using `klona` instead of `klona/full`, handle symbols edge case, log parsing errors, and use spaces instead of tab for cleaner logs
2023-12-29 20:20:57 -05:00
Nikita Dybov
20971aa005 🌎: Update Russian translations (#1413)
* Update Russian localization

* Update Ru.tsx

* fix: russian translation typing errors
2023-12-29 17:28:59 -05:00
Marco Beretta
443b491286 feat: allow FWA (#1440) 2023-12-29 17:28:07 -05:00
Marco Beretta
8be2b6f380 🌎: Italian translation update & refactor: translations (#1414)
* italian translation update

* fix: removed some translations

* refactor(Translation)
2023-12-28 17:10:58 -05:00
Fuegovic
bce4f41fae 🪪mkdocs: social cards (#1428)
* mkdocs plugins: add plugin for social cards and plugin that allow to exclude a folder

* docs: fix hyperlinks

* mkdocs: social cards (descriptions) for 'contributions' and 'deployment' guides

* mkdocs: social cards (descriptions) for all 'index.md'

* mkdocs: social cards (descriptions) for 'features' and 'plugins'

* mkdocs: social cards (descriptions) for 'general_info'

* mkdocs: social cards (descriptions) for 'configuration'

* mkdocs: social cards (descriptions) for 'installation'

* mkdocs: minor fixes

* update librechat.svg

* update how_to_contribute.md

add reference to the official GitHub documentation
2023-12-28 17:10:06 -05:00
Fuegovic
18cd02d44e Update French Translation (#1444) 2023-12-28 17:07:11 -05:00
Fuegovic
51050cc4d3 🧹📚 docs: refactor and clean up (#1392)
* 📑 update mkdocs

* rename docker override file and add to gitignore

* update .env.example - GOOGLE_MODELS

* update index.md

* doc refactor: split installation and configuration in two sub-folders

* doc update: installation guides

* doc update: configuration guides

* doc: new docker override guide

* doc: new beginner's guide for contributions - Thanks @Berry-13

* doc: update documentation_guidelines.md

* doc: update testing.md

* doc: update deployment guides

* doc: update /dev readme

* doc: update general_info

* doc: add 0 value to doc weight

* doc: add index.md to every doc folders

* doc: add weight to index.md and move openrouter from free_ai_apis.md to ai_setup.md

* doc: update toc so they display properly on the right had side in mkdocs

* doc: update pandoranext.md

* doc: index logging_system.md

* doc: update readme.md

* doc: update litellm.md

* doc: update ./dev/readme.md

* doc:🔖 new presets.md

* doc: minor corrections

* doc update: user_auth_system.md and presets.md, doc feat: add mermaid support to mkdocs

* doc update: add screenshots to presets.md

* doc update: add screenshots to - OpenID with AWS Cognito

* doc update: BingAI cookie instruction

* doc update: discord auth

* doc update: facebook auth

* doc: corrections to user_auth_system.md

* doc update: github auth

* doc update: google auth

* doc update: auth clean up

* doc organization: installation

* doc organization: configuration

* doc organization: features+plugins & update:plugins screenshots

* doc organization: deploymend + general_info  & update: tech_stack.md

* doc organization: contributions

* doc: minor fixes

* doc: minor fixes
2023-12-22 08:36:42 -05:00
Danny Avila
5c27fa304a Update pull_request_template.md (#1417) 2023-12-22 07:26:24 -05:00
Danny Avila
5b28362282 Release v0.6.5 (#1391)
*  Release v0.6.5

* fix(ci): use dynamic currentDateString
2023-12-19 01:09:42 -05:00
Danny Avila
8d563d61f1 feat: Azure Vision Support & Docs Update (#1389)
* feat(AzureOpenAI): Vision Support

* chore(ci/OpenAIClient.test): update test to reflect Azure now uses chatCompletion method as opposed to getCompletion, while still testing the latter method

* docs: update documentation mainly revolving around Azure setup, but also reformatting the 'Tokens and API' section completely

* docs: add images and links to ai_setup.md

* docs: ai setup reference
2023-12-18 18:43:50 -05:00
Danny Avila
c9d3e0ab6a 🚩 fix: Initialize Conversation Only when Necessary Data is Fetched (#1379)
* fix(ChatRoute): only initialize conversation after all data is fetched (models, endpoints, initialConversationQuery if not `new`)

* chore: remove unnecessary packages for rolling up api

* chore: bump data-provider package.json
2023-12-17 18:56:01 -05:00
Danny Avila
7c2134fb12 fix: revert fonts resolution path in vite.config.ts 2023-12-17 16:36:24 -05:00
Danny Avila
0c326797dd 📸 feat: Gemini vision, Improved Logs and Multi-modal Handling (#1368)
* feat: add GOOGLE_MODELS env var

* feat: add gemini vision support

* refactor(GoogleClient): adjust clientOptions handling depending on model

* fix(logger): fix redact logic and redact errors only

* fix(GoogleClient): do not allow non-multiModal messages when gemini-pro-vision is selected

* refactor(OpenAIClient): use `isVisionModel` client property to avoid calling validateVisionModel multiple times

* refactor: better debug logging by correctly traversing, redacting sensitive info, and logging condensed versions of long values

* refactor(GoogleClient): allow response errors to be thrown/caught above client handling so user receives meaningful error message
debug orderedMessages, parentMessageId, and buildMessages result

* refactor(AskController): use model from client.modelOptions.model when saving intermediate messages, which requires for the progress callback to be initialized after the client is initialized

* feat(useSSE): revert to previous model if the model was auto-switched by backend due to message attachments

* docs: update with google updates, notes about Gemini Pro Vision

* fix: redis should not be initialized without USE_REDIS and increase max listeners to 20
2023-12-16 20:45:27 -05:00
Fuegovic
676f133545 🍏Update mac_install.md (#1373)
The manual installation guide for mac was very outdated. This brings it up to date with the current method
2023-12-16 20:26:47 -05:00
Danny Avila
2dfade1c42 Update package.json 2023-12-15 15:52:56 -05:00
Danny Avila
509b1e5c63 🔄 refactor: Consolidate Ask/Edit Controllers (#1365)
* refactor(Ask/Edit): consolidate ask/edit controllers between the main modules and openAI controllers to reduce repetition of code and increase reusability

* fix(winston/logger): circular dependency issue

* fix(config/scripts): fix script imports

* refactor(indexSync): make not configured message an info log message

* chore: create a rollup script for api/server/index.js to check circular dependencies

* chore: bump @keyv/redis
2023-12-15 15:47:40 -05:00
Danny Avila
0958db3825 fix: Enhance Test Coverage and Fix Compatibility Issues 👷‍♂️ (#1363)
* refactor: only remove conversation states from localStorage on login/logout but not on refresh

* chore: add debugging log for azure completion url

* chore: add api-key to redact regex

* fix: do not show endpoint selector if endpoint is falsy

* chore: remove logger from genAzureChatCompletion

* feat(ci): mock fetchEventSource

* refactor(ci): mock all model methods in BaseClient.test, as well as mock the implementation for getCompletion in FakeClient

* fix(OpenAIClient): consider chatCompletion if model name includes `gpt` as opposed to `gpt-`

* fix(ChatGPTClient/azureOpenAI): Remove 'model' option for Azure compatibility (cannot be sent in payload body)

* feat(ci): write new test suite that significantly increase test coverage for OpenAIClient and BaseClient by covering most of the real implementation of the `sendMessage` method
- test for the azure edge case where model option is appended to modelOptions, ensuring removal before sent to the azure endpoint
- test for expected azure url being passed to SSE POST request
- test for AZURE_OPENAI_DEFAULT_MODEL being set, but is not included in the URL deployment name as expected
- test getCompletion method to have correct payload
fix(ci/OpenAIClient.test.js): correctly mock hanging/async methods

* refactor(addTitle): allow azure to title as it aborts signal on completion
2023-12-15 13:27:13 -05:00
Fuegovic
072a7e5f05 update: docker-compose.yaml 🐋 (#1341) 2023-12-15 02:41:33 -05:00
Danny Avila
ff59a2e41d fix: Avoid Throwing Errors for Unsupported Token Count Endpoints 🪙 (#1356) 2023-12-15 02:40:15 -05:00
Danny Avila
561ce8e86a feat: Google Gemini ❇️ (#1355)
* refactor: add gemini-pro to google Models list; use defaultModels for central model listing

* refactor(SetKeyDialog): create useMultipleKeys hook to use for Azure, export `isJson` from utils, use EModelEndpoint

* refactor(useUserKey): change variable names to make keyName setting more clear

* refactor(FileUpload): allow passing container className string

* feat(GoogleClient): Gemini support

* refactor(GoogleClient): alternate stream speed for Gemini models

* feat(Gemini): styling/settings configuration for Gemini

* refactor(GoogleClient): substract max response tokens from max context tokens if context is above 32k (I/O max is combined between the two)

* refactor(tokens): correct google max token counts and subtract max response tokens when input/output count are combined towards max context count

* feat(google/initializeClient): handle both local and user_provided credentials and write tests

* fix(GoogleClient): catch if credentials are undefined, handle if serviceKey is string or object correctly, handle no examples passed, throw error if not a Generative Language model and no service account JSON key is provided, throw error if it is a Generative m
odel, but not google API key was provided

* refactor(loadAsyncEndpoints/google): activate Google endpoint if either the service key JSON file is provided in /api/data, or a GOOGLE_KEY is defined.

* docs: updated Google configuration

* fix(ci): Mock import of Service Account Key JSON file (auth.json)

* Update apis_and_tokens.md

* feat: increase max output tokens slider for gemini pro

* refactor(GoogleSettings): handle max and default maxOutputTokens on model change

* chore: add sensitive redact regex

* docs: add warning about data privacy

* Update apis_and_tokens.md
2023-12-15 02:18:07 -05:00
Danny Avila
d259431316 fix: Add error handling for missing role in OpenAIClient.js (#1352) 2023-12-14 10:53:40 -05:00
Danny Avila
ea1dd59ef4 refactor(api): Central Logging 📜 (#1348)
* WIP: initial logging changes
add several transports in ~/config/winston
omit messages in logs, truncate long strings
add short blurb in dotenv for debug logging
GoogleClient: using logger
OpenAIClient: using logger, handleOpenAIErrors
Adding typedef for payload message
bumped winston and using winston-daily-rotate-file
moved config for server paths to ~/config dir
Added `DEBUG_LOGGING=true` to .env.example

* WIP: Refactor logging statements in code

* WIP: Refactor logging statements and import configurations

* WIP: Refactor logging statements and import configurations

* refactor: broadcast Redis initialization message with `info` not `debug`

* refactor: complete Refactor logging statements and import configurations

* chore: delete unused tools

* fix: circular dependencies due to accessing logger

* refactor(handleText): handle booleans and write tests

* refactor: redact sensitive values, better formatting

* chore: improve log formatting, avoid passing strings to 2nd arg

* fix(ci): fix jest tests due to logger changes

* refactor(getAvailablePluginsController): cache plugins as they are static and avoids async addOpenAPISpecs call every time

* chore: update docs

* chore: update docs

* chore: create separate meiliSync logger, clean up logs to avoid being unnecessarily verbose

* chore: spread objects where they are commonly logged to allow string truncation

* chore: improve error log formatting
2023-12-14 07:49:27 -05:00
Ed Burnette
49571ac635 chore: Get the latest of all github actions (#1335) 2023-12-14 07:44:38 -05:00
Fuegovic
1f5cb71a64 documentation update: mongodb (#1347)
* update dotenv.md

add details about the MONGO_URI connection string format

* update mongodb.md

add details about the MONGO_URI connection string format
2023-12-14 07:44:20 -05:00
Fuegovic
bff365785a update: issue templates (#1346)
* update BUG-REPORT.yml

remove the contact field asking for the email address since it exposes them to the web when used

* update FEATURE-REQUEST.yml

remove the contact field since it exposes users email address

* Update QUESTION.yml

remove the contact field since it exposes users email address
2023-12-13 12:42:18 -05:00
Fuegovic
f2fc47e741 📚 documentation update (#1340) 2023-12-13 09:45:03 -05:00
Fuegovic
44755c964f update huggingface.md (#1342)
change the URL of the space to duplicate for a cleaner template I made
2023-12-13 06:52:21 -05:00
Danny Avila
fac2580a19 fix(librechat-data-provider): Update types paths in package.json (#1333)
* fix(librechat-data-provider): Update types paths in package.json

* chore: bump version

* fix(librechat-data-provider): Update types paths in react-query/package.json
2023-12-12 09:16:29 -05:00
Danny Avila
6829d66c1f Update docker_compose_install.md 2023-12-11 22:44:27 -05:00
Danny Avila
4df6a261d3 Update README.md 2023-12-11 22:43:37 -05:00
Danny Avila
e69644d7b4 fix: docker issues with volume mapping (#1330)
* fix: docker issues with volume mapping

* Update docker-compose.yml

---------

Co-authored-by: stunt_pilot <twitchstuntpilot@gmail.com>
2023-12-11 22:39:24 -05:00
Fuegovic
9db3d792cc update .env.example (#1327)
remove client_id and secret values for discord and github so they won't show in the UI without being properly configured
2023-12-11 17:23:38 -05:00
Danny Avila
df1dfa7d46 refactor: Use librechat-data-provider app-wide 🔄 (#1326)
* chore: bump vite, vitejs/plugin-react, mark client package as esm, move react-query as a peer dep in data-provider

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

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

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

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

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

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

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

* fix(ci): jest `librechat-data-provider/react-query` module resolution
2023-12-11 14:48:40 -05:00
Ed Burnette
d4c846b543 fix: fonts warning (#1318)
* fix: Fix a fonts warning
    The warning was:
    files in the public directory are served at the root path.
    Instead of /public/fonts/soehne-buch.woff2, use /fonts/soehne-buch.woff2.

* See if it likes /fonts better
2023-12-10 17:19:51 -05:00
Danny Avila
968b8ccdbd 🔒 fix: Robust Cache Reset on User Logout (#1324)
* refactor(Logout): rely on hooks for mutation behavior

* fix: logging out now correctly resets cache, disallowing any cache mixing between the next logged in user on the same browser

* chore: remove additional localStorage values on logout
2023-12-10 17:13:42 -05:00
Danny Avila
583e978a82 feat(Google): Support all Text/Chat Models, Response streaming, PaLM -> Google 🤖 (#1316)
* feat: update PaLM icons

* feat: add additional google models

* POC: formatting inputs for Vertex AI streaming

* refactor: move endpoints services outside of /routes dir to /services/Endpoints

* refactor: shorten schemas import

* refactor: rename PALM to GOOGLE

* feat: make Google editable endpoint

* feat: reusable Ask and Edit controllers based off Anthropic

* chore: organize imports/logic

* fix(parseConvo): include examples in googleSchema

* fix: google only allows odd number of messages to be sent

* fix: pass proxy to AnthropicClient

* refactor: change `google` altName to `Google`

* refactor: update getModelMaxTokens and related functions to handle maxTokensMap with nested endpoint model key/values

* refactor: google Icon and response sender changes (Codey and Google logo instead of PaLM in all cases)

* feat: google support for maxTokensMap

* feat: google updated endpoints with Ask/Edit controllers, buildOptions, and initializeClient

* feat(GoogleClient): now builds prompt for text models and supports real streaming from Vertex AI through langchain

* chore(GoogleClient): remove comments, left before for reference in git history

* docs: update google instructions (WIP)

* docs(apis_and_tokens.md): add images to google instructions

* docs: remove typo apis_and_tokens.md

* Update apis_and_tokens.md

* feat(Google): use default settings map, fully support context for both text and chat models, fully support examples for chat models

* chore: update more PaLM references to Google

* chore: move playwright out of workflows to avoid failing tests
2023-12-10 14:54:13 -05:00
Ed Burnette
8a1968b2f8 chore: Clean up the devcontainer files (#1317)
* Spruce up docker-compose for dev container

* Update devcontainer.json to remove unused lines

* It's /workspaces not /workspace
2023-12-10 09:49:21 -05:00
Marco Beretta
34d2da1ffc 📚 docs: Facebook update (#1312)
* Update user_auth_system.md

* Update user_auth_system.md

* Update user_auth_system.md
2023-12-08 14:05:24 -05:00
eniyiweb
427b05b891 🌎: Additional Turkish translations (#1310)
* Language translation:Turkish translation update

* 🌍: Turkish Translation - Update

* Additional Turkish translations

* Additional Turkish translations
2023-12-08 06:58:47 -05:00
Fuegovic
c2d8ae8616 📚 documentation update (#1307)
* fix .env.example

comment out DALLE_API_KEY by default and remove `user_provided` as default value since it is not supported

* 📚 docs update
2023-12-07 22:44:26 -05:00
Danny Avila
9041fe7472 feat: Make Nav Visible by Default on Clean Install 🧭 (#1309) 2023-12-07 22:42:14 -05:00
Marco Beretta
20b93ad065 feat: open sidebar popup for new users (#1308) 2023-12-07 22:40:23 -05:00
Danny Avila
10ace5fa75 🌎: Add Supported Languages to README.md 2023-12-07 14:37:56 -05:00
Fuegovic
b822cd48d2 bug fix: remove 3rd party code interpreter (#1306) 2023-12-07 14:27:52 -05:00
Ken Taniguchi
4d528efaf6 🇯🇵🗾: Japanese Translations (add and improve) (#1298) 2023-12-07 09:35:22 -05:00
Danny Avila
0bae503a0a refactor: Speed up Config fetching and Setup Config Groundwork 👷🚧 (#1297)
* refactor: move endpoint services to own directory

* refactor: make endpointconfig handling more concise, separate logic, and cache result for subsequent serving

* refactor: ModelController gets same treatment as EndpointController, draft OverrideController

* wip: flesh out override controller more to return real value

* refactor: client/api changes in anticipation of override
2023-12-06 19:36:57 -05:00
Danny Avila
9b2359fc27 🛠️ refactor: Improve Input Placeholder Handling and Error Management 🔄 (#1296)
* chore: identify new chat buttons with testid

* fix: avoid parsing error in useSSE, which causes errorHandler to fail

* fix: ensure last message isn't setting latestMessage when conversationId is `new` and text is the same due to possible re-renders

* refactor: set placeholder through inputRef and useEffect

* Update useSSE.ts

* Update useSSE.ts
2023-12-06 14:10:06 -05:00
Marco Beretta
2e390596ea return 404 instead of 200 (#1294) 2023-12-06 14:08:15 -05:00
Danny Avila
ca64efec1b feat: Implement Default Preset Selection for Conversations 📌 (#1275)
* fix: type issues with icons

* refactor: use react query for presets, show toasts on preset crud, refactor mutations, remove presetsQuery from Root (breaking change)

* refactor: change preset titling

* refactor: update preset schemas and methods for necessary new properties `order` and `defaultPreset`

* feat: add `defaultPreset` Recoil value

* refactor(getPresetTitle): make logic cleaner and more concise

* feat: complete UI portion of defaultPreset feature, with animations added to preset items

* chore: remove console.logs()

* feat: complete default preset handling

* refactor: remove user sensitive values on logout

* fix: allow endpoint selection without default preset overwriting
2023-12-06 14:00:15 -05:00
Marco Beretta
fdb65366d7 📧 feat: disable login (ALLOW_EMAIL_LOGIN) (#1282)
* added ALLOW_EMAIL_LOGIN

* update .env.example

* fix(config) email login true by default

* Update dotenv.md
2023-12-06 07:08:49 -05:00
Fuegovic
1706886a64 doc: PandoraNext guide (#1276) 2023-12-06 06:57:10 -05:00
Danny Avila
00b6af8c74 fix: Ensure Message Send Requires Key 🔑 (#1281)
* fix: only allow message send when key is provided when required
- create useRequiresKey hook
- pass same disabled prop to Textarea, AttachFile, and SendButton
- EndpointItem: add localization, stopPropagation, and remove commented code
- separate some hooks to new Input dir
- completely remove textareaHeight recoil state as is not needed
- update imports for moved hooks
- pass disabled prop to useTextarea

* feat: add localization to textarea placeholders
2023-12-05 09:38:04 -05:00
Fuegovic
f6118879e5 🔎 update: meilisearch (#1269) 2023-12-05 08:38:41 -05:00
MACHINSOFT
270031c783 🪟 Minor UI Styling Changes (#1260)
* Correct the display of the interface when hovering with the mouse

* Replace ring-1 with border completely.

* Fix it so that the text does not overlap with the SVG in mobile navigation.

* Remove the extra class -ml-0.5 -mt-0.5, there is no need to shift the buttons
2023-12-05 08:37:36 -05:00
Danny Avila
f1bc711cd7 🐛 fix: Prevent Node Server Crash Due to Unhandled ChatCompletionMessage Error (#1278)
* refactor(addTitle): avoid generating title when a request was aborted

* chore: bump openai to latest

* fix: catch OpenAIError Uncaught error as last resort

* fix: handle final messages excludes role=assistant

* Update OpenAIClient.js

* chore: fix linting errors
2023-12-04 22:58:23 -05:00
eniyiweb
076a9b9b9c 🇹🇷: Additional Turkish translations (#1265)
* Language translation:Turkish translation update

* 🌍: Turkish Translation - Update

* Additional Turkish translations
2023-12-04 16:50:33 -05:00
Danny Avila
329aa6d164 docs: update README. with features on top 2023-12-03 11:43:59 -05:00
Fuegovic
9d21d1c5b9 Refactor .env.example and Add dotenv.md (#1258) 2023-12-03 09:52:13 -05:00
Raí Santos
25f460f454 Fix: AzureAISearch Plugin Files 🔎 (#1259)
* Update azure_cognitive_search.md

* Updated: Azure Cognitive Search Plugin to Azure AI Search Plugin.

Update Docs: Azure Cognitive Search Plugin to Azure AI Search Plugin.

Updated:.env.example Azure Cognitive Search to Azure AI Search

Updated: mkdocs.yml link

Updated: SDK Azure 11.3.2 to 12.0.0

* fix:.env AZURE- to AZURE_

* Update azure_ai_search.md

* Updated:(api/package.json, package-lock.json): updated for new version the
  plugin (@azure/search-documents)

* fix:Resolved incorrect file name AzureAISearch

* fix:.env Azure AI Search

* fix:"-" to "_"

* Update Docs: Azure AI Search ith an improved tutorial featuring images and easier-to-understand instructions

fix: Change name of plugin "Azure Ai Search" to "Azure AI Search" i

* Update:Version of REST API versions (Azure AI Search)

* Update azure_ai_search.md

* Update azure_ai_search.md

* Update azure_ai_search.md

* fix: docs Azure AI Seach Images were not appearing.

* fix:Updated to the new repository with working APIs

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: o AzureAiSearch.js

* Atualizar o AzureAISearch.js

* Update/fix:EnvironmentVariablesForDeprecation

* fix:The file is outdated and needs to be updated.

* fix:The file is outdated and needs to be updated.

* update: translation portuguese brazilian

* Refactor:Improve Readability and Cleanliness of AzureAISearch Class

* Update AzureAiSearch.js

* Update AzureAISearch.js

* fix:getServiceEndpoint

* fix: getServiceEndpoint

* fix:AzureAISearch

* fix: Fix functions erros AzureAISearch

* fix: Update API_VERSION

* fix: AzureAISearch files outdated
2023-12-02 19:22:12 -05:00
Danny Avila
4674a54c70 refactor: Consolidate Message Scrolling & other Logic to Custom Hooks 🔄 (#1257)
* refactor: remove unnecessary drilling/invoking of ScrollToBottom
- feat: useMessageScrolling: consolidates all scrolling logic to hook
- feat: useMessageHelpers: creates message utilities and consolidates logic from UI component

* fix: ensure automatic scrolling is triggered by messagesTree re-render and is throttled
2023-12-01 19:54:09 -05:00
MACHINSOFT
ebd23f7295 🌎: Additional Russian translations (#1251) 2023-12-01 18:10:17 -05:00
Danny Avila
1d24f39830 style: update Mobile Nav with new ChatGPT styling; fix: New Chat on Mobile will correctly reset conversation state (#1255) 2023-12-01 17:00:57 -05:00
Danny Avila
3e7a29c9dd 🎨 fix: Update MessagesView Styling (#1254)
* style: update MessagesView to exact ChatGPT styling

* style(ScrollToBottom): make fixed for larger screens

* fix(ScrollToBottom): revert to absolute from fixed and change bottom values
2023-12-01 10:11:39 -05:00
Danny Avila
98827440eb fix(images/resize): invoke rotate to auto-orient the image based on the EXIF data (#1250) 2023-11-30 13:59:51 -05:00
Ishaan Jaff
2bcfb04a72 📚 docs: Add LiteLLM Proxy - Load balance 100+ LLMs & Spend Tracking ⚖️🤖📈 (#1249)
* (docs) add instructions on using litellm

* Update litellm.md

---------

Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>
2023-11-30 13:59:16 -05:00
Raí Santos
d327c8f5d2 Updated: Azure Cognitive Search Plugin/ Free AI APIs 🔎 (#1230)
* Update azure_cognitive_search.md

* Updated: Azure Cognitive Search Plugin to Azure AI Search Plugin.

Update Docs: Azure Cognitive Search Plugin to Azure AI Search Plugin.

Updated:.env.example Azure Cognitive Search to Azure AI Search

Updated: mkdocs.yml link

Updated: SDK Azure 11.3.2 to 12.0.0

* fix:.env AZURE- to AZURE_

* Update azure_ai_search.md

* Updated:(api/package.json, package-lock.json): updated for new version the
  plugin (@azure/search-documents)

* fix:Resolved incorrect file name AzureAISearch

* fix:.env Azure AI Search

* fix:"-" to "_"

* Update Docs: Azure AI Search ith an improved tutorial featuring images and easier-to-understand instructions

fix: Change name of plugin "Azure Ai Search" to "Azure AI Search" i

* Update:Version of REST API versions (Azure AI Search)

* Update azure_ai_search.md

* Update azure_ai_search.md

* Update azure_ai_search.md

* fix: docs Azure AI Seach Images were not appearing.

* fix:Updated to the new repository with working APIs

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: Added Compatibility for Previous Environment Variable Names in AzureAISearch Plugin

* Update: o AzureAiSearch.js

* Atualizar o AzureAISearch.js

* Update/fix:EnvironmentVariablesForDeprecation

* fix:The file is outdated and needs to be updated.

* fix:The file is outdated and needs to be updated.

* update: translation portuguese brazilian

* Refactor:Improve Readability and Cleanliness of AzureAISearch Class

* Update AzureAiSearch.js

* Update AzureAISearch.js
2023-11-30 13:50:28 -05:00
Fuegovic
690acf1c93 docs: mongo-express 🍃 (#1247)
* docs: mongo-express

* Update manage_your_database.md

add screenshot and mongodb logo

* Update manage_your_database.md

upload smaller mongodb logo
2023-11-30 13:49:39 -05:00
Danny Avila
53d0ffcd11 Fix: catch uncaught OpenAIError handling in server index.js and log info (#1248) 2023-11-30 13:29:55 -05:00
Danny Avila
94df631c44 fix(PluginsClient/getFunctionModelName): returns input if agent model is function capable (#1246) 2023-11-30 12:50:52 -05:00
Danny Avila
166a4fa44f 🛠️ fix: Improve SSE Handling and Fix Typo in sendEmail Template (#1245)
* fix: typo for passwordReset.handlebars

* fix(useSSE): prevent unnecessary JSON.parse abort error, handle immediate abort-submit gracefully by reverting to previous state before immediate abort-submit, add showStopButton state to explicitly render disabled sendButton when message generation is cancelled, filter undefined messages and replace undefined convo for cancelHandler
2023-11-30 10:23:57 -05:00
Danny Avila
e13b146d6d 🔧 fix: Correct Properties Passed to getResponseSender, Catch OpenAI Errors (#1244)
* fix: attempt to catch more errors, especially when generation started

* fix: pass the right properties to getResponseSender

* chore: Update .eslintrc.js and fix sendEmail.js linting errors
2023-11-29 13:40:16 -05:00
David
ae03267d9b 📧 feat: Allow usage of custom SMTP server (#1219)
Co-authored-by: David Reis <post@d-reis.com>
2023-11-28 18:00:07 -05:00
Marco Beretta
3838ff4617 🌍: Dutch translation, fix translation, style(Dropdown): added scroll (#1218)
* italian translation

* some translation fixes + dutch translation

* fix(Dropdown) more dynamic

* fix(Nl)

* fix(Nl)

* added comment in Nl.tsx
2023-11-28 17:42:31 -05:00
Jonas Wunderlich
822914d521 fix: conversation title truncation (#1237) 2023-11-27 21:07:32 -05:00
Danny Avila
f5f5b2bbdb fix: Resolve Token Credit Balance Issues for Instruct Models 🛠️ (#1232)
* Fix: balance update error and add environment variable check

* fix(ChatGPTClient): return promptTokens for instruct/davinci models

* chore: remove unnecessary comments
2023-11-26 18:12:27 -05:00
Danny Avila
d7ef4590ea 🔧 Fix: Resolve Anthropic Client Issues 🧠 (#1226)
* fix: correct preset title for Anthropic endpoint

* fix(Settings/Anthropic): show correct default value for LLM temperature

* fix(AnthropicClient): use `getModelMaxTokens` to get the correct LLM max context tokens, correctly set default temperature to 1, use only 2 params for class constructor, use `getResponseSender` to add correct sender to response message

* refactor(/api/ask|edit/anthropic): save messages to database after the final response is sent to the client, and do not save conversation from route controller

* fix(initializeClient/anthropic): correctly pass client options (endpointOption) to class initialization

* feat(ModelService/Anthropic): add claude-1.2
2023-11-26 14:44:57 -05:00
Danny Avila
4b289640f2 fix: will correctly switch endpoints and reset the convo if the first message returned was an error (#1225) 2023-11-26 14:24:43 -05:00
Danny Avila
12209fe0dd refactor: address potential issues with deploy-compose.yml (#1220)
* chore: remove /config/loader

* chore: remove config/loader steps from Dockerfile.multi

* chore: remove install script
2023-11-25 16:34:51 -05:00
Danny Avila
4dab094855 fix: prevent convo overwrite on convo refresh and combine with remote models handling (#1217) 2023-11-25 09:19:13 -05:00
MACHINSOFT
ebe62ad250 style: Login and registration 🛂 (#1214) 2023-11-24 16:49:14 -05:00
Danny Avila
cc39074e0a 🛠️ refactor: Handle .webp, Improve File Life Cycle 📁 (#1213)
* fix: handle webp images correctly

* refactor: use the userPath from the start of the filecycle to avoid handling the blob, whose loading may fail upon user request

* refactor: delete temp files on reload and new chat
2023-11-24 16:45:06 -05:00
Danny Avila
650759306d feat: deploy-compose NGINX volume mapping, add image removal to update script (#1211) 2023-11-22 23:35:08 -05:00
Danny Avila
398687fad0 fix: Increase client_max_body_size for larger file uploads through nginx (#1210) 2023-11-22 19:07:01 -05:00
Danny Avila
55cdd2eec6 refactor: use fileSize limiternative to multer (#1209) 2023-11-22 18:42:21 -05:00
Danny Avila
5e6f8cbce7 fix: Correct Default Model Name in Response Sender and Update Anthropics 🤖 (#1208)
* feat: add claude-2.1 to default anthropic models

* chore: remove console log in NavLinks

* fix: issue with response sender not using model name, change anthropic default value to Claude

* fix: preset will not be selected on edit
2023-11-22 18:29:09 -05:00
Danny Avila
f3402401f1 feat: Order/disable endpoints with ENDPOINTS env var (#1206)
* fix: endpoint will not be select if disabled

* feat: order and disable endpoints with ENDPOINTS env var

* chore: remove console.log
2023-11-22 13:56:38 -05:00
Danny Avila
f05f6826f5 fix: Textarea Scroll fix, Duplicate Key fix (#1204)
* fix(Es): duplicate keys

* fix(Textarea): overflowY auto
2023-11-22 08:29:22 -05:00
Danny Avila
317cdd3f77 feat: Vision Support + New UI (#1203)
* feat: add timer duration to showToast, show toast for preset selection

* refactor: replace old /chat/ route with /c/. e2e tests will fail here

* refactor: move typedefs to root of /api/ and add a few to assistant types in TS

* refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages

* feat: add dataService for uploading images

* feat(data-provider): add mutation keys

* feat: file resizing and upload

* WIP: initial API image handling

* fix: catch JSON.parse of localStorage tools

* chore: experimental: use module-alias for absolute imports

* refactor: change temp_file_id strategy

* fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling

* feat: properly handle file deletion

* refactor: unexpose complete filepath and resize from server for higher fidelity

* fix: make sure resized height, width is saved, catch bad requests

* refactor: use absolute imports

* fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient

* refactor: import supportsFiles and models vars from schemas

* fix: correctly replace temp file id

* refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays

* feat: add validateVisionModel to determine if model has vision capabilities

* chore(checkBalance): update jsdoc

* feat: formatVisionMessage: change message content format dependent on role and image_urls passed

* refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL

* feat: working vision support
TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging

* feat: clipboard support for uploading images

* feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook  has ChatContext

* fix(Images): replace uploaded images in place

* feat: add filepath validation to protect sensitive files

* fix: ensure correct file_ids are push and not the Map key values

* fix(ToastContext): type issue

* feat: add basic file validation

* fix(useDragHelpers): correct context issue with `files` dependency

* refactor: consolidate setErrors logic to setError

* feat: add dialog Image overlay on image click

* fix: close endpoints menu on click

* chore: set detail to auto, make note for configuration

* fix: react warning (button desc. of button)

* refactor: optimize filepath handling, pass file_ids to images for easier re-use

* refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages

* feat: lazy loading images including use of upload preview

* fix: SetKeyDialog closing, stopPropagation on Dialog content click

* style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly

* style: change maxheight of all settings textareas to 138px from 300px

* style: better styling for textarea and enclosing buttons

* refactor(PresetItems): swap back edit and delete icons

* feat: make textarea placeholder dynamic to endpoint

* style: show user hover buttons only on hover when message is streaming

* fix: ordered list not going past 9, fix css

* feat: add User/AI labels; style: hide loading spinner

* feat: add back custom footer, change original footer text

* feat: dynamic landing icons based on endpoint

* chore: comment out assistants route

* fix: autoScroll to newest on /c/ view

* fix: Export Conversation on new UI

* style: match message style of official more closely

* ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed

* feat: more file validation and use blob in preview field, not filepath, to fix temp deletion

* feat: filefilter for multer

* feat: better AI labels based on custom name, model, and endpoint instead of  `ChatGPT`
2023-11-21 20:12:48 -05:00
eniyiweb
345f4b2e85 🌍: Turkish Translation - Update (#1195)
* Language translation:Turkish translation update

* 🌍: Turkish Translation - Update
2023-11-21 11:33:04 -05:00
madonchik123
d043a849a9 Added Reverse Proxy for Anthropic (#1106)
* Update AnthropicClient.js

Added BaseURL

* Update .env.example

Added ANTHROPIC_REVERSE_PROXY ENV

* Update initializeClient.js

Added Reverse_Proxy

* Update .env.example

* Update initializeClient.js

* Update AnthropicClient.js

* Update .env.example

Request

* Update initializeClient.js

Mae ANTHROPIC_REVERSE_PROXY let instead of const

* fix: lint errors, refactor(initializeClient)

* chore: change casing of reverseProxy

---------

Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>
2023-11-20 20:12:53 -05:00
Raí Santos
b7dcc4264d 🌍: Portuguese and Spanish Translation - Update (#1202)
* Update Translation to Portugues Brasil

* Update Translation to Language Portugues Brasileiro

* Update Translation to Language Español

* Fix Translation to Language Español

* Update Es.tsx

* Update Br.tsx
2023-11-19 16:03:27 -05:00
Marco Beretta
ab5c81d063 style: Beta UI fixes (#1199)
* fix(EditPresetDialog) endpoint menu

* style: update anthropic's icon & removed hover:bg in PresetItems

* style(OptionsPopover) rounded SaveAsPreset

* style(PresetItems) removed hover:bg

* style(NavLinks) match to openai

* style(NavLinks)

* fix(EditPresetDialog): remove empty cn call

---------

Co-authored-by: Danny Avila <110412045+danny-avila@users.noreply.github.com>
2023-11-18 16:45:51 -05:00
ngoctuanai
1fc896d0bd Update Vi.tsx (#1200) 2023-11-18 10:42:50 -05:00
Danny Avila
1ba8d4ffa9 style: Minor Beta UI fixes (#1197)
* style(Header): hide scrollbar but still allow side scroll/swipe/drag/touch

* feat: make menu buttons flexiblewith min-width, delete passed in classes, add pointer-cursor

* refactor: use conditional for visibility of plugins settings

* fix: make advanced settings popover appear over nav

* refactor(textarea): minor padding restyling, add max height

* style: make menuItem checkmark invisible instead of hidden so it takes up width space

* style: make presetsMenu trigger an icon button, remove max-width of presets except in mobile view

* style: improve advanced settings mobile styling

* feat: newchat and convo items toggle nav on small screens

* style: improve no presets view

* style: make sure toggle hover effect does not apply on smaller screens
2023-11-17 08:00:42 -05:00
Danny Avila
c64970525b feat: allow any reverse proxy URLs, add proxy support to model fetching (#1192)
* feat: allow any reverse proxy URLs

* feat: add proxy support to model fetching
2023-11-16 18:56:09 -05:00
Danny Avila
bac1fb67d2 WIP: Update UI to match Official Style; Vision and Assistants 👷🏽 (#1190)
* wip: initial client side code

* wip: initial api code

* refactor: export query keys from own module, export assistant hooks

* refactor(SelectDropDown): more customization via props

* feat: create Assistant and render real Assistants

* refactor: major refactor of UI components to allow multi-chat, working alongside CreationPanel

* refactor: move assistant routes to own directory

* fix(CreationHeader): state issue with assistant select

* refactor: style changes for form, fix setSiblingIdx from useChatHelpers to use latestMessageParentId, fix render issue with ChatView and change location

* feat: parseCompactConvo: begin refactor of slimmer JSON payloads between client/api

* refactor(endpoints): add assistant endpoint, also use EModelEndpoint as much as possible

* refactor(useGetConversationsQuery): use object to access query data easily

* fix(MultiMessage): react warning of bad state set, making use of effect during render (instead of useEffect)

* fix(useNewConvo): use correct atom key (index instead of convoId) for reset latestMessageFamily

* refactor: make routing navigation/conversation change simpler

* chore: add removeNullishValues for smaller payloads, remove unused fields, setup frontend pinging of assistant endpoint

* WIP: initial complete assistant run handling

* fix: CreationPanel form correctly setting internal state

* refactor(api/assistants/chat): revise functions to working run handling strategy

* refactor(UI): initial major refactor of ChatForm and options

* feat: textarea hook

* refactor: useAuthRedirect hook and change directory name

* feat: add ChatRoute (/c/), make optionsBar absolute and change on textarea height, add temp header

* feat: match new toggle Nav open button to ChatGPT's

* feat: add OpenAI custom classnames

* feat: useOriginNavigate

* feat: messages loading view

* fix: conversation navigation and effects

* refactor: make toggle change nav opacity

* WIP: new endpoint menu

* feat: NewEndpointsMenu complete

* fix: ensure set key dialog shows on endpoint change, and new conversation resets messages

* WIP: textarea styling fix, add temp footer, create basic file handling component

* feat: image file handling (UI)

* feat: PopOver and ModelSelect in Header, remove GenButtons

* feat: drop file handling

* refactor: bug fixes
use SSE at route level
add opts to useOriginNavigate
delay render of unfinishedMessage to avoid flickering
pass params (convoId) to chatHelpers to set messages query data based on param when the route is new (fixes can't continue convo on /new/)
style(MessagesView): matches height to official
fix(SSE): pass paramId and invalidate convos
style(Message): make bg uniform

* refactor(useSSE): setStorage within setConversation updates

* feat: conversationKeysAtom, allConversationsSelector, update convos query data on created message (if new), correctly handle convo deletion (individual)

* feat: add popover select dropdowns to allow options in header while allowing horizontal scroll for mobile

* style(pluginsSelect): styling changes

* refactor(NewEndpointsMenu): make UI components modular

* feat: Presets complete

* fix: preset editing, make by index

* fix: conversations not setting on inital navigation, fix getMessages() based on query param

* fix: changing preset no longer resets latestMessage

* feat: useOnClickOutside for OptionsPopover and fix bug that causes selection of preset when deleting

* fix: revert /chat/ switchToConvo, also use NewDeleteButton in Convo

* fix: Popover correctly closes on close Popover button using custom condition for useOnClickOutside

* style: new message and nav styling

* style: hover/sibling buttons and preset menu scrolling

* feat: new convo header button

* style(Textarea): minor style changes to textarea buttons

* feat: stop/continue generating and hide hoverbuttons when submitting

* feat: compact AI Provider schemas to make json payloads and db saves smaller

* style: styling changes for consistency on chat route

* fix: created usePresetIndexOptions to prevent bugs between /c/ and /chat/ routes when editing presets, removed redundant code from the new dialog

* chore: make /chat/ route default for now since we still lack full image support
2023-11-16 10:42:24 -05:00
1757 changed files with 190959 additions and 40973 deletions

5
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,5 @@
FROM node:18-bullseye
RUN useradd -m -s /bin/bash vscode
RUN mkdir -p /workspaces && chown -R vscode:vscode /workspaces
WORKDIR /workspaces

View File

@@ -1,58 +1,18 @@
// {
// "name": "LibreChat_dev",
// // Update the 'dockerComposeFile' list if you have more compose files or use different names.
// "dockerComposeFile": "docker-compose.yml",
// // The 'service' property is the name of the service for the container that VS Code should
// // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
// "service": "librechat",
// // The 'workspaceFolder' property is the path VS Code should open by default when
// // connected. Corresponds to a volume mount in .devcontainer/docker-compose.yml
// "workspaceFolder": "/workspace"
// //,
// // // Set *default* container specific settings.json values on container create.
// // "settings": {},
// // // Add the IDs of extensions you want installed when the container is created.
// // "extensions": [],
// // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// // "shutdownAction": "none",
// // Uncomment the next line to use 'postCreateCommand' to run commands after the container is created.
// // "postCreateCommand": "uname -a",
// // Comment out to connect as root instead. To add a non-root user, see: https://aka.ms/vscode-remote/containers/non-root.
// // "remoteUser": "vscode"
// }
{
// "name": "LibreChat_dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
// "image": "node:19-alpine",
// "workspaceFolder": "/workspaces",
"workspaceFolder": "/workspace",
// Set *default* container specific settings.json values on container create.
// "overrideCommand": true,
"customizations": {
"vscode": {
"extensions": [],
"settings": {
"terminal.integrated.profiles.linux": {
"bash": null
}
}
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces",
"customizations": {
"vscode": {
"extensions": [],
"settings": {
"terminal.integrated.profiles.linux": {
"bash": null
}
},
"postCreateCommand": "",
// "workspaceMount": "src=${localWorkspaceFolder},dst=/code,type=bind,consistency=cached"
// "runArgs": [
// "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined",
// "-v", "/tmp/.X11-unix:/tmp/.X11-unix",
// "-v", "${env:XAUTHORITY}:/root/.Xauthority:rw",
// "-v", "/home/${env:USER}/.cdh:/root/.cdh",
// "-e", "DISPLAY=${env:DISPLAY}",
// "--name=tgw_assistant_backend_dev",
// "--network=host"
// ],
// "settings": {
// "terminal.integrated.shell.linux": "/bin/bash"
// },
"features": {"ghcr.io/devcontainers/features/git:1": {}}
}
}
},
"postCreateCommand": "",
"features": { "ghcr.io/devcontainers/features/git:1": {} },
"remoteUser": "vscode"
}

View File

@@ -1,17 +1,9 @@
version: '3.4'
services:
app:
# container_name: LibreChat_dev
image: node:19-bullseye
# Using a Dockerfile is optional, but included for completeness.
# build:
# context: .
# dockerfile: Dockerfile
# # [Optional] You can use build args to set options. e.g. 'VARIANT' below affects the image in the Dockerfile
# args:
# VARIANT: buster
# network_mode: "host"
build:
context: ..
dockerfile: .devcontainer/Dockerfile
# restart: always
links:
- mongodb
- meilisearch
@@ -21,17 +13,16 @@ services:
- "host.docker.internal:host-gateway"
volumes:
# # This is where VS Code should expect to find your project's source code and the value of "workspaceFolder" in .devcontainer/devcontainer.json
- ..:/workspace:cached
# # - /app/client/node_modules
# # - ./api:/app/api
# # - ./.env:/app/.env
# # - ./.env.development:/app/.env.development
# # - ./.env.production:/app/.env.production
# # - /app/api/node_modules
# # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
# # - /var/run/docker.sock:/var/run/docker.sock
# This is where VS Code should expect to find your project's source code and the value of "workspaceFolder" in .devcontainer/devcontainer.json
- ..:/workspaces:cached
# Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
# - /var/run/docker.sock:/var/run/docker.sock
environment:
- HOST=0.0.0.0
- MONGO_URI=mongodb://mongodb:27017/LibreChat
# - CHATGPT_REVERSE_PROXY=http://host.docker.internal:8080/api/conversation # if you are hosting your own chatgpt reverse proxy with docker
# - OPENAI_REVERSE_PROXY=http://host.docker.internal:8070/v1/chat/completions # if you are hosting your own chatgpt reverse proxy with docker
- MEILI_HOST=http://meilisearch:7700
# Runs app on the same network as the service container, allows "forwardPorts" in devcontainer.json function.
# network_mode: service:another-service
@@ -39,45 +30,34 @@ services:
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)
# Uncomment the next line to use a non-root user for all processes - See https://aka.ms/vscode-remote/containers/non-root for details.
# user: vscode
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined
# Use a non-root user for all processes - See https://aka.ms/vscode-remote/containers/non-root for details.
user: vscode
# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
mongodb:
container_name: chat-mongodb
# network_mode: "host"
expose:
- 27017
# ports:
# - 27018:27017
image: mongo
# restart: always
# restart: always
volumes:
- ./data-node:/data/db
command: mongod --noauth
meilisearch:
container_name: chat-meilisearch
image: getmeili/meilisearch:v1.0
# network_mode: "host"
image: getmeili/meilisearch:v1.5
# restart: always
expose:
- 7700
# ports:
# - 7700:7700
# env_file:
# - .env
# Uncomment this to access meilisearch from outside docker
# ports:
# - 7700:7700 # if exposing these ports, make sure your master key is not the default value
environment:
- SEARCH=false
- MEILI_HOST=http://0.0.0.0:7700
- MEILI_HTTP_ADDR=0.0.0.0:7700
- MEILI_NO_ANALYTICS=true
- MEILI_MASTER_KEY=5c71cf56d672d009e36070b5bc5e47b743535ae55c818ae3b735bb6ebfb4ba63
volumes:
- ./meili_data:/meili_data
- ./meili_data_v1.5:/meili_data

View File

@@ -1,5 +1,17 @@
**/.circleci
**/.editorconfig
**/.dockerignore
**/.git
**/.DS_Store
**/.vscode
**/node_modules
client/dist/images
# Specific patterns to ignore
data-node
.env
**/.env
meili_data*
librechat*
Dockerfile*
docs
# Ignore all hidden files
.*

View File

@@ -1,48 +1,333 @@
##########################
# Server configuration:
##########################
#=====================================================================#
# LibreChat Configuration #
#=====================================================================#
# Please refer to the reference documentation for assistance #
# with configuring your LibreChat environment. #
# #
# https://www.librechat.ai/docs/configuration/dotenv #
#=====================================================================#
APP_TITLE=LibreChat
#==================================================#
# Server Configuration #
#==================================================#
# Uncomment to add a custom footer.
# Uncomment and make empty "" to remove the footer.
# CUSTOM_FOOTER="My custom footer"
# The server will listen to localhost:3080 by default. You can change the target IP as you want.
# If you want to make this server available externally, for example to share the server with others
# or expose this from a Docker container, set host to 0.0.0.0 or your external IP interface.
# Tips: Setting host to 0.0.0.0 means listening on all interfaces. It's not a real IP.
# Use localhost:port rather than 0.0.0.0:port to access the server.
# Set Node env to development if running in dev mode.
HOST=localhost
PORT=3080
# Note: the following enables user balances, which you can add manually
# or you will need to build out a balance accruing system for users.
# For more info, see https://docs.librechat.ai/features/token_usage.html
MONGO_URI=mongodb://127.0.0.1:27017/LibreChat
# To manually add balances, run the following command:
# `npm run add-balance`
DOMAIN_CLIENT=http://localhost:3080
DOMAIN_SERVER=http://localhost:3080
# You can also specify the email and token credit amount to add, e.g.:
# `npm run add-balance example@example.com 1000`
NO_INDEX=true
# Use the address that is at most n number of hops away from the Express application.
# req.socket.remoteAddress is the first hop, and the rest are looked for in the X-Forwarded-For header from right to left.
# A value of 0 means that the first untrusted address would be req.socket.remoteAddress, i.e. there is no reverse proxy.
# Defaulted to 1.
TRUST_PROXY=1
# This works well to track your own usage for personal use; 1000 credits = $0.001 (1 mill USD)
#===============#
# JSON Logging #
#===============#
# Set to true to enable token credit balances for the OpenAI/Plugins endpoints
CHECK_BALANCE=false
# Use when process console logs in cloud deployment like GCP/AWS
CONSOLE_JSON=false
# Automated Moderation System
# The Automated Moderation System uses a scoring mechanism to track user violations. As users commit actions
# like excessive logins, registrations, or messaging, they accumulate violation scores. Upon reaching
# a set threshold, the user and their IP are temporarily banned. This system ensures platform security
# by monitoring and penalizing rapid or suspicious activities.
#===============#
# Debug Logging #
#===============#
BAN_VIOLATIONS=true # Whether or not to enable banning users for violations (they will still be logged)
BAN_DURATION=1000 * 60 * 60 * 2 # how long the user and associated IP are banned for
BAN_INTERVAL=20 # a user will be banned everytime their score reaches/crosses over the interval threshold
DEBUG_LOGGING=true
DEBUG_CONSOLE=false
# The score for each violation
#=============#
# Permissions #
#=============#
# UID=1000
# GID=1000
#===============#
# Configuration #
#===============#
# Use an absolute path, a relative path, or a URL
# CONFIG_PATH="/alternative/path/to/librechat.yaml"
#===================================================#
# Endpoints #
#===================================================#
# ENDPOINTS=openAI,assistants,azureOpenAI,google,gptPlugins,anthropic
PROXY=
#===================================#
# Known Endpoints - librechat.yaml #
#===================================#
# https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints
# ANYSCALE_API_KEY=
# APIPIE_API_KEY=
# COHERE_API_KEY=
# DEEPSEEK_API_KEY=
# DATABRICKS_API_KEY=
# FIREWORKS_API_KEY=
# GROQ_API_KEY=
# HUGGINGFACE_TOKEN=
# MISTRAL_API_KEY=
# OPENROUTER_KEY=
# PERPLEXITY_API_KEY=
# SHUTTLEAI_API_KEY=
# TOGETHERAI_API_KEY=
# UNIFY_API_KEY=
# XAI_API_KEY=
#============#
# Anthropic #
#============#
ANTHROPIC_API_KEY=user_provided
# ANTHROPIC_MODELS=claude-3-7-sonnet-latest,claude-3-7-sonnet-20250219,claude-3-5-haiku-20241022,claude-3-5-sonnet-20241022,claude-3-5-sonnet-latest,claude-3-5-sonnet-20240620,claude-3-opus-20240229,claude-3-sonnet-20240229,claude-3-haiku-20240307,claude-2.1,claude-2,claude-1.2,claude-1,claude-1-100k,claude-instant-1,claude-instant-1-100k
# ANTHROPIC_REVERSE_PROXY=
#============#
# Azure #
#============#
# Note: these variables are DEPRECATED
# Use the `librechat.yaml` configuration for `azureOpenAI` instead
# You may also continue to use them if you opt out of using the `librechat.yaml` configuration
# AZURE_OPENAI_DEFAULT_MODEL=gpt-3.5-turbo # Deprecated
# AZURE_OPENAI_MODELS=gpt-3.5-turbo,gpt-4 # Deprecated
# AZURE_USE_MODEL_AS_DEPLOYMENT_NAME=TRUE # Deprecated
# AZURE_API_KEY= # Deprecated
# AZURE_OPENAI_API_INSTANCE_NAME= # Deprecated
# AZURE_OPENAI_API_DEPLOYMENT_NAME= # Deprecated
# AZURE_OPENAI_API_VERSION= # Deprecated
# AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME= # Deprecated
# AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME= # Deprecated
# PLUGINS_USE_AZURE="true" # Deprecated
#=================#
# AWS Bedrock #
#=================#
# BEDROCK_AWS_DEFAULT_REGION=us-east-1 # A default region must be provided
# BEDROCK_AWS_ACCESS_KEY_ID=someAccessKey
# BEDROCK_AWS_SECRET_ACCESS_KEY=someSecretAccessKey
# BEDROCK_AWS_SESSION_TOKEN=someSessionToken
# Note: This example list is not meant to be exhaustive. If omitted, all known, supported model IDs will be included for you.
# BEDROCK_AWS_MODELS=anthropic.claude-3-5-sonnet-20240620-v1:0,meta.llama3-1-8b-instruct-v1:0
# See all Bedrock model IDs here: https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html#model-ids-arns
# Notes on specific models:
# The following models are not support due to not supporting streaming:
# ai21.j2-mid-v1
# The following models are not support due to not supporting conversation history:
# ai21.j2-ultra-v1, cohere.command-text-v14, cohere.command-light-text-v14
#============#
# Google #
#============#
GOOGLE_KEY=user_provided
# GOOGLE_REVERSE_PROXY=
# Some reverse proxies do not support the X-goog-api-key header, uncomment to pass the API key in Authorization header instead.
# GOOGLE_AUTH_HEADER=true
# Gemini API (AI Studio)
# GOOGLE_MODELS=gemini-2.0-flash-exp,gemini-2.0-flash-thinking-exp-1219,gemini-exp-1121,gemini-exp-1114,gemini-1.5-flash-latest,gemini-1.0-pro,gemini-1.0-pro-001,gemini-1.0-pro-latest,gemini-1.0-pro-vision-latest,gemini-1.5-pro-latest,gemini-pro,gemini-pro-vision
# Vertex AI
# GOOGLE_MODELS=gemini-1.5-flash-preview-0514,gemini-1.5-pro-preview-0514,gemini-1.0-pro-vision-001,gemini-1.0-pro-002,gemini-1.0-pro-001,gemini-pro-vision,gemini-1.0-pro
# GOOGLE_TITLE_MODEL=gemini-pro
# GOOGLE_LOC=us-central1
# Google Safety Settings
# NOTE: These settings apply to both Vertex AI and Gemini API (AI Studio)
#
# For Vertex AI:
# To use the BLOCK_NONE setting, you need either:
# (a) Access through an allowlist via your Google account team, or
# (b) Switch to monthly invoiced billing: https://cloud.google.com/billing/docs/how-to/invoiced-billing
#
# For Gemini API (AI Studio):
# BLOCK_NONE is available by default, no special account requirements.
#
# Available options: BLOCK_NONE, BLOCK_ONLY_HIGH, BLOCK_MEDIUM_AND_ABOVE, BLOCK_LOW_AND_ABOVE
#
# GOOGLE_SAFETY_SEXUALLY_EXPLICIT=BLOCK_ONLY_HIGH
# GOOGLE_SAFETY_HATE_SPEECH=BLOCK_ONLY_HIGH
# GOOGLE_SAFETY_HARASSMENT=BLOCK_ONLY_HIGH
# GOOGLE_SAFETY_DANGEROUS_CONTENT=BLOCK_ONLY_HIGH
# GOOGLE_SAFETY_CIVIC_INTEGRITY=BLOCK_ONLY_HIGH
#============#
# OpenAI #
#============#
OPENAI_API_KEY=user_provided
# OPENAI_MODELS=o1,o1-mini,o1-preview,gpt-4o,chatgpt-4o-latest,gpt-4o-mini,gpt-3.5-turbo-0125,gpt-3.5-turbo-0301,gpt-3.5-turbo,gpt-4,gpt-4-0613,gpt-4-vision-preview,gpt-3.5-turbo-0613,gpt-3.5-turbo-16k-0613,gpt-4-0125-preview,gpt-4-turbo-preview,gpt-4-1106-preview,gpt-3.5-turbo-1106,gpt-3.5-turbo-instruct,gpt-3.5-turbo-instruct-0914,gpt-3.5-turbo-16k
DEBUG_OPENAI=false
# TITLE_CONVO=false
# OPENAI_TITLE_MODEL=gpt-4o-mini
# OPENAI_SUMMARIZE=true
# OPENAI_SUMMARY_MODEL=gpt-4o-mini
# OPENAI_FORCE_PROMPT=true
# OPENAI_REVERSE_PROXY=
# OPENAI_ORGANIZATION=
#====================#
# Assistants API #
#====================#
ASSISTANTS_API_KEY=user_provided
# ASSISTANTS_BASE_URL=
# ASSISTANTS_MODELS=gpt-4o,gpt-4o-mini,gpt-3.5-turbo-0125,gpt-3.5-turbo-16k-0613,gpt-3.5-turbo-16k,gpt-3.5-turbo,gpt-4,gpt-4-0314,gpt-4-32k-0314,gpt-4-0613,gpt-3.5-turbo-0613,gpt-3.5-turbo-1106,gpt-4-0125-preview,gpt-4-turbo-preview,gpt-4-1106-preview
#==========================#
# Azure Assistants API #
#==========================#
# Note: You should map your credentials with custom variables according to your Azure OpenAI Configuration
# The models for Azure Assistants are also determined by your Azure OpenAI configuration.
# More info, including how to enable use of Assistants with Azure here:
# https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints/azure#using-assistants-with-azure
#============#
# Plugins #
#============#
# PLUGIN_MODELS=gpt-4o,gpt-4o-mini,gpt-4,gpt-4-turbo-preview,gpt-4-0125-preview,gpt-4-1106-preview,gpt-4-0613,gpt-3.5-turbo,gpt-3.5-turbo-0125,gpt-3.5-turbo-1106,gpt-3.5-turbo-0613
DEBUG_PLUGINS=true
CREDS_KEY=f34be427ebb29de8d88c107a71546019685ed8b241d8f2ed00c3df97ad2566f0
CREDS_IV=e2341419ec3dd3d19b13a1a87fafcbfb
# Azure AI Search
#-----------------
AZURE_AI_SEARCH_SERVICE_ENDPOINT=
AZURE_AI_SEARCH_INDEX_NAME=
AZURE_AI_SEARCH_API_KEY=
AZURE_AI_SEARCH_API_VERSION=
AZURE_AI_SEARCH_SEARCH_OPTION_QUERY_TYPE=
AZURE_AI_SEARCH_SEARCH_OPTION_TOP=
AZURE_AI_SEARCH_SEARCH_OPTION_SELECT=
# DALL·E
#----------------
# DALLE_API_KEY=
# DALLE3_API_KEY=
# DALLE2_API_KEY=
# DALLE3_SYSTEM_PROMPT=
# DALLE2_SYSTEM_PROMPT=
# DALLE_REVERSE_PROXY=
# DALLE3_BASEURL=
# DALLE2_BASEURL=
# DALL·E (via Azure OpenAI)
# Note: requires some of the variables above to be set
#----------------
# DALLE3_AZURE_API_VERSION=
# DALLE2_AZURE_API_VERSION=
# Google
#-----------------
GOOGLE_SEARCH_API_KEY=
GOOGLE_CSE_ID=
# YOUTUBE
#-----------------
YOUTUBE_API_KEY=
# SerpAPI
#-----------------
SERPAPI_API_KEY=
# Stable Diffusion
#-----------------
SD_WEBUI_URL=http://host.docker.internal:7860
# Tavily
#-----------------
TAVILY_API_KEY=
# Traversaal
#-----------------
TRAVERSAAL_API_KEY=
# WolframAlpha
#-----------------
WOLFRAM_APP_ID=
# Zapier
#-----------------
ZAPIER_NLA_API_KEY=
#==================================================#
# Search #
#==================================================#
SEARCH=true
MEILI_NO_ANALYTICS=true
MEILI_HOST=http://0.0.0.0:7700
MEILI_MASTER_KEY=DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFCt
# Optional: Disable indexing, useful in a multi-node setup
# where only one instance should perform an index sync.
# MEILI_NO_SYNC=true
#==================================================#
# Speech to Text & Text to Speech #
#==================================================#
STT_API_KEY=
TTS_API_KEY=
#==================================================#
# RAG #
#==================================================#
# More info: https://www.librechat.ai/docs/configuration/rag_api
# RAG_OPENAI_BASEURL=
# RAG_OPENAI_API_KEY=
# RAG_USE_FULL_CONTEXT=
# EMBEDDINGS_PROVIDER=openai
# EMBEDDINGS_MODEL=text-embedding-3-small
#===================================================#
# User System #
#===================================================#
#========================#
# Moderation #
#========================#
OPENAI_MODERATION=false
OPENAI_MODERATION_API_KEY=
# OPENAI_MODERATION_REVERSE_PROXY=
BAN_VIOLATIONS=true
BAN_DURATION=1000 * 60 * 60 * 2
BAN_INTERVAL=20
LOGIN_VIOLATION_SCORE=1
REGISTRATION_VIOLATION_SCORE=1
@@ -50,398 +335,206 @@ CONCURRENT_VIOLATION_SCORE=1
MESSAGE_VIOLATION_SCORE=1
NON_BROWSER_VIOLATION_SCORE=20
# Login and registration rate limiting.
LOGIN_MAX=7
LOGIN_WINDOW=5
REGISTER_MAX=5
REGISTER_WINDOW=60
LOGIN_MAX=7 # The max amount of logins allowed per IP per LOGIN_WINDOW
LOGIN_WINDOW=5 # in minutes, determines the window of time for LOGIN_MAX logins
REGISTER_MAX=5 # The max amount of registrations allowed per IP per REGISTER_WINDOW
REGISTER_WINDOW=60 # in minutes, determines the window of time for REGISTER_MAX registrations
LIMIT_CONCURRENT_MESSAGES=true
CONCURRENT_MESSAGE_MAX=2
# Message rate limiting (per user & IP)
LIMIT_MESSAGE_IP=true
MESSAGE_IP_MAX=40
MESSAGE_IP_WINDOW=1
LIMIT_CONCURRENT_MESSAGES=true # Whether to limit the amount of messages a user can send per request
CONCURRENT_MESSAGE_MAX=2 # The max amount of messages a user can send per request
LIMIT_MESSAGE_USER=false
MESSAGE_USER_MAX=40
MESSAGE_USER_WINDOW=1
LIMIT_MESSAGE_IP=true # Whether to limit the amount of messages an IP can send per MESSAGE_IP_WINDOW
MESSAGE_IP_MAX=40 # The max amount of messages an IP can send per MESSAGE_IP_WINDOW
MESSAGE_IP_WINDOW=1 # in minutes, determines the window of time for MESSAGE_IP_MAX messages
ILLEGAL_MODEL_REQ_SCORE=5
# Note: You can utilize both limiters, but default is to limit by IP only.
LIMIT_MESSAGE_USER=false # Whether to limit the amount of messages an IP can send per MESSAGE_USER_WINDOW
MESSAGE_USER_MAX=40 # The max amount of messages an IP can send per MESSAGE_USER_WINDOW
MESSAGE_USER_WINDOW=1 # in minutes, determines the window of time for MESSAGE_USER_MAX messages
#========================#
# Balance #
#========================#
# If you have permission problems, set here the UID and GID of the user running
# the docker compose command. The applications in the container will run with these uid/gid.
# UID=1000
# GID=1000
CHECK_BALANCE=false
# START_BALANCE=20000 # note: the number of tokens that will be credited after registration.
# Change this to proxy any API request.
# It's useful if your machine has difficulty calling the original API server.
# PROXY=
#========================#
# Registration and Login #
#========================#
# Change this to your MongoDB URI if different. I recommend appending LibreChat.
MONGO_URI=mongodb://127.0.0.1:27018/LibreChat
##########################
# OpenAI Endpoint:
##########################
# Access key from OpenAI platform.
# Leave it blank to disable this feature.
# Set to "user_provided" to allow the user to provide their API key from the UI.
OPENAI_API_KEY=user_provided
DEBUG_OPENAI=false # Set to true to enable debug mode for the OpenAI endpoint
# Identify the available models, separated by commas *without spaces*.
# The first will be default.
# Leave it blank to use internal settings.
# OPENAI_MODELS=gpt-3.5-turbo-1106,gpt-4-1106-preview,gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314,gpt-4-0613
# Titling is enabled by default when initiating a conversation.
# Uncomment the following variable to disable this feature.
# TITLE_CONVO=false
# (Optional) The default model used for titling by is gpt-3.5-turbo-0613
# You can change it by uncommenting the following and setting the desired model
# Must be compatible with the OpenAI Endpoint.
# OPENAI_TITLE_MODEL=gpt-3.5-turbo
# (Optional/Experimental) Enable message summarization by uncommenting the following:
# Note: this may affect response time when a summary is being generated.
# OPENAI_SUMMARIZE=true
# Not yet implemented: this will be a conversation option enabled by default to save users on tokens
# We are using the ConversationSummaryBufferMemory method to summarize messages.
# To learn more about this, see this article:
# https://www.pinecone.io/learn/series/langchain/langchain-conversational-memory/
# (Optional) The default model used for summarizing is gpt-3.5-turbo
# You can change it by uncommenting the following and setting the desired model
# Must be compatible with the OpenAI Endpoint.
# OPENAI_SUMMARY_MODEL=gpt-3.5-turbo
# Reverse proxy settings for OpenAI:
# https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy
# The URL must match the "url/v1," pattern, the "openai" suffix is also allowed.
# Examples:
# - https://open.ai/v1
# - https://open.ai/v1/ACCOUNT/GATEWAY/openai
# - https://open.ai/v1/hi/openai
# OPENAI_REVERSE_PROXY=
# (Advanced) Sometimes when using Local LLM APIs, you may need to force the API
# to be called with a `prompt` payload instead of a `messages` payload; to mimic the
# a `/v1/completions` request instead of `/v1/chat/completions`
# This may be the case for LocalAI with some models. To do so, uncomment the following:
# OPENAI_FORCE_PROMPT=true
# (Advanced) For customization of the DALL-E-3 System prompt,
# uncomment the following, and provide your own prompt:
# See official prompt for reference:
# https://github.com/spdustin/ChatGPT-AutoExpert/blob/main/_system-prompts/dall-e.md
# DALLE3_SYSTEM_PROMPT="Your System Prompt here"
# (Advanced) DALL-E Proxy settings
# This is separate from its OpenAI counterpart for customization purposes
# Reverse proxy settings, changes the baseURL for the DALL-E-3 API Calls
# The URL must match the "url/v1," pattern, the "openai" suffix is also allowed.
# Examples:
# - https://open.ai/v1
# - https://open.ai/v1/ACCOUNT/GATEWAY/openai
# - https://open.ai/v1/hi/openai
# DALLE_REVERSE_PROXY=
# Note: if you have PROXY set, it will be used for DALLE calls also, which is universal for the app
##########################
# OpenRouter (overrides OpenAI and Plugins Endpoints):
##########################
# OpenRouter is a legitimate proxy service to a multitude of LLMs, both closed and open source, including:
# OpenAI models, Anthropic models, Meta's Llama models, pygmalionai/mythalion-13b
# and many more open source models. Newer integrations are usually discounted, too!
# Note: this overrides the OpenAI and Plugins Endpoints.
# See ./docs/install/free_ai_apis.md for more info.
# OPENROUTER_API_KEY=
##########################
# AZURE Endpoint:
##########################
# To use Azure with this project, set the following variables. These will be used to build the API URL.
# Chat completion:
# `https://{AZURE_OPENAI_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/{AZURE_OPENAI_API_DEPLOYMENT_NAME}/chat/completions?api-version={AZURE_OPENAI_API_VERSION}`;
# You should also consider changing the `OPENAI_MODELS` variable above to the models available in your instance/deployment.
# Note: I've noticed that the Azure API is much faster than the OpenAI API, so the streaming looks almost instantaneous.
# Note "AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME" and "AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME" are optional but might be used in the future
# AZURE_API_KEY=
# AZURE_OPENAI_API_INSTANCE_NAME=
# AZURE_OPENAI_API_DEPLOYMENT_NAME=
# AZURE_OPENAI_API_VERSION=
# AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME=
# AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME=
# NOTE: As of 2023-11-10, the Azure API only allows one model per deployment,
# It's recommended to name your deployments after the model name, e.g. "gpt-35-turbo,"
# which allows for fast deployment switching and AZURE_USE_MODEL_AS_DEPLOYMENT_NAME enabled.
# However, you can use non-model deployment names and setting the AZURE_OPENAI_DEFAULT_MODEL to ensure it works as expected.
# Identify the available models, separated by commas *without spaces*.
# The first will be default. Leave it blank or as is to use internal settings.
# NOTE: as deployment names can't have periods, they will be removed when the endpoint is generated.
AZURE_OPENAI_MODELS=gpt-3.5-turbo,gpt-4
# (Advanced) this enables the use of the model name as the deployment name, e.g. "gpt-3.5-turbo" as the deployment name
AZURE_USE_MODEL_AS_DEPLOYMENT_NAME=TRUE
# (Advanced) this overrides the model setting for Azure, in case you want to use your custom deployment names
# as the values for AZURE_OPENAI_MODELS
# AZURE_OPENAI_DEFAULT_MODEL=gpt-3.5-turbo
# To use Azure with the Plugins endpoint, you need the variables above, and uncomment the following variable:
# NOTE: This may not work as expected and Azure OpenAI may not support OpenAI Functions yet
# Omit/leave it commented to use the default OpenAI API
# PLUGINS_USE_AZURE="true"
##########################
# ChatGPT Endpoint:
##########################
# ChatGPT Browser Client (free but use at your own risk)
# Access token from https://chat.openai.com/api/auth/session
# Exposes your access token to `CHATGPT_REVERSE_PROXY`
# Set to "user_provided" to allow the user to provide its token from the UI.
# Leave it blank to disable this endpoint
CHATGPT_TOKEN=user_provided
# Identify the available models, separated by commas. The first will be default.
# Leave it blank to use internal settings.
CHATGPT_MODELS=text-davinci-002-render-sha,gpt-4
# NOTE: you can add gpt-4-plugins, gpt-4-code-interpreter, and gpt-4-browsing to the list above and use the models for these features;
# however, the view/display portion of these features are not supported, but you can use the underlying models, which have higher token context
# Also: text-davinci-002-render-paid is deprecated as of May 2023
# Reverse proxy setting for OpenAI
# https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy
# By default it will use the node-chatgpt-api recommended proxy, (it's a third party server)
# CHATGPT_REVERSE_PROXY=<YOUR REVERSE PROXY>
##########################
# BingAI Endpoint:
##########################
# Also used for Sydney and jailbreak
# To get your Access token for Bing, login to https://www.bing.com
# Use dev tools or an extension while logged into the site to copy the content of the _U cookie.
# If this fails, follow these instructions https://github.com/danny-avila/LibreChat/issues/370#issuecomment-1560382302 to provide the full cookie strings
# or check out our discord https://discord.com/channels/1086345563026489514/1143941308684177429
# Set to "user_provided" to allow the user to provide its token from the UI.
# Leave it blank to disable this endpoint.
BINGAI_TOKEN=user_provided
# BingAI Host:
# Necessary for some people in different countries, e.g. China (https://cn.bing.com)
# Leave it blank to use default server.
# BINGAI_HOST=https://cn.bing.com
#############################
# Plugins:
#############################
# Identify the available models, separated by commas *without spaces*.
# The first will be default.
# Leave it blank to use internal settings.
# PLUGIN_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,gpt-4,gpt-4-0314,gpt-4-0613
DEBUG_PLUGINS=true # Set to false or comment out to disable debug mode for plugins
# For securely storing credentials, you need a fixed key and IV. You can set them here for prod and dev environments
# If you don't set them, the app will crash on startup.
# You need a 32-byte key (64 characters in hex) and 16-byte IV (32 characters in hex)
# Use this replit to generate some quickly: https://replit.com/@daavila/crypto#index.js
# Here are some examples (THESE ARE NOT SECURE!)
CREDS_KEY=f34be427ebb29de8d88c107a71546019685ed8b241d8f2ed00c3df97ad2566f0
CREDS_IV=e2341419ec3dd3d19b13a1a87fafcbfb
# AI-Assisted Google Search
# This bot supports searching google for answers to your questions with assistance from GPT!
# See detailed instructions here: https://github.com/danny-avila/LibreChat/blob/main/docs/features/plugins/google_search.md
GOOGLE_API_KEY=
GOOGLE_CSE_ID=
# StableDiffusion WebUI
# This bot supports StableDiffusion WebUI, using it's API to generated requested images.
# See detailed instructions here: https://github.com/danny-avila/LibreChat/blob/main/docs/features/plugins/stable_diffusion.md
# Use "http://127.0.0.1:7860" with local install and "http://host.docker.internal:7860" for docker
SD_WEBUI_URL=http://host.docker.internal:7860
# Azure Cognitive Search
# This plugin supports searching Azure Cognitive Search for answers to your questions.
# See detailed instructions here: https://github.com/danny-avila/LibreChat/blob/main/docs/features/plugins/azure_cognitive_search.md
AZURE_COGNITIVE_SEARCH_SERVICE_ENDPOINT=
AZURE_COGNITIVE_SEARCH_INDEX_NAME=
AZURE_COGNITIVE_SEARCH_API_KEY=
AZURE_COGNITIVE_SEARCH_API_VERSION=
AZURE_COGNITIVE_SEARCH_SEARCH_OPTION_QUERY_TYPE=
AZURE_COGNITIVE_SEARCH_SEARCH_OPTION_TOP=
AZURE_COGNITIVE_SEARCH_SEARCH_OPTION_SELECT=
##########################
# PaLM (Google) Endpoint:
##########################
# Follow the instruction here to setup:
# https://github.com/danny-avila/LibreChat/blob/main/docs/install/apis_and_tokens.md
PALM_KEY=user_provided
# In case you need a reverse proxy for this endpoint:
# GOOGLE_REVERSE_PROXY=
##########################
# Anthropic Endpoint:
##########################
# Access key from https://console.anthropic.com/
# Leave it blank to disable this feature.
# Set to "user_provided" to allow the user to provide their API key from the UI.
# Note that access to claude-1 may potentially become unavailable with the release of claude-2.
ANTHROPIC_API_KEY=user_provided
ANTHROPIC_MODELS=claude-1,claude-instant-1,claude-2
##########################
# Proxy: To be Used by all endpoints
##########################
PROXY=
##########################
# Search:
##########################
# ENABLING SEARCH MESSAGES/CONVOS
# Requires the installation of the free self-hosted Meilisearch or a paid Remote Plan (Remote not tested)
# The easiest setup for this is through docker-compose, which takes care of it for you.
SEARCH=true
# HIGHLY RECOMMENDED: Disable anonymized telemetry analytics for MeiliSearch for absolute privacy.
MEILI_NO_ANALYTICS=true
# REQUIRED FOR SEARCH: MeiliSearch Host, mainly for the API server to connect to the search server.
# Replace '0.0.0.0' with 'meilisearch' if serving MeiliSearch with docker-compose.
MEILI_HOST=http://0.0.0.0:7700
# REQUIRED FOR SEARCH: MeiliSearch HTTP Address, mainly for docker-compose to expose the search server.
# Replace '0.0.0.0' with 'meilisearch' if serving MeiliSearch with docker-compose.
MEILI_HTTP_ADDR=0.0.0.0:7700
# REQUIRED FOR SEARCH: In production env., a secure key is needed. You can generate your own.
# This master key must be at least 16 bytes, composed of valid UTF-8 characters.
# MeiliSearch will throw an error and refuse to launch if no master key is provided,
# or if it is under 16 bytes. MeiliSearch will suggest a secure autogenerated master key.
# Using docker, it seems recognized as production so use a secure key.
# This is a ready made secure key for docker-compose, you can replace it with your own.
MEILI_MASTER_KEY=DrhYf7zENyR6AlUCKmnz0eYASOQdl6zxH7s7MKFSfFCt
##########################
# User System:
##########################
# Allow Public Registration
ALLOW_EMAIL_LOGIN=true
ALLOW_REGISTRATION=true
# Allow Social Registration
ALLOW_SOCIAL_LOGIN=false
# Allow Social Registration (WORKS ONLY for Google, Github, Discord)
ALLOW_SOCIAL_REGISTRATION=false
ALLOW_PASSWORD_RESET=false
# ALLOW_ACCOUNT_DELETION=true # note: enabled by default if omitted/commented out
ALLOW_UNVERIFIED_EMAIL_LOGIN=true
SESSION_EXPIRY=1000 * 60 * 15
REFRESH_TOKEN_EXPIRY=(1000 * 60 * 60 * 24) * 7
# JWT Secrets
# You should use secure values. The examples given are 32-byte keys (64 characters in hex)
# Use this replit to generate some quickly: https://replit.com/@daavila/crypto#index.js
JWT_SECRET=16f8c0ef4a5d391b26034086c628469d3f9f497f08163ab9b40137092f2909ef
JWT_REFRESH_SECRET=eaa5191f2914e30b9387fd84e254e4ba6fc51b4654968a9b0803b456a54b8418
# Google:
# Add your Google Client ID and Secret here, you must register an app with Google Cloud to get these values
# https://cloud.google.com/
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CALLBACK_URL=/oauth/google/callback
# Discord
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_CALLBACK_URL=/oauth/discord/callback
# Facebook:
# Add your Facebook Client ID and Secret here, you must register an app with Facebook to get these values
# https://developers.facebook.com/
# Facebook
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
FACEBOOK_CALLBACK_URL=/oauth/facebook/callback
# OpenID:
# See OpenID provider to get the below values
# Create random string for OPENID_SESSION_SECRET
# For Azure AD
# ISSUER: https://login.microsoftonline.com/(tenant id)/v2.0/
# SCOPE: openid profile email
# GitHub
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GITHUB_CALLBACK_URL=/oauth/github/callback
# GitHub Enterprise
# GITHUB_ENTERPRISE_BASE_URL=
# GITHUB_ENTERPRISE_USER_AGENT=
# Google
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CALLBACK_URL=/oauth/google/callback
# Apple
APPLE_CLIENT_ID=
APPLE_TEAM_ID=
APPLE_KEY_ID=
APPLE_PRIVATE_KEY_PATH=
APPLE_CALLBACK_URL=/oauth/apple/callback
# OpenID
OPENID_CLIENT_ID=
OPENID_CLIENT_SECRET=
OPENID_ISSUER=
OPENID_SESSION_SECRET=
OPENID_SCOPE="openid profile email"
OPENID_CALLBACK_URL=/oauth/openid/callback
# If LABEL and URL are left empty, then the default OpenID label and logo are used.
OPENID_REQUIRED_ROLE=
OPENID_REQUIRED_ROLE_TOKEN_KIND=
OPENID_REQUIRED_ROLE_PARAMETER_PATH=
# Set to determine which user info property returned from OpenID Provider to store as the User's username
OPENID_USERNAME_CLAIM=
# Set to determine which user info property returned from OpenID Provider to store as the User's name
OPENID_NAME_CLAIM=
OPENID_BUTTON_LABEL=
OPENID_IMAGE_URL=
# Set the expiration delay for the secure cookie with the JWT token
# Recommend session expiry to be 15 minutes
# Delay is in millisecond e.g. 7 days is 1000*60*60*24*7
SESSION_EXPIRY=1000 * 60 * 15
REFRESH_TOKEN_EXPIRY=(1000 * 60 * 60 * 24) * 7
# LDAP
LDAP_URL=
LDAP_BIND_DN=
LDAP_BIND_CREDENTIALS=
LDAP_USER_SEARCH_BASE=
LDAP_SEARCH_FILTER=mail={{username}}
LDAP_CA_CERT_PATH=
# LDAP_TLS_REJECT_UNAUTHORIZED=
# LDAP_LOGIN_USES_USERNAME=true
# LDAP_ID=
# LDAP_USERNAME=
# LDAP_EMAIL=
# LDAP_FULL_NAME=
# Github:
# Get the Client ID and Secret from your Discord Application
# Add your Discord Client ID and Client Secret here:
#========================#
# Email Password Reset #
#========================#
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secret
GITHUB_CALLBACK_URL=/oauth/github/callback # this should be the same for everyone
EMAIL_SERVICE=
EMAIL_HOST=
EMAIL_PORT=25
EMAIL_ENCRYPTION=
EMAIL_ENCRYPTION_HOSTNAME=
EMAIL_ALLOW_SELFSIGNED=
EMAIL_USERNAME=
EMAIL_PASSWORD=
EMAIL_FROM_NAME=
EMAIL_FROM=noreply@librechat.ai
# Discord:
# Get the Client ID and Secret from your Discord Application
# Add your Github Client ID and Client Secret here:
#========================#
# Firebase CDN #
#========================#
DISCORD_CLIENT_ID=your_client_id
DISCORD_CLIENT_SECRET=your_client_secret
DISCORD_CALLBACK_URL=/oauth/discord/callback # this should be the same for everyone
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=
FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=
###########################
# Application Domains
###########################
#========================#
# Shared Links #
#========================#
# Note:
# Server = Backend
# Client = Public (the client is the url you visit)
# For the Google login to work in dev mode, you will need to change DOMAIN_SERVER to localhost:3090 or place it in .env.development
ALLOW_SHARED_LINKS=true
ALLOW_SHARED_LINKS_PUBLIC=true
DOMAIN_CLIENT=http://localhost:3080
DOMAIN_SERVER=http://localhost:3080
#==============================#
# Static File Cache Control #
#==============================#
###########################
# Email
###########################
# Leave commented out to use defaults: 1 day (86400 seconds) for s-maxage and 2 days (172800 seconds) for max-age
# NODE_ENV must be set to production for these to take effect
# STATIC_CACHE_MAX_AGE=172800
# STATIC_CACHE_S_MAX_AGE=86400
# Email is used for password reset. Note that all 4 values must be set for email to work.
# Failing to set the 4 values will result in LibreChat using the unsecured password reset!
EMAIL_SERVICE= # eg. gmail
EMAIL_USERNAME= # eg. your email address if using gmail
EMAIL_PASSWORD= # eg. this is the "app password" if using gmail
EMAIL_FROM=noreply@librechat.ai # email address for from field, it is required to set a value here even in the cases where it's not porperly working.
# If you have another service in front of your LibreChat doing compression, disable express based compression here
# DISABLE_COMPRESSION=true
#===================================================#
# UI #
#===================================================#
APP_TITLE=LibreChat
# CUSTOM_FOOTER="My custom footer"
HELP_AND_FAQ_URL=https://librechat.ai
# SHOW_BIRTHDAY_ICON=true
# Google tag manager id
#ANALYTICS_GTM_ID=user provided google tag manager id
#===============#
# REDIS Options #
#===============#
# REDIS_URI=10.10.10.10:6379
# USE_REDIS=true
# USE_REDIS_CLUSTER=true
# REDIS_CA=/path/to/ca.crt
#==================================================#
# Others #
#==================================================#
# You should leave the following commented out #
# NODE_ENV=
# E2E_USER_EMAIL=
# E2E_USER_PASSWORD=
#=====================================================#
# Cache Headers #
#=====================================================#
# Headers that control caching of the index.html #
# Default configuration prevents caching to ensure #
# users always get the latest version. Customize #
# only if you understand caching implications. #
# INDEX_HTML_CACHE_CONTROL=no-cache, no-store, must-revalidate
# INDEX_HTML_PRAGMA=no-cache
# INDEX_HTML_EXPIRES=0
# no-cache: Forces validation with server before using cached version
# no-store: Prevents storing the response entirely
# must-revalidate: Prevents using stale content when offline
#=====================================================#
# OpenWeather #
#=====================================================#
OPENWEATHER_API_KEY=

View File

@@ -1,152 +0,0 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
commonjs: true,
es6: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jest/recommended',
'prettier',
],
ignorePatterns: [
'client/dist/**/*',
'client/public/**/*',
'e2e/playwright-report/**/*',
'packages/data-provider/types/**/*',
'packages/data-provider/dist/**/*',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
plugins: ['react', 'react-hooks', '@typescript-eslint', 'import'],
rules: {
'react/react-in-jsx-scope': 'off',
'@typescript-eslint/ban-ts-comment': ['error', { 'ts-ignore': 'allow' }],
indent: ['error', 2, { SwitchCase: 1 }],
'max-len': [
'error',
{
code: 120,
ignoreStrings: true,
ignoreTemplateLiterals: true,
ignoreComments: true,
},
],
'linebreak-style': 0,
curly: ['error', 'all'],
semi: ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'no-multiple-empty-lines': ['error', { max: 1 }],
'no-trailing-spaces': 'error',
'comma-dangle': ['error', 'always-multiline'],
// "arrow-parens": [2, "as-needed", { requireForBlockBody: true }],
// 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
'no-console': 'off',
'import/no-cycle': 'error',
'import/no-self-import': 'error',
'import/extensions': 'off',
'no-promise-executor-return': 'off',
'no-param-reassign': 'off',
'no-continue': 'off',
'no-restricted-syntax': 'off',
'react/prop-types': ['off'],
'react/display-name': ['off'],
'no-unused-vars': ['error', { varsIgnorePattern: '^_' }],
quotes: ['error', 'single'],
},
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
'no-unused-vars': 'off', // off because it conflicts with '@typescript-eslint/no-unused-vars'
'react/display-name': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
},
},
{
files: ['rollup.config.js', '.eslintrc.js', 'jest.config.js'],
env: {
node: true,
},
},
{
files: [
'**/*.test.js',
'**/*.test.jsx',
'**/*.test.ts',
'**/*.test.tsx',
'**/*.spec.js',
'**/*.spec.jsx',
'**/*.spec.ts',
'**/*.spec.tsx',
'setupTests.js',
],
env: {
jest: true,
node: true,
},
rules: {
'react/display-name': 'off',
'react/prop-types': 'off',
'react/no-unescaped-entities': 'off',
},
},
{
files: ['**/*.ts', '**/*.tsx'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './client/tsconfig.json',
},
plugins: ['@typescript-eslint/eslint-plugin', 'jest'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'@typescript-eslint/no-explicit-any': 'error',
},
},
{
files: './packages/data-provider/**/*.ts',
overrides: [
{
files: '**/*.ts',
parser: '@typescript-eslint/parser',
parserOptions: {
project: './packages/data-provider/tsconfig.json',
},
},
],
},
],
settings: {
react: {
createClass: 'createReactClass', // Regex for Component Factory to use,
// default to "createReactClass"
pragma: 'React', // Pragma to use, default to "React"
fragment: 'Fragment', // Fragment to use (may be a property of <pragma>), default to "Fragment"
version: 'detect', // React version. "detect" automatically picks the version you have installed.
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: ['./client/tsconfig.json'],
},
node: {
project: ['./client/tsconfig.json'],
},
},
},
};

View File

@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement here on GitHub or
on the official [Discord Server](https://discord.gg/uDyZ5Tzhct).
on the official [Discord Server](https://discord.librechat.ai).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -8,7 +8,7 @@ If the feature you would like to contribute has not already received prior appro
Please note that a pull request involving a feature that has not been reviewed and approved by the project maintainers may be rejected. We appreciate your understanding and cooperation.
If you would like to discuss the changes you wish to make, join our [Discord community](https://discord.gg/uDyZ5Tzhct), where you can engage with other contributors and seek guidance from the community.
If you would like to discuss the changes you wish to make, join our [Discord community](https://discord.librechat.ai), where you can engage with other contributors and seek guidance from the community.
## Our Standards
@@ -126,6 +126,18 @@ Apply the following naming conventions to branches, labels, and other Git-relate
- **Current Stance**: At present, this backend transition is of lower priority and might not be pursued.
## 7. Module Import Conventions
- `npm` packages first,
- from shortest line (top) to longest (bottom)
- Followed by typescript types (pertains to data-provider and client workspaces)
- longest line (top) to shortest (bottom)
- types from package come first
- Lastly, local imports
- longest line (top) to shortest (bottom)
- imports with alias `~` treated the same as relative import with respect to line length
---

View File

@@ -1,20 +1,19 @@
name: Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug"]
labels: ["🐛 bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. email@example.com
validations:
required: false
Before submitting, please:
- Search existing [Issues and Discussions](https://github.com/danny-avila/LibreChat/discussions) to see if your bug has already been reported
- Use [Discussions](https://github.com/danny-avila/LibreChat/discussions) instead of Issues for:
- General inquiries
- Help with setup
- Questions about whether you're experiencing a bug
- type: textarea
id: what-happened
attributes:
@@ -23,6 +22,23 @@ body:
placeholder: Please give as many details as possible
validations:
required: true
- type: textarea
id: version-info
attributes:
label: Version Information
description: |
If using Docker, please run and provide the output of:
```bash
docker images | grep librechat
```
If running from source, please run and provide the output of:
```bash
git rev-parse HEAD
```
placeholder: Paste the output here
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
@@ -47,7 +63,21 @@ body:
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
description: |
Please paste relevant logs that were created when reproducing the error.
Log locations:
- Docker: Project root directory ./logs
- npm: ./api/logs
There are two types of logs that can help diagnose the issue:
- debug logs (debug-YYYY-MM-DD.log)
- error logs (error-YYYY-MM-DD.log)
Error logs contain exact stack traces and are especially helpful, but both can provide valuable information.
Please only include the relevant portions of logs that correspond to when you reproduced the error.
For UI-related issues, browser console logs can be very helpful. You can provide these as screenshots or paste the text here.
render: shell
- type: textarea
id: screenshots
@@ -58,7 +88,7 @@ body:
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/CODE_OF_CONDUCT.md)
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/.github/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
required: true

View File

@@ -1,20 +1,12 @@
name: Feature Request
description: File a feature request
title: "Enhancement: "
labels: ["enhancement"]
title: "[Enhancement]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill this out!
- type: input
id: contact
attributes:
label: Contact Details
description: How can we contact you if we need more information?
placeholder: ex. email@example.com
validations:
required: false
- type: textarea
id: what
attributes:
@@ -51,7 +43,7 @@ body:
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/CODE_OF_CONDUCT.md)
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/.github/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true

View File

@@ -0,0 +1,42 @@
name: Locize Translation Access Request
description: Request access to an additional language in Locize for LibreChat translations.
title: "Locize Access Request: "
labels: ["🌍 i18n", "🔑 access request"]
body:
- type: markdown
attributes:
value: |
Thank you for your interest in contributing to LibreChat translations!
Please fill out the form below to request access to an additional language in **Locize**.
**🔗 Available Languages:** [View the list here](https://www.librechat.ai/docs/translation)
**📌 Note:** Ensure that the requested language is supported before submitting your request.
- type: input
id: account_name
attributes:
label: Locize Account Name
description: Please provide your Locize account name (e.g., John Doe).
placeholder: e.g., John Doe
validations:
required: true
- type: input
id: language_requested
attributes:
label: Language Code (ISO 639-1)
description: |
Enter the **ISO 639-1** language code for the language you want to translate into.
Example: `es` for Spanish, `zh-Hant` for Traditional Chinese.
**🔗 Reference:** [Available Languages](https://www.librechat.ai/docs/translation)
placeholder: e.g., es
validations:
required: true
- type: checkboxes
id: agreement
attributes:
label: Agreement
description: By submitting this request, you confirm that you will contribute responsibly and adhere to the project guidelines.
options:
- label: I agree to use my access solely for contributing to LibreChat translations.
required: true

View File

@@ -0,0 +1,33 @@
name: New Language Request
description: Request to add a new language for LibreChat translations.
title: "New Language Request: "
labels: ["✨ enhancement", "🌍 i18n"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to submit a new language request! Please fill out the following details so we can review your request.
- type: input
id: language_name
attributes:
label: Language Name
description: Please provide the full name of the language (e.g., Spanish, Mandarin).
placeholder: e.g., Spanish
validations:
required: true
- type: input
id: iso_code
attributes:
label: ISO 639-1 Code
description: Please provide the ISO 639-1 code for the language (e.g., es for Spanish). You can refer to [this list](https://www.w3schools.com/tags/ref_language_codes.asp) for valid codes.
placeholder: e.g., es
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/.github/CODE_OF_CONDUCT.md).
options:
- label: I agree to follow this project's Code of Conduct
required: true

View File

@@ -1,58 +0,0 @@
name: Question
description: Ask your question
title: "[Question]: "
labels: ["question"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill this!
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. email@example.com
validations:
required: false
- type: textarea
id: what-is-your-question
attributes:
label: What is your question?
description: Please give as many details as possible
placeholder: Please give as many details as possible
validations:
required: true
- type: textarea
id: more-details
attributes:
label: More Details
description: Please provide more details if needed.
placeholder: Please provide more details if needed.
validations:
required: true
- type: dropdown
id: browsers
attributes:
label: What is the main subject of your question?
multiple: true
options:
- Documentation
- Installation
- UI
- Endpoints
- User System/OAuth
- Other
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem. You can drag and drop, paste images directly here or link to them.
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/danny-avila/LibreChat/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true

6
.github/SECURITY.md vendored
View File

@@ -12,7 +12,7 @@ When reporting a security vulnerability, you have the following options to reach
- **Option 2: GitHub Issues**: You can initiate first contact via GitHub Issues. However, please note that initial contact through GitHub Issues should not include any sensitive details.
- **Option 3: Discord Server**: You can join our [Discord community](https://discord.gg/5rbRxn4uME) and initiate first contact in the `#issues` channel. However, please ensure that initial contact through Discord does not include any sensitive details.
- **Option 3: Discord Server**: You can join our [Discord community](https://discord.librechat.ai) and initiate first contact in the `#issues` channel. However, please ensure that initial contact through Discord does not include any sensitive details.
_After the initial contact, we will establish a private communication channel for further discussion._
@@ -39,11 +39,11 @@ Please note that as a security-conscious community, we may not always disclose d
This security policy applies to the following GitHub repository:
- Repository: [LibreChat](https://github.com/danny-avila/LibreChat)
- Repository: [LibreChat](https://github.librechat.ai)
## Contact
If you have any questions or concerns regarding the security of our project, please join our [Discord community](https://discord.gg/NGaa9RPCft) and report them in the appropriate channel. You can also reach out to us by [opening an issue](https://github.com/danny-avila/LibreChat/issues/new) on GitHub. Please note that the response time may vary depending on the nature and severity of the inquiry.
If you have any questions or concerns regarding the security of our project, please join our [Discord community](https://discord.librechat.ai) and report them in the appropriate channel. You can also reach out to us by [opening an issue](https://github.com/danny-avila/LibreChat/issues/new) on GitHub. Please note that the response time may vary depending on the nature and severity of the inquiry.
## Acknowledgments

60
.github/configuration-release.json vendored Normal file
View File

@@ -0,0 +1,60 @@
{
"categories": [
{
"title": "### ✨ New Features",
"labels": ["feat"]
},
{
"title": "### 🌍 Internationalization",
"labels": ["i18n"]
},
{
"title": "### 👐 Accessibility",
"labels": ["a11y"]
},
{
"title": "### 🔧 Fixes",
"labels": ["Fix", "fix"]
},
{
"title": "### ⚙️ Other Changes",
"labels": ["ci", "style", "docs", "refactor", "chore"]
}
],
"ignore_labels": [
"🔁 duplicate",
"📊 analytics",
"🌱 good first issue",
"🔍 investigation",
"🙏 help wanted",
"❌ invalid",
"❓ question",
"🚫 wontfix",
"🚀 release",
"version"
],
"base_branches": ["main"],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"label_extractor": [
{
"pattern": "^(?:[^A-Za-z0-9]*)(feat|fix|chore|docs|refactor|ci|style|a11y|i18n)\\s*:",
"target": "$1",
"flags": "i",
"on_property": "title",
"method": "match"
},
{
"pattern": "^(?:[^A-Za-z0-9]*)(v\\d+\\.\\d+\\.\\d+(?:-rc\\d+)?).*",
"target": "version",
"flags": "i",
"on_property": "title",
"method": "match"
}
],
"template": "## [#{{TO_TAG}}] - #{{TO_TAG_DATE}}\n\nChanges from #{{FROM_TAG}} to #{{TO_TAG}}.\n\n#{{CHANGELOG}}\n\n[See full release details][release-#{{TO_TAG}}]\n\n[release-#{{TO_TAG}}]: https://github.com/#{{OWNER}}/#{{REPO}}/releases/tag/#{{TO_TAG}}\n\n---",
"pr_template": "- #{{TITLE}} by **@#{{AUTHOR}}** in [##{{NUMBER}}](#{{URL}})",
"empty_template": "- no changes"
}

68
.github/configuration-unreleased.json vendored Normal file
View File

@@ -0,0 +1,68 @@
{
"categories": [
{
"title": "### ✨ New Features",
"labels": ["feat"]
},
{
"title": "### 🌍 Internationalization",
"labels": ["i18n"]
},
{
"title": "### 👐 Accessibility",
"labels": ["a11y"]
},
{
"title": "### 🔧 Fixes",
"labels": ["Fix", "fix"]
},
{
"title": "### ⚙️ Other Changes",
"labels": ["ci", "style", "docs", "refactor", "chore"]
}
],
"ignore_labels": [
"🔁 duplicate",
"📊 analytics",
"🌱 good first issue",
"🔍 investigation",
"🙏 help wanted",
"❌ invalid",
"❓ question",
"🚫 wontfix",
"🚀 release",
"version",
"action"
],
"base_branches": ["main"],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"label_extractor": [
{
"pattern": "^(?:[^A-Za-z0-9]*)(feat|fix|chore|docs|refactor|ci|style|a11y|i18n)\\s*:",
"target": "$1",
"flags": "i",
"on_property": "title",
"method": "match"
},
{
"pattern": "^(?:[^A-Za-z0-9]*)(v\\d+\\.\\d+\\.\\d+(?:-rc\\d+)?).*",
"target": "version",
"flags": "i",
"on_property": "title",
"method": "match"
},
{
"pattern": "^(?:[^A-Za-z0-9]*)(action)\\b.*",
"target": "action",
"flags": "i",
"on_property": "title",
"method": "match"
}
],
"template": "## [Unreleased]\n\n#{{CHANGELOG}}\n\n---",
"pr_template": "- #{{TITLE}} by **@#{{AUTHOR}}** in [##{{NUMBER}}](#{{URL}})",
"empty_template": "- no changes"
}

View File

@@ -1,47 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/api" # Location of package manifests
target-branch: "dev"
versioning-strategy: increase-if-necessary
schedule:
interval: "weekly"
allow:
# Allow both direct and indirect updates for all packages
- dependency-type: "all"
commit-message:
prefix: "npm api prod"
prefix-development: "npm api dev"
include: "scope"
- package-ecosystem: "npm" # See documentation for possible values
directory: "/client" # Location of package manifests
target-branch: "dev"
versioning-strategy: increase-if-necessary
schedule:
interval: "weekly"
allow:
# Allow both direct and indirect updates for all packages
- dependency-type: "all"
commit-message:
prefix: "npm client prod"
prefix-development: "npm client dev"
include: "scope"
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
target-branch: "dev"
versioning-strategy: increase-if-necessary
schedule:
interval: "weekly"
allow:
# Allow both direct and indirect updates for all packages
- dependency-type: "all"
commit-message:
prefix: "npm all prod"
prefix-development: "npm all dev"
include: "scope"

72
.github/playwright.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
# name: Playwright Tests
# on:
# pull_request:
# branches:
# - main
# - dev
# - release/*
# paths:
# - 'api/**'
# - 'client/**'
# - 'packages/**'
# - 'e2e/**'
# jobs:
# tests_e2e:
# name: Run Playwright tests
# if: github.event.pull_request.head.repo.full_name == 'danny-avila/LibreChat'
# timeout-minutes: 60
# runs-on: ubuntu-latest
# env:
# NODE_ENV: CI
# CI: true
# SEARCH: false
# BINGAI_TOKEN: user_provided
# CHATGPT_TOKEN: user_provided
# MONGO_URI: ${{ secrets.MONGO_URI }}
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# E2E_USER_EMAIL: ${{ secrets.E2E_USER_EMAIL }}
# E2E_USER_PASSWORD: ${{ secrets.E2E_USER_PASSWORD }}
# JWT_SECRET: ${{ secrets.JWT_SECRET }}
# JWT_REFRESH_SECRET: ${{ secrets.JWT_REFRESH_SECRET }}
# CREDS_KEY: ${{ secrets.CREDS_KEY }}
# CREDS_IV: ${{ secrets.CREDS_IV }}
# DOMAIN_CLIENT: ${{ secrets.DOMAIN_CLIENT }}
# DOMAIN_SERVER: ${{ secrets.DOMAIN_SERVER }}
# PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 # Skip downloading during npm install
# PLAYWRIGHT_BROWSERS_PATH: 0 # Places binaries to node_modules/@playwright/test
# TITLE_CONVO: false
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-node@v4
# with:
# node-version: 18
# cache: 'npm'
# - name: Install global dependencies
# run: npm ci
# # - name: Remove sharp dependency
# # run: rm -rf node_modules/sharp
# # - name: Install sharp with linux dependencies
# # run: cd api && SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux --libc=glibc sharp
# - name: Build Client
# run: npm run frontend
# - name: Install Playwright
# run: |
# npx playwright install-deps
# npm install -D @playwright/test@latest
# npx playwright install chromium
# - name: Run Playwright tests
# run: npm run e2e:ci
# - name: Upload playwright report
# uses: actions/upload-artifact@v3
# if: always()
# with:
# name: playwright-report
# path: e2e/playwright-report/
# retention-days: 30

View File

@@ -1,7 +1,10 @@
# Pull Request Template
⚠️ Before Submitting a PR, Please Review:
- Please ensure that you have thoroughly read and understood the [Contributing Docs](https://github.com/danny-avila/LibreChat/blob/main/.github/CONTRIBUTING.md) before submitting your Pull Request.
### ⚠️ Before Submitting a PR, read the [Contributing Docs](./CONTRIBUTING.md) in full!
⚠️ Documentation Updates Notice:
- Kindly note that documentation updates are managed in this repository: [librechat.ai](https://github.com/LibreChat-AI/librechat.ai)
## Summary
@@ -15,7 +18,7 @@ Please delete any irrelevant options.
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Documentation update
- [ ] Translation update
## Testing
@@ -25,6 +28,8 @@ Please describe your test process and include instructions so that we can reprod
## Checklist
Please delete any irrelevant options.
- [ ] My code adheres to this project's style guidelines
- [ ] I have performed a self-review of my own code
- [ ] I have commented in any complex areas of my code
@@ -33,3 +38,4 @@ Please describe your test process and include instructions so that we can reprod
- [ ] I have written tests demonstrating that my changes are effective or that my feature works
- [ ] Local unit tests pass with my changes
- [ ] Any changes dependent on mine have been merged and published in downstream modules.
- [ ] A pull request for updating the documentation has been submitted.

26
.github/workflows/a11y.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Lint for accessibility issues
on:
pull_request:
paths:
- 'client/src/**'
workflow_dispatch:
inputs:
run_workflow:
description: 'Set to true to run this workflow'
required: true
default: 'false'
jobs:
axe-linter:
runs-on: ubuntu-latest
if: >
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'danny-avila/LibreChat') ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.run_workflow == 'true')
steps:
- uses: actions/checkout@v4
- uses: dequelabs/axe-linter-action@v1
with:
api_key: ${{ secrets.AXE_LINTER_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -23,9 +23,9 @@ jobs:
BAN_INTERVAL: ${{ secrets.BAN_INTERVAL }}
NODE_ENV: CI
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
@@ -33,13 +33,32 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Install Data Provider
- name: Install Data Provider Package
run: npm run build:data-provider
- name: Install MCP Package
run: npm run build:mcp
- name: Create empty auth.json file
run: |
mkdir -p api/data
echo '{}' > api/data/auth.json
- name: Check for Circular dependency in rollup
working-directory: ./packages/data-provider
run: |
output=$(npm run rollup:api)
echo "$output"
if echo "$output" | grep -q "Circular dependency"; then
echo "Error: Circular dependency detected!"
exit 1
fi
- name: Prepare .env.test file
run: cp api/test/.env.test.example api/test/.env.test
- name: Run unit tests
run: cd api && npm run test:ci
- name: Run linters
uses: wearerequired/lint-action@v2
with:
eslint: true
- name: Run librechat-data-provider unit tests
run: cd packages/data-provider && npm run test:ci

View File

@@ -1,52 +0,0 @@
name: Docker Compose Build on Tag
# The workflow is triggered when a tag is pushed
on:
push:
tags:
- "*"
jobs:
build:
runs-on: ubuntu-latest
steps:
# Check out the repository
- name: Checkout
uses: actions/checkout@v2
# Set up Docker
- name: Set up Docker
uses: docker/setup-buildx-action@v1
# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Run docker-compose build
- name: Build Docker images
run: |
cp .env.example .env
docker-compose build
docker build -f Dockerfile.multi --target api-build -t librechat-api .
# Get Tag Name
- name: Get Tag Name
id: tag_name
run: echo "TAG_NAME=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
# Tag it properly before push to github
- name: tag image and push
run: |
docker tag librechat:latest ghcr.io/${{ github.repository_owner }}/librechat:${{ env.TAG_NAME }}
docker push ghcr.io/${{ github.repository_owner }}/librechat:${{ env.TAG_NAME }}
docker tag librechat:latest ghcr.io/${{ github.repository_owner }}/librechat:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat:latest
docker tag librechat-api:latest ghcr.io/${{ github.repository_owner }}/librechat-api:${{ env.TAG_NAME }}
docker push ghcr.io/${{ github.repository_owner }}/librechat-api:${{ env.TAG_NAME }}
docker tag librechat-api:latest ghcr.io/${{ github.repository_owner }}/librechat-api:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat-api:latest

View File

@@ -11,8 +11,8 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
- run: cd packages/data-provider && npm ci
@@ -22,8 +22,8 @@ jobs:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'

41
.github/workflows/deploy-dev.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Update Test Server
on:
workflow_run:
workflows: ["Docker Dev Images Build"]
types:
- completed
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
if: |
github.repository == 'danny-avila/LibreChat' &&
(github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success')
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install SSH Key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.DO_SSH_PRIVATE_KEY }}
known_hosts: ${{ secrets.DO_KNOWN_HOSTS }}
- name: Run update script on DigitalOcean Droplet
env:
DO_HOST: ${{ secrets.DO_HOST }}
DO_USER: ${{ secrets.DO_USER }}
run: |
ssh -o StrictHostKeyChecking=no ${DO_USER}@${DO_HOST} << EOF
sudo -i -u danny bash << EEOF
cd ~/LibreChat && \
git fetch origin main && \
npm run update:deployed && \
git checkout do-deploy && \
git rebase main && \
npm run start:deployed && \
echo "Update completed. Application should be running now."
EEOF
EOF

View File

@@ -17,7 +17,7 @@ jobs:
steps:
# checkout the repo
- name: 'Checkout GitHub Action'
uses: actions/checkout@main
uses: actions/checkout@v4
- name: 'Login via Azure CLI'
uses: azure/login@v1

View File

@@ -8,19 +8,33 @@ on:
paths:
- 'api/**'
- 'client/**'
- 'packages/**'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: api-build
file: Dockerfile.multi
image_name: librechat-dev-api
- target: node
file: Dockerfile
image_name: librechat-dev
steps:
# Check out the repository
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
# Set up Docker
- name: Set up Docker
uses: docker/setup-buildx-action@v1
# Set up QEMU
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
@@ -30,22 +44,29 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Build Docker images
- name: Build Docker images
# Login to Docker Hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Prepare the environment
- name: Prepare environment
run: |
cp .env.example .env
docker build -f Dockerfile.multi --target api-build -t librechat-dev-api .
docker build -f Dockerfile -t librechat-dev .
# Tag and push the images to GitHub Container Registry
- name: Tag and push images
run: |
docker tag librechat-dev-api:latest ghcr.io/${{ github.repository_owner }}/librechat-dev-api:${{ github.sha }}
docker push ghcr.io/${{ github.repository_owner }}/librechat-dev-api:${{ github.sha }}
docker tag librechat-dev-api:latest ghcr.io/${{ github.repository_owner }}/librechat-dev-api:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat-dev-api:latest
docker tag librechat-dev:latest ghcr.io/${{ github.repository_owner }}/librechat-dev:${{ github.sha }}
docker push ghcr.io/${{ github.repository_owner }}/librechat-dev:${{ github.sha }}
docker tag librechat-dev:latest ghcr.io/${{ github.repository_owner }}/librechat-dev:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat-dev:latest
# Build and push Docker images for each target
- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.file }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.sha }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
platforms: linux/amd64,linux/arm64
target: ${{ matrix.target }}

73
.github/workflows/eslint-ci.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
name: ESLint Code Quality Checks
on:
pull_request:
branches:
- main
- dev
- release/*
paths:
- 'api/**'
- 'client/**'
jobs:
eslint_checks:
name: Run ESLint Linting
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
# Run ESLint on changed files within the api/ and client/ directories.
- name: Run ESLint on changed files
env:
SARIF_ESLINT_IGNORE_SUPPRESSED: "true"
run: |
# Extract the base commit SHA from the pull_request event payload.
BASE_SHA=$(jq --raw-output .pull_request.base.sha "$GITHUB_EVENT_PATH")
echo "Base commit SHA: $BASE_SHA"
# Get changed files (only JS/TS files in api/ or client/)
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "$BASE_SHA" HEAD | grep -E '^(api|client)/.*\.(js|jsx|ts|tsx)$' || true)
# Debug output
echo "Changed files:"
echo "$CHANGED_FILES"
# Ensure there are files to lint before running ESLint
if [[ -z "$CHANGED_FILES" ]]; then
echo "No matching files changed. Skipping ESLint."
echo "UPLOAD_SARIF=false" >> $GITHUB_ENV
exit 0
fi
# Set variable to allow SARIF upload
echo "UPLOAD_SARIF=true" >> $GITHUB_ENV
# Run ESLint
npx eslint --no-error-on-unmatched-pattern \
--config eslint.config.mjs \
--format @microsoft/eslint-formatter-sarif \
--output-file eslint-results.sarif $CHANGED_FILES || true
- name: Upload analysis results to GitHub
if: env.UPLOAD_SARIF == 'true'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: eslint-results.sarif
wait-for-processing: true

View File

@@ -1,11 +1,6 @@
#github action to run unit tests for frontend with jest
name: Frontend Unit Tests
on:
# push:
# branches:
# - main
# - dev
# - release/*
pull_request:
branches:
- main
@@ -14,15 +9,38 @@ on:
paths:
- 'client/**'
- 'packages/**'
jobs:
tests_frontend:
name: Run frontend unit tests
tests_frontend_ubuntu:
name: Run frontend unit tests on Ubuntu
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Client
run: npm run frontend:ci
- name: Run unit tests
run: npm run test:ci --verbose
working-directory: client
tests_frontend_windows:
name: Run frontend unit tests on Windows
timeout-minutes: 60
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'

View File

@@ -0,0 +1,94 @@
name: Generate Release Changelog PR
on:
push:
tags:
- 'v*.*.*'
jobs:
generate-release-changelog-pr:
permissions:
contents: write # Needed for pushing commits and creating branches.
pull-requests: write
runs-on: ubuntu-latest
steps:
# 1. Checkout the repository (with full history).
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
# 2. Generate the release changelog using our custom configuration.
- name: Generate Release Changelog
id: generate_release
uses: mikepenz/release-changelog-builder-action@v5.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
configuration: ".github/configuration-release.json"
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
outputFile: CHANGELOG-release.md
# 3. Update the main CHANGELOG.md:
# - If it doesn't exist, create it with a basic header.
# - Remove the "Unreleased" section (if present).
# - Prepend the new release changelog above previous releases.
# - Remove all temporary files before committing.
- name: Update CHANGELOG.md
run: |
# Determine the release tag, e.g. "v1.2.3"
TAG=${GITHUB_REF##*/}
echo "Using release tag: $TAG"
# Ensure CHANGELOG.md exists; if not, create a basic header.
if [ ! -f CHANGELOG.md ]; then
echo "# Changelog" > CHANGELOG.md
echo "" >> CHANGELOG.md
echo "All notable changes to this project will be documented in this file." >> CHANGELOG.md
echo "" >> CHANGELOG.md
fi
echo "Updating CHANGELOG.md…"
# Remove the "Unreleased" section (from "## [Unreleased]" until the first occurrence of '---') if it exists.
if grep -q "^## \[Unreleased\]" CHANGELOG.md; then
awk '/^## \[Unreleased\]/{flag=1} flag && /^---/{flag=0; next} !flag' CHANGELOG.md > CHANGELOG.cleaned
else
cp CHANGELOG.md CHANGELOG.cleaned
fi
# Split the cleaned file into:
# - header.md: content before the first release header ("## [v...").
# - tail.md: content from the first release header onward.
awk '/^## \[v/{exit} {print}' CHANGELOG.cleaned > header.md
awk 'f{print} /^## \[v/{f=1; print}' CHANGELOG.cleaned > tail.md
# Combine header, the new release changelog, and the tail.
echo "Combining updated changelog parts..."
cat header.md CHANGELOG-release.md > CHANGELOG.md.new
echo "" >> CHANGELOG.md.new
cat tail.md >> CHANGELOG.md.new
mv CHANGELOG.md.new CHANGELOG.md
# Remove temporary files.
rm -f CHANGELOG.cleaned header.md tail.md CHANGELOG-release.md
echo "Final CHANGELOG.md content:"
cat CHANGELOG.md
# 4. Create (or update) the Pull Request with the updated CHANGELOG.md.
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
sign-commits: true
commit-message: "chore: update CHANGELOG for release ${GITHUB_REF##*/}"
base: main
branch: "changelog/${GITHUB_REF##*/}"
reviewers: danny-avila
title: "chore: update CHANGELOG for release ${GITHUB_REF##*/}"
body: |
**Description**:
- This PR updates the CHANGELOG.md by removing the "Unreleased" section and adding new release notes for release ${GITHUB_REF##*/} above previous releases.

View File

@@ -0,0 +1,106 @@
name: Generate Unreleased Changelog PR
on:
schedule:
- cron: "0 0 * * 1" # Runs every Monday at 00:00 UTC
jobs:
generate-unreleased-changelog-pr:
permissions:
contents: write # Needed for pushing commits and creating branches.
pull-requests: write
runs-on: ubuntu-latest
steps:
# 1. Checkout the repository on main.
- name: Checkout Repository on Main
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
# 4. Get the latest version tag.
- name: Get Latest Tag
id: get_latest_tag
run: |
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1) || echo "none")
echo "Latest tag: $LATEST_TAG"
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
# 5. Generate the Unreleased changelog.
- name: Generate Unreleased Changelog
id: generate_unreleased
uses: mikepenz/release-changelog-builder-action@v5.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
configuration: ".github/configuration-unreleased.json"
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
outputFile: CHANGELOG-unreleased.md
fromTag: ${{ steps.get_latest_tag.outputs.tag }}
toTag: main
# 7. Update CHANGELOG.md with the new Unreleased section.
- name: Update CHANGELOG.md
id: update_changelog
run: |
# Create CHANGELOG.md if it doesn't exist.
if [ ! -f CHANGELOG.md ]; then
echo "# Changelog" > CHANGELOG.md
echo "" >> CHANGELOG.md
echo "All notable changes to this project will be documented in this file." >> CHANGELOG.md
echo "" >> CHANGELOG.md
fi
echo "Updating CHANGELOG.md…"
# Extract content before the "## [Unreleased]" (or first version header if missing).
if grep -q "^## \[Unreleased\]" CHANGELOG.md; then
awk '/^## \[Unreleased\]/{exit} {print}' CHANGELOG.md > CHANGELOG_TMP.md
else
awk '/^## \[v/{exit} {print}' CHANGELOG.md > CHANGELOG_TMP.md
fi
# Append the generated Unreleased changelog.
echo "" >> CHANGELOG_TMP.md
cat CHANGELOG-unreleased.md >> CHANGELOG_TMP.md
echo "" >> CHANGELOG_TMP.md
# Append the remainder of the original changelog (starting from the first version header).
awk 'f{print} /^## \[v/{f=1; print}' CHANGELOG.md >> CHANGELOG_TMP.md
# Replace the old file with the updated file.
mv CHANGELOG_TMP.md CHANGELOG.md
# Remove the temporary generated file.
rm -f CHANGELOG-unreleased.md
echo "Final CHANGELOG.md:"
cat CHANGELOG.md
# 8. Check if CHANGELOG.md has any updates.
- name: Check for CHANGELOG.md changes
id: changelog_changes
run: |
if git diff --quiet CHANGELOG.md; then
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "has_changes=true" >> $GITHUB_OUTPUT
fi
# 9. Create (or update) the Pull Request only if there are changes.
- name: Create Pull Request
if: steps.changelog_changes.outputs.has_changes == 'true'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
base: main
branch: "changelog/unreleased-update"
sign-commits: true
commit-message: "action: update Unreleased changelog"
title: "action: update Unreleased changelog"
body: |
**Description**:
- This PR updates the Unreleased section in CHANGELOG.md.
- It compares the current main branch with the latest version tag (determined as ${{ steps.get_latest_tag.outputs.tag }}),
regenerates the Unreleased changelog, removes any old Unreleased block, and inserts the new content.

View File

@@ -0,0 +1,20 @@
name: 'generate_embeddings'
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'docs/**'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: supabase/embeddings-generator@v0.0.5
with:
supabase-url: ${{ secrets.SUPABASE_URL }}
supabase-service-role-key: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
openai-key: ${{ secrets.OPENAI_DOC_EMBEDDINGS_KEY }}
docs-root-path: 'docs'

33
.github/workflows/helmcharts.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Build Helm Charts on Tag
# The workflow is triggered when a tag is pushed
on:
push:
tags:
- "*"
jobs:
release:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

93
.github/workflows/i18n-unused-keys.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: Detect Unused i18next Strings
on:
pull_request:
paths:
- "client/src/**"
- "api/**"
jobs:
detect-unused-i18n-keys:
runs-on: ubuntu-latest
permissions:
pull-requests: write # Required for posting PR comments
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Find unused i18next keys
id: find-unused
run: |
echo "🔍 Scanning for unused i18next keys..."
# Define paths
I18N_FILE="client/src/locales/en/translation.json"
SOURCE_DIRS=("client/src" "api")
# Check if translation file exists
if [[ ! -f "$I18N_FILE" ]]; then
echo "::error title=Missing i18n File::Translation file not found: $I18N_FILE"
exit 1
fi
# Extract all keys from the JSON file
KEYS=$(jq -r 'keys[]' "$I18N_FILE")
# Track unused keys
UNUSED_KEYS=()
# Check if each key is used in the source code
for KEY in $KEYS; do
FOUND=false
for DIR in "${SOURCE_DIRS[@]}"; do
if grep -r --include=\*.{js,jsx,ts,tsx} -q "$KEY" "$DIR"; then
FOUND=true
break
fi
done
if [[ "$FOUND" == false ]]; then
UNUSED_KEYS+=("$KEY")
fi
done
# Output results
if [[ ${#UNUSED_KEYS[@]} -gt 0 ]]; then
echo "🛑 Found ${#UNUSED_KEYS[@]} unused i18n keys:"
echo "unused_keys=$(echo "${UNUSED_KEYS[@]}" | jq -R -s -c 'split(" ")')" >> $GITHUB_ENV
for KEY in "${UNUSED_KEYS[@]}"; do
echo "::warning title=Unused i18n Key::'$KEY' is defined but not used in the codebase."
done
else
echo "✅ No unused i18n keys detected!"
echo "unused_keys=[]" >> $GITHUB_ENV
fi
- name: Post verified comment on PR
if: env.unused_keys != '[]'
run: |
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
# Format the unused keys list as checkboxes for easy manual checking.
FILTERED_KEYS=$(echo "$unused_keys" | jq -r '.[]' | grep -v '^\s*$' | sed 's/^/- [ ] `/;s/$/`/' )
COMMENT_BODY=$(cat <<EOF
### 🚨 Unused i18next Keys Detected
The following translation keys are defined in \`translation.json\` but are **not used** in the codebase:
$FILTERED_KEYS
⚠️ **Please remove these unused keys to keep the translation files clean.**
EOF
)
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
-f body="$COMMENT_BODY" \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Fail workflow if unused keys found
if: env.unused_keys != '[]'
run: exit 1

View File

@@ -1,40 +0,0 @@
name: Docker Compose Build on Main Branch
on:
workflow_dispatch: # This line allows manual triggering
jobs:
build:
runs-on: ubuntu-latest
steps:
# Check out the repository
- name: Checkout
uses: actions/checkout@v2
# Set up Docker
- name: Set up Docker
uses: docker/setup-buildx-action@v1
# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Run docker-compose build
- name: Build Docker images
run: |
cp .env.example .env
docker-compose build
docker build -f Dockerfile.multi --target api-build -t librechat-api .
# Tag and push the images with the 'latest' tag
- name: Tag image and push
run: |
docker tag librechat:latest ghcr.io/${{ github.repository_owner }}/librechat:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat:latest
docker tag librechat-api:latest ghcr.io/${{ github.repository_owner }}/librechat-api:latest
docker push ghcr.io/${{ github.repository_owner }}/librechat-api:latest

72
.github/workflows/locize-i18n-sync.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Sync Locize Translations & Create Translation PR
on:
push:
branches: [main]
repository_dispatch:
types: [locize/versionPublished]
jobs:
sync-translations:
name: Sync Translation Keys with Locize
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install locize CLI
run: npm install -g locize-cli
# Sync translations (Push missing keys & remove deleted ones)
- name: Sync Locize with Repository
if: ${{ github.event_name == 'push' }}
run: |
cd client/src/locales
locize sync --api-key ${{ secrets.LOCIZE_API_KEY }} --project-id ${{ secrets.LOCIZE_PROJECT_ID }} --language en
# When triggered by repository_dispatch, skip sync step.
- name: Skip sync step on non-push events
if: ${{ github.event_name != 'push' }}
run: echo "Skipping sync as the event is not a push."
create-pull-request:
name: Create Translation PR on Version Published
runs-on: ubuntu-latest
needs: sync-translations
permissions:
contents: write
pull-requests: write
steps:
# 1. Check out the repository.
- name: Checkout Repository
uses: actions/checkout@v4
# 2. Download translation files from locize.
- name: Download Translations from locize
uses: locize/download@v1
with:
project-id: ${{ secrets.LOCIZE_PROJECT_ID }}
path: "client/src/locales"
# 3. Create a Pull Request using built-in functionality.
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
sign-commits: true
commit-message: "🌍 i18n: Update translation.json with latest translations"
base: main
branch: i18n/locize-translation-update
reviewers: danny-avila
title: "🌍 i18n: Update translation.json with latest translations"
body: |
**Description**:
- 🎯 **Objective**: Update `translation.json` with the latest translations from locize.
- 🔍 **Details**: This PR is automatically generated upon receiving a versionPublished event with version "latest". It reflects the newest translations provided by locize.
- ✅ **Status**: Ready for review.
labels: "🌍 i18n"

View File

@@ -0,0 +1,69 @@
name: Docker Compose Build Latest Main Image Tag (Manual Dispatch)
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: api-build
file: Dockerfile.multi
image_name: librechat-api
- target: node
file: Dockerfile
image_name: librechat
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Fetch tags and set the latest tag
run: |
git fetch --tags
echo "LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_ENV
# Set up QEMU
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Login to Docker Hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Prepare the environment
- name: Prepare environment
run: |
cp .env.example .env
# Build and push Docker images for each target
- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.file }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ env.LATEST_TAG }}
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ env.LATEST_TAG }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
platforms: linux/amd64,linux/arm64
target: ${{ matrix.target }}

View File

@@ -1,24 +0,0 @@
name: mkdocs
on:
push:
branches:
- main
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v3
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: mkdocs gh-deploy --force

View File

@@ -1,72 +0,0 @@
name: Playwright Tests
on:
pull_request:
branches:
- main
- dev
- release/*
paths:
- 'api/**'
- 'client/**'
- 'packages/**'
- 'e2e/**'
jobs:
tests_e2e:
name: Run Playwright tests
if: github.event.pull_request.head.repo.full_name == 'danny-avila/LibreChat'
timeout-minutes: 60
runs-on: ubuntu-latest
env:
NODE_ENV: CI
CI: true
SEARCH: false
BINGAI_TOKEN: user_provided
CHATGPT_TOKEN: user_provided
MONGO_URI: ${{ secrets.MONGO_URI }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
E2E_USER_EMAIL: ${{ secrets.E2E_USER_EMAIL }}
E2E_USER_PASSWORD: ${{ secrets.E2E_USER_PASSWORD }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
JWT_REFRESH_SECRET: ${{ secrets.JWT_REFRESH_SECRET }}
CREDS_KEY: ${{ secrets.CREDS_KEY }}
CREDS_IV: ${{ secrets.CREDS_IV }}
DOMAIN_CLIENT: ${{ secrets.DOMAIN_CLIENT }}
DOMAIN_SERVER: ${{ secrets.DOMAIN_SERVER }}
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 # Skip downloading during npm install
PLAYWRIGHT_BROWSERS_PATH: 0 # Places binaries to node_modules/@playwright/test
TITLE_CONVO: false
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'npm'
- name: Install global dependencies
run: npm ci
# - name: Remove sharp dependency
# run: rm -rf node_modules/sharp
# - name: Install sharp with linux dependencies
# run: cd api && SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux --libc=glibc sharp
- name: Build Client
run: npm run frontend
- name: Install Playwright
run: |
npx playwright install-deps
npm install -D @playwright/test@latest
npx playwright install chromium
- name: Run Playwright tests
run: npm run e2e:ci
- name: Upload playwright report
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: e2e/playwright-report/
retention-days: 30

67
.github/workflows/tag-images.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: Docker Images Build on Tag
on:
push:
tags:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: api-build
file: Dockerfile.multi
image_name: librechat-api
- target: node
file: Dockerfile
image_name: librechat
steps:
# Check out the repository
- name: Checkout
uses: actions/checkout@v4
# Set up QEMU
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log in to GitHub Container Registry
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Login to Docker Hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Prepare the environment
- name: Prepare environment
run: |
cp .env.example .env
# Build and push Docker images for each target
- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.file }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.ref_name }}
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.ref_name }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
platforms: linux/amd64,linux/arm64
target: ${{ matrix.target }}

153
.github/workflows/unused-packages.yml vendored Normal file
View File

@@ -0,0 +1,153 @@
name: Detect Unused NPM Packages
on:
pull_request:
paths:
- 'package.json'
- 'package-lock.json'
- 'client/**'
- 'api/**'
jobs:
detect-unused-packages:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install depcheck
run: npm install -g depcheck
- name: Validate JSON files
run: |
for FILE in package.json client/package.json api/package.json; do
if [[ -f "$FILE" ]]; then
jq empty "$FILE" || (echo "::error title=Invalid JSON::$FILE is invalid" && exit 1)
fi
done
- name: Extract Dependencies Used in Scripts
id: extract-used-scripts
run: |
extract_deps_from_scripts() {
local package_file=$1
if [[ -f "$package_file" ]]; then
jq -r '.scripts | to_entries[].value' "$package_file" | \
grep -oE '([a-zA-Z0-9_-]+)' | sort -u > used_scripts.txt
else
touch used_scripts.txt
fi
}
extract_deps_from_scripts "package.json"
mv used_scripts.txt root_used_deps.txt
extract_deps_from_scripts "client/package.json"
mv used_scripts.txt client_used_deps.txt
extract_deps_from_scripts "api/package.json"
mv used_scripts.txt api_used_deps.txt
- name: Extract Dependencies Used in Source Code
id: extract-used-code
run: |
extract_deps_from_code() {
local folder=$1
local output_file=$2
if [[ -d "$folder" ]]; then
grep -rEho "require\\(['\"]([a-zA-Z0-9@/._-]+)['\"]\\)" "$folder" --include=\*.{js,ts,mjs,cjs} | \
sed -E "s/require\\(['\"]([a-zA-Z0-9@/._-]+)['\"]\\)/\1/" > "$output_file"
grep -rEho "import .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{js,ts,mjs,cjs} | \
sed -E "s/import .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]/\1/" >> "$output_file"
sort -u "$output_file" -o "$output_file"
else
touch "$output_file"
fi
}
extract_deps_from_code "." root_used_code.txt
extract_deps_from_code "client" client_used_code.txt
extract_deps_from_code "api" api_used_code.txt
- name: Run depcheck for root package.json
id: check-root
run: |
if [[ -f "package.json" ]]; then
UNUSED=$(depcheck --json | jq -r '.dependencies | join("\n")' || echo "")
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat root_used_deps.txt root_used_code.txt | sort) || echo "")
echo "ROOT_UNUSED<<EOF" >> $GITHUB_ENV
echo "$UNUSED" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
fi
- name: Run depcheck for client/package.json
id: check-client
run: |
if [[ -f "client/package.json" ]]; then
chmod -R 755 client
cd client
UNUSED=$(depcheck --json | jq -r '.dependencies | join("\n")' || echo "")
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../client_used_deps.txt ../client_used_code.txt | sort) || echo "")
echo "CLIENT_UNUSED<<EOF" >> $GITHUB_ENV
echo "$UNUSED" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
cd ..
fi
- name: Run depcheck for api/package.json
id: check-api
run: |
if [[ -f "api/package.json" ]]; then
chmod -R 755 api
cd api
UNUSED=$(depcheck --json | jq -r '.dependencies | join("\n")' || echo "")
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../api_used_deps.txt ../api_used_code.txt | sort) || echo "")
echo "API_UNUSED<<EOF" >> $GITHUB_ENV
echo "$UNUSED" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
cd ..
fi
- name: Post comment on PR if unused dependencies are found
if: env.ROOT_UNUSED != '' || env.CLIENT_UNUSED != '' || env.API_UNUSED != ''
run: |
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
ROOT_LIST=$(echo "$ROOT_UNUSED" | awk '{print "- `" $0 "`"}')
CLIENT_LIST=$(echo "$CLIENT_UNUSED" | awk '{print "- `" $0 "`"}')
API_LIST=$(echo "$API_UNUSED" | awk '{print "- `" $0 "`"}')
COMMENT_BODY=$(cat <<EOF
### 🚨 Unused NPM Packages Detected
The following **unused dependencies** were found:
$(if [[ ! -z "$ROOT_UNUSED" ]]; then echo "#### 📂 Root \`package.json\`"; echo ""; echo "$ROOT_LIST"; echo ""; fi)
$(if [[ ! -z "$CLIENT_UNUSED" ]]; then echo "#### 📂 Client \`client/package.json\`"; echo ""; echo "$CLIENT_LIST"; echo ""; fi)
$(if [[ ! -z "$API_UNUSED" ]]; then echo "#### 📂 API \`api/package.json\`"; echo ""; echo "$API_LIST"; echo ""; fi)
⚠️ **Please remove these unused dependencies to keep your project clean.**
EOF
)
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
-f body="$COMMENT_BODY" \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Fail workflow if unused dependencies found
if: env.ROOT_UNUSED != '' || env.CLIENT_UNUSED != '' || env.API_UNUSED != ''
run: exit 1

34
.gitignore vendored
View File

@@ -2,7 +2,7 @@
# Logs
data-node
meili_data
meili_data*
data/
logs
*.log
@@ -11,6 +11,7 @@ logs
pids
*.pid
*.seed
.git
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
@@ -21,6 +22,10 @@ coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# translation services
config/translations/stores/*
client/src/localization/languages/*_missing_keys.json
# Compiled Dirs (http://nodejs.org/api/addons.html)
build/
dist/
@@ -40,7 +45,8 @@ meili_data/
api/node_modules/
client/node_modules/
bower_components/
types/
*.d.ts
!vite-env.d.ts
# Floobits
.floo
@@ -48,6 +54,10 @@ types/
.floo
.flooignore
#config file
librechat.yaml
librechat.yml
# Environment
.npmrc
.env*
@@ -65,11 +75,20 @@ src/style - official.css
/playwright/.cache/
.DS_Store
*.code-workspace
.idx
monospace.json
.idea
*.iml
*.pem
config.local.ts
**/storageState.json
junit.xml
**/.venv/
**/venv/
# docker override file
docker-compose.override.yaml
docker-compose.override.yml
# meilisearch
meilisearch
@@ -78,4 +97,13 @@ data.ms/*
auth.json
/packages/ux-shared/
/images
/images
!client/src/components/Nav/SettingsTabs/Data/
# User uploads
uploads/
# owner
release/
!/client/src/@types/i18next.d.ts

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env sh
set -e
. "$(dirname -- "$0")/_/husky.sh"
[ -n "$CI" ] && exit 0

19
.prettierrc Normal file
View File

@@ -0,0 +1,19 @@
{
"tailwindConfig": "./client/tailwind.config.mjs",
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always",
"embeddedLanguageFormatting": "auto",
"insertPragma": false,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"rangeStart": 0,
"endOfLine": "auto",
"jsxSingleQuote": false,
"plugins": ["prettier-plugin-tailwindcss"]
}

17
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch LibreChat (debug)",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/api/server/index.js",
"env": {
"NODE_ENV": "production"
},
"console": "integratedTerminal",
"envFile": "${workspaceFolder}/.env"
}
]
}

View File

@@ -1,21 +1,32 @@
# Base node image
FROM node:19-alpine AS node
# v0.7.7-rc1
COPY . /app
# Base node image
FROM node:20-alpine AS node
RUN apk --no-cache add curl
RUN mkdir -p /app && chown node:node /app
WORKDIR /app
# Install call deps - Install curl for health check
RUN apk --no-cache add curl && \
# We want to inherit env from the container, not the file
# This will preserve any existing env file if it's already in souce
# otherwise it will create a new one
touch .env && \
# Build deps in seperate
npm ci
USER node
# React client build
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN npm run frontend
COPY --chown=node:node . .
RUN \
# Allow mounting of these files, which have no default
touch .env ; \
# Create directories for the volumes to inherit the correct permissions
mkdir -p /app/client/public/images /app/api/logs ; \
npm config set fetch-retry-maxtimeout 600000 ; \
npm config set fetch-retries 5 ; \
npm config set fetch-retry-mintimeout 15000 ; \
npm install --no-audit; \
# React client build
NODE_OPTIONS="--max-old-space-size=2048" npm run frontend; \
npm prune --production; \
npm cache clean --force
RUN mkdir -p /app/client/public/images /app/api/logs
# Node API setup
EXPOSE 3080

View File

@@ -1,40 +1,56 @@
# Build API, Client and Data Provider
FROM node:19-alpine AS base
# Dockerfile.multi
# v0.7.7-rc1
# Base for all builds
FROM node:20-alpine AS base-min
WORKDIR /app
COPY config/loader.js ./config/
RUN npm install dotenv
RUN apk --no-cache add curl
RUN npm config set fetch-retry-maxtimeout 600000 && \
npm config set fetch-retries 5 && \
npm config set fetch-retry-mintimeout 15000
COPY package*.json ./
COPY packages/data-provider/package*.json ./packages/data-provider/
COPY packages/mcp/package*.json ./packages/mcp/
COPY client/package*.json ./client/
COPY api/package*.json ./api/
WORKDIR /app/api
COPY api/package*.json ./
COPY api/ ./
RUN npm install
# Install all dependencies for every build
FROM base-min AS base
WORKDIR /app
RUN npm ci
# React client build
# Build data-provider
FROM base AS data-provider-build
WORKDIR /app/packages/data-provider
COPY packages/data-provider ./
RUN npm run build
# Build mcp package
FROM base AS mcp-build
WORKDIR /app/packages/mcp
COPY packages/mcp ./
COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist
RUN npm run build
# Client build
FROM base AS client-build
WORKDIR /app/client
COPY ./client/ ./
WORKDIR /app/packages/data-provider
COPY ./packages/data-provider ./
RUN npm install
RUN npm run build
RUN mkdir -p /app/client/node_modules/librechat-data-provider/
RUN cp -R /app/packages/data-provider/* /app/client/node_modules/librechat-data-provider/
WORKDIR /app/client
RUN npm install
COPY client ./
COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN npm run build
# Node API setup
FROM base AS api-build
COPY --from=client-build /app/client/dist /app/client/dist
# API setup (including client dist)
FROM base-min AS api-build
WORKDIR /app
# Install only production deps
RUN npm ci --omit=dev
COPY api ./api
COPY config ./config
COPY --from=data-provider-build /app/packages/data-provider/dist ./packages/data-provider/dist
COPY --from=mcp-build /app/packages/mcp/dist ./packages/mcp/dist
COPY --from=client-build /app/client/dist ./client/dist
WORKDIR /app/api
EXPOSE 3080
ENV HOST=0.0.0.0
CMD ["node", "server/index.js"]
# Nginx setup
FROM nginx:1.21.1-alpine AS prod-stage
COPY ./client/nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 LibreChat
Copyright (c) 2025 LibreChat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

272
README.md
View File

@@ -1,14 +1,14 @@
<p align="center">
<a href="https://docs.librechat.ai">
<img src="docs/assets/LibreChat.svg" height="256">
</a>
<a href="https://docs.librechat.ai">
<h1 align="center">LibreChat</h1>
<a href="https://librechat.ai">
<img src="client/public/assets/logo.svg" height="256">
</a>
<h1 align="center">
<a href="https://librechat.ai">LibreChat</a>
</h1>
</p>
<p align="center">
<a href="https://discord.gg/NGaa9RPCft">
<a href="https://discord.librechat.ai">
<img
src="https://img.shields.io/discord/1086345563026489514?label=&logo=discord&style=for-the-badge&logoWidth=20&logoColor=white&labelColor=000000&color=blueviolet">
</a>
@@ -20,145 +20,183 @@
<img
src="https://img.shields.io/badge/DOCS-blue.svg?style=for-the-badge&logo=read-the-docs&logoColor=white&labelColor=000000&logoWidth=20">
</a>
<a aria-label="Sponsors" href="#sponsors">
<a aria-label="Sponsors" href="https://github.com/sponsors/danny-avila">
<img
src="https://img.shields.io/badge/SPONSORS-brightgreen.svg?style=for-the-badge&logo=github-sponsors&logoColor=white&labelColor=000000&logoWidth=20">
</a>
</p>
## All-In-One AI Conversations with LibreChat ##
<p align="center">
<a href="https://railway.app/template/b5k2mn?referralCode=HI9hWz">
<img src="https://railway.app/button.svg" alt="Deploy on Railway" height="30">
</a>
<a href="https://zeabur.com/templates/0X2ZY8">
<img src="https://zeabur.com/button.svg" alt="Deploy on Zeabur" height="30"/>
</a>
<a href="https://template.cloud.sealos.io/deploy?templateName=librechat">
<img src="https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg" alt="Deploy on Sealos" height="30">
</a>
</p>
<p align="center">
<a href="https://www.librechat.ai/docs/translation">
<img
src="https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge&color=2096F3&label=locize&query=%24.translatedPercentage&url=https://api.locize.app/badgedata/4cb2598b-ed4d-469c-9b04-2ed531a8cb45&suffix=%+translated"
alt="Translation Progress">
</a>
</p>
# ✨ Features
- 🖥️ **UI & Experience** inspired by ChatGPT with enhanced design and features
- 🤖 **AI Model Selection**:
- Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, Google, Vertex AI, OpenAI Assistants API (incl. Azure)
- [Custom Endpoints](https://www.librechat.ai/docs/quick_start/custom_endpoints): Use any OpenAI-compatible API with LibreChat, no proxy required
- Compatible with [Local & Remote AI Providers](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints):
- Ollama, groq, Cohere, Mistral AI, Apple MLX, koboldcpp, together.ai,
- OpenRouter, Perplexity, ShuttleAI, Deepseek, Qwen, and more
- 🔧 **[Code Interpreter API](https://www.librechat.ai/docs/features/code_interpreter)**:
- Secure, Sandboxed Execution in Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust, and Fortran
- Seamless File Handling: Upload, process, and download files directly
- No Privacy Concerns: Fully isolated and secure execution
- 🔦 **Agents & Tools Integration**:
- **[LibreChat Agents](https://www.librechat.ai/docs/features/agents)**:
- No-Code Custom Assistants: Build specialized, AI-driven helpers without coding
- Flexible & Extensible: Attach tools like DALL-E-3, file search, code execution, and more
- Compatible with Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, and more
- [Model Context Protocol (MCP) Support](https://modelcontextprotocol.io/clients#librechat) for Tools
- Use LibreChat Agents and OpenAI Assistants with Files, Code Interpreter, Tools, and API Actions
- 🪄 **Generative UI with Code Artifacts**:
- [Code Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3) allow creation of React, HTML, and Mermaid diagrams directly in chat
- 💾 **Presets & Context Management**:
- Create, Save, & Share Custom Presets
- Switch between AI Endpoints and Presets mid-chat
- Edit, Resubmit, and Continue Messages with Conversation branching
- [Fork Messages & Conversations](https://www.librechat.ai/docs/features/fork) for Advanced Context control
- 💬 **Multimodal & File Interactions**:
- Upload and analyze images with Claude 3, GPT-4o, o1, Llama-Vision, and Gemini 📸
- Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, & Google 🗃️
- 🌎 **Multilingual UI**:
- English, 中文, Deutsch, Español, Français, Italiano, Polski, Português Brasileiro
- Русский, 日本語, Svenska, 한국어, Tiếng Việt, 繁體中文, العربية, Türkçe, Nederlands, עברית
- 🧠 **Reasoning UI**:
- Dynamic Reasoning UI for Chain-of-Thought/Reasoning AI models like DeepSeek-R1
- 🎨 **Customizable Interface**:
- Customizable Dropdown & Interface that adapts to both power users and newcomers
- 🗣️ **Speech & Audio**:
- Chat hands-free with Speech-to-Text and Text-to-Speech
- Automatically send and play Audio
- Supports OpenAI, Azure OpenAI, and Elevenlabs
- 📥 **Import & Export Conversations**:
- Import Conversations from LibreChat, ChatGPT, Chatbot UI
- Export conversations as screenshots, markdown, text, json
- 🔍 **Search & Discovery**:
- Search all messages/conversations
- 👥 **Multi-User & Secure Access**:
- Multi-User, Secure Authentication with OAuth2, LDAP, & Email Login Support
- Built-in Moderation, and Token spend tools
- ⚙️ **Configuration & Deployment**:
- Configure Proxy, Reverse Proxy, Docker, & many Deployment options
- Use completely local or deploy on the cloud
- 📖 **Open-Source & Community**:
- Completely Open-Source & Built in Public
- Community-driven development, support, and feedback
[For a thorough review of our features, see our docs here](https://docs.librechat.ai/) 📚
## 🪶 All-In-One AI Conversations with LibreChat
LibreChat brings together the future of assistant AIs with the revolutionary technology of OpenAI's ChatGPT. Celebrating the original styling, LibreChat gives you the ability to integrate multiple AI models. It also integrates and enhances original client features such as conversation and message search, prompt templates and plugins.
With LibreChat, you no longer need to opt for ChatGPT Plus and can instead use free or pay-per-call APIs. We welcome contributions, cloning, and forking to enhance the capabilities of this advanced chatbot platform.
<!-- https://github.com/danny-avila/LibreChat/assets/110412045/c1eb0c0f-41f6-4335-b982-84b278b53d59 -->
[![Watch the video](https://img.youtube.com/vi/pNIOs1ovsXw/maxresdefault.jpg)](https://youtu.be/pNIOs1ovsXw)
[![Watch the video](https://raw.githubusercontent.com/LibreChat-AI/librechat.ai/main/public/images/changelog/v0.7.6.gif)](https://www.youtube.com/watch?v=ilfwGQtJNlI)
Click on the thumbnail to open the video☝
# Features
- Response streaming identical to ChatGPT through server-sent events
- UI from original ChatGPT, including Dark mode
- AI model selection: OpenAI API, BingAI, ChatGPT Browser, PaLM2, Anthropic (Claude), Plugins
- Create, Save, & Share custom presets - [More info on prompt presets here](https://github.com/danny-avila/LibreChat/releases/tag/v0.3.0)
- Edit and Resubmit messages with conversation branching
- Search all messages/conversations - [More info here](https://github.com/danny-avila/LibreChat/releases/tag/v0.1.0)
- Plugins now available (including web access, image generation and more)
---
## 🌐 Resources
**GitHub Repo:**
- **RAG API:** [github.com/danny-avila/rag_api](https://github.com/danny-avila/rag_api)
- **Website:** [github.com/LibreChat-AI/librechat.ai](https://github.com/LibreChat-AI/librechat.ai)
**Other:**
- **Website:** [librechat.ai](https://librechat.ai)
- **Documentation:** [docs.librechat.ai](https://docs.librechat.ai)
- **Blog:** [blog.librechat.ai](https://blog.librechat.ai)
---
## ⚠️ [Breaking Changes](docs/general_info/breaking_changes.md) ⚠️
## 📝 Changelog
**Please read this before updating from a previous version**
Keep up with the latest updates by visiting the releases page and notes:
- [Releases](https://github.com/danny-avila/LibreChat/releases)
- [Changelog](https://www.librechat.ai/changelog)
**⚠️ Please consult the [changelog](https://www.librechat.ai/changelog) for breaking changes before updating.**
---
## Changelog
Keep up with the latest updates by visiting the releases page - [Releases](https://github.com/danny-avila/LibreChat/releases)
## ⭐ Star History
<p align="center">
<a href="https://star-history.com/#danny-avila/LibreChat&Date">
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date&theme=dark" onerror="this.src='https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date'" />
</a>
</p>
<p align="center">
<a href="https://trendshift.io/repositories/4685" target="_blank" style="padding: 10px;">
<img src="https://trendshift.io/api/badge/repositories/4685" alt="danny-avila%2FLibreChat | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
</a>
<a href="https://runacap.com/ross-index/q1-24/" target="_blank" rel="noopener" style="margin-left: 20px;">
<img style="width: 260px; height: 56px" src="https://runacap.com/wp-content/uploads/2024/04/ROSS_badge_white_Q1_2024.svg" alt="ROSS Index - Fastest Growing Open-Source Startups in Q1 2024 | Runa Capital" width="260" height="56"/>
</a>
</p>
---
<h1>Table of Contents</h1>
## ✨ Contributions
<details open>
<summary><strong>Getting Started</strong></summary>
Contributions, suggestions, bug reports and fixes are welcome!
* Installation
* [Docker Compose Install🐳](docs/install/docker_compose_install.md)
* [Linux Install🐧](docs/install/linux_install.md)
* [Mac Install🍎](docs/install/mac_install.md)
* [Windows Install💙](docs/install/windows_install.md)
* Configuration
* [APIs and Tokens](docs/install/apis_and_tokens.md)
* [User Auth System](docs/install/user_auth_system.md)
* [Online MongoDB Database](docs/install/mongodb.md)
* [Default Language](docs/install/default_language.md)
</details>
<details>
<summary><strong>General Information</strong></summary>
* [Code of Conduct](.github/CODE_OF_CONDUCT.md)
* [Project Origin](docs/general_info/project_origin.md)
* [Multilingual Information](docs/general_info/multilingual_information.md)
* [Tech Stack](docs/general_info/tech_stack.md)
</details>
<details>
<summary><strong>Features</strong></summary>
* **Plugins**
* [Introduction](docs/features/plugins/introduction.md)
* [Google](docs/features/plugins/google_search.md)
* [Stable Diffusion](docs/features/plugins/stable_diffusion.md)
* [Wolfram](docs/features/plugins/wolfram.md)
* [Make Your Own Plugin](docs/features/plugins/make_your_own.md)
* [Using official ChatGPT Plugins](docs/features/plugins/chatgpt_plugins_openapi.md)
* [Automated Moderation](docs/features/mod_system.md)
* [Third-Party Tools](docs/features/third_party.md)
* [Proxy](docs/features/proxy.md)
* [Bing Jailbreak](docs/features/bing_jailbreak.md)
* [Token Usage](docs/features/token_usage.md)
</details>
<details>
<summary><strong>Cloud Deployment</strong></summary>
* [DigitalOcean](docs/deployment/digitalocean.md)
* [Azure](docs/deployment/azure-terraform.md)
* [Linode](docs/deployment/linode.md)
* [Cloudflare](docs/deployment/cloudflare.md)
* [Ngrok](docs/deployment/ngrok.md)
* [HuggingFace](docs/deployment/huggingface.md)
* [Render](docs/deployment/render.md)
* [Meilisearch in Render](docs/deployment/meilisearch_in_render.md)
* [Hetzner](docs/deployment/hetzner_ubuntu.md)
* [Heroku](docs/deployment/heroku.md)
</details>
<details>
<summary><strong>Contributions</strong></summary>
* [Contributor Guidelines](.github/CONTRIBUTING.md)
* [Documentation Guidelines](docs/contributions/documentation_guidelines.md)
* [Contribute a Translation](docs/contributions/translation_contribution.md)
* [Code Standards and Conventions](docs/contributions/coding_conventions.md)
* [Testing](docs/contributions/testing.md)
* [Security](.github/SECURITY.md)
* [Project Roadmap](https://github.com/users/danny-avila/projects/2)
</details>
For new features, components, or extensions, please open an issue and discuss before sending a PR.
If you'd like to help translate LibreChat into your language, we'd love your contribution! Improving our translations not only makes LibreChat more accessible to users around the world but also enhances the overall user experience. Please check out our [Translation Guide](https://www.librechat.ai/docs/translation).
---
## Star History
## 💖 This project exists in its current state thanks to all the people who contribute
<a href="https://star-history.com/#danny-avila/LibreChat&Date">
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date&theme=dark" onerror="this.src='https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date'" />
</a>
---
## Sponsors
Sponsored by <a href="https://github.com/mjtechguy"><b>@mjtechguy</b></a>, <a href="https://github.com/SphaeroX"><b>@SphaeroX</b></a>, <a href="https://github.com/DavidDev1334"><b>@DavidDev1334</b></a>, <a href="https://github.com/fuegovic"><b>@fuegovic</b></a>, <a href="https://github.com/Pharrcyde"><b>@Pharrcyde</b></a>
---
## Contributors
Contributions and suggestions bug reports and fixes are welcome!
Please read the documentation before you do!
---
For new features, components, or extensions, please open an issue and discuss before sending a PR.
- Join the [Discord community](https://discord.gg/uDyZ5Tzhct)
This project exists in its current state thanks to all the people who contribute
---
<a href="https://github.com/danny-avila/LibreChat/graphs/contributors">
<img src="https://contrib.rocks/image?repo=danny-avila/LibreChat" />
</a>
---
## 🎉 Special Thanks
We thank [Locize](https://locize.com) for their translation management tools that support multiple languages in LibreChat.
<p align="center">
<a href="https://locize.com" target="_blank" rel="noopener noreferrer">
<img src="https://locize.com/img/locize_color.svg" alt="Locize Logo" height="50">
</a>
</p>

View File

@@ -1,113 +0,0 @@
require('dotenv').config();
const { KeyvFile } = require('keyv-file');
const { getUserKey, checkUserKeyExpiry } = require('../server/services/UserService');
const askBing = async ({
text,
parentMessageId,
conversationId,
jailbreak,
jailbreakConversationId,
context,
systemMessage,
conversationSignature,
clientId,
invocationId,
toneStyle,
key: expiresAt,
onProgress,
userId,
}) => {
const isUserProvided = process.env.BINGAI_TOKEN === 'user_provided';
let key = null;
if (expiresAt && isUserProvided) {
checkUserKeyExpiry(
expiresAt,
'Your BingAI Cookies have expired. Please provide your cookies again.',
);
key = await getUserKey({ userId, name: 'bingAI' });
}
const { BingAIClient } = await import('nodejs-gpt');
const store = {
store: new KeyvFile({ filename: './data/cache.json' }),
};
const bingAIClient = new BingAIClient({
// "_U" cookie from bing.com
// userToken:
// isUserProvided ? key : process.env.BINGAI_TOKEN ?? null,
// If the above doesn't work, provide all your cookies as a string instead
cookies: isUserProvided ? key : process.env.BINGAI_TOKEN ?? null,
debug: false,
cache: store,
host: process.env.BINGAI_HOST || null,
proxy: process.env.PROXY || null,
});
let options = {};
if (jailbreakConversationId == 'false') {
jailbreakConversationId = false;
}
if (jailbreak) {
options = {
jailbreakConversationId: jailbreakConversationId || jailbreak,
context,
systemMessage,
parentMessageId,
toneStyle,
onProgress,
clientOptions: {
features: {
genImage: {
server: {
enable: true,
type: 'markdown_list',
},
},
},
},
};
} else {
options = {
conversationId,
context,
systemMessage,
parentMessageId,
toneStyle,
onProgress,
clientOptions: {
features: {
genImage: {
server: {
enable: true,
type: 'markdown_list',
},
},
},
},
};
// don't give those parameters for new conversation
// for new conversation, conversationSignature always is null
if (conversationSignature) {
options.encryptedConversationSignature = conversationSignature;
options.clientId = clientId;
options.invocationId = invocationId;
}
}
console.log('bing options', options);
const res = await bingAIClient.sendMessage(text, options);
return res;
// for reference:
// https://github.com/waylaidwanderer/node-chatgpt-api/blob/main/demos/use-bing-client.js
};
module.exports = { askBing };

View File

@@ -1,59 +0,0 @@
require('dotenv').config();
const { KeyvFile } = require('keyv-file');
const { getUserKey, checkUserKeyExpiry } = require('../server/services/UserService');
const browserClient = async ({
text,
parentMessageId,
conversationId,
model,
key: expiresAt,
onProgress,
onEventMessage,
abortController,
userId,
}) => {
const isUserProvided = process.env.CHATGPT_TOKEN === 'user_provided';
let key = null;
if (expiresAt && isUserProvided) {
checkUserKeyExpiry(
expiresAt,
'Your ChatGPT Access Token has expired. Please provide your token again.',
);
key = await getUserKey({ userId, name: 'chatGPTBrowser' });
}
const { ChatGPTBrowserClient } = await import('nodejs-gpt');
const store = {
store: new KeyvFile({ filename: './data/cache.json' }),
};
const clientOptions = {
// Warning: This will expose your access token to a third party. Consider the risks before using this.
reverseProxyUrl:
process.env.CHATGPT_REVERSE_PROXY ?? 'https://ai.fakeopen.com/api/conversation',
// Access token from https://chat.openai.com/api/auth/session
accessToken: isUserProvided ? key : process.env.CHATGPT_TOKEN ?? null,
model: model,
debug: false,
proxy: process.env.PROXY ?? null,
user: userId,
};
const client = new ChatGPTBrowserClient(clientOptions, store);
let options = { onProgress, onEventMessage, abortController };
if (!!parentMessageId && !!conversationId) {
options = { ...options, parentMessageId, conversationId };
}
if (parentMessageId === '00000000-0000-0000-0000-000000000000') {
delete options.conversationId;
}
const res = await client.sendMessage(text, options);
return res;
};
module.exports = { browserClient };

View File

@@ -1,21 +1,90 @@
// const { Agent, ProxyAgent } = require('undici');
const BaseClient = require('./BaseClient');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const Anthropic = require('@anthropic-ai/sdk');
const { HttpsProxyAgent } = require('https-proxy-agent');
const {
Constants,
EModelEndpoint,
anthropicSettings,
getResponseSender,
validateVisionModel,
} = require('librechat-data-provider');
const { SplitStreamHandler: _Handler, GraphEvents } = require('@librechat/agents');
const {
truncateText,
formatMessage,
addCacheControl,
titleFunctionPrompt,
parseParamFromPrompt,
createContextHandlers,
} = require('./prompts');
const {
getClaudeHeaders,
configureReasoning,
checkPromptCacheSupport,
} = require('~/server/services/Endpoints/anthropic/helpers');
const { getModelMaxTokens, getModelMaxOutputTokens, matchModelName } = require('~/utils');
const { spendTokens, spendStructuredTokens } = require('~/models/spendTokens');
const { encodeAndFormat } = require('~/server/services/Files/images/encode');
const Tokenizer = require('~/server/services/Tokenizer');
const { logger, sendEvent } = require('~/config');
const { sleep } = require('~/server/utils');
const BaseClient = require('./BaseClient');
const HUMAN_PROMPT = '\n\nHuman:';
const AI_PROMPT = '\n\nAssistant:';
const tokenizersCache = {};
class SplitStreamHandler extends _Handler {
getDeltaContent(chunk) {
return (chunk?.delta?.text ?? chunk?.completion) || '';
}
getReasoningDelta(chunk) {
return chunk?.delta?.thinking || '';
}
}
/** Helper function to introduce a delay before retrying */
function delayBeforeRetry(attempts, baseDelay = 1000) {
return new Promise((resolve) => setTimeout(resolve, baseDelay * attempts));
}
const tokenEventTypes = new Set(['message_start', 'message_delta']);
const { legacy } = anthropicSettings;
class AnthropicClient extends BaseClient {
constructor(apiKey, options = {}, cacheOptions = {}) {
super(apiKey, options, cacheOptions);
constructor(apiKey, options = {}) {
super(apiKey, options);
this.apiKey = apiKey || process.env.ANTHROPIC_API_KEY;
this.sender = 'Anthropic';
this.userLabel = HUMAN_PROMPT;
this.assistantLabel = AI_PROMPT;
this.contextStrategy = options.contextStrategy
? options.contextStrategy.toLowerCase()
: 'discard';
this.setOptions(options);
/** @type {string | undefined} */
this.systemMessage;
/** @type {AnthropicMessageStartEvent| undefined} */
this.message_start;
/** @type {AnthropicMessageDeltaEvent| undefined} */
this.message_delta;
/** Whether the model is part of the Claude 3 Family
* @type {boolean} */
this.isClaude3;
/** Whether to use Messages API or Completions API
* @type {boolean} */
this.useMessages;
/** Whether or not the model is limited to the legacy amount of output tokens
* @type {boolean} */
this.isLegacyOutput;
/** Whether or not the model supports Prompt Caching
* @type {boolean} */
this.supportsCacheControl;
/** The key for the usage object's input tokens
* @type {string} */
this.inputTokensKey = 'input_tokens';
/** The key for the usage object's output tokens
* @type {string} */
this.outputTokensKey = 'output_tokens';
/** @type {SplitStreamHandler | undefined} */
this.streamHandler;
}
setOptions(options) {
@@ -35,19 +104,46 @@ class AnthropicClient extends BaseClient {
this.options = options;
}
const modelOptions = this.options.modelOptions || {};
this.modelOptions = {
...modelOptions,
// set some good defaults (check for undefined in some cases because they may be 0)
model: modelOptions.model || 'claude-1',
temperature: typeof modelOptions.temperature === 'undefined' ? 0.7 : modelOptions.temperature, // 0 - 1, 0.7 is recommended
topP: typeof modelOptions.topP === 'undefined' ? 0.7 : modelOptions.topP, // 0 - 1, default: 0.7
topK: typeof modelOptions.topK === 'undefined' ? 40 : modelOptions.topK, // 1-40, default: 40
stop: modelOptions.stop, // no stop method for now
};
this.modelOptions = Object.assign(
{
model: anthropicSettings.model.default,
},
this.modelOptions,
this.options.modelOptions,
);
this.maxContextTokens = this.options.maxContextTokens || 99999;
this.maxResponseTokens = this.modelOptions.maxOutputTokens || 1500;
const modelMatch = matchModelName(this.modelOptions.model, EModelEndpoint.anthropic);
this.isClaude3 = modelMatch.includes('claude-3');
this.isLegacyOutput = !(
/claude-3[-.]5-sonnet/.test(modelMatch) || /claude-3[-.]7/.test(modelMatch)
);
this.supportsCacheControl = this.options.promptCache && checkPromptCacheSupport(modelMatch);
if (
this.isLegacyOutput &&
this.modelOptions.maxOutputTokens &&
this.modelOptions.maxOutputTokens > legacy.maxOutputTokens.default
) {
this.modelOptions.maxOutputTokens = legacy.maxOutputTokens.default;
}
this.useMessages = this.isClaude3 || !!this.options.attachments;
this.defaultVisionModel = this.options.visionModel ?? 'claude-3-sonnet-20240229';
this.options.attachments?.then((attachments) => this.checkVisionRequest(attachments));
this.maxContextTokens =
this.options.maxContextTokens ??
getModelMaxTokens(this.modelOptions.model, EModelEndpoint.anthropic) ??
100000;
this.maxResponseTokens =
this.modelOptions.maxOutputTokens ??
getModelMaxOutputTokens(
this.modelOptions.model,
this.options.endpointType ?? this.options.endpoint,
this.options.endpointTokenConfig,
) ??
anthropicSettings.maxOutputTokens.reset(this.modelOptions.model);
this.maxPromptTokens =
this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
@@ -59,35 +155,193 @@ class AnthropicClient extends BaseClient {
);
}
this.sender =
this.options.sender ??
getResponseSender({
model: this.modelOptions.model,
endpoint: EModelEndpoint.anthropic,
modelLabel: this.options.modelLabel,
});
this.startToken = '||>';
this.endToken = '';
this.gptEncoder = this.constructor.getTokenizer('cl100k_base');
if (!this.modelOptions.stop) {
const stopTokens = [this.startToken];
if (this.endToken && this.endToken !== this.startToken) {
stopTokens.push(this.endToken);
}
stopTokens.push(`${this.userLabel}`);
stopTokens.push('<|diff_marker|>');
this.modelOptions.stop = stopTokens;
}
return this;
}
getClient() {
if (this.options.reverseProxyUrl) {
return new Anthropic({
apiKey: this.apiKey,
baseURL: this.options.reverseProxyUrl,
});
} else {
return new Anthropic({
apiKey: this.apiKey,
});
/**
* Get the initialized Anthropic client.
* @param {Partial<Anthropic.ClientOptions>} requestOptions - The options for the client.
* @returns {Anthropic} The Anthropic client instance.
*/
getClient(requestOptions) {
/** @type {Anthropic.ClientOptions} */
const options = {
fetch: this.fetch,
apiKey: this.apiKey,
};
if (this.options.proxy) {
options.httpAgent = new HttpsProxyAgent(this.options.proxy);
}
if (this.options.reverseProxyUrl) {
options.baseURL = this.options.reverseProxyUrl;
}
const headers = getClaudeHeaders(requestOptions?.model, this.supportsCacheControl);
if (headers) {
options.defaultHeaders = headers;
}
return new Anthropic(options);
}
/**
* Get stream usage as returned by this client's API response.
* @returns {AnthropicStreamUsage} The stream usage object.
*/
getStreamUsage() {
const inputUsage = this.message_start?.message?.usage ?? {};
const outputUsage = this.message_delta?.usage ?? {};
return Object.assign({}, inputUsage, outputUsage);
}
/**
* Calculates the correct token count for the current user message based on the token count map and API usage.
* Edge case: If the calculation results in a negative value, it returns the original estimate.
* If revisiting a conversation with a chat history entirely composed of token estimates,
* the cumulative token count going forward should become more accurate as the conversation progresses.
* @param {Object} params - The parameters for the calculation.
* @param {Record<string, number>} params.tokenCountMap - A map of message IDs to their token counts.
* @param {string} params.currentMessageId - The ID of the current message to calculate.
* @param {AnthropicStreamUsage} params.usage - The usage object returned by the API.
* @returns {number} The correct token count for the current user message.
*/
calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage }) {
const originalEstimate = tokenCountMap[currentMessageId] || 0;
if (!usage || typeof usage.input_tokens !== 'number') {
return originalEstimate;
}
tokenCountMap[currentMessageId] = 0;
const totalTokensFromMap = Object.values(tokenCountMap).reduce((sum, count) => {
const numCount = Number(count);
return sum + (isNaN(numCount) ? 0 : numCount);
}, 0);
const totalInputTokens =
(usage.input_tokens ?? 0) +
(usage.cache_creation_input_tokens ?? 0) +
(usage.cache_read_input_tokens ?? 0);
const currentMessageTokens = totalInputTokens - totalTokensFromMap;
return currentMessageTokens > 0 ? currentMessageTokens : originalEstimate;
}
/**
* Get Token Count for LibreChat Message
* @param {TMessage} responseMessage
* @returns {number}
*/
getTokenCountForResponse(responseMessage) {
return this.getTokenCountForMessage({
role: 'assistant',
content: responseMessage.text,
});
}
/**
*
* Checks if the model is a vision model based on request attachments and sets the appropriate options:
* - Sets `this.modelOptions.model` to `gpt-4-vision-preview` if the request is a vision request.
* - Sets `this.isVisionModel` to `true` if vision request.
* - Deletes `this.modelOptions.stop` if vision request.
* @param {MongoFile[]} attachments
*/
checkVisionRequest(attachments) {
const availableModels = this.options.modelsConfig?.[EModelEndpoint.anthropic];
this.isVisionModel = validateVisionModel({ model: this.modelOptions.model, availableModels });
const visionModelAvailable = availableModels?.includes(this.defaultVisionModel);
if (
attachments &&
attachments.some((file) => file?.type && file?.type?.includes('image')) &&
visionModelAvailable &&
!this.isVisionModel
) {
this.modelOptions.model = this.defaultVisionModel;
this.isVisionModel = true;
}
}
/**
* Calculate the token cost in tokens for an image based on its dimensions and detail level.
*
* For reference, see: https://docs.anthropic.com/claude/docs/vision#image-costs
*
* @param {Object} image - The image object.
* @param {number} image.width - The width of the image.
* @param {number} image.height - The height of the image.
* @returns {number} The calculated token cost measured by tokens.
*
*/
calculateImageTokenCost({ width, height }) {
return Math.ceil((width * height) / 750);
}
async addImageURLs(message, attachments) {
const { files, image_urls } = await encodeAndFormat(
this.options.req,
attachments,
EModelEndpoint.anthropic,
);
message.image_urls = image_urls.length ? image_urls : undefined;
return files;
}
/**
* @param {object} params
* @param {number} params.promptTokens
* @param {number} params.completionTokens
* @param {AnthropicStreamUsage} [params.usage]
* @param {string} [params.model]
* @param {string} [params.context='message']
* @returns {Promise<void>}
*/
async recordTokenUsage({ promptTokens, completionTokens, usage, model, context = 'message' }) {
if (usage != null && usage?.input_tokens != null) {
const input = usage.input_tokens ?? 0;
const write = usage.cache_creation_input_tokens ?? 0;
const read = usage.cache_read_input_tokens ?? 0;
await spendStructuredTokens(
{
context,
user: this.user,
conversationId: this.conversationId,
model: model ?? this.modelOptions.model,
endpointTokenConfig: this.options.endpointTokenConfig,
},
{
promptTokens: { input, write, read },
completionTokens,
},
);
return;
}
await spendTokens(
{
context,
user: this.user,
conversationId: this.conversationId,
model: model ?? this.modelOptions.model,
endpointTokenConfig: this.options.endpointTokenConfig,
},
{ promptTokens, completionTokens },
);
}
async buildMessages(messages, parentMessageId) {
@@ -95,32 +349,148 @@ class AnthropicClient extends BaseClient {
messages,
parentMessageId,
});
if (this.options.debug) {
console.debug('AnthropicClient: orderedMessages', orderedMessages, parentMessageId);
logger.debug('[AnthropicClient] orderedMessages', { orderedMessages, parentMessageId });
if (this.options.attachments) {
const attachments = await this.options.attachments;
const images = attachments.filter((file) => file.type.includes('image'));
if (images.length && !this.isVisionModel) {
throw new Error('Images are only supported with the Claude 3 family of models');
}
const latestMessage = orderedMessages[orderedMessages.length - 1];
if (this.message_file_map) {
this.message_file_map[latestMessage.messageId] = attachments;
} else {
this.message_file_map = {
[latestMessage.messageId]: attachments,
};
}
const files = await this.addImageURLs(latestMessage, attachments);
this.options.attachments = files;
}
const formattedMessages = orderedMessages.map((message) => ({
author: message.isCreatedByUser ? this.userLabel : this.assistantLabel,
content: message?.content ?? message.text,
}));
if (this.message_file_map) {
this.contextHandlers = createContextHandlers(
this.options.req,
orderedMessages[orderedMessages.length - 1].text,
);
}
const formattedMessages = orderedMessages.map((message, i) => {
const formattedMessage = this.useMessages
? formatMessage({
message,
endpoint: EModelEndpoint.anthropic,
})
: {
author: message.isCreatedByUser ? this.userLabel : this.assistantLabel,
content: message?.content ?? message.text,
};
const needsTokenCount = this.contextStrategy && !orderedMessages[i].tokenCount;
/* If tokens were never counted, or, is a Vision request and the message has files, count again */
if (needsTokenCount || (this.isVisionModel && (message.image_urls || message.files))) {
orderedMessages[i].tokenCount = this.getTokenCountForMessage(formattedMessage);
}
/* If message has files, calculate image token cost */
if (this.message_file_map && this.message_file_map[message.messageId]) {
const attachments = this.message_file_map[message.messageId];
for (const file of attachments) {
if (file.embedded) {
this.contextHandlers?.processFile(file);
continue;
}
orderedMessages[i].tokenCount += this.calculateImageTokenCost({
width: file.width,
height: file.height,
});
}
}
formattedMessage.tokenCount = orderedMessages[i].tokenCount;
return formattedMessage;
});
if (this.contextHandlers) {
this.augmentedPrompt = await this.contextHandlers.createContext();
this.options.promptPrefix = this.augmentedPrompt + (this.options.promptPrefix ?? '');
}
let { context: messagesInWindow, remainingContextTokens } =
await this.getMessagesWithinTokenLimit({ messages: formattedMessages });
const tokenCountMap = orderedMessages
.slice(orderedMessages.length - messagesInWindow.length)
.reduce((map, message, index) => {
const { messageId } = message;
if (!messageId) {
return map;
}
map[messageId] = orderedMessages[index].tokenCount;
return map;
}, {});
logger.debug('[AnthropicClient]', {
messagesInWindow: messagesInWindow.length,
remainingContextTokens,
});
let lastAuthor = '';
let groupedMessages = [];
for (let message of formattedMessages) {
for (let i = 0; i < messagesInWindow.length; i++) {
const message = messagesInWindow[i];
const author = message.role ?? message.author;
// If last author is not same as current author, add to new group
if (lastAuthor !== message.author) {
groupedMessages.push({
author: message.author,
if (lastAuthor !== author) {
const newMessage = {
content: [message.content],
});
lastAuthor = message.author;
};
if (message.role) {
newMessage.role = message.role;
} else {
newMessage.author = message.author;
}
groupedMessages.push(newMessage);
lastAuthor = author;
// If same author, append content to the last group
} else {
groupedMessages[groupedMessages.length - 1].content.push(message.content);
}
}
groupedMessages = groupedMessages.map((msg, i) => {
const isLast = i === groupedMessages.length - 1;
if (msg.content.length === 1) {
const content = msg.content[0];
return {
...msg,
// reason: final assistant content cannot end with trailing whitespace
content:
isLast && this.useMessages && msg.role === 'assistant' && typeof content === 'string'
? content?.trim()
: content,
};
}
if (!this.useMessages && msg.tokenCount) {
delete msg.tokenCount;
}
return msg;
});
let identityPrefix = '';
if (this.options.userLabel) {
identityPrefix = `\nHuman's name: ${this.options.userLabel}`;
@@ -130,7 +500,10 @@ class AnthropicClient extends BaseClient {
identityPrefix = `${identityPrefix}\nYou are ${this.options.modelLabel}`;
}
let promptPrefix = (this.options.promptPrefix || '').trim();
let promptPrefix = (this.options.promptPrefix ?? '').trim();
if (typeof this.options.artifactsPrompt === 'string' && this.options.artifactsPrompt) {
promptPrefix = `${promptPrefix ?? ''}\n${this.options.artifactsPrompt}`.trim();
}
if (promptPrefix) {
// If the prompt prefix doesn't end with the end token, add it.
if (!promptPrefix.endsWith(`${this.endToken}`)) {
@@ -146,9 +519,10 @@ class AnthropicClient extends BaseClient {
// Prompt AI to respond, empty if last message was from AI
let isEdited = lastAuthor === this.assistantLabel;
const promptSuffix = isEdited ? '' : `${promptPrefix}${this.assistantLabel}\n`;
let currentTokenCount = isEdited
? this.getTokenCount(promptPrefix)
: this.getTokenCount(promptSuffix);
let currentTokenCount =
isEdited || this.useMessages
? this.getTokenCount(promptPrefix)
: this.getTokenCount(promptSuffix);
let promptBody = '';
const maxTokenCount = this.maxPromptTokens;
@@ -216,7 +590,69 @@ class AnthropicClient extends BaseClient {
return true;
};
await buildPromptBody();
const messagesPayload = [];
const buildMessagesPayload = async () => {
let canContinue = true;
if (promptPrefix) {
this.systemMessage = promptPrefix;
}
while (currentTokenCount < maxTokenCount && groupedMessages.length > 0 && canContinue) {
const message = groupedMessages.pop();
let tokenCountForMessage = message.tokenCount ?? this.getTokenCountForMessage(message);
const newTokenCount = currentTokenCount + tokenCountForMessage;
const exceededMaxCount = newTokenCount > maxTokenCount;
if (exceededMaxCount && messagesPayload.length === 0) {
throw new Error(
`Prompt is too long. Max token count is ${maxTokenCount}, but prompt is ${newTokenCount} tokens long.`,
);
} else if (exceededMaxCount) {
canContinue = false;
break;
}
delete message.tokenCount;
messagesPayload.unshift(message);
currentTokenCount = newTokenCount;
// Switch off isEdited after using it once
if (isEdited && message.role === 'assistant') {
isEdited = false;
}
// Wait for next tick to avoid blocking the event loop
await new Promise((resolve) => setImmediate(resolve));
}
};
const processTokens = () => {
// Add 2 tokens for metadata after all messages have been counted.
currentTokenCount += 2;
// Use up to `this.maxContextTokens` tokens (prompt + response), but try to leave `this.maxTokens` tokens for the response.
this.modelOptions.maxOutputTokens = Math.min(
this.maxContextTokens - currentTokenCount,
this.maxResponseTokens,
);
};
if (this.modelOptions.model.includes('claude-3')) {
await buildMessagesPayload();
processTokens();
return {
prompt: messagesPayload,
context: messagesInWindow,
promptTokens: currentTokenCount,
tokenCountMap,
};
} else {
await buildPromptBody();
processTokens();
}
if (nextMessage.remove) {
promptBody = promptBody.replace(nextMessage.messageString, '');
@@ -226,20 +662,53 @@ class AnthropicClient extends BaseClient {
let prompt = `${promptBody}${promptSuffix}`;
// Add 2 tokens for metadata after all messages have been counted.
currentTokenCount += 2;
// Use up to `this.maxContextTokens` tokens (prompt + response), but try to leave `this.maxTokens` tokens for the response.
this.modelOptions.maxOutputTokens = Math.min(
this.maxContextTokens - currentTokenCount,
this.maxResponseTokens,
);
return { prompt, context };
return { prompt, context, promptTokens: currentTokenCount, tokenCountMap };
}
getCompletion() {
console.log('AnthropicClient doesn\'t use getCompletion (all handled in sendCompletion)');
logger.debug('AnthropicClient doesn\'t use getCompletion (all handled in sendCompletion)');
}
/**
* Creates a message or completion response using the Anthropic client.
* @param {Anthropic} client - The Anthropic client instance.
* @param {Anthropic.default.MessageCreateParams | Anthropic.default.CompletionCreateParams} options - The options for the message or completion.
* @param {boolean} useMessages - Whether to use messages or completions. Defaults to `this.useMessages`.
* @returns {Promise<Anthropic.default.Message | Anthropic.default.Completion>} The response from the Anthropic client.
*/
async createResponse(client, options, useMessages) {
return (useMessages ?? this.useMessages)
? await client.messages.create(options)
: await client.completions.create(options);
}
getMessageMapMethod() {
/**
* @param {TMessage} msg
*/
return (msg) => {
if (msg.text != null && msg.text && msg.text.startsWith(':::thinking')) {
msg.text = msg.text.replace(/:::thinking.*?:::/gs, '').trim();
}
return msg;
};
}
/**
* @param {string[]} [intermediateReply]
* @returns {string}
*/
getStreamText(intermediateReply) {
if (!this.streamHandler) {
return intermediateReply?.join('') ?? '';
}
const reasoningText = this.streamHandler.reasoningTokens.join('');
const reasoningBlock = reasoningText.length > 0 ? `:::thinking\n${reasoningText}\n:::\n` : '';
return `${reasoningBlock}${this.streamHandler.tokens.join('')}`;
}
async sendCompletion(payload, { onProgress, abortController }) {
@@ -254,19 +723,11 @@ class AnthropicClient extends BaseClient {
modelOptions.stream = true;
}
const { debug } = this.options;
if (debug) {
console.debug();
console.debug(modelOptions);
console.debug();
}
const client = this.getClient();
logger.debug('modelOptions', { modelOptions });
const metadata = {
user_id: this.user,
};
let text = '';
const {
stream,
model,
@@ -276,79 +737,237 @@ class AnthropicClient extends BaseClient {
topP: top_p,
topK: top_k,
} = this.modelOptions;
const requestOptions = {
prompt: payload,
let requestOptions = {
model,
stream: stream || true,
max_tokens_to_sample: maxOutputTokens || 1500,
stop_sequences,
temperature,
metadata,
top_p,
top_k,
};
if (this.options.debug) {
console.log('AnthropicClient: requestOptions');
console.dir(requestOptions, { depth: null });
}
const response = await client.completions.create(requestOptions);
signal.addEventListener('abort', () => {
if (this.options.debug) {
console.log('AnthropicClient: message aborted!');
if (!/claude-3[-.]7/.test(model)) {
if (top_p !== undefined) {
requestOptions.top_p = top_p;
}
response.controller.abort();
});
for await (const completion of response) {
if (this.options.debug) {
// Uncomment to debug message stream
// console.debug(completion);
if (top_k !== undefined) {
requestOptions.top_k = top_k;
}
text += completion.completion;
onProgress(completion.completion);
}
signal.removeEventListener('abort', () => {
if (this.options.debug) {
console.log('AnthropicClient: message aborted!');
}
response.controller.abort();
if (this.useMessages) {
requestOptions.messages = payload;
requestOptions.max_tokens =
maxOutputTokens || anthropicSettings.maxOutputTokens.reset(requestOptions.model);
} else {
requestOptions.prompt = payload;
requestOptions.max_tokens_to_sample = maxOutputTokens || legacy.maxOutputTokens.default;
}
requestOptions = configureReasoning(requestOptions, {
thinking: this.options.thinking,
thinkingBudget: this.options.thinkingBudget,
});
return text.trim();
if (this.systemMessage && this.supportsCacheControl === true) {
requestOptions.system = [
{
type: 'text',
text: this.systemMessage,
cache_control: { type: 'ephemeral' },
},
];
} else if (this.systemMessage) {
requestOptions.system = this.systemMessage;
}
if (this.supportsCacheControl === true && this.useMessages) {
requestOptions.messages = addCacheControl(requestOptions.messages);
}
logger.debug('[AnthropicClient]', { ...requestOptions });
this.streamHandler = new SplitStreamHandler({
accumulate: true,
runId: this.responseMessageId,
handlers: {
[GraphEvents.ON_RUN_STEP]: (event) => sendEvent(this.options.res, event),
[GraphEvents.ON_MESSAGE_DELTA]: (event) => sendEvent(this.options.res, event),
[GraphEvents.ON_REASONING_DELTA]: (event) => sendEvent(this.options.res, event),
},
});
let intermediateReply = this.streamHandler.tokens;
const maxRetries = 3;
const streamRate = this.options.streamRate ?? Constants.DEFAULT_STREAM_RATE;
async function processResponse() {
let attempts = 0;
while (attempts < maxRetries) {
let response;
try {
const client = this.getClient(requestOptions);
response = await this.createResponse(client, requestOptions);
signal.addEventListener('abort', () => {
logger.debug('[AnthropicClient] message aborted!');
if (response.controller?.abort) {
response.controller.abort();
}
});
for await (const completion of response) {
const type = completion?.type ?? '';
if (tokenEventTypes.has(type)) {
logger.debug(`[AnthropicClient] ${type}`, completion);
this[type] = completion;
}
this.streamHandler.handle(completion);
await sleep(streamRate);
}
break;
} catch (error) {
attempts += 1;
logger.warn(
`User: ${this.user} | Anthropic Request ${attempts} failed: ${error.message}`,
);
if (attempts < maxRetries) {
await delayBeforeRetry(attempts, 350);
} else if (this.streamHandler && this.streamHandler.reasoningTokens.length) {
return this.getStreamText();
} else if (intermediateReply.length > 0) {
return this.getStreamText(intermediateReply);
} else {
throw new Error(`Operation failed after ${maxRetries} attempts: ${error.message}`);
}
} finally {
signal.removeEventListener('abort', () => {
logger.debug('[AnthropicClient] message aborted!');
if (response.controller?.abort) {
response.controller.abort();
}
});
}
}
}
await processResponse.bind(this)();
return this.getStreamText(intermediateReply);
}
getSaveOptions() {
return {
maxContextTokens: this.options.maxContextTokens,
artifacts: this.options.artifacts,
promptPrefix: this.options.promptPrefix,
modelLabel: this.options.modelLabel,
promptCache: this.options.promptCache,
thinking: this.options.thinking,
thinkingBudget: this.options.thinkingBudget,
resendFiles: this.options.resendFiles,
iconURL: this.options.iconURL,
greeting: this.options.greeting,
spec: this.options.spec,
...this.modelOptions,
};
}
getBuildMessagesOptions() {
if (this.options.debug) {
console.log('AnthropicClient doesn\'t use getBuildMessagesOptions');
}
logger.debug('AnthropicClient doesn\'t use getBuildMessagesOptions');
}
static getTokenizer(encoding, isModelName = false, extendSpecialTokens = {}) {
if (tokenizersCache[encoding]) {
return tokenizersCache[encoding];
}
let tokenizer;
if (isModelName) {
tokenizer = encodingForModel(encoding, extendSpecialTokens);
} else {
tokenizer = getEncoding(encoding, extendSpecialTokens);
}
tokenizersCache[encoding] = tokenizer;
return tokenizer;
getEncoding() {
return 'cl100k_base';
}
/**
* Returns the token count of a given text. It also checks and resets the tokenizers if necessary.
* @param {string} text - The text to get the token count for.
* @returns {number} The token count of the given text.
*/
getTokenCount(text) {
return this.gptEncoder.encode(text, 'all').length;
const encoding = this.getEncoding();
return Tokenizer.getTokenCount(text, encoding);
}
/**
* Generates a concise title for a conversation based on the user's input text and response.
* Involves sending a chat completion request with specific instructions for title generation.
*
* This function capitlizes on [Anthropic's function calling training](https://docs.anthropic.com/claude/docs/functions-external-tools).
*
* @param {Object} params - The parameters for the conversation title generation.
* @param {string} params.text - The user's input.
* @param {string} [params.responseText=''] - The AI's immediate response to the user.
*
* @returns {Promise<string | 'New Chat'>} A promise that resolves to the generated conversation title.
* In case of failure, it will return the default title, "New Chat".
*/
async titleConvo({ text, responseText = '' }) {
let title = 'New Chat';
this.message_delta = undefined;
this.message_start = undefined;
const convo = `<initial_message>
${truncateText(text)}
</initial_message>
<response>
${JSON.stringify(truncateText(responseText))}
</response>`;
const { ANTHROPIC_TITLE_MODEL } = process.env ?? {};
const model = this.options.titleModel ?? ANTHROPIC_TITLE_MODEL ?? 'claude-3-haiku-20240307';
const system = titleFunctionPrompt;
const titleChatCompletion = async () => {
const content = `<conversation_context>
${convo}
</conversation_context>
Please generate a title for this conversation.`;
const titleMessage = { role: 'user', content };
const requestOptions = {
model,
temperature: 0.3,
max_tokens: 1024,
system,
stop_sequences: ['\n\nHuman:', '\n\nAssistant', '</function_calls>'],
messages: [titleMessage],
};
try {
const response = await this.createResponse(
this.getClient(requestOptions),
requestOptions,
true,
);
let promptTokens = response?.usage?.input_tokens;
let completionTokens = response?.usage?.output_tokens;
if (!promptTokens) {
promptTokens = this.getTokenCountForMessage(titleMessage);
promptTokens += this.getTokenCountForMessage({ role: 'system', content: system });
}
if (!completionTokens) {
completionTokens = this.getTokenCountForMessage(response.content[0]);
}
await this.recordTokenUsage({
model,
promptTokens,
completionTokens,
context: 'title',
});
const text = response.content[0].text;
title = parseParamFromPrompt(text, 'title');
} catch (e) {
logger.error('[AnthropicClient] There was an issue generating the title', e);
}
};
await titleChatCompletion();
logger.debug('[AnthropicClient] Convo Title: ' + title);
return title;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,20 @@
const crypto = require('crypto');
const Keyv = require('keyv');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const crypto = require('crypto');
const { CohereClient } = require('cohere-ai');
const { fetchEventSource } = require('@waylaidwanderer/fetch-event-source');
const { Agent, ProxyAgent } = require('undici');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const {
ImageDetail,
EModelEndpoint,
resolveHeaders,
CohereConstants,
mapModelToAzureConfig,
} = require('librechat-data-provider');
const { extractBaseURL, constructAzureURL, genAzureChatCompletion } = require('~/utils');
const { createContextHandlers } = require('./prompts');
const { createCoherePayload } = require('./llm');
const BaseClient = require('./BaseClient');
const { logger } = require('~/config');
const CHATGPT_MODEL = 'gpt-3.5-turbo';
const tokenizersCache = {};
@@ -140,11 +151,13 @@ class ChatGPTClient extends BaseClient {
return tokenizer;
}
async getCompletion(input, onProgress, abortController = null) {
/** @type {getCompletion} */
async getCompletion(input, onProgress, onTokenProgress, abortController = null) {
if (!abortController) {
abortController = new AbortController();
}
const modelOptions = { ...this.modelOptions };
let modelOptions = { ...this.modelOptions };
if (typeof onProgress === 'function') {
modelOptions.stream = true;
}
@@ -159,50 +172,178 @@ class ChatGPTClient extends BaseClient {
}
const { debug } = this.options;
const url = this.completionsUrl;
let baseURL = this.completionsUrl;
if (debug) {
console.debug();
console.debug(url);
console.debug(baseURL);
console.debug(modelOptions);
console.debug();
}
const opts = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(modelOptions),
dispatcher: new Agent({
bodyTimeout: 0,
headersTimeout: 0,
}),
};
if (this.apiKey && this.options.azure) {
opts.headers['api-key'] = this.apiKey;
if (this.isVisionModel) {
modelOptions.max_tokens = 4000;
}
/** @type {TAzureConfig | undefined} */
const azureConfig = this.options?.req?.app?.locals?.[EModelEndpoint.azureOpenAI];
const isAzure = this.azure || this.options.azure;
if (
(isAzure && this.isVisionModel && azureConfig) ||
(azureConfig && this.isVisionModel && this.options.endpoint === EModelEndpoint.azureOpenAI)
) {
const { modelGroupMap, groupMap } = azureConfig;
const {
azureOptions,
baseURL,
headers = {},
serverless,
} = mapModelToAzureConfig({
modelName: modelOptions.model,
modelGroupMap,
groupMap,
});
opts.headers = resolveHeaders(headers);
this.langchainProxy = extractBaseURL(baseURL);
this.apiKey = azureOptions.azureOpenAIApiKey;
const groupName = modelGroupMap[modelOptions.model].group;
this.options.addParams = azureConfig.groupMap[groupName].addParams;
this.options.dropParams = azureConfig.groupMap[groupName].dropParams;
// Note: `forcePrompt` not re-assigned as only chat models are vision models
this.azure = !serverless && azureOptions;
this.azureEndpoint =
!serverless && genAzureChatCompletion(this.azure, modelOptions.model, this);
if (serverless === true) {
this.options.defaultQuery = azureOptions.azureOpenAIApiVersion
? { 'api-version': azureOptions.azureOpenAIApiVersion }
: undefined;
this.options.headers['api-key'] = this.apiKey;
}
}
if (this.options.defaultQuery) {
opts.defaultQuery = this.options.defaultQuery;
}
if (this.options.headers) {
opts.headers = { ...opts.headers, ...this.options.headers };
}
if (isAzure) {
// Azure does not accept `model` in the body, so we need to remove it.
delete modelOptions.model;
baseURL = this.langchainProxy
? constructAzureURL({
baseURL: this.langchainProxy,
azureOptions: this.azure,
})
: this.azureEndpoint.split(/(?<!\/)\/(chat|completion)\//)[0];
if (this.options.forcePrompt) {
baseURL += '/completions';
} else {
baseURL += '/chat/completions';
}
opts.defaultQuery = { 'api-version': this.azure.azureOpenAIApiVersion };
opts.headers = { ...opts.headers, 'api-key': this.apiKey };
} else if (this.apiKey) {
opts.headers.Authorization = `Bearer ${this.apiKey}`;
}
if (process.env.OPENAI_ORGANIZATION) {
opts.headers['OpenAI-Organization'] = process.env.OPENAI_ORGANIZATION;
}
if (this.useOpenRouter) {
opts.headers['HTTP-Referer'] = 'https://librechat.ai';
opts.headers['X-Title'] = 'LibreChat';
}
if (this.options.headers) {
opts.headers = { ...opts.headers, ...this.options.headers };
/* hacky fixes for Mistral AI API:
- Re-orders system message to the top of the messages payload, as not allowed anywhere else
- If there is only one message and it's a system message, change the role to user
*/
if (baseURL.includes('https://api.mistral.ai/v1') && modelOptions.messages) {
const { messages } = modelOptions;
const systemMessageIndex = messages.findIndex((msg) => msg.role === 'system');
if (systemMessageIndex > 0) {
const [systemMessage] = messages.splice(systemMessageIndex, 1);
messages.unshift(systemMessage);
}
modelOptions.messages = messages;
if (messages.length === 1 && messages[0].role === 'system') {
modelOptions.messages[0].role = 'user';
}
}
if (this.options.proxy) {
opts.dispatcher = new ProxyAgent(this.options.proxy);
if (this.options.addParams && typeof this.options.addParams === 'object') {
modelOptions = {
...modelOptions,
...this.options.addParams,
};
logger.debug('[ChatGPTClient] chatCompletion: added params', {
addParams: this.options.addParams,
modelOptions,
});
}
if (this.options.dropParams && Array.isArray(this.options.dropParams)) {
this.options.dropParams.forEach((param) => {
delete modelOptions[param];
});
logger.debug('[ChatGPTClient] chatCompletion: dropped params', {
dropParams: this.options.dropParams,
modelOptions,
});
}
if (baseURL.startsWith(CohereConstants.API_URL)) {
const payload = createCoherePayload({ modelOptions });
return await this.cohereChatCompletion({ payload, onTokenProgress });
}
if (baseURL.includes('v1') && !baseURL.includes('/completions') && !this.isChatCompletion) {
baseURL = baseURL.split('v1')[0] + 'v1/completions';
} else if (
baseURL.includes('v1') &&
!baseURL.includes('/chat/completions') &&
this.isChatCompletion
) {
baseURL = baseURL.split('v1')[0] + 'v1/chat/completions';
}
const BASE_URL = new URL(baseURL);
if (opts.defaultQuery) {
Object.entries(opts.defaultQuery).forEach(([key, value]) => {
BASE_URL.searchParams.append(key, value);
});
delete opts.defaultQuery;
}
const completionsURL = BASE_URL.toString();
opts.body = JSON.stringify(modelOptions);
if (modelOptions.stream) {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
try {
let done = false;
await fetchEventSource(url, {
await fetchEventSource(completionsURL, {
...opts,
signal: abortController.signal,
async onopen(response) {
@@ -230,7 +371,6 @@ class ChatGPTClient extends BaseClient {
// workaround for private API not sending [DONE] event
if (!done) {
onProgress('[DONE]');
abortController.abort();
resolve();
}
},
@@ -243,14 +383,13 @@ class ChatGPTClient extends BaseClient {
},
onmessage(message) {
if (debug) {
// console.debug(message);
console.debug(message);
}
if (!message.data || message.event === 'ping') {
return;
}
if (message.data === '[DONE]') {
onProgress('[DONE]');
abortController.abort();
resolve();
done = true;
return;
@@ -263,7 +402,7 @@ class ChatGPTClient extends BaseClient {
}
});
}
const response = await fetch(url, {
const response = await fetch(completionsURL, {
...opts,
signal: abortController.signal,
});
@@ -281,6 +420,43 @@ class ChatGPTClient extends BaseClient {
return response.json();
}
/** @type {cohereChatCompletion} */
async cohereChatCompletion({ payload, onTokenProgress }) {
const cohere = new CohereClient({
token: this.apiKey,
environment: this.completionsUrl,
});
if (!payload.stream) {
const chatResponse = await cohere.chat(payload);
return chatResponse.text;
}
const chatStream = await cohere.chatStream(payload);
let reply = '';
for await (const message of chatStream) {
if (!message) {
continue;
}
if (message.eventType === 'text-generation' && message.text) {
onTokenProgress(message.text);
reply += message.text;
}
/*
Cohere API Chinese Unicode character replacement hotfix.
Should be un-commented when the following issue is resolved:
https://github.com/cohere-ai/cohere-typescript/issues/151
else if (message.eventType === 'stream-end' && message.response) {
reply = message.response.text;
}
*/
}
return reply;
}
async generateTitle(userMessage, botMessage) {
const instructionsPayload = {
role: 'system',
@@ -439,26 +615,70 @@ ${botMessage.message}
async buildPrompt(messages, { isChatGptModel = false, promptPrefix = null }) {
promptPrefix = (promptPrefix || this.options.promptPrefix || '').trim();
// Handle attachments and create augmentedPrompt
if (this.options.attachments) {
const attachments = await this.options.attachments;
const lastMessage = messages[messages.length - 1];
if (this.message_file_map) {
this.message_file_map[lastMessage.messageId] = attachments;
} else {
this.message_file_map = {
[lastMessage.messageId]: attachments,
};
}
const files = await this.addImageURLs(lastMessage, attachments);
this.options.attachments = files;
this.contextHandlers = createContextHandlers(this.options.req, lastMessage.text);
}
if (this.message_file_map) {
this.contextHandlers = createContextHandlers(
this.options.req,
messages[messages.length - 1].text,
);
}
// Calculate image token cost and process embedded files
messages.forEach((message, i) => {
if (this.message_file_map && this.message_file_map[message.messageId]) {
const attachments = this.message_file_map[message.messageId];
for (const file of attachments) {
if (file.embedded) {
this.contextHandlers?.processFile(file);
continue;
}
messages[i].tokenCount =
(messages[i].tokenCount || 0) +
this.calculateImageTokenCost({
width: file.width,
height: file.height,
detail: this.options.imageDetail ?? ImageDetail.auto,
});
}
}
});
if (this.contextHandlers) {
this.augmentedPrompt = await this.contextHandlers.createContext();
promptPrefix = this.augmentedPrompt + promptPrefix;
}
if (promptPrefix) {
// If the prompt prefix doesn't end with the end token, add it.
if (!promptPrefix.endsWith(`${this.endToken}`)) {
promptPrefix = `${promptPrefix.trim()}${this.endToken}\n\n`;
}
promptPrefix = `${this.startToken}Instructions:\n${promptPrefix}`;
} else {
const currentDateString = new Date().toLocaleDateString('en-us', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
promptPrefix = `${this.startToken}Instructions:\nYou are ChatGPT, a large language model trained by OpenAI. Respond conversationally.\nCurrent date: ${currentDateString}${this.endToken}\n\n`;
}
const promptSuffix = `${this.startToken}${this.chatGptLabel}:\n`; // Prompt ChatGPT to respond.
const instructionsPayload = {
role: 'system',
name: 'instructions',
content: promptPrefix,
};
@@ -541,14 +761,10 @@ ${botMessage.message}
this.maxResponseTokens,
);
if (this.options.debug) {
console.debug(`Prompt : ${prompt}`);
}
if (isChatGptModel) {
return { prompt: [instructionsPayload, messagePayload], context };
}
return { prompt, context };
return { prompt, context, promptTokens: currentTokenCount };
}
getTokenCount(text) {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,161 @@
const { z } = require('zod');
const axios = require('axios');
const { Ollama } = require('ollama');
const { Constants } = require('librechat-data-provider');
const { deriveBaseURL, logAxiosError } = require('~/utils');
const { sleep } = require('~/server/utils');
const { logger } = require('~/config');
const ollamaPayloadSchema = z.object({
mirostat: z.number().optional(),
mirostat_eta: z.number().optional(),
mirostat_tau: z.number().optional(),
num_ctx: z.number().optional(),
repeat_last_n: z.number().optional(),
repeat_penalty: z.number().optional(),
temperature: z.number().optional(),
seed: z.number().nullable().optional(),
stop: z.array(z.string()).optional(),
tfs_z: z.number().optional(),
num_predict: z.number().optional(),
top_k: z.number().optional(),
top_p: z.number().optional(),
stream: z.optional(z.boolean()),
model: z.string(),
});
/**
* @param {string} imageUrl
* @returns {string}
* @throws {Error}
*/
const getValidBase64 = (imageUrl) => {
const parts = imageUrl.split(';base64,');
if (parts.length === 2) {
return parts[1];
} else {
logger.error('Invalid or no Base64 string found in URL.');
}
};
class OllamaClient {
constructor(options = {}) {
const host = deriveBaseURL(options.baseURL ?? 'http://localhost:11434');
this.streamRate = options.streamRate ?? Constants.DEFAULT_STREAM_RATE;
/** @type {Ollama} */
this.client = new Ollama({ host });
}
/**
* Fetches Ollama models from the specified base API path.
* @param {string} baseURL
* @returns {Promise<string[]>} The Ollama models.
*/
static async fetchModels(baseURL) {
let models = [];
if (!baseURL) {
return models;
}
try {
const ollamaEndpoint = deriveBaseURL(baseURL);
/** @type {Promise<AxiosResponse<OllamaListResponse>>} */
const response = await axios.get(`${ollamaEndpoint}/api/tags`, {
timeout: 5000,
});
models = response.data.models.map((tag) => tag.name);
return models;
} catch (error) {
const logMessage =
'Failed to fetch models from Ollama API. If you are not using Ollama directly, and instead, through some aggregator or reverse proxy that handles fetching via OpenAI spec, ensure the name of the endpoint doesn\'t start with `ollama` (case-insensitive).';
logAxiosError({ message: logMessage, error });
return [];
}
}
/**
* @param {ChatCompletionMessage[]} messages
* @returns {OllamaMessage[]}
*/
static formatOpenAIMessages(messages) {
const ollamaMessages = [];
for (const message of messages) {
if (typeof message.content === 'string') {
ollamaMessages.push({
role: message.role,
content: message.content,
});
continue;
}
let aggregatedText = '';
let imageUrls = [];
for (const content of message.content) {
if (content.type === 'text') {
aggregatedText += content.text + ' ';
} else if (content.type === 'image_url') {
imageUrls.push(getValidBase64(content.image_url.url));
}
}
const ollamaMessage = {
role: message.role,
content: aggregatedText.trim(),
};
if (imageUrls.length > 0) {
ollamaMessage.images = imageUrls;
}
ollamaMessages.push(ollamaMessage);
}
return ollamaMessages;
}
/***
* @param {Object} params
* @param {ChatCompletionPayload} params.payload
* @param {onTokenProgress} params.onProgress
* @param {AbortController} params.abortController
*/
async chatCompletion({ payload, onProgress, abortController = null }) {
let intermediateReply = '';
const parameters = ollamaPayloadSchema.parse(payload);
const messages = OllamaClient.formatOpenAIMessages(payload.messages);
if (parameters.stream) {
const stream = await this.client.chat({
messages,
...parameters,
});
for await (const chunk of stream) {
const token = chunk.message.content;
intermediateReply += token;
onProgress(token);
if (abortController.signal.aborted) {
stream.controller.abort();
break;
}
await sleep(this.streamRate);
}
}
// TODO: regular completion
else {
// const generation = await this.client.generate(payload);
}
return intermediateReply;
}
catch(err) {
logger.error('[OllamaClient.chatCompletion]', err);
throw err;
}
}
module.exports = { OllamaClient, ollamaPayloadSchema };

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,16 @@
const OpenAIClient = require('./OpenAIClient');
const { CallbackManager } = require('langchain/callbacks');
const { CallbackManager } = require('@langchain/core/callbacks/manager');
const { BufferMemory, ChatMessageHistory } = require('langchain/memory');
const { initializeCustomAgent, initializeFunctionsAgent } = require('./agents');
const { addImages, buildErrorInput, buildPromptPrefix } = require('./output_parsers');
const checkBalance = require('../../models/checkBalance');
const { initializeCustomAgent, initializeFunctionsAgent } = require('./agents');
const { processFileURL } = require('~/server/services/Files/process');
const { EModelEndpoint } = require('librechat-data-provider');
const { formatLangChainMessages } = require('./prompts');
const { isEnabled } = require('../../server/utils');
const { extractBaseURL } = require('../../utils');
const { SelfReflectionTool } = require('./tools');
const checkBalance = require('~/models/checkBalance');
const { isEnabled } = require('~/server/utils');
const { extractBaseURL } = require('~/utils');
const { loadTools } = require('./tools/util');
const { logger } = require('~/config');
class PluginsClient extends OpenAIClient {
constructor(apiKey, options = {}) {
@@ -28,27 +30,25 @@ class PluginsClient extends OpenAIClient {
super.setOptions(options);
if (this.functionsAgent && this.agentOptions.model && !this.useOpenRouter) {
this.agentOptions.model = this.getFunctionModelName(this.agentOptions.model);
}
this.isGpt3 = this.modelOptions?.model?.includes('gpt-3');
if (this.options.reverseProxyUrl) {
this.langchainProxy = extractBaseURL(this.options.reverseProxyUrl);
!this.langchainProxy &&
console.warn(`The reverse proxy URL ${this.options.reverseProxyUrl} is not valid for Plugins.
The url must follow OpenAI specs, for example: https://localhost:8080/v1/chat/completions
If your reverse proxy is compatible to OpenAI specs in every other way, it may still work without plugins enabled.`);
}
}
getSaveOptions() {
return {
artifacts: this.options.artifacts,
chatGptLabel: this.options.chatGptLabel,
modelLabel: this.options.modelLabel,
promptPrefix: this.options.promptPrefix,
tools: this.options.tools,
...this.modelOptions,
agentOptions: this.agentOptions,
iconURL: this.options.iconURL,
greeting: this.options.greeting,
spec: this.options.spec,
};
}
@@ -57,7 +57,9 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
}
getFunctionModelName(input) {
if (input.includes('gpt-3.5-turbo')) {
if (/-(?!0314)\d{4}/.test(input)) {
return input;
} else if (input.includes('gpt-3.5-turbo')) {
return 'gpt-3.5-turbo';
} else if (input.includes('gpt-4')) {
return 'gpt-4';
@@ -86,17 +88,15 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
initialMessageCount: this.currentMessages.length + 1,
});
if (this.options.debug) {
console.debug(
`<-----Agent Model: ${model.modelName} | Temp: ${model.temperature} | Functions: ${this.functionsAgent}----->`,
);
}
logger.debug(
`[PluginsClient] Agent Model: ${model.modelName} | Temp: ${model.temperature} | Functions: ${this.functionsAgent}`,
);
// Map Messages to Langchain format
const pastMessages = formatLangChainMessages(this.currentMessages.slice(0, -1), {
userName: this.options?.name,
});
this.options.debug && console.debug('pastMessages: ', pastMessages);
logger.debug('[PluginsClient] pastMessages: ' + pastMessages.length);
// TODO: use readOnly memory, TokenBufferMemory? (both unavailable in LangChainJS)
const memory = new BufferMemory({
@@ -104,7 +104,7 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
chatHistory: new ChatMessageHistory(pastMessages),
});
this.tools = await loadTools({
const { loadedTools } = await loadTools({
user,
model,
tools: this.options.tools,
@@ -114,30 +114,29 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
signal: this.abortController.signal,
openAIApiKey: this.openAIApiKey,
conversationId: this.conversationId,
debug: this.options?.debug,
fileStrategy: this.options.req.app.locals.fileStrategy,
processFileURL,
message,
},
useSpecs: true,
});
if (this.tools.length > 0 && !this.functionsAgent) {
this.tools.push(new SelfReflectionTool({ message, isGpt3: false }));
} else if (this.tools.length === 0) {
if (loadedTools.length === 0) {
return;
}
if (this.options.debug) {
console.debug('Requested Tools');
console.debug(this.options.tools);
console.debug('Loaded Tools');
console.debug(this.tools.map((tool) => tool.name));
}
this.tools = loadedTools;
logger.debug('[PluginsClient] Requested Tools', this.options.tools);
logger.debug(
'[PluginsClient] Loaded Tools',
this.tools.map((tool) => tool.name),
);
const handleAction = (action, runId, callback = null) => {
this.saveLatestAction(action);
if (this.options.debug) {
console.debug('Latest Agent Action ', this.actions[this.actions.length - 1]);
}
logger.debug('[PluginsClient] Latest Agent Action ', this.actions[this.actions.length - 1]);
if (typeof callback === 'function') {
callback(action, runId);
@@ -146,14 +145,22 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
// initialize agent
const initializer = this.functionsAgent ? initializeFunctionsAgent : initializeCustomAgent;
let customInstructions = (this.options.promptPrefix ?? '').trim();
if (typeof this.options.artifactsPrompt === 'string' && this.options.artifactsPrompt) {
customInstructions = `${customInstructions ?? ''}\n${this.options.artifactsPrompt}`.trim();
}
this.executor = await initializer({
model,
signal,
pastMessages,
tools: this.tools,
currentDateString: this.currentDateString,
customInstructions,
verbose: this.options.debug,
returnIntermediateSteps: true,
customName: this.options.chatGptLabel,
currentDateString: this.currentDateString,
callbackManager: CallbackManager.fromHandlers({
async handleAgentAction(action, runId) {
handleAction(action, runId, onAgentAction);
@@ -166,9 +173,7 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
}),
});
if (this.options.debug) {
console.debug('Loaded agent.');
}
logger.debug('[PluginsClient] Loaded agent.');
}
async executorCall(message, { signal, stream, onToolStart, onToolEnd }) {
@@ -184,12 +189,10 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
});
const input = attempts > 1 ? errorInput : message;
if (this.options.debug) {
console.debug(`Attempt ${attempts} of ${maxAttempts}`);
}
logger.debug(`[PluginsClient] Attempt ${attempts} of ${maxAttempts}`);
if (this.options.debug && errorMessage.length > 0) {
console.debug('Caught error, input:', input);
if (errorMessage.length > 0) {
logger.debug('[PluginsClient] Caught error, input: ' + JSON.stringify(input));
}
try {
@@ -212,10 +215,10 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
]);
break; // Exit the loop if the function call is successful
} catch (err) {
console.error(err);
logger.error('[PluginsClient] executorCall error:', err);
if (attempts === maxAttempts) {
const { run } = this.runManager.getRunByConversationId(this.conversationId);
const defaultOutput = `Encountered an error while attempting to respond. Error: ${err.message}`;
const defaultOutput = `Encountered an error while attempting to respond: ${err.message}`;
this.result.output = run && run.error ? run.error : defaultOutput;
this.result.errorMessage = run && run.error ? run.error : err.message;
this.result.intermediateSteps = this.actions;
@@ -225,10 +228,20 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
}
}
/**
*
* @param {TMessage} responseMessage
* @param {Partial<TMessage>} saveOptions
* @param {string} user
* @returns
*/
async handleResponseMessage(responseMessage, saveOptions, user) {
const { output, errorMessage, ...result } = this.result;
this.options.debug &&
console.debug('[handleResponseMessage] Output:', { output, errorMessage, ...result });
logger.debug('[PluginsClient][handleResponseMessage] Output:', {
output,
errorMessage,
...result,
});
const { error } = responseMessage;
if (!error) {
responseMessage.tokenCount = this.getTokenCountForResponse(responseMessage);
@@ -240,22 +253,33 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
await this.recordTokenUsage(responseMessage);
}
await this.saveMessageToDatabase(responseMessage, saveOptions, user);
this.responsePromise = this.saveMessageToDatabase(responseMessage, saveOptions, user);
delete responseMessage.tokenCount;
return { ...responseMessage, ...result };
}
async sendMessage(message, opts = {}) {
/** @type {{ filteredTools: string[], includedTools: string[] }} */
const { filteredTools = [], includedTools = [] } = this.options.req.app.locals;
if (includedTools.length > 0) {
const tools = this.options.tools.filter((plugin) => includedTools.includes(plugin));
this.options.tools = tools;
} else {
const tools = this.options.tools.filter((plugin) => !filteredTools.includes(plugin));
this.options.tools = tools;
}
// If a message is edited, no tools can be used.
const completionMode = this.options.tools.length === 0 || opts.isEdited;
if (completionMode) {
this.setOptions(opts);
return super.sendMessage(message, opts);
}
this.options.debug && console.log('Plugins sendMessage', message, opts);
logger.debug('[PluginsClient] sendMessage', { userMessageText: message, opts });
const {
user,
isEdited,
conversationId,
responseMessageId,
saveOptions,
@@ -266,6 +290,14 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
onToolEnd,
} = await this.handleStartMethods(message, opts);
if (opts.progressCallback) {
opts.onProgress = opts.progressCallback.call(null, {
...(opts.progressOptions ?? {}),
parentMessageId: userMessage.messageId,
messageId: responseMessageId,
});
}
this.currentMessages.push(userMessage);
let {
@@ -282,10 +314,10 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
);
if (tokenCountMap) {
console.dir(tokenCountMap, { depth: null });
logger.debug('[PluginsClient] tokenCountMap', { tokenCountMap });
if (tokenCountMap[userMessage.messageId]) {
userMessage.tokenCount = tokenCountMap[userMessage.messageId];
console.log('userMessage.tokenCount', userMessage.tokenCount);
logger.debug('[PluginsClient] userMessage.tokenCount', userMessage.tokenCount);
}
this.handleTokenCountMap(tokenCountMap);
}
@@ -294,7 +326,15 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
if (payload) {
this.currentMessages = payload;
}
await this.saveMessageToDatabase(userMessage, saveOptions, user);
if (!this.skipSaveUserMessage) {
this.userMessagePromise = this.saveMessageToDatabase(userMessage, saveOptions, user);
if (typeof opts?.getReqData === 'function') {
opts.getReqData({
userMessagePromise: this.userMessagePromise,
});
}
}
if (isEnabled(process.env.CHECK_BALANCE)) {
await checkBalance({
@@ -306,16 +346,18 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
amount: promptTokens,
debug: this.options.debug,
model: this.modelOptions.model,
endpoint: EModelEndpoint.openAI,
},
});
}
const responseMessage = {
endpoint: EModelEndpoint.gptPlugins,
iconURL: this.options.iconURL,
messageId: responseMessageId,
conversationId,
parentMessageId: userMessage.messageId,
isCreatedByUser: false,
isEdited,
model: this.modelOptions.model,
sender: this.sender,
promptTokens,
@@ -370,10 +412,7 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
return await this.handleResponseMessage(responseMessage, saveOptions, user);
}
if (this.options.debug) {
console.debug('Plugins completion phase: this.result');
console.debug(this.result);
}
logger.debug('[PluginsClient] Completion phase: this.result', this.result);
const promptPrefix = buildPromptPrefix({
result: this.result,
@@ -381,28 +420,20 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
functionsAgent: this.functionsAgent,
});
if (this.options.debug) {
console.debug('Plugins: promptPrefix');
console.debug(promptPrefix);
}
logger.debug('[PluginsClient]', { promptPrefix });
payload = await this.buildCompletionPrompt({
messages: this.currentMessages,
promptPrefix,
});
if (this.options.debug) {
console.debug('buildCompletionPrompt Payload');
console.debug(payload);
}
logger.debug('[PluginsClient] buildCompletionPrompt Payload', payload);
responseMessage.text = await this.sendCompletion(payload, opts);
return await this.handleResponseMessage(responseMessage, saveOptions, user);
}
async buildCompletionPrompt({ messages, promptPrefix: _promptPrefix }) {
if (this.options.debug) {
console.debug('buildCompletionPrompt messages', messages);
}
logger.debug('[PluginsClient] buildCompletionPrompt messages', messages);
const orderedMessages = messages;
let promptPrefix = _promptPrefix.trim();
@@ -415,7 +446,6 @@ If your reverse proxy is compatible to OpenAI specs in every other way, it may s
const instructionsPayload = {
role: 'system',
name: 'instructions',
content: promptPrefix,
};

View File

@@ -1,4 +1,5 @@
const { Readable } = require('stream');
const { logger } = require('~/config');
class TextStream extends Readable {
constructor(text, options = {}) {
@@ -38,7 +39,7 @@ class TextStream extends Readable {
});
this.on('end', () => {
// console.log('Stream ended');
// logger.debug('[processTextStream] Stream ended');
resolve();
});
@@ -50,7 +51,7 @@ class TextStream extends Readable {
try {
await streamPromise;
} catch (err) {
console.error('Error processing text stream:', err);
logger.error('[processTextStream] Error in text stream:', err);
// Handle the error appropriately, e.g., return an error message or throw an error
}
}

View File

@@ -1,5 +1,5 @@
const { ZeroShotAgent } = require('langchain/agents');
const { PromptTemplate, renderTemplate } = require('langchain/prompts');
const { PromptTemplate, renderTemplate } = require('@langchain/core/prompts');
const { gpt3, gpt4 } = require('./instructions');
class CustomAgent extends ZeroShotAgent {

View File

@@ -7,16 +7,24 @@ const {
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
} = require('langchain/prompts');
} = require('@langchain/core/prompts');
const initializeCustomAgent = async ({
tools,
model,
pastMessages,
customName,
customInstructions,
currentDateString,
...rest
}) => {
let prompt = CustomAgent.createPrompt(tools, { currentDateString, model: model.modelName });
if (customName) {
prompt = `You are "${customName}".\n${prompt}`;
}
if (customInstructions) {
prompt = `${prompt}\n${customInstructions}`;
}
const chatPrompt = ChatPromptTemplate.fromMessages([
new SystemMessagePromptTemplate(prompt),

View File

@@ -1,44 +1,3 @@
/*
module.exports = `You are ChatGPT, a Large Language model with useful tools.
Talk to the human and provide meaningful answers when questions are asked.
Use the tools when you need them, but use your own knowledge if you are confident of the answer. Keep answers short and concise.
A tool is not usually needed for creative requests, so do your best to answer them without tools.
Avoid repeating identical answers if it appears before. Only fulfill the human's requests, do not create extra steps beyond what the human has asked for.
Your input for 'Action' should be the name of tool used only.
Be honest. If you can't answer something, or a tool is not appropriate, say you don't know or answer to the best of your ability.
Attempt to fulfill the human's requests in as few actions as possible`;
*/
// module.exports = `You are ChatGPT, a highly knowledgeable and versatile large language model.
// Engage with the Human conversationally, providing concise and meaningful answers to questions. Utilize built-in tools when necessary, except for creative requests, where relying on your own knowledge is preferred. Aim for variety and avoid repetitive answers.
// For your 'Action' input, state the name of the tool used only, and honor user requests without adding extra steps. Always be honest; if you cannot provide an appropriate answer or tool, admit that or do your best.
// Strive to meet the user's needs efficiently with minimal actions.`;
// import {
// BasePromptTemplate,
// BaseStringPromptTemplate,
// SerializedBasePromptTemplate,
// renderTemplate,
// } from "langchain/prompts";
// prefix: `You are ChatGPT, a highly knowledgeable and versatile large language model.
// Your objective is to help users by understanding their intent and choosing the best action. Prioritize direct, specific responses. Use concise, varied answers and rely on your knowledge for creative tasks. Utilize tools when needed, and structure results for machine compatibility.
// prefix: `Objective: to comprehend human intentions based on user input and available tools. Goal: identify the best action to directly address the human's query. In your subsequent steps, you will utilize the chosen action. You may select multiple actions and list them in a meaningful order. Prioritize actions that directly relate to the user's query over general ones. Ensure that the generated thought is highly specific and explicit to best match the user's expectations. Construct the result in a manner that an online open-API would most likely expect. Provide concise and meaningful answers to human queries. Utilize tools when necessary. Relying on your own knowledge is preferred for creative requests. Aim for variety and avoid repetitive answers.
// # Available Actions & Tools:
// N/A: no suitable action, use your own knowledge.`,
// suffix: `Remember, all your responses MUST adhere to the described format and only respond if the format is followed. Output exactly with the requested format, avoiding any other text as this will be parsed by a machine. Following 'Action:', provide only one of the actions listed above. If a tool is not necessary, deduce this quickly and finish your response. Honor the human's requests without adding extra steps. Carry out tasks in the sequence written by the human. Always be honest; if you cannot provide an appropriate answer or tool, do your best with your own knowledge. Strive to meet the user's needs efficiently with minimal actions.`;
module.exports = {
'gpt3-v1': {
prefix: `Objective: Understand human intentions using user input and available tools. Goal: Identify the most suitable actions to directly address user queries.

View File

@@ -1,4 +1,5 @@
const { ZeroShotAgentOutputParser } = require('langchain/agents');
const { logger } = require('~/config');
class CustomOutputParser extends ZeroShotAgentOutputParser {
constructor(fields) {
@@ -64,9 +65,9 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
const match = this.actionValues.exec(text); // old v2
if (!match) {
console.log(
'\n\n<----------------------HIT NO MATCH PARSING ERROR---------------------->\n\n',
match,
logger.debug(
'\n\n<----------------------[CustomOutputParser] HIT NO MATCH PARSING ERROR---------------------->\n\n' +
match,
);
const thoughts = text.replace(/[tT]hought:/, '').split('\n');
// return {
@@ -84,9 +85,9 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
let selectedTool = match?.[1].trim().toLowerCase();
if (match && selectedTool === 'n/a') {
console.log(
'\n\n<----------------------HIT N/A PARSING ERROR---------------------->\n\n',
match,
logger.debug(
'\n\n<----------------------[CustomOutputParser] HIT N/A PARSING ERROR---------------------->\n\n' +
match,
);
return {
tool: 'self-reflection',
@@ -97,25 +98,25 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
let toolIsValid = this.checkIfValidTool(selectedTool);
if (match && !toolIsValid) {
console.log(
'\n\n<----------------Tool invalid: Re-assigning Selected Tool---------------->\n\n',
match,
logger.debug(
'\n\n<----------------[CustomOutputParser] Tool invalid: Re-assigning Selected Tool---------------->\n\n' +
match,
);
selectedTool = this.getValidTool(selectedTool);
}
if (match && !selectedTool) {
console.log(
'\n\n<----------------------HIT INVALID TOOL PARSING ERROR---------------------->\n\n',
match,
logger.debug(
'\n\n<----------------------[CustomOutputParser] HIT INVALID TOOL PARSING ERROR---------------------->\n\n' +
match,
);
selectedTool = 'self-reflection';
}
if (match && !match[2]) {
console.log(
'\n\n<----------------------HIT NO ACTION INPUT PARSING ERROR---------------------->\n\n',
match,
logger.debug(
'\n\n<----------------------[CustomOutputParser] HIT NO ACTION INPUT PARSING ERROR---------------------->\n\n' +
match,
);
// In case there is no action input, let's double-check if there is an action input in 'text' variable
@@ -139,7 +140,9 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
}
if (match && selectedTool.length > this.longestToolName.length) {
console.log('\n\n<----------------------HIT LONG PARSING ERROR---------------------->\n\n');
logger.debug(
'\n\n<----------------------[CustomOutputParser] HIT LONG PARSING ERROR---------------------->\n\n',
);
let action, input, thought;
let firstIndex = Infinity;
@@ -156,9 +159,9 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
// In case there is no action input, let's double-check if there is an action input in 'text' variable
const actionInputMatch = this.actionInputRegex.exec(text);
if (action && actionInputMatch) {
console.log(
'\n\n<------Matched Action Input in Long Parsing Error------>\n\n',
actionInputMatch,
logger.debug(
'\n\n<------[CustomOutputParser] Matched Action Input in Long Parsing Error------>\n\n' +
actionInputMatch,
);
return {
tool: action,
@@ -185,15 +188,14 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
const inputMatch = this.actionValues.exec(returnValues.log); //new
if (inputMatch) {
console.log('inputMatch');
console.dir(inputMatch, { depth: null });
logger.debug('[CustomOutputParser] inputMatch', inputMatch);
returnValues.toolInput = inputMatch[1].replaceAll('"', '').trim();
returnValues.log = returnValues.log.replace(this.actionValues, '');
}
return returnValues;
} else {
console.log('No valid tool mentioned.', this.tools, text);
logger.debug('[CustomOutputParser] No valid tool mentioned.', this.tools, text);
return {
tool: 'self-reflection',
toolInput: 'Hypothetical actions: \n"' + text + '"\n',
@@ -202,8 +204,8 @@ class CustomOutputParser extends ZeroShotAgentOutputParser {
}
// if (action && input) {
// console.log('Action:', action);
// console.log('Input:', input);
// logger.debug('Action:', action);
// logger.debug('Input:', input);
// }
}

View File

@@ -1,120 +0,0 @@
const { Agent } = require('langchain/agents');
const { LLMChain } = require('langchain/chains');
const { FunctionChatMessage, AIChatMessage } = require('langchain/schema');
const {
ChatPromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
} = require('langchain/prompts');
const PREFIX = 'You are a helpful AI assistant.';
function parseOutput(message) {
if (message.additional_kwargs.function_call) {
const function_call = message.additional_kwargs.function_call;
return {
tool: function_call.name,
toolInput: function_call.arguments ? JSON.parse(function_call.arguments) : {},
log: message.text,
};
} else {
return { returnValues: { output: message.text }, log: message.text };
}
}
class FunctionsAgent extends Agent {
constructor(input) {
super({ ...input, outputParser: undefined });
this.tools = input.tools;
}
lc_namespace = ['langchain', 'agents', 'openai'];
_agentType() {
return 'openai-functions';
}
observationPrefix() {
return 'Observation: ';
}
llmPrefix() {
return 'Thought:';
}
_stop() {
return ['Observation:'];
}
static createPrompt(_tools, fields) {
const { prefix = PREFIX, currentDateString } = fields || {};
return ChatPromptTemplate.fromMessages([
SystemMessagePromptTemplate.fromTemplate(`Date: ${currentDateString}\n${prefix}`),
new MessagesPlaceholder('chat_history'),
HumanMessagePromptTemplate.fromTemplate('Query: {input}'),
new MessagesPlaceholder('agent_scratchpad'),
]);
}
static fromLLMAndTools(llm, tools, args) {
FunctionsAgent.validateTools(tools);
const prompt = FunctionsAgent.createPrompt(tools, args);
const chain = new LLMChain({
prompt,
llm,
callbacks: args?.callbacks,
});
return new FunctionsAgent({
llmChain: chain,
allowedTools: tools.map((t) => t.name),
tools,
});
}
async constructScratchPad(steps) {
return steps.flatMap(({ action, observation }) => [
new AIChatMessage('', {
function_call: {
name: action.tool,
arguments: JSON.stringify(action.toolInput),
},
}),
new FunctionChatMessage(observation, action.tool),
]);
}
async plan(steps, inputs, callbackManager) {
// Add scratchpad and stop to inputs
const thoughts = await this.constructScratchPad(steps);
const newInputs = Object.assign({}, inputs, { agent_scratchpad: thoughts });
if (this._stop().length !== 0) {
newInputs.stop = this._stop();
}
// Split inputs between prompt and llm
const llm = this.llmChain.llm;
const valuesForPrompt = Object.assign({}, newInputs);
const valuesForLLM = {
tools: this.tools,
};
for (let i = 0; i < this.llmChain.llm.callKeys.length; i++) {
const key = this.llmChain.llm.callKeys[i];
if (key in inputs) {
valuesForLLM[key] = inputs[key];
delete valuesForPrompt[key];
}
}
const promptValue = await this.llmChain.prompt.formatPromptValue(valuesForPrompt);
const message = await llm.predictMessages(
promptValue.toChatMessages(),
valuesForLLM,
callbackManager,
);
console.log('message', message);
return parseOutput(message);
}
}
module.exports = FunctionsAgent;

View File

@@ -10,6 +10,8 @@ const initializeFunctionsAgent = async ({
tools,
model,
pastMessages,
customName,
customInstructions,
currentDateString,
...rest
}) => {
@@ -24,7 +26,13 @@ const initializeFunctionsAgent = async ({
returnMessages: true,
});
const prefix = addToolDescriptions(`Current Date: ${currentDateString}\n${PREFIX}`, tools);
let prefix = addToolDescriptions(`Current Date: ${currentDateString}\n${PREFIX}`, tools);
if (customName) {
prefix = `You are "${customName}".\n${prefix}`;
}
if (customInstructions) {
prefix = `${prefix}\n${customInstructions}`;
}
return await initializeAgentExecutorWithOptions(tools, model, {
agentType: 'openai-functions',

View File

@@ -1,7 +1,9 @@
const { promptTokensEstimate } = require('openai-chat-tokens');
const checkBalance = require('../../../models/checkBalance');
const { isEnabled } = require('../../../server/utils');
const { formatFromLangChain } = require('../prompts');
const { EModelEndpoint, supportsBalanceCheck } = require('librechat-data-provider');
const { formatFromLangChain } = require('~/app/clients/prompts');
const checkBalance = require('~/models/checkBalance');
const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');
const createStartHandler = ({
context,
@@ -15,9 +17,15 @@ const createStartHandler = ({
const { model, functions, function_call } = invocation_params;
const messages = _messages[0].map(formatFromLangChain);
if (manager.debug) {
console.log(`handleChatModelStart: ${context}`);
console.dir({ model, functions, function_call }, { depth: null });
logger.debug(`[createStartHandler] handleChatModelStart: ${context}`, {
model,
function_call,
});
if (context !== 'title') {
logger.debug(`[createStartHandler] handleChatModelStart: ${context}`, {
functions,
});
}
const payload = { messages };
@@ -34,13 +42,15 @@ const createStartHandler = ({
}
prelimPromptTokens += promptTokensEstimate(payload);
if (manager.debug) {
console.log('Prelim Prompt Tokens & Token Buffer', prelimPromptTokens, tokenBuffer);
}
logger.debug('[createStartHandler]', {
prelimPromptTokens,
tokenBuffer,
});
prelimPromptTokens += tokenBuffer;
try {
if (isEnabled(process.env.CHECK_BALANCE)) {
// TODO: if plugins extends to non-OpenAI models, this will need to be updated
if (isEnabled(process.env.CHECK_BALANCE) && supportsBalanceCheck[EModelEndpoint.openAI]) {
const generations =
initialMessageCount && messages.length > initialMessageCount
? messages.slice(initialMessageCount)
@@ -55,11 +65,12 @@ const createStartHandler = ({
debug: manager.debug,
generations,
model,
endpoint: EModelEndpoint.openAI,
},
});
}
} catch (err) {
console.error(`[${context}] checkBalance error`, err);
logger.error(`[createStartHandler][${context}] checkBalance error`, err);
manager.abortController.abort();
if (context === 'summary' || context === 'plugins') {
manager.addRun(runId, { conversationId, error: err.message });

View File

@@ -1,6 +1,7 @@
const { z } = require('zod');
const { langPrompt, createTitlePrompt, escapeBraces, getSnippet } = require('../prompts');
const { createStructuredOutputChainFromZod } = require('langchain/chains/openai_functions');
const { logger } = require('~/config');
const langSchema = z.object({
language: z.string().describe('The language of the input text (full noun, no abbreviations).'),
@@ -30,8 +31,7 @@ const runTitleChain = async ({ llm, text, convo, signal, callbacks }) => {
try {
snippet = getSnippet(text);
} catch (e) {
console.log('Error getting snippet of text for titleChain');
console.log(e);
logger.error('[runTitleChain] Error getting snippet of text for titleChain', e);
}
const languageChain = createLanguageChain({ llm, callbacks });
const titleChain = createTitleChain({ llm, callbacks, convo: escapeBraces(convo) });

View File

@@ -1,4 +1,4 @@
const { TokenTextSplitter } = require('langchain/text_splitter');
const { TokenTextSplitter } = require('@langchain/textsplitters');
/**
* Splits a given text by token chunks, based on the provided parameters for the TokenTextSplitter.

View File

@@ -12,7 +12,7 @@ describe('tokenSplit', () => {
returnSize: 5,
});
expect(result).toEqual(['. Null', ' Nullam', 'am id', ' id.', '.']);
expect(result).toEqual(['it.', '. Null', ' Nullam', 'am id', ' id.']);
});
it('returns correct text chunks with default parameters', async () => {

View File

@@ -1,5 +1,6 @@
const { createStartHandler } = require('../callbacks');
const spendTokens = require('../../../models/spendTokens');
const { createStartHandler } = require('~/app/clients/callbacks');
const { spendTokens } = require('~/models/spendTokens');
const { logger } = require('~/config');
class RunManager {
constructor(fields) {
@@ -35,7 +36,7 @@ class RunManager {
if (this.runs.has(runId)) {
this.runs.delete(runId);
} else {
console.error(`Run with ID ${runId} does not exist.`);
logger.error(`[api/app/clients/llm/RunManager] Run with ID ${runId} does not exist.`);
}
}
@@ -57,10 +58,19 @@ class RunManager {
{
handleChatModelStart: createStartHandler({ ...metadata, manager: this }),
handleLLMEnd: async (output, runId, _parentRunId) => {
if (this.debug) {
console.log(`handleLLMEnd: ${JSON.stringify(metadata)}`);
console.dir({ output, runId, _parentRunId }, { depth: null });
const { llmOutput, ..._output } = output;
logger.debug(`[RunManager] handleLLMEnd: ${JSON.stringify(metadata)}`, {
runId,
_parentRunId,
llmOutput,
});
if (metadata.context !== 'title') {
logger.debug('[RunManager] handleLLMEnd:', {
output: _output,
});
}
const { tokenUsage } = output.llmOutput;
const run = this.getRunById(runId);
this.removeRun(runId);
@@ -74,8 +84,7 @@ class RunManager {
await spendTokens(txData, tokenUsage);
},
handleLLMError: async (err) => {
this.debug && console.log(`handleLLMError: ${JSON.stringify(metadata)}`);
this.debug && console.error(err);
logger.error(`[RunManager] handleLLMError: ${JSON.stringify(metadata)}`, err);
if (metadata.context === 'title') {
return;
} else if (metadata.context === 'plugins') {

View File

@@ -0,0 +1,85 @@
const { CohereConstants } = require('librechat-data-provider');
const { titleInstruction } = require('../prompts/titlePrompts');
// Mapping OpenAI roles to Cohere roles
const roleMap = {
user: CohereConstants.ROLE_USER,
assistant: CohereConstants.ROLE_CHATBOT,
system: CohereConstants.ROLE_SYSTEM, // Recognize and map the system role explicitly
};
/**
* Adjusts an OpenAI ChatCompletionPayload to conform with Cohere's expected chat payload format.
* Now includes handling for "system" roles explicitly mentioned.
*
* @param {Object} options - Object containing the model options.
* @param {ChatCompletionPayload} options.modelOptions - The OpenAI model payload options.
* @returns {CohereChatStreamRequest} Cohere-compatible chat API payload.
*/
function createCoherePayload({ modelOptions }) {
/** @type {string | undefined} */
let preamble;
let latestUserMessageContent = '';
const {
stream,
stop,
top_p,
temperature,
frequency_penalty,
presence_penalty,
max_tokens,
messages,
model,
...rest
} = modelOptions;
// Filter out the latest user message and transform remaining messages to Cohere's chat_history format
let chatHistory = messages.reduce((acc, message, index, arr) => {
const isLastUserMessage = index === arr.length - 1 && message.role === 'user';
const messageContent =
typeof message.content === 'string'
? message.content
: message.content.map((part) => (part.type === 'text' ? part.text : '')).join(' ');
if (isLastUserMessage) {
latestUserMessageContent = messageContent;
} else {
acc.push({
role: roleMap[message.role] || CohereConstants.ROLE_USER,
message: messageContent,
});
}
return acc;
}, []);
if (
chatHistory.length === 1 &&
chatHistory[0].role === CohereConstants.ROLE_SYSTEM &&
!latestUserMessageContent.length
) {
const message = chatHistory[0].message;
latestUserMessageContent = message.includes(titleInstruction)
? CohereConstants.TITLE_MESSAGE
: '.';
preamble = message;
}
return {
message: latestUserMessageContent,
model: model,
chatHistory,
stream: stream ?? false,
temperature: temperature,
frequencyPenalty: frequency_penalty,
presencePenalty: presence_penalty,
maxTokens: max_tokens,
stopSequences: stop,
preamble,
p: top_p,
...rest,
};
}
module.exports = createCoherePayload;

View File

@@ -1,38 +1,6 @@
const { ChatOpenAI } = require('langchain/chat_models/openai');
const { sanitizeModelName } = require('../../../utils');
const { isEnabled } = require('../../../server/utils');
/**
* @typedef {Object} ModelOptions
* @property {string} modelName - The name of the model.
* @property {number} [temperature] - The temperature setting for the model.
* @property {number} [presence_penalty] - The presence penalty setting.
* @property {number} [frequency_penalty] - The frequency penalty setting.
* @property {number} [max_tokens] - The maximum number of tokens to generate.
*/
/**
* @typedef {Object} ConfigOptions
* @property {string} [basePath] - The base path for the API requests.
* @property {Object} [baseOptions] - Base options for the API requests, including headers.
* @property {Object} [httpAgent] - The HTTP agent for the request.
* @property {Object} [httpsAgent] - The HTTPS agent for the request.
*/
/**
* @typedef {Object} Callbacks
* @property {Function} [handleChatModelStart] - A callback function for handleChatModelStart
* @property {Function} [handleLLMEnd] - A callback function for handleLLMEnd
* @property {Function} [handleLLMError] - A callback function for handleLLMError
*/
/**
* @typedef {Object} AzureOptions
* @property {string} [azureOpenAIApiKey] - The Azure OpenAI API key.
* @property {string} [azureOpenAIApiInstanceName] - The Azure OpenAI API instance name.
* @property {string} [azureOpenAIApiDeploymentName] - The Azure OpenAI API deployment name.
* @property {string} [azureOpenAIApiVersion] - The Azure OpenAI API version.
*/
const { ChatOpenAI } = require('@langchain/openai');
const { sanitizeModelName, constructAzureURL } = require('~/utils');
const { isEnabled } = require('~/server/utils');
/**
* Creates a new instance of a language model (LLM) for chat interactions.
@@ -40,7 +8,7 @@ const { isEnabled } = require('../../../server/utils');
* @param {Object} options - The options for creating the LLM.
* @param {ModelOptions} options.modelOptions - The options specific to the model, including modelName, temperature, presence_penalty, frequency_penalty, and other model-related settings.
* @param {ConfigOptions} options.configOptions - Configuration options for the API requests, including proxy settings and custom headers.
* @param {Callbacks} options.callbacks - Callback functions for managing the lifecycle of the LLM, including token buffers, context, and initial message count.
* @param {Callbacks} [options.callbacks] - Callback functions for managing the lifecycle of the LLM, including token buffers, context, and initial message count.
* @param {boolean} [options.streaming=false] - Determines if the LLM should operate in streaming mode.
* @param {string} options.openAIApiKey - The API key for OpenAI, used for authentication.
* @param {AzureOptions} [options.azure={}] - Optional Azure-specific configurations. If provided, Azure configurations take precedence over OpenAI configurations.
@@ -49,7 +17,7 @@ const { isEnabled } = require('../../../server/utils');
*
* @example
* const llm = createLLM({
* modelOptions: { modelName: 'gpt-3.5-turbo', temperature: 0.2 },
* modelOptions: { modelName: 'gpt-4o-mini', temperature: 0.2 },
* configOptions: { basePath: 'https://example.api/path' },
* callbacks: { onMessage: handleMessage },
* openAIApiKey: 'your-api-key'
@@ -68,6 +36,7 @@ function createLLM({
apiKey: openAIApiKey,
};
/** @type {AzureOptions} */
let azureOptions = {};
if (azure) {
const useModelName = isEnabled(process.env.AZURE_USE_MODEL_AS_DEPLOYMENT_NAME);
@@ -85,17 +54,24 @@ function createLLM({
modelOptions.modelName = process.env.AZURE_OPENAI_DEFAULT_MODEL;
}
// console.debug('createLLM: configOptions');
// console.debug(configOptions);
if (azure && configOptions.basePath) {
const azureURL = constructAzureURL({
baseURL: configOptions.basePath,
azureOptions,
});
azureOptions.azureOpenAIBasePath = azureURL.split(
`/${azureOptions.azureOpenAIApiDeploymentName}`,
)[0];
}
return new ChatOpenAI(
{
streaming,
verbose: true,
credentials,
configuration,
...azureOptions,
...modelOptions,
...credentials,
callbacks,
},
configOptions,

View File

@@ -1,7 +1,9 @@
const createLLM = require('./createLLM');
const RunManager = require('./RunManager');
const createCoherePayload = require('./createCoherePayload');
module.exports = {
createLLM,
RunManager,
createCoherePayload,
};

View File

@@ -1,9 +1,9 @@
require('dotenv').config();
const { ChatOpenAI } = require('langchain/chat_models/openai');
const { ChatOpenAI } = require('@langchain/openai');
const { getBufferString, ConversationSummaryBufferMemory } = require('langchain/memory');
const chatPromptMemory = new ConversationSummaryBufferMemory({
llm: new ChatOpenAI({ modelName: 'gpt-3.5-turbo', temperature: 0 }),
llm: new ChatOpenAI({ modelName: 'gpt-4o-mini', temperature: 0 }),
maxTokenLimit: 10,
returnMessages: true,
});

View File

@@ -1,6 +1,7 @@
const { ConversationSummaryBufferMemory, ChatMessageHistory } = require('langchain/memory');
const { formatLangChainMessages, SUMMARY_PROMPT } = require('../prompts');
const { predictNewSummary } = require('../chains');
const { logger } = require('~/config');
const createSummaryBufferMemory = ({ llm, prompt, messages, ...rest }) => {
const chatHistory = new ChatMessageHistory(messages);
@@ -22,9 +23,8 @@ const summaryBuffer = async ({
prompt = SUMMARY_PROMPT,
signal,
}) => {
if (debug && previous_summary) {
console.log('<-----------PREVIOUS SUMMARY----------->\n\n');
console.log(previous_summary);
if (previous_summary) {
logger.debug('[summaryBuffer]', { previous_summary });
}
const formattedMessages = formatLangChainMessages(context, formatOptions);
@@ -46,8 +46,7 @@ const summaryBuffer = async ({
const messages = await chatPromptMemory.chatHistory.getMessages();
if (debug) {
console.log('<-----------SUMMARY BUFFER MESSAGES----------->\n\n');
console.log(JSON.stringify(messages));
logger.debug('[summaryBuffer]', { summary_buffer_messages: messages.length });
}
const predictSummary = await predictNewSummary({
@@ -58,8 +57,7 @@ const summaryBuffer = async ({
});
if (debug) {
console.log('<-----------SUMMARY----------->\n\n');
console.log(JSON.stringify(predictSummary));
logger.debug('[summaryBuffer]', { summary: predictSummary });
}
return { role: 'system', content: predictSummary };

View File

@@ -1,3 +1,5 @@
const { logger } = require('~/config');
/**
* The `addImages` function corrects any erroneous image URLs in the `responseMessage.text`
* and appends image observations from `intermediateSteps` if they are not already present.
@@ -20,7 +22,7 @@
*
* addImages(intermediateSteps, responseMessage);
*
* console.log(responseMessage.text);
* logger.debug(responseMessage.text);
* // Outputs: 'Some text with ![desc](/images/test.png)\n![desc](/images/test.png)'
*
* @returns {void}
@@ -58,12 +60,10 @@ function addImages(intermediateSteps, responseMessage) {
if (!observation || !observation.includes('![')) {
return;
}
const observedImagePath = observation.match(/\(\/images\/.*\.\w*\)/g);
const observedImagePath = observation.match(/!\[[^(]*\]\([^)]*\)/g);
if (observedImagePath && !responseMessage.text.includes(observedImagePath[0])) {
responseMessage.text += '\n' + observation;
if (process.env.DEBUG_PLUGINS) {
console.debug('[addImages] added image from intermediateSteps');
}
responseMessage.text += '\n' + observedImagePath[0];
logger.debug('[addImages] added image from intermediateSteps:', observedImagePath[0]);
}
});
}

View File

@@ -81,4 +81,62 @@ describe('addImages', () => {
addImages(intermediateSteps, responseMessage);
expect(responseMessage.text).toBe(`${originalText}\n${imageMarkdown}`);
});
it('should extract only image markdowns when there is text between them', () => {
const markdownWithTextBetweenImages = `
![image1](/images/image1.png)
Some text between images that should not be included.
![image2](/images/image2.png)
More text that should be ignored.
![image3](/images/image3.png)
`;
intermediateSteps.push({ observation: markdownWithTextBetweenImages });
addImages(intermediateSteps, responseMessage);
expect(responseMessage.text).toBe('\n![image1](/images/image1.png)');
});
it('should only return the first image when multiple images are present', () => {
const markdownWithMultipleImages = `
![image1](/images/image1.png)
![image2](/images/image2.png)
![image3](/images/image3.png)
`;
intermediateSteps.push({ observation: markdownWithMultipleImages });
addImages(intermediateSteps, responseMessage);
expect(responseMessage.text).toBe('\n![image1](/images/image1.png)');
});
it('should not include any text or metadata surrounding the image markdown', () => {
const markdownWithMetadata = `
Title: Test Document
Author: John Doe
![image1](/images/image1.png)
Some content after the image.
Vector values: [0.1, 0.2, 0.3]
`;
intermediateSteps.push({ observation: markdownWithMetadata });
addImages(intermediateSteps, responseMessage);
expect(responseMessage.text).toBe('\n![image1](/images/image1.png)');
});
it('should handle complex markdown with multiple images and only return the first one', () => {
const complexMarkdown = `
# Document Title
## Section 1
Here's some text with an embedded image:
![image1](/images/image1.png)
## Section 2
More text here...
![image2](/images/image2.png)
### Subsection
Even more content
![image3](/images/image3.png)
`;
intermediateSteps.push({ observation: complexMarkdown });
addImages(intermediateSteps, responseMessage);
expect(responseMessage.text).toBe('\n![image1](/images/image1.png)');
});
});

View File

@@ -0,0 +1,45 @@
/**
* Anthropic API: Adds cache control to the appropriate user messages in the payload.
* @param {Array<AnthropicMessage | BaseMessage>} messages - The array of message objects.
* @returns {Array<AnthropicMessage | BaseMessage>} - The updated array of message objects with cache control added.
*/
function addCacheControl(messages) {
if (!Array.isArray(messages) || messages.length < 2) {
return messages;
}
const updatedMessages = [...messages];
let userMessagesModified = 0;
for (let i = updatedMessages.length - 1; i >= 0 && userMessagesModified < 2; i--) {
const message = updatedMessages[i];
if (message.getType != null && message.getType() !== 'human') {
continue;
} else if (message.getType == null && message.role !== 'user') {
continue;
}
if (typeof message.content === 'string') {
message.content = [
{
type: 'text',
text: message.content,
cache_control: { type: 'ephemeral' },
},
];
userMessagesModified++;
} else if (Array.isArray(message.content)) {
for (let j = message.content.length - 1; j >= 0; j--) {
if (message.content[j].type === 'text') {
message.content[j].cache_control = { type: 'ephemeral' };
userMessagesModified++;
break;
}
}
}
}
return updatedMessages;
}
module.exports = addCacheControl;

View File

@@ -0,0 +1,227 @@
const addCacheControl = require('./addCacheControl');
describe('addCacheControl', () => {
test('should add cache control to the last two user messages with array content', () => {
const messages = [
{ role: 'user', content: [{ type: 'text', text: 'Hello' }] },
{ role: 'assistant', content: [{ type: 'text', text: 'Hi there' }] },
{ role: 'user', content: [{ type: 'text', text: 'How are you?' }] },
{ role: 'assistant', content: [{ type: 'text', text: 'I\'m doing well, thanks!' }] },
{ role: 'user', content: [{ type: 'text', text: 'Great!' }] },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).not.toHaveProperty('cache_control');
expect(result[2].content[0].cache_control).toEqual({ type: 'ephemeral' });
expect(result[4].content[0].cache_control).toEqual({ type: 'ephemeral' });
});
test('should add cache control to the last two user messages with string content', () => {
const messages = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there' },
{ role: 'user', content: 'How are you?' },
{ role: 'assistant', content: 'I\'m doing well, thanks!' },
{ role: 'user', content: 'Great!' },
];
const result = addCacheControl(messages);
expect(result[0].content).toBe('Hello');
expect(result[2].content[0]).toEqual({
type: 'text',
text: 'How are you?',
cache_control: { type: 'ephemeral' },
});
expect(result[4].content[0]).toEqual({
type: 'text',
text: 'Great!',
cache_control: { type: 'ephemeral' },
});
});
test('should handle mixed string and array content', () => {
const messages = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there' },
{ role: 'user', content: [{ type: 'text', text: 'How are you?' }] },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).toEqual({
type: 'text',
text: 'Hello',
cache_control: { type: 'ephemeral' },
});
expect(result[2].content[0].cache_control).toEqual({ type: 'ephemeral' });
});
test('should handle less than two user messages', () => {
const messages = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there' },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).toEqual({
type: 'text',
text: 'Hello',
cache_control: { type: 'ephemeral' },
});
expect(result[1].content).toBe('Hi there');
});
test('should return original array if no user messages', () => {
const messages = [
{ role: 'assistant', content: 'Hi there' },
{ role: 'assistant', content: 'How can I help?' },
];
const result = addCacheControl(messages);
expect(result).toEqual(messages);
});
test('should handle empty array', () => {
const messages = [];
const result = addCacheControl(messages);
expect(result).toEqual([]);
});
test('should handle non-array input', () => {
const messages = 'not an array';
const result = addCacheControl(messages);
expect(result).toBe('not an array');
});
test('should not modify assistant messages', () => {
const messages = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there' },
{ role: 'user', content: 'How are you?' },
];
const result = addCacheControl(messages);
expect(result[1].content).toBe('Hi there');
});
test('should handle multiple content items in user messages', () => {
const messages = [
{
role: 'user',
content: [
{ type: 'text', text: 'Hello' },
{ type: 'image', url: 'http://example.com/image.jpg' },
{ type: 'text', text: 'This is an image' },
],
},
{ role: 'assistant', content: 'Hi there' },
{ role: 'user', content: 'How are you?' },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).not.toHaveProperty('cache_control');
expect(result[0].content[1]).not.toHaveProperty('cache_control');
expect(result[0].content[2].cache_control).toEqual({ type: 'ephemeral' });
expect(result[2].content[0]).toEqual({
type: 'text',
text: 'How are you?',
cache_control: { type: 'ephemeral' },
});
});
test('should handle an array with mixed content types', () => {
const messages = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there' },
{ role: 'user', content: [{ type: 'text', text: 'How are you?' }] },
{ role: 'assistant', content: 'I\'m doing well, thanks!' },
{ role: 'user', content: 'Great!' },
];
const result = addCacheControl(messages);
expect(result[0].content).toEqual('Hello');
expect(result[2].content[0]).toEqual({
type: 'text',
text: 'How are you?',
cache_control: { type: 'ephemeral' },
});
expect(result[4].content).toEqual([
{
type: 'text',
text: 'Great!',
cache_control: { type: 'ephemeral' },
},
]);
expect(result[1].content).toBe('Hi there');
expect(result[3].content).toBe('I\'m doing well, thanks!');
});
test('should handle edge case with multiple content types', () => {
const messages = [
{
role: 'user',
content: [
{
type: 'image',
source: { type: 'base64', media_type: 'image/png', data: 'some_base64_string' },
},
{
type: 'image',
source: { type: 'base64', media_type: 'image/png', data: 'another_base64_string' },
},
{ type: 'text', text: 'what do all these images have in common' },
],
},
{ role: 'assistant', content: 'I see multiple images.' },
{ role: 'user', content: 'Correct!' },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).not.toHaveProperty('cache_control');
expect(result[0].content[1]).not.toHaveProperty('cache_control');
expect(result[0].content[2].cache_control).toEqual({ type: 'ephemeral' });
expect(result[2].content[0]).toEqual({
type: 'text',
text: 'Correct!',
cache_control: { type: 'ephemeral' },
});
});
test('should handle user message with no text block', () => {
const messages = [
{
role: 'user',
content: [
{
type: 'image',
source: { type: 'base64', media_type: 'image/png', data: 'some_base64_string' },
},
{
type: 'image',
source: { type: 'base64', media_type: 'image/png', data: 'another_base64_string' },
},
],
},
{ role: 'assistant', content: 'I see two images.' },
{ role: 'user', content: 'Correct!' },
];
const result = addCacheControl(messages);
expect(result[0].content[0]).not.toHaveProperty('cache_control');
expect(result[0].content[1]).not.toHaveProperty('cache_control');
expect(result[2].content[0]).toEqual({
type: 'text',
text: 'Correct!',
cache_control: { type: 'ephemeral' },
});
});
});

View File

@@ -0,0 +1,527 @@
const dedent = require('dedent');
const { EModelEndpoint, ArtifactModes } = require('librechat-data-provider');
const { generateShadcnPrompt } = require('~/app/clients/prompts/shadcn-docs/generate');
const { components } = require('~/app/clients/prompts/shadcn-docs/components');
// eslint-disable-next-line no-unused-vars
const artifactsPromptV1 = dedent`The assistant can create and reference artifacts during conversations.
Artifacts are for substantial, self-contained content that users might modify or reuse, displayed in a separate UI window for clarity.
# Good artifacts are...
- Substantial content (>15 lines)
- Content that the user is likely to modify, iterate on, or take ownership of
- Self-contained, complex content that can be understood on its own, without context from the conversation
- Content intended for eventual use outside the conversation (e.g., reports, emails, presentations)
- Content likely to be referenced or reused multiple times
# Don't use artifacts for...
- Simple, informational, or short content, such as brief code snippets, mathematical equations, or small examples
- Primarily explanatory, instructional, or illustrative content, such as examples provided to clarify a concept
- Suggestions, commentary, or feedback on existing artifacts
- Conversational or explanatory content that doesn't represent a standalone piece of work
- Content that is dependent on the current conversational context to be useful
- Content that is unlikely to be modified or iterated upon by the user
- Request from users that appears to be a one-off question
# Usage notes
- One artifact per message unless specifically requested
- Prefer in-line content (don't use artifacts) when possible. Unnecessary use of artifacts can be jarring for users.
- If a user asks the assistant to "draw an SVG" or "make a website," the assistant does not need to explain that it doesn't have these capabilities. Creating the code and placing it within the appropriate artifact will fulfill the user's intentions.
- If asked to generate an image, the assistant can offer an SVG instead. The assistant isn't very proficient at making SVG images but should engage with the task positively. Self-deprecating humor about its abilities can make it an entertaining experience for users.
- The assistant errs on the side of simplicity and avoids overusing artifacts for content that can be effectively presented within the conversation.
- Always provide complete, specific, and fully functional content without any placeholders, ellipses, or 'remains the same' comments.
<artifact_instructions>
When collaborating with the user on creating content that falls into compatible categories, the assistant should follow these steps:
1. Create the artifact using the following format:
:::artifact{identifier="unique-identifier" type="mime-type" title="Artifact Title"}
\`\`\`
Your artifact content here
\`\`\`
:::
2. Assign an identifier to the \`identifier\` attribute. For updates, reuse the prior identifier. For new artifacts, the identifier should be descriptive and relevant to the content, using kebab-case (e.g., "example-code-snippet"). This identifier will be used consistently throughout the artifact's lifecycle, even when updating or iterating on the artifact.
3. Include a \`title\` attribute to provide a brief title or description of the content.
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
- HTML: "text/html"
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
- Mermaid Diagrams: "application/vnd.mermaid"
- The user interface will render Mermaid diagrams placed within the artifact tags.
- React Components: "application/vnd.react"
- Use this for displaying either: React elements, e.g. \`<strong>Hello World!</strong>\`, React pure functional components, e.g. \`() => <strong>Hello World!</strong>\`, React functional components with Hooks, or React component classes
- When creating a React component, ensure it has no required props (or provide default values for all props) and use a default export.
- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. \`h-[600px]\`).
- Base React is available to be imported. To use hooks, first import it at the top of the artifact, e.g. \`import { useState } from "react"\`
- The lucide-react@0.263.1 library is available to be imported. e.g. \`import { Camera } from "lucide-react"\` & \`<Camera color="red" size={48} />\`
- The recharts charting library is available to be imported, e.g. \`import { LineChart, XAxis, ... } from "recharts"\` & \`<LineChart ...><XAxis dataKey="name"> ...\`
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
6. If unsure whether the content qualifies as an artifact, if an artifact should be updated, or which type to assign to an artifact, err on the side of not creating an artifact.
7. Always use triple backticks (\`\`\`) to enclose the content within the artifact, regardless of the content type.
</artifact_instructions>
Here are some examples of correct usage of artifacts:
<examples>
<example_docstring>
This example demonstrates how to create a Mermaid artifact for a simple flow chart.
</example_docstring>
<example>
<user_query>Can you create a simple flow chart showing the process of making tea using Mermaid?</user_query>
<assistant_response>
Sure! Here's a simple flow chart depicting the process of making tea using Mermaid syntax:
:::artifact{identifier="tea-making-flowchart" type="application/vnd.mermaid" title="Flow chart: Making Tea"}
\`\`\`mermaid
graph TD
A[Start] --> B{Water boiled?}
B -->|Yes| C[Add tea leaves to cup]
B -->|No| D[Boil water]
D --> B
C --> E[Pour boiling water into cup]
E --> F[Steep tea for desired time]
F --> G[Remove tea leaves]
G --> H[Add milk or sugar, if desired]
H --> I[Enjoy your tea!]
I --> J[End]
\`\`\`
:::
This flow chart uses Mermaid syntax to visualize the steps involved in making a cup of tea. Here's a brief explanation of the process:
1. Start
2. Check if water is boiled
3. If not boiled, boil the water
4. Once water is boiled, add tea leaves to the cup
5. Pour boiling water into the cup
6. Steep the tea for the desired time
7. Remove the tea leaves
8. Optionally add milk or sugar
9. Enjoy your tea!
10. End
This chart provides a clear visual representation of the tea-making process. You can easily modify or expand this chart if you want to add more details or steps to the process. Let me know if you'd like any changes or have any questions!
</assistant_response>
</example>
</examples>`;
const artifactsPrompt = dedent`The assistant can create and reference artifacts during conversations.
Artifacts are for substantial, self-contained content that users might modify or reuse, displayed in a separate UI window for clarity.
# Good artifacts are...
- Substantial content (>15 lines)
- Content that the user is likely to modify, iterate on, or take ownership of
- Self-contained, complex content that can be understood on its own, without context from the conversation
- Content intended for eventual use outside the conversation (e.g., reports, emails, presentations)
- Content likely to be referenced or reused multiple times
# Don't use artifacts for...
- Simple, informational, or short content, such as brief code snippets, mathematical equations, or small examples
- Primarily explanatory, instructional, or illustrative content, such as examples provided to clarify a concept
- Suggestions, commentary, or feedback on existing artifacts
- Conversational or explanatory content that doesn't represent a standalone piece of work
- Content that is dependent on the current conversational context to be useful
- Content that is unlikely to be modified or iterated upon by the user
- Request from users that appears to be a one-off question
# Usage notes
- One artifact per message unless specifically requested
- Prefer in-line content (don't use artifacts) when possible. Unnecessary use of artifacts can be jarring for users.
- If a user asks the assistant to "draw an SVG" or "make a website," the assistant does not need to explain that it doesn't have these capabilities. Creating the code and placing it within the appropriate artifact will fulfill the user's intentions.
- If asked to generate an image, the assistant can offer an SVG instead. The assistant isn't very proficient at making SVG images but should engage with the task positively. Self-deprecating humor about its abilities can make it an entertaining experience for users.
- The assistant errs on the side of simplicity and avoids overusing artifacts for content that can be effectively presented within the conversation.
- Always provide complete, specific, and fully functional content for artifacts without any snippets, placeholders, ellipses, or 'remains the same' comments.
- If an artifact is not necessary or requested, the assistant should not mention artifacts at all, and respond to the user accordingly.
<artifact_instructions>
When collaborating with the user on creating content that falls into compatible categories, the assistant should follow these steps:
1. Create the artifact using the following format:
:::artifact{identifier="unique-identifier" type="mime-type" title="Artifact Title"}
\`\`\`
Your artifact content here
\`\`\`
:::
2. Assign an identifier to the \`identifier\` attribute. For updates, reuse the prior identifier. For new artifacts, the identifier should be descriptive and relevant to the content, using kebab-case (e.g., "example-code-snippet"). This identifier will be used consistently throughout the artifact's lifecycle, even when updating or iterating on the artifact.
3. Include a \`title\` attribute to provide a brief title or description of the content.
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
- HTML: "text/html"
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
- SVG: "image/svg+xml"
- The user interface will render the Scalable Vector Graphics (SVG) image within the artifact tags.
- The assistant should specify the viewbox of the SVG rather than defining a width/height
- Mermaid Diagrams: "application/vnd.mermaid"
- The user interface will render Mermaid diagrams placed within the artifact tags.
- React Components: "application/vnd.react"
- Use this for displaying either: React elements, e.g. \`<strong>Hello World!</strong>\`, React pure functional components, e.g. \`() => <strong>Hello World!</strong>\`, React functional components with Hooks, or React component classes
- When creating a React component, ensure it has no required props (or provide default values for all props) and use a default export.
- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. \`h-[600px]\`).
- Base React is available to be imported. To use hooks, first import it at the top of the artifact, e.g. \`import { useState } from "react"\`
- The lucide-react@0.394.0 library is available to be imported. e.g. \`import { Camera } from "lucide-react"\` & \`<Camera color="red" size={48} />\`
- The recharts charting library is available to be imported, e.g. \`import { LineChart, XAxis, ... } from "recharts"\` & \`<LineChart ...><XAxis dataKey="name"> ...\`
- The three.js library is available to be imported, e.g. \`import * as THREE from "three";\`
- The date-fns library is available to be imported, e.g. \`import { compareAsc, format } from "date-fns";\`
- The react-day-picker library is available to be imported, e.g. \`import { DayPicker } from "react-day-picker";\`
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- When iterating on code, ensure that the code is complete and functional without any snippets, placeholders, or ellipses.
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
6. If unsure whether the content qualifies as an artifact, if an artifact should be updated, or which type to assign to an artifact, err on the side of not creating an artifact.
7. Always use triple backticks (\`\`\`) to enclose the content within the artifact, regardless of the content type.
</artifact_instructions>
Here are some examples of correct usage of artifacts:
<examples>
<example_docstring>
This example demonstrates how to create a Mermaid artifact for a simple flow chart.
</example_docstring>
<example>
<user_query>Can you create a simple flow chart showing the process of making tea using Mermaid?</user_query>
<assistant_response>
Sure! Here's a simple flow chart depicting the process of making tea using Mermaid syntax:
:::artifact{identifier="tea-making-flowchart" type="application/vnd.mermaid" title="Flow chart: Making Tea"}
\`\`\`mermaid
graph TD
A[Start] --> B{Water boiled?}
B -->|Yes| C[Add tea leaves to cup]
B -->|No| D[Boil water]
D --> B
C --> E[Pour boiling water into cup]
E --> F[Steep tea for desired time]
F --> G[Remove tea leaves]
G --> H[Add milk or sugar, if desired]
H --> I[Enjoy your tea!]
I --> J[End]
\`\`\`
:::
This flow chart uses Mermaid syntax to visualize the steps involved in making a cup of tea. Here's a brief explanation of the process:
1. Start
2. Check if water is boiled
3. If not boiled, boil the water
4. Once water is boiled, add tea leaves to the cup
5. Pour boiling water into the cup
6. Steep the tea for the desired time
7. Remove the tea leaves
8. Optionally add milk or sugar
9. Enjoy your tea!
10. End
This chart provides a clear visual representation of the tea-making process. You can easily modify or expand this chart if you want to add more details or steps to the process. Let me know if you'd like any changes or have any questions!
</assistant_response>
</example>
<example>
<user_query>Create a simple React counter component</user_query>
<assistant_response>
Here's a simple React counter component:
:::artifact{identifier="react-counter" type="application/vnd.react" title="React Counter"}
\`\`\`
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div className="p-4">
<p className="mb-2">Count: {count}</p>
<button className="bg-blue-500 text-white px-4 py-2 rounded" onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
\`\`\`
:::
This component creates a simple counter with an increment button.
</assistant_response>
</example>
<example>
<user_query>Create a basic HTML structure for a blog post</user_query>
<assistant_response>
Here's a basic HTML structure for a blog post:
:::artifact{identifier="blog-post-html" type="text/html" title="Blog Post HTML"}
\`\`\`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Blog Post</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #333; }
p { margin-bottom: 15px; }
</style>
</head>
<body>
<header>
<h1>My First Blog Post</h1>
</header>
<main>
<article>
<p>This is the content of my blog post. It's short and sweet!</p>
</article>
</main>
<footer>
<p>&copy; 2023 My Blog</p>
</footer>
</body>
</html>
\`\`\`
:::
This HTML structure provides a simple layout for a blog post.
</assistant_response>
</example>
</examples>`;
const artifactsOpenAIPrompt = dedent`The assistant can create and reference artifacts during conversations.
Artifacts are for substantial, self-contained content that users might modify or reuse, displayed in a separate UI window for clarity.
# Good artifacts are...
- Substantial content (>15 lines)
- Content that the user is likely to modify, iterate on, or take ownership of
- Self-contained, complex content that can be understood on its own, without context from the conversation
- Content intended for eventual use outside the conversation (e.g., reports, emails, presentations)
- Content likely to be referenced or reused multiple times
# Don't use artifacts for...
- Simple, informational, or short content, such as brief code snippets, mathematical equations, or small examples
- Primarily explanatory, instructional, or illustrative content, such as examples provided to clarify a concept
- Suggestions, commentary, or feedback on existing artifacts
- Conversational or explanatory content that doesn't represent a standalone piece of work
- Content that is dependent on the current conversational context to be useful
- Content that is unlikely to be modified or iterated upon by the user
- Request from users that appears to be a one-off question
# Usage notes
- One artifact per message unless specifically requested
- Prefer in-line content (don't use artifacts) when possible. Unnecessary use of artifacts can be jarring for users.
- If a user asks the assistant to "draw an SVG" or "make a website," the assistant does not need to explain that it doesn't have these capabilities. Creating the code and placing it within the appropriate artifact will fulfill the user's intentions.
- If asked to generate an image, the assistant can offer an SVG instead. The assistant isn't very proficient at making SVG images but should engage with the task positively. Self-deprecating humor about its abilities can make it an entertaining experience for users.
- The assistant errs on the side of simplicity and avoids overusing artifacts for content that can be effectively presented within the conversation.
- Always provide complete, specific, and fully functional content for artifacts without any snippets, placeholders, ellipses, or 'remains the same' comments.
- If an artifact is not necessary or requested, the assistant should not mention artifacts at all, and respond to the user accordingly.
## Artifact Instructions
When collaborating with the user on creating content that falls into compatible categories, the assistant should follow these steps:
1. Create the artifact using the following remark-directive markdown format:
:::artifact{identifier="unique-identifier" type="mime-type" title="Artifact Title"}
\`\`\`
Your artifact content here
\`\`\`
:::
a. Example of correct format:
:::artifact{identifier="example-artifact" type="text/plain" title="Example Artifact"}
\`\`\`
This is the content of the artifact.
It can span multiple lines.
\`\`\`
:::
b. Common mistakes to avoid:
- Don't split the opening ::: line
- Don't add extra backticks outside the artifact structure
- Don't omit the closing :::
2. Assign an identifier to the \`identifier\` attribute. For updates, reuse the prior identifier. For new artifacts, the identifier should be descriptive and relevant to the content, using kebab-case (e.g., "example-code-snippet"). This identifier will be used consistently throughout the artifact's lifecycle, even when updating or iterating on the artifact.
3. Include a \`title\` attribute to provide a brief title or description of the content.
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
- HTML: "text/html"
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
- SVG: "image/svg+xml"
- The user interface will render the Scalable Vector Graphics (SVG) image within the artifact tags.
- The assistant should specify the viewbox of the SVG rather than defining a width/height
- Mermaid Diagrams: "application/vnd.mermaid"
- The user interface will render Mermaid diagrams placed within the artifact tags.
- React Components: "application/vnd.react"
- Use this for displaying either: React elements, e.g. \`<strong>Hello World!</strong>\`, React pure functional components, e.g. \`() => <strong>Hello World!</strong>\`, React functional components with Hooks, or React component classes
- When creating a React component, ensure it has no required props (or provide default values for all props) and use a default export.
- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. \`h-[600px]\`).
- Base React is available to be imported. To use hooks, first import it at the top of the artifact, e.g. \`import { useState } from "react"\`
- The lucide-react@0.394.0 library is available to be imported. e.g. \`import { Camera } from "lucide-react"\` & \`<Camera color="red" size={48} />\`
- The recharts charting library is available to be imported, e.g. \`import { LineChart, XAxis, ... } from "recharts"\` & \`<LineChart ...><XAxis dataKey="name"> ...\`
- The three.js library is available to be imported, e.g. \`import * as THREE from "three";\`
- The date-fns library is available to be imported, e.g. \`import { compareAsc, format } from "date-fns";\`
- The react-day-picker library is available to be imported, e.g. \`import { DayPicker } from "react-day-picker";\`
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
- When iterating on code, ensure that the code is complete and functional without any snippets, placeholders, or ellipses.
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
6. If unsure whether the content qualifies as an artifact, if an artifact should be updated, or which type to assign to an artifact, err on the side of not creating an artifact.
7. NEVER use triple backticks to enclose the artifact, ONLY the content within the artifact.
Here are some examples of correct usage of artifacts:
## Examples
### Example 1
This example demonstrates how to create a Mermaid artifact for a simple flow chart.
User: Can you create a simple flow chart showing the process of making tea using Mermaid?
Assistant: Sure! Here's a simple flow chart depicting the process of making tea using Mermaid syntax:
:::artifact{identifier="tea-making-flowchart" type="application/vnd.mermaid" title="Flow chart: Making Tea"}
\`\`\`mermaid
graph TD
A[Start] --> B{Water boiled?}
B -->|Yes| C[Add tea leaves to cup]
B -->|No| D[Boil water]
D --> B
C --> E[Pour boiling water into cup]
E --> F[Steep tea for desired time]
F --> G[Remove tea leaves]
G --> H[Add milk or sugar, if desired]
H --> I[Enjoy your tea!]
I --> J[End]
\`\`\`
:::
This flow chart uses Mermaid syntax to visualize the steps involved in making a cup of tea. Here's a brief explanation of the process:
1. Start
2. Check if water is boiled
3. If not boiled, boil the water
4. Once water is boiled, add tea leaves to the cup
5. Pour boiling water into the cup
6. Steep the tea for the desired time
7. Remove the tea leaves
8. Optionally add milk or sugar
9. Enjoy your tea!
10. End
This chart provides a clear visual representation of the tea-making process. You can easily modify or expand this chart if you want to add more details or steps to the process. Let me know if you'd like any changes or have any questions!
---
### Example 2
User: Create a simple React counter component
Assistant: Here's a simple React counter component:
:::artifact{identifier="react-counter" type="application/vnd.react" title="React Counter"}
\`\`\`
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div className="p-4">
<p className="mb-2">Count: {count}</p>
<button className="bg-blue-500 text-white px-4 py-2 rounded" onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
\`\`\`
:::
This component creates a simple counter with an increment button.
---
### Example 3
User: Create a basic HTML structure for a blog post
Assistant: Here's a basic HTML structure for a blog post:
:::artifact{identifier="blog-post-html" type="text/html" title="Blog Post HTML"}
\`\`\`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Blog Post</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #333; }
p { margin-bottom: 15px; }
</style>
</head>
<body>
<header>
<h1>My First Blog Post</h1>
</header>
<main>
<article>
<p>This is the content of my blog post. It's short and sweet!</p>
</article>
</main>
<footer>
<p>&copy; 2023 My Blog</p>
</footer>
</body>
</html>
\`\`\`
:::
This HTML structure provides a simple layout for a blog post.
---`;
/**
*
* @param {Object} params
* @param {EModelEndpoint | string} params.endpoint - The current endpoint
* @param {ArtifactModes} params.artifacts - The current artifact mode
* @returns
*/
const generateArtifactsPrompt = ({ endpoint, artifacts }) => {
if (artifacts === ArtifactModes.CUSTOM) {
return null;
}
let prompt = artifactsPrompt;
if (endpoint !== EModelEndpoint.anthropic) {
prompt = artifactsOpenAIPrompt;
}
if (artifacts === ArtifactModes.SHADCNUI) {
prompt += generateShadcnPrompt({ components, useXML: endpoint === EModelEndpoint.anthropic });
}
return prompt;
};
module.exports = generateArtifactsPrompt;

View File

@@ -0,0 +1,160 @@
const axios = require('axios');
const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');
const footer = `Use the context as your learned knowledge to better answer the user.
In your response, remember to follow these guidelines:
- If you don't know the answer, simply say that you don't know.
- If you are unsure how to answer, ask for clarification.
- Avoid mentioning that you obtained the information from the context.
`;
function createContextHandlers(req, userMessageContent) {
if (!process.env.RAG_API_URL) {
return;
}
const queryPromises = [];
const processedFiles = [];
const processedIds = new Set();
const jwtToken = req.headers.authorization.split(' ')[1];
const useFullContext = isEnabled(process.env.RAG_USE_FULL_CONTEXT);
const query = async (file) => {
if (useFullContext) {
return axios.get(`${process.env.RAG_API_URL}/documents/${file.file_id}/context`, {
headers: {
Authorization: `Bearer ${jwtToken}`,
},
});
}
return axios.post(
`${process.env.RAG_API_URL}/query`,
{
file_id: file.file_id,
query: userMessageContent,
k: 4,
},
{
headers: {
Authorization: `Bearer ${jwtToken}`,
'Content-Type': 'application/json',
},
},
);
};
const processFile = async (file) => {
if (file.embedded && !processedIds.has(file.file_id)) {
try {
const promise = query(file);
queryPromises.push(promise);
processedFiles.push(file);
processedIds.add(file.file_id);
} catch (error) {
logger.error(`Error processing file ${file.filename}:`, error);
}
}
};
const createContext = async () => {
try {
if (!queryPromises.length || !processedFiles.length) {
return '';
}
const oneFile = processedFiles.length === 1;
const header = `The user has attached ${oneFile ? 'a' : processedFiles.length} file${
!oneFile ? 's' : ''
} to the conversation:`;
const files = `${
oneFile
? ''
: `
<files>`
}${processedFiles
.map(
(file) => `
<file>
<filename>${file.filename}</filename>
<type>${file.type}</type>
</file>`,
)
.join('')}${
oneFile
? ''
: `
</files>`
}`;
const resolvedQueries = await Promise.all(queryPromises);
const context =
resolvedQueries.length === 0
? '\n\tThe semantic search did not return any results.'
: resolvedQueries
.map((queryResult, index) => {
const file = processedFiles[index];
let contextItems = queryResult.data;
const generateContext = (currentContext) =>
`
<file>
<filename>${file.filename}</filename>
<context>${currentContext}
</context>
</file>`;
if (useFullContext) {
return generateContext(`\n${contextItems}`);
}
contextItems = queryResult.data
.map((item) => {
const pageContent = item[0].page_content;
return `
<contextItem>
<![CDATA[${pageContent?.trim()}]]>
</contextItem>`;
})
.join('');
return generateContext(contextItems);
})
.join('');
if (useFullContext) {
const prompt = `${header}
${context}
${footer}`;
return prompt;
}
const prompt = `${header}
${files}
A semantic search was executed with the user's message as the query, retrieving the following context inside <context></context> XML tags.
<context>${context}
</context>
${footer}`;
return prompt;
} catch (error) {
logger.error('Error creating context:', error);
throw error;
}
};
return {
processFile,
createContext,
};
}
module.exports = createContextHandlers;

View File

@@ -0,0 +1,34 @@
/**
* Generates a prompt instructing the user to describe an image in detail, tailored to different types of visual content.
* @param {boolean} pluralized - Whether to pluralize the prompt for multiple images.
* @returns {string} - The generated vision prompt.
*/
const createVisionPrompt = (pluralized = false) => {
return `Please describe the image${
pluralized ? 's' : ''
} in detail, covering relevant aspects such as:
For photographs, illustrations, or artwork:
- The main subject(s) and their appearance, positioning, and actions
- The setting, background, and any notable objects or elements
- Colors, lighting, and overall mood or atmosphere
- Any interesting details, textures, or patterns
- The style, technique, or medium used (if discernible)
For screenshots or images containing text:
- The content and purpose of the text
- The layout, formatting, and organization of the information
- Any notable visual elements, such as logos, icons, or graphics
- The overall context or message conveyed by the screenshot
For graphs, charts, or data visualizations:
- The type of graph or chart (e.g., bar graph, line chart, pie chart)
- The variables being compared or analyzed
- Any trends, patterns, or outliers in the data
- The axis labels, scales, and units of measurement
- The title, legend, and any additional context provided
Be as specific and descriptive as possible while maintaining clarity and concision.`;
};
module.exports = createVisionPrompt;

View File

@@ -0,0 +1,328 @@
const { ToolMessage } = require('@langchain/core/messages');
const { ContentTypes } = require('librechat-data-provider');
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
const { formatAgentMessages } = require('./formatMessages');
describe('formatAgentMessages', () => {
it('should format simple user and AI messages', () => {
const payload = [
{ role: 'user', content: 'Hello' },
{ role: 'assistant', content: 'Hi there!' },
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(2);
expect(result[0]).toBeInstanceOf(HumanMessage);
expect(result[1]).toBeInstanceOf(AIMessage);
});
it('should handle system messages', () => {
const payload = [{ role: 'system', content: 'You are a helpful assistant.' }];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(1);
expect(result[0]).toBeInstanceOf(SystemMessage);
});
it('should format messages with content arrays', () => {
const payload = [
{
role: 'user',
content: [{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Hello' }],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(1);
expect(result[0]).toBeInstanceOf(HumanMessage);
});
it('should handle tool calls and create ToolMessages', () => {
const payload = [
{
role: 'assistant',
content: [
{
type: ContentTypes.TEXT,
[ContentTypes.TEXT]: 'Let me check that for you.',
tool_call_ids: ['123'],
},
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: '123',
name: 'search',
args: '{"query":"weather"}',
output: 'The weather is sunny.',
},
},
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(2);
expect(result[0]).toBeInstanceOf(AIMessage);
expect(result[1]).toBeInstanceOf(ToolMessage);
expect(result[0].tool_calls).toHaveLength(1);
expect(result[1].tool_call_id).toBe('123');
});
it('should handle multiple content parts in assistant messages', () => {
const payload = [
{
role: 'assistant',
content: [
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Part 1' },
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Part 2' },
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(1);
expect(result[0]).toBeInstanceOf(AIMessage);
expect(result[0].content).toHaveLength(2);
});
it('should throw an error for invalid tool call structure', () => {
const payload = [
{
role: 'assistant',
content: [
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: '123',
name: 'search',
args: '{"query":"weather"}',
output: 'The weather is sunny.',
},
},
],
},
];
expect(() => formatAgentMessages(payload)).toThrow('Invalid tool call structure');
});
it('should handle tool calls with non-JSON args', () => {
const payload = [
{
role: 'assistant',
content: [
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Checking...', tool_call_ids: ['123'] },
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: '123',
name: 'search',
args: 'non-json-string',
output: 'Result',
},
},
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(2);
expect(result[0].tool_calls[0].args).toStrictEqual({ input: 'non-json-string' });
});
it('should handle complex tool calls with multiple steps', () => {
const payload = [
{
role: 'assistant',
content: [
{
type: ContentTypes.TEXT,
[ContentTypes.TEXT]: 'I\'ll search for that information.',
tool_call_ids: ['search_1'],
},
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: 'search_1',
name: 'search',
args: '{"query":"weather in New York"}',
output: 'The weather in New York is currently sunny with a temperature of 75°F.',
},
},
{
type: ContentTypes.TEXT,
[ContentTypes.TEXT]: 'Now, I\'ll convert the temperature.',
tool_call_ids: ['convert_1'],
},
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: 'convert_1',
name: 'convert_temperature',
args: '{"temperature": 75, "from": "F", "to": "C"}',
output: '23.89°C',
},
},
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Here\'s your answer.' },
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(5);
expect(result[0]).toBeInstanceOf(AIMessage);
expect(result[1]).toBeInstanceOf(ToolMessage);
expect(result[2]).toBeInstanceOf(AIMessage);
expect(result[3]).toBeInstanceOf(ToolMessage);
expect(result[4]).toBeInstanceOf(AIMessage);
// Check first AIMessage
expect(result[0].content).toBe('I\'ll search for that information.');
expect(result[0].tool_calls).toHaveLength(1);
expect(result[0].tool_calls[0]).toEqual({
id: 'search_1',
name: 'search',
args: { query: 'weather in New York' },
});
// Check first ToolMessage
expect(result[1].tool_call_id).toBe('search_1');
expect(result[1].name).toBe('search');
expect(result[1].content).toBe(
'The weather in New York is currently sunny with a temperature of 75°F.',
);
// Check second AIMessage
expect(result[2].content).toBe('Now, I\'ll convert the temperature.');
expect(result[2].tool_calls).toHaveLength(1);
expect(result[2].tool_calls[0]).toEqual({
id: 'convert_1',
name: 'convert_temperature',
args: { temperature: 75, from: 'F', to: 'C' },
});
// Check second ToolMessage
expect(result[3].tool_call_id).toBe('convert_1');
expect(result[3].name).toBe('convert_temperature');
expect(result[3].content).toBe('23.89°C');
// Check final AIMessage
expect(result[4].content).toStrictEqual([
{ [ContentTypes.TEXT]: 'Here\'s your answer.', type: ContentTypes.TEXT },
]);
});
it.skip('should not produce two consecutive assistant messages and format content correctly', () => {
const payload = [
{ role: 'user', content: 'Hello' },
{
role: 'assistant',
content: [{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Hi there!' }],
},
{
role: 'assistant',
content: [{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'How can I help you?' }],
},
{ role: 'user', content: 'What\'s the weather?' },
{
role: 'assistant',
content: [
{
type: ContentTypes.TEXT,
[ContentTypes.TEXT]: 'Let me check that for you.',
tool_call_ids: ['weather_1'],
},
{
type: ContentTypes.TOOL_CALL,
tool_call: {
id: 'weather_1',
name: 'check_weather',
args: '{"location":"New York"}',
output: 'Sunny, 75°F',
},
},
],
},
{
role: 'assistant',
content: [
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Here\'s the weather information.' },
],
},
];
const result = formatAgentMessages(payload);
// Check correct message count and types
expect(result).toHaveLength(6);
expect(result[0]).toBeInstanceOf(HumanMessage);
expect(result[1]).toBeInstanceOf(AIMessage);
expect(result[2]).toBeInstanceOf(HumanMessage);
expect(result[3]).toBeInstanceOf(AIMessage);
expect(result[4]).toBeInstanceOf(ToolMessage);
expect(result[5]).toBeInstanceOf(AIMessage);
// Check content of messages
expect(result[0].content).toStrictEqual([
{ [ContentTypes.TEXT]: 'Hello', type: ContentTypes.TEXT },
]);
expect(result[1].content).toStrictEqual([
{ [ContentTypes.TEXT]: 'Hi there!', type: ContentTypes.TEXT },
{ [ContentTypes.TEXT]: 'How can I help you?', type: ContentTypes.TEXT },
]);
expect(result[2].content).toStrictEqual([
{ [ContentTypes.TEXT]: 'What\'s the weather?', type: ContentTypes.TEXT },
]);
expect(result[3].content).toBe('Let me check that for you.');
expect(result[4].content).toBe('Sunny, 75°F');
expect(result[5].content).toStrictEqual([
{ [ContentTypes.TEXT]: 'Here\'s the weather information.', type: ContentTypes.TEXT },
]);
// Check that there are no consecutive AIMessages
const messageTypes = result.map((message) => message.constructor);
for (let i = 0; i < messageTypes.length - 1; i++) {
expect(messageTypes[i] === AIMessage && messageTypes[i + 1] === AIMessage).toBe(false);
}
// Additional check to ensure the consecutive assistant messages were combined
expect(result[1].content).toHaveLength(2);
});
it('should skip THINK type content parts', () => {
const payload = [
{
role: 'assistant',
content: [
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Initial response' },
{ type: ContentTypes.THINK, [ContentTypes.THINK]: 'Reasoning about the problem...' },
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Final answer' },
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(1);
expect(result[0]).toBeInstanceOf(AIMessage);
expect(result[0].content).toEqual('Initial response\nFinal answer');
});
it('should join TEXT content as string when THINK content type is present', () => {
const payload = [
{
role: 'assistant',
content: [
{ type: ContentTypes.THINK, [ContentTypes.THINK]: 'Analyzing the problem...' },
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'First part of response' },
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Second part of response' },
{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: 'Final part of response' },
],
},
];
const result = formatAgentMessages(payload);
expect(result).toHaveLength(1);
expect(result[0]).toBeInstanceOf(AIMessage);
expect(typeof result[0].content).toBe('string');
expect(result[0].content).toBe(
'First part of response\nSecond part of response\nFinal part of response',
);
expect(result[0].content).not.toContain('Analyzing the problem...');
});
});

View File

@@ -0,0 +1,42 @@
/**
* Formats an object to match the struct_val, list_val, string_val, float_val, and int_val format.
*
* @param {Object} obj - The object to be formatted.
* @returns {Object} The formatted object.
*
* Handles different types:
* - Arrays are wrapped in list_val and each element is processed.
* - Objects are recursively processed.
* - Strings are wrapped in string_val.
* - Numbers are wrapped in float_val or int_val depending on whether they are floating-point or integers.
*/
function formatGoogleInputs(obj) {
const formattedObj = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key];
// Handle arrays
if (Array.isArray(value)) {
formattedObj[key] = { list_val: value.map((item) => formatGoogleInputs(item)) };
}
// Handle objects
else if (typeof value === 'object' && value !== null) {
formattedObj[key] = formatGoogleInputs(value);
}
// Handle numbers
else if (typeof value === 'number') {
formattedObj[key] = Number.isInteger(value) ? { int_val: value } : { float_val: value };
}
// Handle other types (e.g., strings)
else {
formattedObj[key] = { string_val: [value] };
}
}
}
return { struct_val: formattedObj };
}
module.exports = formatGoogleInputs;

View File

@@ -0,0 +1,274 @@
const formatGoogleInputs = require('./formatGoogleInputs');
describe('formatGoogleInputs', () => {
it('formats message correctly', () => {
const input = {
messages: [
{
content: 'hi',
author: 'user',
},
],
context: 'context',
examples: [
{
input: {
author: 'user',
content: 'user input',
},
output: {
author: 'bot',
content: 'bot output',
},
},
],
parameters: {
temperature: 0.2,
topP: 0.8,
topK: 40,
maxOutputTokens: 1024,
},
};
const expectedOutput = {
struct_val: {
messages: {
list_val: [
{
struct_val: {
content: {
string_val: ['hi'],
},
author: {
string_val: ['user'],
},
},
},
],
},
context: {
string_val: ['context'],
},
examples: {
list_val: [
{
struct_val: {
input: {
struct_val: {
author: {
string_val: ['user'],
},
content: {
string_val: ['user input'],
},
},
},
output: {
struct_val: {
author: {
string_val: ['bot'],
},
content: {
string_val: ['bot output'],
},
},
},
},
},
],
},
parameters: {
struct_val: {
temperature: {
float_val: 0.2,
},
topP: {
float_val: 0.8,
},
topK: {
int_val: 40,
},
maxOutputTokens: {
int_val: 1024,
},
},
},
},
};
const result = formatGoogleInputs(input);
expect(JSON.stringify(result)).toEqual(JSON.stringify(expectedOutput));
});
it('formats real payload parts', () => {
const input = {
instances: [
{
context: 'context',
examples: [
{
input: {
author: 'user',
content: 'user input',
},
output: {
author: 'bot',
content: 'user output',
},
},
],
messages: [
{
author: 'user',
content: 'hi',
},
],
},
],
parameters: {
candidateCount: 1,
maxOutputTokens: 1024,
temperature: 0.2,
topP: 0.8,
topK: 40,
},
};
const expectedOutput = {
struct_val: {
instances: {
list_val: [
{
struct_val: {
context: { string_val: ['context'] },
examples: {
list_val: [
{
struct_val: {
input: {
struct_val: {
author: { string_val: ['user'] },
content: { string_val: ['user input'] },
},
},
output: {
struct_val: {
author: { string_val: ['bot'] },
content: { string_val: ['user output'] },
},
},
},
},
],
},
messages: {
list_val: [
{
struct_val: {
author: { string_val: ['user'] },
content: { string_val: ['hi'] },
},
},
],
},
},
},
],
},
parameters: {
struct_val: {
candidateCount: { int_val: 1 },
maxOutputTokens: { int_val: 1024 },
temperature: { float_val: 0.2 },
topP: { float_val: 0.8 },
topK: { int_val: 40 },
},
},
},
};
const result = formatGoogleInputs(input);
expect(JSON.stringify(result)).toEqual(JSON.stringify(expectedOutput));
});
it('helps create valid payload parts', () => {
const instances = {
context: 'context',
examples: [
{
input: {
author: 'user',
content: 'user input',
},
output: {
author: 'bot',
content: 'user output',
},
},
],
messages: [
{
author: 'user',
content: 'hi',
},
],
};
const expectedInstances = {
struct_val: {
context: { string_val: ['context'] },
examples: {
list_val: [
{
struct_val: {
input: {
struct_val: {
author: { string_val: ['user'] },
content: { string_val: ['user input'] },
},
},
output: {
struct_val: {
author: { string_val: ['bot'] },
content: { string_val: ['user output'] },
},
},
},
},
],
},
messages: {
list_val: [
{
struct_val: {
author: { string_val: ['user'] },
content: { string_val: ['hi'] },
},
},
],
},
},
};
const parameters = {
candidateCount: 1,
maxOutputTokens: 1024,
temperature: 0.2,
topP: 0.8,
topK: 40,
};
const expectedParameters = {
struct_val: {
candidateCount: { int_val: 1 },
maxOutputTokens: { int_val: 1024 },
temperature: { float_val: 0.2 },
topP: { float_val: 0.8 },
topK: { int_val: 40 },
},
};
const instancesResult = formatGoogleInputs(instances);
const parametersResult = formatGoogleInputs(parameters);
expect(JSON.stringify(instancesResult)).toEqual(JSON.stringify(expectedInstances));
expect(JSON.stringify(parametersResult)).toEqual(JSON.stringify(expectedParameters));
});
});

View File

@@ -1,4 +1,28 @@
const { HumanMessage, AIMessage, SystemMessage } = require('langchain/schema');
const { ToolMessage } = require('@langchain/core/messages');
const { EModelEndpoint, ContentTypes } = require('librechat-data-provider');
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
/**
* Formats a message to OpenAI Vision API payload format.
*
* @param {Object} params - The parameters for formatting.
* @param {Object} params.message - The message object to format.
* @param {string} [params.message.role] - The role of the message sender (must be 'user').
* @param {string} [params.message.content] - The text content of the message.
* @param {EModelEndpoint} [params.endpoint] - Identifier for specific endpoint handling
* @param {Array<string>} [params.image_urls] - The image_urls to attach to the message.
* @returns {(Object)} - The formatted message.
*/
const formatVisionMessage = ({ message, image_urls, endpoint }) => {
if (endpoint === EModelEndpoint.anthropic) {
message.content = [...image_urls, { type: ContentTypes.TEXT, text: message.content }];
return message;
}
message.content = [{ type: ContentTypes.TEXT, text: message.content }, ...image_urls];
return message;
};
/**
* Formats a message to OpenAI payload format based on the provided options.
@@ -10,12 +34,14 @@ const { HumanMessage, AIMessage, SystemMessage } = require('langchain/schema');
* @param {string} [params.message.sender] - The sender of the message.
* @param {string} [params.message.text] - The text content of the message.
* @param {string} [params.message.content] - The content of the message.
* @param {Array<string>} [params.message.image_urls] - The image_urls attached to the message for Vision API.
* @param {string} [params.userName] - The name of the user.
* @param {string} [params.assistantName] - The name of the assistant.
* @param {string} [params.endpoint] - Identifier for specific endpoint handling
* @param {boolean} [params.langChain=false] - Whether to return a LangChain message object.
* @returns {(Object|HumanMessage|AIMessage|SystemMessage)} - The formatted message.
*/
const formatMessage = ({ message, userName, assistantName, langChain = false }) => {
const formatMessage = ({ message, userName, assistantName, endpoint, langChain = false }) => {
let { role: _role, _name, sender, text, content: _content, lc_id } = message;
if (lc_id && lc_id[2] && !langChain) {
const roleMapping = {
@@ -26,12 +52,21 @@ const formatMessage = ({ message, userName, assistantName, langChain = false })
_role = roleMapping[lc_id[2]];
}
const role = _role ?? (sender && sender?.toLowerCase() === 'user' ? 'user' : 'assistant');
const content = text ?? _content ?? '';
const content = _content ?? text ?? '';
const formattedMessage = {
role,
content,
};
const { image_urls } = message;
if (Array.isArray(image_urls) && image_urls.length > 0 && role === 'user') {
return formatVisionMessage({
message: formattedMessage,
image_urls: message.image_urls,
endpoint,
});
}
if (_name) {
formattedMessage.name = _name;
}
@@ -97,4 +132,144 @@ const formatFromLangChain = (message) => {
};
};
module.exports = { formatMessage, formatLangChainMessages, formatFromLangChain };
/**
* Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.
*
* @param {Array<Partial<TMessage>>} payload - The array of messages to format.
* @returns {Array<(HumanMessage|AIMessage|SystemMessage|ToolMessage)>} - The array of formatted LangChain messages, including ToolMessages for tool calls.
*/
const formatAgentMessages = (payload) => {
const messages = [];
for (const message of payload) {
if (typeof message.content === 'string') {
message.content = [{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content }];
}
if (message.role !== 'assistant') {
messages.push(formatMessage({ message, langChain: true }));
continue;
}
let currentContent = [];
let lastAIMessage = null;
let hasReasoning = false;
for (const part of message.content) {
if (part.type === ContentTypes.TEXT && part.tool_call_ids) {
/*
If there's pending content, it needs to be aggregated as a single string to prepare for tool calls.
For Anthropic models, the "tool_calls" field on a message is only respected if content is a string.
*/
if (currentContent.length > 0) {
let content = currentContent.reduce((acc, curr) => {
if (curr.type === ContentTypes.TEXT) {
return `${acc}${curr[ContentTypes.TEXT]}\n`;
}
return acc;
}, '');
content = `${content}\n${part[ContentTypes.TEXT] ?? ''}`.trim();
lastAIMessage = new AIMessage({ content });
messages.push(lastAIMessage);
currentContent = [];
continue;
}
// Create a new AIMessage with this text and prepare for tool calls
lastAIMessage = new AIMessage({
content: part.text || '',
});
messages.push(lastAIMessage);
} else if (part.type === ContentTypes.TOOL_CALL) {
if (!lastAIMessage) {
throw new Error('Invalid tool call structure: No preceding AIMessage with tool_call_ids');
}
// Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it
const { output, args: _args, ...tool_call } = part.tool_call;
// TODO: investigate; args as dictionary may need to be provider-or-tool-specific
let args = _args;
try {
args = JSON.parse(_args);
} catch (e) {
if (typeof _args === 'string') {
args = { input: _args };
}
}
tool_call.args = args;
lastAIMessage.tool_calls.push(tool_call);
// Add the corresponding ToolMessage
messages.push(
new ToolMessage({
tool_call_id: tool_call.id,
name: tool_call.name,
content: output || '',
}),
);
} else if (part.type === ContentTypes.THINK) {
hasReasoning = true;
continue;
} else {
currentContent.push(part);
}
}
if (hasReasoning) {
currentContent = currentContent
.reduce((acc, curr) => {
if (curr.type === ContentTypes.TEXT) {
return `${acc}${curr[ContentTypes.TEXT]}\n`;
}
return acc;
}, '')
.trim();
}
if (currentContent.length > 0) {
messages.push(new AIMessage({ content: currentContent }));
}
}
return messages;
};
/**
* Formats an array of messages for LangChain, making sure all content fields are strings
* @param {Array<(HumanMessage|AIMessage|SystemMessage|ToolMessage)>} payload - The array of messages to format.
* @returns {Array<(HumanMessage|AIMessage|SystemMessage|ToolMessage)>} - The array of formatted LangChain messages, including ToolMessages for tool calls.
*/
const formatContentStrings = (payload) => {
const messages = [];
for (const message of payload) {
if (typeof message.content === 'string') {
continue;
}
if (!Array.isArray(message.content)) {
continue;
}
// Reduce text types to a single string, ignore all other types
const content = message.content.reduce((acc, curr) => {
if (curr.type === ContentTypes.TEXT) {
return `${acc}${curr[ContentTypes.TEXT]}\n`;
}
return acc;
}, '');
message.content = content.trim();
}
return messages;
};
module.exports = {
formatMessage,
formatFromLangChain,
formatAgentMessages,
formatContentStrings,
formatLangChainMessages,
};

View File

@@ -1,5 +1,6 @@
const { Constants } = require('librechat-data-provider');
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
const { formatMessage, formatLangChainMessages, formatFromLangChain } = require('./formatMessages');
const { HumanMessage, AIMessage, SystemMessage } = require('langchain/schema');
describe('formatMessage', () => {
it('formats user message', () => {
@@ -54,15 +55,13 @@ describe('formatMessage', () => {
_id: '6512cdfb92cbf69fea615331',
messageId: 'b620bf73-c5c3-4a38-b724-76886aac24c4',
__v: 0,
cancelled: false,
conversationId: '5c23d24f-941f-4aab-85df-127b596c8aa5',
createdAt: Date.now(),
error: false,
finish_reason: null,
isCreatedByUser: true,
isEdited: false,
model: null,
parentMessageId: '00000000-0000-0000-0000-000000000000',
parentMessageId: Constants.NO_PARENT,
sender: 'User',
text: 'hi',
tokenCount: 5,

View File

@@ -1,15 +1,21 @@
const addCacheControl = require('./addCacheControl');
const formatMessages = require('./formatMessages');
const summaryPrompts = require('./summaryPrompts');
const handleInputs = require('./handleInputs');
const instructions = require('./instructions');
const titlePrompts = require('./titlePrompts');
const truncateText = require('./truncateText');
const truncate = require('./truncate');
const createVisionPrompt = require('./createVisionPrompt');
const createContextHandlers = require('./createContextHandlers');
module.exports = {
addCacheControl,
...formatMessages,
...summaryPrompts,
...handleInputs,
...instructions,
...titlePrompts,
truncateText,
...truncate,
createVisionPrompt,
createContextHandlers,
};

View File

@@ -0,0 +1,495 @@
// Essential Components
const essentialComponents = {
avatar: {
componentName: 'Avatar',
importDocs: 'import { Avatar, AvatarFallback, AvatarImage } from "/components/ui/avatar"',
usageDocs: `
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>`,
},
button: {
componentName: 'Button',
importDocs: 'import { Button } from "/components/ui/button"',
usageDocs: `
<Button variant="outline">Button</Button>`,
},
card: {
componentName: 'Card',
importDocs: `
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "/components/ui/card"`,
usageDocs: `
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>`,
},
checkbox: {
componentName: 'Checkbox',
importDocs: 'import { Checkbox } from "/components/ui/checkbox"',
usageDocs: '<Checkbox />',
},
input: {
componentName: 'Input',
importDocs: 'import { Input } from "/components/ui/input"',
usageDocs: '<Input />',
},
label: {
componentName: 'Label',
importDocs: 'import { Label } from "/components/ui/label"',
usageDocs: '<Label htmlFor="email">Your email address</Label>',
},
radioGroup: {
componentName: 'RadioGroup',
importDocs: `
import { Label } from "/components/ui/label"
import { RadioGroup, RadioGroupItem } from "/components/ui/radio-group"`,
usageDocs: `
<RadioGroup defaultValue="option-one">
<div className="flex items-center space-x-2">
<RadioGroupItem value="option-one" id="option-one" />
<Label htmlFor="option-one">Option One</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="option-two" id="option-two" />
<Label htmlFor="option-two">Option Two</Label>
</div>
</RadioGroup>`,
},
select: {
componentName: 'Select',
importDocs: `
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "/components/ui/select"`,
usageDocs: `
<Select>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
<SelectItem value="light">Light</SelectItem>
<SelectItem value="dark">Dark</SelectItem>
<SelectItem value="system">System</SelectItem>
</SelectContent>
</Select>`,
},
textarea: {
componentName: 'Textarea',
importDocs: 'import { Textarea } from "/components/ui/textarea"',
usageDocs: '<Textarea />',
},
};
// Extra Components
const extraComponents = {
accordion: {
componentName: 'Accordion',
importDocs: `
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "/components/ui/accordion"`,
usageDocs: `
<Accordion type="single" collapsible>
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
</Accordion>`,
},
alertDialog: {
componentName: 'AlertDialog',
importDocs: `
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "/components/ui/alert-dialog"`,
usageDocs: `
<AlertDialog>
<AlertDialogTrigger>Open</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>`,
},
alert: {
componentName: 'Alert',
importDocs: `
import {
Alert,
AlertDescription,
AlertTitle,
} from "/components/ui/alert"`,
usageDocs: `
<Alert>
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components to your app using the cli.
</AlertDescription>
</Alert>`,
},
aspectRatio: {
componentName: 'AspectRatio',
importDocs: 'import { AspectRatio } from "/components/ui/aspect-ratio"',
usageDocs: `
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>`,
},
badge: {
componentName: 'Badge',
importDocs: 'import { Badge } from "/components/ui/badge"',
usageDocs: '<Badge>Badge</Badge>',
},
calendar: {
componentName: 'Calendar',
importDocs: 'import { Calendar } from "/components/ui/calendar"',
usageDocs: '<Calendar />',
},
carousel: {
componentName: 'Carousel',
importDocs: `
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "/components/ui/carousel"`,
usageDocs: `
<Carousel>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>`,
},
collapsible: {
componentName: 'Collapsible',
importDocs: `
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "/components/ui/collapsible"`,
usageDocs: `
<Collapsible>
<CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
<CollapsibleContent>
Yes. Free to use for personal and commercial projects. No attribution required.
</CollapsibleContent>
</Collapsible>`,
},
dialog: {
componentName: 'Dialog',
importDocs: `
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "/components/ui/dialog"`,
usageDocs: `
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>`,
},
dropdownMenu: {
componentName: 'DropdownMenu',
importDocs: `
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "/components/ui/dropdown-menu"`,
usageDocs: `
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuItem>Subscription</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>`,
},
menubar: {
componentName: 'Menubar',
importDocs: `
import {
Menubar,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarSeparator,
MenubarShortcut,
MenubarTrigger,
} from "/components/ui/menubar"`,
usageDocs: `
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
</MenubarItem>
<MenubarItem>New Window</MenubarItem>
<MenubarSeparator />
<MenubarItem>Share</MenubarItem>
<MenubarSeparator />
<MenubarItem>Print</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>`,
},
navigationMenu: {
componentName: 'NavigationMenu',
importDocs: `
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "/components/ui/navigation-menu"`,
usageDocs: `
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Item One</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Link</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>`,
},
popover: {
componentName: 'Popover',
importDocs: `
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "/components/ui/popover"`,
usageDocs: `
<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent>Place content for the popover here.</PopoverContent>
</Popover>`,
},
progress: {
componentName: 'Progress',
importDocs: 'import { Progress } from "/components/ui/progress"',
usageDocs: '<Progress value={33} />',
},
separator: {
componentName: 'Separator',
importDocs: 'import { Separator } from "/components/ui/separator"',
usageDocs: '<Separator />',
},
sheet: {
componentName: 'Sheet',
importDocs: `
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "/components/ui/sheet"`,
usageDocs: `
<Sheet>
<SheetTrigger>Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Are you sure absolutely sure?</SheetTitle>
<SheetDescription>
This action cannot be undone.
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>`,
},
skeleton: {
componentName: 'Skeleton',
importDocs: 'import { Skeleton } from "/components/ui/skeleton"',
usageDocs: '<Skeleton className="w-[100px] h-[20px] rounded-full" />',
},
slider: {
componentName: 'Slider',
importDocs: 'import { Slider } from "/components/ui/slider"',
usageDocs: '<Slider defaultValue={[33]} max={100} step={1} />',
},
switch: {
componentName: 'Switch',
importDocs: 'import { Switch } from "/components/ui/switch"',
usageDocs: '<Switch />',
},
table: {
componentName: 'Table',
importDocs: `
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "/components/ui/table"`,
usageDocs: `
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead className="w-[100px]">Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-medium">INV001</TableCell>
<TableCell>Paid</TableCell>
<TableCell>Credit Card</TableCell>
<TableCell className="text-right">$250.00</TableCell>
</TableRow>
</TableBody>
</Table>`,
},
tabs: {
componentName: 'Tabs',
importDocs: `
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "/components/ui/tabs"`,
usageDocs: `
<Tabs defaultValue="account" className="w-[400px]">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
</TabsList>
<TabsContent value="account">Make changes to your account here.</TabsContent>
<TabsContent value="password">Change your password here.</TabsContent>
</Tabs>`,
},
toast: {
componentName: 'Toast',
importDocs: `
import { useToast } from "/components/ui/use-toast"
import { Button } from "/components/ui/button"`,
usageDocs: `
export function ToastDemo() {
const { toast } = useToast()
return (
<Button
onClick={() => {
toast({
title: "Scheduled: Catch up",
description: "Friday, February 10, 2023 at 5:57 PM",
})
}}
>
Show Toast
</Button>
)
}`,
},
toggle: {
componentName: 'Toggle',
importDocs: 'import { Toggle } from "/components/ui/toggle"',
usageDocs: '<Toggle>Toggle</Toggle>',
},
tooltip: {
componentName: 'Tooltip',
importDocs: `
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "/components/ui/tooltip"`,
usageDocs: `
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Hover</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>`,
},
};
const components = Object.assign({}, essentialComponents, extraComponents);
module.exports = {
components,
};

View File

@@ -0,0 +1,50 @@
const dedent = require('dedent');
/**
* Generate system prompt for AI-assisted React component creation
* @param {Object} options - Configuration options
* @param {Object} options.components - Documentation for shadcn components
* @param {boolean} [options.useXML=false] - Whether to use XML-style formatting for component instructions
* @returns {string} The generated system prompt
*/
function generateShadcnPrompt(options) {
const { components, useXML = false } = options;
let systemPrompt = dedent`
## Additional Artifact Instructions for React Components: "application/vnd.react"
There are some prestyled components (primitives) available for use. Please use your best judgement to use any of these components if the app calls for one.
Here are the components that are available, along with how to import them, and how to use them:
${Object.values(components)
.map((component) => {
if (useXML) {
return dedent`
<component>
<name>${component.componentName}</name>
<import-instructions>${component.importDocs}</import-instructions>
<usage-instructions>${component.usageDocs}</usage-instructions>
</component>
`;
} else {
return dedent`
# ${component.componentName}
## Import Instructions
${component.importDocs}
## Usage Instructions
${component.usageDocs}
`;
}
})
.join('\n\n')}
`;
return systemPrompt;
}
module.exports = {
generateShadcnPrompt,
};

View File

@@ -1,4 +1,4 @@
const { PromptTemplate } = require('langchain/prompts');
const { PromptTemplate } = require('@langchain/core/prompts');
/*
* Without `{summary}` and `{new_lines}`, token count is 98
* We are counting this towards the max context tokens for summaries, +3 for the assistant label (101)

View File

@@ -2,7 +2,7 @@ const {
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
} = require('langchain/prompts');
} = require('@langchain/core/prompts');
const langPrompt = new ChatPromptTemplate({
promptMessages: [
@@ -27,7 +27,110 @@ ${convo}`,
return titlePrompt;
};
const titleInstruction =
'a concise, 5-word-or-less title for the conversation, using its same language, with no punctuation. Apply title case conventions appropriate for the language. Never directly mention the language name or the word "title"';
const titleFunctionPrompt = `In this environment you have access to a set of tools you can use to generate the conversation title.
You may call them like this:
<function_calls>
<invoke>
<tool_name>$TOOL_NAME</tool_name>
<parameters>
<$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>
...
</parameters>
</invoke>
</function_calls>
Here are the tools available:
<tools>
<tool_description>
<tool_name>submit_title</tool_name>
<description>
Submit a brief title in the conversation's language, following the parameter description closely.
</description>
<parameters>
<parameter>
<name>title</name>
<type>string</type>
<description>${titleInstruction}</description>
</parameter>
</parameters>
</tool_description>
</tools>`;
const genTranslationPrompt = (
translationPrompt,
) => `In this environment you have access to a set of tools you can use to translate text.
You may call them like this:
<function_calls>
<invoke>
<tool_name>$TOOL_NAME</tool_name>
<parameters>
<$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>
...
</parameters>
</invoke>
</function_calls>
Here are the tools available:
<tools>
<tool_description>
<tool_name>submit_translation</tool_name>
<description>
Submit a translation in the target language, following the parameter description and its language closely.
</description>
<parameters>
<parameter>
<name>translation</name>
<type>string</type>
<description>${translationPrompt}
ONLY include the generated translation without quotations, nor its related key</description>
</parameter>
</parameters>
</tool_description>
</tools>`;
/**
* Parses specified parameter from the provided prompt.
* @param {string} prompt - The prompt containing the desired parameter.
* @param {string} paramName - The name of the parameter to extract.
* @returns {string} The parsed parameter's value or a default value if not found.
*/
function parseParamFromPrompt(prompt, paramName) {
// Handle null/undefined prompt
if (!prompt) {
return `No ${paramName} provided`;
}
// Try original format first: <title>value</title>
const simpleRegex = new RegExp(`<${paramName}>(.*?)</${paramName}>`, 's');
const simpleMatch = prompt.match(simpleRegex);
if (simpleMatch) {
return simpleMatch[1].trim();
}
// Try parameter format: <parameter name="title">value</parameter>
const paramRegex = new RegExp(`<parameter name="${paramName}">(.*?)</parameter>`, 's');
const paramMatch = prompt.match(paramRegex);
if (paramMatch) {
return paramMatch[1].trim();
}
if (prompt && prompt.length) {
return `NO TOOL INVOCATION: ${prompt}`;
}
return `No ${paramName} provided`;
}
module.exports = {
langPrompt,
titleInstruction,
createTitlePrompt,
titleFunctionPrompt,
parseParamFromPrompt,
genTranslationPrompt,
};

View File

@@ -0,0 +1,73 @@
const { parseParamFromPrompt } = require('./titlePrompts');
describe('parseParamFromPrompt', () => {
// Original simple format tests
test('extracts parameter from simple format', () => {
const prompt = '<title>Simple Title</title>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('Simple Title');
});
// Parameter format tests
test('extracts parameter from parameter format', () => {
const prompt =
'<function_calls> <invoke name="submit_title"> <parameter name="title">Complex Title</parameter> </invoke>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('Complex Title');
});
// Edge cases and error handling
test('returns NO TOOL INVOCATION message for non-matching content', () => {
const prompt = 'Some random text without parameters';
expect(parseParamFromPrompt(prompt, 'title')).toBe(
'NO TOOL INVOCATION: Some random text without parameters',
);
});
test('returns default message for empty prompt', () => {
expect(parseParamFromPrompt('', 'title')).toBe('No title provided');
});
test('returns default message for null prompt', () => {
expect(parseParamFromPrompt(null, 'title')).toBe('No title provided');
});
// Multiple parameter tests
test('works with different parameter names', () => {
const prompt = '<name>John Doe</name>';
expect(parseParamFromPrompt(prompt, 'name')).toBe('John Doe');
});
test('handles multiline content', () => {
const prompt = `<parameter name="description">This is a
multiline
description</parameter>`;
expect(parseParamFromPrompt(prompt, 'description')).toBe(
'This is a\n multiline\n description',
);
});
// Whitespace handling
test('trims whitespace from extracted content', () => {
const prompt = '<title> Padded Title </title>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('Padded Title');
});
test('handles whitespace in parameter format', () => {
const prompt = '<parameter name="title"> Padded Parameter Title </parameter>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('Padded Parameter Title');
});
// Invalid format tests
test('handles malformed tags', () => {
const prompt = '<title>Incomplete Tag';
expect(parseParamFromPrompt(prompt, 'title')).toBe('NO TOOL INVOCATION: <title>Incomplete Tag');
});
test('handles empty tags', () => {
const prompt = '<title></title>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('');
});
test('handles empty parameter tags', () => {
const prompt = '<parameter name="title"></parameter>';
expect(parseParamFromPrompt(prompt, 'title')).toBe('');
});
});

View File

@@ -0,0 +1,115 @@
const MAX_CHAR = 255;
/**
* Truncates a given text to a specified maximum length, appending ellipsis and a notification
* if the original text exceeds the maximum length.
*
* @param {string} text - The text to be truncated.
* @param {number} [maxLength=MAX_CHAR] - The maximum length of the text after truncation. Defaults to MAX_CHAR.
* @returns {string} The truncated text if the original text length exceeds maxLength, otherwise returns the original text.
*/
function truncateText(text, maxLength = MAX_CHAR) {
if (text.length > maxLength) {
return `${text.slice(0, maxLength)}... [text truncated for brevity]`;
}
return text;
}
/**
* Truncates a given text to a specified maximum length by showing the first half and the last half of the text,
* separated by ellipsis. This method ensures the output does not exceed the maximum length, including the addition
* of ellipsis and notification if the original text exceeds the maximum length.
*
* @param {string} text - The text to be truncated.
* @param {number} [maxLength=MAX_CHAR] - The maximum length of the output text after truncation. Defaults to MAX_CHAR.
* @returns {string} The truncated text showing the first half and the last half, or the original text if it does not exceed maxLength.
*/
function smartTruncateText(text, maxLength = MAX_CHAR) {
const ellipsis = '...';
const notification = ' [text truncated for brevity]';
const halfMaxLength = Math.floor((maxLength - ellipsis.length - notification.length) / 2);
if (text.length > maxLength) {
const startLastHalf = text.length - halfMaxLength;
return `${text.slice(0, halfMaxLength)}${ellipsis}${text.slice(startLastHalf)}${notification}`;
}
return text;
}
/**
* @param {TMessage[]} _messages
* @param {number} maxContextTokens
* @param {function({role: string, content: TMessageContent[]}): number} getTokenCountForMessage
*
* @returns {{
* dbMessages: TMessage[],
* editedIndices: number[]
* }}
*/
function truncateToolCallOutputs(_messages, maxContextTokens, getTokenCountForMessage) {
const THRESHOLD_PERCENTAGE = 0.5;
const targetTokenLimit = maxContextTokens * THRESHOLD_PERCENTAGE;
let currentTokenCount = 3;
const messages = [..._messages];
const processedMessages = [];
let currentIndex = messages.length;
const editedIndices = new Set();
while (messages.length > 0) {
currentIndex--;
const message = messages.pop();
currentTokenCount += message.tokenCount;
if (currentTokenCount < targetTokenLimit) {
processedMessages.push(message);
continue;
}
if (!message.content || !Array.isArray(message.content)) {
processedMessages.push(message);
continue;
}
const toolCallIndices = message.content
.map((item, index) => (item.type === 'tool_call' ? index : -1))
.filter((index) => index !== -1)
.reverse();
if (toolCallIndices.length === 0) {
processedMessages.push(message);
continue;
}
const newContent = [...message.content];
// Truncate all tool outputs since we're over threshold
for (const index of toolCallIndices) {
const toolCall = newContent[index].tool_call;
if (!toolCall || !toolCall.output) {
continue;
}
editedIndices.add(currentIndex);
newContent[index] = {
...newContent[index],
tool_call: {
...toolCall,
output: '[OUTPUT_OMITTED_FOR_BREVITY]',
},
};
}
const truncatedMessage = {
...message,
content: newContent,
tokenCount: getTokenCountForMessage({ role: 'assistant', content: newContent }),
};
processedMessages.push(truncatedMessage);
}
return { dbMessages: processedMessages.reverse(), editedIndices: Array.from(editedIndices) };
}
module.exports = { truncateText, smartTruncateText, truncateToolCallOutputs };

View File

@@ -1,10 +0,0 @@
const MAX_CHAR = 255;
function truncateText(text) {
if (text.length > MAX_CHAR) {
return `${text.slice(0, MAX_CHAR)}... [text truncated for brevity]`;
}
return text;
}
module.exports = truncateText;

View File

@@ -1,4 +1,7 @@
const AnthropicClient = require('../AnthropicClient');
const { SplitStreamHandler } = require('@librechat/agents');
const { anthropicSettings } = require('librechat-data-provider');
const AnthropicClient = require('~/app/clients/AnthropicClient');
const HUMAN_PROMPT = '\n\nHuman:';
const AI_PROMPT = '\n\nAssistant:';
@@ -22,7 +25,7 @@ describe('AnthropicClient', () => {
const options = {
modelOptions: {
model,
temperature: 0.7,
temperature: anthropicSettings.temperature.default,
},
};
client = new AnthropicClient('test-api-key');
@@ -33,7 +36,42 @@ describe('AnthropicClient', () => {
it('should set the options correctly', () => {
expect(client.apiKey).toBe('test-api-key');
expect(client.modelOptions.model).toBe(model);
expect(client.modelOptions.temperature).toBe(0.7);
expect(client.modelOptions.temperature).toBe(anthropicSettings.temperature.default);
});
it('should set legacy maxOutputTokens for non-Claude-3 models', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-2',
maxOutputTokens: anthropicSettings.maxOutputTokens.default,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
it('should not set maxOutputTokens if not provided', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-3',
},
});
expect(client.modelOptions.maxOutputTokens).toBeUndefined();
});
it('should not set legacy maxOutputTokens for Claude-3 models', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-3-opus-20240229',
maxOutputTokens: anthropicSettings.legacy.maxOutputTokens.default,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
});
@@ -136,4 +174,510 @@ describe('AnthropicClient', () => {
expect(prompt).toContain('You are Claude-2');
});
});
describe('getClient', () => {
it('should set legacy maxOutputTokens for non-Claude-3 models', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-2',
maxOutputTokens: anthropicSettings.legacy.maxOutputTokens.default,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
it('should not set legacy maxOutputTokens for Claude-3 models', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-3-opus-20240229',
maxOutputTokens: anthropicSettings.legacy.maxOutputTokens.default,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
it('should add "max-tokens" & "prompt-caching" beta header for claude-3-5-sonnet model', () => {
const client = new AnthropicClient('test-api-key');
const modelOptions = {
model: 'claude-3-5-sonnet-20241022',
};
client.setOptions({ modelOptions, promptCache: true });
const anthropicClient = client.getClient(modelOptions);
expect(anthropicClient._options.defaultHeaders).toBeDefined();
expect(anthropicClient._options.defaultHeaders).toHaveProperty('anthropic-beta');
expect(anthropicClient._options.defaultHeaders['anthropic-beta']).toBe(
'max-tokens-3-5-sonnet-2024-07-15,prompt-caching-2024-07-31',
);
});
it('should add "prompt-caching" beta header for claude-3-haiku model', () => {
const client = new AnthropicClient('test-api-key');
const modelOptions = {
model: 'claude-3-haiku-2028',
};
client.setOptions({ modelOptions, promptCache: true });
const anthropicClient = client.getClient(modelOptions);
expect(anthropicClient._options.defaultHeaders).toBeDefined();
expect(anthropicClient._options.defaultHeaders).toHaveProperty('anthropic-beta');
expect(anthropicClient._options.defaultHeaders['anthropic-beta']).toBe(
'prompt-caching-2024-07-31',
);
});
it('should add "prompt-caching" beta header for claude-3-opus model', () => {
const client = new AnthropicClient('test-api-key');
const modelOptions = {
model: 'claude-3-opus-2028',
};
client.setOptions({ modelOptions, promptCache: true });
const anthropicClient = client.getClient(modelOptions);
expect(anthropicClient._options.defaultHeaders).toBeDefined();
expect(anthropicClient._options.defaultHeaders).toHaveProperty('anthropic-beta');
expect(anthropicClient._options.defaultHeaders['anthropic-beta']).toBe(
'prompt-caching-2024-07-31',
);
});
it('should not add beta header for claude-3-5-sonnet-latest model', () => {
const client = new AnthropicClient('test-api-key');
const modelOptions = {
model: 'anthropic/claude-3-5-sonnet-latest',
};
client.setOptions({ modelOptions, promptCache: true });
const anthropicClient = client.getClient(modelOptions);
expect(anthropicClient.defaultHeaders).not.toHaveProperty('anthropic-beta');
});
it('should not add beta header for other models', () => {
const client = new AnthropicClient('test-api-key');
client.setOptions({
modelOptions: {
model: 'claude-2',
},
});
const anthropicClient = client.getClient();
expect(anthropicClient.defaultHeaders).not.toHaveProperty('anthropic-beta');
});
});
describe('calculateCurrentTokenCount', () => {
let client;
beforeEach(() => {
client = new AnthropicClient('test-api-key');
});
it('should calculate correct token count when usage is provided', () => {
const tokenCountMap = {
msg1: 10,
msg2: 20,
currentMsg: 30,
};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 70,
output_tokens: 50,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(40); // 70 - (10 + 20) = 40
});
it('should return original estimate if calculation results in negative value', () => {
const tokenCountMap = {
msg1: 40,
msg2: 50,
currentMsg: 30,
};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 80,
output_tokens: 50,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(30); // Original estimate
});
it('should handle cache creation and read input tokens', () => {
const tokenCountMap = {
msg1: 10,
msg2: 20,
currentMsg: 30,
};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 50,
cache_creation_input_tokens: 10,
cache_read_input_tokens: 20,
output_tokens: 40,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(50); // (50 + 10 + 20) - (10 + 20) = 50
});
it('should handle missing usage properties', () => {
const tokenCountMap = {
msg1: 10,
msg2: 20,
currentMsg: 30,
};
const currentMessageId = 'currentMsg';
const usage = {
output_tokens: 40,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(30); // Original estimate
});
it('should handle empty tokenCountMap', () => {
const tokenCountMap = {};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 50,
output_tokens: 40,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(50);
expect(Number.isNaN(result)).toBe(false);
});
it('should handle zero values in usage', () => {
const tokenCountMap = {
msg1: 10,
currentMsg: 20,
};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 0,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
output_tokens: 0,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(20); // Should return original estimate
expect(Number.isNaN(result)).toBe(false);
});
it('should handle undefined usage', () => {
const tokenCountMap = {
msg1: 10,
currentMsg: 20,
};
const currentMessageId = 'currentMsg';
const usage = undefined;
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(20); // Should return original estimate
expect(Number.isNaN(result)).toBe(false);
});
it('should handle non-numeric values in tokenCountMap', () => {
const tokenCountMap = {
msg1: 'ten',
currentMsg: 20,
};
const currentMessageId = 'currentMsg';
const usage = {
input_tokens: 30,
output_tokens: 10,
};
const result = client.calculateCurrentTokenCount({ tokenCountMap, currentMessageId, usage });
expect(result).toBe(30); // Should return 30 (input_tokens) - 0 (ignored 'ten') = 30
expect(Number.isNaN(result)).toBe(false);
});
});
describe('maxOutputTokens handling for different models', () => {
it('should not cap maxOutputTokens for Claude 3.5 Sonnet models', () => {
const client = new AnthropicClient('test-api-key');
const highTokenValue = anthropicSettings.legacy.maxOutputTokens.default * 10;
client.setOptions({
modelOptions: {
model: 'claude-3-5-sonnet',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(highTokenValue);
// Test with decimal notation
client.setOptions({
modelOptions: {
model: 'claude-3.5-sonnet',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(highTokenValue);
});
it('should not cap maxOutputTokens for Claude 3.7 models', () => {
const client = new AnthropicClient('test-api-key');
const highTokenValue = anthropicSettings.legacy.maxOutputTokens.default * 2;
client.setOptions({
modelOptions: {
model: 'claude-3-7-sonnet',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(highTokenValue);
// Test with decimal notation
client.setOptions({
modelOptions: {
model: 'claude-3.7-sonnet',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(highTokenValue);
});
it('should cap maxOutputTokens for Claude 3.5 Haiku models', () => {
const client = new AnthropicClient('test-api-key');
const highTokenValue = anthropicSettings.legacy.maxOutputTokens.default * 2;
client.setOptions({
modelOptions: {
model: 'claude-3-5-haiku',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
// Test with decimal notation
client.setOptions({
modelOptions: {
model: 'claude-3.5-haiku',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
it('should cap maxOutputTokens for Claude 3 Haiku and Opus models', () => {
const client = new AnthropicClient('test-api-key');
const highTokenValue = anthropicSettings.legacy.maxOutputTokens.default * 2;
// Test haiku
client.setOptions({
modelOptions: {
model: 'claude-3-haiku',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
// Test opus
client.setOptions({
modelOptions: {
model: 'claude-3-opus',
maxOutputTokens: highTokenValue,
},
});
expect(client.modelOptions.maxOutputTokens).toBe(
anthropicSettings.legacy.maxOutputTokens.default,
);
});
});
describe('topK/topP parameters for different models', () => {
beforeEach(() => {
// Mock the SplitStreamHandler
jest.spyOn(SplitStreamHandler.prototype, 'handle').mockImplementation(() => {});
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should include top_k and top_p parameters for non-claude-3.7 models', async () => {
const client = new AnthropicClient('test-api-key');
// Create a mock async generator function
async function* mockAsyncGenerator() {
yield { type: 'message_start', message: { usage: {} } };
yield { delta: { text: 'Test response' } };
yield { type: 'message_delta', usage: {} };
}
// Mock createResponse to return the async generator
jest.spyOn(client, 'createResponse').mockImplementation(() => {
return mockAsyncGenerator();
});
client.setOptions({
modelOptions: {
model: 'claude-3-opus',
temperature: 0.7,
topK: 10,
topP: 0.9,
},
});
// Mock getClient to capture the request options
let capturedOptions = null;
jest.spyOn(client, 'getClient').mockImplementation((options) => {
capturedOptions = options;
return {};
});
const payload = [{ role: 'user', content: 'Test message' }];
await client.sendCompletion(payload, {});
// Check the options passed to getClient
expect(capturedOptions).toHaveProperty('top_k', 10);
expect(capturedOptions).toHaveProperty('top_p', 0.9);
});
it('should include top_k and top_p parameters for claude-3-5-sonnet models', async () => {
const client = new AnthropicClient('test-api-key');
// Create a mock async generator function
async function* mockAsyncGenerator() {
yield { type: 'message_start', message: { usage: {} } };
yield { delta: { text: 'Test response' } };
yield { type: 'message_delta', usage: {} };
}
// Mock createResponse to return the async generator
jest.spyOn(client, 'createResponse').mockImplementation(() => {
return mockAsyncGenerator();
});
client.setOptions({
modelOptions: {
model: 'claude-3-5-sonnet',
temperature: 0.7,
topK: 10,
topP: 0.9,
},
});
// Mock getClient to capture the request options
let capturedOptions = null;
jest.spyOn(client, 'getClient').mockImplementation((options) => {
capturedOptions = options;
return {};
});
const payload = [{ role: 'user', content: 'Test message' }];
await client.sendCompletion(payload, {});
// Check the options passed to getClient
expect(capturedOptions).toHaveProperty('top_k', 10);
expect(capturedOptions).toHaveProperty('top_p', 0.9);
});
it('should not include top_k and top_p parameters for claude-3-7-sonnet models', async () => {
const client = new AnthropicClient('test-api-key');
// Create a mock async generator function
async function* mockAsyncGenerator() {
yield { type: 'message_start', message: { usage: {} } };
yield { delta: { text: 'Test response' } };
yield { type: 'message_delta', usage: {} };
}
// Mock createResponse to return the async generator
jest.spyOn(client, 'createResponse').mockImplementation(() => {
return mockAsyncGenerator();
});
client.setOptions({
modelOptions: {
model: 'claude-3-7-sonnet',
temperature: 0.7,
topK: 10,
topP: 0.9,
},
});
// Mock getClient to capture the request options
let capturedOptions = null;
jest.spyOn(client, 'getClient').mockImplementation((options) => {
capturedOptions = options;
return {};
});
const payload = [{ role: 'user', content: 'Test message' }];
await client.sendCompletion(payload, {});
// Check the options passed to getClient
expect(capturedOptions).not.toHaveProperty('top_k');
expect(capturedOptions).not.toHaveProperty('top_p');
});
it('should not include top_k and top_p parameters for models with decimal notation (claude-3.7)', async () => {
const client = new AnthropicClient('test-api-key');
// Create a mock async generator function
async function* mockAsyncGenerator() {
yield { type: 'message_start', message: { usage: {} } };
yield { delta: { text: 'Test response' } };
yield { type: 'message_delta', usage: {} };
}
// Mock createResponse to return the async generator
jest.spyOn(client, 'createResponse').mockImplementation(() => {
return mockAsyncGenerator();
});
client.setOptions({
modelOptions: {
model: 'claude-3.7-sonnet',
temperature: 0.7,
topK: 10,
topP: 0.9,
},
});
// Mock getClient to capture the request options
let capturedOptions = null;
jest.spyOn(client, 'getClient').mockImplementation((options) => {
capturedOptions = options;
return {};
});
const payload = [{ role: 'user', content: 'Test message' }];
await client.sendCompletion(payload, {});
// Check the options passed to getClient
expect(capturedOptions).not.toHaveProperty('top_k');
expect(capturedOptions).not.toHaveProperty('top_p');
});
});
});

View File

@@ -1,21 +1,36 @@
const { Constants } = require('librechat-data-provider');
const { initializeFakeClient } = require('./FakeClient');
jest.mock('../../../lib/db/connectDb');
jest.mock('../../../models', () => {
return function () {
return {
save: jest.fn(),
deleteConvos: jest.fn(),
getConvo: jest.fn(),
getMessages: jest.fn(),
saveMessage: jest.fn(),
updateMessage: jest.fn(),
saveConvo: jest.fn(),
};
};
});
jest.mock('~/lib/db/connectDb');
jest.mock('~/models', () => ({
User: jest.fn(),
Key: jest.fn(),
Session: jest.fn(),
Balance: jest.fn(),
Transaction: jest.fn(),
getMessages: jest.fn().mockResolvedValue([]),
saveMessage: jest.fn(),
updateMessage: jest.fn(),
deleteMessagesSince: jest.fn(),
deleteMessages: jest.fn(),
getConvoTitle: jest.fn(),
getConvo: jest.fn(),
saveConvo: jest.fn(),
deleteConvos: jest.fn(),
getPreset: jest.fn(),
getPresets: jest.fn(),
savePreset: jest.fn(),
deletePresets: jest.fn(),
findFileById: jest.fn(),
createFile: jest.fn(),
updateFile: jest.fn(),
deleteFile: jest.fn(),
deleteFiles: jest.fn(),
getFiles: jest.fn(),
updateFileUsage: jest.fn(),
}));
jest.mock('langchain/chat_models/openai', () => {
jest.mock('@langchain/openai', () => {
return {
ChatOpenAI: jest.fn().mockImplementation(() => {
return {};
@@ -46,7 +61,7 @@ describe('BaseClient', () => {
const options = {
// debug: true,
modelOptions: {
model: 'gpt-3.5-turbo',
model: 'gpt-4o-mini',
temperature: 0,
},
};
@@ -73,6 +88,19 @@ describe('BaseClient', () => {
const messages = [{ content: 'Hello' }, { content: 'How are you?' }, { content: 'Goodbye' }];
const instructions = { content: 'Please respond to the question.' };
const result = TestClient.addInstructions(messages, instructions);
const expected = [
{ content: 'Please respond to the question.' },
{ content: 'Hello' },
{ content: 'How are you?' },
{ content: 'Goodbye' },
];
expect(result).toEqual(expected);
});
test('returns the input messages with instructions properly added when addInstructions() with legacy flag', () => {
const messages = [{ content: 'Hello' }, { content: 'How are you?' }, { content: 'Goodbye' }];
const instructions = { content: 'Please respond to the question.' };
const result = TestClient.addInstructions(messages, instructions, true);
const expected = [
{ content: 'Hello' },
{ content: 'How are you?' },
@@ -131,7 +159,7 @@ describe('BaseClient', () => {
expectedMessagesToRefine?.[expectedMessagesToRefine.length - 1] ?? {};
const expectedIndex = messages.findIndex((msg) => msg.content === lastExpectedMessage?.content);
const result = await TestClient.getMessagesWithinTokenLimit(messages);
const result = await TestClient.getMessagesWithinTokenLimit({ messages });
expect(result.context).toEqual(expectedContext);
expect(result.summaryIndex).toEqual(expectedIndex);
@@ -167,7 +195,7 @@ describe('BaseClient', () => {
expectedMessagesToRefine?.[expectedMessagesToRefine.length - 1] ?? {};
const expectedIndex = messages.findIndex((msg) => msg.content === lastExpectedMessage?.content);
const result = await TestClient.getMessagesWithinTokenLimit(messages);
const result = await TestClient.getMessagesWithinTokenLimit({ messages });
expect(result.context).toEqual(expectedContext);
expect(result.summaryIndex).toEqual(expectedIndex);
@@ -175,66 +203,6 @@ describe('BaseClient', () => {
expect(result.messagesToRefine).toEqual(expectedMessagesToRefine);
});
test('handles context strategy correctly in handleContextStrategy()', async () => {
TestClient.addInstructions = jest
.fn()
.mockReturnValue([
{ content: 'Hello' },
{ content: 'How can I help you?' },
{ content: 'Please provide more details.' },
{ content: 'I can assist you with that.' },
]);
TestClient.getMessagesWithinTokenLimit = jest.fn().mockReturnValue({
context: [
{ content: 'How can I help you?' },
{ content: 'Please provide more details.' },
{ content: 'I can assist you with that.' },
],
remainingContextTokens: 80,
messagesToRefine: [{ content: 'Hello' }],
summaryIndex: 3,
});
TestClient.getTokenCount = jest.fn().mockReturnValue(40);
const instructions = { content: 'Please provide more details.' };
const orderedMessages = [
{ content: 'Hello' },
{ content: 'How can I help you?' },
{ content: 'Please provide more details.' },
{ content: 'I can assist you with that.' },
];
const formattedMessages = [
{ content: 'Hello' },
{ content: 'How can I help you?' },
{ content: 'Please provide more details.' },
{ content: 'I can assist you with that.' },
];
const expectedResult = {
payload: [
{
role: 'system',
content: 'Refined answer',
},
{ content: 'How can I help you?' },
{ content: 'Please provide more details.' },
{ content: 'I can assist you with that.' },
],
promptTokens: expect.any(Number),
tokenCountMap: {},
messages: expect.any(Array),
};
TestClient.shouldSummarize = true;
const result = await TestClient.handleContextStrategy({
instructions,
orderedMessages,
formattedMessages,
});
expect(result).toEqual(expectedResult);
});
describe('getMessagesForConversation', () => {
it('should return an empty array if the parentMessageId does not exist', () => {
const result = TestClient.constructor.getMessagesForConversation({
@@ -293,7 +261,7 @@ describe('BaseClient', () => {
const unorderedMessages = [
{ id: '3', parentMessageId: '2', text: 'Message 3' },
{ id: '2', parentMessageId: '1', text: 'Message 2' },
{ id: '1', parentMessageId: '00000000-0000-0000-0000-000000000000', text: 'Message 1' },
{ id: '1', parentMessageId: Constants.NO_PARENT, text: 'Message 1' },
];
it('should return ordered messages based on parentMessageId', () => {
@@ -302,7 +270,7 @@ describe('BaseClient', () => {
parentMessageId: '3',
});
expect(result).toEqual([
{ id: '1', parentMessageId: '00000000-0000-0000-0000-000000000000', text: 'Message 1' },
{ id: '1', parentMessageId: Constants.NO_PARENT, text: 'Message 1' },
{ id: '2', parentMessageId: '1', text: 'Message 2' },
{ id: '3', parentMessageId: '2', text: 'Message 3' },
]);
@@ -529,9 +497,9 @@ describe('BaseClient', () => {
);
});
test('setOptions is called with the correct arguments', async () => {
test('setOptions is called with the correct arguments only when replaceOptions is set to true', async () => {
TestClient.setOptions = jest.fn();
const opts = { conversationId: '123', parentMessageId: '456' };
const opts = { conversationId: '123', parentMessageId: '456', replaceOptions: true };
await TestClient.sendMessage('Hello, world!', opts);
expect(TestClient.setOptions).toHaveBeenCalledWith(opts);
TestClient.setOptions.mockClear();
@@ -550,18 +518,24 @@ describe('BaseClient', () => {
const getReqData = jest.fn();
const opts = { getReqData };
const response = await TestClient.sendMessage('Hello, world!', opts);
expect(getReqData).toHaveBeenCalledWith({
userMessage: expect.objectContaining({ text: 'Hello, world!' }),
conversationId: response.conversationId,
responseMessageId: response.messageId,
});
expect(getReqData).toHaveBeenCalledWith(
expect.objectContaining({
userMessage: expect.objectContaining({ text: 'Hello, world!' }),
conversationId: response.conversationId,
responseMessageId: response.messageId,
}),
);
});
test('onStart is called with the correct arguments', async () => {
const onStart = jest.fn();
const opts = { onStart };
await TestClient.sendMessage('Hello, world!', opts);
expect(onStart).toHaveBeenCalledWith(expect.objectContaining({ text: 'Hello, world!' }));
expect(onStart).toHaveBeenCalledWith(
expect.objectContaining({ text: 'Hello, world!' }),
expect.any(String),
);
});
test('saveMessageToDatabase is called with the correct arguments', async () => {
@@ -594,9 +568,9 @@ describe('BaseClient', () => {
test('getTokenCount for response is called with the correct arguments', async () => {
const tokenCountMap = {}; // Mock tokenCountMap
TestClient.buildMessages.mockReturnValue({ prompt: [], tokenCountMap });
TestClient.getTokenCount = jest.fn();
TestClient.getTokenCountForResponse = jest.fn();
const response = await TestClient.sendMessage('Hello, world!', {});
expect(TestClient.getTokenCount).toHaveBeenCalledWith(response.text);
expect(TestClient.getTokenCountForResponse).toHaveBeenCalledWith(response);
});
test('returns an object with the correct shape', async () => {
@@ -612,5 +586,140 @@ describe('BaseClient', () => {
}),
);
});
test('userMessagePromise is awaited before saving response message', async () => {
// Mock the saveMessageToDatabase method
TestClient.saveMessageToDatabase = jest.fn().mockImplementation(() => {
return new Promise((resolve) => setTimeout(resolve, 100)); // Simulate a delay
});
// Send a message
const messagePromise = TestClient.sendMessage('Hello, world!');
// Wait a short time to ensure the user message save has started
await new Promise((resolve) => setTimeout(resolve, 50));
// Check that saveMessageToDatabase has been called once (for the user message)
expect(TestClient.saveMessageToDatabase).toHaveBeenCalledTimes(1);
// Wait for the message to be fully processed
await messagePromise;
// Check that saveMessageToDatabase has been called twice (once for user message, once for response)
expect(TestClient.saveMessageToDatabase).toHaveBeenCalledTimes(2);
// Check the order of calls
const calls = TestClient.saveMessageToDatabase.mock.calls;
expect(calls[0][0].isCreatedByUser).toBe(true); // First call should be for user message
expect(calls[1][0].isCreatedByUser).toBe(false); // Second call should be for response message
});
});
describe('getMessagesWithinTokenLimit with instructions', () => {
test('should always include instructions when present', async () => {
TestClient.maxContextTokens = 50;
const instructions = {
role: 'system',
content: 'System instructions',
tokenCount: 20,
};
const messages = [
instructions,
{ role: 'user', content: 'Hello', tokenCount: 10 },
{ role: 'assistant', content: 'Hi there', tokenCount: 15 },
];
const result = await TestClient.getMessagesWithinTokenLimit({
messages,
instructions,
});
expect(result.context[0]).toBe(instructions);
expect(result.remainingContextTokens).toBe(2);
});
test('should handle case when messages exceed limit but instructions must be preserved', async () => {
TestClient.maxContextTokens = 30;
const instructions = {
role: 'system',
content: 'System instructions',
tokenCount: 20,
};
const messages = [
instructions,
{ role: 'user', content: 'Hello', tokenCount: 10 },
{ role: 'assistant', content: 'Hi there', tokenCount: 15 },
];
const result = await TestClient.getMessagesWithinTokenLimit({
messages,
instructions,
});
// Should only include instructions and the last message that fits
expect(result.context).toHaveLength(1);
expect(result.context[0].content).toBe(instructions.content);
expect(result.messagesToRefine).toHaveLength(2);
expect(result.remainingContextTokens).toBe(7); // 30 - 20 - 3 (assistant label)
});
test('should work correctly without instructions (1/2)', async () => {
TestClient.maxContextTokens = 50;
const messages = [
{ role: 'user', content: 'Hello', tokenCount: 10 },
{ role: 'assistant', content: 'Hi there', tokenCount: 15 },
];
const result = await TestClient.getMessagesWithinTokenLimit({
messages,
});
expect(result.context).toHaveLength(2);
expect(result.remainingContextTokens).toBe(22); // 50 - 10 - 15 - 3(assistant label)
expect(result.messagesToRefine).toHaveLength(0);
});
test('should work correctly without instructions (2/2)', async () => {
TestClient.maxContextTokens = 30;
const messages = [
{ role: 'user', content: 'Hello', tokenCount: 10 },
{ role: 'assistant', content: 'Hi there', tokenCount: 20 },
];
const result = await TestClient.getMessagesWithinTokenLimit({
messages,
});
expect(result.context).toHaveLength(1);
expect(result.remainingContextTokens).toBe(7);
expect(result.messagesToRefine).toHaveLength(1);
});
test('should handle case when only instructions fit within limit', async () => {
TestClient.maxContextTokens = 25;
const instructions = {
role: 'system',
content: 'System instructions',
tokenCount: 20,
};
const messages = [
instructions,
{ role: 'user', content: 'Hello', tokenCount: 10 },
{ role: 'assistant', content: 'Hi there', tokenCount: 15 },
];
const result = await TestClient.getMessagesWithinTokenLimit({
messages,
instructions,
});
expect(result.context).toHaveLength(1);
expect(result.context[0]).toBe(instructions);
expect(result.messagesToRefine).toHaveLength(2);
expect(result.remainingContextTokens).toBe(2); // 25 - 20 - 3(assistant label)
});
});
});

View File

@@ -40,9 +40,9 @@ class FakeClient extends BaseClient {
};
}
this.maxContextTokens = getModelMaxTokens(this.modelOptions.model) ?? 4097;
this.maxContextTokens =
this.options.maxContextTokens ?? getModelMaxTokens(this.modelOptions.model) ?? 4097;
}
getCompletion() {}
buildMessages() {}
getTokenCount(str) {
return str.length;
@@ -86,6 +86,19 @@ const initializeFakeClient = (apiKey, options, fakeMessages) => {
return 'Mock response text';
});
// eslint-disable-next-line no-unused-vars
TestClient.getCompletion = jest.fn().mockImplementation(async (..._args) => {
return {
choices: [
{
message: {
content: 'Mock response text',
},
},
],
};
});
TestClient.buildMessages = jest.fn(async (messages, parentMessageId) => {
const orderedMessages = TestClient.constructor.getMessagesForConversation({
messages,

View File

@@ -1,10 +1,148 @@
jest.mock('~/cache/getLogStores');
require('dotenv').config();
const OpenAI = require('openai');
const getLogStores = require('~/cache/getLogStores');
const { fetchEventSource } = require('@waylaidwanderer/fetch-event-source');
const { genAzureChatCompletion } = require('~/utils/azureUtils');
const OpenAIClient = require('../OpenAIClient');
jest.mock('meilisearch');
jest.mock('~/lib/db/connectDb');
jest.mock('~/models', () => ({
User: jest.fn(),
Key: jest.fn(),
Session: jest.fn(),
Balance: jest.fn(),
Transaction: jest.fn(),
getMessages: jest.fn().mockResolvedValue([]),
saveMessage: jest.fn(),
updateMessage: jest.fn(),
deleteMessagesSince: jest.fn(),
deleteMessages: jest.fn(),
getConvoTitle: jest.fn(),
getConvo: jest.fn(),
saveConvo: jest.fn(),
deleteConvos: jest.fn(),
getPreset: jest.fn(),
getPresets: jest.fn(),
savePreset: jest.fn(),
deletePresets: jest.fn(),
findFileById: jest.fn(),
createFile: jest.fn(),
updateFile: jest.fn(),
deleteFile: jest.fn(),
deleteFiles: jest.fn(),
getFiles: jest.fn(),
updateFileUsage: jest.fn(),
}));
jest.mock('@langchain/openai', () => {
return {
ChatOpenAI: jest.fn().mockImplementation(() => {
return {};
}),
};
});
jest.mock('openai');
jest.spyOn(OpenAI, 'constructor').mockImplementation(function (...options) {
// We can add additional logic here if needed
return new OpenAI(...options);
});
const finalChatCompletion = jest.fn().mockResolvedValue({
choices: [
{
message: { role: 'assistant', content: 'Mock message content' },
finish_reason: 'Mock finish reason',
},
],
});
const stream = jest.fn().mockImplementation(() => {
let isDone = false;
let isError = false;
let errorCallback = null;
const onEventHandlers = {
abort: () => {
// Mock abort behavior
},
error: (callback) => {
errorCallback = callback; // Save the error callback for later use
},
finalMessage: (callback) => {
callback({ role: 'assistant', content: 'Mock Response' });
isDone = true; // Set stream to done
},
};
const mockStream = {
on: jest.fn((event, callback) => {
if (onEventHandlers[event]) {
onEventHandlers[event](callback);
}
return mockStream;
}),
finalChatCompletion,
controller: { abort: jest.fn() },
triggerError: () => {
isError = true;
if (errorCallback) {
errorCallback(new Error('Mock error'));
}
},
[Symbol.asyncIterator]: () => {
return {
next: () => {
if (isError) {
return Promise.reject(new Error('Mock error'));
}
if (isDone) {
return Promise.resolve({ done: true });
}
const chunk = { choices: [{ delta: { content: 'Mock chunk' } }] };
return Promise.resolve({ value: chunk, done: false });
},
};
},
};
return mockStream;
});
const create = jest.fn().mockResolvedValue({
choices: [
{
message: { content: 'Mock message content' },
finish_reason: 'Mock finish reason',
},
],
});
OpenAI.mockImplementation(() => ({
beta: {
chat: {
completions: {
stream,
},
},
},
chat: {
completions: {
create,
},
},
}));
describe('OpenAIClient', () => {
let client, client2;
const mockSet = jest.fn();
const mockCache = { set: mockSet };
beforeEach(() => {
getLogStores.mockReturnValue(mockCache);
});
let client;
const model = 'gpt-4';
const parentMessageId = '1';
const messages = [
@@ -12,25 +150,40 @@ describe('OpenAIClient', () => {
{ role: 'assistant', sender: 'Assistant', text: 'Hi', messageId: '2' },
];
const defaultOptions = {
// debug: true,
req: {},
openaiApiKey: 'new-api-key',
modelOptions: {
model,
temperature: 0.7,
},
};
const defaultAzureOptions = {
azureOpenAIApiInstanceName: 'your-instance-name',
azureOpenAIApiDeploymentName: 'your-deployment-name',
azureOpenAIApiVersion: '2020-07-01-preview',
};
let originalWarn;
beforeAll(() => {
jest.spyOn(console, 'warn').mockImplementation(() => {});
originalWarn = console.warn;
console.warn = jest.fn();
});
afterAll(() => {
console.warn.mockRestore();
console.warn = originalWarn;
});
beforeEach(() => {
const options = {
// debug: true,
openaiApiKey: 'new-api-key',
modelOptions: {
model,
temperature: 0.7,
},
};
console.warn.mockClear();
});
beforeEach(() => {
const options = { ...defaultOptions };
client = new OpenAIClient('test-api-key', options);
client2 = new OpenAIClient('test-api-key', options);
client.summarizeMessages = jest.fn().mockResolvedValue({
role: 'assistant',
content: 'Refined answer',
@@ -39,7 +192,7 @@ describe('OpenAIClient', () => {
client.buildPrompt = jest
.fn()
.mockResolvedValue({ prompt: messages.map((m) => m.text).join('\n') });
client.constructor.freeAndResetAllEncoders();
client.getMessages = jest.fn().mockResolvedValue([]);
});
describe('setOptions', () => {
@@ -49,14 +202,6 @@ describe('OpenAIClient', () => {
expect(client.modelOptions.temperature).toBe(0.7);
});
it('should set apiKey and useOpenRouter if OPENROUTER_API_KEY is present', () => {
process.env.OPENROUTER_API_KEY = 'openrouter-key';
client.setOptions({});
expect(client.apiKey).toBe('openrouter-key');
expect(client.useOpenRouter).toBe(true);
delete process.env.OPENROUTER_API_KEY; // Cleanup
});
it('should set FORCE_PROMPT based on OPENAI_FORCE_PROMPT or reverseProxyUrl', () => {
process.env.OPENAI_FORCE_PROMPT = 'true';
client.setOptions({});
@@ -74,7 +219,7 @@ describe('OpenAIClient', () => {
it('should set isChatCompletion based on useOpenRouter, reverseProxyUrl, or model', () => {
client.setOptions({ reverseProxyUrl: null });
// true by default since default model will be gpt-3.5-turbo
// true by default since default model will be gpt-4o-mini
expect(client.isChatCompletion).toBe(true);
client.isChatCompletion = undefined;
@@ -83,7 +228,7 @@ describe('OpenAIClient', () => {
expect(client.isChatCompletion).toBe(false);
client.isChatCompletion = undefined;
client.setOptions({ modelOptions: { model: 'gpt-3.5-turbo' }, reverseProxyUrl: null });
client.setOptions({ modelOptions: { model: 'gpt-4o-mini' }, reverseProxyUrl: null });
expect(client.isChatCompletion).toBe(true);
});
@@ -94,7 +239,7 @@ describe('OpenAIClient', () => {
client.setOptions({ reverseProxyUrl: 'https://example.com/completions' });
expect(client.completionsUrl).toBe('https://example.com/completions');
expect(client.langchainProxy).toBe(null);
expect(client.langchainProxy).toBe('https://example.com/completions');
});
});
@@ -188,83 +333,18 @@ describe('OpenAIClient', () => {
});
});
describe('selectTokenizer', () => {
it('should get the correct tokenizer based on the instance state', () => {
const tokenizer = client.selectTokenizer();
expect(tokenizer).toBeDefined();
});
});
describe('freeAllTokenizers', () => {
it('should free all tokenizers', () => {
// Create a tokenizer
const tokenizer = client.selectTokenizer();
// Mock 'free' method on the tokenizer
tokenizer.free = jest.fn();
client.constructor.freeAndResetAllEncoders();
// Check if 'free' method has been called on the tokenizer
expect(tokenizer.free).toHaveBeenCalled();
});
});
describe('getTokenCount', () => {
it('should return the correct token count', () => {
const count = client.getTokenCount('Hello, world!');
expect(count).toBeGreaterThan(0);
});
it('should reset the encoder and count when count reaches 25', () => {
const freeAndResetEncoderSpy = jest.spyOn(client.constructor, 'freeAndResetAllEncoders');
// Call getTokenCount 25 times
for (let i = 0; i < 25; i++) {
client.getTokenCount('test text');
}
expect(freeAndResetEncoderSpy).toHaveBeenCalled();
});
it('should not reset the encoder and count when count is less than 25', () => {
const freeAndResetEncoderSpy = jest.spyOn(client.constructor, 'freeAndResetAllEncoders');
freeAndResetEncoderSpy.mockClear();
// Call getTokenCount 24 times
for (let i = 0; i < 24; i++) {
client.getTokenCount('test text');
}
expect(freeAndResetEncoderSpy).not.toHaveBeenCalled();
});
it('should handle errors and reset the encoder', () => {
const freeAndResetEncoderSpy = jest.spyOn(client.constructor, 'freeAndResetAllEncoders');
// Mock encode function to throw an error
client.selectTokenizer().encode = jest.fn().mockImplementation(() => {
throw new Error('Test error');
});
client.getTokenCount('test text');
expect(freeAndResetEncoderSpy).toHaveBeenCalled();
});
it('should not throw null pointer error when freeing the same encoder twice', () => {
client.constructor.freeAndResetAllEncoders();
client2.constructor.freeAndResetAllEncoders();
const count = client2.getTokenCount('test text');
expect(count).toBeGreaterThan(0);
});
});
describe('getSaveOptions', () => {
it('should return the correct save options', () => {
const options = client.getSaveOptions();
expect(options).toHaveProperty('chatGptLabel');
expect(options).toHaveProperty('modelLabel');
expect(options).toHaveProperty('promptPrefix');
});
});
@@ -299,7 +379,7 @@ describe('OpenAIClient', () => {
promptPrefix: 'Test Prefix',
});
expect(result).toHaveProperty('prompt');
const instructions = result.prompt.find((item) => item.name === 'instructions');
const instructions = result.prompt.find((item) => item.content.includes('Test Prefix'));
expect(instructions).toBeDefined();
expect(instructions.content).toContain('Test Prefix');
});
@@ -329,7 +409,9 @@ describe('OpenAIClient', () => {
const result = await client.buildMessages(messages, parentMessageId, {
isChatCompletion: true,
});
const instructions = result.prompt.find((item) => item.name === 'instructions');
const instructions = result.prompt.find((item) =>
item.content.includes('Test Prefix from options'),
);
expect(instructions.content).toContain('Test Prefix from options');
});
@@ -337,7 +419,7 @@ describe('OpenAIClient', () => {
const result = await client.buildMessages(messages, parentMessageId, {
isChatCompletion: true,
});
const instructions = result.prompt.find((item) => item.name === 'instructions');
const instructions = result.prompt.find((item) => item.content.includes('Test Prefix'));
expect(instructions).toBeUndefined();
});
@@ -398,7 +480,6 @@ describe('OpenAIClient', () => {
testCases.forEach((testCase) => {
it(`should return ${testCase.expected} tokens for model ${testCase.model}`, () => {
client.modelOptions.model = testCase.model;
client.selectTokenizer();
// 3 tokens for assistant label
let totalTokens = 3;
for (let message of example_messages) {
@@ -407,5 +488,207 @@ describe('OpenAIClient', () => {
expect(totalTokens).toBe(testCase.expected);
});
});
const vision_request = [
{
role: 'user',
content: [
{
type: 'text',
text: 'describe what is in this image?',
},
{
type: 'image_url',
image_url: {
url: 'https://venturebeat.com/wp-content/uploads/2019/03/openai-1.png',
detail: 'high',
},
},
],
},
];
const expectedTokens = 14;
const visionModel = 'gpt-4-vision-preview';
it(`should return ${expectedTokens} tokens for model ${visionModel} (Vision Request)`, () => {
client.modelOptions.model = visionModel;
// 3 tokens for assistant label
let totalTokens = 3;
for (let message of vision_request) {
totalTokens += client.getTokenCountForMessage(message);
}
expect(totalTokens).toBe(expectedTokens);
});
});
describe('sendMessage/getCompletion/chatCompletion', () => {
afterEach(() => {
delete process.env.AZURE_OPENAI_DEFAULT_MODEL;
delete process.env.AZURE_USE_MODEL_AS_DEPLOYMENT_NAME;
});
it('should call getCompletion and fetchEventSource when using a text/instruct model', async () => {
const model = 'text-davinci-003';
const onProgress = jest.fn().mockImplementation(() => ({}));
const testClient = new OpenAIClient('test-api-key', {
...defaultOptions,
modelOptions: { model },
});
const getCompletion = jest.spyOn(testClient, 'getCompletion');
await testClient.sendMessage('Hi mom!', { onProgress });
expect(getCompletion).toHaveBeenCalled();
expect(getCompletion.mock.calls.length).toBe(1);
expect(getCompletion.mock.calls[0][0]).toBe('||>User:\nHi mom!\n||>Assistant:\n');
expect(fetchEventSource).toHaveBeenCalled();
expect(fetchEventSource.mock.calls.length).toBe(1);
// Check if the first argument (url) is correct
const firstCallArgs = fetchEventSource.mock.calls[0];
const expectedURL = 'https://api.openai.com/v1/completions';
expect(firstCallArgs[0]).toBe(expectedURL);
const requestBody = JSON.parse(firstCallArgs[1].body);
expect(requestBody).toHaveProperty('model');
expect(requestBody.model).toBe(model);
});
it('[Azure OpenAI] should call chatCompletion and OpenAI.stream with correct args', async () => {
// Set a default model
process.env.AZURE_OPENAI_DEFAULT_MODEL = 'gpt4-turbo';
const onProgress = jest.fn().mockImplementation(() => ({}));
client.azure = defaultAzureOptions;
const chatCompletion = jest.spyOn(client, 'chatCompletion');
await client.sendMessage('Hi mom!', {
replaceOptions: true,
...defaultOptions,
modelOptions: { model: 'gpt4-turbo', stream: true },
onProgress,
azure: defaultAzureOptions,
});
expect(chatCompletion).toHaveBeenCalled();
expect(chatCompletion.mock.calls.length).toBe(1);
const chatCompletionArgs = chatCompletion.mock.calls[0][0];
const { payload } = chatCompletionArgs;
expect(payload[0].role).toBe('user');
expect(payload[0].content).toBe('Hi mom!');
// Azure OpenAI does not use the model property, and will error if it's passed
// This check ensures the model property is not present
const streamArgs = stream.mock.calls[0][0];
expect(streamArgs).not.toHaveProperty('model');
// Check if the baseURL is correct
const constructorArgs = OpenAI.mock.calls[0][0];
const expectedURL = genAzureChatCompletion(defaultAzureOptions).split('/chat')[0];
expect(constructorArgs.baseURL).toBe(expectedURL);
});
});
describe('checkVisionRequest functionality', () => {
let client;
const attachments = [{ type: 'image/png' }];
beforeEach(() => {
client = new OpenAIClient('test-api-key', {
endpoint: 'ollama',
modelOptions: {
model: 'initial-model',
},
modelsConfig: {
ollama: ['initial-model', 'llava', 'other-model'],
},
});
client.defaultVisionModel = 'non-valid-default-model';
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should set "llava" as the model if it is the first valid model when default validation fails', () => {
client.checkVisionRequest(attachments);
expect(client.modelOptions.model).toBe('llava');
expect(client.isVisionModel).toBeTruthy();
expect(client.modelOptions.stop).toBeUndefined();
});
});
describe('getStreamUsage', () => {
it('should return this.usage when completion_tokens_details is null', () => {
const client = new OpenAIClient('test-api-key', defaultOptions);
client.usage = {
completion_tokens_details: null,
prompt_tokens: 10,
completion_tokens: 20,
};
client.inputTokensKey = 'prompt_tokens';
client.outputTokensKey = 'completion_tokens';
const result = client.getStreamUsage();
expect(result).toEqual(client.usage);
});
it('should return this.usage when completion_tokens_details is missing reasoning_tokens', () => {
const client = new OpenAIClient('test-api-key', defaultOptions);
client.usage = {
completion_tokens_details: {
other_tokens: 5,
},
prompt_tokens: 10,
completion_tokens: 20,
};
client.inputTokensKey = 'prompt_tokens';
client.outputTokensKey = 'completion_tokens';
const result = client.getStreamUsage();
expect(result).toEqual(client.usage);
});
it('should calculate output tokens correctly when completion_tokens_details is present with reasoning_tokens', () => {
const client = new OpenAIClient('test-api-key', defaultOptions);
client.usage = {
completion_tokens_details: {
reasoning_tokens: 30,
other_tokens: 5,
},
prompt_tokens: 10,
completion_tokens: 20,
};
client.inputTokensKey = 'prompt_tokens';
client.outputTokensKey = 'completion_tokens';
const result = client.getStreamUsage();
expect(result).toEqual({
reasoning_tokens: 30,
other_tokens: 5,
prompt_tokens: 10,
completion_tokens: 10, // |30 - 20| = 10
});
});
it('should return this.usage when it is undefined', () => {
const client = new OpenAIClient('test-api-key', defaultOptions);
client.usage = undefined;
const result = client.getStreamUsage();
expect(result).toBeUndefined();
});
});
});

View File

@@ -38,7 +38,12 @@ const run = async () => {
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."
`;
const model = 'gpt-3.5-turbo';
const maxContextTokens = model === 'gpt-4' ? 8191 : model === 'gpt-4-32k' ? 32767 : 4095; // 1 less than maximum
let maxContextTokens = 4095;
if (model === 'gpt-4') {
maxContextTokens = 8191;
} else if (model === 'gpt-4-32k') {
maxContextTokens = 32767;
}
const clientOptions = {
reverseProxyUrl: process.env.OPENAI_REVERSE_PROXY || null,
maxContextTokens,

View File

@@ -1,9 +1,10 @@
const { HumanChatMessage, AIChatMessage } = require('langchain/schema');
const PluginsClient = require('../PluginsClient');
const crypto = require('crypto');
const { Constants } = require('librechat-data-provider');
const { HumanMessage, AIMessage } = require('@langchain/core/messages');
const PluginsClient = require('../PluginsClient');
jest.mock('../../../lib/db/connectDb');
jest.mock('../../../models/Conversation', () => {
jest.mock('~/lib/db/connectDb');
jest.mock('~/models/Conversation', () => {
return function () {
return {
save: jest.fn(),
@@ -12,6 +13,12 @@ jest.mock('../../../models/Conversation', () => {
};
});
const defaultAzureOptions = {
azureOpenAIApiInstanceName: 'your-instance-name',
azureOpenAIApiDeploymentName: 'your-deployment-name',
azureOpenAIApiVersion: '2020-07-01-preview',
};
describe('PluginsClient', () => {
let TestAgent;
let options = {
@@ -48,8 +55,8 @@ describe('PluginsClient', () => {
const chatMessages = orderedMessages.map((msg) =>
msg?.isCreatedByUser || msg?.role?.toLowerCase() === 'user'
? new HumanChatMessage(msg.text)
: new AIChatMessage(msg.text),
? new HumanMessage(msg.text)
: new AIMessage(msg.text),
);
TestAgent.currentMessages = orderedMessages;
@@ -60,7 +67,7 @@ describe('PluginsClient', () => {
TestAgent.setOptions(opts);
}
const conversationId = opts.conversationId || crypto.randomUUID();
const parentMessageId = opts.parentMessageId || '00000000-0000-0000-0000-000000000000';
const parentMessageId = opts.parentMessageId || Constants.NO_PARENT;
const userMessageId = opts.overrideParentMessageId || crypto.randomUUID();
this.pastMessages = await TestAgent.loadHistory(
conversationId,
@@ -144,4 +151,164 @@ describe('PluginsClient', () => {
expect(chatMessages[0].text).toEqual(userMessage);
});
});
describe('getFunctionModelName', () => {
let client;
beforeEach(() => {
client = new PluginsClient('dummy_api_key');
});
test('should return the input when it includes a dash followed by four digits', () => {
expect(client.getFunctionModelName('-1234')).toBe('-1234');
expect(client.getFunctionModelName('gpt-4-5678-preview')).toBe('gpt-4-5678-preview');
});
test('should return the input for all function-capable models (`0613` models and above)', () => {
expect(client.getFunctionModelName('gpt-4-0613')).toBe('gpt-4-0613');
expect(client.getFunctionModelName('gpt-4-32k-0613')).toBe('gpt-4-32k-0613');
expect(client.getFunctionModelName('gpt-3.5-turbo-0613')).toBe('gpt-3.5-turbo-0613');
expect(client.getFunctionModelName('gpt-3.5-turbo-16k-0613')).toBe('gpt-3.5-turbo-16k-0613');
expect(client.getFunctionModelName('gpt-3.5-turbo-1106')).toBe('gpt-3.5-turbo-1106');
expect(client.getFunctionModelName('gpt-4-1106-preview')).toBe('gpt-4-1106-preview');
expect(client.getFunctionModelName('gpt-4-1106')).toBe('gpt-4-1106');
});
test('should return the corresponding model if input is non-function capable (`0314` models)', () => {
expect(client.getFunctionModelName('gpt-4-0314')).toBe('gpt-4');
expect(client.getFunctionModelName('gpt-4-32k-0314')).toBe('gpt-4');
expect(client.getFunctionModelName('gpt-3.5-turbo-0314')).toBe('gpt-3.5-turbo');
expect(client.getFunctionModelName('gpt-3.5-turbo-16k-0314')).toBe('gpt-3.5-turbo');
});
test('should return "gpt-3.5-turbo" when the input includes "gpt-3.5-turbo"', () => {
expect(client.getFunctionModelName('test gpt-3.5-turbo model')).toBe('gpt-3.5-turbo');
});
test('should return "gpt-4" when the input includes "gpt-4"', () => {
expect(client.getFunctionModelName('testing gpt-4')).toBe('gpt-4');
});
test('should return "gpt-3.5-turbo" for input that does not meet any specific condition', () => {
expect(client.getFunctionModelName('random string')).toBe('gpt-3.5-turbo');
expect(client.getFunctionModelName('')).toBe('gpt-3.5-turbo');
});
});
describe('Azure OpenAI tests specific to Plugins', () => {
// TODO: add more tests for Azure OpenAI integration with Plugins
// let client;
// beforeEach(() => {
// client = new PluginsClient('dummy_api_key');
// });
test('should not call getFunctionModelName when azure options are set', () => {
const spy = jest.spyOn(PluginsClient.prototype, 'getFunctionModelName');
const model = 'gpt-4-turbo';
// note, without the azure change in PR #1766, `getFunctionModelName` is called twice
const testClient = new PluginsClient('dummy_api_key', {
agentOptions: {
model,
agent: 'functions',
},
azure: defaultAzureOptions,
});
expect(spy).not.toHaveBeenCalled();
expect(testClient.agentOptions.model).toBe(model);
spy.mockRestore();
});
});
describe('sendMessage with filtered tools', () => {
let TestAgent;
const apiKey = 'fake-api-key';
const mockTools = [{ name: 'tool1' }, { name: 'tool2' }, { name: 'tool3' }, { name: 'tool4' }];
beforeEach(() => {
TestAgent = new PluginsClient(apiKey, {
tools: mockTools,
modelOptions: {
model: 'gpt-3.5-turbo',
temperature: 0,
max_tokens: 2,
},
agentOptions: {
model: 'gpt-3.5-turbo',
},
});
TestAgent.options.req = {
app: {
locals: {},
},
};
TestAgent.sendMessage = jest.fn().mockImplementation(async () => {
const { filteredTools = [], includedTools = [] } = TestAgent.options.req.app.locals;
if (includedTools.length > 0) {
const tools = TestAgent.options.tools.filter((plugin) =>
includedTools.includes(plugin.name),
);
TestAgent.options.tools = tools;
} else {
const tools = TestAgent.options.tools.filter(
(plugin) => !filteredTools.includes(plugin.name),
);
TestAgent.options.tools = tools;
}
return {
text: 'Mocked response',
tools: TestAgent.options.tools,
};
});
});
test('should filter out tools when filteredTools is provided', async () => {
TestAgent.options.req.app.locals.filteredTools = ['tool1', 'tool3'];
const response = await TestAgent.sendMessage('Test message');
expect(response.tools).toHaveLength(2);
expect(response.tools).toEqual(
expect.arrayContaining([
expect.objectContaining({ name: 'tool2' }),
expect.objectContaining({ name: 'tool4' }),
]),
);
});
test('should only include specified tools when includedTools is provided', async () => {
TestAgent.options.req.app.locals.includedTools = ['tool2', 'tool4'];
const response = await TestAgent.sendMessage('Test message');
expect(response.tools).toHaveLength(2);
expect(response.tools).toEqual(
expect.arrayContaining([
expect.objectContaining({ name: 'tool2' }),
expect.objectContaining({ name: 'tool4' }),
]),
);
});
test('should prioritize includedTools over filteredTools', async () => {
TestAgent.options.req.app.locals.filteredTools = ['tool1', 'tool3'];
TestAgent.options.req.app.locals.includedTools = ['tool1', 'tool2'];
const response = await TestAgent.sendMessage('Test message');
expect(response.tools).toHaveLength(2);
expect(response.tools).toEqual(
expect.arrayContaining([
expect.objectContaining({ name: 'tool1' }),
expect.objectContaining({ name: 'tool2' }),
]),
);
});
test('should not modify tools when no filters are provided', async () => {
const response = await TestAgent.sendMessage('Test message');
expect(response.tools).toHaveLength(4);
expect(response.tools).toEqual(expect.arrayContaining(mockTools));
});
});
});

Some files were not shown because too many files have changed in this diff Show More