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>

ff1ca1412a0a39157727a476eb67af2515d27563

lunar sheep <102860538+dylenyedc@users.noreply.github.com>

Signed
4 files changed, +95 -77Ignore whitespace
public/scripts/extensions/shared.js+2 -0
@@ -435,6 +435,7 @@ export class ConnectionManagerRequestService {
435 max_tokens: maxTokens,435 max_tokens: maxTokens,
436 model: profile.model,436 model: profile.model,
437 chat_completion_source: selectedApiMap.source,437 chat_completion_source: selectedApiMap.source,
438 secret_id: profile['secret-id'],
438 custom_url: profile['api-url'],439 custom_url: profile['api-url'],
439 vertexai_region: profile['api-url'],440 vertexai_region: profile['api-url'],
440 zai_endpoint: profile['api-url'],441 zai_endpoint: profile['api-url'],
@@ -459,6 +460,7 @@ export class ConnectionManagerRequestService {
459 model: profile.model,460 model: profile.model,
460 api_type: selectedApiMap.type,461 api_type: selectedApiMap.type,
461 api_server: profile['api-url'],462 api_server: profile['api-url'],
463 secret_id: profile['secret-id'],
462 ...overridePayload,464 ...overridePayload,
463 }, {465 }, {
464 instructName: includeInstruct ? profile.instruct : undefined,466 instructName: includeInstruct ? profile.instruct : undefined,
src/additional-headers.js+47 -32
@@ -5,10 +5,11 @@ import { getConfigValue } from './util.js';
5/**5/**
6 * Gets the headers for the Mancer API.6 * Gets the headers for the Mancer API.
7 * @param {import('./users.js').UserDirectoryList} directories User directories7 * @param {import('./users.js').UserDirectoryList} directories User directories
8 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
8 * @returns {object} Headers for the request9 * @returns {object} Headers for the request
9 */10 */
10function getMancerHeaders(directories) {11function getMancerHeaders(directories, secretId = null) {
11 const apiKey = readSecret(directories, SECRET_KEYS.MANCER);12 const apiKey = readSecret(directories, SECRET_KEYS.MANCER, secretId);
1213
13 return apiKey ? ({14 return apiKey ? ({
14 'X-API-KEY': apiKey,15 'X-API-KEY': apiKey,
@@ -19,10 +20,11 @@ function getMancerHeaders(directories) {
19/**20/**
20 * Gets the headers for the TogetherAI API.21 * Gets the headers for the TogetherAI API.
21 * @param {import('./users.js').UserDirectoryList} directories User directories22 * @param {import('./users.js').UserDirectoryList} directories User directories
23 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
22 * @returns {object} Headers for the request24 * @returns {object} Headers for the request
23 */25 */
24function getTogetherAIHeaders(directories) {26function getTogetherAIHeaders(directories, secretId = null) {
25 const apiKey = readSecret(directories, SECRET_KEYS.TOGETHERAI);27 const apiKey = readSecret(directories, SECRET_KEYS.TOGETHERAI, secretId);
2628
27 return apiKey ? ({29 return apiKey ? ({
28 'Authorization': `Bearer ${apiKey}`,30 'Authorization': `Bearer ${apiKey}`,
@@ -32,10 +34,11 @@ function getTogetherAIHeaders(directories) {
32/**34/**
33 * Gets the headers for the InfermaticAI API.35 * Gets the headers for the InfermaticAI API.
34 * @param {import('./users.js').UserDirectoryList} directories User directories36 * @param {import('./users.js').UserDirectoryList} directories User directories
37 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
35 * @returns {object} Headers for the request38 * @returns {object} Headers for the request
36 */39 */
37function getInfermaticAIHeaders(directories) {40function getInfermaticAIHeaders(directories, secretId = null) {
38 const apiKey = readSecret(directories, SECRET_KEYS.INFERMATICAI);41 const apiKey = readSecret(directories, SECRET_KEYS.INFERMATICAI, secretId);
3942
40 return apiKey ? ({43 return apiKey ? ({
41 'Authorization': `Bearer ${apiKey}`,44 'Authorization': `Bearer ${apiKey}`,
@@ -45,10 +48,11 @@ function getInfermaticAIHeaders(directories) {
45/**48/**
46 * Gets the headers for the DreamGen API.49 * Gets the headers for the DreamGen API.
47 * @param {import('./users.js').UserDirectoryList} directories User directories50 * @param {import('./users.js').UserDirectoryList} directories User directories
51 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
48 * @returns {object} Headers for the request52 * @returns {object} Headers for the request
49 */53 */
50function getDreamGenHeaders(directories) {54function getDreamGenHeaders(directories, secretId = null) {
51 const apiKey = readSecret(directories, SECRET_KEYS.DREAMGEN);55 const apiKey = readSecret(directories, SECRET_KEYS.DREAMGEN, secretId);
5256
53 return apiKey ? ({57 return apiKey ? ({
54 'Authorization': `Bearer ${apiKey}`,58 'Authorization': `Bearer ${apiKey}`,
@@ -58,10 +62,11 @@ function getDreamGenHeaders(directories) {
58/**62/**
59 * Gets the headers for the OpenRouter API.63 * Gets the headers for the OpenRouter API.
60 * @param {import('./users.js').UserDirectoryList} directories User directories64 * @param {import('./users.js').UserDirectoryList} directories User directories
65 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
61 * @returns {object} Headers for the request66 * @returns {object} Headers for the request
62 */67 */
63function getOpenRouterHeaders(directories) {68function getOpenRouterHeaders(directories, secretId = null) {
64 const apiKey = readSecret(directories, SECRET_KEYS.OPENROUTER);69 const apiKey = readSecret(directories, SECRET_KEYS.OPENROUTER, secretId);
65 const baseHeaders = { ...OPENROUTER_HEADERS };70 const baseHeaders = { ...OPENROUTER_HEADERS };
6671
67 return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;72 return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;
@@ -70,10 +75,11 @@ function getOpenRouterHeaders(directories) {
70/**75/**
71 * Gets the headers for the vLLM API.76 * Gets the headers for the vLLM API.
72 * @param {import('./users.js').UserDirectoryList} directories User directories77 * @param {import('./users.js').UserDirectoryList} directories User directories
78 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
73 * @returns {object} Headers for the request79 * @returns {object} Headers for the request
74 */80 */
75function getVllmHeaders(directories) {81function getVllmHeaders(directories, secretId = null) {
76 const apiKey = readSecret(directories, SECRET_KEYS.VLLM);82 const apiKey = readSecret(directories, SECRET_KEYS.VLLM, secretId);
7783
78 return apiKey ? ({84 return apiKey ? ({
79 'Authorization': `Bearer ${apiKey}`,85 'Authorization': `Bearer ${apiKey}`,
@@ -83,10 +89,11 @@ function getVllmHeaders(directories) {
83/**89/**
84 * Gets the headers for the Aphrodite API.90 * Gets the headers for the Aphrodite API.
85 * @param {import('./users.js').UserDirectoryList} directories User directories91 * @param {import('./users.js').UserDirectoryList} directories User directories
92 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
86 * @returns {object} Headers for the request93 * @returns {object} Headers for the request
87 */94 */
88function getAphroditeHeaders(directories) {95function getAphroditeHeaders(directories, secretId = null) {
89 const apiKey = readSecret(directories, SECRET_KEYS.APHRODITE);96 const apiKey = readSecret(directories, SECRET_KEYS.APHRODITE, secretId);
9097
91 return apiKey ? ({98 return apiKey ? ({
92 'X-API-KEY': apiKey,99 'X-API-KEY': apiKey,
@@ -97,10 +104,11 @@ function getAphroditeHeaders(directories) {
97/**104/**
98 * Gets the headers for the Tabby API.105 * Gets the headers for the Tabby API.
99 * @param {import('./users.js').UserDirectoryList} directories User directories106 * @param {import('./users.js').UserDirectoryList} directories User directories
107 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
100 * @returns {object} Headers for the request108 * @returns {object} Headers for the request
101 */109 */
102function getTabbyHeaders(directories) {110function getTabbyHeaders(directories, secretId = null) {
103 const apiKey = readSecret(directories, SECRET_KEYS.TABBY);111 const apiKey = readSecret(directories, SECRET_KEYS.TABBY, secretId);
104112
105 return apiKey ? ({113 return apiKey ? ({
106 'x-api-key': apiKey,114 'x-api-key': apiKey,
@@ -111,10 +119,11 @@ function getTabbyHeaders(directories) {
111/**119/**
112 * Gets the headers for the LlamaCPP API.120 * Gets the headers for the LlamaCPP API.
113 * @param {import('./users.js').UserDirectoryList} directories User directories121 * @param {import('./users.js').UserDirectoryList} directories User directories
122 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
114 * @returns {object} Headers for the request123 * @returns {object} Headers for the request
115 */124 */
116function getLlamaCppHeaders(directories) {125function getLlamaCppHeaders(directories, secretId = null) {
117 const apiKey = readSecret(directories, SECRET_KEYS.LLAMACPP);126 const apiKey = readSecret(directories, SECRET_KEYS.LLAMACPP, secretId);
118127
119 return apiKey ? ({128 return apiKey ? ({
120 'Authorization': `Bearer ${apiKey}`,129 'Authorization': `Bearer ${apiKey}`,
@@ -123,11 +132,12 @@ function getLlamaCppHeaders(directories) {
123132
124/**133/**
125 * Gets the headers for the Ooba API.134 * Gets the headers for the Ooba API.
126 * @param {import('./users.js').UserDirectoryList} directories135 * @param {import('./users.js').UserDirectoryList} directories User directories
136 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
127 * @returns {object} Headers for the request137 * @returns {object} Headers for the request
128 */138 */
129function getOobaHeaders(directories) {139function getOobaHeaders(directories, secretId = null) {
130 const apiKey = readSecret(directories, SECRET_KEYS.OOBA);140 const apiKey = readSecret(directories, SECRET_KEYS.OOBA, secretId);
131141
132 return apiKey ? ({142 return apiKey ? ({
133 'Authorization': `Bearer ${apiKey}`,143 'Authorization': `Bearer ${apiKey}`,
@@ -137,10 +147,11 @@ function getOobaHeaders(directories) {
137/**147/**
138 * Gets the headers for the KoboldCpp API.148 * Gets the headers for the KoboldCpp API.
139 * @param {import('./users.js').UserDirectoryList} directories149 * @param {import('./users.js').UserDirectoryList} directories
150 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
140 * @returns {object} Headers for the request151 * @returns {object} Headers for the request
141 */152 */
142function getKoboldCppHeaders(directories) {153function getKoboldCppHeaders(directories, secretId = null) {
143 const apiKey = readSecret(directories, SECRET_KEYS.KOBOLDCPP);154 const apiKey = readSecret(directories, SECRET_KEYS.KOBOLDCPP, secretId);
144155
145 return apiKey ? ({156 return apiKey ? ({
146 'Authorization': `Bearer ${apiKey}`,157 'Authorization': `Bearer ${apiKey}`,
@@ -150,10 +161,11 @@ function getKoboldCppHeaders(directories) {
150/**161/**
151 * Gets the headers for the Featherless API.162 * Gets the headers for the Featherless API.
152 * @param {import('./users.js').UserDirectoryList} directories163 * @param {import('./users.js').UserDirectoryList} directories
164 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
153 * @returns {object} Headers for the request165 * @returns {object} Headers for the request
154 */166 */
155function getFeatherlessHeaders(directories) {167function getFeatherlessHeaders(directories, secretId = null) {
156 const apiKey = readSecret(directories, SECRET_KEYS.FEATHERLESS);168 const apiKey = readSecret(directories, SECRET_KEYS.FEATHERLESS, secretId);
157 const baseHeaders = { ...FEATHERLESS_HEADERS };169 const baseHeaders = { ...FEATHERLESS_HEADERS };
158170
159 return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;171 return apiKey ? Object.assign(baseHeaders, { 'Authorization': `Bearer ${apiKey}` }) : baseHeaders;
@@ -162,10 +174,11 @@ function getFeatherlessHeaders(directories) {
162/**174/**
163 * Gets the headers for the HuggingFace API.175 * Gets the headers for the HuggingFace API.
164 * @param {import('./users.js').UserDirectoryList} directories176 * @param {import('./users.js').UserDirectoryList} directories
177 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
165 * @returns {object} Headers for the request178 * @returns {object} Headers for the request
166 */179 */
167function getHuggingFaceHeaders(directories) {180function getHuggingFaceHeaders(directories, secretId = null) {
168 const apiKey = readSecret(directories, SECRET_KEYS.HUGGINGFACE);181 const apiKey = readSecret(directories, SECRET_KEYS.HUGGINGFACE, secretId);
169182
170 return apiKey ? ({183 return apiKey ? ({
171 'Authorization': `Bearer ${apiKey}`,184 'Authorization': `Bearer ${apiKey}`,
@@ -175,10 +188,11 @@ function getHuggingFaceHeaders(directories) {
175/**188/**
176 * Gets the headers for the Generic text completion API.189 * Gets the headers for the Generic text completion API.
177 * @param {import('./users.js').UserDirectoryList} directories190 * @param {import('./users.js').UserDirectoryList} directories
191 * @param {string|null} secretId Secret ID for the request (optional, used to determine which secret to use)
178 * @returns {object} Headers for the request192 * @returns {object} Headers for the request
179 */193 */
180function getGenericHeaders(directories) {194function getGenericHeaders(directories, secretId = null) {
181 const apiKey = readSecret(directories, SECRET_KEYS.GENERIC);195 const apiKey = readSecret(directories, SECRET_KEYS.GENERIC, secretId);
182196
183 return apiKey ? ({197 return apiKey ? ({
184 'Authorization': `Bearer ${apiKey}`,198 'Authorization': `Bearer ${apiKey}`,
@@ -202,7 +216,7 @@ export function getOverrideHeaders(urlHost) {
202 * @param {string|null} server API server for new request216 * @param {string|null} server API server for new request
203 */217 */
204export function setAdditionalHeaders(request, args, server) {218export function setAdditionalHeaders(request, args, server) {
205 setAdditionalHeadersByType(args.headers, request.body.api_type, server, request.user.directories);219 setAdditionalHeadersByType(args.headers, request.body.api_type, server, request.user.directories, request.body.secret_id);
206}220}
207221
208/**222/**
@@ -211,8 +225,9 @@ export function setAdditionalHeaders(request, args, server) {
211 * @param {string} type API type225 * @param {string} type API type
212 * @param {string|null} server API server for new request226 * @param {string|null} server API server for new request
213 * @param {import('./users.js').UserDirectoryList} directories User directories227 * @param {import('./users.js').UserDirectoryList} directories User directories
228 * @param {string|null} secretId Secret ID for the request (optional, used for some API types to determine which secret to use)
214 */229 */
215export function setAdditionalHeadersByType(requestHeaders, type, server, directories) {230export function setAdditionalHeadersByType(requestHeaders, type, server, directories, secretId = null) {
216 const headerGetters = {231 const headerGetters = {
217 [TEXTGEN_TYPES.MANCER]: getMancerHeaders,232 [TEXTGEN_TYPES.MANCER]: getMancerHeaders,
218 [TEXTGEN_TYPES.VLLM]: getVllmHeaders,233 [TEXTGEN_TYPES.VLLM]: getVllmHeaders,
@@ -231,7 +246,7 @@ export function setAdditionalHeadersByType(requestHeaders, type, server, directo
231 };246 };
232247
233 const getHeaders = headerGetters[type];248 const getHeaders = headerGetters[type];
234 const headers = getHeaders ? getHeaders(directories) : {};249 const headers = getHeaders ? getHeaders(directories, secretId) : {};
235250
236 if (typeof server === 'string' && server.length > 0) {251 if (typeof server === 'string' && server.length > 0) {
237 try {252 try {
src/endpoints/backends/chat-completions.js+43 -43
@@ -208,7 +208,7 @@ function setJsonObjectFormat(bodyParams, messages, jsonSchema) {
208 */208 */
209async function sendClaudeRequest(request, response) {209async function sendClaudeRequest(request, response) {
210 const apiUrl = new URL(request.body.reverse_proxy || API_CLAUDE).toString();210 const apiUrl = new URL(request.body.reverse_proxy || API_CLAUDE).toString();
211 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE);211 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE, request.body.secret_id);
212 const divider = '-'.repeat(process.stdout.columns);212 const divider = '-'.repeat(process.stdout.columns);
213213
214 if (!apiKey) {214 if (!apiKey) {
@@ -425,7 +425,7 @@ async function sendMakerSuiteRequest(request, response) {
425 }425 }
426 } else {426 } else {
427 apiUrl = new URL(request.body.reverse_proxy || API_MAKERSUITE);427 apiUrl = new URL(request.body.reverse_proxy || API_MAKERSUITE);
428 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);428 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE, request.body.secret_id);
429429
430 if (!request.body.reverse_proxy && !apiKey) {430 if (!request.body.reverse_proxy && !apiKey) {
431 console.warn(`${apiName} API key is missing.`);431 console.warn(`${apiName} API key is missing.`);
@@ -641,7 +641,7 @@ async function sendMakerSuiteRequest(request, response) {
641 } else if (authType === 'full') {641 } else if (authType === 'full') {
642 // For Full mode (service account authentication), use project-specific URL642 // For Full mode (service account authentication), use project-specific URL
643 // Get project ID from Service Account JSON643 // Get project ID from Service Account JSON
644 const serviceAccountJson = readSecret(request.user.directories, SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT);644 const serviceAccountJson = readSecret(request.user.directories, SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT, request.body.secret_id);
645 if (!serviceAccountJson) {645 if (!serviceAccountJson) {
646 console.warn('Vertex AI Service Account JSON is missing.');646 console.warn('Vertex AI Service Account JSON is missing.');
647 return response.status(400).send({ error: true });647 return response.status(400).send({ error: true });
@@ -742,7 +742,7 @@ async function sendMakerSuiteRequest(request, response) {
742async function sendAI21Request(request, response) {742async function sendAI21Request(request, response) {
743 if (!request.body) return response.sendStatus(400);743 if (!request.body) return response.sendStatus(400);
744744
745 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AI21);745 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AI21, request.body.secret_id);
746 if (!apiKey) {746 if (!apiKey) {
747 console.warn('AI21 API key is missing.');747 console.warn('AI21 API key is missing.');
748 return response.status(400).send({ error: true });748 return response.status(400).send({ error: true });
@@ -822,7 +822,7 @@ async function sendAI21Request(request, response) {
822 */822 */
823async function sendMistralAIRequest(request, response) {823async function sendMistralAIRequest(request, response) {
824 const apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();824 const apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();
825 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);825 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI, request.body.secret_id);
826826
827 if (!apiKey) {827 if (!apiKey) {
828 console.warn('MistralAI API key is missing.');828 console.warn('MistralAI API key is missing.');
@@ -911,7 +911,7 @@ async function sendMistralAIRequest(request, response) {
911 * @param {express.Response} response Express response911 * @param {express.Response} response Express response
912 */912 */
913async function sendCohereRequest(request, response) {913async function sendCohereRequest(request, response) {
914 const apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);914 const apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE, request.body.secret_id);
915 const controller = new AbortController();915 const controller = new AbortController();
916 request.socket.removeAllListeners('close');916 request.socket.removeAllListeners('close');
917 request.socket.on('close', function () {917 request.socket.on('close', function () {
@@ -1012,7 +1012,7 @@ async function sendCohereRequest(request, response) {
1012 */1012 */
1013async function sendDeepSeekRequest(request, response) {1013async function sendDeepSeekRequest(request, response) {
1014 const apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK).toString();1014 const apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK).toString();
1015 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);1015 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK, request.body.secret_id);
10161016
1017 if (!apiKey && !request.body.reverse_proxy) {1017 if (!apiKey && !request.body.reverse_proxy) {
1018 console.warn('DeepSeek API key is missing.');1018 console.warn('DeepSeek API key is missing.');
@@ -1122,7 +1122,7 @@ async function sendDeepSeekRequest(request, response) {
1122 */1122 */
1123async function sendXaiRequest(request, response) {1123async function sendXaiRequest(request, response) {
1124 const apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();1124 const apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();
1125 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);1125 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI, request.body.secret_id);
11261126
1127 if (!apiKey && !request.body.reverse_proxy) {1127 if (!apiKey && !request.body.reverse_proxy) {
1128 console.warn('xAI API key is missing.');1128 console.warn('xAI API key is missing.');
@@ -1228,7 +1228,7 @@ async function sendXaiRequest(request, response) {
1228 */1228 */
1229async function sendAimlapiRequest(request, response) {1229async function sendAimlapiRequest(request, response) {
1230 const apiUrl = API_AIMLAPI;1230 const apiUrl = API_AIMLAPI;
1231 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI);1231 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI, request.body.secret_id);
12321232
1233 if (!apiKey) {1233 if (!apiKey) {
1234 console.warn('AI/ML API key is missing.');1234 console.warn('AI/ML API key is missing.');
@@ -1333,7 +1333,7 @@ async function sendAimlapiRequest(request, response) {
1333 */1333 */
1334async function sendElectronHubRequest(request, response) {1334async function sendElectronHubRequest(request, response) {
1335 const apiUrl = API_ELECTRONHUB;1335 const apiUrl = API_ELECTRONHUB;
1336 const apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB);1336 const apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB, request.body.secret_id);
13371337
1338 if (!apiKey) {1338 if (!apiKey) {
1339 console.warn('Electron Hub key is missing.');1339 console.warn('Electron Hub key is missing.');
@@ -1445,7 +1445,7 @@ async function sendElectronHubRequest(request, response) {
1445 */1445 */
1446async function sendChutesRequest(request, response) {1446async function sendChutesRequest(request, response) {
1447 const apiUrl = API_CHUTES;1447 const apiUrl = API_CHUTES;
1448 const apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES);1448 const apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES, request.body.secret_id);
14491449
1450 if (!apiKey) {1450 if (!apiKey) {
1451 console.warn('Chutes key is missing.');1451 console.warn('Chutes key is missing.');
@@ -1547,7 +1547,7 @@ async function sendChutesRequest(request, response) {
1547async function sendAzureOpenAIRequest(request, response) {1547async function sendAzureOpenAIRequest(request, response) {
1548 // 1. GATHER & VALIDATE SETTINGS1548 // 1. GATHER & VALIDATE SETTINGS
1549 const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;1549 const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;
1550 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI);1550 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI, request.body.secret_id);
1551 if (!azure_base_url || !azure_deployment_name || !azure_api_version || !apiKey) {1551 if (!azure_base_url || !azure_deployment_name || !azure_api_version || !apiKey) {
1552 return response.status(400).send({1552 return response.status(400).send({
1553 error: {1553 error: {
@@ -1646,74 +1646,74 @@ router.post('/status', async function (request, statusResponse) {
16461646
1647 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {1647 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
1648 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();1648 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
1649 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);1649 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI, request.body.secret_id);
1650 headers = {};1650 headers = {};
1651 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {1651 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {
1652 apiUrl = 'https://openrouter.ai/api/v1';1652 apiUrl = 'https://openrouter.ai/api/v1';
1653 apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);1653 apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER, request.body.secret_id);
1654 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests1654 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests
1655 headers = { ...OPENROUTER_HEADERS };1655 headers = { ...OPENROUTER_HEADERS };
1656 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {1656 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {
1657 apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();1657 apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();
1658 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);1658 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI, request.body.secret_id);
1659 headers = {};1659 headers = {};
1660 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {1660 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
1661 apiUrl = request.body.custom_url;1661 apiUrl = request.body.custom_url;
1662 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);1662 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM, request.body.secret_id);
1663 headers = {};1663 headers = {};
1664 mergeObjectWithYaml(headers, request.body.custom_include_headers);1664 mergeObjectWithYaml(headers, request.body.custom_include_headers);
1665 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE) {1665 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE) {
1666 apiUrl = API_COHERE_V1;1666 apiUrl = API_COHERE_V1;
1667 apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);1667 apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE, request.body.secret_id);
1668 headers = {};1668 headers = {};
1669 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CHUTES) {1669 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CHUTES) {
1670 apiUrl = API_CHUTES;1670 apiUrl = API_CHUTES;
1671 apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES);1671 apiKey = readSecret(request.user.directories, SECRET_KEYS.CHUTES, request.body.secret_id);
1672 headers = {};1672 headers = {};
1673 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ELECTRONHUB) {1673 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ELECTRONHUB) {
1674 apiUrl = API_ELECTRONHUB;1674 apiUrl = API_ELECTRONHUB;
1675 apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB);1675 apiKey = readSecret(request.user.directories, SECRET_KEYS.ELECTRONHUB, request.body.secret_id);
1676 headers = {};1676 headers = {};
1677 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {1677 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {
1678 apiUrl = API_NANOGPT;1678 apiUrl = API_NANOGPT;
1679 apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);1679 apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT, request.body.secret_id);
1680 headers = {};1680 headers = {};
1681 queryParams = { detailed: true };1681 queryParams = { detailed: true };
1682 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {1682 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {
1683 apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', '')).toString();1683 apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', '')).toString();
1684 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);1684 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK, request.body.secret_id);
1685 headers = {};1685 headers = {};
1686 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) {1686 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) {
1687 apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();1687 apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString();
1688 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);1688 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI, request.body.secret_id);
1689 headers = {};1689 headers = {};
1690 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AIMLAPI) {1690 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AIMLAPI) {
1691 apiUrl = API_AIMLAPI;1691 apiUrl = API_AIMLAPI;
1692 apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI);1692 apiKey = readSecret(request.user.directories, SECRET_KEYS.AIMLAPI, request.body.secret_id);
1693 headers = { ...AIMLAPI_HEADERS };1693 headers = { ...AIMLAPI_HEADERS };
1694 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {1694 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {
1695 apiUrl = 'https://gen.pollinations.ai/text';1695 apiUrl = 'https://gen.pollinations.ai/text';
1696 apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS);1696 apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS, request.body.secret_id);
1697 headers = {};1697 headers = {};
1698 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {1698 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {
1699 apiUrl = API_GROQ;1699 apiUrl = API_GROQ;
1700 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);1700 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ, request.body.secret_id);
1701 headers = {};1701 headers = {};
1702 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {1702 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {
1703 apiUrl = API_COMETAPI;1703 apiUrl = API_COMETAPI;
1704 apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI);1704 apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI, request.body.secret_id);
1705 headers = {};1705 headers = {};
1706 throw new Error('This provider is temporarily disabled.');1706 throw new Error('This provider is temporarily disabled.');
1707 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {1707 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
1708 apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();1708 apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();
1709 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);1709 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT, request.body.secret_id);
1710 headers = {};1710 headers = {};
1711 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {1711 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {
1712 apiUrl = API_FIREWORKS;1712 apiUrl = API_FIREWORKS;
1713 apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS);1713 apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS, request.body.secret_id);
1714 headers = {};1714 headers = {};
1715 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {1715 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {
1716 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);1716 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE, request.body.secret_id);
1717 apiUrl = trimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE);1717 apiUrl = trimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE);
1718 const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');1718 const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');
1719 const modelsUrl = !apiKey && request.body.reverse_proxy1719 const modelsUrl = !apiKey && request.body.reverse_proxy
@@ -1750,7 +1750,7 @@ router.post('/status', async function (request, statusResponse) {
1750 }1750 }
1751 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AZURE_OPENAI) {1751 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AZURE_OPENAI) {
1752 const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;1752 const { azure_base_url, azure_deployment_name, azure_api_version } = request.body;
1753 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI);1753 const apiKey = readSecret(request.user.directories, SECRET_KEYS.AZURE_OPENAI, request.body.secret_id);
17541754
1755 // 1) Validate configuration from the frontend1755 // 1) Validate configuration from the frontend
1756 if (!apiKey || !azure_base_url || !azure_deployment_name || !azure_api_version) {1756 if (!apiKey || !azure_base_url || !azure_deployment_name || !azure_api_version) {
@@ -1830,7 +1830,7 @@ router.post('/status', async function (request, statusResponse) {
1830 const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN1830 const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN
1831 ? API_SILICONFLOW_CN : API_SILICONFLOW;1831 ? API_SILICONFLOW_CN : API_SILICONFLOW;
1832 apiUrl = defaultApiUrl;1832 apiUrl = defaultApiUrl;
1833 apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);1833 apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW, request.body.secret_id);
1834 headers = {};1834 headers = {};
1835 queryParams = { type: 'text', sub_type: 'chat' };1835 queryParams = { type: 'text', sub_type: 'chat' };
1836 } else {1836 } else {
@@ -2053,7 +2053,7 @@ router.post('/generate', async function (request, response) {
20532053
2054 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {2054 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
2055 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();2055 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
2056 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);2056 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI, request.body.secret_id);
2057 headers = {};2057 headers = {};
2058 bodyParams = {2058 bodyParams = {
2059 logprobs: request.body.logprobs,2059 logprobs: request.body.logprobs,
@@ -2073,7 +2073,7 @@ router.post('/generate', async function (request, response) {
2073 embedOpenRouterMedia(request.body.messages, { audio: true, video: false });2073 embedOpenRouterMedia(request.body.messages, { audio: true, video: false });
2074 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {2074 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {
2075 apiUrl = 'https://openrouter.ai/api/v1';2075 apiUrl = 'https://openrouter.ai/api/v1';
2076 apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);2076 apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER, request.body.secret_id);
2077 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests2077 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests
2078 headers = { ...OPENROUTER_HEADERS };2078 headers = { ...OPENROUTER_HEADERS };
2079 const includeReasoning = Boolean(request.body.include_reasoning);2079 const includeReasoning = Boolean(request.body.include_reasoning);
@@ -2161,7 +2161,7 @@ router.post('/generate', async function (request, response) {
2161 }2161 }
2162 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {2162 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
2163 apiUrl = request.body.custom_url;2163 apiUrl = request.body.custom_url;
2164 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);2164 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM, request.body.secret_id);
2165 headers = {};2165 headers = {};
2166 bodyParams = {2166 bodyParams = {
2167 logprobs: request.body.logprobs,2167 logprobs: request.body.logprobs,
@@ -2179,7 +2179,7 @@ router.post('/generate', async function (request, response) {
2179 embedOpenRouterMedia(request.body.messages, { audio: true, video: false });2179 embedOpenRouterMedia(request.body.messages, { audio: true, video: false });
2180 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.PERPLEXITY) {2180 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.PERPLEXITY) {
2181 apiUrl = API_PERPLEXITY;2181 apiUrl = API_PERPLEXITY;
2182 apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY);2182 apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY, request.body.secret_id);
2183 headers = {};2183 headers = {};
2184 bodyParams = {2184 bodyParams = {
2185 reasoning_effort: request.body.reasoning_effort,2185 reasoning_effort: request.body.reasoning_effort,
@@ -2195,7 +2195,7 @@ router.post('/generate', async function (request, response) {
2195 }2195 }
2196 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {2196 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.GROQ) {
2197 apiUrl = API_GROQ;2197 apiUrl = API_GROQ;
2198 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);2198 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ, request.body.secret_id);
2199 headers = {};2199 headers = {};
2200 bodyParams = {};2200 bodyParams = {};
2201 if (request.body.json_schema) {2201 if (request.body.json_schema) {
@@ -2211,7 +2211,7 @@ router.post('/generate', async function (request, response) {
2211 }2211 }
2212 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {2212 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.FIREWORKS) {
2213 apiUrl = API_FIREWORKS;2213 apiUrl = API_FIREWORKS;
2214 apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS);2214 apiKey = readSecret(request.user.directories, SECRET_KEYS.FIREWORKS, request.body.secret_id);
2215 headers = {};2215 headers = {};
2216 bodyParams = {};2216 bodyParams = {};
2217 if (request.body.json_schema) {2217 if (request.body.json_schema) {
@@ -2227,7 +2227,7 @@ router.post('/generate', async function (request, response) {
2227 }2227 }
2228 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {2228 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {
2229 apiUrl = API_NANOGPT;2229 apiUrl = API_NANOGPT;
2230 apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);2230 apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT, request.body.secret_id);
2231 headers = {};2231 headers = {};
2232 bodyParams = {};2232 bodyParams = {};
2233 if (request.body.enable_web_search && !/:online$/.test(request.body.model)) {2233 if (request.body.enable_web_search && !/:online$/.test(request.body.model)) {
@@ -2256,7 +2256,7 @@ router.post('/generate', async function (request, response) {
2256 }2256 }
2257 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {2257 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {
2258 apiUrl = API_POLLINATIONS;2258 apiUrl = API_POLLINATIONS;
2259 apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS);2259 apiKey = readSecret(request.user.directories, SECRET_KEYS.POLLINATIONS, request.body.secret_id);
2260 headers = {};2260 headers = {};
2261 bodyParams = {2261 bodyParams = {
2262 reasoning_effort: request.body.reasoning_effort,2262 reasoning_effort: request.body.reasoning_effort,
@@ -2272,7 +2272,7 @@ router.post('/generate', async function (request, response) {
2272 }2272 }
2273 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {2273 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
2274 apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();2274 apiUrl = new URL(request.body.reverse_proxy || API_MOONSHOT).toString();
2275 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);2275 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MOONSHOT, request.body.secret_id);
2276 headers = {};2276 headers = {};
2277 bodyParams = {2277 bodyParams = {
2278 thinking: {2278 thinking: {
@@ -2284,7 +2284,7 @@ router.post('/generate', async function (request, response) {
2284 : addAssistantPrefix(request.body.messages, [], 'partial');2284 : addAssistantPrefix(request.body.messages, [], 'partial');
2285 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {2285 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COMETAPI) {
2286 apiUrl = API_COMETAPI;2286 apiUrl = API_COMETAPI;
2287 apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI);2287 apiKey = readSecret(request.user.directories, SECRET_KEYS.COMETAPI, request.body.secret_id);
2288 headers = {};2288 headers = {};
2289 bodyParams = {2289 bodyParams = {
2290 reasoning_effort: request.body.reasoning_effort,2290 reasoning_effort: request.body.reasoning_effort,
@@ -2293,7 +2293,7 @@ router.post('/generate', async function (request, response) {
2293 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ZAI) {2293 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ZAI) {
2294 const defaultApiUrl = request.body.zai_endpoint === ZAI_ENDPOINT.CODING ? API_ZAI_CODING : API_ZAI_COMMON;2294 const defaultApiUrl = request.body.zai_endpoint === ZAI_ENDPOINT.CODING ? API_ZAI_CODING : API_ZAI_COMMON;
2295 apiUrl = new URL(request.body.reverse_proxy || defaultApiUrl).toString();2295 apiUrl = new URL(request.body.reverse_proxy || defaultApiUrl).toString();
2296 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.ZAI);2296 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.ZAI, request.body.secret_id);
2297 headers = {2297 headers = {
2298 'Accept-Language': 'en-US,en',2298 'Accept-Language': 'en-US,en',
2299 };2299 };
@@ -2309,7 +2309,7 @@ router.post('/generate', async function (request, response) {
2309 const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN2309 const defaultApiUrl = request.body.siliconflow_endpoint === SILICONFLOW_ENDPOINT.CN
2310 ? API_SILICONFLOW_CN : API_SILICONFLOW;2310 ? API_SILICONFLOW_CN : API_SILICONFLOW;
2311 apiUrl = defaultApiUrl;2311 apiUrl = defaultApiUrl;
2312 apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);2312 apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW, request.body.secret_id);
2313 headers = {};2313 headers = {};
2314 bodyParams = {};2314 bodyParams = {};
2315 if (request.body.json_schema) {2315 if (request.body.json_schema) {
src/endpoints/secrets.js+3 -2
@@ -441,10 +441,11 @@ export function deleteSecret(directories, key) {
441 * Reads a secret from the secrets file441 * Reads a secret from the secrets file
442 * @param {import('../users.js').UserDirectoryList} directories User directories442 * @param {import('../users.js').UserDirectoryList} directories User directories
443 * @param {string} key Secret key443 * @param {string} key Secret key
444 * @param {string?} id Secret ID (optional)
444 * @returns {string} Secret value445 * @returns {string} Secret value
445 */446 */
446export function readSecret(directories, key) {447export function readSecret(directories, key, id = null) {
447 return new SecretManager(directories).readSecret(key, null);448 return new SecretManager(directories).readSecret(key, id);
448}449}
449450
450/**451/**