diff --git a/.env.example b/.env.example index e1479a924f6..a42ed5d683e 100644 --- a/.env.example +++ b/.env.example @@ -2,11 +2,9 @@ # LibreChat Configuration # #=====================================================================# # Please refer to the reference documentation for assistance # -# with configuring your LibreChat environment. The guide is # -# available both online and within your local LibreChat # -# directory: # -# Online: https://docs.librechat.ai/install/configuration/dotenv.html # -# Locally: ./docs/install/configuration/dotenv.md # +# with configuring your LibreChat environment. # +# # +# https://www.librechat.ai/docs/configuration/dotenv # #=====================================================================# #==================================================# @@ -62,7 +60,7 @@ PROXY= #===================================# # Known Endpoints - librechat.yaml # #===================================# -# https://docs.librechat.ai/install/configuration/ai_endpoints.html +# https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints # ANYSCALE_API_KEY= # APIPIE_API_KEY= @@ -118,10 +116,10 @@ GOOGLE_KEY=user_provided # GOOGLE_REVERSE_PROXY= # Gemini API -# GOOGLE_MODELS=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 +# GOOGLE_MODELS=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-pro-preview-0409,gemini-1.0-pro-vision-001,gemini-pro,gemini-pro-vision,chat-bison,chat-bison-32k,codechat-bison,codechat-bison-32k,text-bison,text-bison-32k,text-unicorn,code-gecko,code-bison,code-bison-32k +# GOOGLE_MODELS=gemini-1.5-flash-preview-0514,gemini-1.5-pro-preview-0409,gemini-1.0-pro-vision-001,gemini-pro,gemini-pro-vision,chat-bison,chat-bison-32k,codechat-bison,codechat-bison-32k,text-bison,text-bison-32k,text-unicorn,code-gecko,code-bison,code-bison-32k # Google Gemini Safety Settings # NOTE (Vertex AI): You do not have access to the BLOCK_NONE setting by default. @@ -142,7 +140,7 @@ GOOGLE_KEY=user_provided #============# OPENAI_API_KEY=user_provided -# OPENAI_MODELS=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 +# OPENAI_MODELS=gpt-4o,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 @@ -164,7 +162,7 @@ DEBUG_OPENAI=false ASSISTANTS_API_KEY=user_provided # ASSISTANTS_BASE_URL= -# ASSISTANTS_MODELS=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 +# ASSISTANTS_MODELS=gpt-4o,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 #============# # OpenRouter # @@ -176,7 +174,7 @@ ASSISTANTS_API_KEY=user_provided # Plugins # #============# -# PLUGIN_MODELS=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 +# PLUGIN_MODELS=gpt-4o,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 diff --git a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml index 26155bdc685..d85957fd22e 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml @@ -43,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 diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yml b/.github/ISSUE_TEMPLATE/QUESTION.yml index 8a0cbf5535b..0669fd67244 100644 --- a/.github/ISSUE_TEMPLATE/QUESTION.yml +++ b/.github/ISSUE_TEMPLATE/QUESTION.yml @@ -44,7 +44,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 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a1542cb76e4..cb637787f12 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -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](https://github.com/danny-avila/LibreChat/blob/main/.github/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 @@ -16,8 +19,6 @@ Please delete any irrelevant options. - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update - [ ] Translation update -- [ ] Documentation update - ## Testing @@ -37,4 +38,4 @@ Please delete any irrelevant options. - [ ] 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. -- [ ] New documents have been locally validated with mkdocs +- [ ] A pull request for updating the documentation has been submitted. diff --git a/.github/workflows/mkdocs.yaml b/.github/workflows/mkdocs.yaml deleted file mode 100644 index 3b2878fa2a7..00000000000 --- a/.github/workflows/mkdocs.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: mkdocs -on: - push: - branches: - - main -permissions: - contents: write -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - 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: pip install mkdocs-nav-weight - - run: pip install mkdocs-publisher - - run: pip install mkdocs-exclude - - run: mkdocs gh-deploy --force diff --git a/Dockerfile b/Dockerfile index f688efa7e92..6c70a6d7f24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,8 @@ # v0.7.2 # Base node image -FROM node:18-alpine3.18 AS node +FROM node:20-alpine AS node -RUN apk add g++ make py3-pip -RUN npm install -g node-gyp RUN apk --no-cache add curl RUN mkdir -p /app && chown node:node /app @@ -14,20 +12,20 @@ USER node COPY --chown=node:node . . -# Allow mounting of these files, which have no default -# values. -RUN touch .env -RUN npm config set fetch-retry-maxtimeout 600000 -RUN npm config set fetch-retries 5 -RUN npm config set fetch-retry-mintimeout 15000 -RUN npm install --no-audit +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 -# React client build -ENV NODE_OPTIONS="--max-old-space-size=2048" -RUN npm run frontend - -# Create directories for the volumes to inherit -# the correct permissions RUN mkdir -p /app/client/public/images /app/api/logs # Node API setup diff --git a/Dockerfile.multi b/Dockerfile.multi index a3bc0fed403..41e8825b810 100644 --- a/Dockerfile.multi +++ b/Dockerfile.multi @@ -7,32 +7,31 @@ FROM node:20-alpine AS base FROM base AS data-provider-build WORKDIR /app/packages/data-provider COPY ./packages/data-provider ./ -RUN npm install +RUN npm install; npm cache clean --force RUN npm run build +RUN npm prune --production # React client build -FROM data-provider-build AS client-build +FROM base AS client-build WORKDIR /app/client COPY ./client/package*.json ./ # Copy data-provider to client's node_modules -RUN mkdir -p /app/client/node_modules/librechat-data-provider/ -RUN cp -R /app/packages/data-provider/* /app/client/node_modules/librechat-data-provider/ -RUN npm install +COPY --from=data-provider-build /app/packages/data-provider/ /app/client/node_modules/librechat-data-provider/ +RUN npm install; npm cache clean --force COPY ./client/ ./ ENV NODE_OPTIONS="--max-old-space-size=2048" RUN npm run build # Node API setup -FROM data-provider-build AS api-build +FROM base AS api-build WORKDIR /app/api COPY api/package*.json ./ COPY api/ ./ # Copy helper scripts COPY config/ ./ # Copy data-provider to API's node_modules -RUN mkdir -p /app/api/node_modules/librechat-data-provider/ -RUN cp -R /app/packages/data-provider/* /app/api/node_modules/librechat-data-provider/ -RUN npm install +COPY --from=data-provider-build /app/packages/data-provider/ /app/api/node_modules/librechat-data-provider/ +RUN npm install --include prod; npm cache clean --force COPY --from=client-build /app/client/dist /app/client/dist EXPOSE 3080 ENV HOST=0.0.0.0 diff --git a/README.md b/README.md index c975fa96809..2cb0b593fc8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- +

LibreChat @@ -43,14 +43,14 @@ - 🖥️ UI matching ChatGPT, including Dark mode, Streaming, and latest updates - 🤖 AI model selection: - OpenAI, Azure OpenAI, BingAI, ChatGPT, Google Vertex AI, Anthropic (Claude), Plugins, Assistants API (including Azure Assistants) -- ✅ Compatible across both **[Remote & Local AI services](https://docs.librechat.ai/install/configuration/ai_endpoints.html#intro):** +- ✅ Compatible across both **[Remote & Local AI services](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints):** - groq, Ollama, Cohere, Mistral AI, Apple MLX, koboldcpp, OpenRouter, together.ai, Perplexity, ShuttleAI, and more - 💾 Create, Save, & Share Custom Presets - 🔀 Switch between AI Endpoints and Presets, mid-chat - 🔄 Edit, Resubmit, and Continue Messages with Conversation branching - 🌿 Fork Messages & Conversations for Advanced Context control - 💬 Multimodal Chat: - - Upload and analyze images with Claude 3, GPT-4, and Gemini Vision 📸 + - Upload and analyze images with Claude 3, GPT-4 (including `gpt-4o`), and Gemini Vision 📸 - Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, & Google. 🗃️ - Advanced Agents with Files, Code Interpreter, Tools, and API Actions 🔦 - Available through the [OpenAI Assistants API](https://platform.openai.com/docs/assistants/overview) 🌤️ @@ -69,7 +69,7 @@ - 📖 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/features/plugins/introduction.html) 📚 +[For a thorough review of our features, see our docs here](https://docs.librechat.ai/) 📚 ## 🪶 All-In-One AI Conversations with LibreChat @@ -77,48 +77,48 @@ LibreChat brings together the future of assistant AIs with the revolutionary tec 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. - - -[![Watch the video](https://img.youtube.com/vi/pNIOs1ovsXw/maxresdefault.jpg)](https://youtu.be/pNIOs1ovsXw) +[![Watch the video](https://img.youtube.com/vi/YLVUW5UP9N0/maxresdefault.jpg)](https://www.youtube.com/watch?v=YLVUW5UP9N0) Click on the thumbnail to open the video☝️ --- -## 📚 Documentation +## 🌐 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) -For more information on how to use our advanced features, install and configure our software, and access our guidelines and tutorials, please check out our documentation at [docs.librechat.ai](https://docs.librechat.ai) +**Other:** + - **Website:** [librechat.ai](https://librechat.ai) + - **Documentation:** [docs.librechat.ai](https://docs.librechat.ai) + - **Blog:** [blog.librechat.ai](https://docs.librechat.ai) --- ## 📝 Changelog -Keep up with the latest updates by visiting the releases page - [Releases](https://github.com/danny-avila/LibreChat/releases) +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) -**⚠️ [Breaking Changes](docs/general_info/breaking_changes.md)** -Please consult the breaking changes before updating. +**⚠️ Please consult the [changelog](https://www.librechat.ai/changelog) for breaking changes before updating.** --- ## ⭐ Star History

-danny-avila%2FLibreChat | Trendshift - - ROSS Index - Fastest Growing Open-Source Startups in Q1 2024 | Runa Capital - - - Star History Chart - + + Star History Chart + +

+

+ + danny-avila%2FLibreChat | Trendshift + + + ROSS Index - Fastest Growing Open-Source Startups in Q1 2024 | Runa Capital +

--- diff --git a/api/app/clients/GoogleClient.js b/api/app/clients/GoogleClient.js index e3a33d3e7cb..6852410efb9 100644 --- a/api/app/clients/GoogleClient.js +++ b/api/app/clients/GoogleClient.js @@ -683,11 +683,12 @@ class GoogleClient extends BaseClient { const safetySettings = _payload.safetySettings; requestOptions.safetySettings = safetySettings; + const delay = modelName.includes('flash') ? 8 : 14; const result = await client.generateContentStream(requestOptions); for await (const chunk of result.stream) { const chunkText = chunk.text(); - this.generateTextStream(chunkText, onProgress, { - delay: 12, + await this.generateTextStream(chunkText, onProgress, { + delay, }); reply += chunkText; } @@ -701,10 +702,14 @@ class GoogleClient extends BaseClient { safetySettings: safetySettings, }); + let delay = this.isGenerativeModel ? 12 : 8; + if (modelName.includes('flash')) { + delay = 5; + } for await (const chunk of stream) { const chunkText = chunk?.content ?? chunk; - this.generateTextStream(chunkText, onProgress, { - delay: this.isGenerativeModel ? 12 : 8, + await this.generateTextStream(chunkText, onProgress, { + delay, }); reply += chunkText; } diff --git a/api/app/clients/OpenAIClient.js b/api/app/clients/OpenAIClient.js index 456185c008a..b4a50bc05c6 100644 --- a/api/app/clients/OpenAIClient.js +++ b/api/app/clients/OpenAIClient.js @@ -308,7 +308,7 @@ class OpenAIClient extends BaseClient { let tokenizer; this.encoding = 'text-davinci-003'; if (this.isChatCompletion) { - this.encoding = 'cl100k_base'; + this.encoding = this.modelOptions.model.includes('gpt-4o') ? 'o200k_base' : 'cl100k_base'; tokenizer = this.constructor.getTokenizer(this.encoding); } else if (this.isUnofficialChatGptModel) { const extendSpecialTokens = { diff --git a/api/models/tx.js b/api/models/tx.js index 01ad9953318..1b37ffc8659 100644 --- a/api/models/tx.js +++ b/api/models/tx.js @@ -12,6 +12,7 @@ const tokenValues = { '4k': { prompt: 1.5, completion: 2 }, '16k': { prompt: 3, completion: 4 }, 'gpt-3.5-turbo-1106': { prompt: 1, completion: 2 }, + 'gpt-4o': { prompt: 5, completion: 15 }, 'gpt-4-1106': { prompt: 10, completion: 30 }, 'gpt-3.5-turbo-0125': { prompt: 0.5, completion: 1.5 }, 'claude-3-opus': { prompt: 15, completion: 75 }, @@ -52,6 +53,8 @@ const getValueKey = (model, endpoint) => { return 'gpt-3.5-turbo-1106'; } else if (modelName.includes('gpt-3.5')) { return '4k'; + } else if (modelName.includes('gpt-4o')) { + return 'gpt-4o'; } else if (modelName.includes('gpt-4-vision')) { return 'gpt-4-1106'; } else if (modelName.includes('gpt-4-1106')) { diff --git a/api/models/tx.spec.js b/api/models/tx.spec.js index bf99a1d45e1..ce7d227d518 100644 --- a/api/models/tx.spec.js +++ b/api/models/tx.spec.js @@ -41,6 +41,13 @@ describe('getValueKey', () => { expect(getValueKey('gpt-4-turbo')).toBe('gpt-4-1106'); expect(getValueKey('gpt-4-0125')).toBe('gpt-4-1106'); }); + + it('should return "gpt-4o" for model type of "gpt-4o"', () => { + expect(getValueKey('gpt-4o-2024-05-13')).toBe('gpt-4o'); + expect(getValueKey('openai/gpt-4o')).toBe('gpt-4o'); + expect(getValueKey('gpt-4o-turbo')).toBe('gpt-4o'); + expect(getValueKey('gpt-4o-0125')).toBe('gpt-4o'); + }); }); describe('getMultiplier', () => { @@ -84,6 +91,17 @@ describe('getMultiplier', () => { ); }); + it('should return the correct multiplier for gpt-4o', () => { + const valueKey = getValueKey('gpt-4o-2024-05-13'); + expect(getMultiplier({ valueKey, tokenType: 'prompt' })).toBe(tokenValues['gpt-4o'].prompt); + expect(getMultiplier({ valueKey, tokenType: 'completion' })).toBe( + tokenValues['gpt-4o'].completion, + ); + expect(getMultiplier({ valueKey, tokenType: 'completion' })).not.toBe( + tokenValues['gpt-4-1106'].completion, + ); + }); + it('should derive the valueKey from the model if not provided for new models', () => { expect( getMultiplier({ tokenType: 'prompt', model: 'gpt-3.5-turbo-1106-some-other-info' }), diff --git a/api/package.json b/api/package.json index 328a979ac9a..d91b6031eff 100644 --- a/api/package.json +++ b/api/package.json @@ -89,7 +89,7 @@ "passport-local": "^1.0.0", "pino": "^8.12.1", "sharp": "^0.32.6", - "tiktoken": "^1.0.10", + "tiktoken": "^1.0.15", "traverse": "^0.6.7", "ua-parser-js": "^1.0.36", "winston": "^3.11.0", diff --git a/api/server/controllers/PluginController.js b/api/server/controllers/PluginController.js index cac0b88bcf4..5bb34671f8d 100644 --- a/api/server/controllers/PluginController.js +++ b/api/server/controllers/PluginController.js @@ -55,24 +55,26 @@ const getAvailablePluginsController = async (req, res) => { return; } - /** @type {{ filteredTools: string[] }} */ - const { filteredTools = [] } = req.app.locals; - + /** @type {{ filteredTools: string[], includedTools: string[] }} */ + const { filteredTools = [], includedTools = [] } = req.app.locals; const pluginManifest = await fs.readFile(req.app.locals.paths.pluginManifest, 'utf8'); - const jsonData = JSON.parse(pluginManifest); - /** @type {TPlugin[]} */ + const uniquePlugins = filterUniquePlugins(jsonData); - const authenticatedPlugins = uniquePlugins.map((plugin) => { - if (isPluginAuthenticated(plugin)) { - return { ...plugin, authenticated: true }; - } else { - return plugin; - } - }); + let authenticatedPlugins = []; + for (const plugin of uniquePlugins) { + authenticatedPlugins.push( + isPluginAuthenticated(plugin) ? { ...plugin, authenticated: true } : plugin, + ); + } let plugins = await addOpenAPISpecs(authenticatedPlugins); - plugins = plugins.filter((plugin) => !filteredTools.includes(plugin.pluginKey)); + + if (includedTools.length > 0) { + plugins = plugins.filter((plugin) => includedTools.includes(plugin.pluginKey)); + } else { + plugins = plugins.filter((plugin) => !filteredTools.includes(plugin.pluginKey)); + } await cache.set(CacheKeys.PLUGINS, plugins); res.status(200).json(plugins); diff --git a/api/server/routes/assistants/chat.js b/api/server/routes/assistants/chat.js index 69be8a7b3e4..96a09d02dd8 100644 --- a/api/server/routes/assistants/chat.js +++ b/api/server/routes/assistants/chat.js @@ -514,6 +514,7 @@ router.post('/', validateModel, buildEndpointOption, setHeaders, async (req, res const processRun = async (retry = false) => { if (req.app.locals[EModelEndpoint.azureOpenAI]?.assistants) { + body.model = openai._options.model; openai.attachedFileIds = attachedFileIds; openai.visionPromise = visionPromise; if (retry) { diff --git a/api/server/services/AppService.js b/api/server/services/AppService.js index bcdd0894817..4163a3df87b 100644 --- a/api/server/services/AppService.js +++ b/api/server/services/AppService.js @@ -21,6 +21,7 @@ const AppService = async (app) => { const configDefaults = getConfigDefaults(); const filteredTools = config.filteredTools; + const includedTools = config.includedTools; const fileStrategy = config.fileStrategy ?? configDefaults.fileStrategy; const imageOutputType = config?.imageOutputType ?? configDefaults.imageOutputType; @@ -37,23 +38,26 @@ const AppService = async (app) => { const availableTools = loadAndFormatTools({ directory: paths.structuredTools, adminFilter: filteredTools, + adminIncluded: includedTools, }); const socialLogins = config?.registration?.socialLogins ?? configDefaults?.registration?.socialLogins; const interfaceConfig = loadDefaultInterface(config, configDefaults); - if (!Object.keys(config).length) { - app.locals = { - paths, - fileStrategy, - socialLogins, - filteredTools, - availableTools, - imageOutputType, - interfaceConfig, - }; + const defaultLocals = { + paths, + fileStrategy, + socialLogins, + filteredTools, + includedTools, + availableTools, + imageOutputType, + interfaceConfig, + }; + if (!Object.keys(config).length) { + app.locals = defaultLocals; return; } @@ -79,13 +83,7 @@ const AppService = async (app) => { } app.locals = { - paths, - socialLogins, - fileStrategy, - filteredTools, - availableTools, - imageOutputType, - interfaceConfig, + ...defaultLocals, modelSpecs: config.modelSpecs, fileConfig: config?.fileConfig, secureImageLinks: config?.secureImageLinks, diff --git a/api/server/services/Config/loadCustomConfig.js b/api/server/services/Config/loadCustomConfig.js index dc3105c392f..1b5b2870664 100644 --- a/api/server/services/Config/loadCustomConfig.js +++ b/api/server/services/Config/loadCustomConfig.js @@ -37,7 +37,7 @@ async function loadCustomConfig() { if (!customConfig) { i === 0 && logger.info( - 'Custom config file missing or YAML format invalid.\n\nCheck out the latest config file guide for configurable options and features.\nhttps://docs.librechat.ai/install/configuration/custom_config.html\n\n', + 'Custom config file missing or YAML format invalid.\n\nCheck out the latest config file guide for configurable options and features.\nhttps://www.librechat.ai/docs/configuration/librechat_yaml\n\n', ); i === 0 && i++; return null; @@ -72,7 +72,7 @@ Please specify a correct \`imageOutputType\` value (case-sensitive). - ${EImageOutputType.WEBP} Refer to the latest config file guide for more information: - https://docs.librechat.ai/install/configuration/custom_config.html`, + https://www.librechat.ai/docs/configuration/librechat_yaml`, ); } if (!result.success) { diff --git a/api/server/services/ToolService.js b/api/server/services/ToolService.js index 0a10a9d394f..149afc5df05 100644 --- a/api/server/services/ToolService.js +++ b/api/server/services/ToolService.js @@ -39,57 +39,65 @@ const filteredTools = new Set([ * @param {object} params - The parameters for the function. * @param {string} params.directory - The directory path where the tools are located. * @param {Array} [params.adminFilter=[]] - Array of admin-defined tool keys to exclude from loading. + * @param {Array} [params.adminIncluded=[]] - Array of admin-defined tool keys to include from loading. * @returns {Record} An object mapping each tool's plugin key to its instance. */ -function loadAndFormatTools({ directory, adminFilter = [] }) { +function loadAndFormatTools({ directory, adminFilter = [], adminIncluded = [] }) { const filter = new Set([...adminFilter, ...filteredTools]); + const included = new Set(adminIncluded); const tools = []; /* Structured Tools Directory */ const files = fs.readdirSync(directory); + if (included.size > 0 && adminFilter.length > 0) { + logger.warn( + 'Both `includedTools` and `filteredTools` are defined; `filteredTools` will be ignored.', + ); + } + for (const file of files) { - if (file.endsWith('.js') && !filter.has(file)) { - const filePath = path.join(directory, file); - let ToolClass = null; - try { - ToolClass = require(filePath); - } catch (error) { - logger.error(`[loadAndFormatTools] Error loading tool from ${filePath}:`, error); - continue; - } + const filePath = path.join(directory, file); + if (!file.endsWith('.js') || (filter.has(file) && included.size === 0)) { + continue; + } - if (!ToolClass) { - continue; - } + let ToolClass = null; + try { + ToolClass = require(filePath); + } catch (error) { + logger.error(`[loadAndFormatTools] Error loading tool from ${filePath}:`, error); + continue; + } - if (ToolClass.prototype instanceof StructuredTool) { - /** @type {StructuredTool | null} */ - let toolInstance = null; - try { - toolInstance = new ToolClass({ override: true }); - } catch (error) { - logger.error( - `[loadAndFormatTools] Error initializing \`${file}\` tool; if it requires authentication, is the \`override\` field configured?`, - error, - ); - continue; - } + if (!ToolClass || !(ToolClass.prototype instanceof StructuredTool)) { + continue; + } - if (!toolInstance) { - continue; - } + if (included.size > 0 && !included.has(file)) { + continue; + } - const formattedTool = formatToOpenAIAssistantTool(toolInstance); - tools.push(formattedTool); - } + let toolInstance = null; + try { + toolInstance = new ToolClass({ override: true }); + } catch (error) { + logger.error( + `[loadAndFormatTools] Error initializing \`${file}\` tool; if it requires authentication, is the \`override\` field configured?`, + error, + ); + continue; + } + + if (!toolInstance) { + continue; } + + const formattedTool = formatToOpenAIAssistantTool(toolInstance); + tools.push(formattedTool); } - /** - * Basic Tools; schema: { input: string } - */ + /** Basic Tools; schema: { input: string } */ const basicToolInstances = [new Calculator()]; - for (const toolInstance of basicToolInstances) { const formattedTool = formatToOpenAIAssistantTool(toolInstance); tools.push(formattedTool); diff --git a/api/server/services/start/checks.js b/api/server/services/start/checks.js index 3593a5bafb1..2e7ba0a3d0a 100644 --- a/api/server/services/start/checks.js +++ b/api/server/services/start/checks.js @@ -27,15 +27,13 @@ function checkVariables() { } if (hasDefaultSecrets) { - logger.info( - `Please replace any default secret values. - - For your conveninence, fork & run this replit to generate your own secret values: + logger.info('Please replace any default secret values.'); + logger.info(`\u200B - https://replit.com/@daavila/crypto#index.js - - `, - ); + For your convenience, use this tool to generate your own secret values: + https://www.librechat.ai/toolkit/creds_generator + + \u200B`); } if (process.env.GOOGLE_API_KEY) { @@ -99,7 +97,12 @@ function checkAzureVariables() { function checkConfig(config) { if (config.version !== Constants.CONFIG_VERSION) { logger.info( - `\nOutdated Config version: ${config.version}. Current version: ${Constants.CONFIG_VERSION}\n\nCheck out the latest config file guide for new options and features.\nhttps://docs.librechat.ai/install/configuration/custom_config.html\n\n`, + `\nOutdated Config version: ${config.version} +Latest version: ${Constants.CONFIG_VERSION} + + Check out the Config changelogs for the latest options and features added. + + https://www.librechat.ai/changelog\n\n`, ); } } diff --git a/api/server/utils/import/importers.js b/api/server/utils/import/importers.js index f1762a988eb..6e151ead277 100644 --- a/api/server/utils/import/importers.js +++ b/api/server/utils/import/importers.js @@ -202,7 +202,7 @@ function processConversation(conv, importBatchBuilder, requestUserId) { const isCreatedByUser = role === 'user'; let sender = isCreatedByUser ? 'user' : 'GPT-3.5'; const model = mapping.message.metadata.model_slug || openAISettings.model.default; - if (model === 'gpt-4') { + if (model.includes('gpt-4')) { sender = 'GPT-4'; } diff --git a/api/utils/tokens.js b/api/utils/tokens.js index f049fe08c22..b0d90988219 100644 --- a/api/utils/tokens.js +++ b/api/utils/tokens.js @@ -48,6 +48,7 @@ const openAIModels = { 'gpt-4-32k-0613': 32758, // -10 from max 'gpt-4-1106': 127990, // -10 from max 'gpt-4-0125': 127990, // -10 from max + 'gpt-4o': 127990, // -10 from max 'gpt-4-turbo': 127990, // -10 from max 'gpt-4-vision': 127990, // -10 from max 'gpt-3.5-turbo': 16375, // -10 from max diff --git a/client/src/Providers/SearchContext.tsx b/client/src/Providers/SearchContext.tsx new file mode 100644 index 00000000000..678818aa186 --- /dev/null +++ b/client/src/Providers/SearchContext.tsx @@ -0,0 +1,6 @@ +import { createContext, useContext } from 'react'; +import useSearch from '~/hooks/Conversations/useSearch'; +type SearchContextType = ReturnType; + +export const SearchContext = createContext({} as SearchContextType); +export const useSearchContext = () => useContext(SearchContext); diff --git a/client/src/Providers/index.ts b/client/src/Providers/index.ts index 32e5c25dc49..debfdeac046 100644 --- a/client/src/Providers/index.ts +++ b/client/src/Providers/index.ts @@ -2,6 +2,7 @@ export { default as ToastProvider } from './ToastContext'; export { default as AssistantsProvider } from './AssistantsContext'; export * from './ChatContext'; export * from './ToastContext'; +export * from './SearchContext'; export * from './FileMapContext'; export * from './AssistantsContext'; export * from './AssistantsMapContext'; diff --git a/client/src/components/Chat/Input/Mention.tsx b/client/src/components/Chat/Input/Mention.tsx index 582dd83464a..229dd5a5451 100644 --- a/client/src/components/Chat/Input/Mention.tsx +++ b/client/src/components/Chat/Input/Mention.tsx @@ -99,7 +99,7 @@ export default function Mention({ } else if (e.key === 'ArrowUp') { setActiveIndex((prevIndex) => (prevIndex - 1 + matches.length) % matches.length); } else if (e.key === 'Enter' || e.key === 'Tab') { - const mentionOption = matches[0] as MentionOption | undefined; + const mentionOption = matches[activeIndex] as MentionOption | undefined; if (mentionOption?.type === 'endpoint') { e.preventDefault(); } else if (e.key === 'Enter') { diff --git a/client/src/components/Chat/Landing.tsx b/client/src/components/Chat/Landing.tsx index 073ffd64626..5e2392bfcfb 100644 --- a/client/src/components/Chat/Landing.tsx +++ b/client/src/components/Chat/Landing.tsx @@ -76,7 +76,7 @@ export default function Landing({ Header }: { Header?: ReactNode }) { */} ) : ( -
+
{endpoint === EModelEndpoint.assistants ? conversation?.greeting ?? localize('com_nav_welcome_assistant') : conversation?.greeting ?? localize('com_nav_welcome_message')} diff --git a/client/src/components/Chat/Menus/Models/MenuButton.tsx b/client/src/components/Chat/Menus/Models/MenuButton.tsx index 404b858e7c4..a8ae40ada64 100644 --- a/client/src/components/Chat/Menus/Models/MenuButton.tsx +++ b/client/src/components/Chat/Menus/Models/MenuButton.tsx @@ -2,14 +2,19 @@ import { Trigger } from '@radix-ui/react-popover'; import type { TModelSpec, TEndpointsConfig } from 'librechat-data-provider'; import { useLocalize } from '~/hooks'; import SpecIcon from './SpecIcon'; +import { cn } from '~/utils'; export default function MenuButton({ selected, + className = '', + textClassName = '', primaryText = '', secondaryText = '', endpointsConfig, }: { selected?: TModelSpec; + className?: string; + textClassName?: string; primaryText?: string; secondaryText?: string; endpointsConfig: TEndpointsConfig; @@ -18,13 +23,16 @@ export default function MenuButton({ return (
{selected && selected.showIconInHeader && ( )} -
+
{!selected ? localize('com_ui_none_selected') : primaryText}{' '} {!!secondaryText && {secondaryText}}
diff --git a/client/src/components/Chat/Menus/Models/ModelSpec.tsx b/client/src/components/Chat/Menus/Models/ModelSpec.tsx index e1f578915dd..d268d44125b 100644 --- a/client/src/components/Chat/Menus/Models/ModelSpec.tsx +++ b/client/src/components/Chat/Menus/Models/ModelSpec.tsx @@ -64,7 +64,7 @@ const MenuItem: FC = ({
{showIconInMenu && } -
+
{title}
{description}
diff --git a/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx b/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx index dbd5a441de1..cc1fb2d1d99 100644 --- a/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx +++ b/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx @@ -70,8 +70,10 @@ export default function ModelSpecsMenu({ modelSpecs }: { modelSpecs: TModelSpec[ return ( diff --git a/client/src/components/Chat/Messages/Content/SearchContent.tsx b/client/src/components/Chat/Messages/Content/SearchContent.tsx new file mode 100644 index 00000000000..109bbb1ebf1 --- /dev/null +++ b/client/src/components/Chat/Messages/Content/SearchContent.tsx @@ -0,0 +1,53 @@ +import { Suspense } from 'react'; +import type { TMessage, TMessageContentParts } from 'librechat-data-provider'; +import { UnfinishedMessage } from './MessageContent'; +import { DelayedRender } from '~/components/ui'; +import MarkdownLite from './MarkdownLite'; +import { cn } from '~/utils'; +import Part from './Part'; + +const SearchContent = ({ message }: { message: TMessage }) => { + const { messageId } = message; + if (Array.isArray(message.content) && message.content.length > 0) { + return ( + <> + {message.content + .filter((part: TMessageContentParts | undefined) => part) + .map((part: TMessageContentParts | undefined, idx: number) => { + if (!part) { + return null; + } + return ( + + ); + })} + {message.unfinished && ( + + + + + + )} + + ); + } + + return ( +
+ +
+ ); +}; + +export default SearchContent; diff --git a/client/src/components/Chat/Messages/MinimalMessages.tsx b/client/src/components/Chat/Messages/MinimalMessages.tsx new file mode 100644 index 00000000000..be4d0cad2d7 --- /dev/null +++ b/client/src/components/Chat/Messages/MinimalMessages.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { cn } from '~/utils'; + +const MinimalMessages = React.forwardRef( + ( + props: { children: React.ReactNode; className?: string }, + ref: React.ForwardedRef, + ) => { + return ( +
+
+
+
+
+
+
+ {props.children} +
+
+
+
+
+
+
+
+ ); + }, +); + +export default MinimalMessages; diff --git a/client/src/components/Chat/Messages/SearchButtons.tsx b/client/src/components/Chat/Messages/SearchButtons.tsx new file mode 100644 index 00000000000..eba93e1b491 --- /dev/null +++ b/client/src/components/Chat/Messages/SearchButtons.tsx @@ -0,0 +1,40 @@ +import { Link } from 'lucide-react'; +import type { TMessage } from 'librechat-data-provider'; +import { useLocalize, useNavigateToConvo } from '~/hooks'; +import { useSearchContext } from '~/Providers'; +import { getConversationById } from '~/utils'; + +export default function SearchButtons({ message }: { message: TMessage }) { + const localize = useLocalize(); + const { searchQueryRes } = useSearchContext(); + const { navigateWithLastTools } = useNavigateToConvo(); + + if (!message.conversationId) { + return null; + } + + const clickHandler = (event: React.MouseEvent) => { + event.preventDefault(); + + const conversation = getConversationById(searchQueryRes?.data, message.conversationId); + if (!conversation) { + return; + } + + document.title = message.title ?? ''; + navigateWithLastTools(conversation); + }; + + return ( + + ); +} diff --git a/client/src/components/Chat/Messages/SearchMessage.tsx b/client/src/components/Chat/Messages/SearchMessage.tsx new file mode 100644 index 00000000000..46829dad97a --- /dev/null +++ b/client/src/components/Chat/Messages/SearchMessage.tsx @@ -0,0 +1,61 @@ +import { useRecoilValue } from 'recoil'; +import { useAuthContext, useLocalize } from '~/hooks'; +import type { TMessageProps } from '~/common'; +import Icon from '~/components/Chat/Messages/MessageIcon'; +import SearchContent from './Content/SearchContent'; +import SearchButtons from './SearchButtons'; +import SubRow from './SubRow'; +import { cn } from '~/utils'; +import store from '~/store'; + +export default function Message({ message }: Pick) { + const UsernameDisplay = useRecoilValue(store.UsernameDisplay); + const { user } = useAuthContext(); + const localize = useLocalize(); + + if (!message) { + return null; + } + + const { isCreatedByUser } = message ?? {}; + + let messageLabel = ''; + if (isCreatedByUser) { + messageLabel = UsernameDisplay ? user?.name || user?.username : localize('com_user_message'); + } else { + messageLabel = message.sender; + } + + return ( + <> +
+
+
+
+
+
+
+ +
+
+
+
+
+
{messageLabel}
+
+
+ +
+
+ + + +
+
+
+
+ + ); +} diff --git a/client/src/components/Chat/SearchView.tsx b/client/src/components/Chat/SearchView.tsx deleted file mode 100644 index 5feed132ccd..00000000000 --- a/client/src/components/Chat/SearchView.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { memo } from 'react'; -import { useRecoilValue } from 'recoil'; -import MessagesView from './Messages/MessagesView'; -import store from '~/store'; - -import Header from './Header'; - -function SearchView() { - const searchResultMessagesTree = useRecoilValue(store.searchResultMessagesTree); - - return ( -
-
-
- } /> -
-
-
- ); -} - -export default memo(SearchView); diff --git a/client/src/components/Conversations/ArchiveButton.tsx b/client/src/components/Conversations/ArchiveButton.tsx index ce53584af75..d35e61c9147 100644 --- a/client/src/components/Conversations/ArchiveButton.tsx +++ b/client/src/components/Conversations/ArchiveButton.tsx @@ -1,12 +1,10 @@ -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; +import { useParams, useNavigate } from 'react-router-dom'; import type { MouseEvent, FocusEvent, KeyboardEvent } from 'react'; -import { useParams } from 'react-router-dom'; - -import { useArchiveConversationMutation } from '~/data-provider'; - +import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; import { useConversations, useLocalize, useNewConvo } from '~/hooks'; -import { useToastContext } from '~/Providers'; +import { useArchiveConversationMutation } from '~/data-provider'; import { NotificationSeverity } from '~/common'; +import { useToastContext } from '~/Providers'; type ArchiveButtonProps = { conversationId: string; @@ -23,8 +21,9 @@ export default function ArchiveButton({ className = '', }: ArchiveButtonProps) { const localize = useLocalize(); - const { newConversation } = useNewConvo(); + const navigate = useNavigate(); const { showToast } = useToastContext(); + const { newConversation } = useNewConvo(); const { refreshConversations } = useConversations(); const { conversationId: currentConvoId } = useParams(); @@ -42,8 +41,9 @@ export default function ArchiveButton({ { conversationId, isArchived: shouldArchive }, { onSuccess: () => { - if (currentConvoId === conversationId) { + if (currentConvoId === conversationId || currentConvoId === 'new') { newConversation(); + navigate('/c/new', { replace: true }); } refreshConversations(); retainView(); diff --git a/client/src/components/Conversations/Conversations.tsx b/client/src/components/Conversations/Conversations.tsx index f46e457c4a1..636c11763b0 100644 --- a/client/src/components/Conversations/Conversations.tsx +++ b/client/src/components/Conversations/Conversations.tsx @@ -2,6 +2,7 @@ import { useMemo, memo } from 'react'; import { parseISO, isToday } from 'date-fns'; import { TConversation } from 'librechat-data-provider'; import { groupConversationsByDate } from '~/utils'; +import { useLocalize } from '~/hooks'; import Convo from './Convo'; const Conversations = ({ @@ -13,12 +14,14 @@ const Conversations = ({ moveToTop: () => void; toggleNav: () => void; }) => { + const localize = useLocalize(); const groupedConversations = useMemo( () => groupConversationsByDate(conversations), [conversations], ); const firstTodayConvoId = useMemo( - () => conversations.find((convo) => isToday(parseISO(convo.updatedAt)))?.conversationId, + () => + conversations.find((convo) => convo && isToday(parseISO(convo.updatedAt)))?.conversationId, [conversations], ); @@ -37,7 +40,7 @@ const Conversations = ({ paddingLeft: '10px', }} > - {groupName} + {localize(groupName) || groupName}
{convos.map((convo, i) => ( ) => { diff --git a/client/src/components/Conversations/DeleteButton.tsx b/client/src/components/Conversations/DeleteButton.tsx index 31aa337ec80..904846ab705 100644 --- a/client/src/components/Conversations/DeleteButton.tsx +++ b/client/src/components/Conversations/DeleteButton.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; -import { useParams } from 'react-router-dom'; import { QueryKeys } from 'librechat-data-provider'; import { useQueryClient } from '@tanstack/react-query'; +import { useParams, useNavigate } from 'react-router-dom'; import type { TMessage } from 'librechat-data-provider'; import { useDeleteConversationMutation } from '~/data-provider'; import { @@ -26,13 +26,15 @@ export default function DeleteButton({ className = '', }) { const localize = useLocalize(); + const navigate = useNavigate(); const queryClient = useQueryClient(); const { newConversation } = useNewConvo(); const { conversationId: currentConvoId } = useParams(); const deleteConvoMutation = useDeleteConversationMutation({ onSuccess: () => { - if (currentConvoId === conversationId) { + if (currentConvoId === conversationId || currentConvoId === 'new') { newConversation(); + navigate('/c/new', { replace: true }); } retainView(); }, diff --git a/client/src/components/Nav/Nav.tsx b/client/src/components/Nav/Nav.tsx index f096622ecad..e9d7c66b96e 100644 --- a/client/src/components/Nav/Nav.tsx +++ b/client/src/components/Nav/Nav.tsx @@ -1,7 +1,6 @@ import { useParams } from 'react-router-dom'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useRecoilValue } from 'recoil'; import { useCallback, useEffect, useState, useMemo, memo } from 'react'; -import type { ConversationListResponse } from 'librechat-data-provider'; import { useMediaQuery, useAuthContext, @@ -10,9 +9,10 @@ import { useNavScrolling, useConversations, } from '~/hooks'; -import { useSearchInfiniteQuery, useConversationsInfiniteQuery } from '~/data-provider'; +import { useConversationsInfiniteQuery } from '~/data-provider'; import { TooltipProvider, Tooltip } from '~/components/ui'; import { Conversations } from '~/components/Conversations'; +import { useSearchContext } from '~/Providers'; import { Spinner } from '~/components/svg'; import SearchBar from './SearchBar'; import NavToggle from './NavToggle'; @@ -47,26 +47,18 @@ const Nav = ({ navVisible, setNavVisible }) => { } }, [isSmallScreen]); - const [pageNumber, setPageNumber] = useState(1); + const { newConversation } = useConversation(); const [showLoading, setShowLoading] = useState(false); - - const searchQuery = useRecoilValue(store.searchQuery); const isSearchEnabled = useRecoilValue(store.isSearchEnabled); - const { newConversation, searchPlaceholderConversation } = useConversation(); const { refreshConversations } = useConversations(); - const setSearchResultMessages = useSetRecoilState(store.searchResultMessages); + const { pageNumber, searchQuery, setPageNumber, searchQueryRes } = useSearchContext(); const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useConversationsInfiniteQuery( { pageNumber: pageNumber.toString(), isArchived: false }, { enabled: isAuthenticated }, ); - const searchQueryRes = useSearchInfiniteQuery( - { pageNumber: pageNumber.toString(), searchQuery: searchQuery, isArchived: false }, - { enabled: isAuthenticated && !!searchQuery.length }, - ); - const { containerRef, moveToTop } = useNavScrolling({ setShowLoading, hasNextPage: searchQuery ? searchQueryRes.hasNextPage : hasNextPage, @@ -81,21 +73,6 @@ const Nav = ({ navVisible, setNavVisible }) => { [data, searchQuery, searchQueryRes?.data], ); - const onSearchSuccess = useCallback(({ data }: { data: ConversationListResponse }) => { - const res = data; - searchPlaceholderConversation(); - setSearchResultMessages(res.messages); - /* disabled due recoil methods not recognized as state setters */ - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); // Empty dependency array - - useEffect(() => { - //we use isInitialLoading here instead of isLoading because query is disabled by default - if (searchQueryRes.data) { - onSearchSuccess({ data: searchQueryRes.data.pages[0] }); - } - }, [searchQueryRes.data, searchQueryRes.isInitialLoading, onSearchSuccess]); - const clearSearch = () => { setPageNumber(1); refreshConversations(); @@ -183,7 +160,7 @@ const Nav = ({ navVisible, setNavVisible }) => { setIsHovering={setIsToggleHovering} onToggle={toggleNavVisible} navVisible={navVisible} - className="fixed left-0 top-1/2 z-40" + className="fixed left-0 top-1/2 z-40 hidden md:flex" />
diff --git a/client/src/components/Nav/NewChat.tsx b/client/src/components/Nav/NewChat.tsx index a060235739c..19e99a66209 100644 --- a/client/src/components/Nav/NewChat.tsx +++ b/client/src/components/Nav/NewChat.tsx @@ -1,3 +1,5 @@ +import { Search } from 'lucide-react'; +import { useRecoilValue } from 'recoil'; import { useNavigate } from 'react-router-dom'; import { useGetEndpointsQuery } from 'librechat-data-provider/react-query'; import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; @@ -7,6 +9,50 @@ import ConvoIconURL from '~/components/Endpoints/ConvoIconURL'; import { useLocalize, useNewConvo } from '~/hooks'; import { NewChatIcon } from '~/components/svg'; import store from '~/store'; +import type { TConversation } from 'librechat-data-provider'; + +const NewChatButtonIcon = ({ conversation }: { conversation: TConversation | null }) => { + const searchQuery = useRecoilValue(store.searchQuery); + const { data: endpointsConfig } = useGetEndpointsQuery(); + + if (searchQuery) { + return ( +
+ +
+ ); + } + + let { endpoint = '' } = conversation ?? {}; + const iconURL = conversation?.iconURL ?? ''; + endpoint = getIconEndpoint({ endpointsConfig, iconURL, endpoint }); + + const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); + const endpointIconURL = getEndpointField(endpointsConfig, endpoint, 'iconURL'); + const iconKey = getIconKey({ endpoint, endpointsConfig, endpointType, endpointIconURL }); + const Icon = icons[iconKey]; + + return ( +
+ {iconURL && iconURL.includes('http') ? ( + + ) : ( +
+ {endpoint && + Icon && + Icon({ + size: 41, + context: 'nav', + className: 'h-2/3 w-2/3', + endpoint, + endpointType, + iconURL: endpointIconURL, + })} +
+ )} +
+ ); +}; export default function NewChat({ index = 0, @@ -22,16 +68,7 @@ export default function NewChat({ const navigate = useNavigate(); const localize = useLocalize(); - const { data: endpointsConfig } = useGetEndpointsQuery(); const { conversation } = store.useCreateConversationAtom(index); - let { endpoint = '' } = conversation ?? {}; - const iconURL = conversation?.iconURL ?? ''; - endpoint = getIconEndpoint({ endpointsConfig, iconURL, endpoint }); - - const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); - const endpointIconURL = getEndpointField(endpointsConfig, endpoint, 'iconURL'); - const iconKey = getIconKey({ endpoint, endpointsConfig, endpointType, endpointIconURL }); - const Icon = icons[iconKey]; const clickHandler = (event: React.MouseEvent) => { if (event.button === 0 && !event.ctrlKey) { @@ -53,24 +90,7 @@ export default function NewChat({ onClick={clickHandler} className="group flex h-10 items-center gap-2 rounded-lg px-2 font-medium hover:bg-gray-200 dark:hover:bg-gray-700" > -
- {iconURL && iconURL.includes('http') ? ( - - ) : ( -
- {endpoint && - Icon && - Icon({ - size: 41, - context: 'nav', - className: 'h-2/3 w-2/3', - endpoint, - endpointType, - iconURL: endpointIconURL, - })} -
- )} -
+
{localize('com_ui_new_chat')}
diff --git a/client/src/components/Nav/SearchBar.tsx b/client/src/components/Nav/SearchBar.tsx index abb20f53ac4..5518fb2865c 100644 --- a/client/src/components/Nav/SearchBar.tsx +++ b/client/src/components/Nav/SearchBar.tsx @@ -1,7 +1,9 @@ -import { forwardRef, useState, useCallback, useMemo, Ref } from 'react'; +import debounce from 'lodash/debounce'; import { Search, X } from 'lucide-react'; import { useSetRecoilState } from 'recoil'; -import debounce from 'lodash/debounce'; +import { QueryKeys } from 'librechat-data-provider'; +import { useQueryClient } from '@tanstack/react-query'; +import { forwardRef, useState, useCallback, useMemo, Ref } from 'react'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; import store from '~/store'; @@ -12,6 +14,8 @@ type SearchBarProps = { const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) => { const { clearSearch } = props; + const queryClient = useQueryClient(); + const clearConvoState = store.useClearConvoState(); const setSearchQuery = useSetRecoilState(store.searchQuery); const [showClearIcon, setShowClearIcon] = useState(false); const [text, setText] = useState(''); @@ -31,7 +35,17 @@ const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) = } }; - const sendRequest = useCallback((value: string) => setSearchQuery(value), [setSearchQuery]); + const sendRequest = useCallback( + (value: string) => { + setSearchQuery(value); + if (!value) { + return; + } + queryClient.invalidateQueries([QueryKeys.messages]); + clearConvoState(); + }, + [queryClient, clearConvoState, setSearchQuery], + ); const debouncedSendRequest = useMemo(() => debounce(sendRequest, 350), [sendRequest]); const onChange = (e: React.FormEvent) => { diff --git a/client/src/hooks/Conversations/index.ts b/client/src/hooks/Conversations/index.ts index e517acb58af..be63e73a646 100644 --- a/client/src/hooks/Conversations/index.ts +++ b/client/src/hooks/Conversations/index.ts @@ -1,3 +1,4 @@ +export { default as useSearch } from './useSearch'; export { default as usePresets } from './usePresets'; export { default as useGetSender } from './useGetSender'; export { default as useDefaultConvo } from './useDefaultConvo'; diff --git a/client/src/hooks/Conversations/useNavigateToConvo.tsx b/client/src/hooks/Conversations/useNavigateToConvo.tsx index 0a0e1ae812b..f2384becac3 100644 --- a/client/src/hooks/Conversations/useNavigateToConvo.tsx +++ b/client/src/hooks/Conversations/useNavigateToConvo.tsx @@ -1,6 +1,6 @@ import { useQueryClient } from '@tanstack/react-query'; import { useSetRecoilState, useResetRecoilState } from 'recoil'; -import { QueryKeys } from 'librechat-data-provider'; +import { QueryKeys, EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider'; import type { TConversation, TEndpointsConfig, TModelsConfig } from 'librechat-data-provider'; import { buildDefaultConvo, getDefaultEndpoint, getEndpointField } from '~/utils'; import useOriginNavigate from '../useOriginNavigate'; @@ -51,8 +51,28 @@ const useNavigateToConvo = (index = 0) => { navigate(convo?.conversationId); }; + const navigateWithLastTools = (conversation: TConversation) => { + // set conversation to the new conversation + if (conversation?.endpoint === EModelEndpoint.gptPlugins) { + let lastSelectedTools = []; + try { + lastSelectedTools = + JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_TOOLS) ?? '') ?? []; + } catch (e) { + // console.error(e); + } + navigateToConvo({ + ...conversation, + tools: conversation?.tools?.length ? conversation?.tools : lastSelectedTools, + }); + } else { + navigateToConvo(conversation); + } + }; + return { navigateToConvo, + navigateWithLastTools, }; }; diff --git a/client/src/hooks/Conversations/useSearch.ts b/client/src/hooks/Conversations/useSearch.ts new file mode 100644 index 00000000000..60980b2ab61 --- /dev/null +++ b/client/src/hooks/Conversations/useSearch.ts @@ -0,0 +1,69 @@ +import { useEffect, useState, useCallback } from 'react'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useNavigate, useLocation } from 'react-router-dom'; +import { useGetSearchEnabledQuery } from 'librechat-data-provider/react-query'; +import { useSearchInfiniteQuery } from '~/data-provider'; +import useConversation from './useConversation'; +import store from '~/store'; + +export default function useSearchMessages({ isAuthenticated }: { isAuthenticated: boolean }) { + const navigate = useNavigate(); + const location = useLocation(); + const [pageNumber, setPageNumber] = useState(1); + const { searchPlaceholderConversation } = useConversation(); + + const searchQuery = useRecoilValue(store.searchQuery); + const setIsSearchEnabled = useSetRecoilState(store.isSearchEnabled); + + const searchEnabledQuery = useGetSearchEnabledQuery({ enabled: isAuthenticated }); + const searchQueryRes = useSearchInfiniteQuery( + { pageNumber: pageNumber.toString(), searchQuery: searchQuery, isArchived: false }, + { enabled: isAuthenticated && !!searchQuery.length }, + ); + + useEffect(() => { + if (searchQuery && searchQuery.length > 0) { + navigate('/search', { replace: true }); + return; + } + + if (location.pathname && location.pathname.includes('/c/')) { + return; + } + navigate('/c/new', { replace: true }); + /* Disabled eslint rule because we don't want to run this effect when location changes */ + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [navigate, searchQuery]); + + useEffect(() => { + if (searchEnabledQuery.data) { + setIsSearchEnabled(searchEnabledQuery.data); + } else if (searchEnabledQuery.isError) { + console.error('Failed to get search enabled', searchEnabledQuery.error); + } + }, [ + searchEnabledQuery.data, + searchEnabledQuery.error, + searchEnabledQuery.isError, + setIsSearchEnabled, + ]); + + const onSearchSuccess = useCallback( + () => searchPlaceholderConversation(), + [searchPlaceholderConversation], + ); + + useEffect(() => { + //we use isInitialLoading here instead of isLoading because query is disabled by default + if (searchQueryRes.data) { + onSearchSuccess(); + } + }, [searchQueryRes.data, searchQueryRes.isInitialLoading, onSearchSuccess]); + + return { + pageNumber, + searchQuery, + setPageNumber, + searchQueryRes, + }; +} diff --git a/client/src/hooks/SSE/useSSE.ts b/client/src/hooks/SSE/useSSE.ts index 23422538713..f12e0996703 100644 --- a/client/src/hooks/SSE/useSSE.ts +++ b/client/src/hooks/SSE/useSSE.ts @@ -390,6 +390,11 @@ export default function useSSE(submission: TSubmission | null, index = 0) { }); setIsSubmitting(false); return; + } else if (!data.conversationId) { + const errorResponse = parseErrorResponse(data); + setMessages([...messages, message, errorResponse]); + setIsSubmitting(false); + return; } console.log('Error:', data); @@ -587,7 +592,6 @@ export default function useSSE(submission: TSubmission | null, index = 0) { console.error(error); console.log(e); setIsSubmitting(false); - return; } errorHandler({ data, submission: { ...submission, message } }); diff --git a/client/src/localization/languages/Ar.ts b/client/src/localization/languages/Ar.ts index 5c91af0adf5..ef8219c805f 100644 --- a/client/src/localization/languages/Ar.ts +++ b/client/src/localization/languages/Ar.ts @@ -280,6 +280,24 @@ export default { com_nav_setting_general: 'عام', com_nav_setting_data: 'تحكم في البيانات', /* The following are AI translated */ + com_ui_date_today: 'اليوم', + com_ui_date_yesterday: 'أمس', + com_ui_date_previous_7_days: 'الأيام السبعة السابقة', + com_ui_date_previous_30_days: 'الـ 30 يومًا السابقة', + com_ui_date_january: 'يناير', + com_ui_date_february: 'فبراير', + com_ui_date_march: 'مارس', + com_ui_date_april: 'أبريل', + com_ui_date_may: 'مايو', + com_ui_date_june: 'يونيو', + com_ui_date_july: 'يوليو', + com_ui_date_august: 'أغسطس', + com_ui_date_september: 'سبتمبر', + com_ui_date_october: 'أكتوبر', + com_ui_date_november: 'نوفمبر', + com_ui_date_december: 'ديسمبر', + com_ui_nothing_found: 'لم يتم العثور على أي شيء', + com_ui_go_to_conversation: 'انتقل إلى المحادثة', com_error_moderation: 'يبدو أن المحتوى المقدم قد تم وضع علامة عليه من قبل نظام الرقابة لدينا لعدم توافقه مع إرشادات مجتمعنا. لا نستطيع المضي قدمًا في هذا الموضوع المحدد. إذا كانت لديك أسئلة أخرى أو مواضيع ترغب في استكشافها، يرجى تحرير رسالتك، أو إنشاء محادثة جديدة.', com_error_no_user_key: 'لم يتم العثور على مفتاح. يرجى تقديم مفتاح والمحاولة مرة أخرى.', @@ -1534,6 +1552,78 @@ export const comparisons = { english: 'Data controls', translated: 'تحكم في البيانات', }, + com_ui_date_today: { + english: 'Today', + translated: 'اليوم', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'أمس', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: 'الأيام السبعة السابقة', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: 'الـ 30 يومًا السابقة', + }, + com_ui_date_january: { + english: 'January', + translated: 'يناير', + }, + com_ui_date_february: { + english: 'February', + translated: 'فبراير', + }, + com_ui_date_march: { + english: 'March', + translated: 'مارس', + }, + com_ui_date_april: { + english: 'April', + translated: 'أبريل', + }, + com_ui_date_may: { + english: 'May', + translated: 'مايو', + }, + com_ui_date_june: { + english: 'June', + translated: 'يونيو', + }, + com_ui_date_july: { + english: 'July', + translated: 'يوليو', + }, + com_ui_date_august: { + english: 'August', + translated: 'أغسطس', + }, + com_ui_date_september: { + english: 'September', + translated: 'سبتمبر', + }, + com_ui_date_october: { + english: 'October', + translated: 'أكتوبر', + }, + com_ui_date_november: { + english: 'November', + translated: 'نوفمبر', + }, + com_ui_date_december: { + english: 'December', + translated: 'ديسمبر', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'لم يتم العثور على أي شيء', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'انتقل إلى المحادثة', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/De.ts b/client/src/localization/languages/De.ts index 7c7e0741850..ac6ecec7bcc 100644 --- a/client/src/localization/languages/De.ts +++ b/client/src/localization/languages/De.ts @@ -464,6 +464,24 @@ export default { com_nav_setting_account: 'Konto', com_nav_language: 'Sprache', /* The following are AI Translated */ + com_ui_date_today: 'Heute', + com_ui_date_yesterday: 'Gestern', + com_ui_date_previous_7_days: 'Letzte 7 Tage', + com_ui_date_previous_30_days: 'Letzte 30 Tage', + com_ui_date_january: 'Januar', + com_ui_date_february: 'Februar', + com_ui_date_march: 'März', + com_ui_date_april: 'April', + com_ui_date_may: 'Mai', + com_ui_date_june: 'Juni', + com_ui_date_july: 'Juli', + com_ui_date_august: 'August', + com_ui_date_september: 'September', + com_ui_date_october: 'Oktober', + com_ui_date_november: 'November', + com_ui_date_december: 'Dezember', + com_ui_nothing_found: 'Keine Ergebnisse gefunden', + com_ui_go_to_conversation: 'Zum Chat wechseln', com_error_moderation: 'Es sieht so aus, als ob der übermittelte Inhalt von unserem Moderationssystem als nicht konform mit unseren Gemeinschaftsrichtlinien markiert wurde. Wir können mit diesem spezifischen Thema leider nicht fortfahren. Wenn du andere Fragen oder Themen hast, die du gerne erörtern möchtest, bearbeite bitte deine Nachricht oder starte eine neue Konversation.', com_error_no_user_key: @@ -2203,6 +2221,78 @@ export const comparisons = { english: 'Language', translated: 'Sprache', }, + com_ui_date_today: { + english: 'Today', + translated: 'Heute', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'Gestern', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: 'Letzte 7 Tage', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: 'Letzte 30 Tage', + }, + com_ui_date_january: { + english: 'January', + translated: 'Januar', + }, + com_ui_date_february: { + english: 'February', + translated: 'Februar', + }, + com_ui_date_march: { + english: 'March', + translated: 'März', + }, + com_ui_date_april: { + english: 'April', + translated: 'April', + }, + com_ui_date_may: { + english: 'May', + translated: 'Mai', + }, + com_ui_date_june: { + english: 'June', + translated: 'Juni', + }, + com_ui_date_july: { + english: 'July', + translated: 'Juli', + }, + com_ui_date_august: { + english: 'August', + translated: 'August', + }, + com_ui_date_september: { + english: 'September', + translated: 'September', + }, + com_ui_date_october: { + english: 'October', + translated: 'Oktober', + }, + com_ui_date_november: { + english: 'November', + translated: 'November', + }, + com_ui_date_december: { + english: 'December', + translated: 'Dezember', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'Keine Ergebnisse gefunden', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'Zum Chat wechseln', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/Eng.ts b/client/src/localization/languages/Eng.ts index 315fad50bd1..2007224fc17 100644 --- a/client/src/localization/languages/Eng.ts +++ b/client/src/localization/languages/Eng.ts @@ -54,6 +54,22 @@ export default { com_assistants_update_error: 'There was an error updating your assistant.', com_assistants_create_success: 'Successfully created', com_assistants_create_error: 'There was an error creating your assistant.', + com_ui_date_today: 'Today', + com_ui_date_yesterday: 'Yesterday', + com_ui_date_previous_7_days: 'Previous 7 days', + com_ui_date_previous_30_days: 'Previous 30 days', + com_ui_date_january: 'January', + com_ui_date_february: 'February', + com_ui_date_march: 'March', + com_ui_date_april: 'April', + com_ui_date_may: 'May', + com_ui_date_june: 'June', + com_ui_date_july: 'July', + com_ui_date_august: 'August', + com_ui_date_september: 'September', + com_ui_date_october: 'October', + com_ui_date_november: 'November', + com_ui_date_december: 'December', com_ui_field_required: 'This field is required', com_ui_download_error: 'Error downloading file. The file may have been deleted.', com_ui_attach_error_type: 'Unsupported file type for endpoint:', @@ -165,6 +181,8 @@ export default { com_ui_revoke: 'Revoke', com_ui_revoke_info: 'Revoke all user provided credentials', com_ui_import_conversation: 'Import', + com_ui_nothing_found: 'Nothing found', + com_ui_go_to_conversation: 'Go to conversation', com_ui_import_conversation_info: 'Import conversations from a JSON file', com_ui_import_conversation_success: 'Conversations imported successfully', com_ui_import_conversation_error: 'There was an error importing your conversations', diff --git a/client/src/localization/languages/Es.ts b/client/src/localization/languages/Es.ts index bde260d616c..66669791e5a 100644 --- a/client/src/localization/languages/Es.ts +++ b/client/src/localization/languages/Es.ts @@ -458,6 +458,24 @@ export default { com_nav_lang_auto: 'Detección automática', com_nav_lang_spanish: 'Español', /* The following are AI Translated */ + com_ui_date_today: 'Hoy', + com_ui_date_yesterday: 'Ayer', + com_ui_date_previous_7_days: 'Últimos 7 días', + com_ui_date_previous_30_days: 'Últimos 30 días', + com_ui_date_january: 'Enero', + com_ui_date_february: 'Febrero', + com_ui_date_march: 'Marzo', + com_ui_date_april: 'Abril', + com_ui_date_may: 'Mayo', + com_ui_date_june: 'Junio', + com_ui_date_july: 'Julio', + com_ui_date_august: 'Agosto', + com_ui_date_september: 'Septiembre', + com_ui_date_october: 'Octubre', + com_ui_date_november: 'Noviembre', + com_ui_date_december: 'Diciembre', + com_ui_nothing_found: 'No se encontró nada', + com_ui_go_to_conversation: 'Ir a la conversación', com_error_moderation: 'Parece que el contenido enviado ha sido marcado por nuestro sistema de moderación por no estar alineado con nuestras pautas comunitarias. No podemos proceder con este tema específico. Si tiene alguna otra pregunta o tema que le gustaría explorar, por favor edite su mensaje o cree una nueva conversación.', com_error_no_user_key: @@ -2184,6 +2202,78 @@ export const comparisons = { english: 'Español', translated: 'Español', }, + com_ui_date_today: { + english: 'Today', + translated: 'Hoy', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'Ayer', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: 'Últimos 7 días', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: 'Últimos 30 días', + }, + com_ui_date_january: { + english: 'January', + translated: 'Enero', + }, + com_ui_date_february: { + english: 'February', + translated: 'Febrero', + }, + com_ui_date_march: { + english: 'March', + translated: 'Marzo', + }, + com_ui_date_april: { + english: 'April', + translated: 'Abril', + }, + com_ui_date_may: { + english: 'May', + translated: 'Mayo', + }, + com_ui_date_june: { + english: 'June', + translated: 'Junio', + }, + com_ui_date_july: { + english: 'July', + translated: 'Julio', + }, + com_ui_date_august: { + english: 'August', + translated: 'Agosto', + }, + com_ui_date_september: { + english: 'September', + translated: 'Septiembre', + }, + com_ui_date_october: { + english: 'October', + translated: 'Octubre', + }, + com_ui_date_november: { + english: 'November', + translated: 'Noviembre', + }, + com_ui_date_december: { + english: 'December', + translated: 'Diciembre', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'No se encontró nada', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'Ir a la conversación', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/Fr.ts b/client/src/localization/languages/Fr.ts index 73e7f6b16f1..ea7ea122421 100644 --- a/client/src/localization/languages/Fr.ts +++ b/client/src/localization/languages/Fr.ts @@ -347,6 +347,55 @@ export default { com_nav_setting_data: 'Contrôles des données', com_nav_setting_account: 'Compte', /* The following are AI Translated */ + com_ui_date_today: 'Aujourd\'hui', + com_ui_date_yesterday: 'Hier', + com_ui_date_previous_7_days: '7 derniers jours', + com_ui_date_previous_30_days: '30 derniers jours', + com_ui_date_january: 'Janvier', + com_ui_date_february: 'Février', + com_ui_date_march: 'Mars', + com_ui_date_april: 'Avril', + com_ui_date_may: 'Mai', + com_ui_date_june: 'Juin', + com_ui_date_july: 'Juillet', + com_ui_date_august: 'Août', + com_ui_date_september: 'Septembre', + com_ui_date_october: 'Octobre', + com_ui_date_november: 'Novembre', + com_ui_date_december: 'Décembre', + com_ui_nothing_found: 'Aucun résultat trouvé', + com_ui_go_to_conversation: 'Aller à la conversation', + com_nav_tool_add: 'Ajouter', + com_nav_tool_remove: 'Supprimer', + com_nav_tool_dialog: 'Outils de l\'assistant', + com_nav_tool_dialog_description: + 'L\'assistant doit être sauvegardé pour conserver les sélections d\'outils.', + com_nav_tool_search: 'Outils de recherche', + com_nav_my_files: 'Mes fichiers', + com_nav_enter_to_send: 'Appuyez sur Entrée pour envoyer des messages', + com_nav_show_code: 'Toujours afficher le code lors de l\'utilisation de l\'interpréteur de code', + com_nav_archived_chats_empty: 'Vous n\'avez aucune conversation archivée.', + com_nav_language: 'Langue', + com_nav_lang_auto: 'Détection automatique', + com_nav_lang_english: 'Anglais', + com_nav_lang_chinese: 'Chinois', + com_nav_lang_german: 'Allemand', + com_nav_lang_spanish: 'Espagnol', + com_nav_lang_french: 'Français', + com_nav_lang_italian: 'Italien', + com_nav_lang_polish: 'Polonais', + com_nav_lang_brazilian_portuguese: 'Portugais brésilien', + com_nav_lang_russian: 'Russe', + com_nav_lang_japanese: 'Japonais', + com_nav_lang_swedish: 'Suédois', + com_nav_lang_korean: 'Coréen', + com_nav_lang_vietnamese: 'Vietnamien', + com_nav_lang_traditionalchinese: 'Chinois traditionnel', + com_nav_lang_arabic: 'Arabe', + com_nav_lang_turkish: 'Turc', + com_nav_lang_dutch: 'Néerlandais', + com_nav_lang_indonesia: 'Indonésie', + com_nav_lang_hebrew: 'Hébreu', com_error_moderation: 'Il semble que le contenu soumis ait été signalé par notre système de modération pour ne pas être conforme à nos lignes directrices communautaires. Nous ne pouvons pas procéder avec ce sujet spécifique. Si vous avez d\'autres questions ou sujets que vous souhaitez explorer, veuillez modifier votre message ou créer une nouvelle conversation.', com_error_no_user_key: 'Aucune clé trouvée. Veuillez fournir une clé et réessayer.', @@ -1730,6 +1779,198 @@ export const comparisons = { english: 'Account', translated: 'Compte', }, + com_ui_date_today: { + english: 'Today', + translated: 'Aujourd\'hui', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'Hier', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: '7 derniers jours', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: '30 derniers jours', + }, + com_ui_date_january: { + english: 'January', + translated: 'Janvier', + }, + com_ui_date_february: { + english: 'February', + translated: 'Février', + }, + com_ui_date_march: { + english: 'March', + translated: 'Mars', + }, + com_ui_date_april: { + english: 'April', + translated: 'Avril', + }, + com_ui_date_may: { + english: 'May', + translated: 'Mai', + }, + com_ui_date_june: { + english: 'June', + translated: 'Juin', + }, + com_ui_date_july: { + english: 'July', + translated: 'Juillet', + }, + com_ui_date_august: { + english: 'August', + translated: 'Août', + }, + com_ui_date_september: { + english: 'September', + translated: 'Septembre', + }, + com_ui_date_october: { + english: 'October', + translated: 'Octobre', + }, + com_ui_date_november: { + english: 'November', + translated: 'Novembre', + }, + com_ui_date_december: { + english: 'December', + translated: 'Décembre', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'Aucun résultat trouvé', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'Aller à la conversation', + }, + com_nav_tool_add: { + english: 'Add', + translated: 'Ajouter', + }, + com_nav_tool_remove: { + english: 'Remove', + translated: 'Supprimer', + }, + com_nav_tool_dialog: { + english: 'Assistant Tools', + translated: 'Outils de l\'assistant', + }, + com_nav_tool_dialog_description: { + english: 'Assistant must be saved to persist tool selections.', + translated: 'L\'assistant doit être sauvegardé pour conserver les sélections d\'outils.', + }, + com_nav_tool_search: { + english: 'Search tools', + translated: 'Outils de recherche', + }, + com_nav_my_files: { + english: 'My Files', + translated: 'Mes fichiers', + }, + com_nav_enter_to_send: { + english: 'Press Enter to send messages', + translated: 'Appuyez sur Entrée pour envoyer des messages', + }, + com_nav_show_code: { + english: 'Always show code when using code interpreter', + translated: 'Toujours afficher le code lors de l\'utilisation de l\'interpréteur de code', + }, + com_nav_archived_chats_empty: { + english: 'You have no archived conversations.', + translated: 'Vous n\'avez aucune conversation archivée.', + }, + com_nav_language: { + english: 'Language', + translated: 'Langue', + }, + com_nav_lang_auto: { + english: 'Auto detect', + translated: 'Détection automatique', + }, + com_nav_lang_english: { + english: 'English', + translated: 'Anglais', + }, + com_nav_lang_chinese: { + english: '中文', + translated: 'Chinois', + }, + com_nav_lang_german: { + english: 'Deutsch', + translated: 'Allemand', + }, + com_nav_lang_spanish: { + english: 'Español', + translated: 'Espagnol', + }, + com_nav_lang_french: { + english: 'Français ', + translated: 'Français', + }, + com_nav_lang_italian: { + english: 'Italiano', + translated: 'Italien', + }, + com_nav_lang_polish: { + english: 'Polski', + translated: 'Polonais', + }, + com_nav_lang_brazilian_portuguese: { + english: 'Português Brasileiro', + translated: 'Portugais brésilien', + }, + com_nav_lang_russian: { + english: 'Русский', + translated: 'Russe', + }, + com_nav_lang_japanese: { + english: '日本語', + translated: 'Japonais', + }, + com_nav_lang_swedish: { + english: 'Svenska', + translated: 'Suédois', + }, + com_nav_lang_korean: { + english: '한국어', + translated: 'Coréen', + }, + com_nav_lang_vietnamese: { + english: 'Tiếng Việt', + translated: 'Vietnamien', + }, + com_nav_lang_traditionalchinese: { + english: '繁體中文', + translated: 'Chinois traditionnel', + }, + com_nav_lang_arabic: { + english: 'العربية', + translated: 'Arabe', + }, + com_nav_lang_turkish: { + english: 'Türkçe', + translated: 'Turc', + }, + com_nav_lang_dutch: { + english: 'Nederlands', + translated: 'Néerlandais', + }, + com_nav_lang_indonesia: { + english: 'Indonesia', + translated: 'Indonésie', + }, + com_nav_lang_hebrew: { + english: 'עברית', + translated: 'Hébreu', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/It.ts b/client/src/localization/languages/It.ts index 4bf05abbb8e..83daab8cc97 100644 --- a/client/src/localization/languages/It.ts +++ b/client/src/localization/languages/It.ts @@ -508,6 +508,24 @@ export default { com_nav_setting_data: 'Controlli dati', com_nav_setting_account: 'Account', /* The following are AI Translated */ + com_ui_date_today: 'Oggi', + com_ui_date_yesterday: 'Ieri', + com_ui_date_previous_7_days: 'Ultimi 7 giorni', + com_ui_date_previous_30_days: 'Ultimi 30 giorni', + com_ui_date_january: 'Gennaio', + com_ui_date_february: 'Febbraio', + com_ui_date_march: 'Marzo', + com_ui_date_april: 'Aprile', + com_ui_date_may: 'Maggio', + com_ui_date_june: 'Giugno', + com_ui_date_july: 'Luglio', + com_ui_date_august: 'Agosto', + com_ui_date_september: 'Settembre', + com_ui_date_october: 'Ottobre', + com_ui_date_november: 'Novembre', + com_ui_date_december: 'Dicembre', + com_ui_nothing_found: 'Non è stato trovato nulla', + com_ui_go_to_conversation: 'Vai alla conversazione', com_user_message: 'Mostra nome utente nei messaggi', com_ui_fork: 'Duplica', com_ui_mention: 'Menziona un endpoint, assistente o preset per passare rapidamente ad esso', @@ -2341,6 +2359,78 @@ export const comparisons = { english: 'Account', translated: 'Account', }, + com_ui_date_today: { + english: 'Today', + translated: 'Oggi', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'Ieri', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: 'Ultimi 7 giorni', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: 'Ultimi 30 giorni', + }, + com_ui_date_january: { + english: 'January', + translated: 'Gennaio', + }, + com_ui_date_february: { + english: 'February', + translated: 'Febbraio', + }, + com_ui_date_march: { + english: 'March', + translated: 'Marzo', + }, + com_ui_date_april: { + english: 'April', + translated: 'Aprile', + }, + com_ui_date_may: { + english: 'May', + translated: 'Maggio', + }, + com_ui_date_june: { + english: 'June', + translated: 'Giugno', + }, + com_ui_date_july: { + english: 'July', + translated: 'Luglio', + }, + com_ui_date_august: { + english: 'August', + translated: 'Agosto', + }, + com_ui_date_september: { + english: 'September', + translated: 'Settembre', + }, + com_ui_date_october: { + english: 'October', + translated: 'Ottobre', + }, + com_ui_date_november: { + english: 'November', + translated: 'Novembre', + }, + com_ui_date_december: { + english: 'December', + translated: 'Dicembre', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'Non è stato trovato nulla', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'Vai alla conversazione', + }, com_user_message: { english: 'You', translated: 'Mostra nome utente nei messaggi', diff --git a/client/src/localization/languages/Jp.ts b/client/src/localization/languages/Jp.ts index f04655587ee..5a4227f649b 100644 --- a/client/src/localization/languages/Jp.ts +++ b/client/src/localization/languages/Jp.ts @@ -455,6 +455,24 @@ export default { com_nav_setting_data: 'データ管理', com_nav_setting_account: 'アカウント', /* The following are AI translated */ + com_ui_date_today: '今日', + com_ui_date_yesterday: '昨日', + com_ui_date_previous_7_days: '過去7日間', + com_ui_date_previous_30_days: '過去30日間', + com_ui_date_january: '1月', + com_ui_date_february: '2月', + com_ui_date_march: '3月', + com_ui_date_april: '4月', + com_ui_date_may: '5月', + com_ui_date_june: '6月', + com_ui_date_july: '7月', + com_ui_date_august: '8月', + com_ui_date_september: '9月', + com_ui_date_october: '10月', + com_ui_date_november: '11月', + com_ui_date_december: '12月', + com_ui_nothing_found: '該当するものが見つかりませんでした', + com_ui_go_to_conversation: '会話に移動する', com_error_invalid_user_key: '無効なキーが提供されました。キーを入力して再試行してください。', com_ui_none_selected: '選択されていません', com_ui_fork: '分岐', @@ -2193,6 +2211,78 @@ export const comparisons = { english: 'Account', translated: 'アカウント', }, + com_ui_date_today: { + english: 'Today', + translated: '今日', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: '昨日', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: '過去7日間', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: '過去30日間', + }, + com_ui_date_january: { + english: 'January', + translated: '1月', + }, + com_ui_date_february: { + english: 'February', + translated: '2月', + }, + com_ui_date_march: { + english: 'March', + translated: '3月', + }, + com_ui_date_april: { + english: 'April', + translated: '4月', + }, + com_ui_date_may: { + english: 'May', + translated: '5月', + }, + com_ui_date_june: { + english: 'June', + translated: '6月', + }, + com_ui_date_july: { + english: 'July', + translated: '7月', + }, + com_ui_date_august: { + english: 'August', + translated: '8月', + }, + com_ui_date_september: { + english: 'September', + translated: '9月', + }, + com_ui_date_october: { + english: 'October', + translated: '10月', + }, + com_ui_date_november: { + english: 'November', + translated: '11月', + }, + com_ui_date_december: { + english: 'December', + translated: '12月', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: '該当するものが見つかりませんでした', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: '会話に移動する', + }, com_error_invalid_user_key: { english: 'Invalid key provided. Please provide a key and try again.', translated: '無効なキーが提供されました。キーを入力して再試行してください。', diff --git a/client/src/localization/languages/Ko.ts b/client/src/localization/languages/Ko.ts index 904142c4a21..d84bde4cee2 100644 --- a/client/src/localization/languages/Ko.ts +++ b/client/src/localization/languages/Ko.ts @@ -260,6 +260,276 @@ export default { com_nav_search_placeholder: '메시지 검색', com_nav_setting_general: '일반', com_nav_setting_data: '데이터 제어', + /* The following are AI Translated */ + com_ui_date_today: '오늘', + com_ui_date_yesterday: '어제', + com_ui_date_previous_7_days: '지난 7일', + com_ui_date_previous_30_days: '지난 30일', + com_ui_date_january: '1월', + com_ui_date_february: '2월', + com_ui_date_march: '3월', + com_ui_date_april: '4월', + com_ui_date_may: '5월', + com_ui_date_june: '6월', + com_ui_date_july: '7월', + com_ui_date_august: '8월', + com_ui_date_september: '9월', + com_ui_date_october: '10월', + com_ui_date_november: '11월', + com_ui_date_december: '12월', + com_assistants_domain_info: '어시스턴트가 {0}에게 이 정보를 보냈습니다', + com_assistants_delete_actions_success: '어시스턴트에서 작업이 성공적으로 삭제되었습니다', + com_error_moderation: + '제출된 내용이 커뮤니티 가이드라인에 부합하지 않는다고 판단되어 모더레이션 시스템에 의해 차단되었습니다. 해당 주제로는 진행할 수 없습니다. 다른 질문이나 탐구하고 싶은 주제가 있다면 메시지를 수정하거나 새 대화를 시작해 주세요.', + com_error_no_user_key: '키를 찾을 수 없습니다. 키를 제공하고 다시 시도해주세요.', + com_error_no_base_url: '기본 URL이 없습니다. URL을 제공한 후 다시 시도해 주세요.', + com_error_invalid_user_key: '제공된 키가 유효하지 않습니다. 키를 제공하고 다시 시도해주세요.', + com_error_expired_user_key: + '{0}에 대한 키가 {1}에 만료되었습니다. 새 키를 제공하고 다시 시도해주세요.', + com_files_no_results: '결과가 없습니다.', + com_files_filter: '파일 필터링...', + com_files_number_selected: '{0}개의 파일({1}개 중)이 선택되었습니다', + com_sidepanel_select_assistant: '어시스턴트 선택', + com_sidepanel_parameters: '매개변수', + com_sidepanel_assistant_builder: '어시스턴트 제작기', + com_sidepanel_hide_panel: '패널 숨기기', + com_sidepanel_attach_files: '파일 첨부', + com_sidepanel_manage_files: '파일 관리', + com_assistants_capabilities: '기능', + com_assistants_knowledge: '지식', + com_assistants_knowledge_info: + 'Knowledge에 파일을 업로드하면 어시스턴트와의 대화에서 파일 내용이 포함될 수 있습니다.', + com_assistants_knowledge_disabled: + '지식으로 파일을 업로드하기 전에 Assistant를 생성하고 Code Interpreter 또는 Retrieval을 활성화한 후 저장해야 합니다.', + com_assistants_image_vision: '이미지 인식', + com_assistants_code_interpreter: '코드 인터프리터', + com_assistants_code_interpreter_files: '코드 인터프리터에서만 다음 파일을 사용할 수 있습니다:', + com_assistants_retrieval: '검색', + com_assistants_search_name: '이름으로 도우미 검색', + com_assistants_tools: '도구', + com_assistants_actions: '작업', + com_assistants_add_tools: '도구 추가', + com_assistants_add_actions: '작업 추가', + com_assistants_available_actions: '사용 가능한 작업', + com_assistants_running_action: '작업 진행 중', + com_assistants_completed_action: '{0}과 대화했습니다', + com_assistants_completed_function: '{0}을(를) 실행했습니다', + com_assistants_function_use: '어시스턴트는 {0}을(를) 사용했습니다.', + com_assistants_update_actions_success: '액션이 성공적으로 생성 또는 업데이트되었습니다', + com_assistants_update_actions_error: '작업을 생성하거나 업데이트하는 중에 오류가 발생했습니다.', + com_assistants_delete_actions_error: '작업 삭제 중 오류가 발생했습니다', + com_assistants_actions_info: + '어시스턴트가 API를 통해 정보를 검색하거나 작업을 수행할 수 있게 해줍니다.', + com_assistants_name_placeholder: '선택 사항: 어시스턴트의 이름', + com_assistants_instructions_placeholder: '보조 지침은 보조가 사용하는 시스템 지침입니다.', + com_assistants_description_placeholder: '옵션: 여기에 어시스턴트를 설명하세요', + com_assistants_actions_disabled: '어시스턴트를 만들어야 작업을 추가할 수 있습니다.', + com_assistants_update_success: '업데이트 성공', + com_assistants_update_error: '어시스턴트 업데이트 중 오류가 발생했습니다.', + com_assistants_create_success: '계정이 성공적으로 생성되었습니다', + com_assistants_create_error: '어시스턴트 생성 중 오류가 발생했습니다.', + com_ui_field_required: '이 필드는 필수입니다', + com_ui_download_error: '파일 다운로드 중 오류가 발생했습니다. 파일이 삭제되었을 수 있습니다.', + com_ui_attach_error_type: '엔드포인트에서 지원하지 않는 파일 형식입니다.', + com_ui_attach_error_size: '엔드포인트에 대한 파일 크기 제한을 초과했습니다.', + com_ui_attach_error: + '파일을 첨부할 수 없습니다. 대화를 생성하거나 선택하시거나 페이지를 새로고침해 보세요.', + com_ui_experimental: '실험적 기능', + com_ui_on: '켜기', + com_ui_off: '꺼짐', + com_ui_yes: '네', + com_ui_no: '아니요', + com_ui_ascending: '오름차순', + com_ui_descending: '내림차순', + com_ui_show_all: '전체 보기', + com_ui_name: '이름', + com_ui_date: '날짜', + com_ui_storage: '저장소', + com_ui_context: '맥락', + com_ui_size: '크기', + com_ui_host: '호스트', + com_ui_update: '업데이트', + com_ui_authentication: '인증', + com_ui_instructions: '설명', + com_ui_description: '설명', + com_ui_error: '오류', + com_ui_select: '선택', + com_ui_select_search_model: '이름으로 모델 검색', + com_ui_select_search_plugin: '이름으로 플러그인 검색', + com_ui_stop: '중지', + com_ui_upload_files: '파일 업로드', + com_ui_new_footer: '모든 AI 대화를 한 곳에 모아놓았습니다.', + com_ui_none_selected: '선택된 항목 없음', + com_ui_upload_error: '파일 업로드 중 오류가 발생했습니다', + com_ui_save_submit: '저장 및 제출', + com_user_message: '당신', + com_ui_fork: '포크', + com_ui_fork_info_1: '이 설정을 사용하면 원하는 동작으로 메시지를 분기할 수 있습니다.', + com_ui_fork_info_2: + '"포킹(Forking)"은 현재 대화에서 특정 메시지를 시작/종료 지점으로 하여 새로운 대화를 생성하고, 선택한 옵션에 따라 복사본을 만드는 것을 의미합니다.', + com_ui_fork_info_3: + '"대상 메시지"는 이 팝업이 열린 메시지 또는 "{0}"에 체크하면 대화의 최신 메시지를 의미합니다.', + com_ui_fork_info_visible: + '이 옵션은 표시된 메시지만 분기하여 복사합니다. 즉, 대상 메시지로 가는 직접 경로만 복사하고 다른 분기는 복사하지 않습니다.', + com_ui_fork_info_branches: + '이 옵션은 표시된 메시지와 관련 브랜치를 분기시킵니다. 즉, 대상 메시지에 이르는 직접 경로와 그 경로에 있는 브랜치를 포함합니다.', + com_ui_fork_info_target: + '이 옵션은 대상 메시지와 그 주변 메시지를 포함하여 대상 메시지에 이르는 모든 메시지 분기를 포크합니다. 다시 말해, 표시 여부나 동일한 경로 상에 있는지 여부와 상관없이 모든 메시지 분기가 포함됩니다.', + com_ui_fork_info_start: + '선택 시 이 메시지부터 대화의 최신 메시지까지 위에서 선택한 동작에 따라 포크가 시작됩니다.', + com_ui_fork_info_remember: + '이 옵션을 선택하면 향후 대화를 더 빠르게 분기할 수 있도록 선택한 옵션을 기억합니다.', + com_ui_fork_success: '대화 복제 성공', + com_ui_fork_processing: '대화 분기 중...', + com_ui_fork_error: '대화 분기 중 오류가 발생했습니다', + com_ui_fork_change_default: '기본 포크 옵션', + com_ui_fork_default: '기본 포크 옵션 사용', + com_ui_fork_remember: '기억하기', + com_ui_fork_split_target_setting: '기본적으로 대상 메시지에서 포크 시작', + com_ui_fork_split_target: '여기서 포크 시작', + com_ui_fork_remember_checked: + '선택한 내용은 사용 후에도 기억됩니다. 설정에서 언제든 변경할 수 있습니다.', + com_ui_fork_all_target: '여기부터 전체 포함', + com_ui_fork_branches: '관련 브랜치 포함', + com_ui_fork_visible: '공개 메시지만 표시', + com_ui_fork_from_message: '포크 옵션 선택', + com_ui_mention: '엔드포인트, 어시스턴트 또는 프리셋을 언급하여 빠르게 전환하세요', + com_ui_nothing_found: '찾을 수 없습니다', + com_ui_go_to_conversation: '대화로 이동', + com_ui_import_conversation_file_type_error: '가져올 수 없는 파일 형식입니다', + com_ui_avatar: '프로필 사진', + com_ui_unknown: '알 수 없음', + com_ui_result: '결과', + com_ui_image_gen: '이미지 생성', + com_ui_assistant: '어시스턴트', + com_ui_assistants: '어시스턴트', + com_ui_attachment: '첨부 파일', + com_ui_assistants_output: '어시스턴트 출력', + com_ui_create: '만들기', + com_ui_delete_assistant_confirm: '이 Assistant를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.', + com_ui_preview: '미리보기', + com_ui_upload: '업로드', + com_ui_connect: '연결', + com_ui_upload_delay: + '"{0}" 파일 업로드에 예상보다 시간이 더 걸리고 있습니다. 파일 인덱싱이 완료될 때까지 기다려 주세요.', + com_ui_privacy_policy: '개인정보 보호정책', + com_ui_terms_of_service: '이용 약관', + com_ui_min_tags: '최소 {0}개는 필수로 입력해야 합니다. 더 이상 값을 제거할 수 없습니다.', + com_ui_max_tags: '최대 {0}개까지만 허용됩니다. 최신 값을 사용 중입니다.', + com_auth_error_login_rl: + '짧은 시간 동안 너무 많은 로그인 시도가 있었습니다. 잠시 후 다시 시도해 주세요.', + com_auth_error_login_ban: '서비스 이용 규정을 위반하여 계정이 일시적으로 제한되었습니다.', + com_auth_error_login_server: '내부 서버 오류가 발생했습니다. 잠시 기다렸다가 다시 시도해 주세요.', + com_auth_back_to_login: '로그인 화면으로 돌아가기', + com_endpoint_message: '메시지', + com_endpoint_messages: '메시지', + com_endpoint_message_not_appendable: '메시지를 수정하거나 다시 생성하세요.', + com_endpoint_context_tokens: '최대 컨텍스트 토큰 수', + com_endpoint_context_info: + '컨텍스트로 사용할 수 있는 최대 토큰 수입니다. 요청마다 보내는 토큰 수를 제어하는 데 사용할 수 있습니다. 지정하지 않으면 알려진 모델의 컨텍스트 크기를 기반으로 시스템 기본값을 사용합니다. 더 높은 값을 설정하면 오류가 발생하거나 토큰 비용이 더 높아질 수 있습니다.', + com_endpoint_instructions_assistants_placeholder: + '어시스턴트의 지침을 재정의합니다. 이를 통해 실행마다 동작을 수정할 수 있습니다.', + com_endpoint_prompt_prefix_assistants_placeholder: + '추가 지시사항 또는 컨텍스트를 Assistant의 기본 지시사항에 추가합니다. 비어 있으면 무시됩니다.', + com_endpoint_prompt_prefix_assistants: '추가 지시사항', + com_endpoint_instructions_assistants: '에이전트 지침 재정의', + com_endpoint_stop: '중지 시퀀스', + com_endpoint_stop_placeholder: 'Enter 키를 눌러 값을 구분하세요', + com_endpoint_openai_max_tokens: + '선택적 `max_tokens` 필드로, 채팅 완성에서 생성할 수 있는 최대 토큰 수를 나타냅니다. 입력 토큰과 생성된 토큰의 총 길이는 모델의 컨텍스트 길이로 제한됩니다. 이 숫자가 최대 컨텍스트 토큰 수를 초과하면 오류가 발생할 수 있습니다.', + com_endpoint_openai_resend: + '이전에 첨부한 모든 이미지를 다시 전송합니다. 참고: 이렇게 하면 토큰 비용이 크게 증가할 수 있으며, 많은 이미지를 첨부하면 오류가 발생할 수 있습니다.', + com_endpoint_openai_resend_files: + '이전에 첨부한 모든 파일을 다시 보내세요. 참고: 이렇게 하면 토큰 비용이 증가하고 많은 첨부 파일로 인해 오류가 발생할 수 있습니다.', + com_endpoint_openai_detail: + '비전 요청의 해상도입니다. "낮음"은 저렴하고 빠르며, "높음"은 더 상세하지만 비용이 많이 듭니다. "자동"은 이미지 해상도에 따라 두 가지 중 하나를 자동으로 선택합니다.', + com_endpoint_openai_stop: 'API가 추가 토큰 생성을 중지할 최대 4개의 시퀀스입니다.', + com_endpoint_plug_resend_files: '파일 재전송', + com_endpoint_plug_resend_images: '이미지 재전송', + com_endpoint_plug_image_detail: '이미지 상세 정보', + com_endpoint_preset_delete_confirm: '이 프리셋을 삭제하시겠습니까?', + com_endpoint_preset_clear_all_confirm: '모든 프리셋을 삭제하시겠습니까?', + com_endpoint_preset_import: '프리셋 가져왔습니다!', + com_endpoint_preset_import_error: + '프리셋을 가져오는 중에 오류가 발생했습니다. 다시 시도해주세요.', + com_endpoint_preset_save_error: '프리셋을 저장하는 중에 오류가 발생했습니다. 다시 시도해 주세요.', + com_endpoint_preset_delete_error: + '프리셋을 삭제하는 중에 오류가 발생했습니다. 다시 시도해 주세요.', + com_endpoint_preset_default_removed: '더 이상 기본 프리셋이 아닙니다', + com_endpoint_preset_default_item: '기본값:', + com_endpoint_preset_default_none: '기본 프리셋이 설정되지 않았습니다.', + com_endpoint_preset_title: '프리셋', + com_endpoint_preset_saved: '저장되었습니다!', + com_endpoint_preset_default: '이제 기본 프리셋입니다.', + com_endpoint_preset_selected: '프리셋 활성화됨', + com_endpoint_preset_selected_title: '활성화됨', + com_endpoint_assistant: '어시스턴트', + com_endpoint_use_active_assistant: '활성 에이전트 사용', + com_endpoint_assistant_model: '에이전트 모델', + com_endpoint_assistant_placeholder: '오른쪽 사이드 패널에서 에이전트를 선택하세요', + com_endpoint_config_placeholder: '헤더 메뉴에서 키를 설정하여 채팅하세요.', + com_endpoint_config_click_here: '여기를 클릭하세요', + com_endpoint_config_google_service_key: 'Google 서비스 계정 키', + com_endpoint_config_google_cloud_platform: 'Google Cloud Platform 엔드포인트 설정', + com_endpoint_config_google_api_key: 'Google API 키', + com_endpoint_config_google_gemini_api: 'Gemini API 설정', + com_endpoint_config_google_api_info: 'Gemini에서 Generative Language API 키를 얻으려면', + com_endpoint_config_key_chatgpt: + 'ChatGPT \'무료 버전\'의 액세스 토큰을 얻으려면 다음 사이트에 로그인하세요', + com_endpoint_config_key_chatgpt_then_visit: '그런 다음 방문하세요', + com_endpoint_config_key_chatgpt_copy_token: '액세스 토큰 복사', + com_endpoint_config_key_google_need_to: 'API 키를 설정해야 합니다', + com_endpoint_config_key_google_vertex_ai: 'Vertex AI 사용', + com_endpoint_config_key_google_vertex_api: 'Google Cloud에서 제공하는 API', + com_endpoint_config_key_google_service_account: '서비스 계정 생성', + com_endpoint_config_key_google_vertex_api_role: + '\'Vertex AI 사용자\' 역할을 부여하려면 반드시 \'생성 및 계속\'을 클릭하세요. 마지막으로 여기에 가져올 JSON 키를 생성하세요.', + com_nav_welcome_assistant: '어시스턴트 선택하기', + com_nav_welcome_message: '오늘 무엇을 도와드릴까요?', + com_nav_auto_scroll: '채팅 열렸을 때 최신 메시지로 자동 스크롤', + com_nav_hide_panel: '오른쪽 사이드 패널 숨기기', + com_nav_modular_chat: '대화 중간에 엔드포인트 전환 허용', + com_nav_latex_parsing: '메시지에서 LaTeX 구문 분석(성능에 영향을 줄 수 있음)', + com_nav_profile_picture: '프로필 사진', + com_nav_change_picture: '프로필 사진 변경', + com_nav_plugin_install: '플러그인 설치', + com_nav_plugin_uninstall: '플러그인 제거', + com_nav_tool_add: '추가', + com_nav_tool_remove: '제거', + com_nav_tool_dialog: '어시스턴트 도구', + com_nav_tool_dialog_description: 'Assistant를 저장해야 도구 선택이 유지됩니다.', + com_show_agent_settings: '에이전트 설정 표시', + com_show_completion_settings: '완료 설정 표시', + com_hide_examples: '예시 숨기기', + com_show_examples: '예시 보기', + com_nav_tool_search: '도구 검색', + com_nav_my_files: '내 파일', + com_nav_enter_to_send: '엔터키를 눌러 메시지 보내기', + com_nav_user_name_display: '메시지에서 사용자 이름 표시', + com_nav_show_code: '코드 인터프리터 사용 시 항상 코드 표시', + com_nav_setting_beta: '베타 기능', + com_nav_setting_account: '계정', + com_nav_language: '언어', + com_nav_lang_auto: '자동 감지', + com_nav_lang_english: '영어', + com_nav_lang_chinese: '중국어', + com_nav_lang_german: '독일어', + com_nav_lang_spanish: '스페인어', + com_nav_lang_french: '프랑스어', + com_nav_lang_italian: '이탈리아어', + com_nav_lang_polish: '폴란드어', + com_nav_lang_brazilian_portuguese: '브라질 포르투갈어', + com_nav_lang_russian: '러시아어', + com_nav_lang_japanese: '일본어', + com_nav_lang_swedish: '스웨덴어', + com_nav_lang_korean: '한국어', + com_nav_lang_vietnamese: '베트남어', + com_nav_lang_traditionalchinese: '번체 중국어', + com_nav_lang_arabic: '아랍어', + com_nav_lang_turkish: '터키어', + com_nav_lang_dutch: '네덜란드어', + com_nav_lang_indonesia: '인도네시아', + com_nav_lang_hebrew: '히브리어', }; export const comparisons = { @@ -1227,4 +1497,1011 @@ export const comparisons = { english: 'Data controls', translated: '데이터 제어', }, + com_ui_date_today: { + english: 'Today', + translated: '오늘', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: '어제', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: '지난 7일', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: '지난 30일', + }, + com_ui_date_january: { + english: 'January', + translated: '1월', + }, + com_ui_date_february: { + english: 'February', + translated: '2월', + }, + com_ui_date_march: { + english: 'March', + translated: '3월', + }, + com_ui_date_april: { + english: 'April', + translated: '4월', + }, + com_ui_date_may: { + english: 'May', + translated: '5월', + }, + com_ui_date_june: { + english: 'June', + translated: '6월', + }, + com_ui_date_july: { + english: 'July', + translated: '7월', + }, + com_ui_date_august: { + english: 'August', + translated: '8월', + }, + com_ui_date_september: { + english: 'September', + translated: '9월', + }, + com_ui_date_october: { + english: 'October', + translated: '10월', + }, + com_ui_date_november: { + english: 'November', + translated: '11월', + }, + com_ui_date_december: { + english: 'December', + translated: '12월', + }, + com_assistants_domain_info: { + english: 'Assistant sent this info to {0}', + translated: '어시스턴트가 {0}에게 이 정보를 보냈습니다', + }, + com_assistants_delete_actions_success: { + english: 'Successfully deleted Action from Assistant', + translated: '어시스턴트에서 작업이 성공적으로 삭제되었습니다', + }, + com_error_moderation: { + english: + 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', + translated: + '제출된 내용이 커뮤니티 가이드라인에 부합하지 않는다고 판단되어 모더레이션 시스템에 의해 차단되었습니다. 해당 주제로는 진행할 수 없습니다. 다른 질문이나 탐구하고 싶은 주제가 있다면 메시지를 수정하거나 새 대화를 시작해 주세요.', + }, + com_error_no_user_key: { + english: 'No key found. Please provide a key and try again.', + translated: '키를 찾을 수 없습니다. 키를 제공하고 다시 시도해주세요.', + }, + com_error_no_base_url: { + english: 'No base URL found. Please provide one and try again.', + translated: '기본 URL이 없습니다. URL을 제공한 후 다시 시도해 주세요.', + }, + com_error_invalid_user_key: { + english: 'Invalid key provided. Please provide a key and try again.', + translated: '제공된 키가 유효하지 않습니다. 키를 제공하고 다시 시도해주세요.', + }, + com_error_expired_user_key: { + english: 'Provided key for {0} expired at {1}. Please provide a key and try again.', + translated: '{0}에 대한 키가 {1}에 만료되었습니다. 새 키를 제공하고 다시 시도해주세요.', + }, + com_files_no_results: { + english: 'No results.', + translated: '결과가 없습니다.', + }, + com_files_filter: { + english: 'Filter files...', + translated: '파일 필터링...', + }, + com_files_number_selected: { + english: '{0} of {1} file(s) selected', + translated: '{0}개의 파일({1}개 중)이 선택되었습니다', + }, + com_sidepanel_select_assistant: { + english: 'Select an Assistant', + translated: '어시스턴트 선택', + }, + com_sidepanel_parameters: { + english: 'Parameters', + translated: '매개변수', + }, + com_sidepanel_assistant_builder: { + english: 'Assistant Builder', + translated: '어시스턴트 제작기', + }, + com_sidepanel_hide_panel: { + english: 'Hide Panel', + translated: '패널 숨기기', + }, + com_sidepanel_attach_files: { + english: 'Attach Files', + translated: '파일 첨부', + }, + com_sidepanel_manage_files: { + english: 'Manage Files', + translated: '파일 관리', + }, + com_assistants_capabilities: { + english: 'Capabilities', + translated: '기능', + }, + com_assistants_knowledge: { + english: 'Knowledge', + translated: '지식', + }, + com_assistants_knowledge_info: { + english: + 'If you upload files under Knowledge, conversations with your Assistant may include file contents.', + translated: + 'Knowledge에 파일을 업로드하면 어시스턴트와의 대화에서 파일 내용이 포함될 수 있습니다.', + }, + com_assistants_knowledge_disabled: { + english: + 'Assistant must be created, and Code Interpreter or Retrieval must be enabled and saved before uploading files as Knowledge.', + translated: + '지식으로 파일을 업로드하기 전에 Assistant를 생성하고 Code Interpreter 또는 Retrieval을 활성화한 후 저장해야 합니다.', + }, + com_assistants_image_vision: { + english: 'Image Vision', + translated: '이미지 인식', + }, + com_assistants_code_interpreter: { + english: 'Code Interpreter', + translated: '코드 인터프리터', + }, + com_assistants_code_interpreter_files: { + english: 'The following files are only available for Code Interpreter:', + translated: '코드 인터프리터에서만 다음 파일을 사용할 수 있습니다:', + }, + com_assistants_retrieval: { + english: 'Retrieval', + translated: '검색', + }, + com_assistants_search_name: { + english: 'Search assistants by name', + translated: '이름으로 도우미 검색', + }, + com_assistants_tools: { + english: 'Tools', + translated: '도구', + }, + com_assistants_actions: { + english: 'Actions', + translated: '작업', + }, + com_assistants_add_tools: { + english: 'Add Tools', + translated: '도구 추가', + }, + com_assistants_add_actions: { + english: 'Add Actions', + translated: '작업 추가', + }, + com_assistants_available_actions: { + english: 'Available Actions', + translated: '사용 가능한 작업', + }, + com_assistants_running_action: { + english: 'Running action', + translated: '작업 진행 중', + }, + com_assistants_completed_action: { + english: 'Talked to {0}', + translated: '{0}과 대화했습니다', + }, + com_assistants_completed_function: { + english: 'Ran {0}', + translated: '{0}을(를) 실행했습니다', + }, + com_assistants_function_use: { + english: 'Assistant used {0}', + translated: '어시스턴트는 {0}을(를) 사용했습니다.', + }, + com_assistants_update_actions_success: { + english: 'Successfully created or updated Action', + translated: '액션이 성공적으로 생성 또는 업데이트되었습니다', + }, + com_assistants_update_actions_error: { + english: 'There was an error creating or updating the action.', + translated: '작업을 생성하거나 업데이트하는 중에 오류가 발생했습니다.', + }, + com_assistants_delete_actions_error: { + english: 'There was an error deleting the action.', + translated: '작업 삭제 중 오류가 발생했습니다', + }, + com_assistants_actions_info: { + english: 'Let your Assistant retrieve information or take actions via API\'s', + translated: '어시스턴트가 API를 통해 정보를 검색하거나 작업을 수행할 수 있게 해줍니다.', + }, + com_assistants_name_placeholder: { + english: 'Optional: The name of the assistant', + translated: '선택 사항: 어시스턴트의 이름', + }, + com_assistants_instructions_placeholder: { + english: 'The system instructions that the assistant uses', + translated: '보조 지침은 보조가 사용하는 시스템 지침입니다.', + }, + com_assistants_description_placeholder: { + english: 'Optional: Describe your Assistant here', + translated: '옵션: 여기에 어시스턴트를 설명하세요', + }, + com_assistants_actions_disabled: { + english: 'You need to create an assistant before adding actions.', + translated: '어시스턴트를 만들어야 작업을 추가할 수 있습니다.', + }, + com_assistants_update_success: { + english: 'Successfully updated', + translated: '업데이트 성공', + }, + com_assistants_update_error: { + english: 'There was an error updating your assistant.', + translated: '어시스턴트 업데이트 중 오류가 발생했습니다.', + }, + com_assistants_create_success: { + english: 'Successfully created', + translated: '계정이 성공적으로 생성되었습니다', + }, + com_assistants_create_error: { + english: 'There was an error creating your assistant.', + translated: '어시스턴트 생성 중 오류가 발생했습니다.', + }, + com_ui_field_required: { + english: 'This field is required', + translated: '이 필드는 필수입니다', + }, + com_ui_download_error: { + english: 'Error downloading file. The file may have been deleted.', + translated: '파일 다운로드 중 오류가 발생했습니다. 파일이 삭제되었을 수 있습니다.', + }, + com_ui_attach_error_type: { + english: 'Unsupported file type for endpoint:', + translated: '엔드포인트에서 지원하지 않는 파일 형식입니다.', + }, + com_ui_attach_error_size: { + english: 'File size limit exceeded for endpoint:', + translated: '엔드포인트에 대한 파일 크기 제한을 초과했습니다.', + }, + com_ui_attach_error: { + english: 'Cannot attach file. Create or select a conversation, or try refreshing the page.', + translated: + '파일을 첨부할 수 없습니다. 대화를 생성하거나 선택하시거나 페이지를 새로고침해 보세요.', + }, + com_ui_experimental: { + english: 'Experimental Features', + translated: '실험적 기능', + }, + com_ui_on: { + english: 'On', + translated: '켜기', + }, + com_ui_off: { + english: 'Off', + translated: '꺼짐', + }, + com_ui_yes: { + english: 'Yes', + translated: '네', + }, + com_ui_no: { + english: 'No', + translated: '아니요', + }, + com_ui_ascending: { + english: 'Asc', + translated: '오름차순', + }, + com_ui_descending: { + english: 'Desc', + translated: '내림차순', + }, + com_ui_show_all: { + english: 'Show All', + translated: '전체 보기', + }, + com_ui_name: { + english: 'Name', + translated: '이름', + }, + com_ui_date: { + english: 'Date', + translated: '날짜', + }, + com_ui_storage: { + english: 'Storage', + translated: '저장소', + }, + com_ui_context: { + english: 'Context', + translated: '맥락', + }, + com_ui_size: { + english: 'Size', + translated: '크기', + }, + com_ui_host: { + english: 'Host', + translated: '호스트', + }, + com_ui_update: { + english: 'Update', + translated: '업데이트', + }, + com_ui_authentication: { + english: 'Authentication', + translated: '인증', + }, + com_ui_instructions: { + english: 'Instructions', + translated: '설명', + }, + com_ui_description: { + english: 'Description', + translated: '설명', + }, + com_ui_error: { + english: 'Error', + translated: '오류', + }, + com_ui_select: { + english: 'Select', + translated: '선택', + }, + com_ui_select_search_model: { + english: 'Search model by name', + translated: '이름으로 모델 검색', + }, + com_ui_select_search_plugin: { + english: 'Search plugin by name', + translated: '이름으로 플러그인 검색', + }, + com_ui_stop: { + english: 'Stop', + translated: '중지', + }, + com_ui_upload_files: { + english: 'Upload files', + translated: '파일 업로드', + }, + com_ui_new_footer: { + english: 'All AI conversations in one place.', + translated: '모든 AI 대화를 한 곳에 모아놓았습니다.', + }, + com_ui_none_selected: { + english: 'None selected', + translated: '선택된 항목 없음', + }, + com_ui_upload_error: { + english: 'There was an error uploading your file', + translated: '파일 업로드 중 오류가 발생했습니다', + }, + com_ui_save_submit: { + english: 'Save & Submit', + translated: '저장 및 제출', + }, + com_user_message: { + english: 'You', + translated: '당신', + }, + com_ui_fork: { + english: 'Fork', + translated: '포크', + }, + com_ui_fork_info_1: { + english: 'Use this setting to fork messages with the desired behavior.', + translated: '이 설정을 사용하면 원하는 동작으로 메시지를 분기할 수 있습니다.', + }, + com_ui_fork_info_2: { + english: + '"Forking" refers to creating a new conversation that start/end from specific messages in the current conversation, creating a copy according to the options selected.', + translated: + '"포킹(Forking)"은 현재 대화에서 특정 메시지를 시작/종료 지점으로 하여 새로운 대화를 생성하고, 선택한 옵션에 따라 복사본을 만드는 것을 의미합니다.', + }, + com_ui_fork_info_3: { + english: + 'The "target message" refers to either the message this popup was opened from, or, if you check "{0}", the latest message in the conversation.', + translated: + '"대상 메시지"는 이 팝업이 열린 메시지 또는 "{0}"에 체크하면 대화의 최신 메시지를 의미합니다.', + }, + com_ui_fork_info_visible: { + english: + 'This option forks only the visible messages; in other words, the direct path to the target message, without any branches.', + translated: + '이 옵션은 표시된 메시지만 분기하여 복사합니다. 즉, 대상 메시지로 가는 직접 경로만 복사하고 다른 분기는 복사하지 않습니다.', + }, + com_ui_fork_info_branches: { + english: + 'This option forks the visible messages, along with related branches; in other words, the direct path to the target message, including branches along the path.', + translated: + '이 옵션은 표시된 메시지와 관련 브랜치를 분기시킵니다. 즉, 대상 메시지에 이르는 직접 경로와 그 경로에 있는 브랜치를 포함합니다.', + }, + com_ui_fork_info_target: { + english: + 'This option forks all messages leading up to the target message, including its neighbors; in other words, all message branches, whether or not they are visible or along the same path, are included.', + translated: + '이 옵션은 대상 메시지와 그 주변 메시지를 포함하여 대상 메시지에 이르는 모든 메시지 분기를 포크합니다. 다시 말해, 표시 여부나 동일한 경로 상에 있는지 여부와 상관없이 모든 메시지 분기가 포함됩니다.', + }, + com_ui_fork_info_start: { + english: + 'If checked, forking will commence from this message to the latest message in the conversation, according to the behavior selected above.', + translated: + '선택 시 이 메시지부터 대화의 최신 메시지까지 위에서 선택한 동작에 따라 포크가 시작됩니다.', + }, + com_ui_fork_info_remember: { + english: + 'Check this to remember the options you select for future usage, making it quicker to fork conversations as preferred.', + translated: + '이 옵션을 선택하면 향후 대화를 더 빠르게 분기할 수 있도록 선택한 옵션을 기억합니다.', + }, + com_ui_fork_success: { + english: 'Successfully forked conversation', + translated: '대화 복제 성공', + }, + com_ui_fork_processing: { + english: 'Forking conversation...', + translated: '대화 분기 중...', + }, + com_ui_fork_error: { + english: 'There was an error forking the conversation', + translated: '대화 분기 중 오류가 발생했습니다', + }, + com_ui_fork_change_default: { + english: 'Default fork option', + translated: '기본 포크 옵션', + }, + com_ui_fork_default: { + english: 'Use default fork option', + translated: '기본 포크 옵션 사용', + }, + com_ui_fork_remember: { + english: 'Remember', + translated: '기억하기', + }, + com_ui_fork_split_target_setting: { + english: 'Start fork from target message by default', + translated: '기본적으로 대상 메시지에서 포크 시작', + }, + com_ui_fork_split_target: { + english: 'Start fork here', + translated: '여기서 포크 시작', + }, + com_ui_fork_remember_checked: { + english: + 'Your selection will be remembered after usage. Change this at any time in the settings.', + translated: '선택한 내용은 사용 후에도 기억됩니다. 설정에서 언제든 변경할 수 있습니다.', + }, + com_ui_fork_all_target: { + english: 'Include all to/from here', + translated: '여기부터 전체 포함', + }, + com_ui_fork_branches: { + english: 'Include related branches', + translated: '관련 브랜치 포함', + }, + com_ui_fork_visible: { + english: 'Visible messages only', + translated: '공개 메시지만 표시', + }, + com_ui_fork_from_message: { + english: 'Select a fork option', + translated: '포크 옵션 선택', + }, + com_ui_mention: { + english: 'Mention an endpoint, assistant, or preset to quickly switch to it', + translated: '엔드포인트, 어시스턴트 또는 프리셋을 언급하여 빠르게 전환하세요', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: '찾을 수 없습니다', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: '대화로 이동', + }, + com_ui_import_conversation_file_type_error: { + english: 'Unsupported import type', + translated: '가져올 수 없는 파일 형식입니다', + }, + com_ui_avatar: { + english: 'Avatar', + translated: '프로필 사진', + }, + com_ui_unknown: { + english: 'Unknown', + translated: '알 수 없음', + }, + com_ui_result: { + english: 'Result', + translated: '결과', + }, + com_ui_image_gen: { + english: 'Image Gen', + translated: '이미지 생성', + }, + com_ui_assistant: { + english: 'Assistant', + translated: '어시스턴트', + }, + com_ui_assistants: { + english: 'Assistants', + translated: '어시스턴트', + }, + com_ui_attachment: { + english: 'Attachment', + translated: '첨부 파일', + }, + com_ui_assistants_output: { + english: 'Assistants Output', + translated: '어시스턴트 출력', + }, + com_ui_create: { + english: 'Create', + translated: '만들기', + }, + com_ui_delete_assistant_confirm: { + english: 'Are you sure you want to delete this Assistant? This cannot be undone.', + translated: '이 Assistant를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.', + }, + com_ui_preview: { + english: 'Preview', + translated: '미리보기', + }, + com_ui_upload: { + english: 'Upload', + translated: '업로드', + }, + com_ui_connect: { + english: 'Connect', + translated: '연결', + }, + com_ui_upload_delay: { + english: + 'Uploading "{0}" is taking more time than anticipated. Please wait while the file finishes indexing for retrieval.', + translated: + '"{0}" 파일 업로드에 예상보다 시간이 더 걸리고 있습니다. 파일 인덱싱이 완료될 때까지 기다려 주세요.', + }, + com_ui_privacy_policy: { + english: 'Privacy policy', + translated: '개인정보 보호정책', + }, + com_ui_terms_of_service: { + english: 'Terms of service', + translated: '이용 약관', + }, + com_ui_min_tags: { + english: 'Cannot remove more values, a minimum of {0} are required.', + translated: '최소 {0}개는 필수로 입력해야 합니다. 더 이상 값을 제거할 수 없습니다.', + }, + com_ui_max_tags: { + english: 'Maximum number allowed is {0}, using latest values.', + translated: '최대 {0}개까지만 허용됩니다. 최신 값을 사용 중입니다.', + }, + com_auth_error_login_rl: { + english: 'Too many login attempts in a short amount of time. Please try again later.', + translated: '짧은 시간 동안 너무 많은 로그인 시도가 있었습니다. 잠시 후 다시 시도해 주세요.', + }, + com_auth_error_login_ban: { + english: 'Your account has been temporarily banned due to violations of our service.', + translated: '서비스 이용 규정을 위반하여 계정이 일시적으로 제한되었습니다.', + }, + com_auth_error_login_server: { + english: 'There was an internal server error. Please wait a few moments and try again.', + translated: '내부 서버 오류가 발생했습니다. 잠시 기다렸다가 다시 시도해 주세요.', + }, + com_auth_back_to_login: { + english: 'Back to Login', + translated: '로그인 화면으로 돌아가기', + }, + com_endpoint_message: { + english: 'Message', + translated: '메시지', + }, + com_endpoint_messages: { + english: 'Messages', + translated: '메시지', + }, + com_endpoint_message_not_appendable: { + english: 'Edit your message or Regenerate.', + translated: '메시지를 수정하거나 다시 생성하세요.', + }, + com_endpoint_context_tokens: { + english: 'Max Context Tokens', + translated: '최대 컨텍스트 토큰 수', + }, + com_endpoint_context_info: { + english: + 'The maximum number of tokens that can be used for context. Use this for control of how many tokens are sent per request.\n If unspecified, will use system defaults based on known models\' context size. Setting higher values may result in errors and/or higher token cost.', + translated: + '컨텍스트로 사용할 수 있는 최대 토큰 수입니다. 요청마다 보내는 토큰 수를 제어하는 데 사용할 수 있습니다. 지정하지 않으면 알려진 모델의 컨텍스트 크기를 기반으로 시스템 기본값을 사용합니다. 더 높은 값을 설정하면 오류가 발생하거나 토큰 비용이 더 높아질 수 있습니다.', + }, + com_endpoint_instructions_assistants_placeholder: { + english: + 'Overrides the instructions of the assistant. This is useful for modifying the behavior on a per-run basis.', + translated: '어시스턴트의 지침을 재정의합니다. 이를 통해 실행마다 동작을 수정할 수 있습니다.', + }, + com_endpoint_prompt_prefix_assistants_placeholder: { + english: + 'Set additional instructions or context on top of the Assistant\'s main instructions. Ignored if empty.', + translated: + '추가 지시사항 또는 컨텍스트를 Assistant의 기본 지시사항에 추가합니다. 비어 있으면 무시됩니다.', + }, + com_endpoint_prompt_prefix_assistants: { + english: 'Additional Instructions', + translated: '추가 지시사항', + }, + com_endpoint_instructions_assistants: { + english: 'Override Instructions', + translated: '에이전트 지침 재정의', + }, + com_endpoint_stop: { + english: 'Stop Sequences', + translated: '중지 시퀀스', + }, + com_endpoint_stop_placeholder: { + english: 'Separate values by pressing `Enter`', + translated: 'Enter 키를 눌러 값을 구분하세요', + }, + com_endpoint_openai_max_tokens: { + english: + 'Optional `max_tokens` field, representing the maximum number of tokens that can be generated in the chat completion.\n \n The total length of input tokens and generated tokens is limited by the models context length. You may experience errors if this number exceeds the max context tokens.', + translated: + '선택적 `max_tokens` 필드로, 채팅 완성에서 생성할 수 있는 최대 토큰 수를 나타냅니다. 입력 토큰과 생성된 토큰의 총 길이는 모델의 컨텍스트 길이로 제한됩니다. 이 숫자가 최대 컨텍스트 토큰 수를 초과하면 오류가 발생할 수 있습니다.', + }, + com_endpoint_openai_resend: { + english: + 'Resend all previously attached images. Note: this can significantly increase token cost and you may experience errors with many image attachments.', + translated: + '이전에 첨부한 모든 이미지를 다시 전송합니다. 참고: 이렇게 하면 토큰 비용이 크게 증가할 수 있으며, 많은 이미지를 첨부하면 오류가 발생할 수 있습니다.', + }, + com_endpoint_openai_resend_files: { + english: + 'Resend all previously attached files. Note: this will increase token cost and you may experience errors with many attachments.', + translated: + '이전에 첨부한 모든 파일을 다시 보내세요. 참고: 이렇게 하면 토큰 비용이 증가하고 많은 첨부 파일로 인해 오류가 발생할 수 있습니다.', + }, + com_endpoint_openai_detail: { + english: + 'The resolution for Vision requests. "Low" is cheaper and faster, "High" is more detailed and expensive, and "Auto" will automatically choose between the two based on the image resolution.', + translated: + '비전 요청의 해상도입니다. "낮음"은 저렴하고 빠르며, "높음"은 더 상세하지만 비용이 많이 듭니다. "자동"은 이미지 해상도에 따라 두 가지 중 하나를 자동으로 선택합니다.', + }, + com_endpoint_openai_stop: { + english: 'Up to 4 sequences where the API will stop generating further tokens.', + translated: 'API가 추가 토큰 생성을 중지할 최대 4개의 시퀀스입니다.', + }, + com_endpoint_plug_resend_files: { + english: 'Resend Files', + translated: '파일 재전송', + }, + com_endpoint_plug_resend_images: { + english: 'Resend Images', + translated: '이미지 재전송', + }, + com_endpoint_plug_image_detail: { + english: 'Image Detail', + translated: '이미지 상세 정보', + }, + com_endpoint_preset_delete_confirm: { + english: 'Are you sure you want to delete this preset?', + translated: '이 프리셋을 삭제하시겠습니까?', + }, + com_endpoint_preset_clear_all_confirm: { + english: 'Are you sure you want to delete all of your presets?', + translated: '모든 프리셋을 삭제하시겠습니까?', + }, + com_endpoint_preset_import: { + english: 'Preset Imported!', + translated: '프리셋 가져왔습니다!', + }, + com_endpoint_preset_import_error: { + english: 'There was an error importing your preset. Please try again.', + translated: '프리셋을 가져오는 중에 오류가 발생했습니다. 다시 시도해주세요.', + }, + com_endpoint_preset_save_error: { + english: 'There was an error saving your preset. Please try again.', + translated: '프리셋을 저장하는 중에 오류가 발생했습니다. 다시 시도해 주세요.', + }, + com_endpoint_preset_delete_error: { + english: 'There was an error deleting your preset. Please try again.', + translated: '프리셋을 삭제하는 중에 오류가 발생했습니다. 다시 시도해 주세요.', + }, + com_endpoint_preset_default_removed: { + english: 'is no longer the default preset.', + translated: '더 이상 기본 프리셋이 아닙니다', + }, + com_endpoint_preset_default_item: { + english: 'Default:', + translated: '기본값:', + }, + com_endpoint_preset_default_none: { + english: 'No default preset active.', + translated: '기본 프리셋이 설정되지 않았습니다.', + }, + com_endpoint_preset_title: { + english: 'Preset', + translated: '프리셋', + }, + com_endpoint_preset_saved: { + english: 'Saved!', + translated: '저장되었습니다!', + }, + com_endpoint_preset_default: { + english: 'is now the default preset.', + translated: '이제 기본 프리셋입니다.', + }, + com_endpoint_preset_selected: { + english: 'Preset Active!', + translated: '프리셋 활성화됨', + }, + com_endpoint_preset_selected_title: { + english: 'Active!', + translated: '활성화됨', + }, + com_endpoint_assistant: { + english: 'Assistant', + translated: '어시스턴트', + }, + com_endpoint_use_active_assistant: { + english: 'Use Active Assistant', + translated: '활성 에이전트 사용', + }, + com_endpoint_assistant_model: { + english: 'Assistant Model', + translated: '에이전트 모델', + }, + com_endpoint_assistant_placeholder: { + english: 'Please select an Assistant from the right-hand Side Panel', + translated: '오른쪽 사이드 패널에서 에이전트를 선택하세요', + }, + com_endpoint_config_placeholder: { + english: 'Set your Key in the Header menu to chat.', + translated: '헤더 메뉴에서 키를 설정하여 채팅하세요.', + }, + com_endpoint_config_click_here: { + english: 'Click Here', + translated: '여기를 클릭하세요', + }, + com_endpoint_config_google_service_key: { + english: 'Google Service Account Key', + translated: 'Google 서비스 계정 키', + }, + com_endpoint_config_google_cloud_platform: { + english: '(from Google Cloud Platform)', + translated: 'Google Cloud Platform 엔드포인트 설정', + }, + com_endpoint_config_google_api_key: { + english: 'Google API Key', + translated: 'Google API 키', + }, + com_endpoint_config_google_gemini_api: { + english: '(Gemini API)', + translated: 'Gemini API 설정', + }, + com_endpoint_config_google_api_info: { + english: 'To get your Generative Language API key (for Gemini),', + translated: 'Gemini에서 Generative Language API 키를 얻으려면', + }, + com_endpoint_config_key_chatgpt: { + english: 'To get your Access token For ChatGPT \'Free Version\', login to', + translated: 'ChatGPT \'무료 버전\'의 액세스 토큰을 얻으려면 다음 사이트에 로그인하세요', + }, + com_endpoint_config_key_chatgpt_then_visit: { + english: 'then visit', + translated: '그런 다음 방문하세요', + }, + com_endpoint_config_key_chatgpt_copy_token: { + english: 'Copy access token.', + translated: '액세스 토큰 복사', + }, + com_endpoint_config_key_google_need_to: { + english: 'You need to', + translated: 'API 키를 설정해야 합니다', + }, + com_endpoint_config_key_google_vertex_ai: { + english: 'Enable Vertex AI', + translated: 'Vertex AI 사용', + }, + com_endpoint_config_key_google_vertex_api: { + english: 'API on Google Cloud, then', + translated: 'Google Cloud에서 제공하는 API', + }, + com_endpoint_config_key_google_service_account: { + english: 'Create a Service Account', + translated: '서비스 계정 생성', + }, + com_endpoint_config_key_google_vertex_api_role: { + english: + 'Make sure to click \'Create and Continue\' to give at least the \'Vertex AI User\' role. Lastly, create a JSON key to import here.', + translated: + '\'Vertex AI 사용자\' 역할을 부여하려면 반드시 \'생성 및 계속\'을 클릭하세요. 마지막으로 여기에 가져올 JSON 키를 생성하세요.', + }, + com_nav_welcome_assistant: { + english: 'Please Select an Assistant', + translated: '어시스턴트 선택하기', + }, + com_nav_welcome_message: { + english: 'How can I help you today?', + translated: '오늘 무엇을 도와드릴까요?', + }, + com_nav_auto_scroll: { + english: 'Auto-Scroll to latest message on chat open', + translated: '채팅 열렸을 때 최신 메시지로 자동 스크롤', + }, + com_nav_hide_panel: { + english: 'Hide right-most side panel', + translated: '오른쪽 사이드 패널 숨기기', + }, + com_nav_modular_chat: { + english: 'Enable switching Endpoints mid-conversation', + translated: '대화 중간에 엔드포인트 전환 허용', + }, + com_nav_latex_parsing: { + english: 'Parsing LaTeX in messages (may affect performance)', + translated: '메시지에서 LaTeX 구문 분석(성능에 영향을 줄 수 있음)', + }, + com_nav_profile_picture: { + english: 'Profile Picture', + translated: '프로필 사진', + }, + com_nav_change_picture: { + english: 'Change picture', + translated: '프로필 사진 변경', + }, + com_nav_plugin_install: { + english: 'Install', + translated: '플러그인 설치', + }, + com_nav_plugin_uninstall: { + english: 'Uninstall', + translated: '플러그인 제거', + }, + com_nav_tool_add: { + english: 'Add', + translated: '추가', + }, + com_nav_tool_remove: { + english: 'Remove', + translated: '제거', + }, + com_nav_tool_dialog: { + english: 'Assistant Tools', + translated: '어시스턴트 도구', + }, + com_nav_tool_dialog_description: { + english: 'Assistant must be saved to persist tool selections.', + translated: 'Assistant를 저장해야 도구 선택이 유지됩니다.', + }, + com_show_agent_settings: { + english: 'Show Agent Settings', + translated: '에이전트 설정 표시', + }, + com_show_completion_settings: { + english: 'Show Completion Settings', + translated: '완료 설정 표시', + }, + com_hide_examples: { + english: 'Hide Examples', + translated: '예시 숨기기', + }, + com_show_examples: { + english: 'Show Examples', + translated: '예시 보기', + }, + com_nav_tool_search: { + english: 'Search tools', + translated: '도구 검색', + }, + com_nav_my_files: { + english: 'My Files', + translated: '내 파일', + }, + com_nav_enter_to_send: { + english: 'Press Enter to send messages', + translated: '엔터키를 눌러 메시지 보내기', + }, + com_nav_user_name_display: { + english: 'Display username in messages', + translated: '메시지에서 사용자 이름 표시', + }, + com_nav_show_code: { + english: 'Always show code when using code interpreter', + translated: '코드 인터프리터 사용 시 항상 코드 표시', + }, + com_nav_setting_beta: { + english: 'Beta features', + translated: '베타 기능', + }, + com_nav_setting_account: { + english: 'Account', + translated: '계정', + }, + com_nav_language: { + english: 'Language', + translated: '언어', + }, + com_nav_lang_auto: { + english: 'Auto detect', + translated: '자동 감지', + }, + com_nav_lang_english: { + english: 'English', + translated: '영어', + }, + com_nav_lang_chinese: { + english: '中文', + translated: '중국어', + }, + com_nav_lang_german: { + english: 'Deutsch', + translated: '독일어', + }, + com_nav_lang_spanish: { + english: 'Español', + translated: '스페인어', + }, + com_nav_lang_french: { + english: 'Français ', + translated: '프랑스어', + }, + com_nav_lang_italian: { + english: 'Italiano', + translated: '이탈리아어', + }, + com_nav_lang_polish: { + english: 'Polski', + translated: '폴란드어', + }, + com_nav_lang_brazilian_portuguese: { + english: 'Português Brasileiro', + translated: '브라질 포르투갈어', + }, + com_nav_lang_russian: { + english: 'Русский', + translated: '러시아어', + }, + com_nav_lang_japanese: { + english: '日本語', + translated: '일본어', + }, + com_nav_lang_swedish: { + english: 'Svenska', + translated: '스웨덴어', + }, + com_nav_lang_korean: { + english: '한국어', + translated: '한국어', + }, + com_nav_lang_vietnamese: { + english: 'Tiếng Việt', + translated: '베트남어', + }, + com_nav_lang_traditionalchinese: { + english: '繁體中文', + translated: '번체 중국어', + }, + com_nav_lang_arabic: { + english: 'العربية', + translated: '아랍어', + }, + com_nav_lang_turkish: { + english: 'Türkçe', + translated: '터키어', + }, + com_nav_lang_dutch: { + english: 'Nederlands', + translated: '네덜란드어', + }, + com_nav_lang_indonesia: { + english: 'Indonesia', + translated: '인도네시아', + }, + com_nav_lang_hebrew: { + english: 'עברית', + translated: '히브리어', + }, }; diff --git a/client/src/localization/languages/Ru.ts b/client/src/localization/languages/Ru.ts index 961714eb332..26d44264e4f 100644 --- a/client/src/localization/languages/Ru.ts +++ b/client/src/localization/languages/Ru.ts @@ -364,6 +364,24 @@ export default { com_ui_upload_error: 'Произошла ошибка при загрузке вашего файла', com_user_message: 'Вы', /* The following are AI Translated */ + com_ui_date_today: 'Сегодня', + com_ui_date_yesterday: 'Вчера', + com_ui_date_previous_7_days: 'Предыдущие 7 дней', + com_ui_date_previous_30_days: 'За последние 30 дней', + com_ui_date_january: 'Январь', + com_ui_date_february: 'Февраль', + com_ui_date_march: 'Март', + com_ui_date_april: 'Апрель', + com_ui_date_may: 'Май', + com_ui_date_june: 'Июнь', + com_ui_date_july: 'Июль', + com_ui_date_august: 'Август', + com_ui_date_september: 'Сентябрь', + com_ui_date_october: 'Октябрь', + com_ui_date_november: 'Ноябрь', + com_ui_date_december: 'Декабрь', + com_ui_nothing_found: 'Ничего не найдено', + com_ui_go_to_conversation: 'Перейти к беседе', com_error_moderation: 'К сожалению, отправленный вами контент был помечен нашей системой модерации как не соответствующий правилам сообщества. Мы не можем продолжить обсуждение этой конкретной темы. Если у вас есть другие вопросы или темы, которые вы хотели бы обсудить, пожалуйста, отредактируйте сообщение или начните новый диалог.', com_error_no_user_key: 'Ключ не найден. Пожалуйста, укажите ключ и повторите попытку.', @@ -1846,6 +1864,78 @@ export const comparisons = { english: 'You', translated: 'Вы', }, + com_ui_date_today: { + english: 'Today', + translated: 'Сегодня', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: 'Вчера', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: 'Предыдущие 7 дней', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: 'За последние 30 дней', + }, + com_ui_date_january: { + english: 'January', + translated: 'Январь', + }, + com_ui_date_february: { + english: 'February', + translated: 'Февраль', + }, + com_ui_date_march: { + english: 'March', + translated: 'Март', + }, + com_ui_date_april: { + english: 'April', + translated: 'Апрель', + }, + com_ui_date_may: { + english: 'May', + translated: 'Май', + }, + com_ui_date_june: { + english: 'June', + translated: 'Июнь', + }, + com_ui_date_july: { + english: 'July', + translated: 'Июль', + }, + com_ui_date_august: { + english: 'August', + translated: 'Август', + }, + com_ui_date_september: { + english: 'September', + translated: 'Сентябрь', + }, + com_ui_date_october: { + english: 'October', + translated: 'Октябрь', + }, + com_ui_date_november: { + english: 'November', + translated: 'Ноябрь', + }, + com_ui_date_december: { + english: 'December', + translated: 'Декабрь', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: 'Ничего не найдено', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: 'Перейти к беседе', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/Zh.ts b/client/src/localization/languages/Zh.ts index ff9fb18f49c..e88fc148857 100644 --- a/client/src/localization/languages/Zh.ts +++ b/client/src/localization/languages/Zh.ts @@ -417,6 +417,21 @@ export default { com_nav_setting_data: '数据管理', com_nav_setting_account: '账户', /* The following are AI Translated */ + com_ui_date_today: '今天', + com_ui_date_yesterday: '昨天', + com_ui_date_previous_7_days: '过去7天', + com_ui_date_previous_30_days: '过去30天', + com_ui_date_january: '一月', + com_ui_date_february: '二月', + com_ui_date_march: '三月', + com_ui_date_april: '四月', + com_ui_date_may: '五月', + com_ui_date_june: '六月', + com_ui_date_july: '七月', + com_ui_date_august: '八月', + com_ui_date_september: '九月', + com_ui_nothing_found: '未找到任何内容', + com_ui_go_to_conversation: '转到对话', com_error_moderation: '很抱歉,您提交的内容被我们的审核系统标记为不符合社区指引。我们无法就此特定主题继续交流。如果您有任何其他问题或想探讨的话题,请编辑您的消息或开启新的对话。', com_error_no_user_key: '没有找到密钥。请提供密钥后重试。', @@ -2096,6 +2111,66 @@ export const comparisons = { english: 'Account', translated: '账户', }, + com_ui_date_today: { + english: 'Today', + translated: '今天', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: '昨天', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: '过去7天', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: '过去30天', + }, + com_ui_date_january: { + english: 'January', + translated: '一月', + }, + com_ui_date_february: { + english: 'February', + translated: '二月', + }, + com_ui_date_march: { + english: 'March', + translated: '三月', + }, + com_ui_date_april: { + english: 'April', + translated: '四月', + }, + com_ui_date_may: { + english: 'May', + translated: '五月', + }, + com_ui_date_june: { + english: 'June', + translated: '六月', + }, + com_ui_date_july: { + english: 'July', + translated: '七月', + }, + com_ui_date_august: { + english: 'August', + translated: '八月', + }, + com_ui_date_september: { + english: 'September', + translated: '九月', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: '未找到任何内容', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: '转到对话', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/localization/languages/ZhTraditional.ts b/client/src/localization/languages/ZhTraditional.ts index 2df4e339e82..2331cbb609f 100644 --- a/client/src/localization/languages/ZhTraditional.ts +++ b/client/src/localization/languages/ZhTraditional.ts @@ -266,6 +266,24 @@ export default { com_nav_setting_general: '一般', com_nav_setting_data: '資料控制', /* The following are AI translated */ + com_ui_date_today: '今天', + com_ui_date_yesterday: '昨天', + com_ui_date_previous_7_days: '前 7 天', + com_ui_date_previous_30_days: '過去 30 天', + com_ui_date_january: '一月', + com_ui_date_february: '二月', + com_ui_date_march: '三月', + com_ui_date_april: '四月', + com_ui_date_may: '五月', + com_ui_date_june: '六月', + com_ui_date_july: '七月', + com_ui_date_august: '八月', + com_ui_date_september: '九月', + com_ui_date_october: '十月', + com_ui_date_november: '十一月', + com_ui_date_december: '十二月', + com_ui_nothing_found: '找不到任何內容', + com_ui_go_to_conversation: '前往對話', com_error_moderation: '似乎您所提交的內容被我們的內容審查系統標記為不符合社群準則。我們無法就此特定主題繼續進行。如果您有任何其他問題或想要探討的主題,請編輯您的訊息或開啟新的對話。', com_error_no_user_key: '找不到金鑰,請提供金鑰後再試一次。', @@ -1509,6 +1527,78 @@ export const comparisons = { english: 'Data controls', translated: '資料控制', }, + com_ui_date_today: { + english: 'Today', + translated: '今天', + }, + com_ui_date_yesterday: { + english: 'Yesterday', + translated: '昨天', + }, + com_ui_date_previous_7_days: { + english: 'Previous 7 days', + translated: '前 7 天', + }, + com_ui_date_previous_30_days: { + english: 'Previous 30 days', + translated: '過去 30 天', + }, + com_ui_date_january: { + english: 'January', + translated: '一月', + }, + com_ui_date_february: { + english: 'February', + translated: '二月', + }, + com_ui_date_march: { + english: 'March', + translated: '三月', + }, + com_ui_date_april: { + english: 'April', + translated: '四月', + }, + com_ui_date_may: { + english: 'May', + translated: '五月', + }, + com_ui_date_june: { + english: 'June', + translated: '六月', + }, + com_ui_date_july: { + english: 'July', + translated: '七月', + }, + com_ui_date_august: { + english: 'August', + translated: '八月', + }, + com_ui_date_september: { + english: 'September', + translated: '九月', + }, + com_ui_date_october: { + english: 'October', + translated: '十月', + }, + com_ui_date_november: { + english: 'November', + translated: '十一月', + }, + com_ui_date_december: { + english: 'December', + translated: '十二月', + }, + com_ui_nothing_found: { + english: 'Nothing found', + translated: '找不到任何內容', + }, + com_ui_go_to_conversation: { + english: 'Go to conversation', + translated: '前往對話', + }, com_error_moderation: { english: 'It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We\'re unable to proceed with this specific topic. If you have any other questions or topics you\'d like to explore, please edit your message, or create a new conversation.', diff --git a/client/src/routes/Root.tsx b/client/src/routes/Root.tsx index 529de11726f..4f810885ac8 100644 --- a/client/src/routes/Root.tsx +++ b/client/src/routes/Root.tsx @@ -1,12 +1,10 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { Outlet } from 'react-router-dom'; -import { useSetRecoilState } from 'recoil'; -import { useGetSearchEnabledQuery } from 'librechat-data-provider/react-query'; + import type { ContextType } from '~/common'; -import { useAuthContext, useAssistantsMap, useFileMap } from '~/hooks'; -import { AssistantsMapContext, FileMapContext } from '~/Providers'; +import { useAuthContext, useAssistantsMap, useFileMap, useSearch } from '~/hooks'; +import { AssistantsMapContext, FileMapContext, SearchContext } from '~/Providers'; import { Nav, MobileNav } from '~/components/Nav'; -import store from '~/store'; export default function Root() { const { isAuthenticated } = useAuthContext(); @@ -15,42 +13,29 @@ export default function Root() { return savedNavVisible !== null ? JSON.parse(savedNavVisible) : true; }); - const setIsSearchEnabled = useSetRecoilState(store.isSearchEnabled); - + const search = useSearch({ isAuthenticated }); const fileMap = useFileMap({ isAuthenticated }); const assistantsMap = useAssistantsMap({ isAuthenticated }); - const searchEnabledQuery = useGetSearchEnabledQuery({ enabled: isAuthenticated }); - - useEffect(() => { - if (searchEnabledQuery.data) { - setIsSearchEnabled(searchEnabledQuery.data); - } else if (searchEnabledQuery.isError) { - console.error('Failed to get search enabled', searchEnabledQuery.error); - } - }, [ - searchEnabledQuery.data, - searchEnabledQuery.error, - searchEnabledQuery.isError, - setIsSearchEnabled, - ]); if (!isAuthenticated) { return null; } return ( - - -
-
-