SPB Git

spb/zyquo-mlx Public MIT

The local MLX foundry for your Mac — run, fine-tune, quantize, and ship models. Nothing leaves your machine.

Swift 93.4% Python 3.8% Makefile 2.2% Shell 0.5%
2.7 KB · 100 lines swift
Raw Blame History
1//2//  AppModel.swift3//  Zyquo MLX4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//89import Foundation10import Observation11import SwiftUI1213/// Workbench sections (left navigator, charter §4.2).14enum WorkbenchSection: String, CaseIterable, Identifiable {15    case models16    case datasets17    case train18    case convert19    case playground20    case evaluate2122    var id: String { rawValue }2324    var title: String {25        switch self {26        case .models: "Models"27        case .datasets: "Datasets"28        case .train: "Train"29        case .convert: "Convert"30        case .playground: "Playground"31        case .evaluate: "Evaluate"32        }33    }3435    var icon: String {36        switch self {37        case .models: "shippingbox"38        case .datasets: "tablecells"39        case .train: "flame"40        case .convert: "arrow.triangle.2.circlepath"41        case .playground: "bubble.left.and.text.bubble.right"42        case .evaluate: "checkmark.seal"43        }44    }4546    /// ⌘-shortcuts (charter Phase 6: ⌘L Models, ⌘D Datasets, ⌘R Train,47    /// ⌘I Playground; Convert/Evaluate get the next free letters).48    var shortcut: KeyEquivalent {49        switch self {50        case .models: "l"51        case .datasets: "d"52        case .train: "r"53        case .convert: "u"54        case .playground: "i"55        case .evaluate: "e"56        }57    }58}5960extension Notification.Name {61    /// Posted by the Foundry menu commands to switch workbench sections.62    static let zyquoNavigate = Notification.Name("zyquo.navigate")63}6465/// Root observable state for the workbench: library contents, run history,66/// active jobs, and the live memory readout in the navigator footer.67@Observable68@MainActor69final class AppModel {7071    var selectedSection: WorkbenchSection = .models7273    var models: [LocalModel] = []74    var datasets: [Dataset] = []75    var runs: [TrainingRun] = []76    var jobs: [Job] = []7778    var activeJobCount: Int { jobs.filter { $0.state == .running }.count }7980    /// GPU active memory, refreshed by the footer.81    var memoryUsedBytes: Int64 = 082    var memoryTotalBytes: Int64 = MemoryAdvisor.physicalMemory8384    var lastError: String?8586    /// Refresh all library-backed lists from disk.87    func refresh() async {88        do {89            try PersistenceService.ensureDirectories()90            models = try await ModelStore.shared.scan()91            datasets = try await DatasetService.shared.scan()92            runs = try await RunStore.shared.scan()93            let snapshot = await InferenceEngine.shared.memorySnapshot()94            memoryUsedBytes = Int64(snapshot.active)95        } catch {96            lastError = error.localizedDescription97        }98    }99}100