feat(macos): load models from gateway

This commit is contained in:
Peter Steinberger
2025-12-20 23:24:09 +01:00
parent e3015bbfb7
commit 8c18dd40a3
4 changed files with 46 additions and 7 deletions

View File

@@ -17,6 +17,7 @@ struct ConfigSettings: View {
@State private var models: [ModelChoice] = []
@State private var modelsLoading = false
@State private var modelError: String?
@State private var modelsSourceLabel: String?
@AppStorage(modelCatalogPathKey) private var modelCatalogPath: String = ModelCatalogLoader.defaultPath
@AppStorage(modelCatalogReloadKey) private var modelCatalogReloadBump: Int = 0
@State private var allowAutosave = false
@@ -142,6 +143,12 @@ struct ConfigSettings: View {
.font(.footnote)
.foregroundStyle(.secondary)
}
if let modelsSourceLabel {
Text("Model catalog: \(modelsSourceLabel)")
.font(.footnote)
.foregroundStyle(.secondary)
}
}
private var anthropicAuthHelpText: String {
@@ -410,20 +417,44 @@ struct ConfigSettings: View {
guard !self.modelsLoading else { return }
self.modelsLoading = true
self.modelError = nil
self.modelsSourceLabel = nil
do {
let loaded = try await ModelCatalogLoader.load(from: self.modelCatalogPath)
self.models = loaded
if !self.configModel.isEmpty, !loaded.contains(where: { $0.id == self.configModel }) {
let res: ModelsListResult =
try await GatewayConnection.shared
.requestDecoded(
method: .modelsList,
timeoutMs: 15000)
self.models = res.models
self.modelsSourceLabel = "gateway"
if !self.configModel.isEmpty,
!res.models.contains(where: { $0.id == self.configModel })
{
self.customModel = self.configModel
self.configModel = "__custom__"
}
} catch {
self.modelError = error.localizedDescription
self.models = []
do {
let loaded = try await ModelCatalogLoader.load(from: self.modelCatalogPath)
self.models = loaded
self.modelsSourceLabel = "local fallback"
if !self.configModel.isEmpty,
!loaded.contains(where: { $0.id == self.configModel })
{
self.customModel = self.configModel
self.configModel = "__custom__"
}
} catch {
self.modelError = error.localizedDescription
self.models = []
}
}
self.modelsLoading = false
}
private struct ModelsListResult: Decodable {
let models: [ModelChoice]
}
private var selectedContextLabel: String? {
let chosenId = (self.configModel == "__custom__") ? self.customModel : self.configModel
guard

View File

@@ -404,7 +404,7 @@ struct DebugSettings: View {
.font(.footnote)
.foregroundStyle(.secondary)
}
Text("Used by the Config tab model picker; point at a different build when debugging.")
Text("Local fallback for model picker when gateway models.list is unavailable.")
.font(.footnote)
.foregroundStyle(.tertiary)
}

View File

@@ -47,6 +47,14 @@ actor GatewayConnection {
case setHeartbeats = "set-heartbeats"
case systemEvent = "system-event"
case health
case providersStatus = "providers.status"
case configGet = "config.get"
case configSet = "config.set"
case webLoginStart = "web.login.start"
case webLoginWait = "web.login.wait"
case webLogout = "web.logout"
case telegramLogout = "telegram.logout"
case modelsList = "models.list"
case chatHistory = "chat.history"
case chatSend = "chat.send"
case chatAbort = "chat.abort"

View File

@@ -163,7 +163,7 @@ extension SessionRow {
}
}
struct ModelChoice: Identifiable, Hashable {
struct ModelChoice: Identifiable, Hashable, Codable {
let id: String
let name: String
let provider: String