11import AIModel
2+ import Toast
23import ComposableArchitecture
34import Dependencies
45import Keychain
@@ -40,7 +41,12 @@ struct ChatModelEdit: ReducerProtocol {
4041 case baseURLSelection( BaseURLSelection . Action )
4142 }
4243
43- @Dependency ( \. toast) var toast
44+ var toast : ( String , ToastType ) -> Void {
45+ @Dependency ( \. namespacedToast) var toast
46+ return {
47+ toast ( $0, $1, " ChatModelEdit " )
48+ }
49+ }
4450 @Dependency ( \. apiKeyKeychain) var keychain
4551
4652 var body : some ReducerProtocol < State , Action > {
@@ -86,27 +92,35 @@ struct ChatModelEdit: ReducerProtocol {
8692 )
8793 return . run { send in
8894 do {
89- let reply =
90- try await ChatGPTService (
91- configuration: UserPreferenceChatGPTConfiguration ( )
92- . overriding {
93- $0. model = model
94- }
95- ) . sendAndWait ( content: " Hello " )
95+ let service = ChatGPTService (
96+ configuration: UserPreferenceChatGPTConfiguration ( )
97+ . overriding {
98+ $0. model = model
99+ }
100+ )
101+ let reply = try await service
102+ . sendAndWait ( content: " Respond with \" Test succeeded \" " )
96103 await send ( . testSucceeded( reply ?? " No Message " ) )
104+ let stream = try await service
105+ . send ( content: " Respond with \" Stream response is working \" " )
106+ var streamReply = " "
107+ for try await chunk in stream {
108+ streamReply += chunk
109+ }
110+ await send ( . testSucceeded( streamReply) )
97111 } catch {
98112 await send ( . testFailed( error. localizedDescription) )
99113 }
100114 }
101115
102116 case let . testSucceeded( message) :
103117 state. isTesting = false
104- toast ( message, . info)
118+ toast ( message. trimmingCharacters ( in : . whitespacesAndNewlines ) , . info)
105119 return . none
106120
107121 case let . testFailed( message) :
108122 state. isTesting = false
109- toast ( message, . error)
123+ toast ( message. trimmingCharacters ( in : . whitespacesAndNewlines ) , . error)
110124 return . none
111125
112126 case . refreshAvailableModelNames:
@@ -132,6 +146,15 @@ struct ChatModelEdit: ReducerProtocol {
132146 state. suggestedMaxTokens = nil
133147 }
134148 return . none
149+ case . claude:
150+ if let knownModel = ClaudeChatCompletionsService
151+ . KnownModel ( rawValue: state. modelName)
152+ {
153+ state. suggestedMaxTokens = knownModel. contextWindow
154+ } else {
155+ state. suggestedMaxTokens = nil
156+ }
157+ return . none
135158 default :
136159 state. suggestedMaxTokens = nil
137160 return . none
@@ -192,13 +215,12 @@ extension ChatModel {
192215 isFullURL: state. isFullURL,
193216 maxTokens: state. maxTokens,
194217 supportsFunctionCalling: {
195- if case . googleAI = state. format {
196- return false
197- }
198- if case . ollama = state. format {
218+ switch state. format {
219+ case . googleAI, . ollama, . claude:
199220 return false
221+ case . azureOpenAI, . openAI, . openAICompatible:
222+ return state. supportsFunctionCalling
200223 }
201- return state. supportsFunctionCalling
202224 } ( ) ,
203225 modelName: state. modelName. trimmingCharacters ( in: . whitespacesAndNewlines) ,
204226 ollamaInfo: . init( keepAlive: state. ollamaKeepAlive)
0 commit comments