@@ -49,6 +49,25 @@ struct ChatModelEditView: View {
4949 . controlSize ( . small)
5050 }
5151 }
52+
53+ CustomBodyEdit ( store: store)
54+ . disabled ( {
55+ switch store. format {
56+ case . openAI, . openAICompatible, . claude:
57+ return false
58+ default :
59+ return true
60+ }
61+ } ( ) )
62+ CustomHeaderEdit ( store: store)
63+ . disabled ( {
64+ switch store. format {
65+ case . openAI, . openAICompatible, . ollama, . gitHubCopilot, . claude:
66+ return false
67+ default :
68+ return true
69+ }
70+ } ( ) )
5271
5372 Spacer ( )
5473
@@ -230,6 +249,79 @@ struct ChatModelEditView: View {
230249 }
231250 }
232251
252+ struct CustomBodyEdit : View {
253+ @Perception . Bindable var store : StoreOf < ChatModelEdit >
254+ @State private var isEditing = false
255+ @Dependency ( \. namespacedToast) var toast
256+
257+ var body : some View {
258+ Button ( " Custom Body " ) {
259+ isEditing = true
260+ }
261+ . sheet ( isPresented: $isEditing) {
262+ WithPerceptionTracking {
263+ VStack {
264+ TextEditor ( text: $store. customBody)
265+ . font ( Font . system ( . body, design: . monospaced) )
266+ . padding ( 4 )
267+ . frame ( minHeight: 120 )
268+ . multilineTextAlignment ( . leading)
269+ . overlay (
270+ RoundedRectangle ( cornerRadius: 4 )
271+ . stroke ( Color ( nsColor: . separatorColor) , lineWidth: 1 )
272+ )
273+ . handleToast ( namespace: " CustomBodyEdit " )
274+
275+ Text (
276+ " The custom body will be added to the request body. Please use it to add parameters that are not yet available in the form. It should be a valid JSON object. "
277+ )
278+ . foregroundColor ( . secondary)
279+ . font ( . callout)
280+ . padding ( . bottom)
281+
282+ Button ( action: {
283+ if store. customBody. trimmingCharacters ( in: . whitespacesAndNewlines)
284+ . isEmpty
285+ {
286+ isEditing = false
287+ return
288+ }
289+ guard let _ = try ? JSONSerialization
290+ . jsonObject ( with: store. customBody. data ( using: . utf8) ?? Data ( ) )
291+ else {
292+ toast ( " Invalid JSON object " , . error, " CustomBodyEdit " )
293+ return
294+ }
295+ isEditing = false
296+ } ) {
297+ Text ( " Done " )
298+ }
299+ . keyboardShortcut ( . defaultAction)
300+ }
301+ . padding ( )
302+ . frame ( width: 600 , height: 500 )
303+ . background ( Color ( nsColor: . windowBackgroundColor) )
304+ }
305+ }
306+ }
307+ }
308+
309+ struct CustomHeaderEdit : View {
310+ @Perception . Bindable var store : StoreOf < ChatModelEdit >
311+ @State private var isEditing = false
312+
313+ var body : some View {
314+ Button ( " Custom Headers " ) {
315+ isEditing = true
316+ }
317+ . sheet ( isPresented: $isEditing) {
318+ WithPerceptionTracking {
319+ CustomHeaderSettingsView ( headers: $store. customHeaders)
320+ }
321+ }
322+ }
323+ }
324+
233325 struct OpenAIForm : View {
234326 @Perception . Bindable var store : StoreOf < ChatModelEdit >
235327 var body : some View {
@@ -300,7 +392,6 @@ struct ChatModelEditView: View {
300392
301393 struct OpenAICompatibleForm : View {
302394 @Perception . Bindable var store : StoreOf < ChatModelEdit >
303- @State var isEditingCustomHeader = false
304395
305396 var body : some View {
306397 WithPerceptionTracking {
@@ -340,16 +431,10 @@ struct ChatModelEditView: View {
340431 Toggle ( isOn: $store. openAICompatibleSupportsMultipartMessageContent) {
341432 Text ( " Support multi-part message content " )
342433 }
343-
434+
344435 Toggle ( isOn: $store. requiresBeginWithUserMessage) {
345436 Text ( " Requires the first message to be from the user " )
346437 }
347-
348- Button ( " Custom Headers " ) {
349- isEditingCustomHeader. toggle ( )
350- }
351- } . sheet ( isPresented: $isEditingCustomHeader) {
352- CustomHeaderSettingsView ( headers: $store. customHeaders)
353438 }
354439 }
355440 }
@@ -394,7 +479,6 @@ struct ChatModelEditView: View {
394479
395480 struct OllamaForm : View {
396481 @Perception . Bindable var store : StoreOf < ChatModelEdit >
397- @State var isEditingCustomHeader = false
398482
399483 var body : some View {
400484 WithPerceptionTracking {
@@ -411,20 +495,13 @@ struct ChatModelEditView: View {
411495 TextField ( text: $store. ollamaKeepAlive, prompt: Text ( " Default Value " ) ) {
412496 Text ( " Keep Alive " )
413497 }
414-
415- Button ( " Custom Headers " ) {
416- isEditingCustomHeader. toggle ( )
417- }
418-
498+
419499 VStack ( alignment: . leading, spacing: 8 ) {
420500 Text ( Image ( systemName: " exclamationmark.triangle.fill " ) ) + Text(
421501 " For more details, please visit [https://ollama.com](https://ollama.com). "
422502 )
423503 }
424504 . padding ( . vertical)
425-
426- } . sheet ( isPresented: $isEditingCustomHeader) {
427- CustomHeaderSettingsView ( headers: $store. customHeaders)
428505 }
429506 }
430507 }
@@ -475,7 +552,6 @@ struct ChatModelEditView: View {
475552
476553 struct GitHubCopilotForm : View {
477554 @Perception . Bindable var store : StoreOf < ChatModelEdit >
478- @State var isEditingCustomHeader = false
479555
480556 var body : some View {
481557 WithPerceptionTracking {
@@ -507,10 +583,6 @@ struct ChatModelEditView: View {
507583 Text ( " Support multi-part message content " )
508584 }
509585
510- Button ( " Custom Headers " ) {
511- isEditingCustomHeader. toggle ( )
512- }
513-
514586 VStack ( alignment: . leading, spacing: 8 ) {
515587 Text ( Image ( systemName: " exclamationmark.triangle.fill " ) ) + Text(
516588 " Please login in the GitHub Copilot settings to use the model. "
@@ -522,8 +594,6 @@ struct ChatModelEditView: View {
522594 }
523595 . dynamicHeightTextInFormWorkaround ( )
524596 . padding ( . vertical)
525- } . sheet ( isPresented: $isEditingCustomHeader) {
526- CustomHeaderSettingsView ( headers: $store. customHeaders)
527597 }
528598 }
529599 }
0 commit comments