import Foundation /// 运行计算捕获的内存快照,不代表统一持久化文档。监听配置独立保存, /// 控制偏好由各命令更新;代理启动前从此快照派生完整运行配置。 struct ProxyRuntimeSettings: Equatable, Sendable { static let defaultProxyExceptions = "" var listen: ProxyListeningConfiguration /// User-added system-proxy exceptions; these entries do not become ACL rules. var proxyExceptions: String /// The persisted current mode: the mode selector's choice survives GUI /// restarts. First run defaults to rule mode. var preferredMode: ProxyModeKind /// 规则模式预设,首次启动默认为仅 GFW 列表内目标代理。 var rulePreset: RulePreset var ruleDefaultAction: RuleDefaultAction { rulePreset.defaultAction } /// 用户保存的代理服务意图,默认关闭,与当前运行健康状态独立。 var agentEnabled: Bool /// 系统代理意图:默认关闭;与 agent 意图相互独立,开关关闭 /// 关闭时清理匹配 NG2 端点的系统代理配置,不影响本地监听。 var systemProxyEnabled: Bool init( listen: ProxyListeningConfiguration = ProxyListeningConfiguration(), proxyExceptions: String = ProxyRuntimeSettings.defaultProxyExceptions, preferredMode: ProxyModeKind = .rule, rulePreset: RulePreset = .gfwlist, agentEnabled: Bool = false, systemProxyEnabled: Bool = false ) { self.listen = listen self.proxyExceptions = proxyExceptions self.preferredMode = preferredMode self.rulePreset = rulePreset self.agentEnabled = agentEnabled self.systemProxyEnabled = systemProxyEnabled } init(listen: ProxyListeningConfiguration, preferences: ProxyControlPreferences) { self.init( listen: listen, proxyExceptions: preferences.proxyExceptions, preferredMode: preferences.preferredMode, rulePreset: preferences.rulePreset, agentEnabled: preferences.agentEnabled, systemProxyEnabled: preferences.systemProxyEnabled) } /// 系统代理的 ExceptionsList;输入顺序保留,重复项只保留第一次出现的值。 var proxyExceptionList: [String] { var result: [String] = [] var seen = Set() for value in proxyExceptions.split(whereSeparator: { character in character == "," || character == "、" || character.isWhitespace }) { let item = String(value) let identity = item.lowercased() guard !item.isEmpty, seen.insert(identity).inserted else { continue } result.append(item) } return result } var validationErrors: [PortSettingError] { listen.portValidationErrors() } } struct RestoredProxyRuntimeSettings: Equatable { let settings: ProxyRuntimeSettings let unreadableError: ProxyListeningStoreError? }