@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.
Files changed (610) hide show
  1. package/CHANGELOG.md +256 -0
  2. package/LICENSE +373 -21
  3. package/README.md +96 -89
  4. package/THIRD-PARTY-NOTICES.md +651 -0
  5. package/package.json +14 -4
  6. package/.swiftformat +0 -50
  7. package/.swiftlint.yml +0 -160
  8. package/CONTRIBUTING.md +0 -456
  9. package/Icon.icns +0 -0
  10. package/Icon.icon/Assets/runic.png +0 -0
  11. package/Icon.icon/icon.json +0 -36
  12. package/Package.resolved +0 -51
  13. package/Package.swift +0 -136
  14. package/Packages/Helix/LICENSE +0 -21
  15. package/Packages/Helix/Package.swift +0 -29
  16. package/Packages/Helix/README.md +0 -976
  17. package/Packages/Helix/Sources/Helix/Binding.swift +0 -111
  18. package/Packages/Helix/Sources/Helix/CommandParser.swift +0 -160
  19. package/Packages/Helix/Sources/Helix/CommandSignature.swift +0 -117
  20. package/Packages/Helix/Sources/Helix/ExpressibleFromArgument.swift +0 -72
  21. package/Packages/Helix/Sources/Helix/HelpGenerator.swift +0 -175
  22. package/Packages/Helix/Sources/Helix/NameSpecification.swift +0 -98
  23. package/Packages/Helix/Sources/Helix/ParsableCommand.swift +0 -204
  24. package/Packages/Helix/Sources/Helix/Platform/DarwinPlatformContext.swift +0 -44
  25. package/Packages/Helix/Sources/Helix/Platform/LinuxPlatformContext.swift +0 -34
  26. package/Packages/Helix/Sources/Helix/Platform/PlatformContext+Default.swift +0 -91
  27. package/Packages/Helix/Sources/Helix/Platform/PlatformContext.swift +0 -94
  28. package/Packages/Helix/Sources/Helix/Platform/PlatformPath.swift +0 -167
  29. package/Packages/Helix/Sources/Helix/Platform/Stdio.swift +0 -99
  30. package/Packages/Helix/Sources/Helix/Platform/WebPlatformContext.swift +0 -146
  31. package/Packages/Helix/Sources/Helix/Platform/WindowsPlatformContext.swift +0 -97
  32. package/Packages/Helix/Sources/Helix/Program.swift +0 -204
  33. package/Packages/Helix/Sources/Helix/PropertyWrappers.swift +0 -367
  34. package/Packages/Silo/LICENSE +0 -21
  35. package/Packages/Silo/Package.swift +0 -34
  36. package/Packages/Silo/README.md +0 -466
  37. package/Packages/Silo/Sources/Silo/BinaryCookiesReader.swift +0 -169
  38. package/Packages/Silo/Sources/Silo/BrowserCookieAnalytics.swift +0 -365
  39. package/Packages/Silo/Sources/Silo/BrowserCookieBackends.swift +0 -594
  40. package/Packages/Silo/Sources/Silo/BrowserCookieClient.swift +0 -326
  41. package/Packages/Silo/Sources/Silo/BrowserCookieExport.swift +0 -154
  42. package/Packages/Silo/Sources/Silo/BrowserCookieImport.swift +0 -119
  43. package/Packages/Silo/Sources/Silo/BrowserCookieMockStore.swift +0 -121
  44. package/Packages/Silo/Sources/Silo/BrowserCookieModels.swift +0 -391
  45. package/Packages/Silo/Sources/Silo/ChromiumCookieReader.swift +0 -240
  46. package/Packages/Silo/Sources/Silo/CryptoSupport.swift +0 -86
  47. package/Packages/Silo/Sources/Silo/FirefoxCookieReader.swift +0 -172
  48. package/Packages/Silo/Sources/Silo/LinuxChromiumCookieReader.swift +0 -172
  49. package/Packages/Silo/Sources/Silo/LinuxSecretService.swift +0 -105
  50. package/Packages/Silo/Sources/Silo/MacOSChromiumCookieReader.swift +0 -191
  51. package/Packages/Silo/Sources/Silo/SQLiteSnapshot.swift +0 -41
  52. package/Packages/Silo/Sources/Silo/WindowsChromiumCookieReader.swift +0 -110
  53. package/RuniciOS/App/RuniciOSApp.swift +0 -105
  54. package/RuniciOS/Core/RunicTypographyiOS.swift +0 -24
  55. package/RuniciOS/Core/iOSUsageStore.swift +0 -192
  56. package/RuniciOS/Views/ProviderDetailView.swift +0 -312
  57. package/RuniciOS/Views/ProviderListView.swift +0 -228
  58. package/RuniciOS/Widgets/LargeWidget.swift +0 -367
  59. package/RuniciOS/Widgets/LiveActivity.swift +0 -342
  60. package/RuniciOS/Widgets/LockScreenWidget.swift +0 -273
  61. package/RuniciOS/Widgets/MediumWidget.swift +0 -370
  62. package/RuniciOS/Widgets/RunicWidget.swift +0 -274
  63. package/RuniciOS/Widgets/SmallWidget.swift +0 -281
  64. package/RuniciOS/Widgets/WidgetModels.swift +0 -285
  65. package/RuniciOS/Widgets/WidgetTimeline.swift +0 -270
  66. package/Scripts/CREATION-SUMMARY.md +0 -367
  67. package/Scripts/DIRECTORY-STRUCTURE.md +0 -358
  68. package/Scripts/GETTING-STARTED-CHECKLIST.md +0 -364
  69. package/Scripts/INDEX.md +0 -365
  70. package/Scripts/QUICK-REFERENCE.md +0 -164
  71. package/Scripts/README-SCRIPTS.md +0 -926
  72. package/Scripts/build-android.sh +0 -526
  73. package/Scripts/build-ios.sh +0 -529
  74. package/Scripts/build-macos.sh +0 -603
  75. package/Scripts/build-windows.sh +0 -504
  76. package/Scripts/build_icon.sh +0 -49
  77. package/Scripts/changelog-to-html.sh +0 -89
  78. package/Scripts/check-release-assets.sh +0 -10
  79. package/Scripts/ci-config.yml +0 -474
  80. package/Scripts/compile_and_run.sh +0 -219
  81. package/Scripts/compile_and_run_adhoc.sh +0 -4
  82. package/Scripts/docs-list.mjs +0 -119
  83. package/Scripts/make_appcast.sh +0 -58
  84. package/Scripts/package_app.sh +0 -409
  85. package/Scripts/release-lib.sh +0 -214
  86. package/Scripts/release.sh +0 -76
  87. package/Scripts/setup-all.sh +0 -387
  88. package/Scripts/setup-ios.sh +0 -404
  89. package/Scripts/setup-react-native.sh +0 -523
  90. package/Scripts/sign-and-notarize.sh +0 -122
  91. package/Scripts/test_live_update.sh +0 -38
  92. package/Scripts/validate_changelog.sh +0 -23
  93. package/Scripts/verify_appcast.sh +0 -92
  94. package/Sources/Runic/About.swift +0 -93
  95. package/Sources/Runic/AppNotifications.swift +0 -117
  96. package/Sources/Runic/Controllers/StatusItemController+Actions.swift +0 -670
  97. package/Sources/Runic/Controllers/StatusItemController+Animation.swift +0 -519
  98. package/Sources/Runic/Controllers/StatusItemController+ChartSubmenus.swift +0 -824
  99. package/Sources/Runic/Controllers/StatusItemController+CustomProviders.swift +0 -90
  100. package/Sources/Runic/Controllers/StatusItemController+Menu.swift +0 -1412
  101. package/Sources/Runic/Controllers/StatusItemController+MenuCards.swift +0 -339
  102. package/Sources/Runic/Controllers/StatusItemController+MenuHelpers.swift +0 -423
  103. package/Sources/Runic/Controllers/StatusItemController.swift +0 -360
  104. package/Sources/Runic/Core/BudgetNotificationManager.swift +0 -81
  105. package/Sources/Runic/Core/Login/ClaudeLoginRunner.swift +0 -103
  106. package/Sources/Runic/Core/Login/CodexLoginRunner.swift +0 -154
  107. package/Sources/Runic/Core/Login/CursorLoginRunner.swift +0 -206
  108. package/Sources/Runic/Core/Login/GeminiLoginRunner.swift +0 -92
  109. package/Sources/Runic/Core/Rendering/IconRenderer.swift +0 -1222
  110. package/Sources/Runic/Core/Rendering/IconView.swift +0 -122
  111. package/Sources/Runic/Core/Rendering/ProviderBrandIcon.swift +0 -71
  112. package/Sources/Runic/Core/RunicAnimation.swift +0 -53
  113. package/Sources/Runic/Core/RunicColors.swift +0 -73
  114. package/Sources/Runic/Core/RunicCornerRadius.swift +0 -15
  115. package/Sources/Runic/Core/RunicSpacing.swift +0 -68
  116. package/Sources/Runic/Core/RunicTypography.swift +0 -206
  117. package/Sources/Runic/Core/Stores/AuggieTokenStore.swift +0 -117
  118. package/Sources/Runic/Core/Stores/AzureOpenAITokenStore.swift +0 -117
  119. package/Sources/Runic/Core/Stores/CerebrasTokenStore.swift +0 -117
  120. package/Sources/Runic/Core/Stores/CohereTokenStore.swift +0 -117
  121. package/Sources/Runic/Core/Stores/CopilotTokenStore.swift +0 -117
  122. package/Sources/Runic/Core/Stores/CustomProviderStore.swift +0 -158
  123. package/Sources/Runic/Core/Stores/DeepSeekTokenStore.swift +0 -117
  124. package/Sources/Runic/Core/Stores/FireworksTokenStore.swift +0 -117
  125. package/Sources/Runic/Core/Stores/GroqTokenStore.swift +0 -117
  126. package/Sources/Runic/Core/Stores/KimiTokenStore.swift +0 -117
  127. package/Sources/Runic/Core/Stores/MiniMaxCookieHeaderStore.swift +0 -117
  128. package/Sources/Runic/Core/Stores/MiniMaxGroupIDStore.swift +0 -117
  129. package/Sources/Runic/Core/Stores/MiniMaxTokenStore.swift +0 -117
  130. package/Sources/Runic/Core/Stores/MistralTokenStore.swift +0 -117
  131. package/Sources/Runic/Core/Stores/OpenRouterTokenStore.swift +0 -117
  132. package/Sources/Runic/Core/Stores/PerplexityTokenStore.swift +0 -117
  133. package/Sources/Runic/Core/Stores/ProviderToggleStore.swift +0 -30
  134. package/Sources/Runic/Core/Stores/QwenTokenStore.swift +0 -117
  135. package/Sources/Runic/Core/Stores/SambaNovaTokenStore.swift +0 -117
  136. package/Sources/Runic/Core/Stores/SettingsStore.swift +0 -1749
  137. package/Sources/Runic/Core/Stores/TogetherTokenStore.swift +0 -117
  138. package/Sources/Runic/Core/Stores/UsageStore+Accessors.swift +0 -33
  139. package/Sources/Runic/Core/Stores/UsageStore+Status.swift +0 -189
  140. package/Sources/Runic/Core/Stores/UsageStore+TokenCost.swift +0 -33
  141. package/Sources/Runic/Core/Stores/UsageStore+WidgetSnapshot.swift +0 -67
  142. package/Sources/Runic/Core/Stores/UsageStore.swift +0 -3631
  143. package/Sources/Runic/Core/Stores/XAITokenStore.swift +0 -117
  144. package/Sources/Runic/Core/Stores/ZaiTokenStore.swift +0 -117
  145. package/Sources/Runic/Core/UsageExporter.swift +0 -197
  146. package/Sources/Runic/Date+RelativeDescription.swift +0 -21
  147. package/Sources/Runic/HiddenWindowView.swift +0 -32
  148. package/Sources/Runic/InstallOrigin.swift +0 -9
  149. package/Sources/Runic/KeyboardShortcuts+Names.swift +0 -6
  150. package/Sources/Runic/MouseLocationReader.swift +0 -65
  151. package/Sources/Runic/Notifications+Runic.swift +0 -6
  152. package/Sources/Runic/OpenAICreditsPurchaseWindowController.swift +0 -503
  153. package/Sources/Runic/ProviderRegistry.swift +0 -100
  154. package/Sources/Runic/ProviderSwitcherButtons.swift +0 -267
  155. package/Sources/Runic/Providers/Antigravity/AntigravityLoginFlow.swift +0 -11
  156. package/Sources/Runic/Providers/Antigravity/AntigravityProviderImplementation.swift +0 -14
  157. package/Sources/Runic/Providers/Auggie/AuggieProviderImplementation.swift +0 -24
  158. package/Sources/Runic/Providers/Azure/AzureProviderImplementation.swift +0 -52
  159. package/Sources/Runic/Providers/Bedrock/BedrockProviderImplementation.swift +0 -42
  160. package/Sources/Runic/Providers/Cerebras/CerebrasProviderImplementation.swift +0 -24
  161. package/Sources/Runic/Providers/Claude/ClaudeLoginFlow.swift +0 -26
  162. package/Sources/Runic/Providers/Claude/ClaudeProviderImplementation.swift +0 -14
  163. package/Sources/Runic/Providers/Codex/CodexLoginFlow.swift +0 -18
  164. package/Sources/Runic/Providers/Codex/CodexProviderImplementation.swift +0 -15
  165. package/Sources/Runic/Providers/Cohere/CohereProviderImplementation.swift +0 -24
  166. package/Sources/Runic/Providers/Copilot/CopilotLoginFlow.swift +0 -193
  167. package/Sources/Runic/Providers/Copilot/CopilotProviderImplementation.swift +0 -110
  168. package/Sources/Runic/Providers/Cursor/CursorLoginFlow.swift +0 -28
  169. package/Sources/Runic/Providers/Cursor/CursorProviderImplementation.swift +0 -15
  170. package/Sources/Runic/Providers/DeepSeek/DeepSeekProviderImplementation.swift +0 -24
  171. package/Sources/Runic/Providers/Factory/FactoryLoginFlow.swift +0 -12
  172. package/Sources/Runic/Providers/Factory/FactoryProviderImplementation.swift +0 -15
  173. package/Sources/Runic/Providers/Fireworks/FireworksProviderImplementation.swift +0 -24
  174. package/Sources/Runic/Providers/Gemini/GeminiLoginFlow.swift +0 -20
  175. package/Sources/Runic/Providers/Gemini/GeminiProviderImplementation.swift +0 -15
  176. package/Sources/Runic/Providers/Groq/GroqProviderImplementation.swift +0 -24
  177. package/Sources/Runic/Providers/Kimi/KimiProviderImplementation.swift +0 -24
  178. package/Sources/Runic/Providers/MiniMax/MiniMaxProviderImplementation.swift +0 -32
  179. package/Sources/Runic/Providers/Mistral/MistralProviderImplementation.swift +0 -24
  180. package/Sources/Runic/Providers/OpenRouter/OpenRouterProviderImplementation.swift +0 -24
  181. package/Sources/Runic/Providers/Perplexity/PerplexityProviderImplementation.swift +0 -24
  182. package/Sources/Runic/Providers/SambaNova/SambaNovaProviderImplementation.swift +0 -24
  183. package/Sources/Runic/Providers/Shared/ProviderCatalog.swift +0 -15
  184. package/Sources/Runic/Providers/Shared/ProviderImplementation.swift +0 -51
  185. package/Sources/Runic/Providers/Shared/ProviderImplementationRegistry.swift +0 -66
  186. package/Sources/Runic/Providers/Shared/ProviderLoginFlow.swift +0 -12
  187. package/Sources/Runic/Providers/Shared/ProviderSettingsDescriptors.swift +0 -99
  188. package/Sources/Runic/Providers/Shared/SystemSettingsLinks.swift +0 -18
  189. package/Sources/Runic/Providers/Together/TogetherProviderImplementation.swift +0 -24
  190. package/Sources/Runic/Providers/XAI/XAIProviderImplementation.swift +0 -24
  191. package/Sources/Runic/Providers/Zai/ZaiProviderImplementation.swift +0 -24
  192. package/Sources/Runic/Resources/Fonts/Caveat-Bold.ttf +0 -0
  193. package/Sources/Runic/Resources/Fonts/Caveat-Regular.ttf +0 -0
  194. package/Sources/Runic/Resources/Fonts/FiraCode-Bold.ttf +0 -0
  195. package/Sources/Runic/Resources/Fonts/FiraCode-Light.ttf +0 -0
  196. package/Sources/Runic/Resources/Fonts/FiraCode-Medium.ttf +0 -0
  197. package/Sources/Runic/Resources/Fonts/FiraCode-Regular.ttf +0 -0
  198. package/Sources/Runic/Resources/Fonts/FiraCode-SemiBold.ttf +0 -0
  199. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Bold.ttf +0 -0
  200. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Medium.ttf +0 -0
  201. package/Sources/Runic/Resources/Fonts/IBMPlexMono-Regular.ttf +0 -0
  202. package/Sources/Runic/Resources/Fonts/IBMPlexMono-SemiBold.ttf +0 -0
  203. package/Sources/Runic/Resources/Fonts/Inconsolata-Bold.ttf +0 -0
  204. package/Sources/Runic/Resources/Fonts/Inconsolata-Medium.ttf +0 -0
  205. package/Sources/Runic/Resources/Fonts/Inconsolata-Regular.ttf +0 -0
  206. package/Sources/Runic/Resources/Fonts/Inconsolata-SemiBold.ttf +0 -0
  207. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Bold.ttf +0 -0
  208. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Medium.ttf +0 -0
  209. package/Sources/Runic/Resources/Fonts/JetBrainsMono-Regular.ttf +0 -0
  210. package/Sources/Runic/Resources/Fonts/JetBrainsMono-SemiBold.ttf +0 -0
  211. package/Sources/Runic/Resources/Fonts/SpaceMono-Bold.ttf +0 -0
  212. package/Sources/Runic/Resources/Fonts/SpaceMono-Regular.ttf +0 -0
  213. package/Sources/Runic/Resources/ProviderIcon-antigravity.svg +0 -2
  214. package/Sources/Runic/Resources/ProviderIcon-auggie.svg +0 -3
  215. package/Sources/Runic/Resources/ProviderIcon-azure.svg +0 -5
  216. package/Sources/Runic/Resources/ProviderIcon-bedrock.svg +0 -7
  217. package/Sources/Runic/Resources/ProviderIcon-cerebras.svg +0 -3
  218. package/Sources/Runic/Resources/ProviderIcon-claude.svg +0 -1
  219. package/Sources/Runic/Resources/ProviderIcon-codex.svg +0 -1
  220. package/Sources/Runic/Resources/ProviderIcon-cohere.svg +0 -3
  221. package/Sources/Runic/Resources/ProviderIcon-copilot.svg +0 -1
  222. package/Sources/Runic/Resources/ProviderIcon-cursor.svg +0 -3
  223. package/Sources/Runic/Resources/ProviderIcon-deepseek.svg +0 -4
  224. package/Sources/Runic/Resources/ProviderIcon-factory.svg +0 -3
  225. package/Sources/Runic/Resources/ProviderIcon-fireworks.svg +0 -3
  226. package/Sources/Runic/Resources/ProviderIcon-gemini.svg +0 -1
  227. package/Sources/Runic/Resources/ProviderIcon-groq.svg +0 -1
  228. package/Sources/Runic/Resources/ProviderIcon-kimi.svg +0 -4
  229. package/Sources/Runic/Resources/ProviderIcon-minimax.svg +0 -1
  230. package/Sources/Runic/Resources/ProviderIcon-mistral.svg +0 -5
  231. package/Sources/Runic/Resources/ProviderIcon-openrouter.svg +0 -7
  232. package/Sources/Runic/Resources/ProviderIcon-perplexity.svg +0 -4
  233. package/Sources/Runic/Resources/ProviderIcon-qwen.svg +0 -9
  234. package/Sources/Runic/Resources/ProviderIcon-sambanova.svg +0 -4
  235. package/Sources/Runic/Resources/ProviderIcon-together.svg +0 -5
  236. package/Sources/Runic/Resources/ProviderIcon-vertexai.svg +0 -17
  237. package/Sources/Runic/Resources/ProviderIcon-xai.svg +0 -3
  238. package/Sources/Runic/Resources/ProviderIcon-zai.svg +0 -5
  239. package/Sources/Runic/Resources/RunicMenubarIcon.svg +0 -7
  240. package/Sources/Runic/Resources/provider-context-windows.json +0 -20
  241. package/Sources/Runic/RunicApp.swift +0 -367
  242. package/Sources/Runic/SessionQuotaNotifications.swift +0 -58
  243. package/Sources/Runic/UsagePaceText.swift +0 -52
  244. package/Sources/Runic/UsageProgressBar.swift +0 -228
  245. package/Sources/Runic/Utilities/DisplayLink.swift +0 -96
  246. package/Sources/Runic/Utilities/LoadingPattern.swift +0 -62
  247. package/Sources/Runic/Utilities/PerformanceConstants.swift +0 -85
  248. package/Sources/Runic/Views/Menu/AlertsMenuView.swift +0 -254
  249. package/Sources/Runic/Views/Menu/ChartPanelStyle.swift +0 -22
  250. package/Sources/Runic/Views/Menu/CostComparativeChartMenuView.swift +0 -275
  251. package/Sources/Runic/Views/Menu/CostHistoryChartMenuView.swift +0 -377
  252. package/Sources/Runic/Views/Menu/CreditsHistoryChartMenuView.swift +0 -312
  253. package/Sources/Runic/Views/Menu/EfficiencyMetricsMenuView.swift +0 -311
  254. package/Sources/Runic/Views/Menu/HeroStatCardsMenuView.swift +0 -231
  255. package/Sources/Runic/Views/Menu/HourlyActivityChartMenuView.swift +0 -228
  256. package/Sources/Runic/Views/Menu/InlineUsageChartView.swift +0 -157
  257. package/Sources/Runic/Views/Menu/MenuCardEntranceModifier.swift +0 -63
  258. package/Sources/Runic/Views/Menu/MenuCardSidebarView.swift +0 -248
  259. package/Sources/Runic/Views/Menu/MenuCardSkeletonView.swift +0 -104
  260. package/Sources/Runic/Views/Menu/MenuCardView.swift +0 -1889
  261. package/Sources/Runic/Views/Menu/MenuContent.swift +0 -153
  262. package/Sources/Runic/Views/Menu/MenuDescriptor.swift +0 -371
  263. package/Sources/Runic/Views/Menu/MenuHighlightStyle.swift +0 -35
  264. package/Sources/Runic/Views/Menu/ModelBreakdownMenuView.swift +0 -241
  265. package/Sources/Runic/Views/Menu/OverviewMenuView.swift +0 -281
  266. package/Sources/Runic/Views/Menu/ProjectBreakdownMenuView.swift +0 -214
  267. package/Sources/Runic/Views/Menu/ProjectBudgetMenuView.swift +0 -220
  268. package/Sources/Runic/Views/Menu/ProviderTabBarView.swift +0 -86
  269. package/Sources/Runic/Views/Menu/SubscriptionUtilizationChartMenuView.swift +0 -214
  270. package/Sources/Runic/Views/Menu/UsageBreakdownChartMenuView.swift +0 -398
  271. package/Sources/Runic/Views/Menu/UsageHeatmapMenuView.swift +0 -231
  272. package/Sources/Runic/Views/Menu/UsageTimelineChartMenuView.swift +0 -369
  273. package/Sources/Runic/Views/Menu/UsageWindowComparisonChartMenuView.swift +0 -191
  274. package/Sources/Runic/Views/Menu/WeeklyActivityChartMenuView.swift +0 -132
  275. package/Sources/Runic/Views/Performance/PerformanceDashboardView.swift +0 -621
  276. package/Sources/Runic/Views/Preferences/LiquidComponents.swift +0 -306
  277. package/Sources/Runic/Views/Preferences/PreferencesAboutPane.swift +0 -271
  278. package/Sources/Runic/Views/Preferences/PreferencesAdvancedPane.swift +0 -268
  279. package/Sources/Runic/Views/Preferences/PreferencesAlertsPane.swift +0 -418
  280. package/Sources/Runic/Views/Preferences/PreferencesAnalyticsPane.swift +0 -637
  281. package/Sources/Runic/Views/Preferences/PreferencesBudgetsPane.swift +0 -344
  282. package/Sources/Runic/Views/Preferences/PreferencesComponents.swift +0 -230
  283. package/Sources/Runic/Views/Preferences/PreferencesCustomProvidersPane.swift +0 -321
  284. package/Sources/Runic/Views/Preferences/PreferencesDebugPane.swift +0 -469
  285. package/Sources/Runic/Views/Preferences/PreferencesGeneralPane.swift +0 -250
  286. package/Sources/Runic/Views/Preferences/PreferencesHelpPane.swift +0 -50
  287. package/Sources/Runic/Views/Preferences/PreferencesIntegrationsPane.swift +0 -572
  288. package/Sources/Runic/Views/Preferences/PreferencesPerformancePane.swift +0 -291
  289. package/Sources/Runic/Views/Preferences/PreferencesProvidersPane.swift +0 -3480
  290. package/Sources/Runic/Views/Preferences/PreferencesSelection.swift +0 -29
  291. package/Sources/Runic/Views/Preferences/PreferencesSyncPane.swift +0 -61
  292. package/Sources/Runic/Views/Preferences/PreferencesView.swift +0 -213
  293. package/Sources/Runic/Views/Rating/QualityRatingView.swift +0 -238
  294. package/Sources/Runic/Views/Team/TeamDashboardView.swift +0 -376
  295. package/Sources/Runic/Views/Team/TeamInviteSheet.swift +0 -175
  296. package/Sources/Runic/Views/Team/TeamManagementView.swift +0 -762
  297. package/Sources/Runic/Views/Team/TeamMemberRow.swift +0 -181
  298. package/Sources/RunicCLI/CLIEntry.swift +0 -983
  299. package/Sources/RunicCLI/CLIRenderer.swift +0 -87
  300. package/Sources/RunicCLI/Commands/EnhancedUsageCommand.swift +0 -588
  301. package/Sources/RunicCLI/Commands/ModelsCommand.swift +0 -363
  302. package/Sources/RunicCLI/Commands/ProjectsCommand.swift +0 -453
  303. package/Sources/RunicCLI/Commands/ResetCommand.swift +0 -430
  304. package/Sources/RunicCLI/Commands/UsageLedgerSourceFactory.swift +0 -167
  305. package/Sources/RunicClaudeWatchdog/main.swift +0 -122
  306. package/Sources/RunicClaudeWebProbe/main.swift +0 -62
  307. package/Sources/RunicCore/AlertRuleStore.swift +0 -187
  308. package/Sources/RunicCore/BrowserCookieImportOrder.swift +0 -25
  309. package/Sources/RunicCore/CopilotUsageModels.swift +0 -84
  310. package/Sources/RunicCore/CostUsageFetcher.swift +0 -119
  311. package/Sources/RunicCore/CostUsageModels.swift +0 -479
  312. package/Sources/RunicCore/CreditsModels.swift +0 -50
  313. package/Sources/RunicCore/CustomProviders/CustomProviderModels.swift +0 -268
  314. package/Sources/RunicCore/CustomProviders/GenericProviderFetcher.swift +0 -631
  315. package/Sources/RunicCore/CustomProviders/ProviderTemplates.swift +0 -444
  316. package/Sources/RunicCore/Host/PTY/TTYCommandRunner.swift +0 -679
  317. package/Sources/RunicCore/Host/Process/SubprocessRunner.swift +0 -135
  318. package/Sources/RunicCore/Integrations/GitHubIntegration.swift +0 -173
  319. package/Sources/RunicCore/Logging/JSONStderrLogHandler.swift +0 -79
  320. package/Sources/RunicCore/Logging/OSLogLogHandler.swift +0 -86
  321. package/Sources/RunicCore/Logging/RunicLog.swift +0 -123
  322. package/Sources/RunicCore/Models/EnhancedUsageModels.swift +0 -370
  323. package/Sources/RunicCore/OpenAIDashboardModels.swift +0 -210
  324. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift +0 -676
  325. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardFetcher.swift +0 -492
  326. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +0 -51
  327. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardParser.swift +0 -483
  328. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift +0 -558
  329. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift +0 -204
  330. package/Sources/RunicCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift +0 -78
  331. package/Sources/RunicCore/PathEnvironment.swift +0 -482
  332. package/Sources/RunicCore/Performance/PerformanceModels.swift +0 -371
  333. package/Sources/RunicCore/Performance/PerformanceStorageImpl.swift +0 -426
  334. package/Sources/RunicCore/Policy/UsagePolicyEngine.swift +0 -178
  335. package/Sources/RunicCore/ProjectBudgetStore.swift +0 -102
  336. package/Sources/RunicCore/ProviderCostSnapshot.swift +0 -29
  337. package/Sources/RunicCore/Providers/Antigravity/AntigravityProviderDescriptor.swift +0 -68
  338. package/Sources/RunicCore/Providers/Antigravity/AntigravityStatusProbe.swift +0 -685
  339. package/Sources/RunicCore/Providers/Auggie/AuggieProviderDescriptor.swift +0 -83
  340. package/Sources/RunicCore/Providers/Auggie/AuggieUsageFetcher.swift +0 -142
  341. package/Sources/RunicCore/Providers/Azure/AzureProviderDescriptor.swift +0 -141
  342. package/Sources/RunicCore/Providers/Azure/AzureUsageFetcher.swift +0 -188
  343. package/Sources/RunicCore/Providers/Bedrock/BedrockProviderDescriptor.swift +0 -126
  344. package/Sources/RunicCore/Providers/Bedrock/BedrockUsageFetcher.swift +0 -164
  345. package/Sources/RunicCore/Providers/Cerebras/CerebrasProviderDescriptor.swift +0 -84
  346. package/Sources/RunicCore/Providers/Cerebras/CerebrasUsageFetcher.swift +0 -75
  347. package/Sources/RunicCore/Providers/Claude/ClaudeCLISession.swift +0 -332
  348. package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift +0 -180
  349. package/Sources/RunicCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift +0 -137
  350. package/Sources/RunicCore/Providers/Claude/ClaudeProviderDescriptor.swift +0 -209
  351. package/Sources/RunicCore/Providers/Claude/ClaudeStatusProbe.swift +0 -654
  352. package/Sources/RunicCore/Providers/Claude/ClaudeUsageDataSource.swift +0 -30
  353. package/Sources/RunicCore/Providers/Claude/ClaudeUsageFetcher.swift +0 -480
  354. package/Sources/RunicCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift +0 -780
  355. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift +0 -147
  356. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift +0 -280
  357. package/Sources/RunicCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift +0 -100
  358. package/Sources/RunicCore/Providers/Codex/CodexProviderDescriptor.swift +0 -245
  359. package/Sources/RunicCore/Providers/Codex/CodexStatusProbe.swift +0 -125
  360. package/Sources/RunicCore/Providers/Codex/CodexUsageDataSource.swift +0 -26
  361. package/Sources/RunicCore/Providers/Codex/CodexWebDashboardStrategy.swift +0 -183
  362. package/Sources/RunicCore/Providers/Cohere/CohereProviderDescriptor.swift +0 -83
  363. package/Sources/RunicCore/Providers/Cohere/CohereUsageFetcher.swift +0 -85
  364. package/Sources/RunicCore/Providers/Copilot/CopilotDeviceFlow.swift +0 -123
  365. package/Sources/RunicCore/Providers/Copilot/CopilotGitHubCLITokenReader.swift +0 -117
  366. package/Sources/RunicCore/Providers/Copilot/CopilotProviderDescriptor.swift +0 -100
  367. package/Sources/RunicCore/Providers/Copilot/CopilotUsageFetcher.swift +0 -293
  368. package/Sources/RunicCore/Providers/Copilot/CopilotVSCodeTokenReader.swift +0 -385
  369. package/Sources/RunicCore/Providers/Cursor/CursorProviderDescriptor.swift +0 -67
  370. package/Sources/RunicCore/Providers/Cursor/CursorStatusProbe.swift +0 -595
  371. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift +0 -85
  372. package/Sources/RunicCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift +0 -108
  373. package/Sources/RunicCore/Providers/Factory/FactoryLocalStorageImporter.swift +0 -398
  374. package/Sources/RunicCore/Providers/Factory/FactoryProviderDescriptor.swift +0 -67
  375. package/Sources/RunicCore/Providers/Factory/FactoryStatusProbe.swift +0 -1276
  376. package/Sources/RunicCore/Providers/Fireworks/FireworksProviderDescriptor.swift +0 -84
  377. package/Sources/RunicCore/Providers/Fireworks/FireworksUsageFetcher.swift +0 -75
  378. package/Sources/RunicCore/Providers/Gemini/GeminiProviderDescriptor.swift +0 -67
  379. package/Sources/RunicCore/Providers/Gemini/GeminiStatusProbe.swift +0 -839
  380. package/Sources/RunicCore/Providers/Groq/GroqProviderDescriptor.swift +0 -83
  381. package/Sources/RunicCore/Providers/Groq/GroqUsageFetcher.swift +0 -71
  382. package/Sources/RunicCore/Providers/Kimi/KimiProviderDescriptor.swift +0 -83
  383. package/Sources/RunicCore/Providers/Kimi/KimiUsageFetcher.swift +0 -77
  384. package/Sources/RunicCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift +0 -97
  385. package/Sources/RunicCore/Providers/MiniMax/MiniMaxSettingsReader.swift +0 -54
  386. package/Sources/RunicCore/Providers/MiniMax/MiniMaxUsageFetcher.swift +0 -168
  387. package/Sources/RunicCore/Providers/MiniMax/MiniMaxWebUsageFetcher.swift +0 -911
  388. package/Sources/RunicCore/Providers/Mistral/MistralProviderDescriptor.swift +0 -84
  389. package/Sources/RunicCore/Providers/Mistral/MistralUsageFetcher.swift +0 -75
  390. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift +0 -87
  391. package/Sources/RunicCore/Providers/OpenRouter/OpenRouterUsageFetcher.swift +0 -216
  392. package/Sources/RunicCore/Providers/Perplexity/PerplexityProviderDescriptor.swift +0 -84
  393. package/Sources/RunicCore/Providers/Perplexity/PerplexityUsageFetcher.swift +0 -75
  394. package/Sources/RunicCore/Providers/ProviderBranding.swift +0 -25
  395. package/Sources/RunicCore/Providers/ProviderCLIConfig.swift +0 -17
  396. package/Sources/RunicCore/Providers/ProviderDescriptor.swift +0 -129
  397. package/Sources/RunicCore/Providers/ProviderFetchPlan.swift +0 -263
  398. package/Sources/RunicCore/Providers/ProviderSettingsSnapshot.swift +0 -98
  399. package/Sources/RunicCore/Providers/ProviderTokenResolver.swift +0 -501
  400. package/Sources/RunicCore/Providers/ProviderVersionDetector.swift +0 -68
  401. package/Sources/RunicCore/Providers/Providers.swift +0 -184
  402. package/Sources/RunicCore/Providers/Qwen/QwenProviderDescriptor.swift +0 -86
  403. package/Sources/RunicCore/Providers/Qwen/QwenSettingsReader.swift +0 -30
  404. package/Sources/RunicCore/Providers/Qwen/QwenUsageStats.swift +0 -328
  405. package/Sources/RunicCore/Providers/SambaNova/SambaNovaProviderDescriptor.swift +0 -84
  406. package/Sources/RunicCore/Providers/SambaNova/SambaNovaUsageFetcher.swift +0 -75
  407. package/Sources/RunicCore/Providers/Together/TogetherProviderDescriptor.swift +0 -83
  408. package/Sources/RunicCore/Providers/Together/TogetherUsageFetcher.swift +0 -75
  409. package/Sources/RunicCore/Providers/VertexAI/VertexAIProviderDescriptor.swift +0 -123
  410. package/Sources/RunicCore/Providers/VertexAI/VertexAISettingsReader.swift +0 -48
  411. package/Sources/RunicCore/Providers/VertexAI/VertexAIUsageFetcher.swift +0 -144
  412. package/Sources/RunicCore/Providers/XAI/XAIProviderDescriptor.swift +0 -83
  413. package/Sources/RunicCore/Providers/XAI/XAIUsageFetcher.swift +0 -75
  414. package/Sources/RunicCore/Providers/Zai/ZaiProviderDescriptor.swift +0 -74
  415. package/Sources/RunicCore/Providers/Zai/ZaiSettingsReader.swift +0 -41
  416. package/Sources/RunicCore/Providers/Zai/ZaiUsageStats.swift +0 -745
  417. package/Sources/RunicCore/Sync/BackgroundSyncManager.swift +0 -384
  418. package/Sources/RunicCore/Sync/SyncConflictResolver.swift +0 -307
  419. package/Sources/RunicCore/Sync/SyncProtocol.swift +0 -287
  420. package/Sources/RunicCore/Sync/SyncRecord.swift +0 -402
  421. package/Sources/RunicCore/Sync/SyncUsageExample.swift +0 -288
  422. package/Sources/RunicCore/Sync/TeamSyncRecords.swift +0 -768
  423. package/Sources/RunicCore/Sync/iCloudSyncEngine.swift +0 -338
  424. package/Sources/RunicCore/Team/TeamModels.swift +0 -584
  425. package/Sources/RunicCore/Team/TeamShowbackExporter.swift +0 -495
  426. package/Sources/RunicCore/Team/TeamStore.swift +0 -809
  427. package/Sources/RunicCore/TextParsing.swift +0 -55
  428. package/Sources/RunicCore/UsageFetcher.swift +0 -694
  429. package/Sources/RunicCore/UsageFormatter.swift +0 -410
  430. package/Sources/RunicCore/UsageLedger/ClaudeUsageLogSource.swift +0 -441
  431. package/Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift +0 -502
  432. package/Sources/RunicCore/UsageLedger/LedgerCache.swift +0 -161
  433. package/Sources/RunicCore/UsageLedger/OTelGenAILedgerAdapter.swift +0 -550
  434. package/Sources/RunicCore/UsageLedger/UsageLedger.swift +0 -29
  435. package/Sources/RunicCore/UsageLedger/UsageLedgerAggregator.swift +0 -675
  436. package/Sources/RunicCore/UsageLedger/UsageLedgerInsightsAdvisor.swift +0 -209
  437. package/Sources/RunicCore/UsageLedger/UsageLedgerModels.swift +0 -417
  438. package/Sources/RunicCore/UsageLedger/UsageLedgerProjectIdentity.swift +0 -284
  439. package/Sources/RunicCore/UsagePace.swift +0 -81
  440. package/Sources/RunicCore/Vendored/CostUsage/CostUsageCache.swift +0 -73
  441. package/Sources/RunicCore/Vendored/CostUsage/CostUsageJsonl.swift +0 -74
  442. package/Sources/RunicCore/Vendored/CostUsage/CostUsagePricing.swift +0 -208
  443. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Claude.swift +0 -455
  444. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner+Timestamp.swift +0 -132
  445. package/Sources/RunicCore/Vendored/CostUsage/CostUsageScanner.swift +0 -589
  446. package/Sources/RunicCore/WidgetSnapshot.swift +0 -183
  447. package/Sources/RunicMacroSupport/ProviderRegistrationMacros.swift +0 -14
  448. package/Sources/RunicMacros/ProviderRegistrationMacros.swift +0 -216
  449. package/Sources/RunicWidget/RunicWidgetBundle.swift +0 -79
  450. package/Sources/RunicWidget/RunicWidgetProvider.swift +0 -283
  451. package/Sources/RunicWidget/RunicWidgetViews.swift +0 -680
  452. package/Tests/RunicTests/AntigravityStatusProbeTests.swift +0 -50
  453. package/Tests/RunicTests/AppDelegateTests.swift +0 -48
  454. package/Tests/RunicTests/BrowserCookieOrderLabelTests.swift +0 -21
  455. package/Tests/RunicTests/CLIArgumentParsingTests.swift +0 -69
  456. package/Tests/RunicTests/CLICostTests.swift +0 -64
  457. package/Tests/RunicTests/CLIProviderSelectionTests.swift +0 -21
  458. package/Tests/RunicTests/CLISnapshotTests.swift +0 -71
  459. package/Tests/RunicTests/CLIWebFallbackTests.swift +0 -57
  460. package/Tests/RunicTests/ClaudeOAuthTests.swift +0 -163
  461. package/Tests/RunicTests/ClaudeResilienceTests.swift +0 -29
  462. package/Tests/RunicTests/ClaudeUsageTests.swift +0 -369
  463. package/Tests/RunicTests/CodexOAuthTests.swift +0 -121
  464. package/Tests/RunicTests/CodexUsageLogSourceTests.swift +0 -80
  465. package/Tests/RunicTests/CopilotTokenResolverTests.swift +0 -74
  466. package/Tests/RunicTests/CopilotVSCodeTokenReaderTests.swift +0 -74
  467. package/Tests/RunicTests/CostUsageDecodingTests.swift +0 -392
  468. package/Tests/RunicTests/CostUsagePricingTests.swift +0 -48
  469. package/Tests/RunicTests/CostUsageScannerTests.swift +0 -698
  470. package/Tests/RunicTests/CursorStatusProbeTests.swift +0 -322
  471. package/Tests/RunicTests/FactoryStatusProbeTests.swift +0 -67
  472. package/Tests/RunicTests/GeminiAPITestHelpers.swift +0 -94
  473. package/Tests/RunicTests/GeminiLoginAlertTests.swift +0 -27
  474. package/Tests/RunicTests/GeminiStatusProbeAPITests.swift +0 -283
  475. package/Tests/RunicTests/GeminiStatusProbePlanTests.swift +0 -279
  476. package/Tests/RunicTests/GeminiStatusProbeTests.swift +0 -232
  477. package/Tests/RunicTests/GeminiTestEnvironment.swift +0 -87
  478. package/Tests/RunicTests/GoogleWorkspaceStatusTests.swift +0 -72
  479. package/Tests/RunicTests/InstallOriginTests.swift +0 -17
  480. package/Tests/RunicTests/KeyboardShortcutsBundleTests.swift +0 -9
  481. package/Tests/RunicTests/LiveAccountTests.swift +0 -24
  482. package/Tests/RunicTests/LoadingPatternTests.swift +0 -34
  483. package/Tests/RunicTests/MenuCardModelTests.swift +0 -544
  484. package/Tests/RunicTests/MiniMaxCookieHeaderStoreTestSupport.swift +0 -11
  485. package/Tests/RunicTests/MiniMaxGroupIDStoreTestSupport.swift +0 -11
  486. package/Tests/RunicTests/MiniMaxParsingTests.swift +0 -67
  487. package/Tests/RunicTests/MiniMaxTokenStoreTestSupport.swift +0 -11
  488. package/Tests/RunicTests/OTelGenAILedgerAdapterTests.swift +0 -110
  489. package/Tests/RunicTests/OpenAIDashboardBrowserCookieImporterTests.swift +0 -16
  490. package/Tests/RunicTests/OpenAIDashboardFetcherCreditsWaitTests.swift +0 -74
  491. package/Tests/RunicTests/OpenAIDashboardOffscreenHostTests.swift +0 -26
  492. package/Tests/RunicTests/OpenAIDashboardParserTests.swift +0 -133
  493. package/Tests/RunicTests/OpenAIWebAccountSwitchTests.swift +0 -64
  494. package/Tests/RunicTests/OpenRouterTokenStoreTestSupport.swift +0 -131
  495. package/Tests/RunicTests/PathBuilderTests.swift +0 -236
  496. package/Tests/RunicTests/ProviderFetchPipelineTests.swift +0 -159
  497. package/Tests/RunicTests/ProviderIconResourcesTests.swift +0 -37
  498. package/Tests/RunicTests/ProviderMetadataStatusLinkTests.swift +0 -15
  499. package/Tests/RunicTests/ProviderRegistryTests.swift +0 -29
  500. package/Tests/RunicTests/ProviderSettingsDescriptorTests.swift +0 -236
  501. package/Tests/RunicTests/ProviderToggleStoreTests.swift +0 -50
  502. package/Tests/RunicTests/RunicTests.swift +0 -119
  503. package/Tests/RunicTests/SessionQuotaNotificationLogicTests.swift +0 -35
  504. package/Tests/RunicTests/SettingsStoreTests.swift +0 -265
  505. package/Tests/RunicTests/StatusItemAnimationTests.swift +0 -54
  506. package/Tests/RunicTests/StatusMenuTests.swift +0 -475
  507. package/Tests/RunicTests/StatusProbeTests.swift +0 -376
  508. package/Tests/RunicTests/SubprocessRunnerTests.swift +0 -18
  509. package/Tests/RunicTests/SubscriptionDetectionTests.swift +0 -64
  510. package/Tests/RunicTests/TTYCommandRunnerTests.swift +0 -147
  511. package/Tests/RunicTests/TTYIntegrationTests.swift +0 -41
  512. package/Tests/RunicTests/TeamShowbackExporterTests.swift +0 -157
  513. package/Tests/RunicTests/TextParsingTests.swift +0 -11
  514. package/Tests/RunicTests/UsageFormatterTests.swift +0 -111
  515. package/Tests/RunicTests/UsageLedgerAnomalyDetectionTests.swift +0 -170
  516. package/Tests/RunicTests/UsageLedgerForecastTests.swift +0 -211
  517. package/Tests/RunicTests/UsageLedgerInsightsAdvisorTests.swift +0 -81
  518. package/Tests/RunicTests/UsageLedgerProjectNameTests.swift +0 -168
  519. package/Tests/RunicTests/UsagePaceTests.swift +0 -76
  520. package/Tests/RunicTests/UsagePaceTextTests.swift +0 -108
  521. package/Tests/RunicTests/UsagePolicyEngineTests.swift +0 -89
  522. package/Tests/RunicTests/WidgetSnapshotTests.swift +0 -43
  523. package/Tests/RunicTests/ZaiProviderTests.swift +0 -59
  524. package/Tests/RunicTests/ZaiTokenStoreTestSupport.swift +0 -9
  525. package/TestsLinux/PlatformGatingTests.swift +0 -46
  526. package/appcast.xml +0 -104
  527. package/assets/logo-concept-stack.svg +0 -24
  528. package/assets/logo-minimal-bars.svg +0 -15
  529. package/assets/logo.svg +0 -20
  530. package/assets/logo2.svg +0 -43
  531. package/bin/docs-list +0 -5
  532. package/build-and-run.sh +0 -369
  533. package/docs/.nojekyll +0 -1
  534. package/docs/CNAME +0 -1
  535. package/docs/antigravity.md +0 -75
  536. package/docs/architecture.md +0 -32
  537. package/docs/claude.md +0 -93
  538. package/docs/cli-commands/integration_guide.md +0 -371
  539. package/docs/cli-commands/quick_reference.md +0 -362
  540. package/docs/cli-commands/readme.md +0 -361
  541. package/docs/cli.md +0 -156
  542. package/docs/cloudkit_sync_guide.md +0 -495
  543. package/docs/codebase_review.md +0 -288
  544. package/docs/codex-oauth.md +0 -635
  545. package/docs/codex.md +0 -104
  546. package/docs/codexbar.png +0 -0
  547. package/docs/copilot.md +0 -44
  548. package/docs/cursor.md +0 -46
  549. package/docs/design/designcomparisonchart.md +0 -510
  550. package/docs/design/implementationguide.md +0 -792
  551. package/docs/design/menubaricondesignconcepts.md +0 -796
  552. package/docs/design/mockups/hybridiconconcept.svg +0 -62
  553. package/docs/design/mockups/infinityiconconcept.svg +0 -41
  554. package/docs/design/mockups/infinityiconstates.svg +0 -129
  555. package/docs/design/mockups/wavelogorefined.svg +0 -48
  556. package/docs/design/quick_summary.md +0 -426
  557. package/docs/design/readme.md +0 -478
  558. package/docs/design/sizespecifications.md +0 -575
  559. package/docs/design-system.md +0 -836
  560. package/docs/factory.md +0 -103
  561. package/docs/gemini.md +0 -73
  562. package/docs/icon.md +0 -37
  563. package/docs/icon.png +0 -0
  564. package/docs/index.html +0 -175
  565. package/docs/keychain_fix.md +0 -274
  566. package/docs/minimax.md +0 -71
  567. package/docs/packaging.md +0 -25
  568. package/docs/progress-bar-improvements.md +0 -240
  569. package/docs/progress-bar-quick-reference.md +0 -283
  570. package/docs/progress-bar-technical-details.md +0 -432
  571. package/docs/progress-bar-visual-test.swift +0 -375
  572. package/docs/provider.md +0 -202
  573. package/docs/providers.md +0 -86
  574. package/docs/refactor/macros.md +0 -35
  575. package/docs/refresh-loop.md +0 -22
  576. package/docs/releasing-homebrew.md +0 -35
  577. package/docs/releasing.md +0 -121
  578. package/docs/research/concrete_todo_2026-02-22.md +0 -47
  579. package/docs/research/core-feature-research.md +0 -248
  580. package/docs/research/feature_uiux_roadmap_2026-02-22.md +0 -202
  581. package/docs/research/parity_matrix.md +0 -49
  582. package/docs/research/provider_expansion_candidates_2026-02-22.md +0 -80
  583. package/docs/research/provider_model_token_project_matrix_2026-02-23.md +0 -46
  584. package/docs/research/release_gate_checklist.md +0 -57
  585. package/docs/site.css +0 -505
  586. package/docs/sparkle.md +0 -28
  587. package/docs/status.md +0 -28
  588. package/docs/sync/implementation.md +0 -393
  589. package/docs/sync/readme.md +0 -317
  590. package/docs/sync_files_summary.md +0 -391
  591. package/docs/sync_quick_reference.md +0 -225
  592. package/docs/todo.md +0 -11
  593. package/docs/ui.md +0 -29
  594. package/docs/web-integration.md +0 -9
  595. package/docs/widgets.md +0 -85
  596. package/docs/workflows/error-handling-improvements.md +0 -434
  597. package/docs/workflows/folder_structure.md +0 -299
  598. package/docs/workflows/loading_states.md +0 -446
  599. package/docs/workflows/loading_states_examples.md +0 -565
  600. package/docs/workflows/loading_states_flow.md +0 -430
  601. package/docs/workflows/performance_optimizations.md +0 -457
  602. package/docs/workflows/phase1-cli-testing-report.md +0 -313
  603. package/docs/workflows/quick_reference.md +0 -228
  604. package/docs/workflows/readme.md +0 -59
  605. package/docs/workflows/recent_improvements.md +0 -275
  606. package/docs/workflows/sync_enablement_summary.md +0 -400
  607. package/docs/zai.md +0 -43
  608. package/runic.png +0 -0
  609. package/runic.svg +0 -15
  610. package/version.env +0 -2
@@ -1,384 +0,0 @@
1
- import Combine
2
- import Foundation
3
-
4
- #if canImport(UIKit)
5
- import UIKit
6
- #endif
7
-
8
- #if canImport(AppKit)
9
- import AppKit
10
- #endif
11
-
12
- // MARK: - Background Sync Manager
13
-
14
- /// Manages background synchronization with configurable intervals
15
- ///
16
- /// This manager coordinates automatic synchronization operations based on
17
- /// app lifecycle events and configured intervals. It supports:
18
- /// - Active sync (5-minute intervals)
19
- /// - Background sync (hourly intervals)
20
- /// - Manual sync on demand
21
- /// - Lifecycle-aware sync (app launch, foreground, background)
22
- /// - Network reachability monitoring
23
- public actor BackgroundSyncManager {
24
- // MARK: - Properties
25
-
26
- /// The underlying sync engine
27
- private let syncEngine: any SyncEngine
28
-
29
- /// Sync configuration
30
- private let config: SyncConfiguration
31
-
32
- /// Timer for periodic sync operations (must be accessed on main thread)
33
- @MainActor
34
- private var syncTimer: Timer?
35
-
36
- /// Indicates if background sync is currently enabled
37
- private var isEnabled: Bool = false
38
-
39
- /// Last successful sync timestamp
40
- private var lastSyncDate: Date?
41
-
42
- /// Sync history for diagnostics
43
- private var syncHistory: [SyncHistoryEntry] = []
44
-
45
- /// Maximum history entries to retain
46
- private let maxHistoryEntries: Int = 50
47
-
48
- /// Observers registered for sync events
49
- private var observers: [WeakSyncObserver] = []
50
-
51
- // Background task identifier (iOS only)
52
- #if canImport(UIKit)
53
- private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
54
- #endif
55
-
56
- // MARK: - Initialization
57
-
58
- /// Initializes the background sync manager
59
- ///
60
- /// - Parameters:
61
- /// - syncEngine: The sync engine to use for operations
62
- /// - config: Configuration for sync intervals and behavior
63
- public init(
64
- syncEngine: any SyncEngine,
65
- config: SyncConfiguration = .default)
66
- {
67
- self.syncEngine = syncEngine
68
- self.config = config
69
-
70
- // Register for app lifecycle notifications
71
- Task {
72
- await self.registerLifecycleObservers()
73
- }
74
- }
75
-
76
- // MARK: - Public Methods
77
-
78
- /// Starts background synchronization
79
- public func start() {
80
- guard !self.isEnabled else { return }
81
-
82
- self.isEnabled = true
83
- self.scheduleNextSync()
84
- self.notifyObservers { $0.syncDidStart() }
85
- }
86
-
87
- /// Stops background synchronization
88
- public func stop() {
89
- self.isEnabled = false
90
- Task { @MainActor in
91
- self.syncTimer?.invalidate()
92
- self.syncTimer = nil
93
- }
94
- }
95
-
96
- /// Performs a manual sync operation
97
- ///
98
- /// - Parameter options: Optional sync options (uses defaults if nil)
99
- /// - Returns: Result of the sync operation
100
- @discardableResult
101
- public func syncNow(options: SyncOptions? = nil) async -> Result<SyncResult, SyncError> {
102
- let syncOptions = options ?? self.config.defaultSyncOptions
103
-
104
- self.notifyObservers { $0.syncDidStart() }
105
-
106
- let result = await syncEngine.sync(options: syncOptions)
107
-
108
- switch result {
109
- case let .success(syncResult):
110
- self.lastSyncDate = Date()
111
- self.recordSyncHistory(success: true, result: syncResult)
112
- self.notifyObservers { $0.syncDidComplete(result: syncResult) }
113
-
114
- case let .failure(error):
115
- self.recordSyncHistory(success: false, error: error)
116
- self.notifyObservers { $0.syncDidFail(error: error) }
117
- }
118
-
119
- return result
120
- }
121
-
122
- /// Adds an observer for sync events
123
- ///
124
- /// - Parameter observer: The observer to add
125
- public func addObserver(_ observer: SyncObserver) {
126
- let weakObserver = WeakSyncObserver(observer)
127
- self.observers.append(weakObserver)
128
- }
129
-
130
- /// Removes an observer
131
- ///
132
- /// - Parameter observer: The observer to remove
133
- public func removeObserver(_ observer: SyncObserver) {
134
- self.observers.removeAll { $0.observer === observer }
135
- }
136
-
137
- /// Returns sync statistics
138
- public var statistics: SyncStatistics {
139
- SyncStatistics(
140
- lastSyncDate: self.lastSyncDate,
141
- totalSyncs: self.syncHistory.count,
142
- successfulSyncs: self.syncHistory.count(where: { $0.success }),
143
- failedSyncs: self.syncHistory.count(where: { !$0.success }),
144
- averageDuration: self.calculateAverageDuration(),
145
- syncHistory: Array(self.syncHistory.suffix(10)))
146
- }
147
-
148
- /// Updates sync configuration
149
- ///
150
- /// - Parameter config: New configuration to apply
151
- public func updateConfiguration(_ config: SyncConfiguration) async {
152
- // Note: Configuration updates require recreating the manager
153
- // This is a placeholder - in practice, you'd want to make config mutable
154
- if self.isEnabled {
155
- self.stop()
156
- // Caller should create a new BackgroundSyncManager with new config
157
- }
158
- }
159
-
160
- // MARK: - Private Methods
161
-
162
- /// Schedules the next automatic sync
163
- private func scheduleNextSync() {
164
- guard self.isEnabled else { return }
165
-
166
- let interval = self.determineNextInterval()
167
-
168
- Task { @MainActor [weak self] in
169
- guard let self else { return }
170
- self.syncTimer?.invalidate()
171
- self.syncTimer = Timer.scheduledTimer(
172
- withTimeInterval: interval,
173
- repeats: false)
174
- { [weak self] _ in
175
- Task {
176
- await self?.performScheduledSync()
177
- }
178
- }
179
- }
180
- }
181
-
182
- /// Determines the appropriate sync interval based on app state
183
- private func determineNextInterval() -> TimeInterval {
184
- #if canImport(UIKit)
185
- let isActive = UIApplication.shared.applicationState == .active
186
- return isActive ? self.config.activeSyncInterval : self.config.backgroundSyncInterval
187
- #else
188
- return self.config.activeSyncInterval
189
- #endif
190
- }
191
-
192
- /// Performs a scheduled background sync
193
- private func performScheduledSync() async {
194
- #if canImport(UIKit)
195
- // Begin background task
196
- self.backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
197
- self?.endBackgroundTask()
198
- }
199
- #endif
200
-
201
- await self.syncNow()
202
-
203
- #if canImport(UIKit)
204
- self.endBackgroundTask()
205
- #endif
206
-
207
- // Schedule next sync
208
- self.scheduleNextSync()
209
- }
210
-
211
- #if canImport(UIKit)
212
- /// Ends the background task
213
- private func endBackgroundTask() {
214
- guard self.backgroundTaskID != .invalid else { return }
215
- UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
216
- self.backgroundTaskID = .invalid
217
- }
218
- #endif
219
-
220
- /// Registers observers for app lifecycle events
221
- private func registerLifecycleObservers() {
222
- #if canImport(UIKit)
223
- NotificationCenter.default.addObserver(
224
- forName: UIApplication.didBecomeActiveNotification,
225
- object: nil,
226
- queue: .main)
227
- { [weak self] _ in
228
- Task { await self?.handleAppBecameActive() }
229
- }
230
-
231
- NotificationCenter.default.addObserver(
232
- forName: UIApplication.didEnterBackgroundNotification,
233
- object: nil,
234
- queue: .main)
235
- { [weak self] _ in
236
- Task { await self?.handleAppEnteredBackground() }
237
- }
238
- #endif
239
-
240
- #if canImport(AppKit)
241
- NotificationCenter.default.addObserver(
242
- forName: NSApplication.didBecomeActiveNotification,
243
- object: nil,
244
- queue: .main)
245
- { [weak self] _ in
246
- Task { await self?.handleAppBecameActive() }
247
- }
248
-
249
- NotificationCenter.default.addObserver(
250
- forName: NSApplication.didResignActiveNotification,
251
- object: nil,
252
- queue: .main)
253
- { [weak self] _ in
254
- Task { await self?.handleAppEnteredBackground() }
255
- }
256
- #endif
257
- }
258
-
259
- /// Handles app becoming active
260
- private func handleAppBecameActive() async {
261
- guard self.config.syncOnForeground else { return }
262
-
263
- // Sync if last sync was more than interval ago
264
- if self.shouldSyncOnForeground() {
265
- await self.syncNow()
266
- }
267
- }
268
-
269
- /// Handles app entering background
270
- private func handleAppEnteredBackground() async {
271
- guard self.config.syncOnBackground else { return }
272
- await self.syncNow()
273
- }
274
-
275
- /// Determines if sync should occur on foreground
276
- private func shouldSyncOnForeground() -> Bool {
277
- guard let lastSync = lastSyncDate else { return true }
278
-
279
- let elapsed = Date().timeIntervalSince(lastSync)
280
- return elapsed >= self.config.activeSyncInterval
281
- }
282
-
283
- /// Records sync operation in history
284
- private func recordSyncHistory(
285
- success: Bool,
286
- result: SyncResult? = nil,
287
- error: SyncError? = nil)
288
- {
289
- let entry = SyncHistoryEntry(
290
- timestamp: Date(),
291
- success: success,
292
- duration: result?.duration ?? 0,
293
- pushedCount: result?.pushedCount ?? 0,
294
- fetchedCount: result?.fetchedCount ?? 0,
295
- error: error?.localizedDescription)
296
-
297
- self.syncHistory.append(entry)
298
-
299
- // Trim history if needed
300
- if self.syncHistory.count > self.maxHistoryEntries {
301
- self.syncHistory.removeFirst(self.syncHistory.count - self.maxHistoryEntries)
302
- }
303
- }
304
-
305
- /// Calculates average sync duration
306
- private func calculateAverageDuration() -> TimeInterval {
307
- let successfulSyncs = self.syncHistory.filter { $0.success && $0.duration > 0 }
308
- guard !successfulSyncs.isEmpty else { return 0 }
309
-
310
- let totalDuration = successfulSyncs.reduce(0.0) { $0 + $1.duration }
311
- return totalDuration / Double(successfulSyncs.count)
312
- }
313
-
314
- /// Notifies all observers
315
- private func notifyObservers(_ action: (SyncObserver) -> Void) {
316
- // Clean up deallocated observers
317
- self.observers.removeAll { $0.observer == nil }
318
-
319
- // Notify active observers
320
- for weakObserver in self.observers {
321
- if let observer = weakObserver.observer {
322
- action(observer)
323
- }
324
- }
325
- }
326
- }
327
-
328
- // MARK: - Supporting Types
329
-
330
- /// Configuration for background sync behavior
331
- public struct SyncConfiguration: Sendable {
332
- public let activeSyncInterval: TimeInterval
333
- public let backgroundSyncInterval: TimeInterval
334
- public let syncOnForeground: Bool
335
- public let syncOnBackground: Bool
336
- public let defaultSyncOptions: SyncOptions
337
-
338
- public init(
339
- activeSyncInterval: TimeInterval = 300,
340
- backgroundSyncInterval: TimeInterval = 3600,
341
- syncOnForeground: Bool = true,
342
- syncOnBackground: Bool = true,
343
- defaultSyncOptions: SyncOptions = SyncOptions())
344
- {
345
- self.activeSyncInterval = activeSyncInterval
346
- self.backgroundSyncInterval = backgroundSyncInterval
347
- self.syncOnForeground = syncOnForeground
348
- self.syncOnBackground = syncOnBackground
349
- self.defaultSyncOptions = defaultSyncOptions
350
- }
351
-
352
- public static let `default` = SyncConfiguration()
353
- }
354
-
355
- /// Statistics about sync operations
356
- public struct SyncStatistics: Sendable {
357
- public let lastSyncDate: Date?
358
- public let totalSyncs: Int
359
- public let successfulSyncs: Int
360
- public let failedSyncs: Int
361
- public let averageDuration: TimeInterval
362
- public let syncHistory: [SyncHistoryEntry]
363
-
364
- public var successRate: Double {
365
- guard self.totalSyncs > 0 else { return 0 }
366
- return Double(self.successfulSyncs) / Double(self.totalSyncs) * 100
367
- }
368
- }
369
-
370
- public struct SyncHistoryEntry: Sendable, Codable {
371
- public let timestamp: Date
372
- public let success: Bool
373
- public let duration: TimeInterval
374
- public let pushedCount: Int
375
- public let fetchedCount: Int
376
- public let error: String?
377
- }
378
-
379
- private struct WeakSyncObserver {
380
- weak var observer: SyncObserver?
381
- init(_ observer: SyncObserver) {
382
- self.observer = observer
383
- }
384
- }
@@ -1,307 +0,0 @@
1
- import Foundation
2
-
3
- // MARK: - Sync Conflict Resolver
4
-
5
- /// Default implementation of conflict resolution for synchronized records
6
- ///
7
- /// This resolver implements multiple conflict resolution strategies:
8
- /// - Last-write-wins (default): Most recently modified record wins
9
- /// - Prefer local: Always keep local version
10
- /// - Prefer remote: Always keep remote version
11
- /// - Highest version: Keep record with highest version number
12
- /// - Merge: Attempt to merge both versions (custom logic required)
13
- public actor SyncConflictResolver: SyncConflictResolverProtocol {
14
- // MARK: - Properties
15
-
16
- /// Statistics about resolved conflicts
17
- public private(set) var conflictStats: ConflictStatistics
18
-
19
- /// Custom merge handlers for specific record types
20
- private var mergeHandlers: [String: MergeHandler] = [:]
21
-
22
- // MARK: - Initialization
23
-
24
- public init() {
25
- self.conflictStats = ConflictStatistics()
26
- }
27
-
28
- // MARK: - Public Methods
29
-
30
- /// Resolves a conflict between local and remote versions
31
- ///
32
- /// - Parameters:
33
- /// - local: The local version of the record
34
- /// - remote: The remote version of the record
35
- /// - strategy: The resolution strategy to apply
36
- /// - Returns: The resolved record that should be kept
37
- public func resolve(
38
- local: SyncableRecord,
39
- remote: SyncableRecord,
40
- strategy: ConflictResolutionStrategy) async -> SyncableRecord
41
- {
42
- // Validate that records are the same type
43
- guard local.recordID == remote.recordID else {
44
- return local // Fallback to local if IDs don't match
45
- }
46
-
47
- let resolved: SyncableRecord = switch strategy {
48
- case .lastWriteWins:
49
- self.resolveLastWriteWins(local: local, remote: remote)
50
-
51
- case .preferLocal:
52
- local
53
-
54
- case .preferRemote:
55
- remote
56
-
57
- case .highestVersion:
58
- self.resolveHighestVersion(local: local, remote: remote)
59
-
60
- case .merge:
61
- self.resolveMerge(local: local, remote: remote)
62
- }
63
-
64
- // Update statistics
65
- self.conflictStats.recordConflict(
66
- recordType: local.recordType,
67
- strategy: strategy,
68
- winner: resolved.recordID == local.recordID ? .local : .remote)
69
-
70
- return resolved
71
- }
72
-
73
- /// Registers a custom merge handler for a specific record type
74
- ///
75
- /// - Parameters:
76
- /// - recordType: The CloudKit record type name
77
- /// - handler: Closure that merges two records of this type
78
- public func registerMergeHandler(
79
- for recordType: String,
80
- handler: @escaping MergeHandler)
81
- {
82
- self.mergeHandlers[recordType] = handler
83
- }
84
-
85
- /// Resets conflict statistics
86
- public func resetStatistics() {
87
- self.conflictStats = ConflictStatistics()
88
- }
89
-
90
- // MARK: - Private Resolution Methods
91
-
92
- /// Resolves conflict by keeping the most recently modified record
93
- private func resolveLastWriteWins(
94
- local: SyncableRecord,
95
- remote: SyncableRecord) -> SyncableRecord
96
- {
97
- if local.modifiedAt > remote.modifiedAt {
98
- local
99
- } else if remote.modifiedAt > local.modifiedAt {
100
- remote
101
- } else {
102
- // Same timestamp, use version as tiebreaker
103
- local.version >= remote.version ? local : remote
104
- }
105
- }
106
-
107
- /// Resolves conflict by keeping the record with highest version number
108
- private func resolveHighestVersion(
109
- local: SyncableRecord,
110
- remote: SyncableRecord) -> SyncableRecord
111
- {
112
- if local.version > remote.version {
113
- local
114
- } else if remote.version > local.version {
115
- remote
116
- } else {
117
- // Same version, use timestamp as tiebreaker
118
- local.modifiedAt >= remote.modifiedAt ? local : remote
119
- }
120
- }
121
-
122
- /// Attempts to merge both versions using custom merge logic
123
- private func resolveMerge(
124
- local: SyncableRecord,
125
- remote: SyncableRecord) -> SyncableRecord
126
- {
127
- // Check for registered merge handler
128
- if let handler = mergeHandlers[local.recordType] {
129
- return handler(local, remote)
130
- }
131
-
132
- // No custom merge handler, fall back to last-write-wins
133
- return self.resolveLastWriteWins(local: local, remote: remote)
134
- }
135
- }
136
-
137
- // MARK: - Supporting Types
138
-
139
- /// Closure type for custom merge handlers
140
- public typealias MergeHandler = @Sendable (SyncableRecord, SyncableRecord) -> SyncableRecord
141
-
142
- /// Indicates which version won during conflict resolution
143
- public enum ConflictWinner: String, Codable, Sendable {
144
- case local
145
- case remote
146
- }
147
-
148
- /// Statistics about conflict resolution operations
149
- public struct ConflictStatistics: Sendable {
150
- /// Total number of conflicts resolved
151
- public private(set) var totalConflicts: Int = 0
152
-
153
- /// Number of conflicts per record type
154
- public private(set) var conflictsByType: [String: Int] = [:]
155
-
156
- /// Number of conflicts per strategy
157
- public private(set) var conflictsByStrategy: [String: Int] = [:]
158
-
159
- /// Number of wins for local vs remote
160
- public private(set) var localWins: Int = 0
161
- public private(set) var remoteWins: Int = 0
162
-
163
- /// Timestamp of last conflict
164
- public private(set) var lastConflictAt: Date?
165
-
166
- public init() {}
167
-
168
- /// Records a conflict resolution event
169
- mutating func recordConflict(
170
- recordType: String,
171
- strategy: ConflictResolutionStrategy,
172
- winner: ConflictWinner)
173
- {
174
- self.totalConflicts += 1
175
- self.conflictsByType[recordType, default: 0] += 1
176
- self.conflictsByStrategy[strategy.rawValue, default: 0] += 1
177
-
178
- switch winner {
179
- case .local:
180
- self.localWins += 1
181
- case .remote:
182
- self.remoteWins += 1
183
- }
184
-
185
- self.lastConflictAt = Date()
186
- }
187
-
188
- /// Percentage of conflicts won by local version
189
- public var localWinRate: Double {
190
- guard self.totalConflicts > 0 else { return 0 }
191
- return Double(self.localWins) / Double(self.totalConflicts)
192
- }
193
-
194
- /// Percentage of conflicts won by remote version
195
- public var remoteWinRate: Double {
196
- guard self.totalConflicts > 0 else { return 0 }
197
- return Double(self.remoteWins) / Double(self.totalConflicts)
198
- }
199
-
200
- /// Human-readable summary of conflict statistics
201
- public var summary: String {
202
- var lines = [
203
- "Conflict Resolution Statistics:",
204
- " Total conflicts: \(totalConflicts)",
205
- " Local wins: \(localWins) (\(String(format: "%.1f%%", localWinRate * 100)))",
206
- " Remote wins: \(remoteWins) (\(String(format: "%.1f%%", remoteWinRate * 100)))",
207
- ]
208
-
209
- if !self.conflictsByType.isEmpty {
210
- lines.append(" By record type:")
211
- for (type, count) in self.conflictsByType.sorted(by: { $0.value > $1.value }) {
212
- lines.append(" \(type): \(count)")
213
- }
214
- }
215
-
216
- if !self.conflictsByStrategy.isEmpty {
217
- lines.append(" By strategy:")
218
- for (strategy, count) in self.conflictsByStrategy.sorted(by: { $0.value > $1.value }) {
219
- lines.append(" \(strategy): \(count)")
220
- }
221
- }
222
-
223
- if let lastConflict = lastConflictAt {
224
- let formatter = RelativeDateTimeFormatter()
225
- let timeAgo = formatter.localizedString(for: lastConflict, relativeTo: Date())
226
- lines.append(" Last conflict: \(timeAgo)")
227
- }
228
-
229
- return lines.joined(separator: "\n")
230
- }
231
- }
232
-
233
- // MARK: - Default Merge Handlers
234
-
235
- extension SyncConflictResolver {
236
- /// Registers default merge handlers for Runic record types
237
- public func registerDefaultMergeHandlers() {
238
- // Usage Snapshot merge: prefer record with most recent data
239
- self.registerMergeHandler(for: CloudKitRecordType.usageSnapshot) { local, remote in
240
- guard let localUsage = local as? UsageSnapshotSyncRecord,
241
- let remoteUsage = remote as? UsageSnapshotSyncRecord
242
- else {
243
- return local
244
- }
245
-
246
- // Prefer the record with more recent usage data
247
- return localUsage.updatedAt > remoteUsage.updatedAt ? local : remote
248
- }
249
-
250
- // User Preferences merge: combine enabled providers
251
- self.registerMergeHandler(for: CloudKitRecordType.userPreferences) { local, remote in
252
- guard let localPrefs = local as? UserPreferencesSyncRecord,
253
- let remotePrefs = remote as? UserPreferencesSyncRecord
254
- else {
255
- return local
256
- }
257
-
258
- // Merge enabled providers (union of both sets)
259
- let mergedProviders = Array(Set(localPrefs.enabledProviders + remotePrefs.enabledProviders))
260
-
261
- // Use most recent settings for other fields
262
- let source = localPrefs.modifiedAt > remotePrefs.modifiedAt ? localPrefs : remotePrefs
263
-
264
- return UserPreferencesSyncRecord(
265
- recordID: localPrefs.recordID,
266
- version: max(localPrefs.version, remotePrefs.version) + 1,
267
- modifiedAt: Date(),
268
- lastModifiedDeviceID: source.lastModifiedDeviceID,
269
- refreshInterval: source.refreshInterval,
270
- enabledProviders: mergedProviders,
271
- notificationsEnabled: source.notificationsEnabled,
272
- autoRefreshEnabled: source.autoRefreshEnabled,
273
- theme: source.theme,
274
- displayFormat: source.displayFormat)
275
- }
276
-
277
- // Alert Configuration merge: prefer most restrictive thresholds
278
- self.registerMergeHandler(for: CloudKitRecordType.alertConfiguration) { local, remote in
279
- guard let localAlert = local as? AlertConfigurationSyncRecord,
280
- let remoteAlert = remote as? AlertConfigurationSyncRecord
281
- else {
282
- return local
283
- }
284
-
285
- // Use lower (more conservative) thresholds
286
- let warningThreshold = min(localAlert.warningThreshold, remoteAlert.warningThreshold)
287
- let criticalThreshold = min(localAlert.criticalThreshold, remoteAlert.criticalThreshold)
288
-
289
- // Merge notification channels (union)
290
- let mergedChannels = Array(Set(localAlert.notificationChannels + remoteAlert.notificationChannels))
291
-
292
- // Enabled if either version has it enabled
293
- let enabled = localAlert.enabled || remoteAlert.enabled
294
-
295
- return AlertConfigurationSyncRecord(
296
- recordID: localAlert.recordID,
297
- version: max(localAlert.version, remoteAlert.version) + 1,
298
- modifiedAt: Date(),
299
- lastModifiedDeviceID: localAlert.lastModifiedDeviceID,
300
- providerID: localAlert.providerID,
301
- warningThreshold: warningThreshold,
302
- criticalThreshold: criticalThreshold,
303
- notificationChannels: mergedChannels,
304
- enabled: enabled)
305
- }
306
- }
307
- }