@sriinnu/runic 2.0.0 → 2.11.1
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 +256 -0
- package/LICENSE +373 -21
- package/README.md +96 -89
- package/THIRD-PARTY-NOTICES.md +651 -0
- package/package.json +14 -4
- package/.swiftformat +0 -50
- package/.swiftlint.yml +0 -160
- package/CONTRIBUTING.md +0 -456
- package/Icon.icns +0 -0
- package/Icon.icon/Assets/runic.png +0 -0
- package/Icon.icon/icon.json +0 -36
- package/Package.resolved +0 -51
- package/Package.swift +0 -136
- package/Packages/Helix/LICENSE +0 -21
- package/Packages/Helix/Package.swift +0 -29
- package/Packages/Helix/README.md +0 -976
- package/Packages/Helix/Sources/Helix/Binding.swift +0 -111
- package/Packages/Helix/Sources/Helix/CommandParser.swift +0 -160
- package/Packages/Helix/Sources/Helix/CommandSignature.swift +0 -117
- package/Packages/Helix/Sources/Helix/ExpressibleFromArgument.swift +0 -72
- package/Packages/Helix/Sources/Helix/HelpGenerator.swift +0 -175
- package/Packages/Helix/Sources/Helix/NameSpecification.swift +0 -98
- package/Packages/Helix/Sources/Helix/ParsableCommand.swift +0 -204
- package/Packages/Helix/Sources/Helix/Platform/DarwinPlatformContext.swift +0 -44
- package/Packages/Helix/Sources/Helix/Platform/LinuxPlatformContext.swift +0 -34
- package/Packages/Helix/Sources/Helix/Platform/PlatformContext+Default.swift +0 -91
- package/Packages/Helix/Sources/Helix/Platform/PlatformContext.swift +0 -94
- package/Packages/Helix/Sources/Helix/Platform/PlatformPath.swift +0 -167
- package/Packages/Helix/Sources/Helix/Platform/Stdio.swift +0 -99
- package/Packages/Helix/Sources/Helix/Platform/WebPlatformContext.swift +0 -146
- package/Packages/Helix/Sources/Helix/Platform/WindowsPlatformContext.swift +0 -97
- package/Packages/Helix/Sources/Helix/Program.swift +0 -204
- package/Packages/Helix/Sources/Helix/PropertyWrappers.swift +0 -367
- package/Packages/Silo/LICENSE +0 -21
- package/Packages/Silo/Package.swift +0 -34
- package/Packages/Silo/README.md +0 -466
- package/Packages/Silo/Sources/Silo/BinaryCookiesReader.swift +0 -169
- package/Packages/Silo/Sources/Silo/BrowserCookieAnalytics.swift +0 -365
- package/Packages/Silo/Sources/Silo/BrowserCookieBackends.swift +0 -594
- package/Packages/Silo/Sources/Silo/BrowserCookieClient.swift +0 -326
- package/Packages/Silo/Sources/Silo/BrowserCookieExport.swift +0 -154
- package/Packages/Silo/Sources/Silo/BrowserCookieImport.swift +0 -119
- package/Packages/Silo/Sources/Silo/BrowserCookieMockStore.swift +0 -121
- package/Packages/Silo/Sources/Silo/BrowserCookieModels.swift +0 -391
- package/Packages/Silo/Sources/Silo/ChromiumCookieReader.swift +0 -240
- package/Packages/Silo/Sources/Silo/CryptoSupport.swift +0 -86
- package/Packages/Silo/Sources/Silo/FirefoxCookieReader.swift +0 -172
- package/Packages/Silo/Sources/Silo/LinuxChromiumCookieReader.swift +0 -172
- package/Packages/Silo/Sources/Silo/LinuxSecretService.swift +0 -105
- package/Packages/Silo/Sources/Silo/MacOSChromiumCookieReader.swift +0 -191
- package/Packages/Silo/Sources/Silo/SQLiteSnapshot.swift +0 -41
- package/Packages/Silo/Sources/Silo/WindowsChromiumCookieReader.swift +0 -110
- package/RuniciOS/App/RuniciOSApp.swift +0 -105
- package/RuniciOS/Core/RunicTypographyiOS.swift +0 -24
- package/RuniciOS/Core/iOSUsageStore.swift +0 -192
- package/RuniciOS/Views/ProviderDetailView.swift +0 -312
- package/RuniciOS/Views/ProviderListView.swift +0 -228
- package/RuniciOS/Widgets/LargeWidget.swift +0 -367
- package/RuniciOS/Widgets/LiveActivity.swift +0 -342
- package/RuniciOS/Widgets/LockScreenWidget.swift +0 -273
- package/RuniciOS/Widgets/MediumWidget.swift +0 -370
- package/RuniciOS/Widgets/RunicWidget.swift +0 -274
- package/RuniciOS/Widgets/SmallWidget.swift +0 -281
- package/RuniciOS/Widgets/WidgetModels.swift +0 -285
- package/RuniciOS/Widgets/WidgetTimeline.swift +0 -270
- package/Scripts/CREATION-SUMMARY.md +0 -367
- package/Scripts/DIRECTORY-STRUCTURE.md +0 -358
- package/Scripts/GETTING-STARTED-CHECKLIST.md +0 -364
- package/Scripts/INDEX.md +0 -365
- package/Scripts/QUICK-REFERENCE.md +0 -164
- package/Scripts/README-SCRIPTS.md +0 -926
- package/Scripts/build-android.sh +0 -526
- package/Scripts/build-ios.sh +0 -529
- package/Scripts/build-macos.sh +0 -603
- package/Scripts/build-windows.sh +0 -504
- package/Scripts/build_icon.sh +0 -49
- package/Scripts/changelog-to-html.sh +0 -89
- package/Scripts/check-release-assets.sh +0 -10
- package/Scripts/ci-config.yml +0 -474
- package/Scripts/compile_and_run.sh +0 -219
- package/Scripts/compile_and_run_adhoc.sh +0 -4
- package/Scripts/docs-list.mjs +0 -119
- package/Scripts/make_appcast.sh +0 -58
- package/Scripts/package_app.sh +0 -409
- package/Scripts/release-lib.sh +0 -214
- package/Scripts/release.sh +0 -76
- package/Scripts/setup-all.sh +0 -387
- package/Scripts/setup-ios.sh +0 -404
- package/Scripts/setup-react-native.sh +0 -523
- package/Scripts/sign-and-notarize.sh +0 -122
- package/Scripts/test_live_update.sh +0 -38
- package/Scripts/validate_changelog.sh +0 -23
- package/Scripts/verify_appcast.sh +0 -92
- package/Sources/Runic/About.swift +0 -93
- package/Sources/Runic/AppNotifications.swift +0 -117
- package/Sources/Runic/Controllers/StatusItemController+Actions.swift +0 -670
- package/Sources/Runic/Controllers/StatusItemController+Animation.swift +0 -519
- package/Sources/Runic/Controllers/StatusItemController+ChartSubmenus.swift +0 -824
- package/Sources/Runic/Controllers/StatusItemController+CustomProviders.swift +0 -90
- package/Sources/Runic/Controllers/StatusItemController+Menu.swift +0 -1412
- package/Sources/Runic/Controllers/StatusItemController+MenuCards.swift +0 -339
- package/Sources/Runic/Controllers/StatusItemController+MenuHelpers.swift +0 -423
- package/Sources/Runic/Controllers/StatusItemController.swift +0 -360
- package/Sources/Runic/Core/BudgetNotificationManager.swift +0 -81
- package/Sources/Runic/Core/Login/ClaudeLoginRunner.swift +0 -103
- package/Sources/Runic/Core/Login/CodexLoginRunner.swift +0 -154
- package/Sources/Runic/Core/Login/CursorLoginRunner.swift +0 -206
- package/Sources/Runic/Core/Login/GeminiLoginRunner.swift +0 -92
- package/Sources/Runic/Core/Rendering/IconRenderer.swift +0 -1222
- package/Sources/Runic/Core/Rendering/IconView.swift +0 -122
- package/Sources/Runic/Core/Rendering/ProviderBrandIcon.swift +0 -71
- package/Sources/Runic/Core/RunicAnimation.swift +0 -53
- package/Sources/Runic/Core/RunicColors.swift +0 -73
- package/Sources/Runic/Core/RunicCornerRadius.swift +0 -15
- package/Sources/Runic/Core/RunicSpacing.swift +0 -68
- package/Sources/Runic/Core/RunicTypography.swift +0 -206
- package/Sources/Runic/Core/Stores/AuggieTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/AzureOpenAITokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/CerebrasTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/CohereTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/CopilotTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/CustomProviderStore.swift +0 -158
- package/Sources/Runic/Core/Stores/DeepSeekTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/FireworksTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/GroqTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/KimiTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/MiniMaxCookieHeaderStore.swift +0 -117
- package/Sources/Runic/Core/Stores/MiniMaxGroupIDStore.swift +0 -117
- package/Sources/Runic/Core/Stores/MiniMaxTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/MistralTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/OpenRouterTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/PerplexityTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/ProviderToggleStore.swift +0 -30
- package/Sources/Runic/Core/Stores/QwenTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/SambaNovaTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/SettingsStore.swift +0 -1749
- package/Sources/Runic/Core/Stores/TogetherTokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/UsageStore+Accessors.swift +0 -33
- package/Sources/Runic/Core/Stores/UsageStore+Status.swift +0 -189
- package/Sources/Runic/Core/Stores/UsageStore+TokenCost.swift +0 -33
- package/Sources/Runic/Core/Stores/UsageStore+WidgetSnapshot.swift +0 -67
- package/Sources/Runic/Core/Stores/UsageStore.swift +0 -3631
- package/Sources/Runic/Core/Stores/XAITokenStore.swift +0 -117
- package/Sources/Runic/Core/Stores/ZaiTokenStore.swift +0 -117
- package/Sources/Runic/Core/UsageExporter.swift +0 -197
- package/Sources/Runic/Date+RelativeDescription.swift +0 -21
- package/Sources/Runic/HiddenWindowView.swift +0 -32
- package/Sources/Runic/InstallOrigin.swift +0 -9
- package/Sources/Runic/KeyboardShortcuts+Names.swift +0 -6
- package/Sources/Runic/MouseLocationReader.swift +0 -65
- package/Sources/Runic/Notifications+Runic.swift +0 -6
- package/Sources/Runic/OpenAICreditsPurchaseWindowController.swift +0 -503
- package/Sources/Runic/ProviderRegistry.swift +0 -100
- package/Sources/Runic/ProviderSwitcherButtons.swift +0 -267
- package/Sources/Runic/Providers/Antigravity/AntigravityLoginFlow.swift +0 -11
- package/Sources/Runic/Providers/Antigravity/AntigravityProviderImplementation.swift +0 -14
- package/Sources/Runic/Providers/Auggie/AuggieProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Azure/AzureProviderImplementation.swift +0 -52
- package/Sources/Runic/Providers/Bedrock/BedrockProviderImplementation.swift +0 -42
- package/Sources/Runic/Providers/Cerebras/CerebrasProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Claude/ClaudeLoginFlow.swift +0 -26
- package/Sources/Runic/Providers/Claude/ClaudeProviderImplementation.swift +0 -14
- package/Sources/Runic/Providers/Codex/CodexLoginFlow.swift +0 -18
- package/Sources/Runic/Providers/Codex/CodexProviderImplementation.swift +0 -15
- package/Sources/Runic/Providers/Cohere/CohereProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Copilot/CopilotLoginFlow.swift +0 -193
- package/Sources/Runic/Providers/Copilot/CopilotProviderImplementation.swift +0 -110
- package/Sources/Runic/Providers/Cursor/CursorLoginFlow.swift +0 -28
- package/Sources/Runic/Providers/Cursor/CursorProviderImplementation.swift +0 -15
- package/Sources/Runic/Providers/DeepSeek/DeepSeekProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Factory/FactoryLoginFlow.swift +0 -12
- package/Sources/Runic/Providers/Factory/FactoryProviderImplementation.swift +0 -15
- package/Sources/Runic/Providers/Fireworks/FireworksProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Gemini/GeminiLoginFlow.swift +0 -20
- package/Sources/Runic/Providers/Gemini/GeminiProviderImplementation.swift +0 -15
- package/Sources/Runic/Providers/Groq/GroqProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Kimi/KimiProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/MiniMax/MiniMaxProviderImplementation.swift +0 -32
- package/Sources/Runic/Providers/Mistral/MistralProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/OpenRouter/OpenRouterProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Perplexity/PerplexityProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/SambaNova/SambaNovaProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Shared/ProviderCatalog.swift +0 -15
- package/Sources/Runic/Providers/Shared/ProviderImplementation.swift +0 -51
- package/Sources/Runic/Providers/Shared/ProviderImplementationRegistry.swift +0 -66
- package/Sources/Runic/Providers/Shared/ProviderLoginFlow.swift +0 -12
- package/Sources/Runic/Providers/Shared/ProviderSettingsDescriptors.swift +0 -99
- package/Sources/Runic/Providers/Shared/SystemSettingsLinks.swift +0 -18
- package/Sources/Runic/Providers/Together/TogetherProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/XAI/XAIProviderImplementation.swift +0 -24
- package/Sources/Runic/Providers/Zai/ZaiProviderImplementation.swift +0 -24
- 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/Resources/ProviderIcon-antigravity.svg +0 -2
- package/Sources/Runic/Resources/ProviderIcon-auggie.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-azure.svg +0 -5
- package/Sources/Runic/Resources/ProviderIcon-bedrock.svg +0 -7
- package/Sources/Runic/Resources/ProviderIcon-cerebras.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-claude.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-codex.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-cohere.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-copilot.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-cursor.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-deepseek.svg +0 -4
- package/Sources/Runic/Resources/ProviderIcon-factory.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-fireworks.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-gemini.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-groq.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-kimi.svg +0 -4
- package/Sources/Runic/Resources/ProviderIcon-minimax.svg +0 -1
- package/Sources/Runic/Resources/ProviderIcon-mistral.svg +0 -5
- package/Sources/Runic/Resources/ProviderIcon-openrouter.svg +0 -7
- package/Sources/Runic/Resources/ProviderIcon-perplexity.svg +0 -4
- package/Sources/Runic/Resources/ProviderIcon-qwen.svg +0 -9
- package/Sources/Runic/Resources/ProviderIcon-sambanova.svg +0 -4
- package/Sources/Runic/Resources/ProviderIcon-together.svg +0 -5
- package/Sources/Runic/Resources/ProviderIcon-vertexai.svg +0 -17
- package/Sources/Runic/Resources/ProviderIcon-xai.svg +0 -3
- package/Sources/Runic/Resources/ProviderIcon-zai.svg +0 -5
- package/Sources/Runic/Resources/RunicMenubarIcon.svg +0 -7
- package/Sources/Runic/Resources/provider-context-windows.json +0 -20
- package/Sources/Runic/RunicApp.swift +0 -367
- package/Sources/Runic/SessionQuotaNotifications.swift +0 -58
- package/Sources/Runic/UsagePaceText.swift +0 -52
- package/Sources/Runic/UsageProgressBar.swift +0 -228
- package/Sources/Runic/Utilities/DisplayLink.swift +0 -96
- package/Sources/Runic/Utilities/LoadingPattern.swift +0 -62
- package/Sources/Runic/Utilities/PerformanceConstants.swift +0 -85
- package/Sources/Runic/Views/Menu/AlertsMenuView.swift +0 -254
- package/Sources/Runic/Views/Menu/ChartPanelStyle.swift +0 -22
- package/Sources/Runic/Views/Menu/CostComparativeChartMenuView.swift +0 -275
- package/Sources/Runic/Views/Menu/CostHistoryChartMenuView.swift +0 -377
- package/Sources/Runic/Views/Menu/CreditsHistoryChartMenuView.swift +0 -312
- package/Sources/Runic/Views/Menu/EfficiencyMetricsMenuView.swift +0 -311
- package/Sources/Runic/Views/Menu/HeroStatCardsMenuView.swift +0 -231
- package/Sources/Runic/Views/Menu/HourlyActivityChartMenuView.swift +0 -228
- package/Sources/Runic/Views/Menu/InlineUsageChartView.swift +0 -157
- package/Sources/Runic/Views/Menu/MenuCardEntranceModifier.swift +0 -63
- package/Sources/Runic/Views/Menu/MenuCardSidebarView.swift +0 -248
- package/Sources/Runic/Views/Menu/MenuCardSkeletonView.swift +0 -104
- package/Sources/Runic/Views/Menu/MenuCardView.swift +0 -1889
- package/Sources/Runic/Views/Menu/MenuContent.swift +0 -153
- package/Sources/Runic/Views/Menu/MenuDescriptor.swift +0 -371
- package/Sources/Runic/Views/Menu/MenuHighlightStyle.swift +0 -35
- package/Sources/Runic/Views/Menu/ModelBreakdownMenuView.swift +0 -241
- package/Sources/Runic/Views/Menu/OverviewMenuView.swift +0 -281
- package/Sources/Runic/Views/Menu/ProjectBreakdownMenuView.swift +0 -214
- package/Sources/Runic/Views/Menu/ProjectBudgetMenuView.swift +0 -220
- package/Sources/Runic/Views/Menu/ProviderTabBarView.swift +0 -86
- package/Sources/Runic/Views/Menu/SubscriptionUtilizationChartMenuView.swift +0 -214
- package/Sources/Runic/Views/Menu/UsageBreakdownChartMenuView.swift +0 -398
- package/Sources/Runic/Views/Menu/UsageHeatmapMenuView.swift +0 -231
- package/Sources/Runic/Views/Menu/UsageTimelineChartMenuView.swift +0 -369
- package/Sources/Runic/Views/Menu/UsageWindowComparisonChartMenuView.swift +0 -191
- package/Sources/Runic/Views/Menu/WeeklyActivityChartMenuView.swift +0 -132
- package/Sources/Runic/Views/Performance/PerformanceDashboardView.swift +0 -621
- package/Sources/Runic/Views/Preferences/LiquidComponents.swift +0 -306
- package/Sources/Runic/Views/Preferences/PreferencesAboutPane.swift +0 -271
- package/Sources/Runic/Views/Preferences/PreferencesAdvancedPane.swift +0 -268
- package/Sources/Runic/Views/Preferences/PreferencesAlertsPane.swift +0 -418
- package/Sources/Runic/Views/Preferences/PreferencesAnalyticsPane.swift +0 -637
- package/Sources/Runic/Views/Preferences/PreferencesBudgetsPane.swift +0 -344
- package/Sources/Runic/Views/Preferences/PreferencesComponents.swift +0 -230
- package/Sources/Runic/Views/Preferences/PreferencesCustomProvidersPane.swift +0 -321
- package/Sources/Runic/Views/Preferences/PreferencesDebugPane.swift +0 -469
- package/Sources/Runic/Views/Preferences/PreferencesGeneralPane.swift +0 -250
- package/Sources/Runic/Views/Preferences/PreferencesHelpPane.swift +0 -50
- package/Sources/Runic/Views/Preferences/PreferencesIntegrationsPane.swift +0 -572
- package/Sources/Runic/Views/Preferences/PreferencesPerformancePane.swift +0 -291
- package/Sources/Runic/Views/Preferences/PreferencesProvidersPane.swift +0 -3480
- package/Sources/Runic/Views/Preferences/PreferencesSelection.swift +0 -29
- package/Sources/Runic/Views/Preferences/PreferencesSyncPane.swift +0 -61
- package/Sources/Runic/Views/Preferences/PreferencesView.swift +0 -213
- package/Sources/Runic/Views/Rating/QualityRatingView.swift +0 -238
- package/Sources/Runic/Views/Team/TeamDashboardView.swift +0 -376
- package/Sources/Runic/Views/Team/TeamInviteSheet.swift +0 -175
- package/Sources/Runic/Views/Team/TeamManagementView.swift +0 -762
- package/Sources/Runic/Views/Team/TeamMemberRow.swift +0 -181
- package/Sources/RunicCLI/CLIEntry.swift +0 -983
- package/Sources/RunicCLI/CLIRenderer.swift +0 -87
- package/Sources/RunicCLI/Commands/EnhancedUsageCommand.swift +0 -588
- package/Sources/RunicCLI/Commands/ModelsCommand.swift +0 -363
- package/Sources/RunicCLI/Commands/ProjectsCommand.swift +0 -453
- package/Sources/RunicCLI/Commands/ResetCommand.swift +0 -430
- package/Sources/RunicCLI/Commands/UsageLedgerSourceFactory.swift +0 -167
- package/Sources/RunicClaudeWatchdog/main.swift +0 -122
- package/Sources/RunicClaudeWebProbe/main.swift +0 -62
- package/Sources/RunicCore/AlertRuleStore.swift +0 -187
- package/Sources/RunicCore/BrowserCookieImportOrder.swift +0 -25
- package/Sources/RunicCore/CopilotUsageModels.swift +0 -84
- package/Sources/RunicCore/CostUsageFetcher.swift +0 -119
- package/Sources/RunicCore/CostUsageModels.swift +0 -479
- package/Sources/RunicCore/CreditsModels.swift +0 -50
- package/Sources/RunicCore/CustomProviders/CustomProviderModels.swift +0 -268
- package/Sources/RunicCore/CustomProviders/GenericProviderFetcher.swift +0 -631
- package/Sources/RunicCore/CustomProviders/ProviderTemplates.swift +0 -444
- package/Sources/RunicCore/Host/PTY/TTYCommandRunner.swift +0 -679
- package/Sources/RunicCore/Host/Process/SubprocessRunner.swift +0 -135
- package/Sources/RunicCore/Integrations/GitHubIntegration.swift +0 -173
- package/Sources/RunicCore/Logging/JSONStderrLogHandler.swift +0 -79
- package/Sources/RunicCore/Logging/OSLogLogHandler.swift +0 -86
- package/Sources/RunicCore/Logging/RunicLog.swift +0 -123
- package/Sources/RunicCore/Models/EnhancedUsageModels.swift +0 -370
- package/Sources/RunicCore/OpenAIDashboardModels.swift +0 -210
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift +0 -676
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardFetcher.swift +0 -492
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +0 -51
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardParser.swift +0 -483
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift +0 -558
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift +0 -204
- package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift +0 -78
- package/Sources/RunicCore/PathEnvironment.swift +0 -482
- package/Sources/RunicCore/Performance/PerformanceModels.swift +0 -371
- package/Sources/RunicCore/Performance/PerformanceStorageImpl.swift +0 -426
- package/Sources/RunicCore/Policy/UsagePolicyEngine.swift +0 -178
- package/Sources/RunicCore/ProjectBudgetStore.swift +0 -102
- package/Sources/RunicCore/ProviderCostSnapshot.swift +0 -29
- package/Sources/RunicCore/Providers/Antigravity/AntigravityProviderDescriptor.swift +0 -68
- package/Sources/RunicCore/Providers/Antigravity/AntigravityStatusProbe.swift +0 -685
- package/Sources/RunicCore/Providers/Auggie/AuggieProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/Auggie/AuggieUsageFetcher.swift +0 -142
- package/Sources/RunicCore/Providers/Azure/AzureProviderDescriptor.swift +0 -141
- package/Sources/RunicCore/Providers/Azure/AzureUsageFetcher.swift +0 -188
- package/Sources/RunicCore/Providers/Bedrock/BedrockProviderDescriptor.swift +0 -126
- package/Sources/RunicCore/Providers/Bedrock/BedrockUsageFetcher.swift +0 -164
- package/Sources/RunicCore/Providers/Cerebras/CerebrasProviderDescriptor.swift +0 -84
- package/Sources/RunicCore/Providers/Cerebras/CerebrasUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/Claude/ClaudeCLISession.swift +0 -332
- package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift +0 -180
- package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift +0 -137
- package/Sources/RunicCore/Providers/Claude/ClaudeProviderDescriptor.swift +0 -209
- package/Sources/RunicCore/Providers/Claude/ClaudeStatusProbe.swift +0 -654
- package/Sources/RunicCore/Providers/Claude/ClaudeUsageDataSource.swift +0 -30
- package/Sources/RunicCore/Providers/Claude/ClaudeUsageFetcher.swift +0 -480
- package/Sources/RunicCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift +0 -780
- package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift +0 -147
- package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift +0 -280
- package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift +0 -100
- package/Sources/RunicCore/Providers/Codex/CodexProviderDescriptor.swift +0 -245
- package/Sources/RunicCore/Providers/Codex/CodexStatusProbe.swift +0 -125
- package/Sources/RunicCore/Providers/Codex/CodexUsageDataSource.swift +0 -26
- package/Sources/RunicCore/Providers/Codex/CodexWebDashboardStrategy.swift +0 -183
- package/Sources/RunicCore/Providers/Cohere/CohereProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/Cohere/CohereUsageFetcher.swift +0 -85
- package/Sources/RunicCore/Providers/Copilot/CopilotDeviceFlow.swift +0 -123
- package/Sources/RunicCore/Providers/Copilot/CopilotGitHubCLITokenReader.swift +0 -117
- package/Sources/RunicCore/Providers/Copilot/CopilotProviderDescriptor.swift +0 -100
- package/Sources/RunicCore/Providers/Copilot/CopilotUsageFetcher.swift +0 -293
- package/Sources/RunicCore/Providers/Copilot/CopilotVSCodeTokenReader.swift +0 -385
- package/Sources/RunicCore/Providers/Cursor/CursorProviderDescriptor.swift +0 -67
- package/Sources/RunicCore/Providers/Cursor/CursorStatusProbe.swift +0 -595
- package/Sources/RunicCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift +0 -85
- package/Sources/RunicCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift +0 -108
- package/Sources/RunicCore/Providers/Factory/FactoryLocalStorageImporter.swift +0 -398
- package/Sources/RunicCore/Providers/Factory/FactoryProviderDescriptor.swift +0 -67
- package/Sources/RunicCore/Providers/Factory/FactoryStatusProbe.swift +0 -1276
- package/Sources/RunicCore/Providers/Fireworks/FireworksProviderDescriptor.swift +0 -84
- package/Sources/RunicCore/Providers/Fireworks/FireworksUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/Gemini/GeminiProviderDescriptor.swift +0 -67
- package/Sources/RunicCore/Providers/Gemini/GeminiStatusProbe.swift +0 -839
- package/Sources/RunicCore/Providers/Groq/GroqProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/Groq/GroqUsageFetcher.swift +0 -71
- package/Sources/RunicCore/Providers/Kimi/KimiProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/Kimi/KimiUsageFetcher.swift +0 -77
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift +0 -97
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxSettingsReader.swift +0 -54
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxUsageFetcher.swift +0 -168
- package/Sources/RunicCore/Providers/MiniMax/MiniMaxWebUsageFetcher.swift +0 -911
- package/Sources/RunicCore/Providers/Mistral/MistralProviderDescriptor.swift +0 -84
- package/Sources/RunicCore/Providers/Mistral/MistralUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift +0 -87
- package/Sources/RunicCore/Providers/OpenRouter/OpenRouterUsageFetcher.swift +0 -216
- package/Sources/RunicCore/Providers/Perplexity/PerplexityProviderDescriptor.swift +0 -84
- package/Sources/RunicCore/Providers/Perplexity/PerplexityUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/ProviderBranding.swift +0 -25
- package/Sources/RunicCore/Providers/ProviderCLIConfig.swift +0 -17
- package/Sources/RunicCore/Providers/ProviderDescriptor.swift +0 -129
- package/Sources/RunicCore/Providers/ProviderFetchPlan.swift +0 -263
- package/Sources/RunicCore/Providers/ProviderSettingsSnapshot.swift +0 -98
- package/Sources/RunicCore/Providers/ProviderTokenResolver.swift +0 -501
- package/Sources/RunicCore/Providers/ProviderVersionDetector.swift +0 -68
- package/Sources/RunicCore/Providers/Providers.swift +0 -184
- package/Sources/RunicCore/Providers/Qwen/QwenProviderDescriptor.swift +0 -86
- package/Sources/RunicCore/Providers/Qwen/QwenSettingsReader.swift +0 -30
- package/Sources/RunicCore/Providers/Qwen/QwenUsageStats.swift +0 -328
- package/Sources/RunicCore/Providers/SambaNova/SambaNovaProviderDescriptor.swift +0 -84
- package/Sources/RunicCore/Providers/SambaNova/SambaNovaUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/Together/TogetherProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/Together/TogetherUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/VertexAI/VertexAIProviderDescriptor.swift +0 -123
- package/Sources/RunicCore/Providers/VertexAI/VertexAISettingsReader.swift +0 -48
- package/Sources/RunicCore/Providers/VertexAI/VertexAIUsageFetcher.swift +0 -144
- package/Sources/RunicCore/Providers/XAI/XAIProviderDescriptor.swift +0 -83
- package/Sources/RunicCore/Providers/XAI/XAIUsageFetcher.swift +0 -75
- package/Sources/RunicCore/Providers/Zai/ZaiProviderDescriptor.swift +0 -74
- package/Sources/RunicCore/Providers/Zai/ZaiSettingsReader.swift +0 -41
- package/Sources/RunicCore/Providers/Zai/ZaiUsageStats.swift +0 -745
- package/Sources/RunicCore/Sync/BackgroundSyncManager.swift +0 -384
- package/Sources/RunicCore/Sync/SyncConflictResolver.swift +0 -307
- package/Sources/RunicCore/Sync/SyncProtocol.swift +0 -287
- package/Sources/RunicCore/Sync/SyncRecord.swift +0 -402
- package/Sources/RunicCore/Sync/SyncUsageExample.swift +0 -288
- package/Sources/RunicCore/Sync/TeamSyncRecords.swift +0 -768
- package/Sources/RunicCore/Sync/iCloudSyncEngine.swift +0 -338
- package/Sources/RunicCore/Team/TeamModels.swift +0 -584
- package/Sources/RunicCore/Team/TeamShowbackExporter.swift +0 -495
- package/Sources/RunicCore/Team/TeamStore.swift +0 -809
- package/Sources/RunicCore/TextParsing.swift +0 -55
- package/Sources/RunicCore/UsageFetcher.swift +0 -694
- package/Sources/RunicCore/UsageFormatter.swift +0 -410
- package/Sources/RunicCore/UsageLedger/ClaudeUsageLogSource.swift +0 -441
- package/Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift +0 -502
- package/Sources/RunicCore/UsageLedger/LedgerCache.swift +0 -161
- package/Sources/RunicCore/UsageLedger/OTelGenAILedgerAdapter.swift +0 -550
- package/Sources/RunicCore/UsageLedger/UsageLedger.swift +0 -29
- package/Sources/RunicCore/UsageLedger/UsageLedgerAggregator.swift +0 -675
- package/Sources/RunicCore/UsageLedger/UsageLedgerInsightsAdvisor.swift +0 -209
- package/Sources/RunicCore/UsageLedger/UsageLedgerModels.swift +0 -417
- package/Sources/RunicCore/UsageLedger/UsageLedgerProjectIdentity.swift +0 -284
- package/Sources/RunicCore/UsagePace.swift +0 -81
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageCache.swift +0 -73
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageJsonl.swift +0 -74
- package/Sources/RunicCore/Vendored/CostUsage/CostUsagePricing.swift +0 -208
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Claude.swift +0 -455
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Timestamp.swift +0 -132
- package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner.swift +0 -589
- package/Sources/RunicCore/WidgetSnapshot.swift +0 -183
- package/Sources/RunicMacroSupport/ProviderRegistrationMacros.swift +0 -14
- package/Sources/RunicMacros/ProviderRegistrationMacros.swift +0 -216
- package/Sources/RunicWidget/RunicWidgetBundle.swift +0 -79
- package/Sources/RunicWidget/RunicWidgetProvider.swift +0 -283
- package/Sources/RunicWidget/RunicWidgetViews.swift +0 -680
- package/Tests/RunicTests/AntigravityStatusProbeTests.swift +0 -50
- package/Tests/RunicTests/AppDelegateTests.swift +0 -48
- package/Tests/RunicTests/BrowserCookieOrderLabelTests.swift +0 -21
- package/Tests/RunicTests/CLIArgumentParsingTests.swift +0 -69
- package/Tests/RunicTests/CLICostTests.swift +0 -64
- package/Tests/RunicTests/CLIProviderSelectionTests.swift +0 -21
- package/Tests/RunicTests/CLISnapshotTests.swift +0 -71
- package/Tests/RunicTests/CLIWebFallbackTests.swift +0 -57
- package/Tests/RunicTests/ClaudeOAuthTests.swift +0 -163
- package/Tests/RunicTests/ClaudeResilienceTests.swift +0 -29
- package/Tests/RunicTests/ClaudeUsageTests.swift +0 -369
- package/Tests/RunicTests/CodexOAuthTests.swift +0 -121
- package/Tests/RunicTests/CodexUsageLogSourceTests.swift +0 -80
- package/Tests/RunicTests/CopilotTokenResolverTests.swift +0 -74
- package/Tests/RunicTests/CopilotVSCodeTokenReaderTests.swift +0 -74
- package/Tests/RunicTests/CostUsageDecodingTests.swift +0 -392
- package/Tests/RunicTests/CostUsagePricingTests.swift +0 -48
- package/Tests/RunicTests/CostUsageScannerTests.swift +0 -698
- package/Tests/RunicTests/CursorStatusProbeTests.swift +0 -322
- package/Tests/RunicTests/FactoryStatusProbeTests.swift +0 -67
- package/Tests/RunicTests/GeminiAPITestHelpers.swift +0 -94
- package/Tests/RunicTests/GeminiLoginAlertTests.swift +0 -27
- package/Tests/RunicTests/GeminiStatusProbeAPITests.swift +0 -283
- package/Tests/RunicTests/GeminiStatusProbePlanTests.swift +0 -279
- package/Tests/RunicTests/GeminiStatusProbeTests.swift +0 -232
- package/Tests/RunicTests/GeminiTestEnvironment.swift +0 -87
- package/Tests/RunicTests/GoogleWorkspaceStatusTests.swift +0 -72
- package/Tests/RunicTests/InstallOriginTests.swift +0 -17
- package/Tests/RunicTests/KeyboardShortcutsBundleTests.swift +0 -9
- package/Tests/RunicTests/LiveAccountTests.swift +0 -24
- package/Tests/RunicTests/LoadingPatternTests.swift +0 -34
- package/Tests/RunicTests/MenuCardModelTests.swift +0 -544
- package/Tests/RunicTests/MiniMaxCookieHeaderStoreTestSupport.swift +0 -11
- package/Tests/RunicTests/MiniMaxGroupIDStoreTestSupport.swift +0 -11
- package/Tests/RunicTests/MiniMaxParsingTests.swift +0 -67
- package/Tests/RunicTests/MiniMaxTokenStoreTestSupport.swift +0 -11
- package/Tests/RunicTests/OTelGenAILedgerAdapterTests.swift +0 -110
- package/Tests/RunicTests/OpenAIDashboardBrowserCookieImporterTests.swift +0 -16
- package/Tests/RunicTests/OpenAIDashboardFetcherCreditsWaitTests.swift +0 -74
- package/Tests/RunicTests/OpenAIDashboardOffscreenHostTests.swift +0 -26
- package/Tests/RunicTests/OpenAIDashboardParserTests.swift +0 -133
- package/Tests/RunicTests/OpenAIWebAccountSwitchTests.swift +0 -64
- package/Tests/RunicTests/OpenRouterTokenStoreTestSupport.swift +0 -131
- package/Tests/RunicTests/PathBuilderTests.swift +0 -236
- package/Tests/RunicTests/ProviderFetchPipelineTests.swift +0 -159
- package/Tests/RunicTests/ProviderIconResourcesTests.swift +0 -37
- package/Tests/RunicTests/ProviderMetadataStatusLinkTests.swift +0 -15
- package/Tests/RunicTests/ProviderRegistryTests.swift +0 -29
- package/Tests/RunicTests/ProviderSettingsDescriptorTests.swift +0 -236
- package/Tests/RunicTests/ProviderToggleStoreTests.swift +0 -50
- package/Tests/RunicTests/RunicTests.swift +0 -119
- package/Tests/RunicTests/SessionQuotaNotificationLogicTests.swift +0 -35
- package/Tests/RunicTests/SettingsStoreTests.swift +0 -265
- package/Tests/RunicTests/StatusItemAnimationTests.swift +0 -54
- package/Tests/RunicTests/StatusMenuTests.swift +0 -475
- package/Tests/RunicTests/StatusProbeTests.swift +0 -376
- package/Tests/RunicTests/SubprocessRunnerTests.swift +0 -18
- package/Tests/RunicTests/SubscriptionDetectionTests.swift +0 -64
- package/Tests/RunicTests/TTYCommandRunnerTests.swift +0 -147
- package/Tests/RunicTests/TTYIntegrationTests.swift +0 -41
- package/Tests/RunicTests/TeamShowbackExporterTests.swift +0 -157
- package/Tests/RunicTests/TextParsingTests.swift +0 -11
- package/Tests/RunicTests/UsageFormatterTests.swift +0 -111
- package/Tests/RunicTests/UsageLedgerAnomalyDetectionTests.swift +0 -170
- package/Tests/RunicTests/UsageLedgerForecastTests.swift +0 -211
- package/Tests/RunicTests/UsageLedgerInsightsAdvisorTests.swift +0 -81
- package/Tests/RunicTests/UsageLedgerProjectNameTests.swift +0 -168
- package/Tests/RunicTests/UsagePaceTests.swift +0 -76
- package/Tests/RunicTests/UsagePaceTextTests.swift +0 -108
- package/Tests/RunicTests/UsagePolicyEngineTests.swift +0 -89
- package/Tests/RunicTests/WidgetSnapshotTests.swift +0 -43
- package/Tests/RunicTests/ZaiProviderTests.swift +0 -59
- package/Tests/RunicTests/ZaiTokenStoreTestSupport.swift +0 -9
- package/TestsLinux/PlatformGatingTests.swift +0 -46
- package/appcast.xml +0 -104
- package/assets/logo-concept-stack.svg +0 -24
- package/assets/logo-minimal-bars.svg +0 -15
- package/assets/logo.svg +0 -20
- package/assets/logo2.svg +0 -43
- package/bin/docs-list +0 -5
- package/build-and-run.sh +0 -369
- package/docs/.nojekyll +0 -1
- package/docs/CNAME +0 -1
- package/docs/antigravity.md +0 -75
- package/docs/architecture.md +0 -32
- package/docs/claude.md +0 -93
- package/docs/cli-commands/integration_guide.md +0 -371
- package/docs/cli-commands/quick_reference.md +0 -362
- package/docs/cli-commands/readme.md +0 -361
- package/docs/cli.md +0 -156
- package/docs/cloudkit_sync_guide.md +0 -495
- package/docs/codebase_review.md +0 -288
- package/docs/codex-oauth.md +0 -635
- package/docs/codex.md +0 -104
- package/docs/codexbar.png +0 -0
- package/docs/copilot.md +0 -44
- package/docs/cursor.md +0 -46
- package/docs/design/designcomparisonchart.md +0 -510
- package/docs/design/implementationguide.md +0 -792
- package/docs/design/menubaricondesignconcepts.md +0 -796
- package/docs/design/mockups/hybridiconconcept.svg +0 -62
- package/docs/design/mockups/infinityiconconcept.svg +0 -41
- package/docs/design/mockups/infinityiconstates.svg +0 -129
- package/docs/design/mockups/wavelogorefined.svg +0 -48
- package/docs/design/quick_summary.md +0 -426
- package/docs/design/readme.md +0 -478
- package/docs/design/sizespecifications.md +0 -575
- package/docs/design-system.md +0 -836
- package/docs/factory.md +0 -103
- package/docs/gemini.md +0 -73
- package/docs/icon.md +0 -37
- package/docs/icon.png +0 -0
- package/docs/index.html +0 -175
- package/docs/keychain_fix.md +0 -274
- package/docs/minimax.md +0 -71
- package/docs/packaging.md +0 -25
- package/docs/progress-bar-improvements.md +0 -240
- package/docs/progress-bar-quick-reference.md +0 -283
- package/docs/progress-bar-technical-details.md +0 -432
- package/docs/progress-bar-visual-test.swift +0 -375
- package/docs/provider.md +0 -202
- package/docs/providers.md +0 -86
- package/docs/refactor/macros.md +0 -35
- package/docs/refresh-loop.md +0 -22
- package/docs/releasing-homebrew.md +0 -35
- package/docs/releasing.md +0 -121
- package/docs/research/concrete_todo_2026-02-22.md +0 -47
- package/docs/research/core-feature-research.md +0 -248
- package/docs/research/feature_uiux_roadmap_2026-02-22.md +0 -202
- package/docs/research/parity_matrix.md +0 -49
- package/docs/research/provider_expansion_candidates_2026-02-22.md +0 -80
- package/docs/research/provider_model_token_project_matrix_2026-02-23.md +0 -46
- package/docs/research/release_gate_checklist.md +0 -57
- package/docs/site.css +0 -505
- package/docs/sparkle.md +0 -28
- package/docs/status.md +0 -28
- package/docs/sync/implementation.md +0 -393
- package/docs/sync/readme.md +0 -317
- package/docs/sync_files_summary.md +0 -391
- package/docs/sync_quick_reference.md +0 -225
- package/docs/todo.md +0 -11
- package/docs/ui.md +0 -29
- package/docs/web-integration.md +0 -9
- package/docs/widgets.md +0 -85
- package/docs/workflows/error-handling-improvements.md +0 -434
- package/docs/workflows/folder_structure.md +0 -299
- package/docs/workflows/loading_states.md +0 -446
- package/docs/workflows/loading_states_examples.md +0 -565
- package/docs/workflows/loading_states_flow.md +0 -430
- package/docs/workflows/performance_optimizations.md +0 -457
- package/docs/workflows/phase1-cli-testing-report.md +0 -313
- package/docs/workflows/quick_reference.md +0 -228
- package/docs/workflows/readme.md +0 -59
- package/docs/workflows/recent_improvements.md +0 -275
- package/docs/workflows/sync_enablement_summary.md +0 -400
- package/docs/zai.md +0 -43
- package/runic.png +0 -0
- package/runic.svg +0 -15
- package/version.env +0 -2
|
@@ -1,792 +0,0 @@
|
|
|
1
|
-
# Runic Menubar Icon - Implementation Guide
|
|
2
|
-
|
|
3
|
-
**Target:** IconRenderer.swift
|
|
4
|
-
**Current File:** `/Users/srinivaspendela/Sriinnu/AI/Runic/Sources/Runic/Core/Rendering/IconRenderer.swift`
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
This guide provides step-by-step instructions for implementing the recommended **Infinity Symbol + Provider Icon** design in the existing IconRenderer architecture.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Current Architecture Analysis
|
|
15
|
-
|
|
16
|
-
### Existing Components
|
|
17
|
-
|
|
18
|
-
**IconRenderer.swift Key Elements:**
|
|
19
|
-
|
|
20
|
-
1. **Output Specifications (Lines 51-56):**
|
|
21
|
-
```swift
|
|
22
|
-
private static let baseSize = NSSize(width: 38, height: 22)
|
|
23
|
-
private static let outputSize = NSSize(width: 38, height: 22)
|
|
24
|
-
private static let outputScale: CGFloat = 2
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
2. **Wave Logo Template (Lines 57-64):**
|
|
28
|
-
```swift
|
|
29
|
-
private static let waveLogoTemplate: NSImage? = {
|
|
30
|
-
guard let url = Bundle.main.url(forResource: "RunicMenubarIcon", withExtension: "svg"),
|
|
31
|
-
let image = NSImage(contentsOf: url) else {
|
|
32
|
-
return nil
|
|
33
|
-
}
|
|
34
|
-
return image
|
|
35
|
-
}()
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
3. **Icon Cache System (Lines 84-143):**
|
|
39
|
-
- `IconCacheKey` struct with hashable properties
|
|
40
|
-
- `IconCacheStore` class with LRU eviction
|
|
41
|
-
- Cache limit: `PerformanceConstants.iconCacheSize`
|
|
42
|
-
|
|
43
|
-
4. **Main Rendering Function (Lines 177-247):**
|
|
44
|
-
- `makeIcon()` - Entry point for icon generation
|
|
45
|
-
- Supports pressure colors, stale states, animations
|
|
46
|
-
- Returns cached icons when possible
|
|
47
|
-
|
|
48
|
-
5. **Drawing Functions:**
|
|
49
|
-
- `drawWaveLogo()` (Lines 516-546) - Current wave rendering
|
|
50
|
-
- `drawStatusOverlay()` (Lines 781-813) - Error/status indicators
|
|
51
|
-
- `drawUnbraidMorph()` (Lines 668-755) - Animation morphs
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## Implementation Plan
|
|
56
|
-
|
|
57
|
-
### Phase 1: Add Infinity Symbol SVG Resource
|
|
58
|
-
|
|
59
|
-
**Step 1.1: Create Infinity Icon SVG**
|
|
60
|
-
|
|
61
|
-
Create: `/Users/srinivaspendela/Sriinnu/AI/Runic/Sources/Runic/Resources/RunicMenubarIconInfinity.svg`
|
|
62
|
-
|
|
63
|
-
```xml
|
|
64
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 48" fill="none">
|
|
65
|
-
<!-- Infinity path optimized for template rendering -->
|
|
66
|
-
<path d="M 12,24
|
|
67
|
-
C 12,14 20,10 28,14
|
|
68
|
-
C 36,18 36,24 40,24
|
|
69
|
-
C 44,24 44,18 52,14
|
|
70
|
-
C 60,10 68,14 68,24
|
|
71
|
-
C 68,34 60,38 52,34
|
|
72
|
-
C 44,30 44,24 40,24
|
|
73
|
-
C 36,24 36,30 28,34
|
|
74
|
-
C 20,38 12,34 12,24 Z"
|
|
75
|
-
stroke="#14B8A6"
|
|
76
|
-
stroke-width="8"
|
|
77
|
-
fill="none"
|
|
78
|
-
stroke-linecap="round"
|
|
79
|
-
stroke-linejoin="round"/>
|
|
80
|
-
</svg>
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
**Step 1.2: Update Bundle Resources**
|
|
84
|
-
|
|
85
|
-
Ensure SVG is included in `Package.swift` or Xcode target resources.
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
### Phase 2: Modify IconRenderer.swift
|
|
90
|
-
|
|
91
|
-
**Step 2.1: Add Infinity Logo Template**
|
|
92
|
-
|
|
93
|
-
Add after line 64 (after `waveLogoTemplate`):
|
|
94
|
-
|
|
95
|
-
```swift
|
|
96
|
-
// Infinity logo base template - loaded lazily from Resources
|
|
97
|
-
private static let infinityLogoTemplate: NSImage? = {
|
|
98
|
-
guard let url = Bundle.main.url(forResource: "RunicMenubarIconInfinity", withExtension: "svg"),
|
|
99
|
-
let image = NSImage(contentsOf: url) else {
|
|
100
|
-
return nil
|
|
101
|
-
}
|
|
102
|
-
return image
|
|
103
|
-
}()
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**Step 2.2: Update Output Size (Optional)**
|
|
107
|
-
|
|
108
|
-
Increase size from 38×22 to 40×24 for better clarity (line 51-52):
|
|
109
|
-
|
|
110
|
-
```swift
|
|
111
|
-
private static let baseSize = NSSize(width: 40, height: 24)
|
|
112
|
-
private static let outputSize = NSSize(width: 40, height: 24)
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Step 2.3: Add Icon Style Enum**
|
|
116
|
-
|
|
117
|
-
Add new enum to control which icon design to use:
|
|
118
|
-
|
|
119
|
-
```swift
|
|
120
|
-
enum IconDesign: Sendable {
|
|
121
|
-
case wave // Current wave logo
|
|
122
|
-
case infinity // Infinity symbol with provider icon
|
|
123
|
-
case hybrid // Infinity outline with center bar
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Step 2.4: Update makeIcon() Signature**
|
|
128
|
-
|
|
129
|
-
Modify `makeIcon()` function (line 177) to accept design parameter:
|
|
130
|
-
|
|
131
|
-
```swift
|
|
132
|
-
static func makeIcon(
|
|
133
|
-
primaryRemaining: Double?,
|
|
134
|
-
weeklyRemaining: Double?,
|
|
135
|
-
creditsRemaining: Double?,
|
|
136
|
-
stale: Bool,
|
|
137
|
-
style: IconStyle,
|
|
138
|
-
design: IconDesign = .infinity, // NEW PARAMETER
|
|
139
|
-
blink: CGFloat = 0,
|
|
140
|
-
wiggle: CGFloat = 0,
|
|
141
|
-
tilt: CGFloat = 0,
|
|
142
|
-
statusIndicator: ProviderStatusIndicator = .none,
|
|
143
|
-
appearance: IconAppearance = .template,
|
|
144
|
-
dataMode: IconDataMode = .remaining) -> NSImage
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
**Step 2.5: Add Design Routing Logic**
|
|
148
|
-
|
|
149
|
-
Inside `makeIcon()`, route to appropriate drawing function:
|
|
150
|
-
|
|
151
|
-
```swift
|
|
152
|
-
let render = {
|
|
153
|
-
self.renderImage(isTemplate: appearance == .template) {
|
|
154
|
-
let topValue = primaryRemaining
|
|
155
|
-
let bottomValue = weeklyRemaining
|
|
156
|
-
let creditsRatio = creditsRemaining.map { min($0 / Self.creditsCap * 100, 100) }
|
|
157
|
-
let pressure = Self.usagePressure(
|
|
158
|
-
primary: topValue,
|
|
159
|
-
weekly: bottomValue,
|
|
160
|
-
credits: creditsRatio,
|
|
161
|
-
dataMode: dataMode)
|
|
162
|
-
let accentColor = Self.vibrantAccentColor(pressure: pressure, stale: stale)
|
|
163
|
-
let baseColor = appearance == .template ? NSColor.labelColor : accentColor
|
|
164
|
-
|
|
165
|
-
// NEW: Route based on design type
|
|
166
|
-
switch design {
|
|
167
|
-
case .wave:
|
|
168
|
-
let fillPercent = Self.iconFillPercent(
|
|
169
|
-
primary: topValue,
|
|
170
|
-
weekly: bottomValue,
|
|
171
|
-
credits: creditsRatio,
|
|
172
|
-
dataMode: dataMode)
|
|
173
|
-
Self.drawWaveLogo(
|
|
174
|
-
fillPercent: fillPercent,
|
|
175
|
-
baseColor: baseColor.withAlphaComponent(stale ? 0.18 : 0.28),
|
|
176
|
-
fillColor: baseColor.withAlphaComponent(stale ? 0.55 : 1.0))
|
|
177
|
-
|
|
178
|
-
case .infinity:
|
|
179
|
-
Self.drawInfinityLogo(
|
|
180
|
-
providerStyle: Self.sigilStyle(for: style),
|
|
181
|
-
pressure: pressure,
|
|
182
|
-
stale: stale,
|
|
183
|
-
baseColor: baseColor,
|
|
184
|
-
appearance: appearance)
|
|
185
|
-
|
|
186
|
-
case .hybrid:
|
|
187
|
-
let fillPercent = Self.iconFillPercent(
|
|
188
|
-
primary: topValue,
|
|
189
|
-
weekly: bottomValue,
|
|
190
|
-
credits: creditsRatio,
|
|
191
|
-
dataMode: dataMode)
|
|
192
|
-
Self.drawHybridLogo(
|
|
193
|
-
providerStyle: Self.sigilStyle(for: style),
|
|
194
|
-
fillPercent: fillPercent,
|
|
195
|
-
pressure: pressure,
|
|
196
|
-
stale: stale,
|
|
197
|
-
baseColor: baseColor,
|
|
198
|
-
appearance: appearance)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Status overlay remains the same
|
|
202
|
-
let overlayColor = appearance == .template
|
|
203
|
-
? NSColor.labelColor
|
|
204
|
-
: NSColor.white.withAlphaComponent(0.92)
|
|
205
|
-
Self.drawStatusOverlay(indicator: statusIndicator, color: overlayColor)
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
### Phase 3: Implement Drawing Functions
|
|
213
|
-
|
|
214
|
-
**Step 3.1: Create drawInfinityLogo() Function**
|
|
215
|
-
|
|
216
|
-
Add new function after `drawWaveLogo()`:
|
|
217
|
-
|
|
218
|
-
```swift
|
|
219
|
-
/// Draws infinity symbol with provider icon in center
|
|
220
|
-
private static func drawInfinityLogo(
|
|
221
|
-
providerStyle: SigilStyle,
|
|
222
|
-
pressure: Double,
|
|
223
|
-
stale: Bool,
|
|
224
|
-
baseColor: NSColor,
|
|
225
|
-
appearance: IconAppearance)
|
|
226
|
-
{
|
|
227
|
-
guard let infinityLogo = self.infinityLogoTemplate,
|
|
228
|
-
let ctx = NSGraphicsContext.current?.cgContext else {
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
let rect = CGRect(origin: .zero, size: self.outputSize)
|
|
233
|
-
let opacity: CGFloat = stale ? 0.55 : 1.0
|
|
234
|
-
|
|
235
|
-
// Draw infinity path
|
|
236
|
-
ctx.saveGState()
|
|
237
|
-
infinityLogo.draw(in: rect, from: .zero, operation: .sourceOver, fraction: 1.0)
|
|
238
|
-
ctx.setBlendMode(.sourceIn)
|
|
239
|
-
baseColor.setFill()
|
|
240
|
-
ctx.fill(rect)
|
|
241
|
-
ctx.restoreGState()
|
|
242
|
-
|
|
243
|
-
// Draw provider icon in center gap
|
|
244
|
-
let centerX = rect.midX
|
|
245
|
-
let centerY = rect.midY
|
|
246
|
-
let iconSize: CGFloat = 16 // 8pt @ 2x scale
|
|
247
|
-
let iconRect = RectPx(
|
|
248
|
-
x: Int((centerX - iconSize / 2) * outputScale),
|
|
249
|
-
y: Int((centerY - iconSize / 2) * outputScale),
|
|
250
|
-
w: Int(iconSize * outputScale),
|
|
251
|
-
h: Int(iconSize * outputScale))
|
|
252
|
-
|
|
253
|
-
// Create white background circle for icon visibility
|
|
254
|
-
let bgCircleRadius: CGFloat = 10
|
|
255
|
-
let bgCircle = NSBezierPath(
|
|
256
|
-
ovalIn: CGRect(
|
|
257
|
-
x: centerX - bgCircleRadius,
|
|
258
|
-
y: centerY - bgCircleRadius,
|
|
259
|
-
width: bgCircleRadius * 2,
|
|
260
|
-
height: bgCircleRadius * 2))
|
|
261
|
-
NSColor.white.withAlphaComponent(appearance == .template ? 0.0 : 0.9).setFill()
|
|
262
|
-
bgCircle.fill()
|
|
263
|
-
|
|
264
|
-
// Draw provider sigil
|
|
265
|
-
ctx.saveGState()
|
|
266
|
-
ctx.setBlendMode(appearance == .template ? .clear : .normal)
|
|
267
|
-
self.drawSigil(providerStyle, in: iconRect)
|
|
268
|
-
ctx.restoreGState()
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
**Step 3.2: Create drawHybridLogo() Function**
|
|
273
|
-
|
|
274
|
-
Add hybrid variant combining infinity outline with center bar:
|
|
275
|
-
|
|
276
|
-
```swift
|
|
277
|
-
/// Draws infinity outline with usage bar in center and provider badge
|
|
278
|
-
private static func drawHybridLogo(
|
|
279
|
-
providerStyle: SigilStyle,
|
|
280
|
-
fillPercent: Double,
|
|
281
|
-
pressure: Double,
|
|
282
|
-
stale: Bool,
|
|
283
|
-
baseColor: NSColor,
|
|
284
|
-
appearance: IconAppearance)
|
|
285
|
-
{
|
|
286
|
-
guard let infinityLogo = self.infinityLogoTemplate,
|
|
287
|
-
let ctx = NSGraphicsContext.current?.cgContext else {
|
|
288
|
-
return
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
let rect = CGRect(origin: .zero, size: self.outputSize)
|
|
292
|
-
let opacity: CGFloat = stale ? 0.55 : 1.0
|
|
293
|
-
|
|
294
|
-
// Draw infinity outline (lighter opacity)
|
|
295
|
-
ctx.saveGState()
|
|
296
|
-
infinityLogo.draw(in: rect, from: .zero, operation: .sourceOver, fraction: 1.0)
|
|
297
|
-
ctx.setBlendMode(.sourceIn)
|
|
298
|
-
baseColor.withAlphaComponent(0.3 * opacity).setFill()
|
|
299
|
-
ctx.fill(rect)
|
|
300
|
-
ctx.restoreGState()
|
|
301
|
-
|
|
302
|
-
// Draw center usage bar
|
|
303
|
-
let centerX = rect.midX
|
|
304
|
-
let centerY = rect.midY
|
|
305
|
-
let barWidth: CGFloat = 16
|
|
306
|
-
let barHeight: CGFloat = 16
|
|
307
|
-
let barX = centerX - barWidth / 2
|
|
308
|
-
let barY = centerY - barHeight / 2
|
|
309
|
-
|
|
310
|
-
// Bar background
|
|
311
|
-
let barBgPath = NSBezierPath(
|
|
312
|
-
roundedRect: CGRect(x: barX, y: barY, width: barWidth, height: barHeight),
|
|
313
|
-
xRadius: 3,
|
|
314
|
-
yRadius: 3)
|
|
315
|
-
baseColor.withAlphaComponent(0.15 * opacity).setFill()
|
|
316
|
-
barBgPath.fill()
|
|
317
|
-
|
|
318
|
-
// Bar fill (from bottom)
|
|
319
|
-
let fillHeight = barHeight * CGFloat(max(0, min(fillPercent, 1)))
|
|
320
|
-
let barFillPath = NSBezierPath(
|
|
321
|
-
roundedRect: CGRect(x: barX, y: barY + barHeight - fillHeight, width: barWidth, height: fillHeight),
|
|
322
|
-
xRadius: 3,
|
|
323
|
-
yRadius: 3)
|
|
324
|
-
baseColor.withAlphaComponent(opacity).setFill()
|
|
325
|
-
barFillPath.fill()
|
|
326
|
-
|
|
327
|
-
// Draw provider badge in corner
|
|
328
|
-
let badgeX: CGFloat = rect.maxX - 14
|
|
329
|
-
let badgeY: CGFloat = 8
|
|
330
|
-
let badgeRadius: CGFloat = 6
|
|
331
|
-
|
|
332
|
-
let badgeBg = NSBezierPath(
|
|
333
|
-
ovalIn: CGRect(x: badgeX, y: badgeY, width: badgeRadius * 2, height: badgeRadius * 2))
|
|
334
|
-
NSColor.white.withAlphaComponent(appearance == .template ? 0.0 : 0.9).setFill()
|
|
335
|
-
badgeBg.fill()
|
|
336
|
-
|
|
337
|
-
let badgeStroke = NSBezierPath(
|
|
338
|
-
ovalIn: CGRect(x: badgeX, y: badgeY, width: badgeRadius * 2, height: badgeRadius * 2))
|
|
339
|
-
badgeStroke.lineWidth = 1.5
|
|
340
|
-
baseColor.withAlphaComponent(opacity).setStroke()
|
|
341
|
-
badgeStroke.stroke()
|
|
342
|
-
|
|
343
|
-
// Draw mini provider sigil in badge
|
|
344
|
-
let badgeIconRect = RectPx(
|
|
345
|
-
x: Int((badgeX + badgeRadius - 2) * outputScale),
|
|
346
|
-
y: Int((badgeY + badgeRadius - 2) * outputScale),
|
|
347
|
-
w: Int(4 * outputScale),
|
|
348
|
-
h: Int(4 * outputScale))
|
|
349
|
-
ctx.saveGState()
|
|
350
|
-
ctx.setBlendMode(appearance == .template ? .clear : .normal)
|
|
351
|
-
self.drawSigil(providerStyle, in: badgeIconRect)
|
|
352
|
-
ctx.restoreGState()
|
|
353
|
-
}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
### Phase 4: Update Cache Key
|
|
359
|
-
|
|
360
|
-
**Step 4.1: Add Design to IconCacheKey**
|
|
361
|
-
|
|
362
|
-
Modify `IconCacheKey` struct (line 84) to include design:
|
|
363
|
-
|
|
364
|
-
```swift
|
|
365
|
-
private struct IconCacheKey: Hashable {
|
|
366
|
-
let primary: Int
|
|
367
|
-
let weekly: Int
|
|
368
|
-
let credits: Int
|
|
369
|
-
let stale: Bool
|
|
370
|
-
let style: Int
|
|
371
|
-
let indicator: Int
|
|
372
|
-
let appearance: Int
|
|
373
|
-
let dataMode: Int
|
|
374
|
-
let design: Int // NEW
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
**Step 4.2: Add Design Key Helper**
|
|
379
|
-
|
|
380
|
-
Add helper function after other key helpers:
|
|
381
|
-
|
|
382
|
-
```swift
|
|
383
|
-
private static func designKey(_ design: IconDesign) -> Int {
|
|
384
|
-
switch design {
|
|
385
|
-
case .wave: 0
|
|
386
|
-
case .infinity: 1
|
|
387
|
-
case .hybrid: 2
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
**Step 4.3: Update Cache Key Creation**
|
|
393
|
-
|
|
394
|
-
Modify cache key creation in `makeIcon()`:
|
|
395
|
-
|
|
396
|
-
```swift
|
|
397
|
-
let key = IconCacheKey(
|
|
398
|
-
primary: self.quantizedPercent(primaryRemaining),
|
|
399
|
-
weekly: self.quantizedPercent(weeklyRemaining),
|
|
400
|
-
credits: self.quantizedCredits(creditsRemaining),
|
|
401
|
-
stale: stale,
|
|
402
|
-
style: self.styleKey(style),
|
|
403
|
-
indicator: self.indicatorKey(statusIndicator),
|
|
404
|
-
appearance: self.appearanceKey(appearance),
|
|
405
|
-
dataMode: self.dataModeKey(dataMode),
|
|
406
|
-
design: self.designKey(design)) // NEW
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
### Phase 5: Integrate with Settings
|
|
412
|
-
|
|
413
|
-
**Step 5.1: Add User Preference in SettingsStore**
|
|
414
|
-
|
|
415
|
-
Add to `SettingsStore.swift`:
|
|
416
|
-
|
|
417
|
-
```swift
|
|
418
|
-
@AppStorage("iconDesign") var iconDesign: IconDesign = .infinity
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
**Step 5.2: Add Preference UI**
|
|
422
|
-
|
|
423
|
-
In preferences pane (e.g., `PreferencesGeneralPane.swift`), add picker:
|
|
424
|
-
|
|
425
|
-
```swift
|
|
426
|
-
Picker("Menubar Icon Style", selection: $settings.iconDesign) {
|
|
427
|
-
Text("Infinity Symbol").tag(IconDesign.infinity)
|
|
428
|
-
Text("Wave Logo (Classic)").tag(IconDesign.wave)
|
|
429
|
-
Text("Hybrid").tag(IconDesign.hybrid)
|
|
430
|
-
}
|
|
431
|
-
.pickerStyle(.segmented)
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**Step 5.3: Pass Design to makeIcon()**
|
|
435
|
-
|
|
436
|
-
Update all calls to `makeIcon()` to use user preference:
|
|
437
|
-
|
|
438
|
-
```swift
|
|
439
|
-
let icon = IconRenderer.makeIcon(
|
|
440
|
-
primaryRemaining: snap.sessionRemaining,
|
|
441
|
-
weeklyRemaining: snap.weeklyRemaining,
|
|
442
|
-
creditsRemaining: snap.creditsRemaining,
|
|
443
|
-
stale: isStale,
|
|
444
|
-
style: iconStyle,
|
|
445
|
-
design: settings.iconDesign, // NEW
|
|
446
|
-
statusIndicator: statusIndicator,
|
|
447
|
-
appearance: settings.iconAppearance,
|
|
448
|
-
dataMode: settings.iconDataMode)
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
---
|
|
452
|
-
|
|
453
|
-
## Testing Plan
|
|
454
|
-
|
|
455
|
-
### Visual Testing
|
|
456
|
-
|
|
457
|
-
**Test Matrix:**
|
|
458
|
-
|
|
459
|
-
| Size | Design | Provider | Pressure | Stale | Template | Expected |
|
|
460
|
-
|------|--------|----------|----------|-------|----------|----------|
|
|
461
|
-
| 40×24pt | Infinity | Claude | 0% | No | Yes | Clear infinity with Claude slits |
|
|
462
|
-
| 40×24pt | Infinity | Codex | 50% | No | Yes | Orange infinity with square eyes |
|
|
463
|
-
| 40×24pt | Infinity | Gemini | 90% | No | Yes | Red infinity with diamond |
|
|
464
|
-
| 40×24pt | Infinity | Claude | 30% | Yes | Yes | Teal infinity at 55% opacity |
|
|
465
|
-
| 40×24pt | Wave | — | 65% | No | Yes | Current wave with bars |
|
|
466
|
-
| 40×24pt | Hybrid | Cursor | 75% | No | Yes | Infinity outline + bar + badge |
|
|
467
|
-
|
|
468
|
-
**Manual Test Steps:**
|
|
469
|
-
|
|
470
|
-
1. **Build and Run:**
|
|
471
|
-
```bash
|
|
472
|
-
swift build -c release
|
|
473
|
-
open .build/release/Runic.app
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
2. **Test Provider Switching:**
|
|
477
|
-
- Enable multiple providers (Claude, Codex, Gemini)
|
|
478
|
-
- Verify icon updates when switching active provider
|
|
479
|
-
- Check provider icon visibility in center
|
|
480
|
-
|
|
481
|
-
3. **Test Pressure Colors:**
|
|
482
|
-
- Simulate different usage levels (0%, 50%, 80%, 100%)
|
|
483
|
-
- Verify color transitions: teal → orange → red
|
|
484
|
-
- Check template mode adapts to system theme
|
|
485
|
-
|
|
486
|
-
4. **Test Display Sizes:**
|
|
487
|
-
- Test on Retina (2×) and non-Retina displays
|
|
488
|
-
- Verify clarity at 18pt, 22pt, 24pt, 28pt
|
|
489
|
-
- Check pixel alignment (no blurry edges)
|
|
490
|
-
|
|
491
|
-
5. **Test Dark Mode:**
|
|
492
|
-
- Switch system appearance light ↔ dark
|
|
493
|
-
- Verify template rendering adapts correctly
|
|
494
|
-
- Check vibrant mode colors remain consistent
|
|
495
|
-
|
|
496
|
-
6. **Test Stale State:**
|
|
497
|
-
- Disconnect network or pause auto-refresh
|
|
498
|
-
- Wait >5 minutes for data to become stale
|
|
499
|
-
- Verify 55% opacity applied correctly
|
|
500
|
-
|
|
501
|
-
### Performance Testing
|
|
502
|
-
|
|
503
|
-
**Cache Efficiency:**
|
|
504
|
-
|
|
505
|
-
```swift
|
|
506
|
-
// Add debug logging to IconCacheStore
|
|
507
|
-
func cachedIcon(for key: IconCacheKey) -> NSImage? {
|
|
508
|
-
self.lock.lock()
|
|
509
|
-
defer { self.lock.unlock() }
|
|
510
|
-
let hit = self.cache[key] != nil
|
|
511
|
-
print("Cache \(hit ? "HIT" : "MISS") for key: \(key)")
|
|
512
|
-
return self.cache[key]
|
|
513
|
-
}
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
**Expected Results:**
|
|
517
|
-
- Cache hit rate >80% during normal operation
|
|
518
|
-
- Cache size stays <100 entries (PerformanceConstants.iconCacheSize = 64)
|
|
519
|
-
- No memory leaks (check with Instruments)
|
|
520
|
-
|
|
521
|
-
**Rendering Speed:**
|
|
522
|
-
|
|
523
|
-
```swift
|
|
524
|
-
// Measure rendering time
|
|
525
|
-
let start = CFAbsoluteTimeGetCurrent()
|
|
526
|
-
let icon = IconRenderer.makeIcon(...)
|
|
527
|
-
let elapsed = CFAbsoluteTimeGetCurrent() - start
|
|
528
|
-
assert(elapsed < 0.016, "Icon rendering exceeded 16ms (60 FPS)")
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
**Expected Results:**
|
|
532
|
-
- First render (cache miss): <10ms
|
|
533
|
-
- Cached render: <0.5ms
|
|
534
|
-
- No dropped frames during animations
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
## Migration Strategy
|
|
539
|
-
|
|
540
|
-
### Rollout Plan
|
|
541
|
-
|
|
542
|
-
**Option 1: Immediate Switch (Recommended)**
|
|
543
|
-
|
|
544
|
-
- Default to `IconDesign.infinity` for all users
|
|
545
|
-
- Keep wave logo available as preference option
|
|
546
|
-
- Announce change in release notes
|
|
547
|
-
|
|
548
|
-
**Option 2: Gradual Rollout**
|
|
549
|
-
|
|
550
|
-
- Default to wave logo for existing users
|
|
551
|
-
- Default to infinity for new installs
|
|
552
|
-
- Encourage switch via in-app notification
|
|
553
|
-
|
|
554
|
-
**Option 3: A/B Testing**
|
|
555
|
-
|
|
556
|
-
- Randomly assign 50% of users to infinity design
|
|
557
|
-
- Track engagement metrics (menu opens, preference changes)
|
|
558
|
-
- Choose winner after 2 weeks
|
|
559
|
-
|
|
560
|
-
### Backward Compatibility
|
|
561
|
-
|
|
562
|
-
Maintain wave logo indefinitely:
|
|
563
|
-
- Keep `drawWaveLogo()` function
|
|
564
|
-
- Keep `RunicMenubarIcon.svg` resource
|
|
565
|
-
- Allow users to switch back in preferences
|
|
566
|
-
|
|
567
|
-
### Release Notes Template
|
|
568
|
-
|
|
569
|
-
```markdown
|
|
570
|
-
## New Menubar Icon Design
|
|
571
|
-
|
|
572
|
-
We've redesigned Runic's menubar icon with a fresh "infinity symbol" concept that:
|
|
573
|
-
|
|
574
|
-
- **Symbolizes continuous monitoring** - The infinity loops represent Runic's eyes watching your AI usage
|
|
575
|
-
- **Shows your active provider** - The icon in the center indicates which AI service you're currently using
|
|
576
|
-
- **Adapts to usage levels** - Color changes from teal (safe) to orange (warning) to red (critical)
|
|
577
|
-
- **Clearer at all sizes** - Simpler design ensures visibility on any display
|
|
578
|
-
|
|
579
|
-
**Prefer the classic wave design?** You can switch back in Preferences → General → Menubar Icon Style.
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
---
|
|
583
|
-
|
|
584
|
-
## Troubleshooting
|
|
585
|
-
|
|
586
|
-
### Common Issues
|
|
587
|
-
|
|
588
|
-
**Issue 1: Provider Icon Not Visible**
|
|
589
|
-
|
|
590
|
-
**Symptom:** Infinity loops render, but center icon is missing
|
|
591
|
-
|
|
592
|
-
**Solution:**
|
|
593
|
-
- Check `drawSigil()` is being called with correct `RectPx`
|
|
594
|
-
- Verify blend mode is set correctly (`.clear` for template, `.normal` for vibrant)
|
|
595
|
-
- Ensure provider style matches available cases in `SigilStyle` enum
|
|
596
|
-
|
|
597
|
-
**Issue 2: Blurry Rendering**
|
|
598
|
-
|
|
599
|
-
**Symptom:** Icon edges appear fuzzy or aliased
|
|
600
|
-
|
|
601
|
-
**Solution:**
|
|
602
|
-
- Verify `outputScale = 2` for Retina displays
|
|
603
|
-
- Check pixel alignment: all coordinates should be integers at 2× scale
|
|
604
|
-
- Use `snap()` function to align to pixel grid
|
|
605
|
-
|
|
606
|
-
**Issue 3: Wrong Colors in Dark Mode**
|
|
607
|
-
|
|
608
|
-
**Symptom:** Icon is too dark or invisible in dark menubar
|
|
609
|
-
|
|
610
|
-
**Solution:**
|
|
611
|
-
- Ensure `isTemplate = true` for template rendering
|
|
612
|
-
- Check `NSColor.labelColor` is used for template mode
|
|
613
|
-
- Verify system appearance detection is working
|
|
614
|
-
|
|
615
|
-
**Issue 4: Cache Growing Too Large**
|
|
616
|
-
|
|
617
|
-
**Symptom:** Memory usage increases over time
|
|
618
|
-
|
|
619
|
-
**Solution:**
|
|
620
|
-
- Check `iconCacheLimit` is set correctly
|
|
621
|
-
- Verify LRU eviction is working in `IconCacheStore.storeIcon()`
|
|
622
|
-
- Consider reducing quantization levels if cache still grows
|
|
623
|
-
|
|
624
|
-
**Issue 5: Animation Stuttering**
|
|
625
|
-
|
|
626
|
-
**Symptom:** Icon animations drop frames
|
|
627
|
-
|
|
628
|
-
**Solution:**
|
|
629
|
-
- Profile with Instruments (Time Profiler)
|
|
630
|
-
- Check cache hit rate during animations
|
|
631
|
-
- Pre-cache morph frames in `MorphCache`
|
|
632
|
-
- Reduce animation complexity
|
|
633
|
-
|
|
634
|
-
---
|
|
635
|
-
|
|
636
|
-
## Future Enhancements
|
|
637
|
-
|
|
638
|
-
### Phase 2 Features (Post-Launch)
|
|
639
|
-
|
|
640
|
-
1. **Animated Provider Switching:**
|
|
641
|
-
- Smooth cross-fade when provider changes
|
|
642
|
-
- Morph old icon into new icon over 0.3s
|
|
643
|
-
|
|
644
|
-
2. **Usage Percentage Tooltip:**
|
|
645
|
-
- On hover, show exact percentages
|
|
646
|
-
- Display provider name and sync status
|
|
647
|
-
|
|
648
|
-
3. **Custom Icon Colors:**
|
|
649
|
-
- User-selectable color schemes
|
|
650
|
-
- Match system accent color option
|
|
651
|
-
|
|
652
|
-
4. **Accessibility Improvements:**
|
|
653
|
-
- VoiceOver descriptions for all states
|
|
654
|
-
- High contrast mode support
|
|
655
|
-
- Reduced motion alternative
|
|
656
|
-
|
|
657
|
-
5. **Icon Animation Library:**
|
|
658
|
-
- Pulse during sync
|
|
659
|
-
- Flash on quota alerts
|
|
660
|
-
- Subtle breathing effect when idle
|
|
661
|
-
|
|
662
|
-
---
|
|
663
|
-
|
|
664
|
-
## Appendix: Code Snippets
|
|
665
|
-
|
|
666
|
-
### Complete drawInfinityLogo() with Error Handling
|
|
667
|
-
|
|
668
|
-
```swift
|
|
669
|
-
private static func drawInfinityLogo(
|
|
670
|
-
providerStyle: SigilStyle,
|
|
671
|
-
pressure: Double,
|
|
672
|
-
stale: Bool,
|
|
673
|
-
baseColor: NSColor,
|
|
674
|
-
appearance: IconAppearance)
|
|
675
|
-
{
|
|
676
|
-
guard let infinityLogo = self.infinityLogoTemplate else {
|
|
677
|
-
// Fallback: draw simple circle if template fails to load
|
|
678
|
-
let fallbackPath = NSBezierPath(ovalIn: CGRect(x: 8, y: 6, width: 24, height: 12))
|
|
679
|
-
fallbackPath.lineWidth = 4
|
|
680
|
-
baseColor.setStroke()
|
|
681
|
-
fallbackPath.stroke()
|
|
682
|
-
return
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
guard let ctx = NSGraphicsContext.current?.cgContext else {
|
|
686
|
-
return
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
let rect = CGRect(origin: .zero, size: self.outputSize)
|
|
690
|
-
let opacity: CGFloat = stale ? 0.55 : 1.0
|
|
691
|
-
|
|
692
|
-
// Draw infinity path
|
|
693
|
-
ctx.saveGState()
|
|
694
|
-
infinityLogo.draw(in: rect, from: .zero, operation: .sourceOver, fraction: 1.0)
|
|
695
|
-
ctx.setBlendMode(.sourceIn)
|
|
696
|
-
baseColor.withAlphaComponent(opacity).setFill()
|
|
697
|
-
ctx.fill(rect)
|
|
698
|
-
ctx.restoreGState()
|
|
699
|
-
|
|
700
|
-
// Draw provider icon in center gap
|
|
701
|
-
let centerX = rect.midX
|
|
702
|
-
let centerY = rect.midY
|
|
703
|
-
let iconSize: CGFloat = 16 // 8pt @ 2x scale
|
|
704
|
-
let iconRect = RectPx(
|
|
705
|
-
x: Int((centerX - iconSize / 2) * outputScale),
|
|
706
|
-
y: Int((centerY - iconSize / 2) * outputScale),
|
|
707
|
-
w: Int(iconSize * outputScale),
|
|
708
|
-
h: Int(iconSize * outputScale))
|
|
709
|
-
|
|
710
|
-
// Create white background circle for icon visibility (vibrant mode only)
|
|
711
|
-
if appearance == .vibrant {
|
|
712
|
-
let bgCircleRadius: CGFloat = 10
|
|
713
|
-
let bgCircle = NSBezierPath(
|
|
714
|
-
ovalIn: CGRect(
|
|
715
|
-
x: centerX - bgCircleRadius,
|
|
716
|
-
y: centerY - bgCircleRadius,
|
|
717
|
-
width: bgCircleRadius * 2,
|
|
718
|
-
height: bgCircleRadius * 2))
|
|
719
|
-
NSColor.white.withAlphaComponent(0.9).setFill()
|
|
720
|
-
bgCircle.fill()
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Draw provider sigil
|
|
724
|
-
ctx.saveGState()
|
|
725
|
-
ctx.setBlendMode(appearance == .template ? .clear : .normal)
|
|
726
|
-
self.drawSigil(providerStyle, in: iconRect)
|
|
727
|
-
ctx.restoreGState()
|
|
728
|
-
}
|
|
729
|
-
```
|
|
730
|
-
|
|
731
|
-
### Settings Integration Example
|
|
732
|
-
|
|
733
|
-
```swift
|
|
734
|
-
// In SettingsStore.swift
|
|
735
|
-
@AppStorage("iconDesign") var iconDesign: IconDesign = .infinity
|
|
736
|
-
@AppStorage("iconAppearance") var iconAppearance: IconAppearance = .template
|
|
737
|
-
@AppStorage("iconDataMode") var iconDataMode: IconDataMode = .remaining
|
|
738
|
-
|
|
739
|
-
// In StatusItemController.swift
|
|
740
|
-
func updateIcon() {
|
|
741
|
-
let icon = IconRenderer.makeIcon(
|
|
742
|
-
primaryRemaining: self.store.sessionRemaining,
|
|
743
|
-
weeklyRemaining: self.store.weeklyRemaining,
|
|
744
|
-
creditsRemaining: self.store.creditsRemaining,
|
|
745
|
-
stale: self.store.isStale,
|
|
746
|
-
style: self.store.activeProvider.iconStyle,
|
|
747
|
-
design: self.settings.iconDesign,
|
|
748
|
-
statusIndicator: self.statusIndicator,
|
|
749
|
-
appearance: self.settings.iconAppearance,
|
|
750
|
-
dataMode: self.settings.iconDataMode)
|
|
751
|
-
|
|
752
|
-
self.statusItem.button?.image = icon
|
|
753
|
-
}
|
|
754
|
-
```
|
|
755
|
-
|
|
756
|
-
---
|
|
757
|
-
|
|
758
|
-
## Summary
|
|
759
|
-
|
|
760
|
-
This implementation guide provides a complete roadmap for adding the infinity symbol icon design to Runic while:
|
|
761
|
-
|
|
762
|
-
- Maintaining backward compatibility with the wave logo
|
|
763
|
-
- Preserving existing performance characteristics
|
|
764
|
-
- Adding minimal code complexity
|
|
765
|
-
- Enabling user choice through preferences
|
|
766
|
-
- Supporting future enhancements
|
|
767
|
-
|
|
768
|
-
**Estimated Implementation Time:** 8-12 hours for experienced Swift developer
|
|
769
|
-
|
|
770
|
-
**Key Files to Modify:**
|
|
771
|
-
1. `IconRenderer.swift` - Core rendering logic
|
|
772
|
-
2. `SettingsStore.swift` - User preferences
|
|
773
|
-
3. `PreferencesGeneralPane.swift` - UI controls
|
|
774
|
-
4. `StatusItemController.swift` - Icon updates
|
|
775
|
-
|
|
776
|
-
**New Files to Create:**
|
|
777
|
-
1. `RunicMenubarIconInfinity.svg` - Infinity template
|
|
778
|
-
2. Unit tests for new rendering functions
|
|
779
|
-
|
|
780
|
-
**Testing Checklist:**
|
|
781
|
-
- [ ] Visual testing on Retina display
|
|
782
|
-
- [ ] Visual testing on non-Retina display
|
|
783
|
-
- [ ] Dark mode rendering
|
|
784
|
-
- [ ] Light mode rendering
|
|
785
|
-
- [ ] All provider icons visible
|
|
786
|
-
- [ ] Pressure colors correct
|
|
787
|
-
- [ ] Stale state rendering
|
|
788
|
-
- [ ] Cache hit rate >80%
|
|
789
|
-
- [ ] No memory leaks
|
|
790
|
-
- [ ] Animation performance >60 FPS
|
|
791
|
-
- [ ] User preference persistence
|
|
792
|
-
- [ ] A/B testing data collected (optional)
|