diff --git a/clients/macos/vellum-assistant/Features/MainWindow/Panels/IdentityPanel.swift b/clients/macos/vellum-assistant/Features/MainWindow/Panels/IdentityPanel.swift index 80c05b0c091..3f0e1fa4d64 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/Panels/IdentityPanel.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/Panels/IdentityPanel.swift @@ -301,12 +301,15 @@ struct IdentityPanel: View { let response = await SkillsClient().fetchSkillsList(includeCatalog: false) if let response { let enabled = response.skills.filter { $0.status == "enabled" } + let map = await Task.detached { + var m: [String: SkillCategory] = [:] + m.reserveCapacity(enabled.count) + for skill in enabled { + m[skill.id] = inferCategory(skill) + } + return m + }.value skills = enabled - var map: [String: SkillCategory] = [:] - map.reserveCapacity(enabled.count) - for skill in enabled { - map[skill.id] = inferCategory(skill) - } skillCategoryLookup = map } } diff --git a/clients/macos/vellum-assistant/Features/MainWindow/Panels/SkillsManager.swift b/clients/macos/vellum-assistant/Features/MainWindow/Panels/SkillsManager.swift index 96be2872b4f..bea40aefbb6 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/Panels/SkillsManager.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/Panels/SkillsManager.swift @@ -37,6 +37,7 @@ final class SkillsManager { /// Cached skill-id -> category map, rebuilt whenever `skills` changes. /// Use `category(for:)` for O(1) lookups instead of calling `inferCategory` in view bodies. private(set) var categoryMap: [String: SkillCategory] = [:] + @ObservationIgnored private var categoryFingerprints: [String: String] = [:] var loadedBodies: [String: String] = [:] var isLoading = false var uninstallResult: SkillsStore.UninstallResult? @@ -122,11 +123,20 @@ final class SkillsManager { private func rebuildCategoryMap(from skills: [SkillInfo]) { var map: [String: SkillCategory] = [:] + var fingerprints: [String: String] = [:] map.reserveCapacity(skills.count) + fingerprints.reserveCapacity(skills.count) for skill in skills { - map[skill.id] = inferCategory(skill) + let fp = skill.name + "\0" + skill.description + if let cached = categoryMap[skill.id], categoryFingerprints[skill.id] == fp { + map[skill.id] = cached + } else { + map[skill.id] = inferCategory(skill) + } + fingerprints[skill.id] = fp } categoryMap = map + categoryFingerprints = fingerprints } // MARK: - Recomputation