Merge pull request #4113 from InterestingDarknessII/google-dynamic-model Implement Google AI Studio model list dynamic fetching

88cd8bbbf3b46dc714babf4815312798f2398bc9

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

Signed
3 files changed, +74 -1Ignore whitespace
public/index.html+1 -0
@@ -3236,6 +3236,7 @@
32363236 <optgroup label="LearnLM">
32373237 <option value="learnlm-2.0-flash-experimental">learnlm-2.0-flash-experimental</option>
32383238 </optgroup>
3239+ <optgroup id="google_other_models" label="Other"></optgroup>
32393240 </select>
32403241 </div>
32413242 </form>
public/scripts/openai.js+30 -1
@@ -1912,6 +1912,36 @@ function saveModelList(data) {
19121912
19131913 $('#model_pollinations_select').val(oai_settings.pollinations_model).trigger('change');
19141914 }
1915+
1916+ if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) {
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
1927+ model_list.forEach((model) => {
1928+ // Only add if not already in static list
1929+ if (!staticModels.includes(model.id)) {
1930+ $('#google_other_models').append(
1931+ $('<option>', {
1932+ value: model.id,
1933+ text: model.id,
1934+ }));
1935+ }
1936+ });
1937+
1938+ const selectedModel = model_list.find(model => model.id === oai_settings.google_model);
1939+ if (model_list.length > 0 && (!selectedModel || !oai_settings.google_model)) {
1940+ oai_settings.google_model = model_list[0].id;
1941+ }
1942+
1943+ $('#model_google_select').val(oai_settings.google_model).trigger('change');
1944+ }
19151945}
19161946
19171947function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {
@@ -3700,7 +3730,6 @@ async function getStatusOpen() {
37003730 chat_completion_sources.SCALE,
37013731 chat_completion_sources.CLAUDE,
37023732 chat_completion_sources.AI21,
3703- chat_completion_sources.MAKERSUITE,
37043733 chat_completion_sources.VERTEXAI,
37053734 chat_completion_sources.PERPLEXITY,
37063735 chat_completion_sources.GROQ,
src/endpoints/backends/chat-completions.js+43 -0
@@ -1092,6 +1092,49 @@ router.post('/status', async function (request, response_getstatus_openai) {
10921092 api_url = 'https://text.pollinations.ai';
10931093 api_key_openai = 'NONE';
10941094 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+ const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta');
1100+ let models_url = `${api_url.origin}/${apiVersion}/models?key=${api_key_makersuite}`;
1101+
1102+ if (!api_key_makersuite && 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.');
1106+ return response_getstatus_openai.status(400).send({ error: true });
1107+ }
1108+
1109+ try {
1110+ const response = await fetch(models_url, {
1111+ method: 'GET',
1112+ headers: {
1113+ 'Content-Type': 'application/json',
1114+ },
1115+ });
1116+
1117+ if (response.ok) {
1118+ /** @type {any} */
1119+ const data = await response.json();
1120+ // Transform Google AI Studio models to OpenAI format
1121+ const models = data.models
1122+ ?.filter(model => model.supportedGenerationMethods?.includes('generateContent'))
1123+ ?.map(model => ({
1124+ id: model.name.replace('models/', ''),
1125+ })) || [];
1126+
1127+ response_getstatus_openai.send({ data: models });
1128+ console.info('Available Google AI Studio models:', models.map(m => m.id));
1129+ return;
1130+ } else {
1131+ console.error('Google AI Studio models endpoint failed:', response.status, response.statusText);
1132+ return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
1133+ }
1134+ } catch (error) {
1135+ console.error('Error fetching Google AI Studio models:', error);
1136+ return response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
1137+ }
10951138 } else {
10961139 console.warn('This chat completion source is not supported yet.');
10971140 return response_getstatus_openai.status(400).send({ error: true });