Skip to content
Open
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
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,10 @@
# ANTHROPIC_DEFAULT_OPUS_MODEL=kimi-k2.5
# ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k2.5
# ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.5
#
# OrcaRouter:
# ANTHROPIC_BASE_URL=https://api.orcarouter.ai
# ANTHROPIC_AUTH_TOKEN=your-orcarouter-api-key
# ANTHROPIC_DEFAULT_OPUS_MODEL=anthropic/claude-opus-5
# ANTHROPIC_DEFAULT_SONNET_MODEL=anthropic/claude-sonnet-5
# ANTHROPIC_DEFAULT_HAIKU_MODEL=anthropic/claude-haiku-4.5
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,11 @@ Run coding agents via Google Cloud Vertex AI:

**Note:** Use `@` instead of `-` in model names for Vertex AI.

### Alternative API Providers (GLM, Ollama, Kimi, Custom)
### Alternative API Providers (GLM, Ollama, Kimi, OrcaRouter, Custom)

Alternative providers are configured via the **Settings UI** (gear icon > API Provider section). Select a provider, set the base URL, auth token, and model — no `.env` changes needed.

**Available providers:** Claude (default), GLM (Zhipu AI), Ollama (local models), Kimi (Moonshot), Custom
**Available providers:** Claude (default), GLM (Zhipu AI), Ollama (local models), Kimi (Moonshot), OrcaRouter, Custom

**Ollama notes:**
- Requires Ollama v0.14.0+ with Anthropic API compatibility
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,16 @@ When test progress increases, the agent sends:
}
```

### Alternative API Providers (GLM, Ollama, Kimi, Custom)
### Alternative API Providers (GLM, Ollama, Kimi, OrcaRouter, Custom)

Alternative providers are configured via the **Settings UI** (gear icon > API Provider). Select your provider, set the base URL, auth token, and model directly in the UI — no `.env` changes needed.

Available providers: **Claude** (default), **GLM** (Zhipu AI), **Ollama** (local models), **Kimi** (Moonshot), **Custom**
Available providers: **Claude** (default), **GLM** (Zhipu AI), **Ollama** (local models), **Kimi** (Moonshot), **OrcaRouter**, **Custom**

For Ollama, install [Ollama v0.14.0+](https://ollama.com), run `ollama serve`, and pull a coding model (e.g., `ollama pull qwen3-coder`). Then select "Ollama" in the Settings UI.

For OrcaRouter, get an API key at [https://www.orcarouter.ai](https://www.orcarouter.ai), then select "OrcaRouter" in the Settings UI and paste your API key. OrcaRouter routes to Claude and other models through a unified Anthropic-compatible endpoint (`https://api.orcarouter.ai/v1/messages`).

### Using Vertex AI

Add these variables to your `.env` file to run agents via Google Cloud Vertex AI:
Expand Down
2 changes: 1 addition & 1 deletion client.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def create_client(
}
# Build environment overrides for API endpoint configuration
# Uses get_effective_sdk_env() which reads provider settings from the database,
# ensuring UI-configured alternative providers (GLM, Ollama, Kimi, Custom) propagate
# ensuring UI-configured alternative providers (GLM, Ollama, Kimi, OrcaRouter, Custom) propagate
# correctly to the Claude CLI subprocess
from registry import get_effective_sdk_env, get_effort_setting
sdk_env = get_effective_sdk_env()
Expand Down
12 changes: 12 additions & 0 deletions registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,18 @@ def get_all_settings() -> dict[str, str]:
],
"default_model": "qwen3-coder",
},
"orcarouter": {
"name": "OrcaRouter",
"base_url": "https://api.orcarouter.ai",
"requires_auth": True,
"auth_env_var": "ANTHROPIC_AUTH_TOKEN",
"models": [
{"id": "anthropic/claude-opus-5", "name": "Claude Opus"},
{"id": "anthropic/claude-sonnet-5", "name": "Claude Sonnet"},
{"id": "anthropic/claude-haiku-4.5", "name": "Claude Haiku"},
],
"default_model": "anthropic/claude-sonnet-5",
},
"custom": {
"name": "Custom Provider",
"base_url": "",
Expand Down
4 changes: 4 additions & 0 deletions server/routers/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,14 @@ async def get_settings():

glm_mode = api_provider == "glm"
ollama_mode = api_provider == "ollama"
orcarouter_mode = api_provider == "orcarouter"

return SettingsResponse(
yolo_mode=_parse_yolo_mode(all_settings.get("yolo_mode")),
model=all_settings.get("model", DEFAULT_MODEL),
glm_mode=glm_mode,
ollama_mode=ollama_mode,
orcarouter_mode=orcarouter_mode,
testing_agent_ratio=_parse_int(all_settings.get("testing_agent_ratio"), 1),
playwright_headless=True, # Always headless - embedded browser view replaces desktop windows
batch_size=_parse_int(all_settings.get("batch_size"), 3),
Expand Down Expand Up @@ -179,12 +181,14 @@ async def update_settings(update: SettingsUpdate):
api_provider = all_settings.get("api_provider", "claude")
glm_mode = api_provider == "glm"
ollama_mode = api_provider == "ollama"
orcarouter_mode = api_provider == "orcarouter"

return SettingsResponse(
yolo_mode=_parse_yolo_mode(all_settings.get("yolo_mode")),
model=all_settings.get("model", DEFAULT_MODEL),
glm_mode=glm_mode,
ollama_mode=ollama_mode,
orcarouter_mode=orcarouter_mode,
testing_agent_ratio=_parse_int(all_settings.get("testing_agent_ratio"), 1),
playwright_headless=True, # Always headless - embedded browser view replaces desktop windows
batch_size=_parse_int(all_settings.get("batch_size"), 3),
Expand Down
1 change: 1 addition & 0 deletions server/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class SettingsResponse(BaseModel):
model: str = DEFAULT_MODEL
glm_mode: bool = False # True when api_provider is "glm"
ollama_mode: bool = False # True when api_provider is "ollama"
orcarouter_mode: bool = False # True when api_provider is "orcarouter"
testing_agent_ratio: int = 1 # Regression testing agents (0-3)
playwright_headless: bool = True
batch_size: int = 3 # Features per coding agent batch (1-15)
Expand Down
1 change: 1 addition & 0 deletions ui/src/components/SettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const PROVIDER_INFO_TEXT: Record<string, string> = {
kimi: 'Get an API key at kimi.com',
glm: 'Get an API key at open.bigmodel.cn',
ollama: 'Run models locally. Install from ollama.com',
orcarouter: 'Get an API key at https://www.orcarouter.ai',
custom: 'Connect to any OpenAI-compatible API endpoint.',
}

Expand Down
6 changes: 6 additions & 0 deletions ui/src/components/layout/ControlBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export function ControlBar() {
</Badge>
)}

{settings?.orcarouter_mode && (
<Badge className="hidden sm:inline-flex bg-slate-700 text-white hover:bg-slate-800 text-[11px]">
OrcaRouter
</Badge>
)}

<Tooltip>
<TooltipTrigger asChild>
<Button
Expand Down
1 change: 1 addition & 0 deletions ui/src/components/views/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const PROVIDER_INFO_TEXT: Record<string, string> = {
kimi: 'Get an API key at kimi.com',
glm: 'Get an API key at open.bigmodel.cn',
ollama: 'Run models locally. Install from ollama.com',
orcarouter: 'Get an API key at https://www.orcarouter.ai',
custom: 'Connect to any OpenAI-compatible API endpoint.',
}

Expand Down
1 change: 1 addition & 0 deletions ui/src/hooks/useProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ const DEFAULT_SETTINGS: Settings = {
model: 'claude-opus-4-7',
glm_mode: false,
ollama_mode: false,
orcarouter_mode: false,
testing_agent_ratio: 1,
playwright_headless: true,
batch_size: 3,
Expand Down
1 change: 1 addition & 0 deletions ui/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ export interface Settings {
model: string
glm_mode: boolean
ollama_mode: boolean
orcarouter_mode: boolean
testing_agent_ratio: number // Regression testing agents (0-3)
playwright_headless: boolean
batch_size: number // Features per coding agent batch (1-15)
Expand Down