diff --git a/CHANGELOG.md b/CHANGELOG.md index 191c2592..ee4607f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on Keep a Changelog, and this project currently tracks chang ### Added +- Built-in `gemini` provider profile so `oh setup` offers Google Gemini as a first-class provider choice, with `gemini_api_key` auth source and `gemini-2.5-flash` as the default model. - `diagnose` skill: trace agent run failures and regressions using structured evidence from run artifacts. - OpenAI-compatible API client (`--api-format openai`) supporting any provider that implements the OpenAI `/v1/chat/completions` format, including Alibaba DashScope, DeepSeek, GitHub Models, Groq, Together AI, Ollama, and more. - `OPENHARNESS_API_FORMAT` environment variable for selecting the API format. diff --git a/README.md b/README.md index 96d6cd30..ea967639 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,7 @@ Any provider implementing the OpenAI `/v1/chat/completions` style API works: | **DeepSeek** | `https://api.deepseek.com` | `deepseek-chat`, `deepseek-reasoner` | | **GitHub Models** | `https://models.inference.ai.azure.com` | `gpt-4o`, `Meta-Llama-3.1-405B-Instruct` | | **SiliconFlow** | `https://api.siliconflow.cn/v1` | `deepseek-ai/DeepSeek-V3` | +| **Google Gemini** | `https://generativelanguage.googleapis.com/v1beta/openai` | `gemini-2.5-flash`, `gemini-2.5-pro` | | **Groq** | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | | **Ollama (local)** | `http://localhost:11434/v1` | any local model | diff --git a/README.zh-CN.md b/README.zh-CN.md index c3c942eb..5babdb2f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -104,6 +104,7 @@ oh setup - DeepSeek - GitHub Models - SiliconFlow +- Google Gemini - Groq - Ollama - 其他 OpenAI-compatible endpoint diff --git a/src/openharness/auth/manager.py b/src/openharness/auth/manager.py index 5510945b..a9e5ee5d 100644 --- a/src/openharness/auth/manager.py +++ b/src/openharness/auth/manager.py @@ -35,6 +35,7 @@ "bedrock", "vertex", "moonshot", + "gemini", ] _AUTH_SOURCES = [ @@ -47,6 +48,7 @@ "bedrock_api_key", "vertex_api_key", "moonshot_api_key", + "gemini_api_key", ] _PROFILE_BY_PROVIDER = { @@ -56,6 +58,7 @@ "openai_codex": "codex", "copilot": "copilot", "moonshot": "moonshot", + "gemini": "gemini", } diff --git a/src/openharness/cli.py b/src/openharness/cli.py index ea359e40..a403f047 100644 --- a/src/openharness/cli.py +++ b/src/openharness/cli.py @@ -271,6 +271,7 @@ def cron_logs_cmd( "bedrock": "AWS Bedrock", "vertex": "Google Vertex AI", "moonshot": "Moonshot (Kimi)", + "gemini": "Google Gemini", } _AUTH_SOURCE_LABELS: dict[str, str] = { @@ -283,6 +284,7 @@ def cron_logs_cmd( "bedrock_api_key": "Bedrock credentials", "vertex_api_key": "Vertex credentials", "moonshot_api_key": "Moonshot API key", + "gemini_api_key": "Gemini API key", } @@ -724,7 +726,7 @@ def _login_provider(provider: str) -> None: _bind_external_provider(provider) return - if provider in ("anthropic", "openai", "dashscope", "bedrock", "vertex", "moonshot"): + if provider in ("anthropic", "openai", "dashscope", "bedrock", "vertex", "moonshot", "gemini"): label = _PROVIDER_LABELS.get(provider, provider) flow = ApiKeyFlow(provider=provider, prompt_text=f"Enter your {label} API key") try: diff --git a/src/openharness/config/settings.py b/src/openharness/config/settings.py index bea3df0d..bc938c44 100644 --- a/src/openharness/config/settings.py +++ b/src/openharness/config/settings.py @@ -189,6 +189,14 @@ def default_provider_profiles() -> dict[str, ProviderProfile]: default_model="kimi-k2.5", base_url="https://api.moonshot.cn/v1", ), + "gemini": ProviderProfile( + label="Google Gemini", + provider="gemini", + api_format="openai", + auth_source="gemini_api_key", + default_model="gemini-2.5-flash", + base_url="https://generativelanguage.googleapis.com/v1beta/openai", + ), } @@ -275,6 +283,7 @@ def auth_source_provider_name(auth_source: str) -> str: "bedrock_api_key": "bedrock", "vertex_api_key": "vertex", "moonshot_api_key": "moonshot", + "gemini_api_key": "gemini", } return mapping.get(auth_source, auth_source) @@ -312,6 +321,8 @@ def default_auth_source_for_provider(provider: str, api_format: str | None = Non return "vertex_api_key" if provider == "moonshot": return "moonshot_api_key" + if provider == "gemini": + return "gemini_api_key" if provider == "openai" or api_format == "openai": return "openai_api_key" return "anthropic_api_key"