Stores leben jetzt im Package mit App-übergreifenden Keys (mana.llm.backend, mana.llm.allowCellular). Auto-Migration aus memoro.* Legacy-Keys beim ersten Read (memoro.llmBackend, memoro.onDeviceLLMEnabled Bool-Toggle, memoro.llmDownloadOverCellular). Ermöglicht ManaLLMUI in mana-swift-ui 0.8.0 als geteilte Settings- Schicht für alle 4 Konsumenten (Memoro, Pageta, Comicello, Herbatrium). Außerdem: - LLMBackend.removeCachedModel() als Protocol-Methode mit Default- No-Op. GemmaBackend überschreibt (async throws statt throws). - 13 neue Tests in LLMPreferenceStoresTests (.serialized wegen UserDefaults.standard). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
62 lines
2.4 KiB
Swift
62 lines
2.4 KiB
Swift
import Foundation
|
|
|
|
/// Persistenter UserDefaults-Store für die User-Wahl des On-Device-LLM-
|
|
/// Backends. Geteilt von allen mana-e.V.-Apps (Memoro, Pageta, Comicello,
|
|
/// Herbatrium, …) — Wert lebt pro App in `UserDefaults.standard`, weil
|
|
/// verschiedene Apps verschiedene Use-Case-Präferenzen haben können
|
|
/// (z.B. Moodlit favorisiert Gemma E2B wegen Creative-Mood-Mapping,
|
|
/// Pageta favorisiert AppleFM wegen Latenz beim Artikel-Summary).
|
|
///
|
|
/// **Default-Wert:** `.appleFM`. Auf Geräten ohne Apple Intelligence
|
|
/// fällt der Router zur Runtime über `availability()` auf den nächsten
|
|
/// selectable Backend zurück; der Default ist also "optimistisch" und
|
|
/// muss in der UI nicht selbst nachgepflegt werden.
|
|
///
|
|
/// **Legacy-Migration:** Apps die früher eigene Keys hatten werden
|
|
/// einmalig migriert:
|
|
/// - `memoro.llmBackend` (Memoros bisheriger Key) → `mana.llm.backend`
|
|
/// - `memoro.onDeviceLLMEnabled` (Memoros älterer Bool-Toggle) →
|
|
/// `.appleFM` (true) bzw. `.noOp` (false), dann auf
|
|
/// `mana.llm.backend`
|
|
///
|
|
/// Die Migration läuft auf jedem Read aus `current`. Erster Read
|
|
/// migriert + löscht den Legacy-Key; danach existiert nur noch der
|
|
/// neue Key.
|
|
public enum LLMBackendPreferenceStore {
|
|
private static let key = "mana.llm.backend"
|
|
private static let legacyMemoroKey = "memoro.llmBackend"
|
|
private static let legacyMemoroBoolKey = "memoro.onDeviceLLMEnabled"
|
|
|
|
/// Aktuelle Backend-Wahl. Läuft die Migration aus Legacy-Keys
|
|
/// einmalig durch (siehe Doc-Kommentar oben).
|
|
public static var current: LLMBackendID {
|
|
// 1. Neuer Key
|
|
if let raw = UserDefaults.standard.string(forKey: key),
|
|
let value = LLMBackendID(rawValue: raw)
|
|
{
|
|
return value
|
|
}
|
|
// 2. Memoro-Legacy-String-Key
|
|
if let raw = UserDefaults.standard.string(forKey: legacyMemoroKey),
|
|
let value = LLMBackendID(rawValue: raw)
|
|
{
|
|
set(value)
|
|
UserDefaults.standard.removeObject(forKey: legacyMemoroKey)
|
|
return value
|
|
}
|
|
// 3. Memoros älterer Bool-Toggle
|
|
if UserDefaults.standard.object(forKey: legacyMemoroBoolKey) != nil {
|
|
let wasEnabled = UserDefaults.standard.bool(forKey: legacyMemoroBoolKey)
|
|
let migrated: LLMBackendID = wasEnabled ? .appleFM : .noOp
|
|
set(migrated)
|
|
UserDefaults.standard.removeObject(forKey: legacyMemoroBoolKey)
|
|
return migrated
|
|
}
|
|
// 4. Default
|
|
return .appleFM
|
|
}
|
|
|
|
public static func set(_ value: LLMBackendID) {
|
|
UserDefaults.standard.set(value.rawValue, forKey: key)
|
|
}
|
|
}
|