You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
4.6 KiB
113 lines
4.6 KiB
|
|
import '../../../data/models/appconfig_model.dart';
|
|
|
|
class AppConfig {
|
|
static late UserGetAppConfigResp config;
|
|
|
|
// 新增一个私有的静态布尔值来跟踪初始化状态
|
|
static bool _isInitialized = false;
|
|
|
|
/// 检查AppConfig单例是否已经被初始化
|
|
/// 外部通过调用此方法来安全地检查状态
|
|
static bool isInitialized() {
|
|
return _isInitialized;
|
|
}
|
|
|
|
// 可选:提供初始化方法
|
|
static void initialize(UserGetAppConfigResp resp) {
|
|
config = resp;
|
|
_isInitialized = true; // <-- 新增此行
|
|
}
|
|
|
|
//环境变量(应用参数 + 老客户端兼容层)
|
|
static String? env(String key) {
|
|
return config.env[key];
|
|
}
|
|
|
|
// ───── 第三方服务(结构化,2026-09-14 起凭据的首选来源)─────
|
|
//
|
|
// 后台「服务与环境配置 → 第三方服务」每个应用一套;服务端按用户区域合并区域分叉、解密后经加密的
|
|
// user_getappconfig_v3 下发为 thirdsvcs。各业务服务应改用 [cred] 取凭据:先查 thirdsvcs 的
|
|
// 「服务 id + 字段名」,取不到再退回 env[老键名]——这样对没配 GATEWAY_ENCRYPT_KEY、或还在跑旧版
|
|
// 服务端的环境也能继续工作,而不是一刀切断。
|
|
|
|
/// 按服务 id 取一条(如 'stt_azure')。未初始化或不存在返回 null。
|
|
static ThirdSvc? svc(String id) {
|
|
if (!_isInitialized) return null;
|
|
for (final s in config.thirdsvcs) {
|
|
if (s.id == id) return s;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// 某类别下的全部服务(类别 id 见 ThirdSvc 注释)。
|
|
static List<ThirdSvc> svcsByCategory(int cat) {
|
|
if (!_isInitialized) return const [];
|
|
return config.thirdsvcs.where((s) => s.hasCategory(cat)).toList();
|
|
}
|
|
|
|
/// 取某服务的某个字段;服务不存在、字段不存在或为空串都返回 null(空串等同没配)。
|
|
static String? field(String svcId, String fieldKey) {
|
|
final v = svc(svcId)?.fields[fieldKey]?.trim();
|
|
return (v == null || v.isEmpty) ? null : v;
|
|
}
|
|
|
|
/// 凭据读取入口:thirdsvcs 的 (svcId, fieldKey) 优先,退回 env[envKey]。
|
|
///
|
|
/// 返回 null 表示两边都没配。调用方自己决定 `?? ''` 还是 `?? 默认值`——
|
|
/// 别在这里给空串,那会把调用方的 `?? 默认值` 顶掉(AZURE_TRANSLATION_ENDPOINT 栽过)。
|
|
static String? cred(String svcId, String fieldKey, String envKey) {
|
|
final v = field(svcId, fieldKey);
|
|
if (v != null) return v;
|
|
final e = _isInitialized ? config.env[envKey]?.trim() : null;
|
|
return (e == null || e.isEmpty) ? null : e;
|
|
}
|
|
|
|
/// 当前是否已从结构化通道拿到凭据(用于日志/诊断:为 false 说明还在走 env 兼容层)。
|
|
static bool get usingThirdSvcs => _isInitialized && config.thirdsvcs.isNotEmpty;
|
|
|
|
//mcp配置
|
|
static dynamic mcpConfig() {
|
|
return {"mcpServers": config.mcps};
|
|
}
|
|
|
|
//智能体配置
|
|
///
|
|
/// 找不到该 agentId 时返回 null。**不要改回 `firstWhere`**——它没有 orElse,
|
|
/// 查不到时抛 StateError 而不是返回 null,调用方(ble_manager 的
|
|
/// startAgentService)那句 try 会把整个智能体服务的启动一起吞掉。
|
|
static String? agentsystemPrompt(String agentId) {
|
|
if (!_isInitialized) return null;
|
|
for (final agent in config.agents) {
|
|
if (agent.id == agentId) return agent.systemPrompt;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static List<String> allproductNames() {
|
|
List<String> names =
|
|
config.products.map((user) => user.devicename).toList();
|
|
return names;
|
|
}
|
|
|
|
/// 根据产品名称获取产品配置,查不到返回 null。
|
|
///
|
|
/// ⚠️ **不要改回 `firstWhere`**:它没有 orElse,查不到时抛 StateError 而不是
|
|
/// 返回 null。所有调用点写的都是 `if (product != null)`,那个 null 分支于是
|
|
/// 永远等不到,异常被外层 try 吞掉后直接走兜底——设备类型退化成 unknown、
|
|
/// 通话翻译的 broadcastpeertranslate 恒为 false,且全程不报任何错。
|
|
///
|
|
/// 未初始化(`user_getappconfig` 还没回来)时同样返回 null,而不是让
|
|
/// `late config` 抛 LateInitializationError——否则 null 契约仍然不成立。
|
|
///
|
|
/// 空设备名也返回 null:`devicename.contains('')` 恒为 true,原实现会把
|
|
/// **产品表里的第一个产品**当成匹配结果返回。调用点本来就都在紧接着判
|
|
/// `deviceName != ''`,没有一处依赖这个行为。
|
|
static DBProduct? getproduct(String name) {
|
|
if (!_isInitialized || name.isEmpty) return null;
|
|
for (final product in config.products) {
|
|
if (product.devicename.contains(name)) return product;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|