diff --git a/apps/macos/Sources/Clawdis/ConfigSettings.swift b/apps/macos/Sources/Clawdis/ConfigSettings.swift index 1d3d20691..1548e9e27 100644 --- a/apps/macos/Sources/Clawdis/ConfigSettings.swift +++ b/apps/macos/Sources/Clawdis/ConfigSettings.swift @@ -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 diff --git a/apps/macos/Sources/Clawdis/DebugSettings.swift b/apps/macos/Sources/Clawdis/DebugSettings.swift index efa209aad..5e0df03e1 100644 --- a/apps/macos/Sources/Clawdis/DebugSettings.swift +++ b/apps/macos/Sources/Clawdis/DebugSettings.swift @@ -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) } diff --git a/apps/macos/Sources/Clawdis/GatewayConnection.swift b/apps/macos/Sources/Clawdis/GatewayConnection.swift index c0458b8c9..0a4c176d3 100644 --- a/apps/macos/Sources/Clawdis/GatewayConnection.swift +++ b/apps/macos/Sources/Clawdis/GatewayConnection.swift @@ -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" diff --git a/apps/macos/Sources/Clawdis/SessionData.swift b/apps/macos/Sources/Clawdis/SessionData.swift index de0544df9..ebfbaac7f 100644 --- a/apps/macos/Sources/Clawdis/SessionData.swift +++ b/apps/macos/Sources/Clawdis/SessionData.swift @@ -163,7 +163,7 @@ extension SessionRow { } } -struct ModelChoice: Identifiable, Hashable { +struct ModelChoice: Identifiable, Hashable, Codable { let id: String let name: String let provider: String