Skip to content

Commit 8dc12f0

Browse files
committed
Add support to store api keys in user defaults
1 parent 2346fad commit 8dc12f0

File tree

3 files changed

+63
-17
lines changed

3 files changed

+63
-17
lines changed

Core/Sources/HostApp/DebugView.swift

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ final class DebugSettings: ObservableObject {
1414
@AppStorage(\.disableFunctionCalling) var disableFunctionCalling
1515
@AppStorage(\.disableGitHubCopilotSettingsAutoRefreshOnAppear)
1616
var disableGitHubCopilotSettingsAutoRefreshOnAppear
17+
@AppStorage(\.useUserDefaultsBaseAPIKeychain) var useUserDefaultsBaseAPIKeychain
1718
init() {}
1819
}
1920

@@ -41,17 +42,22 @@ struct DebugSettingsView: View {
4142
Toggle(isOn: $settings.triggerActionWithAccessibilityAPI) {
4243
Text("Trigger command with AccessibilityAPI")
4344
}
44-
Toggle(isOn: $settings.alwaysAcceptSuggestionWithAccessibilityAPI) {
45-
Text("Always accept suggestion with Accessibility API")
46-
}
47-
Toggle(isOn: $settings.enableXcodeInspectorDebugMenu) {
48-
Text("Enable Xcode inspector debug menu")
49-
}
50-
Toggle(isOn: $settings.disableFunctionCalling) {
51-
Text("Disable function calling for chat feature")
52-
}
53-
Toggle(isOn: $settings.disableGitHubCopilotSettingsAutoRefreshOnAppear) {
54-
Text("Disable GitHub Copilot settings auto refresh status on appear")
45+
Group {
46+
Toggle(isOn: $settings.alwaysAcceptSuggestionWithAccessibilityAPI) {
47+
Text("Always accept suggestion with Accessibility API")
48+
}
49+
Toggle(isOn: $settings.enableXcodeInspectorDebugMenu) {
50+
Text("Enable Xcode inspector debug menu")
51+
}
52+
Toggle(isOn: $settings.disableFunctionCalling) {
53+
Text("Disable function calling for chat feature")
54+
}
55+
Toggle(isOn: $settings.disableGitHubCopilotSettingsAutoRefreshOnAppear) {
56+
Text("Disable GitHub Copilot settings auto refresh status on appear")
57+
}
58+
Toggle(isOn: $settings.useUserDefaultsBaseAPIKeychain) {
59+
Text("Store API keys in UserDefaults")
60+
}
5561
}
5662
}
5763
.padding()

Tool/Sources/Keychain/Keychain.swift

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Configs
22
import Foundation
3+
import Preferences
34
import Security
45

56
public protocol KeychainType {
@@ -31,13 +32,48 @@ public final class FakeKeyChain: KeychainType {
3132
}
3233
}
3334

35+
public final class UserDefaultsBaseAPIKeychain: KeychainType {
36+
let defaults = UserDefaults.shared
37+
let scope: String
38+
var key: String {
39+
"UserDefaultsBaseAPIKeychain-\(scope)"
40+
}
41+
42+
init(scope: String) {
43+
self.scope = scope
44+
}
45+
46+
public func getAll() throws -> [String : String] {
47+
defaults.dictionary(forKey: key) as? [String: String] ?? [:]
48+
}
49+
50+
public func update(_ value: String, key: String) throws {
51+
var dict = try getAll()
52+
dict[key] = value
53+
defaults.set(dict, forKey: self.key)
54+
}
55+
56+
public func get(_ key: String) throws -> String? {
57+
try getAll()[key]
58+
}
59+
60+
public func remove(_ key: String) throws {
61+
var dict = try getAll()
62+
dict[key] = nil
63+
defaults.set(dict, forKey: self.key)
64+
}
65+
}
66+
3467
public struct Keychain: KeychainType {
3568
let service = keychainService
3669
let accessGroup = keychainAccessGroup
3770
let scope: String
3871

39-
public static var apiKey: Keychain {
40-
Keychain(scope: "apiKey")
72+
public static var apiKey: KeychainType {
73+
if UserDefaults.shared.value(for: \.useUserDefaultsBaseAPIKeychain) {
74+
return UserDefaultsBaseAPIKeychain(scope: "apiKey")
75+
}
76+
return Keychain(scope: "apiKey")
4177
}
4278

4379
public enum Error: Swift.Error {

Tool/Sources/Preferences/Keys.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public extension UserDefaultPreferenceKeys {
213213
supportsFunctionCalling: true,
214214
modelName: ChatGPTModel.gpt35Turbo.rawValue
215215
)
216-
)
216+
),
217217
], key: "ChatModels")
218218
}
219219

@@ -245,7 +245,7 @@ public extension UserDefaultPreferenceKeys {
245245
maxTokens: OpenAIEmbeddingModel.textEmbeddingAda002.maxToken,
246246
modelName: OpenAIEmbeddingModel.textEmbeddingAda002.rawValue
247247
)
248-
)
248+
),
249249
], key: "EmbeddingModels")
250250
}
251251
}
@@ -320,15 +320,15 @@ public extension UserDefaultPreferenceKeys {
320320
var chatFeatureProvider: DeprecatedPreferenceKey<ChatFeatureProvider> {
321321
.init(defaultValue: .openAI, key: "ChatFeatureProvider")
322322
}
323-
323+
324324
var defaultChatFeatureChatModelId: PreferenceKey<String> {
325325
.init(defaultValue: "", key: "DefaultChatFeatureChatModelId")
326326
}
327327

328328
var embeddingFeatureProvider: DeprecatedPreferenceKey<EmbeddingFeatureProvider> {
329329
.init(defaultValue: .openAI, key: "EmbeddingFeatureProvider")
330330
}
331-
331+
332332
var defaultChatFeatureEmbeddingModelId: PreferenceKey<String> {
333333
.init(defaultValue: "", key: "DefaultChatFeatureEmbeddingModelId")
334334
}
@@ -481,6 +481,10 @@ public extension UserDefaultPreferenceKeys {
481481
.init(defaultValue: false, key: "FeatureFlag-DisableFunctionCalling")
482482
}
483483

484+
var useUserDefaultsBaseAPIKeychain: FeatureFlag {
485+
.init(defaultValue: false, key: "FeatureFlag-UseUserDefaultsBaseAPIKeychain")
486+
}
487+
484488
var disableGitHubCopilotSettingsAutoRefreshOnAppear: FeatureFlag {
485489
.init(
486490
defaultValue: false,

0 commit comments

Comments
 (0)