feat(secrets): update readSecret function to accept optional secret ID (#5356)
* feat(secrets): update readSecret function to accept optional secret ID * add secret_id to ConnectionManagerRequestService payload * fix: pass secret_id for Text Completion types --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
@@ -435,6 +435,7 @@ export class ConnectionManagerRequestService {
|
||||
max_tokens: maxTokens,
|
||||
model: profile.model,
|
||||
chat_completion_source: selectedApiMap.source,
|
||||
secret_id: profile['secret-id'],
|
||||
custom_url: profile['api-url'],
|
||||
vertexai_region: profile['api-url'],
|
||||
zai_endpoint: profile['api-url'],
|
||||
@@ -459,6 +460,7 @@ export class ConnectionManagerRequestService {
|
||||
model: profile.model,
|
||||
api_type: selectedApiMap.type,
|
||||
api_server: profile['api-url'],
|
||||
secret_id: profile['secret-id'],
|
||||
...overridePayload,
|
||||
}, {
|
||||
instructName: includeInstruct ? profile.instruct : undefined,
|
||||
|
||||
+47
-32
@@ -5,10 +5,11 @@ import { getConfigValue } from './util.js';
|
||||
/**
|
||||
* Gets the headers for the Mancer API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getMancerHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.MANCER);
|
||||
function getMancerHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.MANCER, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'X-API-KEY': apiKey,
|
||||
@@ -19,10 +20,11 @@ function getMancerHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the TogetherAI API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getTogetherAIHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.TOGETHERAI);
|
||||
function getTogetherAIHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.TOGETHERAI, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -32,10 +34,11 @@ function getTogetherAIHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the InfermaticAI API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getInfermaticAIHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.INFERMATICAI);
|
||||
function getInfermaticAIHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.INFERMATICAI, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -45,10 +48,11 @@ function getInfermaticAIHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the DreamGen API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getDreamGenHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.DREAMGEN);
|
||||
function getDreamGenHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.DREAMGEN, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -58,10 +62,11 @@ function getDreamGenHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the OpenRouter API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getOpenRouterHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.OPENROUTER);
|
||||
function getOpenRouterHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.OPENROUTER, secretId);
|
||||
const baseHeaders = { ...OPENROUTER_HEADERS };
|
||||
|
||||
return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;
|
||||
@@ -70,10 +75,11 @@ function getOpenRouterHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the vLLM API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getVllmHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.VLLM);
|
||||
function getVllmHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.VLLM, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -83,10 +89,11 @@ function getVllmHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the Aphrodite API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getAphroditeHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.APHRODITE);
|
||||
function getAphroditeHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.APHRODITE, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'X-API-KEY': apiKey,
|
||||
@@ -97,10 +104,11 @@ function getAphroditeHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the Tabby API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getTabbyHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.TABBY);
|
||||
function getTabbyHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.TABBY, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'x-api-key': apiKey,
|
||||
@@ -111,10 +119,11 @@ function getTabbyHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the LlamaCPP API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getLlamaCppHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.LLAMACPP);
|
||||
function getLlamaCppHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.LLAMACPP, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -123,11 +132,12 @@ function getLlamaCppHeaders(directories) {
|
||||
|
||||
/**
|
||||
* Gets the headers for the Ooba API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getOobaHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.OOBA);
|
||||
function getOobaHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.OOBA, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -137,10 +147,11 @@ function getOobaHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the KoboldCpp API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getKoboldCppHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.KOBOLDCPP);
|
||||
function getKoboldCppHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.KOBOLDCPP, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -150,10 +161,11 @@ function getKoboldCppHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the Featherless API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getFeatherlessHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.FEATHERLESS);
|
||||
function getFeatherlessHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.FEATHERLESS, secretId);
|
||||
const baseHeaders = { ...FEATHERLESS_HEADERS };
|
||||
|
||||
return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;
|
||||
@@ -162,10 +174,11 @@ function getFeatherlessHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the HuggingFace API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getHuggingFaceHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.HUGGINGFACE);
|
||||
function getHuggingFaceHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.HUGGINGFACE, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -175,10 +188,11 @@ function getHuggingFaceHeaders(directories) {
|
||||
/**
|
||||
* Gets the headers for the Generic text completion API.
|
||||
* @param {import('./users.js').UserDirectoryList} directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
|
||||
* @returns {object} Headers for the request
|
||||
*/
|
||||
function getGenericHeaders(directories) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.GENERIC);
|
||||
function getGenericHeaders(directories, secretId = null) {
|
||||
const apiKey = readSecret(directories, SECRET_KEYS.GENERIC, secretId);
|
||||
|
||||
return apiKey ? ({
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
@@ -202,7 +216,7 @@ export function getOverrideHeaders(urlHost) {
|
||||
* @param {string|null} server API server for new request
|
||||
*/
|
||||
export function setAdditionalHeaders(request, args, server) {
|
||||
setAdditionalHeadersByType(args.headers, request.body.api_type, server, request.user.directories);
|
||||
setAdditionalHeadersByType(args.headers, request.body.api_type, server, request.user.directories, request.body.secret_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,8 +225,9 @@ export function setAdditionalHeaders(request, args, server) {
|
||||
* @param {string} type API type
|
||||
* @param {string|null} server API server for new request
|
||||
* @param {import('./users.js').UserDirectoryList} directories User directories
|
||||
* @param {string|null} secretId Secret ID for the request (optional, used for some API types to determine which secret to use)
|
||||
*/
|
||||
export function setAdditionalHeadersByType(requestHeaders, type, server, directories) {
|
||||
export function setAdditionalHeadersByType(requestHeaders, type, server, directories, secretId = null) {
|
||||
const headerGetters = {
|
||||
[TEXTGEN_TYPES.MANCER]: getMancerHeaders,
|
||||
[TEXTGEN_TYPES.VLLM]: getVllmHeaders,
|
||||
@@ -231,7 +246,7 @@ export function setAdditionalHeadersByType(requestHeaders, type, server, directo
|
||||
};
|
||||
|
||||
const getHeaders = headerGetters[type];
|
||||
const headers = getHeaders ? getHeaders(directories) : {};
|
||||
const headers = getHeaders ? getHeaders(directories, secretId) : {};
|
||||
|
||||
if (typeof server === 'string' && server.length > 0) {
|
||||
try {
|
||||
|
||||
@@ -208,7 +208,7 @@ function setJsonObjectFormat(bodyParams, messages, jsonSchema) {
|
||||
*/
|
||||
async function sendClaudeRequest(request, response) {
|
||||
const apiUrl = new URL(request.body.reverse_proxy || API_CLAUDE).toString();
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE);
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE, request.body.secret_id);
|
||||
const divider = '-'.repeat(process.stdout.columns);
|
||||
|
||||
if (!apiKey) {
|
||||
@@ -425,7 +425,7 @@ async function sendMakerSuiteRequest(request, response) {
|
||||
}
|
||||
} else {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_MAKERSUITE);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE, request.body.secret_id);
|
||||
|
||||
if (!request.body.reverse_proxy && !apiKey) {
|
||||
console.warn(`${apiName} API key is missing.`);
|
||||
@@ -641,7 +641,7 @@ async function sendMakerSuiteRequest(request, response) {
|
||||
} else if (authType === 'full') {
|
||||
// For Full mode (service account authentication), use project-specific URL
|
||||
// Get project ID from Service Account JSON
|
||||
const serviceAccountJson = readSecret(request.user.directories, SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT);
|
||||
const serviceAccountJson = readSecret(request.user.directories, SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT, request.body.secret_id);
|
||||
if (!serviceAccountJson) {
|
||||
console.warn('Vertex AI Service Account JSON is missing.');
|
||||
return response.status(400).send({ error: true });
|
||||
@@ -742,7 +742,7 @@ async function sendMakerSuiteRequest(request, response) {
|
||||
async function sendAI21Request(request, response) {
|
||||
if (!request.body) return response.sendStatus(400);
|
||||
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AI21);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AI21, request.body.secret_id);
|
||||
if (!apiKey) {
|
||||
console.warn('AI21 API key is missing.');
|
||||
return response.status(400).send({ error: true });
|
||||
@@ -822,7 +822,7 @@ async function sendAI21Request(request, response) {
|
||||
*/
|
||||
async function sendMistralAIRequest(request, response) {
|
||||
const apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI, request.body.secret_id);
|
||||
|
||||
if (!apiKey) {
|
||||
console.warn('MistralAI API key is missing.');
|
||||
@@ -911,7 +911,7 @@ async function sendMistralAIRequest(request, response) {
|
||||
* @param {express.Response} response Express response
|
||||
*/
|
||||
async function sendCohereRequest(request, response) {
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE, request.body.secret_id);
|
||||
const controller = new AbortController();
|
||||
request.socket.removeAllListeners('close');
|
||||
request.socket.on('close', function () {
|
||||
@@ -1012,7 +1012,7 @@ async function sendCohereRequest(request, response) {
|
||||
*/
|
||||
async function sendDeepSeekRequest(request, response) {
|
||||
const apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK).toString();
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK, request.body.secret_id);
|
||||
|
||||
if (!apiKey && !request.body.reverse_proxy) {
|
||||
console.warn('DeepSeek API key is missing.');
|
||||
@@ -1122,7 +1122,7 @@ async function sendDeepSeekRequest(request, response) {
|
||||
*/
|
||||
async function sendXaiRequest(request, response) {
|
||||
const apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);
|
||||
const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI, request.body.secret_id);
|
||||
|
||||
if (!apiKey && !request.body.reverse_proxy) {
|
||||
console.warn('xAI API key is missing.');
|
||||
@@ -1228,7 +1228,7 @@ async function sendXaiRequest(request, response) {
|
||||
*/
|
||||
async function sendAimlapiRequest(request, response) {
|
||||
const apiUrl = API_AIMLAPI;
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI, request.body.secret_id);
|
||||
|
||||
if (!apiKey) {
|
||||
console.warn('AI/ML API key is missing.');
|
||||
@@ -1333,7 +1333,7 @@ async function sendAimlapiRequest(request, response) {
|
||||
*/
|
||||
async function sendElectronHubRequest(request, response) {
|
||||
const apiUrl = API_ELECTRONHUB;
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB, request.body.secret_id);
|
||||
|
||||
if (!apiKey) {
|
||||
console.warn('Electron Hub key is missing.');
|
||||
@@ -1445,7 +1445,7 @@ async function sendElectronHubRequest(request, response) {
|
||||
*/
|
||||
async function sendChutesRequest(request, response) {
|
||||
const apiUrl = API_CHUTES;
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES, request.body.secret_id);
|
||||
|
||||
if (!apiKey) {
|
||||
console.warn('Chutes key is missing.');
|
||||
@@ -1547,7 +1547,7 @@ async function sendChutesRequest(request, response) {
|
||||
async function sendAzureOpenAIRequest(request, response) {
|
||||
// 1. GATHER & VALIDATE SETTINGS
|
||||
const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI, request.body.secret_id);
|
||||
if (!azure_base_url || !azure_deployment_name || !azure_api_version || !apiKey) {
|
||||
return response.status(400).send({
|
||||
error: {
|
||||
@@ -1646,74 +1646,74 @@ router.post('/status', async function (request, statusResponse) {
|
||||
|
||||
if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {
|
||||
apiUrl = 'https://openrouter.ai/api/v1';
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER, request.body.secret_id);
|
||||
// OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests
|
||||
headers = { ...OPENROUTER_HEADERS };
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
|
||||
apiUrl = request.body.custom_url;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM, request.body.secret_id);
|
||||
headers = {};
|
||||
mergeObjectWithYaml(headers, request.body.custom_include_headers);
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE) {
|
||||
apiUrl = API_COHERE_V1;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CHUTES) {
|
||||
apiUrl = API_CHUTES;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ELECTRONHUB) {
|
||||
apiUrl = API_ELECTRONHUB;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {
|
||||
apiUrl = API_NANOGPT;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT, request.body.secret_id);
|
||||
headers = {};
|
||||
queryParams = { detailed: true };
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', '')).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AIMLAPI) {
|
||||
apiUrl = API_AIMLAPI;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI, request.body.secret_id);
|
||||
headers = { ...AIMLAPI_HEADERS };
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {
|
||||
apiUrl = 'https://gen.pollinations.ai/text';
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {
|
||||
apiUrl = API_GROQ;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {
|
||||
apiUrl = API_COMETAPI;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI, request.body.secret_id);
|
||||
headers = {};
|
||||
throw new Error('This provider is temporarily disabled.');
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {
|
||||
apiUrl = API_FIREWORKS;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS, request.body.secret_id);
|
||||
headers = {};
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE, request.body.secret_id);
|
||||
apiUrl = trimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE);
|
||||
const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');
|
||||
const modelsUrl = !apiKey && request.body.reverse_proxy
|
||||
@@ -1750,7 +1750,7 @@ router.post('/status', async function (request, statusResponse) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AZURE_OPENAI) {
|
||||
const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI);
|
||||
const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI, request.body.secret_id);
|
||||
|
||||
// 1) Validate configuration from the frontend
|
||||
if (!apiKey || !azure_base_url || !azure_deployment_name || !azure_api_version) {
|
||||
@@ -1830,7 +1830,7 @@ router.post('/status', async function (request, statusResponse) {
|
||||
const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN
|
||||
? API_SILICONFLOW_CN : API_SILICONFLOW;
|
||||
apiUrl = defaultApiUrl;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW, request.body.secret_id);
|
||||
headers = {};
|
||||
queryParams = { type: 'text', sub_type: 'chat' };
|
||||
} else {
|
||||
@@ -2053,7 +2053,7 @@ router.post('/generate', async function (request, response) {
|
||||
|
||||
if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
logprobs: request.body.logprobs,
|
||||
@@ -2073,7 +2073,7 @@ router.post('/generate', async function (request, response) {
|
||||
embedOpenRouterMedia(request.body.messages, { audio: true, video: false });
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {
|
||||
apiUrl = 'https://openrouter.ai/api/v1';
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER, request.body.secret_id);
|
||||
// OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests
|
||||
headers = { ...OPENROUTER_HEADERS };
|
||||
const includeReasoning = Boolean(request.body.include_reasoning);
|
||||
@@ -2161,7 +2161,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
|
||||
apiUrl = request.body.custom_url;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
logprobs: request.body.logprobs,
|
||||
@@ -2179,7 +2179,7 @@ router.post('/generate', async function (request, response) {
|
||||
embedOpenRouterMedia(request.body.messages, { audio: true, video: false });
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.PERPLEXITY) {
|
||||
apiUrl = API_PERPLEXITY;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
reasoning_effort: request.body.reasoning_effort,
|
||||
@@ -2195,7 +2195,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {
|
||||
apiUrl = API_GROQ;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {};
|
||||
if (request.body.json_schema) {
|
||||
@@ -2211,7 +2211,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {
|
||||
apiUrl = API_FIREWORKS;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {};
|
||||
if (request.body.json_schema) {
|
||||
@@ -2227,7 +2227,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {
|
||||
apiUrl = API_NANOGPT;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {};
|
||||
if (request.body.enable_web_search && !/:online$/.test(request.body.model)) {
|
||||
@@ -2256,7 +2256,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {
|
||||
apiUrl = API_POLLINATIONS;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
reasoning_effort: request.body.reasoning_effort,
|
||||
@@ -2272,7 +2272,7 @@ router.post('/generate', async function (request, response) {
|
||||
}
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
thinking: {
|
||||
@@ -2284,7 +2284,7 @@ router.post('/generate', async function (request, response) {
|
||||
: addAssistantPrefix(request.body.messages, [], 'partial');
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {
|
||||
apiUrl = API_COMETAPI;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {
|
||||
reasoning_effort: request.body.reasoning_effort,
|
||||
@@ -2293,7 +2293,7 @@ router.post('/generate', async function (request, response) {
|
||||
} else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ZAI) {
|
||||
const defaultApiUrl = request.body.zai_endpoint === ZAI_ENDPOINT.CODING ? API_ZAI_CODING : API_ZAI_COMMON;
|
||||
apiUrl = new URL(request.body.reverse_proxy || defaultApiUrl).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.ZAI);
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.ZAI, request.body.secret_id);
|
||||
headers = {
|
||||
'Accept-Language': 'en-US,en',
|
||||
};
|
||||
@@ -2309,7 +2309,7 @@ router.post('/generate', async function (request, response) {
|
||||
const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN
|
||||
? API_SILICONFLOW_CN : API_SILICONFLOW;
|
||||
apiUrl = defaultApiUrl;
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);
|
||||
apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW, request.body.secret_id);
|
||||
headers = {};
|
||||
bodyParams = {};
|
||||
if (request.body.json_schema) {
|
||||
|
||||
@@ -441,10 +441,11 @@ export function deleteSecret(directories, key) {
|
||||
* Reads a secret from the secrets file
|
||||
* @param {import('../users.js').UserDirectoryList} directories User directories
|
||||
* @param {string} key Secret key
|
||||
* @param {string?} id Secret ID (optional)
|
||||
* @returns {string} Secret value
|
||||
*/
|
||||
export function readSecret(directories, key) {
|
||||
return new SecretManager(directories).readSecret(key, null);
|
||||
export function readSecret(directories, key, id = null) {
|
||||
return new SecretManager(directories).readSecret(key, id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user