Skip to content

Commit 03a0810

Browse files
emerybergerclaude
andauthored
Add Google Gemini provider, environment variable support, and UI modernization (#973)
* Modernize AI provider UI and improve UX - Clean up UI with CSS classes instead of inline styles - Add password inputs with Show/Hide toggle for API keys - Add collapsible "Advanced options" for custom model/URL fields - Alphabetize provider dropdown (Local at bottom) - Auto-select default provider based on environment variables - Add autocomplete="off" to prevent browser password prompts - Fix optimization target alignment (left-aligned radio/checkbox) - Streamline model options in dropdowns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add dynamic model fetching for OpenAI and Gemini - Add fetchOpenAIModels() to query /v1/models endpoint - Add fetchGeminiModels() to query /v1beta/models endpoint - Add refresh buttons (↻) next to model dropdowns - Filter models to show only relevant chat/generation models - Use autocomplete="one-time-code" to prevent browser password prompts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0eebcd4 commit 03a0810

5 files changed

Lines changed: 689 additions & 447 deletions

File tree

scalene/scalene-gui/gemini.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ interface GeminiResponse extends GeminiErrorResponse {
2323
candidates?: GeminiCandidate[];
2424
}
2525

26+
interface GeminiModelInfo {
27+
name: string;
28+
displayName: string;
29+
supportedGenerationMethods: string[];
30+
}
31+
32+
interface GeminiModelsResponse extends GeminiErrorResponse {
33+
models?: GeminiModelInfo[];
34+
}
35+
2636
export async function sendPromptToGemini(
2737
prompt: string,
2838
apiKey: string
@@ -104,3 +114,41 @@ export async function sendPromptToGemini(
104114
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
105115
}
106116
}
117+
118+
// Fetch available models from Gemini API
119+
export async function fetchGeminiModels(apiKey: string): Promise<string[]> {
120+
if (!apiKey) return [];
121+
122+
// Check for custom URL
123+
const customUrlElement = document.getElementById("gemini-custom-url") as HTMLInputElement | null;
124+
const customUrl = customUrlElement?.value?.trim() || "";
125+
const baseUrl = customUrl || "https://generativelanguage.googleapis.com/v1beta";
126+
const endpoint = `${baseUrl}/models?key=${apiKey}`;
127+
128+
try {
129+
const response = await fetch(endpoint, {
130+
method: "GET",
131+
headers: {
132+
"Content-Type": "application/json",
133+
},
134+
});
135+
136+
const data: GeminiModelsResponse = await response.json();
137+
if (data.error || !data.models) {
138+
console.error("Failed to fetch Gemini models:", data.error);
139+
return [];
140+
}
141+
142+
// Filter for models that support generateContent and extract model ID
143+
const chatModels = data.models
144+
.filter((m) => m.supportedGenerationMethods?.includes("generateContent"))
145+
.map((m) => m.name.replace("models/", ""))
146+
.filter((id) => id.includes("gemini"))
147+
.sort();
148+
149+
return chatModels;
150+
} catch (error) {
151+
console.error("Error fetching Gemini models:", error);
152+
return [];
153+
}
154+
}

0 commit comments

Comments
 (0)