Implement Google AI Studio model list dynamic fetching

ff4a98a9399d349745e9abe10380735bd24fc89d

InterestingDarkness <computeridiot999@gmail.com>

3 files changed, +63 -48Showing whitespace changes
public/index.html+1 -47
@@ -3189,53 +3189,7 @@
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 <optgroup label="Gemini 2.5">3192 <option value="" data-i18n="-- Connect to the API --">-- Connect to the API --</option>
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 </select>3193 </select>
3240 </div>3194 </div>
3241 </form>3195 </form>
public/scripts/openai.js+18 -1
@@ -1912,6 +1912,24 @@ function saveModelList(data) {
19121912
1913 $('#model_pollinations_select').val(oai_settings.pollinations_model).trigger('change');1913 $('#model_pollinations_select').val(oai_settings.pollinations_model).trigger('change');
1914 }1914 }
1915
1916 if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) {
1917 $('#model_google_select').empty();
1918 model_list.forEach((model) => {
1919 $('#model_google_select').append(
1920 $('<option>', {
1921 value: model.id,
1922 text: model.id,
1923 }));
1924 });
1925
1926 const selectedModel = model_list.find(model => model.id === oai_settings.google_model);
1927 if (model_list.length > 0 && (!selectedModel || !oai_settings.google_model)) {
1928 oai_settings.google_model = model_list[0].id;
1929 }
1930
1931 $('#model_google_select').val(oai_settings.google_model).trigger('change');
1932 }
1915}1933}
19161934
1917function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {1935function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {
@@ -3700,7 +3718,6 @@ async function getStatusOpen() {
3700 chat_completion_sources.SCALE,3718 chat_completion_sources.SCALE,
3701 chat_completion_sources.CLAUDE,3719 chat_completion_sources.CLAUDE,
3702 chat_completion_sources.AI21,3720 chat_completion_sources.AI21,
3703 chat_completion_sources.MAKERSUITE,
3704 chat_completion_sources.VERTEXAI,3721 chat_completion_sources.VERTEXAI,
3705 chat_completion_sources.PERPLEXITY,3722 chat_completion_sources.PERPLEXITY,
3706 chat_completion_sources.GROQ,3723 chat_completion_sources.GROQ,
src/endpoints/backends/chat-completions.js+44 -0
@@ -1092,6 +1092,50 @@ router.post('/status', async function (request, response_getstatus_openai) {
1092 api_url = 'https://text.pollinations.ai';1092 api_url = 'https://text.pollinations.ai';
1093 api_key_openai = 'NONE';1093 api_key_openai = 'NONE';
1094 headers = {};1094 headers = {};
1095 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {
1096 // 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);
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}`;
1100
1101 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 key
1103 } else if (!api_key_makersuite && !request.body.reverse_proxy) {
1104 console.warn('Google AI Studio API key is missing.');
1105 return response_getstatus_openai.status(400).send({ error: true });
1106 }
1107
1108 try {
1109 const response = await fetch(models_url, {
1110 method: 'GET',
1111 headers: {
1112 'Content-Type': 'application/json',
1113 },
1114 });
1115
1116 if (response.ok) {
1117 const data = await response.json();
1118 // Transform Google AI Studio models to OpenAI format
1119 const models = data.models
1120 ?.filter(model => model.supportedGenerationMethods?.includes('generateContent'))
1121 ?.map(model => ({
1122 id: model.name.replace('models/', ''),
1123 object: 'model',
1124 created: Date.now(),
1125 owned_by: 'google',
1126 })) || [];
1127
1128 response_getstatus_openai.send({ data: models });
1129 console.info('Available Google AI Studio models:', models.map(m => m.id));
1130 return;
1131 } else {
1132 console.error('Google AI Studio models endpoint failed:', response.status, response.statusText);
1133 return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
1134 }
1135 } catch (error) {
1136 console.error('Error fetching Google AI Studio models:', error);
1137 return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
1138 }
1095 } else {1139 } else {
1096 console.warn('This chat completion source is not supported yet.');1140 console.warn('This chat completion source is not supported yet.');
1097 return response_getstatus_openai.status(400).send({ error: true });1141 return response_getstatus_openai.status(400).send({ error: true });