ios: initial commit
This commit is contained in:
73
ios/Packages/Sybil/Sources/Sybil/SybilSettingsStore.swift
Normal file
73
ios/Packages/Sybil/Sources/Sybil/SybilSettingsStore.swift
Normal file
@@ -0,0 +1,73 @@
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
final class SybilSettingsStore {
|
||||
private enum Keys {
|
||||
static let apiBaseURL = "sybil.ios.apiBaseURL"
|
||||
static let adminToken = "sybil.ios.adminToken"
|
||||
static let preferredProvider = "sybil.ios.preferredProvider"
|
||||
static let preferredOpenAIModel = "sybil.ios.preferredOpenAIModel"
|
||||
static let preferredAnthropicModel = "sybil.ios.preferredAnthropicModel"
|
||||
static let preferredXAIModel = "sybil.ios.preferredXAIModel"
|
||||
}
|
||||
|
||||
private let defaults: UserDefaults
|
||||
|
||||
var apiBaseURL: String
|
||||
var adminToken: String
|
||||
var preferredProvider: Provider
|
||||
var preferredModelByProvider: [Provider: String]
|
||||
|
||||
init(defaults: UserDefaults = .standard) {
|
||||
self.defaults = defaults
|
||||
|
||||
let storedBaseURL = defaults.string(forKey: Keys.apiBaseURL)?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let fallbackBaseURL = "http://127.0.0.1:8787/api"
|
||||
self.apiBaseURL = storedBaseURL?.isEmpty == false ? storedBaseURL! : fallbackBaseURL
|
||||
|
||||
self.adminToken = defaults.string(forKey: Keys.adminToken) ?? ""
|
||||
|
||||
let provider = defaults.string(forKey: Keys.preferredProvider).flatMap(Provider.init(rawValue:)) ?? .openai
|
||||
self.preferredProvider = provider
|
||||
|
||||
self.preferredModelByProvider = [
|
||||
.openai: defaults.string(forKey: Keys.preferredOpenAIModel) ?? "gpt-4.1-mini",
|
||||
.anthropic: defaults.string(forKey: Keys.preferredAnthropicModel) ?? "claude-3-5-sonnet-latest",
|
||||
.xai: defaults.string(forKey: Keys.preferredXAIModel) ?? "grok-3-mini"
|
||||
]
|
||||
}
|
||||
|
||||
func persist() {
|
||||
defaults.set(apiBaseURL.trimmingCharacters(in: .whitespacesAndNewlines), forKey: Keys.apiBaseURL)
|
||||
|
||||
let trimmedToken = adminToken.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if trimmedToken.isEmpty {
|
||||
defaults.removeObject(forKey: Keys.adminToken)
|
||||
} else {
|
||||
defaults.set(trimmedToken, forKey: Keys.adminToken)
|
||||
}
|
||||
|
||||
defaults.set(preferredProvider.rawValue, forKey: Keys.preferredProvider)
|
||||
defaults.set(preferredModelByProvider[.openai], forKey: Keys.preferredOpenAIModel)
|
||||
defaults.set(preferredModelByProvider[.anthropic], forKey: Keys.preferredAnthropicModel)
|
||||
defaults.set(preferredModelByProvider[.xai], forKey: Keys.preferredXAIModel)
|
||||
}
|
||||
|
||||
var trimmedTokenOrNil: String? {
|
||||
let value = adminToken.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return value.isEmpty ? nil : value
|
||||
}
|
||||
|
||||
var normalizedAPIBaseURL: URL? {
|
||||
var raw = apiBaseURL.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !raw.isEmpty else { return nil }
|
||||
|
||||
if raw.hasSuffix("/") {
|
||||
raw.removeLast()
|
||||
}
|
||||
|
||||
return URL(string: raw)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user