Refactor /status endpoint

c22d70793d3d3e612c4b816f84edc77ac7496f43

Cohee <18619528+Cohee1207@users.noreply.github.com>

2 files changed, +47 -54Ignore whitespace
public/scripts/openai.js+1 -1
@@ -1919,7 +1919,7 @@ function saveModelList(data) {
19191919
1920 // Get static model options that are already in the HTML1920 // Get static model options that are already in the HTML
1921 const staticModels = [];1921 const staticModels = [];
1922 $('#model_google_select option').each(function() {1922 $('#model_google_select option').each(function () {
1923 staticModels.push($(this).val());1923 staticModels.push($(this).val());
1924 });1924 });
19251925
src/endpoints/backends/chat-completions.js+46 -53
@@ -1043,76 +1043,70 @@ async function sendXaiRequest(request, response) {
10431043
1044export const router = express.Router();1044export const router = express.Router();
10451045
1046router.post('/status', async function (request, response_getstatus_openai) {1046router.post('/status', async function (request, statusResponse) {
1047 if (!request.body) return response_getstatus_openai.sendStatus(400);1047 if (!request.body) return statusResponse.sendStatus(400);
10481048
1049 let api_url;1049 let apiUrl;
1050 let api_key_openai;1050 let apiKey;
1051 let headers;1051 let headers;
10521052
1053 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {1053 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
1054 api_url = new URL(request.body.reverse_proxy || API_OPENAI).toString();1054 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
1055 api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);1055 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);
1056 headers = {};1056 headers = {};
1057 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {1057 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENROUTER) {
1058 api_url = 'https://openrouter.ai/api/v1';1058 apiUrl = 'https://openrouter.ai/api/v1';
1059 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);1059 apiKey = readSecret(request.user.directories, SECRET_KEYS.OPENROUTER);
1060 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests1060 // OpenRouter needs to pass the Referer and X-Title: https://openrouter.ai/docs#requests
1061 headers = { ...OPENROUTER_HEADERS };1061 headers = { ...OPENROUTER_HEADERS };
1062 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {1062 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) {
1063 api_url = new URL(request.body.reverse_proxy || API_MISTRAL).toString();1063 apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString();
1064 api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);1064 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);
1065 headers = {};1065 headers = {};
1066 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {1066 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
1067 api_url = request.body.custom_url;1067 apiUrl = request.body.custom_url;
1068 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);1068 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);
1069 headers = {};1069 headers = {};
1070 mergeObjectWithYaml(headers, request.body.custom_include_headers);1070 mergeObjectWithYaml(headers, request.body.custom_include_headers);
1071 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE) {1071 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE) {
1072 api_url = API_COHERE_V1;1072 apiUrl = API_COHERE_V1;
1073 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.COHERE);1073 apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);
1074 headers = {};1074 headers = {};
1075 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ZEROONEAI) {1075 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.ZEROONEAI) {
1076 api_url = API_01AI;1076 apiUrl = API_01AI;
1077 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.ZEROONEAI);1077 apiKey = readSecret(request.user.directories, SECRET_KEYS.ZEROONEAI);
1078 headers = {};1078 headers = {};
1079 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {1079 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.NANOGPT) {
1080 api_url = API_NANOGPT;1080 apiUrl = API_NANOGPT;
1081 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);1081 apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
1082 headers = {};1082 headers = {};
1083 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {1083 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {
1084 api_url = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', ''));1084 apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', ''));
1085 api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);1085 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
1086 headers = {};1086 headers = {};
1087 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) {1087 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) {
1088 api_url = new URL(request.body.reverse_proxy || API_XAI);1088 apiUrl = new URL(request.body.reverse_proxy || API_XAI);
1089 api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);1089 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI);
1090 headers = {};1090 headers = {};
1091 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {1091 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.POLLINATIONS) {
1092 api_url = 'https://text.pollinations.ai';1092 apiUrl = 'https://text.pollinations.ai';
1093 api_key_openai = 'NONE';1093 apiKey = 'NONE';
1094 headers = {};1094 headers = {};
1095 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {1095 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {
1096 // For Google AI Studio, we need to get models from the API1096 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);
1097 const api_key_makersuite = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);1097 apiUrl = new URL(request.body.reverse_proxy || API_MAKERSUITE);
1098 const api_url = new URL(request.body.reverse_proxy || API_MAKERSUITE);
1099 const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');1098 const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');
1100 let models_url = `${api_url.origin}/${apiVersion}/models?key=${api_key_makersuite}`;1099 const modelsUrl = !apiKey && request.body.reverse_proxy
1100 ? `${apiUrl.origin}/${apiVersion}/models`
1101 : `${apiUrl.origin}/${apiVersion}/models?key=${apiKey}`;
11011102
1102 if (!api_key_makersuite && request.body.reverse_proxy) {1103 if (!apiKey && !request.body.reverse_proxy) {
1103 models_url = `${api_url.origin}/${apiVersion}/models`; // For some special reverse proxy, we can't pass the API key
1104 } else if (!api_key_makersuite && !request.body.reverse_proxy) {
1105 console.warn('Google AI Studio API key is missing.');1104 console.warn('Google AI Studio API key is missing.');
1106 return response_getstatus_openai.status(400).send({ error: true });1105 return statusResponse.status(400).send({ error: true });
1107 }1106 }
11081107
1109 try {1108 try {
1110 const response = await fetch(models_url, {1109 const response = await fetch(modelsUrl);
1111 method: 'GET',
1112 headers: {
1113 'Content-Type': 'application/json',
1114 },
1115 });
11161110
1117 if (response.ok) {1111 if (response.ok) {
1118 /** @type {any} */1112 /** @type {any} */
@@ -1124,32 +1118,31 @@ router.post('/status', async function (request, response_getstatus_openai) {
1124 id: model.name.replace('models/', ''),1118 id: model.name.replace('models/', ''),
1125 })) || [];1119 })) || [];
11261120
1127 response_getstatus_openai.send({ data: models });
1128 console.info('Available Google AI Studio models:', models.map(m => m.id));1121 console.info('Available Google AI Studio models:', models.map(m => m.id));
1129 return;1122 return statusResponse.send({ data: models });
1130 } else {1123 } else {
1131 console.error('Google AI Studio models endpoint failed:', response.status, response.statusText);1124 console.warn('Google AI Studio models endpoint failed:', response.status, response.statusText);
1132 return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });1125 return statusResponse.send({ error: true, can_bypass: true, data: { data: [] } });
1133 }1126 }
1134 } catch (error) {1127 } catch (error) {
1135 console.error('Error fetching Google AI Studio models:', error);1128 console.error('Error fetching Google AI Studio models:', error);
1136 return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });1129 return statusResponse.send({ error: true, can_bypass: true, data: { data: [] } });
1137 }1130 }
1138 } else {1131 } else {
1139 console.warn('This chat completion source is not supported yet.');1132 console.warn('This chat completion source is not supported yet.');
1140 return response_getstatus_openai.status(400).send({ error: true });1133 return statusResponse.status(400).send({ error: true });
1141 }1134 }
11421135
1143 if (!api_key_openai && !request.body.reverse_proxy && request.body.chat_completion_source !== CHAT_COMPLETION_SOURCES.CUSTOM) {1136 if (!apiKey && !request.body.reverse_proxy && request.body.chat_completion_source !== CHAT_COMPLETION_SOURCES.CUSTOM) {
1144 console.warn('Chat Completion API key is missing.');1137 console.warn('Chat Completion API key is missing.');
1145 return response_getstatus_openai.status(400).send({ error: true });1138 return statusResponse.status(400).send({ error: true });
1146 }1139 }
11471140
1148 try {1141 try {
1149 const response = await fetch(api_url + '/models', {1142 const response = await fetch(apiUrl + '/models', {
1150 method: 'GET',1143 method: 'GET',
1151 headers: {1144 headers: {
1152 'Authorization': 'Bearer ' + api_key_openai,1145 'Authorization': 'Bearer ' + apiKey,
1153 ...headers,1146 ...headers,
1154 },1147 },
1155 });1148 });
@@ -1162,7 +1155,7 @@ router.post('/status', async function (request, response_getstatus_openai) {
1162 data = { data: data.map(model => ({ id: model.name, ...model })) };1155 data = { data: data.map(model => ({ id: model.name, ...model })) };
1163 }1156 }
11641157
1165 response_getstatus_openai.send(data);1158 statusResponse.send(data);
11661159
1167 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE && Array.isArray(data?.models)) {1160 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.COHERE && Array.isArray(data?.models)) {
1168 data.data = data.models.map(model => ({ id: model.name, ...model }));1161 data.data = data.models.map(model => ({ id: model.name, ...model }));
@@ -1198,15 +1191,15 @@ router.post('/status', async function (request, response_getstatus_openai) {
1198 }1191 }
1199 else {1192 else {
1200 console.error('Chat Completion status check failed. Either Access Token is incorrect or API endpoint is down.');1193 console.error('Chat Completion status check failed. Either Access Token is incorrect or API endpoint is down.');
1201 response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });1194 statusResponse.send({ error: true, can_bypass: true, data: { data: [] } });
1202 }1195 }
1203 } catch (e) {1196 } catch (e) {
1204 console.error(e);1197 console.error(e);
12051198
1206 if (!response_getstatus_openai.headersSent) {1199 if (!statusResponse.headersSent) {
1207 response_getstatus_openai.send({ error: true });1200 statusResponse.send({ error: true });
1208 } else {1201 } else {
1209 response_getstatus_openai.end();1202 statusResponse.end();
1210 }1203 }
1211 }1204 }
1212});1205});