@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
@@ -1,6 +1,6 @@
1
1
  import AppKit
2
- import RunicCore
3
2
  import Observation
3
+ import RunicCore
4
4
  import ServiceManagement
5
5
 
6
6
  enum RefreshFrequency: String, CaseIterable, Identifiable {
@@ -10,7 +10,9 @@ enum RefreshFrequency: String, CaseIterable, Identifiable {
10
10
  case fiveMinutes
11
11
  case fifteenMinutes
12
12
 
13
- var id: String { self.rawValue }
13
+ var id: String {
14
+ self.rawValue
15
+ }
14
16
 
15
17
  var seconds: TimeInterval? {
16
18
  switch self {
@@ -38,7 +40,9 @@ enum UsageMetricDisplayMode: String, CaseIterable, Identifiable {
38
40
  case barsOnly
39
41
  case percentOnly
40
42
 
41
- var id: String { self.rawValue }
43
+ var id: String {
44
+ self.rawValue
45
+ }
42
46
 
43
47
  var label: String {
44
48
  switch self {
@@ -72,7 +76,9 @@ enum MenuMode: String, CaseIterable, Identifiable {
72
76
  case analyst
73
77
  case `operator`
74
78
 
75
- var id: String { self.rawValue }
79
+ var id: String {
80
+ self.rawValue
81
+ }
76
82
 
77
83
  var label: String {
78
84
  switch self {
@@ -80,7 +86,7 @@ enum MenuMode: String, CaseIterable, Identifiable {
80
86
  "Glance"
81
87
  case .analyst:
82
88
  "Analyst"
83
- case .`operator`:
89
+ case .operator:
84
90
  "Operator"
85
91
  }
86
92
  }
@@ -91,13 +97,15 @@ enum ChartStyle: String, CaseIterable, Identifiable {
91
97
  case area
92
98
  case bar
93
99
 
94
- var id: String { self.rawValue }
100
+ var id: String {
101
+ self.rawValue
102
+ }
95
103
 
96
104
  var label: String {
97
105
  switch self {
98
- case .line: return "Line"
99
- case .area: return "Area"
100
- case .bar: return "Bar"
106
+ case .line: "Line"
107
+ case .area: "Area"
108
+ case .bar: "Bar"
101
109
  }
102
110
  }
103
111
  }
@@ -106,12 +114,14 @@ enum NumberFormat: String, CaseIterable, Identifiable {
106
114
  case abbreviated
107
115
  case full
108
116
 
109
- var id: String { self.rawValue }
117
+ var id: String {
118
+ self.rawValue
119
+ }
110
120
 
111
121
  var label: String {
112
122
  switch self {
113
- case .abbreviated: return "Abbreviated"
114
- case .full: return "Full"
123
+ case .abbreviated: "Abbreviated"
124
+ case .full: "Full"
115
125
  }
116
126
  }
117
127
  }
@@ -120,12 +130,14 @@ enum DateFormat: String, CaseIterable, Identifiable {
120
130
  case relative
121
131
  case absolute
122
132
 
123
- var id: String { self.rawValue }
133
+ var id: String {
134
+ self.rawValue
135
+ }
124
136
 
125
137
  var label: String {
126
138
  switch self {
127
- case .relative: return "Relative"
128
- case .absolute: return "Absolute"
139
+ case .relative: "Relative"
140
+ case .absolute: "Absolute"
129
141
  }
130
142
  }
131
143
  }
@@ -135,13 +147,15 @@ enum Theme: String, CaseIterable, Identifiable {
135
147
  case light
136
148
  case dark
137
149
 
138
- var id: String { self.rawValue }
150
+ var id: String {
151
+ self.rawValue
152
+ }
139
153
 
140
154
  var label: String {
141
155
  switch self {
142
- case .system: return "System"
143
- case .light: return "Light"
144
- case .dark: return "Dark"
156
+ case .system: "System"
157
+ case .light: "Light"
158
+ case .dark: "Dark"
145
159
  }
146
160
  }
147
161
  }
@@ -150,12 +164,14 @@ enum ProviderSwitcherLayout: String, CaseIterable, Identifiable {
150
164
  case top
151
165
  case sidebar
152
166
 
153
- var id: String { self.rawValue }
167
+ var id: String {
168
+ self.rawValue
169
+ }
154
170
 
155
171
  var label: String {
156
172
  switch self {
157
- case .top: return "Top"
158
- case .sidebar: return "Sidebar"
173
+ case .top: "Top"
174
+ case .sidebar: "Sidebar"
159
175
  }
160
176
  }
161
177
  }
@@ -164,12 +180,14 @@ enum ProviderSwitcherIconSize: String, CaseIterable, Identifiable {
164
180
  case small
165
181
  case medium
166
182
 
167
- var id: String { self.rawValue }
183
+ var id: String {
184
+ self.rawValue
185
+ }
168
186
 
169
187
  var label: String {
170
188
  switch self {
171
- case .small: return "Small"
172
- case .medium: return "Medium"
189
+ case .small: "Small"
190
+ case .medium: "Medium"
173
191
  }
174
192
  }
175
193
  }
@@ -189,15 +207,21 @@ final class SettingsStore {
189
207
  }
190
208
 
191
209
  var autoDisableRefreshWhenIdleEnabled: Bool {
192
- didSet { self.userDefaults.set(self.autoDisableRefreshWhenIdleEnabled, forKey: "autoDisableRefreshWhenIdleEnabled") }
210
+ didSet { self.userDefaults.set(
211
+ self.autoDisableRefreshWhenIdleEnabled,
212
+ forKey: "autoDisableRefreshWhenIdleEnabled") }
193
213
  }
194
214
 
195
215
  var autoDisableRefreshWhenIdleMinutes: Int {
196
- didSet { self.userDefaults.set(self.autoDisableRefreshWhenIdleMinutes, forKey: "autoDisableRefreshWhenIdleMinutes") }
216
+ didSet { self.userDefaults.set(
217
+ self.autoDisableRefreshWhenIdleMinutes,
218
+ forKey: "autoDisableRefreshWhenIdleMinutes") }
197
219
  }
198
220
 
199
221
  var autoDisableRefreshOnSleepEnabled: Bool {
200
- didSet { self.userDefaults.set(self.autoDisableRefreshOnSleepEnabled, forKey: "autoDisableRefreshOnSleepEnabled") }
222
+ didSet {
223
+ self.userDefaults.set(self.autoDisableRefreshOnSleepEnabled, forKey: "autoDisableRefreshOnSleepEnabled")
224
+ }
201
225
  }
202
226
 
203
227
  var autoRefreshWarningEnabled: Bool {
@@ -210,13 +234,17 @@ final class SettingsStore {
210
234
 
211
235
  var autoSuspendInactiveProvidersEnabled: Bool {
212
236
  didSet {
213
- self.userDefaults.set(self.autoSuspendInactiveProvidersEnabled, forKey: "autoSuspendInactiveProvidersEnabled")
237
+ self.userDefaults.set(
238
+ self.autoSuspendInactiveProvidersEnabled,
239
+ forKey: "autoSuspendInactiveProvidersEnabled")
214
240
  }
215
241
  }
216
242
 
217
243
  var autoSuspendInactiveProvidersMinutes: Int {
218
244
  didSet {
219
- self.userDefaults.set(self.autoSuspendInactiveProvidersMinutes, forKey: "autoSuspendInactiveProvidersMinutes")
245
+ self.userDefaults.set(
246
+ self.autoSuspendInactiveProvidersMinutes,
247
+ forKey: "autoSuspendInactiveProvidersMinutes")
220
248
  }
221
249
  }
222
250
 
@@ -227,7 +255,8 @@ final class SettingsStore {
227
255
  }
228
256
  }
229
257
 
230
- /// Hidden toggle to reveal debug-only menu items (enable via defaults write com.sriinnu.athena.Runic debugMenuEnabled
258
+ /// Hidden toggle to reveal debug-only menu items (enable via defaults write com.sriinnu.athena.Runic
259
+ /// debugMenuEnabled
231
260
  /// -bool YES).
232
261
  var debugMenuEnabled: Bool {
233
262
  didSet { self.userDefaults.set(self.debugMenuEnabled, forKey: "debugMenuEnabled") }
@@ -296,6 +325,13 @@ final class SettingsStore {
296
325
  }
297
326
  }
298
327
 
328
+ var selectedFontFamily: String {
329
+ didSet {
330
+ self.userDefaults.set(self.selectedFontFamily, forKey: "selectedFontFamily")
331
+ RunicFont.family = self.selectedFontFamily
332
+ }
333
+ }
334
+
299
335
  /// Optional: use provider branding icons with a percentage in the menu bar.
300
336
  var menuBarShowsBrandIconWithPercent: Bool {
301
337
  didSet {
@@ -406,7 +442,7 @@ final class SettingsStore {
406
442
  var zaiAPIToken: String {
407
443
  didSet {
408
444
  self.schedulePersistZaiAPIToken()
409
- if !zaiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
445
+ if !self.zaiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
410
446
  self.autoEnableProviderIfNeeded(cliName: "zai")
411
447
  }
412
448
  }
@@ -416,7 +452,7 @@ final class SettingsStore {
416
452
  var minimaxAPIToken: String {
417
453
  didSet {
418
454
  self.schedulePersistMiniMaxAPIToken()
419
- if !minimaxAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
455
+ if !self.minimaxAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
420
456
  self.autoEnableProviderIfNeeded(cliName: "minimax")
421
457
  }
422
458
  }
@@ -426,7 +462,7 @@ final class SettingsStore {
426
462
  var minimaxCookieHeader: String {
427
463
  didSet {
428
464
  self.schedulePersistMiniMaxCookieHeader()
429
- if !minimaxCookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
465
+ if !self.minimaxCookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
430
466
  self.autoEnableProviderIfNeeded(cliName: "minimax")
431
467
  }
432
468
  }
@@ -441,7 +477,7 @@ final class SettingsStore {
441
477
  var copilotAPIToken: String {
442
478
  didSet {
443
479
  self.schedulePersistCopilotAPIToken()
444
- if !copilotAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
480
+ if !self.copilotAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
445
481
  self.autoEnableProviderIfNeeded(cliName: "copilot")
446
482
  }
447
483
  }
@@ -451,7 +487,7 @@ final class SettingsStore {
451
487
  var openRouterAPIToken: String {
452
488
  didSet {
453
489
  self.schedulePersistOpenRouterAPIToken()
454
- if !openRouterAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
490
+ if !self.openRouterAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
455
491
  self.autoEnableProviderIfNeeded(cliName: "openrouter")
456
492
  }
457
493
  }
@@ -461,7 +497,7 @@ final class SettingsStore {
461
497
  var groqAPIToken: String {
462
498
  didSet {
463
499
  self.schedulePersistGroqAPIToken()
464
- if !groqAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
500
+ if !self.groqAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
465
501
  self.autoEnableProviderIfNeeded(cliName: "groq")
466
502
  }
467
503
  }
@@ -471,7 +507,7 @@ final class SettingsStore {
471
507
  var deepSeekAPIToken: String {
472
508
  didSet {
473
509
  self.schedulePersistDeepSeekAPIToken()
474
- if !deepSeekAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
510
+ if !self.deepSeekAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
475
511
  self.autoEnableProviderIfNeeded(cliName: "deepseek")
476
512
  }
477
513
  }
@@ -481,7 +517,7 @@ final class SettingsStore {
481
517
  var fireworksAPIToken: String {
482
518
  didSet {
483
519
  self.schedulePersistFireworksAPIToken()
484
- if !fireworksAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
520
+ if !self.fireworksAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
485
521
  self.autoEnableProviderIfNeeded(cliName: "fireworks")
486
522
  }
487
523
  }
@@ -491,7 +527,7 @@ final class SettingsStore {
491
527
  var mistralAPIToken: String {
492
528
  didSet {
493
529
  self.schedulePersistMistralAPIToken()
494
- if !mistralAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
530
+ if !self.mistralAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
495
531
  self.autoEnableProviderIfNeeded(cliName: "mistral")
496
532
  }
497
533
  }
@@ -501,7 +537,7 @@ final class SettingsStore {
501
537
  var perplexityAPIToken: String {
502
538
  didSet {
503
539
  self.schedulePersistPerplexityAPIToken()
504
- if !perplexityAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
540
+ if !self.perplexityAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
505
541
  self.autoEnableProviderIfNeeded(cliName: "perplexity")
506
542
  }
507
543
  }
@@ -511,7 +547,7 @@ final class SettingsStore {
511
547
  var kimiAPIToken: String {
512
548
  didSet {
513
549
  self.schedulePersistKimiAPIToken()
514
- if !kimiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
550
+ if !self.kimiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
515
551
  self.autoEnableProviderIfNeeded(cliName: "kimi")
516
552
  }
517
553
  }
@@ -521,7 +557,7 @@ final class SettingsStore {
521
557
  var auggieAPIToken: String {
522
558
  didSet {
523
559
  self.schedulePersistAuggieAPIToken()
524
- if !auggieAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
560
+ if !self.auggieAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
525
561
  self.autoEnableProviderIfNeeded(cliName: "auggie")
526
562
  }
527
563
  }
@@ -531,7 +567,7 @@ final class SettingsStore {
531
567
  var togetherAPIToken: String {
532
568
  didSet {
533
569
  self.schedulePersistTogetherAPIToken()
534
- if !togetherAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
570
+ if !self.togetherAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
535
571
  self.autoEnableProviderIfNeeded(cliName: "together")
536
572
  }
537
573
  }
@@ -541,7 +577,7 @@ final class SettingsStore {
541
577
  var cohereAPIToken: String {
542
578
  didSet {
543
579
  self.schedulePersistCohereAPIToken()
544
- if !cohereAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
580
+ if !self.cohereAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
545
581
  self.autoEnableProviderIfNeeded(cliName: "cohere")
546
582
  }
547
583
  }
@@ -551,7 +587,7 @@ final class SettingsStore {
551
587
  var xaiAPIToken: String {
552
588
  didSet {
553
589
  self.schedulePersistXAiAPIToken()
554
- if !xaiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
590
+ if !self.xaiAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
555
591
  self.autoEnableProviderIfNeeded(cliName: "xai")
556
592
  }
557
593
  }
@@ -561,7 +597,7 @@ final class SettingsStore {
561
597
  var cerebrasAPIToken: String {
562
598
  didSet {
563
599
  self.schedulePersistCerebrasAPIToken()
564
- if !cerebrasAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
600
+ if !self.cerebrasAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
565
601
  self.autoEnableProviderIfNeeded(cliName: "cerebras")
566
602
  }
567
603
  }
@@ -571,7 +607,7 @@ final class SettingsStore {
571
607
  var qwenAPIToken: String {
572
608
  didSet {
573
609
  self.schedulePersistQwenAPIToken()
574
- if !qwenAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
610
+ if !self.qwenAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
575
611
  self.autoEnableProviderIfNeeded(cliName: "qwen")
576
612
  }
577
613
  }
@@ -581,7 +617,7 @@ final class SettingsStore {
581
617
  var sambaNovaAPIToken: String {
582
618
  didSet {
583
619
  self.schedulePersistSambaNovaAPIToken()
584
- if !sambaNovaAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
620
+ if !self.sambaNovaAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
585
621
  self.autoEnableProviderIfNeeded(cliName: "sambanova")
586
622
  }
587
623
  }
@@ -606,7 +642,7 @@ final class SettingsStore {
606
642
  var azureOpenAIAPIToken: String {
607
643
  didSet {
608
644
  self.schedulePersistAzureOpenAIAPIToken()
609
- if !azureOpenAIAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
645
+ if !self.azureOpenAIAPIToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
610
646
  self.autoEnableProviderIfNeeded(cliName: "azure")
611
647
  }
612
648
  }
@@ -884,7 +920,7 @@ final class SettingsStore {
884
920
  let metricDisplayRaw = userDefaults.string(forKey: "usageMetricDisplayMode")
885
921
  self.usageMetricDisplayMode = UsageMetricDisplayMode(rawValue: metricDisplayRaw ?? "") ?? .barsAndPercent
886
922
  let menuModeRaw = userDefaults.string(forKey: "menuMode")
887
- self.menuMode = MenuMode(rawValue: menuModeRaw ?? "") ?? .`operator`
923
+ self.menuMode = MenuMode(rawValue: menuModeRaw ?? "") ?? .operator
888
924
  let chartStyleRaw = userDefaults.string(forKey: "chartStyle")
889
925
  self.chartStyle = ChartStyle(rawValue: chartStyleRaw ?? "") ?? .line
890
926
  let numberFormatRaw = userDefaults.string(forKey: "numberFormat")
@@ -893,6 +929,7 @@ final class SettingsStore {
893
929
  self.dateFormat = DateFormat(rawValue: dateFormatRaw ?? "") ?? .relative
894
930
  let themeRaw = userDefaults.string(forKey: "theme")
895
931
  self.theme = Theme(rawValue: themeRaw ?? "") ?? .system
932
+ self.selectedFontFamily = userDefaults.string(forKey: "selectedFontFamily") ?? "Fira Code"
896
933
  self.menuBarShowsBrandIconWithPercent = userDefaults.object(
897
934
  forKey: "menuBarShowsBrandIconWithPercent") as? Bool ?? false
898
935
  self.menuBarVibrantIconEnabled = userDefaults.object(
@@ -965,6 +1002,7 @@ final class SettingsStore {
965
1002
  if self.claudeUsageDataSource != .cli {
966
1003
  self.claudeWebExtrasEnabled = false
967
1004
  }
1005
+ RunicFont.family = self.selectedFontFamily
968
1006
  }
969
1007
 
970
1008
  func orderedProviders() -> [UsageProvider] {
@@ -1,5 +1,5 @@
1
- import RunicCore
2
1
  import Foundation
2
+ import RunicCore
3
3
  import Security
4
4
 
5
5
  protocol TogetherTokenStoring: Sendable {
@@ -64,7 +64,6 @@ struct KeychainTogetherTokenStore: TogetherTokenStoring {
64
64
  addQuery[kSecValueData as String] = data
65
65
  addQuery[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
66
66
 
67
-
68
67
  let addStatus = SecItemAdd(addQuery as CFDictionary, nil)
69
68
  guard addStatus == errSecSuccess else {
70
69
  Self.log.error("Keychain add failed: \(addStatus)")
@@ -115,5 +114,4 @@ struct KeychainTogetherTokenStore: TogetherTokenStoring {
115
114
  }
116
115
  return q
117
116
  }
118
-
119
117
  }
@@ -1,13 +1,26 @@
1
- import RunicCore
2
1
  import Foundation
2
+ import RunicCore
3
3
 
4
4
  extension UsageStore {
5
- var codexSnapshot: UsageSnapshot? { self.snapshots[.codex] }
6
- var claudeSnapshot: UsageSnapshot? { self.snapshots[.claude] }
7
- var lastCodexError: String? { self.errors[.codex] }
8
- var lastClaudeError: String? { self.errors[.claude] }
5
+ var codexSnapshot: UsageSnapshot? {
6
+ self.snapshots[.codex]
7
+ }
8
+
9
+ var claudeSnapshot: UsageSnapshot? {
10
+ self.snapshots[.claude]
11
+ }
9
12
 
10
- func error(for provider: UsageProvider) -> String? { self.errors[provider] }
13
+ var lastCodexError: String? {
14
+ self.errors[.codex]
15
+ }
16
+
17
+ var lastClaudeError: String? {
18
+ self.errors[.claude]
19
+ }
20
+
21
+ func error(for provider: UsageProvider) -> String? {
22
+ self.errors[provider]
23
+ }
11
24
 
12
25
  func status(for provider: UsageProvider) -> ProviderStatus? {
13
26
  guard self.statusChecksEnabled else { return nil }
@@ -1,5 +1,5 @@
1
- import RunicCore
2
1
  import Foundation
2
+ import RunicCore
3
3
 
4
4
  extension UsageStore {
5
5
  func tokenSnapshot(for provider: UsageProvider) -> CostUsageTokenSnapshot? {
@@ -1,5 +1,5 @@
1
- import RunicCore
2
1
  import Foundation
2
+ import RunicCore
3
3
  #if canImport(WidgetKit)
4
4
  import WidgetKit
5
5
  #endif