diff --git a/client/src/hooks/Input/useMentions.ts b/client/src/hooks/Input/useMentions.ts index 4d5205a72d2..ce5fde1de92 100644 --- a/client/src/hooks/Input/useMentions.ts +++ b/client/src/hooks/Input/useMentions.ts @@ -7,6 +7,7 @@ import { import { alternateName, EModelEndpoint, + isAgentsEndpoint, getConfigDefaults, isAssistantsEndpoint, } from 'librechat-data-provider'; @@ -121,6 +122,26 @@ export default function useMentions({ if (!includeAssistants) { validEndpoints = endpoints.filter((endpoint) => !isAssistantsEndpoint(endpoint)); } + + const modelOptions = validEndpoints.flatMap((endpoint) => { + if (isAssistantsEndpoint(endpoint) || isAgentsEndpoint(endpoint)) { + return []; + } + + const models = (modelsConfig?.[endpoint] ?? []).map((model) => ({ + value: endpoint, + label: model, + type: 'model' as const, + icon: EndpointIcon({ + conversation: { endpoint, model }, + endpointsConfig, + context: 'menu-item', + size: 20, + }), + })); + return models; + }); + const mentions = [ ...(modelSpecs.length > 0 ? modelSpecs : []).map((modelSpec) => ({ value: modelSpec.name, @@ -169,6 +190,7 @@ export default function useMentions({ }), type: 'preset' as const, })) ?? []), + ...modelOptions, ]; return mentions; @@ -178,6 +200,7 @@ export default function useMentions({ modelSpecs, agentsList, assistantMap, + modelsConfig, endpointsConfig, assistantListMap, includeAssistants, diff --git a/client/src/hooks/Input/useQueryParams.ts b/client/src/hooks/Input/useQueryParams.ts index 343f2141690..ecca0ec8f28 100644 --- a/client/src/hooks/Input/useQueryParams.ts +++ b/client/src/hooks/Input/useQueryParams.ts @@ -1,64 +1,213 @@ -import { useEffect, useRef } from 'react'; +import { useEffect, useCallback, useRef } from 'react'; +import { useRecoilValue } from 'recoil'; import { useSearchParams } from 'react-router-dom'; -import { useChatFormContext } from '~/Providers'; +import { useQueryClient } from '@tanstack/react-query'; +import { + QueryKeys, + EModelEndpoint, + isAgentsEndpoint, + tQueryParamsSchema, + isAssistantsEndpoint, +} from 'librechat-data-provider'; +import type { TPreset, TEndpointsConfig } from 'librechat-data-provider'; +import type { ZodAny } from 'zod'; +import { getConvoSwitchLogic, removeUnavailableTools } from '~/utils'; +import useDefaultConvo from '~/hooks/Conversations/useDefaultConvo'; +import { useChatContext, useChatFormContext } from '~/Providers'; +import store from '~/store'; + +const parseQueryValue = (value: string) => { + if (value === 'true') { + return true; + } + if (value === 'false') { + return false; + } + if (!isNaN(Number(value))) { + return Number(value); + } + return value; +}; + +const processValidSettings = (queryParams: Record) => { + const validSettings = {} as TPreset; + + Object.entries(queryParams).forEach(([key, value]) => { + try { + const schema = tQueryParamsSchema.shape[key] as ZodAny | undefined; + if (schema) { + const parsedValue = parseQueryValue(value); + const validValue = schema.parse(parsedValue); + validSettings[key] = validValue; + } + } catch (error) { + console.warn(`Invalid value for setting ${key}:`, error); + } + }); + + if ( + validSettings.assistant_id != null && + validSettings.assistant_id && + !isAssistantsEndpoint(validSettings.endpoint) + ) { + validSettings.endpoint = EModelEndpoint.assistants; + } + if ( + validSettings.agent_id != null && + validSettings.agent_id && + !isAgentsEndpoint(validSettings.endpoint) + ) { + validSettings.endpoint = EModelEndpoint.agents; + } + + return validSettings; +}; export default function useQueryParams({ textAreaRef, }: { textAreaRef: React.RefObject; }) { - const methods = useChatFormContext(); - const [searchParams] = useSearchParams(); + const maxAttempts = 50; const attemptsRef = useRef(0); const processedRef = useRef(false); - const maxAttempts = 50; // 5 seconds maximum (50 * 100ms) + const methods = useChatFormContext(); + const [searchParams] = useSearchParams(); + const getDefaultConversation = useDefaultConvo(); + const modularChat = useRecoilValue(store.modularChat); + const availableTools = useRecoilValue(store.availableTools); + + const queryClient = useQueryClient(); + const { conversation, newConversation } = useChatContext(); + + const newQueryConvo = useCallback( + (_newPreset?: TPreset) => { + if (!_newPreset) { + return; + } + + const newPreset = removeUnavailableTools(_newPreset, availableTools); + let newEndpoint = newPreset.endpoint ?? ''; + const endpointsConfig = queryClient.getQueryData([QueryKeys.endpoints]); + + if (newEndpoint && endpointsConfig && !endpointsConfig[newEndpoint]) { + const normalizedNewEndpoint = newEndpoint.toLowerCase(); + for (const [key, value] of Object.entries(endpointsConfig)) { + if ( + value && + value.type === EModelEndpoint.custom && + key.toLowerCase() === normalizedNewEndpoint + ) { + newEndpoint = key; + newPreset.endpoint = key; + newPreset.endpointType = EModelEndpoint.custom; + break; + } + } + } + + const { + template, + shouldSwitch, + isNewModular, + newEndpointType, + isCurrentModular, + isExistingConversation, + } = getConvoSwitchLogic({ + newEndpoint, + modularChat, + conversation, + endpointsConfig, + }); + + const isModular = isCurrentModular && isNewModular && shouldSwitch; + if (isExistingConversation && isModular) { + template.endpointType = newEndpointType as EModelEndpoint | undefined; + + const currentConvo = getDefaultConversation({ + /* target endpointType is necessary to avoid endpoint mixing */ + conversation: { ...(conversation ?? {}), endpointType: template.endpointType }, + preset: template, + }); + + /* We don't reset the latest message, only when changing settings mid-converstion */ + newConversation({ + template: currentConvo, + preset: newPreset, + keepLatestMessage: true, + keepAddedConvos: true, + }); + return; + } + + newConversation({ preset: newPreset, keepAddedConvos: true }); + }, + [ + queryClient, + modularChat, + conversation, + availableTools, + newConversation, + getDefaultConversation, + ], + ); useEffect(() => { - const decodedPrompt = searchParams.get('prompt') ?? ''; - if (!decodedPrompt) { - return; - } + const processQueryParams = () => { + const queryParams: Record = {}; + searchParams.forEach((value, key) => { + queryParams[key] = value; + }); + + const decodedPrompt = queryParams.prompt || ''; + delete queryParams.prompt; + const validSettings = processValidSettings(queryParams); + + return { decodedPrompt, validSettings }; + }; const intervalId = setInterval(() => { - // If already processed or max attempts reached, clear interval and stop if (processedRef.current || attemptsRef.current >= maxAttempts) { clearInterval(intervalId); if (attemptsRef.current >= maxAttempts) { - console.warn('Max attempts reached, failed to process prompt'); + console.warn('Max attempts reached, failed to process parameters'); } return; } attemptsRef.current += 1; - if (textAreaRef.current) { - const currentText = methods.getValues('text'); - - // Only update if the textarea is empty - if (!currentText) { - methods.setValue('text', decodedPrompt, { shouldValidate: true }); - textAreaRef.current.focus(); - textAreaRef.current.setSelectionRange(decodedPrompt.length, decodedPrompt.length); + if (!textAreaRef.current) { + return; + } + const { decodedPrompt, validSettings } = processQueryParams(); + const currentText = methods.getValues('text'); - // Remove the 'prompt' parameter from the URL - searchParams.delete('prompt'); - const newUrl = `${window.location.pathname}${ - searchParams.toString() ? `?${searchParams.toString()}` : '' - }`; - window.history.replaceState({}, '', newUrl); + /** Clean up URL parameters after successful processing */ + const success = () => { + const newUrl = window.location.pathname; + window.history.replaceState({}, '', newUrl); + processedRef.current = true; + console.log('Parameters processed successfully'); + clearInterval(intervalId); + }; - processedRef.current = true; - console.log('Prompt processed successfully'); - } + if (!currentText && decodedPrompt) { + methods.setValue('text', decodedPrompt, { shouldValidate: true }); + textAreaRef.current.focus(); + textAreaRef.current.setSelectionRange(decodedPrompt.length, decodedPrompt.length); + } - clearInterval(intervalId); + if (Object.keys(validSettings).length > 0) { + newQueryConvo(validSettings); } - }, 100); // Check every 100ms - // Clean up the interval on unmount + success(); + }, 100); + return () => { clearInterval(intervalId); - console.log('Cleanup: interval cleared'); + console.log('Cleanup: `useQueryParams` interval cleared'); }; - }, [searchParams, methods, textAreaRef]); + }, [searchParams, methods, textAreaRef, newQueryConvo, newConversation]); } diff --git a/client/src/hooks/Input/useSelectMention.ts b/client/src/hooks/Input/useSelectMention.ts index df11ec0440f..b4748a1cbc2 100644 --- a/client/src/hooks/Input/useSelectMention.ts +++ b/client/src/hooks/Input/useSelectMention.ts @@ -144,6 +144,10 @@ export default function useSelectMention({ if (assistant_id) { template.assistant_id = assistant_id; } + const agent_id = kwargs.agent_id ?? ''; + if (agent_id) { + template.agent_id = agent_id; + } if (isExistingConversation && isCurrentModular && isNewModular && shouldSwitch) { template.endpointType = newEndpointType; diff --git a/client/src/hooks/Input/useTextarea.ts b/client/src/hooks/Input/useTextarea.ts index d30dc199d9e..ca7bf79e0c8 100644 --- a/client/src/hooks/Input/useTextarea.ts +++ b/client/src/hooks/Input/useTextarea.ts @@ -128,7 +128,10 @@ export default function useTextarea({ ? getEntityName({ name: entityName, isAgent, localize }) : getSender(conversation as TEndpointOption); - return `${localize('com_endpoint_message')} ${sender ? sender : 'AI'}`; + return `${localize( + 'com_endpoint_message_new', + sender ? sender : localize('com_endpoint_ai'), + )}`; }; const placeholder = getPlaceholderText(); diff --git a/client/src/localization/languages/Ar.ts b/client/src/localization/languages/Ar.ts index 2dccc94d07b..6d61bc2e6ad 100644 --- a/client/src/localization/languages/Ar.ts +++ b/client/src/localization/languages/Ar.ts @@ -871,7 +871,8 @@ export default { com_error_invalid_action_error: 'تم رفض الطلب: نطاق الإجراء المحدد غير مسموح به', com_agents_code_interpreter_title: 'واجهة برمجة مُفسِّر الشفرة', com_agents_by_librechat: 'بواسطة LibreChat', - com_agents_code_interpreter: 'عند التمكين، يسمح للوكيل الخاص بك باستخدام واجهة برمجة التطبيقات لمفسر الشفرة LibreChat لتشغيل الشفرة المُنشأة، بما في ذلك معالجة الملفات، بشكل آمن. يتطلب مفتاح API صالح.', + com_agents_code_interpreter: + 'عند التمكين، يسمح للوكيل الخاص بك باستخدام واجهة برمجة التطبيقات لمفسر الشفرة LibreChat لتشغيل الشفرة المُنشأة، بما في ذلك معالجة الملفات، بشكل آمن. يتطلب مفتاح API صالح.', com_ui_export_convo_modal: 'نافذة تصدير المحادثة', com_ui_endpoints_available: 'نقاط النهاية المتاحة', com_ui_endpoint_menu: 'قائمة نقطة نهاية LLM', @@ -885,7 +886,8 @@ export default { com_ui_upload_code_files: 'تحميل لمفسر الكود', com_ui_zoom: 'تكبير', com_ui_role_select: 'الدور', - com_ui_admin_access_warning: 'قد يؤدي تعطيل وصول المسؤول إلى هذه الميزة إلى مشاكل غير متوقعة في واجهة المستخدم تتطلب تحديث الصفحة. في حالة الحفظ، الطريقة الوحيدة للتراجع هي عبر إعداد الواجهة في ملف librechat.yaml والذي يؤثر على جميع الأدوار.', + com_ui_admin_access_warning: + 'قد يؤدي تعطيل وصول المسؤول إلى هذه الميزة إلى مشاكل غير متوقعة في واجهة المستخدم تتطلب تحديث الصفحة. في حالة الحفظ، الطريقة الوحيدة للتراجع هي عبر إعداد الواجهة في ملف librechat.yaml والذي يؤثر على جميع الأدوار.', com_ui_run_code_error: 'حدث خطأ أثناء تشغيل الكود', com_ui_duplication_success: 'تم نسخ المحادثة بنجاح', com_ui_duplication_processing: 'جارِ نسخ المحادثة...', @@ -905,4 +907,10 @@ export default { com_ui_enter_openapi_schema: 'أدخل مخطط OpenAPI هنا', com_ui_delete_shared_link: 'حذف الرابط المشترك؟', com_nav_welcome_agent: 'الرجاء اختيار مساعد', + com_ui_bookmarks_edit: 'تعديل الإشارة المرجعية', + com_ui_page: 'صفحة', + com_ui_bookmarks_add: 'إضافة إشارات مرجعية', + com_endpoint_ai: 'الذكاء الاصطناعي', + com_endpoint_message_new: 'الرسالة {0} أو اكتب "@" للتبديل إلى الذكاء الاصطناعي', + com_nav_maximize_chat_space: 'تكبير مساحة الدردشة', }; diff --git a/client/src/localization/languages/De.ts b/client/src/localization/languages/De.ts index 29a251a6b54..f310e3c1b42 100644 --- a/client/src/localization/languages/De.ts +++ b/client/src/localization/languages/De.ts @@ -939,4 +939,10 @@ export default { com_nav_welcome_agent: 'Bitte wähle einen Agenten', com_endpoint_agent_placeholder: 'Bitte wähle einen Agenten aus', com_ui_delete_shared_link: 'Geteilten Link löschen?', + com_ui_bookmarks_edit: 'Lesezeichen bearbeiten', + com_endpoint_ai: 'KI', + com_ui_page: 'Seite', + com_ui_bookmarks_add: 'Lesezeichen hinzufügen', + com_endpoint_message_new: 'Nachricht {0} oder "@" eingeben, um KI zu wechseln', + com_nav_maximize_chat_space: 'Chat-Bereich maximieren', }; diff --git a/client/src/localization/languages/Eng.ts b/client/src/localization/languages/Eng.ts index fab402fa333..46397cee405 100644 --- a/client/src/localization/languages/Eng.ts +++ b/client/src/localization/languages/Eng.ts @@ -525,6 +525,8 @@ export default { 'WARNING: Misuse of this feature can get you BANNED from using Bing! Click on \'System Message\' for full instructions and the default message if omitted, which is the \'Sydney\' preset that is considered safe.', com_endpoint_system_message: 'System Message', com_endpoint_message: 'Message', + com_endpoint_ai: 'AI', + com_endpoint_message_new: 'Message {0} or type "@" to switch AI', com_endpoint_message_not_appendable: 'Edit your message or Regenerate.', com_endpoint_default_blank: 'default: blank', com_endpoint_default_false: 'default: false', diff --git a/client/src/localization/languages/Es.ts b/client/src/localization/languages/Es.ts index 6dceed7f9f7..d2701df4054 100644 --- a/client/src/localization/languages/Es.ts +++ b/client/src/localization/languages/Es.ts @@ -1195,4 +1195,10 @@ export default { com_endpoint_agent_placeholder: 'Por favor seleccione un Agente', com_nav_welcome_agent: 'Seleccione un agente', com_ui_delete_shared_link: '¿Eliminar enlace compartido?', + com_ui_bookmarks_add: 'Agregar Marcadores', + com_ui_page: 'Página', + com_ui_bookmarks_edit: 'Editar Marcador', + com_endpoint_message_new: 'Mensaje {0} o escriba "@" para cambiar de IA', + com_nav_maximize_chat_space: 'Maximizar espacio del chat', + com_endpoint_ai: 'IA', }; diff --git a/client/src/localization/languages/Fr.ts b/client/src/localization/languages/Fr.ts index 4935ba092ef..692ff19d6b8 100644 --- a/client/src/localization/languages/Fr.ts +++ b/client/src/localization/languages/Fr.ts @@ -957,4 +957,10 @@ export default { com_endpoint_agent_placeholder: 'Veuillez sélectionner un Agent', com_nav_welcome_agent: 'Veuillez sélectionner un agent', com_ui_delete_shared_link: 'Supprimer le lien partagé ?', + com_ui_bookmarks_add: 'Ajouter des signets', + com_ui_bookmarks_edit: 'Modifier le signet', + com_endpoint_ai: 'IA', + com_nav_maximize_chat_space: 'Maximiser l\'espace de discussion', + com_endpoint_message_new: 'Message {0} ou tapez "@" pour changer d\'IA', + com_ui_page: 'Page', }; diff --git a/client/src/localization/languages/It.ts b/client/src/localization/languages/It.ts index 77488c0efb2..a262c4345fa 100644 --- a/client/src/localization/languages/It.ts +++ b/client/src/localization/languages/It.ts @@ -951,4 +951,10 @@ export default { com_nav_welcome_agent: 'Seleziona un Assistente', com_endpoint_agent_placeholder: 'Seleziona un Agente', com_ui_delete_shared_link: 'Eliminare il link condiviso?', + com_ui_bookmarks_add: 'Aggiungi Segnalibri', + com_ui_bookmarks_edit: 'Modifica Segnalibro', + com_endpoint_message_new: 'Messaggio {0} oppure digita "@" per cambiare IA', + com_endpoint_ai: 'IA', + com_nav_maximize_chat_space: 'Massimizza spazio chat', + com_ui_page: 'Pagina', }; diff --git a/client/src/localization/languages/Jp.ts b/client/src/localization/languages/Jp.ts index 055c3a5df62..911078eaa6d 100644 --- a/client/src/localization/languages/Jp.ts +++ b/client/src/localization/languages/Jp.ts @@ -905,4 +905,10 @@ export default { com_ui_duplicate_agent_confirm: 'このエージェントを複製しますか?', com_nav_welcome_agent: 'エージェントを選択してください', com_ui_delete_shared_link: '共有リンクを削除しますか?', + com_ui_bookmarks_add: 'ブックマークを追加', + com_ui_page: 'ページ', + com_ui_bookmarks_edit: 'ブックマークを編集', + com_endpoint_ai: 'AI', + com_endpoint_message_new: 'メッセージ {0} または「@」を入力してAIを切り替え', + com_nav_maximize_chat_space: 'チャット画面を最大化', }; diff --git a/client/src/localization/languages/Ko.ts b/client/src/localization/languages/Ko.ts index 9742e4206d5..6620385d5bb 100644 --- a/client/src/localization/languages/Ko.ts +++ b/client/src/localization/languages/Ko.ts @@ -1143,4 +1143,10 @@ export default { com_ui_duplicate_agent_confirm: '이 에이전트를 복제하시겠습니까?', com_nav_welcome_agent: '에이전트를 선택해 주세요', com_ui_delete_shared_link: '공유 링크를 삭제하시겠습니까?', + com_ui_bookmarks_add: '북마크 추가', + com_ui_bookmarks_edit: '북마크 수정', + com_ui_page: '페이지', + com_endpoint_ai: '인공지능', + com_nav_maximize_chat_space: '채팅창 최대화', + com_endpoint_message_new: '메시지 {0} 또는 "@"를 입력하여 AI 전환', }; diff --git a/client/src/localization/languages/Ru.ts b/client/src/localization/languages/Ru.ts index 81a238212b5..f4eddc124f3 100644 --- a/client/src/localization/languages/Ru.ts +++ b/client/src/localization/languages/Ru.ts @@ -1169,4 +1169,10 @@ export default { com_nav_welcome_agent: 'Выберите агента', com_ui_duplicate_agent_confirm: 'Вы действительно хотите создать копию этого агента?', com_ui_delete_shared_link: 'Удалить общую ссылку?', + com_ui_bookmarks_edit: 'Редактировать закладку', + com_ui_page: 'Страница', + com_endpoint_ai: 'ИИ', + com_endpoint_message_new: 'Сообщение {0} или введите "@" для смены ИИ', + com_nav_maximize_chat_space: 'Развернуть чат', + com_ui_bookmarks_add: 'Добавить закладку', }; diff --git a/client/src/localization/languages/Zh.ts b/client/src/localization/languages/Zh.ts index d0537ad530a..4b1c0e01d2a 100644 --- a/client/src/localization/languages/Zh.ts +++ b/client/src/localization/languages/Zh.ts @@ -897,4 +897,10 @@ export default { com_endpoint_agent_placeholder: '请选择代理', com_ui_delete_shared_link: '删除分享链接?', com_nav_welcome_agent: '请选择 Agent', + com_ui_bookmarks_add: '添加书签', + com_ui_bookmarks_edit: '编辑书签', + com_endpoint_ai: '人工智能', + com_ui_page: '页面', + com_nav_maximize_chat_space: '最大化聊天窗口', + com_endpoint_message_new: '发送消息 {0} 或输入"@"切换AI', }; diff --git a/client/src/localization/languages/ZhTraditional.ts b/client/src/localization/languages/ZhTraditional.ts index 9da9ee93bba..e18b3ca4d2d 100644 --- a/client/src/localization/languages/ZhTraditional.ts +++ b/client/src/localization/languages/ZhTraditional.ts @@ -874,4 +874,10 @@ export default { com_ui_duplicate_agent_confirm: '您確定要複製這個助理嗎?', com_ui_delete_shared_link: '刪除共享連結?', com_nav_welcome_agent: '請選擇代理', + com_ui_bookmarks_edit: '編輯書籤', + com_ui_bookmarks_add: '新增書籤', + com_ui_page: '頁面', + com_nav_maximize_chat_space: '最大化聊天視窗', + com_endpoint_ai: 'AI', + com_endpoint_message_new: '輸入訊息 {0} 或輸入 "@" 以切換 AI', }; diff --git a/config/translations/README.md b/config/translations/README.md index 75571f4524f..e411aff79f5 100644 --- a/config/translations/README.md +++ b/config/translations/README.md @@ -11,7 +11,20 @@ This script can be expensive, several dollars worth, even with prompt caching. I ### Instructions: -1. Main script: Run `bun config/translations/scan.ts` from the root directory. -2. Observe translations being generated in all supported languages. - - Supported languages are localizations with general translation prompts: - - These prompts are directly found in `client/src/localization/prompts`. \ No newline at end of file +*All commands are run from the root directory.* + +**Supported languages are localizations with general translation prompts** +- These prompts are directly found in `client/src/localization/prompts`. +- If your language is missing, you can contribute by adding a new file in `client/src/localization/prompts` with the language code as the file name. + +0. Make sure git history is clean with `git status`. +1. Install `hnswlib-node` package temporarily (we don't need to include it in the project): +```bash +npm install --save-dev hnswlib-node +``` +2. Run `bun install`. +3. Main script: Run `bun config/translations/scan.ts`. +4. Observe translations being generated in all supported languages and saved in `client/src/localization/languages`. + - e.g.: `client/src/localization/languages/Es_missing_keys.json` +5. Discard all git changes with `git checkout .`. +6. Copy the generated translations to their respective files, e.g.: `client/src/localization/languages/Es.ts`. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index af6307b409e..02697d754d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36292,7 +36292,7 @@ }, "packages/data-provider": { "name": "librechat-data-provider", - "version": "0.7.68", + "version": "0.7.69", "license": "ISC", "dependencies": { "axios": "^1.7.7", diff --git a/packages/data-provider/package.json b/packages/data-provider/package.json index d0573fa8e0c..184f4687b07 100644 --- a/packages/data-provider/package.json +++ b/packages/data-provider/package.json @@ -1,6 +1,6 @@ { "name": "librechat-data-provider", - "version": "0.7.68", + "version": "0.7.69", "description": "data services for librechat apps", "main": "dist/index.js", "module": "dist/index.es.js", diff --git a/packages/data-provider/src/schemas.ts b/packages/data-provider/src/schemas.ts index 88ebfe7254e..3608791921f 100644 --- a/packages/data-provider/src/schemas.ts +++ b/packages/data-provider/src/schemas.ts @@ -16,16 +16,19 @@ export const authTypeSchema = z.nativeEnum(AuthType); export enum EModelEndpoint { azureOpenAI = 'azureOpenAI', openAI = 'openAI', - bingAI = 'bingAI', - chatGPTBrowser = 'chatGPTBrowser', google = 'google', - gptPlugins = 'gptPlugins', anthropic = 'anthropic', assistants = 'assistants', azureAssistants = 'azureAssistants', agents = 'agents', custom = 'custom', bedrock = 'bedrock', + /** @deprecated */ + bingAI = 'bingAI', + /** @deprecated */ + chatGPTBrowser = 'chatGPTBrowser', + /** @deprecated */ + gptPlugins = 'gptPlugins', } export const paramEndpoints = new Set([ @@ -630,6 +633,69 @@ export const tConvoUpdateSchema = tConversationSchema.merge( }), ); +export const tQueryParamsSchema = tConversationSchema + .pick({ + // librechat settings + /** The AI context window, overrides the system-defined window as determined by `model` value */ + maxContextTokens: true, + /** + * Whether or not to re-submit files from previous messages on subsequent messages + * */ + resendFiles: true, + /** + * AKA Custom Instructions, dynamically added to chat history as a system message; + * for `bedrock` endpoint, this is used as the `system` model param if the provider uses it; + * for `assistants` endpoint, this is used as the `additional_instructions` model param: + * https://platform.openai.com/docs/api-reference/runs/createRun#runs-createrun-additional_instructions + * ; otherwise, a message with `system` role is added to the chat history + */ + promptPrefix: true, + // Model parameters + /** @endpoints openAI, custom, azureOpenAI, google, anthropic, assistants, azureAssistants, bedrock */ + model: true, + /** @endpoints openAI, custom, azureOpenAI, google, anthropic, bedrock */ + temperature: true, + /** @endpoints openAI, custom, azureOpenAI */ + presence_penalty: true, + /** @endpoints openAI, custom, azureOpenAI */ + frequency_penalty: true, + /** @endpoints openAI, custom, azureOpenAI */ + stop: true, + /** @endpoints openAI, custom, azureOpenAI */ + top_p: true, + /** @endpoints openAI, custom, azureOpenAI */ + max_tokens: true, + /** @endpoints google, anthropic, bedrock */ + topP: true, + /** @endpoints google, anthropic */ + topK: true, + /** @endpoints google, anthropic */ + maxOutputTokens: true, + /** @endpoints anthropic */ + promptCache: true, + /** @endpoints bedrock */ + region: true, + /** @endpoints bedrock */ + maxTokens: true, + /** @endpoints agents */ + agent_id: true, + /** @endpoints assistants, azureAssistants */ + assistant_id: true, + /** + * @endpoints assistants, azureAssistants + * + * Overrides existing assistant instructions, only used for the current run: + * https://platform.openai.com/docs/api-reference/runs/createRun#runs-createrun-instructions + * */ + instructions: true, + }) + .merge( + z.object({ + /** @endpoints openAI, custom, azureOpenAI, google, anthropic, assistants, azureAssistants, bedrock, agents */ + endpoint: extendedModelEndpointSchema.nullable(), + }), + ); + export type TPreset = z.infer; export type TSetOption = (