Fixed restriction checks for OpenRouter
This commit is contained in:
@@ -14,7 +14,7 @@ import os
|
|||||||
# These values are used in server responses and for tracking releases
|
# These values are used in server responses and for tracking releases
|
||||||
# IMPORTANT: This is the single source of truth for version and author info
|
# IMPORTANT: This is the single source of truth for version and author info
|
||||||
# Semantic versioning: MAJOR.MINOR.PATCH
|
# Semantic versioning: MAJOR.MINOR.PATCH
|
||||||
__version__ = "5.6.1"
|
__version__ = "5.6.2"
|
||||||
# Last update date in ISO format
|
# Last update date in ISO format
|
||||||
__updated__ = "2025-06-23"
|
__updated__ = "2025-06-23"
|
||||||
# Primary maintainer
|
# Primary maintainer
|
||||||
|
|||||||
@@ -50,14 +50,6 @@ class OpenRouterProvider(OpenAICompatibleProvider):
|
|||||||
aliases = self._registry.list_aliases()
|
aliases = self._registry.list_aliases()
|
||||||
logging.info(f"OpenRouter loaded {len(models)} models with {len(aliases)} aliases")
|
logging.info(f"OpenRouter loaded {len(models)} models with {len(aliases)} aliases")
|
||||||
|
|
||||||
def _parse_allowed_models(self) -> None:
|
|
||||||
"""Override to disable environment-based allow-list.
|
|
||||||
|
|
||||||
OpenRouter model access is controlled via the OpenRouter dashboard,
|
|
||||||
not through environment variables.
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _resolve_model_name(self, model_name: str) -> str:
|
def _resolve_model_name(self, model_name: str) -> str:
|
||||||
"""Resolve model aliases to OpenRouter model names.
|
"""Resolve model aliases to OpenRouter model names.
|
||||||
|
|
||||||
@@ -130,16 +122,34 @@ class OpenRouterProvider(OpenAICompatibleProvider):
|
|||||||
|
|
||||||
As the catch-all provider, OpenRouter accepts any model name that wasn't
|
As the catch-all provider, OpenRouter accepts any model name that wasn't
|
||||||
handled by higher-priority providers. OpenRouter will validate based on
|
handled by higher-priority providers. OpenRouter will validate based on
|
||||||
the API key's permissions.
|
the API key's permissions and local restrictions.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
model_name: Model name to validate
|
model_name: Model name to validate
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Always True - OpenRouter is the catch-all provider
|
True if model is allowed, False if restricted
|
||||||
"""
|
"""
|
||||||
# Accept any model name - OpenRouter is the fallback provider
|
# Check model restrictions if configured
|
||||||
# Higher priority providers (native APIs, custom endpoints) get first chance
|
from utils.model_restrictions import get_restriction_service
|
||||||
|
|
||||||
|
restriction_service = get_restriction_service()
|
||||||
|
if restriction_service:
|
||||||
|
# Check if model name itself is allowed
|
||||||
|
if restriction_service.is_allowed(self.get_provider_type(), model_name):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Also check aliases - model_name might be an alias
|
||||||
|
model_config = self._registry.resolve(model_name)
|
||||||
|
if model_config and model_config.aliases:
|
||||||
|
for alias in model_config.aliases:
|
||||||
|
if restriction_service.is_allowed(self.get_provider_type(), alias):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If restrictions are configured and model/alias not in allowed list, reject
|
||||||
|
return False
|
||||||
|
|
||||||
|
# No restrictions configured - accept any model name as the fallback provider
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def generate_content(
|
def generate_content(
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ class ModelProviderRegistry:
|
|||||||
logging.debug(f"Available providers in registry: {list(instance._providers.keys())}")
|
logging.debug(f"Available providers in registry: {list(instance._providers.keys())}")
|
||||||
|
|
||||||
for provider_type in PROVIDER_PRIORITY_ORDER:
|
for provider_type in PROVIDER_PRIORITY_ORDER:
|
||||||
logging.debug(f"Checking provider_type: {provider_type}")
|
|
||||||
if provider_type in instance._providers:
|
if provider_type in instance._providers:
|
||||||
logging.debug(f"Found {provider_type} in registry")
|
logging.debug(f"Found {provider_type} in registry")
|
||||||
# Get or create provider instance
|
# Get or create provider instance
|
||||||
|
|||||||
16
server.py
16
server.py
@@ -673,6 +673,11 @@ def parse_model_option(model_string: str) -> tuple[str, Optional[str]]:
|
|||||||
"""
|
"""
|
||||||
Parse model:option format into model name and option.
|
Parse model:option format into model name and option.
|
||||||
|
|
||||||
|
Handles different formats:
|
||||||
|
- OpenRouter models: preserve :free, :beta, :preview suffixes as part of model name
|
||||||
|
- Ollama/Custom models: split on : to extract tags like :latest
|
||||||
|
- Consensus stance: extract options like :for, :against
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
model_string: String that may contain "model:option" format
|
model_string: String that may contain "model:option" format
|
||||||
|
|
||||||
@@ -680,6 +685,17 @@ def parse_model_option(model_string: str) -> tuple[str, Optional[str]]:
|
|||||||
tuple: (model_name, option) where option may be None
|
tuple: (model_name, option) where option may be None
|
||||||
"""
|
"""
|
||||||
if ":" in model_string and not model_string.startswith("http"): # Avoid parsing URLs
|
if ":" in model_string and not model_string.startswith("http"): # Avoid parsing URLs
|
||||||
|
# Check if this looks like an OpenRouter model (contains /)
|
||||||
|
if "/" in model_string and model_string.count(":") == 1:
|
||||||
|
# Could be openai/gpt-4:something - check what comes after colon
|
||||||
|
parts = model_string.split(":", 1)
|
||||||
|
suffix = parts[1].strip().lower()
|
||||||
|
|
||||||
|
# Known OpenRouter suffixes to preserve
|
||||||
|
if suffix in ["free", "beta", "preview"]:
|
||||||
|
return model_string.strip(), None
|
||||||
|
|
||||||
|
# For other patterns (Ollama tags, consensus stances), split normally
|
||||||
parts = model_string.split(":", 1)
|
parts = model_string.split(":", 1)
|
||||||
model_name = parts[0].strip()
|
model_name = parts[0].strip()
|
||||||
model_option = parts[1].strip() if len(parts) > 1 else None
|
model_option = parts[1].strip() if len(parts) > 1 else None
|
||||||
|
|||||||
@@ -45,10 +45,17 @@ class TestCustomProvider:
|
|||||||
|
|
||||||
def test_get_capabilities_from_registry(self):
|
def test_get_capabilities_from_registry(self):
|
||||||
"""Test get_capabilities returns registry capabilities when available."""
|
"""Test get_capabilities returns registry capabilities when available."""
|
||||||
|
# Save original environment
|
||||||
|
original_env = os.environ.get("OPENROUTER_ALLOWED_MODELS")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Clear any restrictions
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None)
|
||||||
|
|
||||||
provider = CustomProvider(api_key="test-key", base_url="http://localhost:11434/v1")
|
provider = CustomProvider(api_key="test-key", base_url="http://localhost:11434/v1")
|
||||||
|
|
||||||
# Test with a model that should be in the registry (OpenRouter model) and is allowed by restrictions
|
# Test with a model that should be in the registry (OpenRouter model)
|
||||||
capabilities = provider.get_capabilities("o3") # o3 is in OPENROUTER_ALLOWED_MODELS
|
capabilities = provider.get_capabilities("o3") # o3 is an OpenRouter model
|
||||||
|
|
||||||
assert capabilities.provider == ProviderType.OPENROUTER # o3 is an OpenRouter model (is_custom=false)
|
assert capabilities.provider == ProviderType.OPENROUTER # o3 is an OpenRouter model (is_custom=false)
|
||||||
assert capabilities.context_window > 0
|
assert capabilities.context_window > 0
|
||||||
@@ -58,6 +65,13 @@ class TestCustomProvider:
|
|||||||
assert capabilities.provider == ProviderType.CUSTOM # local-llama has is_custom=true
|
assert capabilities.provider == ProviderType.CUSTOM # local-llama has is_custom=true
|
||||||
assert capabilities.context_window > 0
|
assert capabilities.context_window > 0
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Restore original environment
|
||||||
|
if original_env is None:
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None)
|
||||||
|
else:
|
||||||
|
os.environ["OPENROUTER_ALLOWED_MODELS"] = original_env
|
||||||
|
|
||||||
def test_get_capabilities_generic_fallback(self):
|
def test_get_capabilities_generic_fallback(self):
|
||||||
"""Test get_capabilities returns generic capabilities for unknown models."""
|
"""Test get_capabilities returns generic capabilities for unknown models."""
|
||||||
provider = CustomProvider(api_key="test-key", base_url="http://localhost:11434/v1")
|
provider = CustomProvider(api_key="test-key", base_url="http://localhost:11434/v1")
|
||||||
|
|||||||
79
tests/test_parse_model_option.py
Normal file
79
tests/test_parse_model_option.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
"""Tests for parse_model_option function."""
|
||||||
|
|
||||||
|
from server import parse_model_option
|
||||||
|
|
||||||
|
|
||||||
|
class TestParseModelOption:
|
||||||
|
"""Test cases for model option parsing."""
|
||||||
|
|
||||||
|
def test_openrouter_free_suffix_preserved(self):
|
||||||
|
"""Test that OpenRouter :free suffix is preserved as part of model name."""
|
||||||
|
model, option = parse_model_option("openai/gpt-3.5-turbo:free")
|
||||||
|
assert model == "openai/gpt-3.5-turbo:free"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
def test_openrouter_beta_suffix_preserved(self):
|
||||||
|
"""Test that OpenRouter :beta suffix is preserved as part of model name."""
|
||||||
|
model, option = parse_model_option("anthropic/claude-3-opus:beta")
|
||||||
|
assert model == "anthropic/claude-3-opus:beta"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
def test_openrouter_preview_suffix_preserved(self):
|
||||||
|
"""Test that OpenRouter :preview suffix is preserved as part of model name."""
|
||||||
|
model, option = parse_model_option("google/gemini-pro:preview")
|
||||||
|
assert model == "google/gemini-pro:preview"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
def test_ollama_tag_parsed_as_option(self):
|
||||||
|
"""Test that Ollama tags are parsed as options."""
|
||||||
|
model, option = parse_model_option("llama3.2:latest")
|
||||||
|
assert model == "llama3.2"
|
||||||
|
assert option == "latest"
|
||||||
|
|
||||||
|
def test_consensus_stance_parsed_as_option(self):
|
||||||
|
"""Test that consensus stances are parsed as options."""
|
||||||
|
model, option = parse_model_option("o3:for")
|
||||||
|
assert model == "o3"
|
||||||
|
assert option == "for"
|
||||||
|
|
||||||
|
model, option = parse_model_option("gemini-2.5-pro:against")
|
||||||
|
assert model == "gemini-2.5-pro"
|
||||||
|
assert option == "against"
|
||||||
|
|
||||||
|
def test_openrouter_unknown_suffix_parsed_as_option(self):
|
||||||
|
"""Test that unknown suffixes on OpenRouter models are parsed as options."""
|
||||||
|
model, option = parse_model_option("openai/gpt-4:custom-tag")
|
||||||
|
assert model == "openai/gpt-4"
|
||||||
|
assert option == "custom-tag"
|
||||||
|
|
||||||
|
def test_plain_model_name(self):
|
||||||
|
"""Test plain model names without colons."""
|
||||||
|
model, option = parse_model_option("gpt-4")
|
||||||
|
assert model == "gpt-4"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
def test_url_not_parsed(self):
|
||||||
|
"""Test that URLs are not parsed for options."""
|
||||||
|
model, option = parse_model_option("http://localhost:8080")
|
||||||
|
assert model == "http://localhost:8080"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
def test_whitespace_handling(self):
|
||||||
|
"""Test that whitespace is properly stripped."""
|
||||||
|
model, option = parse_model_option(" openai/gpt-3.5-turbo:free ")
|
||||||
|
assert model == "openai/gpt-3.5-turbo:free"
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
model, option = parse_model_option(" llama3.2 : latest ")
|
||||||
|
assert model == "llama3.2"
|
||||||
|
assert option == "latest"
|
||||||
|
|
||||||
|
def test_case_insensitive_suffix_matching(self):
|
||||||
|
"""Test that OpenRouter suffix matching is case-insensitive."""
|
||||||
|
model, option = parse_model_option("openai/gpt-3.5-turbo:FREE")
|
||||||
|
assert model == "openai/gpt-3.5-turbo:FREE" # Original case preserved
|
||||||
|
assert option is None
|
||||||
|
|
||||||
|
model, option = parse_model_option("openai/gpt-3.5-turbo:Free")
|
||||||
|
assert model == "openai/gpt-3.5-turbo:Free" # Original case preserved
|
||||||
|
assert option is None
|
||||||
@@ -58,7 +58,13 @@ class TestProviderRoutingBugs:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -66,6 +72,7 @@ class TestProviderRoutingBugs:
|
|||||||
os.environ.pop("GEMINI_API_KEY", None) # No Google API key
|
os.environ.pop("GEMINI_API_KEY", None) # No Google API key
|
||||||
os.environ.pop("OPENAI_API_KEY", None)
|
os.environ.pop("OPENAI_API_KEY", None)
|
||||||
os.environ.pop("XAI_API_KEY", None)
|
os.environ.pop("XAI_API_KEY", None)
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) # Clear any restrictions
|
||||||
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
||||||
|
|
||||||
# Register only OpenRouter provider (like in server.py:configure_providers)
|
# Register only OpenRouter provider (like in server.py:configure_providers)
|
||||||
@@ -113,12 +120,24 @@ class TestProviderRoutingBugs:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Set up scenario: NO API keys at all
|
# Set up scenario: NO API keys at all
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
os.environ.pop(key, None)
|
os.environ.pop(key, None)
|
||||||
|
|
||||||
# Create tool to test fallback logic
|
# Create tool to test fallback logic
|
||||||
@@ -151,7 +170,13 @@ class TestProviderRoutingBugs:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -160,6 +185,7 @@ class TestProviderRoutingBugs:
|
|||||||
os.environ["OPENAI_API_KEY"] = "test-openai-key"
|
os.environ["OPENAI_API_KEY"] = "test-openai-key"
|
||||||
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
||||||
os.environ.pop("XAI_API_KEY", None)
|
os.environ.pop("XAI_API_KEY", None)
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) # Clear any restrictions
|
||||||
|
|
||||||
# Register providers in priority order (like server.py)
|
# Register providers in priority order (like server.py)
|
||||||
from providers.gemini import GeminiModelProvider
|
from providers.gemini import GeminiModelProvider
|
||||||
|
|||||||
@@ -48,7 +48,13 @@ class TestWorkflowMetadata:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -56,6 +62,7 @@ class TestWorkflowMetadata:
|
|||||||
os.environ.pop("GEMINI_API_KEY", None)
|
os.environ.pop("GEMINI_API_KEY", None)
|
||||||
os.environ.pop("OPENAI_API_KEY", None)
|
os.environ.pop("OPENAI_API_KEY", None)
|
||||||
os.environ.pop("XAI_API_KEY", None)
|
os.environ.pop("XAI_API_KEY", None)
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) # Clear any restrictions
|
||||||
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
||||||
|
|
||||||
# Register OpenRouter provider
|
# Register OpenRouter provider
|
||||||
@@ -124,7 +131,13 @@ class TestWorkflowMetadata:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -132,6 +145,7 @@ class TestWorkflowMetadata:
|
|||||||
os.environ.pop("GEMINI_API_KEY", None)
|
os.environ.pop("GEMINI_API_KEY", None)
|
||||||
os.environ.pop("OPENAI_API_KEY", None)
|
os.environ.pop("OPENAI_API_KEY", None)
|
||||||
os.environ.pop("XAI_API_KEY", None)
|
os.environ.pop("XAI_API_KEY", None)
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) # Clear any restrictions
|
||||||
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
||||||
|
|
||||||
# Register OpenRouter provider
|
# Register OpenRouter provider
|
||||||
@@ -182,6 +196,15 @@ class TestWorkflowMetadata:
|
|||||||
"""
|
"""
|
||||||
Test that workflow tools handle metadata gracefully when model context is missing.
|
Test that workflow tools handle metadata gracefully when model context is missing.
|
||||||
"""
|
"""
|
||||||
|
# Save original environment
|
||||||
|
original_env = {}
|
||||||
|
for key in ["OPENROUTER_ALLOWED_MODELS"]:
|
||||||
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Clear any restrictions
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None)
|
||||||
|
|
||||||
# Create debug tool
|
# Create debug tool
|
||||||
debug_tool = DebugIssueTool()
|
debug_tool = DebugIssueTool()
|
||||||
|
|
||||||
@@ -220,6 +243,14 @@ class TestWorkflowMetadata:
|
|||||||
assert metadata["model_used"] == "flash", "model_used should be from request"
|
assert metadata["model_used"] == "flash", "model_used should be from request"
|
||||||
assert metadata["provider_used"] == "unknown", "provider_used should be 'unknown' in fallback"
|
assert metadata["provider_used"] == "unknown", "provider_used should be 'unknown' in fallback"
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Restore original environment
|
||||||
|
for key, value in original_env.items():
|
||||||
|
if value is None:
|
||||||
|
os.environ.pop(key, None)
|
||||||
|
else:
|
||||||
|
os.environ[key] = value
|
||||||
|
|
||||||
@pytest.mark.no_mock_provider
|
@pytest.mark.no_mock_provider
|
||||||
def test_workflow_metadata_preserves_existing_response_fields(self):
|
def test_workflow_metadata_preserves_existing_response_fields(self):
|
||||||
"""
|
"""
|
||||||
@@ -227,7 +258,13 @@ class TestWorkflowMetadata:
|
|||||||
"""
|
"""
|
||||||
# Save original environment
|
# Save original environment
|
||||||
original_env = {}
|
original_env = {}
|
||||||
for key in ["GEMINI_API_KEY", "OPENAI_API_KEY", "XAI_API_KEY", "OPENROUTER_API_KEY"]:
|
for key in [
|
||||||
|
"GEMINI_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"XAI_API_KEY",
|
||||||
|
"OPENROUTER_API_KEY",
|
||||||
|
"OPENROUTER_ALLOWED_MODELS",
|
||||||
|
]:
|
||||||
original_env[key] = os.environ.get(key)
|
original_env[key] = os.environ.get(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -235,6 +272,7 @@ class TestWorkflowMetadata:
|
|||||||
os.environ.pop("GEMINI_API_KEY", None)
|
os.environ.pop("GEMINI_API_KEY", None)
|
||||||
os.environ.pop("OPENAI_API_KEY", None)
|
os.environ.pop("OPENAI_API_KEY", None)
|
||||||
os.environ.pop("XAI_API_KEY", None)
|
os.environ.pop("XAI_API_KEY", None)
|
||||||
|
os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) # Clear any restrictions
|
||||||
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key"
|
||||||
|
|
||||||
# Register OpenRouter provider
|
# Register OpenRouter provider
|
||||||
|
|||||||
@@ -128,6 +128,10 @@ class ModelRestrictionService:
|
|||||||
|
|
||||||
allowed_set = self.restrictions[provider_type]
|
allowed_set = self.restrictions[provider_type]
|
||||||
|
|
||||||
|
if len(allowed_set) == 0:
|
||||||
|
# Empty set - allowed
|
||||||
|
return True
|
||||||
|
|
||||||
# Check both the resolved name and original name (if different)
|
# Check both the resolved name and original name (if different)
|
||||||
names_to_check = {model_name.lower()}
|
names_to_check = {model_name.lower()}
|
||||||
if original_name and original_name.lower() != model_name.lower():
|
if original_name and original_name.lower() != model_name.lower():
|
||||||
|
|||||||
Reference in New Issue
Block a user