@sriinnu/runic 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/.swiftformat +50 -0
  2. package/.swiftlint.yml +160 -0
  3. package/CHANGELOG.md +307 -0
  4. package/CONTRIBUTING.md +456 -0
  5. package/Icon.icns +0 -0
  6. package/Icon.icon/Assets/runic.png +0 -0
  7. package/Icon.icon/icon.json +36 -0
  8. package/LICENSE +21 -0
  9. package/Package.resolved +51 -0
  10. package/Package.swift +136 -0
  11. package/Packages/Helix/LICENSE +21 -0
  12. package/Packages/Helix/Package.swift +29 -0
  13. package/Packages/Helix/README.md +976 -0
  14. package/Packages/Helix/Sources/Helix/Binding.swift +111 -0
  15. package/Packages/Helix/Sources/Helix/CommandParser.swift +160 -0
  16. package/Packages/Helix/Sources/Helix/CommandSignature.swift +117 -0
  17. package/Packages/Helix/Sources/Helix/ExpressibleFromArgument.swift +72 -0
  18. package/Packages/Helix/Sources/Helix/HelpGenerator.swift +175 -0
  19. package/Packages/Helix/Sources/Helix/NameSpecification.swift +98 -0
  20. package/Packages/Helix/Sources/Helix/ParsableCommand.swift +204 -0
  21. package/Packages/Helix/Sources/Helix/Platform/DarwinPlatformContext.swift +44 -0
  22. package/Packages/Helix/Sources/Helix/Platform/LinuxPlatformContext.swift +34 -0
  23. package/Packages/Helix/Sources/Helix/Platform/PlatformContext+Default.swift +91 -0
  24. package/Packages/Helix/Sources/Helix/Platform/PlatformContext.swift +94 -0
  25. package/Packages/Helix/Sources/Helix/Platform/PlatformPath.swift +167 -0
  26. package/Packages/Helix/Sources/Helix/Platform/Stdio.swift +99 -0
  27. package/Packages/Helix/Sources/Helix/Platform/WebPlatformContext.swift +146 -0
  28. package/Packages/Helix/Sources/Helix/Platform/WindowsPlatformContext.swift +97 -0
  29. package/Packages/Helix/Sources/Helix/Program.swift +204 -0
  30. package/Packages/Helix/Sources/Helix/PropertyWrappers.swift +367 -0
  31. package/Packages/Silo/LICENSE +21 -0
  32. package/Packages/Silo/Package.swift +34 -0
  33. package/Packages/Silo/README.md +466 -0
  34. package/Packages/Silo/Sources/Silo/BinaryCookiesReader.swift +169 -0
  35. package/Packages/Silo/Sources/Silo/BrowserCookieAnalytics.swift +365 -0
  36. package/Packages/Silo/Sources/Silo/BrowserCookieBackends.swift +594 -0
  37. package/Packages/Silo/Sources/Silo/BrowserCookieClient.swift +326 -0
  38. package/Packages/Silo/Sources/Silo/BrowserCookieExport.swift +154 -0
  39. package/Packages/Silo/Sources/Silo/BrowserCookieImport.swift +119 -0
  40. package/Packages/Silo/Sources/Silo/BrowserCookieMockStore.swift +121 -0
  41. package/Packages/Silo/Sources/Silo/BrowserCookieModels.swift +391 -0
  42. package/Packages/Silo/Sources/Silo/ChromiumCookieReader.swift +240 -0
  43. package/Packages/Silo/Sources/Silo/CryptoSupport.swift +86 -0
  44. package/Packages/Silo/Sources/Silo/FirefoxCookieReader.swift +172 -0
  45. package/Packages/Silo/Sources/Silo/LinuxChromiumCookieReader.swift +172 -0
  46. package/Packages/Silo/Sources/Silo/LinuxSecretService.swift +105 -0
  47. package/Packages/Silo/Sources/Silo/MacOSChromiumCookieReader.swift +191 -0
  48. package/Packages/Silo/Sources/Silo/SQLiteSnapshot.swift +41 -0
  49. package/Packages/Silo/Sources/Silo/WindowsChromiumCookieReader.swift +110 -0
  50. package/README.md +109 -0
  51. package/RuniciOS/App/RuniciOSApp.swift +105 -0
  52. package/RuniciOS/Core/iOSUsageStore.swift +192 -0
  53. package/RuniciOS/Views/ProviderDetailView.swift +312 -0
  54. package/RuniciOS/Views/ProviderListView.swift +228 -0
  55. package/RuniciOS/Widgets/LargeWidget.swift +367 -0
  56. package/RuniciOS/Widgets/LiveActivity.swift +342 -0
  57. package/RuniciOS/Widgets/LockScreenWidget.swift +273 -0
  58. package/RuniciOS/Widgets/MediumWidget.swift +370 -0
  59. package/RuniciOS/Widgets/RunicWidget.swift +274 -0
  60. package/RuniciOS/Widgets/SmallWidget.swift +281 -0
  61. package/RuniciOS/Widgets/WidgetModels.swift +285 -0
  62. package/RuniciOS/Widgets/WidgetTimeline.swift +270 -0
  63. package/Scripts/CREATION-SUMMARY.md +367 -0
  64. package/Scripts/DIRECTORY-STRUCTURE.md +358 -0
  65. package/Scripts/GETTING-STARTED-CHECKLIST.md +364 -0
  66. package/Scripts/INDEX.md +365 -0
  67. package/Scripts/QUICK-REFERENCE.md +164 -0
  68. package/Scripts/README-SCRIPTS.md +926 -0
  69. package/Scripts/build-android.sh +526 -0
  70. package/Scripts/build-ios.sh +529 -0
  71. package/Scripts/build-macos.sh +603 -0
  72. package/Scripts/build-windows.sh +504 -0
  73. package/Scripts/build_icon.sh +49 -0
  74. package/Scripts/changelog-to-html.sh +89 -0
  75. package/Scripts/check-release-assets.sh +10 -0
  76. package/Scripts/ci-config.yml +474 -0
  77. package/Scripts/compile_and_run.sh +219 -0
  78. package/Scripts/compile_and_run_adhoc.sh +4 -0
  79. package/Scripts/docs-list.mjs +119 -0
  80. package/Scripts/make_appcast.sh +58 -0
  81. package/Scripts/package_app.sh +409 -0
  82. package/Scripts/release-lib.sh +214 -0
  83. package/Scripts/release.sh +76 -0
  84. package/Scripts/setup-all.sh +387 -0
  85. package/Scripts/setup-ios.sh +404 -0
  86. package/Scripts/setup-react-native.sh +523 -0
  87. package/Scripts/sign-and-notarize.sh +122 -0
  88. package/Scripts/test_live_update.sh +38 -0
  89. package/Scripts/validate_changelog.sh +23 -0
  90. package/Scripts/verify_appcast.sh +92 -0
  91. package/Sources/Runic/About.swift +93 -0
  92. package/Sources/Runic/AppNotifications.swift +115 -0
  93. package/Sources/Runic/Controllers/StatusItemController+Actions.swift +657 -0
  94. package/Sources/Runic/Controllers/StatusItemController+Animation.swift +518 -0
  95. package/Sources/Runic/Controllers/StatusItemController+ChartSubmenus.swift +810 -0
  96. package/Sources/Runic/Controllers/StatusItemController+CustomProviders.swift +87 -0
  97. package/Sources/Runic/Controllers/StatusItemController+Menu.swift +1379 -0
  98. package/Sources/Runic/Controllers/StatusItemController+MenuCards.swift +337 -0
  99. package/Sources/Runic/Controllers/StatusItemController+MenuHelpers.swift +395 -0
  100. package/Sources/Runic/Controllers/StatusItemController.swift +360 -0
  101. package/Sources/Runic/Core/BudgetNotificationManager.swift +80 -0
  102. package/Sources/Runic/Core/Login/ClaudeLoginRunner.swift +103 -0
  103. package/Sources/Runic/Core/Login/CodexLoginRunner.swift +154 -0
  104. package/Sources/Runic/Core/Login/CursorLoginRunner.swift +206 -0
  105. package/Sources/Runic/Core/Login/GeminiLoginRunner.swift +95 -0
  106. package/Sources/Runic/Core/Rendering/IconRenderer.swift +1216 -0
  107. package/Sources/Runic/Core/Rendering/IconView.swift +120 -0
  108. package/Sources/Runic/Core/Rendering/ProviderBrandIcon.swift +71 -0
  109. package/Sources/Runic/Core/RunicAnimation.swift +53 -0
  110. package/Sources/Runic/Core/RunicColors.swift +73 -0
  111. package/Sources/Runic/Core/RunicCornerRadius.swift +15 -0
  112. package/Sources/Runic/Core/RunicSpacing.swift +68 -0
  113. package/Sources/Runic/Core/Stores/AuggieTokenStore.swift +143 -0
  114. package/Sources/Runic/Core/Stores/AzureOpenAITokenStore.swift +143 -0
  115. package/Sources/Runic/Core/Stores/CerebrasTokenStore.swift +143 -0
  116. package/Sources/Runic/Core/Stores/CohereTokenStore.swift +143 -0
  117. package/Sources/Runic/Core/Stores/CopilotTokenStore.swift +143 -0
  118. package/Sources/Runic/Core/Stores/CustomProviderStore.swift +158 -0
  119. package/Sources/Runic/Core/Stores/DeepSeekTokenStore.swift +143 -0
  120. package/Sources/Runic/Core/Stores/FireworksTokenStore.swift +143 -0
  121. package/Sources/Runic/Core/Stores/GroqTokenStore.swift +143 -0
  122. package/Sources/Runic/Core/Stores/KimiTokenStore.swift +143 -0
  123. package/Sources/Runic/Core/Stores/MiniMaxCookieHeaderStore.swift +143 -0
  124. package/Sources/Runic/Core/Stores/MiniMaxGroupIDStore.swift +143 -0
  125. package/Sources/Runic/Core/Stores/MiniMaxTokenStore.swift +143 -0
  126. package/Sources/Runic/Core/Stores/MistralTokenStore.swift +143 -0
  127. package/Sources/Runic/Core/Stores/OpenRouterTokenStore.swift +143 -0
  128. package/Sources/Runic/Core/Stores/PerplexityTokenStore.swift +143 -0
  129. package/Sources/Runic/Core/Stores/ProviderToggleStore.swift +30 -0
  130. package/Sources/Runic/Core/Stores/QwenTokenStore.swift +143 -0
  131. package/Sources/Runic/Core/Stores/SambaNovaTokenStore.swift +143 -0
  132. package/Sources/Runic/Core/Stores/SettingsStore.swift +1702 -0
  133. package/Sources/Runic/Core/Stores/TogetherTokenStore.swift +143 -0
  134. package/Sources/Runic/Core/Stores/UsageStore+Accessors.swift +20 -0
  135. package/Sources/Runic/Core/Stores/UsageStore+Status.swift +189 -0
  136. package/Sources/Runic/Core/Stores/UsageStore+TokenCost.swift +33 -0
  137. package/Sources/Runic/Core/Stores/UsageStore+WidgetSnapshot.swift +67 -0
  138. package/Sources/Runic/Core/Stores/UsageStore.swift +3564 -0
  139. package/Sources/Runic/Core/Stores/XAITokenStore.swift +143 -0
  140. package/Sources/Runic/Core/Stores/ZaiTokenStore.swift +143 -0
  141. package/Sources/Runic/Core/UsageExporter.swift +193 -0
  142. package/Sources/Runic/Date+RelativeDescription.swift +21 -0
  143. package/Sources/Runic/HiddenWindowView.swift +32 -0
  144. package/Sources/Runic/InstallOrigin.swift +9 -0
  145. package/Sources/Runic/KeyboardShortcuts+Names.swift +6 -0
  146. package/Sources/Runic/MouseLocationReader.swift +65 -0
  147. package/Sources/Runic/Notifications+Runic.swift +6 -0
  148. package/Sources/Runic/OpenAICreditsPurchaseWindowController.swift +503 -0
  149. package/Sources/Runic/ProviderRegistry.swift +100 -0
  150. package/Sources/Runic/ProviderSwitcherButtons.swift +267 -0
  151. package/Sources/Runic/Providers/Antigravity/AntigravityLoginFlow.swift +11 -0
  152. package/Sources/Runic/Providers/Antigravity/AntigravityProviderImplementation.swift +14 -0
  153. package/Sources/Runic/Providers/Auggie/AuggieProviderImplementation.swift +24 -0
  154. package/Sources/Runic/Providers/Azure/AzureProviderImplementation.swift +52 -0
  155. package/Sources/Runic/Providers/Bedrock/BedrockProviderImplementation.swift +42 -0
  156. package/Sources/Runic/Providers/Cerebras/CerebrasProviderImplementation.swift +24 -0
  157. package/Sources/Runic/Providers/Claude/ClaudeLoginFlow.swift +26 -0
  158. package/Sources/Runic/Providers/Claude/ClaudeProviderImplementation.swift +14 -0
  159. package/Sources/Runic/Providers/Codex/CodexLoginFlow.swift +18 -0
  160. package/Sources/Runic/Providers/Codex/CodexProviderImplementation.swift +15 -0
  161. package/Sources/Runic/Providers/Cohere/CohereProviderImplementation.swift +24 -0
  162. package/Sources/Runic/Providers/Copilot/CopilotLoginFlow.swift +193 -0
  163. package/Sources/Runic/Providers/Copilot/CopilotProviderImplementation.swift +110 -0
  164. package/Sources/Runic/Providers/Cursor/CursorLoginFlow.swift +28 -0
  165. package/Sources/Runic/Providers/Cursor/CursorProviderImplementation.swift +15 -0
  166. package/Sources/Runic/Providers/DeepSeek/DeepSeekProviderImplementation.swift +24 -0
  167. package/Sources/Runic/Providers/Factory/FactoryLoginFlow.swift +12 -0
  168. package/Sources/Runic/Providers/Factory/FactoryProviderImplementation.swift +15 -0
  169. package/Sources/Runic/Providers/Fireworks/FireworksProviderImplementation.swift +24 -0
  170. package/Sources/Runic/Providers/Gemini/GeminiLoginFlow.swift +20 -0
  171. package/Sources/Runic/Providers/Gemini/GeminiProviderImplementation.swift +15 -0
  172. package/Sources/Runic/Providers/Groq/GroqProviderImplementation.swift +24 -0
  173. package/Sources/Runic/Providers/Kimi/KimiProviderImplementation.swift +24 -0
  174. package/Sources/Runic/Providers/MiniMax/MiniMaxProviderImplementation.swift +32 -0
  175. package/Sources/Runic/Providers/Mistral/MistralProviderImplementation.swift +24 -0
  176. package/Sources/Runic/Providers/OpenRouter/OpenRouterProviderImplementation.swift +24 -0
  177. package/Sources/Runic/Providers/Perplexity/PerplexityProviderImplementation.swift +24 -0
  178. package/Sources/Runic/Providers/SambaNova/SambaNovaProviderImplementation.swift +24 -0
  179. package/Sources/Runic/Providers/Shared/ProviderCatalog.swift +15 -0
  180. package/Sources/Runic/Providers/Shared/ProviderImplementation.swift +48 -0
  181. package/Sources/Runic/Providers/Shared/ProviderImplementationRegistry.swift +66 -0
  182. package/Sources/Runic/Providers/Shared/ProviderLoginFlow.swift +12 -0
  183. package/Sources/Runic/Providers/Shared/ProviderSettingsDescriptors.swift +99 -0
  184. package/Sources/Runic/Providers/Shared/SystemSettingsLinks.swift +18 -0
  185. package/Sources/Runic/Providers/Together/TogetherProviderImplementation.swift +24 -0
  186. package/Sources/Runic/Providers/XAI/XAIProviderImplementation.swift +24 -0
  187. package/Sources/Runic/Providers/Zai/ZaiProviderImplementation.swift +24 -0
  188. package/Sources/Runic/Resources/ProviderIcon-antigravity.svg +2 -0
  189. package/Sources/Runic/Resources/ProviderIcon-auggie.svg +3 -0
  190. package/Sources/Runic/Resources/ProviderIcon-azure.svg +5 -0
  191. package/Sources/Runic/Resources/ProviderIcon-bedrock.svg +7 -0
  192. package/Sources/Runic/Resources/ProviderIcon-cerebras.svg +3 -0
  193. package/Sources/Runic/Resources/ProviderIcon-claude.svg +1 -0
  194. package/Sources/Runic/Resources/ProviderIcon-codex.svg +1 -0
  195. package/Sources/Runic/Resources/ProviderIcon-cohere.svg +3 -0
  196. package/Sources/Runic/Resources/ProviderIcon-copilot.svg +1 -0
  197. package/Sources/Runic/Resources/ProviderIcon-cursor.svg +3 -0
  198. package/Sources/Runic/Resources/ProviderIcon-deepseek.svg +4 -0
  199. package/Sources/Runic/Resources/ProviderIcon-factory.svg +3 -0
  200. package/Sources/Runic/Resources/ProviderIcon-fireworks.svg +3 -0
  201. package/Sources/Runic/Resources/ProviderIcon-gemini.svg +1 -0
  202. package/Sources/Runic/Resources/ProviderIcon-groq.svg +1 -0
  203. package/Sources/Runic/Resources/ProviderIcon-kimi.svg +4 -0
  204. package/Sources/Runic/Resources/ProviderIcon-minimax.svg +1 -0
  205. package/Sources/Runic/Resources/ProviderIcon-mistral.svg +5 -0
  206. package/Sources/Runic/Resources/ProviderIcon-openrouter.svg +7 -0
  207. package/Sources/Runic/Resources/ProviderIcon-perplexity.svg +4 -0
  208. package/Sources/Runic/Resources/ProviderIcon-qwen.svg +9 -0
  209. package/Sources/Runic/Resources/ProviderIcon-sambanova.svg +4 -0
  210. package/Sources/Runic/Resources/ProviderIcon-together.svg +5 -0
  211. package/Sources/Runic/Resources/ProviderIcon-vertexai.svg +17 -0
  212. package/Sources/Runic/Resources/ProviderIcon-xai.svg +3 -0
  213. package/Sources/Runic/Resources/ProviderIcon-zai.svg +5 -0
  214. package/Sources/Runic/Resources/RunicMenubarIcon.svg +7 -0
  215. package/Sources/Runic/RunicApp.swift +357 -0
  216. package/Sources/Runic/SessionQuotaNotifications.swift +58 -0
  217. package/Sources/Runic/UsagePaceText.swift +52 -0
  218. package/Sources/Runic/UsageProgressBar.swift +224 -0
  219. package/Sources/Runic/Utilities/DisplayLink.swift +96 -0
  220. package/Sources/Runic/Utilities/LoadingPattern.swift +60 -0
  221. package/Sources/Runic/Utilities/PerformanceConstants.swift +85 -0
  222. package/Sources/Runic/Views/Menu/AlertsMenuView.swift +256 -0
  223. package/Sources/Runic/Views/Menu/ChartPanelStyle.swift +22 -0
  224. package/Sources/Runic/Views/Menu/CostComparativeChartMenuView.swift +275 -0
  225. package/Sources/Runic/Views/Menu/CostHistoryChartMenuView.swift +377 -0
  226. package/Sources/Runic/Views/Menu/CreditsHistoryChartMenuView.swift +312 -0
  227. package/Sources/Runic/Views/Menu/EfficiencyMetricsMenuView.swift +312 -0
  228. package/Sources/Runic/Views/Menu/HeroStatCardsMenuView.swift +228 -0
  229. package/Sources/Runic/Views/Menu/HourlyActivityChartMenuView.swift +228 -0
  230. package/Sources/Runic/Views/Menu/InlineUsageChartView.swift +162 -0
  231. package/Sources/Runic/Views/Menu/MenuCardEntranceModifier.swift +64 -0
  232. package/Sources/Runic/Views/Menu/MenuCardSidebarView.swift +268 -0
  233. package/Sources/Runic/Views/Menu/MenuCardSkeletonView.swift +104 -0
  234. package/Sources/Runic/Views/Menu/MenuCardView.swift +1900 -0
  235. package/Sources/Runic/Views/Menu/MenuContent.swift +150 -0
  236. package/Sources/Runic/Views/Menu/MenuDescriptor.swift +369 -0
  237. package/Sources/Runic/Views/Menu/MenuHighlightStyle.swift +42 -0
  238. package/Sources/Runic/Views/Menu/ModelBreakdownMenuView.swift +235 -0
  239. package/Sources/Runic/Views/Menu/OverviewMenuView.swift +141 -0
  240. package/Sources/Runic/Views/Menu/ProjectBreakdownMenuView.swift +209 -0
  241. package/Sources/Runic/Views/Menu/ProjectBudgetMenuView.swift +220 -0
  242. package/Sources/Runic/Views/Menu/ProviderTabBarView.swift +88 -0
  243. package/Sources/Runic/Views/Menu/SubscriptionUtilizationChartMenuView.swift +201 -0
  244. package/Sources/Runic/Views/Menu/UsageBreakdownChartMenuView.swift +398 -0
  245. package/Sources/Runic/Views/Menu/UsageHeatmapMenuView.swift +232 -0
  246. package/Sources/Runic/Views/Menu/UsageTimelineChartMenuView.swift +417 -0
  247. package/Sources/Runic/Views/Menu/UsageWindowComparisonChartMenuView.swift +190 -0
  248. package/Sources/Runic/Views/Menu/WeeklyActivityChartMenuView.swift +132 -0
  249. package/Sources/Runic/Views/Performance/PerformanceDashboardView.swift +618 -0
  250. package/Sources/Runic/Views/Preferences/LiquidComponents.swift +305 -0
  251. package/Sources/Runic/Views/Preferences/PreferencesAboutPane.swift +271 -0
  252. package/Sources/Runic/Views/Preferences/PreferencesAdvancedPane.swift +268 -0
  253. package/Sources/Runic/Views/Preferences/PreferencesAlertsPane.swift +422 -0
  254. package/Sources/Runic/Views/Preferences/PreferencesAnalyticsPane.swift +641 -0
  255. package/Sources/Runic/Views/Preferences/PreferencesBudgetsPane.swift +344 -0
  256. package/Sources/Runic/Views/Preferences/PreferencesComponents.swift +230 -0
  257. package/Sources/Runic/Views/Preferences/PreferencesCustomProvidersPane.swift +322 -0
  258. package/Sources/Runic/Views/Preferences/PreferencesDebugPane.swift +469 -0
  259. package/Sources/Runic/Views/Preferences/PreferencesGeneralPane.swift +231 -0
  260. package/Sources/Runic/Views/Preferences/PreferencesHelpPane.swift +50 -0
  261. package/Sources/Runic/Views/Preferences/PreferencesIntegrationsPane.swift +497 -0
  262. package/Sources/Runic/Views/Preferences/PreferencesPerformancePane.swift +288 -0
  263. package/Sources/Runic/Views/Preferences/PreferencesProvidersPane.swift +3435 -0
  264. package/Sources/Runic/Views/Preferences/PreferencesSelection.swift +25 -0
  265. package/Sources/Runic/Views/Preferences/PreferencesSyncPane.swift +59 -0
  266. package/Sources/Runic/Views/Preferences/PreferencesView.swift +206 -0
  267. package/Sources/Runic/Views/Rating/QualityRatingView.swift +238 -0
  268. package/Sources/Runic/Views/Team/TeamDashboardView.swift +371 -0
  269. package/Sources/Runic/Views/Team/TeamInviteSheet.swift +175 -0
  270. package/Sources/Runic/Views/Team/TeamManagementView.swift +761 -0
  271. package/Sources/Runic/Views/Team/TeamMemberRow.swift +181 -0
  272. package/Sources/RunicCLI/CLIEntry.swift +942 -0
  273. package/Sources/RunicCLI/CLIRenderer.swift +87 -0
  274. package/Sources/RunicCLI/Commands/EnhancedUsageCommand.swift +588 -0
  275. package/Sources/RunicCLI/Commands/ModelsCommand.swift +362 -0
  276. package/Sources/RunicCLI/Commands/ProjectsCommand.swift +439 -0
  277. package/Sources/RunicCLI/Commands/ResetCommand.swift +429 -0
  278. package/Sources/RunicCLI/Commands/UsageLedgerSourceFactory.swift +168 -0
  279. package/Sources/RunicClaudeWatchdog/main.swift +122 -0
  280. package/Sources/RunicClaudeWebProbe/main.swift +62 -0
  281. package/Sources/RunicCore/AlertRuleStore.swift +187 -0
  282. package/Sources/RunicCore/BrowserCookieImportOrder.swift +25 -0
  283. package/Sources/RunicCore/CopilotUsageModels.swift +84 -0
  284. package/Sources/RunicCore/CostUsageFetcher.swift +119 -0
  285. package/Sources/RunicCore/CostUsageModels.swift +479 -0
  286. package/Sources/RunicCore/CreditsModels.swift +50 -0
  287. package/Sources/RunicCore/CustomProviders/CustomProviderModels.swift +269 -0
  288. package/Sources/RunicCore/CustomProviders/GenericProviderFetcher.swift +622 -0
  289. package/Sources/RunicCore/CustomProviders/ProviderTemplates.swift +500 -0
  290. package/Sources/RunicCore/Host/PTY/TTYCommandRunner.swift +679 -0
  291. package/Sources/RunicCore/Host/Process/SubprocessRunner.swift +135 -0
  292. package/Sources/RunicCore/Integrations/GitHubIntegration.swift +173 -0
  293. package/Sources/RunicCore/Logging/JSONStderrLogHandler.swift +79 -0
  294. package/Sources/RunicCore/Logging/OSLogLogHandler.swift +86 -0
  295. package/Sources/RunicCore/Logging/RunicLog.swift +123 -0
  296. package/Sources/RunicCore/Models/EnhancedUsageModels.swift +371 -0
  297. package/Sources/RunicCore/OpenAIDashboardModels.swift +210 -0
  298. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift +676 -0
  299. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardFetcher.swift +492 -0
  300. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +51 -0
  301. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardParser.swift +483 -0
  302. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift +558 -0
  303. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift +204 -0
  304. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift +78 -0
  305. package/Sources/RunicCore/PathEnvironment.swift +482 -0
  306. package/Sources/RunicCore/Performance/PerformanceModels.swift +371 -0
  307. package/Sources/RunicCore/Performance/PerformanceStorageImpl.swift +409 -0
  308. package/Sources/RunicCore/Policy/UsagePolicyEngine.swift +178 -0
  309. package/Sources/RunicCore/ProjectBudgetStore.swift +99 -0
  310. package/Sources/RunicCore/ProviderCostSnapshot.swift +29 -0
  311. package/Sources/RunicCore/Providers/Antigravity/AntigravityProviderDescriptor.swift +66 -0
  312. package/Sources/RunicCore/Providers/Antigravity/AntigravityStatusProbe.swift +685 -0
  313. package/Sources/RunicCore/Providers/Auggie/AuggieProviderDescriptor.swift +83 -0
  314. package/Sources/RunicCore/Providers/Auggie/AuggieUsageFetcher.swift +142 -0
  315. package/Sources/RunicCore/Providers/Azure/AzureProviderDescriptor.swift +141 -0
  316. package/Sources/RunicCore/Providers/Azure/AzureUsageFetcher.swift +186 -0
  317. package/Sources/RunicCore/Providers/Bedrock/BedrockProviderDescriptor.swift +126 -0
  318. package/Sources/RunicCore/Providers/Bedrock/BedrockUsageFetcher.swift +168 -0
  319. package/Sources/RunicCore/Providers/Cerebras/CerebrasProviderDescriptor.swift +84 -0
  320. package/Sources/RunicCore/Providers/Cerebras/CerebrasUsageFetcher.swift +75 -0
  321. package/Sources/RunicCore/Providers/Claude/ClaudeCLISession.swift +332 -0
  322. package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift +180 -0
  323. package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift +137 -0
  324. package/Sources/RunicCore/Providers/Claude/ClaudeProviderDescriptor.swift +207 -0
  325. package/Sources/RunicCore/Providers/Claude/ClaudeStatusProbe.swift +654 -0
  326. package/Sources/RunicCore/Providers/Claude/ClaudeUsageDataSource.swift +28 -0
  327. package/Sources/RunicCore/Providers/Claude/ClaudeUsageFetcher.swift +480 -0
  328. package/Sources/RunicCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift +780 -0
  329. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift +146 -0
  330. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift +269 -0
  331. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift +100 -0
  332. package/Sources/RunicCore/Providers/Codex/CodexProviderDescriptor.swift +243 -0
  333. package/Sources/RunicCore/Providers/Codex/CodexStatusProbe.swift +125 -0
  334. package/Sources/RunicCore/Providers/Codex/CodexUsageDataSource.swift +24 -0
  335. package/Sources/RunicCore/Providers/Codex/CodexWebDashboardStrategy.swift +181 -0
  336. package/Sources/RunicCore/Providers/Cohere/CohereProviderDescriptor.swift +83 -0
  337. package/Sources/RunicCore/Providers/Cohere/CohereUsageFetcher.swift +85 -0
  338. package/Sources/RunicCore/Providers/Copilot/CopilotDeviceFlow.swift +123 -0
  339. package/Sources/RunicCore/Providers/Copilot/CopilotGitHubCLITokenReader.swift +114 -0
  340. package/Sources/RunicCore/Providers/Copilot/CopilotProviderDescriptor.swift +100 -0
  341. package/Sources/RunicCore/Providers/Copilot/CopilotUsageFetcher.swift +291 -0
  342. package/Sources/RunicCore/Providers/Copilot/CopilotVSCodeTokenReader.swift +386 -0
  343. package/Sources/RunicCore/Providers/Cursor/CursorProviderDescriptor.swift +65 -0
  344. package/Sources/RunicCore/Providers/Cursor/CursorStatusProbe.swift +594 -0
  345. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift +85 -0
  346. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift +108 -0
  347. package/Sources/RunicCore/Providers/Factory/FactoryLocalStorageImporter.swift +398 -0
  348. package/Sources/RunicCore/Providers/Factory/FactoryProviderDescriptor.swift +65 -0
  349. package/Sources/RunicCore/Providers/Factory/FactoryStatusProbe.swift +1275 -0
  350. package/Sources/RunicCore/Providers/Fireworks/FireworksProviderDescriptor.swift +84 -0
  351. package/Sources/RunicCore/Providers/Fireworks/FireworksUsageFetcher.swift +75 -0
  352. package/Sources/RunicCore/Providers/Gemini/GeminiProviderDescriptor.swift +65 -0
  353. package/Sources/RunicCore/Providers/Gemini/GeminiStatusProbe.swift +835 -0
  354. package/Sources/RunicCore/Providers/Groq/GroqProviderDescriptor.swift +83 -0
  355. package/Sources/RunicCore/Providers/Groq/GroqUsageFetcher.swift +71 -0
  356. package/Sources/RunicCore/Providers/Kimi/KimiProviderDescriptor.swift +83 -0
  357. package/Sources/RunicCore/Providers/Kimi/KimiUsageFetcher.swift +77 -0
  358. package/Sources/RunicCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift +92 -0
  359. package/Sources/RunicCore/Providers/MiniMax/MiniMaxSettingsReader.swift +54 -0
  360. package/Sources/RunicCore/Providers/MiniMax/MiniMaxUsageFetcher.swift +171 -0
  361. package/Sources/RunicCore/Providers/MiniMax/MiniMaxWebUsageFetcher.swift +911 -0
  362. package/Sources/RunicCore/Providers/Mistral/MistralProviderDescriptor.swift +84 -0
  363. package/Sources/RunicCore/Providers/Mistral/MistralUsageFetcher.swift +75 -0
  364. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift +87 -0
  365. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterUsageFetcher.swift +207 -0
  366. package/Sources/RunicCore/Providers/Perplexity/PerplexityProviderDescriptor.swift +84 -0
  367. package/Sources/RunicCore/Providers/Perplexity/PerplexityUsageFetcher.swift +75 -0
  368. package/Sources/RunicCore/Providers/ProviderBranding.swift +25 -0
  369. package/Sources/RunicCore/Providers/ProviderCLIConfig.swift +17 -0
  370. package/Sources/RunicCore/Providers/ProviderDescriptor.swift +129 -0
  371. package/Sources/RunicCore/Providers/ProviderFetchPlan.swift +263 -0
  372. package/Sources/RunicCore/Providers/ProviderSettingsSnapshot.swift +98 -0
  373. package/Sources/RunicCore/Providers/ProviderTokenResolver.swift +501 -0
  374. package/Sources/RunicCore/Providers/ProviderVersionDetector.swift +68 -0
  375. package/Sources/RunicCore/Providers/Providers.swift +184 -0
  376. package/Sources/RunicCore/Providers/Qwen/QwenProviderDescriptor.swift +84 -0
  377. package/Sources/RunicCore/Providers/Qwen/QwenSettingsReader.swift +30 -0
  378. package/Sources/RunicCore/Providers/Qwen/QwenUsageStats.swift +317 -0
  379. package/Sources/RunicCore/Providers/SambaNova/SambaNovaProviderDescriptor.swift +84 -0
  380. package/Sources/RunicCore/Providers/SambaNova/SambaNovaUsageFetcher.swift +75 -0
  381. package/Sources/RunicCore/Providers/Together/TogetherProviderDescriptor.swift +83 -0
  382. package/Sources/RunicCore/Providers/Together/TogetherUsageFetcher.swift +75 -0
  383. package/Sources/RunicCore/Providers/VertexAI/VertexAIProviderDescriptor.swift +123 -0
  384. package/Sources/RunicCore/Providers/VertexAI/VertexAISettingsReader.swift +48 -0
  385. package/Sources/RunicCore/Providers/VertexAI/VertexAIUsageFetcher.swift +144 -0
  386. package/Sources/RunicCore/Providers/XAI/XAIProviderDescriptor.swift +83 -0
  387. package/Sources/RunicCore/Providers/XAI/XAIUsageFetcher.swift +75 -0
  388. package/Sources/RunicCore/Providers/Zai/ZaiProviderDescriptor.swift +72 -0
  389. package/Sources/RunicCore/Providers/Zai/ZaiSettingsReader.swift +41 -0
  390. package/Sources/RunicCore/Providers/Zai/ZaiUsageStats.swift +724 -0
  391. package/Sources/RunicCore/Sync/BackgroundSyncManager.swift +385 -0
  392. package/Sources/RunicCore/Sync/SyncConflictResolver.swift +310 -0
  393. package/Sources/RunicCore/Sync/SyncProtocol.swift +288 -0
  394. package/Sources/RunicCore/Sync/SyncRecord.swift +405 -0
  395. package/Sources/RunicCore/Sync/SyncUsageExample.swift +294 -0
  396. package/Sources/RunicCore/Sync/TeamSyncRecords.swift +775 -0
  397. package/Sources/RunicCore/Sync/iCloudSyncEngine.swift +333 -0
  398. package/Sources/RunicCore/Team/TeamModels.swift +583 -0
  399. package/Sources/RunicCore/Team/TeamShowbackExporter.swift +495 -0
  400. package/Sources/RunicCore/Team/TeamStore.swift +792 -0
  401. package/Sources/RunicCore/TextParsing.swift +55 -0
  402. package/Sources/RunicCore/UsageFetcher.swift +694 -0
  403. package/Sources/RunicCore/UsageFormatter.swift +410 -0
  404. package/Sources/RunicCore/UsageLedger/ClaudeUsageLogSource.swift +329 -0
  405. package/Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift +448 -0
  406. package/Sources/RunicCore/UsageLedger/OTelGenAILedgerAdapter.swift +550 -0
  407. package/Sources/RunicCore/UsageLedger/UsageLedger.swift +29 -0
  408. package/Sources/RunicCore/UsageLedger/UsageLedgerAggregator.swift +660 -0
  409. package/Sources/RunicCore/UsageLedger/UsageLedgerInsightsAdvisor.swift +209 -0
  410. package/Sources/RunicCore/UsageLedger/UsageLedgerModels.swift +417 -0
  411. package/Sources/RunicCore/UsageLedger/UsageLedgerProjectIdentity.swift +245 -0
  412. package/Sources/RunicCore/UsagePace.swift +81 -0
  413. package/Sources/RunicCore/Vendored/CostUsage/CostUsageCache.swift +73 -0
  414. package/Sources/RunicCore/Vendored/CostUsage/CostUsageJsonl.swift +74 -0
  415. package/Sources/RunicCore/Vendored/CostUsage/CostUsagePricing.swift +208 -0
  416. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Claude.swift +455 -0
  417. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Timestamp.swift +132 -0
  418. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner.swift +589 -0
  419. package/Sources/RunicCore/WidgetSnapshot.swift +183 -0
  420. package/Sources/RunicMacroSupport/ProviderRegistrationMacros.swift +14 -0
  421. package/Sources/RunicMacros/ProviderRegistrationMacros.swift +216 -0
  422. package/Sources/RunicWidget/RunicWidgetBundle.swift +79 -0
  423. package/Sources/RunicWidget/RunicWidgetProvider.swift +283 -0
  424. package/Sources/RunicWidget/RunicWidgetViews.swift +680 -0
  425. package/Tests/RunicTests/AntigravityStatusProbeTests.swift +50 -0
  426. package/Tests/RunicTests/AppDelegateTests.swift +43 -0
  427. package/Tests/RunicTests/BrowserCookieOrderLabelTests.swift +22 -0
  428. package/Tests/RunicTests/CLIArgumentParsingTests.swift +70 -0
  429. package/Tests/RunicTests/CLICostTests.swift +65 -0
  430. package/Tests/RunicTests/CLIProviderSelectionTests.swift +22 -0
  431. package/Tests/RunicTests/CLISnapshotTests.swift +72 -0
  432. package/Tests/RunicTests/CLIWebFallbackTests.swift +58 -0
  433. package/Tests/RunicTests/ClaudeOAuthTests.swift +164 -0
  434. package/Tests/RunicTests/ClaudeResilienceTests.swift +30 -0
  435. package/Tests/RunicTests/ClaudeUsageTests.swift +370 -0
  436. package/Tests/RunicTests/CodexOAuthTests.swift +122 -0
  437. package/Tests/RunicTests/CodexUsageLogSourceTests.swift +82 -0
  438. package/Tests/RunicTests/CopilotTokenResolverTests.swift +75 -0
  439. package/Tests/RunicTests/CopilotVSCodeTokenReaderTests.swift +75 -0
  440. package/Tests/RunicTests/CostUsageDecodingTests.swift +394 -0
  441. package/Tests/RunicTests/CostUsagePricingTests.swift +50 -0
  442. package/Tests/RunicTests/CostUsageScannerTests.swift +700 -0
  443. package/Tests/RunicTests/CursorStatusProbeTests.swift +323 -0
  444. package/Tests/RunicTests/FactoryStatusProbeTests.swift +69 -0
  445. package/Tests/RunicTests/GeminiAPITestHelpers.swift +94 -0
  446. package/Tests/RunicTests/GeminiLoginAlertTests.swift +28 -0
  447. package/Tests/RunicTests/GeminiStatusProbeAPITests.swift +283 -0
  448. package/Tests/RunicTests/GeminiStatusProbePlanTests.swift +279 -0
  449. package/Tests/RunicTests/GeminiStatusProbeTests.swift +233 -0
  450. package/Tests/RunicTests/GeminiTestEnvironment.swift +87 -0
  451. package/Tests/RunicTests/GoogleWorkspaceStatusTests.swift +73 -0
  452. package/Tests/RunicTests/InstallOriginTests.swift +18 -0
  453. package/Tests/RunicTests/KeyboardShortcutsBundleTests.swift +9 -0
  454. package/Tests/RunicTests/LiveAccountTests.swift +24 -0
  455. package/Tests/RunicTests/LoadingPatternTests.swift +35 -0
  456. package/Tests/RunicTests/MenuCardModelTests.swift +545 -0
  457. package/Tests/RunicTests/MiniMaxCookieHeaderStoreTestSupport.swift +8 -0
  458. package/Tests/RunicTests/MiniMaxGroupIDStoreTestSupport.swift +8 -0
  459. package/Tests/RunicTests/MiniMaxParsingTests.swift +68 -0
  460. package/Tests/RunicTests/MiniMaxTokenStoreTestSupport.swift +8 -0
  461. package/Tests/RunicTests/OTelGenAILedgerAdapterTests.swift +112 -0
  462. package/Tests/RunicTests/OpenAIDashboardBrowserCookieImporterTests.swift +17 -0
  463. package/Tests/RunicTests/OpenAIDashboardFetcherCreditsWaitTests.swift +75 -0
  464. package/Tests/RunicTests/OpenAIDashboardOffscreenHostTests.swift +27 -0
  465. package/Tests/RunicTests/OpenAIDashboardParserTests.swift +134 -0
  466. package/Tests/RunicTests/OpenAIWebAccountSwitchTests.swift +53 -0
  467. package/Tests/RunicTests/OpenRouterTokenStoreTestSupport.swift +92 -0
  468. package/Tests/RunicTests/PathBuilderTests.swift +237 -0
  469. package/Tests/RunicTests/ProviderFetchPipelineTests.swift +160 -0
  470. package/Tests/RunicTests/ProviderIconResourcesTests.swift +38 -0
  471. package/Tests/RunicTests/ProviderMetadataStatusLinkTests.swift +16 -0
  472. package/Tests/RunicTests/ProviderRegistryTests.swift +29 -0
  473. package/Tests/RunicTests/ProviderSettingsDescriptorTests.swift +202 -0
  474. package/Tests/RunicTests/ProviderToggleStoreTests.swift +51 -0
  475. package/Tests/RunicTests/RunicTests.swift +120 -0
  476. package/Tests/RunicTests/SessionQuotaNotificationLogicTests.swift +36 -0
  477. package/Tests/RunicTests/SettingsStoreTests.swift +161 -0
  478. package/Tests/RunicTests/StatusItemAnimationTests.swift +49 -0
  479. package/Tests/RunicTests/StatusMenuTests.swift +434 -0
  480. package/Tests/RunicTests/StatusProbeTests.swift +377 -0
  481. package/Tests/RunicTests/SubprocessRunnerTests.swift +20 -0
  482. package/Tests/RunicTests/SubscriptionDetectionTests.swift +65 -0
  483. package/Tests/RunicTests/TTYCommandRunnerTests.swift +148 -0
  484. package/Tests/RunicTests/TTYIntegrationTests.swift +41 -0
  485. package/Tests/RunicTests/TeamShowbackExporterTests.swift +159 -0
  486. package/Tests/RunicTests/TextParsingTests.swift +12 -0
  487. package/Tests/RunicTests/UsageFormatterTests.swift +112 -0
  488. package/Tests/RunicTests/UsageLedgerAnomalyDetectionTests.swift +172 -0
  489. package/Tests/RunicTests/UsageLedgerForecastTests.swift +213 -0
  490. package/Tests/RunicTests/UsageLedgerInsightsAdvisorTests.swift +83 -0
  491. package/Tests/RunicTests/UsageLedgerProjectNameTests.swift +170 -0
  492. package/Tests/RunicTests/UsagePaceTests.swift +77 -0
  493. package/Tests/RunicTests/UsagePaceTextTests.swift +109 -0
  494. package/Tests/RunicTests/UsagePolicyEngineTests.swift +91 -0
  495. package/Tests/RunicTests/WidgetSnapshotTests.swift +45 -0
  496. package/Tests/RunicTests/ZaiProviderTests.swift +61 -0
  497. package/Tests/RunicTests/ZaiTokenStoreTestSupport.swift +6 -0
  498. package/TestsLinux/PlatformGatingTests.swift +46 -0
  499. package/appcast.xml +105 -0
  500. package/assets/logo-concept-stack.svg +24 -0
  501. package/assets/logo-minimal-bars.svg +15 -0
  502. package/assets/logo.svg +20 -0
  503. package/assets/logo2.svg +43 -0
  504. package/bin/docs-list +5 -0
  505. package/bin/install-runic-cli.sh +32 -0
  506. package/build-and-run.sh +369 -0
  507. package/docs/.nojekyll +1 -0
  508. package/docs/CNAME +1 -0
  509. package/docs/antigravity.md +75 -0
  510. package/docs/architecture.md +32 -0
  511. package/docs/claude.md +93 -0
  512. package/docs/cli-commands/integration_guide.md +371 -0
  513. package/docs/cli-commands/quick_reference.md +362 -0
  514. package/docs/cli-commands/readme.md +361 -0
  515. package/docs/cli.md +156 -0
  516. package/docs/cloudkit_sync_guide.md +495 -0
  517. package/docs/codebase_review.md +288 -0
  518. package/docs/codex-oauth.md +635 -0
  519. package/docs/codex.md +104 -0
  520. package/docs/codexbar.png +0 -0
  521. package/docs/copilot.md +44 -0
  522. package/docs/cursor.md +46 -0
  523. package/docs/design/designcomparisonchart.md +510 -0
  524. package/docs/design/implementationguide.md +792 -0
  525. package/docs/design/menubaricondesignconcepts.md +796 -0
  526. package/docs/design/mockups/hybridiconconcept.svg +62 -0
  527. package/docs/design/mockups/infinityiconconcept.svg +41 -0
  528. package/docs/design/mockups/infinityiconstates.svg +129 -0
  529. package/docs/design/mockups/wavelogorefined.svg +48 -0
  530. package/docs/design/quick_summary.md +426 -0
  531. package/docs/design/readme.md +478 -0
  532. package/docs/design/sizespecifications.md +575 -0
  533. package/docs/design-system.md +836 -0
  534. package/docs/factory.md +103 -0
  535. package/docs/gemini.md +73 -0
  536. package/docs/icon.md +37 -0
  537. package/docs/icon.png +0 -0
  538. package/docs/index.html +175 -0
  539. package/docs/keychain_fix.md +274 -0
  540. package/docs/minimax.md +71 -0
  541. package/docs/packaging.md +25 -0
  542. package/docs/progress-bar-improvements.md +240 -0
  543. package/docs/progress-bar-quick-reference.md +283 -0
  544. package/docs/progress-bar-technical-details.md +432 -0
  545. package/docs/progress-bar-visual-test.swift +375 -0
  546. package/docs/provider.md +202 -0
  547. package/docs/providers.md +86 -0
  548. package/docs/refactor/macros.md +35 -0
  549. package/docs/refresh-loop.md +22 -0
  550. package/docs/releasing-homebrew.md +35 -0
  551. package/docs/releasing.md +121 -0
  552. package/docs/research/concrete_todo_2026-02-22.md +47 -0
  553. package/docs/research/core-feature-research.md +248 -0
  554. package/docs/research/feature_uiux_roadmap_2026-02-22.md +202 -0
  555. package/docs/research/parity_matrix.md +49 -0
  556. package/docs/research/provider_expansion_candidates_2026-02-22.md +80 -0
  557. package/docs/research/provider_model_token_project_matrix_2026-02-23.md +46 -0
  558. package/docs/research/release_gate_checklist.md +57 -0
  559. package/docs/site.css +505 -0
  560. package/docs/sparkle.md +28 -0
  561. package/docs/status.md +28 -0
  562. package/docs/sync/implementation.md +393 -0
  563. package/docs/sync/readme.md +317 -0
  564. package/docs/sync_files_summary.md +391 -0
  565. package/docs/sync_quick_reference.md +225 -0
  566. package/docs/todo.md +11 -0
  567. package/docs/ui.md +29 -0
  568. package/docs/web-integration.md +9 -0
  569. package/docs/widgets.md +85 -0
  570. package/docs/workflows/error-handling-improvements.md +434 -0
  571. package/docs/workflows/folder_structure.md +299 -0
  572. package/docs/workflows/loading_states.md +446 -0
  573. package/docs/workflows/loading_states_examples.md +565 -0
  574. package/docs/workflows/loading_states_flow.md +430 -0
  575. package/docs/workflows/performance_optimizations.md +457 -0
  576. package/docs/workflows/phase1-cli-testing-report.md +313 -0
  577. package/docs/workflows/quick_reference.md +228 -0
  578. package/docs/workflows/readme.md +59 -0
  579. package/docs/workflows/recent_improvements.md +275 -0
  580. package/docs/workflows/sync_enablement_summary.md +400 -0
  581. package/docs/zai.md +43 -0
  582. package/package.json +36 -0
  583. package/runic.png +0 -0
  584. package/version.env +2 -0
@@ -0,0 +1,326 @@
1
+ import Foundation
2
+
3
+ #if canImport(FoundationNetworking)
4
+ import FoundationNetworking
5
+ #endif
6
+
7
+ /// High-level API for enumerating and reading browser cookies.
8
+ public struct BrowserCookieClient: Sendable {
9
+ public enum MutationError: LocalizedError, Sendable {
10
+ case duplicateCookie(details: String)
11
+ case missingCookie(details: String)
12
+
13
+ public var errorDescription: String? {
14
+ switch self {
15
+ case let .duplicateCookie(details):
16
+ return "Cookie already exists: \(details)"
17
+ case let .missingCookie(details):
18
+ return "Cookie not found: \(details)"
19
+ }
20
+ }
21
+ }
22
+
23
+ public struct Configuration: Sendable {
24
+ public var homeDirectories: [URL]
25
+ public var decryptionFailurePolicy: BrowserCookieDecryptionFailurePolicy
26
+
27
+ public init(
28
+ homeDirectories: [URL] = Self.defaultHomeDirectories(),
29
+ decryptionFailurePolicy: BrowserCookieDecryptionFailurePolicy = .bestEffort)
30
+ {
31
+ self.homeDirectories = homeDirectories
32
+ self.decryptionFailurePolicy = decryptionFailurePolicy
33
+ }
34
+
35
+ public static func defaultHomeDirectories() -> [URL] {
36
+ var dirs: [URL] = []
37
+ #if os(macOS) || os(iOS)
38
+ dirs.append(FileManager.default.homeDirectoryForCurrentUser)
39
+ #elseif os(Linux) || os(Windows)
40
+ if let home = ProcessInfo.processInfo.environment["HOME"] {
41
+ dirs.append(URL(fileURLWithPath: home))
42
+ }
43
+ #endif
44
+ return dirs
45
+ }
46
+ }
47
+
48
+ public let configuration: Configuration
49
+
50
+ public init(configuration: Configuration = Configuration()) {
51
+ self.configuration = configuration
52
+ }
53
+
54
+ /// Returns cookie stores for a specific browser.
55
+ public func stores(for browser: Browser) -> [BrowserCookieStore] {
56
+ Self.backend(for: browser).stores(for: browser, configuration: self.configuration)
57
+ }
58
+
59
+ /// Returns cookie stores for multiple browsers.
60
+ public func stores(in browsers: [Browser]) -> [BrowserCookieStore] {
61
+ browsers.flatMap { self.stores(for: $0) }
62
+ }
63
+
64
+ /// Loads cookie records from multiple browsers.
65
+ public func records(
66
+ matching query: BrowserCookieQuery,
67
+ in browsers: [Browser]) throws -> [BrowserCookieStoreRecords]
68
+ {
69
+ try browsers.flatMap { try self.records(matching: query, in: $0) }
70
+ }
71
+
72
+ /// Loads cookie records from a specific browser.
73
+ public func records(
74
+ matching query: BrowserCookieQuery,
75
+ in browser: Browser) throws -> [BrowserCookieStoreRecords]
76
+ {
77
+ let stores = self.stores(for: browser)
78
+ return try stores.compactMap { store in
79
+ let records = try self.records(matching: query, in: store)
80
+ guard !records.isEmpty else { return nil }
81
+ return BrowserCookieStoreRecords(store: store, records: records)
82
+ }
83
+ }
84
+
85
+ /// Loads cookie records from a specific cookie store.
86
+ public func records(
87
+ matching query: BrowserCookieQuery,
88
+ in store: BrowserCookieStore) throws -> [BrowserCookieRecord]
89
+ {
90
+ let records = try Self.backend(for: store.browser).records(
91
+ matching: query,
92
+ in: store,
93
+ configuration: self.configuration)
94
+ return try Self.apply(query: query, to: records)
95
+ }
96
+
97
+ /// Loads HTTPCookie values from a specific store.
98
+ public func cookies(
99
+ matching query: BrowserCookieQuery,
100
+ in store: BrowserCookieStore) throws -> [HTTPCookie]
101
+ {
102
+ let records = try self.records(matching: query, in: store)
103
+ return Self.makeHTTPCookies(records, origin: query.origin)
104
+ }
105
+
106
+ /// Loads HTTPCookie values from multiple browser stores.
107
+ public func cookies(
108
+ matching query: BrowserCookieQuery,
109
+ in browser: Browser) throws -> [HTTPCookie]
110
+ {
111
+ let sources = try self.records(matching: query, in: browser)
112
+ return sources.flatMap { $0.cookies(origin: query.origin) }
113
+ }
114
+
115
+ /// Loads HTTPCookie values from multiple browsers.
116
+ public func cookies(
117
+ matching query: BrowserCookieQuery,
118
+ in browsers: [Browser]) throws -> [HTTPCookie]
119
+ {
120
+ let sources = try self.records(matching: query, in: browsers)
121
+ return sources.flatMap { $0.cookies(origin: query.origin) }
122
+ }
123
+
124
+ /// Convert cookie records into HTTPCookie values.
125
+ public static func makeHTTPCookies(
126
+ _ records: [BrowserCookieRecord],
127
+ origin: BrowserCookieOriginStrategy = .domainBased) -> [HTTPCookie]
128
+ {
129
+ records.compactMap { record in
130
+ let host = record.domain.trimmingCharacters(in: .whitespacesAndNewlines)
131
+ guard !host.isEmpty else { return nil }
132
+ let domain = record.isHostOnly ? host : ".\(host)"
133
+ var props: [HTTPCookiePropertyKey: Any] = [
134
+ .domain: domain,
135
+ .name: record.name,
136
+ .path: record.path,
137
+ .value: record.value,
138
+ ]
139
+ if record.isSecure {
140
+ props[.secure] = "TRUE"
141
+ }
142
+ if record.isHTTPOnly {
143
+ props[HTTPCookiePropertyKey("HttpOnly")] = "TRUE"
144
+ }
145
+ if let expires = record.expires {
146
+ props[.expires] = expires
147
+ }
148
+ if let sameSite = record.sameSite {
149
+ props[HTTPCookiePropertyKey("SameSite")] = sameSite.propertyValue
150
+ }
151
+ if let originURL = origin.resolve(domain: host) {
152
+ props[.originURL] = originURL
153
+ }
154
+ return HTTPCookie(properties: props)
155
+ }
156
+ }
157
+
158
+ private static func backend(for browser: Browser) -> BrowserCookieBackend {
159
+ BrowserCookieBackendRegistry.backend(for: browser)
160
+ }
161
+
162
+ static func apply(
163
+ query: BrowserCookieQuery,
164
+ to records: [BrowserCookieRecord]) throws -> [BrowserCookieRecord]
165
+ {
166
+ var filtered = records
167
+
168
+ if !query.includeExpired {
169
+ filtered = filtered.filter { record in
170
+ guard let expires = record.expires else { return true }
171
+ return expires >= query.referenceDate
172
+ }
173
+ }
174
+
175
+ if query.excludeSession {
176
+ filtered = filtered.filter { !$0.isSession }
177
+ }
178
+
179
+ if let minExpiry = query.minExpiryDate {
180
+ filtered = filtered.filter { record in
181
+ guard let expires = record.expires else { return false }
182
+ return expires >= minExpiry
183
+ }
184
+ }
185
+
186
+ if let maxExpiry = query.maxExpiryDate {
187
+ filtered = filtered.filter { record in
188
+ guard let expires = record.expires else { return false }
189
+ return expires <= maxExpiry
190
+ }
191
+ }
192
+
193
+ if let secureOnly = query.secureOnly {
194
+ filtered = filtered.filter { $0.isSecure == secureOnly }
195
+ }
196
+
197
+ if let httpOnlyOnly = query.httpOnlyOnly {
198
+ filtered = filtered.filter { $0.isHTTPOnly == httpOnlyOnly }
199
+ }
200
+
201
+ if let sameSite = query.sameSite {
202
+ filtered = filtered.filter { $0.sameSite == sameSite }
203
+ }
204
+
205
+ if !query.paths.isEmpty {
206
+ filtered = filtered.filter { record in
207
+ Self.matchesPath(record.path, patterns: query.paths, match: query.pathMatch)
208
+ }
209
+ }
210
+
211
+ if query.useRegex, let pattern = query.pathPattern, !pattern.isEmpty {
212
+ let regex: NSRegularExpression
213
+ do {
214
+ regex = try NSRegularExpression(pattern: pattern, options: [])
215
+ } catch {
216
+ throw BrowserCookieQueryError.invalidPathPattern(pattern)
217
+ }
218
+ filtered = filtered.filter { record in
219
+ let range = NSRange(record.path.startIndex..<record.path.endIndex, in: record.path)
220
+ return regex.firstMatch(in: record.path, options: [], range: range) != nil
221
+ }
222
+ }
223
+
224
+ if !query.domains.isEmpty {
225
+ filtered = filtered.filter { record in
226
+ Self.matchesDomain(record.domain, patterns: query.domains, match: query.domainMatch)
227
+ }
228
+ }
229
+
230
+ if query.useRegex, let pattern = query.domainPattern, !pattern.isEmpty {
231
+ let regex: NSRegularExpression
232
+ do {
233
+ regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive])
234
+ } catch {
235
+ throw BrowserCookieQueryError.invalidDomainPattern(pattern)
236
+ }
237
+ filtered = filtered.filter { record in
238
+ let range = NSRange(record.domain.startIndex..<record.domain.endIndex, in: record.domain)
239
+ return regex.firstMatch(in: record.domain, options: [], range: range) != nil
240
+ }
241
+ }
242
+
243
+ return filtered
244
+ }
245
+
246
+ private static func matchesDomain(
247
+ _ domain: String,
248
+ patterns: [String],
249
+ match: BrowserCookieDomainMatch) -> Bool
250
+ {
251
+ let host = domain.lowercased()
252
+ for pattern in patterns {
253
+ let trimmed = pattern.trimmingCharacters(in: .whitespacesAndNewlines)
254
+ if trimmed.isEmpty { continue }
255
+ let normalized = trimmed.hasPrefix(".") ? String(trimmed.dropFirst()) : trimmed
256
+ let target = normalized.lowercased()
257
+ switch match {
258
+ case .contains:
259
+ if host.contains(target) { return true }
260
+ case .suffix:
261
+ if host == target || host.hasSuffix(".\(target)") { return true }
262
+ case .exact:
263
+ if host == target { return true }
264
+ }
265
+ }
266
+ return false
267
+ }
268
+
269
+ private static func matchesPath(
270
+ _ path: String,
271
+ patterns: [String],
272
+ match: BrowserCookiePathMatch) -> Bool
273
+ {
274
+ for pattern in patterns {
275
+ if pattern.isEmpty { continue }
276
+ switch match {
277
+ case .contains:
278
+ if path.contains(pattern) { return true }
279
+ case .prefix:
280
+ if path.hasPrefix(pattern) { return true }
281
+ case .exact:
282
+ if path == pattern { return true }
283
+ }
284
+ }
285
+ return false
286
+ }
287
+ }
288
+
289
+ public extension BrowserCookieClient {
290
+ func records(
291
+ matching query: BrowserCookieQuery,
292
+ in store: BrowserCookieMockStore) throws -> [BrowserCookieRecord]
293
+ {
294
+ try store.records(matching: query)
295
+ }
296
+
297
+ func cookies(
298
+ matching query: BrowserCookieQuery,
299
+ in store: BrowserCookieMockStore) throws -> [HTTPCookie]
300
+ {
301
+ let records = try store.records(matching: query)
302
+ return Self.makeHTTPCookies(records, origin: query.origin)
303
+ }
304
+
305
+ func create(_ record: BrowserCookieRecord, in store: BrowserCookieMockStore) throws {
306
+ try store.create(record)
307
+ }
308
+
309
+ func update(_ record: BrowserCookieRecord, in store: BrowserCookieMockStore) throws {
310
+ try store.update(record)
311
+ }
312
+
313
+ func upsert(_ record: BrowserCookieRecord, in store: BrowserCookieMockStore) {
314
+ store.upsert(record)
315
+ }
316
+
317
+ @discardableResult
318
+ func delete(_ record: BrowserCookieRecord, in store: BrowserCookieMockStore) -> Bool {
319
+ store.delete(record)
320
+ }
321
+
322
+ @discardableResult
323
+ func delete(matching query: BrowserCookieQuery, in store: BrowserCookieMockStore) throws -> Int {
324
+ try store.delete(matching: query)
325
+ }
326
+ }
@@ -0,0 +1,154 @@
1
+ import Foundation
2
+
3
+ public struct BrowserCookieExportRecord: Codable, Sendable {
4
+ public let domain: String
5
+ public let name: String
6
+ public let path: String
7
+ public let value: String
8
+ public let expires: Date?
9
+ public let createdAt: Date?
10
+ public let lastAccessedAt: Date?
11
+ public let isSecure: Bool
12
+ public let isHTTPOnly: Bool
13
+ public let isHostOnly: Bool?
14
+ public let sameSite: BrowserCookieSameSite?
15
+ public let priority: BrowserCookiePriority?
16
+ public let partitionKey: String?
17
+ public let isSameParty: Bool?
18
+
19
+ public init(record: BrowserCookieRecord) {
20
+ self.domain = record.domain
21
+ self.name = record.name
22
+ self.path = record.path
23
+ self.value = record.value
24
+ self.expires = record.expires
25
+ self.createdAt = record.createdAt
26
+ self.lastAccessedAt = record.lastAccessedAt
27
+ self.isSecure = record.isSecure
28
+ self.isHTTPOnly = record.isHTTPOnly
29
+ self.isHostOnly = record.isHostOnly
30
+ self.sameSite = record.sameSite
31
+ self.priority = record.priority
32
+ self.partitionKey = record.partitionKey
33
+ self.isSameParty = record.isSameParty
34
+ }
35
+ }
36
+
37
+ public struct BrowserCookieStoreExport: Codable, Sendable {
38
+ public let browser: Browser
39
+ public let profileId: String
40
+ public let profileName: String
41
+ public let kind: BrowserCookieStoreKind
42
+ public let label: String
43
+ public let records: [BrowserCookieExportRecord]
44
+
45
+ public init(store: BrowserCookieStore, records: [BrowserCookieRecord]) {
46
+ self.browser = store.browser
47
+ self.profileId = store.profile.id
48
+ self.profileName = store.profile.name
49
+ self.kind = store.kind
50
+ self.label = store.label
51
+ self.records = records.map(BrowserCookieExportRecord.init(record:))
52
+ }
53
+ }
54
+
55
+ public struct BrowserCookieExport: Codable, Sendable {
56
+ public let schemaVersion: Int
57
+ public let generatedAt: Date
58
+ public let stores: [BrowserCookieStoreExport]
59
+
60
+ public init(
61
+ schemaVersion: Int = 1,
62
+ generatedAt: Date = Date(),
63
+ stores: [BrowserCookieStoreExport])
64
+ {
65
+ self.schemaVersion = schemaVersion
66
+ self.generatedAt = generatedAt
67
+ self.stores = stores
68
+ }
69
+
70
+ public func jsonData(
71
+ prettyPrinted: Bool = true,
72
+ dateEncodingStrategy: JSONEncoder.DateEncodingStrategy = .iso8601) throws -> Data
73
+ {
74
+ let encoder = JSONEncoder()
75
+ encoder.dateEncodingStrategy = dateEncodingStrategy
76
+ if prettyPrinted {
77
+ encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
78
+ }
79
+ return try encoder.encode(self)
80
+ }
81
+
82
+ private enum CodingKeys: String, CodingKey {
83
+ case schemaVersion
84
+ case generatedAt
85
+ case stores
86
+ }
87
+
88
+ public init(from decoder: Decoder) throws {
89
+ let container = try decoder.container(keyedBy: CodingKeys.self)
90
+ self.schemaVersion = (try? container.decode(Int.self, forKey: .schemaVersion)) ?? 1
91
+ self.generatedAt = try container.decode(Date.self, forKey: .generatedAt)
92
+ self.stores = try container.decode([BrowserCookieStoreExport].self, forKey: .stores)
93
+ }
94
+
95
+ public func encode(to encoder: Encoder) throws {
96
+ var container = encoder.container(keyedBy: CodingKeys.self)
97
+ try container.encode(schemaVersion, forKey: .schemaVersion)
98
+ try container.encode(generatedAt, forKey: .generatedAt)
99
+ try container.encode(stores, forKey: .stores)
100
+ }
101
+ }
102
+
103
+ public extension BrowserCookieClient {
104
+ func export(
105
+ matching query: BrowserCookieQuery,
106
+ in store: BrowserCookieStore) throws -> BrowserCookieExport
107
+ {
108
+ let records = try self.records(matching: query, in: store)
109
+ let exportStore = BrowserCookieStoreExport(store: store, records: records)
110
+ return BrowserCookieExport(stores: [exportStore])
111
+ }
112
+
113
+ func export(
114
+ matching query: BrowserCookieQuery,
115
+ in browser: Browser) throws -> BrowserCookieExport
116
+ {
117
+ let sources = try self.records(matching: query, in: browser)
118
+ let stores = sources.map { BrowserCookieStoreExport(store: $0.store, records: $0.records) }
119
+ return BrowserCookieExport(stores: stores)
120
+ }
121
+
122
+ func export(
123
+ matching query: BrowserCookieQuery,
124
+ in browsers: [Browser]) throws -> BrowserCookieExport
125
+ {
126
+ let sources = try self.records(matching: query, in: browsers)
127
+ let stores = sources.map { BrowserCookieStoreExport(store: $0.store, records: $0.records) }
128
+ return BrowserCookieExport(stores: stores)
129
+ }
130
+
131
+ func exportJSON(
132
+ matching query: BrowserCookieQuery,
133
+ in store: BrowserCookieStore,
134
+ prettyPrinted: Bool = true) throws -> Data
135
+ {
136
+ try self.export(matching: query, in: store).jsonData(prettyPrinted: prettyPrinted)
137
+ }
138
+
139
+ func exportJSON(
140
+ matching query: BrowserCookieQuery,
141
+ in browser: Browser,
142
+ prettyPrinted: Bool = true) throws -> Data
143
+ {
144
+ try self.export(matching: query, in: browser).jsonData(prettyPrinted: prettyPrinted)
145
+ }
146
+
147
+ func exportJSON(
148
+ matching query: BrowserCookieQuery,
149
+ in browsers: [Browser],
150
+ prettyPrinted: Bool = true) throws -> Data
151
+ {
152
+ try self.export(matching: query, in: browsers).jsonData(prettyPrinted: prettyPrinted)
153
+ }
154
+ }
@@ -0,0 +1,119 @@
1
+ import Foundation
2
+
3
+ public struct BrowserCookieImportOptions: Sendable {
4
+ /// Default host-only behavior when the JSON payload does not specify it.
5
+ public var defaultHostOnly: Bool
6
+
7
+ public init(defaultHostOnly: Bool = true) {
8
+ self.defaultHostOnly = defaultHostOnly
9
+ }
10
+ }
11
+
12
+ public struct BrowserCookieImport: Sendable {
13
+ public let schemaVersion: Int
14
+ public let generatedAt: Date
15
+ public let stores: [BrowserCookieStoreRecords]
16
+
17
+ public init(schemaVersion: Int = 1, generatedAt: Date = Date(), stores: [BrowserCookieStoreRecords]) {
18
+ self.schemaVersion = schemaVersion
19
+ self.generatedAt = generatedAt
20
+ self.stores = stores
21
+ }
22
+
23
+ public var records: [BrowserCookieRecord] {
24
+ self.stores.flatMap(\.records)
25
+ }
26
+
27
+ public var browsers: [Browser] {
28
+ var seen: Set<Browser> = []
29
+ var ordered: [Browser] = []
30
+ for store in self.stores {
31
+ if seen.insert(store.store.browser).inserted {
32
+ ordered.append(store.store.browser)
33
+ }
34
+ }
35
+ return ordered
36
+ }
37
+
38
+ public init(
39
+ export: BrowserCookieExport,
40
+ options: BrowserCookieImportOptions = BrowserCookieImportOptions())
41
+ {
42
+ self.schemaVersion = export.schemaVersion
43
+ self.generatedAt = export.generatedAt
44
+ self.stores = export.stores.map { storeExport in
45
+ let store = BrowserCookieStore(
46
+ browser: storeExport.browser,
47
+ profile: BrowserProfile(id: storeExport.profileId, name: storeExport.profileName),
48
+ kind: storeExport.kind,
49
+ label: storeExport.label,
50
+ databaseURL: nil)
51
+ let records = storeExport.records.map { exportRecord in
52
+ Self.makeRecord(from: exportRecord, options: options)
53
+ }
54
+ return BrowserCookieStoreRecords(store: store, records: records)
55
+ }
56
+ }
57
+
58
+ public init(
59
+ data: Data,
60
+ dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .iso8601,
61
+ options: BrowserCookieImportOptions = BrowserCookieImportOptions()) throws
62
+ {
63
+ let decoder = JSONDecoder()
64
+ decoder.dateDecodingStrategy = dateDecodingStrategy
65
+ let export = try decoder.decode(BrowserCookieExport.self, from: data)
66
+ self.init(export: export, options: options)
67
+ }
68
+
69
+ private static func makeRecord(
70
+ from exportRecord: BrowserCookieExportRecord,
71
+ options: BrowserCookieImportOptions) -> BrowserCookieRecord
72
+ {
73
+ let hostOnlyOverride = hostOnlyOverride(
74
+ domain: exportRecord.domain,
75
+ isHostOnly: exportRecord.isHostOnly,
76
+ defaultHostOnly: options.defaultHostOnly)
77
+
78
+ return BrowserCookieRecord(
79
+ domain: exportRecord.domain,
80
+ name: exportRecord.name,
81
+ path: exportRecord.path,
82
+ value: exportRecord.value,
83
+ expires: exportRecord.expires,
84
+ createdAt: exportRecord.createdAt,
85
+ lastAccessedAt: exportRecord.lastAccessedAt,
86
+ isSecure: exportRecord.isSecure,
87
+ isHTTPOnly: exportRecord.isHTTPOnly,
88
+ isHostOnly: hostOnlyOverride,
89
+ sameSite: exportRecord.sameSite,
90
+ priority: exportRecord.priority,
91
+ partitionKey: exportRecord.partitionKey,
92
+ isSameParty: exportRecord.isSameParty)
93
+ }
94
+
95
+ private static func hostOnlyOverride(
96
+ domain: String,
97
+ isHostOnly: Bool?,
98
+ defaultHostOnly: Bool) -> Bool?
99
+ {
100
+ if let isHostOnly {
101
+ return isHostOnly
102
+ }
103
+ let trimmed = domain.trimmingCharacters(in: .whitespacesAndNewlines)
104
+ if trimmed.hasPrefix(".") {
105
+ return nil
106
+ }
107
+ return defaultHostOnly
108
+ }
109
+ }
110
+
111
+ public extension BrowserCookieClient {
112
+ func importJSON(
113
+ _ data: Data,
114
+ dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .iso8601,
115
+ options: BrowserCookieImportOptions = BrowserCookieImportOptions()) throws -> BrowserCookieImport
116
+ {
117
+ try BrowserCookieImport(data: data, dateDecodingStrategy: dateDecodingStrategy, options: options)
118
+ }
119
+ }