Skip to content

Commit 182d426

Browse files
committed
Change ChatGPTEndpoint to OpenAIBaseURL
1 parent a27f5c7 commit 182d426

5 files changed

Lines changed: 51 additions & 14 deletions

File tree

Core/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ let package = Package(
4242
"LaunchAgentManager",
4343
"Logger",
4444
"UpdateChecker",
45+
"OpenAIService",
4546
]
4647
),
4748
],

Core/Sources/HostApp/AccountSettings/OpenAIView.swift

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AppKit
2+
import OpenAIService
23
import Client
34
import Preferences
45
import SuggestionModel
@@ -8,7 +9,7 @@ final class OpenAIViewSettings: ObservableObject {
89
static let availableLocalizedLocales = Locale.availableLocalizedLocales
910
@AppStorage(\.openAIAPIKey) var openAIAPIKey: String
1011
@AppStorage(\.chatGPTModel) var chatGPTModel: String
11-
@AppStorage(\.chatGPTEndpoint) var chatGPTEndpoint: String
12+
@AppStorage(\.openAIBaseURL) var openAIBaseURL: String
1213
@AppStorage(\.chatGPTLanguage) var chatGPTLanguage: String
1314
@AppStorage(\.chatGPTMaxToken) var chatGPTMaxToken: Int
1415
@AppStorage(\.chatGPTTemperature) var chatGPTTemperature: Double
@@ -22,6 +23,7 @@ struct OpenAIView: View {
2223
string: "https://platform.openai.com/docs/models/model-endpoint-compatibility"
2324
)!
2425
@Environment(\.openURL) var openURL
26+
@Environment(\.toast) var toast
2527
@StateObject var settings = OpenAIViewSettings()
2628
@State var maxTokenOverLimit = false
2729

@@ -39,6 +41,27 @@ struct OpenAIView: View {
3941
}.buttonStyle(.plain)
4042
}
4143

44+
HStack {
45+
TextField(
46+
text: $settings.openAIBaseURL,
47+
prompt: Text("https://api.openai.com")
48+
) {
49+
Text("OpenAI Base URL")
50+
}.textFieldStyle(.roundedBorder)
51+
52+
Button("Test") {
53+
Task {
54+
do {
55+
let reply = try await ChatGPTService()
56+
.sendAndWait(content: "Hello", summary: nil)
57+
toast(Text("ChatGPT replied: \(reply ?? "N/A")"), .info)
58+
} catch {
59+
toast(Text(error.localizedDescription), .error)
60+
}
61+
}
62+
}
63+
}
64+
4265
HStack {
4366
Picker(selection: $settings.chatGPTModel) {
4467
if !settings.chatGPTModel.isEmpty,
@@ -59,13 +82,6 @@ struct OpenAIView: View {
5982
}.buttonStyle(.plain)
6083
}
6184

62-
TextField(
63-
text: $settings.chatGPTEndpoint,
64-
prompt: Text("https://api.openai.com/v1/chat/completions")
65-
) {
66-
Text("ChatGPT Server")
67-
}.textFieldStyle(.roundedBorder)
68-
6985
if #available(macOS 13.0, *) {
7086
LabeledContent("Reply in Language") {
7187
languagePicker
@@ -107,7 +123,7 @@ struct OpenAIView: View {
107123
.labelsHidden()
108124
.textFieldStyle(.roundedBorder)
109125
.foregroundColor(maxTokenOverLimit ? .red : .primary)
110-
126+
111127
if let model = ChatGPTModel(rawValue: settings.chatGPTModel) {
112128
Text("Max: \(model.maxToken)")
113129
}

Core/Sources/OpenAIService/ChatGPTService.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,9 @@ public actor ChatGPTService: ChatGPTServiceType {
6969
}
7070

7171
public var endpoint: String {
72-
let value = UserDefaults.shared.value(for: \.chatGPTEndpoint)
73-
if value.isEmpty { return "https://api.openai.com/v1/chat/completions" }
74-
75-
return value
72+
var baseURL = UserDefaults.shared.value(for: \.openAIBaseURL)
73+
if baseURL.isEmpty { return "https://api.openai.com/v1/chat/completions" }
74+
return "\(baseURL)/v1/chat/completions"
7675
}
7776

7877
public var apiKey: String {

Core/Sources/Preferences/Keys.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,15 @@ public extension UserDefaultPreferenceKeys {
6969
.init(defaultValue: "", key: "OpenAIAPIKey")
7070
}
7171

72+
@available(*, deprecated, message: "Use `openAIBaseURL` instead.")
7273
var chatGPTEndpoint: PreferenceKey<String> {
7374
.init(defaultValue: "", key: "ChatGPTEndpoint")
7475
}
7576

77+
var openAIBaseURL: PreferenceKey<String> {
78+
.init(defaultValue: "", key: "OpenAIBaseURL")
79+
}
80+
7681
var chatGPTModel: PreferenceKey<String> {
7782
.init(defaultValue: Preferences.ChatGPTModel.gpt35Turbo.rawValue, key: "ChatGPTModel")
7883
}
@@ -196,7 +201,7 @@ public extension UserDefaultPreferenceKeys {
196201
var embedFileContentInChatContextIfNoSelection: PreferenceKey<Bool> {
197202
.init(defaultValue: false, key: "EmbedFileContentInChatContextIfNoSelection")
198203
}
199-
204+
200205
var maxEmbeddableFileInChatContextLineCount: PreferenceKey<Int> {
201206
.init(defaultValue: 100, key: "MaxEmbeddableFileInChatContextLineCount")
202207
}

Core/Sources/Preferences/UserDefaults.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ public extension UserDefaults {
1313
shared.setupDefaultValue(for: \.widgetColorScheme)
1414
shared.setupDefaultValue(for: \.customCommands)
1515
shared.setupDefaultValue(for: \.runNodeWith, defaultValue: .env)
16+
shared.setupDefaultValue(for: \.openAIBaseURL, defaultValue: {
17+
guard let url = URL(string: shared.value(for: \.chatGPTEndpoint)) else { return "" }
18+
let scheme = url.scheme ?? "https"
19+
guard let host = url.host else { return "" }
20+
return "\(scheme)://\(host)"
21+
}() as String)
1622
}
1723
}
1824

@@ -71,6 +77,16 @@ public extension UserDefaults {
7177
set(key.defaultValue, forKey: key.key)
7278
}
7379
}
80+
81+
func setupDefaultValue<K: UserDefaultPreferenceKey>(
82+
for keyPath: KeyPath<UserDefaultPreferenceKeys, K>,
83+
defaultValue: K.Value
84+
) where K.Value: UserDefaultsStorable {
85+
let key = UserDefaultPreferenceKeys()[keyPath: keyPath]
86+
if value(forKey: key.key) == nil {
87+
set(defaultValue, forKey: key.key)
88+
}
89+
}
7490

7591
// MARK: - Raw Representable
7692

0 commit comments

Comments
 (0)