Skip to content

Commit 3b32e7f

Browse files
committed
feat: add OpenRouter provider support (200+ models, pay-per-use, free tier)
1 parent 8e3048d commit 3b32e7f

4 files changed

Lines changed: 23 additions & 5 deletions

File tree

deepworm/__main__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,7 @@ def _show_models_interactive(config: "Config") -> None:
16661666
"openai": ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-3.5-turbo"],
16671667
"anthropic": ["claude-sonnet-4-20250514", "claude-3-5-sonnet-20241022", "claude-3-haiku-20240307"],
16681668
"google": ["gemini-2.5-flash-lite", "gemini-2.5-flash", "gemini-2.5-pro", "gemini-2.0-flash", "gemini-3-flash-preview"],
1669+
"openrouter": ["google/gemini-2.0-flash-exp:free", "google/gemini-2.5-flash-preview-05-20", "meta-llama/llama-3.1-8b-instruct:free", "microsoft/phi-3-mini-128k-instruct:free", "deepseek/deepseek-r1:free"],
16691670
"ollama": ["llama3.2", "llama3.1", "mistral", "codellama", "phi3", "qwen2.5"],
16701671
}
16711672

@@ -1706,7 +1707,7 @@ def _handle_set_command(user_input: str, config: "Config") -> None:
17061707
value = parts[2].strip()
17071708

17081709
if key == "provider":
1709-
valid = ("openai", "anthropic", "google", "ollama")
1710+
valid = ("openai", "anthropic", "google", "openrouter", "ollama")
17101711
if value not in valid:
17111712
console.print(f" [yellow]Valid providers: {', '.join(valid)}[/yellow]")
17121713
return

deepworm/config.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ def from_env(cls, **overrides: Any) -> "Config":
7979

8080
def _detect_provider(self):
8181
"""Auto-detect provider from environment variables."""
82-
if os.getenv("OPENAI_API_KEY"):
82+
if os.getenv("OPENROUTER_API_KEY"):
83+
self.provider = "openrouter"
84+
self.api_key = os.getenv("OPENROUTER_API_KEY")
85+
self.base_url = "https://openrouter.ai/api/v1"
86+
elif os.getenv("OPENAI_API_KEY"):
8387
self.provider = "openai"
8488
self.api_key = os.getenv("OPENAI_API_KEY")
8589
elif os.getenv("ANTHROPIC_API_KEY"):
@@ -100,6 +104,7 @@ def _default_model(self, provider: str | None = None) -> str:
100104
"openai": "gpt-4o-mini",
101105
"anthropic": "claude-3-5-haiku-latest",
102106
"google": "gemini-2.5-flash-lite",
107+
"openrouter": "google/gemini-2.0-flash-exp:free",
103108
"ollama": "llama3.2",
104109
}
105110
return defaults.get(provider or self.provider, "gpt-4o-mini")
@@ -114,7 +119,7 @@ def validate(self) -> None:
114119
Raises:
115120
ValueError: If any configuration value is invalid.
116121
"""
117-
VALID_PROVIDERS = {"openai", "anthropic", "google", "ollama"}
122+
VALID_PROVIDERS = {"openai", "anthropic", "google", "openrouter", "ollama"}
118123
VALID_FORMATS = {"markdown", "html", "text", "json", "pdf"}
119124
VALID_SEARCH_PROVIDERS = {"duckduckgo", "brave", "searxng"}
120125

deepworm/llm.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,22 @@ def get_client(config: Config) -> "LLMClient":
133133
hint="Set GOOGLE_API_KEY environment variable or add api_key to config file",
134134
)
135135
return GoogleClient(api_key=api_key, model=config.model)
136+
elif provider == "openrouter":
137+
api_key = config.api_key or os.environ.get("OPENROUTER_API_KEY", "")
138+
if not api_key:
139+
raise APIKeyError(
140+
"OpenRouter API key not found",
141+
hint="Set OPENROUTER_API_KEY environment variable or add api_key to config file",
142+
)
143+
return OpenAICompatibleClient(
144+
api_key=api_key,
145+
base_url=config.base_url or "https://openrouter.ai/api/v1",
146+
model=config.model,
147+
)
136148
else:
137149
raise ProviderError(
138150
f"Unknown provider: {provider}",
139-
hint="Supported providers: openai, anthropic, google, ollama",
151+
hint="Supported providers: openai, anthropic, google, openrouter, ollama",
140152
)
141153

142154

tests/test_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
def test_default_config():
1010
"""Config should auto-detect provider."""
1111
config = Config.auto()
12-
assert config.provider in ("openai", "anthropic", "google", "ollama")
12+
assert config.provider in ("openai", "anthropic", "google", "openrouter", "ollama")
1313
assert config.model is not None
1414
assert config.depth == 1
1515
assert config.breadth == 1

0 commit comments

Comments
 (0)