adds gemini support
TestFlight / testflight (push) Successful in 1m53s

This commit is contained in:
2026-07-11 14:16:21 -07:00
parent 69f50064a3
commit 93ca8a76c3
23 changed files with 645 additions and 27 deletions
+10 -2
View File
@@ -123,6 +123,7 @@ const PROVIDER_FALLBACK_MODELS: Record<Provider, string[]> = {
openai: ["gpt-4.1-mini"],
anthropic: ["claude-3-5-sonnet-latest"],
xai: ["grok-3-mini"],
gemini: ["gemini-3.5-flash", "gemini-flash-latest"],
"hermes-agent": ["hermes-agent"],
};
@@ -130,9 +131,10 @@ const EMPTY_MODEL_CATALOG: ModelCatalogResponse["providers"] = {
openai: { models: [], loadedAt: null, error: null },
anthropic: { models: [], loadedAt: null, error: null },
xai: { models: [], loadedAt: null, error: null },
gemini: { models: [], loadedAt: null, error: null },
};
const BASE_PROVIDERS: Provider[] = ["openai", "anthropic", "xai"];
const BASE_PROVIDERS: Provider[] = ["openai", "anthropic", "xai", "gemini"];
const ALL_PROVIDERS: Provider[] = [...BASE_PROVIDERS, "hermes-agent"];
const MODEL_PREFERENCES_STORAGE_KEY = "sybil:modelPreferencesByProvider";
@@ -149,6 +151,7 @@ const EMPTY_MODEL_PREFERENCES: ProviderModelPreferences = {
openai: null,
anthropic: null,
xai: null,
gemini: null,
"hermes-agent": null,
};
const EMPTY_ACTIVE_RUNS: ActiveRunsState = {
@@ -345,6 +348,7 @@ function loadStoredModelPreferences() {
openai: typeof parsed.openai === "string" && parsed.openai.trim() ? parsed.openai.trim() : null,
anthropic: typeof parsed.anthropic === "string" && parsed.anthropic.trim() ? parsed.anthropic.trim() : null,
xai: typeof parsed.xai === "string" && parsed.xai.trim() ? parsed.xai.trim() : null,
gemini: typeof parsed.gemini === "string" && parsed.gemini.trim() ? parsed.gemini.trim() : null,
"hermes-agent":
typeof parsed["hermes-agent"] === "string" && parsed["hermes-agent"].trim() ? parsed["hermes-agent"].trim() : null,
};
@@ -354,7 +358,9 @@ function loadStoredModelPreferences() {
}
function normalizeStoredProvider(value: unknown): Provider {
return value === "anthropic" || value === "xai" || value === "openai" || value === "hermes-agent" ? value : "openai";
return value === "anthropic" || value === "xai" || value === "gemini" || value === "openai" || value === "hermes-agent"
? value
: "openai";
}
function normalizeStoredModelPreferences(value: unknown): ProviderModelPreferences {
@@ -364,6 +370,7 @@ function normalizeStoredModelPreferences(value: unknown): ProviderModelPreferenc
openai: typeof parsed.openai === "string" && parsed.openai.trim() ? parsed.openai.trim() : null,
anthropic: typeof parsed.anthropic === "string" && parsed.anthropic.trim() ? parsed.anthropic.trim() : null,
xai: typeof parsed.xai === "string" && parsed.xai.trim() ? parsed.xai.trim() : null,
gemini: typeof parsed.gemini === "string" && parsed.gemini.trim() ? parsed.gemini.trim() : null,
"hermes-agent":
typeof parsed["hermes-agent"] === "string" && parsed["hermes-agent"].trim() ? parsed["hermes-agent"].trim() : null,
};
@@ -395,6 +402,7 @@ function getProviderLabel(provider: Provider | null | undefined) {
if (provider === "openai") return "OpenAI";
if (provider === "anthropic") return "Anthropic";
if (provider === "xai") return "xAI";
if (provider === "gemini") return "Gemini";
if (provider === "hermes-agent") return "Hermes Agent";
return "";
}
+1 -1
View File
@@ -149,7 +149,7 @@ export type CompletionRequestMessage = {
attachments?: ChatAttachment[];
};
export type Provider = "openai" | "anthropic" | "xai" | "hermes-agent";
export type Provider = "openai" | "anthropic" | "xai" | "gemini" | "hermes-agent";
export type ProviderModelInfo = {
models: string[];