| | const { Telemetry } = require("../../models/telemetry"); |
| | const { |
| | SUPPORTED_CONNECTION_METHODS, |
| | } = require("../AiProviders/bedrock/utils"); |
| | const { resetAllVectorStores } = require("../vectorStore/resetAllVectorStores"); |
| |
|
| | const KEY_MAPPING = { |
| | LLMProvider: { |
| | envKey: "LLM_PROVIDER", |
| | checks: [isNotEmpty, supportedLLM], |
| | }, |
| | |
| | OpenAiKey: { |
| | envKey: "OPEN_AI_KEY", |
| | checks: [isNotEmpty, validOpenAIKey], |
| | }, |
| | OpenAiModelPref: { |
| | envKey: "OPEN_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | |
| | AzureOpenAiEndpoint: { |
| | envKey: "AZURE_OPENAI_ENDPOINT", |
| | checks: [isNotEmpty], |
| | }, |
| | AzureOpenAiTokenLimit: { |
| | envKey: "AZURE_OPENAI_TOKEN_LIMIT", |
| | checks: [validOpenAiTokenLimit], |
| | }, |
| | AzureOpenAiKey: { |
| | envKey: "AZURE_OPENAI_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | AzureOpenAiModelPref: { |
| | envKey: "OPEN_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | AzureOpenAiEmbeddingModelPref: { |
| | envKey: "EMBEDDING_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | AzureOpenAiModelType: { |
| | envKey: "AZURE_OPENAI_MODEL_TYPE", |
| | checks: [ |
| | (input) => |
| | ["default", "reasoning"].includes(input) |
| | ? null |
| | : "Invalid model type. Must be one of: default, reasoning.", |
| | ], |
| | }, |
| |
|
| | |
| | AnthropicApiKey: { |
| | envKey: "ANTHROPIC_API_KEY", |
| | checks: [isNotEmpty, validAnthropicApiKey], |
| | }, |
| | AnthropicModelPref: { |
| | envKey: "ANTHROPIC_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | GeminiLLMApiKey: { |
| | envKey: "GEMINI_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | GeminiLLMModelPref: { |
| | envKey: "GEMINI_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | GeminiSafetySetting: { |
| | envKey: "GEMINI_SAFETY_SETTING", |
| | checks: [validGeminiSafetySetting], |
| | }, |
| |
|
| | |
| | LMStudioBasePath: { |
| | envKey: "LMSTUDIO_BASE_PATH", |
| | checks: [isNotEmpty, validLLMExternalBasePath, validDockerizedUrl], |
| | }, |
| | LMStudioModelPref: { |
| | envKey: "LMSTUDIO_MODEL_PREF", |
| | checks: [], |
| | }, |
| | LMStudioTokenLimit: { |
| | envKey: "LMSTUDIO_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | LocalAiBasePath: { |
| | envKey: "LOCAL_AI_BASE_PATH", |
| | checks: [isNotEmpty, validLLMExternalBasePath, validDockerizedUrl], |
| | }, |
| | LocalAiModelPref: { |
| | envKey: "LOCAL_AI_MODEL_PREF", |
| | checks: [], |
| | }, |
| | LocalAiTokenLimit: { |
| | envKey: "LOCAL_AI_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | LocalAiApiKey: { |
| | envKey: "LOCAL_AI_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | OllamaLLMBasePath: { |
| | envKey: "OLLAMA_BASE_PATH", |
| | checks: [isNotEmpty, validOllamaLLMBasePath, validDockerizedUrl], |
| | }, |
| | OllamaLLMModelPref: { |
| | envKey: "OLLAMA_MODEL_PREF", |
| | checks: [], |
| | }, |
| | OllamaLLMTokenLimit: { |
| | envKey: "OLLAMA_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | OllamaLLMPerformanceMode: { |
| | envKey: "OLLAMA_PERFORMANCE_MODE", |
| | checks: [], |
| | }, |
| | OllamaLLMKeepAliveSeconds: { |
| | envKey: "OLLAMA_KEEP_ALIVE_TIMEOUT", |
| | checks: [isInteger], |
| | }, |
| | OllamaLLMAuthToken: { |
| | envKey: "OLLAMA_AUTH_TOKEN", |
| | checks: [], |
| | }, |
| |
|
| | |
| | MistralApiKey: { |
| | envKey: "MISTRAL_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | MistralModelPref: { |
| | envKey: "MISTRAL_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | HuggingFaceLLMEndpoint: { |
| | envKey: "HUGGING_FACE_LLM_ENDPOINT", |
| | checks: [isNotEmpty, isValidURL, validHuggingFaceEndpoint], |
| | }, |
| | HuggingFaceLLMAccessToken: { |
| | envKey: "HUGGING_FACE_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | HuggingFaceLLMTokenLimit: { |
| | envKey: "HUGGING_FACE_LLM_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | KoboldCPPBasePath: { |
| | envKey: "KOBOLD_CPP_BASE_PATH", |
| | checks: [isNotEmpty, isValidURL], |
| | }, |
| | KoboldCPPModelPref: { |
| | envKey: "KOBOLD_CPP_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | KoboldCPPTokenLimit: { |
| | envKey: "KOBOLD_CPP_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | KoboldCPPMaxTokens: { |
| | envKey: "KOBOLD_CPP_MAX_TOKENS", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | TextGenWebUIBasePath: { |
| | envKey: "TEXT_GEN_WEB_UI_BASE_PATH", |
| | checks: [isValidURL], |
| | }, |
| | TextGenWebUITokenLimit: { |
| | envKey: "TEXT_GEN_WEB_UI_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | TextGenWebUIAPIKey: { |
| | envKey: "TEXT_GEN_WEB_UI_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | |
| | LiteLLMModelPref: { |
| | envKey: "LITE_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | LiteLLMTokenLimit: { |
| | envKey: "LITE_LLM_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | LiteLLMBasePath: { |
| | envKey: "LITE_LLM_BASE_PATH", |
| | checks: [isValidURL], |
| | }, |
| | LiteLLMApiKey: { |
| | envKey: "LITE_LLM_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | |
| | GenericOpenAiBasePath: { |
| | envKey: "GENERIC_OPEN_AI_BASE_PATH", |
| | checks: [isValidURL], |
| | }, |
| | GenericOpenAiModelPref: { |
| | envKey: "GENERIC_OPEN_AI_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | GenericOpenAiTokenLimit: { |
| | envKey: "GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | GenericOpenAiKey: { |
| | envKey: "GENERIC_OPEN_AI_API_KEY", |
| | checks: [], |
| | }, |
| | GenericOpenAiMaxTokens: { |
| | envKey: "GENERIC_OPEN_AI_MAX_TOKENS", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | AwsBedrockLLMConnectionMethod: { |
| | envKey: "AWS_BEDROCK_LLM_CONNECTION_METHOD", |
| | checks: [ |
| | (input) => |
| | SUPPORTED_CONNECTION_METHODS.includes(input) ? null : "invalid Value", |
| | ], |
| | }, |
| | AwsBedrockLLMAccessKeyId: { |
| | envKey: "AWS_BEDROCK_LLM_ACCESS_KEY_ID", |
| | checks: [isNotEmpty], |
| | }, |
| | AwsBedrockLLMAccessKey: { |
| | envKey: "AWS_BEDROCK_LLM_ACCESS_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | AwsBedrockLLMSessionToken: { |
| | envKey: "AWS_BEDROCK_LLM_SESSION_TOKEN", |
| | checks: [], |
| | }, |
| | AwsBedrockLLMRegion: { |
| | envKey: "AWS_BEDROCK_LLM_REGION", |
| | checks: [isNotEmpty], |
| | }, |
| | AwsBedrockLLMModel: { |
| | envKey: "AWS_BEDROCK_LLM_MODEL_PREFERENCE", |
| | checks: [isNotEmpty], |
| | }, |
| | AwsBedrockLLMTokenLimit: { |
| | envKey: "AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| | AwsBedrockLLMMaxOutputTokens: { |
| | envKey: "AWS_BEDROCK_LLM_MAX_OUTPUT_TOKENS", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | DellProAiStudioBasePath: { |
| | envKey: "DPAIS_LLM_BASE_PATH", |
| | checks: [isNotEmpty, validDockerizedUrl], |
| | }, |
| | DellProAiStudioModelPref: { |
| | envKey: "DPAIS_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | DellProAiStudioTokenLimit: { |
| | envKey: "DPAIS_LLM_MODEL_TOKEN_LIMIT", |
| | checks: [nonZero], |
| | }, |
| |
|
| | EmbeddingEngine: { |
| | envKey: "EMBEDDING_ENGINE", |
| | checks: [supportedEmbeddingModel], |
| | postUpdate: [handleVectorStoreReset], |
| | }, |
| | EmbeddingBasePath: { |
| | envKey: "EMBEDDING_BASE_PATH", |
| | checks: [isNotEmpty, validDockerizedUrl], |
| | }, |
| | EmbeddingModelPref: { |
| | envKey: "EMBEDDING_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | postUpdate: [handleVectorStoreReset, downloadEmbeddingModelIfRequired], |
| | }, |
| | EmbeddingModelMaxChunkLength: { |
| | envKey: "EMBEDDING_MODEL_MAX_CHUNK_LENGTH", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | GeminiEmbeddingApiKey: { |
| | envKey: "GEMINI_EMBEDDING_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | GenericOpenAiEmbeddingApiKey: { |
| | envKey: "GENERIC_OPEN_AI_EMBEDDING_API_KEY", |
| | checks: [], |
| | }, |
| | GenericOpenAiEmbeddingMaxConcurrentChunks: { |
| | envKey: "GENERIC_OPEN_AI_EMBEDDING_MAX_CONCURRENT_CHUNKS", |
| | checks: [nonZero], |
| | }, |
| |
|
| | |
| | VectorDB: { |
| | envKey: "VECTOR_DB", |
| | checks: [isNotEmpty, supportedVectorDB], |
| | postUpdate: [handleVectorStoreReset], |
| | }, |
| |
|
| | |
| | ChromaEndpoint: { |
| | envKey: "CHROMA_ENDPOINT", |
| | checks: [isValidURL, validChromaURL, validDockerizedUrl], |
| | }, |
| | ChromaApiHeader: { |
| | envKey: "CHROMA_API_HEADER", |
| | checks: [], |
| | }, |
| | ChromaApiKey: { |
| | envKey: "CHROMA_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | |
| | ChromaCloudApiKey: { |
| | envKey: "CHROMACLOUD_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | ChromaCloudTenant: { |
| | envKey: "CHROMACLOUD_TENANT", |
| | checks: [isNotEmpty], |
| | }, |
| | ChromaCloudDatabase: { |
| | envKey: "CHROMACLOUD_DATABASE", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | WeaviateEndpoint: { |
| | envKey: "WEAVIATE_ENDPOINT", |
| | checks: [isValidURL, validDockerizedUrl], |
| | }, |
| | WeaviateApiKey: { |
| | envKey: "WEAVIATE_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | |
| | QdrantEndpoint: { |
| | envKey: "QDRANT_ENDPOINT", |
| | checks: [isValidURL, validDockerizedUrl], |
| | }, |
| | QdrantApiKey: { |
| | envKey: "QDRANT_API_KEY", |
| | checks: [], |
| | }, |
| | PineConeKey: { |
| | envKey: "PINECONE_API_KEY", |
| | checks: [], |
| | }, |
| | PineConeIndex: { |
| | envKey: "PINECONE_INDEX", |
| | checks: [], |
| | }, |
| |
|
| | |
| | MilvusAddress: { |
| | envKey: "MILVUS_ADDRESS", |
| | checks: [isValidURL, validDockerizedUrl], |
| | }, |
| | MilvusUsername: { |
| | envKey: "MILVUS_USERNAME", |
| | checks: [isNotEmpty], |
| | }, |
| | MilvusPassword: { |
| | envKey: "MILVUS_PASSWORD", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | ZillizEndpoint: { |
| | envKey: "ZILLIZ_ENDPOINT", |
| | checks: [isValidURL], |
| | }, |
| | ZillizApiToken: { |
| | envKey: "ZILLIZ_API_TOKEN", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | AstraDBApplicationToken: { |
| | envKey: "ASTRA_DB_APPLICATION_TOKEN", |
| | checks: [isNotEmpty], |
| | }, |
| | AstraDBEndpoint: { |
| | envKey: "ASTRA_DB_ENDPOINT", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | PGVectorConnectionString: { |
| | envKey: "PGVECTOR_CONNECTION_STRING", |
| | checks: [isNotEmpty, looksLikePostgresConnectionString], |
| | preUpdate: [validatePGVectorConnectionString], |
| | }, |
| | PGVectorTableName: { |
| | envKey: "PGVECTOR_TABLE_NAME", |
| | checks: [isNotEmpty], |
| | preUpdate: [validatePGVectorTableName], |
| | }, |
| |
|
| | |
| | TogetherAiApiKey: { |
| | envKey: "TOGETHER_AI_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | TogetherAiModelPref: { |
| | envKey: "TOGETHER_AI_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | FireworksAiLLMApiKey: { |
| | envKey: "FIREWORKS_AI_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | FireworksAiLLMModelPref: { |
| | envKey: "FIREWORKS_AI_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | PerplexityApiKey: { |
| | envKey: "PERPLEXITY_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | PerplexityModelPref: { |
| | envKey: "PERPLEXITY_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | OpenRouterApiKey: { |
| | envKey: "OPENROUTER_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | OpenRouterModelPref: { |
| | envKey: "OPENROUTER_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | OpenRouterTimeout: { |
| | envKey: "OPENROUTER_TIMEOUT_MS", |
| | checks: [], |
| | }, |
| |
|
| | |
| | NovitaLLMApiKey: { |
| | envKey: "NOVITA_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | NovitaLLMModelPref: { |
| | envKey: "NOVITA_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | NovitaLLMTimeout: { |
| | envKey: "NOVITA_LLM_TIMEOUT_MS", |
| | checks: [], |
| | }, |
| |
|
| | |
| | GroqApiKey: { |
| | envKey: "GROQ_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | GroqModelPref: { |
| | envKey: "GROQ_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | CohereApiKey: { |
| | envKey: "COHERE_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | CohereModelPref: { |
| | envKey: "COHERE_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | VoyageAiApiKey: { |
| | envKey: "VOYAGEAI_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | WhisperProvider: { |
| | envKey: "WHISPER_PROVIDER", |
| | checks: [isNotEmpty, supportedTranscriptionProvider], |
| | postUpdate: [], |
| | }, |
| | WhisperModelPref: { |
| | envKey: "WHISPER_MODEL_PREF", |
| | checks: [validLocalWhisper], |
| | postUpdate: [], |
| | }, |
| |
|
| | |
| | AuthToken: { |
| | envKey: "AUTH_TOKEN", |
| | checks: [requiresForceMode, noRestrictedChars], |
| | }, |
| | JWTSecret: { |
| | envKey: "JWT_SECRET", |
| | checks: [requiresForceMode], |
| | }, |
| | DisableTelemetry: { |
| | envKey: "DISABLE_TELEMETRY", |
| | checks: [], |
| | preUpdate: [ |
| | (_, __, nextValue) => { |
| | if (nextValue === "true") Telemetry.sendTelemetry("telemetry_disabled"); |
| | }, |
| | ], |
| | }, |
| |
|
| | |
| | AgentGoogleSearchEngineId: { |
| | envKey: "AGENT_GSE_CTX", |
| | checks: [], |
| | }, |
| | AgentGoogleSearchEngineKey: { |
| | envKey: "AGENT_GSE_KEY", |
| | checks: [], |
| | }, |
| | AgentSearchApiKey: { |
| | envKey: "AGENT_SEARCHAPI_API_KEY", |
| | checks: [], |
| | }, |
| | AgentSearchApiEngine: { |
| | envKey: "AGENT_SEARCHAPI_ENGINE", |
| | checks: [], |
| | }, |
| | AgentSerperApiKey: { |
| | envKey: "AGENT_SERPER_DEV_KEY", |
| | checks: [], |
| | }, |
| | AgentBingSearchApiKey: { |
| | envKey: "AGENT_BING_SEARCH_API_KEY", |
| | checks: [], |
| | }, |
| | AgentSerplyApiKey: { |
| | envKey: "AGENT_SERPLY_API_KEY", |
| | checks: [], |
| | }, |
| | AgentSearXNGApiUrl: { |
| | envKey: "AGENT_SEARXNG_API_URL", |
| | checks: [], |
| | }, |
| | AgentTavilyApiKey: { |
| | envKey: "AGENT_TAVILY_API_KEY", |
| | checks: [], |
| | }, |
| | AgentExaApiKey: { |
| | envKey: "AGENT_EXA_API_KEY", |
| | checks: [], |
| | }, |
| |
|
| | |
| | TextToSpeechProvider: { |
| | envKey: "TTS_PROVIDER", |
| | checks: [supportedTTSProvider], |
| | }, |
| |
|
| | |
| | TTSOpenAIKey: { |
| | envKey: "TTS_OPEN_AI_KEY", |
| | checks: [validOpenAIKey], |
| | }, |
| | TTSOpenAIVoiceModel: { |
| | envKey: "TTS_OPEN_AI_VOICE_MODEL", |
| | checks: [], |
| | }, |
| |
|
| | |
| | TTSElevenLabsKey: { |
| | envKey: "TTS_ELEVEN_LABS_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | TTSElevenLabsVoiceModel: { |
| | envKey: "TTS_ELEVEN_LABS_VOICE_MODEL", |
| | checks: [], |
| | }, |
| |
|
| | |
| | TTSPiperTTSVoiceModel: { |
| | envKey: "TTS_PIPER_VOICE_MODEL", |
| | checks: [], |
| | }, |
| |
|
| | |
| | TTSOpenAICompatibleKey: { |
| | envKey: "TTS_OPEN_AI_COMPATIBLE_KEY", |
| | checks: [], |
| | }, |
| | TTSOpenAICompatibleModel: { |
| | envKey: "TTS_OPEN_AI_COMPATIBLE_MODEL", |
| | checks: [], |
| | }, |
| | TTSOpenAICompatibleVoiceModel: { |
| | envKey: "TTS_OPEN_AI_COMPATIBLE_VOICE_MODEL", |
| | checks: [isNotEmpty], |
| | }, |
| | TTSOpenAICompatibleEndpoint: { |
| | envKey: "TTS_OPEN_AI_COMPATIBLE_ENDPOINT", |
| | checks: [isValidURL], |
| | }, |
| |
|
| | |
| | DeepSeekApiKey: { |
| | envKey: "DEEPSEEK_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | DeepSeekModelPref: { |
| | envKey: "DEEPSEEK_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | ApipieLLMApiKey: { |
| | envKey: "APIPIE_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | ApipieLLMModelPref: { |
| | envKey: "APIPIE_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | XAIApiKey: { |
| | envKey: "XAI_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | XAIModelPref: { |
| | envKey: "XAI_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | NvidiaNimLLMBasePath: { |
| | envKey: "NVIDIA_NIM_LLM_BASE_PATH", |
| | checks: [isValidURL], |
| | postUpdate: [ |
| | (_, __, nextValue) => { |
| | const { parseNvidiaNimBasePath } = require("../AiProviders/nvidiaNim"); |
| | process.env.NVIDIA_NIM_LLM_BASE_PATH = |
| | parseNvidiaNimBasePath(nextValue); |
| | }, |
| | ], |
| | }, |
| | NvidiaNimLLMModelPref: { |
| | envKey: "NVIDIA_NIM_LLM_MODEL_PREF", |
| | checks: [], |
| | postUpdate: [ |
| | async (_, __, nextValue) => { |
| | const { NvidiaNimLLM } = require("../AiProviders/nvidiaNim"); |
| | await NvidiaNimLLM.setModelTokenLimit(nextValue); |
| | }, |
| | ], |
| | }, |
| |
|
| | |
| | PPIOApiKey: { |
| | envKey: "PPIO_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | PPIOModelPref: { |
| | envKey: "PPIO_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | MoonshotAiApiKey: { |
| | envKey: "MOONSHOT_AI_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | MoonshotAiModelPref: { |
| | envKey: "MOONSHOT_AI_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| |
|
| | |
| | CometApiLLMApiKey: { |
| | envKey: "COMETAPI_LLM_API_KEY", |
| | checks: [isNotEmpty], |
| | }, |
| | CometApiLLMModelPref: { |
| | envKey: "COMETAPI_LLM_MODEL_PREF", |
| | checks: [isNotEmpty], |
| | }, |
| | CometApiLLMTimeout: { |
| | envKey: "COMETAPI_LLM_TIMEOUT_MS", |
| | checks: [], |
| | }, |
| | }; |
| |
|
| | function isNotEmpty(input = "") { |
| | return !input || input.length === 0 ? "Value cannot be empty" : null; |
| | } |
| |
|
| | function nonZero(input = "") { |
| | if (isNaN(Number(input))) return "Value must be a number"; |
| | return Number(input) <= 0 ? "Value must be greater than zero" : null; |
| | } |
| |
|
| | function isInteger(input = "") { |
| | if (isNaN(Number(input))) return "Value must be a number"; |
| | return Number(input); |
| | } |
| |
|
| | function isValidURL(input = "") { |
| | try { |
| | new URL(input); |
| | return null; |
| | } catch (e) { |
| | return "URL is not a valid URL."; |
| | } |
| | } |
| |
|
| | function validOpenAIKey(input = "") { |
| | return input.startsWith("sk-") ? null : "OpenAI Key must start with sk-"; |
| | } |
| |
|
| | function validAnthropicApiKey(input = "") { |
| | return input.startsWith("sk-ant-") |
| | ? null |
| | : "Anthropic Key must start with sk-ant-"; |
| | } |
| |
|
| | function validLLMExternalBasePath(input = "") { |
| | try { |
| | new URL(input); |
| | if (!input.includes("v1")) return "URL must include /v1"; |
| | if (input.split("").slice(-1)?.[0] === "/") |
| | return "URL cannot end with a slash"; |
| | return null; |
| | } catch { |
| | return "Not a valid URL"; |
| | } |
| | } |
| |
|
| | function validOllamaLLMBasePath(input = "") { |
| | try { |
| | new URL(input); |
| | if (input.split("").slice(-1)?.[0] === "/") |
| | return "URL cannot end with a slash"; |
| | return null; |
| | } catch { |
| | return "Not a valid URL"; |
| | } |
| | } |
| |
|
| | function supportedTTSProvider(input = "") { |
| | const validSelection = [ |
| | "native", |
| | "openai", |
| | "elevenlabs", |
| | "piper_local", |
| | "generic-openai", |
| | ].includes(input); |
| | return validSelection ? null : `${input} is not a valid TTS provider.`; |
| | } |
| |
|
| | function validLocalWhisper(input = "") { |
| | const validSelection = [ |
| | "Xenova/whisper-small", |
| | "Xenova/whisper-large", |
| | ].includes(input); |
| | return validSelection |
| | ? null |
| | : `${input} is not a valid Whisper model selection.`; |
| | } |
| |
|
| | function supportedLLM(input = "") { |
| | const validSelection = [ |
| | "openai", |
| | "azure", |
| | "anthropic", |
| | "gemini", |
| | "lmstudio", |
| | "localai", |
| | "ollama", |
| | "togetherai", |
| | "fireworksai", |
| | "mistral", |
| | "huggingface", |
| | "perplexity", |
| | "openrouter", |
| | "novita", |
| | "groq", |
| | "koboldcpp", |
| | "textgenwebui", |
| | "cohere", |
| | "litellm", |
| | "generic-openai", |
| | "bedrock", |
| | "deepseek", |
| | "apipie", |
| | "xai", |
| | "nvidia-nim", |
| | "ppio", |
| | "dpais", |
| | "moonshotai", |
| | "cometapi", |
| | ].includes(input); |
| | return validSelection ? null : `${input} is not a valid LLM provider.`; |
| | } |
| |
|
| | function supportedTranscriptionProvider(input = "") { |
| | const validSelection = ["openai", "local"].includes(input); |
| | return validSelection |
| | ? null |
| | : `${input} is not a valid transcription model provider.`; |
| | } |
| |
|
| | function validGeminiSafetySetting(input = "") { |
| | const validModes = [ |
| | "BLOCK_NONE", |
| | "BLOCK_ONLY_HIGH", |
| | "BLOCK_MEDIUM_AND_ABOVE", |
| | "BLOCK_LOW_AND_ABOVE", |
| | ]; |
| | return validModes.includes(input) |
| | ? null |
| | : `Invalid Safety setting. Must be one of ${validModes.join(", ")}.`; |
| | } |
| |
|
| | function supportedEmbeddingModel(input = "") { |
| | const supported = [ |
| | "openai", |
| | "azure", |
| | "gemini", |
| | "localai", |
| | "native", |
| | "ollama", |
| | "lmstudio", |
| | "cohere", |
| | "voyageai", |
| | "litellm", |
| | "generic-openai", |
| | "mistral", |
| | ]; |
| | return supported.includes(input) |
| | ? null |
| | : `Invalid Embedding model type. Must be one of ${supported.join(", ")}.`; |
| | } |
| |
|
| | function supportedVectorDB(input = "") { |
| | const supported = [ |
| | "chroma", |
| | "chromacloud", |
| | "pinecone", |
| | "lancedb", |
| | "weaviate", |
| | "qdrant", |
| | "milvus", |
| | "zilliz", |
| | "astra", |
| | "pgvector", |
| | ]; |
| | return supported.includes(input) |
| | ? null |
| | : `Invalid VectorDB type. Must be one of ${supported.join(", ")}.`; |
| | } |
| |
|
| | function validChromaURL(input = "") { |
| | return input.slice(-1) === "/" |
| | ? `Chroma Instance URL should not end in a trailing slash.` |
| | : null; |
| | } |
| |
|
| | function validOpenAiTokenLimit(input = "") { |
| | const tokenLimit = Number(input); |
| | if (isNaN(tokenLimit)) return "Token limit is not a number"; |
| | return null; |
| | } |
| |
|
| | function requiresForceMode(_, forceModeEnabled = false) { |
| | return forceModeEnabled === true ? null : "Cannot set this setting."; |
| | } |
| |
|
| | async function validDockerizedUrl(input = "") { |
| | if (process.env.ANYTHING_LLM_RUNTIME !== "docker") return null; |
| |
|
| | try { |
| | const { isPortInUse, getLocalHosts } = require("./portAvailabilityChecker"); |
| | const localInterfaces = getLocalHosts(); |
| | const url = new URL(input); |
| | const hostname = url.hostname.toLowerCase(); |
| | const port = parseInt(url.port, 10); |
| |
|
| | |
| | if (!localInterfaces.includes(hostname)) return null; |
| | if (isNaN(port)) return "Invalid URL: Port is not specified or invalid"; |
| |
|
| | const isPortAvailableFromDocker = await isPortInUse(port, hostname); |
| | if (isPortAvailableFromDocker) |
| | return "Port is not running a reachable service on loopback address from inside the AnythingLLM container. Please use host.docker.internal (for linux use 172.17.0.1), a real machine ip, or domain to connect to your service."; |
| | } catch (error) { |
| | console.error(error.message); |
| | return "An error occurred while validating the URL"; |
| | } |
| |
|
| | return null; |
| | } |
| |
|
| | function validHuggingFaceEndpoint(input = "") { |
| | return input.slice(-6) !== ".cloud" |
| | ? `Your HF Endpoint should end in ".cloud"` |
| | : null; |
| | } |
| |
|
| | function noRestrictedChars(input = "") { |
| | const regExp = new RegExp(/^[a-zA-Z0-9_\-!@$%^&*();]+$/); |
| | return !regExp.test(input) |
| | ? `Your password has restricted characters in it. Allowed symbols are _,-,!,@,$,%,^,&,*,(,),;` |
| | : null; |
| | } |
| |
|
| | async function handleVectorStoreReset(key, prevValue, nextValue) { |
| | if (prevValue === nextValue) return; |
| | if (key === "VectorDB") { |
| | console.log( |
| | `Vector configuration changed from ${prevValue} to ${nextValue} - resetting ${prevValue} namespaces` |
| | ); |
| | return await resetAllVectorStores({ vectorDbKey: prevValue }); |
| | } |
| |
|
| | if (key === "EmbeddingEngine" || key === "EmbeddingModelPref") { |
| | console.log( |
| | `${key} changed from ${prevValue} to ${nextValue} - resetting ${process.env.VECTOR_DB} namespaces` |
| | ); |
| | return await resetAllVectorStores({ vectorDbKey: process.env.VECTOR_DB }); |
| | } |
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | async function downloadEmbeddingModelIfRequired(key, prevValue, nextValue) { |
| | if (prevValue === nextValue) return; |
| | if (key !== "EmbeddingModelPref" || process.env.EMBEDDING_ENGINE !== "native") |
| | return; |
| |
|
| | const { NativeEmbedder } = require("../EmbeddingEngines/native"); |
| | if (!NativeEmbedder.supportedModels[nextValue]) return; |
| | new NativeEmbedder().embedderClient(); |
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | async function looksLikePostgresConnectionString(connectionString = null) { |
| | if (!connectionString || !connectionString.startsWith("postgresql://")) |
| | return "Invalid Postgres connection string. Must start with postgresql://"; |
| | if (connectionString.includes(" ")) |
| | return "Invalid Postgres connection string. Must not contain spaces."; |
| | return null; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | async function validatePGVectorConnectionString(key, prevValue, nextValue) { |
| | const envKey = KEY_MAPPING[key].envKey; |
| |
|
| | if (prevValue === nextValue) return; |
| | if (!nextValue) return; |
| | if (nextValue === process.env[envKey]) return; |
| |
|
| | const { PGVector } = require("../vectorDbProviders/pgvector"); |
| | const { error, success } = await PGVector.validateConnection({ |
| | connectionString: nextValue, |
| | }); |
| | if (!success) return error; |
| |
|
| | |
| | process.env[envKey] = nextValue; |
| | return null; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | async function validatePGVectorTableName(key, prevValue, nextValue) { |
| | const envKey = KEY_MAPPING[key].envKey; |
| |
|
| | if (prevValue === nextValue) return; |
| | if (!nextValue) return; |
| | if (nextValue === process.env[envKey]) return; |
| | if (!process.env.PGVECTOR_CONNECTION_STRING) return; |
| |
|
| | const { PGVector } = require("../vectorDbProviders/pgvector"); |
| | const { error, success } = await PGVector.validateConnection({ |
| | connectionString: process.env.PGVECTOR_CONNECTION_STRING, |
| | tableName: nextValue, |
| | }); |
| | if (!success) return error; |
| |
|
| | return null; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | async function updateENV(newENVs = {}, force = false, userId = null) { |
| | let error = ""; |
| | const validKeys = Object.keys(KEY_MAPPING); |
| | const ENV_KEYS = Object.keys(newENVs).filter( |
| | (key) => validKeys.includes(key) && !newENVs[key].includes("******") |
| | ); |
| | const newValues = {}; |
| |
|
| | for (const key of ENV_KEYS) { |
| | const { |
| | envKey, |
| | checks, |
| | preUpdate = [], |
| | postUpdate = [], |
| | } = KEY_MAPPING[key]; |
| | const prevValue = process.env[envKey]; |
| | const nextValue = newENVs[key]; |
| | let errors = await executeValidationChecks(checks, nextValue, force); |
| |
|
| | |
| | |
| | if (errors.length > 0) { |
| | error += errors.join("\n"); |
| | break; |
| | } |
| |
|
| | |
| | errors = []; |
| | for (const preUpdateFunc of preUpdate) { |
| | const errorMsg = await preUpdateFunc(key, prevValue, nextValue); |
| | if (!!errorMsg && typeof errorMsg === "string") errors.push(errorMsg); |
| | } |
| |
|
| | |
| | |
| | if (errors.length > 0) { |
| | error += errors.join("\n"); |
| | break; |
| | } |
| |
|
| | newValues[key] = nextValue; |
| | process.env[envKey] = nextValue; |
| |
|
| | for (const postUpdateFunc of postUpdate) |
| | await postUpdateFunc(key, prevValue, nextValue); |
| | } |
| |
|
| | await logChangesToEventLog(newValues, userId); |
| | if (process.env.NODE_ENV === "production") dumpENV(); |
| | return { newValues, error: error?.length > 0 ? error : false }; |
| | } |
| |
|
| | async function executeValidationChecks(checks, value, force) { |
| | const results = await Promise.all( |
| | checks.map((validator) => validator(value, force)) |
| | ); |
| | return results.filter((err) => typeof err === "string"); |
| | } |
| |
|
| | async function logChangesToEventLog(newValues = {}, userId = null) { |
| | const { EventLogs } = require("../../models/eventLogs"); |
| | const eventMapping = { |
| | LLMProvider: "update_llm_provider", |
| | EmbeddingEngine: "update_embedding_engine", |
| | VectorDB: "update_vector_db", |
| | }; |
| |
|
| | for (const [key, eventName] of Object.entries(eventMapping)) { |
| | if (!newValues.hasOwnProperty(key)) continue; |
| | await EventLogs.logEvent(eventName, {}, userId); |
| | } |
| | return; |
| | } |
| |
|
| | function dumpENV() { |
| | const fs = require("fs"); |
| | const path = require("path"); |
| |
|
| | const frozenEnvs = {}; |
| | const protectedKeys = [ |
| | ...Object.values(KEY_MAPPING).map((values) => values.envKey), |
| | |
| | |
| | "JWT_EXPIRY", |
| |
|
| | "STORAGE_DIR", |
| | "SERVER_PORT", |
| | |
| | "SIG_KEY", |
| | "SIG_SALT", |
| | |
| | "PASSWORDMINCHAR", |
| | "PASSWORDMAXCHAR", |
| | "PASSWORDLOWERCASE", |
| | "PASSWORDUPPERCASE", |
| | "PASSWORDNUMERIC", |
| | "PASSWORDSYMBOL", |
| | "PASSWORDREQUIREMENTS", |
| | |
| | "ENABLE_HTTPS", |
| | "HTTPS_CERT_PATH", |
| | "HTTPS_KEY_PATH", |
| | |
| | "DISABLE_VIEW_CHAT_HISTORY", |
| | |
| | "SIMPLE_SSO_ENABLED", |
| | "SIMPLE_SSO_NO_LOGIN", |
| | "SIMPLE_SSO_NO_LOGIN_REDIRECT", |
| | |
| | "COMMUNITY_HUB_BUNDLE_DOWNLOADS_ENABLED", |
| |
|
| | |
| | "NVIDIA_NIM_LLM_MODEL_TOKEN_LIMIT", |
| |
|
| | |
| | "TARGET_OCR_LANG", |
| |
|
| | |
| | "COLLECTOR_ALLOW_ANY_IP", |
| |
|
| | |
| | "GENERIC_OPENAI_STREAMING_DISABLED", |
| |
|
| | |
| | "ANYTHINGLLM_CHROMIUM_ARGS", |
| | ]; |
| |
|
| | |
| | function sanitizeValue(value) { |
| | const offendingChars = |
| | /[\n\r\t\v\f\u0085\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000"'`#]/; |
| | const firstOffendingCharIndex = value.search(offendingChars); |
| | if (firstOffendingCharIndex === -1) return value; |
| |
|
| | return value.substring(0, firstOffendingCharIndex); |
| | } |
| |
|
| | for (const key of protectedKeys) { |
| | const envValue = process.env?.[key] || null; |
| | if (!envValue) continue; |
| | frozenEnvs[key] = process.env?.[key] || null; |
| | } |
| |
|
| | var envResult = `# Auto-dump ENV from system call on ${new Date().toTimeString()}\n`; |
| | envResult += Object.entries(frozenEnvs) |
| | .map(([key, value]) => `${key}='${sanitizeValue(value)}'`) |
| | .join("\n"); |
| |
|
| | const envPath = path.join(__dirname, "../../.env"); |
| | fs.writeFileSync(envPath, envResult, { encoding: "utf8", flag: "w" }); |
| | return true; |
| | } |
| |
|
| | module.exports = { |
| | dumpENV, |
| | updateENV, |
| | }; |
| |
|