@sriinnu/runic 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +8 -1
  3. package/RuniciOS/Core/RunicTypographyiOS.swift +24 -0
  4. package/RuniciOS/Views/ProviderDetailView.swift +9 -9
  5. package/RuniciOS/Views/ProviderListView.swift +10 -10
  6. package/RuniciOS/Widgets/LargeWidget.swift +14 -14
  7. package/RuniciOS/Widgets/LiveActivity.swift +19 -19
  8. package/RuniciOS/Widgets/LockScreenWidget.swift +15 -15
  9. package/RuniciOS/Widgets/MediumWidget.swift +10 -10
  10. package/RuniciOS/Widgets/RunicWidget.swift +5 -5
  11. package/RuniciOS/Widgets/SmallWidget.swift +9 -9
  12. package/Sources/Runic/About.swift +3 -3
  13. package/Sources/Runic/AppNotifications.swift +5 -3
  14. package/Sources/Runic/Controllers/StatusItemController+Actions.swift +7 -3
  15. package/Sources/Runic/Controllers/StatusItemController+Animation.swift +5 -4
  16. package/Sources/Runic/Controllers/StatusItemController+ChartSubmenus.swift +30 -16
  17. package/Sources/Runic/Controllers/StatusItemController+CustomProviders.swift +6 -3
  18. package/Sources/Runic/Controllers/StatusItemController+Menu.swift +18 -13
  19. package/Sources/Runic/Controllers/StatusItemController+MenuCards.swift +6 -4
  20. package/Sources/Runic/Controllers/StatusItemController+MenuHelpers.swift +40 -12
  21. package/Sources/Runic/Controllers/StatusItemController.swift +43 -43
  22. package/Sources/Runic/Core/BudgetNotificationManager.swift +2 -1
  23. package/Sources/Runic/Core/Login/ClaudeLoginRunner.swift +2 -2
  24. package/Sources/Runic/Core/Login/CodexLoginRunner.swift +1 -1
  25. package/Sources/Runic/Core/Login/CursorLoginRunner.swift +4 -4
  26. package/Sources/Runic/Core/Login/GeminiLoginRunner.swift +1 -1
  27. package/Sources/Runic/Core/Rendering/IconRenderer.swift +91 -85
  28. package/Sources/Runic/Core/Rendering/IconView.swift +3 -1
  29. package/Sources/Runic/Core/RunicColors.swift +6 -6
  30. package/Sources/Runic/Core/RunicSpacing.swift +7 -7
  31. package/Sources/Runic/Core/RunicTypography.swift +206 -0
  32. package/Sources/Runic/Core/Stores/AuggieTokenStore.swift +1 -3
  33. package/Sources/Runic/Core/Stores/AzureOpenAITokenStore.swift +1 -3
  34. package/Sources/Runic/Core/Stores/CerebrasTokenStore.swift +1 -3
  35. package/Sources/Runic/Core/Stores/CohereTokenStore.swift +1 -3
  36. package/Sources/Runic/Core/Stores/CopilotTokenStore.swift +1 -3
  37. package/Sources/Runic/Core/Stores/CustomProviderStore.swift +10 -10
  38. package/Sources/Runic/Core/Stores/DeepSeekTokenStore.swift +1 -3
  39. package/Sources/Runic/Core/Stores/FireworksTokenStore.swift +1 -3
  40. package/Sources/Runic/Core/Stores/GroqTokenStore.swift +1 -3
  41. package/Sources/Runic/Core/Stores/KimiTokenStore.swift +1 -3
  42. package/Sources/Runic/Core/Stores/MiniMaxCookieHeaderStore.swift +1 -3
  43. package/Sources/Runic/Core/Stores/MiniMaxGroupIDStore.swift +1 -3
  44. package/Sources/Runic/Core/Stores/MiniMaxTokenStore.swift +1 -3
  45. package/Sources/Runic/Core/Stores/MistralTokenStore.swift +1 -3
  46. package/Sources/Runic/Core/Stores/OpenRouterTokenStore.swift +1 -3
  47. package/Sources/Runic/Core/Stores/PerplexityTokenStore.swift +1 -3
  48. package/Sources/Runic/Core/Stores/ProviderToggleStore.swift +1 -1
  49. package/Sources/Runic/Core/Stores/QwenTokenStore.swift +1 -3
  50. package/Sources/Runic/Core/Stores/SambaNovaTokenStore.swift +1 -3
  51. package/Sources/Runic/Core/Stores/SettingsStore.swift +89 -51
  52. package/Sources/Runic/Core/Stores/TogetherTokenStore.swift +1 -3
  53. package/Sources/Runic/Core/Stores/UsageStore+Accessors.swift +19 -6
  54. package/Sources/Runic/Core/Stores/UsageStore+TokenCost.swift +1 -1
  55. package/Sources/Runic/Core/Stores/UsageStore+WidgetSnapshot.swift +1 -1
  56. package/Sources/Runic/Core/Stores/UsageStore.swift +187 -161
  57. package/Sources/Runic/Core/Stores/XAITokenStore.swift +1 -3
  58. package/Sources/Runic/Core/Stores/ZaiTokenStore.swift +1 -2
  59. package/Sources/Runic/Core/UsageExporter.swift +8 -4
  60. package/Sources/Runic/ProviderRegistry.swift +1 -1
  61. package/Sources/Runic/Providers/Antigravity/AntigravityProviderImplementation.swift +1 -1
  62. package/Sources/Runic/Providers/Auggie/AuggieProviderImplementation.swift +1 -1
  63. package/Sources/Runic/Providers/Azure/AzureProviderImplementation.swift +1 -1
  64. package/Sources/Runic/Providers/Bedrock/BedrockProviderImplementation.swift +1 -1
  65. package/Sources/Runic/Providers/Cerebras/CerebrasProviderImplementation.swift +1 -1
  66. package/Sources/Runic/Providers/Codex/CodexProviderImplementation.swift +1 -1
  67. package/Sources/Runic/Providers/Cohere/CohereProviderImplementation.swift +1 -1
  68. package/Sources/Runic/Providers/Cursor/CursorProviderImplementation.swift +1 -1
  69. package/Sources/Runic/Providers/DeepSeek/DeepSeekProviderImplementation.swift +1 -1
  70. package/Sources/Runic/Providers/Factory/FactoryProviderImplementation.swift +1 -1
  71. package/Sources/Runic/Providers/Fireworks/FireworksProviderImplementation.swift +1 -1
  72. package/Sources/Runic/Providers/Gemini/GeminiProviderImplementation.swift +1 -1
  73. package/Sources/Runic/Providers/Groq/GroqProviderImplementation.swift +1 -1
  74. package/Sources/Runic/Providers/Kimi/KimiProviderImplementation.swift +1 -1
  75. package/Sources/Runic/Providers/MiniMax/MiniMaxProviderImplementation.swift +1 -1
  76. package/Sources/Runic/Providers/Mistral/MistralProviderImplementation.swift +1 -1
  77. package/Sources/Runic/Providers/OpenRouter/OpenRouterProviderImplementation.swift +1 -1
  78. package/Sources/Runic/Providers/Perplexity/PerplexityProviderImplementation.swift +1 -1
  79. package/Sources/Runic/Providers/SambaNova/SambaNovaProviderImplementation.swift +1 -1
  80. package/Sources/Runic/Providers/Shared/ProviderImplementation.swift +5 -2
  81. package/Sources/Runic/Providers/Shared/ProviderImplementationRegistry.swift +1 -1
  82. package/Sources/Runic/Providers/Shared/ProviderSettingsDescriptors.swift +1 -1
  83. package/Sources/Runic/Providers/Together/TogetherProviderImplementation.swift +1 -1
  84. package/Sources/Runic/Providers/XAI/XAIProviderImplementation.swift +1 -1
  85. package/Sources/Runic/Providers/Zai/ZaiProviderImplementation.swift +1 -1
  86. package/Sources/Runic/Resources/Fonts/Caveat-Bold.ttf +0 -0
  87. package/Sources/Runic/Resources/Fonts/Caveat-Regular.ttf +0 -0
  88. package/Sources/Runic/Resources/Fonts/FiraCode-Bold.ttf +0 -0
  89. package/Sources/Runic/Resources/Fonts/FiraCode-Light.ttf +0 -0
  90. package/Sources/Runic/Resources/Fonts/FiraCode-Medium.ttf +0 -0
  91. package/Sources/Runic/Resources/Fonts/FiraCode-Regular.ttf +0 -0
  92. package/Sources/Runic/Resources/Fonts/FiraCode-SemiBold.ttf +0 -0
  93. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Bold.ttf +0 -0
  94. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Medium.ttf +0 -0
  95. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Regular.ttf +0 -0
  96. package/Sources/Runic/Resources/Fonts/IBMPlexMono-SemiBold.ttf +0 -0
  97. package/Sources/Runic/Resources/Fonts/Inconsolata-Bold.ttf +0 -0
  98. package/Sources/Runic/Resources/Fonts/Inconsolata-Medium.ttf +0 -0
  99. package/Sources/Runic/Resources/Fonts/Inconsolata-Regular.ttf +0 -0
  100. package/Sources/Runic/Resources/Fonts/Inconsolata-SemiBold.ttf +0 -0
  101. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Bold.ttf +0 -0
  102. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Medium.ttf +0 -0
  103. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Regular.ttf +0 -0
  104. package/Sources/Runic/Resources/Fonts/JetBrainsMono-SemiBold.ttf +0 -0
  105. package/Sources/Runic/Resources/Fonts/SpaceMono-Bold.ttf +0 -0
  106. package/Sources/Runic/Resources/Fonts/SpaceMono-Regular.ttf +0 -0
  107. package/Sources/Runic/RunicApp.swift +46 -36
  108. package/Sources/Runic/SessionQuotaNotifications.swift +2 -2
  109. package/Sources/Runic/UsagePaceText.swift +1 -1
  110. package/Sources/Runic/UsageProgressBar.swift +13 -9
  111. package/Sources/Runic/Utilities/LoadingPattern.swift +4 -2
  112. package/Sources/Runic/Utilities/PerformanceConstants.swift +28 -28
  113. package/Sources/Runic/Views/Menu/AlertsMenuView.swift +19 -21
  114. package/Sources/Runic/Views/Menu/CostComparativeChartMenuView.swift +19 -19
  115. package/Sources/Runic/Views/Menu/CostHistoryChartMenuView.swift +7 -7
  116. package/Sources/Runic/Views/Menu/CreditsHistoryChartMenuView.swift +5 -5
  117. package/Sources/Runic/Views/Menu/EfficiencyMetricsMenuView.swift +29 -30
  118. package/Sources/Runic/Views/Menu/HeroStatCardsMenuView.swift +20 -17
  119. package/Sources/Runic/Views/Menu/HourlyActivityChartMenuView.swift +14 -14
  120. package/Sources/Runic/Views/Menu/InlineUsageChartView.swift +12 -10
  121. package/Sources/Runic/Views/Menu/MenuCardEntranceModifier.swift +3 -4
  122. package/Sources/Runic/Views/Menu/MenuCardSidebarView.swift +5 -25
  123. package/Sources/Runic/Views/Menu/MenuCardSkeletonView.swift +1 -1
  124. package/Sources/Runic/Views/Menu/MenuCardView.swift +120 -131
  125. package/Sources/Runic/Views/Menu/MenuContent.swift +11 -8
  126. package/Sources/Runic/Views/Menu/MenuDescriptor.swift +4 -2
  127. package/Sources/Runic/Views/Menu/MenuHighlightStyle.swift +1 -8
  128. package/Sources/Runic/Views/Menu/ModelBreakdownMenuView.swift +20 -14
  129. package/Sources/Runic/Views/Menu/OverviewMenuView.swift +18 -15
  130. package/Sources/Runic/Views/Menu/ProjectBreakdownMenuView.swift +16 -11
  131. package/Sources/Runic/Views/Menu/ProjectBudgetMenuView.swift +27 -27
  132. package/Sources/Runic/Views/Menu/ProviderTabBarView.swift +4 -6
  133. package/Sources/Runic/Views/Menu/SubscriptionUtilizationChartMenuView.swift +24 -11
  134. package/Sources/Runic/Views/Menu/UsageBreakdownChartMenuView.swift +5 -5
  135. package/Sources/Runic/Views/Menu/UsageHeatmapMenuView.swift +7 -8
  136. package/Sources/Runic/Views/Menu/UsageTimelineChartMenuView.swift +22 -17
  137. package/Sources/Runic/Views/Menu/UsageWindowComparisonChartMenuView.swift +8 -7
  138. package/Sources/Runic/Views/Menu/WeeklyActivityChartMenuView.swift +7 -7
  139. package/Sources/Runic/Views/Performance/PerformanceDashboardView.swift +50 -47
  140. package/Sources/Runic/Views/Preferences/LiquidComponents.swift +15 -14
  141. package/Sources/Runic/Views/Preferences/PreferencesAboutPane.swift +7 -7
  142. package/Sources/Runic/Views/Preferences/PreferencesAdvancedPane.swift +27 -27
  143. package/Sources/Runic/Views/Preferences/PreferencesAlertsPane.swift +38 -42
  144. package/Sources/Runic/Views/Preferences/PreferencesAnalyticsPane.swift +39 -43
  145. package/Sources/Runic/Views/Preferences/PreferencesBudgetsPane.swift +21 -21
  146. package/Sources/Runic/Views/Preferences/PreferencesComponents.swift +7 -7
  147. package/Sources/Runic/Views/Preferences/PreferencesCustomProvidersPane.swift +49 -50
  148. package/Sources/Runic/Views/Preferences/PreferencesDebugPane.swift +10 -10
  149. package/Sources/Runic/Views/Preferences/PreferencesGeneralPane.swift +40 -21
  150. package/Sources/Runic/Views/Preferences/PreferencesHelpPane.swift +7 -7
  151. package/Sources/Runic/Views/Preferences/PreferencesIntegrationsPane.swift +44 -39
  152. package/Sources/Runic/Views/Preferences/PreferencesPerformancePane.swift +26 -23
  153. package/Sources/Runic/Views/Preferences/PreferencesProvidersPane.swift +271 -226
  154. package/Sources/Runic/Views/Preferences/PreferencesSelection.swift +6 -2
  155. package/Sources/Runic/Views/Preferences/PreferencesSyncPane.swift +7 -5
  156. package/Sources/Runic/Views/Preferences/PreferencesView.swift +38 -31
  157. package/Sources/Runic/Views/Rating/QualityRatingView.swift +11 -11
  158. package/Sources/Runic/Views/Team/TeamDashboardView.swift +29 -24
  159. package/Sources/Runic/Views/Team/TeamInviteSheet.swift +16 -16
  160. package/Sources/Runic/Views/Team/TeamManagementView.swift +50 -49
  161. package/Sources/Runic/Views/Team/TeamMemberRow.swift +8 -8
  162. package/Sources/RunicCLI/CLIEntry.swift +83 -42
  163. package/Sources/RunicCLI/CLIRenderer.swift +1 -1
  164. package/Sources/RunicCLI/Commands/EnhancedUsageCommand.swift +60 -60
  165. package/Sources/RunicCLI/Commands/ModelsCommand.swift +45 -44
  166. package/Sources/RunicCLI/Commands/ProjectsCommand.swift +83 -69
  167. package/Sources/RunicCLI/Commands/ResetCommand.swift +50 -49
  168. package/Sources/RunicCLI/Commands/UsageLedgerSourceFactory.swift +31 -32
  169. package/Sources/RunicClaudeWebProbe/main.swift +1 -1
  170. package/Sources/RunicCore/AlertRuleStore.swift +20 -20
  171. package/Sources/RunicCore/BrowserCookieImportOrder.swift +3 -3
  172. package/Sources/RunicCore/CostUsageModels.swift +1 -1
  173. package/Sources/RunicCore/CustomProviders/CustomProviderModels.swift +29 -30
  174. package/Sources/RunicCore/CustomProviders/GenericProviderFetcher.swift +73 -75
  175. package/Sources/RunicCore/CustomProviders/ProviderTemplates.swift +53 -109
  176. package/Sources/RunicCore/Host/PTY/TTYCommandRunner.swift +3 -3
  177. package/Sources/RunicCore/Integrations/GitHubIntegration.swift +3 -3
  178. package/Sources/RunicCore/Models/EnhancedUsageModels.swift +47 -48
  179. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift +1 -1
  180. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardFetcher.swift +1 -1
  181. package/Sources/RunicCore/Performance/PerformanceModels.swift +4 -4
  182. package/Sources/RunicCore/Performance/PerformanceStorageImpl.swift +81 -64
  183. package/Sources/RunicCore/Policy/UsagePolicyEngine.swift +2 -2
  184. package/Sources/RunicCore/ProjectBudgetStore.swift +15 -12
  185. package/Sources/RunicCore/Providers/Antigravity/AntigravityProviderDescriptor.swift +4 -2
  186. package/Sources/RunicCore/Providers/Antigravity/AntigravityStatusProbe.swift +2 -2
  187. package/Sources/RunicCore/Providers/Auggie/AuggieProviderDescriptor.swift +2 -2
  188. package/Sources/RunicCore/Providers/Auggie/AuggieUsageFetcher.swift +3 -3
  189. package/Sources/RunicCore/Providers/Azure/AzureProviderDescriptor.swift +8 -8
  190. package/Sources/RunicCore/Providers/Azure/AzureUsageFetcher.swift +3 -3
  191. package/Sources/RunicCore/Providers/Bedrock/BedrockProviderDescriptor.swift +6 -6
  192. package/Sources/RunicCore/Providers/Bedrock/BedrockUsageFetcher.swift +3 -7
  193. package/Sources/RunicCore/Providers/Cerebras/CerebrasProviderDescriptor.swift +2 -2
  194. package/Sources/RunicCore/Providers/Cerebras/CerebrasUsageFetcher.swift +2 -2
  195. package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift +3 -3
  196. package/Sources/RunicCore/Providers/Claude/ClaudeProviderDescriptor.swift +4 -2
  197. package/Sources/RunicCore/Providers/Claude/ClaudeStatusProbe.swift +4 -4
  198. package/Sources/RunicCore/Providers/Claude/ClaudeUsageDataSource.swift +3 -1
  199. package/Sources/RunicCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift +1 -1
  200. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift +1 -1
  201. package/Sources/RunicCore/Providers/Codex/CodexProviderDescriptor.swift +4 -2
  202. package/Sources/RunicCore/Providers/Codex/CodexUsageDataSource.swift +3 -1
  203. package/Sources/RunicCore/Providers/Codex/CodexWebDashboardStrategy.swift +5 -3
  204. package/Sources/RunicCore/Providers/Cohere/CohereProviderDescriptor.swift +2 -2
  205. package/Sources/RunicCore/Providers/Cohere/CohereUsageFetcher.swift +3 -3
  206. package/Sources/RunicCore/Providers/Copilot/CopilotGitHubCLITokenReader.swift +7 -4
  207. package/Sources/RunicCore/Providers/Copilot/CopilotProviderDescriptor.swift +4 -4
  208. package/Sources/RunicCore/Providers/Copilot/CopilotUsageFetcher.swift +5 -3
  209. package/Sources/RunicCore/Providers/Copilot/CopilotVSCodeTokenReader.swift +9 -10
  210. package/Sources/RunicCore/Providers/Cursor/CursorProviderDescriptor.swift +4 -2
  211. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift +2 -2
  212. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift +2 -2
  213. package/Sources/RunicCore/Providers/Factory/FactoryLocalStorageImporter.swift +4 -4
  214. package/Sources/RunicCore/Providers/Factory/FactoryProviderDescriptor.swift +4 -2
  215. package/Sources/RunicCore/Providers/Factory/FactoryStatusProbe.swift +2 -2
  216. package/Sources/RunicCore/Providers/Fireworks/FireworksProviderDescriptor.swift +2 -2
  217. package/Sources/RunicCore/Providers/Fireworks/FireworksUsageFetcher.swift +2 -2
  218. package/Sources/RunicCore/Providers/Gemini/GeminiProviderDescriptor.swift +4 -2
  219. package/Sources/RunicCore/Providers/Gemini/GeminiStatusProbe.swift +5 -2
  220. package/Sources/RunicCore/Providers/Groq/GroqProviderDescriptor.swift +2 -2
  221. package/Sources/RunicCore/Providers/Groq/GroqUsageFetcher.swift +2 -2
  222. package/Sources/RunicCore/Providers/Kimi/KimiProviderDescriptor.swift +2 -2
  223. package/Sources/RunicCore/Providers/Kimi/KimiUsageFetcher.swift +2 -2
  224. package/Sources/RunicCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift +10 -5
  225. package/Sources/RunicCore/Providers/MiniMax/MiniMaxUsageFetcher.swift +7 -7
  226. package/Sources/RunicCore/Providers/MiniMax/MiniMaxWebUsageFetcher.swift +10 -10
  227. package/Sources/RunicCore/Providers/Mistral/MistralProviderDescriptor.swift +2 -2
  228. package/Sources/RunicCore/Providers/Mistral/MistralUsageFetcher.swift +2 -2
  229. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift +2 -2
  230. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterUsageFetcher.swift +23 -10
  231. package/Sources/RunicCore/Providers/Perplexity/PerplexityProviderDescriptor.swift +2 -2
  232. package/Sources/RunicCore/Providers/Perplexity/PerplexityUsageFetcher.swift +2 -2
  233. package/Sources/RunicCore/Providers/ProviderFetchPlan.swift +2 -2
  234. package/Sources/RunicCore/Providers/ProviderTokenResolver.swift +2 -2
  235. package/Sources/RunicCore/Providers/Qwen/QwenProviderDescriptor.swift +5 -3
  236. package/Sources/RunicCore/Providers/Qwen/QwenUsageStats.swift +26 -13
  237. package/Sources/RunicCore/Providers/SambaNova/SambaNovaProviderDescriptor.swift +2 -2
  238. package/Sources/RunicCore/Providers/SambaNova/SambaNovaUsageFetcher.swift +2 -2
  239. package/Sources/RunicCore/Providers/Together/TogetherProviderDescriptor.swift +2 -2
  240. package/Sources/RunicCore/Providers/Together/TogetherUsageFetcher.swift +2 -2
  241. package/Sources/RunicCore/Providers/VertexAI/VertexAIProviderDescriptor.swift +5 -5
  242. package/Sources/RunicCore/Providers/VertexAI/VertexAISettingsReader.swift +1 -1
  243. package/Sources/RunicCore/Providers/VertexAI/VertexAIUsageFetcher.swift +3 -3
  244. package/Sources/RunicCore/Providers/XAI/XAIProviderDescriptor.swift +2 -2
  245. package/Sources/RunicCore/Providers/XAI/XAIUsageFetcher.swift +2 -2
  246. package/Sources/RunicCore/Providers/Zai/ZaiProviderDescriptor.swift +4 -2
  247. package/Sources/RunicCore/Providers/Zai/ZaiUsageStats.swift +48 -21
  248. package/Sources/RunicCore/Sync/BackgroundSyncManager.swift +76 -77
  249. package/Sources/RunicCore/Sync/SyncConflictResolver.swift +55 -58
  250. package/Sources/RunicCore/Sync/SyncProtocol.swift +21 -22
  251. package/Sources/RunicCore/Sync/SyncRecord.swift +46 -49
  252. package/Sources/RunicCore/Sync/SyncUsageExample.swift +44 -50
  253. package/Sources/RunicCore/Sync/TeamSyncRecords.swift +94 -101
  254. package/Sources/RunicCore/Sync/iCloudSyncEngine.swift +51 -46
  255. package/Sources/RunicCore/Team/TeamModels.swift +111 -110
  256. package/Sources/RunicCore/Team/TeamStore.swift +126 -109
  257. package/Sources/RunicCore/UsageFetcher.swift +2 -2
  258. package/Sources/RunicCore/UsageFormatter.swift +25 -25
  259. package/Sources/RunicCore/UsageLedger/ClaudeUsageLogSource.swift +27 -13
  260. package/Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift +11 -3
  261. package/Sources/RunicCore/UsageLedger/LedgerCache.swift +5 -2
  262. package/Sources/RunicCore/UsageLedger/OTelGenAILedgerAdapter.swift +1 -1
  263. package/Sources/RunicCore/UsageLedger/UsageLedgerAggregator.swift +40 -25
  264. package/Sources/RunicCore/UsageLedger/UsageLedgerInsightsAdvisor.swift +1 -1
  265. package/Sources/RunicCore/UsageLedger/UsageLedgerProjectIdentity.swift +55 -16
  266. package/Sources/RunicCore/Vendored/CostUsage/CostUsageCache.swift +6 -6
  267. package/Sources/RunicCore/Vendored/CostUsage/CostUsageJsonl.swift +1 -1
  268. package/Sources/RunicCore/Vendored/CostUsage/CostUsagePricing.swift +2 -2
  269. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner.swift +5 -5
  270. package/Tests/RunicTests/AppDelegateTests.swift +8 -3
  271. package/Tests/RunicTests/BrowserCookieOrderLabelTests.swift +2 -3
  272. package/Tests/RunicTests/CLIArgumentParsingTests.swift +3 -4
  273. package/Tests/RunicTests/CLICostTests.swift +6 -7
  274. package/Tests/RunicTests/CLIProviderSelectionTests.swift +2 -3
  275. package/Tests/RunicTests/CLISnapshotTests.swift +3 -4
  276. package/Tests/RunicTests/CLIWebFallbackTests.swift +3 -4
  277. package/Tests/RunicTests/ClaudeOAuthTests.swift +11 -12
  278. package/Tests/RunicTests/ClaudeResilienceTests.swift +3 -4
  279. package/Tests/RunicTests/ClaudeUsageTests.swift +20 -21
  280. package/Tests/RunicTests/CodexOAuthTests.swift +7 -8
  281. package/Tests/RunicTests/CodexUsageLogSourceTests.swift +1 -3
  282. package/Tests/RunicTests/CopilotTokenResolverTests.swift +5 -6
  283. package/Tests/RunicTests/CopilotVSCodeTokenReaderTests.swift +4 -5
  284. package/Tests/RunicTests/CostUsageDecodingTests.swift +15 -17
  285. package/Tests/RunicTests/CostUsagePricingTests.swift +5 -7
  286. package/Tests/RunicTests/CostUsageScannerTests.swift +10 -12
  287. package/Tests/RunicTests/CursorStatusProbeTests.swift +15 -16
  288. package/Tests/RunicTests/FactoryStatusProbeTests.swift +3 -5
  289. package/Tests/RunicTests/GeminiLoginAlertTests.swift +3 -4
  290. package/Tests/RunicTests/GeminiStatusProbeAPITests.swift +11 -11
  291. package/Tests/RunicTests/GeminiStatusProbePlanTests.swift +8 -8
  292. package/Tests/RunicTests/GeminiStatusProbeTests.swift +20 -21
  293. package/Tests/RunicTests/GoogleWorkspaceStatusTests.swift +2 -3
  294. package/Tests/RunicTests/InstallOriginTests.swift +1 -2
  295. package/Tests/RunicTests/KeyboardShortcutsBundleTests.swift +2 -2
  296. package/Tests/RunicTests/LiveAccountTests.swift +3 -3
  297. package/Tests/RunicTests/LoadingPatternTests.swift +3 -4
  298. package/Tests/RunicTests/MenuCardModelTests.swift +33 -34
  299. package/Tests/RunicTests/MiniMaxCookieHeaderStoreTestSupport.swift +4 -1
  300. package/Tests/RunicTests/MiniMaxGroupIDStoreTestSupport.swift +4 -1
  301. package/Tests/RunicTests/MiniMaxParsingTests.swift +4 -5
  302. package/Tests/RunicTests/MiniMaxTokenStoreTestSupport.swift +4 -1
  303. package/Tests/RunicTests/OTelGenAILedgerAdapterTests.swift +4 -6
  304. package/Tests/RunicTests/OpenAIDashboardBrowserCookieImporterTests.swift +1 -2
  305. package/Tests/RunicTests/OpenAIDashboardFetcherCreditsWaitTests.swift +5 -6
  306. package/Tests/RunicTests/OpenAIDashboardOffscreenHostTests.swift +2 -3
  307. package/Tests/RunicTests/OpenAIDashboardParserTests.swift +12 -13
  308. package/Tests/RunicTests/OpenAIWebAccountSwitchTests.swift +17 -6
  309. package/Tests/RunicTests/OpenRouterTokenStoreTestSupport.swift +52 -13
  310. package/Tests/RunicTests/PathBuilderTests.swift +14 -15
  311. package/Tests/RunicTests/ProviderFetchPipelineTests.swift +3 -4
  312. package/Tests/RunicTests/ProviderIconResourcesTests.swift +1 -2
  313. package/Tests/RunicTests/ProviderMetadataStatusLinkTests.swift +1 -2
  314. package/Tests/RunicTests/ProviderSettingsDescriptorTests.swift +53 -19
  315. package/Tests/RunicTests/ProviderToggleStoreTests.swift +10 -11
  316. package/Tests/RunicTests/RunicTests.swift +6 -7
  317. package/Tests/RunicTests/SessionQuotaNotificationLogicTests.swift +5 -6
  318. package/Tests/RunicTests/SettingsStoreTests.swift +149 -45
  319. package/Tests/RunicTests/StatusItemAnimationTests.swift +8 -3
  320. package/Tests/RunicTests/StatusMenuTests.swift +63 -22
  321. package/Tests/RunicTests/StatusProbeTests.swift +28 -29
  322. package/Tests/RunicTests/SubprocessRunnerTests.swift +1 -3
  323. package/Tests/RunicTests/SubscriptionDetectionTests.swift +8 -9
  324. package/Tests/RunicTests/TTYCommandRunnerTests.swift +8 -9
  325. package/Tests/RunicTests/TeamShowbackExporterTests.swift +2 -4
  326. package/Tests/RunicTests/TextParsingTests.swift +1 -2
  327. package/Tests/RunicTests/UsageFormatterTests.swift +15 -16
  328. package/Tests/RunicTests/UsageLedgerAnomalyDetectionTests.swift +12 -14
  329. package/Tests/RunicTests/UsageLedgerForecastTests.swift +4 -6
  330. package/Tests/RunicTests/UsageLedgerInsightsAdvisorTests.swift +7 -9
  331. package/Tests/RunicTests/UsageLedgerProjectNameTests.swift +6 -8
  332. package/Tests/RunicTests/UsagePaceTests.swift +5 -6
  333. package/Tests/RunicTests/UsagePaceTextTests.swift +8 -9
  334. package/Tests/RunicTests/UsagePolicyEngineTests.swift +3 -5
  335. package/Tests/RunicTests/WidgetSnapshotTests.swift +1 -3
  336. package/Tests/RunicTests/ZaiProviderTests.swift +3 -5
  337. package/Tests/RunicTests/ZaiTokenStoreTestSupport.swift +4 -1
  338. package/appcast.xml +36 -76
  339. package/package.json +1 -1
  340. package/runic.png +0 -0
  341. package/runic.svg +15 -0
  342. package/version.env +2 -2
@@ -26,32 +26,32 @@ struct HeroTodayStatView: View {
26
26
  VStack(alignment: .leading, spacing: 0) {
27
27
  HStack(alignment: .firstTextBaseline, spacing: RunicSpacing.xxs) {
28
28
  Text(UsageFormatter.tokenCountString(self.tokenCount))
29
- .font(.system(size: 26, weight: .bold, design: .rounded))
29
+ .font(RunicFont.system(size: 26, weight: .bold))
30
30
  .foregroundStyle(MenuHighlightStyle.primary(self.isHighlighted))
31
31
  Text("today")
32
- .font(.system(.subheadline, design: .rounded))
32
+ .font(RunicFont.subheadline)
33
33
  .foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
34
34
  }
35
35
  }
36
36
  Spacer()
37
37
  if let cost = self.costUSD, cost > 0 {
38
38
  Text(UsageFormatter.usdString(cost))
39
- .font(.system(.subheadline, design: .rounded))
39
+ .font(RunicFont.subheadline)
40
40
  .fontWeight(.medium)
41
41
  .foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
42
42
  .padding(.horizontal, RunicSpacing.xs)
43
43
  .padding(.vertical, RunicSpacing.xxxs)
44
44
  .background(
45
45
  Capsule(style: .continuous)
46
- .fill(Color(nsColor: .controlBackgroundColor).opacity(RunicColors.Opacity.light))
47
- )
46
+ .fill(Color(nsColor: .controlBackgroundColor).opacity(RunicColors.Opacity.light)))
48
47
  }
49
48
  }
50
49
  .padding(.horizontal, MenuCardMetrics.horizontalPadding)
51
50
  .padding(.vertical, RunicSpacing.xxs)
52
51
  .frame(minWidth: self.width, maxWidth: .infinity, alignment: .leading)
53
52
  .accessibilityElement(children: .ignore)
54
- .accessibilityLabel("Today usage: \(UsageFormatter.tokenCountString(self.tokenCount)) tokens\(self.costUSD.map { ", \(UsageFormatter.usdString($0))" } ?? "")")
53
+ .accessibilityLabel(
54
+ "Today usage: \(UsageFormatter.tokenCountString(self.tokenCount)) tokens\(self.costUSD.map { ", \(UsageFormatter.usdString($0))" } ?? "")")
55
55
  }
56
56
  }
57
57
 
@@ -89,7 +89,8 @@ struct GlassmorphismStatCardsView: View {
89
89
  .padding(.vertical, RunicSpacing.xxs)
90
90
  .frame(minWidth: self.width, maxWidth: .infinity, alignment: .leading)
91
91
  .accessibilityElement(children: .ignore)
92
- .accessibilityLabel("Peak hour \(self.peakHourLabel), \(self.peakHourTokens). This week \(self.weekTotalTokens)")
92
+ .accessibilityLabel(
93
+ "Peak hour \(self.peakHourLabel), \(self.peakHourTokens). This week \(self.weekTotalTokens)")
93
94
  }
94
95
  }
95
96
 
@@ -104,18 +105,18 @@ private struct GlassStatCard: View {
104
105
  var body: some View {
105
106
  VStack(alignment: .leading, spacing: RunicSpacing.xxs) {
106
107
  Text(self.title)
107
- .font(.system(.caption2, design: .rounded))
108
+ .font(RunicFont.caption2)
108
109
  .fontWeight(.medium)
109
110
  .foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
110
111
  MiniSparklineView(data: self.sparkline, color: self.sparkColor)
111
112
  .frame(height: 24)
112
113
  Text(self.value)
113
- .font(.system(.title3, design: .rounded))
114
+ .font(RunicFont.title3)
114
115
  .fontWeight(.bold)
115
116
  .foregroundStyle(MenuHighlightStyle.primary(self.isHighlighted))
116
117
  if let detail {
117
118
  Text(detail)
118
- .font(.system(.caption2, design: .rounded))
119
+ .font(RunicFont.caption2)
119
120
  .foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
120
121
  }
121
122
  }
@@ -123,12 +124,10 @@ private struct GlassStatCard: View {
123
124
  .frame(maxWidth: .infinity, alignment: .leading)
124
125
  .background(
125
126
  RoundedRectangle(cornerRadius: RunicCornerRadius.lg, style: .continuous)
126
- .fill(.ultraThinMaterial)
127
- )
127
+ .fill(.ultraThinMaterial))
128
128
  .overlay(
129
129
  RoundedRectangle(cornerRadius: RunicCornerRadius.lg, style: .continuous)
130
- .stroke(Color(nsColor: .separatorColor).opacity(RunicColors.Opacity.medium), lineWidth: 0.5)
131
- )
130
+ .stroke(Color(nsColor: .separatorColor).opacity(RunicColors.Opacity.medium), lineWidth: 0.5))
132
131
  .shadow(color: .black.opacity(0.08), radius: 4, y: 2)
133
132
  .glassShimmer()
134
133
  }
@@ -147,7 +146,9 @@ private struct MiniSparklineView: View {
147
146
  // Filled gradient area under the line
148
147
  Path { path in
149
148
  path.move(to: CGPoint(x: points[0].x, y: geo.size.height))
150
- for point in points { path.addLine(to: point) }
149
+ for point in points {
150
+ path.addLine(to: point)
151
+ }
151
152
  path.addLine(to: CGPoint(x: points.last!.x, y: geo.size.height))
152
153
  path.closeSubpath()
153
154
  }
@@ -159,7 +160,9 @@ private struct MiniSparklineView: View {
159
160
  // Line stroke
160
161
  Path { path in
161
162
  path.move(to: points[0])
162
- for point in points.dropFirst() { path.addLine(to: point) }
163
+ for point in points.dropFirst() {
164
+ path.addLine(to: point)
165
+ }
163
166
  }
164
167
  .stroke(self.color, style: StrokeStyle(lineWidth: 1.5, lineCap: .round, lineJoin: .round))
165
168
  } else if self.data.count == 1, maxVal > 0 {
@@ -199,7 +202,7 @@ struct UpdatedTimestampView: View {
199
202
  TimelineView(.periodic(from: .now, by: 5)) { context in
200
203
  let text = Self.relativeString(from: self.updatedAt, to: context.date)
201
204
  Text(text)
202
- .font(.system(.caption2, design: .rounded))
205
+ .font(RunicFont.caption2)
203
206
  .foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted).opacity(0.7))
204
207
  }
205
208
  .padding(.horizontal, MenuCardMetrics.horizontalPadding)
@@ -38,19 +38,19 @@ struct HourlyActivityChartMenuView: View {
38
38
  // Header
39
39
  HStack(alignment: .firstTextBaseline) {
40
40
  Text("Today by Hour")
41
- .font(.system(.subheadline, design: .rounded))
41
+ .font(RunicFont.subheadline)
42
42
  .fontWeight(.semibold)
43
43
  Spacer()
44
44
  if let peak = model.peakHour {
45
45
  Text("Peak \(peak.label)")
46
- .font(.system(.caption, design: .rounded))
46
+ .font(RunicFont.caption)
47
47
  .foregroundStyle(.secondary)
48
48
  }
49
49
  }
50
50
 
51
51
  if model.bars.allSatisfy({ $0.totalTokens == 0 }) {
52
52
  Text("No usage recorded today.")
53
- .font(.system(.footnote, design: .rounded))
53
+ .font(RunicFont.footnote)
54
54
  .foregroundStyle(.secondary)
55
55
  .frame(height: 80)
56
56
  } else {
@@ -70,7 +70,7 @@ struct HourlyActivityChartMenuView: View {
70
70
  .foregroundStyle(Color(nsColor: .labelColor).opacity(0.3))
71
71
  .annotation(position: .top, spacing: 4) {
72
72
  Text(UsageFormatter.tokenCountString(bar.totalTokens))
73
- .font(.system(.caption2, design: .rounded))
73
+ .font(RunicFont.caption2)
74
74
  .fontWeight(.medium)
75
75
  .padding(.horizontal, 6)
76
76
  .padding(.vertical, 2)
@@ -85,7 +85,7 @@ struct HourlyActivityChartMenuView: View {
85
85
  AxisValueLabel {
86
86
  if let hour = value.as(Int.self) {
87
87
  Text(Self.hourAxisLabel(hour))
88
- .font(.system(.caption2, design: .rounded))
88
+ .font(RunicFont.caption2)
89
89
  .foregroundStyle(Color(nsColor: .tertiaryLabelColor))
90
90
  }
91
91
  }
@@ -98,7 +98,7 @@ struct HourlyActivityChartMenuView: View {
98
98
  AxisValueLabel {
99
99
  if let tokens = value.as(Int.self) {
100
100
  Text(UsageFormatter.tokenCountString(tokens))
101
- .font(.system(.caption2, design: .rounded))
101
+ .font(RunicFont.caption2)
102
102
  .foregroundStyle(Color(nsColor: .tertiaryLabelColor))
103
103
  }
104
104
  }
@@ -120,27 +120,27 @@ struct HourlyActivityChartMenuView: View {
120
120
  HStack(spacing: RunicSpacing.md) {
121
121
  VStack(alignment: .leading, spacing: RunicSpacing.xxxs) {
122
122
  Text("Today")
123
- .font(.system(.caption2, design: .rounded))
123
+ .font(RunicFont.caption2)
124
124
  .foregroundStyle(.tertiary)
125
125
  Text(UsageFormatter.tokenCountString(model.totalTokens))
126
- .font(.system(.caption, design: .rounded))
126
+ .font(RunicFont.caption)
127
127
  .fontWeight(.medium)
128
128
  }
129
129
  VStack(alignment: .leading, spacing: RunicSpacing.xxxs) {
130
130
  Text("Active hours")
131
- .font(.system(.caption2, design: .rounded))
131
+ .font(RunicFont.caption2)
132
132
  .foregroundStyle(.tertiary)
133
133
  Text("\(model.activeHours)")
134
- .font(.system(.caption, design: .rounded))
134
+ .font(RunicFont.caption)
135
135
  .fontWeight(.medium)
136
136
  }
137
137
  if model.totalRequests > 0 {
138
138
  VStack(alignment: .leading, spacing: RunicSpacing.xxxs) {
139
139
  Text("Requests")
140
- .font(.system(.caption2, design: .rounded))
140
+ .font(RunicFont.caption2)
141
141
  .foregroundStyle(.tertiary)
142
142
  Text("\(model.totalRequests)")
143
- .font(.system(.caption, design: .rounded))
143
+ .font(RunicFont.caption)
144
144
  .fontWeight(.medium)
145
145
  }
146
146
  }
@@ -182,12 +182,12 @@ struct HourlyActivityChartMenuView: View {
182
182
  let tokens = tokensByHour[hour] ?? 0
183
183
  let isPeak = tokens > 0 && tokens == maxTokens
184
184
  let bar = HourBar(id: hour, hour: hour, totalTokens: tokens, isPeak: isPeak)
185
- if isPeak && tokens > 0 { peakHour = bar }
185
+ if isPeak, tokens > 0 { peakHour = bar }
186
186
  return bar
187
187
  }
188
188
 
189
189
  let totalTokens = tokensByHour.values.reduce(0, +)
190
- let activeHours = tokensByHour.values.filter { $0 > 0 }.count
190
+ let activeHours = tokensByHour.values.count(where: { $0 > 0 })
191
191
  let totalRequests = requestsByHour.values.reduce(0, +)
192
192
 
193
193
  return HourlyModel(
@@ -15,15 +15,17 @@ struct InlineUsageChartView: View {
15
15
 
16
16
  var cutoffInterval: TimeInterval {
17
17
  switch self {
18
- case .threeDays: return -259200
19
- case .sevenDays: return -604800
20
- case .thirtyDays: return -2592000
21
- case .quarter: return -7776000
22
- case .year: return -31536000
18
+ case .threeDays: -259_200
19
+ case .sevenDays: -604_800
20
+ case .thirtyDays: -2_592_000
21
+ case .quarter: -7_776_000
22
+ case .year: -31_536_000
23
23
  }
24
24
  }
25
25
 
26
- var usesHourlyData: Bool { false }
26
+ var usesHourlyData: Bool {
27
+ false
28
+ }
27
29
  }
28
30
 
29
31
  private struct ChartPoint: Identifiable {
@@ -58,7 +60,7 @@ struct InlineUsageChartView: View {
58
60
  HStack {
59
61
  Spacer()
60
62
  Text("No data")
61
- .font(.system(.caption2, design: .rounded))
63
+ .font(RunicFont.caption2)
62
64
  .foregroundStyle(.tertiary)
63
65
  Spacer()
64
66
  }
@@ -94,7 +96,7 @@ struct InlineUsageChartView: View {
94
96
  AxisValueLabel {
95
97
  if let tokens = value.as(Int.self) {
96
98
  Text(UsageFormatter.tokenCountString(tokens))
97
- .font(.system(size: 8, design: .rounded))
99
+ .font(RunicFont.system(size: 8))
98
100
  .foregroundStyle(Color(nsColor: .tertiaryLabelColor))
99
101
  }
100
102
  }
@@ -103,7 +105,7 @@ struct InlineUsageChartView: View {
103
105
  .chartXAxis {
104
106
  AxisMarks(values: .automatic(desiredCount: 4)) { _ in
105
107
  AxisValueLabel(format: self.xAxisFormat)
106
- .font(.system(size: 8, design: .rounded))
108
+ .font(RunicFont.system(size: 8))
107
109
  .foregroundStyle(Color(nsColor: .tertiaryLabelColor))
108
110
  }
109
111
  }
@@ -113,7 +115,7 @@ struct InlineUsageChartView: View {
113
115
  // Peak badge
114
116
  if let peak = points.max(by: { $0.tokens < $1.tokens }), peak.tokens > 0 {
115
117
  Text("Peak \(UsageFormatter.tokenCountString(peak.tokens))")
116
- .font(.system(size: 8, weight: .medium, design: .rounded))
118
+ .font(RunicFont.system(size: 8, weight: .medium))
117
119
  .foregroundStyle(.secondary)
118
120
  .padding(.horizontal, 4)
119
121
  .padding(.vertical, 1)
@@ -14,8 +14,8 @@ struct MenuCardEntranceModifier: ViewModifier {
14
14
  .scaleEffect(self.appeared ? 1 : 0.97, anchor: .top)
15
15
  .onAppear {
16
16
  withAnimation(
17
- RunicAnimation.cardEntrance.delay(Double(self.index) * RunicAnimation.cardEntranceStagger)
18
- ) {
17
+ RunicAnimation.cardEntrance.delay(Double(self.index) * RunicAnimation.cardEntranceStagger))
18
+ {
19
19
  self.appeared = true
20
20
  }
21
21
  }
@@ -41,8 +41,7 @@ struct GlassShimmerModifier: ViewModifier {
41
41
  .frame(width: geo.size.width, height: geo.size.height)
42
42
  .allowsHitTesting(false)
43
43
  }
44
- .clipShape(RoundedRectangle(cornerRadius: RunicCornerRadius.lg, style: .continuous))
45
- )
44
+ .clipShape(RoundedRectangle(cornerRadius: RunicCornerRadius.lg, style: .continuous)))
46
45
  .onAppear {
47
46
  withAnimation(.easeInOut(duration: 2.0).delay(0.5)) {
48
47
  self.shimmerPhase = 1.2
@@ -61,29 +61,7 @@ struct ProviderSidebarMenuCardView<Content: View>: View {
61
61
  let iconProvider: (UsageProvider, CGFloat) -> NSImage
62
62
  let weeklyRemainingProvider: (UsageProvider) -> Double?
63
63
  let onSelect: (UsageProvider) -> Void
64
- let content: (CGFloat) -> Content
65
-
66
- init(
67
- providers: [UsageProvider],
68
- selected: UsageProvider?,
69
- totalWidth: CGFloat,
70
- showIcons: Bool,
71
- iconSize: ProviderSwitcherIconSize,
72
- iconProvider: @escaping (UsageProvider, CGFloat) -> NSImage,
73
- weeklyRemainingProvider: @escaping (UsageProvider) -> Double?,
74
- onSelect: @escaping (UsageProvider) -> Void,
75
- @ViewBuilder content: @escaping (CGFloat) -> Content)
76
- {
77
- self.providers = providers
78
- self.selected = selected
79
- self.totalWidth = totalWidth
80
- self.showIcons = showIcons
81
- self.iconSize = iconSize
82
- self.iconProvider = iconProvider
83
- self.weeklyRemainingProvider = weeklyRemainingProvider
84
- self.onSelect = onSelect
85
- self.content = content
86
- }
64
+ @ViewBuilder let content: (CGFloat) -> Content
87
65
 
88
66
  var body: some View {
89
67
  let style = MenuCardSidebarMetrics.style(for: self.providers.count, iconSize: self.iconSize)
@@ -124,7 +102,8 @@ private struct ProviderSidebarRailView: View {
124
102
  @Environment(\.menuItemHighlighted) private var isHighlighted
125
103
 
126
104
  private var railBackground: LinearGradient {
127
- let base = Color(nsColor: .controlTextColor).opacity(self.isHighlighted ? RunicColors.Opacity.subtle : RunicColors.Opacity.nano)
105
+ let base = Color(nsColor: .controlTextColor)
106
+ .opacity(self.isHighlighted ? RunicColors.Opacity.subtle : RunicColors.Opacity.nano)
128
107
  return LinearGradient(
129
108
  colors: [base, base.opacity(0.6)],
130
109
  startPoint: .top,
@@ -164,7 +143,8 @@ private struct ProviderSidebarRailView: View {
164
143
  }
165
144
 
166
145
  Rectangle()
167
- .fill(Color(nsColor: .separatorColor).opacity(self.isHighlighted ? RunicColors.Opacity.emphasis : RunicColors.Opacity.strong))
146
+ .fill(Color(nsColor: .separatorColor)
147
+ .opacity(self.isHighlighted ? RunicColors.Opacity.emphasis : RunicColors.Opacity.strong))
168
148
  .frame(width: 1)
169
149
  .padding(.top, MenuCardMetrics.headerTopPadding + 4)
170
150
  .padding(.bottom, MenuCardMetrics.tailPadding)
@@ -80,7 +80,7 @@ struct MenuCardSkeletonView: View {
80
80
  /// Computes a repeating phase (0...1) from the timeline date for the sliding gradient.
81
81
  private func shimmerPhase(date: Date) -> Double {
82
82
  let seconds = date.timeIntervalSinceReferenceDate
83
- let period: Double = 1.5
83
+ let period = 1.5
84
84
  return (seconds.truncatingRemainder(dividingBy: period)) / period
85
85
  }
86
86