diff --git a/ai-hub/app/core/services/preference.py b/ai-hub/app/core/services/preference.py index 22179c9..7c4fe55 100644 --- a/ai-hub/app/core/services/preference.py +++ b/ai-hub/app/core/services/preference.py @@ -95,23 +95,28 @@ def get_merged_system_defaults(section_name, hardcoded_defaults): # M6/M3: Merge Admin overrides with hardcoded config.yaml defaults. - # This prevents the admin from losing system-level keys when they - # customize other fields (like model names) in the UI. + # If the admin has configured ANY providers in the DB, we treat the DB + # as the Source of Truth for the LIST of available providers. + # We only use hardcoded_defaults to backfill missing fields (like API keys) + # for the providers that are present in the DB. sys_prefs_section = system_prefs.get(section_name, {}) sys_providers = sys_prefs_section.get("providers", {}) if not sys_providers: + # If nothing in DB, fall back to everything in config.yaml/env return hardcoded_defaults - # Start with hardcoded defaults - merged = copy.deepcopy(hardcoded_defaults) - for p_id, p_data in sys_providers.items(): - if p_id not in merged: - merged[p_id] = p_data - else: - for field, val in p_data.items(): - if val is not None and val != "" and str(val).lower() != "none": - merged[p_id][field] = val + # Start with the list of providers defined in the DB + merged = copy.deepcopy(sys_providers) + + # Backfill secrets/defaults from hardcoded config for these specific providers + for p_id, p_data in merged.items(): + if p_id in hardcoded_defaults: + for field, val in hardcoded_defaults[p_id].items(): + # Only backfill if the DB value is missing or effectively empty + db_val = p_data.get(field) + if db_val is None or db_val == "" or str(db_val).lower() == "none": + p_data[field] = val return merged system_llm = get_merged_system_defaults("llm", settings.LLM_PROVIDERS)