Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
97c6ec9
feat(agents): add native Google Gemini provider with full tool support
claude Feb 5, 2026
de1767b
feat(agents): add Google Gemini OAuth provider with device flow
claude Feb 5, 2026
8c8be99
docs: add Gemini provider implementation documentation
claude Feb 5, 2026
e17a9a7
docs: move Gemini documentation to docs/ directory
claude Feb 5, 2026
fae2cb0
refactor(agents): switch Gemini OAuth from device flow to PKCE
penso Feb 5, 2026
c393106
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
73fcdc7
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
67de41a
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
f8ecf03
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
a82b641
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
17325d2
docs: move gemini.md to docs/src and update SUMMARY
penso Feb 5, 2026
7b39139
Merge main into claude/add-gemini-provider-HP53H
penso Feb 5, 2026
a0e92df
Merge main into claude/add-gemini-provider-HP53H
penso Feb 6, 2026
9c5c23b
Merge main into claude/add-gemini-provider-HP53H
penso Feb 6, 2026
2de794f
Merge main into claude/add-gemini-provider-HP53H
penso Feb 6, 2026
2f3cbf0
Merge main into claude/add-gemini-provider-HP53H
penso Feb 7, 2026
50b689d
docs: add CHANGELOG entry for Gemini provider
penso Feb 7, 2026
d153cf4
feat(agents): add dynamic model listing for Gemini providers
penso Feb 7, 2026
9a6b369
Merge branch 'main' into claude/add-gemini-provider-HP53H
penso Feb 7, 2026
448c198
Merge branch 'main' into claude/add-gemini-provider-HP53H
penso Feb 7, 2026
ae030aa
refactor(agents): update Gemini providers to use ChatMessage type
penso Feb 7, 2026
67ad06b
Merge branch 'main' into claude/add-gemini-provider-HP53H
penso Feb 8, 2026
343ffc6
Merge branch 'main' into claude/add-gemini-provider-HP53H
penso Feb 9, 2026
388797e
fix(agents): update Gemini providers for Usage struct changes
penso Feb 9, 2026
cc42e31
merge(main): sync origin/main into claude/add-gemini-provider-HP53H
penso Mar 2, 2026
4a97230
Merge remote-tracking branch 'origin/main' into claude/add-gemini-pro…
penso Mar 2, 2026
0929d24
Merge remote-tracking branch 'origin/main' into claude/add-gemini-pro…
penso Mar 2, 2026
bd28b7c
fix(providers): integrate gemini-oauth and remove duplicate gemini path
penso Mar 2, 2026
049df7e
chore: merge origin/main into claude/add-gemini-provider-HP53H
penso Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- **Google Gemini OAuth provider** (`gemini-oauth`): Added browser-based Authorization Code + PKCE authentication using Google accounts
- Integrates with provider setup UI and token storage
- Supports model discovery from Gemini OAuth credentials with fallback catalog
- API usage is billed to the authenticated user's Google account
- **Voice Provider Management UI**: Configure TTS and STT providers from Settings > Voice
- Auto-detection of API keys from environment variables and LLM provider configs
- Toggle switches to enable/disable providers without removing configuration
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ moltis-plugins = { path = "crates/plugins" }
moltis-projects = { path = "crates/projects" }
moltis-protocol = { path = "crates/protocol" }
moltis-provider-setup = { path = "crates/provider-setup" }
moltis-providers = { features = ["provider-github-copilot", "provider-kimi-code", "provider-openai-codex"], path = "crates/providers" }
moltis-providers = { features = ["provider-gemini-oauth", "provider-github-copilot", "provider-kimi-code", "provider-openai-codex"], path = "crates/providers" }
moltis-qmd = { path = "crates/qmd" }
moltis-routing = { path = "crates/routing" }
moltis-schema-export = { path = "crates/schema-export" }
Expand Down
5 changes: 4 additions & 1 deletion crates/config/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2053,7 +2053,10 @@ pub struct ProvidersConfig {
pub offered: Vec<String>,

/// Provider-specific settings keyed by provider name.
/// Known keys: "anthropic", "openai", "gemini", "groq", "xai", "deepseek"
/// Known keys include "anthropic", "openai", "gemini", "gemini-oauth",
/// "groq", "xai", "deepseek", "mistral", "openrouter", "cerebras",
/// "minimax", "moonshot", "venice", "ollama", "lmstudio",
/// "openai-codex", "github-copilot", and "kimi-code".
#[serde(flatten)]
pub providers: HashMap<String, ProviderEntry>,

Expand Down
2 changes: 1 addition & 1 deletion crates/config/src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ offered = ["local-llm", "github-copilot", "openai-codex", "openai", "anthropic",
# All available providers:
# "anthropic", "openai", "gemini", "groq", "xai", "deepseek",
# "mistral", "openrouter", "cerebras", "minimax", "moonshot",
# "zai", "venice", "ollama", "local-llm", "openai-codex",
# "zai", "venice", "ollama", "local-llm", "gemini-oauth", "openai-codex",
# "github-copilot", "kimi-code"

# ── Anthropic (Claude) ────────────────────────────────────────
Expand Down
4 changes: 4 additions & 0 deletions crates/config/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const KNOWN_PROVIDER_NAMES: &[&str] = &[
"anthropic",
"openai",
"gemini",
"gemini-oauth",
"groq",
"xai",
"deepseek",
Expand All @@ -99,6 +100,9 @@ const KNOWN_PROVIDER_NAMES: &[&str] = &[
"venice",
"ollama",
"lmstudio",
"openai-codex",
"github-copilot",
"kimi-code",
];

/// Static metadata keys allowed directly under `[providers]`.
Expand Down
36 changes: 36 additions & 0 deletions crates/oauth/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ fn builtin_defaults() -> HashMap<String, OAuthConfig> {
],
device_flow: false,
});
// Google Gemini uses Authorization Code + PKCE flow.
// Users authenticate with their Google account; API usage is billed to their account.
// The client_id is a public identifier (not secret) for the Moltis application.
m.insert("gemini-oauth".into(), OAuthConfig {
// TODO: Replace with actual Moltis client ID from Google Cloud Console
client_id: "MOLTIS_GEMINI_CLIENT_ID".into(),
auth_url: "https://accounts.google.com/o/oauth2/v2/auth".into(),
token_url: "https://oauth2.googleapis.com/token".into(),
redirect_uri: "http://localhost:1456/auth/callback".into(),
resource: None,
scopes: vec![
// Scope for Gemini API access
"https://www.googleapis.com/auth/generative-language.retriever".into(),
"https://www.googleapis.com/auth/cloud-platform".into(),
],
extra_auth_params: vec![
// Request offline access to get a refresh token
("access_type".into(), "offline".into()),
// Force consent screen to always show (ensures refresh token)
("prompt".into(), "consent".into()),
],
device_flow: false,
});
m
}

Expand Down Expand Up @@ -156,4 +179,17 @@ mod tests {
let config = load_oauth_config("openai-codex").unwrap();
assert_eq!(callback_port(&config), 1455);
}

#[test]
fn load_gemini_oauth_config() {
let config = load_oauth_config("gemini-oauth").expect("should have gemini-oauth");
assert!(!config.device_flow);
assert!(!config.redirect_uri.is_empty());
assert_eq!(
config.auth_url,
"https://accounts.google.com/o/oauth2/v2/auth"
);
assert_eq!(config.token_url, "https://oauth2.googleapis.com/token");
assert_eq!(callback_port(&config), 1456);
}
}
21 changes: 21 additions & 0 deletions crates/provider-setup/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,15 @@ pub fn known_providers() -> Vec<KnownProvider> {
requires_model: false,
key_optional: false,
},
KnownProvider {
name: "gemini-oauth",
display_name: "Google Gemini (OAuth)",
auth_type: AuthType::Oauth,
env_key: None,
default_base_url: None,
requires_model: false,
key_optional: false,
},
KnownProvider {
name: "groq",
display_name: "Groq",
Expand Down Expand Up @@ -3720,6 +3729,7 @@ mod tests {
assert!(names.contains(&"venice"), "missing venice");
assert!(names.contains(&"ollama"), "missing ollama");
// OAuth providers
assert!(names.contains(&"gemini-oauth"), "missing gemini-oauth");
assert!(names.contains(&"github-copilot"), "missing github-copilot");
}

Expand All @@ -3734,6 +3744,17 @@ mod tests {
assert!(copilot.env_key.is_none());
}

#[test]
fn gemini_oauth_is_oauth_provider() {
let providers = known_providers();
let gemini_oauth = providers
.iter()
.find(|p| p.name == "gemini-oauth")
.expect("gemini-oauth not in known_providers");
assert_eq!(gemini_oauth.auth_type, AuthType::Oauth);
assert!(gemini_oauth.env_key.is_none());
}

#[test]
fn new_api_key_providers_have_correct_env_keys() {
let expected = [
Expand Down
1 change: 1 addition & 0 deletions crates/providers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local-llm-metal = ["llama-cpp-2/metal", "local-llm"]
metrics = ["dep:moltis-metrics"]
provider-async-openai = ["dep:async-openai"]
provider-genai = ["dep:genai"]
provider-gemini-oauth = ["dep:moltis-oauth"]
provider-github-copilot = ["dep:moltis-oauth"]
provider-kimi-code = ["dep:moltis-oauth"]
provider-openai-codex = ["dep:base64", "dep:moltis-oauth"]
Expand Down
Loading
Loading