Add static model list for Google AI Studio

a106602f254713351e6f2cf47397dff53a307ada

InterestingDarkness <computeridiot999@gmail.com>

3 files changed, +70 -12Ignore whitespace
public/index.html+48 -1
@@ -3189,7 +3189,54 @@
3189 <div>3189 <div>
3190 <h4 data-i18n="Google Model">Google Model</h4>3190 <h4 data-i18n="Google Model">Google Model</h4>
3191 <select id="model_google_select">3191 <select id="model_google_select">
3192 <option value="" data-i18n="-- Connect to the API --">-- Connect to the API --</option>3192 <optgroup label="Gemini 2.5">
3193 <option value="gemini-2.5-pro-preview-06-05">gemini-2.5-pro-preview-06-05</option>
3194 <option value="gemini-2.5-pro-preview-05-06">gemini-2.5-pro-preview-05-06</option>
3195 <option value="gemini-2.5-pro-preview-03-25">gemini-2.5-pro-preview-03-25</option>
3196 <option value="gemini-2.5-pro-exp-03-25">gemini-2.5-pro-exp-03-25</option>
3197 <option value="gemini-2.5-flash-preview-05-20">gemini-2.5-flash-preview-05-20</option>
3198 <option value="gemini-2.5-flash-preview-04-17">gemini-2.5-flash-preview-04-17</option>
3199 </optgroup>
3200 <optgroup label="Gemini 2.0">
3201 <option value="gemini-2.0-pro-exp-02-05">gemini-2.0-pro-exp-02-05 → 2.5-pro-exp-03-25</option>
3202 <option value="gemini-2.0-pro-exp">gemini-2.0-pro-exp → 2.5-pro-exp-03-25</option>
3203 <option value="gemini-exp-1206">gemini-exp-1206 → 2.5-pro-exp-03-25</option>
3204 <option value="gemini-2.0-flash-001">gemini-2.0-flash-001</option>
3205 <option value="gemini-2.0-flash-exp-image-generation">gemini-2.0-flash-exp-image-generation</option>
3206 <option value="gemini-2.0-flash-exp">gemini-2.0-flash-exp</option>
3207 <option value="gemini-2.0-flash">gemini-2.0-flash</option>
3208 <option value="gemini-2.0-flash-thinking-exp-01-21">gemini-2.0-flash-thinking-exp-01-21 → 2.5-flash-preview-04-17</option>
3209 <option value="gemini-2.0-flash-thinking-exp-1219">gemini-2.0-flash-thinking-exp-1219 → 2.5-flash-preview-04-17</option>
3210 <option value="gemini-2.0-flash-thinking-exp">gemini-2.0-flash-thinking-exp → 2.5-flash-preview-04-17</option>
3211 <option value="gemini-2.0-flash-lite-001">gemini-2.0-flash-lite-001</option>
3212 <option value="gemini-2.0-flash-lite-preview-02-05">gemini-2.0-flash-lite-preview-02-05</option>
3213 <option value="gemini-2.0-flash-lite-preview">gemini-2.0-flash-lite-preview</option>
3214 </optgroup>
3215 <optgroup label="Gemini 1.5">
3216 <option value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
3217 <option value="gemini-1.5-pro-002">gemini-1.5-pro-002</option>
3218 <option value="gemini-1.5-pro-001">gemini-1.5-pro-001</option>
3219 <option value="gemini-1.5-pro">gemini-1.5-pro</option>
3220 <option value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
3221 <option value="gemini-1.5-flash-002">gemini-1.5-flash-002</option>
3222 <option value="gemini-1.5-flash-001">gemini-1.5-flash-001</option>
3223 <option value="gemini-1.5-flash">gemini-1.5-flash</option>
3224 <option value="gemini-1.5-flash-8b-001">gemini-1.5-flash-8b-001</option>
3225 <option value="gemini-1.5-flash-8b-exp-0924">gemini-1.5-flash-8b-exp-0924</option>
3226 <option value="gemini-1.5-flash-8b-exp-0827">gemini-1.5-flash-8b-exp-0827</option>
3227 <option value="gemini-1.5-flash-8b">gemini-1.5-flash-8b</option>
3228 </optgroup>
3229 <optgroup label="Gemma">
3230 <option value="gemma-3n-e4b-it">gemma-3n-e4b-it</option>
3231 <option value="gemma-3-27b-it">gemma-3-27b-it</option>
3232 <option value="gemma-3-12b-it">gemma-3-12b-it</option>
3233 <option value="gemma-3-4b-it">gemma-3-4b-it</option>
3234 <option value="gemma-3-1b-it">gemma-3-1b-it</option>
3235 </optgroup>
3236 <optgroup label="LearnLM">
3237 <option value="learnlm-2.0-flash-experimental">learnlm-2.0-flash-experimental</option>
3238 </optgroup>
3239 <optgroup id="google_other_models" label="Other"></optgroup>
3193 </select>3240 </select>
3194 </div>3241 </div>
3195 </form>3242 </form>
public/scripts/openai.js+18 -6
@@ -1914,13 +1914,25 @@ function saveModelList(data) {
1914 }1914 }
19151915
1916 if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) {1916 if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) {
1917 $('#model_google_select').empty();1917 // Clear only the "Other" optgroup for dynamic models
1918 $('#google_other_models').empty();
1919
1920 // Get static model options that are already in the HTML
1921 const staticModels = [];
1922 $('#model_google_select option').each(function() {
1923 staticModels.push($(this).val());
1924 });
1925
1926 // Add dynamic models to the "Other" group
1918 model_list.forEach((model) => {1927 model_list.forEach((model) => {
1919 $('#model_google_select').append(1928 // Only add if not already in static list
1920 $('<option>', {1929 if (!staticModels.includes(model.id)) {
1921 value: model.id,1930 $('#google_other_models').append(
1922 text: model.id,1931 $('<option>', {
1923 }));1932 value: model.id,
1933 text: model.id,
1934 }));
1935 }
1924 });1936 });
19251937
1926 const selectedModel = model_list.find(model => model.id === oai_settings.google_model);1938 const selectedModel = model_list.find(model => model.id === oai_settings.google_model);
src/endpoints/backends/chat-completions.js+4 -5
@@ -1096,10 +1096,11 @@ router.post('/status', async function (request, response_getstatus_openai) {
1096 // For Google AI Studio, we need to get models from the API1096 // For Google AI Studio, we need to get models from the API
1097 const api_key_makersuite = 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);
1098 const api_url = new URL(request.body.reverse_proxy || API_MAKERSUITE);1098 const api_url = new URL(request.body.reverse_proxy || API_MAKERSUITE);
1099 let models_url = `${api_url.origin}/v1beta/models?key=${api_key_makersuite}`;1099 const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');
1100 let models_url = `${api_url.origin}/${apiVersion}/models?key=${api_key_makersuite}`;
11001101
1101 if (!api_key_makersuite && request.body.reverse_proxy) {1102 if (!api_key_makersuite && request.body.reverse_proxy) {
1102 models_url = `${api_url.origin}/v1beta/models`; // For some special reverse proxy, we can't pass the API key1103 models_url = `${api_url.origin}/${apiVersion}/models`; // For some special reverse proxy, we can't pass the API key
1103 } else if (!api_key_makersuite && !request.body.reverse_proxy) {1104 } else if (!api_key_makersuite && !request.body.reverse_proxy) {
1104 console.warn('Google AI Studio API key is missing.');1105 console.warn('Google AI Studio API key is missing.');
1105 return response_getstatus_openai.status(400).send({ error: true });1106 return response_getstatus_openai.status(400).send({ error: true });
@@ -1114,15 +1115,13 @@ router.post('/status', async function (request, response_getstatus_openai) {
1114 });1115 });
11151116
1116 if (response.ok) {1117 if (response.ok) {
1118 /** @type {any} */
1117 const data = await response.json();1119 const data = await response.json();
1118 // Transform Google AI Studio models to OpenAI format1120 // Transform Google AI Studio models to OpenAI format
1119 const models = data.models1121 const models = data.models
1120 ?.filter(model => model.supportedGenerationMethods?.includes('generateContent'))1122 ?.filter(model => model.supportedGenerationMethods?.includes('generateContent'))
1121 ?.map(model => ({1123 ?.map(model => ({
1122 id: model.name.replace('models/', ''),1124 id: model.name.replace('models/', ''),
1123 object: 'model',
1124 created: Date.now(),
1125 owned_by: 'google',
1126 })) || [];1125 })) || [];
11271126
1128 response_getstatus_openai.send({ data: models });1127 response_getstatus_openai.send({ data: models });