sync: 159 file da Baida98/AI@3e4accc9 (2026-08-16 08:10 UTC) [deploy-all]

#43
by Baida07 - opened
models/ai_client.py CHANGED
@@ -87,8 +87,22 @@ class AIClient:
87
  truth dichiarata in supabase/migrations/20260711_ai_providers_fleet.sql),
88
  fallback sui provider reali via env se Supabase non è raggiungibile/vuoto
89
  (es. progetto sospeso per fatturazione, tabella non ancora popolata)."""
90
- providers = self._try_load_from_supabase()
91
- return providers if providers else self._discover_providers_from_env()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  @staticmethod
94
  def _runtime_model_override(row: dict) -> str:
 
87
  truth dichiarata in supabase/migrations/20260711_ai_providers_fleet.sql),
88
  fallback sui provider reali via env se Supabase non è raggiungibile/vuoto
89
  (es. progetto sospeso per fatturazione, tabella non ancora popolata)."""
90
+ database_providers = self._try_load_from_supabase()
91
+ environment_profiles = [
92
+ profile
93
+ for definition in _PROVIDER_DEFS
94
+ for profile in self._profile_rows_from_env(definition)
95
+ ]
96
+ if environment_profiles:
97
+ profiled_names = {profile.name for profile in environment_profiles}
98
+ # Explicit profile pools override a same-provider Supabase credential;
99
+ # DB providers not covered by a pool remain available as fallbacks.
100
+ database_providers = [
101
+ provider for provider in database_providers
102
+ if provider.name not in profiled_names
103
+ ]
104
+ return environment_profiles + database_providers
105
+ return database_providers or self._discover_providers_from_env()
106
 
107
  @staticmethod
108
  def _runtime_model_override(row: dict) -> str:
tests/test_provider_profile_pool.py CHANGED
@@ -22,8 +22,8 @@ class ProviderProfilePoolTests(unittest.TestCase):
22
  with patch.dict(os.environ, {"OPENROUTER_PROFILES_JSON": raw, "OPENROUTER_API_KEY": "legacy-key"}, clear=True):
23
  client = AIClient()
24
  profiles = [p for p in client.providers if p.name == "openrouter"]
25
- self.assertEqual([p.profile for p in profiles], ["primary", "backup", "legacy"])
26
- self.assertEqual([p.api_key for p in profiles], ["profile-key-1", "profile-key-2", "legacy-key"])
27
 
28
  def test_profile_json_is_supported_for_every_provider(self):
29
  env = {
@@ -39,6 +39,22 @@ class ProviderProfilePoolTests(unittest.TestCase):
39
  profiles = [p for p in client.providers if p.name == definition["name"]]
40
  self.assertEqual([p.profile for p in profiles], ["primary", "backup"])
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  def test_profiles_have_distinct_client_cache_entries(self):
43
  client = AIClient()
44
  first, second = self._profiles()[:2]
 
22
  with patch.dict(os.environ, {"OPENROUTER_PROFILES_JSON": raw, "OPENROUTER_API_KEY": "legacy-key"}, clear=True):
23
  client = AIClient()
24
  profiles = [p for p in client.providers if p.name == "openrouter"]
25
+ self.assertEqual([p.profile for p in profiles], ["primary", "backup"])
26
+ self.assertEqual([p.api_key for p in profiles], ["profile-key-1", "profile-key-2"])
27
 
28
  def test_profile_json_is_supported_for_every_provider(self):
29
  env = {
 
39
  profiles = [p for p in client.providers if p.name == definition["name"]]
40
  self.assertEqual([p.profile for p in profiles], ["primary", "backup"])
41
 
42
+ def test_environment_pool_overrides_same_provider_database_row(self):
43
+ raw = json.dumps([
44
+ {"profile": "primary", "api_key": "profile-key-1"},
45
+ {"profile": "backup", "api_key": "profile-key-2"},
46
+ ])
47
+ database_row = ProviderConfig(
48
+ name="openrouter", api_key="database-key",
49
+ base_url="https://openrouter.ai/api/v1", profile="db-1",
50
+ )
51
+ with patch.dict(os.environ, {"OPENROUTER_PROFILES_JSON": raw}, clear=True), \
52
+ patch.object(AIClient, "_try_load_from_supabase", return_value=[database_row]):
53
+ client = AIClient()
54
+ profiles = [p for p in client.providers if p.name == "openrouter"]
55
+ self.assertEqual([p.profile for p in profiles], ["primary", "backup"])
56
+ self.assertNotIn("database-key", [p.api_key for p in profiles])
57
+
58
  def test_profiles_have_distinct_client_cache_entries(self):
59
  client = AIClient()
60
  first, second = self._profiles()[:2]