Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |

Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ oh setup
- DeepSeek
- GitHub Models
- SiliconFlow
- Google Gemini
- Groq
- Ollama
- 其他 OpenAI-compatible endpoint
Expand Down
3 changes: 3 additions & 0 deletions src/openharness/auth/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"bedrock",
"vertex",
"moonshot",
"gemini",
]

_AUTH_SOURCES = [
Expand All @@ -47,6 +48,7 @@
"bedrock_api_key",
"vertex_api_key",
"moonshot_api_key",
"gemini_api_key",
]

_PROFILE_BY_PROVIDER = {
Expand All @@ -56,6 +58,7 @@
"openai_codex": "codex",
"copilot": "copilot",
"moonshot": "moonshot",
"gemini": "gemini",
}


Expand Down
4 changes: 3 additions & 1 deletion src/openharness/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand All @@ -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",
}


Expand Down Expand Up @@ -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:
Expand Down
11 changes: 11 additions & 0 deletions src/openharness/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
),
}


Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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"
Expand Down
Loading