@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.
- package/CHANGELOG.md +11 -0
- package/README.md +8 -1
- package/RuniciOS/Core/RunicTypographyiOS.swift +24 -0
- package/RuniciOS/Views/ProviderDetailView.swift +9 -9
- package/RuniciOS/Views/ProviderListView.swift +10 -10
- package/RuniciOS/Widgets/LargeWidget.swift +14 -14
- package/RuniciOS/Widgets/LiveActivity.swift +19 -19
- package/RuniciOS/Widgets/LockScreenWidget.swift +15 -15
- package/RuniciOS/Widgets/MediumWidget.swift +10 -10
- package/RuniciOS/Widgets/RunicWidget.swift +5 -5
- package/RuniciOS/Widgets/SmallWidget.swift +9 -9
- package/Sources/Runic/About.swift +3 -3
- package/Sources/Runic/AppNotifications.swift +5 -3
- package/Sources/Runic/Controllers/StatusItemController+Actions.swift +7 -3
- package/Sources/Runic/Controllers/StatusItemController+Animation.swift +5 -4
- package/Sources/Runic/Controllers/StatusItemController+ChartSubmenus.swift +30 -16
- package/Sources/Runic/Controllers/StatusItemController+CustomProviders.swift +6 -3
- package/Sources/Runic/Controllers/StatusItemController+Menu.swift +18 -13
- package/Sources/Runic/Controllers/StatusItemController+MenuCards.swift +6 -4
- package/Sources/Runic/Controllers/StatusItemController+MenuHelpers.swift +40 -12
- package/Sources/Runic/Controllers/StatusItemController.swift +43 -43
- package/Sources/Runic/Core/BudgetNotificationManager.swift +2 -1
- package/Sources/Runic/Core/Login/ClaudeLoginRunner.swift +2 -2
- package/Sources/Runic/Core/Login/CodexLoginRunner.swift +1 -1
- package/Sources/Runic/Core/Login/CursorLoginRunner.swift +4 -4
- package/Sources/Runic/Core/Login/GeminiLoginRunner.swift +1 -1
- package/Sources/Runic/Core/Rendering/IconRenderer.swift +91 -85
- package/Sources/Runic/Core/Rendering/IconView.swift +3 -1
- package/Sources/Runic/Core/RunicColors.swift +6 -6
- package/Sources/Runic/Core/RunicSpacing.swift +7 -7
- package/Sources/Runic/Core/RunicTypography.swift +206 -0
- package/Sources/Runic/Core/Stores/AuggieTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/AzureOpenAITokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/CerebrasTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/CohereTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/CopilotTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/CustomProviderStore.swift +10 -10
- package/Sources/Runic/Core/Stores/DeepSeekTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/FireworksTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/GroqTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/KimiTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/MiniMaxCookieHeaderStore.swift +1 -3
- package/Sources/Runic/Core/Stores/MiniMaxGroupIDStore.swift +1 -3
- package/Sources/Runic/Core/Stores/MiniMaxTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/MistralTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/OpenRouterTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/PerplexityTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/ProviderToggleStore.swift +1 -1
- package/Sources/Runic/Core/Stores/QwenTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/SambaNovaTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/SettingsStore.swift +89 -51
- package/Sources/Runic/Core/Stores/TogetherTokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/UsageStore+Accessors.swift +19 -6
- package/Sources/Runic/Core/Stores/UsageStore+TokenCost.swift +1 -1
- package/Sources/Runic/Core/Stores/UsageStore+WidgetSnapshot.swift +1 -1
- package/Sources/Runic/Core/Stores/UsageStore.swift +187 -161
- package/Sources/Runic/Core/Stores/XAITokenStore.swift +1 -3
- package/Sources/Runic/Core/Stores/ZaiTokenStore.swift +1 -2
- package/Sources/Runic/Core/UsageExporter.swift +8 -4
- package/Sources/Runic/ProviderRegistry.swift +1 -1
- package/Sources/Runic/Providers/Antigravity/AntigravityProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Auggie/AuggieProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Azure/AzureProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Bedrock/BedrockProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Cerebras/CerebrasProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Codex/CodexProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Cohere/CohereProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Cursor/CursorProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/DeepSeek/DeepSeekProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Factory/FactoryProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Fireworks/FireworksProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Gemini/GeminiProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Groq/GroqProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Kimi/KimiProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/MiniMax/MiniMaxProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Mistral/MistralProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/OpenRouter/OpenRouterProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Perplexity/PerplexityProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/SambaNova/SambaNovaProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Shared/ProviderImplementation.swift +5 -2
- package/Sources/Runic/Providers/Shared/ProviderImplementationRegistry.swift +1 -1
- package/Sources/Runic/Providers/Shared/ProviderSettingsDescriptors.swift +1 -1
- package/Sources/Runic/Providers/Together/TogetherProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/XAI/XAIProviderImplementation.swift +1 -1
- package/Sources/Runic/Providers/Zai/ZaiProviderImplementation.swift +1 -1
- package/Sources/Runic/Resources/Fonts/Caveat-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/Caveat-Regular.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/FiraCode-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/FiraCode-Light.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/FiraCode-Medium.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/FiraCode-Regular.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/FiraCode-SemiBold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/IBMPlexMono-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/IBMPlexMono-Medium.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/IBMPlexMono-Regular.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/IBMPlexMono-SemiBold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/Inconsolata-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/Inconsolata-Medium.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/Inconsolata-Regular.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/Inconsolata-SemiBold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/JetBrainsMono-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/JetBrainsMono-Medium.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/JetBrainsMono-Regular.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/JetBrainsMono-SemiBold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/SpaceMono-Bold.ttf +0 -0
- package/Sources/Runic/Resources/Fonts/SpaceMono-Regular.ttf +0 -0
- package/Sources/Runic/RunicApp.swift +46 -36
- package/Sources/Runic/SessionQuotaNotifications.swift +2 -2
- package/Sources/Runic/UsagePaceText.swift +1 -1
- package/Sources/Runic/UsageProgressBar.swift +13 -9
- package/Sources/Runic/Utilities/LoadingPattern.swift +4 -2
- package/Sources/Runic/Utilities/PerformanceConstants.swift +28 -28
- package/Sources/Runic/Views/Menu/AlertsMenuView.swift +19 -21
- package/Sources/Runic/Views/Menu/CostComparativeChartMenuView.swift +19 -19
- package/Sources/Runic/Views/Menu/CostHistoryChartMenuView.swift +7 -7
- package/Sources/Runic/Views/Menu/CreditsHistoryChartMenuView.swift +5 -5
- package/Sources/Runic/Views/Menu/EfficiencyMetricsMenuView.swift +29 -30
- package/Sources/Runic/Views/Menu/HeroStatCardsMenuView.swift +20 -17
- package/Sources/Runic/Views/Menu/HourlyActivityChartMenuView.swift +14 -14
- package/Sources/Runic/Views/Menu/InlineUsageChartView.swift +12 -10
- package/Sources/Runic/Views/Menu/MenuCardEntranceModifier.swift +3 -4
- package/Sources/Runic/Views/Menu/MenuCardSidebarView.swift +5 -25
- package/Sources/Runic/Views/Menu/MenuCardSkeletonView.swift +1 -1
- package/Sources/Runic/Views/Menu/MenuCardView.swift +120 -131
- package/Sources/Runic/Views/Menu/MenuContent.swift +11 -8
- package/Sources/Runic/Views/Menu/MenuDescriptor.swift +4 -2
- package/Sources/Runic/Views/Menu/MenuHighlightStyle.swift +1 -8
- package/Sources/Runic/Views/Menu/ModelBreakdownMenuView.swift +20 -14
- package/Sources/Runic/Views/Menu/OverviewMenuView.swift +18 -15
- package/Sources/Runic/Views/Menu/ProjectBreakdownMenuView.swift +16 -11
- package/Sources/Runic/Views/Menu/ProjectBudgetMenuView.swift +27 -27
- package/Sources/Runic/Views/Menu/ProviderTabBarView.swift +4 -6
- package/Sources/Runic/Views/Menu/SubscriptionUtilizationChartMenuView.swift +24 -11
- package/Sources/Runic/Views/Menu/UsageBreakdownChartMenuView.swift +5 -5
- package/Sources/Runic/Views/Menu/UsageHeatmapMenuView.swift +7 -8
- package/Sources/Runic/Views/Menu/UsageTimelineChartMenuView.swift +22 -17
- package/Sources/Runic/Views/Menu/UsageWindowComparisonChartMenuView.swift +8 -7
- package/Sources/Runic/Views/Menu/WeeklyActivityChartMenuView.swift +7 -7
- package/Sources/Runic/Views/Performance/PerformanceDashboardView.swift +50 -47
- package/Sources/Runic/Views/Preferences/LiquidComponents.swift +15 -14
- package/Sources/Runic/Views/Preferences/PreferencesAboutPane.swift +7 -7
- package/Sources/Runic/Views/Preferences/PreferencesAdvancedPane.swift +27 -27
- package/Sources/Runic/Views/Preferences/PreferencesAlertsPane.swift +38 -42
- package/Sources/Runic/Views/Preferences/PreferencesAnalyticsPane.swift +39 -43
- package/Sources/Runic/Views/Preferences/PreferencesBudgetsPane.swift +21 -21
- package/Sources/Runic/Views/Preferences/PreferencesComponents.swift +7 -7
- package/Sources/Runic/Views/Preferences/PreferencesCustomProvidersPane.swift +49 -50
- package/Sources/Runic/Views/Preferences/PreferencesDebugPane.swift +10 -10
- package/Sources/Runic/Views/Preferences/PreferencesGeneralPane.swift +40 -21
- package/Sources/Runic/Views/Preferences/PreferencesHelpPane.swift +7 -7
- package/Sources/Runic/Views/Preferences/PreferencesIntegrationsPane.swift +44 -39
- package/Sources/Runic/Views/Preferences/PreferencesPerformancePane.swift +26 -23
- package/Sources/Runic/Views/Preferences/PreferencesProvidersPane.swift +271 -226
- package/Sources/Runic/Views/Preferences/PreferencesSelection.swift +6 -2
- package/Sources/Runic/Views/Preferences/PreferencesSyncPane.swift +7 -5
- package/Sources/Runic/Views/Preferences/PreferencesView.swift +38 -31
- package/Sources/Runic/Views/Rating/QualityRatingView.swift +11 -11
- package/Sources/Runic/Views/Team/TeamDashboardView.swift +29 -24
- package/Sources/Runic/Views/Team/TeamInviteSheet.swift +16 -16
- package/Sources/Runic/Views/Team/TeamManagementView.swift +50 -49
- package/Sources/Runic/Views/Team/TeamMemberRow.swift +8 -8
- package/Sources/RunicCLI/CLIEntry.swift +83 -42
- package/Sources/RunicCLI/CLIRenderer.swift +1 -1
- package/Sources/RunicCLI/Commands/EnhancedUsageCommand.swift +60 -60
- package/Sources/RunicCLI/Commands/ModelsCommand.swift +45 -44
- package/Sources/RunicCLI/Commands/ProjectsCommand.swift +83 -69
- package/Sources/RunicCLI/Commands/ResetCommand.swift +50 -49
- package/Sources/RunicCLI/Commands/UsageLedgerSourceFactory.swift +31 -32
- package/Sources/RunicClaudeWebProbe/main.swift +1 -1
- package/Sources/RunicCore/AlertRuleStore.swift +20 -20
- package/Sources/RunicCore/BrowserCookieImportOrder.swift +3 -3
- package/Sources/RunicCore/CostUsageModels.swift +1 -1
- package/Sources/RunicCore/CustomProviders/CustomProviderModels.swift +29 -30
- package/Sources/RunicCore/CustomProviders/GenericProviderFetcher.swift +73 -75
- package/Sources/RunicCore/CustomProviders/ProviderTemplates.swift +53 -109
- package/Sources/RunicCore/Host/PTY/TTYCommandRunner.swift +3 -3
- package/Sources/RunicCore/Integrations/GitHubIntegration.swift +3 -3
- package/Sources/RunicCore/Models/EnhancedUsageModels.swift +47 -48
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift +1 -1
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardFetcher.swift +1 -1
- package/Sources/RunicCore/Performance/PerformanceModels.swift +4 -4
- package/Sources/RunicCore/Performance/PerformanceStorageImpl.swift +81 -64
- package/Sources/RunicCore/Policy/UsagePolicyEngine.swift +2 -2
- package/Sources/RunicCore/ProjectBudgetStore.swift +15 -12
- package/Sources/RunicCore/Providers/Antigravity/AntigravityProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Antigravity/AntigravityStatusProbe.swift +2 -2
- package/Sources/RunicCore/Providers/Auggie/AuggieProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Auggie/AuggieUsageFetcher.swift +3 -3
- package/Sources/RunicCore/Providers/Azure/AzureProviderDescriptor.swift +8 -8
- package/Sources/RunicCore/Providers/Azure/AzureUsageFetcher.swift +3 -3
- package/Sources/RunicCore/Providers/Bedrock/BedrockProviderDescriptor.swift +6 -6
- package/Sources/RunicCore/Providers/Bedrock/BedrockUsageFetcher.swift +3 -7
- package/Sources/RunicCore/Providers/Cerebras/CerebrasProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Cerebras/CerebrasUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift +3 -3
- package/Sources/RunicCore/Providers/Claude/ClaudeProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Claude/ClaudeStatusProbe.swift +4 -4
- package/Sources/RunicCore/Providers/Claude/ClaudeUsageDataSource.swift +3 -1
- package/Sources/RunicCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift +1 -1
- package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift +1 -1
- package/Sources/RunicCore/Providers/Codex/CodexProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Codex/CodexUsageDataSource.swift +3 -1
- package/Sources/RunicCore/Providers/Codex/CodexWebDashboardStrategy.swift +5 -3
- package/Sources/RunicCore/Providers/Cohere/CohereProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Cohere/CohereUsageFetcher.swift +3 -3
- package/Sources/RunicCore/Providers/Copilot/CopilotGitHubCLITokenReader.swift +7 -4
- package/Sources/RunicCore/Providers/Copilot/CopilotProviderDescriptor.swift +4 -4
- package/Sources/RunicCore/Providers/Copilot/CopilotUsageFetcher.swift +5 -3
- package/Sources/RunicCore/Providers/Copilot/CopilotVSCodeTokenReader.swift +9 -10
- package/Sources/RunicCore/Providers/Cursor/CursorProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Factory/FactoryLocalStorageImporter.swift +4 -4
- package/Sources/RunicCore/Providers/Factory/FactoryProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Factory/FactoryStatusProbe.swift +2 -2
- package/Sources/RunicCore/Providers/Fireworks/FireworksProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Fireworks/FireworksUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Gemini/GeminiProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Gemini/GeminiStatusProbe.swift +5 -2
- package/Sources/RunicCore/Providers/Groq/GroqProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Groq/GroqUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Kimi/KimiProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Kimi/KimiUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift +10 -5
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxUsageFetcher.swift +7 -7
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxWebUsageFetcher.swift +10 -10
- package/Sources/RunicCore/Providers/Mistral/MistralProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Mistral/MistralUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/OpenRouter/OpenRouterUsageFetcher.swift +23 -10
- package/Sources/RunicCore/Providers/Perplexity/PerplexityProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Perplexity/PerplexityUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/ProviderFetchPlan.swift +2 -2
- package/Sources/RunicCore/Providers/ProviderTokenResolver.swift +2 -2
- package/Sources/RunicCore/Providers/Qwen/QwenProviderDescriptor.swift +5 -3
- package/Sources/RunicCore/Providers/Qwen/QwenUsageStats.swift +26 -13
- package/Sources/RunicCore/Providers/SambaNova/SambaNovaProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/SambaNova/SambaNovaUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Together/TogetherProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/Together/TogetherUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/VertexAI/VertexAIProviderDescriptor.swift +5 -5
- package/Sources/RunicCore/Providers/VertexAI/VertexAISettingsReader.swift +1 -1
- package/Sources/RunicCore/Providers/VertexAI/VertexAIUsageFetcher.swift +3 -3
- package/Sources/RunicCore/Providers/XAI/XAIProviderDescriptor.swift +2 -2
- package/Sources/RunicCore/Providers/XAI/XAIUsageFetcher.swift +2 -2
- package/Sources/RunicCore/Providers/Zai/ZaiProviderDescriptor.swift +4 -2
- package/Sources/RunicCore/Providers/Zai/ZaiUsageStats.swift +48 -21
- package/Sources/RunicCore/Sync/BackgroundSyncManager.swift +76 -77
- package/Sources/RunicCore/Sync/SyncConflictResolver.swift +55 -58
- package/Sources/RunicCore/Sync/SyncProtocol.swift +21 -22
- package/Sources/RunicCore/Sync/SyncRecord.swift +46 -49
- package/Sources/RunicCore/Sync/SyncUsageExample.swift +44 -50
- package/Sources/RunicCore/Sync/TeamSyncRecords.swift +94 -101
- package/Sources/RunicCore/Sync/iCloudSyncEngine.swift +51 -46
- package/Sources/RunicCore/Team/TeamModels.swift +111 -110
- package/Sources/RunicCore/Team/TeamStore.swift +126 -109
- package/Sources/RunicCore/UsageFetcher.swift +2 -2
- package/Sources/RunicCore/UsageFormatter.swift +25 -25
- package/Sources/RunicCore/UsageLedger/ClaudeUsageLogSource.swift +27 -13
- package/Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift +11 -3
- package/Sources/RunicCore/UsageLedger/LedgerCache.swift +5 -2
- package/Sources/RunicCore/UsageLedger/OTelGenAILedgerAdapter.swift +1 -1
- package/Sources/RunicCore/UsageLedger/UsageLedgerAggregator.swift +40 -25
- package/Sources/RunicCore/UsageLedger/UsageLedgerInsightsAdvisor.swift +1 -1
- package/Sources/RunicCore/UsageLedger/UsageLedgerProjectIdentity.swift +55 -16
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageCache.swift +6 -6
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageJsonl.swift +1 -1
- package/Sources/RunicCore/Vendored/CostUsage/CostUsagePricing.swift +2 -2
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner.swift +5 -5
- package/Tests/RunicTests/AppDelegateTests.swift +8 -3
- package/Tests/RunicTests/BrowserCookieOrderLabelTests.swift +2 -3
- package/Tests/RunicTests/CLIArgumentParsingTests.swift +3 -4
- package/Tests/RunicTests/CLICostTests.swift +6 -7
- package/Tests/RunicTests/CLIProviderSelectionTests.swift +2 -3
- package/Tests/RunicTests/CLISnapshotTests.swift +3 -4
- package/Tests/RunicTests/CLIWebFallbackTests.swift +3 -4
- package/Tests/RunicTests/ClaudeOAuthTests.swift +11 -12
- package/Tests/RunicTests/ClaudeResilienceTests.swift +3 -4
- package/Tests/RunicTests/ClaudeUsageTests.swift +20 -21
- package/Tests/RunicTests/CodexOAuthTests.swift +7 -8
- package/Tests/RunicTests/CodexUsageLogSourceTests.swift +1 -3
- package/Tests/RunicTests/CopilotTokenResolverTests.swift +5 -6
- package/Tests/RunicTests/CopilotVSCodeTokenReaderTests.swift +4 -5
- package/Tests/RunicTests/CostUsageDecodingTests.swift +15 -17
- package/Tests/RunicTests/CostUsagePricingTests.swift +5 -7
- package/Tests/RunicTests/CostUsageScannerTests.swift +10 -12
- package/Tests/RunicTests/CursorStatusProbeTests.swift +15 -16
- package/Tests/RunicTests/FactoryStatusProbeTests.swift +3 -5
- package/Tests/RunicTests/GeminiLoginAlertTests.swift +3 -4
- package/Tests/RunicTests/GeminiStatusProbeAPITests.swift +11 -11
- package/Tests/RunicTests/GeminiStatusProbePlanTests.swift +8 -8
- package/Tests/RunicTests/GeminiStatusProbeTests.swift +20 -21
- package/Tests/RunicTests/GoogleWorkspaceStatusTests.swift +2 -3
- package/Tests/RunicTests/InstallOriginTests.swift +1 -2
- package/Tests/RunicTests/KeyboardShortcutsBundleTests.swift +2 -2
- package/Tests/RunicTests/LiveAccountTests.swift +3 -3
- package/Tests/RunicTests/LoadingPatternTests.swift +3 -4
- package/Tests/RunicTests/MenuCardModelTests.swift +33 -34
- package/Tests/RunicTests/MiniMaxCookieHeaderStoreTestSupport.swift +4 -1
- package/Tests/RunicTests/MiniMaxGroupIDStoreTestSupport.swift +4 -1
- package/Tests/RunicTests/MiniMaxParsingTests.swift +4 -5
- package/Tests/RunicTests/MiniMaxTokenStoreTestSupport.swift +4 -1
- package/Tests/RunicTests/OTelGenAILedgerAdapterTests.swift +4 -6
- package/Tests/RunicTests/OpenAIDashboardBrowserCookieImporterTests.swift +1 -2
- package/Tests/RunicTests/OpenAIDashboardFetcherCreditsWaitTests.swift +5 -6
- package/Tests/RunicTests/OpenAIDashboardOffscreenHostTests.swift +2 -3
- package/Tests/RunicTests/OpenAIDashboardParserTests.swift +12 -13
- package/Tests/RunicTests/OpenAIWebAccountSwitchTests.swift +17 -6
- package/Tests/RunicTests/OpenRouterTokenStoreTestSupport.swift +52 -13
- package/Tests/RunicTests/PathBuilderTests.swift +14 -15
- package/Tests/RunicTests/ProviderFetchPipelineTests.swift +3 -4
- package/Tests/RunicTests/ProviderIconResourcesTests.swift +1 -2
- package/Tests/RunicTests/ProviderMetadataStatusLinkTests.swift +1 -2
- package/Tests/RunicTests/ProviderSettingsDescriptorTests.swift +53 -19
- package/Tests/RunicTests/ProviderToggleStoreTests.swift +10 -11
- package/Tests/RunicTests/RunicTests.swift +6 -7
- package/Tests/RunicTests/SessionQuotaNotificationLogicTests.swift +5 -6
- package/Tests/RunicTests/SettingsStoreTests.swift +149 -45
- package/Tests/RunicTests/StatusItemAnimationTests.swift +8 -3
- package/Tests/RunicTests/StatusMenuTests.swift +63 -22
- package/Tests/RunicTests/StatusProbeTests.swift +28 -29
- package/Tests/RunicTests/SubprocessRunnerTests.swift +1 -3
- package/Tests/RunicTests/SubscriptionDetectionTests.swift +8 -9
- package/Tests/RunicTests/TTYCommandRunnerTests.swift +8 -9
- package/Tests/RunicTests/TeamShowbackExporterTests.swift +2 -4
- package/Tests/RunicTests/TextParsingTests.swift +1 -2
- package/Tests/RunicTests/UsageFormatterTests.swift +15 -16
- package/Tests/RunicTests/UsageLedgerAnomalyDetectionTests.swift +12 -14
- package/Tests/RunicTests/UsageLedgerForecastTests.swift +4 -6
- package/Tests/RunicTests/UsageLedgerInsightsAdvisorTests.swift +7 -9
- package/Tests/RunicTests/UsageLedgerProjectNameTests.swift +6 -8
- package/Tests/RunicTests/UsagePaceTests.swift +5 -6
- package/Tests/RunicTests/UsagePaceTextTests.swift +8 -9
- package/Tests/RunicTests/UsagePolicyEngineTests.swift +3 -5
- package/Tests/RunicTests/WidgetSnapshotTests.swift +1 -3
- package/Tests/RunicTests/ZaiProviderTests.swift +3 -5
- package/Tests/RunicTests/ZaiTokenStoreTestSupport.swift +4 -1
- package/appcast.xml +36 -76
- package/package.json +1 -1
- package/runic.png +0 -0
- package/runic.svg +15 -0
- package/version.env +2 -2
|
@@ -38,7 +38,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
38
38
|
self.width = width
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
private static let barColor = RunicColors.chartColor(at: 4)
|
|
41
|
+
private static let barColor = RunicColors.chartColor(at: 4) // teal
|
|
42
42
|
private static let wastedColor = Color(nsColor: .systemGray).opacity(0.2)
|
|
43
43
|
|
|
44
44
|
var body: some View {
|
|
@@ -50,7 +50,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
50
50
|
|
|
51
51
|
VStack(alignment: .leading, spacing: RunicSpacing.xs) {
|
|
52
52
|
Text("Utilization")
|
|
53
|
-
.font(.
|
|
53
|
+
.font(RunicFont.subheadline)
|
|
54
54
|
.fontWeight(.semibold)
|
|
55
55
|
|
|
56
56
|
Picker("", selection: self.$selectedPeriod) {
|
|
@@ -62,7 +62,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
62
62
|
|
|
63
63
|
if model.bars.isEmpty {
|
|
64
64
|
Text("No utilization data available.")
|
|
65
|
-
.font(.
|
|
65
|
+
.font(RunicFont.footnote)
|
|
66
66
|
.foregroundStyle(.secondary)
|
|
67
67
|
.frame(height: 80)
|
|
68
68
|
} else {
|
|
@@ -83,7 +83,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
83
83
|
AxisValueLabel {
|
|
84
84
|
if let pct = value.as(Int.self) {
|
|
85
85
|
Text("\(pct)%")
|
|
86
|
-
.font(.
|
|
86
|
+
.font(RunicFont.caption2)
|
|
87
87
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -92,7 +92,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
92
92
|
.chartXAxis {
|
|
93
93
|
AxisMarks(values: .automatic(desiredCount: 5)) { _ in
|
|
94
94
|
AxisValueLabel()
|
|
95
|
-
.font(.
|
|
95
|
+
.font(RunicFont.caption2)
|
|
96
96
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -104,7 +104,7 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
104
104
|
let used = Int(latest.usedPercent.rounded())
|
|
105
105
|
let unused = max(0, 100 - used)
|
|
106
106
|
Text("\(latest.label): \(used)% used, \(unused)% unused")
|
|
107
|
-
.font(.
|
|
107
|
+
.font(RunicFont.caption)
|
|
108
108
|
.foregroundStyle(.secondary)
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -159,7 +159,8 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
159
159
|
// Aggregate by ISO week
|
|
160
160
|
var weekBuckets: [(label: String, tokens: Int, date: Date, isThisWeek: Bool)] = []
|
|
161
161
|
for weekOffset in stride(from: -3, through: 0, by: 1) {
|
|
162
|
-
guard let weekStart = calendar.date(byAdding: .weekOfYear, value: weekOffset, to: todayStart)
|
|
162
|
+
guard let weekStart = calendar.date(byAdding: .weekOfYear, value: weekOffset, to: todayStart)
|
|
163
|
+
else { continue }
|
|
163
164
|
var total = 0
|
|
164
165
|
for dayOffset in 0..<7 {
|
|
165
166
|
guard let date = calendar.date(byAdding: .day, value: dayOffset, to: weekStart) else { continue }
|
|
@@ -171,20 +172,27 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
171
172
|
let maxWeekTokens = weekBuckets.map(\.tokens).max() ?? 1
|
|
172
173
|
let bars = weekBuckets.map { bucket in
|
|
173
174
|
let pct = maxWeekTokens > 0 ? Double(bucket.tokens) / Double(maxWeekTokens) * 100 : 0
|
|
174
|
-
return UtilizationBar(
|
|
175
|
+
return UtilizationBar(
|
|
176
|
+
id: bucket.label,
|
|
177
|
+
label: bucket.label,
|
|
178
|
+
date: bucket.date,
|
|
179
|
+
usedPercent: pct,
|
|
180
|
+
isToday: bucket.isThisWeek)
|
|
175
181
|
}
|
|
176
182
|
return UtilizationModel(bars: bars)
|
|
177
183
|
|
|
178
184
|
case .monthly:
|
|
179
185
|
var monthBuckets: [(label: String, tokens: Int, date: Date, isThisMonth: Bool)] = []
|
|
180
186
|
for monthOffset in stride(from: -2, through: 0, by: 1) {
|
|
181
|
-
guard let monthStart = calendar.date(byAdding: .month, value: monthOffset, to: todayStart)
|
|
187
|
+
guard let monthStart = calendar.date(byAdding: .month, value: monthOffset, to: todayStart)
|
|
188
|
+
else { continue }
|
|
182
189
|
let monthComponents = calendar.dateComponents([.year, .month], from: monthStart)
|
|
183
190
|
guard let actualMonthStart = calendar.date(from: monthComponents),
|
|
184
191
|
let range = calendar.range(of: .day, in: .month, for: actualMonthStart) else { continue }
|
|
185
192
|
var total = 0
|
|
186
193
|
for dayOffset in 0..<range.count {
|
|
187
|
-
guard let date = calendar.date(byAdding: .day, value: dayOffset, to: actualMonthStart)
|
|
194
|
+
guard let date = calendar.date(byAdding: .day, value: dayOffset, to: actualMonthStart)
|
|
195
|
+
else { continue }
|
|
188
196
|
total += tokensByDay[formatter.string(from: date)] ?? 0
|
|
189
197
|
}
|
|
190
198
|
let label = monthStart.formatted(.dateTime.month(.abbreviated))
|
|
@@ -193,7 +201,12 @@ struct SubscriptionUtilizationChartMenuView: View {
|
|
|
193
201
|
let maxMonthTokens = monthBuckets.map(\.tokens).max() ?? 1
|
|
194
202
|
let bars = monthBuckets.map { bucket in
|
|
195
203
|
let pct = maxMonthTokens > 0 ? Double(bucket.tokens) / Double(maxMonthTokens) * 100 : 0
|
|
196
|
-
return UtilizationBar(
|
|
204
|
+
return UtilizationBar(
|
|
205
|
+
id: bucket.label,
|
|
206
|
+
label: bucket.label,
|
|
207
|
+
date: bucket.date,
|
|
208
|
+
usedPercent: pct,
|
|
209
|
+
isToday: bucket.isThisMonth)
|
|
197
210
|
}
|
|
198
211
|
return UtilizationModel(bars: bars)
|
|
199
212
|
}
|
|
@@ -32,7 +32,7 @@ struct UsageBreakdownChartMenuView: View {
|
|
|
32
32
|
VStack(alignment: .leading, spacing: RunicSpacing.sm) {
|
|
33
33
|
if model.points.isEmpty {
|
|
34
34
|
Text("No usage breakdown data.")
|
|
35
|
-
.font(.footnote)
|
|
35
|
+
.font(RunicFont.footnote)
|
|
36
36
|
.foregroundStyle(.secondary)
|
|
37
37
|
} else {
|
|
38
38
|
Chart {
|
|
@@ -58,7 +58,7 @@ struct UsageBreakdownChartMenuView: View {
|
|
|
58
58
|
AxisGridLine().foregroundStyle(Color.clear)
|
|
59
59
|
AxisTick().foregroundStyle(Color.clear)
|
|
60
60
|
AxisValueLabel(format: .dateTime.month(.abbreviated).day())
|
|
61
|
-
.font(.caption2)
|
|
61
|
+
.font(RunicFont.caption2)
|
|
62
62
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -88,13 +88,13 @@ struct UsageBreakdownChartMenuView: View {
|
|
|
88
88
|
let detail = self.detailLines(model: model)
|
|
89
89
|
VStack(alignment: .leading, spacing: 0) {
|
|
90
90
|
Text(detail.primary)
|
|
91
|
-
.font(.
|
|
91
|
+
.font(RunicFont.caption)
|
|
92
92
|
.foregroundStyle(.secondary)
|
|
93
93
|
.lineLimit(1)
|
|
94
94
|
.truncationMode(.tail)
|
|
95
95
|
.frame(height: 16, alignment: .leading)
|
|
96
96
|
Text(detail.secondary ?? " ")
|
|
97
|
-
.font(.
|
|
97
|
+
.font(RunicFont.caption)
|
|
98
98
|
.foregroundStyle(.secondary)
|
|
99
99
|
.lineLimit(1)
|
|
100
100
|
.truncationMode(.tail)
|
|
@@ -113,7 +113,7 @@ struct UsageBreakdownChartMenuView: View {
|
|
|
113
113
|
.fill(model.color(for: service))
|
|
114
114
|
.frame(width: RunicSpacing.chartLegendDot, height: RunicSpacing.chartLegendDot)
|
|
115
115
|
Text(service)
|
|
116
|
-
.font(.caption2)
|
|
116
|
+
.font(RunicFont.caption2)
|
|
117
117
|
.foregroundStyle(.secondary)
|
|
118
118
|
.lineLimit(1)
|
|
119
119
|
}
|
|
@@ -46,12 +46,12 @@ struct UsageHeatmapMenuView: View {
|
|
|
46
46
|
let model = Self.makeModel(from: self.hourlySummaries)
|
|
47
47
|
VStack(alignment: .leading, spacing: RunicSpacing.sm) {
|
|
48
48
|
Text("Usage Heatmap (24×7)")
|
|
49
|
-
.font(.headline)
|
|
49
|
+
.font(RunicFont.headline)
|
|
50
50
|
.fontWeight(.semibold)
|
|
51
51
|
|
|
52
52
|
if model.isEmpty {
|
|
53
53
|
Text("No heatmap data.")
|
|
54
|
-
.font(.footnote)
|
|
54
|
+
.font(RunicFont.footnote)
|
|
55
55
|
.foregroundStyle(.secondary)
|
|
56
56
|
} else {
|
|
57
57
|
ScrollView(.horizontal, showsIndicators: true) {
|
|
@@ -62,7 +62,7 @@ struct UsageHeatmapMenuView: View {
|
|
|
62
62
|
.frame(width: 40, alignment: .leading)
|
|
63
63
|
ForEach(0..<24, id: \.self) { hour in
|
|
64
64
|
Text(self.hourLabel(hour))
|
|
65
|
-
.font(.caption2)
|
|
65
|
+
.font(RunicFont.caption2)
|
|
66
66
|
.foregroundStyle(.secondary)
|
|
67
67
|
.frame(width: 40, alignment: .center)
|
|
68
68
|
.lineLimit(1)
|
|
@@ -73,7 +73,7 @@ struct UsageHeatmapMenuView: View {
|
|
|
73
73
|
ForEach(0..<7, id: \.self) { weekday in
|
|
74
74
|
HStack(spacing: 2) {
|
|
75
75
|
Text(self.weekdayLabel(weekday))
|
|
76
|
-
.font(.caption)
|
|
76
|
+
.font(RunicFont.caption)
|
|
77
77
|
.foregroundStyle(.secondary)
|
|
78
78
|
.frame(width: 38, alignment: .leading)
|
|
79
79
|
|
|
@@ -99,7 +99,7 @@ struct UsageHeatmapMenuView: View {
|
|
|
99
99
|
// Legend
|
|
100
100
|
HStack(spacing: RunicSpacing.xs) {
|
|
101
101
|
Text("Low")
|
|
102
|
-
.font(.caption2)
|
|
102
|
+
.font(RunicFont.caption2)
|
|
103
103
|
.foregroundStyle(.secondary)
|
|
104
104
|
HStack(spacing: 2) {
|
|
105
105
|
ForEach(0..<5, id: \.self) { level in
|
|
@@ -110,7 +110,7 @@ struct UsageHeatmapMenuView: View {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
Text("High")
|
|
113
|
-
.font(.caption2)
|
|
113
|
+
.font(RunicFont.caption2)
|
|
114
114
|
.foregroundStyle(.secondary)
|
|
115
115
|
}
|
|
116
116
|
.padding(.top, RunicSpacing.xs)
|
|
@@ -121,7 +121,7 @@ struct UsageHeatmapMenuView: View {
|
|
|
121
121
|
|
|
122
122
|
let detail = self.detailText(model: model)
|
|
123
123
|
Text(detail)
|
|
124
|
-
.font(.caption)
|
|
124
|
+
.font(RunicFont.caption)
|
|
125
125
|
.foregroundStyle(.secondary)
|
|
126
126
|
.lineLimit(2)
|
|
127
127
|
.frame(height: 32, alignment: .leading)
|
|
@@ -229,4 +229,3 @@ private struct HeatmapCellView: View {
|
|
|
229
229
|
.cornerRadius(RunicCornerRadius.xs)
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
|
-
|
|
@@ -13,17 +13,21 @@ struct UsageTimelineChartMenuView: View {
|
|
|
13
13
|
|
|
14
14
|
var cutoffInterval: TimeInterval {
|
|
15
15
|
switch self {
|
|
16
|
-
case .threeDays:
|
|
17
|
-
case .sevenDays:
|
|
18
|
-
case .thirtyDays:
|
|
19
|
-
case .quarter:
|
|
20
|
-
case .year:
|
|
16
|
+
case .threeDays: -259_200
|
|
17
|
+
case .sevenDays: -604_800
|
|
18
|
+
case .thirtyDays: -2_592_000
|
|
19
|
+
case .quarter: -7_776_000
|
|
20
|
+
case .year: -31_536_000
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
var usesHourlyData: Bool {
|
|
24
|
+
var usesHourlyData: Bool {
|
|
25
|
+
false
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
var label: String {
|
|
28
|
+
var label: String {
|
|
29
|
+
self.rawValue
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
private struct Point: Identifiable {
|
|
@@ -65,7 +69,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
65
69
|
VStack(alignment: .leading, spacing: RunicSpacing.xs) {
|
|
66
70
|
// Header on its own line
|
|
67
71
|
Text("Timeline")
|
|
68
|
-
.font(.
|
|
72
|
+
.font(RunicFont.subheadline)
|
|
69
73
|
.fontWeight(.semibold)
|
|
70
74
|
|
|
71
75
|
// Range picker on its own line
|
|
@@ -78,7 +82,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
78
82
|
|
|
79
83
|
if model.points.isEmpty {
|
|
80
84
|
Text("No data for selected range.")
|
|
81
|
-
.font(.
|
|
85
|
+
.font(RunicFont.footnote)
|
|
82
86
|
.foregroundStyle(.secondary)
|
|
83
87
|
.frame(height: 100)
|
|
84
88
|
} else {
|
|
@@ -112,7 +116,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
112
116
|
.symbolSize(60)
|
|
113
117
|
.annotation(position: .top, spacing: 4) {
|
|
114
118
|
Text("Peak")
|
|
115
|
-
.font(.
|
|
119
|
+
.font(RunicFont.caption2)
|
|
116
120
|
.foregroundStyle(Color(nsColor: .systemYellow))
|
|
117
121
|
}
|
|
118
122
|
}
|
|
@@ -124,7 +128,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
124
128
|
AxisValueLabel {
|
|
125
129
|
if let tokens = value.as(Int.self) {
|
|
126
130
|
Text(UsageFormatter.tokenCountString(tokens))
|
|
127
|
-
.font(.
|
|
131
|
+
.font(RunicFont.caption2)
|
|
128
132
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
129
133
|
}
|
|
130
134
|
}
|
|
@@ -135,7 +139,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
135
139
|
AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5, dash: [4, 3]))
|
|
136
140
|
.foregroundStyle(Color(nsColor: .separatorColor).opacity(0.3))
|
|
137
141
|
AxisValueLabel(format: model.xAxisFormat)
|
|
138
|
-
.font(.
|
|
142
|
+
.font(RunicFont.caption2)
|
|
139
143
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
140
144
|
}
|
|
141
145
|
}
|
|
@@ -163,7 +167,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
163
167
|
// Detail line
|
|
164
168
|
let detail = self.detailText(model: model)
|
|
165
169
|
Text(detail)
|
|
166
|
-
.font(.
|
|
170
|
+
.font(RunicFont.caption)
|
|
167
171
|
.foregroundStyle(.secondary)
|
|
168
172
|
.lineLimit(1)
|
|
169
173
|
.truncationMode(.tail)
|
|
@@ -184,7 +188,8 @@ struct UsageTimelineChartMenuView: View {
|
|
|
184
188
|
}
|
|
185
189
|
.chartPanelStyle(width: self.width)
|
|
186
190
|
.accessibilityElement(children: .ignore)
|
|
187
|
-
.accessibilityLabel(
|
|
191
|
+
.accessibilityLabel(
|
|
192
|
+
"Usage timeline chart showing \(model.points.count) data points over \(self.selectedTimeRange.label)")
|
|
188
193
|
}
|
|
189
194
|
|
|
190
195
|
// MARK: - Stat cell
|
|
@@ -196,10 +201,10 @@ struct UsageTimelineChartMenuView: View {
|
|
|
196
201
|
var body: some View {
|
|
197
202
|
VStack(alignment: .leading, spacing: RunicSpacing.xxxs) {
|
|
198
203
|
Text(self.label)
|
|
199
|
-
.font(.
|
|
204
|
+
.font(RunicFont.caption2)
|
|
200
205
|
.foregroundStyle(.tertiary)
|
|
201
206
|
Text(self.value)
|
|
202
|
-
.font(.
|
|
207
|
+
.font(RunicFont.caption)
|
|
203
208
|
.fontWeight(.medium)
|
|
204
209
|
}
|
|
205
210
|
}
|
|
@@ -254,7 +259,7 @@ struct UsageTimelineChartMenuView: View {
|
|
|
254
259
|
}
|
|
255
260
|
}
|
|
256
261
|
|
|
257
|
-
let desiredAxisCount
|
|
262
|
+
let desiredAxisCount = switch timeRange {
|
|
258
263
|
case .threeDays: 3
|
|
259
264
|
case .sevenDays: 5
|
|
260
265
|
case .thirtyDays: 6
|
|
@@ -49,12 +49,12 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
49
49
|
|
|
50
50
|
VStack(alignment: .leading, spacing: RunicSpacing.xs) {
|
|
51
51
|
Text("Windows")
|
|
52
|
-
.font(.
|
|
52
|
+
.font(RunicFont.subheadline)
|
|
53
53
|
.fontWeight(.semibold)
|
|
54
54
|
|
|
55
55
|
if model.points.isEmpty {
|
|
56
56
|
Text("No usage window data available.")
|
|
57
|
-
.font(.
|
|
57
|
+
.font(RunicFont.footnote)
|
|
58
58
|
.foregroundStyle(.secondary)
|
|
59
59
|
.frame(height: 80)
|
|
60
60
|
} else {
|
|
@@ -64,7 +64,8 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
64
64
|
x: .value("Date", point.date),
|
|
65
65
|
y: .value("%", point.percent),
|
|
66
66
|
series: .value("Window", point.series))
|
|
67
|
-
.foregroundStyle(point.series == self.primaryLabel ? Self.primaryColor : Self
|
|
67
|
+
.foregroundStyle(point.series == self.primaryLabel ? Self.primaryColor : Self
|
|
68
|
+
.secondaryColor)
|
|
68
69
|
.lineStyle(StrokeStyle(lineWidth: 2))
|
|
69
70
|
.interpolationMethod(.catmullRom)
|
|
70
71
|
}
|
|
@@ -77,7 +78,7 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
77
78
|
AxisValueLabel {
|
|
78
79
|
if let pct = value.as(Int.self) {
|
|
79
80
|
Text("\(pct)%")
|
|
80
|
-
.font(.
|
|
81
|
+
.font(RunicFont.caption2)
|
|
81
82
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
82
83
|
}
|
|
83
84
|
}
|
|
@@ -88,7 +89,7 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
88
89
|
AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5, dash: [4, 3]))
|
|
89
90
|
.foregroundStyle(Color(nsColor: .separatorColor).opacity(0.3))
|
|
90
91
|
AxisValueLabel(format: .dateTime.month(.abbreviated).day())
|
|
91
|
-
.font(.
|
|
92
|
+
.font(RunicFont.caption2)
|
|
92
93
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
93
94
|
}
|
|
94
95
|
}
|
|
@@ -102,7 +103,7 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
102
103
|
.fill(Self.primaryColor)
|
|
103
104
|
.frame(width: RunicSpacing.chartLegendDot, height: RunicSpacing.chartLegendDot)
|
|
104
105
|
Text(self.primaryLabel)
|
|
105
|
-
.font(.
|
|
106
|
+
.font(RunicFont.caption2)
|
|
106
107
|
.foregroundStyle(.secondary)
|
|
107
108
|
}
|
|
108
109
|
if let secondaryLabel = self.secondaryLabel {
|
|
@@ -111,7 +112,7 @@ struct UsageWindowComparisonChartMenuView: View {
|
|
|
111
112
|
.fill(Self.secondaryColor)
|
|
112
113
|
.frame(width: RunicSpacing.chartLegendDot, height: RunicSpacing.chartLegendDot)
|
|
113
114
|
Text(secondaryLabel)
|
|
114
|
-
.font(.
|
|
115
|
+
.font(RunicFont.caption2)
|
|
115
116
|
.foregroundStyle(.secondary)
|
|
116
117
|
}
|
|
117
118
|
}
|
|
@@ -33,20 +33,20 @@ struct WeeklyActivityChartMenuView: View {
|
|
|
33
33
|
VStack(alignment: .leading, spacing: RunicSpacing.sm) {
|
|
34
34
|
HStack(alignment: .firstTextBaseline) {
|
|
35
35
|
Text("Last 7 Days")
|
|
36
|
-
.font(.
|
|
36
|
+
.font(RunicFont.subheadline)
|
|
37
37
|
.fontWeight(.semibold)
|
|
38
38
|
Spacer()
|
|
39
39
|
if model.bars.count > 1 {
|
|
40
|
-
let avg = model.totalTokens / max(1, model.bars.
|
|
40
|
+
let avg = model.totalTokens / max(1, model.bars.count(where: { $0.totalTokens > 0 }))
|
|
41
41
|
Text("\(UsageFormatter.tokenCountString(avg)) avg")
|
|
42
|
-
.font(.
|
|
42
|
+
.font(RunicFont.caption)
|
|
43
43
|
.foregroundStyle(.secondary)
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if model.bars.allSatisfy({ $0.totalTokens == 0 }) {
|
|
48
48
|
Text("No usage in the last 7 days.")
|
|
49
|
-
.font(.
|
|
49
|
+
.font(RunicFont.footnote)
|
|
50
50
|
.foregroundStyle(.secondary)
|
|
51
51
|
.frame(height: 80)
|
|
52
52
|
} else {
|
|
@@ -60,9 +60,9 @@ struct WeeklyActivityChartMenuView: View {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
.chartXAxis {
|
|
63
|
-
AxisMarks {
|
|
63
|
+
AxisMarks { _ in
|
|
64
64
|
AxisValueLabel()
|
|
65
|
-
.font(.
|
|
65
|
+
.font(RunicFont.caption2)
|
|
66
66
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -73,7 +73,7 @@ struct WeeklyActivityChartMenuView: View {
|
|
|
73
73
|
AxisValueLabel {
|
|
74
74
|
if let tokens = value.as(Int.self) {
|
|
75
75
|
Text(UsageFormatter.tokenCountString(tokens))
|
|
76
|
-
.font(.
|
|
76
|
+
.font(RunicFont.caption2)
|
|
77
77
|
.foregroundStyle(Color(nsColor: .tertiaryLabelColor))
|
|
78
78
|
}
|
|
79
79
|
}
|