Провайдера, модель, baseUrl и API-ключ задаёт оператор: конфигурация хранится в public.global_settings (ключ aiConfig, шифрование enc:), читается общей для всех тенантов и используется AiProviderConfigBuilder во всех ИИ-вызовах. Настройки тенанта больше не содержат aiProvider/aiConfigs, пользовательский POST /api/ai/check удалён. Добавлены операторские ручки GET/PUT /api/operator/settings/ai-config и POST .../check с аудитом ai_config_changed.
30 lines
1.7 KiB
C#
30 lines
1.7 KiB
C#
namespace Deal.Modules.Settings.Application.Models;
|
|
|
|
/// <summary>
|
|
/// Снимок глобальной конфигурации ИИ-провайдера с расшифрованным ключом (только для внутреннего использования).
|
|
/// </summary>
|
|
/// <param name="ProviderId">Id провайдера из каталога <see cref="AiProviders"/>; пусто — конфигурация не задана.</param>
|
|
/// <param name="BaseUrl">Базовый URL API (эффективный: сохранённый или дефолт каталога).</param>
|
|
/// <param name="Model">Активная модель (эффективная: сохранённая или первая из каталога).</param>
|
|
/// <param name="ApiKey">API-ключ открытым текстом (пусто — не задан; локальным провайдерам не нужен).</param>
|
|
public sealed record AiGlobalConfigSnapshot(
|
|
string ProviderId,
|
|
string BaseUrl,
|
|
string Model,
|
|
string ApiKey)
|
|
{
|
|
/// <summary>
|
|
/// Провайдер каталога по <see cref="ProviderId"/> или null для неизвестного/незаданного id
|
|
/// </summary>
|
|
public AiProviderDefinition? Meta => AiProviders.All.FirstOrDefault(provider => provider.Id == ProviderId);
|
|
|
|
/// <summary>
|
|
/// Конфигурация готова к вызовам ИИ: провайдер известен, адрес и модель непустые,
|
|
/// ключ задан (или не нужен локальному провайдеру)
|
|
/// </summary>
|
|
public bool Configured => Meta is not null
|
|
&& BaseUrl.Length > 0
|
|
&& Model.Length > 0
|
|
&& (Meta.Local || ApiKey.Length > 0);
|
|
}
|