import ArgumentParser import Foundation @main struct CapTrain: AsyncParsableCommand { @Argument(help: "The path to the configuration file") var configPath: String? @Option(name: .shortAndLong, help: "The number of iterations to train") var iterations: Int? @Option(name: .shortAndLong, help: "The url of the caps server") var serverPath: String? @Option(name: .shortAndLong, help: "The authentication token for the server") var authentication: String? @Option(name: .shortAndLong, help: "The folder where the content (images, classifier, thumbnails) is stored") var folder: String? func run() async throws { let configurationFile = try configurationFile() guard let contentFolder = folder ?? configurationFile?.contentFolder, let trainingIterations = iterations ?? configurationFile?.trainingIterations, let serverPath = serverPath ?? configurationFile?.serverPath, let authenticationToken = authentication ?? configurationFile?.authenticationToken else { throw TrainingError.missingArguments } let configuration = Configuration( contentFolder: contentFolder, trainingIterations: trainingIterations, serverPath: serverPath, authenticationToken: authenticationToken) let creator = try ClassifierCreator(configuration: configuration) try await creator.run() } private func configurationFile() throws -> ConfigurationFile? { guard let configPath else { return nil } let configurationFileUrl = URL(fileURLWithPath: configPath) return try ConfigurationFile(at: configurationFileUrl) } }