|
|
process.env.NODE_ENV === "development" |
|
|
? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }) |
|
|
: require("dotenv").config(); |
|
|
|
|
|
const { default: slugify } = require("slugify"); |
|
|
const { isValidUrl, safeJsonParse } = require("../utils/http"); |
|
|
const prisma = require("../utils/prisma"); |
|
|
const { v4 } = require("uuid"); |
|
|
const { MetaGenerator } = require("../utils/boot/MetaGenerator"); |
|
|
const { PGVector } = require("../utils/vectorDbProviders/pgvector"); |
|
|
const { NativeEmbedder } = require("../utils/EmbeddingEngines/native"); |
|
|
const { getBaseLLMProviderModel } = require("../utils/helpers"); |
|
|
|
|
|
function isNullOrNaN(value) { |
|
|
if (value === null) return true; |
|
|
return isNaN(value); |
|
|
} |
|
|
|
|
|
const SystemSettings = { |
|
|
protectedFields: ["multi_user_mode", "hub_api_key"], |
|
|
publicFields: [ |
|
|
"footer_data", |
|
|
"support_email", |
|
|
"text_splitter_chunk_size", |
|
|
"text_splitter_chunk_overlap", |
|
|
"max_embed_chunk_size", |
|
|
"agent_search_provider", |
|
|
"agent_sql_connections", |
|
|
"default_agent_skills", |
|
|
"disabled_agent_skills", |
|
|
"imported_agent_skills", |
|
|
"custom_app_name", |
|
|
"feature_flags", |
|
|
"meta_page_title", |
|
|
"meta_page_favicon", |
|
|
], |
|
|
supportedFields: [ |
|
|
"logo_filename", |
|
|
"telemetry_id", |
|
|
"footer_data", |
|
|
"support_email", |
|
|
|
|
|
"text_splitter_chunk_size", |
|
|
"text_splitter_chunk_overlap", |
|
|
"agent_search_provider", |
|
|
"default_agent_skills", |
|
|
"disabled_agent_skills", |
|
|
"agent_sql_connections", |
|
|
"custom_app_name", |
|
|
|
|
|
|
|
|
"meta_page_title", |
|
|
"meta_page_favicon", |
|
|
|
|
|
|
|
|
"experimental_live_file_sync", |
|
|
|
|
|
|
|
|
"hub_api_key", |
|
|
], |
|
|
validations: { |
|
|
footer_data: (updates) => { |
|
|
try { |
|
|
const array = JSON.parse(updates) |
|
|
.filter((setting) => isValidUrl(setting.url)) |
|
|
.slice(0, 3); |
|
|
return JSON.stringify(array); |
|
|
} catch (e) { |
|
|
console.error(`Failed to run validation function on footer_data`); |
|
|
return JSON.stringify([]); |
|
|
} |
|
|
}, |
|
|
text_splitter_chunk_size: (update) => { |
|
|
try { |
|
|
if (isNullOrNaN(update)) throw new Error("Value is not a number."); |
|
|
if (Number(update) <= 0) throw new Error("Value must be non-zero."); |
|
|
const { purgeEntireVectorCache } = require("../utils/files"); |
|
|
purgeEntireVectorCache(); |
|
|
return Number(update); |
|
|
} catch (e) { |
|
|
console.error( |
|
|
`Failed to run validation function on text_splitter_chunk_size`, |
|
|
e.message |
|
|
); |
|
|
return 1000; |
|
|
} |
|
|
}, |
|
|
text_splitter_chunk_overlap: (update) => { |
|
|
try { |
|
|
if (isNullOrNaN(update)) throw new Error("Value is not a number"); |
|
|
if (Number(update) < 0) throw new Error("Value cannot be less than 0."); |
|
|
const { purgeEntireVectorCache } = require("../utils/files"); |
|
|
purgeEntireVectorCache(); |
|
|
return Number(update); |
|
|
} catch (e) { |
|
|
console.error( |
|
|
`Failed to run validation function on text_splitter_chunk_overlap`, |
|
|
e.message |
|
|
); |
|
|
return 20; |
|
|
} |
|
|
}, |
|
|
agent_search_provider: (update) => { |
|
|
try { |
|
|
if (update === "none") return null; |
|
|
if ( |
|
|
![ |
|
|
"google-search-engine", |
|
|
"searchapi", |
|
|
"serper-dot-dev", |
|
|
"bing-search", |
|
|
"serply-engine", |
|
|
"searxng-engine", |
|
|
"tavily-search", |
|
|
"duckduckgo-engine", |
|
|
"exa-search", |
|
|
].includes(update) |
|
|
) |
|
|
throw new Error("Invalid SERP provider."); |
|
|
return String(update); |
|
|
} catch (e) { |
|
|
console.error( |
|
|
`Failed to run validation function on agent_search_provider`, |
|
|
e.message |
|
|
); |
|
|
return null; |
|
|
} |
|
|
}, |
|
|
default_agent_skills: (updates) => { |
|
|
try { |
|
|
const skills = updates.split(",").filter((skill) => !!skill); |
|
|
return JSON.stringify(skills); |
|
|
} catch (e) { |
|
|
console.error(`Could not validate agent skills.`); |
|
|
return JSON.stringify([]); |
|
|
} |
|
|
}, |
|
|
disabled_agent_skills: (updates) => { |
|
|
try { |
|
|
const skills = updates.split(",").filter((skill) => !!skill); |
|
|
return JSON.stringify(skills); |
|
|
} catch (e) { |
|
|
console.error(`Could not validate disabled agent skills.`); |
|
|
return JSON.stringify([]); |
|
|
} |
|
|
}, |
|
|
agent_sql_connections: async (updates) => { |
|
|
const existingConnections = safeJsonParse( |
|
|
(await SystemSettings.get({ label: "agent_sql_connections" }))?.value, |
|
|
[] |
|
|
); |
|
|
try { |
|
|
const updatedConnections = mergeConnections( |
|
|
existingConnections, |
|
|
safeJsonParse(updates, []) |
|
|
); |
|
|
return JSON.stringify(updatedConnections); |
|
|
} catch (e) { |
|
|
console.error(`Failed to merge connections`); |
|
|
return JSON.stringify(existingConnections ?? []); |
|
|
} |
|
|
}, |
|
|
experimental_live_file_sync: (update) => { |
|
|
if (typeof update === "boolean") |
|
|
return update === true ? "enabled" : "disabled"; |
|
|
if (!["enabled", "disabled"].includes(update)) return "disabled"; |
|
|
return String(update); |
|
|
}, |
|
|
meta_page_title: (newTitle) => { |
|
|
try { |
|
|
if (typeof newTitle !== "string" || !newTitle) return null; |
|
|
return String(newTitle); |
|
|
} catch { |
|
|
return null; |
|
|
} finally { |
|
|
new MetaGenerator().clearConfig(); |
|
|
} |
|
|
}, |
|
|
meta_page_favicon: (faviconUrl) => { |
|
|
if (!faviconUrl) return null; |
|
|
try { |
|
|
const url = new URL(faviconUrl); |
|
|
return url.toString(); |
|
|
} catch { |
|
|
return null; |
|
|
} finally { |
|
|
new MetaGenerator().clearConfig(); |
|
|
} |
|
|
}, |
|
|
hub_api_key: (apiKey) => { |
|
|
if (!apiKey) return null; |
|
|
return String(apiKey); |
|
|
}, |
|
|
}, |
|
|
currentSettings: async function () { |
|
|
const { hasVectorCachedFiles } = require("../utils/files"); |
|
|
const llmProvider = process.env.LLM_PROVIDER; |
|
|
const vectorDB = process.env.VECTOR_DB; |
|
|
const embeddingEngine = process.env.EMBEDDING_ENGINE ?? "native"; |
|
|
return { |
|
|
|
|
|
|
|
|
|
|
|
RequiresAuth: !!process.env.AUTH_TOKEN, |
|
|
AuthToken: !!process.env.AUTH_TOKEN, |
|
|
JWTSecret: !!process.env.JWT_SECRET, |
|
|
StorageDir: process.env.STORAGE_DIR, |
|
|
MultiUserMode: await this.isMultiUserMode(), |
|
|
DisableTelemetry: process.env.DISABLE_TELEMETRY || "false", |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EmbeddingEngine: embeddingEngine, |
|
|
HasExistingEmbeddings: await this.hasEmbeddings(), |
|
|
HasCachedEmbeddings: hasVectorCachedFiles(), |
|
|
EmbeddingBasePath: process.env.EMBEDDING_BASE_PATH, |
|
|
EmbeddingModelPref: |
|
|
embeddingEngine === "native" |
|
|
? NativeEmbedder._getEmbeddingModel() |
|
|
: process.env.EMBEDDING_MODEL_PREF, |
|
|
EmbeddingModelMaxChunkLength: |
|
|
process.env.EMBEDDING_MODEL_MAX_CHUNK_LENGTH, |
|
|
VoyageAiApiKey: !!process.env.VOYAGEAI_API_KEY, |
|
|
GenericOpenAiEmbeddingApiKey: |
|
|
!!process.env.GENERIC_OPEN_AI_EMBEDDING_API_KEY, |
|
|
GenericOpenAiEmbeddingMaxConcurrentChunks: |
|
|
process.env.GENERIC_OPEN_AI_EMBEDDING_MAX_CONCURRENT_CHUNKS || 500, |
|
|
GeminiEmbeddingApiKey: !!process.env.GEMINI_EMBEDDING_API_KEY, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VectorDB: vectorDB, |
|
|
...this.vectorDBPreferenceKeys(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LLMProvider: llmProvider, |
|
|
LLMModel: getBaseLLMProviderModel({ provider: llmProvider }) || null, |
|
|
...this.llmPreferenceKeys(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WhisperProvider: process.env.WHISPER_PROVIDER || "local", |
|
|
WhisperModelPref: |
|
|
process.env.WHISPER_MODEL_PREF || "Xenova/whisper-small", |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TextToSpeechProvider: process.env.TTS_PROVIDER || "native", |
|
|
TTSOpenAIKey: !!process.env.TTS_OPEN_AI_KEY, |
|
|
TTSOpenAIVoiceModel: process.env.TTS_OPEN_AI_VOICE_MODEL, |
|
|
|
|
|
|
|
|
TTSElevenLabsKey: !!process.env.TTS_ELEVEN_LABS_KEY, |
|
|
TTSElevenLabsVoiceModel: process.env.TTS_ELEVEN_LABS_VOICE_MODEL, |
|
|
|
|
|
TTSPiperTTSVoiceModel: |
|
|
process.env.TTS_PIPER_VOICE_MODEL ?? "en_US-hfc_female-medium", |
|
|
|
|
|
TTSOpenAICompatibleKey: !!process.env.TTS_OPEN_AI_COMPATIBLE_KEY, |
|
|
TTSOpenAICompatibleModel: process.env.TTS_OPEN_AI_COMPATIBLE_MODEL, |
|
|
TTSOpenAICompatibleVoiceModel: |
|
|
process.env.TTS_OPEN_AI_COMPATIBLE_VOICE_MODEL, |
|
|
TTSOpenAICompatibleEndpoint: process.env.TTS_OPEN_AI_COMPATIBLE_ENDPOINT, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AgentGoogleSearchEngineId: process.env.AGENT_GSE_CTX || null, |
|
|
AgentGoogleSearchEngineKey: !!process.env.AGENT_GSE_KEY || null, |
|
|
AgentSearchApiKey: !!process.env.AGENT_SEARCHAPI_API_KEY || null, |
|
|
AgentSearchApiEngine: process.env.AGENT_SEARCHAPI_ENGINE || "google", |
|
|
AgentSerperApiKey: !!process.env.AGENT_SERPER_DEV_KEY || null, |
|
|
AgentBingSearchApiKey: !!process.env.AGENT_BING_SEARCH_API_KEY || null, |
|
|
AgentSerplyApiKey: !!process.env.AGENT_SERPLY_API_KEY || null, |
|
|
AgentSearXNGApiUrl: process.env.AGENT_SEARXNG_API_URL || null, |
|
|
AgentTavilyApiKey: !!process.env.AGENT_TAVILY_API_KEY || null, |
|
|
AgentExaApiKey: !!process.env.AGENT_EXA_API_KEY || null, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DisableViewChatHistory: |
|
|
"DISABLE_VIEW_CHAT_HISTORY" in process.env || false, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SimpleSSOEnabled: "SIMPLE_SSO_ENABLED" in process.env || false, |
|
|
SimpleSSONoLogin: "SIMPLE_SSO_NO_LOGIN" in process.env || false, |
|
|
SimpleSSONoLoginRedirect: this.simpleSSO.noLoginRedirect(), |
|
|
}; |
|
|
}, |
|
|
|
|
|
get: async function (clause = {}) { |
|
|
try { |
|
|
const setting = await prisma.system_settings.findFirst({ where: clause }); |
|
|
return setting || null; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return null; |
|
|
} |
|
|
}, |
|
|
|
|
|
getValueOrFallback: async function (clause = {}, fallback = null) { |
|
|
try { |
|
|
return (await this.get(clause))?.value ?? fallback; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return fallback; |
|
|
} |
|
|
}, |
|
|
|
|
|
where: async function (clause = {}, limit) { |
|
|
try { |
|
|
const settings = await prisma.system_settings.findMany({ |
|
|
where: clause, |
|
|
take: limit || undefined, |
|
|
}); |
|
|
return settings; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return []; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateSettings: async function (updates = {}) { |
|
|
const validFields = Object.keys(updates).filter((key) => |
|
|
this.supportedFields.includes(key) |
|
|
); |
|
|
|
|
|
Object.entries(updates).forEach(([key]) => { |
|
|
if (validFields.includes(key)) return; |
|
|
delete updates[key]; |
|
|
}); |
|
|
|
|
|
return this._updateSettings(updates); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_updateSettings: async function (updates = {}) { |
|
|
try { |
|
|
const updatePromises = []; |
|
|
for (const key of Object.keys(updates)) { |
|
|
let validatedValue = updates[key]; |
|
|
if (this.validations.hasOwnProperty(key)) { |
|
|
if (this.validations[key].constructor.name === "AsyncFunction") { |
|
|
validatedValue = await this.validations[key](updates[key]); |
|
|
} else { |
|
|
validatedValue = this.validations[key](updates[key]); |
|
|
} |
|
|
} |
|
|
|
|
|
updatePromises.push( |
|
|
prisma.system_settings.upsert({ |
|
|
where: { label: key }, |
|
|
update: { |
|
|
value: validatedValue === null ? null : String(validatedValue), |
|
|
}, |
|
|
create: { |
|
|
label: key, |
|
|
value: validatedValue === null ? null : String(validatedValue), |
|
|
}, |
|
|
}) |
|
|
); |
|
|
} |
|
|
|
|
|
await Promise.all(updatePromises); |
|
|
return { success: true, error: null }; |
|
|
} catch (error) { |
|
|
console.error("FAILED TO UPDATE SYSTEM SETTINGS", error.message); |
|
|
return { success: false, error: error.message }; |
|
|
} |
|
|
}, |
|
|
|
|
|
isMultiUserMode: async function () { |
|
|
try { |
|
|
const setting = await this.get({ label: "multi_user_mode" }); |
|
|
return setting?.value === "true"; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return false; |
|
|
} |
|
|
}, |
|
|
|
|
|
currentLogoFilename: async function () { |
|
|
try { |
|
|
const setting = await this.get({ label: "logo_filename" }); |
|
|
return setting?.value || null; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return null; |
|
|
} |
|
|
}, |
|
|
|
|
|
hasEmbeddings: async function () { |
|
|
try { |
|
|
const { Document } = require("./documents"); |
|
|
const count = await Document.count({}, 1); |
|
|
return count > 0; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return false; |
|
|
} |
|
|
}, |
|
|
|
|
|
vectorDBPreferenceKeys: function () { |
|
|
return { |
|
|
|
|
|
PineConeKey: !!process.env.PINECONE_API_KEY, |
|
|
PineConeIndex: process.env.PINECONE_INDEX, |
|
|
|
|
|
|
|
|
ChromaEndpoint: process.env.CHROMA_ENDPOINT, |
|
|
ChromaApiHeader: process.env.CHROMA_API_HEADER, |
|
|
ChromaApiKey: !!process.env.CHROMA_API_KEY, |
|
|
|
|
|
|
|
|
ChromaCloudApiKey: !!process.env.CHROMACLOUD_API_KEY, |
|
|
ChromaCloudTenant: process.env.CHROMACLOUD_TENANT, |
|
|
ChromaCloudDatabase: process.env.CHROMACLOUD_DATABASE, |
|
|
|
|
|
|
|
|
WeaviateEndpoint: process.env.WEAVIATE_ENDPOINT, |
|
|
WeaviateApiKey: process.env.WEAVIATE_API_KEY, |
|
|
|
|
|
|
|
|
QdrantEndpoint: process.env.QDRANT_ENDPOINT, |
|
|
QdrantApiKey: process.env.QDRANT_API_KEY, |
|
|
|
|
|
|
|
|
MilvusAddress: process.env.MILVUS_ADDRESS, |
|
|
MilvusUsername: process.env.MILVUS_USERNAME, |
|
|
MilvusPassword: !!process.env.MILVUS_PASSWORD, |
|
|
|
|
|
|
|
|
ZillizEndpoint: process.env.ZILLIZ_ENDPOINT, |
|
|
ZillizApiToken: process.env.ZILLIZ_API_TOKEN, |
|
|
|
|
|
|
|
|
AstraDBApplicationToken: process?.env?.ASTRA_DB_APPLICATION_TOKEN, |
|
|
AstraDBEndpoint: process?.env?.ASTRA_DB_ENDPOINT, |
|
|
|
|
|
|
|
|
PGVectorConnectionString: !!PGVector.connectionString() || false, |
|
|
PGVectorTableName: PGVector.tableName(), |
|
|
}; |
|
|
}, |
|
|
|
|
|
llmPreferenceKeys: function () { |
|
|
return { |
|
|
|
|
|
OpenAiKey: !!process.env.OPEN_AI_KEY, |
|
|
OpenAiModelPref: process.env.OPEN_MODEL_PREF || "gpt-4o", |
|
|
|
|
|
|
|
|
AzureOpenAiEndpoint: process.env.AZURE_OPENAI_ENDPOINT, |
|
|
AzureOpenAiKey: !!process.env.AZURE_OPENAI_KEY, |
|
|
AzureOpenAiModelPref: process.env.OPEN_MODEL_PREF, |
|
|
AzureOpenAiEmbeddingModelPref: process.env.EMBEDDING_MODEL_PREF, |
|
|
AzureOpenAiTokenLimit: process.env.AZURE_OPENAI_TOKEN_LIMIT || 4096, |
|
|
AzureOpenAiModelType: process.env.AZURE_OPENAI_MODEL_TYPE || "default", |
|
|
|
|
|
|
|
|
AnthropicApiKey: !!process.env.ANTHROPIC_API_KEY, |
|
|
AnthropicModelPref: process.env.ANTHROPIC_MODEL_PREF || "claude-2", |
|
|
|
|
|
|
|
|
GeminiLLMApiKey: !!process.env.GEMINI_API_KEY, |
|
|
GeminiLLMModelPref: |
|
|
process.env.GEMINI_LLM_MODEL_PREF || "gemini-2.0-flash-lite", |
|
|
GeminiSafetySetting: |
|
|
process.env.GEMINI_SAFETY_SETTING || "BLOCK_MEDIUM_AND_ABOVE", |
|
|
|
|
|
|
|
|
LMStudioBasePath: process.env.LMSTUDIO_BASE_PATH, |
|
|
LMStudioTokenLimit: process.env.LMSTUDIO_MODEL_TOKEN_LIMIT, |
|
|
LMStudioModelPref: process.env.LMSTUDIO_MODEL_PREF, |
|
|
|
|
|
|
|
|
LocalAiApiKey: !!process.env.LOCAL_AI_API_KEY, |
|
|
LocalAiBasePath: process.env.LOCAL_AI_BASE_PATH, |
|
|
LocalAiModelPref: process.env.LOCAL_AI_MODEL_PREF, |
|
|
LocalAiTokenLimit: process.env.LOCAL_AI_MODEL_TOKEN_LIMIT, |
|
|
|
|
|
|
|
|
OllamaLLMAuthToken: !!process.env.OLLAMA_AUTH_TOKEN, |
|
|
OllamaLLMBasePath: process.env.OLLAMA_BASE_PATH, |
|
|
OllamaLLMModelPref: process.env.OLLAMA_MODEL_PREF, |
|
|
OllamaLLMTokenLimit: process.env.OLLAMA_MODEL_TOKEN_LIMIT, |
|
|
OllamaLLMKeepAliveSeconds: process.env.OLLAMA_KEEP_ALIVE_TIMEOUT ?? 300, |
|
|
OllamaLLMPerformanceMode: process.env.OLLAMA_PERFORMANCE_MODE ?? "base", |
|
|
|
|
|
|
|
|
NovitaLLMApiKey: !!process.env.NOVITA_LLM_API_KEY, |
|
|
NovitaLLMModelPref: process.env.NOVITA_LLM_MODEL_PREF, |
|
|
NovitaLLMTimeout: process.env.NOVITA_LLM_TIMEOUT_MS, |
|
|
|
|
|
|
|
|
TogetherAiApiKey: !!process.env.TOGETHER_AI_API_KEY, |
|
|
TogetherAiModelPref: process.env.TOGETHER_AI_MODEL_PREF, |
|
|
|
|
|
|
|
|
FireworksAiLLMApiKey: !!process.env.FIREWORKS_AI_LLM_API_KEY, |
|
|
FireworksAiLLMModelPref: process.env.FIREWORKS_AI_LLM_MODEL_PREF, |
|
|
|
|
|
|
|
|
PerplexityApiKey: !!process.env.PERPLEXITY_API_KEY, |
|
|
PerplexityModelPref: process.env.PERPLEXITY_MODEL_PREF, |
|
|
|
|
|
|
|
|
OpenRouterApiKey: !!process.env.OPENROUTER_API_KEY, |
|
|
OpenRouterModelPref: process.env.OPENROUTER_MODEL_PREF, |
|
|
OpenRouterTimeout: process.env.OPENROUTER_TIMEOUT_MS, |
|
|
|
|
|
|
|
|
MistralApiKey: !!process.env.MISTRAL_API_KEY, |
|
|
MistralModelPref: process.env.MISTRAL_MODEL_PREF, |
|
|
|
|
|
|
|
|
GroqApiKey: !!process.env.GROQ_API_KEY, |
|
|
GroqModelPref: process.env.GROQ_MODEL_PREF, |
|
|
|
|
|
|
|
|
HuggingFaceLLMEndpoint: process.env.HUGGING_FACE_LLM_ENDPOINT, |
|
|
HuggingFaceLLMAccessToken: !!process.env.HUGGING_FACE_LLM_API_KEY, |
|
|
HuggingFaceLLMTokenLimit: process.env.HUGGING_FACE_LLM_TOKEN_LIMIT, |
|
|
|
|
|
|
|
|
KoboldCPPModelPref: process.env.KOBOLD_CPP_MODEL_PREF, |
|
|
KoboldCPPBasePath: process.env.KOBOLD_CPP_BASE_PATH, |
|
|
KoboldCPPTokenLimit: process.env.KOBOLD_CPP_MODEL_TOKEN_LIMIT, |
|
|
KoboldCPPMaxTokens: process.env.KOBOLD_CPP_MAX_TOKENS, |
|
|
|
|
|
|
|
|
TextGenWebUIBasePath: process.env.TEXT_GEN_WEB_UI_BASE_PATH, |
|
|
TextGenWebUITokenLimit: process.env.TEXT_GEN_WEB_UI_MODEL_TOKEN_LIMIT, |
|
|
TextGenWebUIAPIKey: !!process.env.TEXT_GEN_WEB_UI_API_KEY, |
|
|
|
|
|
|
|
|
LiteLLMModelPref: process.env.LITE_LLM_MODEL_PREF, |
|
|
LiteLLMTokenLimit: process.env.LITE_LLM_MODEL_TOKEN_LIMIT, |
|
|
LiteLLMBasePath: process.env.LITE_LLM_BASE_PATH, |
|
|
LiteLLMApiKey: !!process.env.LITE_LLM_API_KEY, |
|
|
|
|
|
|
|
|
MoonshotAiApiKey: !!process.env.MOONSHOT_AI_API_KEY, |
|
|
MoonshotAiModelPref: |
|
|
process.env.MOONSHOT_AI_MODEL_PREF || "moonshot-v1-32k", |
|
|
|
|
|
|
|
|
GenericOpenAiBasePath: process.env.GENERIC_OPEN_AI_BASE_PATH, |
|
|
GenericOpenAiModelPref: process.env.GENERIC_OPEN_AI_MODEL_PREF, |
|
|
GenericOpenAiTokenLimit: process.env.GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT, |
|
|
GenericOpenAiKey: !!process.env.GENERIC_OPEN_AI_API_KEY, |
|
|
GenericOpenAiMaxTokens: process.env.GENERIC_OPEN_AI_MAX_TOKENS, |
|
|
|
|
|
AwsBedrockLLMConnectionMethod: |
|
|
process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD || "iam", |
|
|
AwsBedrockLLMAccessKeyId: !!process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, |
|
|
AwsBedrockLLMAccessKey: !!process.env.AWS_BEDROCK_LLM_ACCESS_KEY, |
|
|
AwsBedrockLLMSessionToken: !!process.env.AWS_BEDROCK_LLM_SESSION_TOKEN, |
|
|
AwsBedrockLLMRegion: process.env.AWS_BEDROCK_LLM_REGION, |
|
|
AwsBedrockLLMModel: process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE, |
|
|
AwsBedrockLLMTokenLimit: |
|
|
process.env.AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT || 8192, |
|
|
AwsBedrockLLMMaxOutputTokens: |
|
|
process.env.AWS_BEDROCK_LLM_MAX_OUTPUT_TOKENS || 4096, |
|
|
|
|
|
|
|
|
CohereApiKey: !!process.env.COHERE_API_KEY, |
|
|
CohereModelPref: process.env.COHERE_MODEL_PREF, |
|
|
|
|
|
|
|
|
DeepSeekApiKey: !!process.env.DEEPSEEK_API_KEY, |
|
|
DeepSeekModelPref: process.env.DEEPSEEK_MODEL_PREF, |
|
|
|
|
|
|
|
|
ApipieLLMApiKey: !!process.env.APIPIE_LLM_API_KEY, |
|
|
ApipieLLMModelPref: process.env.APIPIE_LLM_MODEL_PREF, |
|
|
|
|
|
|
|
|
XAIApiKey: !!process.env.XAI_LLM_API_KEY, |
|
|
XAIModelPref: process.env.XAI_LLM_MODEL_PREF, |
|
|
|
|
|
|
|
|
NvidiaNimLLMBasePath: process.env.NVIDIA_NIM_LLM_BASE_PATH, |
|
|
NvidiaNimLLMModelPref: process.env.NVIDIA_NIM_LLM_MODEL_PREF, |
|
|
NvidiaNimLLMTokenLimit: process.env.NVIDIA_NIM_LLM_MODEL_TOKEN_LIMIT, |
|
|
|
|
|
|
|
|
PPIOApiKey: !!process.env.PPIO_API_KEY, |
|
|
PPIOModelPref: process.env.PPIO_MODEL_PREF, |
|
|
|
|
|
|
|
|
DellProAiStudioBasePath: process.env.DPAIS_LLM_BASE_PATH, |
|
|
DellProAiStudioModelPref: process.env.DPAIS_LLM_MODEL_PREF, |
|
|
DellProAiStudioTokenLimit: |
|
|
process.env.DPAIS_LLM_MODEL_TOKEN_LIMIT ?? 4096, |
|
|
|
|
|
|
|
|
CometApiLLMApiKey: !!process.env.COMETAPI_LLM_API_KEY, |
|
|
CometApiLLMModelPref: process.env.COMETAPI_LLM_MODEL_PREF, |
|
|
CometApiLLMTimeout: process.env.COMETAPI_LLM_TIMEOUT_MS, |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
brief: { |
|
|
agent_sql_connections: async function () { |
|
|
const setting = await SystemSettings.get({ |
|
|
label: "agent_sql_connections", |
|
|
}); |
|
|
if (!setting) return []; |
|
|
return safeJsonParse(setting.value, []).map((dbConfig) => { |
|
|
const { connectionString, ...rest } = dbConfig; |
|
|
return rest; |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
getFeatureFlags: async function () { |
|
|
return { |
|
|
experimental_live_file_sync: |
|
|
(await SystemSettings.get({ label: "experimental_live_file_sync" })) |
|
|
?.value === "enabled", |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hubSettings: async function () { |
|
|
try { |
|
|
const hubKey = await this.get({ label: "hub_api_key" }); |
|
|
return { connectionKey: hubKey?.value || null }; |
|
|
} catch (error) { |
|
|
console.error(error.message); |
|
|
return { connectionKey: null }; |
|
|
} |
|
|
}, |
|
|
|
|
|
simpleSSO: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
noLoginRedirect: () => { |
|
|
if (!("SIMPLE_SSO_ENABLED" in process.env)) return null; |
|
|
if (!("SIMPLE_SSO_NO_LOGIN" in process.env)) return null; |
|
|
if (!("SIMPLE_SSO_NO_LOGIN_REDIRECT" in process.env)) return null; |
|
|
|
|
|
try { |
|
|
let url = new URL(process.env.SIMPLE_SSO_NO_LOGIN_REDIRECT); |
|
|
return url.toString(); |
|
|
} catch {} |
|
|
|
|
|
|
|
|
return null; |
|
|
}, |
|
|
}, |
|
|
}; |
|
|
|
|
|
function mergeConnections(existingConnections = [], updates = []) { |
|
|
let updatedConnections = [...existingConnections]; |
|
|
const existingDbIds = existingConnections.map((conn) => conn.database_id); |
|
|
|
|
|
|
|
|
const toRemove = updates |
|
|
.filter((conn) => conn.action === "remove") |
|
|
.map((conn) => conn.database_id); |
|
|
updatedConnections = updatedConnections.filter( |
|
|
(conn) => !toRemove.includes(conn.database_id) |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
updates |
|
|
.filter((conn) => conn.action === "add") |
|
|
.forEach((update) => { |
|
|
if (!update.connectionString) return; |
|
|
|
|
|
|
|
|
if (existingDbIds.includes(update.database_id)) { |
|
|
update.database_id = slugify( |
|
|
`${update.database_id}-${v4().slice(0, 4)}` |
|
|
); |
|
|
} else { |
|
|
update.database_id = slugify(update.database_id); |
|
|
} |
|
|
|
|
|
updatedConnections.push({ |
|
|
engine: update.engine, |
|
|
database_id: update.database_id, |
|
|
connectionString: update.connectionString, |
|
|
}); |
|
|
}); |
|
|
|
|
|
return updatedConnections; |
|
|
} |
|
|
|
|
|
module.exports.SystemSettings = SystemSettings; |
|
|
|