@@ -1970,57 +1970,15 @@ extension TalkModeManager {
19701970 return trimmed
19711971 }
19721972
1973- struct TalkProviderConfigSelection {
1974- let provider : String
1975- let config : [ String : Any ]
1976- }
1977-
1978- private static func normalizedTalkProviderID( _ raw: String ? ) -> String ? {
1979- let trimmed = ( raw ?? " " ) . trimmingCharacters ( in: . whitespacesAndNewlines) . lowercased ( )
1980- return trimmed. isEmpty ? nil : trimmed
1981- }
1982-
1983- static func selectTalkProviderConfig( _ talk: [ String : Any ] ? ) -> TalkProviderConfigSelection ? {
1984- guard let talk else { return nil }
1985- let rawProvider = talk [ " provider " ] as? String
1986- let rawProviders = talk [ " providers " ] as? [ String : Any ]
1987- guard rawProvider != nil || rawProviders != nil else { return nil }
1988- let providers = rawProviders ?? [ : ]
1989- let normalizedProviders = providers. reduce ( into: [ String: [ String: Any] ] ( ) ) { acc, entry in
1990- guard
1991- let providerID = Self . normalizedTalkProviderID ( entry. key) ,
1992- let config = entry. value as? [ String : Any ]
1993- else { return }
1994- acc [ providerID] = config
1995- }
1996- let providerID =
1997- Self . normalizedTalkProviderID ( rawProvider) ??
1998- normalizedProviders. keys. min ( ) ??
1999- Self . defaultTalkProvider
2000- return TalkProviderConfigSelection (
2001- provider: providerID,
2002- config: normalizedProviders [ providerID] ?? [ : ] )
2003- }
2004-
2005- static func resolvedSilenceTimeoutMs( _ talk: [ String : Any ] ? ) -> Int {
2006- switch talk ? [ " silenceTimeoutMs " ] {
2007- case let timeout as Int where timeout > 0 :
2008- return timeout
2009- case let timeout as Double
2010- where timeout > 0 && timeout. rounded ( . towardZero) == timeout && timeout <= Double ( Int . max) :
2011- return Int ( timeout)
2012- case let timeout as NSNumber :
2013- if CFGetTypeID ( timeout) == CFBooleanGetTypeID ( ) {
2014- return Self . defaultSilenceTimeoutMs
2015- }
2016- let value = timeout. doubleValue
2017- if value > 0 && value. rounded ( . towardZero) == value && value <= Double ( Int . max) {
2018- return Int ( value)
2019- }
2020- return Self . defaultSilenceTimeoutMs
2021- default :
2022- return Self . defaultSilenceTimeoutMs
2023- }
1973+ static func selectTalkProviderConfig( _ talk: [ String : AnyCodable ] ? ) -> TalkProviderConfigSelection ? {
1974+ TalkConfigParsing . selectProviderConfig (
1975+ talk,
1976+ defaultProvider: Self . defaultTalkProvider,
1977+ allowLegacyFallback: false )
1978+ }
1979+
1980+ static func resolvedSilenceTimeoutMs( _ talk: [ String : AnyCodable ] ? ) -> Int {
1981+ TalkConfigParsing . resolvedSilenceTimeoutMs ( talk, fallback: Self . defaultSilenceTimeoutMs)
20241982 }
20251983
20261984 func reloadConfig( ) async {
@@ -2034,7 +1992,7 @@ extension TalkModeManager {
20341992 )
20351993 guard let json = try JSONSerialization . jsonObject ( with: res) as? [ String : Any ] else { return }
20361994 guard let config = json [ " config " ] as? [ String : Any ] else { return }
2037- let talk = config [ " talk " ] as? [ String : Any ]
1995+ let talk = TalkConfigParsing . bridgeFoundationDictionary ( config [ " talk " ] as? [ String : Any ] )
20381996 let selection = Self . selectTalkProviderConfig ( talk)
20391997 if talk != nil , selection == nil {
20401998 GatewayDiagnostics . log (
@@ -2043,12 +2001,12 @@ extension TalkModeManager {
20432001 let activeProvider = selection? . provider ?? Self . defaultTalkProvider
20442002 let activeConfig = selection? . config
20452003 let silenceTimeoutMs = Self . resolvedSilenceTimeoutMs ( talk)
2046- self . defaultVoiceId = ( activeConfig ? [ " voiceId " ] as? String ) ?
2004+ self . defaultVoiceId = activeConfig ? [ " voiceId " ] ? . stringValue ?
20472005 . trimmingCharacters ( in: . whitespacesAndNewlines)
2048- if let aliases = activeConfig ? [ " voiceAliases " ] as? [ String : Any ] {
2006+ if let aliases = activeConfig ? [ " voiceAliases " ] ? . dictionaryValue {
20492007 var resolved : [ String : String ] = [ : ]
20502008 for (key, value) in aliases {
2051- guard let id = value as? String else { continue }
2009+ guard let id = value. stringValue else { continue }
20522010 let normalizedKey = key. trimmingCharacters ( in: . whitespacesAndNewlines) . lowercased ( )
20532011 let trimmedId = id. trimmingCharacters ( in: . whitespacesAndNewlines)
20542012 guard !normalizedKey. isEmpty, !trimmedId. isEmpty else { continue }
@@ -2061,14 +2019,14 @@ extension TalkModeManager {
20612019 if !self . voiceOverrideActive {
20622020 self . currentVoiceId = self . defaultVoiceId
20632021 }
2064- let model = ( activeConfig ? [ " modelId " ] as? String ) ? . trimmingCharacters ( in: . whitespacesAndNewlines)
2022+ let model = activeConfig ? [ " modelId " ] ? . stringValue ? . trimmingCharacters ( in: . whitespacesAndNewlines)
20652023 self . defaultModelId = ( model? . isEmpty == false ) ? model : Self . defaultModelIdFallback
20662024 if !self . modelOverrideActive {
20672025 self . currentModelId = self . defaultModelId
20682026 }
2069- self . defaultOutputFormat = ( activeConfig ? [ " outputFormat " ] as? String ) ?
2027+ self . defaultOutputFormat = activeConfig ? [ " outputFormat " ] ? . stringValue ?
20702028 . trimmingCharacters ( in: . whitespacesAndNewlines)
2071- let rawConfigApiKey = ( activeConfig ? [ " apiKey " ] as? String ) ? . trimmingCharacters ( in: . whitespacesAndNewlines)
2029+ let rawConfigApiKey = activeConfig ? [ " apiKey " ] ? . stringValue ? . trimmingCharacters ( in: . whitespacesAndNewlines)
20722030 let configApiKey = Self . normalizedTalkApiKey ( rawConfigApiKey)
20732031 let localApiKey = Self . normalizedTalkApiKey (
20742032 GatewaySettingsStore . loadTalkProviderApiKey ( provider: activeProvider) )
@@ -2087,7 +2045,7 @@ extension TalkModeManager {
20872045 self . gatewayTalkDefaultModelId = self . defaultModelId
20882046 self . gatewayTalkApiKeyConfigured = ( self . apiKey? . isEmpty == false )
20892047 self . gatewayTalkConfigLoaded = true
2090- if let interrupt = talk ? [ " interruptOnSpeech " ] as? Bool {
2048+ if let interrupt = talk ? [ " interruptOnSpeech " ] ? . boolValue {
20912049 self . interruptOnSpeech = interrupt
20922050 }
20932051 self . silenceWindow = TimeInterval ( silenceTimeoutMs) / 1000
0 commit comments