vOOice/VoiceInk/Services/CustomModelManager.swift

139 lines
4.7 KiB
Swift

import Foundation
import os
class CustomModelManager: ObservableObject {
static let shared = CustomModelManager()
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "CustomModelManager")
private let userDefaults = UserDefaults.standard
private let customModelsKey = "customCloudModels"
@Published var customModels: [CustomCloudModel] = []
private init() {
loadCustomModels()
}
// MARK: - CRUD Operations
func addCustomModel(_ model: CustomCloudModel) {
customModels.append(model)
saveCustomModels()
logger.info("Added custom model: \(model.displayName)")
}
func removeCustomModel(withId id: UUID) {
customModels.removeAll { $0.id == id }
saveCustomModels()
logger.info("Removed custom model with ID: \(id)")
}
func updateCustomModel(_ updatedModel: CustomCloudModel) {
if let index = customModels.firstIndex(where: { $0.id == updatedModel.id }) {
customModels[index] = updatedModel
saveCustomModels()
logger.info("Updated custom model: \(updatedModel.displayName)")
}
}
// MARK: - Persistence
private func loadCustomModels() {
guard let data = userDefaults.data(forKey: customModelsKey) else {
logger.info("No custom models found in UserDefaults")
return
}
do {
customModels = try JSONDecoder().decode([CustomCloudModel].self, from: data)
} catch {
logger.error("Failed to decode custom models: \(error.localizedDescription)")
customModels = []
}
}
private func saveCustomModels() {
do {
let data = try JSONEncoder().encode(customModels)
userDefaults.set(data, forKey: customModelsKey)
} catch {
logger.error("Failed to encode custom models: \(error.localizedDescription)")
}
}
// MARK: - Validation
func validateModel(name: String, displayName: String, apiEndpoint: String, apiKey: String, modelName: String) -> [String] {
var errors: [String] = []
if name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Name cannot be empty")
}
if displayName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Display name cannot be empty")
}
if apiEndpoint.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("API endpoint cannot be empty")
} else if !isValidURL(apiEndpoint) {
errors.append("API endpoint must be a valid URL")
}
if apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("API key cannot be empty")
}
if modelName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Model name cannot be empty")
}
// Check for duplicate names
if customModels.contains(where: { $0.name == name }) {
errors.append("A model with this name already exists")
}
return errors
}
func validateModel(name: String, displayName: String, apiEndpoint: String, apiKey: String, modelName: String, excludingId: UUID? = nil) -> [String] {
var errors: [String] = []
if name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Name cannot be empty")
}
if displayName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Display name cannot be empty")
}
if apiEndpoint.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("API endpoint cannot be empty")
} else if !isValidURL(apiEndpoint) {
errors.append("API endpoint must be a valid URL")
}
if apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("API key cannot be empty")
}
if modelName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
errors.append("Model name cannot be empty")
}
// Check for duplicate names, excluding the specified ID
if customModels.contains(where: { $0.name == name && $0.id != excludingId }) {
errors.append("A model with this name already exists")
}
return errors
}
private func isValidURL(_ string: String) -> Bool {
if let url = URL(string: string) {
return url.scheme != nil && url.host != nil
}
return false
}
}