bbcf0c74bb
- 19 Swift source files (~4900 lines) - Complete UI with SwiftUI (MainView, SettingsView, MessageBubble, InputBar) - Inference layer (LlmEngine, Agent, ToolCalling, ConversationContext) - Services (Audio, TTS, WebSearch, ModelDownload, Storage) - Build system: Makefile, Package.swift, Podfile - Documentation: BUILD.md, plan.md, PROJECT_STATUS.md - Ready for Xcode build - just need LiteRT dependency added
55 lines
1.8 KiB
Swift
55 lines
1.8 KiB
Swift
import Foundation
|
|
|
|
@MainActor
|
|
final class AppContainer: ObservableObject {
|
|
let audioRecorder = AudioRecorder()
|
|
let ttsService = TtsService()
|
|
let webSearchService = WebSearchService()
|
|
let modelDownloadService = ModelDownloadService()
|
|
let conversationStorage = ConversationStorage()
|
|
let llmEngine = LlmEngine()
|
|
let conversationContext = ConversationContext()
|
|
|
|
lazy var agent: Agent = {
|
|
Agent(llmEngine: llmEngine, context: conversationContext, webSearch: webSearchService)
|
|
}()
|
|
|
|
lazy var mainViewModel: MainViewModel = {
|
|
MainViewModel(
|
|
agent: agent,
|
|
audioRecorder: audioRecorder,
|
|
ttsService: ttsService,
|
|
conversationStorage: conversationStorage,
|
|
llmEngine: llmEngine
|
|
)
|
|
}()
|
|
|
|
lazy var settingsViewModel: SettingsViewModel = {
|
|
SettingsViewModel(
|
|
modelDownloadService: modelDownloadService,
|
|
llmEngine: llmEngine
|
|
)
|
|
}()
|
|
|
|
init() {
|
|
Task {
|
|
await autoDetectModel()
|
|
}
|
|
}
|
|
|
|
private func autoDetectModel() async {
|
|
let fileManager = FileManager.default
|
|
guard let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.path else { return }
|
|
|
|
let modelsPath = (documentsPath as NSString).appendingPathComponent("models")
|
|
let e2bPath = (modelsPath as NSString).appendingPathComponent("gemma-4-E2B-it.litertlm")
|
|
let e4bPath = (modelsPath as NSString).appendingPathComponent("gemma-4-E4B-it.litertlm")
|
|
|
|
if fileManager.fileExists(atPath: e2bPath) {
|
|
_ = try? await llmEngine.loadModel(path: e2bPath)
|
|
} else if fileManager.fileExists(atPath: e4bPath) {
|
|
_ = try? await llmEngine.loadModel(path: e4bPath)
|
|
}
|
|
}
|
|
}
|